diff --git a/.gitignore b/.gitignore index 4105cfbd6f26397578820c996f82987fd94e77c0..667f54445b4f04591ba47df0b2c35f43064cb6cd 100644 --- a/.gitignore +++ b/.gitignore @@ -118,3 +118,8 @@ all.config # fetched Android config fragments kernel/configs/android-*.cfg + +# +#Ignoring Android.bp link file +# +Android.bp diff --git a/Android.bp b/Android.bp deleted file mode 100644 index 4341e3a71dad646b30295dc450d3a1fdd4960a1a..0000000000000000000000000000000000000000 --- a/Android.bp +++ /dev/null @@ -1,27 +0,0 @@ -cc_binary_host { - name: "unifdef", - srcs: ["scripts/unifdef.c"], - sanitize: { - never: true, - } -} - -gensrcs { - name: "qseecom-kernel-includes", - - // move to out/ as root for header generation because of scripts/unifdef - // storage - at the expense of extra ../ references - cmd: "pushd out && mkdir -p scripts && rm -f scripts/unifdef && ln -s ../../$(location unifdef) scripts/unifdef && ../$(location scripts/headers_install.sh) `dirname ../$(out)` ../ $(in) && popd", - - tools: ["unifdef"], - tool_files: ["scripts/headers_install.sh"], - export_include_dirs: ["include/uapi"], - srcs: ["include/uapi/linux/qseecom.h"], - output_extension: "h", -} - -cc_library_headers { - name: "qseecom-kernel-headers", - generated_headers: ["qseecom-kernel-includes"], - export_generated_headers: ["qseecom-kernel-includes"], -} diff --git a/Androidbp b/Androidbp new file mode 100644 index 0000000000000000000000000000000000000000..1fd921a0e88c7d47ae0d6aa22c29ed501c0aeaa8 --- /dev/null +++ b/Androidbp @@ -0,0 +1,45 @@ +cc_binary_host { + name: "unifdef", + srcs: ["scripts/unifdef.c"], + sanitize: { + never: true, + }, +} + +genrule { + name: "gen-headers_install.sh", + srcs: ["scripts/headers_install.sh"], + tools: ["unifdef"], + out: ["headers_install.sh"], + cmd: "sed 's+scripts/unifdef+$(location unifdef)+g' $(in) > $(out)", +} + +cc_prebuilt_binary { + name: "headers_install.sh", + device_supported: false, + host_supported: true, + srcs: [":gen-headers_install.sh"], +} + +// Use the following for verbose output from kernel_headers.py. +// kernel_headers_verbose = "--verbose " +// Use the following for minimal output from kernel_headers.py. +kernel_headers_verbose = "" + +build = ["gen_headers_arm.bp", "gen_headers_arm64.bp"] + +cc_library_headers { + name: "qti_kernel_headers", + arch: { + arm: { + generated_headers: ["qti_generate_kernel_headers_arm"], + export_generated_headers: ["qti_generate_kernel_headers_arm"], + }, + arm64: { + generated_headers: ["qti_generate_kernel_headers_arm64"], + export_generated_headers: ["qti_generate_kernel_headers_arm64"], + }, + }, + vendor: true, + recovery_available: true, +} diff --git a/Documentation/ABI/testing/sysfs-bus-mei b/Documentation/ABI/testing/sysfs-bus-mei index 6bd45346ac7e4d20ffb445723fe94b5e32d98b3a..3f8701e8fa241d4a2a74ea29ca1cd9772d9360c9 100644 --- a/Documentation/ABI/testing/sysfs-bus-mei +++ b/Documentation/ABI/testing/sysfs-bus-mei @@ -4,7 +4,7 @@ KernelVersion: 3.10 Contact: Samuel Ortiz linux-mei@linux.intel.com Description: Stores the same MODALIAS value emitted by uevent - Format: mei::: + Format: mei::: What: /sys/bus/mei/devices/.../name Date: May 2015 diff --git a/Documentation/devicetree/bindings/arm/msm/sdx-ext-ipc.txt b/Documentation/devicetree/bindings/arm/msm/sdx-ext-ipc.txt new file mode 100644 index 0000000000000000000000000000000000000000..689c5b697fa5522a5e800c8b22698f4e4a985dc6 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/sdx-ext-ipc.txt @@ -0,0 +1,31 @@ +Modem chipset attached to Application processor + +Modem chipset can be connected to an external apss processor. The control +channel between the two chipsets consists of gpios that can relay the +state of one subsytem to another. Modem can indicate different events +(bootup/crash etc.) to AP and can get the same information from AP. + +Required Properties: +- compatible: "qcom,sdx-ext-ipc". + +Required named gpio properties: +- qcom,mdm2ap-status-gpio: gpio for modem to indicate the boot status to APQ. + +- qcom,ap2mdm-status-gpio: gpio for APQ to indicate the boot status to modem. + + + +Optional named gpio properties: +- qcom,mdm2ap-status2-gpio: gpio for modem to indicate to APQ that it is in + E911 call or doing firmware upgrade. + +- qcom,ap2mdm-status2-gpio: gpio for APQ to indicate graceful shutdown to modem. + +Example: + sdx_ext_ipc: qcom,sdx_ext_ipc { + compatible = "qcom,sdx-ext-ipc"; + qcom,ap2mdm-status-gpio = <&tlmm 64 0x00>; + qcom,ap2mdm-status2-gpio = <&tlmm 65 0x00>; + qcom,mdm2ap-status-gpio = <&tlmm 63 0x00>; + qcom,mdm2ap-status2-gpio = <&tlmm 66 0x00>; + }; diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt index ada2eab37e3ec57ba48868e8f450ac65b9bbba9a..66a668f5ffac8ce0b1e1db11b3aaaad1721d0cec 100644 --- a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt +++ b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt @@ -67,6 +67,7 @@ DP Controller: Required properties: within DP AUX, while the remaining entries indicate the programmable values. - qcom,max-pclk-frequency-khz: An integer specifying the max. pixel clock in KHz supported by Display Port. +- qcom,yuv-support: A boolean specifying if any YUV formats are supported by Display Port. - qcom,dp-usbpd-detection: Phandle for the PMI regulator node for USB PHY PD detection. - qcom,-supply-entries: A node that lists the elements of the supply used by the a particular "type" of DSI module. The module "types" can be "core", "ctrl", and "phy". Within the same type, diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index 240bc5b4f292dd02f871fc30fbd0a6b62993c4f8..41c98e3e90740d13c651c05dd88362a0f1db3cf5 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -521,6 +521,7 @@ the fps window. in floating state(not LP00 or LP11) to turn on this property. Software turns off PHY pmic power supply, phy ldo and DSI Lane ldo during idle screen (footswitch control off) when this property is enabled. +- qcom,skip-panel-reset: Boolean. when set, will skip panel reset during panel ON/OFF. [[Optional config sub-nodes]] These subnodes provide different configurations for a given same panel. Default configuration can be chosen by specifying phandle of the selected subnode in the qcom,config-select. diff --git a/Documentation/devicetree/bindings/input/touchscreen/raydium_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/raydium_ts.txt new file mode 100644 index 0000000000000000000000000000000000000000..4e640e01cf7dcfab3d57c33d358a8e6619391413 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/raydium_ts.txt @@ -0,0 +1,52 @@ +Raydium WT030 touch controller + +Please add this description here: The Raydium Touch controller is connected to the +host processor via I2C. The controller generates interrupts when the user touches +the panel. The host controller is expected to read the touch coordinates over I2C and +pass the coordinates to the rest of the system. + +Required properties: + + - compatible : should be "raydium,raydium-ts". + - reg : i2c slave address of the device. + - interrupt-parent : parent of interrupt. + - raydium,irq-gpio : irq gpio. + - raydium,reset-gpio : reset gpio. + - vdd_ana-supply : analog voltage power supply needed to power device. + - vcc_i2c-supply : i2c voltage power supply needed to power device. + +Optional property: + - raydium,max-num-touches : addr of ub-i2c. + - raydium,display-coords : array of display coordinates. + - raydium,x_max : maximal x value of the panel. + - raydium,y_max : maximal y value of the panel. + - raydium,fw_id : firmare id. + - raydium,soft-reset-delay-ms : reset delay for controller (ms), default 100. + - raydium,hard-reset-delay-ms : reset delay for controller (ms), default 100. + +Example: + i2c@78b7000 { + status = "ok"; + raydium_ts@39 { + compatible = "raydium,raydium-ts"; + reg = <0x39>; + interrupt-parent = <&msm_gpio>; + interrupts = <13 0x2008>; + vdd_ana-supply = <&pm8916_l17>; + vcc_i2c-supply = <&pm8916_l6>; + pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + raydium,reset-gpio = <&msm_gpio 12 0x00>; + raydium,irq-gpio = <&msm_gpio 13 0x00>; + raydium,num-max-touches = <2>; + raydium,soft-reset-delay-ms = <50>; + raydium,hard-reset-delay-ms = <100>; + raydium,x_max = <390>; + raydium,y_max = <390>; + raydium,display-coords= <0 0 390 390>; + raydium,fw_id = <0x2202> + }; + }; + diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt index b43b2954e50254056b57e32f2098965dde1a9fc4..5f118dec544489021917d11da84683d82a22a25c 100644 --- a/Documentation/devicetree/bindings/media/video/msm-cci.txt +++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt @@ -338,6 +338,7 @@ Example: clocks = <&clock_mmss clk_mclk0_clk_src>, <&clock_mmss clk_camss_mclk0_clk>; clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; }; &i2c_freq_100Khz { diff --git a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt index be789685a1c24256e8b9846121ccb407d9f39e94..18b892d010d87772c49db004cd48e68c8195a614 100644 --- a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt +++ b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt @@ -27,4 +27,4 @@ and valid to enable charging: - "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V) - "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output - resistor, the other values are in ohm. + resistor, the other values are in kOhm. diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index bdd025ceb763b112a01ff18dc6d04d866e7240e7..85ed3450099a410241d7a26f09c4792f69fc18c7 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -596,3 +596,10 @@ in your dentry operations instead. [mandatory] ->rename() has an added flags argument. Any flags not handled by the filesystem should result in EINVAL being returned. +-- +[mandatory] + + [should've been added in 2016] stale comment in finish_open() + nonwithstanding, failure exits in ->atomic_open() instances should + *NOT* fput() the file, no matter what. Everything is handled by the + caller. diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 9b9c4797fc55653dec668d82ae8c43ccdab58e4b..e988247886fbd6ee7bc1fcdaa2a31196250f0616 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -44,11 +44,10 @@ This document describes the Linux kernel Makefiles. --- 6.11 Post-link pass === 7 Kbuild syntax for exported headers - --- 7.1 header-y - --- 7.2 genhdr-y - --- 7.3 destination-y - --- 7.4 generic-y - --- 7.5 generated-y + --- 7.1 no-export-headers-y + --- 7.2 generic-y + --- 7.3 generated-y + --- 7.4 mandatory-y === 8 Kbuild Variables === 9 Makefile language @@ -1236,7 +1235,7 @@ When kbuild executes, the following steps are followed (roughly): that may be shared between individual architectures. The recommended approach how to use a generic header file is to list the file in the Kbuild file. - See "7.4 generic-y" for further info on syntax etc. + See "7.2 generic-y" for further info on syntax etc. --- 6.11 Post-link pass @@ -1263,53 +1262,21 @@ The pre-processing does: - drop include of compiler.h - drop all sections that are kernel internal (guarded by ifdef __KERNEL__) -Each relevant directory contains a file name "Kbuild" which specifies the -headers to be exported. -See subsequent chapter for the syntax of the Kbuild file. - - --- 7.1 header-y - - header-y specifies header files to be exported. - - Example: - #include/linux/Kbuild - header-y += usb/ - header-y += aio_abi.h - - The convention is to list one file per line and - preferably in alphabetic order. - - header-y also specifies which subdirectories to visit. - A subdirectory is identified by a trailing '/' which - can be seen in the example above for the usb subdirectory. - - Subdirectories are visited before their parent directories. - - --- 7.2 genhdr-y - - genhdr-y specifies generated files to be exported. - Generated files are special as they need to be looked - up in another directory when doing 'make O=...' builds. +All headers under include/uapi/, include/generated/uapi/, +arch//include/uapi/ and arch//include/generated/uapi/ +are exported. - Example: - #include/linux/Kbuild - genhdr-y += version.h - - --- 7.3 destination-y - - When an architecture has a set of exported headers that needs to be - exported to a different directory destination-y is used. - destination-y specifies the destination directory for all exported - headers in the file where it is present. +A Kbuild file may be defined under arch//include/uapi/asm/ and +arch//include/asm/ to list asm files coming from asm-generic. +See subsequent chapter for the syntax of the Kbuild file. - Example: - #arch/xtensa/platforms/s6105/include/platform/Kbuild - destination-y := include/linux + --- 7.1 no-export-headers - In the example above all exported headers in the Kbuild file - will be located in the directory "include/linux" when exported. + no-export-headers is essentially used by include/uapi/linux/Kbuild to + avoid exporting specific headers (e.g. kvm.h) on architectures that do + not support it. It should be avoided as much as possible. - --- 7.4 generic-y + --- 7.2 generic-y If an architecture uses a verbatim copy of a header from include/asm-generic then this is listed in the file @@ -1336,11 +1303,10 @@ See subsequent chapter for the syntax of the Kbuild file. Example: termios.h #include - --- 7.5 generated-y + --- 7.3 generated-y If an architecture generates other header files alongside generic-y - wrappers, and not included in genhdr-y, then generated-y specifies - them. + wrappers, generated-y specifies them. This prevents them being treated as stale asm-generic wrappers and removed. @@ -1349,6 +1315,15 @@ See subsequent chapter for the syntax of the Kbuild file. #arch/x86/include/asm/Kbuild generated-y += syscalls_32.h + --- 7.4 mandatory-y + + mandatory-y is essentially used by include/uapi/asm-generic/Kbuild.asm + to define the minimun set of headers that must be exported in + include/asm. + + The convention is to list one subdir per line and + preferably in alphabetic order. + === 8 Kbuild Variables The top Makefile exports the following variables: diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4d2938c1c6c63f7948b37eda72c03134ed5c9989..cf766467134b166215d88a667050f7eab0730922 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -336,6 +336,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. dynamic table installation which will install SSDT tables to /sys/firmware/acpi/tables/dynamic. + acpi_no_watchdog [HW,ACPI,WDT] + Ignore the ACPI-based watchdog interface (WDAT) and let + a native driver control the watchdog device instead. + acpi_rsdp= [ACPI,EFI,KEXEC] Pass the RSDP address to the kernel, mostly used on machines running EFI runtime service to boot the @@ -1987,6 +1991,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. kmemcheck=2 (one-shot mode) Default: 2 (one-shot mode) + kpti= [ARM64] Control page table isolation of user + and kernel address spaces. + Default: enabled on cores which need mitigation. + 0: force disabled + 1: force enabled + kstack=N [X86] Print N words from the kernel stack in oops dumps. diff --git a/MAINTAINERS b/MAINTAINERS index 01e7290ef9058682998a2799d280ab4d26a899c4..9bb64d03cdc488e649f850b98632f52dba0961fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8606,6 +8606,12 @@ S: Maintained F: Documentation/scsi/NinjaSCSI.txt F: drivers/scsi/nsp32* +NINTENDO HID DRIVER +M: Daniel J. Ogorchock +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/hid/hid-nintendo* + NIOS2 ARCHITECTURE M: Ley Foon Tan L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) diff --git a/Makefile b/Makefile index 3cad17b5b676276fb9cebd4265b1d6590d69e576..874a3a7f03f3c3547745d59597418cb56dabdd92 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 9 -SUBLEVEL = 206 +SUBLEVEL = 217 EXTRAVERSION = NAME = Roaring Lionus @@ -1300,7 +1300,7 @@ firmware_install: export INSTALL_HDR_PATH = $(objtree)/usr # If we do an all arch process set dst to asm-$(hdr-arch) -hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) +hdr-dst = $(if $(KBUILD_HEADERS), dst=include/arch-$(hdr-arch), dst=include) PHONY += archheaders archheaders: @@ -1321,7 +1321,7 @@ headers_install: __headers $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),, \ $(error Headers not exportable for the $(SRCARCH) architecture)) $(Q)$(MAKE) $(hdr-inst)=include/uapi - $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst) $(Q)$(MAKE) $(hdr-inst)=techpack PHONY += headers_check_all @@ -1331,7 +1331,7 @@ headers_check_all: headers_install_all PHONY += headers_check headers_check: headers_install $(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1 - $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1 + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst) HDRCHECK=1 $(Q)$(MAKE) $(hdr-inst)=techpack HDRCHECK=1 # --------------------------------------------------------------------------- @@ -1650,9 +1650,6 @@ else # KBUILD_EXTMOD # We are always building modules KBUILD_MODULES := 1 -PHONY += crmodverdir -crmodverdir: - $(cmd_crmodverdir) PHONY += $(objtree)/Module.symvers $(objtree)/Module.symvers: @@ -1664,7 +1661,7 @@ $(objtree)/Module.symvers: module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) PHONY += $(module-dirs) modules -$(module-dirs): crmodverdir $(objtree)/Module.symvers +$(module-dirs): prepare $(objtree)/Module.symvers $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) modules: $(module-dirs) @@ -1705,7 +1702,8 @@ help: # Dummies... PHONY += prepare scripts -prepare: ; +prepare: + $(cmd_crmodverdir) scripts: ; endif # KBUILD_EXTMOD @@ -1831,17 +1829,14 @@ endif # Modules /: prepare scripts FORCE - $(cmd_crmodverdir) $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ $(build)=$(build-dir) # Make sure the latest headers are built for Documentation Documentation/ samples/: headers_install %/: prepare scripts FORCE - $(cmd_crmodverdir) $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ $(build)=$(build-dir) %.ko: prepare scripts FORCE - $(cmd_crmodverdir) $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ $(build)=$(build-dir) $(@:.ko=.o) $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost diff --git a/arch/alpha/include/uapi/asm/Kbuild b/arch/alpha/include/uapi/asm/Kbuild index d96f2ef5b639c33bd70f13cc3b48a162072a90c7..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/alpha/include/uapi/asm/Kbuild +++ b/arch/alpha/include/uapi/asm/Kbuild @@ -1,43 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += a.out.h -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += compiler.h -header-y += console.h -header-y += errno.h -header-y += fcntl.h -header-y += fpu.h -header-y += gentrap.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += pal.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += reg.h -header-y += regdef.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += sysinfo.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi index d6c1bbc98ac3b40caa94e60420996081bdafe44c..15698b3e490ff1ed3c2fab88f7d9579ff6c3b933 100644 --- a/arch/arc/boot/dts/axs10x_mb.dtsi +++ b/arch/arc/boot/dts/axs10x_mb.dtsi @@ -63,6 +63,7 @@ interrupt-names = "macirq"; phy-mode = "rgmii"; snps,pbl = < 32 >; + snps,multicast-filter-bins = <256>; clocks = <&apbclk>; clock-names = "stmmaceth"; max-speed = <100>; diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index b29f1a9fd6f7359957389d5cd30725b7a449f579..07c8e1a6c56e25dd40463107809e40491baac77c 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -14,6 +14,8 @@ #ifdef __ASSEMBLY__ #define ASM_NL ` /* use '`' to mark new line in macro */ +#define __ALIGN .align 4 +#define __ALIGN_STR __stringify(__ALIGN) /* annotation for data we want in DCCM - if enabled in .config */ .macro ARCFP_DATA nm diff --git a/arch/arc/include/uapi/asm/Kbuild b/arch/arc/include/uapi/asm/Kbuild index f50d02df78d5ec94a9fc15bed9b44096fcbca5b1..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/arc/include/uapi/asm/Kbuild +++ b/arch/arc/include/uapi/asm/Kbuild @@ -1,5 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += elf.h -header-y += page.h -header-y += cachectl.h diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig index 1d175cc6ad6d3b6a8b08dfdf4c354c9e5efafb0e..86f844caa405d47e9110fea702b1932a9266eb29 100644 --- a/arch/arc/plat-eznps/Kconfig +++ b/arch/arc/plat-eznps/Kconfig @@ -7,7 +7,7 @@ menuconfig ARC_PLAT_EZNPS bool "\"EZchip\" ARC dev platform" select ARC_HAS_COH_CACHES if SMP select CPU_BIG_ENDIAN - select CLKSRC_NPS + select CLKSRC_NPS if !PHYS_ADDR_T_64BIT select EZNPS_GIC select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET help diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8f70fb1460264dee3438f2009c90be19aec202de..76b0f4131eaff25d03534a7edb16c115c0bb5fd2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2130,7 +2130,7 @@ config XIP_PHYS_ADDR config KEXEC bool "Kexec system call (EXPERIMENTAL)" depends on (!SMP || PM_SLEEP_SMP) - depends on !CPU_V7M + depends on MMU select KEXEC_CORE help kexec is a system call that implements the ability to shutdown your diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 5499f95f140aaca7a070a15ee390852bec6e34b6..cb8b76cdd92fdb3bdf8f105e7fe5dc80f5a85b6e 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1002,14 +1002,21 @@ choice Say Y here if you want kernel low-level debugging support on SOCFPGA(Cyclone 5 and Arria 5) based platforms. - config DEBUG_SOCFPGA_UART1 + config DEBUG_SOCFPGA_ARRIA10_UART1 depends on ARCH_SOCFPGA - bool "Use SOCFPGA UART1 for low-level debug" + bool "Use SOCFPGA Arria10 UART1 for low-level debug" select DEBUG_UART_8250 help Say Y here if you want kernel low-level debugging support on SOCFPGA(Arria 10) based platforms. + config DEBUG_SOCFPGA_CYCLONE5_UART1 + depends on ARCH_SOCFPGA + bool "Use SOCFPGA Cyclone 5 UART1 for low-level debug" + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on SOCFPGA(Cyclone 5 and Arria 5) based platforms. config DEBUG_SUN9I_UART0 bool "Kernel low-level debugging messages via sun9i UART0" @@ -1549,7 +1556,8 @@ config DEBUG_UART_PHYS default 0xfe800000 if ARCH_IOP32X default 0xff690000 if DEBUG_RK32_UART2 default 0xffc02000 if DEBUG_SOCFPGA_UART0 - default 0xffc02100 if DEBUG_SOCFPGA_UART1 + default 0xffc02100 if DEBUG_SOCFPGA_ARRIA10_UART1 + default 0xffc03000 if DEBUG_SOCFPGA_CYCLONE5_UART1 default 0xffd82340 if ARCH_IOP13XX default 0xffe40000 if DEBUG_RCAR_GEN1_SCIF0 default 0xffe42000 if DEBUG_RCAR_GEN1_SCIF2 @@ -1639,7 +1647,8 @@ config DEBUG_UART_VIRT default 0xfeb30c00 if DEBUG_KEYSTONE_UART0 default 0xfeb31000 if DEBUG_KEYSTONE_UART1 default 0xfec02000 if DEBUG_SOCFPGA_UART0 - default 0xfec02100 if DEBUG_SOCFPGA_UART1 + default 0xfec02100 if DEBUG_SOCFPGA_ARRIA10_UART1 + default 0xfec03000 if DEBUG_SOCFPGA_CYCLONE5_UART1 default 0xfec12000 if (DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE) && ARCH_MVEBU default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE default 0xfec10000 if DEBUG_SIRFATLAS7_UART0 @@ -1687,9 +1696,9 @@ config DEBUG_UART_8250_WORD depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 depends on DEBUG_UART_8250_SHIFT >= 2 default y if DEBUG_PICOXCELL_UART || \ - DEBUG_SOCFPGA_UART0 || DEBUG_SOCFPGA_UART1 || \ - DEBUG_KEYSTONE_UART0 || DEBUG_KEYSTONE_UART1 || \ - DEBUG_ALPINE_UART0 || \ + DEBUG_SOCFPGA_UART0 || DEBUG_SOCFPGA_ARRIA10_UART1 || \ + DEBUG_SOCFPGA_CYCLONE5_UART1 || DEBUG_KEYSTONE_UART0 || \ + DEBUG_KEYSTONE_UART1 || DEBUG_ALPINE_UART0 || \ DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \ DEBUG_DAVINCI_DA8XX_UART2 || \ DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2 diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 9117e86d7c2832e3bce3cbf0e773f4255e5434ce..963a87972cc88ae2e145d2f58de359b089b6cd4d 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -328,8 +328,11 @@ all: $(KBUILD_IMAGE) $(KBUILD_DTBS) boot := arch/arm/boot +archheaders: + $(Q)$(MAKE) $(build)=arch/arm/tools uapi + archprepare: - $(Q)$(MAKE) $(build)=arch/arm/tools include/generated/mach-types.h + $(Q)$(MAKE) $(build)=arch/arm/tools kapi # Convert bzImage to zImage bzImage: zImage diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h index 005bf4ff1b4cb9a9e31558fb146291252039b829..f3ddd4f599e3eabb8eda20d3784fad2373d4ab5f 100644 --- a/arch/arm/boot/compressed/libfdt_env.h +++ b/arch/arm/boot/compressed/libfdt_env.h @@ -1,11 +1,13 @@ #ifndef _ARM_LIBFDT_ENV_H #define _ARM_LIBFDT_ENV_H +#include #include #include #include -#define INT_MAX ((int)(~0U>>1)) +#define INT32_MAX S32_MAX +#define UINT32_MAX U32_MAX typedef __be16 fdt16_t; typedef __be32 fdt32_t; diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index 957840cc7b78748f06530d3aafa8dcf13b271001..b55c094893c635d5be134c050cd4b9f836500fad 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -79,7 +79,7 @@ }; lcd0: display { - compatible = "osddisplays,osd057T0559-34ts", "panel-dpi"; + compatible = "osddisplays,osd070t1718-19ts", "panel-dpi"; label = "lcd"; panel-timing { diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 9d35c3f07cad70ba7d72927cc1c0b3749a07a8d3..21918807c9f6da86199bcbeaf75ce5f67bf8048d 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -41,7 +41,7 @@ }; lcd0: display { - compatible = "osddisplays,osd057T0559-34ts", "panel-dpi"; + compatible = "osddisplays,osd070t1718-19ts", "panel-dpi"; label = "lcd"; panel-timing { diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi index 78bee26361f15847ccc0a950a61d201de9e3feb2..552de167f95fe0371ea9c9d750c744496c671490 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi +++ b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi @@ -27,6 +27,27 @@ reg = <0x0 0x80000000 0x0 0x80000000>; }; + main_12v0: fixedregulator-main_12v0 { + /* main supply */ + compatible = "regulator-fixed"; + regulator-name = "main_12v0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + regulator-boot-on; + }; + + evm_5v0: fixedregulator-evm_5v0 { + /* Output of TPS54531D */ + compatible = "regulator-fixed"; + regulator-name = "evm_5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&main_12v0>; + regulator-always-on; + regulator-boot-on; + }; + vdd_3v3: fixedregulator-vdd_3v3 { compatible = "regulator-fixed"; regulator-name = "vdd_3v3"; diff --git a/arch/arm/boot/dts/arm-realview-pb1176.dts b/arch/arm/boot/dts/arm-realview-pb1176.dts index c1fd5615ddfe3ab8c1ef01bd7e8ec19c4d043928..939c108c24a6cca46665471cb837570f7355e1ec 100644 --- a/arch/arm/boot/dts/arm-realview-pb1176.dts +++ b/arch/arm/boot/dts/arm-realview-pb1176.dts @@ -45,7 +45,7 @@ }; /* The voltage to the MMC card is hardwired at 3.3V */ - vmmc: fixedregulator@0 { + vmmc: regulator-vmmc { compatible = "regulator-fixed"; regulator-name = "vmmc"; regulator-min-microvolt = <3300000>; @@ -53,7 +53,7 @@ regulator-boot-on; }; - veth: fixedregulator@0 { + veth: regulator-veth { compatible = "regulator-fixed"; regulator-name = "veth"; regulator-min-microvolt = <3300000>; diff --git a/arch/arm/boot/dts/arm-realview-pb11mp.dts b/arch/arm/boot/dts/arm-realview-pb11mp.dts index e306f1cceb4ecced70fc2879fb2e23062b60c5a5..95037c48182de9a7b0528757b65b81627030b823 100644 --- a/arch/arm/boot/dts/arm-realview-pb11mp.dts +++ b/arch/arm/boot/dts/arm-realview-pb11mp.dts @@ -145,7 +145,7 @@ }; /* The voltage to the MMC card is hardwired at 3.3V */ - vmmc: fixedregulator@0 { + vmmc: regulator-vmmc { compatible = "regulator-fixed"; regulator-name = "vmmc"; regulator-min-microvolt = <3300000>; @@ -153,7 +153,7 @@ regulator-boot-on; }; - veth: fixedregulator@0 { + veth: regulator-veth { compatible = "regulator-fixed"; regulator-name = "veth"; regulator-min-microvolt = <3300000>; diff --git a/arch/arm/boot/dts/arm-realview-pbx.dtsi b/arch/arm/boot/dts/arm-realview-pbx.dtsi index 2bf3958b2e6b9fe605710947d1ad1c81902a4d51..068293254fbb8fefafaf05cab0a50f2eeab5bd7c 100644 --- a/arch/arm/boot/dts/arm-realview-pbx.dtsi +++ b/arch/arm/boot/dts/arm-realview-pbx.dtsi @@ -43,7 +43,7 @@ }; /* The voltage to the MMC card is hardwired at 3.3V */ - vmmc: fixedregulator@0 { + vmmc: regulator-vmmc { compatible = "regulator-fixed"; regulator-name = "vmmc"; regulator-min-microvolt = <3300000>; @@ -51,7 +51,7 @@ regulator-boot-on; }; - veth: fixedregulator@0 { + veth: regulator-veth { compatible = "regulator-fixed"; regulator-name = "veth"; regulator-min-microvolt = <3300000>; @@ -539,4 +539,3 @@ }; }; }; - diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi index 51dbd8cb91cb5bb6ae222c8c3dc601216db93789..99b3d233197196f967780d8f19a3fab06870b783 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/exynos3250.dtsi @@ -345,7 +345,7 @@ }; hsotg: hsotg@12480000 { - compatible = "snps,dwc2"; + compatible = "samsung,s3c6400-hsotg", "snps,dwc2"; reg = <0x12480000 0x20000>; interrupts = <0 141 0>; clocks = <&cmu CLK_USBOTG>; diff --git a/arch/arm/boot/dts/lpc3250-phy3250.dts b/arch/arm/boot/dts/lpc3250-phy3250.dts index b7bd3a110a8dd0cb9f07144af4ff46a9a51f63c8..dd0bdf765599dd6051ea2e89ce4d3b6b519f7e46 100644 --- a/arch/arm/boot/dts/lpc3250-phy3250.dts +++ b/arch/arm/boot/dts/lpc3250-phy3250.dts @@ -49,8 +49,8 @@ sd_reg: regulator@2 { compatible = "regulator-fixed"; regulator-name = "sd_reg"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; gpio = <&gpio 5 5 0>; enable-active-high; }; diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index 5fa3111731cb0530e9bbbce6b9ed9be81daecf2d..2802c9565b6ca7815798614865cf9d86a582927f 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -139,11 +139,11 @@ }; clcd: clcd@31040000 { - compatible = "arm,pl110", "arm,primecell"; + compatible = "arm,pl111", "arm,primecell"; reg = <0x31040000 0x1000>; interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk LPC32XX_CLK_LCD>; - clock-names = "apb_pclk"; + clocks = <&clk LPC32XX_CLK_LCD>, <&clk LPC32XX_CLK_LCD>; + clock-names = "clcdclk", "apb_pclk"; status = "disabled"; }; @@ -462,7 +462,9 @@ key: key@40050000 { compatible = "nxp,lpc3220-key"; reg = <0x40050000 0x1000>; - interrupts = <54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk LPC32XX_CLK_KEY>; + interrupt-parent = <&sic1>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts index 44715c8ef756b9f44bdc7a7c69b0cdc12c26d93d..72a3fc63d0ece95bcd41ab26d85199678ea4f6e7 100644 --- a/arch/arm/boot/dts/ls1021a-twr.dts +++ b/arch/arm/boot/dts/ls1021a-twr.dts @@ -143,7 +143,7 @@ }; &enet0 { - tbi-handle = <&tbi1>; + tbi-handle = <&tbi0>; phy-handle = <&sgmii_phy2>; phy-connection-type = "sgmii"; status = "okay"; @@ -222,6 +222,13 @@ sgmii_phy2: ethernet-phy@2 { reg = <0x2>; }; + tbi0: tbi-phy@1f { + reg = <0x1f>; + device_type = "tbi-phy"; + }; +}; + +&mdio1 { tbi1: tbi-phy@1f { reg = <0x1f>; device_type = "tbi-phy"; diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index 825f6eae3d1c1ce08cab50e991a075beb5537b8d..0de4ba698d1db1465c7e2bd92f799f52e019e2ec 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -512,6 +512,15 @@ reg = <0x0 0x2d24000 0x0 0x4000>; }; + mdio1: mdio@2d64000 { + compatible = "gianfar"; + device_type = "mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2d64000 0x0 0x4000>, + <0x0 0x2d50030 0x0 0x4>; + }; + ptp_clock@2d10e00 { compatible = "fsl,etsec-ptp"; reg = <0x0 0x2d10e00 0x0 0xb0>; diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi index 47e5b63339d18fbd6d67f1382558bfc182faffba..e95deed6a7973ddff8b4a96a91dc078c70e23576 100644 --- a/arch/arm/boot/dts/mmp2.dtsi +++ b/arch/arm/boot/dts/mmp2.dtsi @@ -180,7 +180,7 @@ clocks = <&soc_clocks MMP2_CLK_GPIO>; resets = <&soc_clocks MMP2_CLK_GPIO>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; ranges; gcb0: gpio@d4019000 { diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi index 53e007abdc7159ee69fd35a120ba30edb0704e3c..964240a0f4a97bc55e8c445026012705993e8af7 100644 --- a/arch/arm/boot/dts/omap3-pandora-common.dtsi +++ b/arch/arm/boot/dts/omap3-pandora-common.dtsi @@ -221,6 +221,17 @@ gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>; /* GPIO_164 */ }; + /* wl1251 wifi+bt module */ + wlan_en: fixed-regulator-wg7210_en { + compatible = "regulator-fixed"; + regulator-name = "vwlan"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <50000>; + enable-active-high; + gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + /* wg7210 (wifi+bt module) 32k clock buffer */ wg7210_32k: fixed-regulator-wg7210_32k { compatible = "regulator-fixed"; @@ -514,9 +525,30 @@ /*wp-gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;*/ /* GPIO_127 */ }; -/* mmc3 is probed using pdata-quirks to pass wl1251 card data */ &mmc3 { - status = "disabled"; + vmmc-supply = <&wlan_en>; + + bus-width = <4>; + non-removable; + ti,non-removable; + cap-power-off-card; + + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins>; + + #address-cells = <1>; + #size-cells = <0>; + + wlan: wifi@1 { + compatible = "ti,wl1251"; + + reg = <1>; + + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* GPIO_21 */ + + ti,wl1251-has-eeprom; + }; }; /* bluetooth*/ diff --git a/arch/arm/boot/dts/omap3-tao3530.dtsi b/arch/arm/boot/dts/omap3-tao3530.dtsi index dc80886b532929eee49ba45608003cf93b9bed1d..e3dfba8b3efec95583dc39e7eb5b5a3121afa798 100644 --- a/arch/arm/boot/dts/omap3-tao3530.dtsi +++ b/arch/arm/boot/dts/omap3-tao3530.dtsi @@ -225,7 +225,7 @@ pinctrl-0 = <&mmc1_pins>; vmmc-supply = <&vmmc1>; vmmc_aux-supply = <&vsim>; - cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_HIGH>; + cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>; bus-width = <8>; }; diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi index 0e1320afa15620df2eb2781da0c0fae613788b70..d629948000db18d4a2ac600858801ff25160f95a 100644 --- a/arch/arm/boot/dts/pxa27x.dtsi +++ b/arch/arm/boot/dts/pxa27x.dtsi @@ -34,7 +34,7 @@ clocks = <&clks CLK_NONE>; }; - pxa27x_ohci: usb@4c000000 { + usb0: usb@4c000000 { compatible = "marvell,pxa-ohci"; reg = <0x4c000000 0x10000>; interrupts = <3>; diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi index 3ff077ca440028a7a1bc6a01f7a36258286927bf..5a6f4ed92dac3fe98330a70d4c14e283336dc30a 100644 --- a/arch/arm/boot/dts/pxa2xx.dtsi +++ b/arch/arm/boot/dts/pxa2xx.dtsi @@ -117,13 +117,6 @@ status = "disabled"; }; - usb0: ohci@4c000000 { - compatible = "marvell,pxa-ohci"; - reg = <0x4c000000 0x10000>; - interrupts = <3>; - status = "disabled"; - }; - mmc0: mmc@41100000 { compatible = "marvell,pxa-mmc"; reg = <0x41100000 0x1000>; diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi index 9d6f3aacedb709e4cd086d0df0bcac4dd3e7586b..4aee1506269025f157a2fde813dfb339693e6c23 100644 --- a/arch/arm/boot/dts/pxa3xx.dtsi +++ b/arch/arm/boot/dts/pxa3xx.dtsi @@ -187,7 +187,7 @@ status = "disabled"; }; - pxa3xx_ohci: usb@4c000000 { + usb0: usb@4c000000 { compatible = "marvell,pxa-ohci"; reg = <0x4c000000 0x10000>; interrupts = <3>; diff --git a/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts index 2eaca0282ab2d72d77f7f1ff3a46ccf54c014479..a14ad6f7eb6333230d4d518cfa27cf36291c5d02 100644 --- a/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts +++ b/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019-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 @@ -58,3 +58,7 @@ &mhi_net_device { status = "okay"; }; + +&sdx_ext_ipc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi b/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi index 91ebc96377848837d560dca1b01b78deac82aaa8..a1649bbf848e9e73b51cac17ff60069aa6f7b0c6 100644 --- a/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi +++ b/arch/arm/boot/dts/qcom/sa415m-ccard.dtsi @@ -146,6 +146,15 @@ gpio = <&tlmm 23 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + sdx_ext_ipc: qcom,sdx_ext_ipc { + compatible = "qcom,sdx-ext-ipc"; + qcom,ap2mdm-status-gpio = <&tlmm 95 0x00>; + qcom,mdm2ap-status-gpio = <&tlmm 36 0x00>; + qcom,mdm2ap-status2-gpio = <&tlmm 88 0x00>; + status = "disabled"; + }; + }; &emac_hw { diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts index 1e4c7231735faec9ec0204b36bc78abae4427615..7d913307c3a89d44ec73bc4c6baa53f4cba9fc1d 100644 --- a/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts +++ b/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts @@ -20,6 +20,26 @@ compatible = "qcom,sa415m-ttp", "qcom,sdxpoorwills", "qcom,ttp"; qcom,board-id = <30 0x102>; + + qcom_gadget { + compatible = "qcom,usb-gadget"; + qcom,vid = <0x05c6>; + + composition1 { + qcom,pid = <0x9103>; + qcom,composition = "diag.diag,ipc.ipc,gsi.rmnet,gsi.rmnet.v2x,ecm.ecm,gsi.dpl"; + }; + + composition2 { + qcom,pid = <0x9105>; + qcom,composition = "diag.diag,gsi.dpl"; + }; + + composition3 { + qcom,pid = <0x9107>; + qcom,composition = "diag.diag,ipc.ipc,gsi.rmnet.v2x,gsi.ecm,gsi.dpl"; + }; + }; }; &blsp1_uart2b_hs { diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi index 289c539c276d263ff45d97977708b760c2b9e788..e0b4b6f1f56d5c0d7f7b9127a15335fe8d8904a5 100644 --- a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi +++ b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi @@ -147,6 +147,7 @@ interrupt-parent = <&tlmm>; interrupts = <78 IRQ_TYPE_EDGE_RISING>; st,drdy-int-pin= <2>; + qcom,asm330_hrtimer; }; }; diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi index 484d29eddf1bff857d30ccc0329226b2ddddf66c..ce5ba9380cb773cf429bd6b68e472fb64096d935 100644 --- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi @@ -1771,7 +1771,7 @@ &pmxpoorwills_gpios { a2b_cdc_sel { a2b_cdc_sel_default: a2b_cdc_sel_default { - pins = "gpio1"; + pins = "gpio5"; power-source = <1>; output-high; }; diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi index 75716613f0e01328ae51fa823726e43352f8dc40..e9c35d3e1ec8013c1b867a7d3b743b3798525860 100644 --- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi +++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-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 @@ -836,7 +836,7 @@ qcom,smem-id = <421>; qcom,proxy-timeout-ms = <10000>; qcom,sysmon-id = <0>; - qcom,ssctl-instance-id = <0x12>; + qcom,ssctl-instance-id = <0x22>; qcom,firmware-name = "modem"; memory-region = <&mss_mem>; status = "ok"; @@ -846,6 +846,7 @@ qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>; qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>; qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>; + qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>; /* GPIO output to mss */ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>; diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index b9bbcce69dfbd5b9efda7ae20a83752cf459c925..6c6d4893e92d40574a7839d38e88a1130877359b 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -67,6 +67,14 @@ <0xf0000100 0x100>; }; + timer@f0000200 { + compatible = "arm,cortex-a9-global-timer"; + reg = <0xf0000200 0x100>; + interrupts = ; + clocks = <&cpg_clocks R8A7779_CLK_ZS>; + }; + timer@f0000600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0xf0000600 0x20>; diff --git a/arch/arm/boot/dts/rk3288-rock2-som.dtsi b/arch/arm/boot/dts/rk3288-rock2-som.dtsi index bb1f01e037ba7e2a5ae8126ccff5d98b16f4a0a0..c1c576875bc857d9a438303fb22a5adef94c6081 100644 --- a/arch/arm/boot/dts/rk3288-rock2-som.dtsi +++ b/arch/arm/boot/dts/rk3288-rock2-som.dtsi @@ -63,7 +63,7 @@ vcc_flash: flash-regulator { compatible = "regulator-fixed"; - regulator-name = "vcc_sys"; + regulator-name = "vcc_flash"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; startup-delay-us = <150>; diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/s3c6410-mini6410.dts index f4afda3594f8a7f272b1d7cbc8997263f7130601..de04d8764b0f946d73927e0cd159dd64cd67556f 100644 --- a/arch/arm/boot/dts/s3c6410-mini6410.dts +++ b/arch/arm/boot/dts/s3c6410-mini6410.dts @@ -167,6 +167,10 @@ }; }; +&clocks { + clocks = <&fin_pll>; +}; + &sdhci0 { pinctrl-names = "default"; pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>; diff --git a/arch/arm/boot/dts/s3c6410-smdk6410.dts b/arch/arm/boot/dts/s3c6410-smdk6410.dts index ecf35ec466f7fd6150d8717730372b5ad1f609db..7ade1a0686d2f0e98520cf1cbea411d92defb3c2 100644 --- a/arch/arm/boot/dts/s3c6410-smdk6410.dts +++ b/arch/arm/boot/dts/s3c6410-smdk6410.dts @@ -71,6 +71,10 @@ }; }; +&clocks { + clocks = <&fin_pll>; +}; + &sdhci0 { pinctrl-names = "default"; pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>; diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 4c84d333fc7e60247bc9325ea132872d2b3d0011..33c0d26689347ce4b07e103f54ee178bb5b028ff 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -1109,49 +1109,49 @@ usart0_clk: usart0_clk { #clock-cells = <0>; reg = <12>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; usart1_clk: usart1_clk { #clock-cells = <0>; reg = <13>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; usart2_clk: usart2_clk { #clock-cells = <0>; reg = <14>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; usart3_clk: usart3_clk { #clock-cells = <0>; reg = <15>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; uart0_clk: uart0_clk { #clock-cells = <0>; reg = <16>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; twi0_clk: twi0_clk { reg = <18>; #clock-cells = <0>; - atmel,clk-output-range = <0 16625000>; + atmel,clk-output-range = <0 41500000>; }; twi1_clk: twi1_clk { #clock-cells = <0>; reg = <19>; - atmel,clk-output-range = <0 16625000>; + atmel,clk-output-range = <0 41500000>; }; twi2_clk: twi2_clk { #clock-cells = <0>; reg = <20>; - atmel,clk-output-range = <0 16625000>; + atmel,clk-output-range = <0 41500000>; }; mci0_clk: mci0_clk { @@ -1167,19 +1167,19 @@ spi0_clk: spi0_clk { #clock-cells = <0>; reg = <24>; - atmel,clk-output-range = <0 133000000>; + atmel,clk-output-range = <0 166000000>; }; spi1_clk: spi1_clk { #clock-cells = <0>; reg = <25>; - atmel,clk-output-range = <0 133000000>; + atmel,clk-output-range = <0 166000000>; }; tcb0_clk: tcb0_clk { #clock-cells = <0>; reg = <26>; - atmel,clk-output-range = <0 133000000>; + atmel,clk-output-range = <0 166000000>; }; pwm_clk: pwm_clk { @@ -1190,7 +1190,7 @@ adc_clk: adc_clk { #clock-cells = <0>; reg = <29>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; dma0_clk: dma0_clk { @@ -1221,13 +1221,13 @@ ssc0_clk: ssc0_clk { #clock-cells = <0>; reg = <38>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; ssc1_clk: ssc1_clk { #clock-cells = <0>; reg = <39>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; sha_clk: sha_clk { diff --git a/arch/arm/boot/dts/sama5d3_can.dtsi b/arch/arm/boot/dts/sama5d3_can.dtsi index c5a3772741bf610b300a10147e76bcc882b973fb..0fac79f75c06ccd3008673a0147a3692656f095f 100644 --- a/arch/arm/boot/dts/sama5d3_can.dtsi +++ b/arch/arm/boot/dts/sama5d3_can.dtsi @@ -37,13 +37,13 @@ can0_clk: can0_clk { #clock-cells = <0>; reg = <40>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; can1_clk: can1_clk { #clock-cells = <0>; reg = <41>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; }; }; diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi index 801f9745e82f1cd06163b1af76d37ab6a5c1b175..b80dbc45a3c20bb207346f08e980faa8b73d07c6 100644 --- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi +++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi @@ -23,6 +23,7 @@ tcb1_clk: tcb1_clk { #clock-cells = <0>; reg = <27>; + atmel,clk-output-range = <0 166000000>; }; }; }; diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/sama5d3_uart.dtsi index 2511d748867bdd17fc3e08140b69ba5f61b594d7..71818c7bfb673c6cf10ea9ef9b4c03b5df9b3d17 100644 --- a/arch/arm/boot/dts/sama5d3_uart.dtsi +++ b/arch/arm/boot/dts/sama5d3_uart.dtsi @@ -42,13 +42,13 @@ uart0_clk: uart0_clk { #clock-cells = <0>; reg = <16>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; uart1_clk: uart1_clk { #clock-cells = <0>; reg = <17>; - atmel,clk-output-range = <0 66000000>; + atmel,clk-output-range = <0 83000000>; }; }; }; diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index ce1960453a0bb96bda88162a50e4826a0fdfb172..3bfa79717dfabaca0600007830144ce17d270e77 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -174,7 +174,7 @@ }; pmu { - compatible = "arm,cortex-a7-pmu", "arm,cortex-a15-pmu"; + compatible = "arm,cortex-a7-pmu"; interrupts = , , , diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 94cf5a1c7172371b3c5691e831a238dd563d83c7..db5d30598ad66a3d0107c187959a3141a0dae807 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -172,7 +172,7 @@ }; pmu { - compatible = "arm,cortex-a7-pmu", "arm,cortex-a15-pmu"; + compatible = "arm,cortex-a7-pmu"; interrupts = , ; }; diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index a923524d1040734d1f5b94b4a6e2f5d59cab99d1..8617323eb2735e80a6066f1023c857531237e40f 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -379,7 +379,7 @@ static int __init nocache_trampoline(unsigned long _arg) unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); phys_reset_t phys_reset; - mcpm_set_entry_vector(cpu, cluster, cpu_resume); + mcpm_set_entry_vector(cpu, cluster, cpu_resume_no_hyp); setup_mm_for_reboot(); __mcpm_cpu_going_down(cpu, cluster); diff --git a/arch/arm/configs/msm8909-minimal-perf_defconfig b/arch/arm/configs/msm8909-minimal-perf_defconfig index bd3cae3c9770504d1214777bbda5bf1720268859..694a17d64ffc2b7b6f83ef47e8c2baa99bbbaea8 100644 --- a/arch/arm/configs/msm8909-minimal-perf_defconfig +++ b/arch/arm/configs/msm8909-minimal-perf_defconfig @@ -228,11 +228,15 @@ CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y @@ -464,9 +468,11 @@ 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_OTA_CRYPTO=y CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_SYSTEM_TRUSTED_KEYS="verity.x509.pem" CONFIG_ARM_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM_NEON=y CONFIG_CRYPTO_SHA2_ARM_CE=y diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig index 23149f0029c4c36d3d5384d2ff86a78978ff3c9e..f80c84a2b0a0bb7bdebd355f2714352b7c23b9bf 100755 --- a/arch/arm/configs/msm8909-perf_defconfig +++ b/arch/arm/configs/msm8909-perf_defconfig @@ -10,6 +10,8 @@ CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_RCU_EXPERT=y CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 @@ -55,6 +57,7 @@ CONFIG_SMP=y CONFIG_SCHED_MC=y CONFIG_PREEMPT=y CONFIG_AEABI=y +CONFIG_HIGHMEM=y CONFIG_ARM_MODULE_PLTS=y CONFIG_CMA=y CONFIG_ZSMALLOC=y @@ -87,6 +90,7 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_INET_AH=y CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y CONFIG_INET_DIAG_DESTROY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -116,12 +120,13 @@ 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_CT=y CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=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 @@ -187,8 +192,11 @@ CONFIG_BRIDGE=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_HTB=y CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=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_EMATCH=y CONFIG_NET_EMATCH_CMP=y @@ -203,12 +211,12 @@ CONFIG_NET_ACT_SKBEDIT=y CONFIG_DNS_RESOLVER=y CONFIG_RMNET_DATA=y CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y CONFIG_CFG80211=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y +CONFIG_NFC_NQ=y CONFIG_IPC_ROUTER=y CONFIG_IPC_ROUTER_SECURITY=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y @@ -219,18 +227,28 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_HDCP_QSEECOM=y CONFIG_QSEECOM=y +CONFIG_UID_SYS_STATS=y CONFIG_MEMORY_STATE_TIME=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_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y @@ -253,14 +271,22 @@ CONFIG_CLD_HL_SDIO_CORE=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_MATRIX=y +# CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y +CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_INPUT_MISC=y CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_STMVL53L0X=y CONFIG_INPUT_UINPUT=y -# CONFIG_VT is not set +CONFIG_INPUT_GPIO=y # CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set CONFIG_SERIAL_MSM_HS=y CONFIG_SERIAL_MSM_SMD=y CONFIG_DIAG_CHAR=y @@ -276,7 +302,6 @@ CONFIG_SPI_QUP=y CONFIG_SPI_SPIDEV=y CONFIG_SLIMBUS_MSM_NGD=y CONFIG_SPMI=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y CONFIG_PINCTRL_MSM8909=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_GPIO_SYSFS=y @@ -300,6 +325,7 @@ CONFIG_THERMAL_QPNP=y CONFIG_THERMAL_QPNP_ADC_TM=y CONFIG_THERMAL_TSENS=y CONFIG_MSM_BCL_PERIPHERAL_CTL=y +CONFIG_QTI_THERMAL_LIMITS_DCVS=y CONFIG_QTI_QMI_COOLING_DEVICE=y CONFIG_REGULATOR_COOLING_DEVICE=y CONFIG_MFD_QCOM_RPM=y @@ -336,35 +362,44 @@ CONFIG_RADIO_IRIS=y CONFIG_RADIO_IRIS_TRANSPORT=y CONFIG_QCOM_KGSL=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_SPI_PANEL=y CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y CONFIG_FB_MSM_MDSS_MDP3=y -CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_LOGO=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_DYNAMIC_MINORS=y CONFIG_SND_SOC=y CONFIG_UHID=y CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y CONFIG_HID_CHICONY=y CONFIG_HID_CYPRESS=y +CONFIG_HID_ELECOM=y CONFIG_HID_EZKEY=y CONFIG_HID_KENSINGTON=y CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y CONFIG_HID_MONTEREY=y -CONFIG_USB=y +CONFIG_HID_MULTITOUCH=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_MON=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ACM=y CONFIG_USB_STORAGE=y +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CP210X=y +CONFIG_USB_SERIAL_FTDI_SIO=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_DEBUG_FS=y @@ -372,13 +407,18 @@ CONFIG_USB_GADGET_VBUS_DRAW=500 CONFIG_USB_CI13XXX_MSM=y CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_RMNET_BAM=y CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y CONFIG_USB_CONFIGFS_UEVENT=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_MMC=y CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_RING_BUFFER=y CONFIG_MMC_PARANOID_SD_INIT=y CONFIG_MMC_CLKGATE=y CONFIG_MMC_BLOCK_MINORS=32 @@ -388,6 +428,7 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y CONFIG_LEDS_CLASS_FLASH=y CONFIG_LEDS_QPNP=y +CONFIG_LEDS_MSM_GPIO_FLASH=y CONFIG_LEDS_QPNP_VIBRATOR=y CONFIG_LEDS_TRIGGERS=y CONFIG_RTC_CLASS=y @@ -401,6 +442,8 @@ CONFIG_ASHMEM=y CONFIG_ANDROID_LOW_MEMORY_KILLER=y CONFIG_ION=y CONFIG_ION_MSM=y +CONFIG_IPA=y +CONFIG_RMNET_IPA=y CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_QPNP_REVID=y @@ -423,18 +466,22 @@ CONFIG_QCOM_SECURE_BUFFER=y CONFIG_QCOM_EARLY_RANDOM=y CONFIG_MSM_SMEM=y CONFIG_MSM_SMD=y -CONFIG_MSM_SMD_DEBUG=y +CONFIG_MSM_GLINK=y CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_GLINK_LOOPBACK_SERVER=y +CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y +CONFIG_MSM_GLINK_SPI_XPRT=y CONFIG_TRACER_PKT=y CONFIG_MSM_SMP2P=y CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y +CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_QMI_INTERFACE=y +CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SUBSYSTEM_RESTART=y CONFIG_MSM_PIL=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_MSM_EVENT_TIMER=y -CONFIG_QTI_RPM_STATS_LOG=y CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_MSM_BAM_DMUX=y @@ -453,31 +500,45 @@ CONFIG_ANDROID_BINDER_IPC=y CONFIG_ANDROID_BINDER_IPC_32BIT=y CONFIG_STM=y CONFIG_SENSORS_SSC=y -CONFIG_MSM_TZ_LOG=y -CONFIG_EXT4_FS=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT3_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_FANOTIFY=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y +CONFIG_ECRYPT_FS=y +CONFIG_ECRYPT_FS_MESSAGING=y CONFIG_SDCARD_FS=y CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_INFO=y CONFIG_FRAME_WARN=2048 -CONFIG_DEBUG_FS=y CONFIG_MAGIC_SYSRQ=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_WQ_WATCHDOG=y CONFIG_PANIC_TIMEOUT=5 CONFIG_PANIC_ON_SCHED_BUG=y CONFIG_PANIC_ON_RT_THROTTLING=y -# CONFIG_DEBUG_PREEMPT is not set -CONFIG_STACKTRACE=y -# CONFIG_FTRACE is not set -CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_QCOM_RTB=y +CONFIG_QCOM_RTB_SEPARATE_CPUS=y +CONFIG_CPU_FREQ_SWITCH_PROFILER=y +CONFIG_LKDTM=y +CONFIG_MEMTEST=y +CONFIG_PANIC_ON_DATA_CORRUPTION=y +CONFIG_PID_IN_CONTEXTIDR=y +CONFIG_CORESIGHT=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_LSM_MMAP_MIN_ADDR=4096 @@ -492,9 +553,11 @@ 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_OTA_CRYPTO=y CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_SYSTEM_TRUSTED_KEYS="verity.x509.pem" CONFIG_ARM_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM_NEON=y CONFIG_CRYPTO_SHA2_ARM_CE=y diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig index 9ce23542234625196c1674fb81cb2e70e6ea3741..a006bff7555e4c10381b11da330c9e789724097e 100644 --- a/arch/arm/configs/msm8909_defconfig +++ b/arch/arm/configs/msm8909_defconfig @@ -239,12 +239,16 @@ CONFIG_SCSI_UFS_QCOM=y CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_SCSI_UFSHCD_CMD_LOGGING=y CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y CONFIG_BLK_DEV_DM=y CONFIG_DM_DEBUG=y CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y @@ -272,6 +276,10 @@ CONFIG_KEYBOARD_MATRIX=y CONFIG_INPUT_JOYSTICK=y CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y +CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_INPUT_MISC=y CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_STMVL53L0X=y @@ -429,6 +437,7 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y CONFIG_LEDS_CLASS_FLASH=y CONFIG_LEDS_QPNP=y +CONFIG_LEDS_MSM_GPIO_FLASH=y CONFIG_LEDS_QPNP_VIBRATOR=y CONFIG_LEDS_TRIGGERS=y CONFIG_RTC_CLASS=y @@ -500,6 +509,7 @@ CONFIG_QTI_MPM=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_ANDROID_BINDER_IPC_32BIT=y +CONFIG_STM=y CONFIG_SENSORS_SSC=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT2_FS=y @@ -573,19 +583,6 @@ CONFIG_DEBUG_USER=y CONFIG_PID_IN_CONTEXTIDR=y CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_CORESIGHT=y -CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y -CONFIG_CORESIGHT_SINK_TPIU=y -CONFIG_CORESIGHT_SOURCE_ETM3X=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 -CONFIG_CORESIGHT_QCOM_REPLICATOR=y -CONFIG_CORESIGHT_DBGUI=y -CONFIG_CORESIGHT_STM=y -CONFIG_CORESIGHT_TPDA=y -CONFIG_CORESIGHT_TPDM=y -CONFIG_CORESIGHT_CTI=y -CONFIG_CORESIGHT_EVENT=y -CONFIG_CORESIGHT_HWEVENT=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_LSM_MMAP_MIN_ADDR=4096 @@ -604,6 +601,7 @@ CONFIG_CRYPTO_DEV_QCRYPTO=y CONFIG_CRYPTO_DEV_QCEDEV=y CONFIG_CRYPTO_DEV_OTA_CRYPTO=y CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_SYSTEM_TRUSTED_KEYS="verity.x509.pem" CONFIG_ARM_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM_NEON=y CONFIG_CRYPTO_SHA2_ARM_CE=y diff --git a/arch/arm/configs/sa415m-perf_defconfig b/arch/arm/configs/sa415m-perf_defconfig index ce8c8b00015a0c6c8690bcbd322650c5471bdafa..192094eee0dc5f63491b9a982b798410262dccba 100644 --- a/arch/arm/configs/sa415m-perf_defconfig +++ b/arch/arm/configs/sa415m-perf_defconfig @@ -224,11 +224,12 @@ CONFIG_PPP=y CONFIG_PPPOL2TP=y CONFIG_PPP_ASYNC=y CONFIG_WCNSS_MEM_PRE_ALLOC=y -CONFIG_CNSS2=y +CONFIG_CNSS2=m CONFIG_CNSS2_DEBUG=y CONFIG_CNSS2_QMI=y CONFIG_CLD_HL_SDIO_CORE=y CONFIG_CLD_LL_CORE=y +CONFIG_CNSS_UTILS=y CONFIG_CNSS_GENL=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=m @@ -369,8 +370,12 @@ CONFIG_IOMMU_DEBUG=y CONFIG_IOMMU_DEBUG_TRACKING=y CONFIG_IOMMU_TESTS=y CONFIG_QCOM_SCM=y +CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y +CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000 +CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000 CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_BOOT_TIME_MARKER=y +CONFIG_SDX_EXT_IPC=y CONFIG_QCOM_WATCHDOG_V2=y CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_BUS_SCALING=y @@ -389,6 +394,7 @@ CONFIG_MSM_QMI_INTERFACE=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SUBSYSTEM_RESTART=y CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_GLINK_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_QCOM_COMMAND_DB=y CONFIG_QCOM_SMCINVOKE=y diff --git a/arch/arm/configs/sa415m_defconfig b/arch/arm/configs/sa415m_defconfig index accaa86a4af366fa8c6f63e0bc991e8fa68045bc..96e21cc50b3c8d9319d33eeaf0533975fe3c7ecd 100644 --- a/arch/arm/configs/sa415m_defconfig +++ b/arch/arm/configs/sa415m_defconfig @@ -225,11 +225,12 @@ CONFIG_PPP=y CONFIG_PPPOL2TP=y CONFIG_PPP_ASYNC=y CONFIG_WCNSS_MEM_PRE_ALLOC=y -CONFIG_CNSS2=y +CONFIG_CNSS2=m CONFIG_CNSS2_DEBUG=y CONFIG_CNSS2_QMI=y CONFIG_CLD_HL_SDIO_CORE=y CONFIG_CLD_LL_CORE=y +CONFIG_CNSS_UTILS=y CONFIG_CNSS_GENL=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=m @@ -386,8 +387,12 @@ CONFIG_IOMMU_DEBUG=y CONFIG_IOMMU_DEBUG_TRACKING=y CONFIG_IOMMU_TESTS=y CONFIG_QCOM_SCM=y +CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y +CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000 +CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000 CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_BOOT_TIME_MARKER=y +CONFIG_SDX_EXT_IPC=y CONFIG_QCOM_WATCHDOG_V2=y CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_BUS_SCALING=y @@ -406,6 +411,7 @@ CONFIG_MSM_QMI_INTERFACE=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SUBSYSTEM_RESTART=y CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_GLINK_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_QCOM_COMMAND_DB=y CONFIG_QCOM_SMCINVOKE=y diff --git a/arch/arm/configs/sdm429-bg-perf_defconfig b/arch/arm/configs/sdm429-bg-perf_defconfig index f0c1178365dcabbedf06f87f4402cb083a636caf..bbb4c4eeff357c3b6f74a08a8cb6d0c52ae647a3 100644 --- a/arch/arm/configs/sdm429-bg-perf_defconfig +++ b/arch/arm/configs/sdm429-bg-perf_defconfig @@ -284,6 +284,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y +CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET=y CONFIG_INPUT_MISC=y CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_QTI_HAPTICS=y @@ -352,9 +353,35 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=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_MSM_VIDC_3X_V4L2=y CONFIG_MSM_VIDC_3X_GOVERNORS=y -CONFIG_ADSP_SHMEM=y CONFIG_QCOM_KGSL=y CONFIG_FB=y CONFIG_FB_VIRTUAL=y @@ -371,6 +398,7 @@ CONFIG_SND=y CONFIG_SND_DYNAMIC_MINORS=y CONFIG_SND_USB_AUDIO=y CONFIG_SND_SOC=y +CONFIG_SND_SOC_TFA98XX=y CONFIG_UHID=y CONFIG_USB=y CONFIG_DUAL_ROLE_USB_INTF=y @@ -408,8 +436,6 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_SDHCI_MSM_ICE=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y CONFIG_LEDS_QPNP_HAPTICS=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y diff --git a/arch/arm/configs/sdm429-bg_defconfig b/arch/arm/configs/sdm429-bg_defconfig index 141f67b48678a6ce0de834198578e75afc829167..6c345f71cd04192da53bc48408ad429d4a47af47 100644 --- a/arch/arm/configs/sdm429-bg_defconfig +++ b/arch/arm/configs/sdm429-bg_defconfig @@ -289,6 +289,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y +CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET=y CONFIG_INPUT_MISC=y CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_QTI_HAPTICS=y @@ -359,9 +360,35 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=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_MSM_VIDC_3X_V4L2=y CONFIG_MSM_VIDC_3X_GOVERNORS=y -CONFIG_ADSP_SHMEM=y CONFIG_QCOM_KGSL=y CONFIG_FB=y CONFIG_FB_VIRTUAL=y @@ -378,6 +405,7 @@ CONFIG_SND=y CONFIG_SND_DYNAMIC_MINORS=y CONFIG_SND_USB_AUDIO=y CONFIG_SND_SOC=y +CONFIG_SND_SOC_TFA98XX=y CONFIG_UHID=y CONFIG_USB=y CONFIG_DUAL_ROLE_USB_INTF=y @@ -416,8 +444,6 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_SDHCI_MSM_ICE=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y CONFIG_LEDS_QPNP_HAPTICS=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y @@ -549,6 +575,7 @@ CONFIG_DEBUG_OBJECTS_TIMERS=y CONFIG_DEBUG_OBJECTS_WORK=y CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_SLUB_DEBUG_ON=y CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/arch/arm/configs/vendor/sa415m-perf_defconfig b/arch/arm/configs/vendor/sa415m-perf_defconfig new file mode 120000 index 0000000000000000000000000000000000000000..7ecd3251e2c83fa5ce4e5c6c54818cdf54efd97e --- /dev/null +++ b/arch/arm/configs/vendor/sa415m-perf_defconfig @@ -0,0 +1 @@ +../sa415m-perf_defconfig \ No newline at end of file diff --git a/arch/arm/configs/vendor/sa415m_defconfig b/arch/arm/configs/vendor/sa415m_defconfig new file mode 120000 index 0000000000000000000000000000000000000000..f2a512d8ca19a443c45d246e7e9b54c9184c093c --- /dev/null +++ b/arch/arm/configs/vendor/sa415m_defconfig @@ -0,0 +1 @@ +../sa415m_defconfig \ No newline at end of file diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index bd12b98e258965e2ecaab33e2fbf14769391dcbd..d690fef3e3600ba6e97c5d7874e67c3912ab0beb 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -37,3 +37,6 @@ generic-y += termbits.h generic-y += termios.h generic-y += timex.h generic-y += trace_clock.h + +generated-y += mach-types.h +generated-y += unistd-nr.h diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h deleted file mode 100644 index 948178cc6ba8defcb97ee3062e59c0e3a1591e1d..0000000000000000000000000000000000000000 --- a/arch/arm/include/asm/mach-types.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h index 6c7182f32cefeb247068e80af9944b4ff01e3727..e6c2f426f8c866d700db5562aa6d8cd87d3c0248 100644 --- a/arch/arm/include/asm/suspend.h +++ b/arch/arm/include/asm/suspend.h @@ -7,6 +7,7 @@ struct sleep_save_sp { }; extern void cpu_resume(void); +extern void cpu_resume_no_hyp(void); extern void cpu_resume_arm(void); extern int cpu_suspend(unsigned long, int (*)(unsigned long)); diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 0f6c6b873bc5fc62247bce91ffc1c5892195fb10..e05c31af48d1b85450d3befe92cc5a7895abb3d0 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -379,6 +379,13 @@ do { \ #define __get_user_asm_byte(x, addr, err) \ __get_user_asm(x, addr, err, ldrb) +#if __LINUX_ARM_ARCH__ >= 6 + +#define __get_user_asm_half(x, addr, err) \ + __get_user_asm(x, addr, err, ldrh) + +#else + #ifndef __ARMEB__ #define __get_user_asm_half(x, __gu_addr, err) \ ({ \ @@ -397,6 +404,8 @@ do { \ }) #endif +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + #define __get_user_asm_word(x, addr, err) \ __get_user_asm(x, addr, err, ldr) #endif @@ -472,6 +481,13 @@ do { \ #define __put_user_asm_byte(x, __pu_addr, err) \ __put_user_asm(x, __pu_addr, err, strb) +#if __LINUX_ARM_ARCH__ >= 6 + +#define __put_user_asm_half(x, __pu_addr, err) \ + __put_user_asm(x, __pu_addr, err, strh) + +#else + #ifndef __ARMEB__ #define __put_user_asm_half(x, __pu_addr, err) \ ({ \ @@ -488,6 +504,8 @@ do { \ }) #endif +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + #define __put_user_asm_word(x, __pu_addr, err) \ __put_user_asm(x, __pu_addr, err, str) diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index ada0d29a660f2fad8bdcf9dbef82affd62e7bf24..076090d2dbf5ebeec44ca4b169df2e77b1a7ed80 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -14,12 +14,7 @@ #define __ASM_ARM_UNISTD_H #include - -/* - * This may need to be greater than __NR_last_syscall+1 in order to - * account for the padding in the syscall table - */ -#define __NR_syscalls (400) +#include #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME @@ -52,4 +47,23 @@ #define __IGNORE_fadvise64_64 #define __IGNORE_migrate_pages +#ifdef __ARM_EABI__ +/* + * The following syscalls are obsolete and no longer available for EABI: + * __NR_time + * __NR_umount + * __NR_stime + * __NR_alarm + * __NR_utime + * __NR_getrlimit + * __NR_select + * __NR_readdir + * __NR_mmap + * __NR_socketcall + * __NR_syscall + * __NR_ipc + */ +#define __IGNORE_getrlimit +#endif + #endif /* __ASM_ARM_UNISTD_H */ diff --git a/arch/arm/include/uapi/asm/Kbuild b/arch/arm/include/uapi/asm/Kbuild index a1c05f93d920dd245287d39f7bd8721cb78fc732..424935e4515dd6fb8a9287c86538644f8919c710 100644 --- a/arch/arm/include/uapi/asm/Kbuild +++ b/arch/arm/include/uapi/asm/Kbuild @@ -1,20 +1,6 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += auxvec.h -header-y += byteorder.h -header-y += fcntl.h -header-y += hwcap.h -header-y += ioctls.h -header-y += kvm_para.h -header-y += mman.h -header-y += perf_regs.h -header-y += posix_types.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += unistd.h +generated-y += unistd-common.h +generated-y += unistd-oabi.h +generated-y += unistd-eabi.h diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/uapi/asm/types.h similarity index 94% rename from arch/arm/include/asm/types.h rename to arch/arm/include/uapi/asm/types.h index a53cdb8f068c2f3a16ea4645d4a846fa2acb9ea0..9435a42f575e02c76199f861b9e0c96ffb77e123 100644 --- a/arch/arm/include/asm/types.h +++ b/arch/arm/include/uapi/asm/types.h @@ -1,5 +1,5 @@ -#ifndef _ASM_TYPES_H -#define _ASM_TYPES_H +#ifndef _UAPI_ASM_TYPES_H +#define _UAPI_ASM_TYPES_H #include @@ -37,4 +37,4 @@ #define __UINTPTR_TYPE__ unsigned long #endif -#endif /* _ASM_TYPES_H */ +#endif /* _UAPI_ASM_TYPES_H */ diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h index d67def5796e3a6671604f0d526490b445021416a..63ff7aadddd8904ebe64ce8807a7877f95d05996 100644 --- a/arch/arm/include/uapi/asm/unistd.h +++ b/arch/arm/include/uapi/asm/unistd.h @@ -17,414 +17,15 @@ #if defined(__thumb__) || defined(__ARM_EABI__) #define __NR_SYSCALL_BASE 0 +#include #else #define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE +#include #endif -/* - * This file contains the system call numbers. - */ +#include +#define __NR_sync_file_range2 __NR_arm_sync_file_range -#define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0) -#define __NR_exit (__NR_SYSCALL_BASE+ 1) -#define __NR_fork (__NR_SYSCALL_BASE+ 2) -#define __NR_read (__NR_SYSCALL_BASE+ 3) -#define __NR_write (__NR_SYSCALL_BASE+ 4) -#define __NR_open (__NR_SYSCALL_BASE+ 5) -#define __NR_close (__NR_SYSCALL_BASE+ 6) - /* 7 was sys_waitpid */ -#define __NR_creat (__NR_SYSCALL_BASE+ 8) -#define __NR_link (__NR_SYSCALL_BASE+ 9) -#define __NR_unlink (__NR_SYSCALL_BASE+ 10) -#define __NR_execve (__NR_SYSCALL_BASE+ 11) -#define __NR_chdir (__NR_SYSCALL_BASE+ 12) -#define __NR_time (__NR_SYSCALL_BASE+ 13) -#define __NR_mknod (__NR_SYSCALL_BASE+ 14) -#define __NR_chmod (__NR_SYSCALL_BASE+ 15) -#define __NR_lchown (__NR_SYSCALL_BASE+ 16) - /* 17 was sys_break */ - /* 18 was sys_stat */ -#define __NR_lseek (__NR_SYSCALL_BASE+ 19) -#define __NR_getpid (__NR_SYSCALL_BASE+ 20) -#define __NR_mount (__NR_SYSCALL_BASE+ 21) -#define __NR_umount (__NR_SYSCALL_BASE+ 22) -#define __NR_setuid (__NR_SYSCALL_BASE+ 23) -#define __NR_getuid (__NR_SYSCALL_BASE+ 24) -#define __NR_stime (__NR_SYSCALL_BASE+ 25) -#define __NR_ptrace (__NR_SYSCALL_BASE+ 26) -#define __NR_alarm (__NR_SYSCALL_BASE+ 27) - /* 28 was sys_fstat */ -#define __NR_pause (__NR_SYSCALL_BASE+ 29) -#define __NR_utime (__NR_SYSCALL_BASE+ 30) - /* 31 was sys_stty */ - /* 32 was sys_gtty */ -#define __NR_access (__NR_SYSCALL_BASE+ 33) -#define __NR_nice (__NR_SYSCALL_BASE+ 34) - /* 35 was sys_ftime */ -#define __NR_sync (__NR_SYSCALL_BASE+ 36) -#define __NR_kill (__NR_SYSCALL_BASE+ 37) -#define __NR_rename (__NR_SYSCALL_BASE+ 38) -#define __NR_mkdir (__NR_SYSCALL_BASE+ 39) -#define __NR_rmdir (__NR_SYSCALL_BASE+ 40) -#define __NR_dup (__NR_SYSCALL_BASE+ 41) -#define __NR_pipe (__NR_SYSCALL_BASE+ 42) -#define __NR_times (__NR_SYSCALL_BASE+ 43) - /* 44 was sys_prof */ -#define __NR_brk (__NR_SYSCALL_BASE+ 45) -#define __NR_setgid (__NR_SYSCALL_BASE+ 46) -#define __NR_getgid (__NR_SYSCALL_BASE+ 47) - /* 48 was sys_signal */ -#define __NR_geteuid (__NR_SYSCALL_BASE+ 49) -#define __NR_getegid (__NR_SYSCALL_BASE+ 50) -#define __NR_acct (__NR_SYSCALL_BASE+ 51) -#define __NR_umount2 (__NR_SYSCALL_BASE+ 52) - /* 53 was sys_lock */ -#define __NR_ioctl (__NR_SYSCALL_BASE+ 54) -#define __NR_fcntl (__NR_SYSCALL_BASE+ 55) - /* 56 was sys_mpx */ -#define __NR_setpgid (__NR_SYSCALL_BASE+ 57) - /* 58 was sys_ulimit */ - /* 59 was sys_olduname */ -#define __NR_umask (__NR_SYSCALL_BASE+ 60) -#define __NR_chroot (__NR_SYSCALL_BASE+ 61) -#define __NR_ustat (__NR_SYSCALL_BASE+ 62) -#define __NR_dup2 (__NR_SYSCALL_BASE+ 63) -#define __NR_getppid (__NR_SYSCALL_BASE+ 64) -#define __NR_getpgrp (__NR_SYSCALL_BASE+ 65) -#define __NR_setsid (__NR_SYSCALL_BASE+ 66) -#define __NR_sigaction (__NR_SYSCALL_BASE+ 67) - /* 68 was sys_sgetmask */ - /* 69 was sys_ssetmask */ -#define __NR_setreuid (__NR_SYSCALL_BASE+ 70) -#define __NR_setregid (__NR_SYSCALL_BASE+ 71) -#define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72) -#define __NR_sigpending (__NR_SYSCALL_BASE+ 73) -#define __NR_sethostname (__NR_SYSCALL_BASE+ 74) -#define __NR_setrlimit (__NR_SYSCALL_BASE+ 75) -#define __NR_getrlimit (__NR_SYSCALL_BASE+ 76) /* Back compat 2GB limited rlimit */ -#define __NR_getrusage (__NR_SYSCALL_BASE+ 77) -#define __NR_gettimeofday (__NR_SYSCALL_BASE+ 78) -#define __NR_settimeofday (__NR_SYSCALL_BASE+ 79) -#define __NR_getgroups (__NR_SYSCALL_BASE+ 80) -#define __NR_setgroups (__NR_SYSCALL_BASE+ 81) -#define __NR_select (__NR_SYSCALL_BASE+ 82) -#define __NR_symlink (__NR_SYSCALL_BASE+ 83) - /* 84 was sys_lstat */ -#define __NR_readlink (__NR_SYSCALL_BASE+ 85) -#define __NR_uselib (__NR_SYSCALL_BASE+ 86) -#define __NR_swapon (__NR_SYSCALL_BASE+ 87) -#define __NR_reboot (__NR_SYSCALL_BASE+ 88) -#define __NR_readdir (__NR_SYSCALL_BASE+ 89) -#define __NR_mmap (__NR_SYSCALL_BASE+ 90) -#define __NR_munmap (__NR_SYSCALL_BASE+ 91) -#define __NR_truncate (__NR_SYSCALL_BASE+ 92) -#define __NR_ftruncate (__NR_SYSCALL_BASE+ 93) -#define __NR_fchmod (__NR_SYSCALL_BASE+ 94) -#define __NR_fchown (__NR_SYSCALL_BASE+ 95) -#define __NR_getpriority (__NR_SYSCALL_BASE+ 96) -#define __NR_setpriority (__NR_SYSCALL_BASE+ 97) - /* 98 was sys_profil */ -#define __NR_statfs (__NR_SYSCALL_BASE+ 99) -#define __NR_fstatfs (__NR_SYSCALL_BASE+100) - /* 101 was sys_ioperm */ -#define __NR_socketcall (__NR_SYSCALL_BASE+102) -#define __NR_syslog (__NR_SYSCALL_BASE+103) -#define __NR_setitimer (__NR_SYSCALL_BASE+104) -#define __NR_getitimer (__NR_SYSCALL_BASE+105) -#define __NR_stat (__NR_SYSCALL_BASE+106) -#define __NR_lstat (__NR_SYSCALL_BASE+107) -#define __NR_fstat (__NR_SYSCALL_BASE+108) - /* 109 was sys_uname */ - /* 110 was sys_iopl */ -#define __NR_vhangup (__NR_SYSCALL_BASE+111) - /* 112 was sys_idle */ -#define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */ -#define __NR_wait4 (__NR_SYSCALL_BASE+114) -#define __NR_swapoff (__NR_SYSCALL_BASE+115) -#define __NR_sysinfo (__NR_SYSCALL_BASE+116) -#define __NR_ipc (__NR_SYSCALL_BASE+117) -#define __NR_fsync (__NR_SYSCALL_BASE+118) -#define __NR_sigreturn (__NR_SYSCALL_BASE+119) -#define __NR_clone (__NR_SYSCALL_BASE+120) -#define __NR_setdomainname (__NR_SYSCALL_BASE+121) -#define __NR_uname (__NR_SYSCALL_BASE+122) - /* 123 was sys_modify_ldt */ -#define __NR_adjtimex (__NR_SYSCALL_BASE+124) -#define __NR_mprotect (__NR_SYSCALL_BASE+125) -#define __NR_sigprocmask (__NR_SYSCALL_BASE+126) - /* 127 was sys_create_module */ -#define __NR_init_module (__NR_SYSCALL_BASE+128) -#define __NR_delete_module (__NR_SYSCALL_BASE+129) - /* 130 was sys_get_kernel_syms */ -#define __NR_quotactl (__NR_SYSCALL_BASE+131) -#define __NR_getpgid (__NR_SYSCALL_BASE+132) -#define __NR_fchdir (__NR_SYSCALL_BASE+133) -#define __NR_bdflush (__NR_SYSCALL_BASE+134) -#define __NR_sysfs (__NR_SYSCALL_BASE+135) -#define __NR_personality (__NR_SYSCALL_BASE+136) - /* 137 was sys_afs_syscall */ -#define __NR_setfsuid (__NR_SYSCALL_BASE+138) -#define __NR_setfsgid (__NR_SYSCALL_BASE+139) -#define __NR__llseek (__NR_SYSCALL_BASE+140) -#define __NR_getdents (__NR_SYSCALL_BASE+141) -#define __NR__newselect (__NR_SYSCALL_BASE+142) -#define __NR_flock (__NR_SYSCALL_BASE+143) -#define __NR_msync (__NR_SYSCALL_BASE+144) -#define __NR_readv (__NR_SYSCALL_BASE+145) -#define __NR_writev (__NR_SYSCALL_BASE+146) -#define __NR_getsid (__NR_SYSCALL_BASE+147) -#define __NR_fdatasync (__NR_SYSCALL_BASE+148) -#define __NR__sysctl (__NR_SYSCALL_BASE+149) -#define __NR_mlock (__NR_SYSCALL_BASE+150) -#define __NR_munlock (__NR_SYSCALL_BASE+151) -#define __NR_mlockall (__NR_SYSCALL_BASE+152) -#define __NR_munlockall (__NR_SYSCALL_BASE+153) -#define __NR_sched_setparam (__NR_SYSCALL_BASE+154) -#define __NR_sched_getparam (__NR_SYSCALL_BASE+155) -#define __NR_sched_setscheduler (__NR_SYSCALL_BASE+156) -#define __NR_sched_getscheduler (__NR_SYSCALL_BASE+157) -#define __NR_sched_yield (__NR_SYSCALL_BASE+158) -#define __NR_sched_get_priority_max (__NR_SYSCALL_BASE+159) -#define __NR_sched_get_priority_min (__NR_SYSCALL_BASE+160) -#define __NR_sched_rr_get_interval (__NR_SYSCALL_BASE+161) -#define __NR_nanosleep (__NR_SYSCALL_BASE+162) -#define __NR_mremap (__NR_SYSCALL_BASE+163) -#define __NR_setresuid (__NR_SYSCALL_BASE+164) -#define __NR_getresuid (__NR_SYSCALL_BASE+165) - /* 166 was sys_vm86 */ - /* 167 was sys_query_module */ -#define __NR_poll (__NR_SYSCALL_BASE+168) -#define __NR_nfsservctl (__NR_SYSCALL_BASE+169) -#define __NR_setresgid (__NR_SYSCALL_BASE+170) -#define __NR_getresgid (__NR_SYSCALL_BASE+171) -#define __NR_prctl (__NR_SYSCALL_BASE+172) -#define __NR_rt_sigreturn (__NR_SYSCALL_BASE+173) -#define __NR_rt_sigaction (__NR_SYSCALL_BASE+174) -#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE+175) -#define __NR_rt_sigpending (__NR_SYSCALL_BASE+176) -#define __NR_rt_sigtimedwait (__NR_SYSCALL_BASE+177) -#define __NR_rt_sigqueueinfo (__NR_SYSCALL_BASE+178) -#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE+179) -#define __NR_pread64 (__NR_SYSCALL_BASE+180) -#define __NR_pwrite64 (__NR_SYSCALL_BASE+181) -#define __NR_chown (__NR_SYSCALL_BASE+182) -#define __NR_getcwd (__NR_SYSCALL_BASE+183) -#define __NR_capget (__NR_SYSCALL_BASE+184) -#define __NR_capset (__NR_SYSCALL_BASE+185) -#define __NR_sigaltstack (__NR_SYSCALL_BASE+186) -#define __NR_sendfile (__NR_SYSCALL_BASE+187) - /* 188 reserved */ - /* 189 reserved */ -#define __NR_vfork (__NR_SYSCALL_BASE+190) -#define __NR_ugetrlimit (__NR_SYSCALL_BASE+191) /* SuS compliant getrlimit */ -#define __NR_mmap2 (__NR_SYSCALL_BASE+192) -#define __NR_truncate64 (__NR_SYSCALL_BASE+193) -#define __NR_ftruncate64 (__NR_SYSCALL_BASE+194) -#define __NR_stat64 (__NR_SYSCALL_BASE+195) -#define __NR_lstat64 (__NR_SYSCALL_BASE+196) -#define __NR_fstat64 (__NR_SYSCALL_BASE+197) -#define __NR_lchown32 (__NR_SYSCALL_BASE+198) -#define __NR_getuid32 (__NR_SYSCALL_BASE+199) -#define __NR_getgid32 (__NR_SYSCALL_BASE+200) -#define __NR_geteuid32 (__NR_SYSCALL_BASE+201) -#define __NR_getegid32 (__NR_SYSCALL_BASE+202) -#define __NR_setreuid32 (__NR_SYSCALL_BASE+203) -#define __NR_setregid32 (__NR_SYSCALL_BASE+204) -#define __NR_getgroups32 (__NR_SYSCALL_BASE+205) -#define __NR_setgroups32 (__NR_SYSCALL_BASE+206) -#define __NR_fchown32 (__NR_SYSCALL_BASE+207) -#define __NR_setresuid32 (__NR_SYSCALL_BASE+208) -#define __NR_getresuid32 (__NR_SYSCALL_BASE+209) -#define __NR_setresgid32 (__NR_SYSCALL_BASE+210) -#define __NR_getresgid32 (__NR_SYSCALL_BASE+211) -#define __NR_chown32 (__NR_SYSCALL_BASE+212) -#define __NR_setuid32 (__NR_SYSCALL_BASE+213) -#define __NR_setgid32 (__NR_SYSCALL_BASE+214) -#define __NR_setfsuid32 (__NR_SYSCALL_BASE+215) -#define __NR_setfsgid32 (__NR_SYSCALL_BASE+216) -#define __NR_getdents64 (__NR_SYSCALL_BASE+217) -#define __NR_pivot_root (__NR_SYSCALL_BASE+218) -#define __NR_mincore (__NR_SYSCALL_BASE+219) -#define __NR_madvise (__NR_SYSCALL_BASE+220) -#define __NR_fcntl64 (__NR_SYSCALL_BASE+221) - /* 222 for tux */ - /* 223 is unused */ -#define __NR_gettid (__NR_SYSCALL_BASE+224) -#define __NR_readahead (__NR_SYSCALL_BASE+225) -#define __NR_setxattr (__NR_SYSCALL_BASE+226) -#define __NR_lsetxattr (__NR_SYSCALL_BASE+227) -#define __NR_fsetxattr (__NR_SYSCALL_BASE+228) -#define __NR_getxattr (__NR_SYSCALL_BASE+229) -#define __NR_lgetxattr (__NR_SYSCALL_BASE+230) -#define __NR_fgetxattr (__NR_SYSCALL_BASE+231) -#define __NR_listxattr (__NR_SYSCALL_BASE+232) -#define __NR_llistxattr (__NR_SYSCALL_BASE+233) -#define __NR_flistxattr (__NR_SYSCALL_BASE+234) -#define __NR_removexattr (__NR_SYSCALL_BASE+235) -#define __NR_lremovexattr (__NR_SYSCALL_BASE+236) -#define __NR_fremovexattr (__NR_SYSCALL_BASE+237) -#define __NR_tkill (__NR_SYSCALL_BASE+238) -#define __NR_sendfile64 (__NR_SYSCALL_BASE+239) -#define __NR_futex (__NR_SYSCALL_BASE+240) -#define __NR_sched_setaffinity (__NR_SYSCALL_BASE+241) -#define __NR_sched_getaffinity (__NR_SYSCALL_BASE+242) -#define __NR_io_setup (__NR_SYSCALL_BASE+243) -#define __NR_io_destroy (__NR_SYSCALL_BASE+244) -#define __NR_io_getevents (__NR_SYSCALL_BASE+245) -#define __NR_io_submit (__NR_SYSCALL_BASE+246) -#define __NR_io_cancel (__NR_SYSCALL_BASE+247) -#define __NR_exit_group (__NR_SYSCALL_BASE+248) -#define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249) -#define __NR_epoll_create (__NR_SYSCALL_BASE+250) -#define __NR_epoll_ctl (__NR_SYSCALL_BASE+251) -#define __NR_epoll_wait (__NR_SYSCALL_BASE+252) -#define __NR_remap_file_pages (__NR_SYSCALL_BASE+253) - /* 254 for set_thread_area */ - /* 255 for get_thread_area */ -#define __NR_set_tid_address (__NR_SYSCALL_BASE+256) -#define __NR_timer_create (__NR_SYSCALL_BASE+257) -#define __NR_timer_settime (__NR_SYSCALL_BASE+258) -#define __NR_timer_gettime (__NR_SYSCALL_BASE+259) -#define __NR_timer_getoverrun (__NR_SYSCALL_BASE+260) -#define __NR_timer_delete (__NR_SYSCALL_BASE+261) -#define __NR_clock_settime (__NR_SYSCALL_BASE+262) -#define __NR_clock_gettime (__NR_SYSCALL_BASE+263) -#define __NR_clock_getres (__NR_SYSCALL_BASE+264) -#define __NR_clock_nanosleep (__NR_SYSCALL_BASE+265) -#define __NR_statfs64 (__NR_SYSCALL_BASE+266) -#define __NR_fstatfs64 (__NR_SYSCALL_BASE+267) -#define __NR_tgkill (__NR_SYSCALL_BASE+268) -#define __NR_utimes (__NR_SYSCALL_BASE+269) -#define __NR_arm_fadvise64_64 (__NR_SYSCALL_BASE+270) -#define __NR_pciconfig_iobase (__NR_SYSCALL_BASE+271) -#define __NR_pciconfig_read (__NR_SYSCALL_BASE+272) -#define __NR_pciconfig_write (__NR_SYSCALL_BASE+273) -#define __NR_mq_open (__NR_SYSCALL_BASE+274) -#define __NR_mq_unlink (__NR_SYSCALL_BASE+275) -#define __NR_mq_timedsend (__NR_SYSCALL_BASE+276) -#define __NR_mq_timedreceive (__NR_SYSCALL_BASE+277) -#define __NR_mq_notify (__NR_SYSCALL_BASE+278) -#define __NR_mq_getsetattr (__NR_SYSCALL_BASE+279) -#define __NR_waitid (__NR_SYSCALL_BASE+280) -#define __NR_socket (__NR_SYSCALL_BASE+281) -#define __NR_bind (__NR_SYSCALL_BASE+282) -#define __NR_connect (__NR_SYSCALL_BASE+283) -#define __NR_listen (__NR_SYSCALL_BASE+284) -#define __NR_accept (__NR_SYSCALL_BASE+285) -#define __NR_getsockname (__NR_SYSCALL_BASE+286) -#define __NR_getpeername (__NR_SYSCALL_BASE+287) -#define __NR_socketpair (__NR_SYSCALL_BASE+288) -#define __NR_send (__NR_SYSCALL_BASE+289) -#define __NR_sendto (__NR_SYSCALL_BASE+290) -#define __NR_recv (__NR_SYSCALL_BASE+291) -#define __NR_recvfrom (__NR_SYSCALL_BASE+292) -#define __NR_shutdown (__NR_SYSCALL_BASE+293) -#define __NR_setsockopt (__NR_SYSCALL_BASE+294) -#define __NR_getsockopt (__NR_SYSCALL_BASE+295) -#define __NR_sendmsg (__NR_SYSCALL_BASE+296) -#define __NR_recvmsg (__NR_SYSCALL_BASE+297) -#define __NR_semop (__NR_SYSCALL_BASE+298) -#define __NR_semget (__NR_SYSCALL_BASE+299) -#define __NR_semctl (__NR_SYSCALL_BASE+300) -#define __NR_msgsnd (__NR_SYSCALL_BASE+301) -#define __NR_msgrcv (__NR_SYSCALL_BASE+302) -#define __NR_msgget (__NR_SYSCALL_BASE+303) -#define __NR_msgctl (__NR_SYSCALL_BASE+304) -#define __NR_shmat (__NR_SYSCALL_BASE+305) -#define __NR_shmdt (__NR_SYSCALL_BASE+306) -#define __NR_shmget (__NR_SYSCALL_BASE+307) -#define __NR_shmctl (__NR_SYSCALL_BASE+308) -#define __NR_add_key (__NR_SYSCALL_BASE+309) -#define __NR_request_key (__NR_SYSCALL_BASE+310) -#define __NR_keyctl (__NR_SYSCALL_BASE+311) -#define __NR_semtimedop (__NR_SYSCALL_BASE+312) -#define __NR_vserver (__NR_SYSCALL_BASE+313) -#define __NR_ioprio_set (__NR_SYSCALL_BASE+314) -#define __NR_ioprio_get (__NR_SYSCALL_BASE+315) -#define __NR_inotify_init (__NR_SYSCALL_BASE+316) -#define __NR_inotify_add_watch (__NR_SYSCALL_BASE+317) -#define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+318) -#define __NR_mbind (__NR_SYSCALL_BASE+319) -#define __NR_get_mempolicy (__NR_SYSCALL_BASE+320) -#define __NR_set_mempolicy (__NR_SYSCALL_BASE+321) -#define __NR_openat (__NR_SYSCALL_BASE+322) -#define __NR_mkdirat (__NR_SYSCALL_BASE+323) -#define __NR_mknodat (__NR_SYSCALL_BASE+324) -#define __NR_fchownat (__NR_SYSCALL_BASE+325) -#define __NR_futimesat (__NR_SYSCALL_BASE+326) -#define __NR_fstatat64 (__NR_SYSCALL_BASE+327) -#define __NR_unlinkat (__NR_SYSCALL_BASE+328) -#define __NR_renameat (__NR_SYSCALL_BASE+329) -#define __NR_linkat (__NR_SYSCALL_BASE+330) -#define __NR_symlinkat (__NR_SYSCALL_BASE+331) -#define __NR_readlinkat (__NR_SYSCALL_BASE+332) -#define __NR_fchmodat (__NR_SYSCALL_BASE+333) -#define __NR_faccessat (__NR_SYSCALL_BASE+334) -#define __NR_pselect6 (__NR_SYSCALL_BASE+335) -#define __NR_ppoll (__NR_SYSCALL_BASE+336) -#define __NR_unshare (__NR_SYSCALL_BASE+337) -#define __NR_set_robust_list (__NR_SYSCALL_BASE+338) -#define __NR_get_robust_list (__NR_SYSCALL_BASE+339) -#define __NR_splice (__NR_SYSCALL_BASE+340) -#define __NR_arm_sync_file_range (__NR_SYSCALL_BASE+341) -#define __NR_sync_file_range2 __NR_arm_sync_file_range -#define __NR_tee (__NR_SYSCALL_BASE+342) -#define __NR_vmsplice (__NR_SYSCALL_BASE+343) -#define __NR_move_pages (__NR_SYSCALL_BASE+344) -#define __NR_getcpu (__NR_SYSCALL_BASE+345) -#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346) -#define __NR_kexec_load (__NR_SYSCALL_BASE+347) -#define __NR_utimensat (__NR_SYSCALL_BASE+348) -#define __NR_signalfd (__NR_SYSCALL_BASE+349) -#define __NR_timerfd_create (__NR_SYSCALL_BASE+350) -#define __NR_eventfd (__NR_SYSCALL_BASE+351) -#define __NR_fallocate (__NR_SYSCALL_BASE+352) -#define __NR_timerfd_settime (__NR_SYSCALL_BASE+353) -#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+354) -#define __NR_signalfd4 (__NR_SYSCALL_BASE+355) -#define __NR_eventfd2 (__NR_SYSCALL_BASE+356) -#define __NR_epoll_create1 (__NR_SYSCALL_BASE+357) -#define __NR_dup3 (__NR_SYSCALL_BASE+358) -#define __NR_pipe2 (__NR_SYSCALL_BASE+359) -#define __NR_inotify_init1 (__NR_SYSCALL_BASE+360) -#define __NR_preadv (__NR_SYSCALL_BASE+361) -#define __NR_pwritev (__NR_SYSCALL_BASE+362) -#define __NR_rt_tgsigqueueinfo (__NR_SYSCALL_BASE+363) -#define __NR_perf_event_open (__NR_SYSCALL_BASE+364) -#define __NR_recvmmsg (__NR_SYSCALL_BASE+365) -#define __NR_accept4 (__NR_SYSCALL_BASE+366) -#define __NR_fanotify_init (__NR_SYSCALL_BASE+367) -#define __NR_fanotify_mark (__NR_SYSCALL_BASE+368) -#define __NR_prlimit64 (__NR_SYSCALL_BASE+369) -#define __NR_name_to_handle_at (__NR_SYSCALL_BASE+370) -#define __NR_open_by_handle_at (__NR_SYSCALL_BASE+371) -#define __NR_clock_adjtime (__NR_SYSCALL_BASE+372) -#define __NR_syncfs (__NR_SYSCALL_BASE+373) -#define __NR_sendmmsg (__NR_SYSCALL_BASE+374) -#define __NR_setns (__NR_SYSCALL_BASE+375) -#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) -#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) -#define __NR_kcmp (__NR_SYSCALL_BASE+378) -#define __NR_finit_module (__NR_SYSCALL_BASE+379) -#define __NR_sched_setattr (__NR_SYSCALL_BASE+380) -#define __NR_sched_getattr (__NR_SYSCALL_BASE+381) -#define __NR_renameat2 (__NR_SYSCALL_BASE+382) -#define __NR_seccomp (__NR_SYSCALL_BASE+383) -#define __NR_getrandom (__NR_SYSCALL_BASE+384) -#define __NR_memfd_create (__NR_SYSCALL_BASE+385) -#define __NR_bpf (__NR_SYSCALL_BASE+386) -#define __NR_execveat (__NR_SYSCALL_BASE+387) -#define __NR_userfaultfd (__NR_SYSCALL_BASE+388) -#define __NR_membarrier (__NR_SYSCALL_BASE+389) -#define __NR_mlock2 (__NR_SYSCALL_BASE+390) -#define __NR_copy_file_range (__NR_SYSCALL_BASE+391) -#define __NR_preadv2 (__NR_SYSCALL_BASE+392) -#define __NR_pwritev2 (__NR_SYSCALL_BASE+393) -#define __NR_pkey_mprotect (__NR_SYSCALL_BASE+394) -#define __NR_pkey_alloc (__NR_SYSCALL_BASE+395) -#define __NR_pkey_free (__NR_SYSCALL_BASE+396) -#define __NR_pidfd_send_signal (__NR_SYSCALL_BASE+424) -#define __NR_pidfd_open (__NR_SYSCALL_BASE+434) /* * The following SWIs are ARM private. @@ -436,24 +37,4 @@ #define __ARM_NR_usr32 (__ARM_NR_BASE+4) #define __ARM_NR_set_tls (__ARM_NR_BASE+5) -/* - * The following syscalls are obsolete and no longer available for EABI. - */ -#if !defined(__KERNEL__) -#if defined(__ARM_EABI__) -#undef __NR_time -#undef __NR_umount -#undef __NR_stime -#undef __NR_alarm -#undef __NR_utime -#undef __NR_getrlimit -#undef __NR_select -#undef __NR_readdir -#undef __NR_mmap -#undef __NR_socketcall -#undef __NR_syscall -#undef __NR_ipc -#endif -#endif - #endif /* _UAPI__ASM_ARM_UNISTD_H */ diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S deleted file mode 100644 index 4585cdf35e847c47be932a088713d28539d5ab30..0000000000000000000000000000000000000000 --- a/arch/arm/kernel/calls.S +++ /dev/null @@ -1,417 +0,0 @@ -/* - * linux/arch/arm/kernel/calls.S - * - * Copyright (C) 1995-2005 Russell King - * - * 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 file is included thrice in entry-common.S - */ -/* 0 */ CALL(sys_restart_syscall) - CALL(sys_exit) - CALL(sys_fork) - CALL(sys_read) - CALL(sys_write) -/* 5 */ CALL(sys_open) - CALL(sys_close) - CALL(sys_ni_syscall) /* was sys_waitpid */ - CALL(sys_creat) - CALL(sys_link) -/* 10 */ CALL(sys_unlink) - CALL(sys_execve) - CALL(sys_chdir) - CALL(OBSOLETE(sys_time)) /* used by libc4 */ - CALL(sys_mknod) -/* 15 */ CALL(sys_chmod) - CALL(sys_lchown16) - CALL(sys_ni_syscall) /* was sys_break */ - CALL(sys_ni_syscall) /* was sys_stat */ - CALL(sys_lseek) -/* 20 */ CALL(sys_getpid) - CALL(sys_mount) - CALL(OBSOLETE(sys_oldumount)) /* used by libc4 */ - CALL(sys_setuid16) - CALL(sys_getuid16) -/* 25 */ CALL(OBSOLETE(sys_stime)) - CALL(sys_ptrace) - CALL(OBSOLETE(sys_alarm)) /* used by libc4 */ - CALL(sys_ni_syscall) /* was sys_fstat */ - CALL(sys_pause) -/* 30 */ CALL(OBSOLETE(sys_utime)) /* used by libc4 */ - CALL(sys_ni_syscall) /* was sys_stty */ - CALL(sys_ni_syscall) /* was sys_getty */ - CALL(sys_access) - CALL(sys_nice) -/* 35 */ CALL(sys_ni_syscall) /* was sys_ftime */ - CALL(sys_sync) - CALL(sys_kill) - CALL(sys_rename) - CALL(sys_mkdir) -/* 40 */ CALL(sys_rmdir) - CALL(sys_dup) - CALL(sys_pipe) - CALL(sys_times) - CALL(sys_ni_syscall) /* was sys_prof */ -/* 45 */ CALL(sys_brk) - CALL(sys_setgid16) - CALL(sys_getgid16) - CALL(sys_ni_syscall) /* was sys_signal */ - CALL(sys_geteuid16) -/* 50 */ CALL(sys_getegid16) - CALL(sys_acct) - CALL(sys_umount) - CALL(sys_ni_syscall) /* was sys_lock */ - CALL(sys_ioctl) -/* 55 */ CALL(sys_fcntl) - CALL(sys_ni_syscall) /* was sys_mpx */ - CALL(sys_setpgid) - CALL(sys_ni_syscall) /* was sys_ulimit */ - CALL(sys_ni_syscall) /* was sys_olduname */ -/* 60 */ CALL(sys_umask) - CALL(sys_chroot) - CALL(sys_ustat) - CALL(sys_dup2) - CALL(sys_getppid) -/* 65 */ CALL(sys_getpgrp) - CALL(sys_setsid) - CALL(sys_sigaction) - CALL(sys_ni_syscall) /* was sys_sgetmask */ - CALL(sys_ni_syscall) /* was sys_ssetmask */ -/* 70 */ CALL(sys_setreuid16) - CALL(sys_setregid16) - CALL(sys_sigsuspend) - CALL(sys_sigpending) - CALL(sys_sethostname) -/* 75 */ CALL(sys_setrlimit) - CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */ - CALL(sys_getrusage) - CALL(sys_gettimeofday) - CALL(sys_settimeofday) -/* 80 */ CALL(sys_getgroups16) - CALL(sys_setgroups16) - CALL(OBSOLETE(sys_old_select)) /* used by libc4 */ - CALL(sys_symlink) - CALL(sys_ni_syscall) /* was sys_lstat */ -/* 85 */ CALL(sys_readlink) - CALL(sys_uselib) - CALL(sys_swapon) - CALL(sys_reboot) - CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ -/* 90 */ CALL(OBSOLETE(sys_old_mmap)) /* used by libc4 */ - CALL(sys_munmap) - CALL(sys_truncate) - CALL(sys_ftruncate) - CALL(sys_fchmod) -/* 95 */ CALL(sys_fchown16) - CALL(sys_getpriority) - CALL(sys_setpriority) - CALL(sys_ni_syscall) /* was sys_profil */ - CALL(sys_statfs) -/* 100 */ CALL(sys_fstatfs) - CALL(sys_ni_syscall) /* sys_ioperm */ - CALL(OBSOLETE(ABI(sys_socketcall, sys_oabi_socketcall))) - CALL(sys_syslog) - CALL(sys_setitimer) -/* 105 */ CALL(sys_getitimer) - CALL(sys_newstat) - CALL(sys_newlstat) - CALL(sys_newfstat) - CALL(sys_ni_syscall) /* was sys_uname */ -/* 110 */ CALL(sys_ni_syscall) /* was sys_iopl */ - CALL(sys_vhangup) - CALL(sys_ni_syscall) - CALL(OBSOLETE(sys_syscall)) /* call a syscall */ - CALL(sys_wait4) -/* 115 */ CALL(sys_swapoff) - CALL(sys_sysinfo) - CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))) - CALL(sys_fsync) - CALL(sys_sigreturn_wrapper) -/* 120 */ CALL(sys_clone) - CALL(sys_setdomainname) - CALL(sys_newuname) - CALL(sys_ni_syscall) /* modify_ldt */ - CALL(sys_adjtimex) -/* 125 */ CALL(sys_mprotect) - CALL(sys_sigprocmask) - CALL(sys_ni_syscall) /* was sys_create_module */ - CALL(sys_init_module) - CALL(sys_delete_module) -/* 130 */ CALL(sys_ni_syscall) /* was sys_get_kernel_syms */ - CALL(sys_quotactl) - CALL(sys_getpgid) - CALL(sys_fchdir) - CALL(sys_bdflush) -/* 135 */ CALL(sys_sysfs) - CALL(sys_personality) - CALL(sys_ni_syscall) /* reserved for afs_syscall */ - CALL(sys_setfsuid16) - CALL(sys_setfsgid16) -/* 140 */ CALL(sys_llseek) - CALL(sys_getdents) - CALL(sys_select) - CALL(sys_flock) - CALL(sys_msync) -/* 145 */ CALL(sys_readv) - CALL(sys_writev) - CALL(sys_getsid) - CALL(sys_fdatasync) - CALL(sys_sysctl) -/* 150 */ CALL(sys_mlock) - CALL(sys_munlock) - CALL(sys_mlockall) - CALL(sys_munlockall) - CALL(sys_sched_setparam) -/* 155 */ CALL(sys_sched_getparam) - CALL(sys_sched_setscheduler) - CALL(sys_sched_getscheduler) - CALL(sys_sched_yield) - CALL(sys_sched_get_priority_max) -/* 160 */ CALL(sys_sched_get_priority_min) - CALL(sys_sched_rr_get_interval) - CALL(sys_nanosleep) - CALL(sys_mremap) - CALL(sys_setresuid16) -/* 165 */ CALL(sys_getresuid16) - CALL(sys_ni_syscall) /* vm86 */ - CALL(sys_ni_syscall) /* was sys_query_module */ - CALL(sys_poll) - CALL(sys_ni_syscall) /* was nfsservctl */ -/* 170 */ CALL(sys_setresgid16) - CALL(sys_getresgid16) - CALL(sys_prctl) - CALL(sys_rt_sigreturn_wrapper) - CALL(sys_rt_sigaction) -/* 175 */ CALL(sys_rt_sigprocmask) - CALL(sys_rt_sigpending) - CALL(sys_rt_sigtimedwait) - CALL(sys_rt_sigqueueinfo) - CALL(sys_rt_sigsuspend) -/* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64)) - CALL(ABI(sys_pwrite64, sys_oabi_pwrite64)) - CALL(sys_chown16) - CALL(sys_getcwd) - CALL(sys_capget) -/* 185 */ CALL(sys_capset) - CALL(sys_sigaltstack) - CALL(sys_sendfile) - CALL(sys_ni_syscall) /* getpmsg */ - CALL(sys_ni_syscall) /* putpmsg */ -/* 190 */ CALL(sys_vfork) - CALL(sys_getrlimit) - CALL(sys_mmap2) - CALL(ABI(sys_truncate64, sys_oabi_truncate64)) - CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64)) -/* 195 */ CALL(ABI(sys_stat64, sys_oabi_stat64)) - CALL(ABI(sys_lstat64, sys_oabi_lstat64)) - CALL(ABI(sys_fstat64, sys_oabi_fstat64)) - CALL(sys_lchown) - CALL(sys_getuid) -/* 200 */ CALL(sys_getgid) - CALL(sys_geteuid) - CALL(sys_getegid) - CALL(sys_setreuid) - CALL(sys_setregid) -/* 205 */ CALL(sys_getgroups) - CALL(sys_setgroups) - CALL(sys_fchown) - CALL(sys_setresuid) - CALL(sys_getresuid) -/* 210 */ CALL(sys_setresgid) - CALL(sys_getresgid) - CALL(sys_chown) - CALL(sys_setuid) - CALL(sys_setgid) -/* 215 */ CALL(sys_setfsuid) - CALL(sys_setfsgid) - CALL(sys_getdents64) - CALL(sys_pivot_root) - CALL(sys_mincore) -/* 220 */ CALL(sys_madvise) - CALL(ABI(sys_fcntl64, sys_oabi_fcntl64)) - CALL(sys_ni_syscall) /* TUX */ - CALL(sys_ni_syscall) - CALL(sys_gettid) -/* 225 */ CALL(ABI(sys_readahead, sys_oabi_readahead)) - CALL(sys_setxattr) - CALL(sys_lsetxattr) - CALL(sys_fsetxattr) - CALL(sys_getxattr) -/* 230 */ CALL(sys_lgetxattr) - CALL(sys_fgetxattr) - CALL(sys_listxattr) - CALL(sys_llistxattr) - CALL(sys_flistxattr) -/* 235 */ CALL(sys_removexattr) - CALL(sys_lremovexattr) - CALL(sys_fremovexattr) - CALL(sys_tkill) - CALL(sys_sendfile64) -/* 240 */ CALL(sys_futex) - CALL(sys_sched_setaffinity) - CALL(sys_sched_getaffinity) - CALL(sys_io_setup) - CALL(sys_io_destroy) -/* 245 */ CALL(sys_io_getevents) - CALL(sys_io_submit) - CALL(sys_io_cancel) - CALL(sys_exit_group) - CALL(sys_lookup_dcookie) -/* 250 */ CALL(sys_epoll_create) - CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)) - CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait)) - CALL(sys_remap_file_pages) - CALL(sys_ni_syscall) /* sys_set_thread_area */ -/* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */ - CALL(sys_set_tid_address) - CALL(sys_timer_create) - CALL(sys_timer_settime) - CALL(sys_timer_gettime) -/* 260 */ CALL(sys_timer_getoverrun) - CALL(sys_timer_delete) - CALL(sys_clock_settime) - CALL(sys_clock_gettime) - CALL(sys_clock_getres) -/* 265 */ CALL(sys_clock_nanosleep) - CALL(sys_statfs64_wrapper) - CALL(sys_fstatfs64_wrapper) - CALL(sys_tgkill) - CALL(sys_utimes) -/* 270 */ CALL(sys_arm_fadvise64_64) - CALL(sys_pciconfig_iobase) - CALL(sys_pciconfig_read) - CALL(sys_pciconfig_write) - CALL(sys_mq_open) -/* 275 */ CALL(sys_mq_unlink) - CALL(sys_mq_timedsend) - CALL(sys_mq_timedreceive) - CALL(sys_mq_notify) - CALL(sys_mq_getsetattr) -/* 280 */ CALL(sys_waitid) - CALL(sys_socket) - CALL(ABI(sys_bind, sys_oabi_bind)) - CALL(ABI(sys_connect, sys_oabi_connect)) - CALL(sys_listen) -/* 285 */ CALL(sys_accept) - CALL(sys_getsockname) - CALL(sys_getpeername) - CALL(sys_socketpair) - CALL(sys_send) -/* 290 */ CALL(ABI(sys_sendto, sys_oabi_sendto)) - CALL(sys_recv) - CALL(sys_recvfrom) - CALL(sys_shutdown) - CALL(sys_setsockopt) -/* 295 */ CALL(sys_getsockopt) - CALL(ABI(sys_sendmsg, sys_oabi_sendmsg)) - CALL(sys_recvmsg) - CALL(ABI(sys_semop, sys_oabi_semop)) - CALL(sys_semget) -/* 300 */ CALL(sys_semctl) - CALL(sys_msgsnd) - CALL(sys_msgrcv) - CALL(sys_msgget) - CALL(sys_msgctl) -/* 305 */ CALL(sys_shmat) - CALL(sys_shmdt) - CALL(sys_shmget) - CALL(sys_shmctl) - CALL(sys_add_key) -/* 310 */ CALL(sys_request_key) - CALL(sys_keyctl) - CALL(ABI(sys_semtimedop, sys_oabi_semtimedop)) -/* vserver */ CALL(sys_ni_syscall) - CALL(sys_ioprio_set) -/* 315 */ CALL(sys_ioprio_get) - CALL(sys_inotify_init) - CALL(sys_inotify_add_watch) - CALL(sys_inotify_rm_watch) - CALL(sys_mbind) -/* 320 */ CALL(sys_get_mempolicy) - CALL(sys_set_mempolicy) - CALL(sys_openat) - CALL(sys_mkdirat) - CALL(sys_mknodat) -/* 325 */ CALL(sys_fchownat) - CALL(sys_futimesat) - CALL(ABI(sys_fstatat64, sys_oabi_fstatat64)) - CALL(sys_unlinkat) - CALL(sys_renameat) -/* 330 */ CALL(sys_linkat) - CALL(sys_symlinkat) - CALL(sys_readlinkat) - CALL(sys_fchmodat) - CALL(sys_faccessat) -/* 335 */ CALL(sys_pselect6) - CALL(sys_ppoll) - CALL(sys_unshare) - CALL(sys_set_robust_list) - CALL(sys_get_robust_list) -/* 340 */ CALL(sys_splice) - CALL(sys_sync_file_range2) - CALL(sys_tee) - CALL(sys_vmsplice) - CALL(sys_move_pages) -/* 345 */ CALL(sys_getcpu) - CALL(sys_epoll_pwait) - CALL(sys_kexec_load) - CALL(sys_utimensat) - CALL(sys_signalfd) -/* 350 */ CALL(sys_timerfd_create) - CALL(sys_eventfd) - CALL(sys_fallocate) - CALL(sys_timerfd_settime) - CALL(sys_timerfd_gettime) -/* 355 */ CALL(sys_signalfd4) - CALL(sys_eventfd2) - CALL(sys_epoll_create1) - CALL(sys_dup3) - CALL(sys_pipe2) -/* 360 */ CALL(sys_inotify_init1) - CALL(sys_preadv) - CALL(sys_pwritev) - CALL(sys_rt_tgsigqueueinfo) - CALL(sys_perf_event_open) -/* 365 */ CALL(sys_recvmmsg) - CALL(sys_accept4) - CALL(sys_fanotify_init) - CALL(sys_fanotify_mark) - CALL(sys_prlimit64) -/* 370 */ CALL(sys_name_to_handle_at) - CALL(sys_open_by_handle_at) - CALL(sys_clock_adjtime) - CALL(sys_syncfs) - CALL(sys_sendmmsg) -/* 375 */ CALL(sys_setns) - CALL(sys_process_vm_readv) - CALL(sys_process_vm_writev) - CALL(sys_kcmp) - CALL(sys_finit_module) -/* 380 */ CALL(sys_sched_setattr) - CALL(sys_sched_getattr) - CALL(sys_renameat2) - CALL(sys_seccomp) - CALL(sys_getrandom) -/* 385 */ CALL(sys_memfd_create) - CALL(sys_bpf) - CALL(sys_execveat) - CALL(sys_userfaultfd) - CALL(sys_membarrier) -/* 390 */ CALL(sys_mlock2) - CALL(sys_copy_file_range) - CALL(sys_preadv2) - CALL(sys_pwritev2) - CALL(sys_pkey_mprotect) -/* 395 */ CALL(sys_pkey_alloc) - CALL(sys_pkey_free) - CALL(sys_pidfd_send_signal) - CALL(sys_pidfd_open) -#ifndef syscalls_counted -.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls -#define syscalls_counted -#endif -.rept syscalls_padding - CALL(sys_ni_syscall) -.endr diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 8d6c75167822cc53e726c3098fef69d31bb3e788..3b5af1c85e40a9d6158dbb68f9d8d64cadd5ee5a 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -13,6 +13,11 @@ #include #include #include +#ifdef CONFIG_AEABI +#include +#endif + + .equ NR_syscalls, __NR_syscalls #ifdef CONFIG_NEED_RET_TO_USER #include @@ -132,21 +137,6 @@ ENTRY(ret_from_fork) b ret_slow_syscall ENDPROC(ret_from_fork) - .equ NR_syscalls,0 -#define CALL(x) .equ NR_syscalls,NR_syscalls+1 -#include "calls.S" - -/* - * Ensure that the system call table is equal to __NR_syscalls, - * which is the value the rest of the system sees - */ -.ifne NR_syscalls - __NR_syscalls -.error "__NR_syscalls is not equal to the size of the syscall table" -.endif - -#undef CALL -#define CALL(x) .long x - /*============================================================================= * SWI handler *----------------------------------------------------------------------------- @@ -294,22 +284,48 @@ __cr_alignment: #endif .ltorg + .macro syscall_table_start, sym + .equ __sys_nr, 0 + .type \sym, #object +ENTRY(\sym) + .endm + + .macro syscall, nr, func + .ifgt __sys_nr - \nr + .error "Duplicated/unorded system call entry" + .endif + .rept \nr - __sys_nr + .long sys_ni_syscall + .endr + .long \func + .equ __sys_nr, \nr + 1 + .endm + + .macro syscall_table_end, sym + .ifgt __sys_nr - __NR_syscalls + .error "System call table too big" + .endif + .rept __NR_syscalls - __sys_nr + .long sys_ni_syscall + .endr + .size \sym, . - \sym + .endm + +#define NATIVE(nr, func) syscall nr, func + /* * This is the syscall table declaration for native ABI syscalls. * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall. */ -#define ABI(native, compat) native + syscall_table_start sys_call_table +#define COMPAT(nr, native, compat) syscall nr, native #ifdef CONFIG_AEABI -#define OBSOLETE(syscall) sys_ni_syscall +#include #else -#define OBSOLETE(syscall) syscall +#include #endif - - .type sys_call_table, #object -ENTRY(sys_call_table) -#include "calls.S" -#undef ABI -#undef OBSOLETE +#undef COMPAT + syscall_table_end sys_call_table /*============================================================================ * Special system call wrappers @@ -414,14 +430,10 @@ ENDPROC(sys_oabi_readahead) * Let's declare a second syscall table for old ABI binaries * using the compatibility syscall entries. */ -#define ABI(native, compat) compat -#define OBSOLETE(syscall) syscall - - .type sys_oabi_call_table, #object -ENTRY(sys_oabi_call_table) -#include "calls.S" -#undef ABI -#undef OBSOLETE + syscall_table_start sys_oabi_call_table +#define COMPAT(nr, native, compat) syscall nr, compat +#include + syscall_table_end sys_oabi_call_table #endif diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S index 15d073ae5da2a2123980b2fc67c3986161cd0839..f5e5e3e196592bccc65c779a4800a345562da666 100644 --- a/arch/arm/kernel/hyp-stub.S +++ b/arch/arm/kernel/hyp-stub.S @@ -179,8 +179,8 @@ ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE @ Check whether GICv3 system registers are available mrc p15, 0, r7, c0, c1, 1 @ ID_PFR1 ubfx r7, r7, #28, #4 - cmp r7, #1 - bne 2f + teq r7, #0 + beq 2f @ Enable system register accesses mrc p15, 4, r7, c12, c9, 5 @ ICC_HSRE diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index 0f6c1000582c359881b6985c57d010037cb4ac17..c8569390e7e7e8f39eb333de26aba62c9221c1ef 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -119,6 +119,14 @@ ENDPROC(cpu_resume_after_mmu) .text .align +#ifdef CONFIG_MCPM + .arm +THUMB( .thumb ) +ENTRY(cpu_resume_no_hyp) +ARM_BE8(setend be) @ ensure we are in BE mode + b no_hyp +#endif + #ifdef CONFIG_MMU .arm ENTRY(cpu_resume_arm) @@ -134,6 +142,7 @@ ARM_BE8(setend be) @ ensure we are in BE mode bl __hyp_stub_install_secondary #endif safe_svcmode_maskall r1 +no_hyp: mov r1, #0 ALT_SMP(mrc p15, 0, r0, c0, c0, 5) ALT_UP_B(1f) @@ -162,6 +171,9 @@ ENDPROC(cpu_resume) #ifdef CONFIG_MMU ENDPROC(cpu_resume_arm) +#endif +#ifdef CONFIG_MCPM +ENDPROC(cpu_resume_no_hyp) #endif .align 2 diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c index 890439737374242e78a0ee8fb26bc6ddbcda0954..bf6e45dec017373d0259b5c83038ca0e2c5749b8 100644 --- a/arch/arm/kernel/vdso.c +++ b/arch/arm/kernel/vdso.c @@ -85,6 +85,8 @@ static bool __init cntvct_functional(void) * this. */ np = of_find_compatible_node(NULL, NULL, "arm,armv7-timer"); + if (!np) + np = of_find_compatible_node(NULL, NULL, "arm,armv8-timer"); if (!np) goto out_put; diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 6709a8d33963b679b0a0f6ec683e3291a7f07a71..f1e34f16cfab9ad98db4628c78bbf558544cebc5 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S @@ -100,7 +100,7 @@ ENTRY(arm_copy_from_user) ENDPROC(arm_copy_from_user) - .pushsection .fixup,"ax" + .pushsection .text.fixup,"ax" .align 0 copy_abort_preamble ldmfd sp!, {r1, r2, r3} diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 746e7801dcdf70fed9e339c2d6800b3f275c49b7..b2e4bc3a635e22002fd90eaf4d802b528f6dab32 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -42,6 +42,12 @@ _ASM_NOKPROBE(__get_user_1) ENTRY(__get_user_2) check_uaccess r0, 2, r1, r2, __get_user_bad +#if __LINUX_ARM_ARCH__ >= 6 + +2: TUSER(ldrh) r2, [r0] + +#else + #ifdef CONFIG_CPU_USE_DOMAINS rb .req ip 2: ldrbt r2, [r0], #1 @@ -56,6 +62,9 @@ rb .req r0 #else orr r2, rb, r2, lsl #8 #endif + +#endif /* __LINUX_ARM_ARCH__ >= 6 */ + mov r0, #0 ret lr ENDPROC(__get_user_2) @@ -145,7 +154,9 @@ _ASM_NOKPROBE(__get_user_bad8) .pushsection __ex_table, "a" .long 1b, __get_user_bad .long 2b, __get_user_bad +#if __LINUX_ARM_ARCH__ < 6 .long 3b, __get_user_bad +#endif .long 4b, __get_user_bad .long 5b, __get_user_bad8 .long 6b, __get_user_bad8 diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 38d660d3705f4f259c5299d2cc8c1126f0a1dbb4..515eeaa9975c6cbf75b8aba01d85df7deb063b25 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -41,16 +41,13 @@ ENDPROC(__put_user_1) ENTRY(__put_user_2) check_uaccess r0, 2, r1, ip, __put_user_bad - mov ip, r2, lsr #8 -#ifdef CONFIG_THUMB2_KERNEL -#ifndef __ARMEB__ -2: TUSER(strb) r2, [r0] -3: TUSER(strb) ip, [r0, #1] +#if __LINUX_ARM_ARCH__ >= 6 + +2: TUSER(strh) r2, [r0] + #else -2: TUSER(strb) ip, [r0] -3: TUSER(strb) r2, [r0, #1] -#endif -#else /* !CONFIG_THUMB2_KERNEL */ + + mov ip, r2, lsr #8 #ifndef __ARMEB__ 2: TUSER(strb) r2, [r0], #1 3: TUSER(strb) ip, [r0] @@ -58,7 +55,8 @@ ENTRY(__put_user_2) 2: TUSER(strb) ip, [r0], #1 3: TUSER(strb) r2, [r0] #endif -#endif /* CONFIG_THUMB2_KERNEL */ + +#endif /* __LINUX_ARM_ARCH__ >= 6 */ mov r0, #0 ret lr ENDPROC(__put_user_2) @@ -91,7 +89,9 @@ ENDPROC(__put_user_bad) .pushsection __ex_table, "a" .long 1b, __put_user_bad .long 2b, __put_user_bad +#if __LINUX_ARM_ARCH__ < 6 .long 3b, __put_user_bad +#endif .long 4b, __put_user_bad .long 5b, __put_user_bad .long 6b, __put_user_bad diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index cab128913e72a710a0f405336b0d814e56935546..3a4014870a91b184ed469c67f0d4ce56d8d3ca13 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -86,6 +86,8 @@ AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o endif +AFLAGS_resume-imx6.o :=-Wa,-march=armv7-a +obj-$(CONFIG_SOC_IMX6) += resume-imx6.o obj-$(CONFIG_SOC_IMX6) += pm-imx6.o obj-$(CONFIG_SOC_IMX1) += mach-imx1.o diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index c4436d9c52ff92fed3417d4604f2801fff67a4e2..a3f6885cefbf9a54f3fbfd4ac788b668818eb978 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -112,17 +112,17 @@ void imx_cpu_die(unsigned int cpu); int imx_cpu_kill(unsigned int cpu); #ifdef CONFIG_SUSPEND -void v7_cpu_resume(void); void imx53_suspend(void __iomem *ocram_vbase); extern const u32 imx53_suspend_sz; void imx6_suspend(void __iomem *ocram_vbase); #else -static inline void v7_cpu_resume(void) {} static inline void imx53_suspend(void __iomem *ocram_vbase) {} static const u32 imx53_suspend_sz; static inline void imx6_suspend(void __iomem *ocram_vbase) {} #endif +void v7_cpu_resume(void); + void imx6_pm_ccm_init(const char *ccm_compat); void imx6q_pm_init(void); void imx6dl_pm_init(void); diff --git a/arch/arm/mach-imx/resume-imx6.S b/arch/arm/mach-imx/resume-imx6.S new file mode 100644 index 0000000000000000000000000000000000000000..5bd1ba7ef15b61cb98d1bd2d3af4e85acc5ec632 --- /dev/null +++ b/arch/arm/mach-imx/resume-imx6.S @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include +#include +#include +#include +#include "hardware.h" + +/* + * The following code must assume it is running from physical address + * where absolute virtual addresses to the data section have to be + * turned into relative ones. + */ + +ENTRY(v7_cpu_resume) + bl v7_invalidate_l1 +#ifdef CONFIG_CACHE_L2X0 + bl l2c310_early_resume +#endif + b cpu_resume +ENDPROC(v7_cpu_resume) diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S index 76ee2ceec8d546d0ca3f51aebcb8f40509213ba6..7d84b617af4815817d3ffbb60b8c067bcbb8a41b 100644 --- a/arch/arm/mach-imx/suspend-imx6.S +++ b/arch/arm/mach-imx/suspend-imx6.S @@ -333,17 +333,3 @@ resume: ret lr ENDPROC(imx6_suspend) - -/* - * The following code must assume it is running from physical address - * where absolute virtual addresses to the data section have to be - * turned into relative ones. - */ - -ENTRY(v7_cpu_resume) - bl v7_invalidate_l1 -#ifdef CONFIG_CACHE_L2X0 - bl l2c310_early_resume -#endif - b cpu_resume -ENDPROC(v7_cpu_resume) diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c index 52de382fc8047148f272dd57d7dd01354ec33801..7e49dfda3d2f4491645abfbd9af4830c132d7dca 100644 --- a/arch/arm/mach-omap1/id.c +++ b/arch/arm/mach-omap1/id.c @@ -200,10 +200,10 @@ void __init omap_check_revision(void) printk(KERN_INFO "Unknown OMAP cpu type: 0x%02x\n", cpu_type); } - printk(KERN_INFO "OMAP%04x", omap_revision >> 16); + pr_info("OMAP%04x", omap_revision >> 16); if ((omap_revision >> 8) & 0xff) - printk(KERN_INFO "%x", (omap_revision >> 8) & 0xff); - printk(KERN_INFO " revision %i handled as %02xxx id: %08x%08x\n", + pr_cont("%x", (omap_revision >> 8) & 0xff); + pr_cont(" revision %i handled as %02xxx id: %08x%08x\n", die_rev, omap_revision & 0xff, system_serial_low, system_serial_high); } diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index cc6d9fa609242e2cb4660db80de5092b95ddd636..9d942f022f2f6fb104cf9ba212f4d886b78ef4f4 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -199,8 +199,8 @@ void __init omap2xxx_check_revision(void) pr_info("%s", soc_name); if ((omap_rev() >> 8) & 0x0f) - pr_info("%s", soc_rev); - pr_info("\n"); + pr_cont("%s", soc_rev); + pr_cont("\n"); } #define OMAP3_SHOW_FEATURE(feat) \ diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bfc74954540ce7f1b037443c01b35998080af813..9421b78f869d3f798817356fd36061dc674ddba1 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2588,7 +2588,7 @@ static void _setup_iclk_autoidle(struct omap_hwmod *oh) */ static int _setup_reset(struct omap_hwmod *oh) { - int r; + int r = 0; if (oh->_state != _HWMOD_STATE_INITIALIZED) return -EINVAL; diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 88676fe9b11941f29b5415063851b6457b501b89..c3b3972c301a59bde1b65ae5cdb441afa0a9fe1f 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -308,108 +308,15 @@ static void __init omap3_logicpd_torpedo_init(void) } /* omap3pandora legacy devices */ -#define PANDORA_WIFI_IRQ_GPIO 21 -#define PANDORA_WIFI_NRESET_GPIO 23 static struct platform_device pandora_backlight = { .name = "pandora-backlight", .id = -1, }; -static struct regulator_consumer_supply pandora_vmmc3_supply[] = { - REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"), -}; - -static struct regulator_init_data pandora_vmmc3 = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_vmmc3_supply), - .consumer_supplies = pandora_vmmc3_supply, -}; - -static struct fixed_voltage_config pandora_vwlan = { - .supply_name = "vwlan", - .microvolts = 1800000, /* 1.8V */ - .gpio = PANDORA_WIFI_NRESET_GPIO, - .startup_delay = 50000, /* 50ms */ - .enable_high = 1, - .init_data = &pandora_vmmc3, -}; - -static struct platform_device pandora_vwlan_device = { - .name = "reg-fixed-voltage", - .id = 1, - .dev = { - .platform_data = &pandora_vwlan, - }, -}; - -static void pandora_wl1251_init_card(struct mmc_card *card) -{ - /* - * We have TI wl1251 attached to MMC3. Pass this information to - * SDIO core because it can't be probed by normal methods. - */ - if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) { - card->quirks |= MMC_QUIRK_NONSTD_SDIO; - card->cccr.wide_bus = 1; - card->cis.vendor = 0x104c; - card->cis.device = 0x9066; - card->cis.blksize = 512; - card->cis.max_dtr = 24000000; - card->ocr = 0x80; - } -} - -static struct omap2_hsmmc_info pandora_mmc3[] = { - { - .mmc = 3, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, - .gpio_cd = -EINVAL, - .gpio_wp = -EINVAL, - .init_card = pandora_wl1251_init_card, - }, - {} /* Terminator */ -}; - -static void __init pandora_wl1251_init(void) -{ - struct wl1251_platform_data pandora_wl1251_pdata; - int ret; - - memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata)); - - pandora_wl1251_pdata.power_gpio = -1; - - ret = gpio_request_one(PANDORA_WIFI_IRQ_GPIO, GPIOF_IN, "wl1251 irq"); - if (ret < 0) - goto fail; - - pandora_wl1251_pdata.irq = gpio_to_irq(PANDORA_WIFI_IRQ_GPIO); - if (pandora_wl1251_pdata.irq < 0) - goto fail_irq; - - pandora_wl1251_pdata.use_eeprom = true; - ret = wl1251_set_platform_data(&pandora_wl1251_pdata); - if (ret < 0) - goto fail_irq; - - return; - -fail_irq: - gpio_free(PANDORA_WIFI_IRQ_GPIO); -fail: - pr_err("wl1251 board initialisation failed\n"); -} - static void __init omap3_pandora_legacy_init(void) { platform_device_register(&pandora_backlight); - platform_device_register(&pandora_vwlan_device); - omap_hsmmc_init(pandora_mmc3); - omap_hsmmc_late_init(pandora_mmc3); - pandora_wl1251_init(); } #endif /* CONFIG_ARCH_OMAP3 */ diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c index 66502e6207fea86a8289d8697cf2db6c8cb6363c..fce7fecbd8fa428b5332f43cebd262d4453e4fb3 100644 --- a/arch/arm/mach-rpc/irq.c +++ b/arch/arm/mach-rpc/irq.c @@ -117,7 +117,7 @@ extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end; void __init rpc_init_irq(void) { - unsigned int irq, clr, set = 0; + unsigned int irq, clr, set; iomd_writeb(0, IOMD_IRQMASKA); iomd_writeb(0, IOMD_IRQMASKB); @@ -129,6 +129,7 @@ void __init rpc_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { clr = IRQ_NOREQUEST; + set = 0; if (irq <= 6 || (irq >= 9 && irq <= 15)) clr |= IRQ_NOPROBE; diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S index e3070fdab80b8b7481c0527e2d649ae7d664dc58..3fe4ae654047fcf73fd5d9734a5f0389bac80c2c 100644 --- a/arch/arm/mach-tegra/reset-handler.S +++ b/arch/arm/mach-tegra/reset-handler.S @@ -56,16 +56,16 @@ ENTRY(tegra_resume) cmp r6, #TEGRA20 beq 1f @ Yes /* Clear the flow controller flags for this CPU. */ - cpu_to_csr_reg r1, r0 + cpu_to_csr_reg r3, r0 mov32 r2, TEGRA_FLOW_CTRL_BASE - ldr r1, [r2, r1] + ldr r1, [r2, r3] /* Clear event & intr flag */ orr r1, r1, \ #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG movw r0, #0x3FFD @ enable, cluster_switch, immed, bitmaps @ & ext flags for CPU power mgnt bic r1, r1, r0 - str r1, [r2] + str r1, [r2, r3] 1: mov32 r9, 0xc09 diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S index 16e5ff03383cad5b709eb42b24340b033f86a2c7..91b3f06e5425bfd52c7ed9dc4ce5ae4b00913e01 100644 --- a/arch/arm/mach-tegra/sleep-tegra30.S +++ b/arch/arm/mach-tegra/sleep-tegra30.S @@ -382,6 +382,14 @@ _pll_m_c_x_done: pll_locked r1, r0, CLK_RESET_PLLC_BASE pll_locked r1, r0, CLK_RESET_PLLX_BASE + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 + cmp r1, #TEGRA30 + beq 1f + ldr r1, [r0, #CLK_RESET_PLLP_BASE] + bic r1, r1, #(1<<31) @ disable PllP bypass + str r1, [r0, #CLK_RESET_PLLP_BASE] +1: + mov32 r7, TEGRA_TMRUS_BASE ldr r1, [r7] add r1, r1, #LOCK_DELAY @@ -641,7 +649,10 @@ tegra30_switch_cpu_to_clk32k: str r0, [r4, #PMC_PLLP_WB0_OVERRIDE] /* disable PLLP, PLLA, PLLC and PLLX */ + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 + cmp r1, #TEGRA30 ldr r0, [r5, #CLK_RESET_PLLP_BASE] + orrne r0, r0, #(1 << 31) @ enable PllP bypass on fast cluster bic r0, r0, #(1 << 30) str r0, [r5, #CLK_RESET_PLLP_BASE] ldr r0, [r5, #CLK_RESET_PLLA_BASE] diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c index fe488523694c17618835e0224347de7a377a821b..635b0d54948741a34e8d23733fe4a343e388787e 100644 --- a/arch/arm/mach-vexpress/spc.c +++ b/arch/arm/mach-vexpress/spc.c @@ -555,8 +555,9 @@ static struct clk *ve_spc_clk_register(struct device *cpu_dev) static int __init ve_spc_clk_init(void) { - int cpu; + int cpu, cluster; struct clk *clk; + bool init_opp_table[MAX_CLUSTERS] = { false }; if (!info) return 0; /* Continue only if SPC is initialised */ @@ -582,8 +583,17 @@ static int __init ve_spc_clk_init(void) continue; } + cluster = topology_physical_package_id(cpu_dev->id); + if (init_opp_table[cluster]) + continue; + if (ve_init_opp_table(cpu_dev)) pr_warn("failed to initialise cpu%d opp table\n", cpu); + else if (dev_pm_opp_set_sharing_cpus(cpu_dev, + topology_core_cpumask(cpu_dev->id))) + pr_warn("failed to mark OPPs shared for cpu%d\n", cpu); + else + init_opp_table[cluster] = true; } platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0); diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index b92673efffffb630e83948604b34d3489eef2ff4..97bd43c16cd872d370229b6b4037914bb910160d 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c @@ -230,18 +230,12 @@ static int pxa_ssp_probe(struct platform_device *pdev) static int pxa_ssp_remove(struct platform_device *pdev) { - struct resource *res; struct ssp_device *ssp; ssp = platform_get_drvdata(pdev); if (ssp == NULL) return -ENODEV; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - clk_put(ssp->clk); - mutex_lock(&ssp_lock); list_del(&ssp->node); mutex_unlock(&ssp_lock); diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile index 6e4cd1867a9f5e915e31bc10395655931fcf18b6..92eb5c3b486c9b64c4927f5781d8a6cff1c7ecf7 100644 --- a/arch/arm/tools/Makefile +++ b/arch/arm/tools/Makefile @@ -4,10 +4,76 @@ # Copyright (C) 2001 Russell King # +gen := arch/$(ARCH)/include/generated +kapi := $(gen)/asm +uapi := $(gen)/uapi/asm +syshdr := $(srctree)/$(src)/syscallhdr.sh +sysnr := $(srctree)/$(src)/syscallnr.sh +systbl := $(srctree)/$(src)/syscalltbl.sh +syscall := $(srctree)/$(src)/syscall.tbl + +gen-y := $(gen)/calls-oabi.S +gen-y += $(gen)/calls-eabi.S +kapi-hdrs-y := $(kapi)/unistd-nr.h +kapi-hdrs-y += $(kapi)/mach-types.h +uapi-hdrs-y := $(uapi)/unistd-common.h +uapi-hdrs-y += $(uapi)/unistd-oabi.h +uapi-hdrs-y += $(uapi)/unistd-eabi.h + +targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y)) + +PHONY += kapi uapi + +kapi: $(kapi-hdrs-y) $(gen-y) + +uapi: $(uapi-hdrs-y) + +# Create output directory if not already present +_dummy := $(shell [ -d '$(kapi)' ] || mkdir -p '$(kapi)') \ + $(shell [ -d '$(uapi)' ] || mkdir -p '$(uapi)') + quiet_cmd_gen_mach = GEN $@ cmd_gen_mach = mkdir -p $(dir $@) && \ $(AWK) -f $(filter-out $(PHONY),$^) > $@ || \ { rm -f $@; /bin/false; } -include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types FORCE +$(kapi)/mach-types.h: $(src)/gen-mach-types $(src)/mach-types FORCE $(call if_changed,gen_mach) + +quiet_cmd_syshdr = SYSHDR $@ + cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \ + '$(syshdr_abi_$(basetarget))' \ + '$(syshdr_pfx_$(basetarget))' \ + '__NR_SYSCALL_BASE' + +quiet_cmd_systbl = SYSTBL $@ + cmd_systbl = $(CONFIG_SHELL) '$(systbl)' '$<' '$@' \ + '$(systbl_abi_$(basetarget))' + +quiet_cmd_sysnr = SYSNR $@ + cmd_sysnr = $(CONFIG_SHELL) '$(sysnr)' '$<' '$@' \ + '$(syshdr_abi_$(basetarget))' + +syshdr_abi_unistd-common := common +$(uapi)/unistd-common.h: $(syscall) $(syshdr) FORCE + $(call if_changed,syshdr) + +syshdr_abi_unistd-oabi := oabi +$(uapi)/unistd-oabi.h: $(syscall) $(syshdr) FORCE + $(call if_changed,syshdr) + +syshdr_abi_unistd-eabi := eabi +$(uapi)/unistd-eabi.h: $(syscall) $(syshdr) FORCE + $(call if_changed,syshdr) + +sysnr_abi_unistd-nr := common,oabi,eabi,compat +$(kapi)/unistd-nr.h: $(syscall) $(sysnr) FORCE + $(call if_changed,sysnr) + +systbl_abi_calls-oabi := common,oabi +$(gen)/calls-oabi.S: $(syscall) $(systbl) FORCE + $(call if_changed,systbl) + +systbl_abi_calls-eabi := common,eabi +$(gen)/calls-eabi.S: $(syscall) $(systbl) FORCE + $(call if_changed,systbl) diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl new file mode 100644 index 0000000000000000000000000000000000000000..98c6dd99cd0c8535ecb509efb0df8161be94b544 --- /dev/null +++ b/arch/arm/tools/syscall.tbl @@ -0,0 +1,415 @@ +# +# Linux system call numbers and entry vectors +# +# The format is: +# [ []] +# +# Where abi is: +# common - for system calls shared between oabi and eabi (may have compat) +# oabi - for oabi-only system calls (may have compat) +# eabi - for eabi-only system calls +# +# For each syscall number, "common" is mutually exclusive with oabi and eabi +# +0 common restart_syscall sys_restart_syscall +1 common exit sys_exit +2 common fork sys_fork +3 common read sys_read +4 common write sys_write +5 common open sys_open +6 common close sys_close +# 7 was sys_waitpid +8 common creat sys_creat +9 common link sys_link +10 common unlink sys_unlink +11 common execve sys_execve +12 common chdir sys_chdir +13 oabi time sys_time +14 common mknod sys_mknod +15 common chmod sys_chmod +16 common lchown sys_lchown16 +# 17 was sys_break +# 18 was sys_stat +19 common lseek sys_lseek +20 common getpid sys_getpid +21 common mount sys_mount +22 oabi umount sys_oldumount +23 common setuid sys_setuid16 +24 common getuid sys_getuid16 +25 oabi stime sys_stime +26 common ptrace sys_ptrace +27 oabi alarm sys_alarm +# 28 was sys_fstat +29 common pause sys_pause +30 oabi utime sys_utime +# 31 was sys_stty +# 32 was sys_gtty +33 common access sys_access +34 common nice sys_nice +# 35 was sys_ftime +36 common sync sys_sync +37 common kill sys_kill +38 common rename sys_rename +39 common mkdir sys_mkdir +40 common rmdir sys_rmdir +41 common dup sys_dup +42 common pipe sys_pipe +43 common times sys_times +# 44 was sys_prof +45 common brk sys_brk +46 common setgid sys_setgid16 +47 common getgid sys_getgid16 +# 48 was sys_signal +49 common geteuid sys_geteuid16 +50 common getegid sys_getegid16 +51 common acct sys_acct +52 common umount2 sys_umount +# 53 was sys_lock +54 common ioctl sys_ioctl +55 common fcntl sys_fcntl +# 56 was sys_mpx +57 common setpgid sys_setpgid +# 58 was sys_ulimit +# 59 was sys_olduname +60 common umask sys_umask +61 common chroot sys_chroot +62 common ustat sys_ustat +63 common dup2 sys_dup2 +64 common getppid sys_getppid +65 common getpgrp sys_getpgrp +66 common setsid sys_setsid +67 common sigaction sys_sigaction +# 68 was sys_sgetmask +# 69 was sys_ssetmask +70 common setreuid sys_setreuid16 +71 common setregid sys_setregid16 +72 common sigsuspend sys_sigsuspend +73 common sigpending sys_sigpending +74 common sethostname sys_sethostname +75 common setrlimit sys_setrlimit +# Back compat 2GB limited rlimit +76 oabi getrlimit sys_old_getrlimit +77 common getrusage sys_getrusage +78 common gettimeofday sys_gettimeofday +79 common settimeofday sys_settimeofday +80 common getgroups sys_getgroups16 +81 common setgroups sys_setgroups16 +82 oabi select sys_old_select +83 common symlink sys_symlink +# 84 was sys_lstat +85 common readlink sys_readlink +86 common uselib sys_uselib +87 common swapon sys_swapon +88 common reboot sys_reboot +89 oabi readdir sys_old_readdir +90 oabi mmap sys_old_mmap +91 common munmap sys_munmap +92 common truncate sys_truncate +93 common ftruncate sys_ftruncate +94 common fchmod sys_fchmod +95 common fchown sys_fchown16 +96 common getpriority sys_getpriority +97 common setpriority sys_setpriority +# 98 was sys_profil +99 common statfs sys_statfs +100 common fstatfs sys_fstatfs +# 101 was sys_ioperm +102 oabi socketcall sys_socketcall sys_oabi_socketcall +103 common syslog sys_syslog +104 common setitimer sys_setitimer +105 common getitimer sys_getitimer +106 common stat sys_newstat +107 common lstat sys_newlstat +108 common fstat sys_newfstat +# 109 was sys_uname +# 110 was sys_iopl +111 common vhangup sys_vhangup +# 112 was sys_idle +# syscall to call a syscall! +113 oabi syscall sys_syscall +114 common wait4 sys_wait4 +115 common swapoff sys_swapoff +116 common sysinfo sys_sysinfo +117 oabi ipc sys_ipc sys_oabi_ipc +118 common fsync sys_fsync +119 common sigreturn sys_sigreturn_wrapper +120 common clone sys_clone +121 common setdomainname sys_setdomainname +122 common uname sys_newuname +# 123 was sys_modify_ldt +124 common adjtimex sys_adjtimex +125 common mprotect sys_mprotect +126 common sigprocmask sys_sigprocmask +# 127 was sys_create_module +128 common init_module sys_init_module +129 common delete_module sys_delete_module +# 130 was sys_get_kernel_syms +131 common quotactl sys_quotactl +132 common getpgid sys_getpgid +133 common fchdir sys_fchdir +134 common bdflush sys_bdflush +135 common sysfs sys_sysfs +136 common personality sys_personality +# 137 was sys_afs_syscall +138 common setfsuid sys_setfsuid16 +139 common setfsgid sys_setfsgid16 +140 common _llseek sys_llseek +141 common getdents sys_getdents +142 common _newselect sys_select +143 common flock sys_flock +144 common msync sys_msync +145 common readv sys_readv +146 common writev sys_writev +147 common getsid sys_getsid +148 common fdatasync sys_fdatasync +149 common _sysctl sys_sysctl +150 common mlock sys_mlock +151 common munlock sys_munlock +152 common mlockall sys_mlockall +153 common munlockall sys_munlockall +154 common sched_setparam sys_sched_setparam +155 common sched_getparam sys_sched_getparam +156 common sched_setscheduler sys_sched_setscheduler +157 common sched_getscheduler sys_sched_getscheduler +158 common sched_yield sys_sched_yield +159 common sched_get_priority_max sys_sched_get_priority_max +160 common sched_get_priority_min sys_sched_get_priority_min +161 common sched_rr_get_interval sys_sched_rr_get_interval +162 common nanosleep sys_nanosleep +163 common mremap sys_mremap +164 common setresuid sys_setresuid16 +165 common getresuid sys_getresuid16 +# 166 was sys_vm86 +# 167 was sys_query_module +168 common poll sys_poll +169 common nfsservctl +170 common setresgid sys_setresgid16 +171 common getresgid sys_getresgid16 +172 common prctl sys_prctl +173 common rt_sigreturn sys_rt_sigreturn_wrapper +174 common rt_sigaction sys_rt_sigaction +175 common rt_sigprocmask sys_rt_sigprocmask +176 common rt_sigpending sys_rt_sigpending +177 common rt_sigtimedwait sys_rt_sigtimedwait +178 common rt_sigqueueinfo sys_rt_sigqueueinfo +179 common rt_sigsuspend sys_rt_sigsuspend +180 common pread64 sys_pread64 sys_oabi_pread64 +181 common pwrite64 sys_pwrite64 sys_oabi_pwrite64 +182 common chown sys_chown16 +183 common getcwd sys_getcwd +184 common capget sys_capget +185 common capset sys_capset +186 common sigaltstack sys_sigaltstack +187 common sendfile sys_sendfile +# 188 reserved +# 189 reserved +190 common vfork sys_vfork +# SuS compliant getrlimit +191 common ugetrlimit sys_getrlimit +192 common mmap2 sys_mmap2 +193 common truncate64 sys_truncate64 sys_oabi_truncate64 +194 common ftruncate64 sys_ftruncate64 sys_oabi_ftruncate64 +195 common stat64 sys_stat64 sys_oabi_stat64 +196 common lstat64 sys_lstat64 sys_oabi_lstat64 +197 common fstat64 sys_fstat64 sys_oabi_fstat64 +198 common lchown32 sys_lchown +199 common getuid32 sys_getuid +200 common getgid32 sys_getgid +201 common geteuid32 sys_geteuid +202 common getegid32 sys_getegid +203 common setreuid32 sys_setreuid +204 common setregid32 sys_setregid +205 common getgroups32 sys_getgroups +206 common setgroups32 sys_setgroups +207 common fchown32 sys_fchown +208 common setresuid32 sys_setresuid +209 common getresuid32 sys_getresuid +210 common setresgid32 sys_setresgid +211 common getresgid32 sys_getresgid +212 common chown32 sys_chown +213 common setuid32 sys_setuid +214 common setgid32 sys_setgid +215 common setfsuid32 sys_setfsuid +216 common setfsgid32 sys_setfsgid +217 common getdents64 sys_getdents64 +218 common pivot_root sys_pivot_root +219 common mincore sys_mincore +220 common madvise sys_madvise +221 common fcntl64 sys_fcntl64 sys_oabi_fcntl64 +# 222 for tux +# 223 is unused +224 common gettid sys_gettid +225 common readahead sys_readahead sys_oabi_readahead +226 common setxattr sys_setxattr +227 common lsetxattr sys_lsetxattr +228 common fsetxattr sys_fsetxattr +229 common getxattr sys_getxattr +230 common lgetxattr sys_lgetxattr +231 common fgetxattr sys_fgetxattr +232 common listxattr sys_listxattr +233 common llistxattr sys_llistxattr +234 common flistxattr sys_flistxattr +235 common removexattr sys_removexattr +236 common lremovexattr sys_lremovexattr +237 common fremovexattr sys_fremovexattr +238 common tkill sys_tkill +239 common sendfile64 sys_sendfile64 +240 common futex sys_futex +241 common sched_setaffinity sys_sched_setaffinity +242 common sched_getaffinity sys_sched_getaffinity +243 common io_setup sys_io_setup +244 common io_destroy sys_io_destroy +245 common io_getevents sys_io_getevents +246 common io_submit sys_io_submit +247 common io_cancel sys_io_cancel +248 common exit_group sys_exit_group +249 common lookup_dcookie sys_lookup_dcookie +250 common epoll_create sys_epoll_create +251 common epoll_ctl sys_epoll_ctl sys_oabi_epoll_ctl +252 common epoll_wait sys_epoll_wait sys_oabi_epoll_wait +253 common remap_file_pages sys_remap_file_pages +# 254 for set_thread_area +# 255 for get_thread_area +256 common set_tid_address sys_set_tid_address +257 common timer_create sys_timer_create +258 common timer_settime sys_timer_settime +259 common timer_gettime sys_timer_gettime +260 common timer_getoverrun sys_timer_getoverrun +261 common timer_delete sys_timer_delete +262 common clock_settime sys_clock_settime +263 common clock_gettime sys_clock_gettime +264 common clock_getres sys_clock_getres +265 common clock_nanosleep sys_clock_nanosleep +266 common statfs64 sys_statfs64_wrapper +267 common fstatfs64 sys_fstatfs64_wrapper +268 common tgkill sys_tgkill +269 common utimes sys_utimes +270 common arm_fadvise64_64 sys_arm_fadvise64_64 +271 common pciconfig_iobase sys_pciconfig_iobase +272 common pciconfig_read sys_pciconfig_read +273 common pciconfig_write sys_pciconfig_write +274 common mq_open sys_mq_open +275 common mq_unlink sys_mq_unlink +276 common mq_timedsend sys_mq_timedsend +277 common mq_timedreceive sys_mq_timedreceive +278 common mq_notify sys_mq_notify +279 common mq_getsetattr sys_mq_getsetattr +280 common waitid sys_waitid +281 common socket sys_socket +282 common bind sys_bind sys_oabi_bind +283 common connect sys_connect sys_oabi_connect +284 common listen sys_listen +285 common accept sys_accept +286 common getsockname sys_getsockname +287 common getpeername sys_getpeername +288 common socketpair sys_socketpair +289 common send sys_send +290 common sendto sys_sendto sys_oabi_sendto +291 common recv sys_recv +292 common recvfrom sys_recvfrom +293 common shutdown sys_shutdown +294 common setsockopt sys_setsockopt +295 common getsockopt sys_getsockopt +296 common sendmsg sys_sendmsg sys_oabi_sendmsg +297 common recvmsg sys_recvmsg +298 common semop sys_semop sys_oabi_semop +299 common semget sys_semget +300 common semctl sys_semctl +301 common msgsnd sys_msgsnd +302 common msgrcv sys_msgrcv +303 common msgget sys_msgget +304 common msgctl sys_msgctl +305 common shmat sys_shmat +306 common shmdt sys_shmdt +307 common shmget sys_shmget +308 common shmctl sys_shmctl +309 common add_key sys_add_key +310 common request_key sys_request_key +311 common keyctl sys_keyctl +312 common semtimedop sys_semtimedop sys_oabi_semtimedop +313 common vserver +314 common ioprio_set sys_ioprio_set +315 common ioprio_get sys_ioprio_get +316 common inotify_init sys_inotify_init +317 common inotify_add_watch sys_inotify_add_watch +318 common inotify_rm_watch sys_inotify_rm_watch +319 common mbind sys_mbind +320 common get_mempolicy sys_get_mempolicy +321 common set_mempolicy sys_set_mempolicy +322 common openat sys_openat +323 common mkdirat sys_mkdirat +324 common mknodat sys_mknodat +325 common fchownat sys_fchownat +326 common futimesat sys_futimesat +327 common fstatat64 sys_fstatat64 sys_oabi_fstatat64 +328 common unlinkat sys_unlinkat +329 common renameat sys_renameat +330 common linkat sys_linkat +331 common symlinkat sys_symlinkat +332 common readlinkat sys_readlinkat +333 common fchmodat sys_fchmodat +334 common faccessat sys_faccessat +335 common pselect6 sys_pselect6 +336 common ppoll sys_ppoll +337 common unshare sys_unshare +338 common set_robust_list sys_set_robust_list +339 common get_robust_list sys_get_robust_list +340 common splice sys_splice +341 common arm_sync_file_range sys_sync_file_range2 +342 common tee sys_tee +343 common vmsplice sys_vmsplice +344 common move_pages sys_move_pages +345 common getcpu sys_getcpu +346 common epoll_pwait sys_epoll_pwait +347 common kexec_load sys_kexec_load +348 common utimensat sys_utimensat +349 common signalfd sys_signalfd +350 common timerfd_create sys_timerfd_create +351 common eventfd sys_eventfd +352 common fallocate sys_fallocate +353 common timerfd_settime sys_timerfd_settime +354 common timerfd_gettime sys_timerfd_gettime +355 common signalfd4 sys_signalfd4 +356 common eventfd2 sys_eventfd2 +357 common epoll_create1 sys_epoll_create1 +358 common dup3 sys_dup3 +359 common pipe2 sys_pipe2 +360 common inotify_init1 sys_inotify_init1 +361 common preadv sys_preadv +362 common pwritev sys_pwritev +363 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo +364 common perf_event_open sys_perf_event_open +365 common recvmmsg sys_recvmmsg +366 common accept4 sys_accept4 +367 common fanotify_init sys_fanotify_init +368 common fanotify_mark sys_fanotify_mark +369 common prlimit64 sys_prlimit64 +370 common name_to_handle_at sys_name_to_handle_at +371 common open_by_handle_at sys_open_by_handle_at +372 common clock_adjtime sys_clock_adjtime +373 common syncfs sys_syncfs +374 common sendmmsg sys_sendmmsg +375 common setns sys_setns +376 common process_vm_readv sys_process_vm_readv +377 common process_vm_writev sys_process_vm_writev +378 common kcmp sys_kcmp +379 common finit_module sys_finit_module +380 common sched_setattr sys_sched_setattr +381 common sched_getattr sys_sched_getattr +382 common renameat2 sys_renameat2 +383 common seccomp sys_seccomp +384 common getrandom sys_getrandom +385 common memfd_create sys_memfd_create +386 common bpf sys_bpf +387 common execveat sys_execveat +388 common userfaultfd sys_userfaultfd +389 common membarrier sys_membarrier +390 common mlock2 sys_mlock2 +391 common copy_file_range sys_copy_file_range +392 common preadv2 sys_preadv2 +393 common pwritev2 sys_pwritev2 +394 common pkey_mprotect sys_pkey_mprotect +395 common pkey_alloc sys_pkey_alloc +396 common pkey_free sys_pkey_free +424 common pidfd_send_signal sys_pidfd_send_signal +434 common pidfd_open sys_pidfd_open diff --git a/arch/arm/tools/syscallhdr.sh b/arch/arm/tools/syscallhdr.sh new file mode 100644 index 0000000000000000000000000000000000000000..72d4b2e3bdec43ee8eec8048a32f404a2556390c --- /dev/null +++ b/arch/arm/tools/syscallhdr.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +in="$1" +out="$2" +my_abis=`echo "($3)" | tr ',' '|'` +prefix="$4" +offset="$5" + +fileguard=_ASM_ARM_`basename "$out" | sed \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ + -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'` +if echo $out | grep -q uapi; then + fileguard="_UAPI$fileguard" +fi +grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | ( + echo "#ifndef ${fileguard}" + echo "#define ${fileguard} 1" + echo "" + + while read nr abi name entry ; do + if [ -z "$offset" ]; then + echo "#define __NR_${prefix}${name} $nr" + else + echo "#define __NR_${prefix}${name} ($offset + $nr)" + fi + done + + echo "" + echo "#endif /* ${fileguard} */" +) > "$out" diff --git a/arch/arm/tools/syscallnr.sh b/arch/arm/tools/syscallnr.sh new file mode 100644 index 0000000000000000000000000000000000000000..d2971296469a676763bfdda8c90bebd111db11a8 --- /dev/null +++ b/arch/arm/tools/syscallnr.sh @@ -0,0 +1,33 @@ +#!/bin/sh +in="$1" +out="$2" +my_abis=`echo "($3)" | tr ',' '|'` +align=1 + +fileguard=_ASM_ARM_`basename "$out" | sed \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ + -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'` + +grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | tail -n1 | ( + echo "#ifndef ${fileguard} +#define ${fileguard} 1 + +/* + * This needs to be greater than __NR_last_syscall+1 in order to account + * for the padding in the syscall table. + */ +" + + while read nr abi name entry; do + nr=$(($nr + 1)) + while [ "$(($nr / (256 * $align) ))" -gt 0 ]; do + align=$(( $align * 4 )) + done + nr=$(( ($nr + $align - 1) & ~($align - 1) )) + echo "/* aligned to $align */" + echo "#define __NR_syscalls $nr" + done + + echo "" + echo "#endif /* ${fileguard} */" +) > "$out" diff --git a/arch/arm/tools/syscalltbl.sh b/arch/arm/tools/syscalltbl.sh new file mode 100644 index 0000000000000000000000000000000000000000..5ca834545ed3275685f471dd8914f70ce8e66403 --- /dev/null +++ b/arch/arm/tools/syscalltbl.sh @@ -0,0 +1,21 @@ +#!/bin/sh +in="$1" +out="$2" +my_abis=`echo "($3)" | tr ',' '|'` + +grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | ( + while read nr abi name entry compat; do + if [ "$abi" = "eabi" -a -n "$compat" ]; then + echo "$in: error: a compat entry for an EABI syscall ($name) makes no sense" >&2 + exit 1 + fi + + if [ -n "$entry" ]; then + if [ -z "$compat" ]; then + echo "NATIVE($nr, $entry)" + else + echo "COMPAT($nr, $entry, $compat)" + fi + fi + done +) > "$out" diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile index ccdfa1f7bbc93f2955d7a208ecf9f2faa08effec..6986f77ccd18576ab946d60eba679e0b49bfc39a 100644 --- a/arch/arm64/boot/Makefile +++ b/arch/arm64/boot/Makefile @@ -18,7 +18,7 @@ include $(srctree)/arch/arm64/boot/dts/Makefile OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S -targets := Image Image.gz +targets := Image Image.bz2 Image.gz Image.lz4 Image.lzma Image.lzo DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES)) ifneq ($(DTB_NAMES),) diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi index e79f3defe00216b695791049744e0aab6e6542fc..c2ad4f97cef0f7a701fdfe49a6a9e7f00968cc2f 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi @@ -56,10 +56,10 @@ pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 120 8>, - <0 121 8>, - <0 122 8>, - <0 123 8>; + interrupts = <0 170 4>, + <0 171 4>, + <0 172 4>, + <0 173 4>; interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, diff --git a/arch/arm64/boot/dts/arm/juno-clocks.dtsi b/arch/arm64/boot/dts/arm/juno-clocks.dtsi index 25352ed943e6e04a98689106b94994e8269a31fb..00bcbf7688c773bb04e2ecb6e1b1ea3d5b5ead46 100644 --- a/arch/arm64/boot/dts/arm/juno-clocks.dtsi +++ b/arch/arm64/boot/dts/arm/juno-clocks.dtsi @@ -8,10 +8,10 @@ */ /* SoC fixed clocks */ - soc_uartclk: refclk7273800hz { + soc_uartclk: refclk7372800hz { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <7273800>; + clock-frequency = <7372800>; clock-output-names = "juno:uartclk"; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi index e5fc67bf46c229fef02c1416e4ab005fb53ab460..a88afb6a9c0c0904759c8b73a7b025640ad272ab 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi @@ -1583,7 +1583,7 @@ regulator-name = "VDD_HDMI_5V0"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&exp1 12 GPIO_ACTIVE_LOW>; + gpio = <&exp1 12 GPIO_ACTIVE_HIGH>; enable-active-high; vin-supply = <&vdd_5v0_sys>; }; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a9df3069a02b5bb8121327d9cc12681cf7a688fd..f6df01c432b3af3653afa68f12fdc0feb1116ab6 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -607,7 +607,9 @@ dtb-$(CONFIG_ARCH_MSM8909) += msm8909-pm8916-mtp.dtb \ sdw3100-msm8909w-1gb-wtp.dtb \ sdw2500-apq8009w-wtp.dtb \ sdw2500-msm8909w-wtp.dtb \ - msm8905-qrd-skub_qseev4.dtb + msm8905-qrd-skub_qseev4.dtb \ + msm8909-mtp.dtb \ + msm8909-1gb-mtp.dtb dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \ sdm450-cdp.dtb \ diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts index d654bf82067bb4fb402b821ce26b5bcc0591a67c..763aa9b546699976051041f3ff37e306f0fa03a0 100644 --- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts +++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts @@ -19,7 +19,6 @@ #include "apq8009-audio-external_codec.dtsi" #include "msm8909-pm8916-camera.dtsi" #include "msm8909-pm8916-camera-sensor-robot-som.dtsi" -#include "dsi-panel-osd-disp-fwvga-video.dtsi" #include "dsi-panel-ili9806e-fwvga-video.dtsi" / { @@ -397,10 +396,6 @@ status = "okay"; }; -&dsi_osd_disp_fwvga_video { - qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>; -}; - &dsi_ili9806e_fwvga_video { qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>; qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; @@ -427,15 +422,17 @@ }; &mdss_dsi0 { - qcom,dsi-pref-prim-pan = <&dsi_osd_disp_fwvga_video>; + qcom,dsi-pref-prim-pan = <&dsi_ili9806e_fwvga_video>; pinctrl-names = "mdss_default", "mdss_sleep"; pinctrl-0 = <&mdss_dsi_active &mdss_dsi_select_gpio>; pinctrl-1 = <&mdss_dsi_suspend &mdss_dsi_select_gpio>; + qcom,platform-te-gpio = <&msm_gpio 24 0>; qcom,platform-reset-gpio = <&msm_gpio 28 0>; qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>; + /delete-property/ qcom,platform-enable-gpio; vdd-supply = <&pm8916_l17>; vddio-supply = <&pm8916_l6>; status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi index 601be6127628a56a19eb6ca93d59d08b4b785fc3..948efff7d830cfe97c4d1bc4b7c6ca407eb66e84 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi @@ -355,6 +355,8 @@ l11 { regulator-min-microvolt = <1750000>; regulator-max-microvolt = <3337000>; + regulator-allow-set-load; + regulator-system-load = <200000>; }; l12 { diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-720p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-720p-video.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..ca83d821e73d89816be89c3ed80b7aacdc5602b0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-720p-video.dtsi @@ -0,0 +1,78 @@ +/* Copyright (c) 2014-2015, 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. + */ + +&mdss_mdp { + dsi_hx8394d_720_vid: qcom,mdss_dsi_hx8394d_720p_video { + qcom,mdss-dsi-panel-name = "hx8394d 720p video mode dsi panel"; + qcom,mdss-dsi-panel-controller = <&mdss_dsi0>; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-destination = "display_1"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <720>; + qcom,mdss-dsi-panel-height = <1280>; + qcom,mdss-dsi-h-front-porch = <52>; + qcom,mdss-dsi-h-back-porch = <100>; + qcom,mdss-dsi-h-pulse-width = <24>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <20>; + qcom,mdss-dsi-v-front-porch = <8>; + qcom,mdss-dsi-v-pulse-width = <4>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [39 01 00 00 00 00 04 b9 ff 83 94 + 39 01 00 00 00 00 03 ba 33 83 + 39 01 00 00 00 00 10 b1 6c 12 12 37 04 11 f1 80 ec 94 23 80 c0 d2 18 + 39 01 00 00 00 00 0c b2 00 64 0e 0d 32 23 08 08 1c 4d 00 + 39 01 00 00 00 00 0d b4 00 ff 03 50 03 50 03 50 01 6a 01 6a + 39 01 00 00 00 00 02 bc 07 + 39 01 00 00 00 00 04 bf 41 0e 01 + 39 01 00 00 00 00 1f d3 00 07 00 00 00 10 00 32 10 05 00 00 32 10 00 00 00 32 10 00 00 00 36 03 09 09 37 00 00 37 + 39 01 00 00 00 00 2d d5 02 03 00 01 06 07 04 05 20 21 22 23 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 24 25 18 18 19 19 + 39 01 00 00 00 00 2d d6 05 04 07 06 01 00 03 02 23 22 21 20 18 18 18 18 18 18 58 58 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 25 24 19 19 18 18 + 39 01 00 00 00 00 02 cc 09 + 39 01 00 00 00 00 03 c0 30 14 + 39 01 00 00 00 00 05 c7 00 c0 40 c0 + 39 01 00 00 00 00 03 b6 43 43 + 05 01 00 00 c8 00 02 11 00 + 05 01 00 00 0a 00 02 29 00]; + qcom,mdss-dsi-off-command = [05 01 00 00 00 00 02 28 00 + 05 01 00 00 00 00 02 10 00]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [79 1a 12 00 3e 42 16 1e 15 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x04>; + qcom,mdss-dsi-t-clk-pre = <0x1b>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>; + qcom,mdss-pan-physical-width-dimension = <59>; + qcom,mdss-pan-physical-height-dimension = <104>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm-pm8909.dtsi b/arch/arm64/boot/dts/qcom/msm-pm8909.dtsi index 5b44204df5fd2819a4b218107a6df206a3869df5..87330d682e58d39824a430f5d8ad3089ab374b4c 100644 --- a/arch/arm64/boot/dts/qcom/msm-pm8909.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-pm8909.dtsi @@ -81,33 +81,14 @@ }; pm8909_gpios: gpios { - compatible = "qcom,qpnp-pin"; - spmi-dev-container; + compatible = "qcom,spmi-gpio"; + reg = <0xc000 0x400>; + interrupts = <0x0 0xc1 0 IRQ_TYPE_NONE>, + <0x0 0xc3 0 IRQ_TYPE_NONE>; + interrupt-names = "pm8909_gpio2", "pm8909_gpio4"; gpio-controller; #gpio-cells = <2>; - #address-cells = <1>; - #size-cells = <1>; - label = "pm8909-gpio"; - - gpio@c000 { - reg = <0xc000 0x100>; - qcom,pin-num = <1>; - }; - - gpio@c100 { - reg = <0xc100 0x100>; - qcom,pin-num = <2>; - }; - - gpio@c200 { - reg = <0xc200 0x100>; - qcom,pin-num = <3>; - }; - - gpio@c300 { - reg = <0xc300 0x100>; - qcom,pin-num = <4>; - }; + qcom,gpios-disallowed = <1 3>; }; pm8909_vadc: vadc@3100 { diff --git a/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi b/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi index 699b8c18f240f85c132806201bec6982dde43ce7..d662415775958792e446283e6dc4c532a389cdcc 100644 --- a/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8905-camera-sensor-skub.dtsi @@ -17,8 +17,17 @@ qcom,pin-func = <2>; label = "SY7807_pins"; SY7807_default: en_default { - drive-strength = <2>; - bias-pull-down; + mux { + pins = "gpio32"; + function = "gpio"; + }; + + configs { + pins = "gpio32"; + drive-strength = <0x2>; + bias-pull-down; + }; + }; }; }; @@ -28,7 +37,7 @@ compatible = "qcom,leds-gpio-flash"; status = "okay"; pinctrl-names = "flash_default"; - pinctrl-0 = <&SY7807_default>; + pinctrl-0 = <&SY7807_default &flash_en_default>; qcom,flash-en = <&pm8909_gpios 4 0>; qcom,flash-now = <&msm_gpio 32 0>; clocks = <&clock_gcc clk_gcc_camss_gp1_clk>, @@ -189,6 +198,7 @@ clocks = <&clock_gcc clk_mclk0_clk_src>, <&clock_gcc clk_gcc_camss_mclk0_clk>; clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; }; qcom,camera@1 { @@ -225,5 +235,6 @@ clocks = <&clock_gcc clk_mclk1_clk_src>, <&clock_gcc clk_gcc_camss_mclk1_clk>; clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi b/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi index a94f88750e9c94622cb13df0551635cd85bb93b4..f993dbe6f9cc705fd38c3f1b8b7ebe1be08b9a06 100644 --- a/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8905-qrd-skub.dtsi @@ -231,9 +231,30 @@ }; &soc { + qcom,msm-audio-apr { + compatible = "qcom,msm-audio-apr"; + msm_audio_apr_dummy { + compatible = "qcom,msm-audio-apr-dummy"; + }; + }; + + qcom,avtimer@c0a300c { + compatible = "qcom,avtimer"; + reg = <0x0c0a300c 0x4>, + <0x0c0a3010 0x4>; + reg-names = "avtimer_lsb_addr", "avtimer_msb_addr"; + qcom,clk-div = <27>; + }; + sound { - compatible = "qcom,msm8x16-audio-codec"; + compatible = "qcom,msm8952-audio-codec"; qcom,model = "msm8909-skub-snd-card"; + reg = <0x7702000 0x4>, + <0x7702004 0x4>, + <0x7702008 0x4>; + reg-names = "csr_gp_io_mux_mic_ctl", + "csr_gp_io_mux_spkr_ctl", + "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel"; qcom,msm-snd-card-id = <0>; qcom,msm-codec-type = "internal"; qcom,msm-ext-pa = "primary"; @@ -251,23 +272,24 @@ "MIC BIAS Internal2", "Headset Mic", "AMIC1", "MIC BIAS Internal1", "AMIC2", "MIC BIAS Internal2"; - pinctrl-names = "cdc_lines_act", - "cdc_lines_sus"; - pinctrl-0 = <&cdc_pdm_lines_act>; - pinctrl-1 = <&cdc_pdm_lines_sus>; - asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>, + + qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>; + + asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, + <&voip>, <&voice>, <&loopback>, <&compress>, <&hostless>, - <&afe>, <&lsm>, <&routing>, <&lpa>, - <&voice_svc>; + <&afe>, <&lsm>, <&routing>, <&pcm_noirq>; asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-pcm-dsp.2", "msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback", "msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe", "msm-lsm-client", "msm-pcm-routing", - "msm-pcm-lpa", "msm-voice-svc"; + "msm-pcm-dsp-noirq"; asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>, <&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>, <&dai_mi2s3>, + <&dai_mi2s4>, <&dai_mi2s5>, <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, <&sb_3_rx>, <&sb_3_tx>, @@ -281,6 +303,7 @@ asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", + "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6", "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", @@ -292,8 +315,17 @@ "msm-dai-q6-dev.241", "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770"; - asoc-codec = <&stub_codec>, <&pm8909_conga_dig>; - asoc-codec-names = "msm-stub-codec.1", "tombak_codec"; + asoc-codec = <&stub_codec>, <&msm_digital_codec>, + <&pmic_analog_codec>; + asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec", + "analog-codec"; + }; + + cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_pdm_lines_act>; + pinctrl-1 = <&cdc_pdm_lines_sus>; }; spi@78b9000 { /* BLSP1 QUP5 */ @@ -344,6 +376,82 @@ }; }; +&pm8909_1 { + pmic_analog_codec: analog-codec@f100 { + status = "okay"; + compatible = "qcom,pmic-analog-codec"; + reg = <0xf000 0x200>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-parent = <&spmi_bus>; + interrupts = + <0x1 0xf0 0x0 IRQ_TYPE_NONE>, + <0x1 0xf0 0x1 IRQ_TYPE_NONE>, + <0x1 0xf0 0x2 IRQ_TYPE_NONE>, + <0x1 0xf0 0x3 IRQ_TYPE_NONE>, + <0x1 0xf0 0x4 IRQ_TYPE_NONE>, + <0x1 0xf0 0x5 IRQ_TYPE_NONE>, + <0x1 0xf0 0x6 IRQ_TYPE_NONE>, + <0x1 0xf0 0x7 IRQ_TYPE_NONE>, + <0x1 0xf1 0x0 IRQ_TYPE_NONE>, + <0x1 0xf1 0x1 IRQ_TYPE_NONE>, + <0x1 0xf1 0x2 IRQ_TYPE_NONE>, + <0x1 0xf1 0x3 IRQ_TYPE_NONE>, + <0x1 0xf1 0x4 IRQ_TYPE_NONE>, + <0x1 0xf1 0x5 IRQ_TYPE_NONE>; + interrupt-names = + "spk_cnp_int", + "spk_clip_int", + "spk_ocp_int", + "ins_rem_det1", + "but_rel_det", + "but_press_det", + "ins_rem_det", + "mbhc_int", + "ear_ocp_int", + "hphr_ocp_int", + "hphl_ocp_det", + "ear_cnp_int", + "hphr_cnp_int", + "hphl_cnp_int"; + + cdc-vdda-cp-supply = <&pm8909_s2>; + qcom,cdc-vdda-cp-voltage = <1800000 2200000>; + qcom,cdc-vdda-cp-current = <500000>; + + cdc-vdda-h-supply = <&pm8909_l5>; + qcom,cdc-vdda-h-voltage = <1800000 1800000>; + qcom,cdc-vdda-h-current = <5000>; + + cdc-vdd-px-supply = <&pm8909_l5>; + qcom,cdc-vdd-px-voltage = <1800000 1800000>; + qcom,cdc-vdd-px-current = <5000>; + + cdc-vdd-pa-supply = <&pm8909_s2>; + qcom,cdc-vdd-pa-voltage = <1800000 2200000>; + qcom,cdc-vdd-pa-current = <260000>; + + cdc-vdd-mic-bias-supply = <&pm8909_l13>; + qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>; + qcom,cdc-vdd-mic-bias-current = <5000>; + + qcom,cdc-mclk-clk-rate = <9600000>; + + qcom,cdc-static-supplies = + "cdc-vdda-h", + "cdc-vdd-px", + "cdc-vdd-pa", + "cdc-vdda-cp"; + + qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias"; + + msm_digital_codec: msm-dig-codec@f000 { + compatible = "qcom,msm-digital-codec"; + reg = <0x771c000 0x100>; + }; + }; +}; + &pm8909_mpps { mpp@a100 { /* MPP 2 */ /* Backlight PWM */ @@ -406,12 +514,24 @@ &pm8909_gpios { /* GPIO 2 (NFC_CLK_REQ) */ - gpio@c100 { - qcom,mode = <0>; - qcom,vin-sel = <1>; - qcom,src-sel = <0>; - qcom,master-en = <1>; - status = "okay"; + nfc-clk { + nfc_clk_default: nfc_clk_default { + pins = "gpio2"; + function = "normal"; + input-enable; + power-source = <1>; + }; + }; + + /* GPIO 4 (FLASH ENABLE GPIO CONFIG) */ + flash_en { + flash_en_default: flash_en_default{ + pins = "gpio4"; + function = "normal"; + input-disable; + output-enable; + status = "okay"; + }; }; }; @@ -430,7 +550,8 @@ interrupts = <21 0>; interrupt-names = "nfc_irq"; pinctrl-names = "nfc_active", "nfc_suspend"; - pinctrl-0 = <&nfc_int_active &nfc_disable_active>; + pinctrl-0 = <&nfc_int_active &nfc_disable_active + &nfc_clk_default>; pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>; clocks = <&clock_rpm clk_bb_clk2_pin>; clock-names = "ref_clk"; @@ -456,3 +577,11 @@ &actuator0 { status = "disabled"; }; + +&pm8909_conga_dig { + status = "disabled"; +}; + +&pm8909_conga_analog { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909-1gb-mtp.dts b/arch/arm64/boot/dts/qcom/msm8909-1gb-mtp.dts new file mode 100644 index 0000000000000000000000000000000000000000..4d5299710723cbf96d17c36436e2ac92821d9300 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8909-1gb-mtp.dts @@ -0,0 +1,24 @@ +/* Copyright (c) 2016,2018, 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. + */ + +/dts-v1/; + +#include "msm8909-mtp.dtsi" +#include "msm8909-pm8909.dtsi" +#include "msm8909-pm8909-mtp.dtsi" +#include "msm8909-mtp_qseev4.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB MTP"; + compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp"; + qcom,board-id= <8 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-camera-sensor-mtp.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..85b350512ce57aa1b036230cfb23a0200855fcee --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8909-camera-sensor-mtp.dtsi @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2014-2017, 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. + */ + +&soc { +}; + +&i2c_3 { + + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x3>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + cam_vaf-supply = <&pm8909_l8>; + qcom,cam-vreg-name = "cam_vaf"; + qcom,cam-vreg-type = <0>; + qcom,cam-vreg-min-voltage = <2850000>; + qcom,cam-vreg-max-voltage = <2900000>; + qcom,cam-vreg-op-mode = <80000>; + }; + + eeprom0: qcom,eeprom@6c{ + cell-index = <0>; + reg = <0x6c>; + qcom,eeprom-name = "sunny_ov8858_q8v19w"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0x6c>; + qcom,cci-master = <0>; + qcom,num-blocks = <4>; + + qcom,page0 = <1 0x0100 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + qcom,page1 = <1 0x3d84 2 0xc0 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x3d00 2 0 1 0>; + qcom,page2 = <1 0x3d88 2 0x7010 2 1>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <0 0x3d00 2 0 1 0>; + qcom,page3 = <1 0x3d8A 2 0x7184 2 1>; + qcom,pageen3 = <1 0x3d81 2 0x01 1 10>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <373 0x7010 2 0 1 1>; + + cam_vdig-supply = <&pm8909_l2>; + cam_vana-supply = <&pm8909_l17>; + cam_vio-supply = <&pm8909_l6>; + cam_vaf-supply = <&pm8909_l8>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", + "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2850000 2900000>; + qcom,cam-vreg-op-mode = <200000 0 80000 100000>; + qcom,enable_pinctrl; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + gpios = <&msm_gpio 26 0>, + <&msm_gpio 35 0>, + <&msm_gpio 34 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK", + "CAM_RESET1", + "CAM_STANDBY"; + qcom,cam-power-seq-type = "sensor_vreg", + "sensor_gpio", "sensor_gpio", + "sensor_clk"; + qcom,cam-power-seq-val = "cam_vaf", + "sensor_gpio_reset", + "sensor_gpio_standby", + "sensor_cam_mclk" ; + qcom,cam-power-seq-cfg-val = <1 1 1 23880000>; + qcom,cam-power-seq-delay = <1 10 10 5>; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + led_flash0: qcom,led-flash@60 { + cell-index = <0>; + reg = <0x60>; + qcom,slave-id = <0x60 0x00 0x0011>; + compatible = "qcom,led-flash"; + label = "adp1660"; + qcom,flash-type = <1>; + qcom,gpio-no-mux = <0>; + qcom,enable_pinctrl; + pinctrl-names = "cam_flash_default", "cam_flash_suspend"; + pinctrl-0 = <&cam_sensor_flash_default>; + pinctrl-1 = <&cam_sensor_flash_sleep>; + gpios = <&msm_gpio 31 0>, + <&msm_gpio 32 0>, + <&msm_gpio 36 0>; + qcom,gpio-flash-en = <0>; + qcom,gpio-flash-now = <1>; + qcom,gpio-flash-rst = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <0 0 0>; + qcom,gpio-req-tbl-label = "FLASH_EN", + "FLASH_NOW", "FLASH_RST"; + qcom,cci-master = <0>; + }; + + qcom,camera@0 { + cell-index = <0>; + compatible = "qcom,camera"; + reg = <0x2>; + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <0>; + qcom,mount-angle = <90>; + qcom,actuator-src = <&actuator0>; + qcom,led-flash-src = <&led_flash0>; + qcom,eeprom-src = <&eeprom0>; + cam_vdig-supply = <&pm8909_l2>; + cam_vana-supply = <&pm8909_l17>; + cam_vio-supply = <&pm8909_l6>; + cam_vaf-supply = <&pm8909_l8>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", + "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2850000 2900000>; + qcom,cam-vreg-op-mode = <200000 0 80000 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + gpios = <&msm_gpio 26 0>, + <&msm_gpio 35 0>, + <&msm_gpio 34 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK", + "CAM_RESET1", + "CAM_STANDBY"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom_camera1: qcom,camera@1 { + cell-index = <1>; + compatible = "qcom,camera"; + reg = <0x1>; + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <1>; + qcom,mount-angle = <90>; + cam_vana-supply = <&pm8909_l17>; + cam_vio-supply = <&pm8909_l6>; + qcom,cam-vreg-name = "cam_vio", "cam_vana"; + qcom,cam-vreg-type = <1 0>; + qcom,cam-vreg-min-voltage = <0 2850000>; + qcom,cam-vreg-max-voltage = <0 2850000>; + qcom,cam-vreg-op-mode = <0 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front_sleep>; + gpios = <&msm_gpio 27 0>, + <&msm_gpio 28 0>, + <&msm_gpio 33 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK", + "CAM_RESET", + "CAM_STANDBY"; + qcom,cci-master = <0>; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909-camera.dtsi b/arch/arm64/boot/dts/qcom/msm8909-camera.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..634407a807a9579c12ac4c652fa64fe088924475 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8909-camera.dtsi @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2014-2015, 2017, 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. + */ +&soc { + qcom,msm-cam@1800000{ + compatible = "qcom,msm-cam"; + reg = <0x1b00000 0x40000>; + reg-names = "msm-cam"; + status = "ok"; + bus-vectors = "suspend", "svs", "nominal", "turbo"; + qcom,bus-votes = <0 320000000 640000000 640000000>; + }; + + qcom,csiphy@1b0ac00 { + cell-index = <0>; + compatible = "qcom,csiphy-v3.1", "qcom,csiphy"; + reg = <0x1b0ac00 0x200>, + <0x1b00030 0x4>; + reg-names = "csiphy", "csiphy_clk_mux"; + interrupts = <0 78 0>; + interrupt-names = "csiphy"; + clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>, + <&clock_gcc clk_gcc_camss_ispif_ahb_clk>, + <&clock_gcc clk_csi0phytimer_clk_src>, + <&clock_gcc clk_gcc_camss_csi0phytimer_clk>, + <&clock_gcc clk_camss_top_ahb_clk_src>, + <&clock_gcc clk_gcc_camss_csi0phy_clk>, + <&clock_gcc clk_gcc_camss_csi1phy_clk>, + <&clock_gcc clk_gcc_camss_ahb_clk>; + clock-names = "camss_top_ahb_clk", "ispif_ahb_clk", + "csiphy_timer_src_clk", "csiphy_timer_clk", + "camss_ahb_src", "csi0_phy_clk", "csi1_phy_clk", + "camss_ahb_clk"; + qcom,clock-rates = <0 0 200000000 0 0 0 0 0>; + }; + + qcom,csid@1b08000 { + cell-index = <0>; + compatible = "qcom,csid-v3.1", "qcom,csid"; + reg = <0x1b08000 0x100>; + reg-names = "csid"; + interrupts = <0 49 0>; + interrupt-names = "csid"; + qcom,csi-vdd-voltage = <1200000>; + qcom,mipi-csi-vdd-supply = <&pm8909_l2>; + clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>, + <&clock_gcc clk_gcc_camss_top_ahb_clk>, + <&clock_gcc clk_gcc_camss_csi0_ahb_clk>, + <&clock_gcc clk_csi0_clk_src>, + <&clock_gcc clk_gcc_camss_csi0_clk>, + <&clock_gcc clk_gcc_camss_csi0pix_clk>, + <&clock_gcc clk_gcc_camss_csi0rdi_clk>, + <&clock_gcc clk_gcc_camss_ahb_clk>; + clock-names = "ispif_ahb_clk", "camss_top_ahb_clk", + "csi_ahb_clk", "csi_src_clk", + "csi_clk", "csi_pix_clk", + "csi_rdi_clk", "camss_ahb_clk"; + qcom,clock-rates = <40000000 0 0 200000000 0 0 0 0>; + }; + + qcom,csid@1b08400 { + cell-index = <1>; + compatible = "qcom,csid-v3.1", "qcom,csid"; + reg = <0x1b08400 0x100>; + reg-names = "csid"; + interrupts = <0 50 0>; + interrupt-names = "csid"; + qcom,csi-vdd-voltage = <1200000>; + qcom,mipi-csi-vdd-supply = <&pm8909_l2>; + clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>, + <&clock_gcc clk_gcc_camss_top_ahb_clk>, + <&clock_gcc clk_gcc_camss_csi1_ahb_clk>, + <&clock_gcc clk_csi1_clk_src>, + <&clock_gcc clk_gcc_camss_csi1_clk>, + <&clock_gcc clk_gcc_camss_csi1pix_clk>, + <&clock_gcc clk_gcc_camss_csi1rdi_clk>, + <&clock_gcc clk_gcc_camss_ahb_clk>, + <&clock_gcc clk_gcc_camss_csi1phy_clk>; + clock-names = "ispif_ahb_clk", "camss_top_ahb_clk", + "csi_ahb_clk", "csi_src_clk", + "csi_clk", "csi_pix_clk", + "csi_rdi_clk", "camss_ahb_clk", "camss_csi1_phy"; + qcom,clock-rates = <40000000 0 0 200000000 0 0 0 0 0>; + }; + + qcom,ispif@1b0a000 { + cell-index = <0>; + compatible = "qcom,ispif"; + reg = <0x1b0a000 0x500>, + <0x1b00020 0x10>; + reg-names = "ispif", "csi_clk_mux"; + interrupts = <0 51 0>; + interrupt-names = "ispif"; + qcom,num-isps = <0x1>; + vfe0_vdd_supply = <&gdsc_vfe>; + clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>, + <&clock_gcc clk_gcc_camss_ispif_ahb_clk>, + + <&clock_gcc clk_csi0_clk_src>, + <&clock_gcc clk_gcc_camss_csi0_clk>, + <&clock_gcc clk_gcc_camss_csi0rdi_clk>, + <&clock_gcc clk_gcc_camss_csi0pix_clk>, + <&clock_gcc clk_csi1_clk_src>, + <&clock_gcc clk_gcc_camss_csi1_clk>, + <&clock_gcc clk_gcc_camss_csi1rdi_clk>, + <&clock_gcc clk_gcc_camss_csi1pix_clk>, + <&clock_gcc clk_vfe0_clk_src>, + <&clock_gcc clk_gcc_camss_vfe0_clk>, + <&clock_gcc clk_gcc_camss_csi_vfe0_clk>; + + clock-names = "camss_top_ahb_clk", "ispif_ahb_clk", + "csi0_src_clk", "csi0_clk", + "csi0_rdi_clk", "csi0_pix_clk", + "csi1_src_clk", "csi1_clk", + "csi1_rdi_clk", "csi1_pix_clk", + "vfe0_clk_src", "camss_vfe_vfe0_clk", + "camss_csi_vfe0_clk"; + qcom,clock-rates = <0 40000000 + 200000000 0 0 0 + 200000000 0 0 0 + 0 0 0>; + qcom,clock-control = "NO_SET_RATE", "SET_RATE", + "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE", + "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE", + "INIT_RATE", "NO_SET_RATE", "NO_SET_RATE"; + }; + + qcom,vfe@1b10000 { + cell-index = <0>; + compatible = "qcom,vfe32"; + reg = <0x1b10000 0x830>, + <0x1b40000 0x200>; + reg-names = "vfe", "vfe_vbif"; + interrupts = <0 52 0>; + interrupt-names = "vfe"; + vdd-supply = <&gdsc_vfe>; + clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>, + <&clock_gcc clk_vfe0_clk_src>, + <&clock_gcc clk_gcc_camss_vfe0_clk>, + <&clock_gcc clk_gcc_camss_csi_vfe0_clk>, + <&clock_gcc clk_gcc_camss_vfe_ahb_clk>, + <&clock_gcc clk_gcc_camss_vfe_axi_clk>, + <&clock_gcc clk_gcc_camss_ahb_clk>, + <&clock_gcc clk_gcc_camss_top_ahb_clk>; + clock-names = "camss_top_ahb_clk", "vfe_clk_src", + "camss_vfe_vfe_clk", "camss_csi_vfe_clk", "iface_clk", + "bus_clk", "camss_ahb_clk", "ispif_ahb_clk"; + qcom,clock-rates = <40000000 266670000 0 0 0 0 0 0>; + + qos-entries = <8>; + qos-regs = <0x7BC 0x7C0 0x7C4 0x7C8 0x7CC 0x7D0 + 0x7D4 0x798>; + qos-settings = <0xAAA5AAA5 0xAAA5AAA5 0xAAA5AAA5 + 0xAAA5AAA5 0xAAA5AAA5 0xAAA5AAA5 + 0xAAA5AAA5 0x00010000>; + vbif-entries = <1>; + vbif-regs = <0x04>; + vbif-settings = <0x1>; + ds-entries = <15>; + ds-regs = <0x7D8 0x7DC 0x7E0 0x7E4 0x7E8 + 0x7EC 0x7F0 0x7F4 0x7F8 0x7FC 0x800 + 0x804 0x808 0x80C 0x810>; + ds-settings = <0xCCCC1111 0xCCCC1111 0xCCCC1111 + 0xCCCC1111 0xCCCC1111 0xCCCC1111 + 0xCCCC1111 0xCCCC1111 0xCCCC1111 + 0xCCCC1111 0xCCCC1111 0xCCCC1111 + 0xCCCC1111 0xCCCC1111 0x00000103>; + + bus-util-factor = <1024>; + }; + + qcom,cam_smmu { + status = "ok"; + compatible = "qcom,msm-cam-smmu"; + msm_cb1: msm_cb1 { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_iommu 0x400 0x0>; + label = "vfe"; + qcom,scratch-buf-support; + }; + }; + + qcom,irqrouter@1b00000 { + status = "ok"; + cell-index = <0>; + compatible = "qcom,irqrouter"; + reg = <0x1b00000 0x100>; + reg-names = "irqrouter"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi index 0a657daa20aa41be83e49991d66c5aaa7cd0b9cd..15f0c31d498abfb40a0ff98710bddb2bd1b8b009 100644 --- a/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, 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 @@ -11,6 +11,7 @@ */ #include "dsi-panel-390p-auo-cmd.dtsi" +#include "dsi-panel-hx8394d-720p-video.dtsi" &soc { dsi_panel_pwr_supply: dsi_panel_pwr_supply { diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dts b/arch/arm64/boot/dts/qcom/msm8909-mtp.dts new file mode 100644 index 0000000000000000000000000000000000000000..a4ca87a0982a32f23cb85229577e6fea65a6c482 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2014-2015, 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. + */ + +/dts-v1/; + +#include "msm8909-mtp.dtsi" +#include "msm8909-pm8909.dtsi" +#include "msm8909-pm8909-mtp.dtsi" +/ { + model = "Qualcomm Technologies, Inc. MSM8909-PM8909 MTP"; + compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp"; + qcom,board-id= <8 0x100>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi index 4844886288711898c266a6bd2eb862b9b7f60f25..591d30d26077cf9a9a75c91e8d37aaaaf7b11835 100644 --- a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, 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 @@ -13,6 +13,7 @@ #include "msm8909.dtsi" #include "msm8909-pinctrl.dtsi" #include "msm8909-regulator.dtsi" +#include "msm8909-camera-sensor-mtp.dtsi" &soc { /* @@ -71,7 +72,7 @@ i2c@78b9000 { /* BLSP1 QUP5 */ synaptics@20 { - compatible = "synaptics,dsx"; + compatible = "synaptics,dsx-i2c"; reg = <0x20>; interrupt-parent = <&msm_gpio>; interrupts = <13 0x2008>; @@ -84,10 +85,16 @@ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; pinctrl-2 = <&ts_release>; synaptics,irq-gpio = <&msm_gpio 13 0x2008>; + synaptics,irq-on-state = <0>; + synaptics,irq-flags = <0x2008>; + synaptics,reset-gpio = <&msm_gpio 12 0x0>; - synaptics,disable-gpios; - synaptics,display-coords = <0 0 719 1279>; - synaptics,panel-coords = <0 0 719 1405>; + synaptics,reset-on-state = <0>; + synaptics,reset-active-ms = <20>; + synaptics,cap-button-codes = <139 158 172>; + /delete-property/ synaptics,disable-gpios; + /delete-property/ synaptics,display-coords; + /delete-property/ synaptics,panel-coords; }; }; @@ -110,6 +117,16 @@ }; }; + gen-vkeys { + compatible = "qcom,gen-vkeys"; + label = "synaptics_dsx_i2c"; + qcom,disp-maxx = <719>; + qcom,disp-maxy = <1279>; + qcom,panel-maxx = <719>; + qcom,panel-maxy = <1405>; + qcom,key-codes = <158 139 172 217>; + }; + gpio_keys { compatible = "gpio-keys"; input-name = "gpio-keys"; @@ -326,6 +343,13 @@ qcom,mdss-pref-prim-intf = "dsi"; }; +&dsi_hx8394d_720_vid { + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm"; + qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>; + qcom,mdss-dsi-bl-pmic-bank-select = <0>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + &msm_gpio { pmx_mdss { mdss_dsi_active: mdss_dsi_active { @@ -412,3 +436,13 @@ }; }; }; + +&mdss_dsi0 { + qcom,dsi-pref-prim-pan = <&dsi_hx8394d_720_vid>; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_dsi_active &mdss_te_active>; + pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>; + + qcom,platform-reset-gpio = <&msm_gpio 25 0>; + qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8909-mtp.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..09d351cecc38c7d43271c835bca9683620be08a4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8909-pm8909-mtp.dtsi @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2014-2015, 2017, 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. + */ + +&pm8909_chg { + status = "ok"; + qcom,charging-disabled; +}; + +&pm8909_bms { + status = "ok"; + qcom,battery-data = <&mtp_batterydata>; + qcom,batt-aging-comp; +}; + +&usb_otg { + extcon = <&pm8909_chg>; +}; + +&dsi_hx8394d_720_vid { + qcom,cont-splash-enabled; + qcom,mdss-dsi-pwm-gpio = <&pm8909_mpps 4 0>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&spmi_bus { + qcom,pm8909@0 { + qcom,leds@a300 { + status = "okay"; + qcom,led_mpp_4 { + label = "mpp"; + linux,name = "button-backlight"; + linux,default-trigger = "none"; + qcom,default-state = "off"; + qcom,max-current = <40>; + qcom,current-setting = <5>; + qcom,id = <6>; + qcom,mode = "manual"; + qcom,source-sel = <1>; + qcom,mode-ctrl = <0x60>; + }; + }; + }; + + qcom,pm8909@1 { + qcom,vibrator@c000 { + status = "okay"; + qcom,vib-timeout-ms = <15000>; + qcom,vib-vtg-level-mV = <3100>; + }; + }; +}; + +&pm8909_mpps { + mpp@a000 { /* MPP 1 */ + /* VDD_PX */ + status = "disabled"; + }; + + mpp@a100 { /* MPP 2 */ + /* Backlight PWM */ + qcom,mode = <1>; /* Digital output */ + qcom,invert = <0>; /* Disable invert */ + qcom,src-sel = <4>; /* DTEST1 */ + qcom,vin-sel = <0>; /* VPH_PWR */ + qcom,master-en = <1>; /* Enable MPP */ + }; + + mpp@a200 { /* MPP 3 */ + /* VREF DAC */ + status = "disabled"; + }; + + mpp@a300 { /* MPP 4 */ + /* HR LED */ + status = "disabled"; + }; +}; + +&pm8909_gpios { + gpio@c000 { /* GPIO 1 */ + /* Battery UICC Alarm */ + status = "disabled"; + }; + + gpio@c100 { /* GPIO 2 */ + /* NFC_CLK_REQ */ + qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */ + qcom,pull = <5>; /* QPNP_PIN_PULL_NO */ + qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */ + qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */ + qcom,master-en = <1>; + }; + + gpio@c200 { /* GPIO 3 */ + /* External regulator control for WTR */ + status = "disabled"; + }; + + gpio@c300 { /* GPIO 4 */ + /* External regulator control for APC */ + status = "disabled"; + }; +}; + +&audio_codec_mtp { + compatible = "qcom,msm8952-audio-codec"; + qcom,model = "msm8909-snd-card"; + reg = <0x7702000 0x4>, + <0x7702004 0x4>, + <0x7702008 0x4>; + reg-names = "csr_gp_io_mux_mic_ctl", + "csr_gp_io_mux_spkr_ctl", + "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel"; + qcom,msm-snd-card-id = <0>; + qcom,msm-codec-type = "internal"; + qcom,msm-ext-pa = "primary"; + qcom,msm-mclk-freq = <9600000>; + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; + qcom,msm-hs-micbias-type = "internal"; + qcom,msm-micbias1-ext-cap; + qcom,msm-micbias2-ext-cap; + qcom,audio-routing = + "RX_BIAS", "MCLK", + "SPK_RX_BIAS", "MCLK", + "INT_LDO_H", "MCLK", + "MIC BIAS External", "Handset Mic", + "MIC BIAS Internal2", "Headset Mic", + "MIC BIAS External", "Secondary Mic", + "AMIC1", "MIC BIAS External", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External"; + + qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>; + qcom,cdc-us-euro-gpios = <&cdc_us_euro_gpios>; + + asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, + <&voip>, <&voice>, + <&loopback>, <&compress>, <&hostless>, + <&afe>, <&lsm>, <&routing>, <&pcm_noirq>; + asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-pcm-dsp.2", + "msm-voip-dsp", "msm-pcm-voice", + "msm-pcm-loopback", "msm-compress-dsp", + "msm-pcm-hostless", "msm-pcm-afe", + "msm-lsm-client", "msm-pcm-routing", + "msm-pcm-dsp-noirq"; + asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>, + <&dai_mi2s0>, <&dai_mi2s1>, + <&dai_mi2s2>, <&dai_mi2s3>, + <&dai_mi2s4>, <&dai_mi2s5>, + <&sb_0_rx>, <&sb_0_tx>, + <&sb_1_rx>, <&sb_1_tx>, + <&sb_3_rx>, <&sb_3_tx>, + <&sb_4_rx>, <&sb_4_tx>, + <&bt_sco_rx>, <&bt_sco_tx>, + <&bt_a2dp_rx>, <&int_fm_rx>, <&int_fm_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, + <&afe_proxy_rx>, <&afe_proxy_tx>, + <&incall_record_rx>, <&incall_record_tx>, + <&incall_music_rx>, <&incall_music_2_rx>; + asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8", + "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", + "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", + "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289", + "msm-dai-q6-dev.12290", + "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293", + "msm-dai-q6-dev.224", "msm-dai-q6-dev.225", + "msm-dai-q6-dev.241", "msm-dai-q6-dev.240", + "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772", + "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770"; + asoc-codec = <&stub_codec>, <&msm_digital_codec>, + <&pmic_analog_codec>; + asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec", + "analog-codec"; +}; + +&pm8909_1 { + pmic_analog_codec: analog-codec@f100 { + status = "okay"; + compatible = "qcom,pmic-analog-codec"; + reg = <0xf000 0x200>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-parent = <&spmi_bus>; + interrupts = + <0x1 0xf0 0x0 IRQ_TYPE_NONE>, + <0x1 0xf0 0x1 IRQ_TYPE_NONE>, + <0x1 0xf0 0x2 IRQ_TYPE_NONE>, + <0x1 0xf0 0x3 IRQ_TYPE_NONE>, + <0x1 0xf0 0x4 IRQ_TYPE_NONE>, + <0x1 0xf0 0x5 IRQ_TYPE_NONE>, + <0x1 0xf0 0x6 IRQ_TYPE_NONE>, + <0x1 0xf0 0x7 IRQ_TYPE_NONE>, + <0x1 0xf1 0x0 IRQ_TYPE_NONE>, + <0x1 0xf1 0x1 IRQ_TYPE_NONE>, + <0x1 0xf1 0x2 IRQ_TYPE_NONE>, + <0x1 0xf1 0x3 IRQ_TYPE_NONE>, + <0x1 0xf1 0x4 IRQ_TYPE_NONE>, + <0x1 0xf1 0x5 IRQ_TYPE_NONE>; + interrupt-names = + "spk_cnp_int", + "spk_clip_int", + "spk_ocp_int", + "ins_rem_det1", + "but_rel_det", + "but_press_det", + "ins_rem_det", + "mbhc_int", + "ear_ocp_int", + "hphr_ocp_int", + "hphl_ocp_det", + "ear_cnp_int", + "hphr_cnp_int", + "hphl_cnp_int"; + + cdc-vdda-cp-supply = <&pm8909_s2>; + qcom,cdc-vdda-cp-voltage = <1800000 2200000>; + qcom,cdc-vdda-cp-current = <500000>; + + cdc-vdda-h-supply = <&pm8909_l5>; + qcom,cdc-vdda-h-voltage = <1800000 1800000>; + qcom,cdc-vdda-h-current = <5000>; + + cdc-vdd-px-supply = <&pm8909_l5>; + qcom,cdc-vdd-px-voltage = <1800000 1800000>; + qcom,cdc-vdd-px-current = <5000>; + + cdc-vdd-pa-supply = <&pm8909_s2>; + qcom,cdc-vdd-pa-voltage = <1800000 2200000>; + qcom,cdc-vdd-pa-current = <260000>; + + cdc-vdd-mic-bias-supply = <&pm8909_l13>; + qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>; + qcom,cdc-vdd-mic-bias-current = <5000>; + + qcom,cdc-mclk-clk-rate = <9600000>; + + qcom,cdc-static-supplies = + "cdc-vdda-h", + "cdc-vdd-px", + "cdc-vdd-pa", + "cdc-vdda-cp"; + + qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias"; + + msm_digital_codec: msm-dig-codec@f000 { + compatible = "qcom,msm-digital-codec"; + reg = <0x771c000 0x100>; + }; + }; +}; + +&spk_vreg { + status = "okay"; +}; + +&pm8909_conga_dig { + status = "disabled"; +}; + +&pm8909_conga_analog { + status = "disabled"; +}; + +&wcnss { + qcom,wcnss-vadc = <&pm8909_vadc>; +}; + +&soc { + i2c@78b6000 { + nq@28 { + qcom,nq-clkreq = <&pm8909_gpios 2 0>; + }; + }; +}; + +&mdss_dsi { + vdda-supply = <&pm8909_l2>; + vddio-supply = <&pm8909_l6>; + qcom,mdss_dsi_ctrl0@1ac8000 { + vdd-supply = <&pm8909_l17>; + vddio-supply = <&pm8909_l6>; + }; +}; + +&vendor_fstab { + status = "disabled"; +}; + +&system_fstab { + status = "disabled"; +}; + +&dsi_hx8394d_720_vid { + qcom,cont-splash-enabled; + qcom,mdss-dsi-pwm-gpio = <&pm8909_mpps 4 0>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&soc { + qcom,msm-audio-apr { + compatible = "qcom,msm-audio-apr"; + msm_audio_apr_dummy { + compatible = "qcom,msm-audio-apr-dummy"; + }; + }; + + qcom,avtimer@c0a300c { + compatible = "qcom,avtimer"; + reg = <0x0c0a300c 0x4>, + <0x0c0a3010 0x4>; + reg-names = "avtimer_lsb_addr", "avtimer_msb_addr"; + qcom,clk-div = <27>; + }; + + cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_pdm_lines_act>; + pinctrl-1 = <&cdc_pdm_lines_sus>; + }; + + cdc_us_euro_gpios: msm_cdc_pinctrl_us_euro { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cross_conn_det_act>; + pinctrl-1 = <&cross_conn_det_sus>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi index 86bee6e3f70867512db35a89ab4a30cf4883f21b..626172e71e5abb9af3e7298ffa33a1194e6ebcfc 100644 --- a/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, 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 @@ -78,6 +78,12 @@ }; }; +&dsi_hx8394d_720_vid { + qcom,cont-splash-enabled; + qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + &spmi_bus { pm8916@0 { qcom,leds@a300 { @@ -185,3 +191,11 @@ }; }; }; + +&vendor_fstab { + status = "disabled"; +}; + +&system_fstab { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi index 54b070bf5d1cf2e6d66fb831f94be58e4b40ddb2..94c93b62fecfdea6afa05d37026329d3ebbe266d 100644 --- a/arch/arm64/boot/dts/qcom/msm8909.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi @@ -243,6 +243,7 @@ #include "msm8909-vidc.dtsi" #include "msm8909-mdss.dtsi" #include "msm8909-mdss-pll.dtsi" +#include "msm8909-camera.dtsi" &soc { #address-cells = <1>; @@ -2017,3 +2018,4 @@ status = "okay"; }; #include "msm8909-thermal.dtsi" +#include "msm8909-pinctrl.dtsi" diff --git a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi index 8c8f175ca7b05b10d4e7546765b9ec13b97d3acc..8d643ebedbbc03a4731d64b0e07f6bc3239cb59f 100644 --- a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2018, 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 @@ -987,28 +987,30 @@ }; /* Venus CTI */ - cti_video_cpu0: cti@6134000 { + cti_video_cpu0: cti@6035000 { compatible = "arm,primecell"; arm,primecell-periphid = <0x0003b966>; - reg = <0x6134000 0x1000>; + reg = <0x6035000 0x1000>; reg-names = "cti-base"; coresight-name = "coresight-cti-video-cpu0"; + status = "disabled"; clocks = <&clock_gcc clk_qdss_clk>, <&clock_gcc clk_qdss_a_clk>; clock-names = "apb_pclk"; }; /* Pronto CTI */ - cti_wcn_cpu0: cti@6139000 { + cti_wcn_cpu0: cti@6039000 { compatible = "arm,primecell"; arm,primecell-periphid = <0x0003b966>; - reg = <0x6139000 0x1000>; + reg = <0x6039000 0x1000>; reg-names = "cti-base"; coresight-name = "coresight-cti-wcn-cpu0"; + status = "disabled"; clocks = <&clock_gcc clk_qdss_clk>, <&clock_gcc clk_qdss_a_clk>; clock-names = "apb_pclk"; diff --git a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi index 6de49002cbf385af7954fc274920a271e5b17137..b2d8749dd050c999fddffa62c5c6592c05bf7831 100644 --- a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2018-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 @@ -350,6 +350,92 @@ }; }; + spi6 { + spi6_default: spi6_default { + /* active state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <12>; /* 12 MA */ + bias-disable = <0>; /* No PULL */ + }; + }; + + spi6_sleep: spi6_sleep { + /* suspended state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "gpio"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <2>; /* 2 MA */ + bias-pull-down; /* PULL Down */ + }; + }; + + spi6_cs0_active: cs0_active { + /* CS */ + mux { + pins = "gpio22"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + + spi6_cs0_sleep: cs0_sleep { + /* CS */ + mux { + pins = "gpio22"; + function = "gpio"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + }; + + blsp2_uart2_active: blsp2_uart2_active { + mux { + pins = "gpio20", "gpio21", "gpio22", "gpio23"; + function = "blsp_uart6"; + }; + + config { + pins = "gpio20", "gpio21", "gpio22", "gpio23"; + drive-strength = <2>; + bias-disable; + }; + }; + + blsp2_uart2_sleep: blsp2_uart2_sleep { + mux { + pins = "gpio20", "gpio21", "gpio22", "gpio23"; + function = "gpio"; + }; + + config { + pins = "gpio20", "gpio21", "gpio22", "gpio23"; + drive-strength = <2>; + bias-disable; + }; + }; + spi7 { spi7_default: spi7_default { mux { diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi index e8e7a63d49de0a26fca426f82cf7d1d0d4b29c1e..18e75a0be4d86aa587661f4f9deb308388fa8b2e 100644 --- a/arch/arm64/boot/dts/qcom/msm8937.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-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 @@ -143,6 +143,7 @@ i2c2 = &i2c_2; i2c5 = &i2c_5; spi3 = &spi_3; + spi6 = &spi_6; i2c3 = &i2c_3; i2c4 = &i2c_4; sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ @@ -667,6 +668,68 @@ status = "disabled"; }; + spi_6: spi@7af6000 { /* BLSP2 QUP1 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "spi_physical", "spi_bam_physical"; + reg = <0x7af6000 0x600>, + <0x7ac4000 0x1f000>; + interrupt-names = "spi_irq", "spi_bam_irq"; + interrupts = <0 300 0>, <0 239 0>; + spi-max-frequency = <19200000>; + pinctrl-names = "spi_default", "spi_sleep"; + pinctrl-0 = <&spi6_default &spi6_cs0_active>; + pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>; + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>, + <&clock_gcc clk_gcc_blsp2_qup1_spi_apps_clk>; + clock-names = "iface_clk", "core_clk"; + qcom,infinite-mode = <0>; + qcom,use-bam; + qcom,use-pinctrl; + qcom,ver-reg-exists; + qcom,bam-consumer-pipe-index = <6>; + qcom,bam-producer-pipe-index = <7>; + qcom,master-id = <84>; + status = "disabled"; + }; + + blsp2_uart2: uart@7af0000 { /* BLSP2 UART2 */ + compatible = "qcom,msm-hsuart-v14"; + reg = <0x7af0000 0x200>, + <0x7ac4000 0x1f000>; + reg-names = "core_mem", "bam_mem"; + interrupt-names = "core_irq", "bam_irq", "wakeup_irq"; + #address-cells = <0>; + interrupt-parent = <&blsp2_uart2>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 307 0 + 1 &intc 0 239 0 + 2 &tlmm 21 0>; + + qcom,inject-rx-on-wakeup; + qcom,rx-char-to-inject = <0xfd>; + + qcom,bam-tx-ep-pipe-index = <2>; + qcom,bam-rx-ep-pipe-index = <3>; + qcom,master-id = <84>; + clock-names = "core_clk", "iface_clk"; + clocks = <&clock_gcc clk_gcc_blsp2_uart2_apps_clk>, + <&clock_gcc clk_gcc_blsp2_ahb_clk>; + pinctrl-names = "sleep", "default"; + pinctrl-0 = <&blsp2_uart2_sleep>; + pinctrl-1 = <&blsp2_uart2_active>; + qcom,msm-bus,name = "blsp2_uart2"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <84 512 0 0>, + <84 512 500 800>; + status = "disabled"; + }; + msm_cpufreq: qcom,msm-cpufreq { compatible = "qcom,msm-cpufreq"; clock-names = "l2_clk", "cpu0_clk", "cpu1_clk", "cpu2_clk", diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi index 3f3c8da6378e8e9ce5c23d04e97941e35fdbe0c8..d21f39e3e66f3a9a6d9071fe772ce29a48792c92 100644 --- a/arch/arm64/boot/dts/qcom/qcs605.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -51,7 +51,7 @@ }; &pil_gpu_mem { - reg = <0 0x90f15000 0 0x2000>; + reg = <0 0x90f15000 0 0x4000>; }; &adsp_mem { diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-wdp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-bg-wdp-overlay.dts index c34e945e16de70b1fc654bccb9eca63d6bd1b02b..4e7053562161de3d6235390a986bd5a81415d593 100644 --- a/arch/arm64/boot/dts/qcom/sda429-bg-wdp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sda429-bg-wdp-overlay.dts @@ -15,6 +15,7 @@ /plugin/; #include "sdm429-spyro-qrd-evt.dtsi" +#include "sdm429-bg-soc.dtsi" / { model = "Qualcomm Technologies, Inc. SDA429 QRD Spyro BG WDP Overlay"; @@ -24,127 +25,6 @@ qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; -&soc { - - qcom,blackghost { - compatible = "qcom,pil-blackghost"; - qcom,pil-force-shutdown; - qcom,firmware-name = "bg-wear"; - /* GPIO inputs from blackghost */ - qcom,bg2ap-status-gpio = <&tlmm 44 0>; - qcom,bg2ap-errfatal-gpio = <&tlmm 72 0>; - /* GPIO output to blackghost */ - qcom,ap2bg-status-gpio = <&tlmm 61 0>; - qcom,ap2bg-errfatal-gpio = <&tlmm 62 0>; - }; - - qcom,msm-ssc-sensors { - compatible = "qcom,msm-ssc-sensors"; - }; - - qcom,glink-bgcom-xprt-bg { - compatible = "qcom,glink-bgcom-xprt"; - label = "bg"; - qcom,qos-config = <&glink_qos_bg>; - qcom,ramp-time = <0x10>, - <0x20>, - <0x30>, - <0x40>; - }; - - glink_qos_bg: qcom,glink-qos-config-bg { - compatible = "qcom,glink-qos-config"; - qcom,flow-info = <0x80 0x0>, - <0x70 0x1>, - <0x60 0x2>, - <0x50 0x3>; - qcom,mtu-size = <0x800>; - qcom,tput-stats-cycle = <0xa>; - }; - - qcom,glink_pkt { - compatible = "qcom,glinkpkt"; - - qcom,glinkpkt-bg-daemon { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon"; - }; - - qcom,glinkpkt-bg-daemon-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon-ctl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon_ctrl"; - }; - - qcom,glinkpkt-bg-display-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl"; - }; - - qcom,glinkpkt-bg-display-data { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-data"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data"; - }; - - qcom,glinkpkt-bg-rsb-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "RSB_CTRL"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl"; - }; - - qcom,glinkpkt-bg-sso-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "sso-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_sso_ctrl"; - }; - - qcom,glinkpkt-bg-buzzer-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "buzzer-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_buzzer_ctrl"; - }; - }; - - spi_3: spi@78b7000 { /* BLSP1 QUP3*/ - status = "ok"; - qcom,bg-spi { - compatible = "qcom,bg-spi"; - reg = <0>; - spi-max-frequency = <16000000>; - interrupt-parent = <&tlmm>; - qcom,irq-gpio = <&tlmm 43 1>; - }; - }; - - i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */ - status = "disabled"; - }; - - qcom,bg-rsb { - compatible = "qcom,bg-rsb"; - vdd-ldo1-supply = <&pm660_l11>; - qcom,bg-rsb-gpio = <&tlmm 40 1>; - qcom,rsb-use-msm-gpio; - }; - - qcom,bg-daemon { - compatible = "qcom,bg-daemon"; - qcom,bg-reset-gpio = <&pm660_gpios 5 0>; - ssr-reg1-supply = <&pm660_l3>; - ssr-reg2-supply = <&pm660_l9>; - }; -}; - &usb_otg { HSUSB_3p3-supply = <&L16A>; }; diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts index d179b7be485c875fa4b21dbc96aaab897fd0e449..9b9a849a003ba2b72661176d75b7dace6f556d23 100644 --- a/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts @@ -15,6 +15,7 @@ /plugin/; #include "sdm429-spyro-qrd-evt.dtsi" +#include "sdm429-bg-soc.dtsi" / { model = "Qualcomm Technologies, Inc. SDA429 QRD BG WTP Overlay"; @@ -24,130 +25,12 @@ qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; -&soc { - - qcom,blackghost { - compatible = "qcom,pil-blackghost"; - qcom,pil-force-shutdown; - qcom,firmware-name = "bg-wear"; - /* GPIO inputs from blackghost */ - qcom,bg2ap-status-gpio = <&tlmm 44 0>; - qcom,bg2ap-errfatal-gpio = <&tlmm 72 0>; - /* GPIO output to blackghost */ - qcom,ap2bg-status-gpio = <&tlmm 61 0>; - qcom,ap2bg-errfatal-gpio = <&tlmm 62 0>; - }; - - qcom,msm-ssc-sensors { - compatible = "qcom,msm-ssc-sensors"; - }; - - qcom,glink-bgcom-xprt-bg { - compatible = "qcom,glink-bgcom-xprt"; - label = "bg"; - qcom,qos-config = <&glink_qos_bg>; - qcom,ramp-time = <0x10>, - <0x20>, - <0x30>, - <0x40>; - }; - - glink_qos_bg: qcom,glink-qos-config-bg { - compatible = "qcom,glink-qos-config"; - qcom,flow-info = <0x80 0x0>, - <0x70 0x1>, - <0x60 0x2>, - <0x50 0x3>; - qcom,mtu-size = <0x800>; - qcom,tput-stats-cycle = <0xa>; - }; - - qcom,glink_pkt { - compatible = "qcom,glinkpkt"; - - qcom,glinkpkt-bg-daemon { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon"; - }; - - qcom,glinkpkt-bg-daemon-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon-ctl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon_ctrl"; - }; - - qcom,glinkpkt-bg-display-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl"; - }; - - qcom,glinkpkt-bg-display-data { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-data"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data"; - }; - - qcom,glinkpkt-bg-rsb-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "RSB_CTRL"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl"; - }; - - qcom,glinkpkt-bg-sso-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "sso-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_sso_ctrl"; - }; - - qcom,glinkpkt-bg-buzzer-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "buzzer-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_buzzer_ctrl"; - }; - }; - - spi_3: spi@78b7000 { /* BLSP1 QUP3*/ - status = "ok"; - qcom,bg-spi { - compatible = "qcom,bg-spi"; - reg = <0>; - spi-max-frequency = <16000000>; - interrupt-parent = <&tlmm>; - qcom,irq-gpio = <&tlmm 43 1>; - }; - }; - - i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */ - status = "disabled"; - }; - - qcom,bg-rsb { - compatible = "qcom,bg-rsb"; - vdd-ldo1-supply = <&pm660_l11>; - qcom,bg-rsb-gpio = <&tlmm 40 1>; - qcom,rsb-use-msm-gpio; - }; - - qcom,bg-daemon { - compatible = "qcom,bg-daemon"; - qcom,bg-reset-gpio = <&pm660_gpios 5 0>; - ssr-reg1-supply = <&pm660_l3>; - ssr-reg2-supply = <&pm660_l9>; - }; -}; - &mdss_dsi0 { qcom,dsi-pref-prim-pan = <&dsi_auo_416p_amoled_cmd>; /delete-property/ vdd-supply; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_te_active>; + pinctrl-1 = <&mdss_te_suspend>; vddio-supply = <&L11A>; qcom,platform-enable-gpio = <&pm660_gpios 12 0>; }; @@ -156,6 +39,36 @@ /delete-node/ qcom,panel-supply-entry@0; }; +&i2c_4 { + status = "ok"; + tsc@24 { + status = "disabled"; + }; + + raydium_ts@39 { + compatible = "raydium,raydium-ts"; + reg = <0x39>; + interrupt-parent = <&tlmm>; + interrupts = <13 0x2008>; + vdd_ana-supply = <&pm660_l11>; + vcc_i2c-supply = <&pm660_l13>; + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + raydium,reset-gpio = <&tlmm 64 0x00>; + raydium,irq-gpio = <&tlmm 65 0x00>; + raydium,num-max-touches = <2>; + raydium,soft-reset-delay-ms = <50>; + raydium,hard-reset-delay-ms = <100>; + raydium,x_max = <416>; + raydium,y_max = <416>; + raydium,display-coords= <0 0 416 416>; + raydium,fw_id = <0x2202>; + }; +}; + &usb_otg { HSUSB_3p3-supply = <&L16A>; }; @@ -177,3 +90,39 @@ }; }; }; + +&msm_gpu { + qcom,initial-pwrlevel = <0>; + qcom,gpu-pwrlevels { + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <2>; + qcom,bus-min = <2>; + qcom,bus-max = <2>; + }; + qcom,gpu-pwrlevel@1{ + reg = <1>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; +}; + +&msm_cpufreq { + qcom,cpufreq-table = + < 960000 >, + < 1305600 >, + < 1497600 >, + < 1708800 >; +}; + +&cpubw { + qcom,bw-tbl = + < 1611 /* 211.2 MHz */ >, /*Low SVS*/ + < 2929 /* 384 MHz */ >, /* SVS */ + < 5053 /* 662.4 MHz */ >, /* SVS+ */ + < 5712 /* 748.8 MHz */ >; /* NOM */ +}; diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts b/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts index d755b0f76adfa528a8b2a0a9e45a1346f4dbbd9c..98b8c1211b55483ec64f0c501652c7513b2375af 100644 --- a/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts +++ b/arch/arm64/boot/dts/qcom/sda429-bg-wtp.dts @@ -24,3 +24,16 @@ qcom,board-id = <0x00010b 8>; qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; + +&msm_gpu { + /delete-property/qcom,enable-ca-jump; + /delete-property/qcom,ca-busy-penalty; + /delete-property/qcom,ca-target-pwrlevel; + + qcom,gpu-pwrlevels { + /delete-node/qcom,gpu-pwrlevel@2; + /delete-node/qcom,gpu-pwrlevel@3; + /delete-node/qcom,gpu-pwrlevel@4; + /delete-node/qcom,gpu-pwrlevel@5; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi b/arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..44bc91c73d23bea2d4d50af4eaf6c5bb8ef4b297 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdm429-bg-soc.dtsi @@ -0,0 +1,132 @@ +/* Copyright (c) 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. + */ + +&soc { + + qcom,blackghost { + compatible = "qcom,pil-blackghost"; + qcom,pil-force-shutdown; + qcom,firmware-name = "bg-wear"; + /* GPIO inputs from blackghost */ + qcom,bg2ap-status-gpio = <&tlmm 44 0>; + qcom,bg2ap-errfatal-gpio = <&tlmm 72 0>; + /* GPIO output to blackghost */ + qcom,ap2bg-status-gpio = <&tlmm 61 0>; + qcom,ap2bg-errfatal-gpio = <&tlmm 62 0>; + }; + + qcom,msm-ssc-sensors { + compatible = "qcom,msm-ssc-sensors"; + }; + + qcom,glink-bgcom-xprt-bg { + compatible = "qcom,glink-bgcom-xprt"; + label = "bg"; + qcom,qos-config = <&glink_qos_bg>; + qcom,ramp-time = <0x10>, + <0x20>, + <0x30>, + <0x40>; + }; + + glink_qos_bg: qcom,glink-qos-config-bg { + compatible = "qcom,glink-qos-config"; + qcom,flow-info = <0x80 0x0>, + <0x70 0x1>, + <0x60 0x2>, + <0x50 0x3>; + qcom,mtu-size = <0x800>; + qcom,tput-stats-cycle = <0xa>; + }; + + qcom,glink_pkt { + compatible = "qcom,glinkpkt"; + + qcom,glinkpkt-bg-daemon { + qcom,glinkpkt-transport = "bgcom"; + qcom,glinkpkt-edge = "bg"; + qcom,glinkpkt-ch-name = "bg-daemon"; + qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon"; + }; + + qcom,glinkpkt-bg-daemon-ctrl { + qcom,glinkpkt-transport = "bgcom"; + qcom,glinkpkt-edge = "bg"; + qcom,glinkpkt-ch-name = "bg-daemon-ctl"; + qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon_ctrl"; + }; + + qcom,glinkpkt-bg-display-ctrl { + qcom,glinkpkt-transport = "bgcom"; + qcom,glinkpkt-edge = "bg"; + qcom,glinkpkt-ch-name = "display-ctrl"; + qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl"; + }; + + qcom,glinkpkt-bg-display-data { + qcom,glinkpkt-transport = "bgcom"; + qcom,glinkpkt-edge = "bg"; + qcom,glinkpkt-ch-name = "display-data"; + qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data"; + }; + + qcom,glinkpkt-bg-rsb-ctrl { + qcom,glinkpkt-transport = "bgcom"; + qcom,glinkpkt-edge = "bg"; + qcom,glinkpkt-ch-name = "RSB_CTRL"; + qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl"; + }; + + qcom,glinkpkt-bg-sso-ctrl { + qcom,glinkpkt-transport = "bgcom"; + qcom,glinkpkt-edge = "bg"; + qcom,glinkpkt-ch-name = "sso-ctrl"; + qcom,glinkpkt-dev-name = "glink_pkt_bg_sso_ctrl"; + }; + + qcom,glinkpkt-bg-buzzer-ctrl { + qcom,glinkpkt-transport = "bgcom"; + qcom,glinkpkt-edge = "bg"; + qcom,glinkpkt-ch-name = "buzzer-ctrl"; + qcom,glinkpkt-dev-name = "glink_pkt_bg_buzzer_ctrl"; + }; + }; + + spi_3: spi@78b7000 { /* BLSP1 QUP3*/ + status = "ok"; + qcom,bg-spi { + compatible = "qcom,bg-spi"; + reg = <0>; + spi-max-frequency = <16000000>; + interrupt-parent = <&tlmm>; + qcom,irq-gpio = <&tlmm 43 1>; + }; + }; + + i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */ + status = "disabled"; + }; + + qcom,bg-rsb { + compatible = "qcom,bg-rsb"; + vdd-ldo1-supply = <&pm660_l11>; + qcom,bg-rsb-gpio = <&tlmm 40 1>; + qcom,rsb-use-msm-gpio; + }; + + qcom,bg-daemon { + compatible = "qcom,bg-daemon"; + qcom,bg-reset-gpio = <&pm660_gpios 5 0>; + ssr-reg1-supply = <&pm660_l3>; + ssr-reg2-supply = <&pm660_l9>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts index 37ff160b226af767f208854506366b4a5f99fb8e..b92688c54a7a39c4da0996a46d943584bd7b18ef 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts @@ -15,136 +15,16 @@ /plugin/; #include "sdm429-spyro-qrd-evt.dtsi" +#include "sdm429-bg-soc.dtsi" / { model = "Qualcomm Technologies, Inc. SDM429 QRD BG WDP Overlay"; compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd"; qcom,msm-id = <416 0x0>; - qcom,board-id = <0x01000b 9>; + qcom,board-id = <0x00010b 9>; qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; -&soc { - - qcom,blackghost { - compatible = "qcom,pil-blackghost"; - qcom,pil-force-shutdown; - qcom,firmware-name = "bg-wear"; - /* GPIO inputs from blackghost */ - qcom,bg2ap-status-gpio = <&tlmm 44 0>; - qcom,bg2ap-errfatal-gpio = <&tlmm 72 0>; - /* GPIO output to blackghost */ - qcom,ap2bg-status-gpio = <&tlmm 61 0>; - qcom,ap2bg-errfatal-gpio = <&tlmm 62 0>; - }; - - qcom,msm-ssc-sensors { - compatible = "qcom,msm-ssc-sensors"; - }; - - qcom,glink-bgcom-xprt-bg { - compatible = "qcom,glink-bgcom-xprt"; - label = "bg"; - qcom,qos-config = <&glink_qos_bg>; - qcom,ramp-time = <0x10>, - <0x20>, - <0x30>, - <0x40>; - }; - - glink_qos_bg: qcom,glink-qos-config-bg { - compatible = "qcom,glink-qos-config"; - qcom,flow-info = <0x80 0x0>, - <0x70 0x1>, - <0x60 0x2>, - <0x50 0x3>; - qcom,mtu-size = <0x800>; - qcom,tput-stats-cycle = <0xa>; - }; - - qcom,glink_pkt { - compatible = "qcom,glinkpkt"; - - qcom,glinkpkt-bg-daemon { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon"; - }; - - qcom,glinkpkt-bg-daemon-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon-ctl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon_ctrl"; - }; - - qcom,glinkpkt-bg-display-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl"; - }; - - qcom,glinkpkt-bg-display-data { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-data"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data"; - }; - - qcom,glinkpkt-bg-rsb-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "RSB_CTRL"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl"; - }; - - qcom,glinkpkt-bg-sso-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "sso-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_sso_ctrl"; - }; - - qcom,glinkpkt-bg-buzzer-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "buzzer-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_buzzer_ctrl"; - }; - }; - - spi_3: spi@78b7000 { /*BLSP1 QUP3*/ - status = "ok"; - qcom,bg-spi { - compatible = "qcom,bg-spi"; - reg = <0>; - spi-max-frequency = <16000000>; - interrupt-parent = <&tlmm>; - qcom,irq-gpio = <&tlmm 43 1>; - }; - }; - - i2c_3: i2c@78b8000 { /* BLSP1 QUP3 */ - status = "disabled"; - }; - - qcom,bg-rsb { - compatible = "qcom,bg-rsb"; - vdd-ldo1-supply = <&pm660_l11>; - qcom,bg-rsb-gpio = <&tlmm 40 1>; - qcom,rsb-use-msm-gpio; - }; - - qcom,bg-daemon { - compatible = "qcom,bg-daemon"; - qcom,bg-reset-gpio = <&pm660_gpios 5 0>; - ssr-reg1-supply = <&pm660_l3>; - ssr-reg2-supply = <&pm660_l9>; - }; -}; - &usb_otg { HSUSB_3p3-supply = <&L16A>; }; diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts index d94565987ac68b8d5d67393c9c07dee0f2e49dee..af981b4574f06ad30bb708e8d24def897ad91ae5 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts +++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp.dts @@ -21,6 +21,6 @@ model = "Qualcomm Technologies, Inc. SDM429 BG WDP"; compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd"; qcom,msm-id = <416 0x0>; - qcom,board-id = <0x01000b 9>; + qcom,board-id = <0x00010b 9>; qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts index 32ae5312d7c4a598933353fe322f49932069963f..d91e3972d3f6732ec9ad1046efe2e7a9da8b13ba 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp-overlay.dts @@ -15,7 +15,7 @@ /plugin/; #include "sdm429-spyro-qrd-evt.dtsi" - +#include "sdm429-bg-soc.dtsi" / { model = "Qualcomm Technologies, Inc. SDM429 QRD BG WTP Overlay"; compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd"; @@ -24,131 +24,13 @@ qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; -&soc { - - qcom,blackghost { - compatible = "qcom,pil-blackghost"; - qcom,pil-force-shutdown; - qcom,firmware-name = "bg-wear"; - /* GPIO inputs from blackghost */ - qcom,bg2ap-status-gpio = <&tlmm 44 0>; - qcom,bg2ap-errfatal-gpio = <&tlmm 72 0>; - /* GPIO output to blackghost */ - qcom,ap2bg-status-gpio = <&tlmm 61 0>; - qcom,ap2bg-errfatal-gpio = <&tlmm 62 0>; - }; - - qcom,msm-ssc-sensors { - compatible = "qcom,msm-ssc-sensors"; - }; - - qcom,glink-bgcom-xprt-bg { - compatible = "qcom,glink-bgcom-xprt"; - label = "bg"; - qcom,qos-config = <&glink_qos_bg>; - qcom,ramp-time = <0x10>, - <0x20>, - <0x30>, - <0x40>; - }; - - glink_qos_bg: qcom,glink-qos-config-bg { - compatible = "qcom,glink-qos-config"; - qcom,flow-info = <0x80 0x0>, - <0x70 0x1>, - <0x60 0x2>, - <0x50 0x3>; - qcom,mtu-size = <0x800>; - qcom,tput-stats-cycle = <0xa>; - }; - - qcom,glink_pkt { - compatible = "qcom,glinkpkt"; - - qcom,glinkpkt-bg-daemon { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon"; - }; - - qcom,glinkpkt-bg-daemon-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "bg-daemon-ctl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon_ctrl"; - }; - - qcom,glinkpkt-bg-display-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl"; - }; - - qcom,glinkpkt-bg-display-data { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "display-data"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data"; - }; - - qcom,glinkpkt-bg-rsb-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "RSB_CTRL"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl"; - }; - - qcom,glinkpkt-bg-sso-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "sso-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_sso_ctrl"; - }; - - qcom,glinkpkt-bg-buzzer-ctrl { - qcom,glinkpkt-transport = "bgcom"; - qcom,glinkpkt-edge = "bg"; - qcom,glinkpkt-ch-name = "buzzer-ctrl"; - qcom,glinkpkt-dev-name = "glink_pkt_bg_buzzer_ctrl"; - }; - }; - - spi_3: spi@78b7000 { /* BLSP1 QUP3*/ - status = "ok"; - qcom,bg-spi { - compatible = "qcom,bg-spi"; - reg = <0>; - spi-max-frequency = <16000000>; - interrupt-parent = <&tlmm>; - qcom,irq-gpio = <&tlmm 43 1>; - }; - }; - - i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */ - status = "disabled"; - }; - - qcom,bg-rsb { - compatible = "qcom,bg-rsb"; - vdd-ldo1-supply = <&pm660_l11>; - qcom,bg-rsb-gpio = <&tlmm 40 1>; - qcom,rsb-use-msm-gpio; - }; - - qcom,bg-daemon { - compatible = "qcom,bg-daemon"; - qcom,bg-reset-gpio = <&pm660_gpios 5 0>; - ssr-reg1-supply = <&pm660_l3>; - ssr-reg2-supply = <&pm660_l9>; - }; -}; - &mdss_dsi0 { qcom,dsi-pref-prim-pan = <&dsi_auo_416p_amoled_cmd>; /delete-property/ vdd-supply; vddio-supply = <&L11A>; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_te_active>; + pinctrl-1 = <&mdss_te_suspend>; qcom,platform-enable-gpio = <&pm660_gpios 12 0>; }; @@ -156,6 +38,36 @@ /delete-node/ qcom,panel-supply-entry@0; }; +&i2c_4 { + status = "ok"; + tsc@24 { + status = "disabled"; + }; + + raydium_ts@39 { + compatible = "raydium,raydium-ts"; + reg = <0x39>; + interrupt-parent = <&tlmm>; + interrupts = <13 0x2008>; + vdd_ana-supply = <&pm660_l11>; + vcc_i2c-supply = <&pm660_l13>; + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + raydium,reset-gpio = <&tlmm 64 0x00>; + raydium,irq-gpio = <&tlmm 65 0x00>; + raydium,num-max-touches = <2>; + raydium,soft-reset-delay-ms = <50>; + raydium,hard-reset-delay-ms = <100>; + raydium,x_max = <416>; + raydium,y_max = <416>; + raydium,display-coords= <0 0 416 416>; + raydium,fw_id = <0x2202>; + }; +}; + &usb_otg { HSUSB_3p3-supply = <&L16A>; }; @@ -177,3 +89,38 @@ }; }; }; + +&msm_gpu { + qcom,initial-pwrlevel = <0>; + qcom,gpu-pwrlevels { + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <2>; + qcom,bus-min = <2>; + qcom,bus-max = <2>; + }; + qcom,gpu-pwrlevel@1{ + reg = <1>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; +}; + +&msm_cpufreq { + qcom,cpufreq-table = + < 960000 >, + < 1305600 >, + < 1497600 >, + < 1708800 >; +}; +&cpubw { + qcom,bw-tbl = + < 1611 /* 211.2 MHz */ >, /*Low SVS*/ + < 2929 /* 384 MHz */ >, /* SVS */ + < 5053 /* 662.4 MHz */ >, /* SVS+ */ + < 5712 /* 748.8 MHz */ >; /* NOM */ +}; diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts index abbbbce04cf10336b25993abc76c3a82eb2dcc8d..12cea266a7a2d9b9414575256477d96f5d4129d3 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts +++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wtp.dts @@ -24,3 +24,16 @@ qcom,board-id = <0x00010b 8>; qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>; }; + +&msm_gpu { + /delete-property/qcom,enable-ca-jump; + /delete-property/qcom,ca-busy-penalty; + /delete-property/qcom,ca-target-pwrlevel; + + qcom,gpu-pwrlevels { + /delete-node/qcom,gpu-pwrlevel@2; + /delete-node/qcom,gpu-pwrlevel@3; + /delete-node/qcom,gpu-pwrlevel@4; + /delete-node/qcom,gpu-pwrlevel@5; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi index cc06f8ab87f8ad017a2cb947ac156ce5d46a30e9..b3b2d2bb60947f12ad6dbe8c8f6f99a5d246d3ed 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi @@ -109,4 +109,5 @@ qcom,mdss-dsi-panel-status-check-mode = "te_signal_check"; qcom,mdss-dsi-power-off-disable; qcom,mdss-dsi-tear-disable; + qcom,mdss-skip-panel-reset; }; diff --git a/arch/arm64/boot/dts/qcom/sdm429-spyro.dtsi b/arch/arm64/boot/dts/qcom/sdm429-spyro.dtsi index 004011c771282e52c0dfd2c9009c76d9006b27fa..d993dc2a73c5fef77d41fd86bd8a38a92f68df76 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-spyro.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-spyro.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019,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 @@ -33,7 +33,7 @@ "/dev/block/platform/soc/7824900.sdhci/by-name/vendor"; type = "ext4"; mnt_flags = "ro,barrier=1,discard"; - fsmgr_flags = "wait"; + fsmgr_flags = "wait,avb"; status = "ok"; }; system { @@ -42,7 +42,7 @@ "/dev/block/platform/soc/7824900.sdhci/by-name/system"; type = "ext4"; mnt_flags = "ro,barrier=1,discard"; - fsmgr_flags = "wait"; + fsmgr_flags = "wait,avb"; status = "ok"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi index 15874ff2e9c142f02e4fed209a299a47db8c84c8..0ea16603ddb80c5cbe959232570060e1b118bc4b 100644 --- a/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 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 @@ -71,11 +71,12 @@ <&incall_music_2_rx>, <&usb_audio_rx>, <&usb_audio_tx>, <&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>, - <&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>, - <&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>, - <&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>, - <&dai_quin_tdm_rx_0>, <&dai_quin_tdm_tx_0>, - <&afe_loopback_tx>; + <&dai_pri_tdm_tx_1>, <&dai_pri_tdm_tx_2>, + <&dai_pri_tdm_tx_3>, <&dai_sec_tdm_rx_0>, + <&dai_sec_tdm_tx_0>, <&dai_tert_tdm_rx_0>, + <&dai_tert_tdm_tx_0>, <&dai_quat_tdm_rx_0>, + <&dai_quat_tdm_tx_0>, <&dai_quin_tdm_rx_0>, + <&dai_quin_tdm_tx_0>, <&afe_loopback_tx>; asoc-cpu-names = "msm-dai-q6-dp.24608", "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -98,11 +99,12 @@ "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770", "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673", "msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865", - "msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881", - "msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897", - "msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913", - "msm-dai-q6-tdm.36928", "msm-dai-q6-tdm.36929", - "msm-dai-q6-dev.24577"; + "msm-dai-q6-tdm.36867", "msm-dai-q6-tdm.36869", + "msm-dai-q6-tdm.36871", "msm-dai-q6-tdm.36880", + "msm-dai-q6-tdm.36881", "msm-dai-q6-tdm.36896", + "msm-dai-q6-tdm.36897", "msm-dai-q6-tdm.36912", + "msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36928", + "msm-dai-q6-tdm.36929", "msm-dai-q6-dev.24577"; }; tasha_snd: sound-tasha { @@ -241,6 +243,40 @@ compatible = "qcom,msm-cpe-lsm"; qcom,msm-cpe-lsm-id = <3>; }; + + pri_tdm_tx: qcom,msm-dai-tdm-pri-tx { + compatible = "qcom,msm-dai-tdm"; + qcom,msm-cpudai-tdm-group-id = <37121>; + qcom,msm-cpudai-tdm-group-num-ports = <4>; + qcom,msm-cpudai-tdm-group-port-id = <36865 36867 36869 36871>; + qcom,msm-cpudai-tdm-clk-rate = <1536000>; + qcom,msm-cpudai-tdm-clk-internal = <1>; + qcom,msm-cpudai-tdm-sync-mode = <1>; + qcom,msm-cpudai-tdm-sync-src = <1>; + qcom,msm-cpudai-tdm-data-out = <0>; + qcom,msm-cpudai-tdm-invert-sync = <1>; + qcom,msm-cpudai-tdm-data-delay = <1>; + dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36865>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + dai_pri_tdm_tx_1: qcom,msm-dai-q6-tdm-pri-tx-1 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36867>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + dai_pri_tdm_tx_2: qcom,msm-dai-q6-tdm-pri-tx-2 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36869>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + dai_pri_tdm_tx_3: qcom,msm-dai-q6-tdm-pri-tx-3 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36871>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + }; }; &slim_aud { diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-svr.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-svr.dtsi index a6535ac8ab1e98919874773cb129361e0dbb6b39..8aaaebb842968ce503e8f95372a5f3f30c5b7f2e 100644 --- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-svr.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-svr.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-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 @@ -402,10 +402,10 @@ }; /* 9282 CCI0 */ - qcom,cam-sensor@2 { - cell-index = <2>; + qcom,cam-sensor@4 { + cell-index = <4>; compatible = "qcom,cam-sensor"; - reg = <0x02>; + reg = <0x04>; csiphy-sd-index = <2>; sensor-position-roll = <270>; sensor-position-pitch = <0>; diff --git a/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi index 948c51d8761cc5b1899aea6793c9793987caf431..670dc4a5ef95848c94fcc976274d28d568d49b04 100644 --- a/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm670-lpi.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-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 @@ -308,5 +308,84 @@ input-enable; }; }; + + quat_mi2s_sck_active: quat_mi2s_sck_active { + mux { + pins = "gpio23"; + function = "func2"; + }; + + config { + pins = "gpio23"; + drive-strength = <2>; /* 2 mA */ + output-low; + }; + }; + + quat_mi2s_sck_sleep: quat_mi2s_sck_sleep { + mux { + pins = "gpio23"; + function = "func2"; + }; + + config { + pins = "gpio23"; + drive-strength = <2>; /* 2 mA */ + pull-down; + }; + }; + + quat_mi2s_ws_active: quat_mi2s_ws_active { + mux { + pins = "gpio24"; + function = "func2"; + }; + + config { + pins = "gpio24"; + drive-strength = <2>; /* 2 mA */ + output-low; + }; + }; + + quat_mi2s_ws_sleep: quat_mi2s_ws_sleep { + mux { + pins = "gpio24"; + function = "func2"; + }; + + config { + pins = "gpio24"; + drive-strength = <2>; /* 2 mA */ + pull-down; + }; + }; + + quat_mi2s_d0_active: quat_mi2s_d0_active { + mux { + pins = "gpio25"; + function = "func2"; + }; + + config { + pins = "gpio25"; + drive-strength = <2>; /* 2 mA */ + bias-disable; + input-enable; + }; + }; + + quat_mi2s_d0_sleep: quat_mi2s_d0_sleep { + mux { + pins = "gpio25"; + function = "func2"; + }; + + config { + pins = "gpio25"; + drive-strength = <2>; /* 2 mA */ + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi b/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi index bc242b0c59235762c3d3df5f15b23f6dd4a33adc..40aceacfc472184c9e2e602799fb82138fe295ba 100644 --- a/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi +++ b/arch/arm64/boot/dts/qcom/sxr1130-svr.dtsi @@ -265,6 +265,19 @@ }; }; + quat_mi2s_gpios: quat_mi2s_pinctrl { + status = "ok"; + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&quat_mi2s_sck_active + &quat_mi2s_ws_active + &quat_mi2s_d0_active>; + pinctrl-1 = <&quat_mi2s_sck_sleep + &quat_mi2s_ws_sleep + &quat_mi2s_d0_sleep>; + qcom,lpi-gpios; + }; + }; @@ -437,7 +450,7 @@ }; &tavil_snd { - qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>; + qcom,msm-mi2s-master = <1>, <1>, <1>, <0>, <1>; qcom,audio-routing = "AIF4 VI", "MCLK", "RX_BIAS", "MCLK", @@ -466,6 +479,8 @@ "MIC BIAS3", "Digital Mic5", "SpkrLeft IN", "SPK1 OUT", "SpkrRight IN", "SPK2 OUT"; + + qcom,quat-mi2s-gpios = <&quat_mi2s_gpios>; qcom,msm-mbhc-hphl-swh = <1>; qcom,msm-mbhc-gnd-swh = <1>; qcom,hph-en0-gpio = <&tavil_hph_en0>; @@ -493,3 +508,13 @@ &pm660_charger { qcom,ufp-only-mode; }; + +&dai_mi2s3 { + qcom,msm-mi2s-rx-lines = <0>; + qcom,msm-mi2s-tx-lines = <1>; + +}; + +&cdc_pdm_gpios { + status = "disabled"; +}; diff --git a/arch/arm64/configs/cuttlefish_defconfig b/arch/arm64/configs/cuttlefish_defconfig index 897c9863f49a3502c73e8b377bfd3664a4824a70..3c5ed7370e8e99482586282b7e12b0c980086524 100644 --- a/arch/arm64/configs/cuttlefish_defconfig +++ b/arch/arm64/configs/cuttlefish_defconfig @@ -48,7 +48,6 @@ CONFIG_PREEMPT=y CONFIG_HZ_100=y # CONFIG_SPARSEMEM_VMEMMAP is not set CONFIG_KSM=y -CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_ZSMALLOC=y CONFIG_SECCOMP=y CONFIG_PARAVIRT=y diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig index 2d3985659aee85adbd04654bfa36a459099541fc..c28587525bbd4e9550dceb4d97484916b645b5af 100755 --- a/arch/arm64/configs/sdm670-perf_defconfig +++ b/arch/arm64/configs/sdm670-perf_defconfig @@ -253,6 +253,9 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_QCOM_XR_SMRTVWR_MISC=y +CONFIG_TUSB1064_XR_MISC=y +CONFIG_VXR200_XR_MISC=y CONFIG_QSEECOM=y CONFIG_UID_SYS_STATS=y CONFIG_MEMORY_STATE_TIME=y diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig index ccfcf65f96080c922e82729b79e8b08b454c4c3f..70b4d60e4766699bb34d0f3365005215df0ed978 100755 --- a/arch/arm64/configs/sdm670_defconfig +++ b/arch/arm64/configs/sdm670_defconfig @@ -262,6 +262,9 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_QCOM_XR_SMRTVWR_MISC=y +CONFIG_TUSB1064_XR_MISC=y +CONFIG_VXR200_XR_MISC=y CONFIG_QSEECOM=y CONFIG_UID_SYS_STATS=y CONFIG_MEMORY_STATE_TIME=y diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index 7e842dcae450935ba9642a7ab31defe385ce5964..3626655175a2e96af5ede5ca064a1bc651f73642 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -29,13 +29,16 @@ typedef void (*alternative_cb_t)(struct alt_instr *alt, void __init apply_alternatives_all(void); void apply_alternatives(void *start, size_t length); -#define ALTINSTR_ENTRY(feature,cb) \ +#define ALTINSTR_ENTRY(feature) \ " .word 661b - .\n" /* label */ \ - " .if " __stringify(cb) " == 0\n" \ " .word 663f - .\n" /* new instruction */ \ - " .else\n" \ + " .hword " __stringify(feature) "\n" /* feature bit */ \ + " .byte 662b-661b\n" /* source len */ \ + " .byte 664f-663f\n" /* replacement len */ + +#define ALTINSTR_ENTRY_CB(feature, cb) \ + " .word 661b - .\n" /* label */ \ " .word " __stringify(cb) "- .\n" /* callback */ \ - " .endif\n" \ " .hword " __stringify(feature) "\n" /* feature bit */ \ " .byte 662b-661b\n" /* source len */ \ " .byte 664f-663f\n" /* replacement len */ @@ -56,15 +59,14 @@ void apply_alternatives(void *start, size_t length); * * Alternatives with callbacks do not generate replacement instructions. */ -#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled, cb) \ +#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \ ".if "__stringify(cfg_enabled)" == 1\n" \ "661:\n\t" \ oldinstr "\n" \ "662:\n" \ ".pushsection .altinstructions,\"a\"\n" \ - ALTINSTR_ENTRY(feature,cb) \ + ALTINSTR_ENTRY(feature) \ ".popsection\n" \ - " .if " __stringify(cb) " == 0\n" \ ".pushsection .altinstr_replacement, \"a\"\n" \ "663:\n\t" \ newinstr "\n" \ @@ -72,17 +74,25 @@ void apply_alternatives(void *start, size_t length); ".popsection\n\t" \ ".org . - (664b-663b) + (662b-661b)\n\t" \ ".org . - (662b-661b) + (664b-663b)\n" \ - ".else\n\t" \ + ".endif\n" + +#define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \ + ".if "__stringify(cfg_enabled)" == 1\n" \ + "661:\n\t" \ + oldinstr "\n" \ + "662:\n" \ + ".pushsection .altinstructions,\"a\"\n" \ + ALTINSTR_ENTRY_CB(feature, cb) \ + ".popsection\n" \ "663:\n\t" \ "664:\n\t" \ - ".endif\n" \ ".endif\n" #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \ - __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg), 0) + __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) #define ALTERNATIVE_CB(oldinstr, cb) \ - __ALTERNATIVE_CFG(oldinstr, "NOT_AN_INSTRUCTION", ARM64_CB_PATCH, 1, cb) + __ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb) #else #include diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 4287acbe25c73fdf50144d84505fdfe2ee95bb92..3ee30c5b6b340da4bc46cdf894936a866be61acf 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -300,6 +300,11 @@ static inline bool __kvm_cpu_uses_extended_idmap(void) return __cpu_uses_extended_idmap(); } +/* + * Can't use pgd_populate here, because the extended idmap adds an extra level + * above CONFIG_PGTABLE_LEVELS (which is 2 or 3 if we're using the extended + * idmap), and pgd_populate is only available if CONFIG_PGTABLE_LEVELS = 4. + */ static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd, pgd_t *hyp_pgd, pgd_t *merged_hyp_pgd, diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index f705d96a76f2e099eb35325fc7026fee12f4234d..5bc3de78306abe83076278051bda713f6d7e4330 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -77,13 +77,12 @@ #define PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) #define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) #define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) -#define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN) #define __P000 PAGE_NONE #define __P001 PAGE_READONLY #define __P010 PAGE_COPY #define __P011 PAGE_COPY -#define __P100 PAGE_EXECONLY +#define __P100 PAGE_READONLY_EXEC #define __P101 PAGE_READONLY_EXEC #define __P110 PAGE_COPY_EXEC #define __P111 PAGE_COPY_EXEC @@ -92,7 +91,7 @@ #define __S001 PAGE_READONLY #define __S010 PAGE_SHARED #define __S011 PAGE_SHARED -#define __S100 PAGE_EXECONLY +#define __S100 PAGE_READONLY_EXEC #define __S101 PAGE_READONLY_EXEC #define __S110 PAGE_SHARED_EXEC #define __S111 PAGE_SHARED_EXEC diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 65d340c5f047b9e1a3831b307a4d7e45e19661b0..d0eeb96c8407e0072ff749531d9f472dae11cf02 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -84,12 +84,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte)) #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) -/* - * Execute-only user mappings do not have the PTE_USER bit set. All valid - * kernel mappings have the PTE_UXN bit set. - */ #define pte_valid_not_user(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == (PTE_VALID | PTE_UXN)) + ((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) \ @@ -105,8 +101,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; /* * p??_access_permitted() is true for valid user mappings (subject to the - * write permission check) other than user execute-only which do not have the - * PTE_USER bit set. PROT_NONE mappings do not have the PTE_VALID bit set. + * write permission check). PROT_NONE mappings do not have the PTE_VALID bit + * set. */ #define pte_access_permitted(pte, write) \ (pte_valid_user(pte) && (!(write) || pte_write(pte))) diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild index 825b0fe51c2b41643dd38e05dd52f4fe2c48707e..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 --- a/arch/arm64/include/uapi/asm/Kbuild +++ b/arch/arm64/include/uapi/asm/Kbuild @@ -2,21 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += kvm_para.h - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += fcntl.h -header-y += hwcap.h -header-y += kvm_para.h -header-y += perf_regs.h -header-y += param.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += stat.h -header-y += statfs.h -header-y += ucontext.h -header-y += unistd.h diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 4f632c41ea00c3e12943269da8b77b36fbe0d695..c8bdc9208bfd530cc89a9340fdc5a6cf08766e19 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -791,6 +791,11 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) { case MIDR_CAVIUM_THUNDERX2: case MIDR_BRCM_VULCAN: + case MIDR_CORTEX_A53: + case MIDR_CORTEX_A55: + case MIDR_CORTEX_A57: + case MIDR_CORTEX_A72: + case MIDR_CORTEX_A73: return false; } diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 0ef0c47fd7cd8fb5b77c9486d3a8527798c7cd7d..464fcccb23bfd19f44cec221e5c4ba83296de705 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -244,8 +244,7 @@ static int create_safe_exec_page(void *src_start, size_t length, } pte = pte_offset_kernel(pmd, dst_addr); - set_pte(pte, __pte(virt_to_phys((void *)dst) | - pgprot_val(PAGE_KERNEL_EXEC))); + set_pte(pte, pfn_pte(virt_to_pfn(dst), PAGE_KERNEL_EXEC)); /* * Load our new page tables. A strict BBM approach requires that we diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c old mode 100644 new mode 100755 index 716a5c2439e83158604a06c34dec67d1e361c295..35e0e6464e62a81b33a0bcdcb3149670224fe65f --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -84,7 +84,8 @@ static void cpu_psci_cpu_die(unsigned int cpu) static int cpu_psci_cpu_kill(unsigned int cpu) { - int err, i; + int err; + unsigned long start, end; if (!psci_ops.affinity_info) return 0; @@ -94,16 +95,18 @@ static int cpu_psci_cpu_kill(unsigned int cpu) * while it is dying. So, try again a few times. */ - for (i = 0; i < 10; i++) { + start = jiffies; + end = start + msecs_to_jiffies(100); + do { err = psci_ops.affinity_info(cpu_logical_map(cpu), 0); if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) { - pr_debug("CPU%d killed.\n", cpu); + pr_debug("CPU%d killed (polled %d ms)\n", cpu, + jiffies_to_msecs(jiffies - start)); return 0; } - msleep(10); - pr_debug("Retrying again to check for CPU kill\n"); - } + usleep_range(100, 1000); + } while (time_before(jiffies, end)); pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n", cpu, err); diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index f0166ee4c17c6dc92888b9176af62186e75c5b36..dd084f3eda32bea4db57f3c7eee5bbf9c3a7aeab 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -327,7 +327,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, struct task_struct *tsk; struct mm_struct *mm; int fault, sig, code; - unsigned long vm_flags = VM_READ | VM_WRITE; + unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC; unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; struct vm_area_struct *vma = NULL; diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c old mode 100644 new mode 100755 index b202a2a2819a4ec228667e61fffbda4dc16c77b4..5889312d0e079166117690b16bcf66ad01c4280f --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -166,8 +166,17 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr, pte = pte_set_fixmap_offset(pmd, addr); do { + pte_t old_pte = *pte; + set_pte(pte, pfn_pte(pfn, prot)); pfn++; + + /* + * After the PTE entry has been populated once, we + * only allow updates to the permission attributes. + */ + BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte))); + } while (pte++, addr += PAGE_SIZE, addr != end); pte_clear_fixmap(); @@ -197,28 +206,29 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, pmd = pmd_set_fixmap_offset(pud, addr); do { + pmd_t old_pmd = *pmd; + next = pmd_addr_end(addr, end); + /* try section mapping first */ if (((addr | next | phys) & ~SECTION_MASK) == 0 && allow_block_mappings && !dma_overlap(phys, phys + next - addr)) { pmd_t old_pmd =*pmd; pmd_set_huge(pmd, phys, prot); + /* - * Check for previous table entries created during - * boot (__create_page_tables) and flush them. + * After the PMD entry has been populated once, we + * only allow updates to the permission attributes. */ - if (!pmd_none(old_pmd)) { - flush_tlb_all(); - if (pmd_table(old_pmd)) { - phys_addr_t table = pmd_page_paddr(old_pmd); - if (!WARN_ON_ONCE(slab_is_available())) - memblock_free(table, PAGE_SIZE); - } - } + BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd), + pmd_val(*pmd))); } else { alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), prot, pgtable_alloc); + + BUG_ON(pmd_val(old_pmd) != 0 && + pmd_val(old_pmd) != pmd_val(*pmd)); } phys += next - addr; } while (pmd++, addr = next, addr != end); @@ -256,6 +266,8 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, pud = pud_set_fixmap_offset(pgd, addr); do { + pud_t old_pud = *pud; + next = pud_addr_end(addr, end); /* @@ -267,23 +279,17 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, pud_set_huge(pud, phys, prot); /* - * If we have an old value for a pud, it will - * be pointing to a pmd table that we no longer - * need (from swapper_pg_dir). - * - * Look up the old pmd table and free it. + * After the PUD entry has been populated once, we + * only allow updates to the permission attributes. */ - if (!pud_none(old_pud)) { - flush_tlb_all(); - if (pud_table(old_pud)) { - phys_addr_t table = pud_page_paddr(old_pud); - if (!WARN_ON_ONCE(slab_is_available())) - memblock_free(table, PAGE_SIZE); - } - } + BUG_ON(!pgattr_change_is_safe(pud_val(old_pud), + pud_val(*pud))); } else { alloc_init_pmd(pud, addr, next, phys, prot, pgtable_alloc, allow_block_mappings); + + BUG_ON(pud_val(old_pud) != 0 && + pud_val(old_pud) != pud_val(*pud)); } phys += next - addr; } while (pud++, addr = next, addr != end); @@ -449,6 +455,9 @@ void mark_rodata_ro(void) section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata; create_mapping_late(__pa_symbol(__start_rodata), (unsigned long)__start_rodata, section_size, PAGE_KERNEL_RO); + + /* flush the TLBs after updating live kernel mappings */ + flush_tlb_all(); } static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end, @@ -532,8 +541,8 @@ static void __init map_kernel(pgd_t *pgd) * entry instead. */ BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES)); - set_pud(pud_set_fixmap_offset(pgd, FIXADDR_START), - __pud(__pa_symbol(bm_pmd) | PUD_TYPE_TABLE)); + pud_populate(&init_mm, pud_set_fixmap_offset(pgd, FIXADDR_START), + lm_alias(bm_pmd)); pud_clear_fixmap(); } else { BUG(); @@ -648,7 +657,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node) if (!p) return -ENOMEM; - set_pmd(pmd, __pmd(__pa(p) | PROT_SECT_NORMAL)); + pmd_set_huge(pmd, __pa(p), __pgprot(PROT_SECT_NORMAL)); } else vmemmap_verify((pte_t *)pmd, node, addr, next); } while (addr = next, addr != end); @@ -840,35 +849,35 @@ int __init arch_ioremap_pmd_supported(void) return !IS_ENABLED(CONFIG_ARM64_PTDUMP_DEBUGFS); } -int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) +int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) { pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); pud_t new_pud = pfn_pud(__phys_to_pfn(phys), sect_prot); /* Only allow permission changes for now */ - if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pud)), + if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), pud_val(new_pud))) return 0; BUG_ON(phys & ~PUD_MASK); - set_pud(pud, new_pud); + set_pud(pudp, new_pud); return 1; } -int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot) +int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) { pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), sect_prot); /* Only allow permission changes for now */ - if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmd)), + if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), pmd_val(new_pmd))) return 0; BUG_ON(phys & ~PMD_MASK); - set_pmd(pmd, new_pmd); + set_pmd(pmdp, new_pmd); return 1; } diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index b41d49046dc20cb6891c91c35b3463e1e349e815..3d81586c21f79ee440511c1e254b35dfcded5d66 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -116,7 +116,11 @@ ENTRY(cpu_do_suspend) mrs x8, mdscr_el1 mrs x9, oslsr_el1 mrs x10, sctlr_el1 +alternative_if_not ARM64_HAS_VIRT_HOST_EXTN mrs x11, tpidr_el1 +alternative_else + mrs x11, tpidr_el2 +alternative_endif mrs x12, sp_el0 stp x2, x3, [x0] stp x4, xzr, [x0, #16] @@ -162,7 +166,11 @@ ENTRY(cpu_do_resume) msr mdscr_el1, x10 msr sctlr_el1, x12 +alternative_if_not ARM64_HAS_VIRT_HOST_EXTN msr tpidr_el1, x13 +alternative_else + msr tpidr_el2, x13 +alternative_endif msr sp_el0, x14 /* * Restore oslsr_el1 by writing oslar_el1 diff --git a/arch/blackfin/include/uapi/asm/Kbuild b/arch/blackfin/include/uapi/asm/Kbuild index 0bd28f77abc35fd0dc47e26e70f3defa90b0341f..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/blackfin/include/uapi/asm/Kbuild +++ b/arch/blackfin/include/uapi/asm/Kbuild @@ -1,19 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += bfin_sport.h -header-y += byteorder.h -header-y += cachectl.h -header-y += fcntl.h -header-y += fixed_code.h -header-y += ioctls.h -header-y += kvm_para.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += stat.h -header-y += swab.h -header-y += unistd.h diff --git a/arch/c6x/include/uapi/asm/Kbuild b/arch/c6x/include/uapi/asm/Kbuild index e9bc2b2b814740d82e9a4fb9eae800a3bbfe5aad..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 --- a/arch/c6x/include/uapi/asm/Kbuild +++ b/arch/c6x/include/uapi/asm/Kbuild @@ -2,11 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += kvm_para.h - -header-y += byteorder.h -header-y += kvm_para.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += swab.h -header-y += unistd.h diff --git a/arch/cris/include/uapi/arch-v10/arch/Kbuild b/arch/cris/include/uapi/arch-v10/arch/Kbuild deleted file mode 100644 index 9048c87a782b51a8e164fecd1791d00b211e2a1c..0000000000000000000000000000000000000000 --- a/arch/cris/include/uapi/arch-v10/arch/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += sv_addr.agh -header-y += sv_addr_ag.h -header-y += svinto.h -header-y += user.h diff --git a/arch/cris/include/uapi/arch-v32/arch/Kbuild b/arch/cris/include/uapi/arch-v32/arch/Kbuild deleted file mode 100644 index 59efffd16b6112979cc92d75ce4b480bafa3c570..0000000000000000000000000000000000000000 --- a/arch/cris/include/uapi/arch-v32/arch/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += cryptocop.h -header-y += user.h diff --git a/arch/cris/include/uapi/asm/Kbuild b/arch/cris/include/uapi/asm/Kbuild index d5564a0ae66adc23b7c42fe31f69ad1f3ac131e6..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/cris/include/uapi/asm/Kbuild +++ b/arch/cris/include/uapi/asm/Kbuild @@ -1,44 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += ../arch-v10/arch/ -header-y += ../arch-v32/arch/ -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += elf.h -header-y += elf_v10.h -header-y += elf_v32.h -header-y += errno.h -header-y += ethernet.h -header-y += etraxgpio.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += ptrace_v10.h -header-y += ptrace_v32.h -header-y += resource.h -header-y += rs485.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += sync_serial.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/frv/include/uapi/asm/Kbuild b/arch/frv/include/uapi/asm/Kbuild index 42a2b33461c042aa867d3392b2a30dfbef98f11a..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/frv/include/uapi/asm/Kbuild +++ b/arch/frv/include/uapi/asm/Kbuild @@ -1,35 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += registers.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/h8300/include/uapi/asm/Kbuild b/arch/h8300/include/uapi/asm/Kbuild index fb6101a5d4f1a5464fa43715475582a07467635c..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/h8300/include/uapi/asm/Kbuild +++ b/arch/h8300/include/uapi/asm/Kbuild @@ -1,30 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += siginfo.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index db8ddabc6bd2819ba579c4c407a569e2232daa51..f3b1ceb5c1e45ec14244c944e1257756ec087dba 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -1,6 +1,3 @@ - -header-y += ucontext.h - generic-y += auxvec.h generic-y += barrier.h generic-y += bug.h diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h index a62ba368b27d1ddf6f750efd1dcaa2b51419d1d8..1ae06190b68fc41e3b4554e3e8eab763761a0ef3 100644 --- a/arch/hexagon/include/asm/atomic.h +++ b/arch/hexagon/include/asm/atomic.h @@ -103,7 +103,7 @@ static inline void atomic_##op(int i, atomic_t *v) \ "1: %0 = memw_locked(%1);\n" \ " %0 = "#op "(%0,%2);\n" \ " memw_locked(%1,P3)=%0;\n" \ - " if !P3 jump 1b;\n" \ + " if (!P3) jump 1b;\n" \ : "=&r" (output) \ : "r" (&v->counter), "r" (i) \ : "memory", "p3" \ @@ -119,7 +119,7 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ "1: %0 = memw_locked(%1);\n" \ " %0 = "#op "(%0,%2);\n" \ " memw_locked(%1,P3)=%0;\n" \ - " if !P3 jump 1b;\n" \ + " if (!P3) jump 1b;\n" \ : "=&r" (output) \ : "r" (&v->counter), "r" (i) \ : "memory", "p3" \ @@ -136,7 +136,7 @@ static inline int atomic_fetch_##op(int i, atomic_t *v) \ "1: %0 = memw_locked(%2);\n" \ " %1 = "#op "(%0,%3);\n" \ " memw_locked(%2,P3)=%1;\n" \ - " if !P3 jump 1b;\n" \ + " if (!P3) jump 1b;\n" \ : "=&r" (output), "=&r" (val) \ : "r" (&v->counter), "r" (i) \ : "memory", "p3" \ @@ -185,7 +185,7 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) " }" " memw_locked(%2, p3) = %1;" " {" - " if !p3 jump 1b;" + " if (!p3) jump 1b;" " }" "2:" : "=&r" (__oldval), "=&r" (tmp) diff --git a/arch/hexagon/include/asm/bitops.h b/arch/hexagon/include/asm/bitops.h index 2691a1857d203db2522ae178fe744225c71d2da9..634306cda00675b0b172e87ad6162f6bf23df722 100644 --- a/arch/hexagon/include/asm/bitops.h +++ b/arch/hexagon/include/asm/bitops.h @@ -52,7 +52,7 @@ static inline int test_and_clear_bit(int nr, volatile void *addr) "1: R12 = memw_locked(R10);\n" " { P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n" " memw_locked(R10,P1) = R12;\n" - " {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n" + " {if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n" : "=&r" (oldval) : "r" (addr), "r" (nr) : "r10", "r11", "r12", "p0", "p1", "memory" @@ -76,7 +76,7 @@ static inline int test_and_set_bit(int nr, volatile void *addr) "1: R12 = memw_locked(R10);\n" " { P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n" " memw_locked(R10,P1) = R12;\n" - " {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n" + " {if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n" : "=&r" (oldval) : "r" (addr), "r" (nr) : "r10", "r11", "r12", "p0", "p1", "memory" @@ -102,7 +102,7 @@ static inline int test_and_change_bit(int nr, volatile void *addr) "1: R12 = memw_locked(R10);\n" " { P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n" " memw_locked(R10,P1) = R12;\n" - " {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n" + " {if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n" : "=&r" (oldval) : "r" (addr), "r" (nr) : "r10", "r11", "r12", "p0", "p1", "memory" @@ -237,7 +237,7 @@ static inline int ffs(int x) int r; asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n" - "{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n" + "{ if (P0) %0 = #0; if (!P0) %0 = add(%0,#1);}\n" : "=&r" (r) : "r" (x) : "p0"); diff --git a/arch/hexagon/include/asm/cmpxchg.h b/arch/hexagon/include/asm/cmpxchg.h index a6e34e2acbbaf6cc07f377db35faa7c744ba23e3..db258424059f4f5ab5257d928bd39e4071fe4a03 100644 --- a/arch/hexagon/include/asm/cmpxchg.h +++ b/arch/hexagon/include/asm/cmpxchg.h @@ -44,7 +44,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, __asm__ __volatile__ ( "1: %0 = memw_locked(%1);\n" /* load into retval */ " memw_locked(%1,P0) = %2;\n" /* store into memory */ - " if !P0 jump 1b;\n" + " if (!P0) jump 1b;\n" : "=&r" (retval) : "r" (ptr), "r" (x) : "memory", "p0" diff --git a/arch/hexagon/include/asm/futex.h b/arch/hexagon/include/asm/futex.h index c607b77c8215d2995e2f30f1df5bcf497bd1e65b..12bd92f3ea4145728ad61670a2193b815d937260 100644 --- a/arch/hexagon/include/asm/futex.h +++ b/arch/hexagon/include/asm/futex.h @@ -15,7 +15,7 @@ /* For example: %1 = %4 */ \ insn \ "2: memw_locked(%3,p2) = %1;\n" \ - " if !p2 jump 1b;\n" \ + " if (!p2) jump 1b;\n" \ " %1 = #0;\n" \ "3:\n" \ ".section .fixup,\"ax\"\n" \ @@ -83,10 +83,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, "1: %1 = memw_locked(%3)\n" " {\n" " p2 = cmp.eq(%1,%4)\n" - " if !p2.new jump:NT 3f\n" + " if (!p2.new) jump:NT 3f\n" " }\n" "2: memw_locked(%3,p2) = %5\n" - " if !p2 jump 1b\n" + " if (!p2) jump 1b\n" "3:\n" ".section .fixup,\"ax\"\n" "4: %0 = #%6\n" diff --git a/arch/hexagon/include/asm/spinlock.h b/arch/hexagon/include/asm/spinlock.h index a1c55788c5d6591eac4786b2dc0fcdd3164eb65c..f61bb3185305c21063f47f6c6fa6fabb8988da9c 100644 --- a/arch/hexagon/include/asm/spinlock.h +++ b/arch/hexagon/include/asm/spinlock.h @@ -44,9 +44,9 @@ static inline void arch_read_lock(arch_rwlock_t *lock) __asm__ __volatile__( "1: R6 = memw_locked(%0);\n" " { P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n" - " { if !P3 jump 1b; }\n" + " { if (!P3) jump 1b; }\n" " memw_locked(%0,P3) = R6;\n" - " { if !P3 jump 1b; }\n" + " { if (!P3) jump 1b; }\n" : : "r" (&lock->lock) : "memory", "r6", "p3" @@ -60,7 +60,7 @@ static inline void arch_read_unlock(arch_rwlock_t *lock) "1: R6 = memw_locked(%0);\n" " R6 = add(R6,#-1);\n" " memw_locked(%0,P3) = R6\n" - " if !P3 jump 1b;\n" + " if (!P3) jump 1b;\n" : : "r" (&lock->lock) : "memory", "r6", "p3" @@ -75,7 +75,7 @@ static inline int arch_read_trylock(arch_rwlock_t *lock) __asm__ __volatile__( " R6 = memw_locked(%1);\n" " { %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n" - " { if !P3 jump 1f; }\n" + " { if (!P3) jump 1f; }\n" " memw_locked(%1,P3) = R6;\n" " { %0 = P3 }\n" "1:\n" @@ -102,9 +102,9 @@ static inline void arch_write_lock(arch_rwlock_t *lock) __asm__ __volatile__( "1: R6 = memw_locked(%0)\n" " { P3 = cmp.eq(R6,#0); R6 = #-1;}\n" - " { if !P3 jump 1b; }\n" + " { if (!P3) jump 1b; }\n" " memw_locked(%0,P3) = R6;\n" - " { if !P3 jump 1b; }\n" + " { if (!P3) jump 1b; }\n" : : "r" (&lock->lock) : "memory", "r6", "p3" @@ -118,7 +118,7 @@ static inline int arch_write_trylock(arch_rwlock_t *lock) __asm__ __volatile__( " R6 = memw_locked(%1)\n" " { %0 = #0; P3 = cmp.eq(R6,#0); R6 = #-1;}\n" - " { if !P3 jump 1f; }\n" + " { if (!P3) jump 1f; }\n" " memw_locked(%1,P3) = R6;\n" " %0 = P3;\n" "1:\n" @@ -141,9 +141,9 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) __asm__ __volatile__( "1: R6 = memw_locked(%0);\n" " P3 = cmp.eq(R6,#0);\n" - " { if !P3 jump 1b; R6 = #1; }\n" + " { if (!P3) jump 1b; R6 = #1; }\n" " memw_locked(%0,P3) = R6;\n" - " { if !P3 jump 1b; }\n" + " { if (!P3) jump 1b; }\n" : : "r" (&lock->lock) : "memory", "r6", "p3" @@ -163,7 +163,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock) __asm__ __volatile__( " R6 = memw_locked(%1);\n" " P3 = cmp.eq(R6,#0);\n" - " { if !P3 jump 1f; R6 = #1; %0 = #0; }\n" + " { if (!P3) jump 1f; R6 = #1; %0 = #0; }\n" " memw_locked(%1,P3) = R6;\n" " %0 = P3;\n" "1:\n" diff --git a/arch/hexagon/include/uapi/asm/Kbuild b/arch/hexagon/include/uapi/asm/Kbuild index c31706c38631b75779b0f472667d5f01fe2c0936..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/hexagon/include/uapi/asm/Kbuild +++ b/arch/hexagon/include/uapi/asm/Kbuild @@ -1,15 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += bitsperlong.h -header-y += byteorder.h -header-y += kvm_para.h -header-y += param.h -header-y += ptrace.h -header-y += registers.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += swab.h -header-y += unistd.h -header-y += user.h diff --git a/arch/hexagon/kernel/stacktrace.c b/arch/hexagon/kernel/stacktrace.c index f94918b449a8aa4258a5f04cc98c7b42b1b27fda..03a0e10ecdcc3d8eba647bde5b7da73b7cbe062f 100644 --- a/arch/hexagon/kernel/stacktrace.c +++ b/arch/hexagon/kernel/stacktrace.c @@ -23,8 +23,6 @@ #include #include -register unsigned long current_frame_pointer asm("r30"); - struct stackframe { unsigned long fp; unsigned long rets; @@ -42,7 +40,7 @@ void save_stack_trace(struct stack_trace *trace) low = (unsigned long)task_stack_page(current); high = low + THREAD_SIZE; - fp = current_frame_pointer; + fp = (unsigned long)__builtin_frame_address(0); while (fp >= low && fp <= (high - sizeof(*frame))) { frame = (struct stackframe *)fp; diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S index 67c6ccc14770320c21f334b16c13e1c480a99cd7..9f4a73ff720300dd3641e65df84ecb9d501a16fe 100644 --- a/arch/hexagon/kernel/vm_entry.S +++ b/arch/hexagon/kernel/vm_entry.S @@ -382,7 +382,7 @@ ret_from_fork: R26.L = #LO(do_work_pending); R0 = #VM_INT_DISABLE; } - if P0 jump check_work_pending + if (P0) jump check_work_pending { R0 = R25; callr R24 diff --git a/arch/ia64/include/uapi/asm/Kbuild b/arch/ia64/include/uapi/asm/Kbuild index 891002bbb995beefd85a66001fa58999e9da1b26..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 --- a/arch/ia64/include/uapi/asm/Kbuild +++ b/arch/ia64/include/uapi/asm/Kbuild @@ -2,48 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += kvm_para.h - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += break.h -header-y += byteorder.h -header-y += cmpxchg.h -header-y += errno.h -header-y += fcntl.h -header-y += fpu.h -header-y += gcc_intrin.h -header-y += ia64regs.h -header-y += intel_intrin.h -header-y += intrinsics.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += perfmon.h -header-y += perfmon_default_smpl.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += ptrace_offsets.h -header-y += resource.h -header-y += rse.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h -header-y += ustack.h diff --git a/arch/m32r/include/uapi/asm/Kbuild b/arch/m32r/include/uapi/asm/Kbuild index 43937a61d6cf97c58bc46aa2470561390d351ca2..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/m32r/include/uapi/asm/Kbuild +++ b/arch/m32r/include/uapi/asm/Kbuild @@ -1,33 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 2081b8cd5591c6d77385de8594e737c9d421f7be..b9aee983e6f4cda91fcc709abb85471d2f5f4b63 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -88,10 +88,19 @@ static irqreturn_t cia_handler(int irq, void *dev_id) struct ciabase *base = dev_id; int mach_irq; unsigned char ints; + unsigned long flags; + /* Interrupts get disabled while the timer irq flag is cleared and + * the timer interrupt serviced. + */ mach_irq = base->cia_irq; + local_irq_save(flags); ints = cia_set_irq(base, CIA_ICR_ALL); amiga_custom.intreq = base->int_mask; + if (ints & 1) + generic_handle_irq(mach_irq); + local_irq_restore(flags); + mach_irq++, ints >>= 1; for (; ints; mach_irq++, ints >>= 1) { if (ints & 1) generic_handle_irq(mach_irq); diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 3d2b63bedf0589c67cdf0471007157bb913f18ac..56f02ea2c248d844e43fb88a4e3742315d741400 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -142,7 +142,7 @@ struct mfptimerbase { .name = "MFP Timer D" }; -static irqreturn_t mfptimer_handler(int irq, void *dev_id) +static irqreturn_t mfp_timer_d_handler(int irq, void *dev_id) { struct mfptimerbase *base = dev_id; int mach_irq; @@ -344,7 +344,7 @@ void __init atari_init_IRQ(void) st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 0xf0) | 0x6; /* request timer D dispatch handler */ - if (request_irq(IRQ_MFP_TIMD, mfptimer_handler, IRQF_SHARED, + if (request_irq(IRQ_MFP_TIMD, mfp_timer_d_handler, IRQF_SHARED, stmfp_base.name, &stmfp_base)) pr_err("Couldn't register %s interrupt\n", stmfp_base.name); diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c index c549b48174ec8342620816d846ea7d492f36d0b1..972181c1fe4b77c64e4bfe0ae5e0bea2737bc846 100644 --- a/arch/m68k/atari/time.c +++ b/arch/m68k/atari/time.c @@ -24,6 +24,18 @@ DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL_GPL(rtc_lock); +static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id) +{ + irq_handler_t timer_routine = dev_id; + unsigned long flags; + + local_irq_save(flags); + timer_routine(0, NULL); + local_irq_restore(flags); + + return IRQ_HANDLED; +} + void __init atari_sched_init(irq_handler_t timer_routine) { @@ -32,7 +44,8 @@ atari_sched_init(irq_handler_t timer_routine) /* start timer C, div = 1:100 */ st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60; /* install interrupt service routine for MFP Timer C */ - if (request_irq(IRQ_MFP_TIMC, timer_routine, 0, "timer", timer_routine)) + if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, 0, "timer", + timer_routine)) pr_err("Couldn't register timer interrupt\n"); } diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 611d4d9ea2bd80aca5cdbf8425fcdbe4c2e8f67b..3978d71d250b4d26131d1dbb4760a65caba5b5da 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -45,11 +45,6 @@ extern int bvme6000_set_clock_mmss (unsigned long); extern void bvme6000_reset (void); void bvme6000_set_vectors (void); -/* Save tick handler routine pointer, will point to xtime_update() in - * kernel/timer/timekeeping.c, called via bvme6000_process_int() */ - -static irq_handler_t tick_handler; - int __init bvme6000_parse_bootinfo(const struct bi_record *bi) { @@ -159,12 +154,18 @@ irqreturn_t bvme6000_abort_int (int irq, void *dev_id) static irqreturn_t bvme6000_timer_int (int irq, void *dev_id) { + irq_handler_t timer_routine = dev_id; + unsigned long flags; volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; - unsigned char msr = rtc->msr & 0xc0; + unsigned char msr; + local_irq_save(flags); + msr = rtc->msr & 0xc0; rtc->msr = msr | 0x20; /* Ack the interrupt */ + timer_routine(0, NULL); + local_irq_restore(flags); - return tick_handler(irq, dev_id); + return IRQ_HANDLED; } /* @@ -183,9 +184,8 @@ void bvme6000_sched_init (irq_handler_t timer_routine) rtc->msr = 0; /* Ensure timer registers accessible */ - tick_handler = timer_routine; - if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, - "timer", bvme6000_timer_int)) + if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, "timer", + timer_routine)) panic ("Couldn't register timer int"); rtc->t1cr_omr = 0x04; /* Mode 2, ext clk */ diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index 749543b425a4b2c6b547485af5fe55c02583f933..03c83b8f903281a996d2fb7423603317b2fa1d30 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c @@ -37,13 +37,19 @@ static irqreturn_t hp300_tick(int irq, void *dev_id) { + irq_handler_t timer_routine = dev_id; + unsigned long flags; unsigned long tmp; - irq_handler_t vector = dev_id; + + local_irq_save(flags); in_8(CLOCKBASE + CLKSR); asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE)); + timer_routine(0, NULL); + local_irq_restore(flags); + /* Turn off the network and SCSI leds */ blinken_leds(0, 0xe0); - return vector(irq, NULL); + return IRQ_HANDLED; } u32 hp300_gettimeoffset(void) diff --git a/arch/m68k/include/uapi/asm/Kbuild b/arch/m68k/include/uapi/asm/Kbuild index 6a2d257bdfb2224492f8f901575d17cc9b4f82d7..64368077235aa9f2234cfee5e99df6995c83eed7 100644 --- a/arch/m68k/include/uapi/asm/Kbuild +++ b/arch/m68k/include/uapi/asm/Kbuild @@ -9,27 +9,3 @@ generic-y += socket.h generic-y += sockios.h generic-y += termbits.h generic-y += termios.h - -header-y += a.out.h -header-y += bootinfo.h -header-y += bootinfo-amiga.h -header-y += bootinfo-apollo.h -header-y += bootinfo-atari.h -header-y += bootinfo-hp300.h -header-y += bootinfo-mac.h -header-y += bootinfo-q40.h -header-y += bootinfo-vme.h -header-y += byteorder.h -header-y += cachectl.h -header-y += fcntl.h -header-y += ioctls.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += stat.h -header-y += swab.h -header-y += unistd.h diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 920ff63d4a81d77af96849d3e7c7f802da8be4a7..a435aced6e43906c34e9ac502f6ec0f1194bb9c2 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -53,16 +53,6 @@ static __u8 rbv_clear; static int gIER,gIFR,gBufA,gBufB; -/* - * Timer defs. - */ - -#define TICK_SIZE 10000 -#define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */ -#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) -#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) - - /* * On Macs with a genuine VIA chip there is no way to mask an individual slot * interrupt. This limitation also seems to apply to VIA clone logic cores in @@ -277,22 +267,6 @@ void __init via_init(void) } } -/* - * Start the 100 Hz clock - */ - -void __init via_init_clock(irq_handler_t func) -{ - via1[vACR] |= 0x40; - via1[vT1LL] = MAC_CLOCK_LOW; - via1[vT1LH] = MAC_CLOCK_HIGH; - via1[vT1CL] = MAC_CLOCK_LOW; - via1[vT1CH] = MAC_CLOCK_HIGH; - - if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func)) - pr_err("Couldn't register %s interrupt\n", "timer"); -} - /* * Debugging dump, used in various places to see what's going on. */ @@ -320,29 +294,6 @@ void via_debug_dump(void) } } -/* - * This is always executed with interrupts disabled. - * - * TBI: get time offset between scheduling timer ticks - */ - -u32 mac_gettimeoffset(void) -{ - unsigned long ticks, offset = 0; - - /* read VIA1 timer 2 current value */ - ticks = via1[vT1CL] | (via1[vT1CH] << 8); - /* The probability of underflow is less than 2% */ - if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50) - /* Check for pending timer interrupt in VIA1 IFR */ - if (via1[vIFR] & 0x40) offset = TICK_SIZE; - - ticks = MAC_CLOCK_TICK - ticks; - ticks = ticks * 10000L / MAC_CLOCK_TICK; - - return (ticks + offset) * 1000; -} - /* * Flush the L2 cache on Macs that have it by flipping * the system into 24-bit mode for an instant. @@ -446,6 +397,8 @@ void via_nubus_irq_shutdown(int irq) * via6522.c :-), disable/pending masks added. */ +#define VIA_TIMER_1_INT BIT(6) + void via1_irq(struct irq_desc *desc) { int irq_num; @@ -455,6 +408,21 @@ void via1_irq(struct irq_desc *desc) if (!events) return; + irq_num = IRQ_MAC_TIMER_1; + irq_bit = VIA_TIMER_1_INT; + if (events & irq_bit) { + unsigned long flags; + + local_irq_save(flags); + via1[vIFR] = irq_bit; + generic_handle_irq(irq_num); + local_irq_restore(flags); + + events &= ~irq_bit; + if (!events) + return; + } + irq_num = VIA1_SOURCE_BASE; irq_bit = 1; do { @@ -619,3 +587,56 @@ int via2_scsi_drq_pending(void) return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ)); } EXPORT_SYMBOL(via2_scsi_drq_pending); + +/* timer and clock source */ + +#define VIA_CLOCK_FREQ 783360 /* VIA "phase 2" clock in Hz */ +#define VIA_TIMER_INTERVAL (1000000 / HZ) /* microseconds per jiffy */ +#define VIA_TIMER_CYCLES (VIA_CLOCK_FREQ / HZ) /* clock cycles per jiffy */ + +#define VIA_TC (VIA_TIMER_CYCLES - 2) /* including 0 and -1 */ +#define VIA_TC_LOW (VIA_TC & 0xFF) +#define VIA_TC_HIGH (VIA_TC >> 8) + +void __init via_init_clock(irq_handler_t timer_routine) +{ + if (request_irq(IRQ_MAC_TIMER_1, timer_routine, 0, "timer", NULL)) { + pr_err("Couldn't register %s interrupt\n", "timer"); + return; + } + + via1[vT1LL] = VIA_TC_LOW; + via1[vT1LH] = VIA_TC_HIGH; + via1[vT1CL] = VIA_TC_LOW; + via1[vT1CH] = VIA_TC_HIGH; + via1[vACR] |= 0x40; +} + +u32 mac_gettimeoffset(void) +{ + unsigned long flags; + u8 count_high; + u16 count, offset = 0; + + /* + * Timer counter wrap-around is detected with the timer interrupt flag + * but reading the counter low byte (vT1CL) would reset the flag. + * Also, accessing both counter registers is essentially a data race. + * These problems are avoided by ignoring the low byte. Clock accuracy + * is 256 times worse (error can reach 0.327 ms) but CPU overhead is + * reduced by avoiding slow VIA register accesses. + */ + + local_irq_save(flags); + count_high = via1[vT1CH]; + if (count_high == 0xFF) + count_high = 0; + if (count_high > 0 && (via1[vIFR] & VIA_TIMER_1_INT)) + offset = VIA_TIMER_CYCLES; + local_irq_restore(flags); + + count = count_high << 8; + count = VIA_TIMER_CYCLES - count + offset; + + return ((count * VIA_TIMER_INTERVAL) / VIA_TIMER_CYCLES) * 1000; +} diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index c11d38dfad08faa12881276e0f41b1b7473d0dec..1a095443790b9521ff6a120f50dcc217e663347a 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -46,11 +46,6 @@ extern void mvme147_reset (void); static int bcd2int (unsigned char b); -/* Save tick handler routine pointer, will point to xtime_update() in - * kernel/time/timekeeping.c, called via mvme147_process_int() */ - -irq_handler_t tick_handler; - int __init mvme147_parse_bootinfo(const struct bi_record *bi) { @@ -106,16 +101,23 @@ void __init config_mvme147(void) static irqreturn_t mvme147_timer_int (int irq, void *dev_id) { + irq_handler_t timer_routine = dev_id; + unsigned long flags; + + local_irq_save(flags); m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; - return tick_handler(irq, dev_id); + timer_routine(0, NULL); + local_irq_restore(flags); + + return IRQ_HANDLED; } void mvme147_sched_init (irq_handler_t timer_routine) { - tick_handler = timer_routine; - if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL)) + if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", + timer_routine)) pr_err("Couldn't register timer interrupt\n"); /* Init the clock with a value */ diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 58e240939d265f69abd5c8c578587178f0f0f27d..ac49fa7ec46b4831362339850fdabc743e2473c2 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -51,11 +51,6 @@ extern void mvme16x_reset (void); int bcd2int (unsigned char b); -/* Save tick handler routine pointer, will point to xtime_update() in - * kernel/time/timekeeping.c, called via mvme16x_process_int() */ - -static irq_handler_t tick_handler; - unsigned short mvme16x_config; EXPORT_SYMBOL(mvme16x_config); @@ -354,8 +349,15 @@ static irqreturn_t mvme16x_abort_int (int irq, void *dev_id) static irqreturn_t mvme16x_timer_int (int irq, void *dev_id) { - *(volatile unsigned char *)0xfff4201b |= 8; - return tick_handler(irq, dev_id); + irq_handler_t timer_routine = dev_id; + unsigned long flags; + + local_irq_save(flags); + *(volatile unsigned char *)0xfff4201b |= 8; + timer_routine(0, NULL); + local_irq_restore(flags); + + return IRQ_HANDLED; } void mvme16x_sched_init (irq_handler_t timer_routine) @@ -363,14 +365,13 @@ void mvme16x_sched_init (irq_handler_t timer_routine) uint16_t brdno = be16_to_cpu(mvme_bdid.brdno); int irq; - tick_handler = timer_routine; /* Using PCCchip2 or MC2 chip tick timer 1 */ *(volatile unsigned long *)0xfff42008 = 0; *(volatile unsigned long *)0xfff42004 = 10000; /* 10ms */ *(volatile unsigned char *)0xfff42017 |= 3; *(volatile unsigned char *)0xfff4201b = 0x16; - if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, - "timer", mvme16x_timer_int)) + if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, "timer", + timer_routine)) panic ("Couldn't register timer int"); if (brdno == 0x0162 || brdno == 0x172) diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index 513f9bb17b9cffe6a667b3becf25471993d0b6e5..60b51f5b9cfc0e50230f48b68bfca4eca989abe5 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -126,10 +126,10 @@ void q40_mksound(unsigned int hz, unsigned int ticks) sound_ticks = ticks << 1; } -static irq_handler_t q40_timer_routine; - -static irqreturn_t q40_timer_int (int irq, void * dev) +static irqreturn_t q40_timer_int(int irq, void *dev_id) { + irq_handler_t timer_routine = dev_id; + ql_ticks = ql_ticks ? 0 : 1; if (sound_ticks) { unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; @@ -138,8 +138,13 @@ static irqreturn_t q40_timer_int (int irq, void * dev) *DAC_RIGHT=sval; } - if (!ql_ticks) - q40_timer_routine(irq, dev); + if (!ql_ticks) { + unsigned long flags; + + local_irq_save(flags); + timer_routine(0, NULL); + local_irq_restore(flags); + } return IRQ_HANDLED; } @@ -147,11 +152,9 @@ void q40_sched_init (irq_handler_t timer_routine) { int timer_irq; - q40_timer_routine = timer_routine; timer_irq = Q40_IRQ_FRAME; - if (request_irq(timer_irq, q40_timer_int, 0, - "timer", q40_timer_int)) + if (request_irq(timer_irq, q40_timer_int, 0, "timer", timer_routine)) panic("Couldn't register timer int"); master_outb(-1, FRAME_CLEAR_REG); diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 6bbca30c91884850e45cc07db24b4b17a00b06e5..a5824abb4a39c2f75a42d3ae8a8a93ee038da465 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -61,8 +61,10 @@ static irqreturn_t sun3_int7(int irq, void *dev_id) static irqreturn_t sun3_int5(int irq, void *dev_id) { + unsigned long flags; unsigned int cnt; + local_irq_save(flags); #ifdef CONFIG_SUN3 intersil_clear(); #endif @@ -76,6 +78,7 @@ static irqreturn_t sun3_int5(int irq, void *dev_id) cnt = kstat_irqs_cpu(irq, 0); if (!(cnt % 20)) sun3_leds(led_pattern[cnt % 160 / 20]); + local_irq_restore(flags); return IRQ_HANDLED; } diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c index 431d3c4306dd8da594f485dbb297830dc7f0293d..a4f6a44d34189ddaf8327bf078c4dd1d91b479a9 100644 --- a/arch/m68k/sun3x/time.c +++ b/arch/m68k/sun3x/time.c @@ -77,15 +77,19 @@ u32 sun3x_gettimeoffset(void) } #if 0 -static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sun3x_timer_tick(int irq, void *dev_id) { - void (*vector)(int, void *, struct pt_regs *) = dev_id; + irq_handler_t timer_routine = dev_id; + unsigned long flags; - /* Clear the pending interrupt - pulse the enable line low */ - disable_irq(5); - enable_irq(5); + local_irq_save(flags); + /* Clear the pending interrupt - pulse the enable line low */ + disable_irq(5); + enable_irq(5); + timer_routine(0, NULL); + local_irq_restore(flags); - vector(irq, NULL, regs); + return IRQ_HANDLED; } #endif diff --git a/arch/metag/include/uapi/asm/Kbuild b/arch/metag/include/uapi/asm/Kbuild index ab78be2b6eb0503f939cc85409d532a3b037b491..b29731ebd7a93b3bd51d42565ccc2b727d0963c2 100644 --- a/arch/metag/include/uapi/asm/Kbuild +++ b/arch/metag/include/uapi/asm/Kbuild @@ -1,14 +1,6 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += byteorder.h -header-y += ech.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += swab.h -header-y += unistd.h - generic-y += mman.h generic-y += resource.h generic-y += setup.h diff --git a/arch/microblaze/include/uapi/asm/Kbuild b/arch/microblaze/include/uapi/asm/Kbuild index 1aac99f87df15841b93241f6bfad81733250b183..2178c78c7c1a6336d4a11c9619de521519245c0e 100644 --- a/arch/microblaze/include/uapi/asm/Kbuild +++ b/arch/microblaze/include/uapi/asm/Kbuild @@ -2,35 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += types.h - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += elf.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += unistd.h diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 0bde47e4fa694264256c1e8d2498436acc66320b..dcba53803fa5f9867eba2a0178c48ee5ed924c20 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -92,7 +92,8 @@ static inline void __disable_dcache_nomsr(void) #define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \ do { \ int align = ~(cache_line_length - 1); \ - end = min(start + cache_size, end); \ + if (start < UINT_MAX - cache_size) \ + end = min(start + cache_size, end); \ start &= align; \ } while (0) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 92bcde046b6b462cd45542fc356ede3a93281d02..f8a529c8527950c0ff4724cf6d4da8db1749db69 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -804,6 +804,7 @@ config SIBYTE_LITTLESUR select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_LITTLE_ENDIAN + select ZONE_DMA32 if 64BIT config SIBYTE_SENTOSA bool "Sibyte BCM91250E-Sentosa" diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index ad31c76c7a296558c30cdeb4bea0a65ab7284170..2f77e250b91d7c68db8a2be9032fe6ddad454812 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -29,6 +29,9 @@ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \ -DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS) +# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. +KCOV_INSTRUMENT := n + # decompressor objects (linked with vmlinuz) vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o diff --git a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c index 8241fc6aa17d8668c21373febf27960e8b495e57..3839feba68f2043c99ad4ed46a24698e7ec5780f 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c +++ b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c @@ -266,7 +266,7 @@ int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id) } else { union cvmx_pko_mem_debug8 debug8; debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); - return debug8.cn58xx.doorbell; + return debug8.cn50xx.doorbell; } case CVMX_CMD_QUEUE_ZIP: case CVMX_CMD_QUEUE_DFA: diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 1ba6bcf9857026c71b10090b35d1bfef64b72c99..2ecc8d1b0539530f63c63626209e5dbafd6fcabb 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -502,7 +502,7 @@ static void __init octeon_fdt_set_phy(int eth, int phy_addr) if (phy_addr >= 256 && alt_phy > 0) { const struct fdt_property *phy_prop; struct fdt_property *alt_prop; - u32 phy_handle_name; + fdt32_t phy_handle_name; /* Use the alt phy node instead.*/ phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL); diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 06049b6b3dddb74616c8f506564a449605a50a5d..5dfae80264b9bbc0e14155c048054330f5de35a1 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -60,21 +60,11 @@ * instruction, so the lower 16 bits must be zero. Should be true on * on any sane architecture; generic code does not use this assumption. */ -extern const unsigned long mips_io_port_base; +extern unsigned long mips_io_port_base; -/* - * Gcc will generate code to load the value of mips_io_port_base after each - * function call which may be fairly wasteful in some cases. So we don't - * play quite by the book. We tell gcc mips_io_port_base is a long variable - * which solves the code generation issue. Now we need to violate the - * aliasing rules a little to make initialization possible and finally we - * will need the barrier() to fight side effects of the aliasing chat. - * This trickery will eventually collapse under gcc's optimizer. Oh well. - */ static inline void set_io_port_base(unsigned long base) { - * (unsigned long *) &mips_io_port_base = base; - barrier(); + mips_io_port_base = base; } /* diff --git a/arch/mips/include/asm/octeon/cvmx-pko.h b/arch/mips/include/asm/octeon/cvmx-pko.h index 5f47f76ed510a53dd760bedf911d3d1414d8a4de..20eb9c46a75ab18dbb2fec8b0a67d7dfb1af7300 100644 --- a/arch/mips/include/asm/octeon/cvmx-pko.h +++ b/arch/mips/include/asm/octeon/cvmx-pko.h @@ -611,7 +611,7 @@ static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear, pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num); cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); - status->doorbell = debug8.cn58xx.doorbell; + status->doorbell = debug8.cn50xx.doorbell; } } diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index e309d8fcb5167b40abdca4f07c82d5d97665d1bc..da1cb0499d6c6eabcb279e12b04ee4f415f99d08 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -52,8 +52,26 @@ struct thread_info { #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) -/* How to get the thread information struct from C. */ +/* + * A pointer to the struct thread_info for the currently executing thread is + * held in register $28/$gp. + * + * We declare __current_thread_info as a global register variable rather than a + * local register variable within current_thread_info() because clang doesn't + * support explicit local register variables. + * + * When building the VDSO we take care not to declare the global register + * variable because this causes GCC to not preserve the value of $28/$gp in + * functions that change its value (which is common in the PIC VDSO when + * accessing the GOT). Since the VDSO shouldn't be accessing + * __current_thread_info anyway we declare it extern in order to cause a link + * failure if it's referenced. + */ +#ifdef __VDSO__ +extern struct thread_info *__current_thread_info; +#else register struct thread_info *__current_thread_info __asm__("$28"); +#endif static inline struct thread_info *current_thread_info(void) { diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild index f2cf4146114679253195769bab10b859f41026d6..a0266feba9e6d996d5469ed18fd23df081a2ab38 100644 --- a/arch/mips/include/uapi/asm/Kbuild +++ b/arch/mips/include/uapi/asm/Kbuild @@ -2,40 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += ipcbuf.h - -header-y += auxvec.h -header-y += bitfield.h -header-y += bitsperlong.h -header-y += break.h -header-y += byteorder.h -header-y += cachectl.h -header-y += errno.h -header-y += fcntl.h -header-y += inst.h -header-y += ioctl.h -header-y += ioctls.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += sgidefs.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += sysmips.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 695950361d2a734289d6554318e106ec1ed15675..7cc1d29334ee1bde50c79e036929c025cab90d6b 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -74,7 +74,7 @@ static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; * mips_io_port_base is the begin of the address space to which x86 style * I/O ports are mapped. */ -const unsigned long mips_io_port_base = -1; +unsigned long mips_io_port_base = -1; EXPORT_SYMBOL(mips_io_port_base); static struct resource code_resource = { .name = "Kernel code", }; diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 544ea21bfef9cdae6361c964d5cdd91c56f57c88..b2683aca401f61f84770317be2358065100f567a 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -134,7 +134,7 @@ void release_vpe(struct vpe *v) { list_del(&v->list); if (v->load_addr) - release_progmem(v); + release_progmem(v->load_addr); kfree(v); } diff --git a/arch/mips/loongson64/loongson-3/platform.c b/arch/mips/loongson64/loongson-3/platform.c index 25a97cc0ee33664f79f16e3ffb4d350a4b033dae..0db4cc3196ebdcc92b98791e139f652636b83c9f 100644 --- a/arch/mips/loongson64/loongson-3/platform.c +++ b/arch/mips/loongson64/loongson-3/platform.c @@ -31,6 +31,9 @@ static int __init loongson3_platform_init(void) continue; pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); + if (!pdev) + return -ENOMEM; + pdev->name = loongson_sysconf.sensors[i].name; pdev->id = loongson_sysconf.sensors[i].id; pdev->dev.platform_data = &loongson_sysconf.sensors[i]; diff --git a/arch/mn10300/include/uapi/asm/Kbuild b/arch/mn10300/include/uapi/asm/Kbuild index 040178cdb3eb9816f3d50769fee272e802becf9b..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/mn10300/include/uapi/asm/Kbuild +++ b/arch/mn10300/include/uapi/asm/Kbuild @@ -1,34 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/nios2/include/uapi/asm/Kbuild b/arch/nios2/include/uapi/asm/Kbuild index e0bb972a50d7425b3f422605ab64bbc82c428cc0..0c74c3c5ebfa4f6a1c47a9ea4c5ce784bc6188ca 100644 --- a/arch/nios2/include/uapi/asm/Kbuild +++ b/arch/nios2/include/uapi/asm/Kbuild @@ -1,5 +1,4 @@ +# UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += elf.h - generic-y += ucontext.h diff --git a/arch/nios2/kernel/nios2_ksyms.c b/arch/nios2/kernel/nios2_ksyms.c index bf2f55d10a4d84f6896a70da6993731368708c6b..4e704046a150c164379d42cada3d09d6f6910107 100644 --- a/arch/nios2/kernel/nios2_ksyms.c +++ b/arch/nios2/kernel/nios2_ksyms.c @@ -9,12 +9,20 @@ #include #include +#include +#include + /* string functions */ EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memmove); +/* memory management */ + +EXPORT_SYMBOL(empty_zero_page); +EXPORT_SYMBOL(flush_icache_range); + /* * libgcc functions - functions that are used internally by the * compiler... (prototypes are not correct though, but that @@ -31,3 +39,7 @@ DECLARE_EXPORT(__udivsi3); DECLARE_EXPORT(__umoddi3); DECLARE_EXPORT(__umodsi3); DECLARE_EXPORT(__muldi3); +DECLARE_EXPORT(__ucmpdi2); +DECLARE_EXPORT(__lshrdi3); +DECLARE_EXPORT(__ashldi3); +DECLARE_EXPORT(__ashrdi3); diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild index 2832f031fb11d0e86fe695ced404c41cf36ebf90..561915716fd915409761035a2150a35e853eca6e 100644 --- a/arch/openrisc/include/asm/Kbuild +++ b/arch/openrisc/include/asm/Kbuild @@ -1,6 +1,3 @@ - -header-y += ucontext.h - generic-y += atomic.h generic-y += auxvec.h generic-y += barrier.h diff --git a/arch/openrisc/include/uapi/asm/Kbuild b/arch/openrisc/include/uapi/asm/Kbuild index 80761eb82b5fd8d272f354eefc7299c7c3406a0a..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/openrisc/include/uapi/asm/Kbuild +++ b/arch/openrisc/include/uapi/asm/Kbuild @@ -1,10 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += byteorder.h -header-y += elf.h -header-y += kvm_para.h -header-y += param.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += unistd.h diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h index 7ada309008073ac62021942709107f526a76a11f..90253bdc2ee5e1ebf9f638f887c2dd8d4cb5c00d 100644 --- a/arch/parisc/include/asm/cmpxchg.h +++ b/arch/parisc/include/asm/cmpxchg.h @@ -43,8 +43,14 @@ __xchg(unsigned long x, __volatile__ void *ptr, int size) ** if (((unsigned long)p & 0xf) == 0) ** return __ldcw(p); */ -#define xchg(ptr, x) \ - ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) +#define xchg(ptr, x) \ +({ \ + __typeof__(*(ptr)) __ret; \ + __typeof__(*(ptr)) _x_ = (x); \ + __ret = (__typeof__(*(ptr))) \ + __xchg((unsigned long)_x_, (ptr), sizeof(*(ptr))); \ + __ret; \ +}) /* bug catcher for when unsupported size is used - won't link */ extern void __cmpxchg_called_with_bad_pointer(void); diff --git a/arch/parisc/include/uapi/asm/Kbuild b/arch/parisc/include/uapi/asm/Kbuild index 348356c99514f0cdfb8876b9f22c0464ab8e3734..3971c60a7e7ff6f987cd36b705ddbf49cce5af7c 100644 --- a/arch/parisc/include/uapi/asm/Kbuild +++ b/arch/parisc/include/uapi/asm/Kbuild @@ -2,31 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += resource.h - -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += pdc.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 062b006d42224283f723d088deee5c4b4309aae8..a4632af7f64e84f02b65fd7a705e1de632ce533e 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -86,6 +86,7 @@ config PPC select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_FORTIFY_SOURCE select OF + select OF_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE select OF_EARLY_FLATTREE select OF_RESERVED_MEM select HAVE_FTRACE_MCOUNT_RECORD diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index a60c9c6e5cc17297e7b2e0e620c48b00838c4a09..de29b88c0e7001033364db1359a9326039f32dcf 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -373,7 +373,9 @@ vdso_install: ifeq ($(CONFIG_PPC64),y) $(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@ endif +ifdef CONFIG_VDSO32 $(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso32 $@ +endif archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/powerpc/boot/4xx.c b/arch/powerpc/boot/4xx.c index 9d3bd4c45a2406992005018d70f1db1e1f56b591..1c4354f922fd902858ec39069712db31fbc79691 100644 --- a/arch/powerpc/boot/4xx.c +++ b/arch/powerpc/boot/4xx.c @@ -232,7 +232,7 @@ void ibm4xx_denali_fixup_memsize(void) dpath = 8; /* 64 bits */ /* get address pins (rows) */ - val = SDRAM0_READ(DDR0_42); + val = SDRAM0_READ(DDR0_42); row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT); if (row > max_row) diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi index e1a961f05dcd5b04b640827810cd198ff6fcb753..baa0c503e741b87f89609ca66c907fd5b36ecea7 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi @@ -63,6 +63,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe1000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy0: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi index c288f3c6c6378dc5fd3c20cf1605ecd031013c89..93095600e8086f617b515047a4c70275d1cf88f8 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi @@ -60,6 +60,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xf1000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy6: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi index 94f3e71750124b5c8a58861909d5d017b05262ca..ff4bd38f064599947096249e51149f8a0e43383f 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi @@ -63,6 +63,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe3000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy1: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi index 94a76982d214b7b963d4b66a9f5161793a2b8b55..1fa38ed6f59e269c70a6de0e8ca41d40024bcb62 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi @@ -60,6 +60,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xf3000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy7: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi index b5ff5f71c6b8b01874dd1b436e416409c2ac0759..a8cc9780c0c4225ac48c3fba7ca096089bf1c2f3 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi @@ -59,6 +59,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe1000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy0: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi index ee44182c634853566c9740b04631c3564e8bd020..8b8bd70c93823df4ca8fc71574f6e9417c7bf1cb 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi @@ -59,6 +59,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe3000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy1: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi index f05f0d775039b53aab57cdcd28fa8ac3ebde3490..619c880b54d8d39202cb58579974992ef2bf919f 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi @@ -59,6 +59,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe5000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy2: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi index a9114ec510759e74036766b1ec1dbcaf42bcfa07..d7ebb73a400d06978aaedadd2efd62770159393c 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi @@ -59,6 +59,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe7000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy3: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi index 44dd00ac7367fd6a100131eec3b7388741062383..b151d696a0699b24e90a5c290dba6cc41e6acccf 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi @@ -59,6 +59,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe9000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy4: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi index 5b1b84b58602fa46e06cebb7be6b390d59372434..adc0ae0013a3ce89f8d1e26bd14a6f6f15af4526 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi @@ -59,6 +59,7 @@ fman@400000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xeb000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy5: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi index 0e1daaef9e74b8fe2b6f51369a11c66b238e7dfd..435047e0e250e2e95d73d0e3de6b605060beb378 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi @@ -60,6 +60,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xf1000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy14: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi index 68c5ef779266a8692e712a0ddcfa51db0822d945..c098657cca0a7b8330590ef69b129af4b06b8e4d 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi @@ -60,6 +60,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xf3000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy15: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi index 605363cc1117fbf38b334e68a9b21815325cfe74..9d06824815f342ca7b1d30c5e94159da76e936e9 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi @@ -59,6 +59,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe1000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy8: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi index 1955dfa136348f12ea29e0c4fdd3abb7438784fe..70e947730c4ba72b715763fb1fe2ddf6c6ef0fec 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi @@ -59,6 +59,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe3000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy9: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi index 2c1476454ee01bb81069c325ed7c02c20f70963d..ad96e6529595960f14be688feee58d3e3a6b84e9 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi @@ -59,6 +59,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe5000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy10: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi index b8b541ff5fb034e597c427431e15b4e01ed0de26..034bc4b71f7a506a064b37c320beea2bedd0f390 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi @@ -59,6 +59,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe7000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy11: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi index 4b2cfddd1b1553bbb34d53a236cd399fb96441b1..93ca23d82b39ba9cfdf0558afe1da18d0518550d 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi @@ -59,6 +59,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xe9000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy12: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi index 0a52ddf7cc171e6b830bc2707bc0be9d8ac26ee0..23b3117a2fd2a3871627bc34a68e14d0159e52ca 100644 --- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi +++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi @@ -59,6 +59,7 @@ fman@500000 { #size-cells = <0>; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; reg = <0xeb000 0x1000>; + fsl,erratum-a011043; /* must ignore read errors */ pcsphy13: ethernet-phy@0 { reg = <0x0>; diff --git a/arch/powerpc/boot/libfdt_env.h b/arch/powerpc/boot/libfdt_env.h index 0b3db6322c793223ab53a351d023ce24fd8746c7..5f2cb1c53e1515fc85da504555e1bff3b5346067 100644 --- a/arch/powerpc/boot/libfdt_env.h +++ b/arch/powerpc/boot/libfdt_env.h @@ -5,6 +5,8 @@ #include #define INT_MAX ((int)(~0U>>1)) +#define UINT32_MAX ((u32)~0U) +#define INT32_MAX ((s32)(UINT32_MAX >> 1)) #include "of.h" diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h index 85e88f7a59c0a072c14f6f686b252ab3b4b8c5ef..9ff848e3c4a627c84616db094fc47f1471e11367 100644 --- a/arch/powerpc/include/asm/archrandom.h +++ b/arch/powerpc/include/asm/archrandom.h @@ -27,7 +27,7 @@ static inline int arch_get_random_seed_int(unsigned int *v) unsigned long val; int rc; - rc = arch_get_random_long(&val); + rc = arch_get_random_seed_long(&val); if (rc) *v = val; diff --git a/arch/powerpc/include/asm/sfp-machine.h b/arch/powerpc/include/asm/sfp-machine.h index d89beaba26ff95d2ab0ed48cdaf1ba7fc8f3bd73..8b957aabb826d3b55674cab70e3fc096869f8ec0 100644 --- a/arch/powerpc/include/asm/sfp-machine.h +++ b/arch/powerpc/include/asm/sfp-machine.h @@ -213,30 +213,18 @@ * respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow * (i.e. carry out) is not stored anywhere, and is lost. */ -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ do { \ if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))); \ - else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ - __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))); \ + __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ else \ - __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "r" ((USItype)(bh)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))); \ + __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ } while (0) /* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to @@ -248,44 +236,24 @@ * and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, * and is lost. */ -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ if (__builtin_constant_p (ah) && (ah) == 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(bh)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(bh)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ else if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ + __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ else \ - __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "r" ((USItype)(bh)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ + __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ } while (0) /* asm fragments for mul and div */ @@ -294,13 +262,10 @@ * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype * word product in HIGH_PROD and LOW_PROD. */ -#define umul_ppmm(ph, pl, m0, m1) \ +#define umul_ppmm(ph, pl, m0, m1) \ do { \ USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mulhwu %0,%1,%2" \ - : "=r" ((USItype)(ph)) \ - : "%r" (__m0), \ - "r" (__m1)); \ + __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ (pl) = __m0 * __m1; \ } while (0) @@ -312,9 +277,10 @@ * significant bit of DENOMINATOR must be 1, then the pre-processor symbol * UDIV_NEEDS_NORMALIZATION is defined to 1. */ -#define udiv_qrnnd(q, r, n1, n0, d) \ +#define udiv_qrnnd(q, r, n1, n0, d) \ do { \ - UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + UWtype __d1, __d0, __q1, __q0; \ + UWtype __r1, __r0, __m; \ __d1 = __ll_highpart (d); \ __d0 = __ll_lowpart (d); \ \ @@ -325,7 +291,7 @@ if (__r1 < __m) \ { \ __q1--, __r1 += (d); \ - if (__r1 >= (d)) /* we didn't get carry when adding to __r1 */ \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ if (__r1 < __m) \ __q1--, __r1 += (d); \ } \ diff --git a/arch/powerpc/include/asm/vdso_datapage.h b/arch/powerpc/include/asm/vdso_datapage.h index 1afe90ade595e161016af3ca712b65f9990407f4..674c03350cd11980a868194756c24f38ea82a215 100644 --- a/arch/powerpc/include/asm/vdso_datapage.h +++ b/arch/powerpc/include/asm/vdso_datapage.h @@ -86,6 +86,7 @@ struct vdso_data { __s32 wtom_clock_nsec; struct timespec stamp_xtime; /* xtime as at tb_orig_stamp */ __u32 stamp_sec_fraction; /* fractional seconds of stamp_xtime */ + __u32 hrtimer_res; /* hrtimer resolution */ __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */ __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */ }; @@ -107,6 +108,7 @@ struct vdso_data { __s32 wtom_clock_nsec; struct timespec stamp_xtime; /* xtime as at tb_orig_stamp */ __u32 stamp_sec_fraction; /* fractional seconds of stamp_xtime */ + __u32 hrtimer_res; /* hrtimer resolution */ __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */ __u32 dcache_block_size; /* L1 d-cache block size */ __u32 icache_block_size; /* L1 i-cache block size */ diff --git a/arch/powerpc/include/uapi/asm/Kbuild b/arch/powerpc/include/uapi/asm/Kbuild index dab3717e3ea09db41c4db172aa675f27059843fc..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/powerpc/include/uapi/asm/Kbuild +++ b/arch/powerpc/include/uapi/asm/Kbuild @@ -1,47 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += bootx.h -header-y += byteorder.h -header-y += cputable.h -header-y += eeh.h -header-y += elf.h -header-y += epapr_hcalls.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += nvram.h -header-y += opal-prd.h -header-y += param.h -header-y += perf_event.h -header-y += poll.h -header-y += posix_types.h -header-y += ps3fb.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += spu_info.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += tm.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 14fbbd9035ca78590424267d7ca45faa31aa34e2..dfcf28be12bae458af4f4dcebf956a4fb1c9596b 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -383,6 +383,7 @@ int main(void) DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); DEFINE(STAMP_XTIME, offsetof(struct vdso_data, stamp_xtime)); DEFINE(STAMP_SEC_FRAC, offsetof(struct vdso_data, stamp_sec_fraction)); + DEFINE(CLOCK_HRTIMER_RES, offsetof(struct vdso_data, hrtimer_res)); DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size)); DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size)); DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size)); @@ -411,7 +412,6 @@ int main(void) DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); DEFINE(NSEC_PER_SEC, NSEC_PER_SEC); - DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); #ifdef CONFIG_BUG DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry)); diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index c641983bbdd68a646b850e42673ce6599fdbc824..3394a72b19f2f35cea7cf0aaa49409333c5395ab 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c @@ -867,4 +867,21 @@ void cacheinfo_cpu_offline(unsigned int cpu_id) if (cache) cache_cpu_clear(cache, cpu_id); } + +void cacheinfo_teardown(void) +{ + unsigned int cpu; + + for_each_online_cpu(cpu) + cacheinfo_cpu_offline(cpu); +} + +void cacheinfo_rebuild(void) +{ + unsigned int cpu; + + for_each_online_cpu(cpu) + cacheinfo_cpu_online(cpu); +} + #endif /* (CONFIG_PPC_PSERIES && CONFIG_SUSPEND) || CONFIG_HOTPLUG_CPU */ diff --git a/arch/powerpc/kernel/cacheinfo.h b/arch/powerpc/kernel/cacheinfo.h index a7b74d36acd7155f7ab03a6fe2f6d833dda0bffa..2cdee87a482c5f354004704f97f1c6391a444606 100644 --- a/arch/powerpc/kernel/cacheinfo.h +++ b/arch/powerpc/kernel/cacheinfo.h @@ -5,4 +5,8 @@ extern void cacheinfo_cpu_online(unsigned int cpu_id); extern void cacheinfo_cpu_offline(unsigned int cpu_id); +/* Allow migration/suspend to tear down and rebuild the hierarchy. */ +extern void cacheinfo_teardown(void); +extern void cacheinfo_rebuild(void); + #endif /* _PPC_CACHEINFO_H */ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 7471ed48f41fa2ebe415179928d06593afb9afc3..514e04b622614c6cd483921e6f0d13bb67ccc4a5 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -2199,11 +2199,13 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset, * oprofile_cpu_type already has a value, then we are * possibly overriding a real PVR with a logical one, * and, in that case, keep the current value for - * oprofile_cpu_type. + * oprofile_cpu_type. Futhermore, let's ensure that the + * fix for the PMAO bug is enabled on compatibility mode. */ if (old.oprofile_cpu_type != NULL) { t->oprofile_cpu_type = old.oprofile_cpu_type; t->oprofile_type = old.oprofile_type; + t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG; } } diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 620e08d4eb6e263189d1f45db647472cee14f3ba..adac3dee4c57ed595473c1864ad8fd8b18cfa067 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -520,12 +520,6 @@ static void *eeh_rmv_device(void *data, void *userdata) pci_iov_remove_virtfn(edev->physfn, pdn->vf_index, 0); edev->pdev = NULL; - - /* - * We have to set the VF PE number to invalid one, which is - * required to plug the VF successfully. - */ - pdn->pe_number = IODA_INVALID_PE; #endif if (rmv_data) list_add(&edev->rmv_list, &rmv_data->edev_list); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index ad713f741ca8500721013c1d06e4159d0114a96e..eff4a336a1b4a38e6c4b00ddc06c1e37d94e8cf6 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -527,8 +527,6 @@ void __do_irq(struct pt_regs *regs) trace_irq_entry(regs); - check_stack_overflow(); - /* * Query the platform PIC for the interrupt & ack it. * @@ -560,6 +558,8 @@ void do_IRQ(struct pt_regs *regs) irqtp = hardirq_ctx[raw_smp_processor_id()]; sirqtp = softirq_ctx[raw_smp_processor_id()]; + check_stack_overflow(); + /* Already there ? */ if (unlikely(curtp == irqtp || curtp == sirqtp)) { __do_irq(regs); diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 592693437070201b84e8aa52b0ca69018746579c..c8f1b78fbd0e248fadad71860784f69a42da783e 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -271,9 +271,22 @@ void remove_dev_pci_data(struct pci_dev *pdev) continue; #ifdef CONFIG_EEH - /* Release EEH device for the VF */ + /* + * Release EEH state for this VF. The PCI core + * has already torn down the pci_dev for this VF, but + * we're responsible to removing the eeh_dev since it + * has the same lifetime as the pci_dn that spawned it. + */ edev = pdn_to_eeh_dev(pdn); if (edev) { + /* + * We allocate pci_dn's for the totalvfs count, + * but only only the vfs that were activated + * have a configured PE. + */ + if (edev->pe) + eeh_rmv_from_parent_pe(edev); + pdn->edev = NULL; kfree(edev); } diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c index 11fff9669cfdf1459047b7bc6834133dd3b370ab..ff85fc8001836627c91f67b1b7110c234baf155f 100644 --- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -135,32 +135,33 @@ ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, cha thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV); - if (rfi_flush || thread_priv) { + if (rfi_flush) { struct seq_buf s; seq_buf_init(&s, buf, PAGE_SIZE - 1); - seq_buf_printf(&s, "Mitigation: "); - - if (rfi_flush) - seq_buf_printf(&s, "RFI Flush"); - - if (rfi_flush && thread_priv) - seq_buf_printf(&s, ", "); - + seq_buf_printf(&s, "Mitigation: RFI Flush"); if (thread_priv) - seq_buf_printf(&s, "L1D private per thread"); + seq_buf_printf(&s, ", L1D private per thread"); seq_buf_printf(&s, "\n"); return s.len; } + if (thread_priv) + return sprintf(buf, "Vulnerable: L1D private per thread\n"); + if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)) return sprintf(buf, "Not affected\n"); return sprintf(buf, "Vulnerable\n"); } + +ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf) +{ + return cpu_show_meltdown(dev, attr, buf); +} #endif ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index ab7b661b6da3a3aa1bb48e2873cf1c2c14f7d682..71315b4989e0510a914c5d0f9ff20c87f9bd719f 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -257,7 +257,7 @@ static u64 scan_dispatch_log(u64 stop_tb) * Accumulate stolen time by scanning the dispatch trace log. * Called on entry from user mode. */ -void accumulate_stolen_time(void) +void notrace accumulate_stolen_time(void) { u64 sst, ust; u8 save_soft_enabled = local_paca->soft_enabled; @@ -862,6 +862,7 @@ void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm, vdso_data->wtom_clock_nsec = wtm->tv_nsec; vdso_data->stamp_xtime = *wall_time; vdso_data->stamp_sec_fraction = frac_sec; + vdso_data->hrtimer_res = hrtimer_resolution; smp_wmb(); ++(vdso_data->tb_update_count); } diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S index 7b341b86216c29b3c8fc909e68478a128866974e..9b24466570c8451999bdbd9ae1578d1042fe6fb9 100644 --- a/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S @@ -160,12 +160,15 @@ V_FUNCTION_BEGIN(__kernel_clock_getres) cror cr0*4+eq,cr0*4+eq,cr1*4+eq bne cr0,99f + mflr r12 + .cfi_register lr,r12 + bl __get_datapage@local /* get data page */ + lwz r5, CLOCK_HRTIMER_RES(r3) + mtlr r12 li r3,0 cmpli cr0,r4,0 crclr cr0*4+so beqlr - lis r5,CLOCK_REALTIME_RES@h - ori r5,r5,CLOCK_REALTIME_RES@l stw r3,TSPC32_TV_SEC(r4) stw r5,TSPC32_TV_NSEC(r4) blr diff --git a/arch/powerpc/kernel/vdso64/cacheflush.S b/arch/powerpc/kernel/vdso64/cacheflush.S index 69c5af2b3c96cfd46a85a2c250a9727e585fcabf..228a4a2383d69e52d5dd4a2d3f779004ce5d6ef1 100644 --- a/arch/powerpc/kernel/vdso64/cacheflush.S +++ b/arch/powerpc/kernel/vdso64/cacheflush.S @@ -39,7 +39,7 @@ V_FUNCTION_BEGIN(__kernel_sync_dicache) subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10) - srw. r8,r8,r9 /* compute line count */ + srd. r8,r8,r9 /* compute line count */ crclr cr0*4+so beqlr /* nothing to do? */ mtctr r8 @@ -56,7 +56,7 @@ V_FUNCTION_BEGIN(__kernel_sync_dicache) subf r8,r6,r4 /* compute length */ add r8,r8,r5 lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10) - srw. r8,r8,r9 /* compute line count */ + srd. r8,r8,r9 /* compute line count */ crclr cr0*4+so beqlr /* nothing to do? */ mtctr r8 diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index 09b2a49f6dd53f907248d27d65a077c8f1ccf2a1..c973378e1f2bccfa60f1e421dcd737c62817c68e 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S @@ -145,12 +145,15 @@ V_FUNCTION_BEGIN(__kernel_clock_getres) cror cr0*4+eq,cr0*4+eq,cr1*4+eq bne cr0,99f + mflr r12 + .cfi_register lr,r12 + bl V_LOCAL_FUNC(__get_datapage) + lwz r5, CLOCK_HRTIMER_RES(r3) + mtlr r12 li r3,0 cmpldi cr0,r4,0 crclr cr0*4+so beqlr - lis r5,CLOCK_REALTIME_RES@h - ori r5,r5,CLOCK_REALTIME_RES@l std r3,TSPC64_TV_SEC(r4) std r5,TSPC64_TV_NSEC(r4) blr diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index e840f943cd2c820cea9b53ac660553562130c546..5cf1392dff96c23bd709626ba5167e76e5f88778 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -1766,7 +1766,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, mutex_unlock(&kvm->lock); if (!vcore) - goto free_vcpu; + goto uninit_vcpu; spin_lock(&vcore->lock); ++vcore->num_threads; @@ -1782,6 +1782,8 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, return vcpu; +uninit_vcpu: + kvm_vcpu_uninit(vcpu); free_vcpu: kmem_cache_free(kvm_vcpu_cache, vcpu); out: diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index e0d88d0890aaa66c354f93f37d930044ad9ca9dc..8172021bcee6501a93c553bc19fb9cbde0279356 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -1482,10 +1482,12 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, err = kvmppc_mmu_init(vcpu); if (err < 0) - goto uninit_vcpu; + goto free_shared_page; return vcpu; +free_shared_page: + free_page((unsigned long)vcpu->arch.shared); uninit_vcpu: kvm_vcpu_uninit(vcpu); free_shadow_vcpu: diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index bd666287c5eda1f9ef6c28607a33cb99fa1ee27b..2dc1fc445f3575d72d9a216c20f8ec222ba06f3e 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -289,10 +289,18 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot, HPTE_V_BOLTED, psize, psize, ssize); - + if (ret == -1) { + /* Try to remove a non bolted entry */ + ret = mmu_hash_ops.hpte_remove(hpteg); + if (ret != -1) + ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot, + HPTE_V_BOLTED, psize, psize, + ssize); + } if (ret < 0) break; + cond_resched(); #ifdef CONFIG_DEBUG_PAGEALLOC if (debug_pagealloc_enabled() && (paddr >> PAGE_SHIFT) < linear_map_hash_count) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 1e93dbc88e8084d038a5a97f36562ab85d2a220d..34f70d36b16de15c2c85043975706b35089a2b31 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -345,6 +345,14 @@ void __init mem_init(void) BUILD_BUG_ON(MMU_PAGE_COUNT > 16); #ifdef CONFIG_SWIOTLB + /* + * Some platforms (e.g. 85xx) limit DMA-able memory way below + * 4G. We force memblock to bottom-up mode to ensure that the + * memory allocated in swiotlb_init() is DMA-able. + * As it's the last memblock allocation, no need to reset it + * back to to-down. + */ + memblock_set_bottom_up(true); swiotlb_init(0); #endif diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 3ec673b4ca6ce3bbd10cca469f43e3b6f8cce6f8..b787a669a1e27fbb27375a41b9c06abf133d3529 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1524,6 +1524,10 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) /* Reserve PE for each VF */ for (vf_index = 0; vf_index < num_vfs; vf_index++) { + int vf_devfn = pci_iov_virtfn_devfn(pdev, vf_index); + int vf_bus = pci_iov_virtfn_bus(pdev, vf_index); + struct pci_dn *vf_pdn; + if (pdn->m64_single_mode) pe_num = pdn->pe_num_map[vf_index]; else @@ -1536,13 +1540,11 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) pe->pbus = NULL; pe->parent_dev = pdev; pe->mve_number = -1; - pe->rid = (pci_iov_virtfn_bus(pdev, vf_index) << 8) | - pci_iov_virtfn_devfn(pdev, vf_index); + pe->rid = (vf_bus << 8) | vf_devfn; pe_info(pe, "VF %04d:%02d:%02d.%d associated with PE#%d\n", hose->global_number, pdev->bus->number, - PCI_SLOT(pci_iov_virtfn_devfn(pdev, vf_index)), - PCI_FUNC(pci_iov_virtfn_devfn(pdev, vf_index)), pe_num); + PCI_SLOT(vf_devfn), PCI_FUNC(vf_devfn), pe_num); if (pnv_ioda_configure_pe(phb, pe)) { /* XXX What do we do here ? */ @@ -1556,6 +1558,15 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) list_add_tail(&pe->list, &phb->ioda.pe_list); mutex_unlock(&phb->ioda.pe_list_mutex); + /* associate this pe to it's pdn */ + list_for_each_entry(vf_pdn, &pdn->parent->child_list, list) { + if (vf_pdn->busno == vf_bus && + vf_pdn->devfn == vf_devfn) { + vf_pdn->pe_number = pe_num; + break; + } + } + pnv_pci_ioda2_setup_dma_pe(phb, pe); } } diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 98cc8ba07c2334f20687eef5abb9f7c3477ceffe..2ed7627e991e092c7521769eec4780c3d7e7d475 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -856,16 +856,12 @@ void pnv_pci_dma_dev_setup(struct pci_dev *pdev) struct pnv_phb *phb = hose->private_data; #ifdef CONFIG_PCI_IOV struct pnv_ioda_pe *pe; - struct pci_dn *pdn; /* Fix the VF pdn PE number */ if (pdev->is_virtfn) { - pdn = pci_get_pdn(pdev); - WARN_ON(pdn->pe_number != IODA_INVALID_PE); list_for_each_entry(pe, &phb->ioda.pe_list, list) { if (pe->rid == ((pdev->bus->number << 8) | (pdev->devfn & 0xff))) { - pdn->pe_number = pe->pe_number; pe->pdev = pdev; break; } @@ -923,6 +919,23 @@ void __init pnv_pci_init(void) if (!firmware_has_feature(FW_FEATURE_OPAL)) return; +#ifdef CONFIG_PCIEPORTBUS + /* + * On PowerNV PCIe devices are (currently) managed in cooperation + * with firmware. This isn't *strictly* required, but there's enough + * assumptions baked into both firmware and the platform code that + * it's unwise to allow the portbus services to be used. + * + * We need to fix this eventually, but for now set this flag to disable + * the portbus driver. The AER service isn't required since that AER + * events are handled via EEH. The pciehp hotplug driver can't work + * without kernel changes (and portbus binding breaks pnv_php). The + * other services also require some thinking about how we're going + * to integrate them. + */ + pcie_ports_disabled = true; +#endif + /* Look for IODA IO-Hubs. */ for_each_compatible_node(np, NULL, "ibm,ioda-hub") { pnv_pci_init_ioda_hub(np); diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index 85018a14217a37a4331af0018f2c10e7b8ab651f..316eded255e7db23dba0e7395aec289e3900eef3 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c @@ -391,6 +391,10 @@ static struct bus_type cmm_subsys = { .dev_name = "cmm", }; +static void cmm_release_device(struct device *dev) +{ +} + /** * cmm_sysfs_register - Register with sysfs * @@ -406,6 +410,7 @@ static int cmm_sysfs_register(struct device *dev) dev->id = 0; dev->bus = &cmm_subsys; + dev->release = cmm_release_device; if ((rc = device_register(dev))) goto subsys_unregister; diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 6c12b02f4a61df21c411680e4807508d53a4f4d7..eee45b9220e049e7d0c58121e3a1a4e9211b8360 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -398,8 +398,10 @@ static bool lmb_is_removable(struct of_drconf_cell *lmb) for (i = 0; i < scns_per_block; i++) { pfn = PFN_DOWN(phys_addr); - if (!pfn_present(pfn)) + if (!pfn_present(pfn)) { + phys_addr += MIN_MEMORY_BLOCK_SIZE; continue; + } rc &= is_mem_section_removable(pfn, PAGES_PER_SECTION); phys_addr += MIN_MEMORY_BLOCK_SIZE; diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 74da18de853af670f911acc800e50d076bff4f8c..73ec15cd27080f256cd86ac57f04f48550686603 100644 --- a/arch/powerpc/platforms/pseries/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c @@ -62,7 +62,7 @@ EXPORT_SYMBOL(hvc_get_chars); * @vtermno: The vtermno or unit_address of the adapter from which the data * originated. * @buf: The character buffer that contains the character data to send to - * firmware. + * firmware. Must be at least 16 bytes, even if count is less than 16. * @count: Send this number of characters. */ int hvc_put_chars(uint32_t vtermno, const char *buf, int count) diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 0024e451bb36f8ef7665835180d34a5e2807679b..c0f094c96cd6a1220bec18e8a3e1c487a499e41d 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -167,10 +167,10 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) return be64_to_cpu(*tcep); } -static void tce_free_pSeriesLP(struct iommu_table*, long, long); +static void tce_free_pSeriesLP(unsigned long liobn, long, long); static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long); -static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, +static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift, long npages, unsigned long uaddr, enum dma_data_direction direction, unsigned long attrs) @@ -181,25 +181,25 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, int ret = 0; long tcenum_start = tcenum, npages_start = npages; - rpn = __pa(uaddr) >> TCE_SHIFT; + rpn = __pa(uaddr) >> tceshift; proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) proto_tce |= TCE_PCI_WRITE; while (npages--) { - tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; - rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); + tce = proto_tce | (rpn & TCE_RPN_MASK) << tceshift; + rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, tce); if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { ret = (int)rc; - tce_free_pSeriesLP(tbl, tcenum_start, + tce_free_pSeriesLP(liobn, tcenum_start, (npages_start - (npages + 1))); break; } if (rc && printk_ratelimit()) { printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc); - printk("\tindex = 0x%llx\n", (u64)tbl->it_index); + printk("\tindex = 0x%llx\n", (u64)liobn); printk("\ttcenum = 0x%llx\n", (u64)tcenum); printk("\ttce val = 0x%llx\n", tce ); dump_stack(); @@ -228,7 +228,8 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, unsigned long flags; if ((npages == 1) || !firmware_has_feature(FW_FEATURE_MULTITCE)) { - return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, + return tce_build_pSeriesLP(tbl->it_index, tcenum, + tbl->it_page_shift, npages, uaddr, direction, attrs); } @@ -244,8 +245,9 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, /* If allocation fails, fall back to the loop implementation */ if (!tcep) { local_irq_restore(flags); - return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, - direction, attrs); + return tce_build_pSeriesLP(tbl->it_index, tcenum, + tbl->it_page_shift, + npages, uaddr, direction, attrs); } __this_cpu_write(tce_page, tcep); } @@ -296,16 +298,16 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, return ret; } -static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) +static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long npages) { u64 rc; while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0); + rc = plpar_tce_put((u64)liobn, (u64)tcenum << 12, 0); if (rc && printk_ratelimit()) { printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc); - printk("\tindex = 0x%llx\n", (u64)tbl->it_index); + printk("\tindex = 0x%llx\n", (u64)liobn); printk("\ttcenum = 0x%llx\n", (u64)tcenum); dump_stack(); } @@ -320,7 +322,7 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n u64 rc; if (!firmware_has_feature(FW_FEATURE_MULTITCE)) - return tce_free_pSeriesLP(tbl, tcenum, npages); + return tce_free_pSeriesLP(tbl->it_index, tcenum, npages); rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages); @@ -435,6 +437,19 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn, u64 rc = 0; long l, limit; + if (!firmware_has_feature(FW_FEATURE_MULTITCE)) { + unsigned long tceshift = be32_to_cpu(maprange->tce_shift); + unsigned long dmastart = (start_pfn << PAGE_SHIFT) + + be64_to_cpu(maprange->dma_base); + unsigned long tcenum = dmastart >> tceshift; + unsigned long npages = num_pfn << PAGE_SHIFT >> tceshift; + void *uaddr = __va(start_pfn << PAGE_SHIFT); + + return tce_build_pSeriesLP(be32_to_cpu(maprange->liobn), + tcenum, tceshift, npages, (unsigned long) uaddr, + DMA_BIDIRECTIONAL, 0); + } + local_irq_disable(); /* to protect tcep and the page behind it */ tcep = __this_cpu_read(tce_page); diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 69b8a41fca84b4acf70b9b435ed5d430b43415af..e094c0cf6936605870cfb96296452f36e6b4537c 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -35,7 +35,7 @@ void __storage_key_init_range(unsigned long start, unsigned long end); static inline void storage_key_init_range(unsigned long start, unsigned long end) { - if (PAGE_DEFAULT_KEY) + if (PAGE_DEFAULT_KEY != 0) __storage_key_init_range(start, end); } diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index 0bb08f341c09b1579d421c706892c28bfdec3a84..f1330245b5840cff6866511c23e00b9fa0c5e8ff 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -146,7 +146,7 @@ static inline void get_tod_clock_ext(char *clk) static inline unsigned long long get_tod_clock(void) { - unsigned char clk[STORE_CLOCK_EXT_SIZE]; + char clk[STORE_CLOCK_EXT_SIZE]; get_tod_clock_ext(clk); return *((unsigned long long *)&clk[1]); diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild index cc44b09c25fc4f04a3173a1a9c734f646ce7bb63..baebb3da1d44160fc6f6f259886656e6f494b167 100644 --- a/arch/s390/include/uapi/asm/Kbuild +++ b/arch/s390/include/uapi/asm/Kbuild @@ -1,53 +1,3 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += chpid.h -header-y += chsc.h -header-y += clp.h -header-y += cmb.h -header-y += dasd.h -header-y += debug.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm.h -header-y += kvm_para.h -header-y += kvm_perf.h -header-y += kvm_virtio.h -header-y += mman.h -header-y += monwriter.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += qeth.h -header-y += resource.h -header-y += schid.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += sclp_ctl.h -header-y += sie.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += tape390.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h -header-y += virtio-ccw.h -header-y += vtoc.h -header-y += zcrypt.h diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index aaf9dab3c1933e7557e679245e58176d1dfbf1a9..f9dca1aed9a4b5c07af1215eba3f3144e6aa62e4 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -1930,10 +1930,11 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr) ptr += sprintf(ptr, "%%c%i", value); else if (operand->flags & OPERAND_VR) ptr += sprintf(ptr, "%%v%i", value); - else if (operand->flags & OPERAND_PCREL) - ptr += sprintf(ptr, "%lx", (signed int) value - + addr); - else if (operand->flags & OPERAND_SIGNED) + else if (operand->flags & OPERAND_PCREL) { + void *pcrel = (void *)((int)value + addr); + + ptr += sprintf(ptr, "%px", pcrel); + } else if (operand->flags & OPERAND_SIGNED) ptr += sprintf(ptr, "%i", value); else ptr += sprintf(ptr, "%u", value); @@ -2005,7 +2006,7 @@ void show_code(struct pt_regs *regs) else *ptr++ = ' '; addr = regs->psw.addr + start - 32; - ptr += sprintf(ptr, "%016lx: ", addr); + ptr += sprintf(ptr, "%px: ", (void *)addr); if (start + opsize >= end) break; for (i = 0; i < opsize; i++) @@ -2033,7 +2034,7 @@ void print_fn_code(unsigned char *code, unsigned long len) opsize = insn_length(*code); if (opsize > len) break; - ptr += sprintf(ptr, "%p: ", code); + ptr += sprintf(ptr, "%px: ", code); for (i = 0; i < opsize; i++) ptr += sprintf(ptr, "%02x", code[i]); *ptr++ = '\t'; diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index be75e8e49e43d7705e04b71aefecce1de7905961..802a4ded9a626ea28e302140892669264c1bea05 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S @@ -24,6 +24,12 @@ ENTRY(ftrace_stub) #define STACK_PTREGS (STACK_FRAME_OVERHEAD) #define STACK_PTREGS_GPRS (STACK_PTREGS + __PT_GPRS) #define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW) +#ifdef __PACK_STACK +/* allocate just enough for r14, r15 and backchain */ +#define TRACED_FUNC_FRAME_SIZE 24 +#else +#define TRACED_FUNC_FRAME_SIZE STACK_FRAME_OVERHEAD +#endif ENTRY(_mcount) BR_EX %r14 @@ -37,9 +43,16 @@ ENTRY(ftrace_caller) #ifndef CC_USING_HOTPATCH aghi %r0,MCOUNT_RETURN_FIXUP #endif - aghi %r15,-STACK_FRAME_SIZE + # allocate stack frame for ftrace_caller to contain traced function + aghi %r15,-TRACED_FUNC_FRAME_SIZE stg %r1,__SF_BACKCHAIN(%r15) + stg %r0,(__SF_GPRS+8*8)(%r15) + stg %r15,(__SF_GPRS+9*8)(%r15) + # allocate pt_regs and stack frame for ftrace_trace_function + aghi %r15,-STACK_FRAME_SIZE stg %r1,(STACK_PTREGS_GPRS+15*8)(%r15) + aghi %r1,-TRACED_FUNC_FRAME_SIZE + stg %r1,__SF_BACKCHAIN(%r15) stg %r0,(STACK_PTREGS_PSW+8)(%r15) stmg %r2,%r14,(STACK_PTREGS_GPRS+2*8)(%r15) #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index f46e5c0cb6d95d5b224ac940227d9b7fd4f00fa9..c62eb09b2ba7b7f029cda50a00c383bb67e331f5 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -185,7 +185,7 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, unsigned long num_sdb, gfp_t gfp_flags) { int i, rc; - unsigned long *new, *tail; + unsigned long *new, *tail, *tail_prev = NULL; if (!sfb->sdbt || !sfb->tail) return -EINVAL; @@ -224,6 +224,7 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, sfb->num_sdbt++; /* Link current page to tail of chain */ *tail = (unsigned long)(void *) new + 1; + tail_prev = tail; tail = new; } @@ -233,10 +234,22 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, * issue, a new realloc call (if required) might succeed. */ rc = alloc_sample_data_block(tail, gfp_flags); - if (rc) + if (rc) { + /* Undo last SDBT. An SDBT with no SDB at its first + * entry but with an SDBT entry instead can not be + * handled by the interrupt handler code. + * Avoid this situation. + */ + if (tail_prev) { + sfb->num_sdbt--; + free_page((unsigned long) new); + tail = tail_prev; + } break; + } sfb->num_sdb++; tail++; + tail_prev = new = NULL; /* Allocated at least one SBD */ } /* Link sampling buffer to its origin */ @@ -1282,18 +1295,28 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) */ if (flush_all && done) break; - - /* If an event overflow happened, discard samples by - * processing any remaining sample-data-blocks. - */ - if (event_overflow) - flush_all = 1; } /* Account sample overflows in the event hardware structure */ if (sampl_overflow) OVERFLOW_REG(hwc) = DIV_ROUND_UP(OVERFLOW_REG(hwc) + sampl_overflow, 1 + num_sdb); + + /* Perf_event_overflow() and perf_event_account_interrupt() limit + * the interrupt rate to an upper limit. Roughly 1000 samples per + * task tick. + * Hitting this limit results in a large number + * of throttled REF_REPORT_THROTTLE entries and the samples + * are dropped. + * Slightly increase the interval to avoid hitting this limit. + */ + if (event_overflow) { + SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10); + debug_sprintf_event(sfdbg, 1, "%s: rate adjustment %ld\n", + __func__, + DIV_ROUND_UP(SAMPL_RATE(hwc), 10)); + } + if (sampl_overflow || event_overflow) debug_sprintf_event(sfdbg, 4, "hw_perf_event_update: " "overflow stats: sample=%llu event=%llu\n", diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index d52a94e9f57fc4727f0dc6d6ca5523499b856659..cba8e56cd63dba86a31b65bc9e1c06b5a6388995 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -691,39 +691,67 @@ static struct sclp_core_info *smp_get_core_info(void) static int smp_add_present_cpu(int cpu); -static int __smp_rescan_cpus(struct sclp_core_info *info, int sysfs_add) +static int smp_add_core(struct sclp_core_entry *core, cpumask_t *avail, + bool configured, bool early) { struct pcpu *pcpu; - cpumask_t avail; - int cpu, nr, i, j; + int cpu, nr, i; u16 address; nr = 0; - cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask); - cpu = cpumask_first(&avail); - for (i = 0; (i < info->combined) && (cpu < nr_cpu_ids); i++) { - if (sclp.has_core_type && info->core[i].type != boot_core_type) + if (sclp.has_core_type && core->type != boot_core_type) + return nr; + cpu = cpumask_first(avail); + address = core->core_id << smp_cpu_mt_shift; + for (i = 0; (i <= smp_cpu_mtid) && (cpu < nr_cpu_ids); i++) { + if (pcpu_find_address(cpu_present_mask, address + i)) continue; - address = info->core[i].core_id << smp_cpu_mt_shift; - for (j = 0; j <= smp_cpu_mtid; j++) { - if (pcpu_find_address(cpu_present_mask, address + j)) - continue; - pcpu = pcpu_devices + cpu; - pcpu->address = address + j; - pcpu->state = - (cpu >= info->configured*(smp_cpu_mtid + 1)) ? - CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; - smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); - set_cpu_present(cpu, true); - if (sysfs_add && smp_add_present_cpu(cpu) != 0) - set_cpu_present(cpu, false); - else - nr++; - cpu = cpumask_next(cpu, &avail); - if (cpu >= nr_cpu_ids) + pcpu = pcpu_devices + cpu; + pcpu->address = address + i; + if (configured) + pcpu->state = CPU_STATE_CONFIGURED; + else + pcpu->state = CPU_STATE_STANDBY; + smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + set_cpu_present(cpu, true); + if (!early && smp_add_present_cpu(cpu) != 0) + set_cpu_present(cpu, false); + else + nr++; + cpumask_clear_cpu(cpu, avail); + cpu = cpumask_next(cpu, avail); + } + return nr; +} + +static int __smp_rescan_cpus(struct sclp_core_info *info, bool early) +{ + struct sclp_core_entry *core; + cpumask_t avail; + bool configured; + u16 core_id; + int nr, i; + + nr = 0; + cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask); + /* + * Add IPL core first (which got logical CPU number 0) to make sure + * that all SMT threads get subsequent logical CPU numbers. + */ + if (early) { + core_id = pcpu_devices[0].address >> smp_cpu_mt_shift; + for (i = 0; i < info->configured; i++) { + core = &info->core[i]; + if (core->core_id == core_id) { + nr += smp_add_core(core, &avail, true, early); break; + } } } + for (i = 0; i < info->combined; i++) { + configured = i < info->configured; + nr += smp_add_core(&info->core[i], &avail, configured, early); + } return nr; } @@ -771,7 +799,7 @@ static void __init smp_detect_cpus(void) /* Add CPUs present at boot */ get_online_cpus(); - __smp_rescan_cpus(info, 0); + __smp_rescan_cpus(info, true); put_online_cpus(); kfree(info); } @@ -1127,7 +1155,7 @@ int __ref smp_rescan_cpus(void) return -ENOMEM; get_online_cpus(); mutex_lock(&smp_cpu_state_mutex); - nr = __smp_rescan_cpus(info, 1); + nr = __smp_rescan_cpus(info, false); mutex_unlock(&smp_cpu_state_mutex); put_online_cpus(); kfree(info); diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index a05218ff3fe465b6e4812d7655360dc1b495a519..c70aceb5d54a6d680528a0eecc5e1349d1f8c4bb 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -1,7 +1,4 @@ -header-y += - - generic-y += barrier.h generic-y += clkdev.h generic-y += cputime.h diff --git a/arch/score/include/uapi/asm/Kbuild b/arch/score/include/uapi/asm/Kbuild index 040178cdb3eb9816f3d50769fee272e802becf9b..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/score/include/uapi/asm/Kbuild +++ b/arch/score/include/uapi/asm/Kbuild @@ -1,34 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7269.h b/arch/sh/include/cpu-sh2a/cpu/sh7269.h index 2a0ca8780f0d8c343fb87e434cf6acec73acaddb..e4caddd443dafbef019ef244f7f41789545cf092 100644 --- a/arch/sh/include/cpu-sh2a/cpu/sh7269.h +++ b/arch/sh/include/cpu-sh2a/cpu/sh7269.h @@ -79,8 +79,15 @@ enum { GPIO_FN_WDTOVF, /* CAN */ - GPIO_FN_CTX1, GPIO_FN_CRX1, GPIO_FN_CTX0, GPIO_FN_CTX0_CTX1, - GPIO_FN_CRX0, GPIO_FN_CRX0_CRX1, GPIO_FN_CRX0_CRX1_CRX2, + GPIO_FN_CTX2, GPIO_FN_CRX2, + GPIO_FN_CTX1, GPIO_FN_CRX1, + GPIO_FN_CTX0, GPIO_FN_CRX0, + GPIO_FN_CTX0_CTX1, GPIO_FN_CRX0_CRX1, + GPIO_FN_CTX0_CTX1_CTX2, GPIO_FN_CRX0_CRX1_CRX2, + GPIO_FN_CTX2_PJ21, GPIO_FN_CRX2_PJ20, + GPIO_FN_CTX1_PJ23, GPIO_FN_CRX1_PJ22, + GPIO_FN_CTX0_CTX1_PJ23, GPIO_FN_CRX0_CRX1_PJ22, + GPIO_FN_CTX0_CTX1_CTX2_PJ21, GPIO_FN_CRX0_CRX1_CRX2_PJ20, /* DMAC */ GPIO_FN_TEND0, GPIO_FN_DACK0, GPIO_FN_DREQ0, diff --git a/arch/sh/include/cpu-sh4/cpu/sh7734.h b/arch/sh/include/cpu-sh4/cpu/sh7734.h index 2fb9a7b71b412714a17b389688d7f6ca2c1461ed..a2667c9b5819a2146655be3096bab78a27c34484 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7734.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7734.h @@ -133,7 +133,7 @@ enum { GPIO_FN_EX_WAIT1, GPIO_FN_SD1_DAT0_A, GPIO_FN_DREQ2, GPIO_FN_CAN1_TX_C, GPIO_FN_ET0_LINK_C, GPIO_FN_ET0_ETXD5_A, GPIO_FN_EX_WAIT0, GPIO_FN_TCLK1_B, - GPIO_FN_RD_WR, GPIO_FN_TCLK0, + GPIO_FN_RD_WR, GPIO_FN_TCLK0, GPIO_FN_CAN_CLK_B, GPIO_FN_ET0_ETXD4, GPIO_FN_EX_CS5, GPIO_FN_SD1_CMD_A, GPIO_FN_ATADIR, GPIO_FN_QSSL_B, GPIO_FN_ET0_ETXD3_A, GPIO_FN_EX_CS4, GPIO_FN_SD1_WP_A, GPIO_FN_ATAWR, GPIO_FN_QMI_QIO1_B, diff --git a/arch/sh/include/uapi/asm/Kbuild b/arch/sh/include/uapi/asm/Kbuild index 60613ae78513a0c60ed146e9d11a0cf734adc4d0..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/sh/include/uapi/asm/Kbuild +++ b/arch/sh/include/uapi/asm/Kbuild @@ -1,25 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += byteorder.h -header-y += cachectl.h -header-y += cpu-features.h -header-y += hw_breakpoint.h -header-y += ioctls.h -header-y += posix_types.h -header-y += posix_types_32.h -header-y += posix_types_64.h -header-y += ptrace.h -header-y += ptrace_32.h -header-y += ptrace_64.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += sockios.h -header-y += stat.h -header-y += swab.h -header-y += types.h -header-y += unistd.h -header-y += unistd_32.h -header-y += unistd_64.h diff --git a/arch/sparc/include/uapi/asm/Kbuild b/arch/sparc/include/uapi/asm/Kbuild index b5843ee09fb53a6e4438b29140adbd34d9c887c1..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/sparc/include/uapi/asm/Kbuild +++ b/arch/sparc/include/uapi/asm/Kbuild @@ -1,50 +1,2 @@ # UAPI Header export list -# User exported sparc header files - include include/uapi/asm-generic/Kbuild.asm - -header-y += apc.h -header-y += asi.h -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += display7seg.h -header-y += envctrl.h -header-y += errno.h -header-y += fbio.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += jsflash.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += openpromio.h -header-y += param.h -header-y += perfctr.h -header-y += poll.h -header-y += posix_types.h -header-y += psr.h -header-y += psrcompat.h -header-y += pstate.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += traps.h -header-y += uctx.h -header-y += unistd.h -header-y += utrap.h -header-y += watchdog.h diff --git a/arch/sparc/include/uapi/asm/ipcbuf.h b/arch/sparc/include/uapi/asm/ipcbuf.h index 66013b4fe10d5a7e5b25736e3ed1c1068bad5e5d..58da9c4addb2d057af4637e7651afc64b8f25bf7 100644 --- a/arch/sparc/include/uapi/asm/ipcbuf.h +++ b/arch/sparc/include/uapi/asm/ipcbuf.h @@ -14,19 +14,19 @@ struct ipc64_perm { - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; + __kernel_key_t key; + __kernel_uid32_t uid; + __kernel_gid32_t gid; + __kernel_uid32_t cuid; + __kernel_gid32_t cgid; #ifndef __arch64__ - unsigned short __pad0; + unsigned short __pad0; #endif - __kernel_mode_t mode; - unsigned short __pad1; - unsigned short seq; - unsigned long long __unused1; - unsigned long long __unused2; + __kernel_mode_t mode; + unsigned short __pad1; + unsigned short seq; + unsigned long long __unused1; + unsigned long long __unused2; }; #endif /* __SPARC_IPCBUF_H */ diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 572db686f845830a69f0815f7d274eae4927483c..385d6d04564d5650e71b8b6c89723a6abb0b31d5 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -151,12 +151,14 @@ SECTIONS } PERCPU_SECTION(SMP_CACHE_BYTES) -#ifdef CONFIG_JUMP_LABEL . = ALIGN(PAGE_SIZE); .exit.text : { EXIT_TEXT } -#endif + + .exit.data : { + EXIT_DATA + } . = ALIGN(PAGE_SIZE); __init_end = .; diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index ba35c41c71fff33b2b2fe95f566ad8b3dc192c32..bf3e6547c7b7b3d3b28a812a8a47ccc0fba01088 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -1,6 +1,3 @@ - -header-y += ../arch/ - generic-y += bug.h generic-y += bugs.h generic-y += clkdev.h diff --git a/arch/tile/include/uapi/arch/Kbuild b/arch/tile/include/uapi/arch/Kbuild deleted file mode 100644 index 97dfbecec6b6bb36e24cca16d7a1eee4995d8ae4..0000000000000000000000000000000000000000 --- a/arch/tile/include/uapi/arch/Kbuild +++ /dev/null @@ -1,17 +0,0 @@ -# UAPI Header export list -header-y += abi.h -header-y += chip.h -header-y += chip_tilegx.h -header-y += chip_tilepro.h -header-y += icache.h -header-y += interrupts.h -header-y += interrupts_32.h -header-y += interrupts_64.h -header-y += opcode.h -header-y += opcode_tilegx.h -header-y += opcode_tilepro.h -header-y += sim.h -header-y += sim_def.h -header-y += spr_def.h -header-y += spr_def_32.h -header-y += spr_def_64.h diff --git a/arch/tile/include/uapi/asm/Kbuild b/arch/tile/include/uapi/asm/Kbuild index c20db8e428bf698cca387f3c71a29e44f1df48ce..0c74c3c5ebfa4f6a1c47a9ea4c5ce784bc6188ca 100644 --- a/arch/tile/include/uapi/asm/Kbuild +++ b/arch/tile/include/uapi/asm/Kbuild @@ -1,21 +1,4 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += cachectl.h -header-y += hardwall.h -header-y += kvm_para.h -header-y += mman.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += stat.h -header-y += swab.h -header-y += ucontext.h -header-y += unistd.h - generic-y += ucontext.h diff --git a/arch/tile/lib/atomic_asm_32.S b/arch/tile/lib/atomic_asm_32.S index 1a70e6c0f25936f62d8e95a77ec9e97ac1b66dc9..94709ab41ed8e1d053946e56874d7e93d0ae2fd8 100644 --- a/arch/tile/lib/atomic_asm_32.S +++ b/arch/tile/lib/atomic_asm_32.S @@ -24,8 +24,7 @@ * has an opportunity to return -EFAULT to the user if needed. * The 64-bit routines just return a "long long" with the value, * since they are only used from kernel space and don't expect to fault. - * Support for 16-bit ops is included in the framework but we don't provide - * any (x86_64 has an atomic_inc_short(), so we might want to some day). + * Support for 16-bit ops is included in the framework but we don't provide any. * * Note that the caller is advised to issue a suitable L1 or L2 * prefetch on the address being manipulated to avoid extra stalls. diff --git a/arch/unicore32/include/uapi/asm/Kbuild b/arch/unicore32/include/uapi/asm/Kbuild index 0514d7ad68551de6b0e7a7946263bfc6c6249ab0..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 --- a/arch/unicore32/include/uapi/asm/Kbuild +++ b/arch/unicore32/include/uapi/asm/Kbuild @@ -1,10 +1,4 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += byteorder.h -header-y += kvm_para.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += unistd.h - generic-y += kvm_para.h diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 4386440fe4635d7b2dc815815e9f723e5d257056..f09a192260f8ede6802d0f69567422e2aff39081 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -192,7 +192,7 @@ config HAVE_MMIOTRACE_SUPPORT config X86_DECODER_SELFTEST bool "x86 instruction decoder selftest" - depends on DEBUG_KERNEL && KPROBES + depends on DEBUG_KERNEL && INSTRUCTION_DECODER depends on !COMPILE_TEST ---help--- Perform x86 instruction decoder selftests at build time. diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index efdfba21a5b2b4e9c3fb3ef46b3d684187aea6e7..9e3a183561a9abe95f8b8e1f6e9747308ec7fd6b 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -227,6 +227,11 @@ ENTRY(efi32_stub_entry) leal efi32_config(%ebp), %eax movl %eax, efi_config(%ebp) + /* Disable paging */ + movl %cr0, %eax + btrl $X86_CR0_PG_BIT, %eax + movl %eax, %cr0 + jmp startup_32 ENDPROC(efi32_stub_entry) #endif diff --git a/arch/x86/configs/x86_64_cuttlefish_defconfig b/arch/x86/configs/x86_64_cuttlefish_defconfig index 7f1277f371e76bacbdf41ef099804eb024343e39..dced28fe987c29b51bd69e0ad43fa96dad574881 100644 --- a/arch/x86/configs/x86_64_cuttlefish_defconfig +++ b/arch/x86/configs/x86_64_cuttlefish_defconfig @@ -56,7 +56,6 @@ CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 -CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_ZSMALLOC=y # CONFIG_MTRR is not set CONFIG_HZ_100=y diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c index 3f9d1a83891adf9f47cba058078b447fb1de7ecf..50c1f77cab150634000a7a592ce6c63fd594ee41 100644 --- a/arch/x86/entry/vdso/vdso32-setup.c +++ b/arch/x86/entry/vdso/vdso32-setup.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index 00b56cc69d37997df51e8558ec29726b88322eaf..836b7e4a2005beee758a6a7af3090322a9068f43 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c @@ -239,6 +239,7 @@ static const u64 amd_f17h_perfmon_event_map[PERF_COUNT_HW_MAX] = [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, [PERF_COUNT_HW_CACHE_REFERENCES] = 0xff60, + [PERF_COUNT_HW_CACHE_MISSES] = 0x0964, [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x0287, diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c index c16c99bc2a1096435d93959ccc91105a0b1686e3..6bfb9a68134c10bce9c6af1fcb4bbd5171a83a4a 100644 --- a/arch/x86/events/amd/uncore.c +++ b/arch/x86/events/amd/uncore.c @@ -185,20 +185,18 @@ static int amd_uncore_event_init(struct perf_event *event) /* * NB and Last level cache counters (MSRs) are shared across all cores - * that share the same NB / Last level cache. Interrupts can be directed - * to a single target core, however, event counts generated by processes - * running on other cores cannot be masked out. So we do not support - * sampling and per-thread events. + * that share the same NB / Last level cache. On family 16h and below, + * Interrupts can be directed to a single target core, however, event + * counts generated by processes running on other cores cannot be masked + * out. So we do not support sampling and per-thread events via + * CAP_NO_INTERRUPT, and we do not enable counter overflow interrupts: */ - if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) - return -EINVAL; /* NB and Last level cache counters do not have usr/os/guest/host bits */ if (event->attr.exclude_user || event->attr.exclude_kernel || event->attr.exclude_host || event->attr.exclude_guest) return -EINVAL; - /* and we do not enable counter overflow interrupts */ hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB; hwc->idx = -1; @@ -275,6 +273,7 @@ static struct pmu amd_nb_pmu = { .start = amd_uncore_start, .stop = amd_uncore_stop, .read = amd_uncore_read, + .capabilities = PERF_PMU_CAP_NO_INTERRUPT, }; static struct pmu amd_llc_pmu = { @@ -287,6 +286,7 @@ static struct pmu amd_llc_pmu = { .start = amd_uncore_start, .stop = amd_uncore_stop, .read = amd_uncore_read, + .capabilities = PERF_PMU_CAP_NO_INTERRUPT, }; static struct amd_uncore *amd_uncore_alloc(unsigned int cpu) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 1e9f610d36a4ae1586834973470c66aaf3e638b1..c26cca506f6463c8cb9473f5f8ea82ff1c4fee6c 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -374,7 +374,7 @@ int x86_add_exclusive(unsigned int what) * LBR and BTS are still mutually exclusive. */ if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt) - return 0; + goto out; if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) { mutex_lock(&pmc_reserve_mutex); @@ -386,6 +386,7 @@ int x86_add_exclusive(unsigned int what) mutex_unlock(&pmc_reserve_mutex); } +out: atomic_inc(&active_events); return 0; @@ -396,11 +397,15 @@ int x86_add_exclusive(unsigned int what) void x86_del_exclusive(unsigned int what) { + atomic_dec(&active_events); + + /* + * See the comment in x86_add_exclusive(). + */ if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt) return; atomic_dec(&x86_pmu.lbr_exclusive[what]); - atomic_dec(&active_events); } int x86_setup_perfctr(struct perf_event *event) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index ad31c01f810fdcc7c026a13f4e348973812fa26d..f562ddbeb20c613a89f5cc16e7f28fa0bb36458f 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1326,6 +1326,8 @@ intel_pmu_save_and_restart_reload(struct perf_event *event, int count) old = ((s64)(prev_raw_count << shift) >> shift); local64_add(new - old + count * period, &event->count); + local64_set(&hwc->period_left, -new); + perf_event_update_userpage(event); return 0; diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 76a35c1213d24effa00bee5f94960eb847c28a4b..305c6eed91410b325761c91991925ceb4431bda9 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -249,19 +249,6 @@ static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u) return c; } -/** - * atomic_inc_short - increment of a short integer - * @v: pointer to type int - * - * Atomically adds 1 to @v - * Returns the new value of @u - */ -static __always_inline short int atomic_inc_short(short int *v) -{ - asm(LOCK_PREFIX "addw $1, %0" : "+m" (*v)); - return *v; -} - #ifdef CONFIG_X86_32 # include #else diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index ccc4420f051b9b1edc75fbf7d29e96004ae1b00d..fb457ba8ccc65fad846e430c36fc20edec5fa59d 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -305,6 +305,7 @@ /* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ #define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ #define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ +#define X86_FEATURE_RDPID (16*32+ 22) /* RDPID instruction */ /* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */ #define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */ diff --git a/arch/x86/include/asm/crash.h b/arch/x86/include/asm/crash.h index f498411f2500bfc57103d84f4123be5193122c86..1b15304dd0980fb9d2732299d90aa14551e7a690 100644 --- a/arch/x86/include/asm/crash.h +++ b/arch/x86/include/asm/crash.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_CRASH_H #define _ASM_X86_CRASH_H +struct kimage; + int crash_load_segments(struct kimage *image); int crash_copy_backup_region(struct kimage *image); int crash_setup_memmap_entries(struct kimage *image, diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 8554f960e21b7ce0d05dfb67fa36f6cff974650e..61d6f2c05757260974c851010b1c0a144fdf5c98 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -142,7 +142,7 @@ extern pte_t *kmap_pte; extern pte_t *pkmap_page_table; void __native_set_fixmap(enum fixed_addresses idx, pte_t pte); -void native_set_fixmap(enum fixed_addresses idx, +void native_set_fixmap(unsigned /* enum fixed_addresses */ idx, phys_addr_t phys, pgprot_t flags); #ifndef CONFIG_PARAVIRT diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h index e728699db7741f0282441a79635a88afd23259c8..3a01996db58fbf7bfa41ca52c86f323d4bb6c937 100644 --- a/arch/x86/include/asm/vgtod.h +++ b/arch/x86/include/asm/vgtod.h @@ -89,8 +89,13 @@ static inline unsigned int __getcpu(void) * works on all CPUs. This is volatile so that it orders * correctly wrt barrier() and to keep gcc from cleverly * hoisting it out of the calling function. + * + * If RDPID is available, use it. */ - asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); + alternative_io ("lsl %[p],%[seg]", + ".byte 0xf3,0x0f,0xc7,0xf8", /* RDPID %eax/rax */ + X86_FEATURE_RDPID, + [p] "=a" (p), [seg] "r" (__PER_CPU_SEG)); return p; } diff --git a/arch/x86/include/uapi/asm/Kbuild b/arch/x86/include/uapi/asm/Kbuild index 1c532b3f18ea84da0ce4843a66be7215a5ed0a55..da1489cb64dce5fcec622f2869cd26d2b58d00ac 100644 --- a/arch/x86/include/uapi/asm/Kbuild +++ b/arch/x86/include/uapi/asm/Kbuild @@ -1,64 +1,6 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -genhdr-y += unistd_32.h -genhdr-y += unistd_64.h -genhdr-y += unistd_x32.h -header-y += a.out.h -header-y += auxvec.h -header-y += bitsperlong.h -header-y += boot.h -header-y += bootparam.h -header-y += byteorder.h -header-y += debugreg.h -header-y += e820.h -header-y += errno.h -header-y += fcntl.h -header-y += hw_breakpoint.h -header-y += hyperv.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += ist.h -header-y += kvm.h -header-y += kvm_para.h -header-y += kvm_perf.h -header-y += ldt.h -header-y += mce.h -header-y += mman.h -header-y += msgbuf.h -header-y += msr.h -header-y += mtrr.h -header-y += param.h -header-y += perf_regs.h -header-y += poll.h -header-y += posix_types.h -header-y += posix_types_32.h -header-y += posix_types_64.h -header-y += posix_types_x32.h -header-y += prctl.h -header-y += processor-flags.h -header-y += ptrace-abi.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += sigcontext32.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += svm.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h -header-y += vm86.h -header-y += vmx.h -header-y += vsyscall.h +generated-y += unistd_32.h +generated-y += unistd_64.h +generated-y += unistd_x32.h diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 09dd95cabfc285e3ae2d86647f6613b7d922fde7..3401b28f131211c1fac82958b9301c9c6ceff8db 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1712,9 +1712,10 @@ static bool io_apic_level_ack_pending(struct mp_chip_data *data) static inline bool ioapic_irqd_mask(struct irq_data *data) { - /* If we are moving the irq we need to mask it */ + /* If we are moving the IRQ we need to mask it */ if (unlikely(irqd_is_setaffinity_pending(data))) { - mask_ioapic_irq(data); + if (!irqd_irq_masked(data)) + mask_ioapic_irq(data); return true; } return false; @@ -1751,7 +1752,9 @@ static inline void ioapic_irqd_unmask(struct irq_data *data, bool masked) */ if (!io_apic_level_ack_pending(data->chip_data)) irq_move_masked_irq(data); - unmask_ioapic_irq(data); + /* If the IRQ is masked in the core, leave it: */ + if (!irqd_irq_masked(data)) + unmask_ioapic_irq(data); } } #else diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 477df9782fdfe5ec4dcce10e8c4a1f6339bb509d..f490a4fab2f71d8b2c692ae94aea201921b2262c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -388,7 +388,7 @@ static __always_inline void setup_pku(struct cpuinfo_x86 *c) * cpuid bit to be set. We need to ensure that we * update that bit in this CPU's "cpu_info". */ - get_cpu_cap(c); + set_cpu_cap(c, X86_FEATURE_OSPKE); } #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index e348bee411e356ec0f9579b725547d7a69bebf96..07188a0124922f4ba31d2350ba4c228b1b860e51 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -782,8 +782,8 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, if (quirk_no_way_out) quirk_no_way_out(i, m, regs); + m->bank = i; if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) { - m->bank = i; mce_read_aux(m, i); *msg = tmp; return 1; @@ -1648,36 +1648,6 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) if (c->x86 == 0x15 && c->x86_model <= 0xf) mce_flags.overflow_recov = 1; - /* - * Turn off MC4_MISC thresholding banks on those models since - * they're not supported there. - */ - if (c->x86 == 0x15 && - (c->x86_model >= 0x10 && c->x86_model <= 0x1f)) { - int i; - u64 hwcr; - bool need_toggle; - u32 msrs[] = { - 0x00000413, /* MC4_MISC0 */ - 0xc0000408, /* MC4_MISC1 */ - }; - - rdmsrl(MSR_K7_HWCR, hwcr); - - /* McStatusWrEn has to be set */ - need_toggle = !(hwcr & BIT(18)); - - if (need_toggle) - wrmsrl(MSR_K7_HWCR, hwcr | BIT(18)); - - /* Clear CntP bit safely */ - for (i = 0; i < ARRAY_SIZE(msrs); i++) - msr_clear_bit(msrs[i], 62); - - /* restore old settings */ - if (need_toggle) - wrmsrl(MSR_K7_HWCR, hwcr); - } } if (c->x86_vendor == X86_VENDOR_INTEL) { diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 39526e1e3132dd1b098d8c4e0429a1aaeca35152..775d5f028fe832fca54d28a3ca98a29821fc08f9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -499,6 +499,40 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr, return offset; } +/* + * Turn off MC4_MISC thresholding banks on all family 0x15 models since + * they're not supported there. + */ +void disable_err_thresholding(struct cpuinfo_x86 *c) +{ + int i; + u64 hwcr; + bool need_toggle; + u32 msrs[] = { + 0x00000413, /* MC4_MISC0 */ + 0xc0000408, /* MC4_MISC1 */ + }; + + if (c->x86 != 0x15) + return; + + rdmsrl(MSR_K7_HWCR, hwcr); + + /* McStatusWrEn has to be set */ + need_toggle = !(hwcr & BIT(18)); + + if (need_toggle) + wrmsrl(MSR_K7_HWCR, hwcr | BIT(18)); + + /* Clear CntP bit safely */ + for (i = 0; i < ARRAY_SIZE(msrs); i++) + msr_clear_bit(msrs[i], 62); + + /* restore old settings */ + if (need_toggle) + wrmsrl(MSR_K7_HWCR, hwcr); +} + /* cpu init entry point, called from mce.c with preempt off */ void mce_amd_feature_init(struct cpuinfo_x86 *c) { @@ -506,6 +540,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) unsigned int bank, block, cpu = smp_processor_id(); int offset = -1; + disable_err_thresholding(c); + for (bank = 0; bank < mca_cfg.banks; ++bank) { if (mce_flags.smca) get_smca_bank_info(bank); @@ -810,9 +846,12 @@ static const struct sysfs_ops threshold_ops = { .store = store, }; +static void threshold_block_release(struct kobject *kobj); + static struct kobj_type threshold_ktype = { .sysfs_ops = &threshold_ops, .default_attrs = default_attrs, + .release = threshold_block_release, }; static const char *get_name(unsigned int bank, struct threshold_block *b) @@ -843,8 +882,9 @@ static const char *get_name(unsigned int bank, struct threshold_block *b) return buf_mcatype; } -static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank, - unsigned int block, u32 address) +static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb, + unsigned int bank, unsigned int block, + u32 address) { struct threshold_block *b = NULL; u32 low, high; @@ -888,16 +928,12 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank, INIT_LIST_HEAD(&b->miscj); - if (per_cpu(threshold_banks, cpu)[bank]->blocks) { - list_add(&b->miscj, - &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj); - } else { - per_cpu(threshold_banks, cpu)[bank]->blocks = b; - } + if (tb->blocks) + list_add(&b->miscj, &tb->blocks->miscj); + else + tb->blocks = b; - err = kobject_init_and_add(&b->kobj, &threshold_ktype, - per_cpu(threshold_banks, cpu)[bank]->kobj, - get_name(bank, b)); + err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b)); if (err) goto out_free; recurse: @@ -905,7 +941,7 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank, if (!address) return 0; - err = allocate_threshold_blocks(cpu, bank, block, address); + err = allocate_threshold_blocks(cpu, tb, bank, block, address); if (err) goto out_free; @@ -990,8 +1026,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank) goto out_free; } - per_cpu(threshold_banks, cpu)[bank] = b; - if (is_shared_bank(bank)) { atomic_set(&b->cpus, 1); @@ -1002,9 +1036,13 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank) } } - err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank)); - if (!err) - goto out; + err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank)); + if (err) + goto out_free; + + per_cpu(threshold_banks, cpu)[bank] = b; + + return 0; out_free: kfree(b); @@ -1038,8 +1076,12 @@ static int threshold_create_device(unsigned int cpu) return err; } -static void deallocate_threshold_block(unsigned int cpu, - unsigned int bank) +static void threshold_block_release(struct kobject *kobj) +{ + kfree(to_block(kobj)); +} + +static void deallocate_threshold_block(unsigned int cpu, unsigned int bank) { struct threshold_block *pos = NULL; struct threshold_block *tmp = NULL; @@ -1049,13 +1091,11 @@ static void deallocate_threshold_block(unsigned int cpu, return; list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) { - kobject_put(&pos->kobj); list_del(&pos->miscj); - kfree(pos); + kobject_put(&pos->kobj); } - kfree(per_cpu(threshold_banks, cpu)[bank]->blocks); - per_cpu(threshold_banks, cpu)[bank]->blocks = NULL; + kobject_put(&head->blocks->kobj); } static void __threshold_remove_blocks(struct threshold_bank *b) diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index c460c91d0c8fd3ae89735874d695d6e03b5ed1df..be2439592b0ecdd7e3c4129cbf9a776e5e3db627 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -190,7 +190,7 @@ static int therm_throt_process(bool new_event, int event, int level) /* if we just entered the thermal event */ if (new_event) { if (event == THERMAL_THROTTLING_EVENT) - pr_crit("CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n", + pr_warn("CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n", this_cpu, level == CORE_LEVEL ? "Core" : "Package", state->count); diff --git a/arch/x86/kernel/cpu/tsx.c b/arch/x86/kernel/cpu/tsx.c index 3e20d322bc98b636cde2747394d26fcec8783a0c..032509adf9de9f664e808083955de464a35f9d34 100644 --- a/arch/x86/kernel/cpu/tsx.c +++ b/arch/x86/kernel/cpu/tsx.c @@ -115,11 +115,12 @@ void __init tsx_init(void) tsx_disable(); /* - * tsx_disable() will change the state of the - * RTM CPUID bit. Clear it here since it is now - * expected to be not set. + * tsx_disable() will change the state of the RTM and HLE CPUID + * bits. Clear them here since they are now expected to be not + * set. */ setup_clear_cpu_cap(X86_FEATURE_RTM); + setup_clear_cpu_cap(X86_FEATURE_HLE); } else if (tsx_ctrl_state == TSX_CTRL_ENABLE) { /* @@ -131,10 +132,10 @@ void __init tsx_init(void) tsx_enable(); /* - * tsx_enable() will change the state of the - * RTM CPUID bit. Force it here since it is now - * expected to be set. + * tsx_enable() will change the state of the RTM and HLE CPUID + * bits. Force them here since they are now expected to be set. */ setup_force_cpu_cap(X86_FEATURE_RTM); + setup_force_cpu_cap(X86_FEATURE_HLE); } } diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 8e36f249646e25d20bc2bcc04b7a0ccc292e498c..904e18bb38c52d50b9e3913a417984652614b325 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -438,7 +438,7 @@ static void kgdb_disable_hw_debug(struct pt_regs *regs) */ void kgdb_roundup_cpus(unsigned long flags) { - apic->send_IPI_allbutself(APIC_DM_NMI); + apic->send_IPI_allbutself(NMI_VECTOR); } #endif diff --git a/arch/x86/kernel/sysfb_simplefb.c b/arch/x86/kernel/sysfb_simplefb.c index 85195d447a922785857db0caacc73d6bc9b9490c..f3215346e47fd8d822191d9ff879896e1f5e7a4f 100644 --- a/arch/x86/kernel/sysfb_simplefb.c +++ b/arch/x86/kernel/sysfb_simplefb.c @@ -94,11 +94,11 @@ __init int create_simplefb(const struct screen_info *si, if (si->orig_video_isVGA == VIDEO_TYPE_VLFB) size <<= 16; length = mode->height * mode->stride; - length = PAGE_ALIGN(length); if (length > size) { printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n"); return -EINVAL; } + length = PAGE_ALIGN(length); /* setup IORESOURCE_MEM as framebuffer memory */ memset(&res, 0, sizeof(res)); diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 18c5b4920e92a9c419a582ba4d0c76b8fd5968db..c57dab0884fed2fad066bdffdec2420492063fc9 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -279,13 +279,18 @@ static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry, { switch (func) { case 0: - entry->eax = 1; /* only one leaf currently */ + entry->eax = 7; ++*nent; break; case 1: entry->ecx = F(MOVBE); ++*nent; break; + case 7: + entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; + if (index == 0) + entry->ecx = F(RDPID); + ++*nent; default: break; } @@ -389,7 +394,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, r = -E2BIG; - if (*nent >= maxnent) + if (WARN_ON(*nent >= maxnent)) goto out; do_cpuid_1_ent(entry, function, index); @@ -691,6 +696,9 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 func, u32 idx, int *nent, int maxnent, unsigned int type) { + if (*nent >= maxnent) + return -E2BIG; + if (type == KVM_GET_EMULATED_CPUID) return __do_cpuid_ent_emulated(entry, func, idx, nent, maxnent); diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 660c35f854f8b6d11d2735512a5b0e8f9591de06..da3cd734dee10c5408957b883e50f7e30e87c859 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -21,6 +21,7 @@ */ #include +#include #include "kvm_cache_regs.h" #include #include @@ -3530,6 +3531,16 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } +static int em_rdpid(struct x86_emulate_ctxt *ctxt) +{ + u64 tsc_aux = 0; + + if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux)) + return emulate_gp(ctxt, 0); + ctxt->dst.val = tsc_aux; + return X86EMUL_CONTINUE; +} + static int em_rdtsc(struct x86_emulate_ctxt *ctxt) { u64 tsc = 0; @@ -4390,10 +4401,20 @@ static const struct opcode group8[] = { F(DstMem | SrcImmByte | Lock | PageTable, em_btc), }; +/* + * The "memory" destination is actually always a register, since we come + * from the register case of group9. + */ +static const struct gprefix pfx_0f_c7_7 = { + N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp), +}; + + static const struct group_dual group9 = { { N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N, }, { - N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, + GP(0, &pfx_0f_c7_7), } }; static const struct opcode group11[] = { @@ -5001,6 +5022,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ctxt->fetch.ptr = ctxt->fetch.data; ctxt->fetch.end = ctxt->fetch.data + insn_len; ctxt->opcode_len = 1; + ctxt->intercept = x86_intercept_none; if (insn_len > 0) memcpy(ctxt->fetch.data, insn, insn_len); else { @@ -5053,16 +5075,28 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ctxt->ad_bytes = def_ad_bytes ^ 6; break; case 0x26: /* ES override */ + has_seg_override = true; + ctxt->seg_override = VCPU_SREG_ES; + break; case 0x2e: /* CS override */ + has_seg_override = true; + ctxt->seg_override = VCPU_SREG_CS; + break; case 0x36: /* SS override */ + has_seg_override = true; + ctxt->seg_override = VCPU_SREG_SS; + break; case 0x3e: /* DS override */ has_seg_override = true; - ctxt->seg_override = (ctxt->b >> 3) & 3; + ctxt->seg_override = VCPU_SREG_DS; break; case 0x64: /* FS override */ + has_seg_override = true; + ctxt->seg_override = VCPU_SREG_FS; + break; case 0x65: /* GS override */ has_seg_override = true; - ctxt->seg_override = ctxt->b & 7; + ctxt->seg_override = VCPU_SREG_GS; break; case 0x40 ... 0x4f: /* REX */ if (mode != X86EMUL_MODE_PROT64) @@ -5146,10 +5180,15 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) } break; case Escape: - if (ctxt->modrm > 0xbf) - opcode = opcode.u.esc->high[ctxt->modrm - 0xc0]; - else + if (ctxt->modrm > 0xbf) { + size_t size = ARRAY_SIZE(opcode.u.esc->high); + u32 index = array_index_nospec( + ctxt->modrm - 0xc0, size); + + opcode = opcode.u.esc->high[index]; + } else { opcode = opcode.u.esc->op[(ctxt->modrm >> 3) & 7]; + } break; case InstrDual: if ((ctxt->modrm >> 6) == 3) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 42b1c83741c8f515ae37a5eb85bc87067f9f48f1..5e837c96e93f26845c976d4f6f50ad52a1adc24d 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -719,11 +720,12 @@ static int kvm_hv_msr_get_crash_data(struct kvm_vcpu *vcpu, u32 index, u64 *pdata) { struct kvm_hv *hv = &vcpu->kvm->arch.hyperv; + size_t size = ARRAY_SIZE(hv->hv_crash_param); - if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param))) + if (WARN_ON_ONCE(index >= size)) return -EINVAL; - *pdata = hv->hv_crash_param[index]; + *pdata = hv->hv_crash_param[array_index_nospec(index, size)]; return 0; } @@ -762,11 +764,12 @@ static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu, u32 index, u64 data) { struct kvm_hv *hv = &vcpu->kvm->arch.hyperv; + size_t size = ARRAY_SIZE(hv->hv_crash_param); - if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param))) + if (WARN_ON_ONCE(index >= size)) return -EINVAL; - hv->hv_crash_param[index] = data; + hv->hv_crash_param[array_index_nospec(index, size)] = data; return 0; } diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index 5f810bb80802ce1c7640e7616786e86fa596a738..aa34b16e62c24790d7c516bde0bc34500ba90970 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -73,13 +74,14 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, default: { u32 redir_index = (ioapic->ioregsel - 0x10) >> 1; - u64 redir_content; + u64 redir_content = ~0ULL; - if (redir_index < IOAPIC_NUM_PINS) - redir_content = - ioapic->redirtbl[redir_index].bits; - else - redir_content = ~0ULL; + if (redir_index < IOAPIC_NUM_PINS) { + u32 index = array_index_nospec( + redir_index, IOAPIC_NUM_PINS); + + redir_content = ioapic->redirtbl[index].bits; + } result = (ioapic->ioregsel & 0x1) ? (redir_content >> 32) & 0xffffffff : @@ -299,6 +301,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) ioapic_debug("change redir index %x val %x\n", index, val); if (index >= IOAPIC_NUM_PINS) return; + index = array_index_nospec(index, IOAPIC_NUM_PINS); e = &ioapic->redirtbl[index]; mask_before = e->fields.mask; /* Preserve read-only fields */ diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c index 6c0191615f23a34bae5c0972a20025cf5b695af9..cf8b3c17657a4ef52e267d21985c42b94d1334f4 100644 --- a/arch/x86/kvm/irq_comm.c +++ b/arch/x86/kvm/irq_comm.c @@ -436,7 +436,7 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu, kvm_set_msi_irq(vcpu->kvm, entry, &irq); - if (irq.level && kvm_apic_match_dest(vcpu, NULL, 0, + if (irq.trig_mode && kvm_apic_match_dest(vcpu, NULL, 0, irq.dest_id, irq.dest_mode)) __set_bit(irq.vector, ioapic_handled_vectors); } diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index cf32533225bb1c0333a48529c3bf7be3cc460cc0..3988e26af3b588aed1a19aae7c20158ce67ffa7a 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -531,9 +532,11 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu) static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu) { u8 val; - if (pv_eoi_get_user(vcpu, &val) < 0) + if (pv_eoi_get_user(vcpu, &val) < 0) { apic_debug("Can't read EOI MSR value: 0x%llx\n", (unsigned long long)vcpu->arch.pv_eoi.msr_val); + return false; + } return val & 0x1; } @@ -1587,15 +1590,20 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) case APIC_LVTTHMR: case APIC_LVTPC: case APIC_LVT1: - case APIC_LVTERR: + case APIC_LVTERR: { /* TODO: Check vector */ + size_t size; + u32 index; + if (!kvm_apic_sw_enabled(apic)) val |= APIC_LVT_MASKED; - - val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4]; + size = ARRAY_SIZE(apic_lvt_mask); + index = array_index_nospec( + (reg - APIC_LVTT) >> 4, size); + val &= apic_lvt_mask[index]; kvm_lapic_set_reg(apic, reg, val); - break; + } case APIC_LVTT: if (!kvm_apic_sw_enabled(apic)) diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c index 0149ac59c273c15921bbe2a8cff7d9427e6a0976..3e3016411020649d2c2c6f3c20375767ed80eab7 100644 --- a/arch/x86/kvm/mtrr.c +++ b/arch/x86/kvm/mtrr.c @@ -17,6 +17,7 @@ */ #include +#include #include #include "cpuid.h" @@ -202,11 +203,15 @@ static bool fixed_msr_to_seg_unit(u32 msr, int *seg, int *unit) break; case MSR_MTRRfix16K_80000 ... MSR_MTRRfix16K_A0000: *seg = 1; - *unit = msr - MSR_MTRRfix16K_80000; + *unit = array_index_nospec( + msr - MSR_MTRRfix16K_80000, + MSR_MTRRfix16K_A0000 - MSR_MTRRfix16K_80000 + 1); break; case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000: *seg = 2; - *unit = msr - MSR_MTRRfix4K_C0000; + *unit = array_index_nospec( + msr - MSR_MTRRfix4K_C0000, + MSR_MTRRfix4K_F8000 - MSR_MTRRfix4K_C0000 + 1); break; default: return false; diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index f96e1f9625873d0a8faea96a18ad1fa8aa7655ef..fbf3d25af765844f6fa8bf93e2e5630a0e3173ec 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -1,6 +1,8 @@ #ifndef __KVM_X86_PMU_H #define __KVM_X86_PMU_H +#include + #define vcpu_to_pmu(vcpu) (&(vcpu)->arch.pmu) #define pmu_to_vcpu(pmu) (container_of((pmu), struct kvm_vcpu, arch.pmu)) #define pmc_to_pmu(pmc) (&(pmc)->vcpu->arch.pmu) @@ -80,8 +82,12 @@ static inline bool pmc_is_enabled(struct kvm_pmc *pmc) static inline struct kvm_pmc *get_gp_pmc(struct kvm_pmu *pmu, u32 msr, u32 base) { - if (msr >= base && msr < base + pmu->nr_arch_gp_counters) - return &pmu->gp_counters[msr - base]; + if (msr >= base && msr < base + pmu->nr_arch_gp_counters) { + u32 index = array_index_nospec(msr - base, + pmu->nr_arch_gp_counters); + + return &pmu->gp_counters[index]; + } return NULL; } @@ -91,8 +97,12 @@ static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr) { int base = MSR_CORE_PERF_FIXED_CTR0; - if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) - return &pmu->fixed_counters[msr - base]; + if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) { + u32 index = array_index_nospec(msr - base, + pmu->nr_arch_fixed_counters); + + return &pmu->fixed_counters[index]; + } return NULL; } diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c index 2729131fe9bfc6d68160100a65e587cd53127622..84ae4dd261caff611a6dff9bd3aae3360a0f37c3 100644 --- a/arch/x86/kvm/pmu_intel.c +++ b/arch/x86/kvm/pmu_intel.c @@ -87,10 +87,14 @@ static unsigned intel_find_arch_event(struct kvm_pmu *pmu, static unsigned intel_find_fixed_event(int idx) { - if (idx >= ARRAY_SIZE(fixed_pmc_events)) + u32 event; + size_t size = ARRAY_SIZE(fixed_pmc_events); + + if (idx >= size) return PERF_COUNT_HW_MAX; - return intel_arch_events[fixed_pmc_events[idx]].event_type; + event = fixed_pmc_events[array_index_nospec(idx, size)]; + return intel_arch_events[event].event_type; } /* check if a PMC is enabled by comparing it with globl_ctrl bits. */ @@ -131,15 +135,19 @@ static struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu, struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); bool fixed = idx & (1u << 30); struct kvm_pmc *counters; + unsigned int num_counters; idx &= ~(3u << 30); - if (!fixed && idx >= pmu->nr_arch_gp_counters) - return NULL; - if (fixed && idx >= pmu->nr_arch_fixed_counters) + if (fixed) { + counters = pmu->fixed_counters; + num_counters = pmu->nr_arch_fixed_counters; + } else { + counters = pmu->gp_counters; + num_counters = pmu->nr_arch_gp_counters; + } + if (idx >= num_counters) return NULL; - counters = fixed ? pmu->fixed_counters : pmu->gp_counters; - - return &counters[idx]; + return &counters[array_index_nospec(idx, num_counters)]; } static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 8e78252973c4d762cff52ba89a5ee6cd3a96cea8..ef97339f3f67fd64b3a9e2e81f7408502f64d6e2 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4641,6 +4641,26 @@ static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu) (ss.selector & SEGMENT_RPL_MASK)); } +static bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, + unsigned int port, int size); +static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12) +{ + unsigned long exit_qualification; + unsigned short port; + int size; + + if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS)) + return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING); + + exit_qualification = vmcs_readl(EXIT_QUALIFICATION); + + port = exit_qualification >> 16; + size = (exit_qualification & 7) + 1; + + return nested_vmx_check_io_bitmaps(vcpu, port, size); +} + /* * Check if guest state is valid. Returns true if valid, false if * not. @@ -7653,8 +7673,10 @@ static int handle_vmread(struct kvm_vcpu *vcpu) /* _system ok, as nested_vmx_check_permission verified cpl=0 */ if (kvm_write_guest_virt_system(vcpu, gva, &field_value, (is_long_mode(vcpu) ? 8 : 4), - &e)) + &e)) { kvm_inject_page_fault(vcpu, &e); + return 1; + } } nested_vmx_succeed(vcpu); @@ -8024,23 +8046,17 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { static const int kvm_vmx_max_exit_handlers = ARRAY_SIZE(kvm_vmx_exit_handlers); -static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12) +/* + * Return true if an IO instruction with the specified port and size should cause + * a VM-exit into L1. + */ +bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port, + int size) { - unsigned long exit_qualification; + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); gpa_t bitmap, last_bitmap; - unsigned int port; - int size; u8 b; - if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS)) - return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING); - - exit_qualification = vmcs_readl(EXIT_QUALIFICATION); - - port = exit_qualification >> 16; - size = (exit_qualification & 7) + 1; - last_bitmap = (gpa_t)-1; b = -1; @@ -11332,11 +11348,71 @@ static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, to_vmx(vcpu)->nested.sync_shadow_vmcs = true; } +static int vmx_check_intercept_io(struct kvm_vcpu *vcpu, + struct x86_instruction_info *info) +{ + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + unsigned short port; + bool intercept; + int size; + + if (info->intercept == x86_intercept_in || + info->intercept == x86_intercept_ins) { + port = info->src_val; + size = info->dst_bytes; + } else { + port = info->dst_val; + size = info->src_bytes; + } + + /* + * If the 'use IO bitmaps' VM-execution control is 0, IO instruction + * VM-exits depend on the 'unconditional IO exiting' VM-execution + * control. + * + * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps. + */ + if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS)) + intercept = nested_cpu_has(vmcs12, + CPU_BASED_UNCOND_IO_EXITING); + else + intercept = nested_vmx_check_io_bitmaps(vcpu, port, size); + + return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; +} + static int vmx_check_intercept(struct kvm_vcpu *vcpu, struct x86_instruction_info *info, enum x86_intercept_stage stage) { - return X86EMUL_CONTINUE; + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; + + switch (info->intercept) { + /* + * RDPID causes #UD if disabled through secondary execution controls. + * Because it is marked as EmulateOnUD, we need to intercept it here. + */ + case x86_intercept_rdtscp: + if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) { + ctxt->exception.vector = UD_VECTOR; + ctxt->exception.error_code_valid = false; + return X86EMUL_PROPAGATE_FAULT; + } + break; + + case x86_intercept_in: + case x86_intercept_ins: + case x86_intercept_out: + case x86_intercept_outs: + return vmx_check_intercept_io(vcpu, info); + + /* TODO: check more intercepts... */ + default: + break; + } + + return X86EMUL_UNHANDLEABLE; } #ifdef CONFIG_X86_64 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 06cd710e1d45c33ddc4bca551dbf4ed79cc8d8b4..43aabd72019b0bc08cd5e2b953a89b7909ca6210 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -273,13 +274,14 @@ int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); int err; - if (((value ^ smsr->values[slot].curr) & mask) == 0) + value = (value & mask) | (smsr->values[slot].host & ~mask); + if (value == smsr->values[slot].curr) return 0; - smsr->values[slot].curr = value; err = wrmsrl_safe(shared_msrs_global.msrs[slot], value); if (err) return 1; + smsr->values[slot].curr = value; if (!smsr->registered) { smsr->urn.on_user_return = kvm_on_user_return; user_return_notifier_register(&smsr->urn); @@ -888,9 +890,11 @@ static u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu) static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) { + size_t size = ARRAY_SIZE(vcpu->arch.db); + switch (dr) { case 0 ... 3: - vcpu->arch.db[dr] = val; + vcpu->arch.db[array_index_nospec(dr, size)] = val; if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) vcpu->arch.eff_db[dr] = val; break; @@ -927,9 +931,11 @@ EXPORT_SYMBOL_GPL(kvm_set_dr); int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) { + size_t size = ARRAY_SIZE(vcpu->arch.db); + switch (dr) { case 0 ... 3: - *val = vcpu->arch.db[dr]; + *val = vcpu->arch.db[array_index_nospec(dr, size)]; break; case 4: /* fall through */ @@ -1074,10 +1080,15 @@ u64 kvm_get_arch_capabilities(void) * If TSX is disabled on the system, guests are also mitigated against * TAA and clear CPU buffer mitigation is not required for guests. */ - if (boot_cpu_has_bug(X86_BUG_TAA) && boot_cpu_has(X86_FEATURE_RTM) && - (data & ARCH_CAP_TSX_CTRL_MSR)) + if (!boot_cpu_has(X86_FEATURE_RTM)) + data &= ~ARCH_CAP_TAA_NO; + else if (!boot_cpu_has_bug(X86_BUG_TAA)) + data |= ARCH_CAP_TAA_NO; + else if (data & ARCH_CAP_TSX_CTRL_MSR) data &= ~ARCH_CAP_MDS_NO; + /* KVM does not emulate MSR_IA32_TSX_CTRL. */ + data &= ~ARCH_CAP_TSX_CTRL_MSR; return data; } @@ -2119,7 +2130,10 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 data) default: if (msr >= MSR_IA32_MC0_CTL && msr < MSR_IA32_MCx_CTL(bank_num)) { - u32 offset = msr - MSR_IA32_MC0_CTL; + u32 offset = array_index_nospec( + msr - MSR_IA32_MC0_CTL, + MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL); + /* only 0 or all 1s can be written to IA32_MCi_CTL * some Linux kernels though clear bit 10 in bank 4 to * workaround a BIOS/GART TBL issue on AMD K8s, ignore @@ -2487,7 +2501,10 @@ static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) default: if (msr >= MSR_IA32_MC0_CTL && msr < MSR_IA32_MCx_CTL(bank_num)) { - u32 offset = msr - MSR_IA32_MC0_CTL; + u32 offset = array_index_nospec( + msr - MSR_IA32_MC0_CTL, + MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL); + data = vcpu->arch.mce_banks[offset]; break; } @@ -6115,14 +6132,12 @@ static void kvm_set_mmio_spte_mask(void) /* Set the present bit. */ mask |= 1ull; -#ifdef CONFIG_X86_64 /* * If reserved bit is not supported, clear the present bit to disable * mmio page fault. */ if (maxphyaddr == 52) mask &= ~1ull; -#endif kvm_mmu_set_mmio_spte_mask(mask); } @@ -7792,7 +7807,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) kvm_mmu_unload(vcpu); vcpu_put(vcpu); - kvm_x86_ops->vcpu_free(vcpu); + kvm_arch_vcpu_free(vcpu); } void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt index 1754e094bc288014e1e173fe0858ebb6d9b5f1b3..82e105b284e01803a5c8520836ebf1dd7b591187 100644 --- a/arch/x86/lib/x86-opcode-map.txt +++ b/arch/x86/lib/x86-opcode-map.txt @@ -333,7 +333,7 @@ AVXcode: 1 06: CLTS 07: SYSRET (o64) 08: INVD -09: WBINVD +09: WBINVD | WBNOINVD (F3) 0a: 0b: UD2 (1B) 0c: @@ -364,7 +364,7 @@ AVXcode: 1 # a ModR/M byte. 1a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev 1b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv -1c: +1c: Grp20 (1A),(1C) 1d: 1e: 1f: NOP Ev @@ -792,6 +792,8 @@ f3: Grp17 (1A) f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v) f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v) f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v) +f8: MOVDIR64B Gv,Mdqq (66) | ENQCMD Gv,Mdqq (F2) | ENQCMDS Gv,Mdqq (F3) +f9: MOVDIRI My,Gy EndTable Table: 3-byte opcode 2 (0x0f 0x3a) @@ -907,7 +909,7 @@ EndTable GrpTable: Grp3_2 0: TEST Ev,Iz -1: +1: TEST Ev,Iz 2: NOT Ev 3: NEG Ev 4: MUL rAX,Ev @@ -943,9 +945,9 @@ GrpTable: Grp6 EndTable GrpTable: Grp7 -0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) -1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B) -2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) +0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) | PCONFIG (101),(11B) | ENCLV (000),(11B) +1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B) | ENCLS (111),(11B) +2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) | ENCLU (111),(11B) 3: LIDT Ms 4: SMSW Mw/Rv 5: rdpkru (110),(11B) | wrpkru (111),(11B) @@ -1011,7 +1013,7 @@ GrpTable: Grp15 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) 4: XSAVE 5: XRSTOR | lfence (11B) -6: XSAVEOPT | clwb (66) | mfence (11B) +6: XSAVEOPT | clwb (66) | mfence (11B) | TPAUSE Rd (66),(11B) | UMONITOR Rv (F3),(11B) | UMWAIT Rd (F2),(11B) 7: clflush | clflushopt (66) | sfence (11B) EndTable @@ -1042,6 +1044,10 @@ GrpTable: Grp19 6: vscatterpf1qps/d Wx (66),(ev) EndTable +GrpTable: Grp20 +0: cldemote Mb +EndTable + # AMD's Prefetch Group GrpTable: GrpP 0: PREFETCH diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index dff8ac2d255cc4528d5fd7afb2d8546e475d974b..08e0380414a9b7068dc34973a90c2ad185c0bb6a 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -544,8 +544,8 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte) fixmaps_set++; } -void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, - pgprot_t flags) +void native_set_fixmap(unsigned /* enum fixed_addresses */ idx, + phys_addr_t phys, pgprot_t flags) { __native_set_fixmap(idx, pfn_pte(phys >> PAGE_SHIFT, flags)); } diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 20fa7c84109d5ddff278b993cd0bb9de709dba00..62950ef7f84ed2ee9f75d5b94a0f5af76f75c51e 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -572,6 +572,17 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar); +/* + * Device [1022:7914] + * When in D0, PME# doesn't get asserted when plugging USB 2.0 device. + */ +static void pci_fixup_amd_fch_xhci_pme(struct pci_dev *dev) +{ + dev_info(&dev->dev, "PME# does not work under D0, disabling it\n"); + dev->pme_support &= ~(PCI_PM_CAP_PME_D0 >> PCI_PM_CAP_PME_SHIFT); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x7914, pci_fixup_amd_fch_xhci_pme); + /* * Apple MacBook Pro: Avoid [mem 0x7fa00000-0x7fbfffff] * diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b6669d326545a28a306719ff534899a9f8cd8080..f08abdf8bb676aed4d6cc65bdeaae6d393ee1b9a 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -478,7 +478,6 @@ void __init efi_init(void) efi_char16_t *c16; char vendor[100] = "unknown"; int i = 0; - void *tmp; #ifdef CONFIG_X86_32 if (boot_params.efi_info.efi_systab_hi || @@ -503,14 +502,16 @@ void __init efi_init(void) /* * Show what we know for posterity */ - c16 = tmp = early_memremap(efi.systab->fw_vendor, 2); + c16 = early_memremap_ro(efi.systab->fw_vendor, + sizeof(vendor) * sizeof(efi_char16_t)); if (c16) { - for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i) - vendor[i] = *c16++; + for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i) + vendor[i] = c16[i]; vendor[i] = '\0'; - } else + early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t)); + } else { pr_err("Could not map the firmware vendor!\n"); - early_memunmap(tmp, 2); + } pr_info("EFI v%u.%.02u by %s\n", efi.systab->hdr.revision >> 16, diff --git a/arch/xtensa/include/uapi/asm/Kbuild b/arch/xtensa/include/uapi/asm/Kbuild index 56aad54e7fb7b7fd62c5a55e13589705d194ebb7..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 --- a/arch/xtensa/include/uapi/asm/Kbuild +++ b/arch/xtensa/include/uapi/asm/Kbuild @@ -1,25 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += byteorder.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += swab.h -header-y += termbits.h -header-y += types.h -header-y += unistd.h diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index 35c822286bbe8b194e654cceef50972c260922c6..3ce5ccdb054d8f7c05168af6a220df83df7f8ea9 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c @@ -218,6 +218,8 @@ static int check_tlb_entry(unsigned w, unsigned e, bool dtlb) unsigned tlbidx = w | (e << PAGE_SHIFT); unsigned r0 = dtlb ? read_dtlb_virtual(tlbidx) : read_itlb_virtual(tlbidx); + unsigned r1 = dtlb ? + read_dtlb_translation(tlbidx) : read_itlb_translation(tlbidx); unsigned vpn = (r0 & PAGE_MASK) | (e << PAGE_SHIFT); unsigned pte = get_pte_for_vaddr(vpn); unsigned mm_asid = (get_rasid_register() >> 8) & ASID_MASK; @@ -233,8 +235,6 @@ static int check_tlb_entry(unsigned w, unsigned e, bool dtlb) } if (tlb_asid == mm_asid) { - unsigned r1 = dtlb ? read_dtlb_translation(tlbidx) : - read_itlb_translation(tlbidx); if ((pte ^ r1) & PAGE_MASK) { pr_err("%cTLB: way: %u, entry: %u, mapping: %08x->%08x, PTE: %08x\n", dtlb ? 'D' : 'I', w, e, r0, r1, pte); diff --git a/block/blk-map.c b/block/blk-map.c index a8b4f526d8bb22a7ab1fca78b7fb1d12e5a5da64..52edbe6b938059866a860fc803b5fe06cd4cb8ac 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -142,7 +142,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, return 0; unmap_rq: - __blk_rq_unmap_user(bio); + blk_rq_unmap_user(bio); fail: rq->bio = NULL; return ret; diff --git a/block/blk-merge.c b/block/blk-merge.c index 8e730d1d09eb3350d38d1cf0c53adf0b9298a475..9246c6460642b5522295be6380ceca721824732a 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -305,13 +305,7 @@ void blk_recalc_rq_segments(struct request *rq) void blk_recount_segments(struct request_queue *q, struct bio *bio) { - unsigned short seg_cnt; - - /* estimate segment number by bi_vcnt for non-cloned bio */ - if (bio_flagged(bio, BIO_CLONED)) - seg_cnt = bio_segments(bio); - else - seg_cnt = bio->bi_vcnt; + unsigned short seg_cnt = bio_segments(bio); if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags) && (seg_cnt < queue_max_segments(q))) diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c index 8c0894e0713b99b66ae6840f27a85ce776dd77ad..5b64d9d7d147ca37930c2d2d0926b5b44faba39e 100644 --- a/block/blk-mq-sysfs.c +++ b/block/blk-mq-sysfs.c @@ -243,20 +243,25 @@ static ssize_t blk_mq_hw_sysfs_active_show(struct blk_mq_hw_ctx *hctx, char *pag static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page) { + const size_t size = PAGE_SIZE - 1; unsigned int i, first = 1; - ssize_t ret = 0; + int ret = 0, pos = 0; for_each_cpu(i, hctx->cpumask) { if (first) - ret += sprintf(ret + page, "%u", i); + ret = snprintf(pos + page, size - pos, "%u", i); else - ret += sprintf(ret + page, ", %u", i); + ret = snprintf(pos + page, size - pos, ", %u", i); + + if (ret >= size - pos) + break; first = 0; + pos += ret; } - ret += sprintf(ret + page, "\n"); - return ret; + ret = snprintf(pos + page, size + 1 - pos, "\n"); + return pos + ret; } static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_dispatched = { diff --git a/block/blk-settings.c b/block/blk-settings.c index 008b6079b5796da20fd23b7963ec36602438c4ce..724febdf2282c3c770005479eda4d6435f5bb516 100755 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -350,7 +350,7 @@ EXPORT_SYMBOL(blk_queue_max_segment_size); * storage device can address. The default of 512 covers most * hardware. **/ -void blk_queue_logical_block_size(struct request_queue *q, unsigned short size) +void blk_queue_logical_block_size(struct request_queue *q, unsigned int size) { q->limits.logical_block_size = size; diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 673aebda08a21fe07f2f483f302e8b2c5ed0430e..12edc20ae219689a41b7465a5fdea41bad1e9063 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -403,6 +404,14 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) case BLKTRACETEARDOWN: /* compatible */ ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); return ret; + case IOC_PR_REGISTER: + case IOC_PR_RESERVE: + case IOC_PR_RELEASE: + case IOC_PR_PREEMPT: + case IOC_PR_PREEMPT_ABORT: + case IOC_PR_CLEAR: + return blkdev_ioctl(bdev, mode, cmd, + (unsigned long)compat_ptr(arg)); default: if (disk->fops->compat_ioctl) ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); diff --git a/crypto/af_alg.c b/crypto/af_alg.c index b5953f1d1a184890c4012cb994c52d576dd3dbac..cf3975ee4fd826cc462041c3bf77bb8c8f54db2b 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -136,11 +136,13 @@ void af_alg_release_parent(struct sock *sk) sk = ask->parent; ask = alg_sk(sk); - lock_sock(sk); + local_bh_disable(); + bh_lock_sock(sk); ask->nokey_refcnt -= nokey; if (!last) last = !--ask->refcnt; - release_sock(sk); + bh_unlock_sock(sk); + local_bh_enable(); if (last) sock_put(sk); diff --git a/crypto/algapi.c b/crypto/algapi.c index 5c098ffa7d3d857deeafff9581df6e1bc5f2f4f5..9e5b24329b413b44d8df7f7dd03afa9f8e25750d 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -652,11 +652,9 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn); void crypto_drop_spawn(struct crypto_spawn *spawn) { - if (!spawn->alg) - return; - down_write(&crypto_alg_sem); - list_del(&spawn->list); + if (spawn->alg) + list_del(&spawn->list); up_write(&crypto_alg_sem); } EXPORT_SYMBOL_GPL(crypto_drop_spawn); @@ -664,22 +662,16 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn); static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn) { struct crypto_alg *alg; - struct crypto_alg *alg2; down_read(&crypto_alg_sem); alg = spawn->alg; - alg2 = alg; - if (alg2) - alg2 = crypto_mod_get(alg2); - up_read(&crypto_alg_sem); - - if (!alg2) { - if (alg) - crypto_shoot_alg(alg); - return ERR_PTR(-EAGAIN); + if (alg && !crypto_mod_get(alg)) { + alg->cra_flags |= CRYPTO_ALG_DYING; + alg = NULL; } + up_read(&crypto_alg_sem); - return alg; + return alg ?: ERR_PTR(-EAGAIN); } struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index aaf2f810d170f2e31039dd5e2b607220645b4122..b28f45aca2eff192b93b428e8206c07918da36b7 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -538,7 +538,7 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg, lock_sock(sk); tx_nents = skcipher_all_sg_nents(ctx); sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL); - if (unlikely(!sreq->tsg)) + if (unlikely(ZERO_OR_NULL_PTR(sreq->tsg))) goto unlock; sg_init_table(sreq->tsg, tx_nents); memcpy(iv, ctx->iv, ivsize); diff --git a/crypto/api.c b/crypto/api.c index f12d6b96660818c17a77fb12189ddc871ef2c1ec..b47796b33a144d61704f120ca3e02788848fca7d 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -356,13 +356,12 @@ static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask) return len; } -void crypto_shoot_alg(struct crypto_alg *alg) +static void crypto_shoot_alg(struct crypto_alg *alg) { down_write(&crypto_alg_sem); alg->cra_flags |= CRYPTO_ALG_DYING; up_write(&crypto_alg_sem); } -EXPORT_SYMBOL_GPL(crypto_shoot_alg); struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, u32 mask) diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 60cf7d163731b965dc5ab572a5e64e45dd85e1dd..810be7a9e3c4ff15b3c2dec5b3962fe9687d2c4f 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -269,8 +269,10 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, drop_alg: crypto_mod_put(alg); - if (err) + if (err) { + kfree_skb(skb); return err; + } return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid); } diff --git a/crypto/ecc.c b/crypto/ecc.c index 414c78a9c2143b700b7200dbf3216d285b93620c..7cf6c3e4825c4b5ef823a3158a3df15d4b2d7178 100644 --- a/crypto/ecc.c +++ b/crypto/ecc.c @@ -897,10 +897,11 @@ static void ecc_point_mult(struct ecc_point *result, static inline void ecc_swap_digits(const u64 *in, u64 *out, unsigned int ndigits) { + const __be64 *src = (__force __be64 *)in; int i; for (i = 0; i < ndigits; i++) - out[i] = __swab64(in[ndigits - 1 - i]); + out[i] = be64_to_cpu(src[ndigits - 1 - i]); } int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits, diff --git a/crypto/internal.h b/crypto/internal.h index 7eefcdb00227740e39a22d61515d016b4f36caa0..6184c4226a8f9c119b7a6f190d300566d6766ce1 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -87,7 +87,6 @@ void crypto_alg_tested(const char *name, int err); void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, struct crypto_alg *nalg); void crypto_remove_final(struct list_head *list); -void crypto_shoot_alg(struct crypto_alg *alg); struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, u32 mask); void *crypto_create_tfm(struct crypto_alg *alg, diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index f8ec3d4ba4a80f8eefed739d9e8a852865a7ac02..85082574c515402581c072e238fefb6b62bc1de8 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -130,7 +130,6 @@ static void pcrypt_aead_done(struct crypto_async_request *areq, int err) struct padata_priv *padata = pcrypt_request_padata(preq); padata->info = err; - req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; padata_do_serial(padata); } @@ -394,7 +393,7 @@ static int pcrypt_sysfs_add(struct padata_instance *pinst, const char *name) int ret; pinst->kobj.kset = pcrypt_kset; - ret = kobject_add(&pinst->kobj, NULL, name); + ret = kobject_add(&pinst->kobj, NULL, "%s", name); if (!ret) kobject_uevent(&pinst->kobj, KOBJ_ADD); @@ -505,11 +504,12 @@ static int __init pcrypt_init(void) static void __exit pcrypt_exit(void) { + crypto_unregister_template(&pcrypt_tmpl); + pcrypt_fini_padata(&pencrypt); pcrypt_fini_padata(&pdecrypt); kset_unregister(pcrypt_kset); - crypto_unregister_template(&pcrypt_tmpl); } module_init(pcrypt_init); diff --git a/crypto/tgr192.c b/crypto/tgr192.c index 321bc6ff2a9d1ff714b3f27e49b68f0d48ce17e0..904c8444aa0a210c6a14757b96bf0b8db48fcebf 100644 --- a/crypto/tgr192.c +++ b/crypto/tgr192.c @@ -25,8 +25,9 @@ #include #include #include -#include #include +#include +#include #define TGR192_DIGEST_SIZE 24 #define TGR160_DIGEST_SIZE 20 @@ -468,10 +469,9 @@ static void tgr192_transform(struct tgr192_ctx *tctx, const u8 * data) u64 a, b, c, aa, bb, cc; u64 x[8]; int i; - const __le64 *ptr = (const __le64 *)data; for (i = 0; i < 8; i++) - x[i] = le64_to_cpu(ptr[i]); + x[i] = get_unaligned_le64(data + i * sizeof(__le64)); /* save */ a = aa = tctx->a; diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c index 396e358c2cee0a7685eb32e5c78f31bc8038161b..4296f4932294fb41082dc39250e53d6021b7447d 100644 --- a/drivers/acpi/acpi_watchdog.c +++ b/drivers/acpi/acpi_watchdog.c @@ -58,12 +58,14 @@ static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat) } #endif +static bool acpi_no_watchdog; + static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void) { const struct acpi_table_wdat *wdat = NULL; acpi_status status; - if (acpi_disabled) + if (acpi_disabled || acpi_no_watchdog) return NULL; status = acpi_get_table(ACPI_SIG_WDAT, 0, @@ -91,6 +93,14 @@ bool acpi_has_watchdog(void) } EXPORT_SYMBOL_GPL(acpi_has_watchdog); +/* ACPI watchdog can be disabled on boot command line */ +static int __init disable_acpi_watchdog(char *str) +{ + acpi_no_watchdog = true; + return 1; +} +__setup("acpi_no_watchdog", disable_acpi_watchdog); + void __init acpi_watchdog_init(void) { const struct acpi_wdat_entry *entries; @@ -129,12 +139,11 @@ void __init acpi_watchdog_init(void) gas = &entries[i].register_region; res.start = gas->address; + res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1; if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { res.flags = IORESOURCE_MEM; - res.end = res.start + ALIGN(gas->access_width, 4) - 1; } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { res.flags = IORESOURCE_IO; - res.end = res.start + gas->access_width - 1; } else { pr_warn("Unsupported address space: %u\n", gas->space_id); diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 6a4b603d0e83418af244caf049180042bfdec762..10bbf6ca082ab5413e442995b95680acf36ad44e 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -272,7 +272,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, * FUNCTION: acpi_ds_get_field_names * * PARAMETERS: info - create_field info structure - * ` walk_state - Current method state + * walk_state - Current method state * arg - First parser arg for the field name list * * RETURN: Status diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index fd34040d4f44afdda54c8b7d87c76c2f9d3a4869..9c41d2153d0f2e41844fa53f372d179fceb8c5e2 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -440,6 +440,27 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); + /* + * Disassembler: handle create field operators here. + * + * create_buffer_field is a deferred op that is typically processed in load + * pass 2. However, disassembly of control method contents walk the parse + * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed + * in a later walk. This is a problem when there is a control method that + * has the same name as the AML_CREATE object. In this case, any use of the + * name segment will be detected as a method call rather than a reference + * to a buffer field. + * + * This earlier creation during disassembly solves this issue by inserting + * the named object in the ACPI namespace so that references to this name + * would be a name string rather than a method call. + */ + if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) && + (walk_state->op_info->flags & AML_CREATE)) { + status = acpi_ds_create_buffer_field(op, walk_state); + return_ACPI_STATUS(status); + } + /* We are only interested in opcodes that have an associated name */ if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0a3ca20f99af30221293df5ccf1e4cbd8292bd6e..6b2c9d68d81070779cc019bbffb5841e61fadbe8 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -158,7 +158,7 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data) { acpi_status status; - if (!*data) + if (!data) return -EINVAL; status = acpi_get_data(handle, acpi_bus_private_data_handler, data); diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 993fd31394c854c99e5ce0c2af824f36c50b7a22..c76e4527620c902708fe206b8dfd5bc5cb7a0aa0 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -1096,9 +1096,19 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) */ int acpi_dev_pm_attach(struct device *dev, bool power_on) { + /* + * Skip devices whose ACPI companions match the device IDs below, + * because they require special power management handling incompatible + * with the generic ACPI PM domain. + */ + static const struct acpi_device_id special_pm_ids[] = { + {"PNP0C0B", }, /* Generic ACPI fan */ + {"INT3404", }, /* Fan */ + {} + }; struct acpi_device *adev = ACPI_COMPANION(dev); - if (!adev) + if (!adev || !acpi_match_device_ids(adev, special_pm_ids)) return -ENODEV; if (dev->pm_domain) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b9fade7a3bcf434050d593f4cb468c30e04a9e7b..c6c7e4287c4d1ddc855840da5e7f9d24ec50a759 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -375,19 +375,21 @@ void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size) } EXPORT_SYMBOL_GPL(acpi_os_map_memory); -static void acpi_os_drop_map_ref(struct acpi_ioremap *map) +/* Must be called with mutex_lock(&acpi_ioremap_lock) */ +static unsigned long acpi_os_drop_map_ref(struct acpi_ioremap *map) { - if (!--map->refcount) + unsigned long refcount = --map->refcount; + + if (!refcount) list_del_rcu(&map->list); + return refcount; } static void acpi_os_map_cleanup(struct acpi_ioremap *map) { - if (!map->refcount) { - synchronize_rcu_expedited(); - acpi_unmap(map->phys, map->virt); - kfree(map); - } + synchronize_rcu_expedited(); + acpi_unmap(map->phys, map->virt); + kfree(map); } /** @@ -407,6 +409,7 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map) void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size) { struct acpi_ioremap *map; + unsigned long refcount; if (!acpi_gbl_permanent_mmap) { __acpi_unmap_table(virt, size); @@ -420,10 +423,11 @@ void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size) WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); return; } - acpi_os_drop_map_ref(map); + refcount = acpi_os_drop_map_ref(map); mutex_unlock(&acpi_ioremap_lock); - acpi_os_map_cleanup(map); + if (!refcount) + acpi_os_map_cleanup(map); } EXPORT_SYMBOL_GPL(acpi_os_unmap_iomem); @@ -464,6 +468,7 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *gas) { u64 addr; struct acpi_ioremap *map; + unsigned long refcount; if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return; @@ -479,10 +484,11 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *gas) mutex_unlock(&acpi_ioremap_lock); return; } - acpi_os_drop_map_ref(map); + refcount = acpi_os_drop_map_ref(map); mutex_unlock(&acpi_ioremap_lock); - acpi_os_map_cleanup(map); + if (!refcount) + acpi_os_map_cleanup(map); } EXPORT_SYMBOL(acpi_os_unmap_generic_address); diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 9ec9b05de5050dd6704f54697fb376ce2c05157c..f7f9a20d5d98304a1039218c4c3ce90c6bb865d1 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3436,7 +3436,7 @@ static void binder_transaction(struct binder_proc *proc, binder_size_t parent_offset; struct binder_fd_array_object *fda = to_binder_fd_array_object(hdr); - size_t num_valid = (buffer_offset - off_start_offset) * + size_t num_valid = (buffer_offset - off_start_offset) / sizeof(binder_size_t); struct binder_buffer_object *parent = binder_validate_ptr(target_proc, t->buffer, @@ -3510,7 +3510,7 @@ static void binder_transaction(struct binder_proc *proc, t->buffer->user_data + sg_buf_offset; sg_buf_offset += ALIGN(bp->length, sizeof(u64)); - num_valid = (buffer_offset - off_start_offset) * + num_valid = (buffer_offset - off_start_offset) / sizeof(binder_size_t); ret = binder_fixup_parent(t, thread, bp, off_start_offset, diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5408a292078b7ac3cb21af452ca7b51944ef46c8..89e62043d02e6aced28803639ca60b50cbff99bc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -86,6 +86,7 @@ enum board_ids { static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void ahci_remove_one(struct pci_dev *dev); +static void ahci_shutdown_one(struct pci_dev *dev); static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, @@ -582,6 +583,7 @@ static struct pci_driver ahci_pci_driver = { .id_table = ahci_pci_tbl, .probe = ahci_init_one, .remove = ahci_remove_one, + .shutdown = ahci_shutdown_one, .driver = { .pm = &ahci_pci_pm_ops, }, @@ -1775,6 +1777,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; } +static void ahci_shutdown_one(struct pci_dev *pdev) +{ + ata_pci_shutdown_one(pdev); +} + static void ahci_remove_one(struct pci_dev *pdev) { pm_runtime_get_noresume(&pdev->dev); diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 6f8a7341fa08a701af61226fab156206b506be20..f50a76ad63e4a0c0045308d9ba81f4ea3a4b7e4e 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "ahci.h" @@ -88,6 +89,7 @@ struct brcm_ahci_priv { u32 port_mask; u32 quirks; enum brcm_ahci_version version; + struct reset_control *rcdev; }; static const struct ata_port_info ahci_brcm_port_info = { @@ -226,19 +228,12 @@ static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv) brcm_sata_phy_disable(priv, i); } -static u32 brcm_ahci_get_portmask(struct platform_device *pdev, +static u32 brcm_ahci_get_portmask(struct ahci_host_priv *hpriv, struct brcm_ahci_priv *priv) { - void __iomem *ahci; - struct resource *res; u32 impl; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci"); - ahci = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ahci)) - return 0; - - impl = readl(ahci + HOST_PORTS_IMPL); + impl = readl(hpriv->mmio + HOST_PORTS_IMPL); if (fls(impl) > SATA_TOP_MAX_PHYS) dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n", @@ -246,9 +241,6 @@ static u32 brcm_ahci_get_portmask(struct platform_device *pdev, else if (!impl) dev_info(priv->dev, "no ports found\n"); - devm_iounmap(&pdev->dev, ahci); - devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); - return impl; } @@ -275,11 +267,10 @@ static int brcm_ahci_suspend(struct device *dev) struct ata_host *host = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host->private_data; struct brcm_ahci_priv *priv = hpriv->plat_data; - int ret; - ret = ahci_platform_suspend(dev); brcm_sata_phys_disable(priv); - return ret; + + return ahci_platform_suspend(dev); } static int brcm_ahci_resume(struct device *dev) @@ -287,11 +278,44 @@ static int brcm_ahci_resume(struct device *dev) struct ata_host *host = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host->private_data; struct brcm_ahci_priv *priv = hpriv->plat_data; + int ret; + + /* Make sure clocks are turned on before re-configuration */ + ret = ahci_platform_enable_clks(hpriv); + if (ret) + return ret; brcm_sata_init(priv); brcm_sata_phys_enable(priv); brcm_sata_alpm_init(hpriv); - return ahci_platform_resume(dev); + + /* Since we had to enable clocks earlier on, we cannot use + * ahci_platform_resume() as-is since a second call to + * ahci_platform_enable_resources() would bump up the resources + * (regulators, clocks, PHYs) count artificially so we copy the part + * after ahci_platform_enable_resources(). + */ + ret = ahci_platform_enable_phys(hpriv); + if (ret) + goto out_disable_phys; + + ret = ahci_platform_resume_host(dev); + if (ret) + goto out_disable_platform_phys; + + /* We resumed so update PM runtime state */ + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; + +out_disable_platform_phys: + ahci_platform_disable_phys(hpriv); +out_disable_phys: + brcm_sata_phys_disable(priv); + ahci_platform_disable_clks(hpriv); + return ret; } #endif @@ -332,43 +356,73 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (IS_ERR(priv->top_ctrl)) return PTR_ERR(priv->top_ctrl); + /* Reset is optional depending on platform */ + priv->rcdev = devm_reset_control_get(&pdev->dev, "ahci"); + if (!IS_ERR_OR_NULL(priv->rcdev)) + reset_control_deassert(priv->rcdev); + if ((priv->version == BRCM_SATA_BCM7425) || (priv->version == BRCM_SATA_NSP)) { priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ; priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE; } + hpriv = ahci_platform_get_resources(pdev); + if (IS_ERR(hpriv)) { + ret = PTR_ERR(hpriv); + goto out_reset; + } + + ret = ahci_platform_enable_clks(hpriv); + if (ret) + goto out_reset; + + /* Must be first so as to configure endianness including that + * of the standard AHCI register space. + */ brcm_sata_init(priv); - priv->port_mask = brcm_ahci_get_portmask(pdev, priv); - if (!priv->port_mask) - return -ENODEV; + /* Initializes priv->port_mask which is used below */ + priv->port_mask = brcm_ahci_get_portmask(hpriv, priv); + if (!priv->port_mask) { + ret = -ENODEV; + goto out_disable_clks; + } + /* Must be done before ahci_platform_enable_phys() */ brcm_sata_phys_enable(priv); - hpriv = ahci_platform_get_resources(pdev); - if (IS_ERR(hpriv)) - return PTR_ERR(hpriv); hpriv->plat_data = priv; hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP; brcm_sata_alpm_init(hpriv); - ret = ahci_platform_enable_resources(hpriv); - if (ret) - return ret; - if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ) hpriv->flags |= AHCI_HFLAG_NO_NCQ; + ret = ahci_platform_enable_phys(hpriv); + if (ret) + goto out_disable_phys; + ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info, &ahci_platform_sht); if (ret) - return ret; + goto out_disable_platform_phys; dev_info(dev, "Broadcom AHCI SATA3 registered\n"); return 0; + +out_disable_platform_phys: + ahci_platform_disable_phys(hpriv); +out_disable_phys: + brcm_sata_phys_disable(priv); +out_disable_clks: + ahci_platform_disable_clks(hpriv); +out_reset: + if (!IS_ERR_OR_NULL(priv->rcdev)) + reset_control_assert(priv->rcdev); + return ret; } static int brcm_ahci_remove(struct platform_device *pdev) @@ -378,12 +432,12 @@ static int brcm_ahci_remove(struct platform_device *pdev) struct brcm_ahci_priv *priv = hpriv->plat_data; int ret; + brcm_sata_phys_disable(priv); + ret = ata_platform_remove_one(pdev); if (ret) return ret; - brcm_sata_phys_disable(priv); - return 0; } diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index f233ce60a67814ca3928291908eecd026fc39b1c..1610fff19bb39dfa5ad9f00187e44801836f7633 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -190,7 +190,6 @@ struct ata_port_operations ahci_pmp_retry_srst_ops = { EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops); static bool ahci_em_messages __read_mostly = true; -EXPORT_SYMBOL_GPL(ahci_em_messages); module_param(ahci_em_messages, bool, 0444); /* add other LED protocol types when they become supported */ MODULE_PARM_DESC(ahci_em_messages, diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 65371e1befe8af32bf276a9a64fae183c1ca76b8..0b80502bc1c510ae6b8398ee7e1101e786502ff5 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -46,7 +46,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_ops); * RETURNS: * 0 on success otherwise a negative error code */ -static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) +int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) { int rc, i; @@ -71,6 +71,7 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) } return rc; } +EXPORT_SYMBOL_GPL(ahci_platform_enable_phys); /** * ahci_platform_disable_phys - Disable PHYs @@ -78,7 +79,7 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) * * This function disables all PHYs found in hpriv->phys. */ -static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) +void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) { int i; @@ -87,6 +88,7 @@ static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) phy_exit(hpriv->phys[i]); } } +EXPORT_SYMBOL_GPL(ahci_platform_disable_phys); /** * ahci_platform_enable_clks - Enable platform clocks diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index da1a987c622a448144b3e6f535f1c17c5b96b5fc..ba0cffbd0bb6ee6bc6e1b3583f6a8994b5f1f920 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6550,6 +6550,9 @@ void ata_host_detach(struct ata_host *host) { int i; + /* Ensure ata_port probe has completed */ + async_synchronize_full(); + for (i = 0; i < host->n_ports; i++) ata_port_detach(host->ports[i]); @@ -6577,6 +6580,26 @@ void ata_pci_remove_one(struct pci_dev *pdev) ata_host_detach(host); } +void ata_pci_shutdown_one(struct pci_dev *pdev) +{ + struct ata_host *host = pci_get_drvdata(pdev); + int i; + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + + ap->pflags |= ATA_PFLAG_FROZEN; + + /* Disable port interrupts */ + if (ap->ops->freeze) + ap->ops->freeze(ap); + + /* Stop the port DMA engines */ + if (ap->ops->port_stop) + ap->ops->port_stop(ap); + } +} + /* move to PCI subsystem */ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits) { @@ -7197,6 +7220,7 @@ EXPORT_SYMBOL_GPL(ata_timing_cycle2mode); #ifdef CONFIG_PCI EXPORT_SYMBOL_GPL(pci_test_config_bits); +EXPORT_SYMBOL_GPL(ata_pci_shutdown_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); #ifdef CONFIG_PM EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend); diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 40c2d561417bdecd6bd386f3c92214a51a6faece..88819409e0bebc986089e86fc8e858e6515f6b5b 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -372,7 +372,7 @@ static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb, here = (eni_vcc->descr+skip) & (eni_vcc->words-1); dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK; - j++; + dma[j++] = 0; } here = (eni_vcc->descr+size+skip) & (eni_vcc->words-1); if (!eff) size += skip; @@ -445,7 +445,7 @@ static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb, if (size != eff) { dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK; - j++; + dma[j++] = 0; } if (!j || j > 2*RX_DMA_BUF) { printk(KERN_CRIT DEV_LABEL "!j or j too big!!!\n"); diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 85aaf2222587bfcc9086686d44ee4e042a46c233..82296fe2ba3bdf1a4623cd3f61f3d00dee375dcc 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -927,6 +927,7 @@ static int fs_open(struct atm_vcc *atm_vcc) } if (!to) { printk ("No more free channels for FS50..\n"); + kfree(vcc); return -EBUSY; } vcc->channo = dev->channo; @@ -937,6 +938,7 @@ static int fs_open(struct atm_vcc *atm_vcc) if (((DO_DIRECTION(rxtp) && dev->atm_vccs[vcc->channo])) || ( DO_DIRECTION(txtp) && test_bit (vcc->channo, dev->tx_inuse))) { printk ("Channel is in use for FS155.\n"); + kfree(vcc); return -EBUSY; } } @@ -950,6 +952,7 @@ static int fs_open(struct atm_vcc *atm_vcc) tc, sizeof (struct fs_transmit_config)); if (!tc) { fs_dprintk (FS_DEBUG_OPEN, "fs: can't alloc transmit_config.\n"); + kfree(vcc); return -ENOMEM; } diff --git a/drivers/base/dd.c b/drivers/base/dd.c index a7baf3c147adb502582d7a0e4e84bce398857b64..fc4b7622a36dd7c5eab2d27b291e71d2dab057b7 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -362,7 +362,10 @@ static int really_probe(struct device *dev, struct device_driver *drv) atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); - WARN_ON(!list_empty(&dev->devres_head)); + if (!list_empty(&dev->devres_head)) { + dev_crit(dev, "Resources present before probing\n"); + return -EBUSY; + } re_probe: dev->driver = drv; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f90b1b9bbad0d9d087ff5d45a8650a5483220d0c..bef299ef62276d3609653df8028a95173b277c26 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -68,7 +69,7 @@ void __weak arch_setup_pdev_archdata(struct platform_device *pdev) struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num) { - int i; + u32 i; for (i = 0; i < dev->num_resources; i++) { struct resource *r = &dev->resource[i]; @@ -153,7 +154,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name) { - int i; + u32 i; for (i = 0; i < dev->num_resources; i++) { struct resource *r = &dev->resource[i]; @@ -350,7 +351,8 @@ EXPORT_SYMBOL_GPL(platform_device_add_properties); */ int platform_device_add(struct platform_device *pdev) { - int i, ret; + u32 i; + int ret; if (!pdev) return -EINVAL; @@ -416,7 +418,7 @@ int platform_device_add(struct platform_device *pdev) pdev->id = PLATFORM_DEVID_AUTO; } - while (--i >= 0) { + while (i--) { struct resource *r = &pdev->resource[i]; if (r->parent) release_resource(r); @@ -437,7 +439,7 @@ EXPORT_SYMBOL_GPL(platform_device_add); */ void platform_device_del(struct platform_device *pdev) { - int i; + u32 i; if (pdev) { device_remove_properties(&pdev->dev); diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index f499a469e66d08d7dfcb50e123c82fc920f32ea9..12b2cc9a3fbe8a1050133582e7f553b599fbcbbf 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -78,7 +78,7 @@ static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u16 device, u8 address) v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); } - v = BCMA_CORE_PCI_MDIODATA_START; + v |= BCMA_CORE_PCI_MDIODATA_START; v |= BCMA_CORE_PCI_MDIODATA_READ; v |= BCMA_CORE_PCI_MDIODATA_TA; @@ -121,7 +121,7 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u16 device, v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); } - v = BCMA_CORE_PCI_MDIODATA_START; + v |= BCMA_CORE_PCI_MDIODATA_START; v |= BCMA_CORE_PCI_MDIODATA_WRITE; v |= BCMA_CORE_PCI_MDIODATA_TA; v |= data; diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 0c76d4016eebebf5525fc4a2aa5351319674dca5..7e35574a17dfc59fdfc334b546d4e5b27c89c24c 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -581,6 +581,25 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data) return kobj; } +static inline void brd_check_and_reset_par(void) +{ + if (unlikely(!max_part)) + max_part = 1; + + /* + * make sure 'max_part' can be divided exactly by (1U << MINORBITS), + * otherwise, it is possiable to get same dev_t when adding partitions. + */ + if ((1U << MINORBITS) % max_part != 0) + max_part = 1UL << fls(max_part); + + if (max_part > DISK_MAX_PARTS) { + pr_info("brd: max_part can't be larger than %d, reset max_part = %d.\n", + DISK_MAX_PARTS, DISK_MAX_PARTS); + max_part = DISK_MAX_PARTS; + } +} + static int __init brd_init(void) { struct brd_device *brd, *next; @@ -604,8 +623,7 @@ static int __init brd_init(void) if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) return -EIO; - if (unlikely(!max_part)) - max_part = 1; + brd_check_and_reset_par(); for (i = 0; i < rd_nr; i++) { brd = brd_alloc(i); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 6813079865646c64ec32fbdb696e27bd985bf367..29c0e73cb5a544fd233f428398d314ccab1fa9f5 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -332,6 +332,8 @@ static int drbd_thread_setup(void *arg) thi->name[0], resource->name); + allow_kernel_signal(DRBD_SIGKILL); + allow_kernel_signal(SIGXCPU); restart: retval = thi->function(thi); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index ece4f706b38fb89732bcdf072c9266952f93cfca..4496e7a49235212ed26d5e5c0cd2e99cbf75cd29 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -848,14 +848,17 @@ static void reset_fdc_info(int mode) /* selects the fdc and drive, and enables the fdc's input/dma. */ static void set_fdc(int drive) { + unsigned int new_fdc = fdc; + if (drive >= 0 && drive < N_DRIVE) { - fdc = FDC(drive); + new_fdc = FDC(drive); current_drive = drive; } - if (fdc != 1 && fdc != 0) { + if (new_fdc >= N_FDC) { pr_info("bad fdc value\n"); return; } + fdc = new_fdc; set_dor(fdc, ~0, 8); #if N_FDC > 1 set_dor(1 - fdc, ~8, 0); diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index 34997df132e240be4bcebedcf0df6c6baaf39907..6beafaa335c71f2681664782be8e494b44f44003 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c @@ -1025,8 +1025,10 @@ static void rsxx_pci_remove(struct pci_dev *dev) cancel_work_sync(&card->event_work); + destroy_workqueue(card->event_wq); rsxx_destroy_dev(card); rsxx_dma_destroy(card); + destroy_workqueue(card->creg_ctrl.creg_wq); spin_lock_irqsave(&card->irq_lock, flags); rsxx_disable_ier_and_isr(card, CR_INTR_ALL); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 44ef1d66caa681eaa123aae9172a4cc897654079..f287eec36b282c62b3e10a8714589db2118f071e 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -215,10 +215,12 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, err = __virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num); if (err) { virtqueue_kick(vblk->vqs[qid].vq); - blk_mq_stop_hw_queue(hctx); + /* Don't stop the queue if -ENOMEM: we may have failed to + * bounce the buffer due to global resource outage. + */ + if (err == -ENOSPC) + blk_mq_stop_hw_queue(hctx); spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); - /* Out of mem doesn't actually happen, since we fall back - * to direct descriptors */ if (err == -ENOMEM || err == -ENOSPC) return BLK_MQ_RQ_QUEUE_BUSY; return BLK_MQ_RQ_QUEUE_ERROR; diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index d6eaaa25d1cc9ee09d376067e3d7ac01e27c9fb0..a700e525535ce0c12b173712f00647d8b48273a8 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -929,6 +929,8 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring, 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++) + pages[i]->handle = BLKBACK_INVALID_HANDLE; return -ENOMEM; } diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index ad736d7de83836f909cc1425e022f6a4dc8fccaf..1d1f8665796793fe92ebc262fbd41f111322f4e4 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -178,6 +178,15 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) blkif->domid = domid; atomic_set(&blkif->refcnt, 1); init_completion(&blkif->drain_complete); + + /* + * Because freeing back to the cache may be deferred, it is not + * safe to unload the module (and hence destroy the cache) until + * this has completed. To prevent premature unloading, take an + * extra module reference here and release only when the object + * has been freed back to the cache. + */ + __module_get(THIS_MODULE); INIT_WORK(&blkif->free_work, xen_blkif_deferred_free); return blkif; @@ -322,6 +331,7 @@ static void xen_blkif_free(struct xen_blkif *blkif) /* Make sure everything is drained before shutting down */ kmem_cache_free(xen_blkif_cachep, blkif); + module_put(THIS_MODULE); } int __init xen_blkif_interface_init(void) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index c08ee8cf1e296d1268a9f0960cbddbc32190ed69..6ee3e928ebf18c8ccca6c17098e6be0f947ba97c 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1104,8 +1104,8 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, if (!VDEV_IS_EXTENDED(info->vdevice)) { err = xen_translate_vdev(info->vdevice, &minor, &offset); if (err) - return err; - nr_parts = PARTS_PER_DISK; + return err; + nr_parts = PARTS_PER_DISK; } else { minor = BLKIF_MINOR_EXT(info->vdevice); nr_parts = PARTS_PER_EXT_DISK; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1d1c0d7aec885a1b90bb6c56ae01677c84f72338..4e3b24a0511ffc73bbfc2797ca4f1799ebf69b0b 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1069,7 +1069,7 @@ static int btusb_open(struct hci_dev *hdev) if (data->setup_on_usb) { err = data->setup_on_usb(hdev); if (err < 0) - return err; + goto setup_fail; } data->intf->needs_remote_wakeup = 1; @@ -1101,6 +1101,7 @@ static int btusb_open(struct hci_dev *hdev) failed: clear_bit(BTUSB_INTR_RUNNING, &data->flags); +setup_fail: usb_autopm_put_interface(data->intf); return err; } diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index 66cb2a92dfc37b95857c03fb7a46b94dbb61e8ee..1b81eb8f26628331e8ca9312dedd7f75a6fc855f 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -1285,6 +1285,10 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, local_rp->ptr, local_rp->dword[0], local_rp->dword[1]); chan = MHI_TRE_GET_EV_CHID(local_rp); + if (chan >= mhi_cntrl->max_chan) { + MHI_ERR("invalid channel id %u\n", chan); + continue; + } mhi_chan = &mhi_cntrl->mhi_chan[chan]; if (likely(type == MHI_PKT_TYPE_TX_EVENT)) { diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index a46f188f679e75d41ff5f0debe750ae99cd1b806..782dbab5ad56afeb151f8e12fd9de98c66e4656a 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -998,6 +998,12 @@ static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype *tracks) tracks->xa = 0; tracks->error = 0; cd_dbg(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n"); + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) { + tracks->error = CDS_NO_INFO; + return; + } + /* Grab the TOC header so we can see how many tracks there are */ ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header); if (ret) { @@ -1164,7 +1170,8 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, ret = open_for_data(cdi); if (ret) goto err; - cdrom_mmc3_profile(cdi); + if (CDROM_CAN(CDC_GENERIC_PACKET)) + cdrom_mmc3_profile(cdi); if (mode & FMODE_WRITE) { ret = -EROFS; if (cdrom_open_write(cdi)) @@ -2873,6 +2880,9 @@ int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written) it doesn't give enough information or fails. then we return the toc contents. */ use_toc: + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + toc.cdte_format = CDROM_MSF; toc.cdte_track = CDROM_LEADOUT; if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 548bd58d44b7f3f4fb70b79bbc592f6a640a9988..2a3b46b73eebfe1aa94c0ff0b230249b954785ad 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -3133,6 +3133,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) kfree(new_entry); new_entry = NULL; } + put_task_struct(current); mutex_unlock(&driver->dci_mutex); return DIAG_DCI_NO_REG; } diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c index 37a58d78aab317a8a97b39ebec02df1fb58fcaae..3324a7f4bee3747b6aae88b4da17e0e89eab2a65 100644 --- a/drivers/char/hw_random/omap3-rom-rng.c +++ b/drivers/char/hw_random/omap3-rom-rng.c @@ -114,7 +114,8 @@ static int omap3_rom_rng_remove(struct platform_device *pdev) { cancel_delayed_work_sync(&idle_work); hwrng_unregister(&omap3_rom_rng_ops); - clk_disable_unprepare(rng_clk); + if (!rng_idle) + clk_disable_unprepare(rng_clk); return 0; } diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 996b9ae154042e9c900945f696cafe75976c2cce..a4ef9a6bd36782349d235db8a38fc637061adc0c 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -746,10 +746,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, flags = ipmi_ssif_lock_cond(ssif_info, &oflags); msg = ssif_info->curr_msg; if (msg) { + if (data) { + if (len > IPMI_MAX_MSG_LENGTH) + len = IPMI_MAX_MSG_LENGTH; + memcpy(msg->rsp, data, len); + } else { + len = 0; + } msg->rsp_size = len; - if (msg->rsp_size > IPMI_MAX_MSG_LENGTH) - msg->rsp_size = IPMI_MAX_MSG_LENGTH; - memcpy(msg->rsp, data, msg->rsp_size); ssif_info->curr_msg = NULL; } diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 336d02a488cc3712ffd77735b4a8152220de4e3f..3648727dfe836644d1019d9b02ae3a9fcd2512fc 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -624,20 +624,27 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (copy_from_user(time32, argp, sizeof(time32))) return -EFAULT; + if ((time32[0] < 0) || (time32[1] < 0)) + return -EINVAL; + return pp_set_timeout(pp->pdev, time32[0], time32[1]); case PPSETTIME64: if (copy_from_user(time64, argp, sizeof(time64))) return -EFAULT; + if ((time64[0] < 0) || (time64[1] < 0)) + return -EINVAL; + + if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall()) + time64[1] >>= 32; + return pp_set_timeout(pp->pdev, time64[0], time64[1]); case PPGETTIME32: jiffies_to_timespec64(pp->pdev->timeout, &ts); time32[0] = ts.tv_sec; time32[1] = ts.tv_nsec / NSEC_PER_USEC; - if ((time32[0] < 0) || (time32[1] < 0)) - return -EINVAL; if (copy_to_user(argp, time32, sizeof(time32))) return -EFAULT; @@ -648,8 +655,9 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) jiffies_to_timespec64(pp->pdev->timeout, &ts); time64[0] = ts.tv_sec; time64[1] = ts.tv_nsec / NSEC_PER_USEC; - if ((time64[0] < 0) || (time64[1] < 0)) - return -EINVAL; + + if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall()) + time64[1] <<= 32; if (copy_to_user(argp, time64, sizeof(time64))) return -EFAULT; diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 67549ce88cc94251ad43e40074c7156f2736ea79..774748497acedf2da7d3d195b57d29fe485cf94f 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -18,10 +18,11 @@ #include #include #include +#include struct ttyprintk_port { struct tty_port port; - struct mutex port_write_mutex; + spinlock_t spinlock; }; static struct ttyprintk_port tpk_port; @@ -100,11 +101,12 @@ static int tpk_open(struct tty_struct *tty, struct file *filp) static void tpk_close(struct tty_struct *tty, struct file *filp) { struct ttyprintk_port *tpkp = tty->driver_data; + unsigned long flags; - mutex_lock(&tpkp->port_write_mutex); + spin_lock_irqsave(&tpkp->spinlock, flags); /* flush tpk_printk buffer */ tpk_printk(NULL, 0); - mutex_unlock(&tpkp->port_write_mutex); + spin_unlock_irqrestore(&tpkp->spinlock, flags); tty_port_close(&tpkp->port, tty, filp); } @@ -116,13 +118,14 @@ static int tpk_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct ttyprintk_port *tpkp = tty->driver_data; + unsigned long flags; int ret; /* exclusive use of tpk_printk within this tty */ - mutex_lock(&tpkp->port_write_mutex); + spin_lock_irqsave(&tpkp->spinlock, flags); ret = tpk_printk(buf, count); - mutex_unlock(&tpkp->port_write_mutex); + spin_unlock_irqrestore(&tpkp->spinlock, flags); return ret; } @@ -172,7 +175,7 @@ static int __init ttyprintk_init(void) { int ret = -ENOMEM; - mutex_init(&tpk_port.port_write_mutex); + spin_lock_init(&tpk_port.spinlock); ttyprintk_driver = tty_alloc_driver(1, TTY_DRIVER_RESET_TERMIOS | diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c index 727ed8e1bb726fd424f97427507abe6f46fe84a9..8e4581004695c44f11ea66250773c60720f4bbb8 100644 --- a/drivers/clk/clk-highbank.c +++ b/drivers/clk/clk-highbank.c @@ -293,6 +293,7 @@ static __init struct clk *hb_clk_init(struct device_node *node, const struct clk /* Map system registers */ srnp = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs"); hb_clk->reg = of_iomap(srnp, 0); + of_node_put(srnp); BUG_ON(!hb_clk->reg); hb_clk->reg += reg; diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index cdce49f6476aaa8516bef9d371b75158d0342c05..65876ff6df4114732594155a8d32ad9ced781bcc 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -1245,6 +1245,7 @@ static void __init clockgen_init(struct device_node *np) pr_err("%s: Couldn't map %s regs\n", __func__, guts->full_name); } + of_node_put(guts); } } diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0426ff778983ab62d4e40f502677d1099dc10e8f..872c9d0746c62e2ba4782ba27b28a4e51dd623d0 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3273,11 +3273,17 @@ static int __clk_core_init(struct clk_core *core) if (core->flags & CLK_IS_CRITICAL) { unsigned long flags; - clk_core_prepare(core); + ret = clk_core_prepare(core); + if (ret) + goto out; flags = clk_enable_lock(); - clk_core_enable(core); + ret = clk_core_enable(core); clk_enable_unlock(flags); + if (ret) { + clk_core_unprepare(core); + goto out; + } } /* diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index 14682df5d3123e7671242a012eecc9aa55e4f707..d83f6221f1b00aeb8ef871fd339bba4e04a112b2 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -174,6 +174,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); base = of_iomap(np, 0); WARN_ON(!base); + of_node_put(np); /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */ if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) { diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index b5c96de41ccf957b5f556794756545714d0a3528..8bbc2542f2f70bc795dcd4572a60f238e9c51c61 100644 --- a/drivers/clk/imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c @@ -164,6 +164,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop"); base = of_iomap(np, 0); WARN_ON(!base); + of_node_put(np); clks[IMX6SX_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); clks[IMX6SX_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index e7c7353a86fc62f319a39c5a42cdc06214f4744c..8c0c0d0151321bc17e5d77cc628a680e99663908 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -415,6 +415,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop"); base = of_iomap(np, 0); WARN_ON(!base); + of_node_put(np); clks[IMX7D_PLL_ARM_MAIN_SRC] = imx_clk_mux("pll_arm_main_src", base + 0x60, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); clks[IMX7D_PLL_DRAM_MAIN_SRC] = imx_clk_mux("pll_dram_main_src", base + 0x70, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 0476353ab423f38155a4ed1c83e6b29af479c011..a19ab032d07317f782068656865694bdafb3a3d5 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -203,6 +203,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,vf610-anatop"); anatop_base = of_iomap(np, 0); BUG_ON(!anatop_base); + of_node_put(np); np = ccm_node; ccm_base = of_iomap(np, 0); diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c index 061a9f10218b3f9da83cb220b67f2bc61db00a8f..20cfdf837bfab49e6e79d46763131da738dd691a 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c @@ -134,7 +134,7 @@ static DEFINE_SPINLOCK(ssp3_lock); static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"}; static DEFINE_SPINLOCK(timer_lock); -static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", "vctcxo"}; +static const char *timer_parent_names[] = {"clk32", "vctcxo_4", "vctcxo_2", "vctcxo"}; static DEFINE_SPINLOCK(reset_lock); diff --git a/drivers/clk/msm/clock-gcc-8909.c b/drivers/clk/msm/clock-gcc-8909.c index d96a3983bdebc8c80ab30de89345999ff16ad109..caeb55a189cef7c532cb5fd41727403dc98b24ad 100644 --- a/drivers/clk/msm/clock-gcc-8909.c +++ b/drivers/clk/msm/clock-gcc-8909.c @@ -817,6 +817,7 @@ static struct rcg_clk blsp1_uart2_apps_clk_src = { }; static struct clk_freq_tbl ftbl_gcc_camss_gp0_1_clk[] = { + F( 150000, xo, 1, 1, 128), F( 100000000, gpll0, 8, 0, 0), F( 200000000, gpll0, 4, 0, 0), F_END diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c index 2c7c1085f88300ca84ac529831876af25376a047..8fdfa97900cd86e15863beb62be4a288cad9549f 100644 --- a/drivers/clk/mvebu/armada-370.c +++ b/drivers/clk/mvebu/armada-370.c @@ -177,8 +177,10 @@ static void __init a370_clk_init(struct device_node *np) mvebu_coreclk_setup(np, &a370_coreclks); - if (cgnp) + if (cgnp) { mvebu_clk_gating_setup(cgnp, a370_gating_desc); + of_node_put(cgnp); + } } CLK_OF_DECLARE(a370_clk, "marvell,armada-370-core-clock", a370_clk_init); diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c index b3094315a3c0faa89926dcf7442d5034f39b4f15..2fa15a2747190205243f0633277b70f0dd2ef14d 100644 --- a/drivers/clk/mvebu/armada-xp.c +++ b/drivers/clk/mvebu/armada-xp.c @@ -202,7 +202,9 @@ static void __init axp_clk_init(struct device_node *np) mvebu_coreclk_setup(np, &axp_coreclks); - if (cgnp) + if (cgnp) { mvebu_clk_gating_setup(cgnp, axp_gating_desc); + of_node_put(cgnp); + } } CLK_OF_DECLARE(axp_clk, "marvell,armada-xp-core-clock", axp_clk_init); diff --git a/drivers/clk/mvebu/dove.c b/drivers/clk/mvebu/dove.c index 59fad9546c847946d71bd8348dcff615f936e0e4..5f258c9bb68bfc72a830d8ac56e428e75ccc19e0 100644 --- a/drivers/clk/mvebu/dove.c +++ b/drivers/clk/mvebu/dove.c @@ -190,10 +190,14 @@ static void __init dove_clk_init(struct device_node *np) mvebu_coreclk_setup(np, &dove_coreclks); - if (ddnp) + if (ddnp) { dove_divider_clk_init(ddnp); + of_node_put(ddnp); + } - if (cgnp) + if (cgnp) { mvebu_clk_gating_setup(cgnp, dove_gating_desc); + of_node_put(cgnp); + } } CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init); diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c index a2a8d614039da91a1b3f99272aa98e5952b79037..890ebf623261b78d237881eb39a51c51e9074a73 100644 --- a/drivers/clk/mvebu/kirkwood.c +++ b/drivers/clk/mvebu/kirkwood.c @@ -333,6 +333,8 @@ static void __init kirkwood_clk_init(struct device_node *np) if (cgnp) { mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc); kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc); + + of_node_put(cgnp); } } CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock", diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index c40b1804f58caf33f7b1bf6cac90cc22ea381248..bb556f9bbeda0cbc543ba444b12f69ac8930855f 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -362,6 +362,7 @@ struct dummy_clk { }; static struct dummy_clk dummy_clks[] __initdata = { DUMMY_CLK(NULL, "pxa27x-gpio", "osc_32_768khz"), + DUMMY_CLK(NULL, "pxa-rtc", "osc_32_768khz"), DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"), DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"), }; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index a4e067056e5a81be10393b879f9d30b9b138985f..1d2361b4f10d59bf1c6c6a365d86d29321a55336 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -306,8 +306,13 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, clk_flags = clk_hw_get_flags(hw); p = clk_hw_get_parent_by_index(hw, index); + if (!p) + return -EINVAL; + if (clk_flags & CLK_SET_RATE_PARENT) { if (f->pre_div) { + if (!rate) + rate = req->rate; rate /= 2; rate *= f->pre_div + 1; } diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 316ac3966e997741af52ca8d9d2e601fca2a5312..e149eb6ff1b0ccaedb120e772bfdceac3fe8fd98 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -42,6 +42,9 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) if (!f) return NULL; + if (!f->freq) + return f; + for (; f->freq; f++) if (rate <= f->freq) return f; diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index fe03e6fbc7df590d9d354891a5aa05d686d59fd7..ea6c227331fcfae72ee9b57939e552fae03d2038 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -140,22 +140,6 @@ static const char * const gcc_xo_gpll0_gpll4_gpll0_early_div[] = { "gpll0_early_div" }; -static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div_map[] = { - { P_XO, 0 }, - { P_GPLL0, 1 }, - { P_GPLL2, 2 }, - { P_GPLL3, 3 }, - { P_GPLL0_EARLY_DIV, 6 } -}; - -static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div[] = { - "xo", - "gpll0", - "gpll2", - "gpll3", - "gpll0_early_div" -}; - static const struct parent_map gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map[] = { { P_XO, 0 }, { P_GPLL0, 1 }, @@ -194,26 +178,6 @@ static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early "gpll0_early_div" }; -static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div_map[] = { - { P_XO, 0 }, - { P_GPLL0, 1 }, - { P_GPLL2, 2 }, - { P_GPLL3, 3 }, - { P_GPLL1, 4 }, - { P_GPLL4, 5 }, - { P_GPLL0_EARLY_DIV, 6 } -}; - -static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div[] = { - "xo", - "gpll0", - "gpll2", - "gpll3", - "gpll1", - "gpll4", - "gpll0_early_div" -}; - static struct clk_fixed_factor xo = { .mult = 1, .div = 1, diff --git a/drivers/clk/qcom/gcc-sdxpoorwills.c b/drivers/clk/qcom/gcc-sdxpoorwills.c index 6732ebed5c6c1d0be8fd383ae4f786e250851664..98a1ecdc9ff75d17f32b263cd238a31ac0c9a882 100644 --- a/drivers/clk/qcom/gcc-sdxpoorwills.c +++ b/drivers/clk/qcom/gcc-sdxpoorwills.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 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 @@ -714,12 +714,24 @@ static struct clk_rcg2 gcc_pdm2_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(20000000, P_GPLL0_OUT_EVEN, 5, 1, 3), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { .cmd_rcgr = 0xf00c, .mnd_width = 8, .hid_width = 5, .parent_map = gcc_parent_map_0, - .freq_tbl = ftbl_gcc_gp1_clk_src, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_sdcc1_apps_clk_src", .parent_names = gcc_parent_names_0, diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 523378d1396e87289c7afc80fd29b5e73895096b..d62031eedbe64e670eccdfaf6a0232c4bebe4b56 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -361,8 +361,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKGATE_CON(2), 5, GFLAGS), MUX(SCLK_MAC, "sclk_macref", mux_sclk_macref_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(21), 4, 1, MFLAGS), - GATE(0, "sclk_mac_lbtest", "sclk_macref", - RK2928_CLKGATE_CON(2), 12, 0, GFLAGS), + GATE(0, "sclk_mac_lbtest", "sclk_macref", 0, + RK2928_CLKGATE_CON(2), 12, GFLAGS), COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0, RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS, @@ -390,8 +390,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { * Clock-Architecture Diagram 4 */ - GATE(SCLK_SMC, "sclk_smc", "hclk_peri", - RK2928_CLKGATE_CON(2), 4, 0, GFLAGS), + GATE(SCLK_SMC, "sclk_smc", "hclk_peri", 0, + RK2928_CLKGATE_CON(2), 4, GFLAGS), COMPOSITE_NOMUX(SCLK_SPI0, "sclk_spi0", "pclk_peri", 0, RK2928_CLKSEL_CON(25), 0, 7, DFLAGS, diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index faab9b31baf5b4b15ec0fec8623d01031e991fa9..91f9b79e39411abc79f151efd3245d1af32c8afe 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1225,6 +1225,7 @@ static unsigned long __init exynos4_get_xom(void) xom = readl(chipid_base + 8); iounmap(chipid_base); + of_node_put(np); } return xom; diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 2bb88d1251136148946aa06eed32fc60e86c70c3..7f8c7cf3c2ab9bc74122acfbfee6b3b1e476e0bb 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -170,6 +170,8 @@ static const unsigned long exynos5x_clk_regs[] __initconst = { GATE_BUS_CPU, GATE_SCLK_CPU, CLKOUT_CMU_CPU, + APLL_CON0, + KPLL_CON0, CPLL_CON0, DPLL_CON0, EPLL_CON0, diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c index 35fabe1a32c30e4b400a77205c892f150b3f5f7c..269467e8e07e13a38399899c75194a347873c658 100644 --- a/drivers/clk/socfpga/clk-pll-a10.c +++ b/drivers/clk/socfpga/clk-pll-a10.c @@ -95,6 +95,7 @@ static struct clk * __init __socfpga_pll_init(struct device_node *node, clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr"); clk_mgr_a10_base_addr = of_iomap(clkmgr_np, 0); + of_node_put(clkmgr_np); BUG_ON(!clk_mgr_a10_base_addr); pll_clk->hw.reg = clk_mgr_a10_base_addr + reg; diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c index c7f463172e4b93d0cec4b46e45558a301aa16234..b4b44e9b5901132a4849261d1563a6f3a797a469 100644 --- a/drivers/clk/socfpga/clk-pll.c +++ b/drivers/clk/socfpga/clk-pll.c @@ -100,6 +100,7 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node, clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr"); clk_mgr_base_addr = of_iomap(clkmgr_np, 0); + of_node_put(clkmgr_np); BUG_ON(!clk_mgr_base_addr); pll_clk->hw.reg = clk_mgr_base_addr + reg; diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c index 5c6d37bdf247cfef1b4da1bcf185d1b56082f036..765c6977484e7df909119700e53b604e748f49df 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c @@ -132,7 +132,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_mipi_clk, "pll-mipi", 8, 4, /* N */ 4, 2, /* K */ 0, 4, /* M */ - BIT(31), /* gate */ + BIT(31) | BIT(23) | BIT(22), /* gate */ BIT(28), /* lock */ CLK_SET_RATE_UNGATE); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index a26c8a19fe93a2b8f1f768b414cb678f364d5542..9dd6daaa1336796154e538e912cd33d5f1c1fb6c 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -458,7 +458,7 @@ static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, 0x134, 16, 4, 24, 3, BIT(31), 0); -static const char * const csi_mclk_parents[] = { "osc24M", "pll-video", "pll-periph0" }; +static const char * const csi_mclk_parents[] = { "osc24M", "pll-video", "pll-periph1" }; static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, 0x134, 0, 5, 8, 3, BIT(15), 0); diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 4ce4e7fb1124d0aa38323454af5a782edffae42c..d9c1f229c644be8fcac5fbe35523133bbb4ae9ef 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -797,7 +797,11 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), - GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), + /* + * Critical for RAM re-repair operation, which must occur on resume + * from LP1 system suspend and as part of CCPLEX cluster switching. + */ + GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, CLK_IS_CRITICAL), GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0), GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0), GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0), diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c index 1ba871b7fe118454cc80d69e1998e6cfe838ac49..e5717807c00a7a18a5a766f518328e4a157e95ff 100644 --- a/drivers/clocksource/asm9260_timer.c +++ b/drivers/clocksource/asm9260_timer.c @@ -198,6 +198,10 @@ static int __init asm9260_timer_init(struct device_node *np) } clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("Failed to get clk!\n"); + return PTR_ERR(clk); + } ret = clk_prepare_enable(clk); if (ret) { diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index d32248e2ceab41d350f6f8134ceba0ac0a3901e3..ae3cbaeffd9c5e265911e97426e597d55c197e5c 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -563,7 +563,19 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem * return 0; out_irq: - free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick); + if (mct_int_type == MCT_INT_PPI) { + free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick); + } else { + for_each_possible_cpu(cpu) { + struct mct_clock_event_device *pcpu_mevt = + per_cpu_ptr(&percpu_mct_tick, cpu); + + if (pcpu_mevt->evt.irq != -1) { + free_irq(pcpu_mevt->evt.irq, pcpu_mevt); + pcpu_mevt->evt.irq = -1; + } + } + } return err; } diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index 4f87f3e76d8328ec6ca462882f873a51b2f72995..c3e96de525a2482389f0a3dd449e52684df52478 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -201,6 +201,11 @@ static int __init sun5i_setup_clocksource(struct device_node *node, } rate = clk_get_rate(clk); + if (!rate) { + pr_err("Couldn't get parent clock rate\n"); + ret = -EINVAL; + goto err_disable_clk; + } cs->timer.base = base; cs->timer.clk = clk; @@ -274,6 +279,11 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem } rate = clk_get_rate(clk); + if (!rate) { + pr_err("Couldn't get parent clock rate\n"); + ret = -EINVAL; + goto err_disable_clk; + } ce->timer.base = base; ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 34355a9e896479d1325015d0654363aae951d4b0..1667bc0e7b50562e8c0e6147a605eba78711c081 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2595,6 +2595,13 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) if (cpufreq_disabled()) return -ENODEV; + /* + * The cpufreq core depends heavily on the availability of device + * structure, make sure they are available before proceeding further. + */ + if (!get_cpu_device(0)) + return -EPROBE_DEFER; + if (!driver_data || !driver_data->verify || !driver_data->init || !(driver_data->setpolicy || driver_data->target_index || driver_data->target) || diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index ab264d393233683c28bac7e0770abb0ffe49b2ec..3780e1aa680772994bb2fa2d47c6dee1e53495f5 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -61,24 +61,23 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) * __cpuidle_set_driver - set per CPU driver variables for the given driver. * @drv: a valid pointer to a struct cpuidle_driver * - * For each CPU in the driver's cpumask, unset the registered driver per CPU - * to @drv. - * - * Returns 0 on success, -EBUSY if the CPUs have driver(s) already. + * Returns 0 on success, -EBUSY if any CPU in the cpumask have a driver + * different from drv already. */ static inline int __cpuidle_set_driver(struct cpuidle_driver *drv) { int cpu; for_each_cpu(cpu, drv->cpumask) { + struct cpuidle_driver *old_drv; - if (__cpuidle_get_cpu_driver(cpu)) { - __cpuidle_unset_driver(drv); + old_drv = __cpuidle_get_cpu_driver(cpu); + if (old_drv && old_drv != drv) return -EBUSY; - } + } + for_each_cpu(cpu, drv->cpumask) per_cpu(cpuidle_drivers, cpu) = drv; - } return 0; } diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 7d066fa9f2ade4915faa8ea1e246d6d15f6d8f70..e5e83c6de5360a35301d783b3961bbbe91b05580 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -400,12 +400,8 @@ static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev) dma_alloc_coherent(dev->core_dev->device, dev->scatter_buffer_size * PPC4XX_NUM_SD, &dev->scatter_buffer_pa, GFP_ATOMIC); - if (!dev->scatter_buffer_va) { - dma_free_coherent(dev->core_dev->device, - sizeof(struct ce_sd) * PPC4XX_NUM_SD, - dev->sdr, dev->sdr_pa); + if (!dev->scatter_buffer_va) return -ENOMEM; - } sd_array = dev->sdr; diff --git a/drivers/crypto/amcc/crypto4xx_trng.h b/drivers/crypto/amcc/crypto4xx_trng.h index 931d22531f51590749c803d0dd694e820cab87d8..7bbda51b7337c3a0f5df5d3b9427c75e2d30908f 100644 --- a/drivers/crypto/amcc/crypto4xx_trng.h +++ b/drivers/crypto/amcc/crypto4xx_trng.h @@ -26,9 +26,9 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev); void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev); #else static inline void ppc4xx_trng_probe( - struct crypto4xx_device *dev __maybe_unused) { } + struct crypto4xx_core_device *dev __maybe_unused) { } static inline void ppc4xx_trng_remove( - struct crypto4xx_device *dev __maybe_unused) { } + struct crypto4xx_core_device *dev __maybe_unused) { } #endif #endif diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index e3d40a8dfffbc35259f3d2342d6343da343b0521..915253b9c9128242d066c2cbbfa9e807453600c4 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -87,7 +87,6 @@ struct atmel_aes_caps { bool has_dualbuff; bool has_cfb64; - bool has_ctr32; bool has_gcm; u32 max_burst_size; }; @@ -923,8 +922,9 @@ static int atmel_aes_ctr_transfer(struct atmel_aes_dev *dd) struct atmel_aes_ctr_ctx *ctx = atmel_aes_ctr_ctx_cast(dd->ctx); struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq); struct scatterlist *src, *dst; - u32 ctr, blocks; size_t datalen; + u32 ctr; + u16 blocks, start, end; bool use_dma, fragmented = false; /* Check for transfer completion. */ @@ -936,27 +936,17 @@ static int atmel_aes_ctr_transfer(struct atmel_aes_dev *dd) datalen = req->nbytes - ctx->offset; blocks = DIV_ROUND_UP(datalen, AES_BLOCK_SIZE); ctr = be32_to_cpu(ctx->iv[3]); - if (dd->caps.has_ctr32) { - /* Check 32bit counter overflow. */ - u32 start = ctr; - u32 end = start + blocks - 1; - - if (end < start) { - ctr |= 0xffffffff; - datalen = AES_BLOCK_SIZE * -start; - fragmented = true; - } - } else { - /* Check 16bit counter overflow. */ - u16 start = ctr & 0xffff; - u16 end = start + (u16)blocks - 1; - - if (blocks >> 16 || end < start) { - ctr |= 0xffff; - datalen = AES_BLOCK_SIZE * (0x10000-start); - fragmented = true; - } + + /* Check 16bit counter overflow. */ + start = ctr & 0xffff; + end = start + blocks - 1; + + if (blocks >> 16 || end < start) { + ctr |= 0xffff; + datalen = AES_BLOCK_SIZE * (0x10000 - start); + fragmented = true; } + use_dma = (datalen >= ATMEL_AES_DMA_THRESHOLD); /* Jump to offset. */ @@ -1926,7 +1916,6 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) { dd->caps.has_dualbuff = 0; dd->caps.has_cfb64 = 0; - dd->caps.has_ctr32 = 0; dd->caps.has_gcm = 0; dd->caps.max_burst_size = 1; @@ -1935,14 +1924,12 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) case 0x500: dd->caps.has_dualbuff = 1; dd->caps.has_cfb64 = 1; - dd->caps.has_ctr32 = 1; dd->caps.has_gcm = 1; dd->caps.max_burst_size = 4; break; case 0x200: dd->caps.has_dualbuff = 1; dd->caps.has_cfb64 = 1; - dd->caps.has_ctr32 = 1; dd->caps.has_gcm = 1; dd->caps.max_burst_size = 4; break; diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c index 9b92af2c72412fd05390da752956c9e52d84014d..a77319bf221d86131e61f11ea709b92fd683b0d7 100644 --- a/drivers/crypto/caam/caamrng.c +++ b/drivers/crypto/caam/caamrng.c @@ -361,7 +361,10 @@ static int __init caam_rng_init(void) goto free_rng_ctx; dev_info(dev, "registering rng-caam\n"); - return hwrng_register(&caam_rng); + + err = hwrng_register(&caam_rng); + if (!err) + return err; free_rng_ctx: kfree(rng_ctx); diff --git a/drivers/crypto/ccp/ccp-crypto-aes.c b/drivers/crypto/ccp/ccp-crypto-aes.c index 89291c15015cd3eb0218ec20747273db310a9dd4..3f768699332ba230d7518dee75ae7ada6b357d3a 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes.c +++ b/drivers/crypto/ccp/ccp-crypto-aes.c @@ -1,7 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * AMD Cryptographic Coprocessor (CCP) AES crypto API support * - * Copyright (C) 2013,2016 Advanced Micro Devices, Inc. + * Copyright (C) 2013-2019 Advanced Micro Devices, Inc. * * Author: Tom Lendacky * @@ -79,8 +80,7 @@ static int ccp_aes_crypt(struct ablkcipher_request *req, bool encrypt) return -EINVAL; if (((ctx->u.aes.mode == CCP_AES_MODE_ECB) || - (ctx->u.aes.mode == CCP_AES_MODE_CBC) || - (ctx->u.aes.mode == CCP_AES_MODE_CFB)) && + (ctx->u.aes.mode == CCP_AES_MODE_CBC)) && (req->nbytes & (AES_BLOCK_SIZE - 1))) return -EINVAL; @@ -291,7 +291,7 @@ static struct ccp_aes_def aes_algs[] = { .version = CCP_VERSION(3, 0), .name = "cfb(aes)", .driver_name = "cfb-aes-ccp", - .blocksize = AES_BLOCK_SIZE, + .blocksize = 1, .ivsize = AES_BLOCK_SIZE, .alg_defaults = &ccp_aes_defaults, }, diff --git a/drivers/crypto/ccp/ccp-dmaengine.c b/drivers/crypto/ccp/ccp-dmaengine.c index 8d0eeb46d4a27437678a34da89f090db2d625c45..c4581510c3a142fa277a6404a27e280004628ec9 100644 --- a/drivers/crypto/ccp/ccp-dmaengine.c +++ b/drivers/crypto/ccp/ccp-dmaengine.c @@ -309,6 +309,7 @@ static struct ccp_dma_desc *ccp_alloc_dma_desc(struct ccp_dma_chan *chan, desc->tx_desc.flags = flags; desc->tx_desc.tx_submit = ccp_tx_submit; desc->ccp = chan->ccp; + INIT_LIST_HEAD(&desc->entry); INIT_LIST_HEAD(&desc->pending); INIT_LIST_HEAD(&desc->active); desc->status = DMA_IN_PROGRESS; diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index db1d3d8f5ca4da076796df8a7f300539f96778cd..a9ec5954238ec9c09ebc7c41eda477d73f9a3694 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1,7 +1,7 @@ /* * QTI CE device driver. * - * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-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 @@ -1918,6 +1918,11 @@ static inline long qcedev_ioctl(struct file *file, goto exit_free_qcedev_areq; } + if (map_buf.num_fds > QCEDEV_MAX_BUFFERS) { + err = -EINVAL; + goto exit_free_qcedev_areq; + } + for (i = 0; i < map_buf.num_fds; i++) { err = qcedev_check_and_map_buffer(handle, map_buf.fd[i], diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c index 47576098831f9db194f81b2cf68dce08e38dece6..b3ea6d60c4583bf2b056194c4710ec27d5d5b89d 100644 --- a/drivers/crypto/picoxcell_crypto.c +++ b/drivers/crypto/picoxcell_crypto.c @@ -1632,6 +1632,11 @@ static bool spacc_is_compatible(struct platform_device *pdev, return false; } +static void spacc_tasklet_kill(void *data) +{ + tasklet_kill(data); +} + static int spacc_probe(struct platform_device *pdev) { int i, err, ret = -EINVAL; @@ -1674,6 +1679,14 @@ static int spacc_probe(struct platform_device *pdev) return -ENXIO; } + tasklet_init(&engine->complete, spacc_spacc_complete, + (unsigned long)engine); + + ret = devm_add_action(&pdev->dev, spacc_tasklet_kill, + &engine->complete); + if (ret) + return ret; + if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0, engine->name, engine)) { dev_err(engine->dev, "failed to request IRQ\n"); @@ -1736,8 +1749,6 @@ static int spacc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&engine->completed); INIT_LIST_HEAD(&engine->in_progress); engine->in_flight = 0; - tasklet_init(&engine->complete, spacc_spacc_complete, - (unsigned long)engine); platform_set_drvdata(pdev, engine); diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c index ec16ec2e284d0bb7fa5d4cc191ac6eafb497fe72..b2e6837135393c2accd05f68619f7dc099898ff4 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c @@ -286,8 +286,8 @@ static int sun4i_hash(struct ahash_request *areq) */ while (op->len < 64 && i < end) { /* how many bytes we can read from current SG */ - in_r = min3(mi.length - in_i, end - i, - 64 - op->len); + in_r = min(end - i, 64 - op->len); + in_r = min_t(size_t, mi.length - in_i, in_r); memcpy(op->buf + op->len, mi.addr + in_i, in_r); op->len += in_r; i += in_r; @@ -307,8 +307,8 @@ static int sun4i_hash(struct ahash_request *areq) } if (mi.length - in_i > 3 && i < end) { /* how many bytes we can read from current SG */ - in_r = min3(mi.length - in_i, areq->nbytes - i, - ((mi.length - in_i) / 4) * 4); + in_r = min_t(size_t, mi.length - in_i, areq->nbytes - i); + in_r = min_t(size_t, ((mi.length - in_i) / 4) * 4, in_r); /* how many bytes we can write in the device*/ todo = min3((u32)(end - i) / 4, rx_cnt, (u32)in_r / 4); writesl(ss->base + SS_RXFIFO, mi.addr + in_i, todo); @@ -334,8 +334,8 @@ static int sun4i_hash(struct ahash_request *areq) if ((areq->nbytes - i) < 64) { while (i < areq->nbytes && in_i < mi.length && op->len < 64) { /* how many bytes we can read from current SG */ - in_r = min3(mi.length - in_i, areq->nbytes - i, - 64 - op->len); + in_r = min(areq->nbytes - i, 64 - op->len); + in_r = min_t(size_t, mi.length - in_i, in_r); memcpy(op->buf + op->len, mi.addr + in_i, in_r); op->len += in_r; i += in_r; diff --git a/drivers/crypto/vmx/Makefile b/drivers/crypto/vmx/Makefile index de6e241b086668291e88c75d9ab7ef391648a895..957377c309a91caec0921cd7585b43e5e940de1d 100644 --- a/drivers/crypto/vmx/Makefile +++ b/drivers/crypto/vmx/Makefile @@ -2,13 +2,13 @@ obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) -TARGET := linux-ppc64le +override flavour := linux-ppc64le else -TARGET := linux-ppc64 +override flavour := linux-ppc64 endif quiet_cmd_perl = PERL $@ - cmd_perl = $(PERL) $(<) $(TARGET) > $(@) + cmd_perl = $(PERL) $(<) $(flavour) > $(@) $(src)/aesp8-ppc.S: $(src)/aesp8-ppc.pl $(call cmd,perl) diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 3a2239ccf9f78ce38cf5816251de33584af9092f..a806ee7d7d07d7d2d9385514a63c9d6dd3c8aa07 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -202,7 +202,8 @@ config ARM_TEGRA_DEVFREQ config ARM_RK3399_DMC_DEVFREQ tristate "ARM RK3399 DMC DEVFREQ Driver" - depends on ARCH_ROCKCHIP + depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \ + (COMPILE_TEST && HAVE_ARM_SMCCC) select DEVFREQ_EVENT_ROCKCHIP_DFI select DEVFREQ_GOV_SIMPLE_ONDEMAND select PM_DEVFREQ_EVENT diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 2298de2a24fdb1af19354a84d610c90c6137b771..5dd0acaa799f9a925db257fdb9ff5a9f7b125958 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -158,6 +158,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) int lev, prev_lev, ret = 0; unsigned long cur_time; + lockdep_assert_held(&devfreq->lock); cur_time = jiffies; /* Immediately exit if previous_freq is not initialized yet. */ @@ -504,11 +505,6 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, static void _remove_devfreq(struct devfreq *devfreq) { mutex_lock(&devfreq_list_lock); - if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) { - mutex_unlock(&devfreq_list_lock); - dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n"); - return; - } list_del(&devfreq->node); mutex_unlock(&devfreq_list_lock); @@ -582,6 +578,7 @@ struct devfreq *devfreq_add_device(struct device *dev, devfreq->dev.parent = dev; devfreq->dev.class = devfreq_class; devfreq->dev.release = devfreq_dev_release; + INIT_LIST_HEAD(&devfreq->node); devfreq->profile = profile; strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN); devfreq->previous_freq = profile->initial_freq; @@ -1024,7 +1021,7 @@ static ssize_t available_governors_show(struct device *d, * The devfreq with immutable governor (e.g., passive) shows * only own governor. */ - if (df->governor->immutable) { + if (df->governor && df->governor->immutable) { count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, "%s ", df->governor_name); /* @@ -1222,12 +1219,17 @@ static ssize_t trans_stat_show(struct device *dev, int i, j; unsigned int max_state = devfreq->profile->max_state; - if (!devfreq->stop_polling && - devfreq_update_status(devfreq, devfreq->previous_freq)) - return 0; if (max_state == 0) return sprintf(buf, "Not Supported.\n"); + mutex_lock(&devfreq->lock); + if (!devfreq->stop_polling && + devfreq_update_status(devfreq, devfreq->previous_freq)) { + mutex_unlock(&devfreq->lock); + return 0; + } + mutex_unlock(&devfreq->lock); + len = sprintf(buf, " From : To\n"); len += sprintf(buf + len, " :"); for (i = 0; i < max_state; i++) diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig index cd949800eed962cffa34b599d3ce66f386763d11..8851bc4e8e3e17935b6fc109ff926722c3d68737 100644 --- a/drivers/devfreq/event/Kconfig +++ b/drivers/devfreq/event/Kconfig @@ -33,7 +33,7 @@ config DEVFREQ_EVENT_EXYNOS_PPMU config DEVFREQ_EVENT_ROCKCHIP_DFI tristate "ROCKCHIP DFI DEVFREQ event Driver" - depends on ARCH_ROCKCHIP + depends on ARCH_ROCKCHIP || COMPILE_TEST help This add the devfreq-event driver for Rockchip SoC. It provides DFI (DDR Monitor Module) driver to count ddr load. diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 1936383c742da6992e126083138a3984ad0fe2a5..426a75dba3bd080ea515fb5cf89f805f4bbdc94f 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -210,7 +210,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, a_fences = get_fences(a, &a_num_fences); b_fences = get_fences(b, &b_num_fences); if (a_num_fences > INT_MAX - b_num_fences) - return NULL; + goto err; num_fences = a_num_fences + b_num_fences; diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 74794c9859f60d072e2ba767c7a015bc4b3bfbe0..f0932f25a9b1ff03e0d8df782f4ddbdd26bd1000 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -1797,13 +1797,10 @@ static struct dma_chan *coh901318_xlate(struct of_phandle_args *dma_spec, static int coh901318_config(struct coh901318_chan *cohc, struct coh901318_params *param) { - unsigned long flags; const struct coh901318_params *p; int channel = cohc->id; void __iomem *virtbase = cohc->base->virtbase; - spin_lock_irqsave(&cohc->lock, flags); - if (param) p = param; else @@ -1823,8 +1820,6 @@ static int coh901318_config(struct coh901318_chan *cohc, coh901318_set_conf(cohc, p->config); coh901318_set_ctrl(cohc, p->ctrl_lli_last); - spin_unlock_irqrestore(&cohc->lock, flags); - return 0; } @@ -1949,8 +1944,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc) return; } - spin_lock(&cohc->lock); - /* * When we reach this point, at least one queue item * should have been moved over from cohc->queue to @@ -1971,8 +1964,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc) if (coh901318_queue_start(cohc) == NULL) cohc->busy = 0; - spin_unlock(&cohc->lock); - /* * This tasklet will remove items from cohc->active * and thus terminates them. diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 7f0b9aa158679aca780d86890426339f48586f4b..9887f2a14aa9885a4211444cf09acd0c9bbe931b 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -451,7 +451,7 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_interleaved( if (chan->hw_2d) { if (!axi_dmac_check_len(chan, xt->sgl[0].size) || - !axi_dmac_check_len(chan, xt->numf)) + xt->numf == 0) return NULL; if (xt->sgl[0].size + dst_icg > chan->max_length || xt->sgl[0].size + src_icg > chan->max_length) diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 5bda0eb9f393f8b25c6bcbe180cbacd675bd8456..7536fe80bc33f6df861ff74a966fba221321e3b0 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -87,13 +87,20 @@ static void dw_dma_acpi_controller_register(struct dw_dma *dw) dma_cap_set(DMA_SLAVE, info->dma_cap); info->filter_fn = dw_dma_acpi_filter; - ret = devm_acpi_dma_controller_register(dev, acpi_dma_simple_xlate, - info); + ret = acpi_dma_controller_register(dev, acpi_dma_simple_xlate, info); if (ret) dev_err(dev, "could not register acpi_dma_controller\n"); } + +static void dw_dma_acpi_controller_free(struct dw_dma *dw) +{ + struct device *dev = dw->dma.dev; + + acpi_dma_controller_free(dev); +} #else /* !CONFIG_ACPI */ static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {} +static inline void dw_dma_acpi_controller_free(struct dw_dma *dw) {} #endif /* !CONFIG_ACPI */ #ifdef CONFIG_OF @@ -226,6 +233,9 @@ static int dw_remove(struct platform_device *pdev) { struct dw_dma_chip *chip = platform_get_drvdata(pdev); + if (ACPI_HANDLE(&pdev->dev)) + dw_dma_acpi_controller_free(chip->dw); + if (pdev->dev.of_node) of_dma_controller_free(pdev->dev.of_node); diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 72f31e837b1d5a759e1686d3cf1ba8b54690a93a..56ec724687456d8f16a0e8b6947fc559b4416bcb 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -2340,8 +2340,10 @@ static int edma_probe(struct platform_device *pdev) ecc->tc_list = devm_kcalloc(dev, ecc->num_tc, sizeof(*ecc->tc_list), GFP_KERNEL); - if (!ecc->tc_list) - return -ENOMEM; + if (!ecc->tc_list) { + ret = -ENOMEM; + goto err_reg1; + } for (i = 0;; i++) { ret = of_parse_phandle_with_fixed_args(node, "ti,tptcs", diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index 29d04ca71d52ed05e47435a869fd7826ae93aa08..15525a2b8ebd71429ab64378721f1e9eb8da592c 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -64,10 +64,10 @@ static void hsu_dma_chan_start(struct hsu_dma_chan *hsuc) if (hsuc->direction == DMA_MEM_TO_DEV) { bsr = config->dst_maxburst; - mtsr = config->src_addr_width; + mtsr = config->dst_addr_width; } else if (hsuc->direction == DMA_DEV_TO_MEM) { bsr = config->src_maxburst; - mtsr = config->dst_addr_width; + mtsr = config->src_addr_width; } hsu_chan_disable(hsuc); diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 9f240b2d85a54b90e50b097e60efc966b11eb72a..558d509b7d855d7c2280a36b40a21099f9d2552b 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1441,6 +1441,14 @@ static void sdma_add_scripts(struct sdma_engine *sdma, if (!sdma->script_number) sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; + if (sdma->script_number > sizeof(struct sdma_script_start_addrs) + / sizeof(s32)) { + dev_err(sdma->dev, + "SDMA script number %d not match with firmware.\n", + sdma->script_number); + return; + } + for (i = 0; i < sdma->script_number; i++) if (addr_arr[i] > 0) saddr_arr[i] = addr_arr[i]; diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 49386ce04bf52ebd7f66855f631f8efcb2a8fa1d..1389f0582e29b64addfb982a682de6de80eff046 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -394,10 +394,11 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags) descs->virt = dma_alloc_coherent(to_dev(ioat_chan), SZ_2M, &descs->hw, flags); - if (!descs->virt && (i > 0)) { + if (!descs->virt) { int idx; for (idx = 0; idx < i; idx++) { + descs = &ioat_chan->descs[idx]; dma_free_coherent(to_dev(ioat_chan), SZ_2M, descs->virt, descs->hw); descs->virt = NULL; diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 23f75285a4d9cce9da54300ea4273e7df32ec133..5d524f29c5f115b454cf6d2044c849cd42e45cbd 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -1044,6 +1044,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev, mv_chan->op_in_desc = XOR_MODE_IN_DESC; dma_dev = &mv_chan->dmadev; + dma_dev->dev = &pdev->dev; mv_chan->xordev = xordev; /* @@ -1076,7 +1077,6 @@ mv_xor_channel_add(struct mv_xor_device *xordev, dma_dev->device_free_chan_resources = mv_xor_free_chan_resources; dma_dev->device_tx_status = mv_xor_status; dma_dev->device_issue_pending = mv_xor_issue_pending; - dma_dev->dev = &pdev->dev; /* set prep routines based on capability */ if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask)) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 22f7f0c68a48cf80590fc58be01381ae7b30f4e1..4eaf92b2b8868a35ee8fda123b60a11372545d3c 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -288,7 +288,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get( /* Do not allocate if desc are waiting for ack */ list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) { - if (async_tx_test_ack(&dma_desc->txd)) { + if (async_tx_test_ack(&dma_desc->txd) && !dma_desc->cb_count) { list_del(&dma_desc->node); spin_unlock_irqrestore(&tdc->lock, flags); dma_desc->txd.flags = 0; @@ -755,10 +755,6 @@ static int tegra_dma_terminate_all(struct dma_chan *dc) bool was_busy; spin_lock_irqsave(&tdc->lock, flags); - if (list_empty(&tdc->pending_sg_req)) { - spin_unlock_irqrestore(&tdc->lock, flags); - return 0; - } if (!tdc->busy) goto skip_dma_stop; diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index e9e46a520745223fb4c71edd1079c018af7c6e16..2d4aeba579f7530d7df5e1571ecfc95006b4a792 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -98,6 +98,7 @@ struct tegra_adma_chan_regs { unsigned int src_addr; unsigned int trg_addr; unsigned int fifo_ctrl; + unsigned int cmd; unsigned int tc; }; @@ -127,6 +128,7 @@ struct tegra_adma_chan { enum dma_transfer_direction sreq_dir; unsigned int sreq_index; bool sreq_reserved; + struct tegra_adma_chan_regs ch_regs; /* Transfer count and position info */ unsigned int tx_buf_count; @@ -635,8 +637,30 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec, static int tegra_adma_runtime_suspend(struct device *dev) { struct tegra_adma *tdma = dev_get_drvdata(dev); + struct tegra_adma_chan_regs *ch_reg; + struct tegra_adma_chan *tdc; + int i; tdma->global_cmd = tdma_read(tdma, ADMA_GLOBAL_CMD); + if (!tdma->global_cmd) + goto clk_disable; + + for (i = 0; i < tdma->nr_channels; i++) { + tdc = &tdma->channels[i]; + ch_reg = &tdc->ch_regs; + ch_reg->cmd = tdma_ch_read(tdc, ADMA_CH_CMD); + /* skip if channel is not active */ + if (!ch_reg->cmd) + continue; + ch_reg->tc = tdma_ch_read(tdc, ADMA_CH_TC); + ch_reg->src_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_SRC_ADDR); + ch_reg->trg_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_TRG_ADDR); + ch_reg->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL); + ch_reg->fifo_ctrl = tdma_ch_read(tdc, ADMA_CH_FIFO_CTRL); + ch_reg->config = tdma_ch_read(tdc, ADMA_CH_CONFIG); + } + +clk_disable: clk_disable_unprepare(tdma->ahub_clk); return 0; @@ -645,7 +669,9 @@ static int tegra_adma_runtime_suspend(struct device *dev) static int tegra_adma_runtime_resume(struct device *dev) { struct tegra_adma *tdma = dev_get_drvdata(dev); - int ret; + struct tegra_adma_chan_regs *ch_reg; + struct tegra_adma_chan *tdc; + int ret, i; ret = clk_prepare_enable(tdma->ahub_clk); if (ret) { @@ -654,6 +680,24 @@ static int tegra_adma_runtime_resume(struct device *dev) } tdma_write(tdma, ADMA_GLOBAL_CMD, tdma->global_cmd); + if (!tdma->global_cmd) + return 0; + + for (i = 0; i < tdma->nr_channels; i++) { + tdc = &tdma->channels[i]; + ch_reg = &tdc->ch_regs; + /* skip if channel was not active earlier */ + if (!ch_reg->cmd) + continue; + tdma_ch_write(tdc, ADMA_CH_TC, ch_reg->tc); + tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR, ch_reg->src_addr); + tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR, ch_reg->trg_addr); + tdma_ch_write(tdc, ADMA_CH_CTRL, ch_reg->ctrl); + tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_reg->fifo_ctrl); + tdma_ch_write(tdc, ADMA_CH_CONFIG, ch_reg->config); + tdma_ch_write(tdc, ADMA_CH_CMD, ch_reg->cmd); + } + return 0; } @@ -700,16 +744,6 @@ static int tegra_adma_probe(struct platform_device *pdev) return PTR_ERR(tdma->ahub_clk); } - pm_runtime_enable(&pdev->dev); - - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) - goto rpm_disable; - - ret = tegra_adma_init(tdma); - if (ret) - goto rpm_put; - INIT_LIST_HEAD(&tdma->dma_dev.channels); for (i = 0; i < tdma->nr_channels; i++) { struct tegra_adma_chan *tdc = &tdma->channels[i]; @@ -727,6 +761,16 @@ static int tegra_adma_probe(struct platform_device *pdev) tdc->tdma = tdma; } + pm_runtime_enable(&pdev->dev); + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + goto rpm_disable; + + ret = tegra_adma_init(tdma); + if (ret) + goto rpm_put; + dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask); dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask); dma_cap_set(DMA_CYCLIC, tdma->dma_dev.cap_mask); @@ -768,13 +812,13 @@ static int tegra_adma_probe(struct platform_device *pdev) dma_remove: dma_async_device_unregister(&tdma->dma_dev); -irq_dispose: - while (--i >= 0) - irq_dispose_mapping(tdma->channels[i].irq); rpm_put: pm_runtime_put_sync(&pdev->dev); rpm_disable: pm_runtime_disable(&pdev->dev); +irq_dispose: + while (--i >= 0) + irq_dispose_mapping(tdma->channels[i].irq); return ret; } diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index e3fa4390f8460685c0bd57fe8d52c9c043de719f..4ddbf6604e2abf13e5c2725392ce4213de691d8c 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c @@ -189,6 +189,7 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev, /* Cleans the error report buffer */ memset(e, 0, sizeof (*e)); e->error_count = 1; + e->grain = 1; strcpy(e->label, "unknown label"); e->msg = pvt->msg; e->other_detail = pvt->other_detail; @@ -284,7 +285,7 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev, /* Error grain */ if (mem_err->validation_bits & CPER_MEM_VALID_PA_MASK) - e->grain = ~(mem_err->physical_addr_mask & ~PAGE_MASK); + e->grain = ~mem_err->physical_addr_mask + 1; /* Memory error location, mapped on e->location */ p = e->location; @@ -391,8 +392,13 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev, if (p > pvt->other_detail) *(p - 1) = '\0'; + /* Sanity-check driver-supplied grain value. */ + if (WARN_ON_ONCE(!e->grain)) + e->grain = 1; + + grain_bits = fls_long(e->grain - 1); + /* Generate the trace event */ - grain_bits = fls_long(e->grain); snprintf(pvt->detail_location, sizeof(pvt->detail_location), "APEI location: %s %s", e->location, e->other_detail); trace_mc_event(type, e->msg, e->label, e->error_count, diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index 4a0612fb9c07029b830c128b13f4efbf3832369a..b9b48d45a6dc444071556d6d150077f56866146a 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -321,12 +321,10 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info, { int ret = 0; - if (usb_type == MAX8997_USB_HOST) { - ret = max8997_muic_set_path(info, info->path_usb, attached); - if (ret < 0) { - dev_err(info->dev, "failed to update muic register\n"); - return ret; - } + ret = max8997_muic_set_path(info, info->path_usb, attached); + if (ret < 0) { + dev_err(info->dev, "failed to update muic register\n"); + return ret; } switch (usb_type) { diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index b223256885033f01a2af1be8da6fbdb8d5a1ae2c..9d2d8a6673c887d6f687c64ff106f8b34215aae1 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -69,6 +69,10 @@ struct sm5502_muic_info { /* Default value of SM5502 register to bring up MUIC device. */ static struct reg_data sm5502_reg_data[] = { { + .reg = SM5502_REG_RESET, + .val = SM5502_REG_RESET_MASK, + .invert = true, + }, { .reg = SM5502_REG_CONTROL, .val = SM5502_REG_CONTROL_MASK_INT_MASK, .invert = false, diff --git a/drivers/extcon/extcon-sm5502.h b/drivers/extcon/extcon-sm5502.h index 974b53222f568df3aefcc25c9fe7c732eec7ec4d..12f8b01e575387be81bde88395d7a2f1e57433ac 100644 --- a/drivers/extcon/extcon-sm5502.h +++ b/drivers/extcon/extcon-sm5502.h @@ -241,6 +241,8 @@ enum sm5502_reg { #define DM_DP_SWITCH_UART ((DM_DP_CON_SWITCH_UART <hh_data + HH_DATA_OFF(sizeof(*h))); h->h_proto = type; memcpy(h->h_dest, neigh->ha, net->addr_len); - hh->hh_len = FWNET_HLEN; + + /* Pairs with the READ_ONCE() in neigh_resolve_output(), + * neigh_hh_output() and neigh_update_hhs(). + */ + smp_store_release(&hh->hh_len, FWNET_HLEN); return 0; } diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 3e626fd9bd4e1fafe6e0f4da4597ed66a978bd08..1c65f5ac43686cea83939ad3672ca29ba00278f1 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -139,13 +139,16 @@ static ssize_t efivar_attr_read(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; + unsigned long size = sizeof(var->Data); char *str = buf; + int ret; if (!entry || !buf) return -EINVAL; - var->DataSize = 1024; - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) + ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); + var->DataSize = size; + if (ret) return -EIO; if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) @@ -172,13 +175,16 @@ static ssize_t efivar_size_read(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; + unsigned long size = sizeof(var->Data); char *str = buf; + int ret; if (!entry || !buf) return -EINVAL; - var->DataSize = 1024; - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) + ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); + var->DataSize = size; + if (ret) return -EIO; str += sprintf(str, "0x%lx\n", var->DataSize); @@ -189,12 +195,15 @@ static ssize_t efivar_data_read(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; + unsigned long size = sizeof(var->Data); + int ret; if (!entry || !buf) return -EINVAL; - var->DataSize = 1024; - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) + ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); + var->DataSize = size; + if (ret) return -EIO; memcpy(buf, var->Data, var->DataSize); @@ -263,6 +272,9 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) u8 *data; int err; + if (!entry || !buf) + return -EINVAL; + if (is_compat()) { struct compat_efi_variable *compat; @@ -314,14 +326,16 @@ efivar_show_raw(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; struct compat_efi_variable *compat; + unsigned long datasize = sizeof(var->Data); size_t size; + int ret; if (!entry || !buf) return 0; - var->DataSize = 1024; - if (efivar_entry_get(entry, &entry->var.Attributes, - &entry->var.DataSize, entry->var.Data)) + ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data); + var->DataSize = datasize; + if (ret) return -EIO; if (is_compat()) { diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c index 24c461dea7afb146a509e097b581aa2fdaede132..fd8053f9556e72090d595a736621333aa5be546a 100644 --- a/drivers/firmware/efi/libstub/gop.c +++ b/drivers/firmware/efi/libstub/gop.c @@ -85,30 +85,6 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, } } -static efi_status_t -__gop_query32(efi_system_table_t *sys_table_arg, - struct efi_graphics_output_protocol_32 *gop32, - struct efi_graphics_output_mode_info **info, - unsigned long *size, u64 *fb_base) -{ - struct efi_graphics_output_protocol_mode_32 *mode; - efi_graphics_output_protocol_query_mode query_mode; - efi_status_t status; - unsigned long m; - - m = gop32->mode; - mode = (struct efi_graphics_output_protocol_mode_32 *)m; - query_mode = (void *)(unsigned long)gop32->query_mode; - - status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size, - info); - if (status != EFI_SUCCESS) - return status; - - *fb_base = mode->frame_buffer_base; - return status; -} - static efi_status_t setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, efi_guid_t *proto, unsigned long size, void **gop_handle) @@ -121,7 +97,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, u64 fb_base; struct efi_pixel_bitmask pixel_info; int pixel_format; - efi_status_t status = EFI_NOT_FOUND; + efi_status_t status; u32 *handles = (u32 *)(unsigned long)gop_handle; int i; @@ -130,6 +106,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, nr_gops = size / sizeof(u32); for (i = 0; i < nr_gops; i++) { + struct efi_graphics_output_protocol_mode_32 *mode; struct efi_graphics_output_mode_info *info = NULL; efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; bool conout_found = false; @@ -147,9 +124,11 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, if (status == EFI_SUCCESS) conout_found = true; - status = __gop_query32(sys_table_arg, gop32, &info, &size, - ¤t_fb_base); - if (status == EFI_SUCCESS && (!first_gop || conout_found) && + mode = (void *)(unsigned long)gop32->mode; + info = (void *)(unsigned long)mode->info; + current_fb_base = mode->frame_buffer_base; + + if ((!first_gop || conout_found) && info->pixel_format != PIXEL_BLT_ONLY) { /* * Systems that use the UEFI Console Splitter may @@ -177,7 +156,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, /* Did we find any GOPs? */ if (!first_gop) - goto out; + return EFI_NOT_FOUND; /* EFI framebuffer */ si->orig_video_isVGA = VIDEO_TYPE_EFI; @@ -199,32 +178,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, si->lfb_size = si->lfb_linelength * si->lfb_height; si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; -out: - return status; -} - -static efi_status_t -__gop_query64(efi_system_table_t *sys_table_arg, - struct efi_graphics_output_protocol_64 *gop64, - struct efi_graphics_output_mode_info **info, - unsigned long *size, u64 *fb_base) -{ - struct efi_graphics_output_protocol_mode_64 *mode; - efi_graphics_output_protocol_query_mode query_mode; - efi_status_t status; - unsigned long m; - - m = gop64->mode; - mode = (struct efi_graphics_output_protocol_mode_64 *)m; - query_mode = (void *)(unsigned long)gop64->query_mode; - - status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size, - info); - if (status != EFI_SUCCESS) - return status; - *fb_base = mode->frame_buffer_base; - return status; + return EFI_SUCCESS; } static efi_status_t @@ -239,7 +194,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, u64 fb_base; struct efi_pixel_bitmask pixel_info; int pixel_format; - efi_status_t status = EFI_NOT_FOUND; + efi_status_t status; u64 *handles = (u64 *)(unsigned long)gop_handle; int i; @@ -248,6 +203,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, nr_gops = size / sizeof(u64); for (i = 0; i < nr_gops; i++) { + struct efi_graphics_output_protocol_mode_64 *mode; struct efi_graphics_output_mode_info *info = NULL; efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; bool conout_found = false; @@ -265,9 +221,11 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, if (status == EFI_SUCCESS) conout_found = true; - status = __gop_query64(sys_table_arg, gop64, &info, &size, - ¤t_fb_base); - if (status == EFI_SUCCESS && (!first_gop || conout_found) && + mode = (void *)(unsigned long)gop64->mode; + info = (void *)(unsigned long)mode->info; + current_fb_base = mode->frame_buffer_base; + + if ((!first_gop || conout_found) && info->pixel_format != PIXEL_BLT_ONLY) { /* * Systems that use the UEFI Console Splitter may @@ -295,7 +253,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, /* Did we find any GOPs? */ if (!first_gop) - goto out; + return EFI_NOT_FOUND; /* EFI framebuffer */ si->orig_video_isVGA = VIDEO_TYPE_EFI; @@ -317,8 +275,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, si->lfb_size = si->lfb_linelength * si->lfb_height; si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; -out: - return status; + + return EFI_SUCCESS; } /* diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 1e2e5198db53882ce616d6ec56be81db8244973b..7c31d27649fe85d650a0f1393c1a8f1911bc4948 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -158,7 +158,7 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, kfree(args_virt); } - if (res->a0 < 0) + if ((long)res->a0 < 0) return qcom_scm_remap_error(res->a0); return 0; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ceb741e254ea4cef1f042edd767216725a6ffd48..5060064acd4550119e2ec0e0e16932041414c49b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -938,6 +938,7 @@ config GPIO_LP873X config GPIO_MAX77620 tristate "GPIO support for PMIC MAX77620 and MAX20024" depends on MFD_MAX77620 + select GPIOLIB_IRQCHIP help GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor. MAX77620 PMIC has 8 pins that can be configured as GPIOs. The diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 7847dd34f86fc5ba8152ebda4cf7d4310a217d27..036a78b70427037ed633c7161b12f60da7ae626d 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -259,17 +259,16 @@ static int grgpio_irq_map(struct irq_domain *d, unsigned int irq, lirq->irq = irq; uirq = &priv->uirqs[lirq->index]; if (uirq->refcnt == 0) { + spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags); ret = request_irq(uirq->uirq, grgpio_irq_handler, 0, dev_name(priv->dev), priv); if (ret) { dev_err(priv->dev, "Could not request underlying irq %d\n", uirq->uirq); - - spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags); - return ret; } + spin_lock_irqsave(&priv->gc.bgpio_lock, flags); } uirq->refcnt++; @@ -315,8 +314,11 @@ static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq) if (index >= 0) { uirq = &priv->uirqs[lirq->index]; uirq->refcnt--; - if (uirq->refcnt == 0) + if (uirq->refcnt == 0) { + spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags); free_irq(uirq->uirq, priv); + return; + } } spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags); diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 793518a30afe6c97a97bfe5db1d62cb1651077c1..b67f61d31e25ecbfb04361f5665b216e0cde3ee6 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -306,6 +306,7 @@ static int mpc8xxx_probe(struct platform_device *pdev) return -ENOMEM; gc = &mpc8xxx_gc->gc; + gc->parent = &pdev->dev; if (of_property_read_bool(np, "little-endian")) { ret = bgpio_init(gc, &pdev->dev, 4, @@ -337,7 +338,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) * It's assumed that only a single type of gpio controller is available * on the current machine, so overwriting global data is fine. */ - mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type; + if (devtype->irq_set_type) + mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type; if (devtype->gpio_dir_out) gc->direction_output = devtype->gpio_dir_out; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6008a30a17d0b2fcfd4038b37fd4fdac8e481d72..505dead076196ba210066171bc017eaf11641a3a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -188,6 +188,14 @@ int gpiod_get_direction(struct gpio_desc *desc) chip = gpiod_to_chip(desc); offset = gpio_chip_hwgpio(desc); + /* + * Open drain emulation using input mode may incorrectly report + * input here, fix that up. + */ + if (test_bit(FLAG_OPEN_DRAIN, &desc->flags) && + test_bit(FLAG_IS_OUT, &desc->flags)) + return 0; + if (!chip->get_direction) return status; @@ -3041,8 +3049,9 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, if (chip->ngpio <= p->chip_hwnum) { dev_err(dev, - "requested GPIO %d is out of range [0..%d] for chip %s\n", - idx, chip->ngpio, chip->label); + "requested GPIO %u (%u) is out of range [0..%u] for chip %s\n", + idx, p->chip_hwnum, chip->ngpio - 1, + chip->label); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 26afdffab5a06ccc4fee8322ef074366b6edb57e..0c2ed1254585e57c073040c4740da3cb6799494d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -336,17 +336,9 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * path_size += le16_to_cpu(path->usSize); if (device_support & le16_to_cpu(path->usDeviceTag)) { - uint8_t con_obj_id, con_obj_num, con_obj_type; - - con_obj_id = + uint8_t con_obj_id = (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; - con_obj_num = - (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) - >> ENUM_ID_SHIFT; - con_obj_type = - (le16_to_cpu(path->usConnObjectId) & - OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; /* Skip TV/CV support */ if ((le16_to_cpu(path->usDeviceTag) == @@ -371,15 +363,7 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * router.ddc_valid = false; router.cd_valid = false; for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { - uint8_t grph_obj_id, grph_obj_num, grph_obj_type; - - grph_obj_id = - (le16_to_cpu(path->usGraphicObjIds[j]) & - OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; - grph_obj_num = - (le16_to_cpu(path->usGraphicObjIds[j]) & - ENUM_ID_MASK) >> ENUM_ID_SHIFT; - grph_obj_type = + uint8_t grph_obj_type = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 9b17a66cf0e16245a50360d22d80a44e8602a94f..aa54a6a2ad1da5fdebc9255adb67fe129414af85 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -81,7 +81,11 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) struct videomode vm; unsigned long prate; unsigned int cfg; - int div; + int div, ret; + + ret = clk_prepare_enable(crtc->dc->hlcdc->sys_clk); + if (ret) + return; vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end; @@ -140,6 +144,8 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK, cfg); + + clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); } static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *c, diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c index a2a82366a7714493488257c357dbc614215712b1..eb97e88a103cada874824da5ae45231d86db9658 100644 --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c @@ -725,7 +725,9 @@ static int anx78xx_init_pdata(struct anx78xx *anx78xx) /* 1.0V digital core power regulator */ pdata->dvdd10 = devm_regulator_get(dev, "dvdd10"); if (IS_ERR(pdata->dvdd10)) { - DRM_ERROR("DVDD10 regulator not found\n"); + if (PTR_ERR(pdata->dvdd10) != -EPROBE_DEFER) + DRM_ERROR("DVDD10 regulator not found\n"); + return PTR_ERR(pdata->dvdd10); } @@ -1344,7 +1346,9 @@ static int anx78xx_i2c_probe(struct i2c_client *client, err = anx78xx_init_pdata(anx78xx); if (err) { - DRM_ERROR("Failed to initialize pdata: %d\n", err); + if (err != -EPROBE_DEFER) + DRM_ERROR("Failed to initialize pdata: %d\n", err); + return err; } diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 4a959740058e29338dab3a6d75f641dc4f4b0c42..17aedaaf364c161acf70359405d88b873f6f039c 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -272,7 +272,7 @@ static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req, memcpy(&buf[idx], req->u.i2c_read.transactions[i].bytes, req->u.i2c_read.transactions[i].num_bytes); idx += req->u.i2c_read.transactions[i].num_bytes; - buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 5; + buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 4; buf[idx] |= (req->u.i2c_read.transactions[i].i2c_transaction_delay & 0xf); idx++; } @@ -980,9 +980,20 @@ static struct drm_dp_mst_port *drm_dp_mst_get_port_ref_locked(struct drm_dp_mst_ static struct drm_dp_mst_port *drm_dp_get_validated_port_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) { struct drm_dp_mst_port *rport = NULL; + mutex_lock(&mgr->lock); - if (mgr->mst_primary) - rport = drm_dp_mst_get_port_ref_locked(mgr->mst_primary, port); + /* + * Port may or may not be 'valid' but we don't care about that when + * destroying the port and we are guaranteed that the port pointer + * will be valid until we've finished + */ + if (current_work() == &mgr->destroy_connector_work) { + kref_get(&port->kref); + rport = port; + } else if (mgr->mst_primary) { + rport = drm_dp_mst_get_port_ref_locked(mgr->mst_primary, + port); + } mutex_unlock(&mgr->lock); return rport; } @@ -1536,7 +1547,11 @@ static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr, if (ret != 1) DRM_DEBUG_KMS("failed to send msg in q %d\n", ret); - txmsg->dst->tx_slots[txmsg->seqno] = NULL; + if (txmsg->seqno != -1) { + WARN_ON((unsigned int)txmsg->seqno > + ARRAY_SIZE(txmsg->dst->tx_slots)); + txmsg->dst->tx_slots[txmsg->seqno] = NULL; + } } static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr, diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a5deca6df7c699eb6584fd46888a17f0ff4500ca..0a8fc7835aefdb4b61f0230402b5fdc3c7b88bc2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1169,77 +1169,77 @@ static const struct drm_display_mode edid_cea_modes[] = { { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116, 5204, 5500, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9,}, + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, /* 94 - 3840x2160p@25Hz 16:9 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896, 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9}, + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, /* 95 - 3840x2160p@30Hz 16:9 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016, 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9}, + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, /* 96 - 3840x2160p@50Hz 16:9 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896, 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9}, + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, /* 97 - 3840x2160p@60Hz 16:9 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016, 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9}, + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, /* 98 - 4096x2160p@24Hz 256:135 */ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116, 5204, 5500, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135}, + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, /* 99 - 4096x2160p@25Hz 256:135 */ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064, 5152, 5280, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135}, + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, /* 100 - 4096x2160p@30Hz 256:135 */ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184, 4272, 4400, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135}, + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, /* 101 - 4096x2160p@50Hz 256:135 */ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064, 5152, 5280, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135}, + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, /* 102 - 4096x2160p@60Hz 256:135 */ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184, 4272, 4400, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135}, + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, /* 103 - 3840x2160p@24Hz 64:27 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116, 5204, 5500, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27}, + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, /* 104 - 3840x2160p@25Hz 64:27 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016, 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27}, + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, /* 105 - 3840x2160p@30Hz 64:27 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016, 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27}, + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, /* 106 - 3840x2160p@50Hz 64:27 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896, 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27}, + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, /* 107 - 3840x2160p@60Hz 64:27 */ { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016, 4104, 4400, 0, 2160, 2168, 2178, 2250, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), - .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27}, + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, }; /* @@ -2960,7 +2960,7 @@ static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_ * * Returns the HDMI Video ID (VIC) of the mode or 0 if it isn't one. */ -static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match) +u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match) { u8 vic; @@ -2982,6 +2982,7 @@ static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match) } return 0; } +EXPORT_SYMBOL(drm_match_hdmi_mode); static bool drm_valid_hdmi_vic(u8 vic) { @@ -3081,6 +3082,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector, if (!newmode) return NULL; + newmode->vic_id = vic; newmode->vrefresh = 0; return newmode; @@ -4313,11 +4315,11 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, * modes and forbids YCRCB422 support for all video modes per * HDMI 1.3 spec. */ - info->color_formats = DRM_COLOR_FORMAT_RGB444; + info->color_formats |= DRM_COLOR_FORMAT_DC_RGB444; /* YCRCB444 is optional according to spec. */ if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) { - info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + info->color_formats |= DRM_COLOR_FORMAT_DC_YCRCB444; DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n", connector->name); } diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 97387cfbbeb51b08b26bac09ba313a0bcded5206..615c85ad56cd42dce3c44447668ffbeb5564f9fa 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -997,6 +997,7 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, mode1->vsync_end == mode2->vsync_end && mode1->vtotal == mode2->vtotal && mode1->vscan == mode2->vscan && + mode1->picture_aspect_ratio == mode2->picture_aspect_ratio && (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) == (mode2->flags & ~DRM_MODE_FLAG_3D_MASK)) return true; @@ -1506,6 +1507,27 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, out->vrefresh = in->vrefresh; out->flags = in->flags; out->type = in->type; + out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK; + + switch (in->picture_aspect_ratio) { + case HDMI_PICTURE_ASPECT_4_3: + out->flags |= DRM_MODE_FLAG_PIC_AR_4_3; + break; + case HDMI_PICTURE_ASPECT_16_9: + out->flags |= DRM_MODE_FLAG_PIC_AR_16_9; + break; + case HDMI_PICTURE_ASPECT_64_27: + out->flags |= DRM_MODE_FLAG_PIC_AR_64_27; + break; + case DRM_MODE_PICTURE_ASPECT_256_135: + out->flags |= DRM_MODE_FLAG_PIC_AR_256_135; + break; + case HDMI_PICTURE_ASPECT_RESERVED: + default: + out->flags |= DRM_MODE_FLAG_PIC_AR_NONE; + break; + } + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; } @@ -1551,6 +1573,27 @@ int drm_mode_convert_umode(struct drm_display_mode *out, strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; + /* Clearing picture aspect ratio bits from out flags */ + out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK; + + switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) { + case DRM_MODE_FLAG_PIC_AR_4_3: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_4_3; + break; + case DRM_MODE_FLAG_PIC_AR_16_9: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_16_9; + break; + case DRM_MODE_FLAG_PIC_AR_64_27: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_64_27; + break; + case DRM_MODE_FLAG_PIC_AR_256_135: + out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_256_135; + break; + default: + out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; + break; + } + out->status = drm_mode_validate_basic(out); if (out->status != MODE_OK) goto out; diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c old mode 100644 new mode 100755 diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c index 2bef501d4a17211069a9c9dfdad233a44d2d0611..5af7c2594a79ece3b18f7da4fdae9862c3917eb9 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c @@ -206,7 +206,7 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) mutex_lock(&obj->lock); pages = etnaviv_gem_get_pages(obj); mutex_unlock(&obj->lock); - if (pages) { + if (!IS_ERR(pages)) { int j; iter.hdr->data[0] = bomap - bomap_start; diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 3a44e705db53809279f40208fcd12852167d16c9..d224fc12b75713a9bef3348e80c408a103f8ba29 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -516,6 +516,7 @@ static int psbfb_probe(struct drm_fb_helper *helper, container_of(helper, struct psb_fbdev, psb_fb_helper); struct drm_device *dev = psb_fbdev->psb_fb_helper.dev; struct drm_psb_private *dev_priv = dev->dev_private; + unsigned int fb_size; int bytespp; bytespp = sizes->surface_bpp / 8; @@ -525,8 +526,11 @@ static int psbfb_probe(struct drm_fb_helper *helper, /* If the mode will not fit in 32bit then switch to 16bit to get a console on full resolution. The X mode setting server will allocate its own 32bit GEM framebuffer */ - if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height > - dev_priv->vram_stolen_size) { + fb_size = ALIGN(sizes->surface_width * bytespp, 64) * + sizes->surface_height; + fb_size = ALIGN(fb_size, PAGE_SIZE); + + if (fb_size > dev_priv->vram_stolen_size) { sizes->surface_bpp = 16; sizes->surface_depth = 16; } diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index da9fd34b95505d519b09fbe9d0da0b84aa486cd0..caa6da02206aa90fd5147172e0760ba188938485 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -139,6 +139,7 @@ static bool mrst_sdvo_find_best_pll(const struct gma_limit_t *limit, s32 freq_error, min_error = 100000; memset(best_clock, 0, sizeof(*best_clock)); + memset(&clock, 0, sizeof(clock)); for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { for (clock.n = limit->n.min; clock.n <= limit->n.max; @@ -195,6 +196,7 @@ static bool mrst_lvds_find_best_pll(const struct gma_limit_t *limit, int err = target; memset(best_clock, 0, sizeof(*best_clock)); + memset(&clock, 0, sizeof(clock)); for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index d91856779bebca20a04f198da3ce486c907927e4..70de29f4e2b47900655f4deb0bf672d59acaabfc 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -723,7 +723,7 @@ static void i810_dma_dispatch_vertex(struct drm_device *dev, if (nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; - if (used > 4 * 1024) + if (used < 0 || used > 4 * 1024) used = 0; if (sarea_priv->dirty) @@ -1043,7 +1043,7 @@ static void i810_dma_dispatch_mc(struct drm_device *dev, struct drm_buf *buf, in if (u != I810_BUF_CLIENT) DRM_DEBUG("MC found buffer that isn't mine!\n"); - if (used > 4 * 1024) + if (used < 0 || used > 4 * 1024) used = 0; sarea_priv->dirty = 0x7f; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 62bcc770a18109264b3a0fc7958b4630b64de1ee..b935d62be91804e3521ca2752f9d04f1988a0a5c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1017,6 +1017,8 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine, int ret; struct drm_i915_private *dev_priv = engine->i915; uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); + u32 scratch_addr = + i915_ggtt_offset(engine->scratch) + 2 * CACHELINE_BYTES; /* WaDisableCtxRestoreArbitration:skl,bxt */ if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) || @@ -1036,22 +1038,17 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine, GEN9_DISABLE_GATHER_AT_SET_SHADER_COMMON_SLICE)); wa_ctx_emit(batch, index, MI_NOOP); - /* WaClearSlmSpaceAtContextSwitch:kbl */ + /* WaClearSlmSpaceAtContextSwitch:skl,bxt,kbl,glk,cfl */ /* Actual scratch location is at 128 bytes offset */ - if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0)) { - u32 scratch_addr = - i915_ggtt_offset(engine->scratch) + 2 * CACHELINE_BYTES; - - wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6)); - wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 | - PIPE_CONTROL_GLOBAL_GTT_IVB | - PIPE_CONTROL_CS_STALL | - PIPE_CONTROL_QW_WRITE)); - wa_ctx_emit(batch, index, scratch_addr); - wa_ctx_emit(batch, index, 0); - wa_ctx_emit(batch, index, 0); - wa_ctx_emit(batch, index, 0); - } + wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6)); + wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 | + PIPE_CONTROL_GLOBAL_GTT_IVB | + PIPE_CONTROL_CS_STALL | + PIPE_CONTROL_QW_WRITE)); + wa_ctx_emit(batch, index, scratch_addr); + wa_ctx_emit(batch, index, 0); + wa_ctx_emit(batch, index, 0); + wa_ctx_emit(batch, index, 0); /* WaMediaPoolStateCmdInWABB:bxt */ if (HAS_POOLED_EU(engine->i915)) { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 01a21dd835b57c865ba685f560aa204d19f7a636..1ed60da76a0ce5713b4b42ab0fdfa97367a7ee41 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -306,6 +306,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) { struct drm_device *drm = mtk_crtc->base.dev; + struct drm_crtc *crtc = &mtk_crtc->base; int i; DRM_DEBUG_DRIVER("%s\n", __func__); @@ -327,6 +328,13 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) mtk_disp_mutex_unprepare(mtk_crtc->mutex); pm_runtime_put(drm->dev); + + if (crtc->state->event && !crtc->state->active) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + spin_unlock_irq(&crtc->dev->event_lock); + } } static void mtk_drm_crtc_enable(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 156abf00c0e2a5fdc00d34d16ba81c36184e6507..7f6bf5e9e628352da9e0d4390f9d9bcb3d60e517 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -383,19 +383,17 @@ static const unsigned int a3xx_registers[] = { 0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e, 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8, 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7, - 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356, - 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d, - 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472, - 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef, - 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511, - 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed, - 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a, - 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce, - 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec, - 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749, - 0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d, - 0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036, - 0x303c, 0x303c, 0x305e, 0x305f, + 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2440, 0x2440, 0x2444, 0x2444, + 0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, + 0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, + 0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, + 0x2510, 0x2511, 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, + 0x25ec, 0x25ed, 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, + 0x261a, 0x261a, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, + 0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, + 0x26ec, 0x26ec, 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, + 0x300c, 0x300e, 0x301c, 0x301d, 0x302a, 0x302a, 0x302c, 0x302d, + 0x3030, 0x3031, 0x3034, 0x3036, 0x303c, 0x303c, 0x305e, 0x305f, ~0 /* sentinel */ }; diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 5396a35ff4bb628443b9522aba555bb699c06dd2..94392d3290ca2579e2729d5be2f3b8bebcc992e4 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -19,6 +19,7 @@ #include "dp_catalog.h" #include "dp_reg.h" +#include "msm_kms.h" #define DP_GET_MSB(x) (x >> 8) #define DP_GET_LSB(x) (x & 0xff) @@ -394,7 +395,8 @@ static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl) return dp_read(catalog, io_data, DP_HDCP_STATUS); } -static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) +static void dp_catalog_panel_setup_hdr_infoframe_sdp( + struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct drm_msm_ext_hdr_metadata *hdr; @@ -501,7 +503,7 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) DUMP_PREFIX_NONE, 16, 4, buf, off, false); } -static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) +static void dp_catalog_panel_setup_hdr_vsc_sdp(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; @@ -627,8 +629,8 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en) cfg2 |= BIT(15) | BIT(16); dp_write(catalog, io_data, MMSS_DP_SDP_CFG2, cfg2); - dp_catalog_panel_setup_vsc_sdp(panel); - dp_catalog_panel_setup_infoframe_sdp(panel); + dp_catalog_panel_setup_hdr_vsc_sdp(panel); + dp_catalog_panel_setup_hdr_infoframe_sdp(panel); /* indicates presence of VSC (BIT(6) of MISC1) */ misc |= BIT(14); @@ -772,6 +774,7 @@ static void dp_catalog_ctrl_config_misc(struct dp_catalog_ctrl *ctrl, catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; + misc_val = cc; misc_val |= (tb << 5); misc_val |= BIT(0); /* Configure clock to synchronous mode */ @@ -780,7 +783,7 @@ static void dp_catalog_ctrl_config_misc(struct dp_catalog_ctrl *ctrl, } static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl, - u32 rate, u32 stream_rate_khz) + u32 rate, u32 stream_rate_khz, u32 out_format) { u32 pixel_m, pixel_n; u32 mvid, nvid; @@ -815,6 +818,9 @@ static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl, pr_debug("rate = %d\n", rate); + if (out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + mvid *= 2; + if (link_rate_hbr2 == rate) nvid *= 2; @@ -1319,6 +1325,158 @@ static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog, return ret; } +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) +{ + struct dp_catalog_private *catalog; + struct dp_io_data *io_data; + u32 header, parity, data; + u8 bpc, off = 0; + u8 buf[SZ_128]; + + if (!panel) { + pr_err("invalid input\n"); + return; + } + + catalog = dp_catalog_get_priv(panel); + io_data = catalog->io.dp_link; + + /* HEADER BYTE 1 */ + header = panel->vsc_sdp_data.vsc_header_byte1; + parity = dp_header_get_parity(header); + data = ((header << HEADER_BYTE_1_BIT) + | (parity << PARITY_BYTE_1_BIT)); + dp_write(catalog, io_data, MMSS_DP_GENERIC0_0, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + /* HEADER BYTE 2 */ + header = panel->vsc_sdp_data.vsc_header_byte2; + parity = dp_header_get_parity(header); + data = ((header << HEADER_BYTE_2_BIT) + | (parity << PARITY_BYTE_2_BIT)); + dp_write(catalog, io_data, MMSS_DP_GENERIC0_1, data); + + /* HEADER BYTE 3 */ + header = panel->vsc_sdp_data.vsc_header_byte3; + parity = dp_header_get_parity(header); + data = ((header << HEADER_BYTE_3_BIT) + | (parity << PARITY_BYTE_3_BIT)); + data |= dp_read(catalog, io_data, MMSS_DP_GENERIC0_1); + dp_write(catalog, io_data, MMSS_DP_GENERIC0_1, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + data = 0; + dp_write(catalog, io_data, MMSS_DP_GENERIC0_2, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + dp_write(catalog, io_data, MMSS_DP_GENERIC0_3, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + dp_write(catalog, io_data, MMSS_DP_GENERIC0_4, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + dp_write(catalog, io_data, MMSS_DP_GENERIC0_5, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + switch (panel->vsc_sdp_data.bpc) { + case 10: + bpc = BIT(1); + break; + case 8: + default: + bpc = BIT(0); + break; + } + + data = (panel->vsc_sdp_data.colorimetry & 0xF) | + ((panel->vsc_sdp_data.pixel_encoding & 0xF) << 4) | + (bpc << 8) | + ((panel->vsc_sdp_data.dynamic_range & 0x1) << 15) | + ((panel->vsc_sdp_data.content_type & 0x7) << 16); + + dp_write(catalog, io_data, MMSS_DP_GENERIC0_6, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + data = 0; + dp_write(catalog, io_data, MMSS_DP_GENERIC0_7, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + dp_write(catalog, io_data, MMSS_DP_GENERIC0_8, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + dp_write(catalog, io_data, MMSS_DP_GENERIC0_9, data); + memcpy(buf + off, &data, sizeof(data)); + off += sizeof(data); + + print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", + DUMP_PREFIX_NONE, 16, 4, buf, off, false); +} + +static void dp_catalog_panel_config_vsc_sdp(struct dp_catalog_panel *panel, + bool en) +{ + struct dp_catalog_private *catalog; + struct dp_io_data *io_data; + u32 cfg, cfg2, misc; + + if (!panel) { + pr_err("invalid input\n"); + return; + } + + catalog = dp_catalog_get_priv(panel); + io_data = catalog->io.dp_link; + + cfg = dp_read(catalog, io_data, MMSS_DP_SDP_CFG); + cfg2 = dp_read(catalog, io_data, MMSS_DP_SDP_CFG2); + misc = dp_read(catalog, io_data, DP_MISC1_MISC0); + + if (en) { + /* GEN0_SDP_EN */ + cfg |= BIT(17); + dp_write(catalog, io_data, MMSS_DP_SDP_CFG, cfg); + + /* GENERIC0_SDPSIZE */ + cfg2 |= BIT(16); + dp_write(catalog, io_data, MMSS_DP_SDP_CFG2, cfg2); + + dp_catalog_panel_setup_vsc_sdp(panel); + + /* indicates presence of VSC (BIT(6) of MISC1) */ + misc |= BIT(14); + + pr_debug("Enabled\n"); + } else { + /* GEN0_SDP_EN */ + cfg &= ~BIT(17); + dp_write(catalog, io_data, MMSS_DP_SDP_CFG, cfg); + + /* GENERIC0_SDPSIZE */ + cfg2 &= ~BIT(16); + dp_write(catalog, io_data, MMSS_DP_SDP_CFG2, cfg2); + + /* switch back to MSA */ + misc &= ~BIT(14); + + pr_debug("Disabled\n"); + } + + pr_debug("misc settings = 0x%x\n", misc); + dp_write(catalog, io_data, DP_MISC1_MISC0, misc); + + dp_write(catalog, io_data, MMSS_DP_SDP_CFG3, 0x01); + dp_write(catalog, io_data, MMSS_DP_SDP_CFG3, 0x00); +} + /* panel related catalog functions */ static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel) { @@ -1762,6 +1920,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) .config_hdr = dp_catalog_panel_config_hdr, .tpg_config = dp_catalog_panel_tpg_cfg, .config_spd = dp_catalog_panel_config_spd, + .config_vsc_sdp = dp_catalog_panel_config_vsc_sdp, }; if (!dev || !parser) { diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index dbcbd8b0efd984cc7ad5b692f763938298913c1a..12dce42857bb5aa1ff5419b2e1f5d70012f8d9f5 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -64,6 +64,22 @@ struct dp_catalog_hdr_data { struct drm_msm_ext_hdr_metadata hdr_meta; }; +struct dp_catalog_vsc_sdp_data { + u32 vsc_header_byte0; + u32 vsc_header_byte1; + u32 vsc_header_byte2; + u32 vsc_header_byte3; + + u32 bpc; + + u32 version; + u32 length; + u32 pixel_encoding; + u32 colorimetry; + u32 dynamic_range; + u32 content_type; +}; + struct dp_catalog_aux { u32 data; u32 isr; @@ -94,7 +110,7 @@ struct dp_catalog_ctrl { void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable); void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb); void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate, - u32 stream_rate_khz); + u32 stream_rate_khz, u32 out_format); void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern); void (*reset)(struct dp_catalog_ctrl *ctrl); void (*usb_reset)(struct dp_catalog_ctrl *ctrl, bool flip); @@ -159,6 +175,7 @@ struct dp_catalog_panel { u8 *spd_vendor_name; u8 *spd_product_description; + struct dp_catalog_vsc_sdp_data vsc_sdp_data; struct dp_catalog_hdr_data hdr_data; /* TPG */ @@ -174,6 +191,7 @@ struct dp_catalog_panel { void (*config_hdr)(struct dp_catalog_panel *panel, bool en); void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); void (*config_spd)(struct dp_catalog_panel *panel); + void (*config_vsc_sdp)(struct dp_catalog_panel *panel, bool en); }; struct dp_catalog { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index befbc5c7f9f9dae7f7b3032ed576dcb4be43b144..365fefc81d0844f9626c9e52c4b7658ac3c67baa 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -18,6 +18,7 @@ #include #include +#include "msm_kms.h" #include "dp_ctrl.h" #define DP_KHZ_TO_HZ 1000 @@ -149,9 +150,16 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) { u32 config = 0, tbd; u8 *dpcd = ctrl->panel->dpcd; + u32 out_format = ctrl->panel->pinfo.out_format; config |= (2 << 13); /* Default-> LSCLK DIV: 1/4 LCLK */ - config |= (0 << 11); /* RGB */ + + if (out_format & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + config |= (1 << 11); /* YUV420 */ + else if (out_format & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) + config |= (2 << 11); /* YUV422 */ + else + config |= (0 << 11); /* RGB */ /* Scrambler reset enable */ if (dpcd[DP_EDP_CONFIGURATION_CAP] & DP_ALTERNATE_SCRAMBLER_RESET_CAP) @@ -178,6 +186,25 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) ctrl->catalog->config_ctrl(ctrl->catalog, config); } +static void dp_ctrl_misc_ctrl(struct dp_ctrl_private *ctrl) +{ + u32 out_format = ctrl->panel->pinfo.out_format; + u32 yres = ctrl->panel->pinfo.v_active; + u32 cc, tb; + + tb = ctrl->link->get_test_bits_depth(ctrl->link, + ctrl->panel->pinfo.bpp); + cc = ctrl->link->get_colorimetry_config(ctrl->link); + if (out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) { + cc |= (0x01 << 1); /* Set 4:2:2 Pixel Encoding */ + cc |= BIT(3); /* Set YCbCr Colorimetry */ + if (yres >= 720) + cc |= BIT(4); /* Set BT709 */ + } + + ctrl->catalog->config_misc(ctrl->catalog, cc, tb); +} + /** * dp_ctrl_configure_source_params() - configures DP transmitter source params * @ctrl: Display Port Driver data @@ -187,17 +214,13 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) */ static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) { - u32 cc, tb; ctrl->catalog->lane_mapping(ctrl->catalog); ctrl->catalog->mainlink_ctrl(ctrl->catalog, true); dp_ctrl_config_ctrl(ctrl); + dp_ctrl_misc_ctrl(ctrl); - tb = ctrl->link->get_test_bits_depth(ctrl->link, - ctrl->panel->pinfo.bpp); - cc = ctrl->link->get_colorimetry_config(ctrl->link); - ctrl->catalog->config_misc(ctrl->catalog, cc, tb); ctrl->panel->timing_cfg(ctrl->panel); } @@ -251,7 +274,8 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, { u32 const multiplier = 1000000; u64 pclk, lclk; - u8 bpp, ln_cnt; + u32 bpp; + u8 ln_cnt; int run_idx = 0; u32 lwidth, h_blank; u32 fifo_empty = 0; @@ -309,6 +333,8 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, int min_hblank_tmp = 0; bool extra_req_bytes_is_neg = false; struct dp_panel_info *pinfo = &ctrl->panel->pinfo; + int div = 0; + u32 out_format = pinfo->out_format; u8 dp_brute_force = 1; u64 brute_force_threshold = 10; @@ -317,10 +343,26 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, ln_cnt = ctrl->link->link_params.lane_count; bpp = pinfo->bpp; - lwidth = pinfo->h_active; - h_blank = pinfo->h_back_porch + pinfo->h_front_porch + - pinfo->h_sync_width; - pclk = pinfo->pixel_clk_khz * 1000; + if (out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) { + switch (pinfo->bpp) { + case 24: + bpp = 16; + break; + case 30: + bpp = 20; + break; + default: + bpp = 16; + break; + }; + } else if (out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) { + div = 1; + } + + lwidth = pinfo->h_active >> div; + h_blank = (pinfo->h_back_porch + pinfo->h_front_porch + + pinfo->h_sync_width) >> div; + pclk = (pinfo->pixel_clk_khz * 1000) >> div; boundary_moderation_en = 0; upper_bdry_cnt = 0; @@ -1201,7 +1243,7 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl); ctrl->dp_ctrl.reset(&ctrl->dp_ctrl); - ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz; + ctrl->pixel_rate = ctrl->panel->get_pixel_clk(ctrl->panel); do { if (ret == -EAGAIN) { @@ -1229,7 +1271,9 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) ctrl->catalog->config_msa(ctrl->catalog, drm_dp_bw_code_to_link_rate( - ctrl->link->link_params.bw_code), ctrl->pixel_rate); + ctrl->link->link_params.bw_code), + ctrl->pixel_rate, + ctrl->panel->pinfo.out_format); reinit_completion(&ctrl->idle_comp); @@ -1374,7 +1418,7 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl) drm_dp_link_rate_to_bw_code(rate); ctrl->link->link_params.lane_count = ctrl->panel->link_info.num_lanes; - ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz; + ctrl->pixel_rate = ctrl->panel->get_pixel_clk(ctrl->panel); } pr_debug("bw_code=%d, lane_count=%d, pixel_rate=%d\n", @@ -1395,7 +1439,8 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl) while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) { ctrl->catalog->config_msa(ctrl->catalog, drm_dp_bw_code_to_link_rate( - ctrl->link->link_params.bw_code), ctrl->pixel_rate); + ctrl->link->link_params.bw_code), + ctrl->pixel_rate, ctrl->panel->pinfo.out_format); rc = dp_ctrl_setup_main_link(ctrl, true); if (!rc) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index d023f64178e5a005ada43890773ffc49084fbd2c..386c56cd7581a186068b643f64a47a5885d963d1 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -533,9 +533,10 @@ static ssize_t dp_debug_read_edid_modes(struct file *file, mutex_lock(&connector->dev->mode_config.mutex); list_for_each_entry(mode, &connector->modes, head) { ret = snprintf(buf + len, max_size, - "%s %d %d %d %d %d 0x%x\n", - mode->name, mode->vrefresh, mode->picture_aspect_ratio, - mode->htotal, mode->vtotal, mode->clock, mode->flags); + "%d %s %d %d %d %d %d 0x%x\n", + mode->vic_id, mode->name, mode->vrefresh, + mode->picture_aspect_ratio, mode->htotal, mode->vtotal, + mode->clock, mode->flags); if (dp_debug_check_buffer_overflow(ret, &max_size, &len)) break; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 9ae048292d7a62899e587a28e97548ec6aaa7a47..9bf732bff5ddb9c95147a4226637d2eb812e4df9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -522,6 +522,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->panel->handle_sink_request(dp->panel); dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; + dp->dp_display.yuv_support = dp->parser->yuv_support; notify: dp_display_send_hpd_notification(dp, true); @@ -1023,6 +1024,8 @@ static int dp_display_set_mode(struct dp_display *dp_display, { const u32 num_components = 3, default_bpp = 24; struct dp_display_private *dp; + u32 pixel_clk_khz = 0; + u32 rate_ratio = RGB_24BPP_TMDS_CHAR_RATE_RATIO; if (!dp_display) { pr_err("invalid input\n"); @@ -1031,13 +1034,43 @@ static int dp_display_set_mode(struct dp_display *dp_display, dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); - mode->timing.bpp = - dp_display->connector->display_info.bpc * num_components; + if (mode->timing.out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) { + mode->timing.bpp = + dp_display->connector->display_info.y420_bpc * + num_components; + rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO; + } else { + mode->timing.bpp = + dp_display->connector->display_info.bpc * + num_components; + } + + pixel_clk_khz = mode->timing.pixel_clk_khz / rate_ratio; + if (!mode->timing.bpp) mode->timing.bpp = default_bpp; mode->timing.bpp = dp->panel->get_mode_bpp(dp->panel, - mode->timing.bpp, mode->timing.pixel_clk_khz); + mode->timing.bpp, pixel_clk_khz); + + /* Refactor bits per pixel for YUV422 format */ + if (mode->timing.out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) { + switch (mode->timing.bpp) { + case 18: + mode->timing.bpp = 24; + break; + case 24: + mode->timing.bpp = 30; + break; + case 30: + mode->timing.bpp = 36; + break; + default: + mode->timing.bpp = 30; + break; + }; + pr_debug("YCC422 bpp = %d\n", mode->timing.bpp); + } dp->panel->pinfo = mode->timing; dp->panel->init(dp->panel); @@ -1287,22 +1320,68 @@ static int dp_display_unprepare(struct dp_display *dp) return 0; } -static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz) +static int dp_display_get_dc_support(struct dp_display *dp, + u32 mode_pclk_khz, u32 out_format, bool dc_enable) +{ + struct dp_display_private *dp_display; + struct drm_dp_link *link_info; + u32 mode_rate_khz = 0, supported_rate_khz = 0; + u32 default_bpp = 24, max_supported_bpp = 30; + u32 rate_ratio = RGB_24BPP_TMDS_CHAR_RATE_RATIO; + + if (!dp || !mode_pclk_khz || !dp->connector) { + pr_err("invalid params\n"); + return -EINVAL; + } + + dp_display = container_of(dp, struct dp_display_private, dp_display); + link_info = &dp_display->panel->link_info; + + if (out_format & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO; + + mode_pclk_khz /= rate_ratio; + + mode_rate_khz = mode_pclk_khz * default_bpp; + if (dc_enable) + mode_rate_khz = mode_pclk_khz * max_supported_bpp; + + supported_rate_khz = link_info->num_lanes * link_info->rate * 8; + + if (mode_rate_khz > supported_rate_khz) + return false; + + return true; +} + +static int dp_display_validate_mode(struct dp_display *dp, + u32 mode_pclk_khz, u32 flags) { const u32 num_components = 3, default_bpp = 24; struct dp_display_private *dp_display; struct drm_dp_link *link_info; u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; - if (!dp || !mode_pclk_khz || !dp->connector) { + if (!dp || !dp->connector) { pr_err("invalid params\n"); return -EINVAL; } + if (!mode_pclk_khz) { + pr_err("invalid mode_pclk_khz\n"); + return -EINVAL; + } + dp_display = container_of(dp, struct dp_display_private, dp_display); link_info = &dp_display->panel->link_info; - mode_bpp = dp->connector->display_info.bpc * num_components; + if ((flags & SDE_DRM_MODE_FLAG_FMT_MASK) == + DRM_MODE_FLAG_SUPPORTS_YUV420) + mode_bpp = + dp->connector->display_info.y420_bpc * num_components; + else + mode_bpp = dp->connector->display_info.bpc * num_components; + if (!mode_bpp) mode_bpp = default_bpp; @@ -1356,6 +1435,42 @@ static int dp_display_config_hdr(struct dp_display *dp_display, return rc; } +static int dp_display_get_display_type(struct dp_display *dp_display, + const char **display_type) +{ + struct dp_display_private *dp; + + if (!dp_display || !display_type) { + pr_err("invalid input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + *display_type = dp->parser->display_type; + + if (!strcmp(*display_type, "primary")) + dp_display->is_primary = true; + else + dp_display->is_primary = false; + + return 0; +} + +static bool dp_display_vsc_sdp_supported(struct dp_display *dp_display) +{ + struct dp_display_private *dp; + + if (!dp_display) { + pr_err("invalid input\n"); + return 0; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + return dp->panel->vsc_sdp_supported(dp->panel); +} + static int dp_display_create_workqueue(struct dp_display_private *dp) { dp->wq = create_singlethread_workqueue("drm_dp"); @@ -1412,6 +1527,7 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->set_mode = dp_display_set_mode; g_dp_display->validate_mode = dp_display_validate_mode; g_dp_display->get_modes = dp_display_get_modes; + g_dp_display->get_dc_support = dp_display_get_dc_support; g_dp_display->prepare = dp_display_prepare; g_dp_display->unprepare = dp_display_unprepare; g_dp_display->request_irq = dp_request_irq; @@ -1419,6 +1535,8 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->post_open = dp_display_post_open; g_dp_display->post_init = dp_display_post_init; g_dp_display->config_hdr = dp_display_config_hdr; + g_dp_display->get_display_type = dp_display_get_display_type; + g_dp_display->vsc_sdp_supported = dp_display_vsc_sdp_supported; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 4da21d98cc1c4abc9f5b645c91ca009a88496f07..3229987f455988eed600f9ccf0c4c7a80e0fc2db 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -25,7 +25,9 @@ struct dp_display { struct dp_bridge *bridge; struct drm_connector *connector; bool is_connected; + bool is_primary; u32 max_pclk_khz; + bool yuv_support; int (*enable)(struct dp_display *dp_display); int (*post_enable)(struct dp_display *dp_display); @@ -35,9 +37,12 @@ struct dp_display { int (*set_mode)(struct dp_display *dp_display, struct dp_display_mode *mode); - int (*validate_mode)(struct dp_display *dp_display, u32 mode_pclk_khz); + int (*validate_mode)(struct dp_display *dp_display, + u32 mode_pclk_khz, u32 flags); int (*get_modes)(struct dp_display *dp_display, struct dp_display_mode *dp_mode); + int (*get_dc_support)(struct dp_display *dp_display, + u32 mode_pclk_khz, u32 out_format, bool dc_enable); int (*prepare)(struct dp_display *dp_display); int (*unprepare)(struct dp_display *dp_display); int (*request_irq)(struct dp_display *dp_display); @@ -46,9 +51,15 @@ struct dp_display { int (*config_hdr)(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr_meta); void (*post_init)(struct dp_display *dp_display); + int (*get_display_type)(struct dp_display *dp_display, + const char **display_type); + bool (*vsc_sdp_supported)(struct dp_display *dp_display); }; int dp_display_get_num_of_displays(void); int dp_display_get_displays(void **displays, int count); bool dp_connector_mode_needs_full_range(void *display); +bool dp_connector_mode_is_cea_mode(void *display); +enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn, + void *data); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 5b78218497b964e3f9ecf0e72a9728a89f81a909..442179f15409c3e78649756a158d48f72c0d133d 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -26,11 +26,87 @@ #define to_dp_bridge(x) container_of((x), struct dp_bridge, base) +enum dp_connector_hdr_state { + HDR_DISABLE, + HDR_ENABLE +}; + +static int get_sink_dc_support(struct dp_display *dp, + struct drm_display_mode *mode) +{ + int dc_format = 0; + struct drm_connector *connector = dp->connector; + + if ((mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV420) && + (connector->display_info.edid_hdmi_dc_modes + & DRM_EDID_YCBCR420_DC_30)) + if (dp->get_dc_support(dp, mode->clock, + MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420, true)) + dc_format |= MSM_MODE_FLAG_YUV420_DC_ENABLE; + + if ((mode->flags & DRM_MODE_FLAG_SUPPORTS_RGB) && + (connector->display_info.edid_hdmi_dc_modes + & DRM_EDID_HDMI_DC_30)) + if (dp->get_dc_support(dp, mode->clock, + MSM_MODE_FLAG_COLOR_FORMAT_RGB444, true)) + dc_format |= MSM_MODE_FLAG_RGB444_DC_ENABLE; + + if ((mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV422) && + (connector->display_info.edid_hdmi_dc_modes + & DRM_EDID_HDMI_DC_30)) + if (dp->get_dc_support(dp, mode->clock, + MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422, false)) + dc_format |= MSM_MODE_FLAG_YUV422_DC_ENABLE; + + return dc_format; +} + +static u32 choose_best_format(struct dp_display *dp, + struct drm_display_mode *mode) +{ + /* + * choose priority: + * 1. DC + RGB + * 2. DC + YUV422 + * 3. DC + YUV420 + * 4. RGB + * 5. YUV420 + */ + int dc_format; + + dc_format = get_sink_dc_support(dp, mode); + if (dc_format & MSM_MODE_FLAG_RGB444_DC_ENABLE) + return (MSM_MODE_FLAG_COLOR_FORMAT_RGB444 + | MSM_MODE_FLAG_RGB444_DC_ENABLE); + else if (dc_format & MSM_MODE_FLAG_YUV422_DC_ENABLE) + return (MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422 + | MSM_MODE_FLAG_YUV422_DC_ENABLE); + else if (dc_format & MSM_MODE_FLAG_YUV420_DC_ENABLE) + return (MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420 + | MSM_MODE_FLAG_YUV420_DC_ENABLE); + else if (mode->flags & DRM_MODE_FLAG_SUPPORTS_RGB) + return MSM_MODE_FLAG_COLOR_FORMAT_RGB444; + else if (mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV420) + return MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420; + + pr_err("Can't get available best display format\n"); + + return MSM_MODE_FLAG_COLOR_FORMAT_RGB444; +} + static void convert_to_dp_mode(const struct drm_display_mode *drm_mode, struct dp_display_mode *dp_mode, struct dp_display *dp) { memset(dp_mode, 0, sizeof(*dp_mode)); + dp_mode->timing.out_format = MSM_MODE_FLAG_COLOR_FORMAT_RGB444; + if (drm_mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) + dp_mode->timing.out_format = + MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422; + else if (drm_mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + dp_mode->timing.out_format = + MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420; + dp_mode->timing.h_active = drm_mode->hdisplay; dp_mode->timing.h_back_porch = drm_mode->htotal - drm_mode->hsync_end; dp_mode->timing.h_sync_width = drm_mode->htotal - @@ -56,6 +132,10 @@ static void convert_to_dp_mode(const struct drm_display_mode *drm_mode, dp_mode->timing.h_active_low = !!(drm_mode->flags & DRM_MODE_FLAG_NHSYNC); + + dp_mode->flags = drm_mode->flags; + + dp_mode->timing.par = drm_mode->picture_aspect_ratio; } static void convert_to_drm_mode(const struct dp_display_mode *dp_mode, @@ -94,6 +174,9 @@ static void convert_to_drm_mode(const struct dp_display_mode *dp_mode, flags |= DRM_MODE_FLAG_PVSYNC; drm_mode->flags = flags; + drm_mode->flags |= (dp_mode->flags & SDE_DRM_MODE_FLAG_FMT_MASK); + + drm_mode->picture_aspect_ratio = dp_mode->timing.par; drm_mode->type = 0x48; drm_mode_set_name(drm_mode); @@ -148,6 +231,7 @@ static void dp_bridge_pre_enable(struct drm_bridge *drm_bridge) bridge->id, rc); dp->unprepare(dp); } + } static void dp_bridge_enable(struct drm_bridge *drm_bridge) @@ -267,6 +351,15 @@ static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge, convert_to_dp_mode(mode, &dp_mode, dp); convert_to_drm_mode(&dp_mode, adjusted_mode); + + /* Clear the private flags before assigning new one */ + adjusted_mode->private_flags = 0; + + adjusted_mode->private_flags |= + choose_best_format(dp, adjusted_mode); + SDE_DEBUG("Adjusted mode private flags: 0x%x\n", + adjusted_mode->private_flags); + end: return ret; } @@ -350,6 +443,7 @@ int dp_connector_get_info(struct msm_display_info *info, void *data) info->num_of_h_tiles = 1; info->h_tile_instance[0] = 0; info->is_connected = display->is_connected; + info->is_primary = display->is_primary; info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG; @@ -384,6 +478,77 @@ bool dp_connector_mode_needs_full_range(void *data) return false; } +bool dp_connector_mode_is_cea_mode(void *data) +{ + struct dp_display *display = data; + struct dp_bridge *bridge; + struct dp_display_mode *mode; + struct drm_display_mode drm_mode; + struct dp_panel_info *timing; + bool is_ce_mode = false; + + if (!display) { + pr_err("invalid input\n"); + return false; + } + + bridge = display->bridge; + if (!bridge) { + pr_err("invalid bridge data\n"); + return false; + } + + mode = &bridge->dp_mode; + timing = &mode->timing; + + if (timing->h_active == 640 && + timing->v_active == 480) + is_ce_mode = false; + + convert_to_drm_mode(mode, &drm_mode); + drm_mode.flags &= ~SDE_DRM_MODE_FLAG_FMT_MASK; + + if (drm_match_cea_mode(&drm_mode) || drm_match_hdmi_mode(&drm_mode)) + is_ce_mode = true; + + pr_debug("%s: %s : %s video format\n", __func__, + drm_mode.name, is_ce_mode ? "CE" : "IT"); + + return is_ce_mode; +} + +enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn, + void *data) +{ + struct dp_display *display = data; + struct sde_connector_state *c_state; + struct drm_msm_ext_hdr_metadata *hdr_meta; + + if (!display || !conn) { + pr_err("invalid input\n"); + goto error; + } + + c_state = to_sde_connector_state(conn->state); + + if (!c_state) { + pr_err("invalid input\n"); + goto error; + } + + hdr_meta = &c_state->hdr_meta; + + if ((hdr_meta->hdr_state == HDR_ENABLE) + && (hdr_meta->eotf != 0)) + return SDE_CSC_RGB2YUV_2020L; + else if (dp_connector_mode_needs_full_range(data) + || conn->yuv_qs) + return SDE_CSC_RGB2YUV_709FR; + +error: + return SDE_CSC_RGB2YUV_709L; +} + enum drm_connector_status dp_connector_detect(struct drm_connector *conn, bool force, void *display) @@ -476,6 +641,19 @@ int dp_connector_get_modes(struct drm_connector *connector, return rc; } +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info) +{ + struct dp_display *dp_display = display; + const char *display_type = NULL; + + dp_display->get_display_type(dp_display, &display_type); + sde_kms_info_add_keystr(info, + "display type", display_type); + + return 0; +} + int dp_drm_bridge_init(void *data, struct drm_encoder *encoder) { int rc = 0; @@ -537,6 +715,8 @@ enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector, { struct dp_display *dp_disp; struct dp_debug *debug; + u32 pclk = 0; + u32 rate_ratio = RGB_24BPP_TMDS_CHAR_RATE_RATIO; if (!mode || !display) { pr_err("invalid params\n"); @@ -548,7 +728,34 @@ enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector, mode->vrefresh = drm_mode_vrefresh(mode); - if (mode->clock > dp_disp->max_pclk_khz) + if (!dp_disp->yuv_support) { + mode->flags &= ~DRM_MODE_FLAG_SUPPORTS_YUV420; + mode->flags &= ~DRM_MODE_FLAG_SUPPORTS_YUV422; + } + + if (!dp_disp->vsc_sdp_supported(dp_disp)) + mode->flags &= ~DRM_MODE_FLAG_SUPPORTS_YUV420; + + if (!(mode->flags & SDE_DRM_MODE_FLAG_FMT_MASK)) + return MODE_BAD; + + if ((mode->flags & SDE_DRM_MODE_FLAG_FMT_MASK) == + DRM_MODE_FLAG_SUPPORTS_YUV420) { + rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO; + } else if ((mode->flags & DRM_MODE_FLAG_SUPPORTS_RGB) && + (mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV420)) { + if (mode->clock > dp_disp->max_pclk_khz) { + /* Clear RGB and YUV422 support flags */ + mode->flags &= ~DRM_MODE_FLAG_SUPPORTS_RGB; + mode->flags &= ~DRM_MODE_FLAG_SUPPORTS_YUV422; + /* Only YUV420 format is now supported */ + rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO; + } + } + + pclk = mode->clock / rate_ratio; + + if (pclk > dp_disp->max_pclk_khz) return MODE_BAD; if (debug->debug_en && (mode->hdisplay != debug->hdisplay || @@ -557,5 +764,5 @@ enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector, mode->picture_aspect_ratio != debug->aspect_ratio)) return MODE_BAD; - return dp_disp->validate_mode(dp_disp, mode->clock); + return dp_disp->validate_mode(dp_disp, pclk, mode->flags); } diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 3ca10c2c9c5ceadd1643d3b28d3676986f42da18..4181472c2a8c3544a53a05e14b2d34002369db0d 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 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 @@ -99,6 +99,17 @@ int dp_connector_get_info(struct msm_display_info *info, void *display); */ void dp_connector_post_open(void *display); +/** + * dp_conn_set_info_blob - callback to perform info blob initialization + * @connector: Pointer to drm connector structure + * @info: Pointer to sde connector info structure + * @display: Pointer to private display handle + * @mode_info: Pointer to mode info structure + * Returns: Zero on success + */ +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info); + int dp_drm_bridge_init(void *display, struct drm_encoder *encoder); diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 71326996f97da4e399ce2dfaf85f566cbf606530..537982383fd8fe4bb01938dd6d20847d7c880a3b 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -14,6 +14,7 @@ #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ +#include "msm_kms.h" #include "dp_panel.h" #define DP_PANEL_DEFAULT_BPP 24 @@ -43,6 +44,17 @@ enum dp_panel_hdr_rgb_colorimetry { ITU_R_BT_2020_RGB, }; +enum dp_panel_hdr_yuv_colorimetry { + ITU_R_BT_601, + ITU_R_BT_709, + xvYCC_601, + xvYCC_709, + sYCC_601, + ADOBE_YCC_601, + ITU_R_BT_2020_YcCBcCRc, + ITU_R_BT_2020_YCBCR, +}; + enum dp_panel_hdr_dynamic_range { VESA, CEA, @@ -537,6 +549,50 @@ static void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable) panel->catalog->tpg_config(catalog, true); } +static int dp_panel_setup_vsc_sdp(struct dp_panel *dp_panel) +{ + struct dp_catalog_panel *catalog; + struct dp_panel_private *panel; + struct dp_panel_info *pinfo; + int rc = 0; + + if (!dp_panel) { + pr_err("invalid input\n"); + rc = -EINVAL; + goto end; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + catalog = panel->catalog; + pinfo = &panel->dp_panel.pinfo; + + memset(&catalog->vsc_sdp_data, 0, sizeof(catalog->vsc_sdp_data)); + + if (pinfo->out_format & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) { + catalog->vsc_sdp_data.vsc_header_byte0 = 0x00; + catalog->vsc_sdp_data.vsc_header_byte1 = 0x07; + catalog->vsc_sdp_data.vsc_header_byte2 = 0x05; + catalog->vsc_sdp_data.vsc_header_byte3 = 0x13; + + /* VSC SDP Payload for DB16 */ + catalog->vsc_sdp_data.pixel_encoding = YCbCr420; + catalog->vsc_sdp_data.colorimetry = ITU_R_BT_709; + + /* VSC SDP Payload for DB17 */ + catalog->vsc_sdp_data.dynamic_range = CEA; + + /* VSC SDP Payload for DB18 */ + catalog->vsc_sdp_data.content_type = GRAPHICS; + + catalog->vsc_sdp_data.bpc = pinfo->bpp / 3; + + if (panel->catalog->config_vsc_sdp) + panel->catalog->config_vsc_sdp(catalog, true); + } +end: + return rc; +} + static int dp_panel_timing_cfg(struct dp_panel *dp_panel) { int rc = 0; @@ -596,11 +652,37 @@ static int dp_panel_timing_cfg(struct dp_panel *dp_panel) catalog->dp_active = data; panel->catalog->timing_cfg(catalog); + dp_panel_setup_vsc_sdp(dp_panel); panel->panel_on = true; end: return rc; } +static u32 dp_panel_get_pixel_clk(struct dp_panel *dp_panel) +{ + struct dp_panel_private *panel; + struct dp_panel_info *pinfo; + u32 pixel_clk_khz = 0; + u32 rate_ratio = RGB_24BPP_TMDS_CHAR_RATE_RATIO; + + if (!dp_panel) { + pr_err("invalid input\n"); + return 0; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + pinfo = &panel->dp_panel.pinfo; + + pixel_clk_khz = pinfo->pixel_clk_khz; + + if (pinfo->out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO; + + pixel_clk_khz /= rate_ratio; + + return pixel_clk_khz; +} + static int dp_panel_edid_register(struct dp_panel_private *panel) { int rc = 0; @@ -619,6 +701,16 @@ static void dp_panel_edid_deregister(struct dp_panel_private *panel) sde_edid_deinit((void **)&panel->dp_panel.edid_ctrl); } +static inline char *get_out_format(u32 out_format) +{ + if (out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + return "Y420"; + else if (out_format == MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) + return "Y422"; + else + return "RGB"; +} + static int dp_panel_init_panel_info(struct dp_panel *dp_panel) { int rc = 0; @@ -648,6 +740,7 @@ static int dp_panel_init_panel_info(struct dp_panel *dp_panel) pinfo->v_front_porch, pinfo->v_sync_width); pr_info("pixel clock (KHz)=(%d)\n", pinfo->pixel_clk_khz); + pr_info("%s\n", get_out_format(pinfo->out_format)); pr_info("bpp = %d\n", pinfo->bpp); pr_info("active low (h|v)=(%d|%d)\n", pinfo->h_active_low, pinfo->v_active_low); @@ -705,6 +798,20 @@ static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel) return min_link_rate_khz; } +static bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel) +{ + struct dp_panel_private *panel; + + if (!dp_panel) { + pr_err("invalid input\n"); + return false; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + + return panel->major >= 1 && panel->minor >= 3 && panel->vsc_supported; +} + static bool dp_panel_hdr_supported(struct dp_panel *dp_panel) { struct dp_panel_private *panel; @@ -726,6 +833,7 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, int rc = 0; struct dp_panel_private *panel; struct dp_catalog_hdr_data *hdr; + struct dp_panel_info *pinfo; if (!dp_panel) { pr_err("invalid input\n"); @@ -735,6 +843,7 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, panel = container_of(dp_panel, struct dp_panel_private, dp_panel); hdr = &panel->catalog->hdr_data; + pinfo = &panel->dp_panel.pinfo; /* use cached meta data in case meta data not provided */ if (!hdr_meta) { @@ -762,8 +871,16 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, hdr->vscext_header_byte3 = 0x13 << 2; /* VSC SDP Payload for DB16 */ - hdr->pixel_encoding = RGB; - hdr->colorimetry = ITU_R_BT_2020_RGB; + if (pinfo->out_format & MSM_MODE_FLAG_COLOR_FORMAT_RGB444) { + hdr->pixel_encoding = RGB; + hdr->colorimetry = ITU_R_BT_2020_RGB; + } else if (pinfo->out_format & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) { + hdr->pixel_encoding = YCbCr422; + hdr->colorimetry = ITU_R_BT_2020_YCBCR; + } else if (pinfo->out_format & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) { + hdr->pixel_encoding = YCbCr420; + hdr->colorimetry = ITU_R_BT_2020_YCBCR; + } /* VSC SDP Payload for DB17 */ hdr->dynamic_range = CEA; @@ -781,8 +898,11 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, else memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta)); cached: - if (panel->panel_on) + if (panel->panel_on) { panel->catalog->config_hdr(panel->catalog, panel->hdr_state); + if (panel->hdr_state == HDR_DISABLED) + dp_panel_setup_vsc_sdp(dp_panel); + } end: return rc; } @@ -856,6 +976,8 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in) dp_panel->spd_config = dp_panel_spd_config; dp_panel->setup_hdr = dp_panel_setup_hdr; dp_panel->hdr_supported = dp_panel_hdr_supported; + dp_panel->vsc_sdp_supported = dp_panel_vsc_sdp_supported; + dp_panel->get_pixel_clk = dp_panel_get_pixel_clk; dp_panel_edid_register(panel); diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 6c2e1862c59686bdec0007619d716236a8673660..1a87a9672baf599a2f5935fad1f7bfa369dce7c2 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -28,6 +28,7 @@ enum dp_lane_count { DP_LANE_COUNT_4 = 4, }; + #define DP_MAX_DOWNSTREAM_PORTS 0x10 struct dp_panel_info { @@ -45,11 +46,14 @@ struct dp_panel_info { u32 refresh_rate; u32 pixel_clk_khz; u32 bpp; + u32 out_format; + enum hdmi_picture_aspect par; }; struct dp_display_mode { struct dp_panel_info timing; u32 capabilities; + u32 flags; }; struct dp_panel_in { @@ -94,6 +98,8 @@ struct dp_panel { void (*tpg_config)(struct dp_panel *dp_panel, bool enable); int (*spd_config)(struct dp_panel *dp_panel); bool (*hdr_supported)(struct dp_panel *dp_panel); + bool (*vsc_sdp_supported)(struct dp_panel *dp_panel); + u32 (*get_pixel_clk)(struct dp_panel *dp_panel); }; /** diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 0174ea107a072d3debe33d1037324dad5ee28b3f..09fa4fd54b4f685f341e927f3f674e59c80c3b23 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019, 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 @@ -157,6 +157,14 @@ static int dp_parser_misc(struct dp_parser *parser) if (rc) parser->max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ; + parser->yuv_support = of_property_read_bool(of_node, + "qcom,yuv-support"); + + parser->display_type = of_get_property(of_node, + "qcom,display-type", NULL); + if (!parser->display_type) + parser->display_type = "unknown"; + return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index a768ca308a14665ea6feb02e9d56454a1d378d35..a32a8ec302db8e362568fd77de3a678a00857742 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019, 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 @@ -161,6 +161,7 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type) * @pinctrl: pin-control related data * @ctrl_resouce: controller's register address realated data * @disp_data: controller's display related data + * @display_type: display type as defined in device tree. * @parse: function to be called by client to parse device tree. * @get_io: function to be called by client to get io data. * @get_io_buf: function to be called by client to get io buffers. @@ -177,6 +178,9 @@ struct dp_parser { u8 l_map[4]; struct dp_aux_cfg aux_cfg[AUX_CFG_LEN]; u32 max_pclk_khz; + bool yuv_support; + + const char *display_type; int (*parse)(struct dp_parser *parser); struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 6f240021705b0c493457560f1782fdd9483c5b98..e49b414c012c66acd9a477dd57bd141b4697aaa2 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -33,6 +33,8 @@ #include "sfpb.xml.h" #include "dsi_cfg.h" +#define DSI_RESET_TOGGLE_DELAY_MS 20 + static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor) { u32 ver; @@ -909,7 +911,7 @@ static void dsi_sw_reset(struct msm_dsi_host *msm_host) wmb(); /* clocks need to be enabled before reset */ dsi_write(msm_host, REG_DSI_RESET, 1); - wmb(); /* make sure reset happen */ + msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */ dsi_write(msm_host, REG_DSI_RESET, 0); } @@ -1288,7 +1290,7 @@ static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host) /* dsi controller can only be reset while clocks are running */ dsi_write(msm_host, REG_DSI_RESET, 1); - wmb(); /* make sure reset happen */ + msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */ dsi_write(msm_host, REG_DSI_RESET, 0); wmb(); /* controller out of reset */ dsi_write(msm_host, REG_DSI_CTRL, data0); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c8d1f19c9a6d92c7a5ee9f642abec21dfdda20a0..d46b9e75a8473d81aea17fb930818d6b33fbd6b7 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -306,7 +306,7 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector) return num; } -static int dsi_mgr_connector_mode_valid(struct drm_connector *connector, +static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { int id = dsi_mgr_connector_get_id(connector); @@ -438,6 +438,7 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); struct mipi_dsi_host *host = msm_dsi->host; struct drm_panel *panel = msm_dsi->panel; + struct msm_dsi_pll *src_pll; bool is_dual_dsi = IS_DUAL_DSI(); int ret; @@ -471,6 +472,10 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) id, ret); } + /* Save PLL status if it is a clock source */ + src_pll = msm_dsi_phy_get_pll(msm_dsi->phy); + msm_dsi_pll_save_state(src_pll); + ret = msm_dsi_host_power_off(host); if (ret) pr_err("%s: host %d power off failed,%d\n", __func__, id, ret); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index 8b4e3004f4518d19341b24c140606404853e379b..86b0448d2ce58d1421016728aab28b182fcaaa20 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -542,7 +542,7 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, if (cfg_handler) mdp5_cfg_destroy(cfg_handler); - return NULL; + return ERR_PTR(ret); } static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c old mode 100644 new mode 100755 index c564a090fb0e6ce4af343aadfc733aa992d5dd72..1c058db125f9685a7b44221116fbc3b8fa05c9bf --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -526,6 +526,14 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) if (ret) goto fail; + if (!dev->dma_parms) { + dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), + GFP_KERNEL); + if (!dev->dma_parms) + return -ENOMEM; + } + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + switch (get_mdp_ver(pdev)) { case KMS_MDP4: kms = mdp4_kms_init(ddev); diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index efd6a774fdaeaf8a36b3ca4a93bb30026812c3ce..828e0f64e2eee256c7de8882ed8be0bf21877bba 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -26,6 +26,9 @@ #define MAX_PLANE 4 +#define RGB_24BPP_TMDS_CHAR_RATE_RATIO 1 +#define YUV420_24BPP_TMDS_CHAR_RATE_RATIO 2 + /** * Device Private DRM Mode Flags * drm_mode->private_flags @@ -53,12 +56,16 @@ */ /* Enable RGB444 30 bit deep color */ #define MSM_MODE_FLAG_RGB444_DC_ENABLE (1<<5) +/* Enable YUV422 30 bit deep color */ +#define MSM_MODE_FLAG_YUV422_DC_ENABLE (1<<6) /* Enable YUV420 30 bit deep color */ -#define MSM_MODE_FLAG_YUV420_DC_ENABLE (1<<6) +#define MSM_MODE_FLAG_YUV420_DC_ENABLE (1<<7) /* Choose RGB444 format to display */ -#define MSM_MODE_FLAG_COLOR_FORMAT_RGB444 (1<<7) +#define MSM_MODE_FLAG_COLOR_FORMAT_RGB444 (1<<8) +/* Choose YUV422 format to display */ +#define MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422 (1<<9) /* Choose YUV420 format to display */ -#define MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420 (1<<8) +#define MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420 (1<<10) /* As there are different display controller blocks depending on the * snapdragon version, the kms support is split out and the appropriate diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 9fba20f1e1aa1383f716c89f9090885e2b2cd3d5..9ef04a80013f363e592ca1ae7f90ecd24eaacf07 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-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 @@ -724,6 +724,28 @@ int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable) return rc; } +enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn) +{ + struct sde_connector *c_conn; + + if (!conn) { + SDE_ERROR("invalid argument\n"); + return -EINVAL; + } + + c_conn = to_sde_connector(conn); + + if (!c_conn->display) { + SDE_ERROR("invalid argument\n"); + return -EINVAL; + } + + if (!c_conn->ops.get_csc_type) + return SDE_CSC_RGB2YUV_601L; + + return c_conn->ops.get_csc_type(conn, c_conn->display); +} + bool sde_connector_mode_needs_full_range(struct drm_connector *connector) { struct sde_connector *c_conn; @@ -746,6 +768,28 @@ bool sde_connector_mode_needs_full_range(struct drm_connector *connector) return c_conn->ops.mode_needs_full_range(c_conn->display); } +bool sde_connector_mode_is_cea_mode(struct drm_connector *connector) +{ + struct sde_connector *c_conn; + + if (!connector) { + SDE_ERROR("invalid argument\n"); + return false; + } + + c_conn = to_sde_connector(connector); + + if (!c_conn->display) { + SDE_ERROR("invalid argument\n"); + return false; + } + + if (!c_conn->ops.mode_is_cea_mode) + return false; + + return c_conn->ops.mode_is_cea_mode(c_conn->display); +} + static void sde_connector_destroy(struct drm_connector *connector) { struct sde_connector *c_conn; @@ -1977,6 +2021,9 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn, sde_kms_info_add_keystr(info, "mode_name", mode->name); + sde_kms_info_add_keyint(info, "VIC", + mode->vic_id); + sde_kms_info_add_keyint(info, "bit_clk_rate", mode_info.clk_rate); diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h index 87c2ee27ef98b71e62ae7c9fe6cb2b7bd17f7d55..3fb4531cb8595be3a57295734c91e99ca6de02f8 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-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 @@ -191,6 +191,14 @@ struct sde_connector_ops { */ bool (*mode_needs_full_range)(void *display); + /** + * mode_is_cea_mode - is this mode a CE video format + * or IT video format. + * @display: Pointer to private display structure + * Returns: true or false based on CE or IT video format + */ + bool (*mode_is_cea_mode)(void *display); + /** * clk_ctrl - perform clk enable/disable on the connector * @handle: Pointer to clk handle @@ -198,6 +206,15 @@ struct sde_connector_ops { * @enable: State of clks */ int (*clk_ctrl)(void *handle, u32 type, u32 state); + /** + * get_csc_type - returns the CSC type to be used + * by the CDM block based on HDR state + * @connector: Pointer to drm connector structure + * @display: Pointer to private display structure + * Returns: type of CSC matrix to be used + */ + enum sde_csc_type (*get_csc_type)(struct drm_connector *connector, + void *display); /** * set_power - update dpms setting @@ -718,6 +735,22 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector) */ bool sde_connector_mode_needs_full_range(struct drm_connector *connector); +/** + * sde_connector_mode_is_cea_mode - query if this mode is + * CE or IT video format + * @connector: Pointer to drm connector object + * Returns: true OR false based on CE or IT video format mode + */ +bool sde_connector_mode_is_cea_mode(struct drm_connector *connector); + +/** + * sde_connector_get_csc_type - query csc type + * to be used for the connector + * @connector: Pointer to drm connector object + * Returns: csc type based on connector HDR state + */ +enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn); + /** * sde_connector_get_dither_cfg - get dither property data * @conn: Pointer to drm_connector struct diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 8594f543ec732130bc80ff36906e0961a7b7cc86..3e625fe2f6efa5fc2ae2ada07a3e74f7a039d801 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -186,6 +186,78 @@ static struct sde_csc_cfg sde_csc_10bit_convert[SDE_MAX_CSC] = { { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, }, + + [SDE_CSC_RGB2YUV_709L] = { + { + TO_S15D16(0x005d), TO_S15D16(0x013a), TO_S15D16(0x0020), + TO_S15D16(0xffcc), TO_S15D16(0xff53), TO_S15D16(0x00e1), + TO_S15D16(0x00e1), TO_S15D16(0xff34), TO_S15D16(0xffeb), + }, + { 0x0, 0x0, 0x0,}, + { 0x0040, 0x0200, 0x0200,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,}, + }, + + [SDE_CSC_RGB2YUV_709FR] = { + { + TO_S15D16(0x006d), TO_S15D16(0x016e), TO_S15D16(0x0025), + TO_S15D16(0xffc5), TO_S15D16(0xff3b), TO_S15D16(0x0100), + TO_S15D16(0x0100), TO_S15D16(0xff17), TO_S15D16(0xffe9), + }, + { 0x0, 0x0, 0x0,}, + { 0x0040, 0x0200, 0x0200,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + }, + + [SDE_CSC_RGB2YUV_2020L] = { + { + TO_S15D16(0x0073), TO_S15D16(0x0129), TO_S15D16(0x001a), + TO_S15D16(0xffc1), TO_S15D16(0xff5e), TO_S15D16(0x00e0), + TO_S15D16(0x00e0), TO_S15D16(0xff32), TO_S15D16(0xffee), + }, + { 0x0, 0x0, 0x0,}, + { 0x0040, 0x0200, 0x0200,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,}, + }, + + [SDE_CSC_RGB2YUV_2020FR] = { + { + TO_S15D16(0x0086), TO_S15D16(0x015b), TO_S15D16(0x001e), + TO_S15D16(0xffb9), TO_S15D16(0xff47), TO_S15D16(0x0100), + TO_S15D16(0x0100), TO_S15D16(0xff15), TO_S15D16(0xffeb), + }, + { 0x0, 0x0, 0x0,}, + { 0x0, 0x0200, 0x0200,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + }, + + [SDE_CSC_RGB2RGB_L] = { + { + TO_S15D16(0x01b7), TO_S15D16(0x0000), TO_S15D16(0x0000), + TO_S15D16(0x0000), TO_S15D16(0x01b7), TO_S15D16(0x0000), + TO_S15D16(0x0000), TO_S15D16(0x0000), TO_S15D16(0x01b7), + }, + { 0x0, 0x0, 0x0,}, + { 0x0040, 0x0040, 0x0040,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x40, 0x3ac, 0x40, 0x3ac, 0x40, 0x3ac,}, + }, + + [SDE_CSC_RGB2RGB_FR] = { + { + TO_S15D16(0x0200), TO_S15D16(0x0000), TO_S15D16(0x0000), + TO_S15D16(0x0000), TO_S15D16(0x0200), TO_S15D16(0x0000), + TO_S15D16(0x0000), TO_S15D16(0x0000), TO_S15D16(0x0200), + }, + { 0x0, 0x0, 0x0,}, + { 0x0, 0x0, 0x0,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + } }; /** @@ -4058,10 +4130,15 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_phys *phys; struct sde_kms *sde_kms = NULL; struct msm_drm_private *priv = NULL; + struct drm_connector *conn_mas = NULL; + struct drm_display_mode *mode; + struct sde_hw_cdm *hw_cdm; + enum sde_csc_type conn_csc; bool needs_hw_reset = false; uint32_t ln_cnt1, ln_cnt2; unsigned int i; int rc, ret = 0; + int mode_is_yuv = 0; if (!drm_enc || !params || !drm_enc->dev || !drm_enc->dev->dev_private) { @@ -4131,13 +4208,50 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, _sde_encoder_update_roi(drm_enc); if (sde_enc->cur_master && sde_enc->cur_master->connector) { - rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector); + conn_mas = sde_enc->cur_master->connector; + rc = sde_connector_pre_kickoff(conn_mas); if (rc) { - SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n", - sde_enc->cur_master->connector->base.id, - rc); + SDE_ERROR_ENC(sde_enc, + "kickoff conn%d failed rc %d\n", + conn_mas->base.id, + rc); ret = rc; } + + for (i = 0; i < sde_enc->num_phys_encs; i++) { + phys = sde_enc->phys_encs[i]; + if (phys) { + mode = &phys->cached_mode; + mode_is_yuv = ((mode->private_flags & + MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) || + (mode->private_flags & + MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422)); + } + /** + * Check the CSC matrix type to which the + * CDM CSC matrix should be updated to based + * on the connector HDR state + */ + conn_csc = sde_connector_get_csc_type(conn_mas); + if (phys && mode_is_yuv) { + if (phys->enc_cdm_csc != conn_csc) { + hw_cdm = phys->hw_cdm; + rc = hw_cdm->ops.setup_csc_data(hw_cdm, + &sde_csc_10bit_convert[conn_csc]); + + if (rc) + SDE_ERROR_ENC(sde_enc, + "CSC setup failed rc %d\n", + rc); + SDE_DEBUG_ENC(sde_enc, + "updating CSC %d to %d\n", + phys->enc_cdm_csc, + conn_csc); + phys->enc_cdm_csc = conn_csc; + + } + } + } } if (_sde_encoder_is_dsc_enabled(drm_enc) && @@ -5181,7 +5295,8 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, } sde_enc = to_sde_encoder_virt(encoder); - if (!SDE_FORMAT_IS_YUV(format)) { + if ((output_type == CDM_CDWN_OUTPUT_WB) && + !SDE_FORMAT_IS_YUV(format)) { SDE_DEBUG_ENC(sde_enc, "[cdm_disable fmt:%x]\n", format->base.pixel_format); @@ -5241,13 +5356,21 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, */ if (output_type == CDM_CDWN_OUTPUT_HDMI) { - if (connector && connector->yuv_qs) - csc_type = SDE_CSC_RGB2YUV_601FR; - else if (connector && - sde_connector_mode_needs_full_range(connector)) - csc_type = SDE_CSC_RGB2YUV_601FR; - else - csc_type = SDE_CSC_RGB2YUV_601L; + if (SDE_FORMAT_IS_YUV(format)) { + if (connector && connector->yuv_qs) + csc_type = SDE_CSC_RGB2YUV_709FR; + else if (connector && + sde_connector_mode_needs_full_range(connector)) + csc_type = SDE_CSC_RGB2YUV_709FR; + else + csc_type = SDE_CSC_RGB2YUV_709L; + } else if (connector && + sde_connector_mode_is_cea_mode(connector)) { + csc_type = SDE_CSC_RGB2RGB_L; + } else { + csc_type = SDE_CSC_RGB2RGB_FR; + } + } else if (output_type == CDM_CDWN_OUTPUT_WB) { csc_type = SDE_CSC_RGB2YUV_601L; } @@ -5261,6 +5384,9 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, } } + /* Cache the CSC default matrix type */ + phys_enc->enc_cdm_csc = csc_type; + if (hw_cdm && hw_cdm->ops.setup_cdwn) { ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg); if (ret < 0) { @@ -5277,3 +5403,21 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, } } } + +void sde_encoder_phys_destroy_cdm(struct sde_encoder_phys *phys_enc) +{ + struct drm_encoder *encoder = phys_enc->parent; + struct sde_encoder_virt *sde_enc = NULL; + struct sde_hw_cdm *hw_cdm = phys_enc->hw_cdm; + + if (!encoder) { + SDE_ERROR("invalid encoder\n"); + return; + } + sde_enc = to_sde_encoder_virt(encoder); + + SDE_DEBUG_ENC(sde_enc, "[cdm_disable]\n"); + + if (hw_cdm && hw_cdm->ops.disable) + hw_cdm->ops.disable(hw_cdm); +} diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 685d5b25f6ecb687f5d05980186ad056c1f9adf0..d5e9f4ac1637ddda11e1d615bcf2eb4df1263558 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-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 @@ -252,6 +252,7 @@ struct sde_encoder_irq { * @intf_mode: Interface mode * @intf_idx: Interface index on sde hardware * @comp_type: Type of compression supported + * @enc_cdm_csc: Cached CSC type of CDM block * @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes * @enable_state: Enable state tracking * @vblank_refcount: Reference count of vblank request @@ -291,6 +292,7 @@ struct sde_encoder_phys { enum sde_intf_mode intf_mode; enum sde_intf intf_idx; enum msm_display_compression_type comp_type; + enum sde_csc_type enc_cdm_csc; spinlock_t *enc_spinlock; enum sde_enc_enable_state enable_state; struct mutex *vblank_ctl_lock; @@ -496,6 +498,8 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, const struct sde_format *format, u32 output_type, struct sde_rect *roi); +void sde_encoder_phys_destroy_cdm(struct sde_encoder_phys *phys_enc); + /** * sde_encoder_helper_trigger_flush - control flush helper function * This helper function may be optionally specified by physical diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 798717b7ebedc40aa28802a9985c674bf2a3daff..bd0868be9ae1106226c3cb6189a1df5d1efa0cde 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -792,6 +792,10 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc) if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) fmt = sde_get_sde_format(DRM_FORMAT_YUV420); + else if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) + fmt = sde_get_sde_format(DRM_FORMAT_NV61); + else if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_RGB444) + fmt = sde_get_sde_format(DRM_FORMAT_RGB888); if (fmt) { struct sde_rect hdmi_roi; @@ -828,6 +832,7 @@ static void sde_encoder_phys_vid_destroy(struct sde_encoder_phys *phys_enc) } vid_enc = to_sde_encoder_phys_vid(phys_enc); + sde_encoder_phys_destroy_cdm(phys_enc); SDE_DEBUG_VIDENC(vid_enc, "\n"); kfree(vid_enc); } @@ -838,22 +843,33 @@ static void sde_encoder_phys_vid_get_hw_resources( struct drm_connector_state *conn_state) { struct sde_encoder_phys_vid *vid_enc; + struct sde_mdss_cfg *vid_catalog; if (!phys_enc || !hw_res) { SDE_ERROR("invalid arg(s), enc %d hw_res %d conn_state %d\n", - phys_enc != 0, hw_res != 0, conn_state != 0); + phys_enc != NULL, hw_res != NULL, conn_state != NULL); return; } + vid_catalog = phys_enc->sde_kms->catalog; vid_enc = to_sde_encoder_phys_vid(phys_enc); - if (!vid_enc->hw_intf) { - SDE_ERROR("invalid arg(s), hw_intf\n"); + if (!vid_enc->hw_intf || !vid_catalog) { + SDE_ERROR("invalid arg(s), hw_intf %d vid_catalog %d\n", + vid_enc->hw_intf != NULL, vid_catalog != NULL); return; } SDE_DEBUG_VIDENC(vid_enc, "\n"); + if (vid_enc->hw_intf->idx > INTF_MAX) { + SDE_ERROR("invalid arg(s), idx %d\n", + vid_enc->hw_intf->idx); + return; + } hw_res->intfs[vid_enc->hw_intf->idx - INTF_0] = INTF_MODE_VIDEO; - hw_res->needs_cdm = true; + + if (vid_catalog->intf[vid_enc->hw_intf->idx - INTF_0].type + == INTF_DP) + hw_res->needs_cdm = true; SDE_DEBUG_DRIVER("[vid] needs_cdm=%d\n", hw_res->needs_cdm); } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c index 84b731ed54075ef8081b9723d0379724ebc0373f..6066d6a744558b0014bdd711aa8c556889d87ca1 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -2348,7 +2348,7 @@ static int sde_cdm_parse_dt(struct device_node *np, /* intf3 and wb2 for cdm block */ cdm->wb_connect = sde_cfg->wb_count ? BIT(WB_2) : BIT(31); - cdm->intf_connect = sde_cfg->intf_count ? BIT(INTF_3) : BIT(31); + cdm->intf_connect = sde_cfg->intf_count ? BIT(INTF_0) : BIT(31); } end: diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c index a223e77f32e7af1513a8b503ece711549e3de4eb..866619830f7dbd8f78f43187112c925d354a40ee 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -226,21 +226,29 @@ int sde_hw_cdm_enable(struct sde_hw_cdm *ctx, u32 opmode = 0; u32 csc = 0; - if (!SDE_FORMAT_IS_YUV(fmt)) + if ((cdm->output_type == CDM_CDWN_OUTPUT_WB) && + !SDE_FORMAT_IS_YUV(fmt)) return -EINVAL; if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) { if (fmt->chroma_sample == SDE_CHROMA_H1V2) return -EINVAL; /*unsupported format */ - opmode = BIT(0); - opmode |= (fmt->chroma_sample << 1); + if (fmt->chroma_sample == SDE_CHROMA_RGB) { + opmode = 0; + } else { + opmode = BIT(0); + opmode |= (fmt->chroma_sample << 1); + } cdm_cfg.intf_en = true; } else { opmode = 0; cdm_cfg.wb_en = true; } - csc |= BIT(2); + if (fmt->chroma_sample == SDE_CHROMA_RGB) + csc &= ~BIT(2); + else + csc |= BIT(2); csc &= ~BIT(1); csc |= BIT(0); diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h index 0c3a9676e6e80506e0024f6ac872bf1f4a4a92f5..db84ba4e060db75d51e87bbfac3233e49e0ff0e5 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -396,6 +396,12 @@ enum sde_3d_blend_mode { enum sde_csc_type { SDE_CSC_RGB2YUV_601L, SDE_CSC_RGB2YUV_601FR, + SDE_CSC_RGB2YUV_709L, + SDE_CSC_RGB2YUV_709FR, + SDE_CSC_RGB2YUV_2020L, + SDE_CSC_RGB2YUV_2020FR, + SDE_CSC_RGB2RGB_L, + SDE_CSC_RGB2RGB_FR, SDE_MAX_CSC }; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c index cf646bdbee40107c661c8c49189b6f45a6595d4a..48fedfde97628eadb24775ac10b5092099195f58 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_top.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2019, 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 @@ -159,7 +159,7 @@ static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp, if (cfg->wb_en) out_ctl |= BIT(24); else if (cfg->intf_en) - out_ctl |= BIT(19); + out_ctl |= BIT(28); SDE_REG_WRITE(c, MDP_OUT_CTL_0, out_ctl); } diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 68c3ca05c1b02a196198fd58ebc4c903a34ed941..df4eaecf779be6a0d47d516655f3d75444807720 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -1306,6 +1306,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_panel_vfp = NULL, }; static const struct sde_connector_ops dp_ops = { + .set_info_blob = dp_connnector_set_info_blob, .post_init = dp_connector_post_init, .detect = dp_connector_detect, .get_modes = dp_connector_get_modes, @@ -1319,6 +1320,8 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .cont_splash_config = NULL, .get_panel_vfp = NULL, .mode_needs_full_range = dp_connector_mode_needs_full_range, + .mode_is_cea_mode = dp_connector_mode_is_cea_mode, + .get_csc_type = dp_connector_get_csc_type, }; static const struct sde_connector_ops ext_bridge_ops = { .set_info_blob = dsi_conn_set_info_blob, diff --git a/drivers/gpu/drm/msm/sde_edid_parser.c b/drivers/gpu/drm/msm/sde_edid_parser.c index c2ba3b97c86eab12ca7fa5c8cc9cb9cf91065067..11051b54258b89a0a3754ab5a9d36514c00334fa 100644 --- a/drivers/gpu/drm/msm/sde_edid_parser.c +++ b/drivers/gpu/drm/msm/sde_edid_parser.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-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 @@ -242,7 +242,7 @@ u32 video_format) if ((cea_mode != 0) && (cea_mode == video_format)) { SDE_EDID_DEBUG("%s found match for %d ", __func__, video_format); - mode->flags |= DRM_MODE_FLAG_SUPPORTS_YUV; + mode->flags |= DRM_MODE_FLAG_SUPPORTS_YUV420; } } } @@ -251,12 +251,13 @@ static void sde_edid_parse_Y420CMDB( struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl, const u8 *db) { - u32 offset = 0; u8 cmdb_len = 0; u8 svd_len = 0; const u8 *svd = NULL; - u32 i = 0, j = 0; + u32 i = 0; u32 video_format = 0; + u32 num_cmdb_svd = 0; + const u32 mult = 8; if (!edid_ctrl) { SDE_ERROR("%s: edid_ctrl is NULL\n", __func__); @@ -270,8 +271,8 @@ const u8 *db) SDE_EDID_DEBUG("%s +\n", __func__); cmdb_len = db[0] & 0x1f; - /* Byte 3 to L+1 contain SVDs */ - offset += 2; + if (cmdb_len < 1) + return; svd = sde_edid_find_block(edid_ctrl->edid, VIDEO_DATA_BLOCK); @@ -281,21 +282,26 @@ const u8 *db) ++svd; } - for (i = 0; i < svd_len; i++, j++) { + if (cmdb_len == 1) + num_cmdb_svd = svd_len; + else { + num_cmdb_svd = (cmdb_len - 1) * mult; + if (num_cmdb_svd > svd_len) + num_cmdb_svd = svd_len; + } + + for (i = 0; i < num_cmdb_svd; i++) { video_format = *(svd + i) & 0x7F; - if (cmdb_len == 1) { - /* If cmdb_len is 1, it means all SVDs support YUV */ - sde_edid_set_y420_support(connector, video_format); - } else if (db[offset] & (1 << j)) { + /* + * If cmdb_len is 1, it means all SVDs support YUV + * Else, we check each byte of the cmdb bitmap bitwise + * and match those bits with the formats populated + * during the parsing of the Video Data Blocks. + * Refer to CTA 861-F section 7.5.11 YCBCR 4:2:0 Capability + * Map Data Block for more details on this. + */ + if (cmdb_len == 1 || (db[2 + i / mult] & (1 << (i % mult)))) sde_edid_set_y420_support(connector, video_format); - - if (j & 0x80) { - j = j/8; - offset++; - if (offset >= cmdb_len) - break; - } - } } SDE_EDID_DEBUG("%s -\n", __func__); @@ -335,6 +341,7 @@ struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl) { const u8 *db = NULL; struct drm_display_mode *mode; + struct drm_display_info *info = &connector->display_info; SDE_EDID_DEBUG("%s +\n", __func__); /* Set YUV mode support flags for YCbcr420VDB */ @@ -347,8 +354,11 @@ struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl) /* Set RGB supported on all modes where YUV is not set */ list_for_each_entry(mode, &connector->probed_modes, head) { - if (!(mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV)) + if (!(mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV420)) { mode->flags |= DRM_MODE_FLAG_SUPPORTS_RGB; + if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) + mode->flags |= DRM_MODE_FLAG_SUPPORTS_YUV422; + } } @@ -378,6 +388,7 @@ struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl) } disp_info = &connector->display_info; + disp_info->y420_bpc = 8; edid_ext = sde_find_cea_extension(edid_ctrl->edid); @@ -398,16 +409,19 @@ struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl) continue; if (hdmi[7] & DRM_EDID_YCBCR420_DC_30) { + disp_info->y420_bpc = 10; hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_30; SDE_EDID_DEBUG("Y420 30-bit supported\n"); } if (hdmi[7] & DRM_EDID_YCBCR420_DC_36) { + disp_info->y420_bpc = 12; hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_36; SDE_EDID_DEBUG("Y420 36-bit supported\n"); } if (hdmi[7] & DRM_EDID_YCBCR420_DC_48) { + disp_info->y420_bpc = 16; hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_36; SDE_EDID_DEBUG("Y420 48-bit supported\n"); } @@ -548,6 +562,12 @@ int _sde_edid_update_modes(struct drm_connector *connector, { int rc = 0; struct sde_edid_ctrl *edid_ctrl = (struct sde_edid_ctrl *)(input); + struct drm_display_info *disp_info; + + disp_info = &connector->display_info; + + if (disp_info) + disp_info->edid_hdmi_dc_modes = 0; SDE_EDID_DEBUG("%s +", __func__); if (edid_ctrl->edid) { diff --git a/drivers/gpu/drm/msm/sde_edid_parser.h b/drivers/gpu/drm/msm/sde_edid_parser.h index fd56116c21e94f13e7735055fa3676f55ec6e024..422ce082ef8d37b32f84cf9660d6f7e3ff2704bc 100644 --- a/drivers/gpu/drm/msm/sde_edid_parser.h +++ b/drivers/gpu/drm/msm/sde_edid_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 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 @@ -33,7 +33,11 @@ #define SDE_CEA_EXT 0x02 #define SDE_EXTENDED_TAG 0x07 -#define SDE_DRM_MODE_FLAG_FMT_MASK (0x3 << 20) +#define MIN_SCRAMBLER_REQ_RATE 340000 + +#define SDE_DRM_MODE_FLAG_FMT_MASK (DRM_MODE_FLAG_SUPPORTS_RGB | \ + DRM_MODE_FLAG_SUPPORTS_YUV422 | \ + DRM_MODE_FLAG_SUPPORTS_YUV420) enum extended_data_block_types { VIDEO_CAPABILITY_DATA_BLOCK = 0x0, diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 4bb9ab892ae19c3afe6f7e1bf235f8e7869bd28b..78e521d00251c4e29282fc4141efa12b82d8d12e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -158,7 +158,7 @@ nouveau_fence_wait_uevent_handler(struct nvif_notify *notify) fence = list_entry(fctx->pending.next, typeof(*fence), head); chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); - if (nouveau_fence_update(fence->channel, fctx)) + if (nouveau_fence_update(chan, fctx)) ret = NVIF_NOTIFY_DROP; } spin_unlock_irqrestore(&fctx->lock, flags); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c index 9d90d8b4b7e65398bd91c903cebf6ee046375825..f5a8db1bb8b7271c0407460b835e328807771af1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c @@ -72,6 +72,8 @@ nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) if (debug > subdev->debug) return; + if (!mthd) + return; for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { u32 base = chan->head * mthd->addr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index de8b806b88fd9dfd8cc1e1b864a3974db04ffbf7..7618b2eb4fdfde85e0b92e946c1754a57ec1418f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -143,23 +143,24 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, nent = (fuc.size / sizeof(struct gk20a_fw_av)); - pack = vzalloc((sizeof(*pack) * max_classes) + - (sizeof(*init) * (nent + 1))); + pack = vzalloc((sizeof(*pack) * (max_classes + 1)) + + (sizeof(*init) * (nent + max_classes + 1))); if (!pack) { ret = -ENOMEM; goto end; } - init = (void *)(pack + max_classes); + init = (void *)(pack + max_classes + 1); - for (i = 0; i < nent; i++) { - struct gf100_gr_init *ent = &init[i]; + for (i = 0; i < nent; i++, init++) { struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i]; u32 class = av->addr & 0xffff; u32 addr = (av->addr & 0xffff0000) >> 14; if (prevclass != class) { - pack[classidx].init = ent; + if (prevclass) /* Add terminator to the method list. */ + init++; + pack[classidx].init = init; pack[classidx].type = class; prevclass = class; if (++classidx >= max_classes) { @@ -169,10 +170,10 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, } } - ent->addr = addr; - ent->data = av->data; - ent->count = 1; - ent->pitch = 1; + init->addr = addr; + init->data = av->data; + init->count = 1; + init->pitch = 1; } *ppack = pack; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c index 60ece0a8a2e1bc1e5acd5753fe3d37f08323ed8e..1d2d6bae73cd1f57aef57a31ed6ce80dfc57e3f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c @@ -87,7 +87,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; /* XXX: Get these values from the VBIOS instead */ DLL = !(ram->mr[1] & 0x1); - RON = !(ram->mr[1] & 0x300) >> 8; + RON = !((ram->mr[1] & 0x300) >> 8); break; default: return -ENOSYS; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c index e6f74168238c72ecc426471f061f676d66cc0829..2ef9e942f43a243d0d6d0316f227988cf28f302b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c @@ -87,10 +87,10 @@ nvkm_memx_fini(struct nvkm_memx **pmemx, bool exec) if (exec) { nvkm_pmu_send(pmu, reply, PROC_MEMX, MEMX_MSG_EXEC, memx->base, finish); + nvkm_debug(subdev, "Exec took %uns, PMU_IN %08x\n", + reply[0], reply[1]); } - nvkm_debug(subdev, "Exec took %uns, PMU_IN %08x\n", - reply[0], reply[1]); kfree(memx); return 0; } diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index b99f3e59011c1500b120d3980f25d3aff05302d3..5fcb5869a4891180a2f909c0aecfdf34f26c7c13 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7026,8 +7026,8 @@ static int cik_irq_init(struct radeon_device *rdev) } /* setup interrupt control */ - /* XXX this should actually be a bus address, not an MC address. same on older asics */ - WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); + /* set dummy read address to dummy page address */ + WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8); interrupt_cntl = RREG32(INTERRUPT_CNTL); /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index f5e84f4b58e60e2e7a5c8cacbd459a5c0567866f..c99a976087987942fe5a3f901c32504dc4a692d6 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1824,8 +1824,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p, track->textures[i].use_pitch = 1; } else { track->textures[i].use_pitch = 0; - track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); - track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); + track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT); + track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT); } if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) track->textures[i].tex_coord_type = 2; diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index c70e6d5bcd198ce139f4eae2c842044da998b0e3..8aa3772e935fed709520b80a48aa5b1dfee6971a 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -476,8 +476,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, track->textures[i].use_pitch = 1; } else { track->textures[i].use_pitch = 0; - track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); - track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); + track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT); + track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT); } if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE) track->textures[i].lookup_disable = true; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index f2eac6b6c46a3082f624670b7d77c1190d985fb3..9569c35f8766a6b9b5f3bdd26152fb8802fefa87 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3697,8 +3697,8 @@ int r600_irq_init(struct radeon_device *rdev) } /* setup interrupt control */ - /* set dummy read address to ring address */ - WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); + /* set dummy read address to dummy page address */ + WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8); interrupt_cntl = RREG32(INTERRUPT_CNTL); /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8b6f8aa238063a73c75481d0a9953dd4bb76df87..432ad7d73cb9b9d2fb8135769d9557f0ae29211e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -110,6 +110,8 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc) DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); + msleep(10); + WREG32(NI_INPUT_CSC_CONTROL + radeon_crtc->crtc_offset, (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) | NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS))); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index b75d809c292e3b6418f06d567febc48175c6bdfa..919d389869ceb3ff2fcd798333aeed2cbc3a7474 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6018,8 +6018,8 @@ static int si_irq_init(struct radeon_device *rdev) } /* setup interrupt control */ - /* set dummy read address to ring address */ - WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); + /* set dummy read address to dummy page address */ + WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8); interrupt_cntl = RREG32(INTERRUPT_CNTL); /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index e7c243f70870292dbafdf3bb2f1919d0953b4efd..08808e3701de96783f76b2a124636adf56908b92 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -740,7 +740,6 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data) return 0; err_sysfs: - drm_bridge_remove(bridge); return -EINVAL; } diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 376b0763c874aaebb88d4bc90927470d20809ed9..a5412a6fbeca2a9c1a3ded6d97323bc6ae16c5d7 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -1352,7 +1352,6 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) return 0; err_sysfs: - drm_bridge_remove(bridge); hdmi->drm_connector = NULL; return -EINVAL; } diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index a1b3ea1ccb65bcb3a7bb3c39c722c20b0f253d18..772a5a3b0ce1a74c1098b5b7c0cb6a4d1dc18a1c 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -681,11 +681,11 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, { struct virtio_gpu_get_capset *cmd_p; struct virtio_gpu_vbuffer *vbuf; - int max_size = vgdev->capsets[idx].max_size; + int max_size; struct virtio_gpu_drv_cap_cache *cache_ent; void *resp_buf; - if (idx > vgdev->num_capsets) + if (idx >= vgdev->num_capsets) return -EINVAL; if (version > vgdev->capsets[idx].max_version) @@ -695,6 +695,7 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, if (!cache_ent) return -ENOMEM; + max_size = vgdev->capsets[idx].max_size; cache_ent->caps_cache = kmalloc(max_size, GFP_KERNEL); if (!cache_ent->caps_cache) { kfree(cache_ent); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c index 1f013d45c9e9a3959dfa19300ba76fc37820592a..0c7c3005594cc8a90fd4c53f19a01c137b169da0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c @@ -210,8 +210,10 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man, cres->hash.key = user_key | (res_type << 24); ret = drm_ht_insert_item(&man->resources, &cres->hash); - if (unlikely(ret != 0)) + if (unlikely(ret != 0)) { + kfree(cres); goto out_invalid_key; + } cres->state = VMW_CMDBUF_RES_ADD; cres->res = vmw_resource_reference(res); diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index ce9e55ed26e09244ebc9998a7c0fd4adfe2bcd4e..7e492394273259080b772fa7dfb7fbeffe0f4df5 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -573,6 +573,17 @@ config HID_MULTITOUCH To compile this driver as a module, choose M here: the module will be called hid-multitouch. +config HID_NINTENDO + tristate "Nintendo Joy-Con and Pro Controller support" + depends on HID + help + Adds support for the Nintendo Switch Joy-Cons and Pro Controller. + All controllers support bluetooth, and the Pro Controller also supports + its USB mode. + + To compile this driver as a module, choose M here: the + module will be called hid-nintendo. + config HID_NTRIG tristate "N-Trig touch screen" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index a11278bf30f65e444698ff94f02b06c3ec20a110..538716e16696ec33032a563614eb12e5159aeebf 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o +obj-$(CONFIG_HID_NINTENDO) += hid-nintendo.o obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o obj-$(CONFIG_HID_ORTEK) += hid-ortek.o obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 6d76e96a5166c63a3d1197386175213b0d5a281f..0a3efa74be35c828ee11993ac4370cccea2fbc4d 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -341,7 +341,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, unsigned long **bit, int *max) { if (usage->hid == (HID_UP_CUSTOM | 0x0003) || - usage->hid == (HID_UP_MSVENDOR | 0x0003)) { + usage->hid == (HID_UP_MSVENDOR | 0x0003) || + usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) { /* The fn key on Apple USB keyboards */ set_bit(EV_REP, hi->input->evbit); hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index acb026182872729f426260957edea2f56fc338be..4f3706e4490597888f7aa7952b8f7bb52b5f902e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -269,6 +269,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign offset = report->size; report->size += parser->global.report_size * parser->global.report_count; + /* Total size check: Allow for possible report index byte */ + if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) { + hid_err(parser->device, "report is too long\n"); + return -1; + } + if (!parser->local.usage_index) /* Ignore padding fields */ return 0; @@ -761,6 +767,10 @@ static void hid_scan_feature_usage(struct hid_parser *parser, u32 usage) if (usage == 0xff0000c5 && parser->global.report_count == 256 && parser->global.report_size == 8) parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8; + + if (usage == 0xff0000c6 && parser->global.report_count == 1 && + parser->global.report_size == 8) + parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8; } static void hid_scan_collection(struct hid_parser *parser, unsigned type) @@ -1537,7 +1547,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, rsize = ((report->size - 1) >> 3) + 1; - if (rsize > HID_MAX_BUFFER_SIZE) + if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE) + rsize = HID_MAX_BUFFER_SIZE - 1; + else if (rsize > HID_MAX_BUFFER_SIZE) rsize = HID_MAX_BUFFER_SIZE; if (csize < rsize) { @@ -2050,6 +2062,16 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, +#if IS_ENABLED(CONFIG_HID_NINTENDO) + { HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_PROCON) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_PROCON) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_JOYCONL) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_JOYCONR) }, +#endif { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 36d69ee04795f55a6131a2c834ff6b63452be910..3df43649075de4bc55904005008294cfc7094fe1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -778,6 +778,9 @@ #define USB_VENDOR_ID_NINTENDO 0x057e #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 #define USB_DEVICE_ID_NINTENDO_WIIMOTE2 0x0330 +#define USB_DEVICE_ID_NINTENDO_JOYCONL 0x2006 +#define USB_DEVICE_ID_NINTENDO_JOYCONR 0x2007 +#define USB_DEVICE_ID_NINTENDO_PROCON 0x2009 #define USB_VENDOR_ID_NOVATEK 0x0603 #define USB_DEVICE_ID_NOVATEK_PCT 0x0600 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 9f7b1cf726a8dd1563d117dd273426ec9e5e2688..5dbb05961cb51294ba0b3f93d3b6175079f51d45 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -342,13 +342,45 @@ static unsigned find_battery_quirk(struct hid_device *hdev) return quirks; } +static int hidinput_scale_battery_capacity(struct hid_device *dev, + int value) +{ + if (dev->battery_min < dev->battery_max && + value >= dev->battery_min && value <= dev->battery_max) + value = ((value - dev->battery_min) * 100) / + (dev->battery_max - dev->battery_min); + + return value; +} + +static int hidinput_query_battery_capacity(struct hid_device *dev) +{ + u8 *buf; + int ret; + + buf = kmalloc(2, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2, + dev->battery_report_type, HID_REQ_GET_REPORT); + if (ret != 2) { + kfree(buf); + return -ENODATA; + } + + ret = hidinput_scale_battery_capacity(dev, buf[1]); + kfree(buf); + return ret; +} + static int hidinput_get_battery_property(struct power_supply *psy, enum power_supply_property prop, union power_supply_propval *val) { struct hid_device *dev = power_supply_get_drvdata(psy); + int value; int ret = 0; - __u8 *buf; switch (prop) { case POWER_SUPPLY_PROP_PRESENT: @@ -357,29 +389,15 @@ static int hidinput_get_battery_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CAPACITY: - - buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - break; + if (dev->battery_report_type == HID_FEATURE_REPORT) { + value = hidinput_query_battery_capacity(dev); + if (value < 0) + return value; + } else { + value = dev->battery_capacity; } - ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2, - dev->battery_report_type, - HID_REQ_GET_REPORT); - if (ret != 2) { - ret = -ENODATA; - kfree(buf); - break; - } - ret = 0; - - if (dev->battery_min < dev->battery_max && - buf[1] >= dev->battery_min && - buf[1] <= dev->battery_max) - val->intval = (100 * (buf[1] - dev->battery_min)) / - (dev->battery_max - dev->battery_min); - kfree(buf); + val->intval = value; break; case POWER_SUPPLY_PROP_MODEL_NAME: @@ -387,7 +405,22 @@ static int hidinput_get_battery_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_STATUS: - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + if (!dev->battery_reported && + dev->battery_report_type == HID_FEATURE_REPORT) { + value = hidinput_query_battery_capacity(dev); + if (value < 0) + return value; + + dev->battery_capacity = value; + dev->battery_reported = true; + } + + if (!dev->battery_reported) + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + else if (dev->battery_capacity == 100) + val->intval = POWER_SUPPLY_STATUS_FULL; + else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; case POWER_SUPPLY_PROP_SCOPE: @@ -402,18 +435,16 @@ static int hidinput_get_battery_property(struct power_supply *psy, return ret; } -static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field) +static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field) { - struct power_supply_desc *psy_desc = NULL; + struct power_supply_desc *psy_desc; struct power_supply_config psy_cfg = { .drv_data = dev, }; unsigned quirks; s32 min, max; + int error; - if (field->usage->hid != HID_DC_BATTERYSTRENGTH) - return false; /* no match */ - - if (dev->battery != NULL) - goto out; /* already initialized? */ + if (dev->battery) + return 0; /* already initialized? */ quirks = find_battery_quirk(dev); @@ -421,16 +452,16 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, dev->bus, dev->vendor, dev->product, dev->version, quirks); if (quirks & HID_BATTERY_QUIRK_IGNORE) - goto out; + return 0; psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL); - if (psy_desc == NULL) - goto out; + if (!psy_desc) + return -ENOMEM; psy_desc->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq); - if (psy_desc->name == NULL) { - kfree(psy_desc); - goto out; + if (!psy_desc->name) { + error = -ENOMEM; + goto err_free_mem; } psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; @@ -457,17 +488,20 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); if (IS_ERR(dev->battery)) { - hid_warn(dev, "can't register power supply: %ld\n", - PTR_ERR(dev->battery)); - kfree(psy_desc->name); - kfree(psy_desc); - dev->battery = NULL; - } else { - power_supply_powers(dev->battery, &dev->dev); + error = PTR_ERR(dev->battery); + hid_warn(dev, "can't register power supply: %d\n", error); + goto err_free_name; } -out: - return true; + power_supply_powers(dev->battery, &dev->dev); + return 0; + +err_free_name: + kfree(psy_desc->name); +err_free_mem: + kfree(psy_desc); + dev->battery = NULL; + return error; } static void hidinput_cleanup_battery(struct hid_device *dev) @@ -483,16 +517,33 @@ static void hidinput_cleanup_battery(struct hid_device *dev) kfree(psy_desc); dev->battery = NULL; } + +static void hidinput_update_battery(struct hid_device *dev, int value) +{ + if (!dev->battery) + return; + + if (value == 0 || value < dev->battery_min || value > dev->battery_max) + return; + + dev->battery_capacity = hidinput_scale_battery_capacity(dev, value); + dev->battery_reported = true; + power_supply_changed(dev->battery); +} #else /* !CONFIG_HID_BATTERY_STRENGTH */ -static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, - struct hid_field *field) +static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, + struct hid_field *field) { - return false; + return 0; } static void hidinput_cleanup_battery(struct hid_device *dev) { } + +static void hidinput_update_battery(struct hid_device *dev, int value) +{ +} #endif /* CONFIG_HID_BATTERY_STRENGTH */ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, @@ -711,6 +762,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } break; + case 0x3b: /* Battery Strength */ + hidinput_setup_battery(device, HID_INPUT_REPORT, field); + usage->type = EV_PWR; + goto ignore; + case 0x3c: /* Invert */ map_key_clear(BTN_TOOL_RUBBER); break; @@ -951,11 +1007,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel break; case HID_UP_GENDEVCTRLS: - if (hidinput_setup_battery(device, HID_INPUT_REPORT, field)) + switch (usage->hid) { + case HID_DC_BATTERYSTRENGTH: + hidinput_setup_battery(device, HID_INPUT_REPORT, field); + usage->type = EV_PWR; goto ignore; - else - goto unknown; - break; + } + goto unknown; case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ set_bit(EV_REP, input->evbit); @@ -1026,9 +1084,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } mapped: - if (device->driver->input_mapped && device->driver->input_mapped(device, - hidinput, field, usage, &bit, &max) < 0) - goto ignore; + if (device->driver->input_mapped && + device->driver->input_mapped(device, hidinput, field, usage, + &bit, &max) < 0) { + /* + * The driver indicated that no further generic handling + * of the usage is desired. + */ + return; + } set_bit(usage->type, input->evbit); @@ -1038,7 +1102,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel if (usage->code > max) goto ignore; - if (usage->type == EV_ABS) { int a = field->logical_minimum; @@ -1087,9 +1150,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel set_bit(MSC_SCAN, input->mscbit); } -ignore: return; +ignore: + usage->type = 0; + usage->code = 0; } void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) @@ -1097,14 +1162,19 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct struct input_dev *input; unsigned *quirks = &hid->quirks; - if (!field->hidinput) + if (!usage->type) return; - input = field->hidinput->input; + if (usage->type == EV_PWR) { + hidinput_update_battery(hid, value); + return; + } - if (!usage->type) + if (!field->hidinput) return; + input = field->hidinput->input; + if (usage->hat_min < usage->hat_max || usage->hat_dir) { int hat_dir = usage->hat_dir; if (!hat_dir) @@ -1381,6 +1451,7 @@ static void report_features(struct hid_device *hid) struct hid_driver *drv = hid->driver; struct hid_report_enum *rep_enum; struct hid_report *rep; + struct hid_usage *usage; int i, j; rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; @@ -1391,12 +1462,15 @@ static void report_features(struct hid_device *hid) continue; for (j = 0; j < rep->field[i]->maxusage; j++) { + usage = &rep->field[i]->usage[j]; + /* Verify if Battery Strength feature is available */ - hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); + if (usage->hid == HID_DC_BATTERYSTRENGTH) + hidinput_setup_battery(hid, HID_FEATURE_REPORT, + rep->field[i]); if (drv->feature_mapping) - drv->feature_mapping(hid, rep->field[i], - rep->field[i]->usage + j); + drv->feature_mapping(hid, rep->field[i], usage); } } } diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c new file mode 100644 index 0000000000000000000000000000000000000000..3695b96694bd4c9510e6e402d67fd9103071a78a --- /dev/null +++ b/drivers/hid/hid-nintendo.c @@ -0,0 +1,820 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * HID driver for Nintendo Switch Joy-Cons and Pro Controllers + * + * Copyright (c) 2019 Daniel J. Ogorchock + * + * The following resources/projects were referenced for this driver: + * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering + * https://gitlab.com/pjranki/joycon-linux-kernel (Peter Rankin) + * https://github.com/FrotBot/SwitchProConLinuxUSB + * https://github.com/MTCKC/ProconXInput + * hid-wiimote kernel hid driver + * hid-logitech-hidpp driver + * + * This driver supports the Nintendo Switch Joy-Cons and Pro Controllers. The + * Pro Controllers can either be used over USB or Bluetooth. + * + * The driver will retrieve the factory calibration info from the controllers, + * so little to no user calibration should be required. + * + */ + +#include "hid-ids.h" +#include +#include +#include +#include +#include +#include + +/* + * Reference the url below for the following HID report defines: + * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering + */ + +/* Output Reports */ +static const u8 JC_OUTPUT_RUMBLE_AND_SUBCMD = 0x01; +static const u8 JC_OUTPUT_FW_UPDATE_PKT = 0x03; +static const u8 JC_OUTPUT_RUMBLE_ONLY = 0x10; +static const u8 JC_OUTPUT_MCU_DATA = 0x11; +static const u8 JC_OUTPUT_USB_CMD = 0x80; + +/* Subcommand IDs */ +static const u8 JC_SUBCMD_STATE /*= 0x00*/; +static const u8 JC_SUBCMD_MANUAL_BT_PAIRING = 0x01; +static const u8 JC_SUBCMD_REQ_DEV_INFO = 0x02; +static const u8 JC_SUBCMD_SET_REPORT_MODE = 0x03; +static const u8 JC_SUBCMD_TRIGGERS_ELAPSED = 0x04; +static const u8 JC_SUBCMD_GET_PAGE_LIST_STATE = 0x05; +static const u8 JC_SUBCMD_SET_HCI_STATE = 0x06; +static const u8 JC_SUBCMD_RESET_PAIRING_INFO = 0x07; +static const u8 JC_SUBCMD_LOW_POWER_MODE = 0x08; +static const u8 JC_SUBCMD_SPI_FLASH_READ = 0x10; +static const u8 JC_SUBCMD_SPI_FLASH_WRITE = 0x11; +static const u8 JC_SUBCMD_RESET_MCU = 0x20; +static const u8 JC_SUBCMD_SET_MCU_CONFIG = 0x21; +static const u8 JC_SUBCMD_SET_MCU_STATE = 0x22; +static const u8 JC_SUBCMD_SET_PLAYER_LIGHTS = 0x30; +static const u8 JC_SUBCMD_GET_PLAYER_LIGHTS = 0x31; +static const u8 JC_SUBCMD_SET_HOME_LIGHT = 0x38; +static const u8 JC_SUBCMD_ENABLE_IMU = 0x40; +static const u8 JC_SUBCMD_SET_IMU_SENSITIVITY = 0x41; +static const u8 JC_SUBCMD_WRITE_IMU_REG = 0x42; +static const u8 JC_SUBCMD_READ_IMU_REG = 0x43; +static const u8 JC_SUBCMD_ENABLE_VIBRATION = 0x48; +static const u8 JC_SUBCMD_GET_REGULATED_VOLTAGE = 0x50; + +/* Input Reports */ +static const u8 JC_INPUT_BUTTON_EVENT = 0x3F; +static const u8 JC_INPUT_SUBCMD_REPLY = 0x21; +static const u8 JC_INPUT_IMU_DATA = 0x30; +static const u8 JC_INPUT_MCU_DATA = 0x31; +static const u8 JC_INPUT_USB_RESPONSE = 0x81; + +/* Feature Reports */ +static const u8 JC_FEATURE_LAST_SUBCMD = 0x02; +static const u8 JC_FEATURE_OTA_FW_UPGRADE = 0x70; +static const u8 JC_FEATURE_SETUP_MEM_READ = 0x71; +static const u8 JC_FEATURE_MEM_READ = 0x72; +static const u8 JC_FEATURE_ERASE_MEM_SECTOR = 0x73; +static const u8 JC_FEATURE_MEM_WRITE = 0x74; +static const u8 JC_FEATURE_LAUNCH = 0x75; + +/* USB Commands */ +static const u8 JC_USB_CMD_CONN_STATUS = 0x01; +static const u8 JC_USB_CMD_HANDSHAKE = 0x02; +static const u8 JC_USB_CMD_BAUDRATE_3M = 0x03; +static const u8 JC_USB_CMD_NO_TIMEOUT = 0x04; +static const u8 JC_USB_CMD_EN_TIMEOUT = 0x05; +static const u8 JC_USB_RESET = 0x06; +static const u8 JC_USB_PRE_HANDSHAKE = 0x91; +static const u8 JC_USB_SEND_UART = 0x92; + +/* SPI storage addresses of factory calibration data */ +static const u16 JC_CAL_DATA_START = 0x603d; +static const u16 JC_CAL_DATA_END = 0x604e; +#define JC_CAL_DATA_SIZE (JC_CAL_DATA_END - JC_CAL_DATA_START + 1) + + +/* The raw analog joystick values will be mapped in terms of this magnitude */ +static const u16 JC_MAX_STICK_MAG = 32767; +static const u16 JC_STICK_FUZZ = 250; +static const u16 JC_STICK_FLAT = 500; + +/* States for controller state machine */ +enum joycon_ctlr_state { + JOYCON_CTLR_STATE_INIT, + JOYCON_CTLR_STATE_READ, +}; + +struct joycon_stick_cal { + s32 max; + s32 min; + s32 center; +}; + +/* + * All the controller's button values are stored in a u32. + * They can be accessed with bitwise ANDs. + */ +static const u32 JC_BTN_Y = BIT(0); +static const u32 JC_BTN_X = BIT(1); +static const u32 JC_BTN_B = BIT(2); +static const u32 JC_BTN_A = BIT(3); +static const u32 JC_BTN_SR_R = BIT(4); +static const u32 JC_BTN_SL_R = BIT(5); +static const u32 JC_BTN_R = BIT(6); +static const u32 JC_BTN_ZR = BIT(7); +static const u32 JC_BTN_MINUS = BIT(8); +static const u32 JC_BTN_PLUS = BIT(9); +static const u32 JC_BTN_RSTICK = BIT(10); +static const u32 JC_BTN_LSTICK = BIT(11); +static const u32 JC_BTN_HOME = BIT(12); +static const u32 JC_BTN_CAP = BIT(13); /* capture button */ +static const u32 JC_BTN_DOWN = BIT(16); +static const u32 JC_BTN_UP = BIT(17); +static const u32 JC_BTN_RIGHT = BIT(18); +static const u32 JC_BTN_LEFT = BIT(19); +static const u32 JC_BTN_SR_L = BIT(20); +static const u32 JC_BTN_SL_L = BIT(21); +static const u32 JC_BTN_L = BIT(22); +static const u32 JC_BTN_ZL = BIT(23); + +enum joycon_msg_type { + JOYCON_MSG_TYPE_NONE, + JOYCON_MSG_TYPE_USB, + JOYCON_MSG_TYPE_SUBCMD, +}; + +struct joycon_subcmd_request { + u8 output_id; /* must be 0x01 for subcommand, 0x10 for rumble only */ + u8 packet_num; /* incremented every send */ + u8 rumble_data[8]; + u8 subcmd_id; + u8 data[0]; /* length depends on the subcommand */ +} __packed; + +struct joycon_subcmd_reply { + u8 ack; /* MSB 1 for ACK, 0 for NACK */ + u8 id; /* id of requested subcmd */ + u8 data[0]; /* will be at most 35 bytes */ +} __packed; + +struct joycon_input_report { + u8 id; + u8 timer; + u8 bat_con; /* battery and connection info */ + u8 button_status[3]; + u8 left_stick[3]; + u8 right_stick[3]; + u8 vibrator_report; + + /* + * If support for firmware updates, gyroscope data, and/or NFC/IR + * are added in the future, this can be swapped for a union. + */ + struct joycon_subcmd_reply reply; +} __packed; + +#define JC_MAX_RESP_SIZE (sizeof(struct joycon_input_report) + 35) + +/* Each physical controller is associated with a joycon_ctlr struct */ +struct joycon_ctlr { + struct hid_device *hdev; + struct input_dev *input; + enum joycon_ctlr_state ctlr_state; + + /* The following members are used for synchronous sends/receives */ + enum joycon_msg_type msg_type; + u8 subcmd_num; + struct mutex output_mutex; + u8 input_buf[JC_MAX_RESP_SIZE]; + wait_queue_head_t wait; + bool received_resp; + u8 usb_ack_match; + u8 subcmd_ack_match; + + /* factory calibration data */ + struct joycon_stick_cal left_stick_cal_x; + struct joycon_stick_cal left_stick_cal_y; + struct joycon_stick_cal right_stick_cal_x; + struct joycon_stick_cal right_stick_cal_y; + +}; + +static int __joycon_hid_send(struct hid_device *hdev, u8 *data, size_t len) +{ + u8 *buf; + int ret; + + buf = kmemdup(data, len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + ret = hid_hw_output_report(hdev, buf, len); + kfree(buf); + if (ret < 0) + hid_dbg(hdev, "Failed to send output report ret=%d\n", ret); + return ret; +} + +static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len) +{ + int ret; + + ret = __joycon_hid_send(ctlr->hdev, data, len); + if (ret < 0) { + memset(ctlr->input_buf, 0, JC_MAX_RESP_SIZE); + return ret; + } + + if (!wait_event_timeout(ctlr->wait, ctlr->received_resp, HZ)) { + hid_dbg(ctlr->hdev, "synchronous send/receive timed out\n"); + memset(ctlr->input_buf, 0, JC_MAX_RESP_SIZE); + return -ETIMEDOUT; + } + + ctlr->received_resp = false; + return 0; +} + +static int joycon_send_usb(struct joycon_ctlr *ctlr, u8 cmd) +{ + int ret; + u8 buf[2] = {JC_OUTPUT_USB_CMD}; + + buf[1] = cmd; + ctlr->usb_ack_match = cmd; + ctlr->msg_type = JOYCON_MSG_TYPE_USB; + ret = joycon_hid_send_sync(ctlr, buf, sizeof(buf)); + if (ret) + hid_dbg(ctlr->hdev, "send usb command failed; ret=%d\n", ret); + return ret; +} + +static int joycon_send_subcmd(struct joycon_ctlr *ctlr, + struct joycon_subcmd_request *subcmd, + size_t data_len) +{ + int ret; + + subcmd->output_id = JC_OUTPUT_RUMBLE_AND_SUBCMD; + subcmd->packet_num = ctlr->subcmd_num; + if (++ctlr->subcmd_num > 0xF) + ctlr->subcmd_num = 0; + ctlr->subcmd_ack_match = subcmd->subcmd_id; + ctlr->msg_type = JOYCON_MSG_TYPE_SUBCMD; + + ret = joycon_hid_send_sync(ctlr, (u8 *)subcmd, + sizeof(*subcmd) + data_len); + if (ret < 0) + hid_dbg(ctlr->hdev, "send subcommand failed; ret=%d\n", ret); + else + ret = 0; + return ret; +} + +/* Supply nibbles for flash and on. Ones correspond to active */ +static int joycon_set_player_leds(struct joycon_ctlr *ctlr, u8 flash, u8 on) +{ + struct joycon_subcmd_request *req; + u8 buffer[sizeof(*req) + 1] = { 0 }; + + req = (struct joycon_subcmd_request *)buffer; + req->subcmd_id = JC_SUBCMD_SET_PLAYER_LIGHTS; + req->data[0] = (flash << 4) | on; + + hid_dbg(ctlr->hdev, "setting player leds\n"); + return joycon_send_subcmd(ctlr, req, 1); +} + +static const u16 DFLT_STICK_CAL_CEN = 2000; +static const u16 DFLT_STICK_CAL_MAX = 3500; +static const u16 DFLT_STICK_CAL_MIN = 500; +static int joycon_request_calibration(struct joycon_ctlr *ctlr) +{ + struct joycon_subcmd_request *req; + u8 buffer[sizeof(*req) + 5] = { 0 }; + struct joycon_input_report *report; + struct joycon_stick_cal *cal_x; + struct joycon_stick_cal *cal_y; + s32 x_max_above; + s32 x_min_below; + s32 y_max_above; + s32 y_min_below; + u8 *data; + u8 *raw_cal; + int ret; + + req = (struct joycon_subcmd_request *)buffer; + req->subcmd_id = JC_SUBCMD_SPI_FLASH_READ; + data = req->data; + data[0] = 0xFF & JC_CAL_DATA_START; + data[1] = 0xFF & (JC_CAL_DATA_START >> 8); + data[2] = 0xFF & (JC_CAL_DATA_START >> 16); + data[3] = 0xFF & (JC_CAL_DATA_START >> 24); + data[4] = JC_CAL_DATA_SIZE; + + hid_dbg(ctlr->hdev, "requesting cal data\n"); + ret = joycon_send_subcmd(ctlr, req, 5); + if (ret) { + hid_warn(ctlr->hdev, + "Failed to read stick cal, using defaults; ret=%d\n", + ret); + + ctlr->left_stick_cal_x.center = DFLT_STICK_CAL_CEN; + ctlr->left_stick_cal_x.max = DFLT_STICK_CAL_MAX; + ctlr->left_stick_cal_x.min = DFLT_STICK_CAL_MIN; + + ctlr->left_stick_cal_y.center = DFLT_STICK_CAL_CEN; + ctlr->left_stick_cal_y.max = DFLT_STICK_CAL_MAX; + ctlr->left_stick_cal_y.min = DFLT_STICK_CAL_MIN; + + ctlr->right_stick_cal_x.center = DFLT_STICK_CAL_CEN; + ctlr->right_stick_cal_x.max = DFLT_STICK_CAL_MAX; + ctlr->right_stick_cal_x.min = DFLT_STICK_CAL_MIN; + + ctlr->right_stick_cal_y.center = DFLT_STICK_CAL_CEN; + ctlr->right_stick_cal_y.max = DFLT_STICK_CAL_MAX; + ctlr->right_stick_cal_y.min = DFLT_STICK_CAL_MIN; + + return ret; + } + + report = (struct joycon_input_report *)ctlr->input_buf; + raw_cal = &report->reply.data[5]; + + /* left stick calibration parsing */ + cal_x = &ctlr->left_stick_cal_x; + cal_y = &ctlr->left_stick_cal_y; + + x_max_above = hid_field_extract(ctlr->hdev, (raw_cal + 0), 0, 12); + y_max_above = hid_field_extract(ctlr->hdev, (raw_cal + 1), 4, 12); + cal_x->center = hid_field_extract(ctlr->hdev, (raw_cal + 3), 0, 12); + cal_y->center = hid_field_extract(ctlr->hdev, (raw_cal + 4), 4, 12); + x_min_below = hid_field_extract(ctlr->hdev, (raw_cal + 6), 0, 12); + y_min_below = hid_field_extract(ctlr->hdev, (raw_cal + 7), 4, 12); + cal_x->max = cal_x->center + x_max_above; + cal_x->min = cal_x->center - x_min_below; + cal_y->max = cal_y->center + y_max_above; + cal_y->min = cal_y->center - y_min_below; + + /* right stick calibration parsing */ + raw_cal += 9; + cal_x = &ctlr->right_stick_cal_x; + cal_y = &ctlr->right_stick_cal_y; + + cal_x->center = hid_field_extract(ctlr->hdev, (raw_cal + 0), 0, 12); + cal_y->center = hid_field_extract(ctlr->hdev, (raw_cal + 1), 4, 12); + x_min_below = hid_field_extract(ctlr->hdev, (raw_cal + 3), 0, 12); + y_min_below = hid_field_extract(ctlr->hdev, (raw_cal + 4), 4, 12); + x_max_above = hid_field_extract(ctlr->hdev, (raw_cal + 6), 0, 12); + y_max_above = hid_field_extract(ctlr->hdev, (raw_cal + 7), 4, 12); + cal_x->max = cal_x->center + x_max_above; + cal_x->min = cal_x->center - x_min_below; + cal_y->max = cal_y->center + y_max_above; + cal_y->min = cal_y->center - y_min_below; + + hid_dbg(ctlr->hdev, "calibration:\n" + "l_x_c=%d l_x_max=%d l_x_min=%d\n" + "l_y_c=%d l_y_max=%d l_y_min=%d\n" + "r_x_c=%d r_x_max=%d r_x_min=%d\n" + "r_y_c=%d r_y_max=%d r_y_min=%d\n", + ctlr->left_stick_cal_x.center, + ctlr->left_stick_cal_x.max, + ctlr->left_stick_cal_x.min, + ctlr->left_stick_cal_y.center, + ctlr->left_stick_cal_y.max, + ctlr->left_stick_cal_y.min, + ctlr->right_stick_cal_x.center, + ctlr->right_stick_cal_x.max, + ctlr->right_stick_cal_x.min, + ctlr->right_stick_cal_y.center, + ctlr->right_stick_cal_y.max, + ctlr->right_stick_cal_y.min); + + return 0; +} + +static int joycon_set_report_mode(struct joycon_ctlr *ctlr) +{ + struct joycon_subcmd_request *req; + u8 buffer[sizeof(*req) + 1] = { 0 }; + + req = (struct joycon_subcmd_request *)buffer; + req->subcmd_id = JC_SUBCMD_SET_REPORT_MODE; + req->data[0] = 0x30; /* standard, full report mode */ + + hid_dbg(ctlr->hdev, "setting controller report mode\n"); + return joycon_send_subcmd(ctlr, req, 1); +} + +static s32 joycon_map_stick_val(struct joycon_stick_cal *cal, s32 val) +{ + s32 center = cal->center; + s32 min = cal->min; + s32 max = cal->max; + s32 new_val; + + if (val > center) { + new_val = (val - center) * JC_MAX_STICK_MAG; + new_val /= (max - center); + } else { + new_val = (center - val) * -JC_MAX_STICK_MAG; + new_val /= (center - min); + } + new_val = clamp(new_val, (s32)-JC_MAX_STICK_MAG, (s32)JC_MAX_STICK_MAG); + return new_val; +} + +static void joycon_parse_report(struct joycon_ctlr *ctlr, + struct joycon_input_report *rep) +{ + struct input_dev *dev = ctlr->input; + u32 btns; + u32 id = ctlr->hdev->product; + + btns = hid_field_extract(ctlr->hdev, rep->button_status, 0, 24); + + if (id != USB_DEVICE_ID_NINTENDO_JOYCONR) { + u16 raw_x; + u16 raw_y; + s32 x; + s32 y; + + /* get raw stick values */ + raw_x = hid_field_extract(ctlr->hdev, rep->left_stick, 0, 12); + raw_y = hid_field_extract(ctlr->hdev, + rep->left_stick + 1, 4, 12); + /* map the stick values */ + x = joycon_map_stick_val(&ctlr->left_stick_cal_x, raw_x); + y = -joycon_map_stick_val(&ctlr->left_stick_cal_y, raw_y); + /* report sticks */ + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + + /* report buttons */ + input_report_key(dev, BTN_TL, btns & JC_BTN_L); + input_report_key(dev, BTN_TL2, btns & JC_BTN_ZL); + if (id != USB_DEVICE_ID_NINTENDO_PROCON) { + /* Report the S buttons as the non-existent triggers */ + input_report_key(dev, BTN_TR, btns & JC_BTN_SL_L); + input_report_key(dev, BTN_TR2, btns & JC_BTN_SR_L); + } + input_report_key(dev, BTN_SELECT, btns & JC_BTN_MINUS); + input_report_key(dev, BTN_THUMBL, btns & JC_BTN_LSTICK); + input_report_key(dev, BTN_Z, btns & JC_BTN_CAP); + input_report_key(dev, BTN_DPAD_DOWN, btns & JC_BTN_DOWN); + input_report_key(dev, BTN_DPAD_UP, btns & JC_BTN_UP); + input_report_key(dev, BTN_DPAD_RIGHT, btns & JC_BTN_RIGHT); + input_report_key(dev, BTN_DPAD_LEFT, btns & JC_BTN_LEFT); + } + if (id != USB_DEVICE_ID_NINTENDO_JOYCONL) { + u16 raw_x; + u16 raw_y; + s32 x; + s32 y; + + /* get raw stick values */ + raw_x = hid_field_extract(ctlr->hdev, rep->right_stick, 0, 12); + raw_y = hid_field_extract(ctlr->hdev, + rep->right_stick + 1, 4, 12); + /* map stick values */ + x = joycon_map_stick_val(&ctlr->right_stick_cal_x, raw_x); + y = -joycon_map_stick_val(&ctlr->right_stick_cal_y, raw_y); + /* report sticks */ + input_report_abs(dev, ABS_RX, x); + input_report_abs(dev, ABS_RY, y); + + /* report buttons */ + input_report_key(dev, BTN_TR, btns & JC_BTN_R); + input_report_key(dev, BTN_TR2, btns & JC_BTN_ZR); + if (id != USB_DEVICE_ID_NINTENDO_PROCON) { + /* Report the S buttons as the non-existent triggers */ + input_report_key(dev, BTN_TL, btns & JC_BTN_SL_R); + input_report_key(dev, BTN_TL2, btns & JC_BTN_SR_R); + } + input_report_key(dev, BTN_START, btns & JC_BTN_PLUS); + input_report_key(dev, BTN_THUMBR, btns & JC_BTN_RSTICK); + input_report_key(dev, BTN_MODE, btns & JC_BTN_HOME); + input_report_key(dev, BTN_WEST, btns & JC_BTN_Y); + input_report_key(dev, BTN_NORTH, btns & JC_BTN_X); + input_report_key(dev, BTN_EAST, btns & JC_BTN_A); + input_report_key(dev, BTN_SOUTH, btns & JC_BTN_B); + } + + input_sync(dev); +} + + +static const unsigned int joycon_button_inputs_l[] = { + BTN_SELECT, BTN_Z, BTN_THUMBL, + BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT, + BTN_TL, BTN_TL2, + 0 /* 0 signals end of array */ +}; + +static const unsigned int joycon_button_inputs_r[] = { + BTN_START, BTN_MODE, BTN_THUMBR, + BTN_SOUTH, BTN_EAST, BTN_NORTH, BTN_WEST, + BTN_TR, BTN_TR2, + 0 /* 0 signals end of array */ +}; + +static DEFINE_MUTEX(joycon_input_num_mutex); +static int joycon_input_create(struct joycon_ctlr *ctlr) +{ + struct hid_device *hdev; + static int input_num = 1; + const char *name; + int ret; + int i; + + hdev = ctlr->hdev; + + switch (hdev->product) { + case USB_DEVICE_ID_NINTENDO_PROCON: + name = "Nintendo Switch Pro Controller"; + break; + case USB_DEVICE_ID_NINTENDO_JOYCONL: + name = "Nintendo Switch Left Joy-Con"; + break; + case USB_DEVICE_ID_NINTENDO_JOYCONR: + name = "Nintendo Switch Right Joy-Con"; + break; + default: /* Should be impossible */ + hid_err(hdev, "Invalid hid product\n"); + return -EINVAL; + } + + ctlr->input = devm_input_allocate_device(&hdev->dev); + if (!ctlr->input) + return -ENOMEM; + ctlr->input->id.bustype = hdev->bus; + ctlr->input->id.vendor = hdev->vendor; + ctlr->input->id.product = hdev->product; + ctlr->input->id.version = hdev->version; + ctlr->input->name = name; + input_set_drvdata(ctlr->input, ctlr); + + + /* set up sticks */ + if (hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONR) { + input_set_abs_params(ctlr->input, ABS_X, + -JC_MAX_STICK_MAG, JC_MAX_STICK_MAG, + JC_STICK_FUZZ, JC_STICK_FLAT); + input_set_abs_params(ctlr->input, ABS_Y, + -JC_MAX_STICK_MAG, JC_MAX_STICK_MAG, + JC_STICK_FUZZ, JC_STICK_FLAT); + } + if (hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONL) { + input_set_abs_params(ctlr->input, ABS_RX, + -JC_MAX_STICK_MAG, JC_MAX_STICK_MAG, + JC_STICK_FUZZ, JC_STICK_FLAT); + input_set_abs_params(ctlr->input, ABS_RY, + -JC_MAX_STICK_MAG, JC_MAX_STICK_MAG, + JC_STICK_FUZZ, JC_STICK_FLAT); + } + + /* set up buttons */ + if (hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONR) { + for (i = 0; joycon_button_inputs_l[i] > 0; i++) + input_set_capability(ctlr->input, EV_KEY, + joycon_button_inputs_l[i]); + } + if (hdev->product != USB_DEVICE_ID_NINTENDO_JOYCONL) { + for (i = 0; joycon_button_inputs_r[i] > 0; i++) + input_set_capability(ctlr->input, EV_KEY, + joycon_button_inputs_r[i]); + } + + ret = input_register_device(ctlr->input); + if (ret) + return ret; + + /* Set the default controller player leds based on controller number */ + mutex_lock(&joycon_input_num_mutex); + mutex_lock(&ctlr->output_mutex); + ret = joycon_set_player_leds(ctlr, 0, 0xF >> (4 - input_num)); + if (ret) + hid_warn(ctlr->hdev, "Failed to set leds; ret=%d\n", ret); + mutex_unlock(&ctlr->output_mutex); + if (++input_num > 4) + input_num = 1; + mutex_unlock(&joycon_input_num_mutex); + + return 0; +} + +/* Common handler for parsing inputs */ +static int joycon_ctlr_read_handler(struct joycon_ctlr *ctlr, u8 *data, + int size) +{ + int ret = 0; + + if (data[0] == JC_INPUT_SUBCMD_REPLY || data[0] == JC_INPUT_IMU_DATA || + data[0] == JC_INPUT_MCU_DATA) { + if (size >= 12) /* make sure it contains the input report */ + joycon_parse_report(ctlr, + (struct joycon_input_report *)data); + } + + return ret; +} + +static int joycon_ctlr_handle_event(struct joycon_ctlr *ctlr, u8 *data, + int size) +{ + int ret = 0; + bool match = false; + struct joycon_input_report *report; + + if (unlikely(mutex_is_locked(&ctlr->output_mutex)) && + ctlr->msg_type != JOYCON_MSG_TYPE_NONE) { + switch (ctlr->msg_type) { + case JOYCON_MSG_TYPE_USB: + if (size < 2) + break; + if (data[0] == JC_INPUT_USB_RESPONSE && + data[1] == ctlr->usb_ack_match) + match = true; + break; + case JOYCON_MSG_TYPE_SUBCMD: + if (size < sizeof(struct joycon_input_report) || + data[0] != JC_INPUT_SUBCMD_REPLY) + break; + report = (struct joycon_input_report *)data; + if (report->reply.id == ctlr->subcmd_ack_match) + match = true; + break; + default: + break; + } + + if (match) { + memcpy(ctlr->input_buf, data, + min(size, (int)JC_MAX_RESP_SIZE)); + ctlr->msg_type = JOYCON_MSG_TYPE_NONE; + ctlr->received_resp = true; + wake_up(&ctlr->wait); + + /* This message has been handled */ + return 1; + } + } + + if (ctlr->ctlr_state == JOYCON_CTLR_STATE_READ) + ret = joycon_ctlr_read_handler(ctlr, data, size); + + return ret; +} + +static int nintendo_hid_event(struct hid_device *hdev, + struct hid_report *report, u8 *raw_data, int size) +{ + struct joycon_ctlr *ctlr = hid_get_drvdata(hdev); + + if (size < 1) + return -EINVAL; + + return joycon_ctlr_handle_event(ctlr, raw_data, size); +} + +static int nintendo_hid_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int ret; + struct joycon_ctlr *ctlr; + + hid_dbg(hdev, "probe - start\n"); + + ctlr = devm_kzalloc(&hdev->dev, sizeof(*ctlr), GFP_KERNEL); + if (!ctlr) { + ret = -ENOMEM; + goto err; + } + + ctlr->hdev = hdev; + ctlr->ctlr_state = JOYCON_CTLR_STATE_INIT; + hid_set_drvdata(hdev, ctlr); + mutex_init(&ctlr->output_mutex); + init_waitqueue_head(&ctlr->wait); + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "HID parse failed\n"); + goto err; + } + + ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); + if (ret) { + hid_err(hdev, "HW start failed\n"); + goto err; + } + + ret = hid_hw_open(hdev); + if (ret) { + hid_err(hdev, "cannot start hardware I/O\n"); + goto err_stop; + } + + hid_device_io_start(hdev); + + /* Initialize the controller */ + mutex_lock(&ctlr->output_mutex); + /* if handshake command fails, assume ble pro controller */ + if (hdev->product == USB_DEVICE_ID_NINTENDO_PROCON && + !joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE)) { + hid_dbg(hdev, "detected USB controller\n"); + /* set baudrate for improved latency */ + ret = joycon_send_usb(ctlr, JC_USB_CMD_BAUDRATE_3M); + if (ret) { + hid_err(hdev, "Failed to set baudrate; ret=%d\n", ret); + goto err_mutex; + } + /* handshake */ + ret = joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE); + if (ret) { + hid_err(hdev, "Failed handshake; ret=%d\n", ret); + goto err_mutex; + } + /* + * Set no timeout (to keep controller in USB mode). + * This doesn't send a response, so ignore the timeout. + */ + joycon_send_usb(ctlr, JC_USB_CMD_NO_TIMEOUT); + } + + /* get controller calibration data, and parse it */ + ret = joycon_request_calibration(ctlr); + if (ret) { + /* + * We can function with default calibration, but it may be + * inaccurate. Provide a warning, and continue on. + */ + hid_warn(hdev, "Analog stick positions may be inaccurate\n"); + } + + /* Set the reporting mode to 0x30, which is the full report mode */ + ret = joycon_set_report_mode(ctlr); + if (ret) { + hid_err(hdev, "Failed to set report mode; ret=%d\n", ret); + goto err_mutex; + } + + mutex_unlock(&ctlr->output_mutex); + + ret = joycon_input_create(ctlr); + if (ret) { + hid_err(hdev, "Failed to create input device; ret=%d\n", ret); + goto err_close; + } + + ctlr->ctlr_state = JOYCON_CTLR_STATE_READ; + + hid_dbg(hdev, "probe - success\n"); + return 0; + +err_mutex: + mutex_unlock(&ctlr->output_mutex); +err_close: + hid_hw_close(hdev); +err_stop: + hid_hw_stop(hdev); +err: + hid_err(hdev, "probe - fail = %d\n", ret); + return ret; +} + +static void nintendo_hid_remove(struct hid_device *hdev) +{ + hid_dbg(hdev, "remove\n"); + hid_hw_close(hdev); + hid_hw_stop(hdev); +} + +static const struct hid_device_id nintendo_hid_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_PROCON) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_PROCON) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_JOYCONL) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_JOYCONR) }, + { } +}; +MODULE_DEVICE_TABLE(hid, nintendo_hid_devices); + +static struct hid_driver nintendo_hid_driver = { + .name = "nintendo", + .id_table = nintendo_hid_devices, + .probe = nintendo_hid_probe, + .remove = nintendo_hid_remove, + .raw_event = nintendo_hid_event, +}; +module_hid_driver(nintendo_hid_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Daniel J. Ogorchock "); +MODULE_DESCRIPTION("Driver for Nintendo Switch Controllers"); diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 750c168971302863e532cd2eca5f8e3d06c71e7d..ed6591f92f712211f80b09f51ad9c5ba15b3157a 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -257,13 +257,14 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t static unsigned int hidraw_poll(struct file *file, poll_table *wait) { struct hidraw_list *list = file->private_data; + unsigned int mask = POLLOUT | POLLWRNORM; /* hidraw is always writable */ poll_wait(file, &list->hidraw->wait, wait); if (list->head != list->tail) - return POLLIN | POLLRDNORM; + mask |= POLLIN | POLLRDNORM; if (!list->hidraw->exist) - return POLLERR | POLLHUP; - return 0; + mask |= POLLERR | POLLHUP; + return mask; } static int hidraw_open(struct inode *inode, struct file *file) diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c index 10af8585c820d253b71301f23efae5db3b40fc14..95052373a828240809c25581b944f1feb2587944 100644 --- a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c @@ -341,6 +341,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { }, .driver_data = (void *)&sipodev_desc }, + { + .ident = "Trekstor SURFBOOK E11B", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"), + }, + .driver_data = (void *)&sipodev_desc + }, { .ident = "Direkt-Tek DTLAPY116-2", .matches = { diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index fbd952ab806fa25e4a6483de754eb7b962005921..7a136847c8b267dee66efd1015c2116516febe65 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -26,6 +26,7 @@ #include #include #include +#include #define UHID_NAME "uhid" #define UHID_BUFSIZE 32 @@ -770,13 +771,14 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer, static unsigned int uhid_char_poll(struct file *file, poll_table *wait) { struct uhid_device *uhid = file->private_data; + unsigned int mask = POLLOUT | POLLWRNORM; /* uhid is always writable */ poll_wait(file, &uhid->waitq, wait); if (uhid->head != uhid->tail) - return POLLIN | POLLRDNORM; + mask |= POLLIN | POLLRDNORM; - return 0; + return mask; } static const struct file_operations uhid_fops = { diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 8903ea09ac587865748ca2fb2a0c3441f0b9245a..dbdd265075daf264b7fbb8b316174b97daa829b3 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -962,9 +962,9 @@ void hiddev_disconnect(struct hid_device *hid) hiddev->exist = 0; if (hiddev->open) { - mutex_unlock(&hiddev->existancelock); usbhid_close(hiddev->hid); wake_up_interruptible(&hiddev->wait); + mutex_unlock(&hiddev->existancelock); } else { mutex_unlock(&hiddev->existancelock); kfree(hiddev); diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 5929e126da6332b2951bd55d9b72b7fdbd5d3246..d9923d63eb4f2b5f01d42170f7bf416b0c93c55e 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -426,7 +426,7 @@ static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) return 0x95; break; } - return -ENODEV; + return 0; } /* Provide labels for sysfs */ diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 9c262d95533150f6fd23fae6d9aeef9126ce607a..d2583caa8087c6932813617322ea321726cd2baf 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -268,9 +268,10 @@ static inline u16 volt2reg(int channel, long volt, u8 bypass_attn) long reg; if (bypass_attn & (1 << channel)) - reg = (volt * 1024) / 2250; + reg = DIV_ROUND_CLOSEST(volt * 1024, 2250); else - reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250); + reg = DIV_ROUND_CLOSEST(volt * r[1] * 1024, + (r[0] + r[1]) * 2250); return clamp_val(reg, 0, 1023) & (0xff << 2); } diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index a74c075a30ec49608308ddd45715f1addc104c84..e0a1a118514f92ec3df98c03fba2861307a33bd7 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -38,16 +38,20 @@ struct hwmon_device { #define to_hwmon_device(d) container_of(d, struct hwmon_device, dev) +#define MAX_SYSFS_ATTR_NAME_LENGTH 32 + struct hwmon_device_attribute { struct device_attribute dev_attr; const struct hwmon_ops *ops; enum hwmon_sensor_types type; u32 attr; int index; + char name[MAX_SYSFS_ATTR_NAME_LENGTH]; }; #define to_hwmon_attr(d) \ container_of(d, struct hwmon_device_attribute, dev_attr) +#define to_dev_attr(a) container_of(a, struct device_attribute, attr) /* * Thermal zone information @@ -55,7 +59,7 @@ struct hwmon_device_attribute { * also provides the sensor index. */ struct hwmon_thermal_data { - struct hwmon_device *hwdev; /* Reference to hwmon device */ + struct device *dev; /* Reference to hwmon device */ int index; /* sensor index */ }; @@ -92,9 +96,27 @@ static const struct attribute_group *hwmon_dev_attr_groups[] = { NULL }; +static void hwmon_free_attrs(struct attribute **attrs) +{ + int i; + + for (i = 0; attrs[i]; i++) { + struct device_attribute *dattr = to_dev_attr(attrs[i]); + struct hwmon_device_attribute *hattr = to_hwmon_attr(dattr); + + kfree(hattr); + } + kfree(attrs); +} + static void hwmon_dev_release(struct device *dev) { - kfree(to_hwmon_device(dev)); + struct hwmon_device *hwdev = to_hwmon_device(dev); + + if (hwdev->group.attrs) + hwmon_free_attrs(hwdev->group.attrs); + kfree(hwdev->groups); + kfree(hwdev); } static struct class hwmon_class = { @@ -118,11 +140,11 @@ static DEFINE_IDA(hwmon_ida); static int hwmon_thermal_get_temp(void *data, int *temp) { struct hwmon_thermal_data *tdata = data; - struct hwmon_device *hwdev = tdata->hwdev; + struct hwmon_device *hwdev = to_hwmon_device(tdata->dev); int ret; long t; - ret = hwdev->chip->ops->read(&hwdev->dev, hwmon_temp, hwmon_temp_input, + ret = hwdev->chip->ops->read(tdata->dev, hwmon_temp, hwmon_temp_input, tdata->index, &t); if (ret < 0) return ret; @@ -136,26 +158,31 @@ static struct thermal_zone_of_device_ops hwmon_thermal_ops = { .get_temp = hwmon_thermal_get_temp, }; -static int hwmon_thermal_add_sensor(struct device *dev, - struct hwmon_device *hwdev, int index) +static int hwmon_thermal_add_sensor(struct device *dev, int index) { struct hwmon_thermal_data *tdata; + struct thermal_zone_device *tzd; tdata = devm_kzalloc(dev, sizeof(*tdata), GFP_KERNEL); if (!tdata) return -ENOMEM; - tdata->hwdev = hwdev; + tdata->dev = dev; tdata->index = index; - devm_thermal_zone_of_sensor_register(&hwdev->dev, index, tdata, - &hwmon_thermal_ops); + tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata, + &hwmon_thermal_ops); + /* + * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV, + * so ignore that error but forward any other error. + */ + if (IS_ERR(tzd) && (PTR_ERR(tzd) != -ENODEV)) + return PTR_ERR(tzd); return 0; } #else -static int hwmon_thermal_add_sensor(struct device *dev, - struct hwmon_device *hwdev, int index) +static int hwmon_thermal_add_sensor(struct device *dev, int index) { return 0; } @@ -205,8 +232,7 @@ static int hwmon_attr_base(enum hwmon_sensor_types type) return 1; } -static struct attribute *hwmon_genattr(struct device *dev, - const void *drvdata, +static struct attribute *hwmon_genattr(const void *drvdata, enum hwmon_sensor_types type, u32 attr, int index, @@ -232,20 +258,18 @@ static struct attribute *hwmon_genattr(struct device *dev, if ((mode & S_IWUGO) && !ops->write) return ERR_PTR(-EINVAL); + hattr = kzalloc(sizeof(*hattr), GFP_KERNEL); + if (!hattr) + return ERR_PTR(-ENOMEM); + if (type == hwmon_chip) { name = (char *)template; } else { - name = devm_kzalloc(dev, strlen(template) + 16, GFP_KERNEL); - if (!name) - return ERR_PTR(-ENOMEM); - scnprintf(name, strlen(template) + 16, template, + scnprintf(hattr->name, sizeof(hattr->name), template, index + hwmon_attr_base(type)); + name = hattr->name; } - hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL); - if (!hattr) - return ERR_PTR(-ENOMEM); - hattr->type = type; hattr->attr = attr; hattr->index = index; @@ -433,8 +457,7 @@ static int hwmon_num_channel_attrs(const struct hwmon_channel_info *info) return n; } -static int hwmon_genattrs(struct device *dev, - const void *drvdata, +static int hwmon_genattrs(const void *drvdata, struct attribute **attrs, const struct hwmon_ops *ops, const struct hwmon_channel_info *info) @@ -460,7 +483,7 @@ static int hwmon_genattrs(struct device *dev, attr_mask &= ~BIT(attr); if (attr >= template_size) return -EINVAL; - a = hwmon_genattr(dev, drvdata, info->type, attr, i, + a = hwmon_genattr(drvdata, info->type, attr, i, templates[attr], ops); if (IS_ERR(a)) { if (PTR_ERR(a) != -ENOENT) @@ -474,8 +497,7 @@ static int hwmon_genattrs(struct device *dev, } static struct attribute ** -__hwmon_create_attrs(struct device *dev, const void *drvdata, - const struct hwmon_chip_info *chip) +__hwmon_create_attrs(const void *drvdata, const struct hwmon_chip_info *chip) { int ret, i, aindex = 0, nattrs = 0; struct attribute **attrs; @@ -486,15 +508,17 @@ __hwmon_create_attrs(struct device *dev, const void *drvdata, if (nattrs == 0) return ERR_PTR(-EINVAL); - attrs = devm_kcalloc(dev, nattrs + 1, sizeof(*attrs), GFP_KERNEL); + attrs = kcalloc(nattrs + 1, sizeof(*attrs), GFP_KERNEL); if (!attrs) return ERR_PTR(-ENOMEM); for (i = 0; chip->info[i]; i++) { - ret = hwmon_genattrs(dev, drvdata, &attrs[aindex], chip->ops, + ret = hwmon_genattrs(drvdata, &attrs[aindex], chip->ops, chip->info[i]); - if (ret < 0) + if (ret < 0) { + hwmon_free_attrs(attrs); return ERR_PTR(ret); + } aindex += ret; } @@ -534,14 +558,13 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, for (i = 0; groups[i]; i++) ngroups++; - hwdev->groups = devm_kcalloc(dev, ngroups, sizeof(*groups), - GFP_KERNEL); + hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL); if (!hwdev->groups) { err = -ENOMEM; goto free_hwmon; } - attrs = __hwmon_create_attrs(dev, drvdata, chip); + attrs = __hwmon_create_attrs(drvdata, chip); if (IS_ERR(attrs)) { err = PTR_ERR(attrs); goto free_hwmon; @@ -585,8 +608,13 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, if (!chip->ops->is_visible(drvdata, hwmon_temp, hwmon_temp_input, j)) continue; - if (info[i]->config[j] & HWMON_T_INPUT) - hwmon_thermal_add_sensor(dev, hwdev, j); + if (info[i]->config[j] & HWMON_T_INPUT) { + err = hwmon_thermal_add_sensor(hdev, j); + if (err) { + device_unregister(hdev); + goto ida_remove; + } + } } } } @@ -594,7 +622,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, return hdev; free_hwmon: - kfree(hwdev); + hwmon_dev_release(hdev); ida_remove: ida_simple_remove(&hwmon_ida, id); return ERR_PTR(err); diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index eff3b24d847370eeca210ee4b83f129cac241dd0..fc31669a86ba807665ffba97df3987da7fa1c606 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -164,7 +164,7 @@ static int lm75_write(struct device *dev, enum hwmon_sensor_types type, temp = DIV_ROUND_CLOSEST(temp << (resolution - 8), 1000) << (16 - resolution); - return regmap_write(data->regmap, reg, temp); + return regmap_write(data->regmap, reg, (u16)temp); } static umode_t lm75_is_visible(const void *data, enum hwmon_sensor_types type, diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index 7f8738a83cb9a2acafe2a56f3940c1ba281c4225..40addb213bdf48877414e7286738a05335d11c70 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -32,8 +32,8 @@ static const u8 REG_VOLTAGE[5] = { 0x09, 0x0a, 0x0c, 0x0d, 0x0e }; static const u8 REG_VOLTAGE_LIMIT_LSB[2][5] = { - { 0x40, 0x00, 0x42, 0x44, 0x46 }, - { 0x3f, 0x00, 0x41, 0x43, 0x45 }, + { 0x46, 0x00, 0x40, 0x42, 0x44 }, + { 0x45, 0x00, 0x3f, 0x41, 0x43 }, }; static const u8 REG_VOLTAGE_LIMIT_MSB[5] = { 0x48, 0x00, 0x47, 0x47, 0x48 }; diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c index 58b789c28b483f062b17822a32487be6bdba14ee..94eea2ac62519625024a5bb0f4340304f65fc8c9 100644 --- a/drivers/hwmon/pmbus/ltc2978.c +++ b/drivers/hwmon/pmbus/ltc2978.c @@ -89,8 +89,8 @@ enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882, #define LTC_POLL_TIMEOUT 100 /* in milli-seconds */ -#define LTC_NOT_BUSY BIT(5) -#define LTC_NOT_PENDING BIT(4) +#define LTC_NOT_BUSY BIT(6) +#define LTC_NOT_PENDING BIT(5) /* * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c index decd7df995abfa2b40381b7b1be251051b6023e5..2a18539591eaffec4f6e2c70e0a0a313ca77ad4f 100644 --- a/drivers/hwmon/shtc1.c +++ b/drivers/hwmon/shtc1.c @@ -38,7 +38,7 @@ static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 }; /* constants for reading the ID register */ #define SHTC1_ID 0x07 -#define SHTC1_ID_REG_MASK 0x1f +#define SHTC1_ID_REG_MASK 0x3f /* delays for non-blocking i2c commands, both in us */ #define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400 diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 721295b9a05176704b156e7dd799ad17da5edd86..43c0f89cefdf0d1395d011c8f9a287b9d7a8a795 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -130,17 +130,23 @@ superio_select(struct w83627hf_sio_data *sio, int ld) outb(ld, sio->sioaddr + 1); } -static inline void +static inline int superio_enter(struct w83627hf_sio_data *sio) { + if (!request_muxed_region(sio->sioaddr, 2, DRVNAME)) + return -EBUSY; + outb(0x87, sio->sioaddr); outb(0x87, sio->sioaddr); + + return 0; } static inline void superio_exit(struct w83627hf_sio_data *sio) { outb(0xAA, sio->sioaddr); + release_region(sio->sioaddr, 2); } #define W627_DEVID 0x52 @@ -1275,7 +1281,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static int __init w83627hf_find(int sioaddr, unsigned short *addr, struct w83627hf_sio_data *sio_data) { - int err = -ENODEV; + int err; u16 val; static __initconst char *const names[] = { @@ -1287,7 +1293,11 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, }; sio_data->sioaddr = sioaddr; - superio_enter(sio_data); + err = superio_enter(sio_data); + if (err) + return err; + + err = -ENODEV; val = force_id ? force_id : superio_inb(sio_data, DEVID); switch (val) { case W627_DEVID: @@ -1641,9 +1651,21 @@ static int w83627thf_read_gpio5(struct platform_device *pdev) struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev); int res = 0xff, sel; - superio_enter(sio_data); + if (superio_enter(sio_data)) { + /* + * Some other driver reserved the address space for itself. + * We don't want to fail driver instantiation because of that, + * so display a warning and keep going. + */ + dev_warn(&pdev->dev, + "Can not read VID data: Failed to enable SuperIO access\n"); + return res; + } + superio_select(sio_data, W83627HF_LD_GPIO5); + res = 0xff; + /* Make sure these GPIO pins are enabled */ if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) { dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); @@ -1674,7 +1696,17 @@ static int w83687thf_read_vid(struct platform_device *pdev) struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev); int res = 0xff; - superio_enter(sio_data); + if (superio_enter(sio_data)) { + /* + * Some other driver reserved the address space for itself. + * We don't want to fail driver instantiation because of that, + * so display a warning and keep going. + */ + dev_warn(&pdev->dev, + "Can not read VID data: Failed to enable SuperIO access\n"); + return res; + } + superio_select(sio_data, W83627HF_LD_HWM); /* Make sure these GPIO pins are enabled */ diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index b9e985fcae4c30c13d47e7f01cf9d487eebd715f..bc3fb791c3d3d4fb62bced5a86d477ef4da57150 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -279,9 +279,7 @@ static void *etb_alloc_buffer(struct coresight_device *csdev, int cpu, int node; struct cs_buffers *buf; - if (cpu == -1) - cpu = smp_processor_id(); - node = cpu_to_node(cpu); + node = (cpu == -1) ? NUMA_NO_NODE : cpu_to_node(cpu); buf = kzalloc_node(sizeof(struct cs_buffers), GFP_KERNEL, node); if (!buf) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 8f3b2640019a3e6f4e00eacb0242fcb917f89964..7412286e148600400259dc284dfa4d3d133a6b69 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -667,10 +667,13 @@ static ssize_t cyc_threshold_store(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; + + /* mask off max threshold before checking min value */ + val &= ETM_CYC_THRESHOLD_MASK; if (val < drvdata->ccitmin) return -EINVAL; - config->ccctlr = val & ETM_CYC_THRESHOLD_MASK; + config->ccctlr = val; return size; } static DEVICE_ATTR_RW(cyc_threshold); @@ -701,14 +704,16 @@ static ssize_t bb_ctrl_store(struct device *dev, return -EINVAL; if (!drvdata->nr_addr_cmp) return -EINVAL; + /* - * Bit[7:0] selects which address range comparator is used for - * branch broadcast control. + * Bit[8] controls include(1) / exclude(0), bits[0-7] select + * individual range comparators. If include then at least 1 + * range must be selected. */ - if (BMVAL(val, 0, 7) > drvdata->nr_addr_cmp) + if ((val & BIT(8)) && (BMVAL(val, 0, 7) == 0)) return -EINVAL; - config->bb_ctrl = val; + config->bb_ctrl = val & GENMASK(8, 0); return size; } static DEVICE_ATTR_RW(bb_ctrl); @@ -1341,8 +1346,8 @@ static ssize_t seq_event_store(struct device *dev, spin_lock(&drvdata->spinlock); idx = config->seq_idx; - /* RST, bits[7:0] */ - config->seq_ctrl[idx] = val & 0xFF; + /* Seq control has two masks B[15:8] F[7:0] */ + config->seq_ctrl[idx] = val & 0xFFFF; spin_unlock(&drvdata->spinlock); return size; } @@ -1597,7 +1602,7 @@ static ssize_t res_ctrl_store(struct device *dev, if (idx % 2 != 0) /* PAIRINV, bit[21] */ val &= ~BIT(21); - config->res_ctrl[idx] = val; + config->res_ctrl[idx] = val & GENMASK(21, 0); spin_unlock(&drvdata->spinlock); return size; } diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 09e66d5a2b3ea40019cca3650b57fb1e910e9c6d..abb46fb4d1a5d237c380ba1e0e247ad702daedd0 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -288,9 +288,7 @@ static void *tmc_alloc_etf_buffer(struct coresight_device *csdev, int cpu, int node; struct cs_buffers *buf; - if (cpu == -1) - cpu = smp_processor_id(); - node = cpu_to_node(cpu); + node = (cpu == -1) ? NUMA_NO_NODE : cpu_to_node(cpu); /* Allocate memory structure for interaction with Perf */ buf = kzalloc_node(sizeof(struct cs_buffers), GFP_KERNEL, node); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index c4188308cefae5b9befe470d60dd43c5c8f81825..9c1be9378dfdec08784a8e222c2fd062fd3b7e9e 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1088,7 +1088,8 @@ static int i2c_imx_probe(struct platform_device *pdev) /* Get I2C clock */ i2c_imx->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c_imx->clk)) { - dev_err(&pdev->dev, "can't get I2C clock\n"); + if (PTR_ERR(i2c_imx->clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "can't get I2C clock\n"); return PTR_ERR(i2c_imx->clk); } diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index 30132c3957cdc3d2d76e03a5a82511d9b0a27829..41ca9ff7b5da75a7b418f61c7a87f028c28403c6 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -82,25 +82,6 @@ #define JZ4780_I2C_STA_TFNF BIT(1) #define JZ4780_I2C_STA_ACT BIT(0) -static const char * const jz4780_i2c_abrt_src[] = { - "ABRT_7B_ADDR_NOACK", - "ABRT_10ADDR1_NOACK", - "ABRT_10ADDR2_NOACK", - "ABRT_XDATA_NOACK", - "ABRT_GCALL_NOACK", - "ABRT_GCALL_READ", - "ABRT_HS_ACKD", - "SBYTE_ACKDET", - "ABRT_HS_NORSTRT", - "SBYTE_NORSTRT", - "ABRT_10B_RD_NORSTRT", - "ABRT_MASTER_DIS", - "ARB_LOST", - "SLVFLUSH_TXFIFO", - "SLV_ARBLOST", - "SLVRD_INTX", -}; - #define JZ4780_I2C_INTST_IGC BIT(11) #define JZ4780_I2C_INTST_ISTT BIT(10) #define JZ4780_I2C_INTST_ISTP BIT(9) @@ -538,21 +519,8 @@ static irqreturn_t jz4780_i2c_irq(int irqno, void *dev_id) static void jz4780_i2c_txabrt(struct jz4780_i2c *i2c, int src) { - int i; - - dev_err(&i2c->adap.dev, "txabrt: 0x%08x\n", src); - dev_err(&i2c->adap.dev, "device addr=%x\n", - jz4780_i2c_readw(i2c, JZ4780_I2C_TAR)); - dev_err(&i2c->adap.dev, "send cmd count:%d %d\n", - i2c->cmd, i2c->cmd_buf[i2c->cmd]); - dev_err(&i2c->adap.dev, "receive data count:%d %d\n", - i2c->cmd, i2c->data_buf[i2c->cmd]); - - for (i = 0; i < 16; i++) { - if (src & BIT(i)) - dev_dbg(&i2c->adap.dev, "I2C TXABRT[%d]=%s\n", - i, jz4780_i2c_abrt_src[i]); - } + dev_dbg(&i2c->adap.dev, "txabrt: 0x%08x, cmd: %d, send: %d, recv: %d\n", + src, i2c->cmd, i2c->cmd_buf[i2c->cmd], i2c->data_buf[i2c->cmd]); } static inline int jz4780_i2c_xfer_read(struct jz4780_i2c *i2c, diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index b127ed60c73364f34a114a8a3033aa42c906b8ca..9dde8390da09bd95e91c2885d1253612c4b82ff4 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -65,6 +65,9 @@ static void cmd64x_program_timings(ide_drive_t *drive, u8 mode) struct ide_timing t; u8 arttim = 0; + if (drive->dn >= ARRAY_SIZE(drwtim_regs)) + return; + ide_timing_compute(drive, mode, &t, T, 0); /* diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index a97affca18abe153be1ba4b3285d25390171e69c..0f57d45484d1d97933ca6dba3fbedcf8cfcf081e 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -114,6 +114,9 @@ static void svwks_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) struct pci_dev *dev = to_pci_dev(hwif->dev); const u8 pio = drive->pio_mode - XFER_PIO_0; + if (drive->dn >= ARRAY_SIZE(drive_pci)) + return; + pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]); if (svwks_csb_check(dev)) { @@ -140,6 +143,9 @@ static void svwks_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0; + if (drive->dn >= ARRAY_SIZE(drive_pci2)) + return; + pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); pci_read_config_byte(dev, 0x54, &ultra_enable); diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 712fbd2b1f16259d9027a74404c0278858f58368..ec3f7bc70b75e9b6276ee1961ff92b201a07ba95 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -471,6 +471,14 @@ static int max1027_probe(struct spi_device *spi) goto fail_dev_register; } + /* Internal reset */ + st->reg = MAX1027_RST_REG; + ret = spi_write(st->spi, &st->reg, 1); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed to reset the ADC\n"); + return ret; + } + /* Disable averaging */ st->reg = MAX1027_AVG_REG; ret = spi_write(st->spi, &st->reg, 1); diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 97d2c5111f4389b7804bab5253262f5532b80271..8bf7fc626a9d4c974c7004ac88da87effea21acd 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -221,7 +221,7 @@ static int ad5380_read_raw(struct iio_dev *indio_dev, if (ret) return ret; *val >>= chan->scan_type.shift; - val -= (1 << chan->scan_type.realbits) / 2; + *val -= (1 << chan->scan_type.realbits) / 2; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 2 * st->vref; diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index a5c5c4e29addc38a94c4a5683f64904550ed32d2..48923ae6ac3bd04051e1640f31c65302bf38bf8a 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -19,6 +19,7 @@ #define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro" #define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro" #define L3GD20_GYRO_DEV_NAME "l3gd20" +#define L3GD20H_GYRO_DEV_NAME "l3gd20h" #define L3G4IS_GYRO_DEV_NAME "l3g4is_ui" #define LSM330_GYRO_DEV_NAME "lsm330_gyro" #define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index aea034d8fe0fb42495de198c1465246d0343c8c8..e366422e85127f27f2ab1df6a47019755af8d52d 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -35,83 +35,11 @@ #define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c /* FULLSCALE */ +#define ST_GYRO_FS_AVL_245DPS 245 #define ST_GYRO_FS_AVL_250DPS 250 #define ST_GYRO_FS_AVL_500DPS 500 #define ST_GYRO_FS_AVL_2000DPS 2000 -/* CUSTOM VALUES FOR SENSOR 1 */ -#define ST_GYRO_1_WAI_EXP 0xd3 -#define ST_GYRO_1_ODR_ADDR 0x20 -#define ST_GYRO_1_ODR_MASK 0xc0 -#define ST_GYRO_1_ODR_AVL_100HZ_VAL 0x00 -#define ST_GYRO_1_ODR_AVL_200HZ_VAL 0x01 -#define ST_GYRO_1_ODR_AVL_400HZ_VAL 0x02 -#define ST_GYRO_1_ODR_AVL_800HZ_VAL 0x03 -#define ST_GYRO_1_PW_ADDR 0x20 -#define ST_GYRO_1_PW_MASK 0x08 -#define ST_GYRO_1_FS_ADDR 0x23 -#define ST_GYRO_1_FS_MASK 0x30 -#define ST_GYRO_1_FS_AVL_250_VAL 0x00 -#define ST_GYRO_1_FS_AVL_500_VAL 0x01 -#define ST_GYRO_1_FS_AVL_2000_VAL 0x02 -#define ST_GYRO_1_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750) -#define ST_GYRO_1_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500) -#define ST_GYRO_1_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000) -#define ST_GYRO_1_BDU_ADDR 0x23 -#define ST_GYRO_1_BDU_MASK 0x80 -#define ST_GYRO_1_DRDY_IRQ_ADDR 0x22 -#define ST_GYRO_1_DRDY_IRQ_INT2_MASK 0x08 -#define ST_GYRO_1_MULTIREAD_BIT true - -/* CUSTOM VALUES FOR SENSOR 2 */ -#define ST_GYRO_2_WAI_EXP 0xd4 -#define ST_GYRO_2_ODR_ADDR 0x20 -#define ST_GYRO_2_ODR_MASK 0xc0 -#define ST_GYRO_2_ODR_AVL_95HZ_VAL 0x00 -#define ST_GYRO_2_ODR_AVL_190HZ_VAL 0x01 -#define ST_GYRO_2_ODR_AVL_380HZ_VAL 0x02 -#define ST_GYRO_2_ODR_AVL_760HZ_VAL 0x03 -#define ST_GYRO_2_PW_ADDR 0x20 -#define ST_GYRO_2_PW_MASK 0x08 -#define ST_GYRO_2_FS_ADDR 0x23 -#define ST_GYRO_2_FS_MASK 0x30 -#define ST_GYRO_2_FS_AVL_250_VAL 0x00 -#define ST_GYRO_2_FS_AVL_500_VAL 0x01 -#define ST_GYRO_2_FS_AVL_2000_VAL 0x02 -#define ST_GYRO_2_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750) -#define ST_GYRO_2_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500) -#define ST_GYRO_2_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000) -#define ST_GYRO_2_BDU_ADDR 0x23 -#define ST_GYRO_2_BDU_MASK 0x80 -#define ST_GYRO_2_DRDY_IRQ_ADDR 0x22 -#define ST_GYRO_2_DRDY_IRQ_INT2_MASK 0x08 -#define ST_GYRO_2_MULTIREAD_BIT true - -/* CUSTOM VALUES FOR SENSOR 3 */ -#define ST_GYRO_3_WAI_EXP 0xd7 -#define ST_GYRO_3_ODR_ADDR 0x20 -#define ST_GYRO_3_ODR_MASK 0xc0 -#define ST_GYRO_3_ODR_AVL_95HZ_VAL 0x00 -#define ST_GYRO_3_ODR_AVL_190HZ_VAL 0x01 -#define ST_GYRO_3_ODR_AVL_380HZ_VAL 0x02 -#define ST_GYRO_3_ODR_AVL_760HZ_VAL 0x03 -#define ST_GYRO_3_PW_ADDR 0x20 -#define ST_GYRO_3_PW_MASK 0x08 -#define ST_GYRO_3_FS_ADDR 0x23 -#define ST_GYRO_3_FS_MASK 0x30 -#define ST_GYRO_3_FS_AVL_250_VAL 0x00 -#define ST_GYRO_3_FS_AVL_500_VAL 0x01 -#define ST_GYRO_3_FS_AVL_2000_VAL 0x02 -#define ST_GYRO_3_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750) -#define ST_GYRO_3_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500) -#define ST_GYRO_3_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000) -#define ST_GYRO_3_BDU_ADDR 0x23 -#define ST_GYRO_3_BDU_MASK 0x80 -#define ST_GYRO_3_DRDY_IRQ_ADDR 0x22 -#define ST_GYRO_3_DRDY_IRQ_INT2_MASK 0x08 -#define ST_GYRO_3_MULTIREAD_BIT true - - static const struct iio_chan_spec st_gyro_16bit_channels[] = { ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), @@ -130,7 +58,7 @@ static const struct iio_chan_spec st_gyro_16bit_channels[] = { static const struct st_sensor_settings st_gyro_sensors_settings[] = { { - .wai = ST_GYRO_1_WAI_EXP, + .wai = 0xd3, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = L3G4200D_GYRO_DEV_NAME, @@ -138,18 +66,18 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { - .addr = ST_GYRO_1_ODR_ADDR, - .mask = ST_GYRO_1_ODR_MASK, + .addr = 0x20, + .mask = 0xc0, .odr_avl = { - { 100, ST_GYRO_1_ODR_AVL_100HZ_VAL, }, - { 200, ST_GYRO_1_ODR_AVL_200HZ_VAL, }, - { 400, ST_GYRO_1_ODR_AVL_400HZ_VAL, }, - { 800, ST_GYRO_1_ODR_AVL_800HZ_VAL, }, + { .hz = 100, .value = 0x00, }, + { .hz = 200, .value = 0x01, }, + { .hz = 400, .value = 0x02, }, + { .hz = 800, .value = 0x03, }, }, }, .pw = { - .addr = ST_GYRO_1_PW_ADDR, - .mask = ST_GYRO_1_PW_MASK, + .addr = 0x20, + .mask = 0x08, .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, }, @@ -158,33 +86,33 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .mask = ST_SENSORS_DEFAULT_AXIS_MASK, }, .fs = { - .addr = ST_GYRO_1_FS_ADDR, - .mask = ST_GYRO_1_FS_MASK, + .addr = 0x23, + .mask = 0x30, .fs_avl = { [0] = { .num = ST_GYRO_FS_AVL_250DPS, - .value = ST_GYRO_1_FS_AVL_250_VAL, - .gain = ST_GYRO_1_FS_AVL_250_GAIN, + .value = 0x00, + .gain = IIO_DEGREE_TO_RAD(8750), }, [1] = { .num = ST_GYRO_FS_AVL_500DPS, - .value = ST_GYRO_1_FS_AVL_500_VAL, - .gain = ST_GYRO_1_FS_AVL_500_GAIN, + .value = 0x01, + .gain = IIO_DEGREE_TO_RAD(17500), }, [2] = { .num = ST_GYRO_FS_AVL_2000DPS, - .value = ST_GYRO_1_FS_AVL_2000_VAL, - .gain = ST_GYRO_1_FS_AVL_2000_GAIN, + .value = 0x02, + .gain = IIO_DEGREE_TO_RAD(70000), }, }, }, .bdu = { - .addr = ST_GYRO_1_BDU_ADDR, - .mask = ST_GYRO_1_BDU_MASK, + .addr = 0x23, + .mask = 0x80, }, .drdy_irq = { - .addr = ST_GYRO_1_DRDY_IRQ_ADDR, - .mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK, + .addr = 0x22, + .mask_int2 = 0x08, /* * The sensor has IHL (active low) and open * drain settings, but only for INT1 and not @@ -192,11 +120,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { */ .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, - .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT, + .multi_read_bit = true, .bootime = 2, }, { - .wai = ST_GYRO_2_WAI_EXP, + .wai = 0xd4, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = L3GD20_GYRO_DEV_NAME, @@ -208,18 +136,18 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { - .addr = ST_GYRO_2_ODR_ADDR, - .mask = ST_GYRO_2_ODR_MASK, + .addr = 0x20, + .mask = 0xc0, .odr_avl = { - { 95, ST_GYRO_2_ODR_AVL_95HZ_VAL, }, - { 190, ST_GYRO_2_ODR_AVL_190HZ_VAL, }, - { 380, ST_GYRO_2_ODR_AVL_380HZ_VAL, }, - { 760, ST_GYRO_2_ODR_AVL_760HZ_VAL, }, + { .hz = 95, .value = 0x00, }, + { .hz = 190, .value = 0x01, }, + { .hz = 380, .value = 0x02, }, + { .hz = 760, .value = 0x03, }, }, }, .pw = { - .addr = ST_GYRO_2_PW_ADDR, - .mask = ST_GYRO_2_PW_MASK, + .addr = 0x20, + .mask = 0x08, .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, }, @@ -228,33 +156,33 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .mask = ST_SENSORS_DEFAULT_AXIS_MASK, }, .fs = { - .addr = ST_GYRO_2_FS_ADDR, - .mask = ST_GYRO_2_FS_MASK, + .addr = 0x23, + .mask = 0x30, .fs_avl = { [0] = { .num = ST_GYRO_FS_AVL_250DPS, - .value = ST_GYRO_2_FS_AVL_250_VAL, - .gain = ST_GYRO_2_FS_AVL_250_GAIN, + .value = 0x00, + .gain = IIO_DEGREE_TO_RAD(8750), }, [1] = { .num = ST_GYRO_FS_AVL_500DPS, - .value = ST_GYRO_2_FS_AVL_500_VAL, - .gain = ST_GYRO_2_FS_AVL_500_GAIN, + .value = 0x01, + .gain = IIO_DEGREE_TO_RAD(17500), }, [2] = { .num = ST_GYRO_FS_AVL_2000DPS, - .value = ST_GYRO_2_FS_AVL_2000_VAL, - .gain = ST_GYRO_2_FS_AVL_2000_GAIN, + .value = 0x02, + .gain = IIO_DEGREE_TO_RAD(70000), }, }, }, .bdu = { - .addr = ST_GYRO_2_BDU_ADDR, - .mask = ST_GYRO_2_BDU_MASK, + .addr = 0x23, + .mask = 0x80, }, .drdy_irq = { - .addr = ST_GYRO_2_DRDY_IRQ_ADDR, - .mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK, + .addr = 0x22, + .mask_int2 = 0x08, /* * The sensor has IHL (active low) and open * drain settings, but only for INT1 and not @@ -262,29 +190,29 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { */ .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, - .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT, + .multi_read_bit = true, .bootime = 2, }, { - .wai = ST_GYRO_3_WAI_EXP, + .wai = 0xd7, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { - [0] = L3GD20_GYRO_DEV_NAME, + [0] = L3GD20H_GYRO_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { - .addr = ST_GYRO_3_ODR_ADDR, - .mask = ST_GYRO_3_ODR_MASK, + .addr = 0x20, + .mask = 0xc0, .odr_avl = { - { 95, ST_GYRO_3_ODR_AVL_95HZ_VAL, }, - { 190, ST_GYRO_3_ODR_AVL_190HZ_VAL, }, - { 380, ST_GYRO_3_ODR_AVL_380HZ_VAL, }, - { 760, ST_GYRO_3_ODR_AVL_760HZ_VAL, }, + { .hz = 100, .value = 0x00, }, + { .hz = 200, .value = 0x01, }, + { .hz = 400, .value = 0x02, }, + { .hz = 800, .value = 0x03, }, }, }, .pw = { - .addr = ST_GYRO_3_PW_ADDR, - .mask = ST_GYRO_3_PW_MASK, + .addr = 0x20, + .mask = 0x08, .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, }, @@ -293,33 +221,33 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .mask = ST_SENSORS_DEFAULT_AXIS_MASK, }, .fs = { - .addr = ST_GYRO_3_FS_ADDR, - .mask = ST_GYRO_3_FS_MASK, + .addr = 0x23, + .mask = 0x30, .fs_avl = { [0] = { - .num = ST_GYRO_FS_AVL_250DPS, - .value = ST_GYRO_3_FS_AVL_250_VAL, - .gain = ST_GYRO_3_FS_AVL_250_GAIN, + .num = ST_GYRO_FS_AVL_245DPS, + .value = 0x00, + .gain = IIO_DEGREE_TO_RAD(8750), }, [1] = { .num = ST_GYRO_FS_AVL_500DPS, - .value = ST_GYRO_3_FS_AVL_500_VAL, - .gain = ST_GYRO_3_FS_AVL_500_GAIN, + .value = 0x01, + .gain = IIO_DEGREE_TO_RAD(17500), }, [2] = { .num = ST_GYRO_FS_AVL_2000DPS, - .value = ST_GYRO_3_FS_AVL_2000_VAL, - .gain = ST_GYRO_3_FS_AVL_2000_GAIN, + .value = 0x02, + .gain = IIO_DEGREE_TO_RAD(70000), }, }, }, .bdu = { - .addr = ST_GYRO_3_BDU_ADDR, - .mask = ST_GYRO_3_BDU_MASK, + .addr = 0x23, + .mask = 0x80, }, .drdy_irq = { - .addr = ST_GYRO_3_DRDY_IRQ_ADDR, - .mask_int2 = ST_GYRO_3_DRDY_IRQ_INT2_MASK, + .addr = 0x22, + .mask_int2 = 0x08, /* * The sensor has IHL (active low) and open * drain settings, but only for INT1 and not @@ -327,7 +255,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { */ .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, }, - .multi_read_bit = ST_GYRO_3_MULTIREAD_BIT, + .multi_read_bit = true, .bootime = 2, }, }; diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 40056b82103640b467db0c10733555476928aaec..3f628746cb93e411685140056c44f55d9ba28eee 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -40,6 +40,10 @@ static const struct of_device_id st_gyro_of_match[] = { .compatible = "st,l3gd20-gyro", .data = L3GD20_GYRO_DEV_NAME, }, + { + .compatible = "st,l3gd20h-gyro", + .data = L3GD20H_GYRO_DEV_NAME, + }, { .compatible = "st,l3g4is-gyro", .data = L3G4IS_GYRO_DEV_NAME, @@ -95,6 +99,7 @@ static const struct i2c_device_id st_gyro_id_table[] = { { LSM330DL_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME }, + { L3GD20H_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME }, diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index fbf2faed501c8628ed23d0ff0fa7590f6e091c01..fa14d8f2170d71018ab47e6ae7bfcaad303b3486 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -52,6 +52,7 @@ static const struct spi_device_id st_gyro_id_table[] = { { LSM330DL_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME }, + { L3GD20H_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME }, diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index e0c9c70c2a4ae6dcc1723abc114ad036511a0c97..c0e2e78c5c62c213152ac1be7cbc959817df334d 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -202,7 +202,7 @@ static int hdc100x_read_raw(struct iio_dev *indio_dev, *val2 = 65536; return IIO_VAL_FRACTIONAL; } else { - *val = 100; + *val = 100000; *val2 = 65536; return IIO_VAL_FRACTIONAL; } diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index 6f975538996cdc0936ffd49ab9a77adc7f499bf9..5abe095901c83dbb0c98b045c44c49fabd1867f0 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -372,12 +372,14 @@ static int adis16480_get_calibbias(struct iio_dev *indio_dev, case IIO_MAGN: case IIO_PRESSURE: ret = adis_read_reg_16(&st->adis, reg, &val16); - *bias = sign_extend32(val16, 15); + if (ret == 0) + *bias = sign_extend32(val16, 15); break; case IIO_ANGL_VEL: case IIO_ACCEL: ret = adis_read_reg_32(&st->adis, reg, &val32); - *bias = sign_extend32(val32, 31); + if (ret == 0) + *bias = sign_extend32(val32, 31); break; default: ret = -EINVAL; @@ -724,6 +726,7 @@ static const struct iio_info adis16480_info = { .write_raw = &adis16480_write_raw, .update_scan_mode = adis_update_scan_mode, .driver_module = THIS_MODULE, + .debugfs_reg_access = adis_debugfs_reg_access, }; static int adis16480_stop_device(struct iio_dev *indio_dev) diff --git a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c index f8d13ccade38c9a7871ee68322305575cee22626..30f67995abce4b41d0de2d1dc76c9a4979fde3e3 100644 --- a/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c +++ b/drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c @@ -809,8 +809,8 @@ static int inv_gyro_read_bootsampl(struct inv_mpu_state *st, { int i = 0; + st->gyro_buffer_inv_samples = false; if (enable_read) { - st->gyro_buffer_inv_samples = false; for (i = 0; i < st->gyro_bufsample_cnt; i++) { dev_dbg(st->dev, "gyro_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n", i, st->inv_gyro_samplist[i]->xyz[0], @@ -853,8 +853,8 @@ static int inv_acc_read_bootsampl(struct inv_mpu_state *st, { int i = 0; + st->acc_buffer_inv_samples = false; if (enable_read) { - st->acc_buffer_inv_samples = false; for (i = 0; i < st->acc_bufsample_cnt; i++) { dev_dbg(st->dev, "acc_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n", i, st->inv_acc_samplist[i]->xyz[0], @@ -922,7 +922,9 @@ static ssize_t read_gyro_boot_sample_store(struct device *dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } + mutex_lock(&st->gyro_sensor_buff); err = inv_gyro_read_bootsampl(st, enable); + mutex_unlock(&st->gyro_sensor_buff); if (err) return err; st->read_gyro_boot_sample = enable; @@ -958,7 +960,9 @@ static ssize_t read_acc_boot_sample_store(struct device *dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } + mutex_lock(&st->acc_sensor_buff); err = inv_acc_read_bootsampl(st, enable); + mutex_unlock(&st->acc_sensor_buff); if (err) return err; st->read_acc_boot_sample = enable; diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c index 65089f2fab130e9264fa2f41d14a456906197dcc..8b45d904e8b385827237f5bdbc7ca3a961a0be39 100644 --- a/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu/inv_mpu_i2c.c @@ -439,6 +439,9 @@ static int inv_acc_gyro_early_buff_init(struct iio_dev *indio_dev) st->acc_buffer_inv_samples = true; st->gyro_buffer_inv_samples = true; + mutex_init(&st->acc_sensor_buff); + mutex_init(&st->gyro_sensor_buff); + inv_enable_acc_gyro(st); return 1; diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu/inv_mpu_iio.h index 1e0a1769e5f31ce93f6568d3b7a95a0dec596251..7a687c25f4af1e54fdbbd8165108c7e3cac82ae0 100644 --- a/drivers/iio/imu/inv_mpu/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu/inv_mpu_iio.h @@ -871,6 +871,8 @@ struct inv_mpu_state { struct input_dev *accbuf_dev; struct input_dev *gyrobuf_dev; int report_evt_cnt; + struct mutex acc_sensor_buff; + struct mutex gyro_sensor_buff; #endif }; diff --git a/drivers/iio/imu/inv_mpu/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu/inv_mpu_ring.c index de64b2c03ae98794d8c3a52e02c47df1dc7c4ad7..be6fa4861539747062f29185b49016bd01a1be5c 100644 --- a/drivers/iio/imu/inv_mpu/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu/inv_mpu_ring.c @@ -303,6 +303,7 @@ static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t, { if (false == st->acc_buffer_inv_samples) return; + mutex_lock(&st->acc_sensor_buff); st->timestamp.tv64 = t; if (ktime_to_timespec(st->timestamp).tv_sec < st->max_buffer_time) { @@ -328,13 +329,14 @@ static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t, st->acc_bufsample_cnt); st->acc_buffer_inv_samples = false; } + mutex_unlock(&st->acc_sensor_buff); } static void store_gyro_boot_sample(struct inv_mpu_state *st, u64 t, s16 x, s16 y, s16 z) { - if (false == st->gyro_buffer_inv_samples) return; + mutex_lock(&st->gyro_sensor_buff); st->timestamp.tv64 = t; if (ktime_to_timespec(st->timestamp).tv_sec < st->max_buffer_time) { @@ -360,6 +362,7 @@ static void store_gyro_boot_sample(struct inv_mpu_state *st, u64 t, st->gyro_bufsample_cnt); st->gyro_buffer_inv_samples = false; } + mutex_unlock(&st->gyro_sensor_buff); } #else static void store_acc_boot_sample(struct inv_mpu_state *st, u64 t, diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h index c582e4fead4f5d9ddb85e1fc1ae76fd6ecc5a3ed..39a99a24c899fdfbb63c993c96d5ab43a8a3afd4 100644 --- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h +++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h @@ -43,6 +43,9 @@ #define ST_ASM330LHH_MAX_ODR 416 +/* Timestamp Tick 25us/LSB */ +#define ST_ASM330LHH_TS_DELTA_NS 25000ULL + /* Define Custom events for FIFO flush */ #define CUSTOM_IIO_EV_DIR_FIFO_EMPTY (IIO_EV_DIR_NONE + 1) #define CUSTOM_IIO_EV_DIR_FIFO_DATA (IIO_EV_DIR_NONE + 2) @@ -82,8 +85,8 @@ static const struct iio_event_spec st_asm330lhh_flush_event = { .num_event_specs = 1, \ } -#define ST_ASM330LHH_RX_MAX_LENGTH 8 -#define ST_ASM330LHH_TX_MAX_LENGTH 8 +#define ST_ASM330LHH_RX_MAX_LENGTH 64 +#define ST_ASM330LHH_TX_MAX_LENGTH 16 #ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING #define ASM_MAXSAMPLE 4000 @@ -188,6 +191,7 @@ struct st_asm330lhh_sensor { int max_buffer_time; struct input_dev *buf_dev; int report_evt_cnt; + struct mutex sensor_buff; #endif }; @@ -197,6 +201,7 @@ struct st_asm330lhh_sensor { * @irq: Device interrupt line (I2C or SPI). * @lock: Mutex to protect read and write operations. * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO. + * @page_lock: Mutex to prevent concurrent memory page configuration. * @fifo_mode: FIFO operating mode supported by the device. * @state: hw operational state. * @enable_mask: Enabled sensor bitmask. @@ -204,6 +209,13 @@ struct st_asm330lhh_sensor { * @hw_ts: Latest hw timestamp from the sensor. * @ts: Latest timestamp from irq handler. * @delta_ts: Delta time between two consecutive interrupts. + * @ts_delta_ns: Calibrate delta time tick. + * @hw_ts: Latest hw timestamp from the sensor. + * @val_ts_old: Hold hw timestamp for timer rollover. + * @hw_ts_high: Save MSB hw timestamp. + * @tsample: Timestamp for each sensor sample. + * @delta_ts: Delta time between two consecutive interrupts. + * @ts: Latest timestamp from irq handler. * @iio_devs: Pointers to acc/gyro iio_dev instances. * @tf: Transfer function structure used by I/O operations. * @tb: Transfer buffers used by SPI I/O operations. @@ -214,34 +226,51 @@ struct st_asm330lhh_hw { struct mutex lock; struct mutex fifo_lock; + struct mutex page_lock; enum st_asm330lhh_fifo_mode fifo_mode; unsigned long state; u8 enable_mask; s64 ts_offset; - u32 hw_val; - u32 hw_val_old; + u64 ts_delta_ns; s64 hw_ts; - s64 hw_ts_high; + u32 val_ts_old; + u32 hw_ts_high; + s64 tsample; s64 delta_ts; s64 ts; - s64 tsample; - s64 hw_ts_old; - s64 delta_hw_ts; - - /* Timestamp sample ODR */ - u16 odr; - struct iio_dev *iio_devs[ST_ASM330LHH_ID_MAX]; const struct st_asm330lhh_transfer_function *tf; struct st_asm330lhh_transfer_buffer tb; int enable_gpio; + bool asm330_hrtimer; + struct hrtimer st_asm330lhh_hrtimer; }; extern const struct dev_pm_ops st_asm330lhh_pm_ops; +static inline int st_asm330lhh_read_atomic(struct st_asm330lhh_hw *hw, u8 addr, + int len, u8 *data) +{ + int err; + + mutex_lock(&hw->page_lock); + err = hw->tf->read(hw->dev, addr, len, data); + mutex_unlock(&hw->page_lock); + + return err; +} + +static inline s64 st_asm330lhh_get_time_ns(void) +{ + struct timespec ts; + + get_monotonic_boottime(&ts); + return timespec_to_ns(&ts); +} + int st_asm330lhh_probe(struct device *dev, int irq, const struct st_asm330lhh_transfer_function *tf_ops); int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor, @@ -268,4 +297,6 @@ int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor, int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable); int asm330_check_acc_gyro_early_buff_enable_flag( struct st_asm330lhh_sensor *sensor); +void st_asm330lhh_set_cpu_idle_state(bool value); +void st_asm330lhh_hrtimer_reset(struct st_asm330lhh_hw *hw, s64 irq_delta_ts); #endif /* ST_ASM330LHH_H */ diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c index c224427d0153d65fc64c74c8ddda28f26bf9a4df..b8b3effd5aeab2d36ce9e17a7417077c2fc73215 100644 --- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c +++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c @@ -1,7 +1,7 @@ /* * STMicroelectronics st_asm330lhh FIFO buffer library driver * - * Copyright 2018 STMicroelectronics Inc. + * Copyright 2020 STMicroelectronics Inc. * * Lorenzo Bianconi * @@ -10,41 +10,41 @@ #include #include #include +#include #include #include #include +#include #include #include "st_asm330lhh.h" #define ST_ASM330LHH_REG_FIFO_THL_ADDR 0x07 #define ST_ASM330LHH_REG_FIFO_LEN_MASK GENMASK(8, 0) +#define ST_ASM330LHH_REG_FIFO_STATUS_DIFF GENMASK(9, 0) #define ST_ASM330LHH_REG_FIFO_MODE_MASK GENMASK(2, 0) #define ST_ASM330LHH_REG_DEC_TS_MASK GENMASK(7, 6) #define ST_ASM330LHH_REG_HLACTIVE_ADDR 0x12 #define ST_ASM330LHH_REG_HLACTIVE_MASK BIT(5) #define ST_ASM330LHH_REG_PP_OD_ADDR 0x12 #define ST_ASM330LHH_REG_PP_OD_MASK BIT(4) -#define ST_ASM330LHH_REG_FIFO_DIFFL_ADDR 0x3a +#define ST_ASM330LHH_REG_FIFO_STATUS1_ADDR 0x3a #define ST_ASM330LHH_REG_TS0_ADDR 0x40 #define ST_ASM330LHH_REG_TS2_ADDR 0x42 #define ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR 0x78 -#define ST_ASM330LHH_GYRO_TAG 0x01 -#define ST_ASM330LHH_ACC_TAG 0x02 -#define ST_ASM330LHH_TS_TAG 0x04 -#define ST_ASM330LHH_TS_DELTA_NS 25000ULL /* 25us/LSB */ - -static inline s64 st_asm330lhh_get_time_ns(void) -{ - struct timespec ts; - - get_monotonic_boottime(&ts); - return timespec_to_ns(&ts); -} +#define ST_ASM330LHH_SAMPLE_DISCHARD 0x7ffd +/* Timestamp convergence filter parameter */ #define ST_ASM330LHH_EWMA_LEVEL 120 #define ST_ASM330LHH_EWMA_DIV 128 + +enum { + ST_ASM330LHH_GYRO_TAG = 0x01, + ST_ASM330LHH_ACC_TAG = 0x02, + ST_ASM330LHH_TS_TAG = 0x04, +}; + static inline s64 st_asm330lhh_ewma(s64 old, s64 new, int weight) { s64 diff, incr; @@ -62,10 +62,12 @@ static inline int st_asm330lhh_reset_hwts(struct st_asm330lhh_hw *hw) hw->ts = st_asm330lhh_get_time_ns(); hw->ts_offset = hw->ts; - hw->hw_ts_old = 0ull; + hw->val_ts_old = 0; + hw->hw_ts_high = 0; hw->tsample = 0ull; - hw->hw_ts_high = 0ull; - hw->hw_val_old = 0ull; + + if (hw->asm330_hrtimer) + st_asm330lhh_set_cpu_idle_state(true); return hw->tf->write(hw->dev, ST_ASM330LHH_REG_TS2_ADDR, sizeof(data), &data); @@ -84,6 +86,11 @@ int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw, hw->fifo_mode = fifo_mode; + if (fifo_mode == ST_ASM330LHH_FIFO_BYPASS) + clear_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state); + else + set_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state); + return 0; } @@ -105,24 +112,6 @@ static int st_asm330lhh_set_sensor_batching_odr(struct st_asm330lhh_sensor *sens sensor->batch_mask, data); } -static u16 st_asm330lhh_ts_odr(struct st_asm330lhh_hw *hw) -{ - struct st_asm330lhh_sensor *sensor; - u16 odr = 0; - u8 i; - - for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - sensor = iio_priv(hw->iio_devs[i]); - if (hw->enable_mask & BIT(sensor->id)) - odr = max_t(u16, odr, sensor->odr); - } - - return odr; -} - int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor, u16 watermark) { @@ -134,6 +123,9 @@ int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor, u8 data; for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) { + if (!hw->iio_devs[i]) + continue; + cur_sensor = iio_priv(hw->iio_devs[i]); if (!(hw->enable_mask & BIT(cur_sensor->id))) @@ -146,6 +138,7 @@ int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor, } fifo_watermark = max_t(u16, fifo_watermark, 2); + mutex_lock(&hw->lock); err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_THL_ADDR + 1, @@ -165,14 +158,6 @@ int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor, return err < 0 ? err : 0; } -static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts) -{ - s64 delta = ts - hw->hw_ts; - - hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta, - ST_ASM330LHH_EWMA_LEVEL); -} - static struct iio_dev *st_asm330lhh_get_iiodev_from_tag(struct st_asm330lhh_hw *hw, u8 tag) { @@ -218,6 +203,7 @@ static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor, if (false == sensor->buffer_asm_samples) return; + mutex_lock(&sensor->sensor_buff); sensor->timestamp = (ktime_t)tsample; x = iio_buf[1]<<8|iio_buf[0]; y = iio_buf[3]<<8|iio_buf[2]; @@ -240,6 +226,7 @@ static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor, sensor->id, sensor->bufsample_cnt); sensor->buffer_asm_samples = false; } + mutex_unlock(&sensor->sensor_buff); } #else static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor, @@ -248,111 +235,116 @@ static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor, } #endif +static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts) +{ + s64 delta = ts - hw->hw_ts; + + hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta, + ST_ASM330LHH_EWMA_LEVEL); +} + static int st_asm330lhh_read_fifo(struct st_asm330lhh_hw *hw) { u8 iio_buf[ALIGN(ST_ASM330LHH_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)]; u8 buf[30 * ST_ASM330LHH_FIFO_SAMPLE_SIZE], tag, *ptr; - s64 ts_delta_hw_ts = 0, ts_irq; - s64 ts_delta_offs; - int i, err, read_len, word_len, fifo_len; - struct st_asm330lhh_sensor *sensor; + int i, err, word_len, fifo_len, read_len; struct iio_dev *iio_dev; + struct st_asm330lhh_sensor *sensor; + s64 ts_irq, hw_ts_old; __le16 fifo_status; u16 fifo_depth; - int ts_processed = 0; - s64 hw_ts = 0ull, delta_hw_ts, cpu_timestamp; + s16 drdymask; + u32 val; + + /* return if FIFO is already disabled */ + if (!test_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state)) { + dev_warn(hw->dev, "%s: FIFO in bypass mode\n", __func__); + + return 0; + } ts_irq = hw->ts - hw->delta_ts; - do { - err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_DIFFL_ADDR, - sizeof(fifo_status), (u8 *)&fifo_status); + err = st_asm330lhh_read_atomic(hw, ST_ASM330LHH_REG_FIFO_STATUS1_ADDR, + sizeof(fifo_status), (u8 *)&fifo_status); + if (err < 0) + return err; + + fifo_depth = le16_to_cpu(fifo_status) & + ST_ASM330LHH_REG_FIFO_STATUS_DIFF; + if (!fifo_depth) + return 0; + + fifo_len = fifo_depth * ST_ASM330LHH_FIFO_SAMPLE_SIZE; + read_len = 0; + while (read_len < fifo_len) { + word_len = min_t(int, fifo_len - read_len, sizeof(buf)); + err = st_asm330lhh_read_atomic(hw, + ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR, + word_len, buf); if (err < 0) return err; - - fifo_depth = le16_to_cpu(fifo_status) & ST_ASM330LHH_REG_FIFO_LEN_MASK; - if (!fifo_depth) - return 0; - - read_len = 0; - fifo_len = fifo_depth * ST_ASM330LHH_FIFO_SAMPLE_SIZE; - while (read_len < fifo_len) { - word_len = min_t(int, fifo_len - read_len, sizeof(buf)); - err = hw->tf->read(hw->dev, - ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR, - word_len, buf); - if (err < 0) - return err; - - for (i = 0; i < word_len; i += ST_ASM330LHH_FIFO_SAMPLE_SIZE) { - ptr = &buf[i + ST_ASM330LHH_TAG_SIZE]; - tag = buf[i] >> 3; - - if (tag == ST_ASM330LHH_TS_TAG) { - hw->hw_val = get_unaligned_le32(ptr); - - /* check for timer rollover */ - if (hw->hw_val < hw->hw_val_old) - hw->hw_ts_high++; - hw->hw_ts = - (hw->hw_val + (hw->hw_ts_high << 32)) - * ST_ASM330LHH_TS_DELTA_NS; - ts_delta_hw_ts = hw->hw_ts - hw->hw_ts_old; - hw_ts += ts_delta_hw_ts; - ts_delta_offs = - div_s64(hw->delta_hw_ts * ST_ASM330LHH_MAX_ODR, hw->odr); - - hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, ts_irq - - hw->hw_ts + ts_delta_offs, ST_ASM330LHH_EWMA_LEVEL); - - ts_irq += (hw->hw_ts + ts_delta_offs); - hw->hw_ts_old = hw->hw_ts; - hw->hw_val_old = hw->hw_val; - ts_processed++; - - if (!hw->tsample) - hw->tsample = - hw->ts_offset + (hw->hw_ts + ts_delta_offs); - else - hw->tsample = - hw->tsample + (ts_delta_hw_ts + ts_delta_offs); - } else { - iio_dev = st_asm330lhh_get_iiodev_from_tag(hw, tag); - if (!iio_dev) - continue; - - sensor = iio_priv(iio_dev); - if (sensor->std_samples < sensor->std_level) { - sensor->std_samples++; - continue; - } - - sensor = iio_priv(iio_dev); - - /* Check if timestamp is in the future. */ - cpu_timestamp = st_asm330lhh_get_time_ns(); - - /* Avoid samples in the future. */ - if (hw->tsample > cpu_timestamp) - hw->tsample = cpu_timestamp; - - memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE); - iio_push_to_buffers_with_timestamp(iio_dev, - iio_buf, - hw->tsample); - store_acc_gyro_boot_sample(sensor, - iio_buf, hw->tsample); + for (i = 0; i < word_len; i += ST_ASM330LHH_FIFO_SAMPLE_SIZE) { + ptr = &buf[i + ST_ASM330LHH_TAG_SIZE]; + tag = buf[i] >> 3; + + if (tag == ST_ASM330LHH_TS_TAG) { + val = get_unaligned_le32(ptr); + + if (hw->val_ts_old > val) + hw->hw_ts_high++; + + hw_ts_old = hw->hw_ts; + + /* check hw rollover */ + hw->val_ts_old = val; + hw->hw_ts = (val + ((s64)hw->hw_ts_high << + 32)) * hw->ts_delta_ns; + hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, + ts_irq - hw->hw_ts, + ST_ASM330LHH_EWMA_LEVEL); + + if (!test_bit(ST_ASM330LHH_HW_FLUSH, + &hw->state)) + /* sync ap timestamp and sensor one */ + st_asm330lhh_sync_hw_ts(hw, ts_irq); + + ts_irq += hw->hw_ts; + + if (!hw->tsample) + hw->tsample = hw->ts_offset + hw->hw_ts; + else + hw->tsample = hw->tsample + + hw->hw_ts - hw_ts_old; + } else { + iio_dev = st_asm330lhh_get_iiodev_from_tag(hw, + tag); + if (!iio_dev) + continue; + sensor = iio_priv(iio_dev); + + /* skip samples if not ready */ + drdymask = (s16)le16_to_cpu( + get_unaligned_le16(ptr)); + if (unlikely(drdymask + >= ST_ASM330LHH_SAMPLE_DISCHARD)) { + continue; } + memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE); + + hw->tsample = min_t(s64, + hw->ts, + hw->tsample); + + iio_push_to_buffers_with_timestamp(iio_dev, + iio_buf, + hw->tsample); + store_acc_gyro_boot_sample(sensor, + iio_buf, hw->tsample); } - read_len += word_len; } - - delta_hw_ts = div_s64(hw->delta_ts - hw_ts, ts_processed); - delta_hw_ts = div_s64(delta_hw_ts * hw->odr, ST_ASM330LHH_MAX_ODR); - hw->delta_hw_ts = st_asm330lhh_ewma(hw->delta_hw_ts, - delta_hw_ts, - ST_ASM330LHH_EWMA_LEVEL); - } while(read_len); + read_len += word_len; + } return read_len; } @@ -412,8 +404,9 @@ ssize_t st_asm330lhh_flush_fifo(struct device *dev, struct iio_dev *iio_dev = dev_get_drvdata(dev); struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev); struct st_asm330lhh_hw *hw = sensor->hw; - s64 type, event; + s64 event; int count; + s64 type; s64 ts; mutex_lock(&hw->fifo_lock); @@ -421,9 +414,7 @@ ssize_t st_asm330lhh_flush_fifo(struct device *dev, hw->delta_ts = ts - hw->ts; hw->ts = ts; set_bit(ST_ASM330LHH_HW_FLUSH, &hw->state); - count = st_asm330lhh_read_fifo(hw); - mutex_unlock(&hw->fifo_lock); type = count > 0 ? CUSTOM_IIO_EV_DIR_FIFO_DATA : CUSTOM_IIO_EV_DIR_FIFO_EMPTY; @@ -439,10 +430,8 @@ int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw) int err; mutex_lock(&hw->fifo_lock); - st_asm330lhh_read_fifo(hw); err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_BYPASS); - mutex_unlock(&hw->fifo_lock); return err; @@ -468,8 +457,6 @@ int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable) if (err < 0) goto out; - hw->odr = st_asm330lhh_ts_odr(hw); - if (enable && hw->fifo_mode == ST_ASM330LHH_FIFO_BYPASS) { st_asm330lhh_reset_hwts(hw); err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_CONT); @@ -491,6 +478,9 @@ static irqreturn_t st_asm330lhh_handler_irq(int irq, void *private) hw->delta_ts = ts - hw->ts; hw->ts = ts; + if (hw->asm330_hrtimer) + st_asm330lhh_hrtimer_reset(hw, hw->delta_ts); + return IRQ_WAKE_THREAD; } @@ -499,12 +489,13 @@ static irqreturn_t st_asm330lhh_handler_thread(int irq, void *private) struct st_asm330lhh_hw *hw = (struct st_asm330lhh_hw *)private; mutex_lock(&hw->fifo_lock); - st_asm330lhh_read_fifo(hw); clear_bit(ST_ASM330LHH_HW_FLUSH, &hw->state); - mutex_unlock(&hw->fifo_lock); + if (hw->asm330_hrtimer) + st_asm330lhh_set_cpu_idle_state(false); + return IRQ_HANDLED; } @@ -548,6 +539,8 @@ int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw) int i, err; irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); + if (irq_type == IRQF_TRIGGER_NONE) + irq_type = IRQF_TRIGGER_HIGH; switch (irq_type) { case IRQF_TRIGGER_HIGH: @@ -605,4 +598,3 @@ int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw) return st_asm330lhh_fifo_init(hw); } - diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c index 623de5df44d25974758f7edc998bdb0d451719c5..eca46591737087b6fd5a26e64b97f21ef1666cfc 100644 --- a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c +++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -26,18 +27,24 @@ #define ST_ASM330LHH_REG_INT2_ADDR 0x0e #define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR 0x0a #define ST_ASM330LHH_REG_FIFO_FTH_IRQ_MASK BIT(3) + #define ST_ASM330LHH_REG_WHOAMI_ADDR 0x0f #define ST_ASM330LHH_WHOAMI_VAL 0x6b #define ST_ASM330LHH_REG_CTRL1_XL_ADDR 0x10 #define ST_ASM330LHH_REG_CTRL2_G_ADDR 0x11 + #define ST_ASM330LHH_REG_RESET_ADDR 0x12 #define ST_ASM330LHH_REG_RESET_MASK BIT(0) + #define ST_ASM330LHH_REG_BDU_ADDR 0x12 #define ST_ASM330LHH_REG_BDU_MASK BIT(6) -#define ST_ASM330LHH_REG_INT2_ON_INT1_ADDR 0x13 -#define ST_ASM330LHH_REG_INT2_ON_INT1_MASK BIT(5) + +#define ST_ASM330LHH_REG_CTRL4_C_ADDR 0x13 +#define ST_ASM330LHH_REG_DRDY_MASK BIT(3) + #define ST_ASM330LHH_REG_ROUNDING_ADDR 0x14 #define ST_ASM330LHH_REG_ROUNDING_MASK GENMASK(6, 5) + #define ST_ASM330LHH_REG_TIMESTAMP_EN_ADDR 0x19 #define ST_ASM330LHH_REG_TIMESTAMP_EN_MASK BIT(5) @@ -64,6 +71,8 @@ #define ST_ASM330LHH_GYRO_FS_2000_GAIN IIO_DEGREE_TO_RAD(70000) #define ST_ASM330LHH_GYRO_FS_4000_GAIN IIO_DEGREE_TO_RAD(140000) +#define ST_ASM330LHH_INTERNAL_FREQ_FINE 0x63 + /* Temperature in uC */ #define ST_ASM330LHH_TEMP_GAIN 256 #define ST_ASM330LHH_TEMP_FS_GAIN (1000000 / ST_ASM330LHH_TEMP_GAIN) @@ -184,6 +193,33 @@ static const struct iio_chan_spec st_asm330lhh_temp_channels[] = { }, }; +void st_asm330lhh_set_cpu_idle_state(bool value) +{ + cpu_idle_poll_ctrl(value); +} +static enum hrtimer_restart st_asm330lhh_timer_function( + struct hrtimer *timer) +{ + st_asm330lhh_set_cpu_idle_state(true); + + return HRTIMER_NORESTART; +} +void st_asm330lhh_hrtimer_reset(struct st_asm330lhh_hw *hw, + s64 irq_delta_ts) +{ + hrtimer_cancel(&hw->st_asm330lhh_hrtimer); + /*forward HRTIMER just before 1ms of irq arrival*/ + hrtimer_forward(&hw->st_asm330lhh_hrtimer, ktime_get(), + ns_to_ktime(irq_delta_ts - 1000000)); + hrtimer_restart(&hw->st_asm330lhh_hrtimer); +} +static void st_asm330lhh_hrtimer_init(struct st_asm330lhh_hw *hw) +{ + hrtimer_init(&hw->st_asm330lhh_hrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + hw->st_asm330lhh_hrtimer.function = st_asm330lhh_timer_function; +} + int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask, u8 val) { @@ -230,6 +266,30 @@ static int st_asm330lhh_check_whoami(struct st_asm330lhh_hw *hw) return 0; } +static int st_asm330lhh_get_odr_calibration(struct st_asm330lhh_hw *hw) +{ + s64 odr_calib; + int err; + s8 data; + + err = hw->tf->read(hw->dev, + ST_ASM330LHH_INTERNAL_FREQ_FINE, + sizeof(data), (u8 *)&data); + if (err < 0) { + dev_err(hw->dev, "failed to read %d register\n", + ST_ASM330LHH_INTERNAL_FREQ_FINE); + return err; + } + + odr_calib = (data * 37500) / 1000; + hw->ts_delta_ns = ST_ASM330LHH_TS_DELTA_NS - odr_calib; + + dev_info(hw->dev, "Freq Fine %lld (ts %lld)\n", + odr_calib, hw->ts_delta_ns); + + return 0; +} + static int st_asm330lhh_set_full_scale(struct st_asm330lhh_sensor *sensor, u32 gain) { @@ -507,8 +567,9 @@ static int asm_read_bootsampl(struct st_asm330lhh_sensor *sensor, { int i = 0; + sensor->buffer_asm_samples = false; + if (enable_read) { - sensor->buffer_asm_samples = false; for (i = 0; i < sensor->bufsample_cnt; i++) { dev_dbg(sensor->hw->dev, "sensor:%d count:%d x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n", @@ -535,7 +596,6 @@ static int asm_read_bootsampl(struct st_asm330lhh_sensor *sensor, for (i = 0; i < ASM_MAXSAMPLE; i++) kmem_cache_free(sensor->asm_cachepool, sensor->asm_samplist[i]); - kmem_cache_destroy(sensor->asm_cachepool); sensor->bufsample_cnt = 0; } @@ -572,10 +632,15 @@ static ssize_t read_gyro_boot_sample_store(struct device *dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } + + mutex_lock(&sensor->sensor_buff); err = asm_read_bootsampl(sensor, enable); + mutex_unlock(&sensor->sensor_buff); if (err) return err; + sensor->read_boot_sample = enable; + return count; } @@ -607,10 +672,15 @@ static ssize_t read_acc_boot_sample_store(struct device *dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } + + mutex_lock(&sensor->sensor_buff); err = asm_read_bootsampl(sensor, enable); + mutex_unlock(&sensor->sensor_buff); if (err) return err; + sensor->read_boot_sample = enable; + return count; } #endif @@ -775,6 +845,12 @@ static int st_asm330lhh_init_device(struct st_asm330lhh_hw *hw) if (err < 0) return err; + /* enable DRDY MASK for filters settling time */ + err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_CTRL4_C_ADDR, + ST_ASM330LHH_REG_DRDY_MASK, 1); + if (err < 0) + return err; + /* enable FIFO watermak interrupt */ err = st_asm330lhh_get_drdy_reg(hw, &drdy_int_reg); if (err < 0) @@ -996,6 +1072,8 @@ static int asm330_acc_gyro_early_buff_init(struct st_asm330lhh_hw *hw) acc->buffer_asm_samples = true; gyro->buffer_asm_samples = true; + mutex_init(&acc->sensor_buff); + mutex_init(&gyro->sensor_buff); return 1; clean_exit5: @@ -1043,6 +1121,7 @@ int st_asm330lhh_probe(struct device *dev, int irq, mutex_init(&hw->lock); mutex_init(&hw->fifo_lock); + mutex_init(&hw->page_lock); hw->dev = dev; hw->irq = irq; @@ -1062,11 +1141,18 @@ int st_asm330lhh_probe(struct device *dev, int irq, msleep(ST_ASM330LHH_TURN_ON_TIME); } + /* use hrtimer if property is enabled */ + hw->asm330_hrtimer = of_property_read_bool(np, "qcom,asm330_hrtimer"); + dev_info(hw->dev, "Ver: %s\n", ST_ASM330LHH_VERSION); err = st_asm330lhh_check_whoami(hw); if (err < 0) return err; + err = st_asm330lhh_get_odr_calibration(hw); + if (err < 0) + return err; + err = st_asm330lhh_init_device(hw); if (err < 0) return err; @@ -1096,6 +1182,9 @@ int st_asm330lhh_probe(struct device *dev, int irq, if (!err) return err; + if (hw->asm330_hrtimer) + st_asm330lhh_hrtimer_init(hw); + st_asm330lhh_enable_acc_gyro(hw); dev_info(hw->dev, "probe ok\n"); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 5d05c38c4ba9c83c062f333bcd96970a8cf085ce..2f037cd59d53c95b79a73e8d0432cd1b05356188 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -546,7 +546,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) { unsigned bytes = 0; - int length, i; + int length, i, largest = 0; /* How much space will the demuxed element take? */ for_each_set_bit(i, mask, @@ -554,13 +554,17 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, length = iio_storage_bytes_for_si(indio_dev, i); bytes = ALIGN(bytes, length); bytes += length; + largest = max(largest, length); } if (timestamp) { length = iio_storage_bytes_for_timestamp(indio_dev); bytes = ALIGN(bytes, length); bytes += length; + largest = max(largest, length); } + + bytes = ALIGN(bytes, largest); return bytes; } diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c index b05946604f804ca333c988762ab5dc54ae217f40..6d5bb11594dc16e308eaaad2c71439f0fc08638d 100644 --- a/drivers/iio/light/bh1750.c +++ b/drivers/iio/light/bh1750.c @@ -62,9 +62,9 @@ struct bh1750_chip_info { u16 int_time_low_mask; u16 int_time_high_mask; -} +}; -static const bh1750_chip_info_tbl[] = { +static const struct bh1750_chip_info bh1750_chip_info_tbl[] = { [BH1710] = { 140, 1022, 300, 400, 250000000, 2, 0x001F, 0x03E0 }, [BH1721] = { 140, 1020, 300, 400, 250000000, 2, 0x0010, 0x03E0 }, [BH1750] = { 31, 254, 69, 1740, 57500000, 1, 0x001F, 0x00E0 }, diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 1baa25e82bdd99a783941653bb520c57434efc2a..f7d23c1081dc489adf297c3ce504642c2a572e0d 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -141,7 +141,7 @@ int ib_nl_handle_ip_res_resp(struct sk_buff *skb, if (ib_nl_is_good_ip_resp(nlh)) ib_nl_process_good_ip_rsep(nlh); - return skb->len; + return 0; } static int ib_nl_ip_send_msg(struct rdma_dev_addr *dev_addr, diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 71c7c4c328ef6bb438273395eb9b2d40667e5da3..304429fd04ddb664d824aeb19db3b354679e3a34 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -1073,6 +1073,7 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device, /* Sharing an ib_cm_id with different handlers is not * supported */ spin_unlock_irqrestore(&cm.lock, flags); + ib_destroy_cm_id(cm_id); return ERR_PTR(-EINVAL); } atomic_inc(&cm_id_priv->refcount); diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index dcfbf326f45c9110c57da13fea7142bfa9116712..27653aad8f2189df77afbcb8d8faf068ef6d135c 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -4440,6 +4440,7 @@ static int __init cma_init(void) unregister_netdevice_notifier(&cma_nb); rdma_addr_unregister_client(&addr_client); ib_sa_unregister_client(&sa_client); + unregister_pernet_subsys(&cma_pernet_operations); err_wq: destroy_workqueue(cma_wq); return ret; diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 5495e22839a7eb4f2c96d44e8dfb9b1531661446..1f71c306923f67697d67aa5226efb06bed2a2b87 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -137,8 +137,10 @@ static void dealloc_work_entries(struct iwcm_id_private *cm_id_priv) { struct list_head *e, *tmp; - list_for_each_safe(e, tmp, &cm_id_priv->work_free_list) + list_for_each_safe(e, tmp, &cm_id_priv->work_free_list) { + list_del(e); kfree(list_entry(e, struct iwcm_work, free_list)); + } } static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count) diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 5879a06ada9383490f08d1ca100f5297158e0101..1c459725d64e7fb4c37291a52d730dc4cd0d8bad 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -848,7 +848,7 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb, } settimeout_out: - return skb->len; + return 0; } static inline int ib_nl_is_good_resolve_resp(const struct nlmsghdr *nlh) @@ -920,7 +920,7 @@ int ib_nl_handle_resolve_resp(struct sk_buff *skb, } resp_out: - return skb->len; + return 0; } static void free_sm_ah(struct kref *kref) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 605d50ad123ccd5602e8b206019fddb8773200bc..a04a53acb24ffe5b07afc5ed3a225bba3fe88225 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -2044,7 +2044,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, } else { pdev = get_real_dev(n->dev); ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, - n, pdev, 0); + n, pdev, rt_tos2priority(tos)); if (!ep->l2t) goto out; ep->mtu = dst_mtu(dst); @@ -2135,7 +2135,8 @@ static int c4iw_reconnect(struct c4iw_ep *ep) laddr6->sin6_addr.s6_addr, raddr6->sin6_addr.s6_addr, laddr6->sin6_port, - raddr6->sin6_port, 0, + raddr6->sin6_port, + ep->com.cm_id->tos, raddr6->sin6_scope_id); iptype = 6; ra = (__u8 *)&raddr6->sin6_addr; @@ -3278,7 +3279,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) laddr6->sin6_addr.s6_addr, raddr6->sin6_addr.s6_addr, laddr6->sin6_port, - raddr6->sin6_port, 0, + raddr6->sin6_port, cm_id->tos, raddr6->sin6_scope_id); } if (!ep->dst) { diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.h b/drivers/infiniband/hw/hns/hns_roce_hem.h index 435748858252d756d065315e5ce4347db46c4477..8e8917ebb013b375c15e443d7524547b967383ae 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.h +++ b/drivers/infiniband/hw/hns/hns_roce_hem.h @@ -52,7 +52,7 @@ enum { #define HNS_ROCE_HEM_CHUNK_LEN \ ((256 - sizeof(struct list_head) - 2 * sizeof(int)) / \ - (sizeof(struct scatterlist))) + (sizeof(struct scatterlist) + sizeof(void *))) enum { HNS_ROCE_HEM_PAGE_SHIFT = 12, diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index 33cf1035030b57ce3ccd674e7fc74c4009ebb6f6..6f3c0ea99dd05d0d4b61dd451e58c99cc27f682d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c @@ -241,7 +241,6 @@ void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp) if ((hr_qp->ibqp.qp_type) != IB_QPT_GSI) { hns_roce_table_put(hr_dev, &qp_table->irrl_table, hr_qp->qpn); - hns_roce_table_put(hr_dev, &qp_table->qp_table, hr_qp->qpn); } } diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 7ccf7225f75a7987af7bd6b812849e39e9f617b8..adc46b809ef2a057832a6feabce1929c39ea51c8 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -3031,16 +3031,17 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) ibdev->ib_active = false; flush_workqueue(wq); - mlx4_ib_close_sriov(ibdev); - mlx4_ib_mad_cleanup(ibdev); - ib_unregister_device(&ibdev->ib_dev); - mlx4_ib_diag_cleanup(ibdev); if (ibdev->iboe.nb.notifier_call) { if (unregister_netdevice_notifier(&ibdev->iboe.nb)) pr_warn("failure unregistering notifier\n"); ibdev->iboe.nb.notifier_call = NULL; } + mlx4_ib_close_sriov(ibdev); + mlx4_ib_mad_cleanup(ibdev); + ib_unregister_device(&ibdev->ib_dev); + mlx4_ib_diag_cleanup(ibdev); + mlx4_qp_release_range(dev, ibdev->steer_qpn_base, ibdev->steer_qpn_count); kfree(ibdev->ib_uc_qpns_bitmap); diff --git a/drivers/infiniband/hw/mlx4/sysfs.c b/drivers/infiniband/hw/mlx4/sysfs.c index 69fb5ba94d0f226c11a8614b29be4c33df329040..19caacd26f61a932a9116f5c77129d86bee7e617 100644 --- a/drivers/infiniband/hw/mlx4/sysfs.c +++ b/drivers/infiniband/hw/mlx4/sysfs.c @@ -352,16 +352,12 @@ static int add_port_entries(struct mlx4_ib_dev *device, int port_num) static void get_name(struct mlx4_ib_dev *dev, char *name, int i, int max) { - char base_name[9]; - - /* pci_name format is: bus:dev:func -> xxxx:yy:zz.n */ - strlcpy(name, pci_name(dev->dev->persist->pdev), max); - strncpy(base_name, name, 8); /*till xxxx:yy:*/ - base_name[8] = '\0'; - /* with no ARI only 3 last bits are used so when the fn is higher than 8 + /* pci_name format is: bus:dev:func -> xxxx:yy:zz.n + * with no ARI only 3 last bits are used so when the fn is higher than 8 * need to add it to the dev num, so count in the last number will be * modulo 8 */ - sprintf(name, "%s%.2d.%d", base_name, (i/8), (i%8)); + snprintf(name, max, "%.8s%.2d.%d", pci_name(dev->dev->persist->pdev), + i / 8, i % 8); } struct mlx4_port { diff --git a/drivers/infiniband/hw/mlx5/gsi.c b/drivers/infiniband/hw/mlx5/gsi.c index 79e6309460dc509777324a9875e46573b7d38070..262c18b2f5252dd967fb32b94b6044bb94140c46 100644 --- a/drivers/infiniband/hw/mlx5/gsi.c +++ b/drivers/infiniband/hw/mlx5/gsi.c @@ -507,8 +507,7 @@ int mlx5_ib_gsi_post_send(struct ib_qp *qp, struct ib_send_wr *wr, ret = ib_post_send(tx_qp, &cur_wr.wr, bad_wr); if (ret) { /* Undo the effect of adding the outstanding wr */ - gsi->outstanding_pi = (gsi->outstanding_pi - 1) % - gsi->cap.max_send_wr; + gsi->outstanding_pi--; goto err; } spin_unlock_irqrestore(&gsi->lock, flags); diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index a7bc89f5dae7e1f4c3e4322e460d9dd7a08f61f7..4d906a79048187217027f0915261f2c4561a0adb 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -2324,6 +2324,11 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_PKEY_INDEX | MLX5_QP_OPTPAR_Q_KEY | MLX5_QP_OPTPAR_PRI_PORT, + [MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PKEY_INDEX | + MLX5_QP_OPTPAR_PRI_PORT, }, [MLX5_QP_STATE_RTR] = { [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH | @@ -2357,6 +2362,12 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q MLX5_QP_OPTPAR_RWE | MLX5_QP_OPTPAR_PM_STATE, [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY, + [MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH | + MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PM_STATE | + MLX5_QP_OPTPAR_RNR_TIMEOUT, }, }, [MLX5_QP_STATE_RTS] = { @@ -2373,6 +2384,12 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY | MLX5_QP_OPTPAR_SRQN | MLX5_QP_OPTPAR_CQN_RCV, + [MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_RNR_TIMEOUT | + MLX5_QP_OPTPAR_PM_STATE | + MLX5_QP_OPTPAR_ALT_ADDR_PATH, }, }, [MLX5_QP_STATE_SQER] = { @@ -2384,6 +2401,10 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q MLX5_QP_OPTPAR_RWE | MLX5_QP_OPTPAR_RAE | MLX5_QP_OPTPAR_RRE, + [MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_RNR_TIMEOUT | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RRE, }, }, }; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 6af44f8db3d5499d46c584ac7fb386c1263f033d..4d28bd8eff01c806d20e281f135f7a23233c9e6b 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -55,7 +55,7 @@ int ocrdma_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) { - if (index > 1) + if (index > 0) return -EINVAL; *pkey = 0xffff; diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index cd0408c2b376f3056e26a23963002c048125f1b1..7603a1641c7d898393b6ff33bb049cdfffff5161 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -54,7 +54,7 @@ int qedr_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) { - if (index > QEDR_ROCE_PKEY_TABLE_LEN) + if (index >= QEDR_ROCE_PKEY_TABLE_LEN) return -EINVAL; *pkey = QEDR_ROCE_PKEY_DEFAULT; diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c index fe4cf5e4acec696a475248c9dffbf2a7bc6b0293..8ce0f6eef89e4b0391ecaa1f92e748d0b5e64b5d 100644 --- a/drivers/infiniband/hw/qib/qib_sysfs.c +++ b/drivers/infiniband/hw/qib/qib_sysfs.c @@ -301,6 +301,9 @@ static ssize_t qib_portattr_show(struct kobject *kobj, struct qib_pportdata *ppd = container_of(kobj, struct qib_pportdata, pport_kobj); + if (!pattr->show) + return -EIO; + return pattr->show(ppd, buf); } @@ -312,6 +315,9 @@ static ssize_t qib_portattr_store(struct kobject *kobj, struct qib_pportdata *ppd = container_of(kobj, struct qib_pportdata, pport_kobj); + if (!pattr->store) + return -EIO; + return pattr->store(ppd, buf, len); } diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c index a5bfbba6bbac0e9d918462ebb37d041608b9d321..cacb720f44a02d6347dcb271e66a9c9313efed28 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c @@ -425,7 +425,7 @@ int usnic_ib_query_gid(struct ib_device *ibdev, u8 port, int index, int usnic_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) { - if (index > 1) + if (index > 0) return -EINVAL; *pkey = 0xffff; diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c index e5e6a5e7dee9c36d90ab98b0720df276ab38fa68..5ac88412f1ffedd40067b920090068732c62b2dd 100644 --- a/drivers/infiniband/sw/rxe/rxe_cq.c +++ b/drivers/infiniband/sw/rxe/rxe_cq.c @@ -30,7 +30,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - +#include #include "rxe.h" #include "rxe_loc.h" #include "rxe_queue.h" @@ -89,7 +89,7 @@ int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe, err = do_mmap_info(rxe, udata, false, context, cq->queue->buf, cq->queue->buf_size, &cq->queue->ip); if (err) { - kvfree(cq->queue->buf); + vfree(cq->queue->buf); kfree(cq->queue); return err; } diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index 44b2108253bd988ec1f5222da999575ed37d3bed..d6672127808b7216f2745e2285c55f7150eacbca 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "rxe.h" #include "rxe_loc.h" @@ -255,7 +256,7 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, qp->sq.queue->buf_size, &qp->sq.queue->ip); if (err) { - kvfree(qp->sq.queue->buf); + vfree(qp->sq.queue->buf); kfree(qp->sq.queue); return err; } @@ -312,7 +313,7 @@ static int rxe_qp_init_resp(struct rxe_dev *rxe, struct rxe_qp *qp, qp->rq.queue->buf_size, &qp->rq.queue->ip); if (err) { - kvfree(qp->rq.queue->buf); + vfree(qp->rq.queue->buf); kfree(qp->rq.queue); return err; } diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h index 47003d2a4a46e5bae1a4ee40ba7d4960a221a0ba..dee3853163b6007c5405f9839e58f9640db4fbce 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.h +++ b/drivers/infiniband/sw/rxe/rxe_verbs.h @@ -422,7 +422,7 @@ struct rxe_dev { struct list_head pending_mmaps; spinlock_t mmap_offset_lock; /* guard mmap_offset */ - int mmap_offset; + u64 mmap_offset; struct rxe_port port; struct list_head list; diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index e46e2b095c18454e59040fe8a374de43f3c7a02e..fdf5179a81c100908bb77fc9789542307fa87e24 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -649,6 +649,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep, if (ib_conn->pi_support) { u32 sig_caps = ib_conn->device->ib_device->attrs.sig_prot_cap; + shost->sg_prot_tablesize = shost->sg_tablesize; scsi_host_set_prot(shost, iser_dif_prot_caps(sig_caps)); scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP | SHOST_DIX_GUARD_CRC); diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index cb48e22afff724c0810bc6e8f7ed51695c6f18e9..a3614f7f0007370e9e6b26b815c9d3d9e0ba7f4d 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -197,7 +197,7 @@ struct iser_data_buf { struct scatterlist *sg; int size; unsigned long data_len; - unsigned int dma_nents; + int dma_nents; }; /* fwd declarations */ diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c index 9c3e9ab53a415710b0e8bef65647efc4716dc239..759c2fe033e717e2183c239e52f625be63304255 100644 --- a/drivers/infiniband/ulp/iser/iser_memory.c +++ b/drivers/infiniband/ulp/iser/iser_memory.c @@ -240,8 +240,8 @@ int iser_fast_reg_fmr(struct iscsi_iser_task *iser_task, page_vec->npages = 0; page_vec->fake_mr.page_size = SIZE_4K; plen = ib_sg_to_pages(&page_vec->fake_mr, mem->sg, - mem->size, NULL, iser_set_page); - if (unlikely(plen < mem->size)) { + mem->dma_nents, NULL, iser_set_page); + if (unlikely(plen < mem->dma_nents)) { iser_err("page vec too short to hold this SG\n"); iser_data_buf_dump(mem, device->ib_device); iser_dump_page_vec(page_vec); @@ -450,10 +450,10 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task, ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey)); - n = ib_map_mr_sg(mr, mem->sg, mem->size, NULL, SIZE_4K); - if (unlikely(n != mem->size)) { + n = ib_map_mr_sg(mr, mem->sg, mem->dma_nents, NULL, SIZE_4K); + if (unlikely(n != mem->dma_nents)) { iser_err("failed to map sg (%d/%d)\n", - n, mem->size); + n, mem->dma_nents); return n < 0 ? n : -EINVAL; } diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 827dc578934a2929ebfc3e3c5366d00f8194f125..d28e57ca6e6b641a9e46ae0800f845b100b95a04 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1234,9 +1234,11 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch, struct srpt_send_ioctx *ioctx, u64 tag, int status) { + struct se_cmd *cmd = &ioctx->cmd; struct srp_rsp *srp_rsp; const u8 *sense_data; int sense_data_len, max_sense_len; + u32 resid = cmd->residual_count; /* * The lowest bit of all SAM-3 status codes is zero (see also @@ -1258,6 +1260,28 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch, srp_rsp->tag = tag; srp_rsp->status = status; + if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { + if (cmd->data_direction == DMA_TO_DEVICE) { + /* residual data from an underflow write */ + srp_rsp->flags = SRP_RSP_FLAG_DOUNDER; + srp_rsp->data_out_res_cnt = cpu_to_be32(resid); + } else if (cmd->data_direction == DMA_FROM_DEVICE) { + /* residual data from an underflow read */ + srp_rsp->flags = SRP_RSP_FLAG_DIUNDER; + srp_rsp->data_in_res_cnt = cpu_to_be32(resid); + } + } else if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { + if (cmd->data_direction == DMA_TO_DEVICE) { + /* residual data from an overflow write */ + srp_rsp->flags = SRP_RSP_FLAG_DOOVER; + srp_rsp->data_out_res_cnt = cpu_to_be32(resid); + } else if (cmd->data_direction == DMA_FROM_DEVICE) { + /* residual data from an overflow read */ + srp_rsp->flags = SRP_RSP_FLAG_DIOVER; + srp_rsp->data_in_res_cnt = cpu_to_be32(resid); + } + } + if (sense_data_len) { BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp)); max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp); diff --git a/drivers/input/input.c b/drivers/input/input.c index d95c34ee5dc1430f5664e8b50d449f01c802ae4a..5d94fc3fce0bb4abbd47e4adb86cd20cd29fda36 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -850,16 +850,18 @@ static int input_default_setkeycode(struct input_dev *dev, } } - __clear_bit(*old_keycode, dev->keybit); - __set_bit(ke->keycode, dev->keybit); - - for (i = 0; i < dev->keycodemax; i++) { - if (input_fetch_keycode(dev, i) == *old_keycode) { - __set_bit(*old_keycode, dev->keybit); - break; /* Setting the bit twice is useless, so break */ + if (*old_keycode <= KEY_MAX) { + __clear_bit(*old_keycode, dev->keybit); + for (i = 0; i < dev->keycodemax; i++) { + if (input_fetch_keycode(dev, i) == *old_keycode) { + __set_bit(*old_keycode, dev->keybit); + /* Setting the bit twice is useless, so break */ + break; + } } } + __set_bit(ke->keycode, dev->keybit); return 0; } @@ -915,9 +917,13 @@ int input_set_keycode(struct input_dev *dev, * Simulate keyup event if keycode is not present * in the keymap anymore */ - if (test_bit(EV_KEY, dev->evbit) && - !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && - __test_and_clear_bit(old_keycode, dev->key)) { + if (old_keycode > KEY_MAX) { + dev_warn(dev->dev.parent ?: &dev->dev, + "%s: got too big old keycode %#x\n", + __func__, old_keycode); + } else if (test_bit(EV_KEY, dev->evbit) && + !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && + __test_and_clear_bit(old_keycode, dev->key)) { struct input_value vals[] = { { EV_KEY, old_keycode, 0 }, input_value_sync diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 8567ee47761e111b31f7c8270bdc6414de6668a1..ae3b04557074010bc708c48db877c486f9d1cd0a 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -100,7 +100,7 @@ static int __init ske_keypad_chip_init(struct ske_keypad *keypad) while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--) cpu_relax(); - if (!timeout) + if (timeout == -1) return -EINVAL; /* diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index a3fe4a990cc95c8f228b7abf5b725532c07086ca..c7b889d13eddd33076a922bf5fc86e540e8783a0 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c @@ -344,7 +344,8 @@ static int keyspan_setup(struct usb_device* dev) int retval = 0; retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0); + 0x11, 0x40, 0x5601, 0x0, NULL, 0, + USB_CTRL_SET_TIMEOUT); if (retval) { dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n", __func__, retval); @@ -352,7 +353,8 @@ static int keyspan_setup(struct usb_device* dev) } retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x44, 0x40, 0x0, 0x0, NULL, 0, 0); + 0x44, 0x40, 0x0, 0x0, NULL, 0, + USB_CTRL_SET_TIMEOUT); if (retval) { dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n", __func__, retval); @@ -360,7 +362,8 @@ static int keyspan_setup(struct usb_device* dev) } retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x22, 0x40, 0x0, 0x0, NULL, 0, 0); + 0x22, 0x40, 0x0, 0x0, NULL, 0, + USB_CTRL_SET_TIMEOUT); if (retval) { dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n", __func__, retval); diff --git a/drivers/input/sensors/smi130/smi130_acc.c b/drivers/input/sensors/smi130/smi130_acc.c index 856485063eb307441132dc52ed14a3cb1c2b61ab..3a667a0709b778051e473be667d468a2fb4bb4c9 100644 --- a/drivers/input/sensors/smi130/smi130_acc.c +++ b/drivers/input/sensors/smi130/smi130_acc.c @@ -1609,6 +1609,7 @@ struct smi130_acc_data { int max_buffer_time; struct input_dev *accbuf_dev; int report_evt_cnt; + struct mutex acc_sensor_buff; #endif #ifdef SMI130_HRTIMER struct hrtimer smi130_hrtimer; @@ -6553,8 +6554,9 @@ static int smi_acc_read_bootsampl(struct smi130_acc_data *client_data, { int i = 0; + client_data->acc_buffer_smi130_samples = false; + if (enable_read) { - client_data->acc_buffer_smi130_samples = false; for (i = 0; i < client_data->acc_bufsample_cnt; i++) { if (client_data->debug_level & 0x08) PINFO("acc=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n", @@ -6621,7 +6623,9 @@ static ssize_t read_acc_boot_sample_store(struct device *dev, PERR("Invalid value of input, input=%ld\n", enable); return -EINVAL; } + mutex_lock(&smi130_acc->acc_sensor_buff); err = smi_acc_read_bootsampl(smi130_acc, enable); + mutex_unlock(&smi130_acc->acc_sensor_buff); if (err) return err; @@ -6963,6 +6967,7 @@ static void store_acc_boot_sample(struct smi130_acc_data *client_data, { if (false == client_data->acc_buffer_smi130_samples) return; + mutex_lock(&client_data->acc_sensor_buff); if (ts.tv_sec < client_data->max_buffer_time) { if (client_data->acc_bufsample_cnt < SMI_ACC_MAXSAMPLE) { client_data->smi130_acc_samplist[client_data-> @@ -6985,6 +6990,7 @@ static void store_acc_boot_sample(struct smi130_acc_data *client_data, smi130_acc_set_mode(client_data->smi130_acc_client, SMI_ACC2X2_MODE_SUSPEND, 1); } + mutex_unlock(&client_data->acc_sensor_buff); } #else static void store_acc_boot_sample(struct smi130_acc_data *client_data, @@ -7055,6 +7061,8 @@ static int smi130_acc_early_buff_init(struct i2c_client *client, smi130_set_cpu_idle_state(true); + mutex_init(&client_data->acc_sensor_buff); + smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1); smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ); smi130_acc_set_range(client, SMI_ACC2X2_RANGE_2G); diff --git a/drivers/input/sensors/smi130/smi130_gyro_driver.c b/drivers/input/sensors/smi130/smi130_gyro_driver.c index e497a0a8a4bbf4c742b213d858d49a301942bef1..61b59339b7b5f46df2cdc1cd46cee2137f446671 100644 --- a/drivers/input/sensors/smi130/smi130_gyro_driver.c +++ b/drivers/input/sensors/smi130/smi130_gyro_driver.c @@ -300,6 +300,7 @@ struct smi_gyro_client_data { int max_buffer_time; struct input_dev *gyrobuf_dev; int report_evt_cnt; + struct mutex gyro_sensor_buff; #endif }; @@ -1521,8 +1522,8 @@ static int smi_gyro_read_bootsampl(struct smi_gyro_client_data *client_data, { int i = 0; + client_data->gyro_buffer_smi130_samples = false; if (enable_read) { - client_data->gyro_buffer_smi130_samples = false; for (i = 0; i < client_data->gyro_bufsample_cnt; i++) { if (client_data->debug_level & 0x08) PINFO("gyro=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n", @@ -1588,7 +1589,9 @@ static ssize_t read_gyro_boot_sample_store(struct device *dev, PERR("Invalid value of input, input=%ld\n", enable); return -EINVAL; } + mutex_lock(&client_data->gyro_sensor_buff); err = smi_gyro_read_bootsampl(client_data, enable); + mutex_unlock(&client_data->gyro_sensor_buff); if (err) return err; client_data->read_gyro_boot_sample = enable; @@ -1740,6 +1743,7 @@ static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, { if (false == client_data->gyro_buffer_smi130_samples) return; + mutex_lock(&client_data->gyro_sensor_buff); if (ts.tv_sec < client_data->max_buffer_time) { if (client_data->gyro_bufsample_cnt < SMI_GYRO_MAXSAMPLE) { client_data->smi130_gyro_samplist[client_data-> @@ -1763,6 +1767,7 @@ static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, smi130_gyro_delay(5); } } + mutex_unlock(&client_data->gyro_sensor_buff); } #else static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, @@ -1832,6 +1837,7 @@ static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data) client_data->gyro_buffer_smi130_samples = true; client_data->gyro_enable = false; + mutex_init(&client_data->gyro_sensor_buff); smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL); smi130_gyro_delay(5); diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 4613f0aefd087b7dabe28750ed8b1e9de6e64646..5a7e5e073e526347458e29b105b14fa44be76273 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -1822,14 +1822,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); /* Verify that a device really has an endpoint */ - if (intf->altsetting[0].desc.bNumEndpoints < 1) { + if (intf->cur_altsetting->desc.bNumEndpoints < 1) { dev_err(&intf->dev, "interface has %d endpoints, but must have minimum 1\n", - intf->altsetting[0].desc.bNumEndpoints); + intf->cur_altsetting->desc.bNumEndpoints); err = -EINVAL; goto fail3; } - endpoint = &intf->altsetting[0].endpoint[0].desc; + endpoint = &intf->cur_altsetting->endpoint[0].desc; /* Go set up our URB, which is called when the tablet receives * input. diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 8af736dc4b18222ef8332ed0fce25897b537299c..dd8dc335daca726e162439123cad70f62bd199c6 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -875,18 +875,14 @@ static int gtco_probe(struct usb_interface *usbinterface, } /* Sanity check that a device has an endpoint */ - if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) { + if (usbinterface->cur_altsetting->desc.bNumEndpoints < 1) { dev_err(&usbinterface->dev, "Invalid number of endpoints\n"); error = -EINVAL; goto err_free_urb; } - /* - * The endpoint is always altsetting 0, we know this since we know - * this device only has one interrupt endpoint - */ - endpoint = &usbinterface->altsetting[0].endpoint[0].desc; + endpoint = &usbinterface->cur_altsetting->endpoint[0].desc; /* Some debug */ dev_dbg(&usbinterface->dev, "gtco # interfaces: %d\n", usbinterface->num_altsetting); @@ -973,7 +969,7 @@ static int gtco_probe(struct usb_interface *usbinterface, input_dev->dev.parent = &usbinterface->dev; /* Setup the URB, it will be posted later on open of input device */ - endpoint = &usbinterface->altsetting[0].endpoint[0].desc; + endpoint = &usbinterface->cur_altsetting->endpoint[0].desc; usb_fill_int_urb(gtco->urbinfo, udev, diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c index 47de5a81172f65a24a656361afdf244f2f61ff4e..2319144802c93ab08a1251eecf8bdde644884a43 100644 --- a/drivers/input/tablet/pegasus_notetaker.c +++ b/drivers/input/tablet/pegasus_notetaker.c @@ -260,7 +260,7 @@ static int pegasus_probe(struct usb_interface *intf, return -ENODEV; /* Sanity check that the device has an endpoint */ - if (intf->altsetting[0].desc.bNumEndpoints < 1) { + if (intf->cur_altsetting->desc.bNumEndpoints < 1) { dev_err(&intf->dev, "Invalid number of endpoints\n"); return -EINVAL; } diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 74276b0d992f4c591226d5e23f113f74e62f0ba6..106e57d5bf34f52ed3cf04e9459ede8a591f3272 100755 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1451,4 +1451,12 @@ config TOUCHSCREEN_EKTF3XXX_CHIPSET If unusre, say N. +config TOUCHSCREEN_RAYDIUM_CHIPSET + bool "Raydium WT030 touchpanel CHIPSET" + depends on I2C + help + Say Y here if you have a Raydium WT030 CHIPSET touchscreen. + + If unsure, say N. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index aa4efb1d3874c2887ba081d56dbcf474520d4461..a164c99791298749eebadc3405c6fd591cd4997f 100755 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -111,3 +111,4 @@ obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28) += gt9xx_v2.8/ obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += hxchipset83112b/ #[20200429][TracyChui]Touch driver porting end obj-$(CONFIG_TOUCHSCREEN_EKTF3XXX_CHIPSET) += ektf3xxx/ +obj-$(CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET) += raydium_wt030/ diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index c2fb0236a47cc6a3a0336d792ee4f63f8b844579..8d871fcb7912af9581754fb90b498ec92ac6627d 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3206,6 +3206,8 @@ static int __maybe_unused mxt_suspend(struct device *dev) mutex_unlock(&input_dev->mutex); + disable_irq(data->irq); + return 0; } @@ -3218,6 +3220,8 @@ static int __maybe_unused mxt_resume(struct device *dev) if (!input_dev) return 0; + enable_irq(data->irq); + mutex_lock(&input_dev->mutex); if (input_dev->users) diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index 44deca88c57972d2a65f3fca51ca852116f48810..c1c29d7487bf3403902f5ea8d7e4467f84203ba6 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -1972,11 +1972,6 @@ static int cyttsp4_mt_probe(struct cyttsp4 *cd) /* get sysinfo */ md->si = &cd->sysinfo; - if (!md->si) { - dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n", - __func__, md->si); - goto error_get_sysinfo; - } rc = cyttsp4_setup_input_device(cd); if (rc) @@ -1986,8 +1981,6 @@ static int cyttsp4_mt_probe(struct cyttsp4 *cd) error_init_input: input_free_device(md->input); -error_get_sysinfo: - input_set_drvdata(md->input, NULL); error_alloc_failed: dev_err(dev, "%s failed.\n", __func__); return rc; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 28466e358fee1dc6399ea8693dfd7e909fd29870..22c8d2070faac0f4ee5182b3d58fdbaa160866dc 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -887,6 +887,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, { const struct edt_i2c_chip_data *chip_data; struct edt_ft5x06_ts_data *tsdata; + u8 buf[2] = { 0xfc, 0x00 }; struct input_dev *input; unsigned long irq_flags; int error; @@ -956,6 +957,12 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; } + /* + * Dummy read access. EP0700MLP1 returns bogus data on the first + * register read access and ignores writes. + */ + edt_ft5x06_ts_readwrite(tsdata->client, 2, buf, 2, buf); + edt_ft5x06_ts_set_regs(tsdata); edt_ft5x06_ts_get_defaults(&client->dev, tsdata); edt_ft5x06_ts_get_parameters(tsdata); diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index c599b5a2373bf76f5eb65d1e826d04dfe37dff32..6a02e7301297d2edec4a05b8ac8902b039eca0ad 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -89,6 +89,15 @@ static const unsigned long goodix_irq_flags[] = { */ static const struct dmi_system_id rotated_screen[] = { #if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + .ident = "Teclast X89", + .matches = { + /* tPAD is too generic, also match on bios date */ + DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), + DMI_MATCH(DMI_BOARD_NAME, "tPAD"), + DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"), + }, + }, { .ident = "WinBook TW100", .matches = { diff --git a/drivers/input/touchscreen/raydium_wt030/Makefile b/drivers/input/touchscreen/raydium_wt030/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..982214b48bd02116526e5b3a0e6bb8017b24c299 --- /dev/null +++ b/drivers/input/touchscreen/raydium_wt030/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for the touchscreen raydium drivers. +# +obj-$(CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET) += raydium_driver.o raydium_sysfs.o raydium_fw_update.o diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_driver.c b/drivers/input/touchscreen/raydium_wt030/raydium_driver.c new file mode 100644 index 0000000000000000000000000000000000000000..c101c1fd364504eda9cc4bcb770b5ca54062af7e --- /dev/null +++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.c @@ -0,0 +1,2473 @@ +/* drivers/input/touchscreen/raydium_wt030/raydium_driver.c + * + * Raydium TouchScreen driver. + * + * Copyright (c) 2010 Raydium tech Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "raydium_driver.h" + +#if defined(CONFIG_FB) +#include +#include +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#endif /*end of CONFIG_FB*/ + +struct raydium_slot_status { + unsigned char pt_id; /*Occupied point ID*/ + unsigned char need_update; /*Mark as info need to be updated*/ + unsigned char pt_report_offset; /*point info offset in report*/ +}; +/*The first 3 elements are currently occupied. therest is new coming points*/ +struct raydium_slot_status gst_slot[MAX_TOUCH_NUM * 2]; +struct raydium_slot_status gst_slot_init = {0xFF, 0, 0}; + +unsigned char g_u8_addr; +unsigned char g_u8_raydium_flag; +unsigned char g_u8_i2c_mode; +unsigned char g_u8_upgrade_type; +unsigned char g_u8_raw_data_type; +unsigned int g_u32_raw_data_len; /* 72 bytes*/ +unsigned long g_u32_addr; +unsigned int g_u32_length; +unsigned int g_u32_driver_version; +unsigned char *g_rad_fw_image, *g_rad_init_image; +unsigned char *g_rad_boot_image, *g_rad_para_image; +unsigned char *g_rad_testfw_image, *g_rad_testpara_image; +unsigned char g_u8_table_setting, g_u8_table_init; +unsigned char g_u8_resetflag; +#ifdef ESD_SOLUTION_EN +unsigned char g_u8_checkflag; +#endif +#ifdef ENABLE_DUMP_DATA +unsigned char g_u8_dumpcount; +unsigned char g_u8_dump_flag; +unsigned char g_u8_palm_flag; +unsigned long timeout; +#endif +struct raydium_ts_data *g_raydium_ts; + +/***************************************************************************** + * Name: raydium_variable_init + * Brief: + * Input: + * Output: + * Return: + *****************************************************************************/ +static void raydium_variable_init(void) +{ + g_u8_addr = RAYDIUM_PDA2_PDA_CFG_ADDR; + g_u8_raydium_flag = 0; + g_u8_i2c_mode = PDA2_MODE; + g_u8_upgrade_type = 0; + g_u8_raw_data_type = RAYDIUM_FT_UPDATE; + g_u32_raw_data_len = 36 * 2; /* 72 bytes*/ + g_u32_addr = RAD_CHK_I2C_CMD; + g_u32_length = 1; + g_u8_table_setting = 0; + g_u8_table_init = 0; + g_rad_fw_image = NULL; + g_rad_init_image = NULL; + g_rad_boot_image = NULL; + g_rad_para_image = NULL; + g_rad_testfw_image = NULL; + g_rad_testpara_image = NULL; + g_u32_driver_version = ((RAD_MAIN_VERSION << 24) | + (RAD_MINOR_VERSION << 16) | + (RAD_CUSTOMER_VERSION)); + g_u8_resetflag = false; +#ifdef ESD_SOLUTION_EN + g_u8_checkflag = false; +#endif +#ifdef ENABLE_DUMP_DATA + g_u8_dumpcount = 0; + g_u8_dump_flag = false; + g_u8_palm_flag = false; +#endif +} + +/***************************************************************************** + * Name: raydium_gpio_configure + * Brief: + * Input: + * Output: + * Return: + *****************************************************************************/ +static int raydium_gpio_configure(bool on) +{ + int i32_err = 0; + + if (on) { + if (gpio_is_valid(g_raydium_ts->irq_gpio)) { + i32_err = gpio_request(g_raydium_ts->irq_gpio, + "raydium_irq_gpio"); + if (i32_err) { + dev_err(&g_raydium_ts->client->dev, + "[touch]irq gpio request failed"); + goto err_irq_gpio_req; + } + + i32_err = gpio_direction_input(g_raydium_ts->irq_gpio); + if (i32_err) { + dev_err(&g_raydium_ts->client->dev, + "[touch]set_direction for irq gpio failed\n"); + goto err_irq_gpio_dir; + } + } + if (gpio_is_valid(g_raydium_ts->rst_gpio)) { + i32_err = gpio_request(g_raydium_ts->rst_gpio, + "raydium_rst_gpio"); + if (i32_err) { + dev_err(&g_raydium_ts->client->dev, + "[touch]rst gpio request failed"); + goto err_irq_gpio_req; + } + + i32_err = gpio_direction_output(g_raydium_ts->rst_gpio, + 1); + if (i32_err) { + dev_err(&g_raydium_ts->client->dev, + "[touch]set_direction for irq gpio failed\n"); + goto err_rst_gpio_dir; + } + } + } else { + if (gpio_is_valid(g_raydium_ts->irq_gpio)) + gpio_free(g_raydium_ts->irq_gpio); + } + + return 0; + +err_rst_gpio_dir: + if (gpio_is_valid(g_raydium_ts->rst_gpio)) + gpio_free(g_raydium_ts->rst_gpio); + return i32_err; +err_irq_gpio_dir: + if (gpio_is_valid(g_raydium_ts->irq_gpio)) + gpio_free(g_raydium_ts->irq_gpio); +err_irq_gpio_req: + return i32_err; +} + +/***************************************************************************** + * Name: raydium_ts_pinctrl_init + * Brief: + * Input: + * Output: + * Return: + *****************************************************************************/ +#ifdef MSM_NEW_VER +static int raydium_ts_pinctrl_init(void) +{ + int i32_ret; + + /* Get pinctrl if target uses pinctrl */ + g_raydium_ts->ts_pinctrl = devm_pinctrl_get(&(g_raydium_ts->client->dev)); + if (IS_ERR_OR_NULL(g_raydium_ts->ts_pinctrl)) { + i32_ret = PTR_ERR(g_raydium_ts->ts_pinctrl); + pr_err("[touch]target does not use pinctrl %d\n", i32_ret); + goto err_pinctrl_get; + } + + g_raydium_ts->pinctrl_state_active + = pinctrl_lookup_state(g_raydium_ts->ts_pinctrl, + PINCTRL_STATE_ACTIVE); + if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_active)) { + i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_active); + pr_err("[touch]Can not lookup %s pinstate %d\n", + PINCTRL_STATE_ACTIVE, i32_ret); + goto err_pinctrl_lookup; + } + + g_raydium_ts->pinctrl_state_suspend + = pinctrl_lookup_state(g_raydium_ts->ts_pinctrl, + PINCTRL_STATE_SUSPEND); + if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_suspend)) { + i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_suspend); + pr_err("[touch]Can not lookup %s pinstate %d\n", + PINCTRL_STATE_SUSPEND, i32_ret); + goto err_pinctrl_lookup; + } + + g_raydium_ts->pinctrl_state_release + = pinctrl_lookup_state(g_raydium_ts->ts_pinctrl, + PINCTRL_STATE_RELEASE); + if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_release)) { + i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_release); + pr_err("[touch]Can not lookup %s pinstate %d\n", + PINCTRL_STATE_RELEASE, i32_ret); + } + + return 0; + +err_pinctrl_lookup: + devm_pinctrl_put(g_raydium_ts->ts_pinctrl); +err_pinctrl_get: + g_raydium_ts->ts_pinctrl = NULL; + return i32_ret; +} +#endif/*end of MSM_NEW_VER*/ + +int wait_irq_state(struct i2c_client *client, unsigned int retry_time, + unsigned int u32_delay_us) +{ + int i32_ret = SUCCESS; + unsigned int u32_retry; + unsigned int u32_irq_value; + unsigned int u32_min_delay_us = u32_delay_us - 500; + unsigned int u32_max_delay_us = u32_delay_us + 500; + + u32_retry = retry_time; + u32_irq_value = 0; + while (u32_retry != 0 && u32_irq_value != 1) { + u32_irq_value = gpio_get_value(g_raydium_ts->irq_gpio); + usleep_range(u32_min_delay_us, u32_max_delay_us); + u32_retry--; + } + pr_debug("[touch]irq_value is %d\n", u32_irq_value); + + if (u32_retry == 0) { + pr_err("[touch]%s, FW not ready, retry error!\n", __func__); + i32_ret = ERROR; + } + + return i32_ret; +} + +#ifdef ESD_SOLUTION_EN +static int raydium_hw_reset_fun(struct i2c_client *client) +{ + int i32_ret = SUCCESS; + + pr_debug("[touch]HW reset\n"); + if ((g_u8_raydium_flag & ENG_MODE) == 0) + raydium_irq_control(DISABLE); + + g_u8_resetflag = true; + /*HW reset*/ + gpio_set_value(g_raydium_ts->rst_gpio, 1); + gpio_set_value(g_raydium_ts->rst_gpio, 0); + msleep(RAYDIUM_RESET_INTERVAL_MSEC); + gpio_set_value(g_raydium_ts->rst_gpio, 1); + + g_u8_i2c_mode = PDA2_MODE; + + i32_ret = wait_irq_state(client, 300, 2000); + if (i32_ret != ERROR) + msleep(25); + + if ((g_u8_raydium_flag & ENG_MODE) == 0) + raydium_irq_control(ENABLE); + + pr_debug("[touch]Raydium HW reset : %d\n", i32_ret); + return i32_ret; +} +#endif +int raydium_i2c_pda_set_address(unsigned int u32_address, + unsigned char u8_mode) +{ + int i32_ret = 0; + unsigned char u8_retry; + unsigned char u8_buf[RAD_I2C_PDA_ADDRESS_LENGTH]; + struct i2c_client *client = g_raydium_ts->client; + + client->addr = RAYDIUM_I2C_EID; + u8_buf[0] = (u32_address & 0x0000FF00) >> 8; + u8_buf[1] = (u32_address & 0x00FF0000) >> 16; + u8_buf[2] = (u32_address & 0xFF000000) >> 24; + u8_buf[3] = u8_mode; + + for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) { + i32_ret = i2c_master_send(client, u8_buf, + RAD_I2C_PDA_ADDRESS_LENGTH); + if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH) { + pr_err("[touch]%s: I2C retry %d\n", + __func__, u8_retry + 1); + usleep_range(500, 1500); + } else { + break; + } + } + + return (i32_ret == RAD_I2C_PDA_ADDRESS_LENGTH) ? i32_ret : -EIO; +} + +/*device attribute raydium_i2c_pda2_mode used*/ +int raydium_i2c_pda_read(struct i2c_client *client, + unsigned int u32_addr, unsigned char *u8_r_data, + unsigned short u16_length) +{ + int i32_ret; + unsigned char u8_retry; + unsigned char u8_mode = 0x00; + unsigned char u8_buf; + + struct i2c_msg msg[] = { + { + .addr = RAYDIUM_I2C_NID, + .flags = RAYDIUM_I2C_WRITE, + .len = 1, + .buf = &u8_buf, + }, + { + .addr = RAYDIUM_I2C_NID, + .flags = RAYDIUM_I2C_READ, + .len = u16_length, + .buf = u8_r_data, + }, + }; + + if (u16_length == 4) + u8_mode |= RAD_I2C_PDA_MODE_ENABLE | + RAD_I2C_PDA_2_MODE_DISABLE | + RAD_I2C_PDA_MODE_WORD_MODE; + else + u8_mode |= RAD_I2C_PDA_MODE_ENABLE | + RAD_I2C_PDA_2_MODE_DISABLE; + + u8_mode |= 0x03; + + u8_buf = u32_addr & MASK_8BIT; + + i32_ret = raydium_i2c_pda_set_address(u32_addr, u8_mode); + if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH) + goto exit; + usleep_range(50, 80); + + for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) { + if (i2c_transfer(g_raydium_ts->client->adapter, msg, 2) == 2) { + i32_ret = u16_length; + break; + } + pr_err("%s: I2C retry %d\n", __func__, u8_retry + 1); + usleep_range(500, 1500); + } + + if (u8_retry == SYN_I2C_RETRY_TIMES) { + pr_err("%s: I2C read over retry limit\n", __func__); + i32_ret = -EIO; + } +exit: + return i32_ret; +} + +int raydium_i2c_pda_write(struct i2c_client *client, + unsigned int u32_addr, unsigned char *u8_w_data, + unsigned short u16_length) +{ + int i32_ret; + unsigned char u8_retry; + unsigned char u8_mode = 0x00; + unsigned char u8_buf[MAX_WRITE_PACKET_SIZE + 1]; + + struct i2c_msg msg[] = { + { + .addr = RAYDIUM_I2C_NID, + .flags = RAYDIUM_I2C_WRITE, + .len = u16_length + 1, + .buf = u8_buf, + }, + }; + + if (u16_length > MAX_WRITE_PACKET_SIZE) + return -EINVAL; + + if (u16_length == 4) + u8_mode |= RAD_I2C_PDA_MODE_ENABLE | + RAD_I2C_PDA_2_MODE_DISABLE | + RAD_I2C_PDA_MODE_WORD_MODE; + else + u8_mode |= RAD_I2C_PDA_MODE_ENABLE | + RAD_I2C_PDA_2_MODE_DISABLE; + + u8_buf[0] = u32_addr & MASK_8BIT; + memcpy(&u8_buf[1], u8_w_data, u16_length); + + i32_ret = raydium_i2c_pda_set_address(u32_addr, u8_mode); + if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH) + goto exit; + + for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) { + i32_ret = u16_length; + break; + } + pr_err("[touch]%s: I2C retry %d\n", __func__, u8_retry + 1); + usleep_range(500, 1500); + } + + if (u8_retry == SYN_I2C_RETRY_TIMES) { + pr_err("[touch]%s: I2C write over retry limit\n", __func__); + i32_ret = -EIO; + } +exit: + return i32_ret; +} + +int raydium_i2c_pda2_set_page(struct i2c_client *client, + unsigned int is_suspend, + unsigned char u8_page) +{ + int i32_ret = -1; + unsigned char u8_retry; + unsigned int u8_ret = (is_suspend) ? 10 : 2; + unsigned char u8_buf[RAYDIUM_I2C_PDA2_PAGE_LENGTH]; + + struct i2c_msg msg[] = { + { + .addr = RAYDIUM_I2C_NID, + .flags = RAYDIUM_I2C_WRITE, + .len = RAYDIUM_I2C_PDA2_PAGE_LENGTH, + .buf = u8_buf, + }, + }; + + u8_buf[0] = RAYDIUM_PDA2_PAGE_ADDR; + u8_buf[1] = u8_page; + for (; u8_ret > 0; u8_ret--) { + for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) { + i32_ret = RAYDIUM_I2C_PDA2_PAGE_LENGTH; + break; + } + usleep_range(500, 1500); + } + if (i32_ret == RAYDIUM_I2C_PDA2_PAGE_LENGTH) + break; + usleep_range(2000, 5000); + } + + if (u8_ret == 0) { + pr_err("[touch]%s: I2C write over retry limit\n", __func__); + i32_ret = -EIO; + } + + return i32_ret; +} + +int raydium_i2c_pda2_read(struct i2c_client *client, + unsigned char u8_addr, + unsigned char *u8_r_data, + unsigned short u16_length) +{ + int i32_ret = -1; + unsigned char u8_retry; + + struct i2c_msg msg[] = { + { + .addr = RAYDIUM_I2C_NID, + .flags = RAYDIUM_I2C_WRITE, + .len = 1, + .buf = &u8_addr, + }, + { + .addr = RAYDIUM_I2C_NID, + .flags = RAYDIUM_I2C_READ, + .len = u16_length, + .buf = u8_r_data, + }, + }; + g_u8_i2c_mode = PDA2_MODE; + for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) { + if (i2c_transfer(g_raydium_ts->client->adapter, msg, 2) == 2) { + i32_ret = u16_length; + break; + } + usleep_range(500, 1500); + } + + if (u8_retry == SYN_I2C_RETRY_TIMES) { + pr_err("[touch]%s: I2C read over retry limit\n", __func__); + i32_ret = -EIO; + } + + return i32_ret; +} + +int raydium_i2c_pda2_write(struct i2c_client *client, + unsigned char u8_addr, + unsigned char *u8_w_data, + unsigned short u16_length) +{ + int i32_ret = -1; + unsigned char u8_retry; + unsigned char u8_buf[MAX_WRITE_PACKET_SIZE + 1]; + + struct i2c_msg msg[] = { + { + .addr = RAYDIUM_I2C_NID, + .flags = RAYDIUM_I2C_WRITE, + .len = u16_length + 1, + .buf = u8_buf, + }, + }; + + if (u16_length > MAX_WRITE_PACKET_SIZE) + return -EINVAL; + g_u8_i2c_mode = PDA2_MODE; + u8_buf[0] = u8_addr; + memcpy(&u8_buf[1], u8_w_data, u16_length); + + for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) { + i32_ret = u16_length; + break; + } + usleep_range(500, 1500); + } + + if (u8_retry == SYN_I2C_RETRY_TIMES) { + pr_err("[touch]%s: I2C write over retry limit\n", __func__); + i32_ret = -EIO; + } + + return i32_ret; +} + +void raydium_irq_control(bool enable) +{ + if (enable) { + if (g_raydium_ts->irq_enabled) { + /*mutex_unlock(&ts->lock);*/ + dev_info(&g_raydium_ts->client->dev, + "[touch]Already enable irq\n"); + return; + } + + /* Clear interrupts first */ + if (g_raydium_ts->blank != FB_BLANK_POWERDOWN && + g_u8_i2c_mode == PDA2_MODE) { + mutex_lock(&g_raydium_ts->lock); + if (raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0) < 0) + pr_err("[touch]set page fail%s\n", + __func__); + mutex_unlock(&g_raydium_ts->lock); + usleep_range(500, 1500); + } + + while (g_raydium_ts->irq_desc->depth > 0) { + pr_debug("[touch]irq enable\n"); + g_raydium_ts->irq_enabled = true; + enable_irq(g_raydium_ts->irq); + } + } else { + if (g_raydium_ts->irq_enabled && + g_raydium_ts->irq_desc->depth == 0) { + disable_irq(g_raydium_ts->irq); + g_raydium_ts->irq_enabled = false; + pr_debug("[touch]irq disable\n"); + } + } +} + +#ifdef CONFIG_RM_SYSFS_DEBUG + +int raydium_i2c_mode_control(struct i2c_client *client, + unsigned char u8_mode) +{ + unsigned char u8_buf[4]; + + switch (u8_mode) { + case 0: /* Disable INT flag */ + pr_debug("[touch]RAD INT flag : %d\n", + g_raydium_ts->irq_enabled); + disable_irq(g_raydium_ts->irq); + g_raydium_ts->irq_enabled = false; + pr_debug("[touch]RAD irq disable\n"); + break; + case 1: /* Enable INT flag */ + pr_debug("[touch]RAD INT flag : %d\n", + g_raydium_ts->irq_enabled); + enable_irq(g_raydium_ts->irq); + g_raydium_ts->irq_enabled = true; + pr_debug("[touch]RAD irq enable\n"); + break; + case 2: /* Disable INT by raydium_irq_control */ + raydium_irq_control(DISABLE); + break; + case 3: /* Enable INT by raydium_irq_control */ + raydium_irq_control(ENABLE); + break; + case 4: /* Show RAD INT depth */ + pr_debug("[touch]RAD INT depth : %d\n", + g_raydium_ts->irq_desc->depth); + break; + case 7: + raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, RAYDIUM_PDA2_2_PDA); + g_u8_i2c_mode = PDA_MODE; + pr_debug("[touch]Disable PDA2_MODE\n"); + break; + case 8: + raydium_i2c_pda_read(client, RAD_PDA2_CTRL_CMD, u8_buf, 4); + u8_buf[0] |= RAD_ENABLE_PDA2 | RAD_ENABLE_SI2; + raydium_i2c_pda_write(client, RAD_PDA2_CTRL_CMD, u8_buf, 4); + raydium_i2c_pda_set_address(0x50000628, DISABLE); + + g_u8_i2c_mode = PDA2_MODE; + pr_debug("[touch]Enable PDA2_MODE\n"); + break; + } + return 0; +} + + +static const struct attribute_group raydium_attr_group = { + .attrs = raydium_attributes +}; + +/*create sysfs for debug update firmware*/ +static int raydium_create_sysfs(struct i2c_client *client) +{ + int ret = -1; + + ret = sysfs_create_group(&(client->dev.kobj), &raydium_attr_group); + if (ret) { + pr_err("[touch]failed to register sysfs\n"); + sysfs_remove_group(&client->dev.kobj, &raydium_attr_group); + ret = -EIO; + } else { + pr_debug("[touch]create raydium sysfs attr_group successful\n"); + } + return ret; +} + +static void raydium_release_sysfs(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &raydium_attr_group); +} +#endif /*end of CONFIG_RM_SYSFS_DEBUG*/ + +#ifdef ESD_SOLUTION_EN +int raydium_esd_check(void) +{ + int i32_ret = 0; + unsigned char u8_esd_status[MAX_TCH_STATUS_PACKET_SIZE]; + unsigned char u8_w_data[4]; + + mutex_lock(&g_raydium_ts->lock); + if (g_u8_i2c_mode == PDA2_MODE) { + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit; + /*read esd status*/ + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, + u8_esd_status, MAX_TCH_STATUS_PACKET_SIZE); + if (i32_ret < 0) { + pr_err("[touch]%s: failed to read data: %d\n", + __func__, __LINE__); + goto exit; + } + + if (u8_esd_status[POS_FW_STATE] != 0x1A && + u8_esd_status[POS_FW_STATE] != 0xAA) { + if (g_u8_resetflag == true) { + pr_err("[touch]%s -> filter abnormal irq\n" + , __func__); + goto exit; + } + pr_err("[touch]%s -> abnormal irq, FW state = 0x%x\n", + __func__, u8_esd_status[POS_FW_STATE]); + g_u8_resetflag = false; + i32_ret = -1; + goto exit; + + } + u8_w_data[POS_SEQ] = 0; + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, + u8_w_data, 1); + if (i32_ret < 0) { + pr_err("[touch]%s: failed to clear seq: %d\n", + __func__, __LINE__); + goto exit; + } + g_u8_resetflag = false; + } +exit: + mutex_unlock(&g_raydium_ts->lock); + pr_debug("[touch] raydium_esd_check\n"); + return i32_ret; +} +#endif + + +#ifdef ENABLE_DUMP_DATA +int raydium_dump_data(unsigned char u8_frame, unsigned char u8_type) +{ + unsigned char u8_rbuffer[MAX_READ_PACKET_SIZE*2]; + short i16_data_buffer[MAX_READ_PACKET_SIZE*2]; + unsigned char u8_w_data[RAYDIUM_FT_CMD_LENGTH]; + unsigned int u32_target_addr; + unsigned int u32_offset; + unsigned short u16_read_length; + int i32_ret = -1; + int i32_retry = 0; + unsigned char u8_i, u8_j, u8_k; + char write_string[1000]; + + pr_debug("[touch] %s -> type:%d\n", __func__, u8_type); + + for (u8_i = 0; u8_i < u8_frame; u8_i++) { + + u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP; + u8_w_data[RAD_FT_CMD_POS] = u8_type; + + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_w_data, RAYDIUM_FT_CMD_LENGTH); + + memset(u8_rbuffer, 0x00, MAX_READ_PACKET_SIZE*2); + /* make sure update flag was set*/ + for (i32_retry = 0; i32_retry < 5; i32_retry++) { + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_rbuffer, + RAYDIUM_FT_CMD_LENGTH); + if (i32_ret < 0) + goto exit_flag_error; + + if ((u8_rbuffer[RAD_FT_CMD_POS] & RAYDIUM_FT_UPDATE) == + RAYDIUM_FT_UPDATE) + break; + + usleep_range(4500, 5500); + } + + if (i32_retry == 5) { + i32_ret = -EAGAIN; + pr_err("[touch] %s -> flag timeout\n", __func__); + } + + u32_offset = 0; + u16_read_length = 0; +#if DATA_MAP_5_5 + g_u32_raw_data_len = 0x32; +#else + g_u32_raw_data_len = 0x48; +#endif + while (u32_offset < g_u32_raw_data_len) { + u16_read_length = g_u32_raw_data_len; + + u32_target_addr = RAD_READ_FT_DATA_CMD + u32_offset; + + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + + *(unsigned int *)u8_rbuffer = + (RAD_I2C_PDA_MODE_ENABLE << 24) + | ((u32_target_addr & (~MASK_8BIT)) >> 8); + + /*using byte mode to read 4 bytes*/ + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_PDA_CFG_ADDR, + u8_rbuffer, 4); + if (i32_ret < 0) + goto exit_i2c_error; + + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_ENABLE_PDA); + if (i32_ret < 0) + goto exit_i2c_error; + + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + (unsigned char)(u32_target_addr + & MASK_8BIT), u8_rbuffer, + u16_read_length); + if (i32_ret < 0) + goto exit_flag_error; + + memcpy((i16_data_buffer + u32_offset), + u8_rbuffer, + u16_read_length); + + u32_offset += u16_read_length; + } + pr_debug("[touch] frame%d\n", u8_i); +#if DATA_MAP_5_5 + for (u8_j = 0; u8_j < 25; u8_j += 5) { + pr_debug("[touch] %4d, %4d, %4d, %4d, %4d\r\n", + i16_data_buffer[u8_j], i16_data_buffer[u8_j+1], + i16_data_buffer[u8_j+2], i16_data_buffer[u8_j+3], + i16_data_buffer[u8_j+4]); + } +#else + for (u8_j = 0; u8_j < 36; u8_j += 6) { + pr_debug("[touch] %4d, %4d, %4d, %4d, %4d, %4d\r\n", + i16_data_buffer[u8_j], i16_data_buffer[u8_j+1], + i16_data_buffer[u8_j+2], i16_data_buffer[u8_j+3], + i16_data_buffer[u8_j+4], i16_data_buffer[u8_j+5]); + } +#endif + /* clear update flag to get next one*/ + u8_rbuffer[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP; + u8_rbuffer[RAD_FT_CMD_POS] = u8_type; + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_rbuffer, RAYDIUM_FT_CMD_LENGTH); + if (i32_ret < 0) + goto exit_flag_error; + + } + return 0; +exit_i2c_error: + pr_err("%s exit_i2c_error return %d\r\n", __func__, i32_ret); +exit_flag_error: + return i32_ret; +} + +static void raydium_dump_data_work(struct work_struct *work) +{ + + int i32_ret = 0; + unsigned char u8_data_type; + unsigned char u8_w_data[RAYDIUM_FT_CMD_LENGTH]; + + /* set mode */ + memset(u8_w_data, 0x00, RAYDIUM_FT_CMD_LENGTH); + pr_debug("[touch] raydium_dump_data_work\n"); + + disable_irq_nosync(g_raydium_ts->irq); + g_raydium_ts->irq_enabled = false; + + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_error; + + u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_FT_MODE; + + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_w_data, 1); + if (i32_ret < 0) + goto exit_error; + pr_debug("[touch] RAYDIUM_HOST_CMD_FT_MODE\n"); + + /*baseline*/ + u8_data_type = 0x02; + raydium_dump_data(1, u8_data_type); + u8_data_type = 0x04; + raydium_dump_data(1, u8_data_type); + u8_data_type = 0x10; + raydium_dump_data(10, u8_data_type); + + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_error; + u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_TP_MODE; + + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_w_data, 1); + + u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP; + u8_w_data[RAD_FT_CMD_POS] = 0; + + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_w_data, RAD_FT_CMD_LENGTH); + if (i32_ret < 0) + goto exit_error; + +exit_error: + enable_irq(g_raydium_ts->irq); + g_raydium_ts->irq_enabled = true; +} + +#endif +#ifdef FILTER_POINTS +int raydium_pointer_filter(int i32_index, + unsigned short u16_diff_x, + unsigned short u16_diff_y) +{ + if (abs(ts->x_pos[i32_index] - ts->last_x_pos[i32_index]) > u16_diff_x) + return 0; + if (abs(ts->y_pos[i32_index] - ts->last_y_pos[i32_index]) > u16_diff_y) + return 0; + + return 1; +} +#endif + +#ifdef HOST_NOTIFY_EN +int raydium_notify_function(unsigned short u16_display_mode) +{ + int i32_ret = 0; + unsigned char u8_rbuffer[4]; + + mutex_lock(&g_raydium_ts->lock); + if (g_u8_i2c_mode == PDA2_MODE) { + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit; + memset(u8_rbuffer, 0, sizeof(u8_rbuffer)); + + u8_rbuffer[0] = RAYDIUM_HOST_CMD_DISPLAY_MODE; + u8_rbuffer[2] = (unsigned char) (u16_display_mode & 0x00ff); + u8_rbuffer[3] = (unsigned char) ((u16_display_mode & 0xff00) >> 8); + pr_debug("[touch] display mode %d %d %d\r\n", u16_display_mode, + u8_rbuffer[2], u8_rbuffer[3]); + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_rbuffer, 4); + } +exit: + mutex_unlock(&g_raydium_ts->lock); + pr_debug("[touch] raydium_notify_function\n"); + return i32_ret; +} +#endif +static int raydium_touch_report(unsigned char *p_u8_buf, + unsigned char u8_points_amount) +{ + unsigned char u8_i, u8_j, u8_offset = 0, u8_pt_id; + signed short i16_wx, i16_wy; + /* number of touch points */ + unsigned char u8_touch_count = 0; + DECLARE_BITMAP(ids, g_raydium_ts->u8_max_touchs); + + bitmap_zero(ids, g_raydium_ts->u8_max_touchs); + + for (u8_i = 0; u8_i < (g_raydium_ts->u8_max_touchs * 2); u8_i++) { + gst_slot[u8_i].need_update = 0; + gst_slot[u8_i].pt_report_offset = 0; + } + + /*Check incoming point info*/ + for (u8_i = 0; u8_i < u8_points_amount; u8_i++) { + u8_pt_id = p_u8_buf[POS_PT_ID + u8_i * LEN_PT]; + /* Current*/ + for (u8_j = 0; u8_j < g_raydium_ts->u8_max_touchs; u8_j++) { + if (u8_pt_id == gst_slot[u8_j].pt_id) { + gst_slot[u8_j].need_update = 1; + gst_slot[u8_j].pt_report_offset = u8_i; + break; + } + } + /* New coming*/ + if (u8_j == g_raydium_ts->u8_max_touchs) { + for (u8_j = g_raydium_ts->u8_max_touchs; + u8_j < (g_raydium_ts->u8_max_touchs * 2); u8_j++) { + if (!gst_slot[u8_j].need_update) { + gst_slot[u8_j].pt_id = u8_pt_id; + gst_slot[u8_j].need_update = 1; + gst_slot[u8_j].pt_report_offset = u8_i; + pr_debug("[touch]x:%d,y:%d\n", + p_u8_buf[POS_X_L + u8_offset] | + p_u8_buf[POS_X_H + u8_offset] << 8, + p_u8_buf[POS_Y_L + u8_offset] | + p_u8_buf[POS_Y_H + u8_offset] << 8); + break; + } + } + } + } + + /*Release slot with non-occupied point*/ + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + if (!gst_slot[u8_i].need_update) { + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, false); + gst_slot[u8_i].pt_id = 0xFF; + gst_slot[u8_i].pt_report_offset = 0; + gst_slot[u8_i].need_update = 0; + } + } + /*Assign new one to non-occupied slot*/ + for (u8_i = g_raydium_ts->u8_max_touchs; + u8_i < (g_raydium_ts->u8_max_touchs * 2); u8_i++) { + if (gst_slot[u8_i].need_update) { + for (u8_j = 0; u8_j < g_raydium_ts->u8_max_touchs; u8_j++) { + if (!gst_slot[u8_j].need_update) { + gst_slot[u8_j] = gst_slot[u8_i]; + gst_slot[u8_i] = gst_slot_init; + break; + } + } + } else { + break; + } + } +#ifdef FILTER_POINTS + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + if (gst_slot[u8_i].need_update) { + u8_offset = gst_slot[u8_i].pt_report_offset * LEN_PT; + g_raydium_ts->x_pos[i] = p_u8_buf[POS_X_L + u8_offset] | + p_u8_buf[POS_X_H + u8_offset] << BYTE_SHIFT; + g_raydium_ts->y_pos[i] = p_u8_buf[POS_Y_L + u8_offset] | + p_u8_buf[POS_Y_H + u8_offset] << BYTE_SHIFT; + g_raydium_ts->pressure = p_u8_buf[POS_PRESSURE_L + u8_offset] | + p_u8_buf[POS_PRESSURE_H + u8_offset] << BYTE_SHIFT; + i16_wx = p_u8_buf[POS_WX_L + u8_offset] | + p_u8_buf[POS_WX_H + u8_offset] << BYTE_SHIFT; + i16_wy = p_u8_buf[POS_WY_L + u8_offset] | + p_u8_buf[POS_WY_H + u8_offset] << BYTE_SHIFT; + + if (!raydium_pointer_filter(g_raydium_ts, u8_i, DELTA_X, DELTA_Y)) { + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, true); + __set_bit(i, ids); + + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_X, g_raydium_ts->x_pos[u8_i]); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_Y, g_raydium_ts->y_pos[u8_i]); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_PRESSURE, g_raydium_ts->pressure); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_TOUCH_MAJOR, max(i16_wx, i16_wy)); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_TOUCH_MINOR, min(i16_wx, i16_wy)); + input_report_key(g_raydium_ts->input_dev, + BTN_TOUCH, 1); + input_report_key(g_raydium_ts->input_dev, + BTN_TOOL_FINGER, 1); + input_sync(g_raydium_ts->input_dev); + g_raydium_ts->last_x_pos[u8_i] = g_raydium_ts->x_pos[u8_i]; + g_raydium_ts->last_y_pos[u8_i] = g_raydium_ts->y_pos[u8_i]; + } else { + g_raydium_ts->x_pos[u8_i] = g_raydium_ts->last_x_pos[u8_i]; + g_raydium_ts->y_pos[u8_i] = g_raydium_ts->last_y_pos[u8_i]; + } + } + } + + if ((gst_slot[0].need_update == 0) && + (gst_slot[1].need_update == 0)) { + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + if (test_bit(u8_i, ids)) + continue; + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, false); + } + input_report_key(g_raydium_ts->input_dev, BTN_TOUCH, 0); + input_report_key(g_raydium_ts->input_dev, BTN_TOOL_FINGER, 0); + input_sync(g_raydium_ts->input_dev); + } +#else + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + if (gst_slot[u8_i].need_update) { + u8_offset = gst_slot[u8_i].pt_report_offset * LEN_PT; + g_raydium_ts->x_pos[u8_i] = p_u8_buf[POS_X_L + u8_offset] | + p_u8_buf[POS_X_H + u8_offset] << BYTE_SHIFT; + g_raydium_ts->y_pos[u8_i] = p_u8_buf[POS_Y_L + u8_offset] | + p_u8_buf[POS_Y_H + u8_offset] << BYTE_SHIFT; + g_raydium_ts->pressure = p_u8_buf[POS_PRESSURE_L + u8_offset] | + p_u8_buf[POS_PRESSURE_H + u8_offset] << BYTE_SHIFT; + i16_wx = p_u8_buf[POS_WX_L + u8_offset] | + p_u8_buf[POS_WX_H + u8_offset] << BYTE_SHIFT; + i16_wy = p_u8_buf[POS_WY_L + u8_offset] | + p_u8_buf[POS_WY_H + u8_offset] << BYTE_SHIFT; + + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, true); + __set_bit(u8_i, ids); + + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_X, g_raydium_ts->x_pos[u8_i]); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_Y, g_raydium_ts->y_pos[u8_i]); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_PRESSURE, g_raydium_ts->pressure); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_TOUCH_MAJOR, max(i16_wx, i16_wy)); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_TOUCH_MINOR, min(i16_wx, i16_wy)); + + u8_touch_count++; + } + } + input_report_key(g_raydium_ts->input_dev, + BTN_TOUCH, u8_touch_count > 0); + input_report_key(g_raydium_ts->input_dev, + BTN_TOOL_FINGER, u8_touch_count > 0); + + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + if (test_bit(u8_i, ids)) + continue; + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, false); + } + + input_sync(g_raydium_ts->input_dev); +#endif + return 0; +} +int raydium_read_touchdata(unsigned char *p_u8_tp_status, + unsigned char *p_u8_buf) +{ + int i32_ret = 0; + unsigned char u8_points_amount; + static unsigned char u8_seq_no; + unsigned char u8_retry; + + u8_retry = 3; + + mutex_lock(&g_raydium_ts->lock); + while (u8_retry != 0) { + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) { + msleep(250); + u8_retry--; + } else + break; + } + if (u8_retry == 0) { + pr_err("[touch]%s: failed to set page, hw reset\n", __func__); + + goto reset_error; + } + + memset(p_u8_buf, 0, MAX_REPORT_PACKET_SIZE); + memset(p_u8_tp_status, 0, MAX_TCH_STATUS_PACKET_SIZE); + + /*read touch point information*/ + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, + p_u8_tp_status, MAX_TCH_STATUS_PACKET_SIZE); + if (i32_ret < 0) { + pr_err("[touch]%s: failed to read data: %d\n", + __func__, __LINE__); + goto exit_error; + } +#ifdef ESD_SOLUTION_EN + if (p_u8_tp_status[POS_FW_STATE] != 0x1A && + p_u8_tp_status[POS_FW_STATE] != 0xAA) { + if (g_u8_resetflag == true) { + pr_err("[touch]%s -> filter irq, FW state = 0x%x\n", + __func__, p_u8_tp_status[POS_FW_STATE]); + i32_ret = -1; + g_u8_resetflag = false; + goto exit_error; + } + pr_err("[touch]%s -> abnormal irq, FW state = 0x%x\n", + __func__, p_u8_tp_status[POS_FW_STATE]); + i32_ret = -1; + goto reset_error; + + } +#endif + /* inform IC to prepare next report*/ + if (u8_seq_no == p_u8_tp_status[POS_SEQ]) { + pr_err("%s -> report not updated.\n", __func__); + goto exit_error; + } + u8_points_amount = p_u8_tp_status[POS_PT_AMOUNT]; + + if (u8_points_amount > MAX_TOUCH_NUM) + goto exit_error; + + /*read touch point report*/ + /*PDA2 only support word mode*/ + if (u8_points_amount != 0) + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + RAYDIUM_PDA2_TCH_RPT_ADDR, p_u8_buf, + u8_points_amount * LEN_PT); + + if (i32_ret < 0) { + pr_err("[touch]%s: failed to read data: %d\n", + __func__, __LINE__); + goto exit_error; + } + + u8_seq_no = p_u8_tp_status[POS_SEQ]; + p_u8_tp_status[POS_SEQ] = 0; + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, p_u8_tp_status, 1); + if (i32_ret < 0) { + pr_err("[touch]%s: write data failed: %d\n", __func__, i32_ret); + goto exit_error; + } + + raydium_touch_report(p_u8_buf, u8_points_amount); + +exit_error: + mutex_unlock(&g_raydium_ts->lock); + + return i32_ret; + +reset_error: + mutex_unlock(&g_raydium_ts->lock); +#ifdef ESD_SOLUTION_EN + u8_retry = 3; + while (u8_retry != 0) { + i32_ret = raydium_hw_reset_fun(g_raydium_ts->client); + if (i32_ret < 0) { + msleep(100); + u8_retry--; + } else + break; + } +#endif + return i32_ret; +} + +static void raydium_work_handler(struct work_struct *work) +{ + int i32_ret = 0; + unsigned char u8_tp_status[MAX_TCH_STATUS_PACKET_SIZE]; + unsigned char u8_buf[MAX_REPORT_PACKET_SIZE]; + +#ifdef GESTURE_EN + unsigned char u8_i; + + if ((g_raydium_ts->blank == FB_BLANK_VSYNC_SUSPEND || + g_raydium_ts->blank == FB_BLANK_POWERDOWN) && + (g_u8_resetflag == false)) { + input_mt_slot(g_raydium_ts->input_dev, 0); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, 1); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_X, 100); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_Y, 100); + input_sync(g_raydium_ts->input_dev); + usleep_range(9500, 10500); + input_mt_slot(g_raydium_ts->input_dev, 0); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, 0); + input_mt_report_pointer_emulation(g_raydium_ts->input_dev, + false); + input_sync(g_raydium_ts->input_dev); + input_report_key(g_raydium_ts->input_dev, KEY_POWER, true); + usleep_range(9500, 10500); + input_sync(g_raydium_ts->input_dev); + + input_report_key(g_raydium_ts->input_dev, KEY_POWER, false); + input_sync(g_raydium_ts->input_dev); +#ifdef ESD_SOLUTION_EN + g_u8_checkflag = true; +#endif + pr_debug("[touch]display wake up with g_u8_resetflag false\n"); + } else { + + if (g_u8_i2c_mode == PDA2_MODE) { + i32_ret = raydium_read_touchdata(u8_tp_status, u8_buf); + if (i32_ret < 0) { + pr_err("[touch]%s, read_touchdata error, ret:%d\n", + __func__, i32_ret); + return; + } + } + /*when display on can use palm to suspend*/ + if (g_raydium_ts->blank == FB_BLANK_UNBLANK) { + if (u8_tp_status[POS_GES_STATUS] == RAD_PALM_ENABLE) { + if (g_raydium_ts->is_palm == 0) { + /* release all touches*/ + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; + u8_i++) { + input_mt_slot(g_raydium_ts->input_dev, + u8_i); + input_mt_report_slot_state( + g_raydium_ts->input_dev, + MT_TOOL_FINGER, false); + } + input_mt_report_pointer_emulation( + g_raydium_ts->input_dev, + false); + /*press sleep key*/ + input_report_key(g_raydium_ts->input_dev, + KEY_SLEEP, true); + input_sync(g_raydium_ts->input_dev); + + pr_debug("[touch]palm_status = %d.\n", + u8_tp_status[POS_GES_STATUS]); + + g_raydium_ts->is_palm = 1; + /*goto exit;*/ + } + } else if ((u8_tp_status[POS_GES_STATUS] + == RAD_PALM_DISABLE) + && (g_raydium_ts->is_palm == 1)) { + pr_debug("[touch]leave palm mode.\n"); + input_report_key(g_raydium_ts->input_dev, + KEY_SLEEP, false); + input_sync(g_raydium_ts->input_dev); + + /*raydium_irq_control(raydium_ts, DISABLE);*/ + g_raydium_ts->is_palm = 0; + /*goto exit;*/ + } + } else if (g_raydium_ts->blank == FB_BLANK_VSYNC_SUSPEND || + g_raydium_ts->blank == FB_BLANK_POWERDOWN) { + /*need check small area*/ + if (u8_tp_status[POS_GES_STATUS] == RAD_WAKE_UP) { + input_mt_slot(g_raydium_ts->input_dev, 0); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, 1); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_X, 100); + input_report_abs(g_raydium_ts->input_dev, + ABS_MT_POSITION_Y, 100); + input_sync(g_raydium_ts->input_dev); + usleep_range(9500, 10500); + input_mt_slot(g_raydium_ts->input_dev, 0); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, 0); + input_mt_report_pointer_emulation( + g_raydium_ts->input_dev, + false); + input_sync(g_raydium_ts->input_dev); + input_report_key(g_raydium_ts->input_dev, KEY_POWER, true); + usleep_range(9500, 10500); + input_sync(g_raydium_ts->input_dev); + + input_report_key(g_raydium_ts->input_dev, + KEY_POWER, false); + input_sync(g_raydium_ts->input_dev); + pr_debug("[touch]display wake up with g_u8_resetflag true\n"); + /*goto exit;*/ + } + } + } +#else + if (g_u8_i2c_mode == PDA2_MODE) { + i32_ret = raydium_read_touchdata(u8_tp_status, u8_buf); + if (i32_ret < 0) { + pr_err("[touch]%s, read_touchdata error, ret:%d\n", + __func__, i32_ret); + } + } +#endif +} + +/*The raydium device will signal the host about TRIGGER_FALLING. + *Processed when the interrupt is asserted. + */ +static irqreturn_t raydium_ts_interrupt(int irq, void *dev_id) +{ + bool result = false; + + /*For bootloader wrt/erase flash and software reset interrupt*/ + if ((g_u8_raydium_flag & ENG_MODE) != 0) { + disable_irq_nosync(g_raydium_ts->irq); + g_raydium_ts->irq_enabled = false; + pr_debug("[touch]RAD_ENG_MODE\n"); + g_u8_raydium_flag |= INT_FLAG; + } else { + if (!work_pending(&g_raydium_ts->work)) { + /* Clear interrupts*/ + result = queue_work(g_raydium_ts->workqueue, + &g_raydium_ts->work); + if (result == false) { + /*queue_work fail*/ + pr_err("[touch]queue_work fail.\n"); + } + } else { + /*work pending*/ + mutex_lock(&g_raydium_ts->lock); + if (raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0) < 0) { + pr_err("[touch]%s: failed to set page in work_pending\n", + __func__); + } + mutex_unlock(&g_raydium_ts->lock); + pr_debug("[touch]work_pending\n"); + } + } + return IRQ_HANDLED; +} + +static int raydium_check_i2c_ready(unsigned short *u16_i2c_data) +{ + unsigned char u8_buf[4]; + int i32_ret = -1; + + mutex_lock(&g_raydium_ts->lock); + + if (g_u8_i2c_mode == PDA2_MODE) { + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_error; + + *(unsigned int *)u8_buf = + (RAD_I2C_PDA_MODE_ENABLE << 24) | + ((RAD_CHK_I2C_CMD & (~MASK_8BIT)) >> 8); + /*using byte mode to read 4 bytes*/ + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_PDA_CFG_ADDR, + u8_buf, + 4); + if (i32_ret < 0) + goto exit_error; + + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_ENABLE_PDA); + if (i32_ret < 0) + goto exit_error; + + i32_ret = raydium_i2c_pda2_read( + g_raydium_ts->client, + (unsigned char)(RAD_CHK_I2C_CMD & MASK_8BIT), + u8_buf, 4); + if (i32_ret < 0) + goto exit_error; + if (u8_buf[3] != 0xF3) { + pr_err("[touch]PDA2 read i2c fail\n"); + g_u8_i2c_mode = PDA_MODE; + i32_ret = raydium_i2c_pda_read(g_raydium_ts->client, + RAD_CHK_I2C_CMD, u8_buf, + 4); + if (i32_ret < 0) + goto exit_error; + } + + } else { + i32_ret = raydium_i2c_pda_read(g_raydium_ts->client, + RAD_CHK_I2C_CMD, u8_buf, + 4); + if (i32_ret < 0) + goto exit_error; + + } + + *u16_i2c_data = u8_buf[3] << 8 | u8_buf[2]; + + pr_debug("[touch]RAD check I2C : 0x%02X%02X\n", u8_buf[3], u8_buf[2]); + +exit_error: + mutex_unlock(&g_raydium_ts->lock); + return i32_ret; +} + +#if defined(CONFIG_PM) +static void raydium_ts_do_suspend(void) +{ + unsigned char u8_i = 0; + + g_u8_resetflag = false; + if (g_raydium_ts->is_suspend == 1) { + pr_info("[touch]Already in suspend state\n"); + return; + } + + /*#ifndef GESTURE_EN*/ + raydium_irq_control(DISABLE); + /*#endif*/ + + /*clear workqueue*/ + if (!cancel_work_sync(&g_raydium_ts->work)) + pr_info("[touch]workqueue is empty!\n"); + + pr_debug("[touch]%s.\n", __func__); + + /* release all touches */ + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, + false); + } + input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false); + input_sync(g_raydium_ts->input_dev); +#ifdef ENABLE_DUMP_DATA + if (!g_u8_dumpcount) + timeout = jiffies + 2*HZ; + if (g_u8_dumpcount < 5) + g_u8_dumpcount++; + if (g_u8_palm_flag || (time_is_before_jiffies(timeout))) { + g_u8_dumpcount = 0; + g_u8_palm_flag = false; + } + if (g_u8_dumpcount == 5) { + g_u8_dump_flag = true; + g_u8_dumpcount = 0; + } +#endif + +#ifdef GESTURE_EN + if (device_may_wakeup(&g_raydium_ts->client->dev)) { + pr_debug("[touch]Device may wakeup\n"); + if (!enable_irq_wake(g_raydium_ts->irq)) + g_raydium_ts->irq_wake = 1; + + } else + pr_debug("[touch]Device not wakeup\n"); + raydium_irq_control(ENABLE); +#endif + + g_raydium_ts->is_suspend = 1; +} + +static void raydium_ts_do_resume(void) +{ +#ifdef ESD_SOLUTION_EN + int i32_ret = 0; + unsigned char u8_retry = 0; +#endif + unsigned char u8_w_data[4]; + + pr_debug("[touch]%s, %d.\n", __func__, g_raydium_ts->is_suspend); + if (g_raydium_ts->is_suspend == 0) { + pr_info("[touch]Already in resume state\n"); + return; + } + + /* clear interrupts*/ + mutex_lock(&g_raydium_ts->lock); + if (raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0) < 0) { + pr_err("[ raydium ]%s: failed to set page\n", __func__); + mutex_unlock(&g_raydium_ts->lock); + return; + } + /* clear seq num*/ + u8_w_data[POS_SEQ] = 0; + if (raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, u8_w_data, 1) < 0) { + pr_err("[ raydium ]%s: failed to clear seq\n", __func__); + mutex_unlock(&g_raydium_ts->lock); + return; + } + + mutex_unlock(&g_raydium_ts->lock); + + /* clear workqueue*/ + if (!cancel_work_sync(&g_raydium_ts->work)) + pr_info("[ raydium ]workqueue is empty!\n"); +#ifdef ESD_SOLUTION_EN + if (g_u8_checkflag == true) { + i32_ret = raydium_esd_check(); + if (i32_ret < 0) { + u8_retry = 3; + while (u8_retry != 0) { + i32_ret = raydium_hw_reset_fun(g_raydium_ts->client); + if (i32_ret < 0) { + msleep(100); + u8_retry--; + } else + break; + } + + } + g_u8_checkflag = false; + } +#endif + raydium_irq_control(ENABLE); +#ifdef ENABLE_DUMP_DATA + if (g_u8_dump_flag) { + schedule_delayed_work(&g_raydium_ts->dump_work, HZ); + g_u8_dump_flag = false; + } +#endif +#ifdef GESTURE_EN + if (device_may_wakeup(&g_raydium_ts->client->dev)) { + pr_debug("[touch]Device may wakeup\n"); + if (g_raydium_ts->irq_wake) { + disable_irq_wake(g_raydium_ts->irq); + g_raydium_ts->irq_wake = 0; + } + } else + pr_debug("[touch]Device not wakeup\n"); +#endif + + g_raydium_ts->is_suspend = 0; +} + +static int raydium_ts_suspend(struct device *dev) +{ + raydium_ts_do_suspend(); + return 0; +} + +static int raydium_ts_resume(struct device *dev) +{ + raydium_ts_do_resume(); + return 0; +} + +static const struct dev_pm_ops raydium_ts_pm_ops = { +#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) + .suspend = raydium_ts_suspend, + .resume = raydium_ts_resume, +#endif /*end of CONFIG_PM*/ +}; + +/*used for touch lock feature*/ +static int raydium_ts_open(struct input_dev *input_dev) +{ + int i32_ret = 0; + + pr_debug("[touch]%s()+\n", __func__); + + pr_debug("[touch]ts->blank:%x\n", g_raydium_ts->blank); + + if (g_raydium_ts->is_sleep == 1) { + mutex_lock(&g_raydium_ts->lock); + if (gpio_is_valid(g_raydium_ts->rst_gpio)) { + + g_u8_resetflag = true; + gpio_set_value(g_raydium_ts->rst_gpio, 1); + gpio_set_value(g_raydium_ts->rst_gpio, 0); + msleep(RAYDIUM_RESET_INTERVAL_MSEC);/*5ms*/ + gpio_set_value(g_raydium_ts->rst_gpio, 1); + msleep(RAYDIUM_RESET_DELAY_MSEC);/*100ms*/ + g_u8_i2c_mode = PDA2_MODE; + } + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); + g_raydium_ts->is_sleep = 0; + pr_debug("[touch]disable touch lock.\n"); + } + return i32_ret; +} + +static void raydium_ts_close(struct input_dev *input_dev) +{ + int i32_ret = 0; + unsigned char u8_i = 0; + unsigned char u8_wbuffer[1]; + + pr_debug("[touch]%s()+\n", __func__); + + if (g_raydium_ts->is_sleep == 1) { + pr_debug("[touch]touch lock already enabled.\n"); + return; + } + + raydium_irq_control(DISABLE); + + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, + false); + } + input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false); + input_sync(g_raydium_ts->input_dev); + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) { + pr_err("[touch]ret:%d\n", i32_ret); + goto exit_i2c_error; + } + u8_wbuffer[0] = RAYDIUM_HOST_CMD_PWR_SLEEP; + i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_wbuffer, + 1); + if (i32_ret < 0) { + pr_err("[touch]ret:%d\n", i32_ret); + goto exit_i2c_error; + } + + mutex_unlock(&g_raydium_ts->lock); + g_raydium_ts->is_sleep = 1; + pr_debug("[touch]enable touch lock.\n"); + return; + +exit_i2c_error: + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); +} + +#else +static int raydium_ts_suspend(struct device *dev) +{ + return 0; +} + +static int raydium_ts_resume(struct device *dev) +{ + return 0; +} +#endif /*end of CONFIG_FB*/ + +#if defined(CONFIG_FB) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, + void *data) +{ + struct fb_event *evdata = data; + int *blank; + + if (evdata && evdata->data && event == FB_EVENT_BLANK && + g_raydium_ts && g_raydium_ts->client) { + blank = evdata->data; + g_raydium_ts->blank = (*blank); + switch (*blank) { + + /*screen on*/ + case FB_BLANK_UNBLANK: + pr_debug("[touch]FB_BLANK_UNBLANK\n"); +#ifdef GESTURE_EN + + /* clear palm status */ + + g_raydium_ts->is_palm = 0; +#endif +#ifdef HOST_NOTIFY_EN + raydium_notify_function(ACTIVE_MODE); +#endif + raydium_ts_resume(&g_raydium_ts->client->dev); + break; + + /*screen off*/ + case FB_BLANK_POWERDOWN: + pr_debug("[touch]FB_BLANK_POWERDOWN\n"); +#ifdef GESTURE_EN + + /* clear palm status */ + + g_raydium_ts->is_palm = 0; +#endif +#ifdef HOST_NOTIFY_EN + raydium_notify_function(SLEEP_MODE); +#endif + raydium_ts_suspend(&g_raydium_ts->client->dev); + break; + + /*ambient mode*/ + case FB_BLANK_VSYNC_SUSPEND: + pr_debug("[touch]FB_BLANK_VSYNC_SUSPEND\n"); +#ifdef GESTURE_EN + + /* clear palm status */ + + g_raydium_ts->is_palm = 0; +#endif +#ifdef HOST_NOTIFY_EN + raydium_notify_function(AMBIENT_MODE); +#endif + raydium_ts_suspend(&g_raydium_ts->client->dev); + break; + + default: + break; + } + } + + return 0; +} + +static void raydium_register_notifier(void) +{ + memset(&g_raydium_ts->fb_notif, 0, sizeof(g_raydium_ts->fb_notif)); + g_raydium_ts->fb_notif.notifier_call = fb_notifier_callback; + + /* register on the fb notifier and work with fb*/ + if (fb_register_client(&g_raydium_ts->fb_notif)) + pr_err("[touch]register notifier failed\n"); +} + +static void raydium_unregister_notifier(void) +{ + fb_unregister_client(&g_raydium_ts->fb_notif); +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void raydium_ts_early_suspend(struct early_suspend *handler) +{ + + raydium_ts_do_suspend(); +} + +static void raydium_ts_late_resume(struct early_suspend *handler) +{ + raydium_ts_do_resume(); +} +#endif /*end of CONFIG_FB*/ + +#ifdef CONFIG_OF +static int raydium_get_dt_coords(struct device *dev, char *name, + struct raydium_ts_platform_data *pdata) +{ + u32 coords[COORDS_ARR_SIZE]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + + if (!prop->value) + return -ENODATA; + + + coords_size = prop->length / sizeof(u32); + if (coords_size != COORDS_ARR_SIZE) { + pr_err("[touch]invalid %s\n", name); + return -EINVAL; + } + + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + pr_err("[touch]unable to read %s\n", name); + return rc; + } + + if (!strcmp(name, "raydium,display-coords")) { + pdata->x_min = coords[0]; + pdata->y_min = coords[1]; + pdata->x_max = coords[2]; + pdata->y_max = coords[3]; + } else { + pr_err("[touch]unsupported property %s\n", name); + return -EINVAL; + } + + return 0; +} + +static int raydium_parse_dt(struct device *dev, + struct raydium_ts_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + int rc = 0; + u32 temp_val = 0; + + pdata->name = RAYDIUM_NAME; + + rc = raydium_get_dt_coords(dev, "raydium,display-coords", pdata); + if (rc) + return rc; + + + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, + "raydium,reset-gpio", + 0, + &pdata->reset_gpio_flags); + if (pdata->reset_gpio < 0) + return pdata->reset_gpio; + + + pdata->irq_gpio = of_get_named_gpio_flags(np, + "raydium,irq-gpio", + 0, + &pdata->irq_gpio_flags); + if (pdata->irq_gpio < 0) + return pdata->irq_gpio; + + + rc = of_property_read_u32(np, + "raydium,hard-reset-delay-ms", &temp_val); + if (!rc) + pdata->hard_rst_dly = temp_val; + else + return rc; + + + rc = of_property_read_u32(np, + "raydium,soft-reset-delay-ms", &temp_val); + if (!rc) + pdata->soft_rst_dly = temp_val; + else + return rc; + + + rc = of_property_read_u32(np, "raydium,num-max-touches", &temp_val); + if (!rc) + pdata->num_max_touches = temp_val; + else + return rc; + +#ifdef FW_MAPPING_BYID_EN + rc = of_property_read_u32(np, "raydium,fw_id", &temp_val); + if (!rc) + pdata->fw_id = temp_val; + else + return rc; +#endif + return 0; +} +#else +static int raydium_parse_dt(struct device *dev, + struct raydium_ts_platform_data *pdata) +{ + return -ENODEV; +} +#endif /*end of CONFIG_OF*/ + +static void raydium_input_set(struct input_dev *input_dev) +{ + int ret = 0; + unsigned char i; + + input_dev->name = "raydium_ts";/*name need same with .idc*/ + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &g_raydium_ts->client->dev; + input_dev->open = raydium_ts_open;/*touch lock*/ + input_dev->close = raydium_ts_close; + input_set_drvdata(input_dev, g_raydium_ts); + + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + pr_debug("[touch]set abs prarams x[%d], y[%d]\n", + g_raydium_ts->x_max, g_raydium_ts->y_max); + + /* Multitouch input params setup */ + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, + g_raydium_ts->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, + g_raydium_ts->y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, PRESS_MAX, 0, 0); + input_set_abs_params(input_dev, + ABS_MT_TOUCH_MAJOR, 0, WIDTH_MAX, 0, 0); + input_set_abs_params(input_dev, + ABS_MT_TOUCH_MINOR, 0, WIDTH_MAX, 0, 0); + + ret = input_mt_init_slots(input_dev, MAX_TOUCH_NUM, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (ret) + pr_err("[touch]failed to initialize MT slots: %d\n", ret); + + for (i = 0; i < (MAX_TOUCH_NUM * 2); i++) + gst_slot[i] = gst_slot_init; + +} +static int raydium_set_resolution(void) +{ + unsigned char u8_buf[4]; + int i32_ret = -1; + unsigned int u32_x, u32_y; + + mutex_lock(&g_raydium_ts->lock); + + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_error; + + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + RAYDIUM_PDA2_DISPLAY_INFO_ADDR, + u8_buf, 4); + if (i32_ret < 0) + goto exit_error; + + u32_x = u8_buf[3] << 8 | u8_buf[2]; + u32_y = u8_buf[1] << 8 | u8_buf[0]; + + pr_debug("[touch]RAD display info x:%d, y:%d\n", u32_x, u32_y); + + if (u32_x > 300 && u32_y > 300 && + u32_x < 600 && u32_y < 600) { + g_raydium_ts->x_max = u32_x - 1; + g_raydium_ts->y_max = u32_y - 1; + } + +exit_error: + mutex_unlock(&g_raydium_ts->lock); + return i32_ret; +} + +static int raydium_get_regulators(struct raydium_ts_data *ts) +{ + struct device *dev = &ts->client->dev; + int rc; + + ts->vdd = devm_regulator_get(dev, "vdd_ana"); + if (IS_ERR(ts->vdd)) { + rc = PTR_ERR(ts->vdd); + dev_err(dev, "Failed to get 'vdd_ana' regulator: %d\n", rc); + return rc; + } + + ts->vcc_i2c = devm_regulator_get(dev, "vcc_i2c"); + if (IS_ERR(ts->vcc_i2c)) { + rc = PTR_ERR(ts->vcc_i2c); + dev_err(dev, "Failed to get 'vcc_i2c' regulator: %d\n", rc); + return rc; + } + + return 0; +} + +static int raydium_config_regulators(struct raydium_ts_data *ts, bool enable) +{ + int retval = 0; + + if (!enable) + goto hw_shutdown; + + if (ts->vdd) { + if (regulator_count_voltages(ts->vdd) > 0) { + retval = regulator_set_voltage(ts->vdd, + VDD_VTG_MIN_UV, VDD_VTG_MAX_UV); + if (retval) { + dev_err(&ts->client->dev, + "regulator set_vtg failed retval =%d\n", + retval); + return retval; + } + } + } + + if (ts->vcc_i2c) { + if (regulator_count_voltages(ts->vcc_i2c) > 0) { + retval = regulator_set_voltage(ts->vcc_i2c, + I2C_VTG_MIN_UV, I2C_VTG_MAX_UV); + if (retval) { + dev_err(&ts->client->dev, + "regulator set_vtg failed retval =%d\n", + retval); + goto err_set_vtg_bus; + } + } + } + + return 0; + +hw_shutdown: + if (ts->vcc_i2c && + regulator_count_voltages(ts->vcc_i2c) > 0) + regulator_set_voltage(ts->vcc_i2c, 0, I2C_VTG_MAX_UV); +err_set_vtg_bus: + if (ts->vdd && + regulator_count_voltages(ts->vdd) > 0) + regulator_set_voltage(ts->vdd, 0, VDD_VTG_MAX_UV); + + return retval; +} + +static int raydium_enable_regulators(struct raydium_ts_data *ts, bool enable) +{ + int retval = 0; + + if (!enable) + goto disable_vdd; + + if (ts->vcc_i2c) { + retval = regulator_enable(ts->vcc_i2c); + if (retval < 0) { + dev_err(&ts->client->dev, + "%s: Failed to enable vcc regulator\n", + __func__); + return retval; + } + } + + if (ts->vdd) { + retval = regulator_enable(ts->vdd); + if (retval < 0) { + dev_err(&ts->client->dev, + "%s: Failed to enable vdd regulator\n", + __func__); + goto disable_vcc_i2c; + } + } + + return 0; +disable_vdd: + if (ts->vdd) + regulator_disable(ts->vdd); +disable_vcc_i2c: + if (ts->vcc_i2c) + regulator_disable(ts->vcc_i2c); + + return retval; +} + +static int raydium_power_on(struct raydium_ts_data *ts, bool on) +{ + int retval = 0; + + if (!on) + goto disable_reg; + + retval = raydium_config_regulators(ts, true); + if (retval) { + dev_err(&ts->client->dev, + "%s: Failed to config regulator\n", + __func__); + return retval; + } + + retval = raydium_enable_regulators(ts, true); + if (retval) { + dev_err(&ts->client->dev, + "%s: Failed to enable regulator\n", + __func__); + goto err_config_reg; + } + + return 0; +disable_reg: + raydium_enable_regulators(ts, false); +err_config_reg: + raydium_config_regulators(ts, false); + return retval; +} + +static int raydium_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct raydium_ts_platform_data *pdata = + (struct raydium_ts_platform_data *)client->dev.platform_data; + + struct input_dev *input_dev; + unsigned short u16_i2c_data; + int ret = 0; + + pr_debug("[touch] probe\n"); + + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, + sizeof(struct raydium_ts_platform_data), + GFP_KERNEL); + if (!pdata) { + dev_err(&client->dev, + "[touch]failed to allocate memory\n"); + return -ENOMEM; + } + + ret = raydium_parse_dt(&client->dev, pdata); + if (ret) { + dev_err(&client->dev, + "[touch]device tree parsing failed\n"); + goto parse_dt_failed; + } + } else + pdata = client->dev.platform_data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + ret = -ENODEV; + goto exit_check_functionality_failed; + } + + g_raydium_ts = devm_kzalloc(&client->dev, + sizeof(struct raydium_ts_data), + GFP_KERNEL); + if (!g_raydium_ts) { + pr_err("[touch]failed to allocate input driver data\n"); + return -ENOMEM; + } + + raydium_variable_init(); + + mutex_init(&g_raydium_ts->lock); + + i2c_set_clientdata(client, g_raydium_ts); + g_raydium_ts->irq_enabled = false; + g_raydium_ts->irq_wake = false; + + g_raydium_ts->irq_gpio = pdata->irq_gpio; + g_raydium_ts->rst_gpio = pdata->reset_gpio; + client->irq = g_raydium_ts->irq_gpio; + g_raydium_ts->u8_max_touchs = pdata->num_max_touches; + g_raydium_ts->client = client; + g_raydium_ts->x_max = pdata->x_max - 1; + g_raydium_ts->y_max = pdata->y_max - 1; + g_raydium_ts->is_suspend = 0; + g_raydium_ts->is_sleep = 0; +#ifdef GESTURE_EN + g_raydium_ts->is_palm = 0; +#endif + g_raydium_ts->fw_version = 0; + device_init_wakeup(&client->dev, 1); + +#ifdef MSM_NEW_VER + ret = raydium_ts_pinctrl_init(); + if (!ret && g_raydium_ts->ts_pinctrl) { + /* + * Pinctrl handle is optional. If pinctrl handle is found + * let pins to be configured in active state. If not + * found continue further without error. + */ + ret = pinctrl_select_state(g_raydium_ts->ts_pinctrl, + g_raydium_ts->pinctrl_state_active); + if (ret < 0) + pr_err("[touch]failed to set pin to active state\n"); + } +#endif /*end of MSM_NEW_VER*/ + + ret = raydium_get_regulators(g_raydium_ts); + if (ret < 0) { + pr_err("[touch]failed to get regulators\n"); + return -EINVAL; + } + + ret = raydium_power_on(g_raydium_ts, true); + if (ret < 0) { + pr_err("[touch]failed to power on\n"); + goto err_reg_req; + } + + ret = raydium_gpio_configure(true); + if (ret < 0) { + pr_err("[touch]failed to configure the gpios\n"); + goto err_gpio_req; + } + /*modify dtsi to 360*/ + msleep(pdata->soft_rst_dly); + + /*print touch i2c ready*/ + ret = raydium_check_i2c_ready(&u16_i2c_data); + if (ret < 0) { + pr_err("[touch]Check I2C failed\n"); + ret = -ENODEV; + goto exit_check_i2c; + } + + /*input device initialization*/ + input_dev = input_allocate_device(); + if (!input_dev) { + ret = -ENOMEM; + pr_err("[touch]failed to allocate input device\n"); + goto exit_input_dev_alloc_failed; + } + + raydium_set_resolution(); + + g_raydium_ts->input_dev = input_dev; + raydium_input_set(input_dev); + + ret = input_register_device(input_dev); + if (ret) { + pr_err("[touch]failed to register input device: %s\n", + dev_name(&client->dev)); + goto exit_input_register_device_failed; + } + +#ifdef GESTURE_EN + input_set_capability(input_dev, EV_KEY, KEY_SLEEP); + input_set_capability(input_dev, EV_KEY, KEY_POWER); +#endif + + /*suspend/resume routine*/ +#if defined(CONFIG_FB) + raydium_register_notifier(); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + /*Early-suspend level*/ + g_raydium_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + g_raydium_ts->early_suspend.suspend = raydium_ts_early_suspend; + g_raydium_ts->early_suspend.resume = raydium_ts_late_resume; + register_early_suspend(&g_raydium_ts->early_suspend); +#endif/*end of CONFIG_FB*/ + +#ifdef CONFIG_RM_SYSFS_DEBUG + raydium_create_sysfs(client); +#endif/*end of CONFIG_RM_SYSFS_DEBUG*/ + + INIT_WORK(&g_raydium_ts->work, raydium_work_handler); + + g_raydium_ts->workqueue = create_singlethread_workqueue("raydium_ts"); +#ifdef ENABLE_DUMP_DATA + INIT_DELAYED_WORK(&g_raydium_ts->dump_work, raydium_dump_data_work); +#endif + /*irq_gpio = 13 irqflags = 108*/ + pr_debug("[touch]pdata irq : %d\n", g_raydium_ts->irq_gpio); + pr_debug("[touch]client irq : %d, pdata flags : %d\n", + client->irq, pdata->irqflags); + + g_raydium_ts->irq = gpio_to_irq(pdata->irq_gpio); + ret = request_threaded_irq(g_raydium_ts->irq, NULL, raydium_ts_interrupt, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_NO_SUSPEND, + client->dev.driver->name, g_raydium_ts); + + if (ret < 0) { + pr_err("[touch]raydium_probe: request irq failed\n"); + goto exit_irq_request_failed; + } + + g_raydium_ts->irq_desc = irq_to_desc(g_raydium_ts->irq); + g_raydium_ts->irq_enabled = true; + + /*disable_irq then enable_irq for avoid Unbalanced enable for IRQ */ + + /*raydium_irq_control(ts, ENABLE);*/ + + pr_info("[touch]RAD Touch driver ver :0x%X\n", g_u32_driver_version); + +#ifdef FW_UPDATE_EN + /*fw update check*/ + ret = raydium_fw_update_check(u16_i2c_data); + if (ret < 0) { + pr_err("[touch]FW update check failed\n"); + ret = -ENODEV; + goto exit_irq_request_failed; + } +#endif + return 0; + +exit_irq_request_failed: +#if defined(CONFIG_FB) + raydium_unregister_notifier(); +#endif/*end of CONFIG_FB*/ + + cancel_work_sync(&g_raydium_ts->work); + input_unregister_device(input_dev); + +exit_input_register_device_failed: + input_free_device(input_dev); + +exit_input_dev_alloc_failed: +exit_check_i2c: + if (gpio_is_valid(pdata->reset_gpio)) + gpio_free(pdata->reset_gpio); + + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); + +err_gpio_req: +#ifdef MSM_NEW_VER + if (g_raydium_ts->ts_pinctrl) { + if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_release)) { + devm_pinctrl_put(g_raydium_ts->ts_pinctrl); + g_raydium_ts->ts_pinctrl = NULL; + } else { + ret = pinctrl_select_state(g_raydium_ts->ts_pinctrl, + g_raydium_ts->pinctrl_state_release); + if (ret) + pr_err("[touch]pinctrl_select_state failed\n"); + } + } +#endif/*end of MSM_NEW_VER*/ + +err_reg_req: + raydium_power_on(g_raydium_ts, false); +parse_dt_failed: +exit_check_functionality_failed: + return ret; + +} + +static int raydium_ts_remove(struct i2c_client *client) +{ + +#if defined(CONFIG_FB) + raydium_unregister_notifier(); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&g_raydium_ts->early_suspend); +#endif/*end of CONFIG_FB*/ + input_unregister_device(g_raydium_ts->input_dev); + input_free_device(g_raydium_ts->input_dev); + gpio_free(g_raydium_ts->rst_gpio); + +#ifdef CONFIG_RM_SYSFS_DEBUG + raydium_release_sysfs(client); +#endif /*end of CONFIG_RM_SYSFS_DEBUG*/ + + free_irq(client->irq, g_raydium_ts); + + if (gpio_is_valid(g_raydium_ts->rst_gpio)) + gpio_free(g_raydium_ts->rst_gpio); + + if (gpio_is_valid(g_raydium_ts->irq_gpio)) + gpio_free(g_raydium_ts->irq_gpio); + + cancel_work_sync(&g_raydium_ts->work); + destroy_workqueue(g_raydium_ts->workqueue); + + + kfree(g_raydium_ts); + + i2c_set_clientdata(client, NULL); + return 0; +} + +static const struct i2c_device_id raydium_ts_id[] = { + {RAYDIUM_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, raydium_ts_id); + +#ifdef CONFIG_OF +static const struct of_device_id raydium_match_table[] = { + { .compatible = "raydium,raydium-ts",}, + { }, +}; +#else +#define raydium_match_table NULL +#endif/*end of CONFIG_OF*/ + +static struct i2c_driver raydium_ts_driver = { + .probe = raydium_ts_probe, + .remove = raydium_ts_remove, + .id_table = raydium_ts_id, + .driver = { + .name = RAYDIUM_NAME, + .owner = THIS_MODULE, + .of_match_table = raydium_match_table, +#if defined(CONFIG_PM) + .pm = &raydium_ts_pm_ops, +#endif/*end of CONFIG_PM*/ + }, +}; + +static int __init raydium_ts_init(void) +{ + int ret; + + ret = i2c_add_driver(&raydium_ts_driver); + return ret; +} + +static void __exit raydium_ts_exit(void) +{ + i2c_del_driver(&raydium_ts_driver); +} + +module_init(raydium_ts_init); +module_exit(raydium_ts_exit); + +MODULE_AUTHOR("Raydium"); +MODULE_DESCRIPTION("Raydium TouchScreen driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_driver.h b/drivers/input/touchscreen/raydium_wt030/raydium_driver.h new file mode 100644 index 0000000000000000000000000000000000000000..e604a59648f632e58a2e5e6c7ab893e490f0b7dd --- /dev/null +++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.h @@ -0,0 +1,378 @@ +/* drivers/input/touchscreen/raydium_wt030/raydium_driver.h + * + * Raydium TouchScreen driver. + * + * Copyright (c) 2010 Raydium tech Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __LINUX_RAYDIUM_H +#define __LINUX_RAYDIUM_H +#define RAYDIUM_NAME "raydium_ts" +#define COORDS_ARR_SIZE 4 +#define I2C_VTG_MIN_UV 1650000 +#define I2C_VTG_MAX_UV 1950000 +#define VDD_VTG_MIN_UV 1650000 +#define VDD_VTG_MAX_UV 1950000 +#define RAD_MAIN_VERSION 0x01 +#define RAD_MINOR_VERSION 0x07 +#define RAD_CUSTOMER_VERSION 0x0100 + +#if defined(CONFIG_TOUCHSCREEN_RAYDIUM_CHIPSET) +/* IC timing control arguments */ +#define RAYDIUM_POWERON_DELAY_USEC 500 +#define RAYDIUM_RESET_INTERVAL_MSEC 5 +#define RAYDIUM_RESET_RESTORE_USEC 200 +#define RAYDIUM_RESET_DELAY_MSEC 100 + +/* I2C bus slave address(ID) */ +#define RAYDIUM_I2C_EID (0x5A) +#define RAYDIUM_I2C_NID (0x39) + +/* I2C R/W configuration literal */ +#define RAYDIUM_I2C_WRITE I2C_SMBUS_WRITE +#define RAYDIUM_I2C_READ I2C_SMBUS_READ +#define SYN_I2C_RETRY_TIMES 2 +#define MAX_WRITE_PACKET_SIZE 64 +#define MAX_READ_PACKET_SIZE 64 + +/* PDA address and bit definition*/ +#define RAD_READ_FT_DATA_CMD 0x2000019C +/* 1byte, disable:0x00 ; enable:0x20*/ +#define RAD_GESTURE_STATE_CMD 0x200005F4 +#define RAD_GESTURE_DISABLE 0x00 +#define RAD_GESTURE_ENABLE 0x20 +/* 4bytes, [0]:ready ; [1]:type ; [2]:direction*/ +#define RAD_GESTURE_RESULT_CMD 0x200005F0 +#define RAD_CHK_I2C_CMD 0x500009BC +#define RAD_PDA2_CTRL_CMD 0x50000628 +#define RAD_ENABLE_PDA2 0x04 +#define RAD_ENABLE_SI2 0x02 + +/* PDA literal */ +#define MASK_8BIT 0xFF +#define RAD_I2C_PDA_ADDRESS_LENGTH 4 +#define PDA_MODE 1 +#define PDA2_MODE 2 +#define RAD_I2C_PDA_MODE_DISABLE 0x00 +#define RAD_I2C_PDA_MODE_ENABLE 0x80 +/* Using byte mode due to data might be not word-aligment */ +#define RAD_I2C_PDA_MODE_WORD_MODE 0x40 +#define RAD_I2C_PDA_2_MODE_DISABLE 0x20 +#define RAD_PALM_DISABLE 0x00 +#define RAD_PALM_ENABLE 0x01 +#define RAD_WAKE_UP 0x02 +#define RAYDIUM_TEST_FW 0x80 +#define RAYDIUM_TEST_PARA 0x40 +#define RAYDIUM_BOOTLOADER 0x20 +#define RAYDIUM_FIRMWARE 0x10 +#define RAYDIUM_PARA 0x08 +#define RAYDIUM_COMP 0x04 +#define RAYDIUM_BASELINE 0x02 +#define RAYDIUM_INIT 0x01 +#define FAIL 0 +#define ERROR -1 +#define SUCCESS 1 +#define DISABLE 0 +#define ENABLE 1 + +/* PDA2 setting */ +/* Page 0 ~ Page A */ +#define MAX_PAGE_AMOUNT 11 + +/* PDA2 address and setting definition*/ +#define RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR 0x00 /* only in Page 0 */ +#define RAYDIUM_PDA2_TCH_RPT_ADDR 0x01 /* only in Page 0 */ +#define RAYDIUM_PDA2_HOST_CMD_ADDR 0x02 /* only in Page 0 */ +#define RAYDIUM_PDA2_PALM_AREA_ADDR 0x03 /* only in Page 0 */ +#define RAYDIUM_PDA2_GESTURE_RPT_ADDR 0x04 /* only in Page 0 */ +#define RAYDIUM_PDA2_PALM_STATUS_ADDR 0x05 /* only in Page 0 */ +#define RAYDIUM_PDA2_FW_VERSION_ADDR 0x06 /* only in Page 0 */ +#define RAYDIUM_PDA2_PANEL_VERSION_ADDR 0x07 /* only in Page 0 */ +#define RAYDIUM_PDA2_DISPLAY_INFO_ADDR 0x08 /* only in Page 0 */ +#define RAYDIUM_PDA2_PDA_CFG_ADDR 0x09 /* only in Page 0 */ +#define RAYDIUM_PDA2_RAWDATA_ADDR 0x0B /* only in Page 0 */ +/* Page 0 ~ Page 9 will be directed to Page 0 */ +#define RAYDIUM_PDA2_PAGE_ADDR 0x0A +#define RAYDIUM_PDA2_PAGE_0 0x00 +/* temporary switch to PDA once */ +#define RAYDIUM_PDA2_ENABLE_PDA 0x0A +/* permanently switch to PDA mode */ +#define RAYDIUM_PDA2_2_PDA (MAX_PAGE_AMOUNT + 2) + +/* Raydium host cmd */ +#define RAYDIUM_HOST_CMD_NO_OP 0x00 +#define RAYDIUM_HOST_CMD_PWR_SLEEP 0x30 +#define RAYDIUM_HOST_CMD_DISPLAY_MODE 0x33 +#define RAYDIUM_HOST_CMD_CALIBRATION 0x5C +#define RAYDIUM_HOST_CMD_TP_MODE 0x60 +#define RAYDIUM_HOST_CMD_FT_MODE 0x61 + +/* PDA2 literal */ +/* entry byte + target page byte */ +#define RAYDIUM_I2C_PDA2_PAGE_LENGTH 2 + + +/* Touch report */ +#define MAX_TOUCH_NUM 2 +#define MAX_REPORT_PACKET_SIZE 35 +#define MAX_TCH_STATUS_PACKET_SIZE 4 +#define PRESS_MAX 0xFFFF +#define WIDTH_MAX 0xFFFF +#define BYTE_SHIFT 8 + +/* FW update literal */ +#define RAYDIUM_FW_BIN_PATH_LENGTH 256 + +#define RAD_BOOT_1X_SIZE 0x800 +#define RAD_INIT_1X_SIZE 0x200 +#define RAD_FW_1X_SIZE 0x5000 +#define RAD_PARA_1X_SIZE 0xE4 +#define RAD_TESTFW_1X_SIZE 0x5600 + +#define RAD_BOOT_2X_SIZE 0x800 +#define RAD_INIT_2X_SIZE 0x200 +#define RAD_FW_2X_SIZE 0x6200 +#define RAD_PARA_2X_SIZE 0x15C +#define RAD_TESTFW_2X_SIZE (RAD_FW_2X_SIZE + RAD_PARA_2X_SIZE + 4) + +#define RAD_CMD_UPDATE_BIN 0x80 +#define RAD_CMD_UPDATE_END 0x81 +#define RAD_CMD_BURN_FINISH 0x82 + +/* FT APK literal */ +#define RAD_HOST_CMD_POS 0x00 +#define RAD_FT_CMD_POS 0x01 +#define RAD_FT_CMD_LENGTH 0x02 + +/* FT APK data type */ +#define RAYDIUM_FT_UPDATE 0x01 + +/*Raydium system flag*/ +#define INT_FLAG 0x01 +#define ENG_MODE 0x02 + +/* define display mode */ +#define ACTIVE_MODE 0x00 +#define AMBIENT_MODE 0x01 +#define SLEEP_MODE 0x02 + +#define RAD_20 0x2209 + +/* Enable sysfs */ +#define CONFIG_RM_SYSFS_DEBUG + +/* Gesture switch */ +#define GESTURE_EN + +/* Enable FW update */ +/* #define FW_UPDATE_EN */ +/* #define FW_MAPPING_EN */ +#define HOST_NOTIFY_EN +#define MSM_NEW_VER + +/* enable ESD */ +/* #define ESD_SOLUTION_EN */ +/* #define ENABLE_DUMP_DATA */ +/* #define ENABLE_FLASHLOG_BACKUP */ +#ifdef ENABLE_DUMP_DATA +#define DATA_MAP_5_5 0 +#endif + + + +#define PINCTRL_STATE_ACTIVE "pmx_ts_active" +#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" +#define PINCTRL_STATE_RELEASE "pmx_ts_release" + +#if defined(CONFIG_TOUCHSCREEN_RM_TS_SELFTEST) +#define RAD_SELFTEST +#endif + +struct raydium_ts_data { + unsigned int irq; + unsigned int irq_gpio; + unsigned int rst_gpio; + unsigned int x_max; + unsigned int y_max; +#ifdef FILTER_POINTS + unsigned int x_pos[2]; + unsigned int y_pos[2]; + unsigned int last_x_pos[2]; + unsigned int last_y_pos[2]; +#else + unsigned int x_pos[2]; + unsigned int y_pos[2]; +#endif + unsigned int pressure; + unsigned int is_suspend; + unsigned int is_sleep; +#ifdef GESTURE_EN + unsigned int is_palm; +#endif + unsigned char u8_max_touchs; + + struct i2c_client *client; + struct input_dev *input_dev; + struct mutex lock; + struct work_struct work; + struct workqueue_struct *workqueue; + struct irq_desc *irq_desc; + bool irq_enabled; + bool irq_wake; + +#if defined(CONFIG_FB) + struct notifier_block fb_notif; + int blank; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif /*end of CONFIG_FB*/ + + struct regulator *vdd; + struct regulator *vcc_i2c; + unsigned int fw_version; + unsigned short id; + char *vcc_name; +#ifdef MSM_NEW_VER + struct pinctrl *ts_pinctrl; + struct pinctrl_state *pinctrl_state_active; + struct pinctrl_state *pinctrl_state_suspend; + struct pinctrl_state *pinctrl_state_release; +#endif /*end of MSM_NEW_VER*/ + +#ifdef ENABLE_DUMP_DATA + struct delayed_work dump_work; + +#endif /*end of ENABLE_DUMP_DATA*/ + +}; +struct raydium_platform_data { + char *vdd_name; + int irq_gpio_number; + int reset_gpio_number; + int x_max; + int y_max; +}; + +struct raydium_ts_platform_data { + char *name; + u32 irqflags; + u32 irq_gpio; + u32 irq_gpio_flags; + u32 reset_gpio; + u32 reset_gpio_flags; + u32 x_max; + u32 y_max; + u32 x_min; + u32 y_min; + u32 hard_rst_dly; + u32 soft_rst_dly; + u32 num_max_touches; + u32 fw_id; +}; + +/* TODO: Using struct+memcpy instead of array+offset*/ +enum raydium_pt_report_status { + POS_SEQ = 0,/*1:touch, 0:no touch*/ + POS_PT_AMOUNT, + POS_GES_STATUS, + POS_FW_STATE, +}; + +enum raydium_pt_report_idx { + POS_PT_ID = 0, + POS_X_L, + POS_X_H, + POS_Y_L, + POS_Y_H, + POS_PRESSURE_L, + POS_PRESSURE_H, + POS_WX_L, + POS_WX_H, + POS_WY_L, + POS_WY_H, + LEN_PT = 11 +}; + +extern int raydium_read_touchdata(unsigned char *tp_status, unsigned char *buf); +extern unsigned char raydium_mem_table_setting(void); +extern int wait_fw_state(struct i2c_client *client, unsigned int u32_addr, + unsigned int u32_state, unsigned long u32_delay_us, + unsigned short u16_retry); +extern int wait_irq_state(struct i2c_client *client, + unsigned int u32_retry_time, + unsigned int u32_delay_us); +extern void raydium_irq_control(bool enable); + +extern int raydium_i2c_mode_control(struct i2c_client *client, + unsigned char u8_mode); +extern int raydium_i2c_pda_read(struct i2c_client *client, + unsigned int u32_addr, unsigned char *u8_r_data, + unsigned short u16_length); +extern int raydium_i2c_pda_write(struct i2c_client *client, + unsigned int u32_addr, unsigned char *u8_w_data, + unsigned short u16_length); +extern int raydium_i2c_pda2_read(struct i2c_client *client, + unsigned char u8_addr, + unsigned char *u8_r_data, + unsigned short u16_length); +extern int raydium_i2c_pda2_write(struct i2c_client *client, + unsigned char u8_addr, + unsigned char *u8_w_data, + unsigned short u16_length); +extern int raydium_i2c_pda2_set_page(struct i2c_client *client, + unsigned int is_suspend, + unsigned char u8_page); +extern unsigned char raydium_selftest_stop_mcu(struct i2c_client *client); +extern int raydium_burn_comp(struct i2c_client *client); +extern int raydium_burn_fw(struct i2c_client *client); +extern int raydium_fw_upgrade_with_bin_file(struct i2c_client *client, + char *arguments, + size_t count, + struct device *dev); +extern int raydium_load_test_fw(struct i2c_client *client); +extern int raydium_fw_update_check(unsigned short u16_i2c_data); +extern int raydium_i2c_pda_set_address(unsigned int u32_address, + unsigned char u8_mode); +extern unsigned char raydium_mem_table_init(unsigned short u16_id); +extern unsigned char raydium_id_init(unsigned char u8_type); + +#ifdef RAD_SELFTEST +extern int raydium_do_selftest(void); +#endif +int raydium_esd_check(void); + +extern struct attribute *raydium_attributes[]; + +extern unsigned char g_u8_raydium_flag; +extern unsigned char g_u8_addr; +extern unsigned char g_u8_i2c_mode; +extern unsigned char g_u8_upgrade_type; +extern unsigned char g_u8_raw_data_type; +extern unsigned int g_u32_raw_data_len; /* 72 bytes*/ +extern unsigned int g_u32_length; +extern unsigned long g_u32_addr; +extern unsigned char *g_rad_fw_image, *g_rad_init_image; +extern unsigned char *g_rad_boot_image, *g_rad_para_image; +extern unsigned char *g_rad_testfw_image, *g_rad_testpara_image; +extern unsigned char g_u8_table_setting, g_u8_table_init; +extern unsigned int g_u32_driver_version; +extern unsigned char g_u8_resetflag; +extern struct raydium_ts_data *g_raydium_ts; + +#endif +#endif /*__LINUX_RAYDIUM_H*/ + +MODULE_AUTHOR("Raydium"); +MODULE_DESCRIPTION("Raydium TouchScreen driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c b/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c new file mode 100644 index 0000000000000000000000000000000000000000..e4a30053d636d192d85a87a0c2c314e21c38f78b --- /dev/null +++ b/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c @@ -0,0 +1,1815 @@ +/* drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c + * + * Raydium TouchScreen driver. + * + * Copyright (c) 2010 Raydium tech Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "raydium_driver.h" +#if defined(FW_MAPPING_EN) +#include "rad_fw_image_21.h" +#endif + +#ifdef FW_UPDATE_EN + +#ifdef ENABLE_FLASHLOG_BACKUP +unsigned char raydium_turn_on_flash_2X(struct i2c_client *client) +{ + unsigned int u32_read = 0; + unsigned char u8_buf[4]; + + /*Turn on Flash*/ + memset(u8_buf, 0, sizeof(u8_buf)); + if (raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4) == ERROR) + return ERROR; + + u8_buf[0] = 0x20; + if (raydium_i2c_pda_write(client, 0x50000914, u8_buf, 4) == ERROR) + return ERROR; + + return SUCCESS; +} + +unsigned char raydium_read_fpc_flash(struct i2c_client *client, + unsigned int u32_addr, unsigned char *u8_r_data) +{ + unsigned int u32_read; + unsigned char u8_buf[4]; + + pr_debug("[touch]raydium_read_fpc_flash\n"); + + if (raydium_i2c_pda_read(client, 0x40000000, u8_buf, 4) == ERROR) + return ERROR; + + u8_buf[0] |= 0x40; + if (raydium_i2c_pda_write(client, 0x40000000, u8_buf, 4) == ERROR) + return ERROR; + + memset(u8_buf, 0, sizeof(u8_buf)); + if (raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4) == ERROR) + return ERROR; + + u8_buf[0] = (u32_addr & 0x000000FF); + u8_buf[1] = ((u32_addr & 0x0000FF00) >> 8); + u8_buf[2] = ((u32_addr & 0x00FF0000) >> 16); + u8_buf[3] = ((u32_addr & 0xFF000000) >> 24); + + if (raydium_i2c_pda_write(client, 0x50000910, u8_buf, 4) == ERROR) + return ERROR; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x40; + + if (raydium_i2c_pda_write(client, 0x50000914, u8_buf, 4) == ERROR) + return ERROR; + + usleep_range(950, 1050); + + if (raydium_i2c_pda_read(client, 0x5000093C, u8_r_data, 4) == ERROR) + return ERROR; + + return SUCCESS; +} + +unsigned char raydium_read_flash_log(void) +{ + unsigned char u8_buf[4]; + unsigned int u32_readbuf; + unsigned char u8_ret = 0; + unsigned char u8_logcount = 0; + unsigned int u32_temp = 0; + unsigned char u8_i = 0, u8_j = 0; + + raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, RAYDIUM_PDA2_2_PDA); + g_u8_i2c_mode = PDA_MODE; + pr_debug("[touch]Disable PDA2_MODE\n"); + + if ((g_raydium_ts->id & 0x2000) != 0) + raydium_turn_on_flash_2X(g_raydium_ts->client); + + for (u8_i = 0; u8_i < 4; u8_i++) { + u32_temp = (0x9000 + (u8_i*4)); + raydium_read_fpc_flash(g_raydium_ts->client, u32_temp, + &u32_readbuf); + if (u8_i == 0 && u32_readbuf == 0xFFFFFFFF) { + pr_err("[touch]Raydium flash no log\n"); + return FAIL; + } + pr_debug("[touch]Raydium flash 0x%x = 0x%x\n", + u32_temp, u32_readbuf); + u32_readbuf = u32_readbuf & (~u32_readbuf + 1); + pr_debug("[touch]Raydium flash reverse = 0x%x\n", + u32_readbuf); + u32_temp = 1; + u8_j = 0; + while (u32_readbuf != u32_temp) { + u8_j++; + u32_temp <<= 1; + if (u8_j == 32) + break; + } + if (u8_i == 0) { + if ((u8_j > 0) && (u8_j < 32)) { + u8_logcount = u8_i*32 + u8_j; + pr_debug("[touch]logcount = Log%d\n", + (u8_logcount - 1)); + break; + } + } else { + if (u8_j < 32) { + u8_logcount = u8_i*32 + u8_j; + pr_debug("[touch]logcount = Log%d\n", + (u8_logcount - 1)); + break; + } + } + } + + if (u8_logcount != 0) { + u32_temp = (0x9014 + (u8_logcount-1) * 48); + raydium_read_fpc_flash(g_raydium_ts->client, u32_temp, u8_buf); + pr_info("[touch]Rad log fw version 0x%x.0x%x.0x%x.0x%x\n", + u8_buf[0], u8_buf[1], u8_buf[2], u8_buf[3]); + if ((g_raydium_ts->id & 0x2000) != 0) + g_raydium_ts->id = 0x2000 | ((u8_buf[0] & 0xF) << 8) + | u8_buf[1]; + + return SUCCESS; + } + return FAIL; +} +#endif +unsigned char raydium_mem_table_init(unsigned short u16_id) +{ + unsigned int u8_ret = 0; + + pr_info("[touch]Raydium table init 0x%x\n", u16_id); + + if ((u16_id & 0x2000) != 0) { + g_rad_boot_image = kzalloc(RAD_BOOT_2X_SIZE, GFP_KERNEL); + g_rad_init_image = kzalloc(RAD_INIT_2X_SIZE, GFP_KERNEL); + g_rad_fw_image = kzalloc(RAD_FW_2X_SIZE, GFP_KERNEL); + g_rad_para_image = kzalloc(RAD_PARA_2X_SIZE + 4, GFP_KERNEL); + g_rad_testfw_image = kzalloc(RAD_TESTFW_2X_SIZE, GFP_KERNEL); + g_rad_testpara_image = kzalloc(RAD_PARA_2X_SIZE + 4, + GFP_KERNEL); + g_u8_table_init = SUCCESS; + u8_ret = SUCCESS; + } + + return u8_ret; +} + +unsigned char raydium_mem_table_setting(void) +{ + unsigned char u8_ret = SUCCESS; +#ifdef ENABLE_FLASHLOG_BACKUP + unsigned char u8_buf[4]; + static unsigned char u8_readflash; +#endif + + pr_info("[touch]Raydium ID is 0x%x\n", g_raydium_ts->id); + switch (g_raydium_ts->id) { + case RAD_20: + memcpy(g_rad_boot_image, u8_rad_boot_20, RAD_BOOT_2X_SIZE); + memcpy(g_rad_init_image, u8_rad_init_20, RAD_INIT_2X_SIZE); + memcpy(g_rad_fw_image, u8_rad_fw_20, RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image, u8_rad_testfw_20, RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE, + u8_rad_testpara_20, RAD_PARA_2X_SIZE + 4); + if (g_rad_boot_image[0x82] >= 4) { + memcpy(g_rad_para_image, + u8_rad_para_20, + RAD_PARA_2X_SIZE + 4); + memcpy(g_rad_testpara_image, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE + 4); + } else { + memcpy(g_rad_para_image, + u8_rad_para_20, + RAD_PARA_2X_SIZE); + memcpy(g_rad_testpara_image, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE); + } + break; +#if defined(FW_MAPPING_EN) + case RAD_21: + memcpy(g_rad_boot_image, u8_rad_boot_21, RAD_BOOT_2X_SIZE); + memcpy(g_rad_init_image, u8_rad_init_21, RAD_INIT_2X_SIZE); + memcpy(g_rad_fw_image, u8_rad_fw_21, RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image, u8_rad_testfw_21, RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE, + u8_rad_testpara_21, + RAD_PARA_2X_SIZE + 4); + if (g_rad_boot_image[0x82] >= 4) { + memcpy(g_rad_para_image, + u8_rad_para_21, + RAD_PARA_2X_SIZE + 4); + memcpy(g_rad_testpara_image, + u8_rad_testpara_21, + RAD_PARA_2X_SIZE + 4); + } else { + memcpy(g_rad_para_image, + u8_rad_para_21, + RAD_PARA_2X_SIZE); + memcpy(g_rad_testpara_image, + u8_rad_testpara_21, + RAD_PARA_2X_SIZE); + } + break; +#endif + default: + pr_info("[touch]mapping ic setting use default fw\n"); +#ifdef ENABLE_FLASHLOG_BACKUP + if (!u8_readflash) { + u8_ret = raydium_read_flash_log(); + u8_readflash = true; + + raydium_i2c_pda_read(g_raydium_ts->client, + RAD_PDA2_CTRL_CMD, + u8_buf, + 4); + u8_buf[0] |= RAD_ENABLE_PDA2 | RAD_ENABLE_SI2; + raydium_i2c_pda_write(g_raydium_ts->client, + RAD_PDA2_CTRL_CMD, + u8_buf, + 4); + raydium_i2c_pda_set_address(0x50000628, DISABLE); + + g_u8_i2c_mode = PDA2_MODE; + pr_debug("[touch]Enable PDA2_MODE\n"); + raydium_mem_table_setting(); + } else { + if ((g_raydium_ts->id & 0x2000) != 0) { + memcpy(g_rad_boot_image, + u8_rad_boot_20, + RAD_BOOT_2X_SIZE); + memcpy(g_rad_init_image, + u8_rad_init_20, + RAD_INIT_2X_SIZE); + memcpy(g_rad_fw_image, + u8_rad_fw_20, + RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image, + u8_rad_testfw_20, + RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE + 4); + if (g_rad_boot_image[0x82] >= 4) { + memcpy(g_rad_para_image, + u8_rad_para_20, + RAD_PARA_2X_SIZE + 4); + memcpy(g_rad_testpara_image, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE + 4); + } else { + memcpy(g_rad_para_image, + u8_rad_para_20, + RAD_PARA_2X_SIZE); + memcpy(g_rad_testpara_image, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE); + } + g_raydium_ts->id = RAD_20; + } + } + u8_ret = SUCCESS; + break; +#else + if ((g_raydium_ts->id & 0x2000) != 0) { + memcpy(g_rad_boot_image, + u8_rad_boot_20, + RAD_BOOT_2X_SIZE); + memcpy(g_rad_init_image, + u8_rad_init_20, + RAD_INIT_2X_SIZE); + memcpy(g_rad_fw_image, + u8_rad_fw_20, + RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image, + u8_rad_testfw_20, + RAD_FW_2X_SIZE); + memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE + 4); + if (g_rad_boot_image[0x82] >= 4) { + memcpy(g_rad_para_image, + u8_rad_para_20, + RAD_PARA_2X_SIZE + 4); + memcpy(g_rad_testpara_image, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE + 4); + } else { + memcpy(g_rad_para_image, + u8_rad_para_20, + RAD_PARA_2X_SIZE); + memcpy(g_rad_testpara_image, + u8_rad_testpara_20, + RAD_PARA_2X_SIZE); + } + g_raydium_ts->id = RAD_20; + } + u8_ret = SUCCESS; + break; +#endif + } + + g_u8_table_setting = 0; + return u8_ret; +} + +unsigned char raydium_id_init(unsigned char u8_type) +{ + unsigned int u8_ret = 0; + + switch (u8_type) { + case 0: + g_raydium_ts->id = RAD_20; + u8_ret = SUCCESS; + break; +#if defined(FW_MAPPING_EN) + case 1: + g_raydium_ts->id = RAD_21; + u8_ret = SUCCESS; + break; +#endif + } + + + return u8_ret; +} + +static unsigned int bits_reverse(unsigned int u32_num, unsigned int bit_num) +{ + unsigned int reverse = 0, u32_i; + + for (u32_i = 0; u32_i < bit_num; u32_i++) { + if (u32_num & (1 << u32_i)) + reverse |= 1 << ((bit_num - 1) - u32_i); + } + return reverse; +} + +static unsigned int rc_crc32(const char *buf, unsigned int u32_len, + unsigned int u32_crc) +{ + unsigned int u32_i; + unsigned char u8_flash_byte, u8_current, u8_j; + + for (u32_i = 0; u32_i < u32_len; u32_i++) { + u8_flash_byte = buf[u32_i]; + u8_current = (unsigned char)bits_reverse(u8_flash_byte, 8); + for (u8_j = 0; u8_j < 8; u8_j++) { + if ((u32_crc ^ u8_current) & 0x01) + u32_crc = (u32_crc >> 1) ^ 0xedb88320; + else + u32_crc >>= 1; + u8_current >>= 1; + } + } + return u32_crc; +} + +int wait_fw_state(struct i2c_client *client, unsigned int u32_addr, + unsigned int u32_state, unsigned long u32_delay_us, + unsigned short u16_retry) +{ + unsigned char u8_buf[4]; + unsigned int u32_read_data; + unsigned int u32_min_delay_us = u32_delay_us - 500; + unsigned int u32_max_delay_us = u32_delay_us + 500; + + do { + if (raydium_i2c_pda_read(client, u32_addr, u8_buf, 4) == ERROR) + return ERROR; + + memcpy(&u32_read_data, u8_buf, 4); + u16_retry--; + usleep_range(u32_min_delay_us, u32_max_delay_us); + } while ((u32_read_data != u32_state) && (u16_retry != 0)); + + if (u32_read_data != u32_state) { + pr_err("[touch]confirm data error : 0x%x\n", u32_read_data); + return ERROR; + } + + return SUCCESS; +} + +int raydium_do_software_reset(struct i2c_client *client) +{ + int i32_ret = SUCCESS; + + unsigned char u8_buf[4]; + + /*SW reset*/ + g_u8_resetflag = true; + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x01; + pr_info("[touch]SW reset\n"); + i32_ret = raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4); + if (i32_ret < 0) + goto exit; + + if ((g_raydium_ts->id & 0x2000) != 0) + msleep(25); +exit: + return i32_ret; +} + +static int raydium_check_fw_ready(struct i2c_client *client) +{ + int i32_ret = SUCCESS; + unsigned int u32_retry = 400; + unsigned char u8_buf[4]; + + u8_buf[1] = 0; + while (u8_buf[1] != 0x40 && u32_retry != 0) { + i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit; + + u32_retry--; + usleep_range(4500, 5500); + } + + if (u32_retry == 0) { + pr_err("[touch]%s, FW not ready, retry error!\n", __func__); + i32_ret = ERROR; + } else { + pr_info("[touch]%s, FW is ready!!\n", __func__); + usleep_range(4500, 5500); + } + +exit: + return i32_ret; +} + +int set_skip_load(struct i2c_client *client) +{ + int i32_ret = SUCCESS; + unsigned int u32_retry_time = 1000; + unsigned char u8_buf[4]; + + /*Skip load*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x10; + u8_buf[1] = 0x08; + i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_do_software_reset(client); + if (i32_ret < 0) + pr_err("[touch]%s, SW reset error!\n", __func__); + + i32_ret = wait_fw_state(client, 0x20000214, 0x82, 2000, u32_retry_time); + if (i32_ret < 0) + pr_err("[touch]%s, wait_fw_state error!\n", __func__); + +exit_upgrade: + return i32_ret; +} + +/*check pram crc32*/ +static int raydium_check_pram_crc_2X(struct i2c_client *client, + unsigned int u32_addr, + unsigned int u32_len) +{ + int i32_ret = SUCCESS; + unsigned int u32_crc_addr = u32_addr + u32_len; + unsigned int u32_end_addr = u32_crc_addr - 1; + unsigned int u32_crc_result, u32_read_data; + unsigned int u32_retry = 400; + unsigned char u8_buf[4], u8_retry = 3; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = (unsigned char)(u32_addr & 0xFF); + u8_buf[1] = (unsigned char)((u32_addr & 0xFF00) >> 8); + u8_buf[2] = (unsigned char)(u32_end_addr & 0xFF); + u8_buf[3] = (unsigned char)((u32_end_addr & 0xFF00) >> 8); + + i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + u8_buf[3] |= 0x81; + i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4); + + while (u8_buf[3] != 0x80 && u32_retry != 0) { + i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + u32_retry--; + usleep_range(4500, 5500); + } + if (u32_retry == 0) { + pr_err("[touch]%s, Cal CRC not ready, retry error!\n", + __func__); + i32_ret = ERROR; + } + + i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + memcpy(&u32_crc_result, u8_buf, 4); + i32_ret = raydium_i2c_pda_read(client, u32_crc_addr, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + memcpy(&u32_read_data, u8_buf, 4); + + while (u32_read_data != u32_crc_result && u8_retry > 0) { + i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + memcpy(&u32_crc_result, u8_buf, 4); + usleep_range(1500, 2500); + u8_retry--; + } + if (u32_read_data != u32_crc_result) { + pr_err("[touch]check pram crc fail!!\n"); + pr_err("[touch]u32_read_data 0x%x\n", u32_read_data); + pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result); + i32_ret = ERROR; + goto exit_upgrade; + } else if (u8_retry != 3) { + pr_err("[touch]check pram crc pass!!\n"); + pr_err("[touch]u8_retry : %d\n", u8_retry); + pr_err("[touch]u32_read_data 0x%x\n", u32_read_data); + pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result); + i32_ret = ERROR; + goto exit_upgrade; + } + +exit_upgrade: + return i32_ret; +} + +/* upgrade firmware with image file */ +static int raydium_write_to_pram_2X(struct i2c_client *client, + unsigned int u32_fw_addr, + unsigned char u8_type) +{ + int i32_ret = ERROR; + unsigned int u32_fw_size = 0; + unsigned char *p_u8_firmware_data = NULL; + unsigned int u32_write_offset = 0; + unsigned short u16_write_length = 0; + + switch (u8_type) { + case RAYDIUM_INIT: + u32_fw_size = 0x200; + p_u8_firmware_data = g_rad_init_image; + break; + + case RAYDIUM_PARA: + u32_fw_size = 0x160; + p_u8_firmware_data = g_rad_para_image; + break; + + case RAYDIUM_FIRMWARE: + u32_fw_size = 0x6200; + p_u8_firmware_data = g_rad_fw_image; + break; + + case RAYDIUM_BOOTLOADER: + u32_fw_size = 0x800; + p_u8_firmware_data = g_rad_boot_image; + break; + + case RAYDIUM_TEST_FW: + u32_fw_size = 0x6360; + p_u8_firmware_data = g_rad_testfw_image; + break; + } + + u32_write_offset = 0; + while (u32_write_offset < u32_fw_size) { + if ((u32_write_offset + MAX_WRITE_PACKET_SIZE) < u32_fw_size) + u16_write_length = MAX_WRITE_PACKET_SIZE; + else + u16_write_length = + (unsigned short)(u32_fw_size - u32_write_offset); + + i32_ret = raydium_i2c_pda_write( + client, + (u32_fw_addr + u32_write_offset), + (p_u8_firmware_data + u32_write_offset), + u16_write_length); + if (i32_ret < 0) + goto exit_upgrate; + + u32_write_offset += (unsigned long)u16_write_length; + } + u32_fw_addr += u32_write_offset; + +exit_upgrate: + if (i32_ret < 0) { + pr_err("[touch]upgrade failed\n"); + return i32_ret; + } + pr_info("[touch]upgrade success\n"); + return 0; +} + +/* upgrade firmware with image file */ +static int raydium_fw_upgrade_with_image(struct i2c_client *client, + unsigned int u32_fw_addr, + unsigned char u8_type) +{ + int i32_ret = ERROR; + unsigned int u32_fw_size = 0; + unsigned char *p_u8_firmware_data = NULL; + unsigned int u32_write_offset = 0; + unsigned short u16_write_length = 0; + unsigned int u32_checksum = 0xFFFFFFFF; + + switch (u8_type) { + case RAYDIUM_INIT: + u32_fw_size = 0x1fc; + p_u8_firmware_data = g_rad_init_image; + break; + case RAYDIUM_PARA: + if ((g_raydium_ts->id & 0x2000) != 0) + u32_fw_size = 0x158; + p_u8_firmware_data = g_rad_para_image; + break; + case RAYDIUM_FIRMWARE: + if ((g_raydium_ts->id & 0x2000) != 0) + u32_fw_size = 0x61fc; + p_u8_firmware_data = g_rad_fw_image; + break; + case RAYDIUM_BOOTLOADER: + if ((g_raydium_ts->id & 0x2000) != 0) + u32_fw_size = 0x7FC; + p_u8_firmware_data = g_rad_boot_image; + break; + case RAYDIUM_TEST_FW: + if ((g_raydium_ts->id & 0x2000) != 0) + u32_fw_size = 0x635C; + p_u8_firmware_data = g_rad_testfw_image; + break; + } + + pr_debug("[touch]CRC 0x%08X\n", + *(unsigned int *)(p_u8_firmware_data + u32_fw_size)); + + u32_checksum = rc_crc32(p_u8_firmware_data, + u32_fw_size, u32_checksum); + u32_checksum = bits_reverse(u32_checksum, 32); + memcpy((p_u8_firmware_data + u32_fw_size), &u32_checksum, 4); + pr_debug("[touch]CRC result 0x%08X\n", u32_checksum); + u32_fw_size += 4; + + u32_write_offset = 0; + while (u32_write_offset < u32_fw_size) { + if ((u32_write_offset + MAX_WRITE_PACKET_SIZE) < u32_fw_size) + u16_write_length = MAX_WRITE_PACKET_SIZE; + else + u16_write_length = + (unsigned short) + (u32_fw_size - u32_write_offset); + + i32_ret = raydium_i2c_pda_write( + client, + (u32_fw_addr + u32_write_offset), + (p_u8_firmware_data + u32_write_offset), + u16_write_length); + if (i32_ret < 0) + goto exit_upgrate; + + u32_write_offset += (unsigned long)u16_write_length; + } + u32_fw_addr += u32_write_offset; + +exit_upgrate: + if (i32_ret < 0) { + pr_err("[touch]upgrade failed\n"); + return i32_ret; + } + pr_info("[touch]upgrade success\n"); + return 0; +} +static int raydium_boot_upgrade_2X(struct i2c_client *client) +{ + int i32_ret = SUCCESS; + unsigned char u8_buf[4]; + + /*set mcu hold*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x20; + i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + msleep(25); + + /*WRT boot-loader to PRAM first*/ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x50000900, u8_buf, 4); + + /*Sending bootloader*/ + i32_ret = raydium_write_to_pram_2X(client, 0x0000, + RAYDIUM_BOOTLOADER); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_check_pram_crc_2X(client, 0x000, 0x7FC); + if (i32_ret < 0) + goto exit_upgrade; + + /*release mcu hold*/ + /*Skip load*/ + i32_ret = set_skip_load(client); + if (i32_ret < 0) + pr_err("[touch]%s, set skip_load error!\n", __func__); + +exit_upgrade: + return i32_ret; +} + +/* Raydium fireware upgrade flow */ +static int raydium_fw_upgrade_2X(struct i2c_client *client, + unsigned char u8_type, + unsigned char u8_check_crc) +{ + int i32_ret = 0; + unsigned char u8_buf[4]; + unsigned short u16_retry = 1000; + + /*##### wait for boot-loader start #####*/ + pr_debug("[touch]Type is %x\n", u8_type); + + /*read Boot version*/ + if (raydium_i2c_pda_read(client, 0x80, u8_buf, 4) == ERROR) + return ERROR; + pr_debug("[touch]Boot version is %x\n", u8_buf[2]); + + if (u8_buf[2] >= 4) { + if (u8_type != RAYDIUM_COMP) { + /*set mcu hold*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x20; + i32_ret = raydium_i2c_pda_write(client, + 0x50000918, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, + 0x40000004, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + msleep(25); + } + + /*#start write data to PRAM*/ + if (u8_type == RAYDIUM_FIRMWARE) { + /* unlock PRAM */ + u8_buf[0] = 0x27; + i32_ret = raydium_i2c_pda_write(client, + 0x50000900, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_write_to_pram_2X(client, 0x800, + RAYDIUM_FIRMWARE); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_write_to_pram_2X(client, 0x6a00, + RAYDIUM_PARA); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_check_pram_crc_2X(client, 0x800, + 0x635C); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_BOOTLOADER) { + /* unlock PRAM */ + u8_buf[0] = 0x0E; + i32_ret = raydium_i2c_pda_write(client, 0x50000900, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_write_to_pram_2X(client, 0x0800, + RAYDIUM_BOOTLOADER); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_write_to_pram_2X(client, 0x1000, + RAYDIUM_INIT); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_check_pram_crc_2X(client, 0x800, + 0x7FC); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_check_pram_crc_2X(client, 0x1000, + 0x1FC); + if (i32_ret < 0) + goto exit_upgrade; + } + + if (u8_type != RAYDIUM_COMP) { + /*release mcu hold*/ + /*Skip load*/ + i32_ret = set_skip_load(client); + if (i32_ret < 0) + pr_err("[touch]%s, set skip_load error!\n", + __func__); + } + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x20000204, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000208, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x2000020C, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#confirm in burn mode*/ + if (wait_fw_state(client, 0x20000214, 255, + 2000, u16_retry) == ERROR) { + pr_err("[touch]Error, confirm in burn mode\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*Clear BL_CRC*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x10; + i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = u8_type; + i32_ret = raydium_i2c_pda_write(client, 0x50000904, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#set PRAM length (at 'h5000_090C)*/ + if (u8_type == RAYDIUM_COMP) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x60; + u8_buf[1] = 0x6b; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x9c; + u8_buf[1] = 0x02; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_FIRMWARE) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x08; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x5c; + u8_buf[1] = 0x63; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_BOOTLOADER) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x08; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x0A; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + } + + /*#set sync_data(0x20000200) = 0 as WRT data finish*/ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wait for input unlock key*/ + if (wait_fw_state(client, 0x20000210, 168, 1000, + u16_retry) == ERROR) { + pr_err("[touch]Error, wait for input unlock key\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#unlock key*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xd7; + i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xa5; + i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xa5; + i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wrt return data as unlock value*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xa8; + i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*pr_debug("[touch]ready burn flash\n");*/ + + /*#clr sync_data(0x20000200) = 0 as finish*/ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /* wait erase/wrt finish + * confirm burning_state result (gu8I2CSyncData.burning_state = + * BURNING_WRT_FLASH_FINISH at 0x2000020C) + */ + if (wait_fw_state(client, 0x2000020c, 6, 2000, + u16_retry) == ERROR) { + pr_err("[touch]Error, wait erase/wrt finish\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + pr_info("[touch]Burn flash ok\n"); + + if (u8_check_crc) { + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wait software reset finish*/ + msleep(25); + + /* wait sw reset finished 0x20000214 = 0x82 */ + if (wait_fw_state(client, 0x20000214, 130, 2000, + u16_retry) == ERROR) { + pr_err("[touch]Error, wait sw reset finished\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#set test_mode = 1*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x20000218, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wait crc check finish*/ + if (wait_fw_state(client, 0x20000208, 2, + 2000, u16_retry) + == ERROR) { + pr_err("[touch]Error, wait crc check finish\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#crc check pass 0x20000214 = 0x81*/ + if (wait_fw_state(client, 0x20000214, 0x81, + 2000, u16_retry) + == ERROR) { + pr_err("[touch]Error, confirm crc result\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + } + + } else { + /*#set main state as burning mode, normal init state*/ + /* #sync_data:200h + * main_state:204h + * normal_state:208h + * burning_state:20Ch + */ + /* #sync_data:210h + * cmd_type:210h + * ret_data:214h + * test_mode:218h + */ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x20000204, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000208, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x2000020C, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#confirm in burn mode*/ + if (wait_fw_state(client, 0x50000900, 63, + 2000, u16_retry) == ERROR) { + pr_err("[touch]Error, confirm in burn mode\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*Clear BL_CRC*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x10; + i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /* + * #set PRAM type (at 0x50000904), wrt param code + * #write PRAM relative data + * #init_code:0x01, + * baseline:0x02 + * COMP:0x04 + * param:0x08 + * FW:0x10 + * bootloader:0x20 + */ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = u8_type; + i32_ret = raydium_i2c_pda_write(client, 0x50000904, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /* + * #set PRAM addr (at 'h5000_0908) + * #init_code:0x800 + * Baseline:0xA00 + * COMP:0xCD4 + * para:0xF1C + * FW:0x1000 + * BOOT:0x5000 + * + * #set PRAM length (at 'h5000_090C) + */ + if (u8_type == RAYDIUM_INIT) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x6e; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x02; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_BASELINE) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xcc; + u8_buf[1] = 0x6c; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x30; + u8_buf[1] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_COMP) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x60; + u8_buf[1] = 0x6b; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x9c; + u8_buf[1] = 0x02; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_PARA) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x6a; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x5c; + u8_buf[1] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_FIRMWARE) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x08; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x5c; + u8_buf[1] = 0x63; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + } else if (u8_type == RAYDIUM_BOOTLOADER) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x08; + i32_ret = raydium_i2c_pda_write(client, 0x50000908, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x00; + u8_buf[1] = 0x0A; + i32_ret = raydium_i2c_pda_write(client, 0x5000090C, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + } + + /*#set sync_data(0x20000200) = 0 as WRT data finish*/ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#Wait bootloader check addr and PRAM unlock*/ + /*#Confirm ret_data at 0x20000214 is SET_ADDR_READY*/ + if (wait_fw_state(client, 0x20000214, 161, + 2000, u16_retry) == ERROR) { + pr_err("[touch]Error, SET_ADDR_READY\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#Confirm cmd_type at 0x20000210 is WRT_PRAM_DATA*/ + if (wait_fw_state(client, 0x20000210, 163, + 1000, u16_retry) == ERROR) { + pr_err("[touch]Error, WRT_PRAM_DATA\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#start write data to PRAM*/ + if (u8_type == RAYDIUM_INIT) { + i32_ret = raydium_fw_upgrade_with_image(client, 0x6E00, + RAYDIUM_INIT); + if (i32_ret < 0) + goto exit_upgrade; + } else if (u8_type == RAYDIUM_PARA) { + i32_ret = raydium_fw_upgrade_with_image(client, 0x6a00, + RAYDIUM_PARA); + if (i32_ret < 0) + goto exit_upgrade; + } else if (u8_type == RAYDIUM_FIRMWARE) { + i32_ret = raydium_fw_upgrade_with_image(client, 0x800, + RAYDIUM_FIRMWARE); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_fw_upgrade_with_image(client, 0x6a00, + RAYDIUM_PARA); + if (i32_ret < 0) + goto exit_upgrade; + + + } else if (u8_type == RAYDIUM_BOOTLOADER) { + i32_ret = raydium_fw_upgrade_with_image(client, 0x0800, + RAYDIUM_BOOTLOADER); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_fw_upgrade_with_image(client, 0x1000, + RAYDIUM_INIT); + if (i32_ret < 0) + goto exit_upgrade; + } + + /* + *set sync_data(0x20000200) = 0 as WRT data finish + *bootloader check checksum + */ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /* + * wait(checksum okay) ACK cmd + * (gu8I2CSyncData.cmd_type=0xa5 at 0x20000210) + */ + if (wait_fw_state(client, 0x20000210, + 165, 2000, u16_retry) == ERROR) { + pr_err("[touch]Error, WRT_CHECKSUM_OK\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#confirm ACK cmd result(ret_data=0xa5 at 0x20000214)*/ + if (wait_fw_state(client, 0x20000214, + 165, 1000, u16_retry) == ERROR) { + pr_err("[touch]Error, confirm ACK cmd result\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /* + * set ACK return data = 0x5A + * adb shell "echo 20000210 1 A5 > /sys/bus/i2c/drivers/ + * raydium_ts/1-0039 raydium_i2c_pda_access" + * above command can be ignored, due to previous while loop + * has check its value. + */ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xa5; + i32_ret = raydium_i2c_pda_write(client, 0x20000210, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x5a; + i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#clr sync_data(0x20000200) = 0 as finish*/ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wait for input unlock key*/ + if (wait_fw_state(client, 0x20000210, + 168, 1000, u16_retry) == ERROR) { + pr_err("[touch]Error, wait for input unlock key\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#unlock key*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xd7; + i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xa5; + i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xa5; + i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wrt return data as unlock value*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0xa8; + i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*pr_info("[touch]ready burn flash\n");*/ + + /*#clr sync_data(0x20000200) = 0 as finish*/ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /* wait erase/wrt finish + * confirm burning_state result (gu8I2CSyncData.burning_state = + * BURNING_WRT_FLASH_FINISH at 0x2000020C) + */ + if (wait_fw_state(client, 0x2000020c, + 6, 2000, u16_retry) == ERROR) { + dev_err(&g_raydium_ts->client->dev, + "[touch]Error, wait erase/wrt finish\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + pr_info("[touch]Burn flash ok\n"); + + + if (u8_type == RAYDIUM_BOOTLOADER) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x10; + u8_buf[1] = 0x08; + i32_ret = raydium_i2c_pda_write(client, 0x50000918, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + } + + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wait software reset finish*/ + msleep(25); + + /* wait sw reset finished 0x20000214 = 0x82 */ + if (wait_fw_state(client, 0x20000214, + 130, 2000, u16_retry) == ERROR) { + pr_err("[touch]Error, wait sw reset finished\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + if (u8_type == RAYDIUM_BASELINE || u8_type == RAYDIUM_COMP || + u8_type == RAYDIUM_FIRMWARE || u8_check_crc == 1) { + /*#set test_mode = 1*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x01; + i32_ret = raydium_i2c_pda_write(client, 0x20000218, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*#wait crc check finish*/ + if (wait_fw_state(client, 0x20000208, 2, + 2000, u16_retry) == ERROR) { + pr_err("[touch]Error, wait crc check finish\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + + /*#crc check pass 0x20000214 = 0x81*/ + if (wait_fw_state(client, 0x20000214, 0x81, + 2000, u16_retry) + == ERROR) { + pr_err("[touch]Error, confirm crc result\n"); + i32_ret = ERROR; + goto exit_upgrade; + } + } + } + + /*#run to next step*/ + pr_info("[touch]Type 0x%x => Pass\n", u8_type); + + if (u8_check_crc) { + /*#clr sync para*/ + memset(u8_buf, 0, sizeof(u8_buf)); + i32_ret = raydium_i2c_pda_write(client, 0x20000210, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + + i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + usleep_range(4500, 5500); + raydium_i2c_pda_set_address(0x50000628, DISABLE); + + g_u8_i2c_mode = PDA2_MODE; + + pr_info("[touch]Burn FW finish!\n"); + } + +exit_upgrade: + return i32_ret; +} + +int raydium_burn_fw(struct i2c_client *client) +{ + int i32_ret = 0; + + g_u8_resetflag = true; + if ((g_raydium_ts->id & 0x2000) != 0) { + pr_debug("[touch]start burn function!\n"); + i32_ret = raydium_boot_upgrade_2X(client); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_BOOTLOADER, 0); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_FIRMWARE, 1); + if (i32_ret < 0) + goto exit_upgrade; + + } + +exit_upgrade: + return i32_ret; +} + +int raydium_fw_update_check(unsigned short u16_i2c_data) +{ + + unsigned char u8_rbuffer[4]; + unsigned int u32_fw_version, u32_image_version; + int i32_ret = ERROR; + unsigned char u8_mode_change; + + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_error; + + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + RAYDIUM_PDA2_FW_VERSION_ADDR, + u8_rbuffer, + 4); + if (i32_ret < 0) + goto exit_error; + + mutex_unlock(&g_raydium_ts->lock); + + u32_fw_version = (u8_rbuffer[0] << 24) | (u8_rbuffer[1] << 16) | + (u8_rbuffer[2] << 8) | u8_rbuffer[3]; + pr_info("[touch]RAD FW ver 0x%.8x\n", u32_fw_version); + + g_raydium_ts->fw_version = u32_fw_version; + + g_raydium_ts->id = ((u16_i2c_data & 0xF) << 12) | + ((u8_rbuffer[0] & 0xF) << 8) | u8_rbuffer[1]; + + raydium_mem_table_init(g_raydium_ts->id); + if (raydium_mem_table_setting()) { + + u32_image_version = (g_rad_para_image[0x0004] << 24) | + (g_rad_para_image[0x0005] << 16) | + (g_rad_para_image[0x0006] << 8) | + g_rad_para_image[0x0007]; + + pr_info("[touch]RAD Image FW ver : 0x%x\n", u32_image_version); + } else { + pr_err("[touch]Mem setting failed, Stop fw upgrade!\n"); + return FAIL; + } + + if (u32_fw_version != u32_image_version) { + pr_info("[touch]FW need update.\n"); + raydium_irq_control(DISABLE); + if ((g_u8_raydium_flag & ENG_MODE) == 0) { + g_u8_raydium_flag |= ENG_MODE; + u8_mode_change = 1; + } + i32_ret = raydium_burn_fw(g_raydium_ts->client); + if (i32_ret < 0) + pr_err("[touch]FW update fail:%d\n", i32_ret); + + if (u8_mode_change) { + g_u8_raydium_flag &= ~ENG_MODE; + u8_mode_change = 0; + } + raydium_irq_control(ENABLE); + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_error; + + i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client, + RAYDIUM_PDA2_FW_VERSION_ADDR, + u8_rbuffer, + 4); + if (i32_ret < 0) + goto exit_error; + + mutex_unlock(&g_raydium_ts->lock); + u32_fw_version = (u8_rbuffer[0] << 24) | + (u8_rbuffer[1] << 16) | + (u8_rbuffer[2] << 8) | + u8_rbuffer[3]; + pr_info("[touch]RAD FW ver is 0x%x\n", + u32_fw_version); + g_raydium_ts->fw_version = u32_fw_version; + } else + pr_info("[touch]FW is the latest version.\n"); + + return i32_ret; + +exit_error: + mutex_unlock(&g_raydium_ts->lock); + return i32_ret; +} +int raydium_burn_comp(struct i2c_client *client) +{ + int i32_ret = FAIL; + + i32_ret = set_skip_load(client); + if (i32_ret < 0) + goto exit_upgrade; + + if ((g_raydium_ts->id & 0x2000) != 0) { + i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_COMP, 1); + if (i32_ret < 0) + goto exit_upgrade; + + } + + i32_ret = SUCCESS; + +exit_upgrade: + return i32_ret; +} + +int raydium_load_test_fw(struct i2c_client *client) +{ + int i32_ret = SUCCESS; + unsigned char u8_buf[4]; + unsigned int u32_crc_result, u32_read_data; + + /*set mcu hold*/ + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x20; + raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4); + raydium_i2c_pda_read(client, 0x40000004, u8_buf, 4); + u8_buf[0] |= 0x01; + raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4); + msleep(25); + + i32_ret = raydium_i2c_pda_read(client, 0x40000000, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + u8_buf[3] |= 0x40; + i32_ret = raydium_i2c_pda_write(client, 0x40000000, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + i32_ret = raydium_i2c_pda_read(client, 0x40000014, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + u8_buf[0] |= 0x04; + u8_buf[1] |= 0x04; + i32_ret = raydium_i2c_pda_write(client, 0x40000014, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + memset(u8_buf, 0, sizeof(u8_buf)); + pr_debug("[touch]Raydium WRT test_fw to PRAM\n"); + + i32_ret = raydium_i2c_pda_write(client, 0x50000900, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + /*Sending test fw*/ + if ((g_raydium_ts->id & 0x2000) != 0) { + i32_ret = raydium_fw_upgrade_with_image(client, + 0x800, RAYDIUM_TEST_FW); + if (i32_ret < 0) + goto exit_upgrade; + } + + /*check pram crc data*/ + if ((g_raydium_ts->id & 0x2000) != 0) { + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[1] = 0x08; + u8_buf[2] = 0x5B; + u8_buf[3] = 0x6B; + i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + u8_buf[3] |= 0x81; + i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4); + usleep_range(9500, 10500); + i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + memcpy(&u32_crc_result, u8_buf, 4); + i32_ret = raydium_i2c_pda_read(client, 0x6B5C, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + memcpy(&u32_read_data, u8_buf, 4); + if (u32_read_data != u32_crc_result) { + pr_err("[touch]check pram fw crc fail, result=0x%x\n", + u32_crc_result); + i32_ret = ERROR; + goto exit_upgrade; + } + + memset(u8_buf, 0, sizeof(u8_buf)); + u8_buf[0] = 0x60; + u8_buf[1] = 0x6B; + u8_buf[2] = 0xFB; + u8_buf[3] = 0x6D; + i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + u8_buf[3] |= 0x81; + i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4); + usleep_range(1000, 2000); + i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + memcpy(&u32_crc_result, u8_buf, 4); + i32_ret = raydium_i2c_pda_read(client, 0x6DFC, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + memcpy(&u32_read_data, u8_buf, 4); + if (u32_read_data != u32_crc_result) { + pr_err("[touch]check pram CB crc fail, result=0x%x\n", + u32_crc_result); + i32_ret = ERROR; + goto exit_upgrade; + } + + i32_ret = raydium_i2c_pda_read(client, 0x80, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + + if (u8_buf[2] > 2) { + pr_err("[touch]bootloader version %x,!!\n", u8_buf[2]); + memset(u8_buf, 0, sizeof(u8_buf)); + + u8_buf[1] = 0x04; + i32_ret = raydium_i2c_pda_write(client, 0x50000918, + u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + } + } + + /*Skip load*/ + pr_info("[touch]Raydium skip load\n"); + i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + u8_buf[0] = 0x10; + i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_do_software_reset(client); + if (i32_ret < 0) + goto exit_upgrade; + i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4); + if (i32_ret < 0) + goto exit_upgrade; + pr_debug("[touch]0x5000918 = 0x%x, 0x%x, 0x%x, 0x%x\n", + u8_buf[0], u8_buf[1], u8_buf[2], u8_buf[3]); + i32_ret = raydium_check_fw_ready(client); + +exit_upgrade: + return i32_ret; +} + +#endif /* FW_UPDATE_EN */ + +MODULE_AUTHOR("Raydium"); +MODULE_DESCRIPTION("Raydium TouchScreen driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c b/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c new file mode 100644 index 0000000000000000000000000000000000000000..439c19b7548f69f2562f7cc1916742c75bf786d1 --- /dev/null +++ b/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c @@ -0,0 +1,1402 @@ +/* drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c + * + * Raydium TouchScreen driver. + * + * Copyright (c) 2010 Raydium tech Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "raydium_driver.h" + +static ssize_t raydium_touch_calibration_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[1]; + int i32_ret = -1; + unsigned char u8_retry = 0; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_raydium_ts->is_suspend) + pr_debug("[touch]RAD is_suspend at %s\n", __func__); + + raydium_irq_control(DISABLE); + mutex_lock(&g_raydium_ts->lock); + + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + + u8_rbuffer[0] = RAYDIUM_HOST_CMD_CALIBRATION; + i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_rbuffer, 1); + if (i32_ret < 0) + goto exit_i2c_error; + + do { + if (u8_rbuffer[0] == RAYDIUM_HOST_CMD_NO_OP) + break; + + msleep(1000); + + i32_ret = raydium_i2c_pda2_read(client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_rbuffer, 1); + if (i32_ret < 0) + goto exit_i2c_error; + + pr_debug("[touch]RAD %s return 0x%02x!!\n", + __func__, u8_rbuffer[0]); + } while (u8_retry++ < (SYN_I2C_RETRY_TIMES * 2)); + + i32_ret = scnprintf(p_i8_buf, PAGE_SIZE, "0x%02x\n", u8_rbuffer[0]); + +exit_i2c_error: + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); + + return i32_ret; +} + +static ssize_t raydium_i2c_pda_access_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[4]; + int i32_ret = -1; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_u32_length > 4) + return -EINVAL; + + memset(u8_rbuffer, 0x00, 4); + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda_read(client, + g_u32_addr, + u8_rbuffer, + g_u32_length); + mutex_unlock(&g_raydium_ts->lock); + if (i32_ret < 0) + return i32_ret; + + return scnprintf(p_i8_buf, PAGE_SIZE, "0x%08X : 0x%02X%02X%02X%02X\n", + (unsigned int)g_u32_addr, u8_rbuffer[3], u8_rbuffer[2], + u8_rbuffer[1], u8_rbuffer[0]); +} + +static ssize_t raydium_check_i2c_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[4]; + int i32_ret = -1; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_raydium_ts->is_suspend) + pr_info("[touch]RAD is_suspend at %s\n", __func__); + raydium_irq_control(DISABLE); + mutex_lock(&g_raydium_ts->lock); + + if (g_u8_i2c_mode == PDA2_MODE) { + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + + /*using byte mode to read 4 bytes*/ + *(unsigned long *)u8_rbuffer = (RAD_I2C_PDA_MODE_ENABLE << 24) + | ((RAD_CHK_I2C_CMD & + (~MASK_8BIT)) >> 8); + + i32_ret = raydium_i2c_pda2_write(client, + RAYDIUM_PDA2_PDA_CFG_ADDR, + u8_rbuffer, + 4); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_ENABLE_PDA); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = raydium_i2c_pda2_read(client, + (unsigned char)(RAD_CHK_I2C_CMD & MASK_8BIT), + u8_rbuffer, 4); + if (i32_ret < 0) + goto exit_i2c_error; + } else { + i32_ret = raydium_i2c_pda_read(client, RAD_CHK_I2C_CMD, + u8_rbuffer, 4); + if (i32_ret < 0) + goto exit_i2c_error; + } + + i32_ret = scnprintf(p_i8_buf, PAGE_SIZE, + "[touch]RAD Touch check i2c: %02X%02X\n", + u8_rbuffer[3], u8_rbuffer[2]); + +exit_i2c_error: + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); + return i32_ret; +} + +static ssize_t raydium_hw_reset_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + int i32_ret = SUCCESS; + + pr_debug("[touch]HW reset\n"); + g_u8_resetflag = true; + if ((g_u8_raydium_flag & ENG_MODE) == 0) + raydium_irq_control(DISABLE); + + /*HW reset*/ + if (gpio_is_valid(g_raydium_ts->rst_gpio)) { + gpio_set_value(g_raydium_ts->rst_gpio, 1); + gpio_set_value(g_raydium_ts->rst_gpio, 0); + msleep(RAYDIUM_RESET_INTERVAL_MSEC); + gpio_set_value(g_raydium_ts->rst_gpio, 1); + } + + g_u8_i2c_mode = PDA2_MODE; + + i32_ret = wait_irq_state(client, 1000, 2000); + if (i32_ret != ERROR) + msleep(25); + + if ((g_u8_raydium_flag & ENG_MODE) == 0) + raydium_irq_control(ENABLE); + + pr_debug("Raydium HW Reset : %d\n", i32_ret); + return scnprintf(p_i8_buf, PAGE_SIZE, + "Raydium HW Reset : %d\n", i32_ret); +} + +static ssize_t raydium_reset_control_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + unsigned char u8_high; + + if (g_raydium_ts->is_suspend) + pr_debug("[touch]RAD is_suspend at %s\n", __func__); + + /* receive command line arguments string */ + if (count > 2) + return -EINVAL; + + i32_ret = kstrtou8(p_i8_buf, 16, &u8_high); + if (i32_ret < 0) + return i32_ret; + + g_u8_i2c_mode = PDA2_MODE; + g_u8_resetflag = true; + + if (u8_high) { + pr_debug("[touch]RAD %s set reset gpio to high!!\n", __func__); + gpio_set_value(g_raydium_ts->rst_gpio, 1); + } else { + pr_debug("[touch]RAD %s set reset gpio to low!!\n", __func__); + gpio_set_value(g_raydium_ts->rst_gpio, 0); + } + + return count; +} + +static ssize_t raydium_palm_status_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_tp_status[MAX_TCH_STATUS_PACKET_SIZE]; + unsigned char u8_tp_buf[MAX_REPORT_PACKET_SIZE]; + + raydium_read_touchdata(u8_tp_status, u8_tp_buf); + return scnprintf(p_i8_buf, PAGE_SIZE, "[touch] palm_status : %d\n", + u8_tp_status[POS_GES_STATUS]); +} + + +static ssize_t raydium_palm_area_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret = 0; + unsigned char w_data[1]; + unsigned char palm_area = 0; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + /* receive command line arguments string */ + if (count > 3) + return -EINVAL; + + ret = kstrtou8(buf, 16, &palm_area); + pr_debug("[touch] input palm area = %d\n", palm_area); + + mutex_lock(&g_raydium_ts->lock); + /* unlock PARM */ + + ret = raydium_i2c_pda2_set_page(client, g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (ret < 0) { + mutex_unlock(&g_raydium_ts->lock); + goto exit_error; + } + + w_data[0] = palm_area; + ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_PALM_AREA_ADDR, + w_data, 1); + if (ret < 0) { + mutex_unlock(&g_raydium_ts->lock); + goto exit_error; + } + + mutex_unlock(&g_raydium_ts->lock); + +exit_error: + return count; +} + +static ssize_t raydium_palm_area_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[4]; + int i32_ret = -1; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_raydium_ts->is_suspend) + pr_debug("[touch]RAD is_suspend at %s\n", __func__); + + raydium_irq_control(DISABLE); + mutex_lock(&g_raydium_ts->lock); + + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = raydium_i2c_pda2_read(client, RAYDIUM_PDA2_PALM_AREA_ADDR, + u8_rbuffer, 4); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = scnprintf(p_i8_buf, PAGE_SIZE, "RAD Palm area : %02X\n", + u8_rbuffer[0]); + +exit_i2c_error: + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); + + return i32_ret; +} + +static ssize_t raydium_irq_state_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned int u32_irq_value; + + u32_irq_value = gpio_get_value(g_raydium_ts->irq_gpio); + + pr_debug("%d\n", u32_irq_value); + return scnprintf(p_i8_buf, PAGE_SIZE, "%d", u32_irq_value); +} + + +static ssize_t raydium_touch_lock_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + unsigned char u8_mode; + unsigned char u8_wbuffer[1]; + + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_raydium_ts->is_suspend) + pr_debug("[touch]RAD is_suspend at %s\n", __func__); + + /* receive command line arguments string */ + if (count > 2) + return -EINVAL; + + i32_ret = kstrtou8(p_i8_buf, 16, &u8_mode); + if (i32_ret < 0) + return i32_ret; + raydium_irq_control(DISABLE); + mutex_lock(&g_raydium_ts->lock); + + switch (u8_mode) { + case 0: /* Disable Touch lock */ + + if (g_raydium_ts->is_sleep != 1) + break; + g_u8_resetflag = true; + if (gpio_is_valid(g_raydium_ts->rst_gpio)) { + gpio_set_value(g_raydium_ts->rst_gpio, 1); + gpio_set_value(g_raydium_ts->rst_gpio, 0); + msleep(RAYDIUM_RESET_INTERVAL_MSEC);/*5ms*/ + gpio_set_value(g_raydium_ts->rst_gpio, 1); + msleep(RAYDIUM_RESET_DELAY_MSEC);/*100ms*/ + } + pr_debug("[touch]RAD %s disable touch lock!!\n", __func__); + + g_raydium_ts->is_sleep = 0; + break; + + case 1: /* Enable Touch lock */ + + if (g_raydium_ts->is_sleep == 1) + break; + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + /*fw enter sleep mode*/ + u8_wbuffer[0] = RAYDIUM_HOST_CMD_PWR_SLEEP; + i32_ret = raydium_i2c_pda2_write(client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_wbuffer, + 1); + if (i32_ret < 0) + goto exit_i2c_error; + + pr_debug("[touch]RAD %s enable touch lock!!\n", __func__); + g_raydium_ts->is_sleep = 1; + break; + } + +exit_i2c_error: + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); + return count; +} + +static ssize_t raydium_check_driver_version_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + return scnprintf(p_i8_buf, PAGE_SIZE, "RAD Driver Ver: 0x%X\n", + g_u32_driver_version); +} + +static ssize_t raydium_check_fw_version_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[4]; + int i32_ret = -1; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + unsigned int fw_version; +#ifdef FW_UPDATE_EN + unsigned int image_version; +#endif + if (g_raydium_ts->is_suspend) + pr_debug("[touch]RAD is_suspend at %s\n", __func__); + + raydium_irq_control(DISABLE); + mutex_lock(&g_raydium_ts->lock); + + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = raydium_i2c_pda2_read(client, RAYDIUM_PDA2_FW_VERSION_ADDR, + u8_rbuffer, 4); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = scnprintf(p_i8_buf, PAGE_SIZE, + "RAD Touch FW Ver : %02X%02X%02X%02X\n", + u8_rbuffer[0], u8_rbuffer[1], + u8_rbuffer[2], u8_rbuffer[3]); + + fw_version = (u8_rbuffer[0] << 24) + | (u8_rbuffer[1] << 16) + | (u8_rbuffer[2] << 8) + | u8_rbuffer[3]; + pr_debug("[touch]RAD FW ver : 0x%x\n", fw_version); + +#ifdef FW_UPDATE_EN + image_version = (g_rad_para_image[0x0004] << 24) | + (g_rad_para_image[0x0005] << 16) | + (g_rad_para_image[0x0006] << 8) | + g_rad_para_image[0x0007]; + + pr_debug("[touch]RAD Image FW ver : 0x%x\n", image_version); + + if (fw_version != image_version) + pr_debug("[touch]%s, FW need upgrade.\n", __func__); +#endif + +exit_i2c_error: + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); + + return i32_ret; +} + +static ssize_t raydium_check_panel_version_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[8]; + int i32_ret = -1; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_raydium_ts->is_suspend) + pr_debug("[touch]RAD is_suspend at %s\n", __func__); + raydium_irq_control(DISABLE); + mutex_lock(&g_raydium_ts->lock); + + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = raydium_i2c_pda2_read(client, + RAYDIUM_PDA2_PANEL_VERSION_ADDR, + u8_rbuffer, 8); + if (i32_ret < 0) + goto exit_i2c_error; + i32_ret = scnprintf(p_i8_buf, PAGE_SIZE, + "RAD Touch Panel Version : %02X%02X%02X%02X%02X%02X\n", + u8_rbuffer[0], u8_rbuffer[1], u8_rbuffer[2], + u8_rbuffer[3], u8_rbuffer[4], u8_rbuffer[5]); + +exit_i2c_error: + mutex_unlock(&g_raydium_ts->lock); + raydium_irq_control(ENABLE); + return i32_ret; +} + +#ifdef FW_UPDATE_EN +static ssize_t raydium_fw_upgrade_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + + /* receive command line arguments string */ + if (count > 2) + return -EINVAL; + + i32_ret = kstrtou8(p_i8_buf, 16, &g_u8_upgrade_type); + if (i32_ret < 0) + return i32_ret; + + return count; +} + +static ssize_t raydium_fw_upgrade_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + int i32_ret = 0, i32_result = FAIL; + unsigned char u8_mode_change; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + raydium_irq_control(DISABLE); + + pr_debug("[touch]RAD burn type is %d\n", g_u8_upgrade_type); + + if ((g_u8_raydium_flag & ENG_MODE) == 0) { + g_u8_raydium_flag |= ENG_MODE; + u8_mode_change = 1; + } + + if ((g_u8_table_setting == 1) && (g_u8_table_init == 1)) + raydium_mem_table_setting(); + + if (g_u8_upgrade_type == 1) { + i32_ret = raydium_burn_fw(client); + if (i32_ret < 0) + goto exit_upgrade; + + i32_result = SUCCESS; + } else if (g_u8_upgrade_type == 2) { + i32_ret = raydium_burn_comp(client); + if (i32_ret < 0) + goto exit_upgrade; + + i32_result = SUCCESS; + } else if (g_u8_upgrade_type == 4) { + i32_ret = raydium_load_test_fw(client); + if (i32_ret < 0) + goto exit_upgrade; + + i32_result = SUCCESS; + } + +exit_upgrade: + if (u8_mode_change) { + pr_debug("[touch]g_u8_raydium_flag : %d", g_u8_raydium_flag); + g_u8_raydium_flag &= ~ENG_MODE; + u8_mode_change = 0; + } + raydium_irq_control(ENABLE); + g_u8_upgrade_type = 0; + + return scnprintf(p_i8_buf, PAGE_SIZE, + "FW Upgrade result : %d\n", i32_result); +} +#endif + +static ssize_t raydium_i2c_pda2_page_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + unsigned char u8_page = 0; + char *temp_buf, *token; + const char *delim = " ,"; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + /* receive command line arguments string */ + if (count < 2) + return -EINVAL; + + temp_buf = kzalloc(count + 1, GFP_KERNEL); + if (temp_buf == NULL) + return -ENOMEM; + + token = kzalloc(count + 1, GFP_KERNEL); + if (token == NULL) { + kfree(temp_buf); + return -ENOMEM; + } + + strlcpy(temp_buf, p_i8_buf, count); + + token = strsep(&temp_buf, delim); + + if (temp_buf) { + pr_err("[touch]input error, extra auguments!n"); + i32_ret = -EINVAL; + goto exit_error; + } + i32_ret = kstrtou8(token, 16, &u8_page); + + if (i32_ret < 0) + goto exit_error; + + mutex_lock(&g_raydium_ts->lock); + + i32_ret = raydium_i2c_pda2_set_page(client, g_raydium_ts->is_suspend, + u8_page); + if (i32_ret < 0) + goto exit_set_error; + + /* TODO: Page check, Due to ISR will change page back to Page_0. + * Or disable IRQ during PDA2 access period + */ + +exit_set_error: + mutex_unlock(&g_raydium_ts->lock); + +exit_error: + kfree(token); + kfree(temp_buf); + return count; +} + +static ssize_t raydium_flag_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + pr_debug("[touch]RAD flag : %d\n", g_u8_raydium_flag); + return scnprintf(p_i8_buf, PAGE_SIZE, "%d", g_u8_raydium_flag); +} + +static ssize_t raydium_flag_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + unsigned char u8_flag = 0; + + /* receive command line arguments string */ + if (count > 2) + return -EINVAL; + + i32_ret = kstrtou8(p_i8_buf, 16, &u8_flag); + if (i32_ret < 0) + return i32_ret; + + g_u8_raydium_flag = u8_flag; + return count; +} + +#ifdef FW_UPDATE_EN +static ssize_t raydium_mem_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + unsigned char u8_type = 0; + unsigned int u32_image_version; + + /* receive command line arguments string */ + if (count > 2) + return -EINVAL; + + pr_debug("[touch]%s\n", __func__); + + i32_ret = kstrtou8(p_i8_buf, 16, &u8_type); + if (i32_ret < 0) + return i32_ret; + + if (u8_type > 3) { + pr_debug("[touch]Input invalid value!!\n"); + return ERROR; + } + + if (g_rad_boot_image != NULL) + kfree(g_rad_boot_image); + if (g_rad_init_image != NULL) + kfree(g_rad_init_image); + if (g_rad_fw_image != NULL) + kfree(g_rad_fw_image); + if (g_rad_para_image != NULL) + kfree(g_rad_para_image); + if (g_rad_testfw_image != NULL) + kfree(g_rad_testfw_image); + if (g_rad_testpara_image != NULL) + kfree(g_rad_testpara_image); + + if (!raydium_id_init(u8_type)) { + pr_debug("[touch]Set Raydium id failed!\n"); + return count; + } + + raydium_mem_table_init(g_raydium_ts->id); + if (raydium_mem_table_setting()) { + u32_image_version = (g_rad_para_image[0x0004] << 24) | + (g_rad_para_image[0x0005] << 16) | + (g_rad_para_image[0x0006] << 8) | + g_rad_para_image[0x0007]; + + pr_debug("[touch]RAD Image FW ver : 0x%x\n", u32_image_version); + } else + pr_debug("[touch]Mem init failed!\n"); + + return count; +} +#endif + +static ssize_t raydium_i2c_raw_data_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + char *temp_buf, *token; + const char *delim = " ,"; + unsigned char u8_w_data[RAD_FT_CMD_LENGTH]; + + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + /* receive command line arguments string */ + if (count < 2) + return -EINVAL; + + temp_buf = kzalloc(count + 1, GFP_KERNEL); + if (temp_buf == NULL) + return -ENOMEM; + + token = kzalloc(count + 1, GFP_KERNEL); + if (token == NULL) { + kfree(temp_buf); + return -ENOMEM; + } + + strlcpy(temp_buf, p_i8_buf, count); + + token = strsep(&temp_buf, delim); + + i32_ret = kstrtou8(token, 16, &g_u8_raw_data_type); + + token = strsep(&temp_buf, delim); + if (token) { + i32_ret = kstrtouint(token, 16, &g_u32_raw_data_len); + if (i32_ret < 0) + goto exit_error; + + + } else { /* without length info*/ + i32_ret = -EINVAL; + goto exit_error; + } + + if (temp_buf) { /* too much arguments*/ + i32_ret = -E2BIG; + goto exit_error; + } + + memset(u8_w_data, 0x00, RAD_FT_CMD_LENGTH); + + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda2_set_page(client, + g_raydium_ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) { + mutex_unlock(&g_raydium_ts->lock); + goto exit_error; + } + + g_u8_resetflag = true; + + u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP; + u8_w_data[RAD_FT_CMD_POS] = g_u8_raw_data_type; + + i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_w_data, RAD_FT_CMD_LENGTH); + mutex_unlock(&g_raydium_ts->lock); + if (i32_ret < 0) + goto exit_error; + + if (g_u8_raw_data_type == 0) { + usleep_range(10000, 20000); + g_u8_resetflag = false; + } +exit_error: + kfree(token); + kfree(temp_buf); + + return count; +} +static ssize_t raydium_i2c_raw_data_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[MAX_READ_PACKET_SIZE]; + unsigned int u32_target_addr; + unsigned int u32_offset; + unsigned short u16_read_length; + + int i32_ret = -1; + int i32_retry = 0; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct raydium_ts_data *ts = + (struct raydium_ts_data *)i2c_get_clientdata(client); + unsigned char u8_retry_limit = (ts->is_suspend) ? 30 : 3; + + memset(u8_rbuffer, 0x00, MAX_READ_PACKET_SIZE); + + /* make sure update flag was set*/ + for (i32_retry = 0; i32_retry < u8_retry_limit; i32_retry++) { + mutex_lock(&ts->lock); + i32_ret = raydium_i2c_pda2_set_page(client, + ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + + i32_ret = raydium_i2c_pda2_read(client, + RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_rbuffer, + RAD_FT_CMD_LENGTH); + mutex_unlock(&ts->lock); + if (i32_ret < 0) + goto exit_flag_error; + + if ((u8_rbuffer[RAD_FT_CMD_POS] & RAYDIUM_FT_UPDATE) + == RAYDIUM_FT_UPDATE) + break; + + usleep_range(4500, 5500); + } + + if (i32_retry == u8_retry_limit) { + i32_ret = -EAGAIN; + goto exit_flag_error; + } + + u32_offset = 0; + u16_read_length = 0; + while (u32_offset < g_u32_raw_data_len) { + if ((u32_offset + MAX_READ_PACKET_SIZE) < + g_u32_raw_data_len) + u16_read_length = MAX_READ_PACKET_SIZE; + else + u16_read_length = + (unsigned short)(g_u32_raw_data_len + - u32_offset); + + u32_target_addr = RAD_READ_FT_DATA_CMD + u32_offset; + + mutex_lock(&(ts->lock)); + i32_ret = raydium_i2c_pda2_set_page(client, + ts->is_suspend, + RAYDIUM_PDA2_PAGE_0); + if (i32_ret < 0) + goto exit_i2c_error; + + *(unsigned int *)u8_rbuffer = (RAD_I2C_PDA_MODE_ENABLE << 24) + | ((u32_target_addr + & (~MASK_8BIT)) >> 8); + + /*using byte mode to read 4 bytes*/ + i32_ret = raydium_i2c_pda2_write(client, + RAYDIUM_PDA2_PDA_CFG_ADDR, u8_rbuffer, 4); + if (i32_ret < 0) + goto exit_i2c_error; + + i32_ret = raydium_i2c_pda2_set_page(client, + ts->is_suspend, + RAYDIUM_PDA2_ENABLE_PDA); + if (i32_ret < 0) + goto exit_i2c_error; + + i32_ret = raydium_i2c_pda2_read(client, + (unsigned char)(u32_target_addr & MASK_8BIT), + u8_rbuffer, + u16_read_length); + + mutex_unlock(&(ts->lock)); + if (i32_ret < 0) + goto exit_flag_error; + + memcpy((p_i8_buf + u32_offset), u8_rbuffer, u16_read_length); + + u32_offset += u16_read_length; + } + + /* clear update flag to get next one*/ + u8_rbuffer[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP; + u8_rbuffer[RAD_FT_CMD_POS] = g_u8_raw_data_type; + mutex_lock(&ts->lock); + i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR, + u8_rbuffer, RAD_FT_CMD_LENGTH); + mutex_unlock(&ts->lock); + if (i32_ret < 0) + goto exit_flag_error; + + return g_u32_raw_data_len; +exit_i2c_error: + mutex_unlock(&(ts->lock)); +exit_flag_error: + return i32_ret; +} +static ssize_t raydium_i2c_pda_access_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + char *temp_buf, *token; + const char *delim = " ,"; + unsigned char u8_w_data[MAX_WRITE_PACKET_SIZE]; + unsigned int u32_data_count = 0; + unsigned int u32_data_index = 0; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + /* receive command line arguments string */ + if (count < 2) + return -EINVAL; + + temp_buf = kzalloc(count + 1, GFP_KERNEL); + if (temp_buf == NULL) + return -ENOMEM; + + token = kzalloc(count + 1, GFP_KERNEL); + if (token == NULL) { + kfree(temp_buf); + return -ENOMEM; + } + + strlcpy(temp_buf, p_i8_buf, count); + + token = strsep(&temp_buf, delim); + + i32_ret = kstrtoul(token, 16, &g_u32_addr); + + token = strsep(&temp_buf, delim); + if (token) + i32_ret = kstrtouint(token, 16, &u32_data_count); + else + goto exit_error; + + if (g_u32_length > MAX_WRITE_PACKET_SIZE) + goto exit_error; + + g_u32_length = u32_data_count; + + memset(u8_w_data, 0x00, MAX_WRITE_PACKET_SIZE); + + if (temp_buf && u32_data_count) { + u32_data_index = 0; + while (u32_data_count) { + token = strsep(&temp_buf, delim); + i32_ret = kstrtou8(token, 16, + &u8_w_data[u32_data_index++]); + if (i32_ret < 0) + goto exit_error; + u32_data_count--; + } + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda_write(client, g_u32_addr, + u8_w_data, g_u32_length); + mutex_unlock(&g_raydium_ts->lock); + } + +exit_error: + kfree(token); + kfree(temp_buf); + return count; +} + +static ssize_t raydium_i2c_pda2_mode_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + unsigned char u8_mode; + + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_raydium_ts->is_suspend) + pr_debug("[touch]RAD is_suspend at %s\n", __func__); + + /* receive command line arguments string */ + if (count > 2) + return -EINVAL; + + i32_ret = kstrtou8(p_i8_buf, 16, &u8_mode); + if (i32_ret < 0) + return i32_ret; + + i32_ret = raydium_i2c_mode_control(client, u8_mode); + if (i32_ret < 0) + return i32_ret; + + return count; +} + +static ssize_t raydium_i2c_pda2_access_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + unsigned char u8_rbuffer[4]; + int i32_ret = -1; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + if (g_u32_length > 4) + return -EINVAL; + + memset(u8_rbuffer, 0x00, 4); + + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda2_read(client, g_u8_addr, + u8_rbuffer, g_u32_length); + mutex_unlock(&g_raydium_ts->lock); + if (i32_ret < 0) + return i32_ret; + + return scnprintf(p_i8_buf, PAGE_SIZE, "0x%04X : 0x%02X%02X%02X%02X\n", + g_u8_addr, u8_rbuffer[3], u8_rbuffer[2], + u8_rbuffer[1], u8_rbuffer[0]); +} + +static ssize_t raydium_i2c_pda2_access_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + char *temp_buf, *token; + const char *delim = " ,"; + unsigned char u8_w_data[MAX_WRITE_PACKET_SIZE]; + unsigned int u32_data_count = 0; + unsigned int u32_data_index = 0; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + /* receive command line arguments string */ + if (count < 2) + return -EINVAL; + + temp_buf = kzalloc(count + 1, GFP_KERNEL); + if (temp_buf == NULL) + return -ENOMEM; + + token = kzalloc(count + 1, GFP_KERNEL); + if (token == NULL) { + kfree(temp_buf); + return -ENOMEM; + } + + strlcpy(temp_buf, p_i8_buf, count); + + token = strsep(&temp_buf, delim); + + i32_ret = kstrtou8(token, 16, &g_u8_addr); + + token = strsep(&temp_buf, delim); + if (token) + i32_ret = kstrtouint(token, 16, &u32_data_count); + else { + i32_ret = -EINVAL; + goto exit_error; + } + + if (u32_data_count > MAX_WRITE_PACKET_SIZE) { + i32_ret = -EINVAL; + goto exit_error; + } + + memset(u8_w_data, 0x00, MAX_WRITE_PACKET_SIZE); + + g_u32_length = u32_data_count; + + if (temp_buf && u32_data_count) { + u32_data_index = 0; + while (u32_data_count) { + token = strsep(&temp_buf, delim); + i32_ret = kstrtou8(token, 16, + &u8_w_data[u32_data_index++]); + if (i32_ret < 0) + goto exit_error; + u32_data_count--; + } + + mutex_lock(&g_raydium_ts->lock); + i32_ret = raydium_i2c_pda2_write(client, g_u8_addr, + u8_w_data, g_u32_length); + mutex_unlock(&g_raydium_ts->lock); + if (i32_ret < 0) + goto exit_error; + } + +exit_error: + kfree(token); + kfree(temp_buf); + return count; +} + +#ifdef FW_UPDATE_EN +static ssize_t raydium_receive_fw_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + const char *delim = " ,"; + char *token, *temp_buf; + static unsigned char *p_u8_firmware_data; + + unsigned char u8_cmd; + unsigned long u32_len; + static unsigned char u8_type; + static unsigned int u32_index; + + if (count == 20) { /*check FW type*/ + temp_buf = kzalloc(32, GFP_KERNEL); + if (temp_buf == NULL) { + pr_err("[touch]kzalloc temp_buf failed\n"); + return -ENOMEM; + } + + token = kzalloc(32, GFP_KERNEL); + if (token == NULL) { + kfree(temp_buf); + return -ENOMEM; + } + + snprintf(temp_buf, PAGE_SIZE, "%s", p_i8_buf); + token = strsep(&temp_buf, delim); + i32_ret = kstrtou8(token, 16, &u8_cmd); + if (i32_ret < 0) { + pr_err("[touch]kstrtou8 failed\n"); + goto exit_error; + } + + token = strsep(&temp_buf, delim); + i32_ret = kstrtou8(token, 16, &u8_type); + if (i32_ret < 0) { + pr_err("[touch]kstrtou8 failed\n"); + goto exit_error; + } + + token = strsep(&temp_buf, delim); + i32_ret = kstrtoul(token, 16, &u32_len); + if (i32_ret < 0) { + pr_err("[touch]kstrtou8 failed\n"); + goto exit_error; + } + + pr_debug("[touch]uc_cmd=0x%x, uc_type=0x%x, u16_len=0x%x\n", + u8_cmd, u8_type, (unsigned int)u32_len); + + if (u8_cmd == RAD_CMD_UPDATE_BIN) { /*check FW length*/ + u32_index = 0; + if (u8_type == RAYDIUM_BOOTLOADER) { + memset(g_rad_boot_image, 0, u32_len); + p_u8_firmware_data = g_rad_boot_image; + } else if (u8_type == RAYDIUM_INIT) { + memset(g_rad_init_image, 0, u32_len); + p_u8_firmware_data = g_rad_init_image; + } else if (u8_type == RAYDIUM_PARA) { + memset(g_rad_para_image, 0, u32_len); + p_u8_firmware_data = g_rad_para_image; + } else if (u8_type == RAYDIUM_FIRMWARE) { + memset(g_rad_fw_image, 0, u32_len); + p_u8_firmware_data = g_rad_fw_image; + } else if (u8_type == RAYDIUM_TEST_PARA) { + memset(g_rad_testpara_image, 0, u32_len); + p_u8_firmware_data = g_rad_testpara_image; + } else if (u8_type == RAYDIUM_TEST_FW) { + memset(g_rad_testfw_image, 0, u32_len); + p_u8_firmware_data = g_rad_testfw_image; + } + + } else if (u8_cmd == RAD_CMD_UPDATE_END) { /*set buffer finish*/ + if (((g_raydium_ts->id & 0x2000) == 0x2000) + && (u8_type == RAYDIUM_TEST_FW)) { + memcpy((g_rad_testfw_image + RAD_FW_2X_SIZE), + g_rad_testpara_image, + RAD_PARA_2X_SIZE + 4); + } + + u32_index = 0; + g_u8_table_setting = 0; + + } else if (u8_cmd == RAD_CMD_BURN_FINISH) { /*free buffer*/ + u8_type = 0; + u32_index = 0; + g_u8_table_setting = 1; + } + + } else if (count > 10) { /*start copy FW to array*/ + memcpy((p_u8_firmware_data + u32_index), p_i8_buf, count); + u32_index += count; + } else + pr_debug("[touch]other case, count=%d\n", count); + +exit_error: + kfree(temp_buf); + kfree(token); + return count; +} +#endif + +#ifdef RAD_SELFTEST +static ssize_t raydium_selftest_show(struct device *dev, + struct device_attribute *attr, + char *p_i8_buf) +{ + int i32_ret = SUCCESS; + + pr_debug("[touch]do selftest\n"); + + i32_ret = raydium_do_selftest(); + + return scnprintf(p_i8_buf, PAGE_SIZE, + "Raydium do selftest : %d\n", i32_ret); +} + +#endif +/* panel calibration cmd (R) + * example:cat raydium_ic_verion + */ +static DEVICE_ATTR(raydium_touch_calibration, 0644, + raydium_touch_calibration_show, + NULL); + +/* check the i2c (R) + * example:cat raydium_check_i2c + */ +static DEVICE_ATTR(raydium_check_i2c, 0644, + raydium_check_i2c_show, + NULL); + +#ifdef FW_UPDATE_EN +/* upgrade configurate and algo firmware from app.bin (W) + * example:echo "offset num_of_bin length *_app.bin [length *_app.bin]" + * > raydium_fw_upgrade_mode + */ +static DEVICE_ATTR(raydium_fw_upgrade, 0644, + raydium_fw_upgrade_show, + raydium_fw_upgrade_store); +#endif + +/* change I2C communication mode (W) + * example:echo 1 > raydium_i2c_pda2_mode ==> enable pda2 mode + * echo 0 > raydium_i2c_pda2_mode ==> disable pda2 mode + */ +static DEVICE_ATTR(raydium_i2c_pda2_mode, 0644, + NULL, + raydium_i2c_pda2_mode_store); + +/* I2C pda mode (R/W) + * example: cat raydium_i2c_pda_access ==> read pda address provided by the + * following cmd + * echo ADDRinHEX [DATAinHEX] > raydium_i2c_pda_access ==> write + * pda address [data] + */ +static DEVICE_ATTR(raydium_i2c_pda_access, 0644, + raydium_i2c_pda_access_show, + raydium_i2c_pda_access_store); + +/* I2C pda2 mode (R/W) + * example: cat raydium_i2c_pda2_access ==> read pda2 address provided by + * the following cmd + * echo ADDRinHEX [DATAinHEX] > raydium_i2c_pda2_access ==> + * write pda2 address [data] + */ +static DEVICE_ATTR(raydium_i2c_pda2_access, 0644, + raydium_i2c_pda2_access_show, + raydium_i2c_pda2_access_store); + +/* I2C pda2 mode page (W) + * example: echo PAGEinHEX > raydium_i2c_pda2_page ==> write pda2 page + */ +static DEVICE_ATTR(raydium_i2c_pda2_page, 0644, + NULL, + raydium_i2c_pda2_page_store); + +/* I2C read/set FT raw data (R/W) + * example: cat raydium_i2c_raw_data ==> read raw data with specific length + * of corresponding type provided by the following cmd + * echo DataTypeinHEX RawDataLengthinHEX > raydium_i2c_raw_data + * ==> set raw data type and its length + */ +static DEVICE_ATTR(raydium_i2c_raw_data, 0644, + raydium_i2c_raw_data_show, + raydium_i2c_raw_data_store); + +/* Read interrupt flag cmd (R) + * example:cat raydium_flag + */ +static DEVICE_ATTR(raydium_flag, 0644, + raydium_flag_show, + raydium_flag_store); + +/* Read interrupt flag cmd (R) + * example:cat raydium_int_flag + */ +static DEVICE_ATTR(raydium_int_flag, 0644, + raydium_flag_show, + raydium_flag_store); + +/* Read selftest flag cmd (R) + * example:cat raydium_int_flag + */ +static DEVICE_ATTR(raydium_selftest_flag, 0644, + raydium_flag_show, + raydium_flag_store); + +/* Touch lock (W) + * example: echo 1 > raydium_i2c_touch_lock ==> enable touch lock + * echo 0 > raydium_i2c_touch_lock ==> disable touch lock + */ +static DEVICE_ATTR(raydium_i2c_touch_lock, 0644, + NULL, + raydium_touch_lock_store); + +/* show the fw version (R) + * example:cat raydium_fw_version + */ +static DEVICE_ATTR(raydium_check_fw_version, 0644, + raydium_check_fw_version_show, + NULL); + +/* show the driver version (R) + * example:cat raydium_check_driver_version + */ +static DEVICE_ATTR(raydium_check_driver_version, 0644, + raydium_check_driver_version_show, + NULL); +/* show the panel version (R) + * example:cat raydium_panel_version + */ +static DEVICE_ATTR(raydium_check_panel_version, 0644, + raydium_check_panel_version_show, + NULL); + +static DEVICE_ATTR(raydium_hw_reset, 0644, + raydium_hw_reset_show, + NULL); + +static DEVICE_ATTR(raydium_irq_state, 0644, + raydium_irq_state_show, + NULL); +static DEVICE_ATTR(raydium_palm_status, 0644, + raydium_palm_status_show, + NULL); +static DEVICE_ATTR(raydium_palm_area, 0644, + raydium_palm_area_show, + raydium_palm_area_store); +static DEVICE_ATTR(raydium_reset_control, 0644, + NULL, + raydium_reset_control_store); +#ifdef FW_UPDATE_EN +static DEVICE_ATTR(raydium_receive_fw_control, 0644, + NULL, + raydium_receive_fw_store); +static DEVICE_ATTR(raydium_mem_setting, 0644, + NULL, + raydium_mem_store); +#endif +#ifdef RAD_SELFTEST +static DEVICE_ATTR(raydium_do_selftest, 0644, + raydium_selftest_show, + NULL); +#endif +/*add your attr in here*/ +struct attribute *raydium_attributes[] = { + &dev_attr_raydium_touch_calibration.attr, + &dev_attr_raydium_check_i2c.attr, + &dev_attr_raydium_i2c_pda2_mode.attr, + &dev_attr_raydium_i2c_pda_access.attr, + &dev_attr_raydium_i2c_pda2_access.attr, + &dev_attr_raydium_i2c_pda2_page.attr, + &dev_attr_raydium_i2c_raw_data.attr, + &dev_attr_raydium_flag.attr, + &dev_attr_raydium_i2c_touch_lock.attr, + &dev_attr_raydium_check_fw_version.attr, + &dev_attr_raydium_check_panel_version.attr, + &dev_attr_raydium_hw_reset.attr, + &dev_attr_raydium_irq_state.attr, + &dev_attr_raydium_palm_status.attr, + &dev_attr_raydium_palm_area.attr, + &dev_attr_raydium_int_flag.attr, + &dev_attr_raydium_selftest_flag.attr, + &dev_attr_raydium_check_driver_version.attr, + &dev_attr_raydium_reset_control.attr, +#ifdef FW_UPDATE_EN + &dev_attr_raydium_fw_upgrade.attr, + &dev_attr_raydium_receive_fw_control.attr, + &dev_attr_raydium_mem_setting.attr, +#endif +#ifdef RAD_SELFTEST + &dev_attr_raydium_do_selftest.attr, +#endif + NULL +}; + +MODULE_AUTHOR("Raydium"); +MODULE_DESCRIPTION("Raydium TouchScreen driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index d07dd29d4848f03d91e40bd762078b969a23bac1..9a94d65bf48339a36d4c3e4fb9a2a1bb0a136097 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -246,6 +246,7 @@ static int sun4i_ts_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct device *hwmon; + struct thermal_zone_device *thermal; int error; u32 reg; bool ts_attached; @@ -365,7 +366,10 @@ static int sun4i_ts_probe(struct platform_device *pdev) if (IS_ERR(hwmon)) return PTR_ERR(hwmon); - devm_thermal_zone_of_sensor_register(ts->dev, 0, ts, &sun4i_ts_tz_ops); + thermal = devm_thermal_zone_of_sensor_register(ts->dev, 0, ts, + &sun4i_ts_tz_ops); + if (IS_ERR(thermal)) + return PTR_ERR(thermal); writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 4c0eecae065c113a26400469d7def3c2b9bcc635..2180fa8b695bd36233b0b8781b1f22068ea851ee 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -523,7 +523,7 @@ static int sur40_probe(struct usb_interface *interface, int error; /* Check if we really have the right interface. */ - iface_desc = &interface->altsetting[0]; + iface_desc = interface->cur_altsetting; if (iface_desc->desc.bInterfaceClass != 0xFF) return -ENODEV; diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c index 21236e9bf1923bf6b966e661f5992418ad39eb50..dd7226157f397a9017b521f3f2ef7bcc91e4cf3d 100644 --- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c @@ -1471,7 +1471,7 @@ static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data, input_mt_sync(rmi4_data->input_dev); #endif - if (rmi4_data->stylus_enable) { + if (rmi4_data->stylus_enable && rmi4_data->stylus_dev) { stylus_presence = 0; input_report_key(rmi4_data->stylus_dev, BTN_TOUCH, 0); @@ -3624,7 +3624,7 @@ static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data) #endif input_sync(rmi4_data->input_dev); - if (rmi4_data->stylus_enable) { + if (rmi4_data->stylus_enable && rmi4_data->stylus_dev) { input_report_key(rmi4_data->stylus_dev, BTN_TOUCH, 0); input_report_key(rmi4_data->stylus_dev, diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index c898c70472bb25bbc2b7d4405c6b4189c5d08a03..bb0448c91f672b75a552075de5d27659ed396eea 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2113,6 +2113,8 @@ static int attach_device(struct device *dev, */ domain_flush_tlb_pde(domain); + domain_flush_complete(domain); + return ret; } diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 9bb8d64b6f94753d8bb9cd889961a4bb6583ef4a..c113e46fdc3ab9711d1cbec78d8dd24ee5949bab 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -383,6 +383,9 @@ static void iommu_enable(struct amd_iommu *iommu) static void iommu_disable(struct amd_iommu *iommu) { + if (!iommu->mmio_base) + return; + /* Disable command buffer */ iommu_feature_disable(iommu, CONTROL_CMDBUF_EN); diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 7bd98585d78d2d57d08df87f2c575fb55e399b63..48d38200878811bbc1a79112236876397f275178 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1103,7 +1103,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, } arm_smmu_sync_ste_for_sid(smmu, sid); - dst[0] = cpu_to_le64(val); + /* See comment in arm_smmu_write_ctx_desc() */ + WRITE_ONCE(dst[0], cpu_to_le64(val)); arm_smmu_sync_ste_for_sid(smmu, sid); /* It's likely that we'll want to use the new STE soon */ diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index d51734e0c35048f65cdb16b7fe9c7b6e5b1a3711..977070ce4fe9751281f00f73ccb19f2446f7b56c 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,13 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) BUG_ON(dev->is_virtfn); + /* + * Ignore devices that have a domain number higher than what can + * be looked up in DMAR, e.g. VMD subdevices with domain 0x10000 + */ + if (pci_domain_nr(dev->bus) > U16_MAX) + return NULL; + /* Only generate path[] for device addition event */ if (event == BUS_NOTIFY_ADD_DEVICE) for (tmp = dev; tmp; tmp = tmp->bus->self) @@ -450,12 +458,13 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header, /* Check for NUL termination within the designated length */ if (strnlen(andd->device_name, header->length - 8) == header->length - 8) { - WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, + pr_warn(FW_BUG "Your BIOS is broken; ANDD object name is not NUL-terminated\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); return -EINVAL; } pr_info("ANDD device: %x name: %s\n", andd->device_number, @@ -481,14 +490,14 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg) return 0; } } - WARN_TAINT( - 1, TAINT_FIRMWARE_WORKAROUND, + pr_warn(FW_BUG "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - drhd->reg_base_addr, + rhsa->base_address, dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); return 0; } @@ -834,14 +843,14 @@ int __init dmar_table_init(void) static void warn_invalid_dmar(u64 addr, const char *message) { - WARN_TAINT_ONCE( - 1, TAINT_FIRMWARE_WORKAROUND, + pr_warn_once(FW_BUG "Your BIOS is broken; DMAR reported at address %llx%s!\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", addr, message, dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); } static int __ref diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 25cc6ae87039d9f336469ebade2fcf147e79ceb9..593a4bfcba42883421e68eab2190300cf24fda8c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3345,9 +3345,12 @@ static int __init init_dmars(void) iommu_identity_mapping |= IDENTMAP_ALL; #ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA - iommu_identity_mapping |= IDENTMAP_GFX; + dmar_map_gfx = 0; #endif + if (!dmar_map_gfx) + iommu_identity_mapping |= IDENTMAP_GFX; + check_tylersburg_isoch(); if (iommu_identity_mapping) { @@ -4082,10 +4085,11 @@ static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) /* we know that the this iommu should be at offset 0xa000 from vtbar */ drhd = dmar_find_matched_drhd_unit(pdev); - if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000, - TAINT_FIRMWARE_WORKAROUND, - "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n")) + if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) { + pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; + } } DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); @@ -5189,8 +5193,10 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, u64 phys = 0; pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level); - if (pte) - phys = dma_pte_addr(pte); + if (pte && dma_pte_present(pte)) + phys = dma_pte_addr(pte) + + (iova & (BIT_MASK(level_to_offset_bits(level) + + VTD_PAGE_SHIFT) - 1)); return phys; } diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index c333a367fcbf4be0511d80c8b9ae50bc5942b6bf..c7c7da7397449a78ca729bb725b1b97f4f14db56 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -443,6 +443,7 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev) mutex_unlock(&group->mutex); dev->iommu_group = NULL; kobject_put(group->devices_kobj); + sysfs_remove_link(group->devices_kobj, device->name); err_free_name: kfree(device->name); err_remove_link: @@ -1701,9 +1702,9 @@ int iommu_request_dm_for_dev(struct device *dev) int ret; /* Device must already be in a group before calling this function */ - group = iommu_group_get_for_dev(dev); - if (IS_ERR(group)) - return PTR_ERR(group); + group = iommu_group_get(dev); + if (!group) + return -EINVAL; mutex_lock(&group->mutex); diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index c4eb293b152426e5f8d693bbc9ab0a3ed8b8f58c..04cec050e42bf677b13b5d2d882b5815286b06a5 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -153,9 +153,9 @@ static bool smmu_dma_addr_valid(struct tegra_smmu *smmu, dma_addr_t addr) return (addr & smmu->pfn_mask) == addr; } -static dma_addr_t smmu_pde_to_dma(u32 pde) +static dma_addr_t smmu_pde_to_dma(struct tegra_smmu *smmu, u32 pde) { - return pde << 12; + return (dma_addr_t)(pde & smmu->pfn_mask) << 12; } static void smmu_flush_ptc_all(struct tegra_smmu *smmu) @@ -540,6 +540,7 @@ static u32 *tegra_smmu_pte_lookup(struct tegra_smmu_as *as, unsigned long iova, dma_addr_t *dmap) { unsigned int pd_index = iova_pd_index(iova); + struct tegra_smmu *smmu = as->smmu; struct page *pt_page; u32 *pd; @@ -548,7 +549,7 @@ static u32 *tegra_smmu_pte_lookup(struct tegra_smmu_as *as, unsigned long iova, return NULL; pd = page_address(as->pd); - *dmap = smmu_pde_to_dma(pd[pd_index]); + *dmap = smmu_pde_to_dma(smmu, pd[pd_index]); return tegra_smmu_pte_offset(pt_page, iova); } @@ -590,7 +591,7 @@ static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova, } else { u32 *pd = page_address(as->pd); - *dmap = smmu_pde_to_dma(pd[pde]); + *dmap = smmu_pde_to_dma(smmu, pd[pde]); } return tegra_smmu_pte_offset(as->pts[pde], iova); @@ -615,7 +616,7 @@ static void tegra_smmu_pte_put_use(struct tegra_smmu_as *as, unsigned long iova) if (--as->count[pde] == 0) { struct tegra_smmu *smmu = as->smmu; u32 *pd = page_address(as->pd); - dma_addr_t pte_dma = smmu_pde_to_dma(pd[pde]); + dma_addr_t pte_dma = smmu_pde_to_dma(smmu, pd[pde]); tegra_smmu_set_pde(as, iova, 0); diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index 6e24facebb46d5b6b9e2088fc216ab9ae5fb0335..a571d9c6e42ae27ecb233bb4174f2ae3531a0256 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -282,6 +282,10 @@ static int __init bcm7038_l1_init_one(struct device_node *dn, pr_err("failed to map parent interrupt %d\n", parent_irq); return -EINVAL; } + + if (of_property_read_bool(dn, "brcm,irq-can-wake")) + enable_irq_wake(parent_irq); + irq_set_chained_handler_and_data(parent_irq, bcm7038_l1_irq_handle, intc); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 0c0cd2768d6e96478122c412ea67a9fb29c07238..d1efbb8dadc537d3280378475c9f706a70b6b342 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -365,7 +365,7 @@ static struct its_collection *its_build_invall_cmd(struct its_cmd_block *cmd, struct its_cmd_desc *desc) { its_encode_cmd(cmd, GITS_CMD_INVALL); - its_encode_collection(cmd, desc->its_mapc_cmd.col->col_id); + its_encode_collection(cmd, desc->its_invall_cmd.col->col_id); its_fixup_cmd(cmd); diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index f28e9ed81197330fb343a0597be45886c1da7a1b..19215cef0df256843558a905f7c78c22c49d5f4a 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1637,6 +1637,7 @@ static struct struct redist_region *redist_regs; u32 nr_redist_regions; bool single_redist; + int enabled_rdists; u32 maint_irq; int maint_irq_mode; phys_addr_t vcpu_base; @@ -1731,8 +1732,10 @@ static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header, * If GICC is enabled and has valid gicr base address, then it means * GICR base is presented via GICC */ - if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) + if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) { + acpi_data.enabled_rdists++; return 0; + } /* * It's perfectly valid firmware can pass disabled GICC entry, driver @@ -1762,8 +1765,10 @@ static int __init gic_acpi_count_gicr_regions(void) count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, gic_acpi_match_gicc, 0); - if (count > 0) + if (count > 0) { acpi_data.single_redist = true; + count = acpi_data.enabled_rdists; + } return count; } diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c index fc5953dea509af10b38abf783dac4fbd83efdaaa..b2e16dca76a603821fc85b16683419cea22979e3 100644 --- a/drivers/irqchip/irq-ingenic.c +++ b/drivers/irqchip/irq-ingenic.c @@ -117,6 +117,14 @@ static int __init ingenic_intc_of_init(struct device_node *node, goto out_unmap_irq; } + domain = irq_domain_add_legacy(node, num_chips * 32, + JZ4740_IRQ_BASE, 0, + &irq_domain_simple_ops, NULL); + if (!domain) { + err = -ENOMEM; + goto out_unmap_base; + } + for (i = 0; i < num_chips; i++) { /* Mask all irqs */ writel(0xffffffff, intc->base + (i * CHIP_SIZE) + @@ -143,14 +151,11 @@ static int __init ingenic_intc_of_init(struct device_node *node, IRQ_NOPROBE | IRQ_LEVEL); } - domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0, - &irq_domain_simple_ops, NULL); - if (!domain) - pr_warn("unable to register IRQ domain\n"); - setup_irq(parent_irq, &intc_cascade_action); return 0; +out_unmap_base: + iounmap(intc->base); out_unmap_irq: irq_dispose_mapping(parent_irq); out_free: diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 5f306e2eece5e2a93c1dd86ac8eb29ab59a33e06..aee4880f972f48da5ce4c263637cbb17e7d34f59 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -574,8 +574,7 @@ static int gigaset_initcshw(struct cardstate *cs) { struct usb_cardstate *ucs; - cs->hw.usb = ucs = - kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL); + cs->hw.usb = ucs = kzalloc(sizeof(struct usb_cardstate), GFP_KERNEL); if (!ucs) { pr_err("out of memory\n"); return -ENOMEM; @@ -587,9 +586,6 @@ static int gigaset_initcshw(struct cardstate *cs) ucs->bchars[3] = 0; ucs->bchars[4] = 0x11; ucs->bchars[5] = 0x13; - ucs->bulk_out_buffer = NULL; - ucs->bulk_out_urb = NULL; - ucs->read_urb = NULL; tasklet_init(&cs->write_tasklet, gigaset_modem_fill, (unsigned long) cs); @@ -688,6 +684,11 @@ static int gigaset_probe(struct usb_interface *interface, return -ENODEV; } + if (hostif->desc.bNumEndpoints < 2) { + dev_err(&interface->dev, "missing endpoints\n"); + return -ENODEV; + } + dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); /* allocate memory for our device state and initialize it */ @@ -707,6 +708,12 @@ static int gigaset_probe(struct usb_interface *interface, endpoint = &hostif->endpoint[0].desc; + if (!usb_endpoint_is_bulk_out(endpoint)) { + dev_err(&interface->dev, "missing bulk-out endpoint\n"); + retval = -ENODEV; + goto error; + } + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); ucs->bulk_out_size = buffer_size; ucs->bulk_out_epnum = usb_endpoint_num(endpoint); @@ -726,6 +733,12 @@ static int gigaset_probe(struct usb_interface *interface, endpoint = &hostif->endpoint[1].desc; + if (!usb_endpoint_is_int_in(endpoint)) { + dev_err(&interface->dev, "missing int-in endpoint\n"); + retval = -ENODEV; + goto error; + } + ucs->busy = 0; ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index f931a2cdf214475d9a002ca4d04e358c7d59f320..c42c84668cf446d3b31316771c22483f32b81cb9 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -705,6 +705,15 @@ config LEDS_QPNP_WLED variable brightness. It also supports outputting the Avdd supply for AMOLED displays. +config LEDS_MSM_GPIO_FLASH + tristate "Support for GPIO Flash LEDs" + help + This driver supports the leds functionality of GPIO Flash LED. It + includes flash mode and torch mode. + + To compile this driver as a module, choose M here: the module will + be called leds-gpio-flash. + config LEDS_QPNP_HAPTICS tristate "Haptics support for QPNP PMIC" depends on LEDS_CLASS && MFD_SPMI_PMIC diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 31d29f0e26c78bea58579e330b4678917543060d..e53ef7ea684a3cdff4ee8494c00372fc05eb8d97 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o +obj-$(CONFIG_LEDS_MSM_GPIO_FLASH) += leds-msm-gpio-flash.o obj-$(CONFIG_LEDS_QTI_TRI_LED) += leds-qti-tri-led.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o diff --git a/drivers/leds/leds-msm-gpio-flash.c b/drivers/leds/leds-msm-gpio-flash.c new file mode 100644 index 0000000000000000000000000000000000000000..6a5332ee1f6172cc0c11a61c590a11fa91c7f950 --- /dev/null +++ b/drivers/leds/leds-msm-gpio-flash.c @@ -0,0 +1,516 @@ +/* Copyright (c) 2013-2014, 2017, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #define CONFIG_GPIO_FLASH_DEBUG */ +#undef CDBG +#ifdef CONFIG_GPIO_FLASH_DEBUG +#define CDBG(fmt, args...) pr_err(fmt, ##args) +#else +#define CDBG(fmt, args...) do { } while (0) +#endif + +#define LED_GPIO_FLASH_DRIVER_NAME "qcom,leds-gpio-flash" +#define LED_TRIGGER_DEFAULT "none" + +#define GPIO_OUT_LOW (0 << 1) +#define GPIO_OUT_HIGH (1 << 1) + +#define DUTY_CYCLE_BASE 100 + +enum msm_flash_seq_type_t { + FLASH_EN, + FLASH_NOW, +}; + +enum msm_flash_gpio_type_t { + NORMAL_GPIO, + CLK_GPIO, +}; + +struct msm_flash_ctrl_seq { + enum msm_flash_seq_type_t seq_type; + uint8_t flash_on_val; + uint8_t torch_on_val; +}; + +struct led_gpio_flash_data { + int flash_en; + int flash_now; + struct clk *flash_en_clk; + struct clk *flash_now_clk; + int brightness; + atomic_t clk_enabled[2]; + uint32_t clk_freq[2]; + uint32_t duty_cycle[2]; + enum msm_flash_gpio_type_t gpio_type[2]; + struct led_classdev cdev; + struct pinctrl *pinctrl; + struct pinctrl_state *gpio_state_default; + struct msm_flash_ctrl_seq ctrl_seq[2]; +}; + +static const struct of_device_id led_gpio_flash_of_match[] = { + {.compatible = LED_GPIO_FLASH_DRIVER_NAME,}, + {}, +}; + +static void led_gpio_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + int rc = 0; + int brightness = value; + int flash_en = 0; + int flash_now = 0; + struct led_gpio_flash_data *flash_led = + container_of(led_cdev, struct led_gpio_flash_data, cdev); + + if (brightness > LED_HALF) { + flash_en = + flash_led->ctrl_seq[FLASH_EN].flash_on_val; + flash_now = + flash_led->ctrl_seq[FLASH_NOW].flash_on_val; + } else if (brightness > LED_OFF) { + flash_en = + flash_led->ctrl_seq[FLASH_EN].torch_on_val; + flash_now = + flash_led->ctrl_seq[FLASH_NOW].torch_on_val; + } else { + flash_en = 0; + flash_now = 0; + } + + CDBG("%s:flash_en=%d, flash_now=%d\n", __func__, flash_en, flash_now); + + if (flash_led->gpio_type[FLASH_EN] == NORMAL_GPIO) { + rc = gpio_direction_output(flash_led->flash_en, flash_en); + } else { + if (flash_en == GPIO_OUT_HIGH && + !atomic_read(&flash_led->clk_enabled[FLASH_EN])) { + rc = clk_prepare_enable(flash_led->flash_en_clk); + atomic_set(&flash_led->clk_enabled[FLASH_EN], 1); + } else if (flash_en == GPIO_OUT_LOW && + atomic_read(&flash_led->clk_enabled[FLASH_EN])) { + clk_disable_unprepare(flash_led->flash_en_clk); + atomic_set(&flash_led->clk_enabled[FLASH_EN], 0); + } + } + + if (rc) { + pr_err("%s: Failed to set flash en.\n", __func__); + return; + } + + if (flash_led->gpio_type[FLASH_NOW] == NORMAL_GPIO) { + rc = gpio_direction_output(flash_led->flash_now, flash_now); + } else { + if (flash_now == GPIO_OUT_HIGH && + !atomic_read(&flash_led->clk_enabled[FLASH_NOW])) { + rc = clk_prepare_enable(flash_led->flash_now_clk); + atomic_set(&flash_led->clk_enabled[FLASH_NOW], 1); + } else if (flash_now == GPIO_OUT_LOW && + atomic_read(&flash_led->clk_enabled[FLASH_NOW])) { + clk_disable_unprepare(flash_led->flash_now_clk); + atomic_set(&flash_led->clk_enabled[FLASH_NOW], 0); + } + } + + if (rc) { + pr_err("%s: Failed to set flash now.\n", __func__); + return; + } + + flash_led->brightness = brightness; +} + +static enum led_brightness led_gpio_brightness_get(struct led_classdev + *led_cdev) +{ + struct led_gpio_flash_data *flash_led = + container_of(led_cdev, struct led_gpio_flash_data, cdev); + return flash_led->brightness; +} + +static int led_gpio_get_dt_data(struct device *dev, + struct led_gpio_flash_data *flash_led) +{ + int rc = 0; + int i = 0; + const char *temp_str = NULL; + const char *seq_name = NULL; + uint32_t array_flash_seq[2]; + uint32_t array_torch_seq[2]; + struct device_node *node = dev->of_node; + + flash_led->cdev.default_trigger = LED_TRIGGER_DEFAULT; + rc = of_property_read_string(node, "linux,default-trigger", + &temp_str); + if (!rc) + flash_led->cdev.default_trigger = temp_str; + + rc = of_property_read_string(node, "linux,name", &flash_led->cdev.name); + if (rc) { + pr_err("Failed to read linux name. rc = %d\n", rc); + return rc; + } + + /* Configure the gpio type as NORMAL_GPIO by default, + * the gpio type should be CLK_GPIO if the frequency + * is not 0. + */ + flash_led->gpio_type[FLASH_EN] = NORMAL_GPIO; + flash_led->gpio_type[FLASH_NOW] = NORMAL_GPIO; + rc = of_property_read_u32_array(node, "qcom,clk-freq", + flash_led->clk_freq, 2); + if (!rc) { + if (flash_led->clk_freq[FLASH_EN]) + flash_led->gpio_type[FLASH_EN] = CLK_GPIO; + + if (flash_led->clk_freq[FLASH_NOW]) + flash_led->gpio_type[FLASH_NOW] = CLK_GPIO; + } + + if (flash_led->gpio_type[FLASH_EN] == NORMAL_GPIO) { + flash_led->flash_en = + of_get_named_gpio(node, "qcom,flash-en", 0); + if (flash_led->flash_en < 0) { + pr_err("Read flash-en property failed. rc = %d\n", + flash_led->flash_en); + return -EINVAL; + } + rc = gpio_request(flash_led->flash_en, "FLASH_EN"); + if (rc) { + pr_err("%s: Failed to request gpio %d,rc = %d\n", + __func__, flash_led->flash_en, rc); + return rc; + } + } else { + flash_led->flash_en_clk = + devm_clk_get(dev, "flash_en_clk"); + if (IS_ERR(flash_led->flash_en_clk)) { + pr_err("Failed to get flash-en clk.\n"); + return -EINVAL; + } + + flash_led->clk_freq[FLASH_EN] = + clk_round_rate(flash_led->flash_en_clk, + flash_led->clk_freq[FLASH_EN]); + rc = clk_set_rate(flash_led->flash_en_clk, + flash_led->clk_freq[FLASH_EN]); + if (rc) { + pr_err("%s: Failed to set rate for flash en.\n", + __func__); + return rc; + } + } + + if (flash_led->gpio_type[FLASH_NOW] == NORMAL_GPIO) { + flash_led->flash_now = + of_get_named_gpio(node, "qcom,flash-now", 0); + if (flash_led->flash_now < 0) { + pr_err("Read flash-now property failed. rc = %d\n", + flash_led->flash_now); + return -EINVAL; + } + rc = gpio_request(flash_led->flash_now, "FLASH_NOW"); + if (rc) { + pr_err("%s: Failed to request gpio %d,rc = %d\n", + __func__, flash_led->flash_now, rc); + return rc; + } + } else { + flash_led->flash_now_clk = + devm_clk_get(dev, "flash_now_clk"); + if (IS_ERR(flash_led->flash_now_clk)) { + pr_err("Failed to get flash-now clk.\n"); + return -EINVAL; + } + + flash_led->clk_freq[FLASH_NOW] = + clk_round_rate(flash_led->flash_now_clk, + flash_led->clk_freq[FLASH_NOW]); + rc = clk_set_rate(flash_led->flash_now_clk, + flash_led->clk_freq[FLASH_NOW]); + if (rc) { + pr_err("%s: Failed to set rate for flash now.\n", + __func__); + return rc; + } + } + + /* Configure the duty cycle if need. */ + if (flash_led->gpio_type[FLASH_EN] == CLK_GPIO || + flash_led->gpio_type[FLASH_NOW] == CLK_GPIO) { + rc = of_property_read_u32_array(node, "qcom,duty-cycle", + flash_led->duty_cycle, 2); + if (!rc && + flash_led->duty_cycle[FLASH_EN] >= DUTY_CYCLE_BASE && + flash_led->duty_cycle[FLASH_NOW] >= DUTY_CYCLE_BASE) { + pr_err("%s: the duty cycle value is invalid.\n", + __func__); + return -EINVAL; + } + } + + /* Based on clk protocol, only RCG clks support duty cycle + * configuration, so if the used clk doesn't support set duty + * cycle, we use the clk's parent rcg clk to configure the + * duty cycle. + */ + if (flash_led->duty_cycle[FLASH_EN]) { + struct clk *flash_en_duty_cycle_clk = NULL; + + flash_en_duty_cycle_clk = devm_clk_get(dev, + "flash_en_duty_cycle_clk"); + if (!IS_ERR(flash_en_duty_cycle_clk)) { + rc = clk_set_duty_cycle(flash_en_duty_cycle_clk, + flash_led->duty_cycle[FLASH_EN], + DUTY_CYCLE_BASE); + clk_put(flash_en_duty_cycle_clk); + } else { + rc = clk_set_duty_cycle(flash_led->flash_en_clk, + flash_led->duty_cycle[FLASH_EN], + DUTY_CYCLE_BASE); + } + + if (rc) { + pr_err("Failed to set duty cycle for flash en.\n"); + return rc; + } + } + + if (flash_led->duty_cycle[FLASH_NOW]) { + struct clk *flash_now_duty_cycle_clk = NULL; + + flash_now_duty_cycle_clk = devm_clk_get(dev, + "flash_now_duty_cycle_clk"); + if (!IS_ERR(flash_now_duty_cycle_clk)) { + rc = clk_set_duty_cycle(flash_now_duty_cycle_clk, + flash_led->duty_cycle[FLASH_NOW], + DUTY_CYCLE_BASE); + clk_put(flash_now_duty_cycle_clk); + } else { + rc = clk_set_duty_cycle(flash_led->flash_now_clk, + flash_led->duty_cycle[FLASH_NOW], + DUTY_CYCLE_BASE); + } + + if (rc) { + pr_err("Failed to set duty cycle for flash now.\n"); + return rc; + } + } + + rc = of_property_read_u32_array(node, "qcom,flash-seq-val", + array_flash_seq, 2); + if (rc < 0) { + pr_err("Failed to get flash op seq, rc = %d\n", rc); + return rc; + } + + rc = of_property_read_u32_array(node, "qcom,torch-seq-val", + array_torch_seq, 2); + if (rc < 0) { + pr_err("Failed to get torch op seq, rc = %d\n", rc); + return rc; + } + + pr_debug("%s: seq: flash: %d, %d torch:%d, %d\n", __func__, + array_flash_seq[0], array_flash_seq[1], + array_torch_seq[0], array_torch_seq[1]); + + for (i = 0; i < 2; i++) { + rc = of_property_read_string_index(node, + "qcom,op-seq", i, + &seq_name); + CDBG("%s seq_name[%d] = %s\n", __func__, i, + seq_name); + if (rc < 0) { + pr_err("%s failed %d\n", __func__, __LINE__); + return rc; + } + + if (!strcmp(seq_name, "flash_en")) { + flash_led->ctrl_seq[FLASH_EN].seq_type = + FLASH_EN; + CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__, + i, flash_led->ctrl_seq[FLASH_EN].seq_type); + if (array_flash_seq[i] == 0) + flash_led->ctrl_seq[FLASH_EN].flash_on_val = + GPIO_OUT_LOW; + else + flash_led->ctrl_seq[FLASH_EN].flash_on_val = + GPIO_OUT_HIGH; + + if (array_torch_seq[i] == 0) + flash_led->ctrl_seq[FLASH_EN].torch_on_val = + GPIO_OUT_LOW; + else + flash_led->ctrl_seq[FLASH_EN].torch_on_val = + GPIO_OUT_HIGH; + } else if (!strcmp(seq_name, "flash_now")) { + flash_led->ctrl_seq[FLASH_NOW].seq_type = + FLASH_NOW; + CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__, + i, flash_led->ctrl_seq[FLASH_NOW].seq_type); + if (array_flash_seq[i] == 0) + flash_led->ctrl_seq[FLASH_NOW].flash_on_val = + GPIO_OUT_LOW; + else + flash_led->ctrl_seq[FLASH_NOW].flash_on_val = + GPIO_OUT_HIGH; + + if (array_torch_seq[i] == 0) + flash_led->ctrl_seq[FLASH_NOW].torch_on_val = + GPIO_OUT_LOW; + else + flash_led->ctrl_seq[FLASH_NOW].torch_on_val = + GPIO_OUT_HIGH; + } + } + + return rc; +} + +static int led_gpio_flash_probe(struct platform_device *pdev) +{ + int rc = 0; + struct led_gpio_flash_data *flash_led = NULL; + + flash_led = devm_kzalloc(&pdev->dev, sizeof(struct led_gpio_flash_data), + GFP_KERNEL); + if (flash_led == NULL) + return -ENOMEM; + + flash_led->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(flash_led->pinctrl)) { + pr_err("%s:failed to get pinctrl\n", __func__); + rc = PTR_ERR(flash_led->pinctrl); + goto error; + } + + flash_led->gpio_state_default = pinctrl_lookup_state(flash_led->pinctrl, + "flash_default"); + if (IS_ERR(flash_led->gpio_state_default)) { + pr_err("%s:can not get active pinstate\n", __func__); + rc = -EINVAL; + goto error; + } + + rc = pinctrl_select_state(flash_led->pinctrl, + flash_led->gpio_state_default); + if (rc) { + pr_err("%s:set state failed!\n", __func__); + goto error; + } + + rc = led_gpio_get_dt_data(&pdev->dev, flash_led); + if (rc) { + pr_err("%s: get device tree data failed.\n", + __func__); + goto error; + } + + /* Add these atomic variables to make sure clk is disabled + * just after the clk has been enabled. + */ + atomic_set(&flash_led->clk_enabled[FLASH_EN], 0); + atomic_set(&flash_led->clk_enabled[FLASH_NOW], 0); + + platform_set_drvdata(pdev, flash_led); + flash_led->cdev.max_brightness = LED_FULL; + flash_led->cdev.brightness_set = led_gpio_brightness_set; + flash_led->cdev.brightness_get = led_gpio_brightness_get; + + rc = led_classdev_register(&pdev->dev, &flash_led->cdev); + if (rc) { + pr_err("%s: Failed to register led dev. rc = %d\n", + __func__, rc); + goto error; + } + pr_err("%s:probe successfully!\n", __func__); + return 0; + +error: + if (flash_led->gpio_type[FLASH_EN] == CLK_GPIO && + IS_ERR(flash_led->flash_en_clk)) + devm_clk_put(&pdev->dev, flash_led->flash_en_clk); + else if (flash_led->gpio_type[FLASH_EN] == NORMAL_GPIO && + flash_led->flash_en) + gpio_free(flash_led->flash_en); + + if (flash_led->gpio_type[FLASH_NOW] == CLK_GPIO && + IS_ERR(flash_led->flash_now_clk)) + devm_clk_put(&pdev->dev, flash_led->flash_now_clk); + else if (flash_led->gpio_type[FLASH_NOW] == NORMAL_GPIO && + flash_led->flash_now) + gpio_free(flash_led->flash_now); + + if (IS_ERR(flash_led->pinctrl)) + devm_pinctrl_put(flash_led->pinctrl); + + devm_kfree(&pdev->dev, flash_led); + return rc; +} + +static int led_gpio_flash_remove(struct platform_device *pdev) +{ + struct led_gpio_flash_data *flash_led = + (struct led_gpio_flash_data *)platform_get_drvdata(pdev); + if (IS_ERR(flash_led->pinctrl)) + devm_pinctrl_put(flash_led->pinctrl); + led_classdev_unregister(&flash_led->cdev); + devm_kfree(&pdev->dev, flash_led); + return 0; +} + +static struct platform_driver led_gpio_flash_driver = { + .probe = led_gpio_flash_probe, + .remove = led_gpio_flash_remove, + .driver = { + .name = LED_GPIO_FLASH_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = led_gpio_flash_of_match, + } +}; + +static int __init led_gpio_flash_init(void) +{ + return platform_driver_register(&led_gpio_flash_driver); +} + +static void __exit led_gpio_flash_exit(void) +{ + return platform_driver_unregister(&led_gpio_flash_driver); +} + +late_initcall(led_gpio_flash_init); +module_exit(led_gpio_flash_exit); + +MODULE_DESCRIPTION("QTI GPIO LEDs driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("leds:leds-msm-gpio-flash"); diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h index b935839ab79c6781c68d8cdc0466418f2798bb95..f483041eed986b0ea0bfbbda7fff0c2c83313811 100644 --- a/drivers/md/bcache/bset.h +++ b/drivers/md/bcache/bset.h @@ -380,7 +380,8 @@ void bch_btree_keys_stats(struct btree_keys *, struct bset_stats *); /* Bkey utility code */ -#define bset_bkey_last(i) bkey_idx((struct bkey *) (i)->d, (i)->keys) +#define bset_bkey_last(i) bkey_idx((struct bkey *) (i)->d, \ + (unsigned int)(i)->keys) static inline struct bkey *bset_bkey_idx(struct bset *i, unsigned idx) { diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 4e34afb6e36a52919b64d08526e5cdf384079787..c8c5e3368b8b8795bfec19f6c7ce2e92906b5282 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -681,6 +681,8 @@ static unsigned long bch_mca_scan(struct shrinker *shrink, * IO can always make forward progress: */ nr /= c->btree_pages; + if (nr == 0) + nr = 1; nr = min_t(unsigned long, nr, mca_can_free(c)); i = 0; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 2dc2bbb0e9b90bfd6c811956c54de68f9a833d57..86a6dbdb6d02b2b0b85d25973a616e852db3d3e5 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1398,9 +1398,6 @@ static void cache_set_flush(struct closure *cl) struct btree *b; unsigned i; - if (!c) - closure_return(cl); - bch_cache_accounting_destroy(&c->accounting); kobject_put(&c->internal); diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index f7ff408567ad56fc6a54c9bb27257529478138c9..63bff4cc70984ddfa356af40ba02853d7a471c92 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1699,7 +1699,7 @@ void bitmap_flush(struct mddev *mddev) /* * free memory that was allocated */ -static void bitmap_free(struct bitmap *bitmap) +static void md_bitmap_free(struct bitmap *bitmap) { unsigned long k, pages; struct bitmap_page *bp; @@ -1749,7 +1749,7 @@ void bitmap_destroy(struct mddev *mddev) if (mddev->thread) mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; - bitmap_free(bitmap); + md_bitmap_free(bitmap); } /* @@ -1834,7 +1834,7 @@ struct bitmap *bitmap_create(struct mddev *mddev, int slot) return bitmap; error: - bitmap_free(bitmap); + md_bitmap_free(bitmap); return ERR_PTR(err); } @@ -1936,7 +1936,7 @@ int bitmap_copy_from_slot(struct mddev *mddev, int slot, *low = lo; *high = hi; err: - bitmap_free(bitmap); + md_bitmap_free(bitmap); return rv; } EXPORT_SYMBOL_GPL(bitmap_copy_from_slot); diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index f3993a4aefc1e3c4ee6c7d5b176b79afaed9aaa1..4dac4bb9d4b8c3047362edf870f3d15b35061872 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2192,8 +2192,8 @@ static void wait_for_migrations(struct cache *cache) static void stop_worker(struct cache *cache) { - cancel_delayed_work(&cache->waker); - flush_workqueue(cache->wq); + cancel_delayed_work_sync(&cache->waker); + drain_workqueue(cache->wq); } static void requeue_deferred_cells(struct cache *cache) diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index b8cf956b577b4a2f235f4910b15ab2ef1942dd9b..771ec28e87cbd485e32912f7c86a33f0f7260dc1 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -17,7 +17,7 @@ #include "dm-bufio.h" #define DM_MSG_PREFIX "persistent snapshot" -#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ +#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32U /* 16KB */ #define DM_PREFETCH_CHUNKS 12 diff --git a/drivers/md/dm.c b/drivers/md/dm.c old mode 100644 new mode 100755 index a2d2ac239c08175f83c31628d24d274b109bd6a8..e96c32d49523e1c55254024b8877dd0d02da3fa4 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1464,7 +1464,6 @@ void dm_init_md_queue(struct mapped_device *md) * - must do so here (in alloc_dev callchain) before queue is used */ md->queue->queuedata = md; - md->queue->backing_dev_info->congested_data = md; } void dm_init_normal_md_queue(struct mapped_device *md) @@ -1475,6 +1474,7 @@ void dm_init_normal_md_queue(struct mapped_device *md) /* * Initialize aspects of queue that aren't relevant for blk-mq */ + md->queue->backing_dev_info->congested_data = md; md->queue->backing_dev_info->congested_fn = dm_any_congested; blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); } @@ -1562,6 +1562,12 @@ static struct mapped_device *alloc_dev(int minor) goto bad; dm_init_md_queue(md); + /* + * default to bio-based required ->make_request_fn until DM + * table is loaded and md->type established. If request-based + * table is loaded: blk-mq will override accordingly. + */ + blk_queue_make_request(md->queue, dm_make_request); md->disk = alloc_disk_node(1, numa_node_id); if (!md->disk) @@ -1860,7 +1866,6 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) case DM_TYPE_BIO_BASED: case DM_TYPE_DAX_BIO_BASED: dm_init_normal_md_queue(md); - blk_queue_make_request(md->queue, dm_make_request); /* * DM handles splitting bios as needed. Free the bio_split bioset * since it won't be used (saves 1 process per bio-based DM device). diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index 21ea537bd55e9984f7cfe5b908a3d6bcad9038e9..eff04fa23dfad46d7d43dee24cde0a1fd90f2f68 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c @@ -203,7 +203,13 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, struct btree_node *right = r->n; uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); - unsigned threshold = 2 * merge_threshold(left) + 1; + /* + * Ensure the number of entries in each child will be greater + * than or equal to (max_entries / 3 + 1), so no matter which + * child is used for removal, the number will still be not + * less than (max_entries / 3). + */ + unsigned int threshold = 2 * (merge_threshold(left) + 1); if (nr_left + nr_right < threshold) { /* diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c index 306d2e4502c480aef245224a5235c37dc8b94d0a..22729fd92a1b93afece3f7f2a727dec0b03bc739 100644 --- a/drivers/md/persistent-data/dm-space-map-common.c +++ b/drivers/md/persistent-data/dm-space-map-common.c @@ -382,6 +382,33 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, return -ENOSPC; } +int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll, + dm_block_t begin, dm_block_t end, dm_block_t *b) +{ + int r; + uint32_t count; + + do { + r = sm_ll_find_free_block(new_ll, begin, new_ll->nr_blocks, b); + if (r) + break; + + /* double check this block wasn't used in the old transaction */ + if (*b >= old_ll->nr_blocks) + count = 0; + else { + r = sm_ll_lookup(old_ll, *b, &count); + if (r) + break; + + if (count) + begin = *b + 1; + } + } while (count); + + return r; +} + static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, int (*mutator)(void *context, uint32_t old, uint32_t *new), void *context, enum allocation_event *ev) diff --git a/drivers/md/persistent-data/dm-space-map-common.h b/drivers/md/persistent-data/dm-space-map-common.h index b3078d5eda0c335c2986b84128d3e5bde01e8b8e..8de63ce39bdd53d099cb91eb50647f0d703d727a 100644 --- a/drivers/md/persistent-data/dm-space-map-common.h +++ b/drivers/md/persistent-data/dm-space-map-common.h @@ -109,6 +109,8 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result); int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result); int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, dm_block_t end, dm_block_t *result); +int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll, + dm_block_t begin, dm_block_t end, dm_block_t *result); int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev); int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev); int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev); diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index 32adf6b4a9c7097e12796f8b396f80bfc8867c0a..bf4c5e2ccb6ffc8d8e0fa5ba049429bdb6dc18d0 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -167,8 +167,10 @@ static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) enum allocation_event ev; struct sm_disk *smd = container_of(sm, struct sm_disk, sm); - /* FIXME: we should loop round a couple of times */ - r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b); + /* + * Any block we allocate has to be free in both the old and current ll. + */ + r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b); if (r) return r; diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 1d29771af380de313209eca0581f35937a5808e9..967d8f2a731fbda3a38b908e5511d91512ca3c76 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -447,7 +447,10 @@ static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b) enum allocation_event ev; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); - r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b); + /* + * Any block we allocate has to be free in both the old and current ll. + */ + r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b); if (r) return r; diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 3716dae9d091bde5130b85ff2a3e1138e64937f4..6f18a1bf59df750632809c58fee1291f1f0a754d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -82,7 +82,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) char b[BDEVNAME_SIZE]; char b2[BDEVNAME_SIZE]; struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL); - unsigned short blksize = 512; + unsigned blksize = 512; *private_conf = ERR_PTR(-ENOMEM); if (!conf) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 0fc99dd6fb361b831a0c938bf7a79e5357cab7ff..2e695c9cbda85f88bc418cff7a5193ed536a2f45 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2633,7 +2633,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, write_targets++; } } - if (bio->bi_end_io) { + if (rdev && bio->bi_end_io) { atomic_inc(&rdev->nr_pending); bio->bi_iter.bi_sector = sector_nr + rdev->data_offset; bio->bi_bdev = rdev->bdev; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 58eb62f1ba214449d72a8f06b09e2f21c1eb47c4..a018a76662df7d0e167aff9fbff765e7da6f731c 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -423,10 +423,12 @@ static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { + struct mt9v032 *mt9v032 = to_mt9v032(subdev); + if (code->index > 0) return -EINVAL; - code->code = MEDIA_BUS_FMT_SGRBG10_1X10; + code->code = mt9v032->format.code; return 0; } @@ -434,7 +436,11 @@ static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { - if (fse->index >= 3 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) + struct mt9v032 *mt9v032 = to_mt9v032(subdev); + + if (fse->index >= 3) + return -EINVAL; + if (mt9v032->format.code != fse->code) return -EINVAL; fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index); diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 3554eea77e04ce1f1f98aa68e0b6f1a49d617588..18546f950d7929c4df76f4d065f489039cdec2a6 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -419,10 +419,14 @@ static struct sensor_register ov2659_720p[] = { { REG_TIMING_YINC, 0x11 }, { REG_TIMING_VERT_FORMAT, 0x80 }, { REG_TIMING_HORIZ_FORMAT, 0x00 }, + { 0x370a, 0x12 }, { 0x3a03, 0xe8 }, { 0x3a09, 0x6f }, { 0x3a0b, 0x5d }, { 0x3a15, 0x9a }, + { REG_VFIFO_READ_START_H, 0x00 }, + { REG_VFIFO_READ_START_L, 0x80 }, + { REG_ISP_CTRL02, 0x00 }, { REG_NULL, 0x00 }, }; @@ -1133,7 +1137,7 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd, mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); *mf = fmt->format; #else - return -ENOTTY; + ret = -ENOTTY; #endif } else { s64 val; @@ -1204,11 +1208,15 @@ static int ov2659_s_stream(struct v4l2_subdev *sd, int on) goto unlock; } - ov2659_set_pixel_clock(ov2659); - ov2659_set_frame_size(ov2659); - ov2659_set_format(ov2659); - ov2659_set_streaming(ov2659, 1); - ov2659->streaming = on; + ret = ov2659_set_pixel_clock(ov2659); + if (!ret) + ret = ov2659_set_frame_size(ov2659); + if (!ret) + ret = ov2659_set_format(ov2659); + if (!ret) { + ov2659_set_streaming(ov2659, 1); + ov2659->streaming = on; + } unlock: mutex_unlock(&ov2659->lock); diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index fc187c5aeb1e9f8a8bd093ac709b690d977011f2..3c959e48855c3808506b9d2514200567f56dda14 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -203,7 +203,6 @@ struct ov6650 { unsigned long pclk_max; /* from resolution and format */ struct v4l2_fract tpf; /* as requested with s_parm */ u32 code; - enum v4l2_colorspace colorspace; }; @@ -216,6 +215,17 @@ static u32 ov6650_codes[] = { MEDIA_BUS_FMT_Y8_1X8, }; +static const struct v4l2_mbus_framefmt ov6650_def_fmt = { + .width = W_CIF, + .height = H_CIF, + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .colorspace = V4L2_COLORSPACE_SRGB, + .field = V4L2_FIELD_NONE, + .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, + .quantization = V4L2_QUANTIZATION_DEFAULT, + .xfer_func = V4L2_XFER_FUNC_DEFAULT, +}; + /* read a register */ static int ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val) { @@ -512,12 +522,20 @@ static int ov6650_get_fmt(struct v4l2_subdev *sd, if (format->pad) return -EINVAL; - mf->width = priv->rect.width >> priv->half_scale; - mf->height = priv->rect.height >> priv->half_scale; - mf->code = priv->code; - mf->colorspace = priv->colorspace; - mf->field = V4L2_FIELD_NONE; + /* initialize response with default media bus frame format */ + *mf = ov6650_def_fmt; + + /* update media bus format code and frame size */ + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + mf->width = cfg->try_fmt.width; + mf->height = cfg->try_fmt.height; + mf->code = cfg->try_fmt.code; + } else { + mf->width = priv->rect.width >> priv->half_scale; + mf->height = priv->rect.height >> priv->half_scale; + mf->code = priv->code; + } return 0; } @@ -612,7 +630,6 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) dev_err(&client->dev, "Pixel format not handled: 0x%x\n", code); return -EINVAL; } - priv->code = code; if (code == MEDIA_BUS_FMT_Y8_1X8 || code == MEDIA_BUS_FMT_SBGGR8_1X8) { @@ -625,11 +642,6 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) priv->pclk_max = 8000000; } - if (code == MEDIA_BUS_FMT_SBGGR8_1X8) - priv->colorspace = V4L2_COLORSPACE_SRGB; - else if (code != 0) - priv->colorspace = V4L2_COLORSPACE_JPEG; - if (half_scale) { dev_dbg(&client->dev, "max resolution: QCIF\n"); coma_set |= COMA_QCIF; @@ -638,7 +650,6 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) dev_dbg(&client->dev, "max resolution: CIF\n"); coma_mask |= COMA_QCIF; } - priv->half_scale = half_scale; if (sense) { if (sense->master_clock == 8000000) { @@ -678,14 +689,14 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask); if (!ret) ret = ov6650_reg_write(client, REG_CLKRC, clkrc); - if (!ret) - ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask); - if (!ret) { - mf->colorspace = priv->colorspace; - mf->width = priv->rect.width >> half_scale; - mf->height = priv->rect.height >> half_scale; + priv->half_scale = half_scale; + + ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask); } + if (!ret) + priv->code = code; + return ret; } @@ -704,8 +715,6 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd, v4l_bound_align_image(&mf->width, 2, W_CIF, 1, &mf->height, 2, H_CIF, 1, 0); - mf->field = V4L2_FIELD_NONE; - switch (mf->code) { case MEDIA_BUS_FMT_Y10_1X10: mf->code = MEDIA_BUS_FMT_Y8_1X8; @@ -714,19 +723,38 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd, case MEDIA_BUS_FMT_YUYV8_2X8: case MEDIA_BUS_FMT_VYUY8_2X8: case MEDIA_BUS_FMT_UYVY8_2X8: - mf->colorspace = V4L2_COLORSPACE_JPEG; break; default: mf->code = MEDIA_BUS_FMT_SBGGR8_1X8; case MEDIA_BUS_FMT_SBGGR8_1X8: - mf->colorspace = V4L2_COLORSPACE_SRGB; break; } - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) - return ov6650_s_fmt(sd, mf); - cfg->try_fmt = *mf; + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + /* store media bus format code and frame size in pad config */ + cfg->try_fmt.width = mf->width; + cfg->try_fmt.height = mf->height; + cfg->try_fmt.code = mf->code; + + /* return default mbus frame format updated with pad config */ + *mf = ov6650_def_fmt; + mf->width = cfg->try_fmt.width; + mf->height = cfg->try_fmt.height; + mf->code = cfg->try_fmt.code; + } else { + /* apply new media bus format code and frame size */ + int ret = ov6650_s_fmt(sd, mf); + + if (ret) + return ret; + + /* return default format updated with active size and code */ + *mf = ov6650_def_fmt; + mf->width = priv->rect.width >> priv->half_scale; + mf->height = priv->rect.height >> priv->half_scale; + mf->code = priv->code; + } return 0; } @@ -1045,7 +1073,6 @@ static int ov6650_probe(struct i2c_client *client, priv->rect.height = H_CIF; priv->half_scale = false; priv->code = MEDIA_BUS_FMT_YUYV8_2X8; - priv->colorspace = V4L2_COLORSPACE_JPEG; ret = ov6650_video_probe(client); if (ret) diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index df837408efd595f67dc9c2c8e6263039f54d4177..0171dc5b8809ea22595636561775ab22a0b6f314 100644 --- a/drivers/media/pci/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c @@ -490,7 +490,7 @@ static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf, CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc); if (rc > 0) - pos += rc; + *pos += rc; return rc; } diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 818f3c2fc98d8507317bd99d49f9d2c7717aee91..1d86e57f4d9fd18031021eb74b467616ca080c9b 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -1471,8 +1471,9 @@ static int dvb_register(struct cx23885_tsport *port) if (fe0->dvb.frontend != NULL) { struct i2c_adapter *tun_i2c; - fe0->dvb.frontend->sec_priv = kmalloc(sizeof(dib7000p_ops), GFP_KERNEL); - memcpy(fe0->dvb.frontend->sec_priv, &dib7000p_ops, sizeof(dib7000p_ops)); + fe0->dvb.frontend->sec_priv = kmemdup(&dib7000p_ops, sizeof(dib7000p_ops), GFP_KERNEL); + if (!fe0->dvb.frontend->sec_priv) + return -ENOMEM; tun_i2c = dib7000p_ops.get_i2c_master(fe0->dvb.frontend, DIBX000_I2C_INTERFACE_TUNER, 1); if (!dvb_attach(dib0070_attach, fe0->dvb.frontend, tun_i2c, &dib7070p_dib0070_config)) return -ENODEV; diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index c9bd018e53de607f63cfe1367404be228ec90806..e2b19c3eaa87633e8109d2da8c9571e7d95ab4a8 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -420,7 +420,7 @@ static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t co IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc); if (rc > 0) - pos += rc; + *pos += rc; return rc; } diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c index 1ddf80f85c248cfb3b810521dfe9817104aec8e9..27ff6e0d98453a6bc68e1a1c934a4aca5b79fc51 100644 --- a/drivers/media/pci/tw5864/tw5864-video.c +++ b/drivers/media/pci/tw5864/tw5864-video.c @@ -1386,13 +1386,13 @@ static void tw5864_handle_frame(struct tw5864_h264_frame *frame) input->vb = NULL; spin_unlock_irqrestore(&input->slock, flags); - v4l2_buf = to_vb2_v4l2_buffer(&vb->vb.vb2_buf); - if (!vb) { /* Gone because of disabling */ dev_dbg(&dev->pci->dev, "vb is empty, dropping frame\n"); return; } + v4l2_buf = to_vb2_v4l2_buffer(&vb->vb.vb2_buf); + /* * Check for space. * Mind the overhead of startcode emulation prevention. diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 05489a401c5c1506efbd7f742ac7ea81e3276ef7..bd500f12d0f79283f4ac50f026e8c18a9b924b44 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1847,6 +1847,10 @@ static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id) if (!(sdinfo->inputs[0].capabilities & V4L2_IN_CAP_STD)) return -ENODATA; + /* if trying to set the same std then nothing to do */ + if (vpfe_standards[vpfe->std_index].std_id == std_id) + return 0; + /* If streaming is started, return error */ if (vb2_is_busy(&vpfe->buffer_queue)) { vpfe_err(vpfe, "%s device busy\n", __func__); diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c index 78e37cf3470f2c059a2edbbfc2f7ae96d8b2f852..b51b875c5a6122b0b0af4fc01d8071fe07721b02 100644 --- a/drivers/media/platform/davinci/isif.c +++ b/drivers/media/platform/davinci/isif.c @@ -890,9 +890,7 @@ static int isif_set_hw_if_params(struct vpfe_hw_if_param *params) static int isif_config_ycbcr(void) { struct isif_ycbcr_config *params = &isif_cfg.ycbcr; - struct vpss_pg_frame_size frame_size; u32 modeset = 0, ccdcfg = 0; - struct vpss_sync_pol sync; dev_dbg(isif_cfg.dev, "\nStarting isif_config_ycbcr..."); @@ -980,13 +978,6 @@ static int isif_config_ycbcr(void) /* two fields are interleaved in memory */ regw(0x00000249, SDOFST); - /* Setup test pattern if enabled */ - if (isif_cfg.bayer.config_params.test_pat_gen) { - sync.ccdpg_hdpol = params->hd_pol; - sync.ccdpg_vdpol = params->vd_pol; - dm365_vpss_set_sync_pol(sync); - dm365_vpss_set_pg_frame_size(frame_size); - } return 0; } diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c index abce9c4a1a8ec9f8b8980d74a73b02c48ba9f779..59518c08528b869a710015c23c759492e0041594 100644 --- a/drivers/media/platform/davinci/vpbe.c +++ b/drivers/media/platform/davinci/vpbe.c @@ -130,7 +130,7 @@ static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev, struct v4l2_output *output) { struct vpbe_config *cfg = vpbe_dev->cfg; - int temp_index = output->index; + unsigned int temp_index = output->index; if (temp_index >= cfg->num_outputs) return -EINVAL; diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index e00fa03ddc3e99c3376c0b798369baca244fcfe6..0c0eec671d4995c26100a55f80d96f6e4a540263 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -316,7 +316,7 @@ static int isp_video_release(struct file *file) ivc->streaming = 0; } - vb2_fop_release(file); + _vb2_fop_release(file, NULL); if (v4l2_fh_is_singular_file(file)) { fimc_pipeline_call(&ivc->ve, close); diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index e418fa97081d32dc7c8ea5bb3abdc7b55e617a91..0dce0fafa5060b95730263e4a070284b7213acd6 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-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 @@ -511,8 +511,8 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller, } } - priority = evt_handler->priority; if (found) { + priority = evt_handler->priority; for (i = 0; i < controller->num_registers; i++) { irq_register = &controller->irq_register_arr[i]; irq_register->top_half_enable_mask[priority] &= diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c index c5808d45b0b134bd8ce080b428a9c33546395d0a..e6a0e015963c4dd67b9517b4e5887296f4078db5 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-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 @@ -511,8 +511,8 @@ int cam_irq_controller_unsubscribe_irq(void *irq_controller, } } - priority = evt_handler->priority; if (found) { + priority = evt_handler->priority; for (i = 0; i < controller->num_registers; i++) { irq_register = &controller->irq_register_arr[i]; irq_register->top_half_enable_mask[priority] &= diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h b/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h index 56b86d7952ca73af28f7f4e9e550e4aa160738fb..7d711aa22ce8db4d78bd8dbbe42aaa27c4d783d1 100644 --- a/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, 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 @@ -40,8 +40,8 @@ #define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1) #define MAX_DEBUGFS_NAME 50 #define DEFAULT_TIMEOUT 3 -#define DEFAULT_HEIGHT 1088 -#define DEFAULT_WIDTH 1920 +#define DEFAULT_HEIGHT 480 +#define DEFAULT_WIDTH 720 #define MIN_SUPPORTED_WIDTH 32 #define MIN_SUPPORTED_HEIGHT 32 #define DEFAULT_FPS 15 diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index a31b95cb3b09c0623be42762cea8d4dc08c99170..77ec70f5fef6623ac547bd4339e14de672164e37 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -1526,23 +1526,20 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) unsigned long size; struct videobuf_buffer *vb; - vb = q->bufs[b->index]; - if (!vout->streaming) return -EINVAL; - if (file->f_flags & O_NONBLOCK) - /* Call videobuf_dqbuf for non blocking mode */ - ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1); - else - /* Call videobuf_dqbuf for blocking mode */ - ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0); + ret = videobuf_dqbuf(q, b, !!(file->f_flags & O_NONBLOCK)); + if (ret) + return ret; + + vb = q->bufs[b->index]; addr = (unsigned long) vout->buf_phy_addr[vb->i]; size = (unsigned long) vb->size; dma_unmap_single(vout->vid_dev->v4l2_dev.dev, addr, size, DMA_TO_DEVICE); - return ret; + return 0; } static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index c89922fb42cef6484490712913b08a3be4d22dc2..a63f4eec366eb6e21704abdf240aad3fef80504b 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1963,7 +1963,7 @@ static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx) v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, V4L2_CID_JPEG_RESTART_INTERVAL, - 0, 3, 0xffff, 0); + 0, 0xffff, 1, 0); if (ctx->jpeg->variant->version == SJPEG_S5P) mask = ~0x06; /* 422, 420 */ } diff --git a/drivers/media/platform/sti/bdisp/bdisp-hw.c b/drivers/media/platform/sti/bdisp/bdisp-hw.c index b7892f3efd988a45da8ebc18b9a2bd9222ed8157..5c4c3f0c57be1c45ea2f258abf2db4602a9bdb8f 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-hw.c +++ b/drivers/media/platform/sti/bdisp/bdisp-hw.c @@ -14,8 +14,8 @@ #define MAX_SRC_WIDTH 2048 /* Reset & boot poll config */ -#define POLL_RST_MAX 50 -#define POLL_RST_DELAY_MS 20 +#define POLL_RST_MAX 500 +#define POLL_RST_DELAY_MS 2 enum bdisp_target_plan { BDISP_RGB, @@ -382,7 +382,7 @@ int bdisp_hw_reset(struct bdisp_dev *bdisp) for (i = 0; i < POLL_RST_MAX; i++) { if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE) break; - msleep(POLL_RST_DELAY_MS); + udelay(POLL_RST_DELAY_MS * 1000); } if (i == POLL_RST_MAX) dev_err(bdisp->dev, "Reset timeout\n"); diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index 45f82b5ddd770757d79b0a2c93f9c31bdc453528..d88c9ba401b5d84d79fb9d9d64a9671cbcef6b58 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -651,8 +651,7 @@ static int bdisp_release(struct file *file) dev_dbg(bdisp->dev, "%s\n", __func__); - if (mutex_lock_interruptible(&bdisp->lock)) - return -ERESTARTSYS; + mutex_lock(&bdisp->lock); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index 0189f7f7cb03fbeba9d3222f77d090d0cd6e1bb3..dbb4829acc4387695bd6b9c171d8f9841f0d6dd2 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -330,20 +330,25 @@ enum { }; /* find our format description corresponding to the passed v4l2_format */ -static struct vpe_fmt *find_format(struct v4l2_format *f) +static struct vpe_fmt *__find_format(u32 fourcc) { struct vpe_fmt *fmt; unsigned int k; for (k = 0; k < ARRAY_SIZE(vpe_formats); k++) { fmt = &vpe_formats[k]; - if (fmt->fourcc == f->fmt.pix.pixelformat) + if (fmt->fourcc == fourcc) return fmt; } return NULL; } +static struct vpe_fmt *find_format(struct v4l2_format *f) +{ + return __find_format(f->fmt.pix.pixelformat); +} + /* * there is one vpe_dev structure in the driver, it is shared by * all instances. @@ -1293,6 +1298,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) d_vb->timecode = s_vb->timecode; d_vb->sequence = ctx->sequence; + s_vb->sequence = ctx->sequence; d_q_data = &ctx->q_data[Q_DATA_DST]; if (d_q_data->flags & Q_DATA_INTERLACED) { @@ -1433,9 +1439,9 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, int i, depth, depth_bytes; if (!fmt || !(fmt->types & type)) { - vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n", + vpe_dbg(ctx->dev, "Fourcc format (0x%08x) invalid.\n", pix->pixelformat); - return -EINVAL; + fmt = __find_format(V4L2_PIX_FMT_YUYV); } if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE) @@ -1992,7 +1998,7 @@ static int vpe_open(struct file *file) v4l2_ctrl_handler_setup(hdl); s_q_data = &ctx->q_data[Q_DATA_SRC]; - s_q_data->fmt = &vpe_formats[2]; + s_q_data->fmt = __find_format(V4L2_PIX_FMT_YUYV); s_q_data->width = 1920; s_q_data->height = 1080; s_q_data->bytesperline[VPE_LUMA] = (s_q_data->width * diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c index bdc380b14e0c47e73461ded4b16d01cbf484ed2d..a95b7c56569e38c65308498093101e5585295d36 100644 --- a/drivers/media/platform/vivid/vivid-osd.c +++ b/drivers/media/platform/vivid/vivid-osd.c @@ -167,7 +167,7 @@ static int _vivid_fb_check_var(struct fb_var_screeninfo *var, struct vivid_dev * var->nonstd = 0; var->vmode &= ~FB_VMODE_MASK; - var->vmode = FB_VMODE_NONINTERLACED; + var->vmode |= FB_VMODE_NONINTERLACED; /* Dummy values */ var->hsync_len = 24; diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index a93f681aa9d67c2f5dcb9bc6871f7239940960bd..6426b07510a77b3b9a3c73d11a8a8da979dc67ad 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1149,8 +1149,7 @@ static int wl1273_fm_fops_release(struct file *file) if (radio->rds_users > 0) { radio->rds_users--; if (radio->rds_users == 0) { - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; + mutex_lock(&core->lock); radio->irq_flags &= ~WL1273_RDS_EVENT; diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index f218886c504d9ad03fada1742c77697bb7a499ad..8f3086773db46ecb051c1f817e4cfb364e0971c9 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -458,8 +458,10 @@ static int si470x_i2c_remove(struct i2c_client *client) free_irq(client->irq, radio); video_unregister_device(&radio->videodev); - kfree(radio); + v4l2_ctrl_handler_free(&radio->hdl); + v4l2_device_unregister(&radio->v4l2_dev); + kfree(radio); return 0; } diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index c1457cf466981918e81db9e90b7d376bbc770e17..db987dda356e0bd75413f9d57a1f5f0f61f122a7 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -1278,8 +1278,9 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) switch (action->type) { case ACTION_SEND_COMMAND: /* Send */ - if (fmc_send_cmd(fmdev, 0, 0, action->data, - action->size, NULL, NULL)) + ret = fmc_send_cmd(fmdev, 0, 0, action->data, + action->size, NULL, NULL); + if (ret) goto rel_fw; cmd_cnt++; diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index 25470395c43f1c838d7b28a1e739894d9fd84c61..246795c31553390da0db73139e387ba392253407 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c @@ -430,7 +430,7 @@ static int iguanair_probe(struct usb_interface *intf, int ret, pipein, pipeout; struct usb_host_interface *idesc; - idesc = intf->altsetting; + idesc = intf->cur_altsetting; if (idesc->desc.bNumEndpoints < 2) return -ENODEV; diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 1fc3c8d7dd9b8c73efb0967529a1aeb0bc0ee2ae..78809bb5e69e513528ef64796e1ecfb644ce632d 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -295,7 +295,7 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, mutex_unlock(&fc_usb->data_mutex); - return 0; + return ret; } /* actual bus specific access functions, @@ -504,7 +504,13 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) static int flexcop_usb_init(struct flexcop_usb *fc_usb) { /* use the alternate setting with the larges buffer */ - usb_set_interface(fc_usb->udev,0,1); + int ret = usb_set_interface(fc_usb->udev, 0, 1); + + if (ret) { + err("set interface failed."); + return ret; + } + switch (fc_usb->udev->speed) { case USB_SPEED_LOW: err("cannot handle USB speed because it is too slow."); diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c index 7853261906b1afd3334e8e67e74a3f4a5311a13e..519e01ba575013064744d4cd4aae2ff169c7470f 100644 --- a/drivers/media/usb/dvb-usb/af9005.c +++ b/drivers/media/usb/dvb-usb/af9005.c @@ -567,7 +567,7 @@ static int af9005_boot_packet(struct usb_device *udev, int type, u8 *reply, u8 *buf, int size) { u16 checksum; - int act_len, i, ret; + int act_len = 0, i, ret; memset(buf, 0, size); buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); @@ -990,8 +990,9 @@ static int af9005_identify_state(struct usb_device *udev, else if (reply == 0x02) *cold = 0; else - return -EIO; - deb_info("Identify state cold = %d\n", *cold); + ret = -EIO; + if (!ret) + deb_info("Identify state cold = %d\n", *cold); err: kfree(buf); diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 475a3c0cdee7f88a9630f337cd9d0aaf59f2e177..20d33f0544ed209020f23dcbacc9abd7c50cfbee 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -233,18 +233,22 @@ static struct rc_map_table rc_map_digitv_table[] = { static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - int i; + int ret, i; u8 key[5]; u8 b[4] = { 0 }; *event = 0; *state = REMOTE_NO_KEY_PRESSED; - digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4); + ret = digitv_ctrl_msg(d, USB_READ_REMOTE, 0, NULL, 0, &key[1], 4); + if (ret) + return ret; /* Tell the device we've read the remote. Not sure how necessary this is, but the Nebula SDK does it. */ - digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); + ret = digitv_ctrl_msg(d, USB_WRITE_REMOTE, 0, b, 4, NULL, 0); + if (ret) + return ret; /* if something is inside the buffer, simulate key press */ if (key[1] != 0) diff --git a/drivers/media/usb/dvb-usb/dvb-usb-urb.c b/drivers/media/usb/dvb-usb/dvb-usb-urb.c index 95f9097498cb86259f0209013ab499894ab39839..2fa8d71385eccef64db064a6613b0d2c01509e9f 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-urb.c @@ -11,7 +11,7 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen, int delay_ms) { - int actlen,ret = -ENOMEM; + int actlen = 0, ret = -ENOMEM; if (!d || wbuf == NULL || wlen == 0) return -EINVAL; diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index af2395a76d8bf930f35bdf1afab4593ae65d162c..2cba2e1acdc68e0a45ff61af49a7947dc93b7a96 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -2043,7 +2043,7 @@ int gspca_dev_probe2(struct usb_interface *intf, pr_err("couldn't kzalloc gspca struct\n"); return -ENOMEM; } - gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); + gspca_dev->usb_buf = kzalloc(USB_BUF_SZ, GFP_KERNEL); if (!gspca_dev->usb_buf) { pr_err("out of memory\n"); ret = -ENOMEM; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 2cc4d2b6f810be171eb2b8bbb9a16cfca84d43b9..d18ced28797dac7dcb8589f8f03cede939c0e1c7 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -919,8 +919,12 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) pvr2_v4l2_dev_disassociate_parent(vp->dev_video); pvr2_v4l2_dev_disassociate_parent(vp->dev_radio); if (!list_empty(&vp->dev_video->devbase.fh_list) || - !list_empty(&vp->dev_radio->devbase.fh_list)) + (vp->dev_radio && + !list_empty(&vp->dev_radio->devbase.fh_list))) { + pvr2_trace(PVR2_TRACE_STRUCT, + "pvr2_v4l2 internal_check exit-empty id=%p", vp); return; + } pvr2_v4l2_destroy_no_lock(vp); } @@ -994,7 +998,8 @@ static int pvr2_v4l2_release(struct file *file) kfree(fhp); if (vp->channel.mc_head->disconnect_flag && list_empty(&vp->dev_video->devbase.fh_list) && - list_empty(&vp->dev_radio->devbase.fh_list)) { + (!vp->dev_radio || + list_empty(&vp->dev_radio->devbase.fh_list))) { pvr2_v4l2_destroy_no_lock(vp); } return 0; diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index 7297fd261df947044cb443b8ab626c4ed8c2f774..f9844f87467b467e5c2e49a442db336c63fab8c7 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -166,7 +166,11 @@ int stk_camera_read_reg(struct stk_camera *dev, u16 index, u8 *value) *value = *buf; kfree(buf); - return ret; + + if (ret < 0) + return ret; + else + return 0; } static int stk_start_stream(struct stk_camera *dev) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index d5347a2804fb5e63389f79df3f45a9edb87fb74a..94acf7ca452d6d951830f712ffc2b97b8d419713 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1411,6 +1411,11 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, break; if (forward == prev) continue; + if (forward->chain.next || forward->chain.prev) { + uvc_trace(UVC_TRACE_DESCR, "Found reference to " + "entity %d already in chain.\n", forward->id); + return -EINVAL; + } switch (UVC_ENTITY_TYPE(forward)) { case UVC_VC_EXTENSION_UNIT: @@ -1492,6 +1497,13 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, return -1; } + if (term->chain.next || term->chain.prev) { + uvc_trace(UVC_TRACE_DESCR, "Found reference to " + "entity %d already in chain.\n", + term->id); + return -EINVAL; + } + if (uvc_trace_param & UVC_TRACE_PROBE) printk(" %d", term->id); diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index e3735bfcc02fcd94f1c5e3855f5effa2353ae3e8..c5513f55e64e068b9d814cbe9368159b606c3806 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -711,7 +711,8 @@ static int zr364xx_vidioc_querycap(struct file *file, void *priv, struct zr364xx_camera *cam = video_drvdata(file); strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); - strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); + if (cam->udev->product) + strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); strlcpy(cap->bus_info, dev_name(&cam->udev->dev), sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index b6189a4958c5ec2d40cfd8486e69794ba9be9bee..025822bc6941f7ad3ef0093ce888834a5818570e 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -352,8 +352,11 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) BUG_ON(dma->sglen); if (dma->pages) { - for (i = 0; i < dma->nr_pages; i++) + for (i = 0; i < dma->nr_pages; i++) { + if (dma->direction == DMA_FROM_DEVICE) + set_page_dirty_lock(dma->pages[i]); put_page(dma->pages[i]); + } kfree(dma->pages); dma->pages = NULL; } diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 14cf6dfc3b1451582b96a5c191f24385f9700dc6..4d837bcad5db8e4fc9260ebd4f227fe2d8c73fc0 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -100,19 +100,19 @@ struct buflist { * Function prototypes. Called from OS entry point mptctl_ioctl. * arg contents specific to function. */ -static int mptctl_fw_download(unsigned long arg); -static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd); -static int mptctl_gettargetinfo(unsigned long arg); -static int mptctl_readtest(unsigned long arg); -static int mptctl_mpt_command(unsigned long arg); -static int mptctl_eventquery(unsigned long arg); -static int mptctl_eventenable(unsigned long arg); -static int mptctl_eventreport(unsigned long arg); -static int mptctl_replace_fw(unsigned long arg); - -static int mptctl_do_reset(unsigned long arg); -static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd); -static int mptctl_hp_targetinfo(unsigned long arg); +static int mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_getiocinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd); +static int mptctl_gettargetinfo(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_readtest(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_mpt_command(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_eventquery(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_eventenable(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_eventreport(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_replace_fw(MPT_ADAPTER *iocp, unsigned long arg); + +static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg); +static int mptctl_hp_hostinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd); +static int mptctl_hp_targetinfo(MPT_ADAPTER *iocp, unsigned long arg); static int mptctl_probe(struct pci_dev *, const struct pci_device_id *); static void mptctl_remove(struct pci_dev *); @@ -123,8 +123,8 @@ static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg); /* * Private function calls. */ -static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr); -static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen); +static int mptctl_do_mpt_command(MPT_ADAPTER *iocp, struct mpt_ioctl_command karg, void __user *mfPtr); +static int mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen); static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags, struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, @@ -656,19 +656,19 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) * by TM and FW reloads. */ if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) { - return mptctl_getiocinfo(arg, _IOC_SIZE(cmd)); + return mptctl_getiocinfo(iocp, arg, _IOC_SIZE(cmd)); } else if (cmd == MPTTARGETINFO) { - return mptctl_gettargetinfo(arg); + return mptctl_gettargetinfo(iocp, arg); } else if (cmd == MPTTEST) { - return mptctl_readtest(arg); + return mptctl_readtest(iocp, arg); } else if (cmd == MPTEVENTQUERY) { - return mptctl_eventquery(arg); + return mptctl_eventquery(iocp, arg); } else if (cmd == MPTEVENTENABLE) { - return mptctl_eventenable(arg); + return mptctl_eventenable(iocp, arg); } else if (cmd == MPTEVENTREPORT) { - return mptctl_eventreport(arg); + return mptctl_eventreport(iocp, arg); } else if (cmd == MPTFWREPLACE) { - return mptctl_replace_fw(arg); + return mptctl_replace_fw(iocp, arg); } /* All of these commands require an interrupt or @@ -678,15 +678,15 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; if (cmd == MPTFWDOWNLOAD) - ret = mptctl_fw_download(arg); + ret = mptctl_fw_download(iocp, arg); else if (cmd == MPTCOMMAND) - ret = mptctl_mpt_command(arg); + ret = mptctl_mpt_command(iocp, arg); else if (cmd == MPTHARDRESET) - ret = mptctl_do_reset(arg); + ret = mptctl_do_reset(iocp, arg); else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK)) - ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd)); + ret = mptctl_hp_hostinfo(iocp, arg, _IOC_SIZE(cmd)); else if (cmd == HP_GETTARGETINFO) - ret = mptctl_hp_targetinfo(arg); + ret = mptctl_hp_targetinfo(iocp, arg); else ret = -EINVAL; @@ -705,11 +705,10 @@ mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } -static int mptctl_do_reset(unsigned long arg) +static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg) { struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg; struct mpt_ioctl_diag_reset krinfo; - MPT_ADAPTER *iocp; if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) { printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - " @@ -718,12 +717,6 @@ static int mptctl_do_reset(unsigned long arg) return -EFAULT; } - if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) { - printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n", - __FILE__, __LINE__, krinfo.hdr.iocnum); - return -ENODEV; /* (-6) No such device or address */ - } - dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n", iocp->name)); @@ -754,7 +747,7 @@ static int mptctl_do_reset(unsigned long arg) * -ENOMSG if FW upload returned bad status */ static int -mptctl_fw_download(unsigned long arg) +mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg) { struct mpt_fw_xfer __user *ufwdl = (void __user *) arg; struct mpt_fw_xfer kfwdl; @@ -766,7 +759,7 @@ mptctl_fw_download(unsigned long arg) return -EFAULT; } - return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen); + return mptctl_do_fw_download(iocp, kfwdl.bufp, kfwdl.fwlen); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -784,11 +777,10 @@ mptctl_fw_download(unsigned long arg) * -ENOMSG if FW upload returned bad status */ static int -mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) +mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen) { FWDownload_t *dlmsg; MPT_FRAME_HDR *mf; - MPT_ADAPTER *iocp; FWDownloadTCSGE_t *ptsge; MptSge_t *sgl, *sgIn; char *sgOut; @@ -808,17 +800,10 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) pFWDownloadReply_t ReplyMsg = NULL; unsigned long timeleft; - if (mpt_verify_adapter(ioc, &iocp) < 0) { - printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n", - ioc); - return -ENODEV; /* (-6) No such device or address */ - } else { - - /* Valid device. Get a message frame and construct the FW download message. - */ - if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL) - return -EAGAIN; - } + /* Valid device. Get a message frame and construct the FW download message. + */ + if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL) + return -EAGAIN; dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id)); @@ -826,8 +811,6 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) iocp->name, ufwbuf)); dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n", iocp->name, (int)fwlen)); - dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc = %04xh\n", - iocp->name, ioc)); dlmsg = (FWDownload_t*) mf; ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL; @@ -1238,13 +1221,11 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTE * -ENODEV if no such device/adapter */ static int -mptctl_getiocinfo (unsigned long arg, unsigned int data_size) +mptctl_getiocinfo (MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size) { struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_iocinfo *karg; - MPT_ADAPTER *ioc; struct pci_dev *pdev; - int iocnum; unsigned int port; int cim_rev; struct scsi_device *sdev; @@ -1272,14 +1253,6 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) return PTR_ERR(karg); } - if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - kfree(karg); - return -ENODEV; - } - /* Verify the data transfer size is correct. */ if (karg->hdr.maxDataSize != data_size) { printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - " @@ -1385,15 +1358,13 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) * -ENODEV if no such device/adapter */ static int -mptctl_gettargetinfo (unsigned long arg) +mptctl_gettargetinfo (MPT_ADAPTER *ioc, unsigned long arg) { struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_targetinfo karg; - MPT_ADAPTER *ioc; VirtDevice *vdevice; char *pmem; int *pdata; - int iocnum; int numDevices = 0; int lun; int maxWordsLeft; @@ -1408,13 +1379,6 @@ mptctl_gettargetinfo (unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } - dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n", ioc->name)); /* Get the port number and set the maximum number of bytes @@ -1510,12 +1474,10 @@ mptctl_gettargetinfo (unsigned long arg) * -ENODEV if no such device/adapter */ static int -mptctl_readtest (unsigned long arg) +mptctl_readtest (MPT_ADAPTER *ioc, unsigned long arg) { struct mpt_ioctl_test __user *uarg = (void __user *) arg; struct mpt_ioctl_test karg; - MPT_ADAPTER *ioc; - int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) { printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - " @@ -1524,13 +1486,6 @@ mptctl_readtest (unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } - dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n", ioc->name)); /* Fill in the data and return the structure to the calling @@ -1571,12 +1526,10 @@ mptctl_readtest (unsigned long arg) * -ENODEV if no such device/adapter */ static int -mptctl_eventquery (unsigned long arg) +mptctl_eventquery (MPT_ADAPTER *ioc, unsigned long arg) { struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg; struct mpt_ioctl_eventquery karg; - MPT_ADAPTER *ioc; - int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) { printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - " @@ -1585,13 +1538,6 @@ mptctl_eventquery (unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } - dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n", ioc->name)); karg.eventEntries = MPTCTL_EVENT_LOG_SIZE; @@ -1610,12 +1556,10 @@ mptctl_eventquery (unsigned long arg) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int -mptctl_eventenable (unsigned long arg) +mptctl_eventenable (MPT_ADAPTER *ioc, unsigned long arg) { struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg; struct mpt_ioctl_eventenable karg; - MPT_ADAPTER *ioc; - int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) { printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - " @@ -1624,13 +1568,6 @@ mptctl_eventenable (unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } - dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n", ioc->name)); if (ioc->events == NULL) { @@ -1658,12 +1595,10 @@ mptctl_eventenable (unsigned long arg) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int -mptctl_eventreport (unsigned long arg) +mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg) { struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg; struct mpt_ioctl_eventreport karg; - MPT_ADAPTER *ioc; - int iocnum; int numBytes, maxEvents, max; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) { @@ -1673,12 +1608,6 @@ mptctl_eventreport (unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n", ioc->name)); @@ -1712,12 +1641,10 @@ mptctl_eventreport (unsigned long arg) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int -mptctl_replace_fw (unsigned long arg) +mptctl_replace_fw (MPT_ADAPTER *ioc, unsigned long arg) { struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg; struct mpt_ioctl_replace_fw karg; - MPT_ADAPTER *ioc; - int iocnum; int newFwSize; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { @@ -1727,13 +1654,6 @@ mptctl_replace_fw (unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } - dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n", ioc->name)); /* If caching FW, Free the old FW image @@ -1780,12 +1700,10 @@ mptctl_replace_fw (unsigned long arg) * -ENOMEM if memory allocation error */ static int -mptctl_mpt_command (unsigned long arg) +mptctl_mpt_command (MPT_ADAPTER *ioc, unsigned long arg) { struct mpt_ioctl_command __user *uarg = (void __user *) arg; struct mpt_ioctl_command karg; - MPT_ADAPTER *ioc; - int iocnum; int rc; @@ -1796,14 +1714,7 @@ mptctl_mpt_command (unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } - - rc = mptctl_do_mpt_command (karg, &uarg->MF); + rc = mptctl_do_mpt_command (ioc, karg, &uarg->MF); return rc; } @@ -1821,9 +1732,8 @@ mptctl_mpt_command (unsigned long arg) * -EPERM if SCSI I/O and target is untagged */ static int -mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) +mptctl_do_mpt_command (MPT_ADAPTER *ioc, struct mpt_ioctl_command karg, void __user *mfPtr) { - MPT_ADAPTER *ioc; MPT_FRAME_HDR *mf = NULL; MPIHeader_t *hdr; char *psge; @@ -1832,7 +1742,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) dma_addr_t dma_addr_in; dma_addr_t dma_addr_out; int sgSize = 0; /* Num SG elements */ - int iocnum, flagsLength; + int flagsLength; int sz, rc = 0; int msgContext; u16 req_idx; @@ -1847,13 +1757,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) bufIn.kptr = bufOut.kptr = NULL; bufIn.len = bufOut.len = 0; - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } - spin_lock_irqsave(&ioc->taskmgmt_lock, flags); if (ioc->ioc_reset_in_progress) { spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); @@ -2418,17 +2321,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) * -ENOMEM if memory allocation error */ static int -mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) +mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size) { hp_host_info_t __user *uarg = (void __user *) arg; - MPT_ADAPTER *ioc; struct pci_dev *pdev; char *pbuf=NULL; dma_addr_t buf_dma; hp_host_info_t karg; CONFIGPARMS cfg; ConfigPageHeader_t hdr; - int iocnum; int rc, cim_rev; ToolboxIstwiReadWriteRequest_t *IstwiRWRequest; MPT_FRAME_HDR *mf = NULL; @@ -2452,12 +2353,6 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n", ioc->name)); @@ -2670,15 +2565,13 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) * -ENOMEM if memory allocation error */ static int -mptctl_hp_targetinfo(unsigned long arg) +mptctl_hp_targetinfo(MPT_ADAPTER *ioc, unsigned long arg) { hp_target_info_t __user *uarg = (void __user *) arg; SCSIDevicePage0_t *pg0_alloc; SCSIDevicePage3_t *pg3_alloc; - MPT_ADAPTER *ioc; MPT_SCSI_HOST *hd = NULL; hp_target_info_t karg; - int iocnum; int data_sz; dma_addr_t page_dma; CONFIGPARMS cfg; @@ -2692,12 +2585,6 @@ mptctl_hp_targetinfo(unsigned long arg) return -EFAULT; } - if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || - (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum); - return -ENODEV; - } if (karg.hdr.id >= MPT_MAX_FC_DEVICES) return -EINVAL; dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n", @@ -2865,7 +2752,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, kfw.fwlen = kfw32.fwlen; kfw.bufp = compat_ptr(kfw32.bufp); - ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); + ret = mptctl_do_fw_download(iocp, kfw.bufp, kfw.fwlen); mutex_unlock(&iocp->ioctl_cmds.mutex); @@ -2919,7 +2806,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd, /* Pass new structure to do_mpt_command */ - ret = mptctl_do_mpt_command (karg, &uarg->MF); + ret = mptctl_do_mpt_command (iocp, karg, &uarg->MF); mutex_unlock(&iocp->ioctl_cmds.mutex); diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index 8f873866ea609487e06beadbd48be1c3b2639116..86aab322da337366a3d680914fc5611e010ee475 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -142,7 +142,7 @@ static const struct mfd_cell da9062_devs[] = { .name = "da9062-watchdog", .num_resources = ARRAY_SIZE(da9062_wdt_resources), .resources = da9062_wdt_resources, - .of_compatible = "dlg,da9062-wdt", + .of_compatible = "dlg,da9062-watchdog", }, { .name = "da9062-thermal", diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 704e189ca162ab6991d9b548c7aa88d67cc7a020..95d0f2df0ad42d4107c5b9ee282d0fa365f6b6c2 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -729,6 +729,8 @@ static int dln2_probe(struct usb_interface *interface, const struct usb_device_id *usb_id) { struct usb_host_interface *hostif = interface->cur_altsetting; + struct usb_endpoint_descriptor *epin; + struct usb_endpoint_descriptor *epout; struct device *dev = &interface->dev; struct dln2_dev *dln2; int ret; @@ -738,12 +740,19 @@ static int dln2_probe(struct usb_interface *interface, hostif->desc.bNumEndpoints < 2) return -ENODEV; + epin = &hostif->endpoint[0].desc; + epout = &hostif->endpoint[1].desc; + if (!usb_endpoint_is_bulk_out(epout)) + return -ENODEV; + if (!usb_endpoint_is_bulk_in(epin)) + return -ENODEV; + dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL); if (!dln2) return -ENOMEM; - dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress; - dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress; + dln2->ep_out = epout->bEndpointAddress; + dln2->ep_in = epin->bEndpointAddress; dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface)); dln2->interface = interface; usb_set_intfdata(interface, dln2); diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 22dd8c055048c2400dd2bc6a0254bee872613293..71cecd7aeea0ccdbc624d355fba837462d740c1f 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -533,6 +533,7 @@ module_init(intel_lpss_init); static void __exit intel_lpss_exit(void) { + ida_destroy(&intel_lpss_devid_ida); debugfs_remove(intel_lpss_debugfs); } module_exit(intel_lpss_exit); diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index ee94080e1cbb704a6106b97d63fffe74e64a5daa..dd20c3e323520d6702507ee889485d88b58412a2 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -32,6 +32,7 @@ static bool rn5t618_volatile_reg(struct device *dev, unsigned int reg) case RN5T618_WATCHDOGCNT: case RN5T618_DCIRQ: case RN5T618_ILIMDATAH ... RN5T618_AIN0DATAL: + case RN5T618_ADCCNT3: case RN5T618_IR_ADC1 ... RN5T618_IR_ADC3: case RN5T618_IR_GPR: case RN5T618_IR_GPF: diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index cf5764efe634a9589914c5e4dcdb361dce1ffb74..c0b539002f46499dcb3e3d54e3a440f28398f6bb 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -282,6 +282,36 @@ config QCOM_COINCELL to maintain PMIC register and RTC state in the absence of external power. +config QCOM_XR_SMRTVWR_MISC + tristate "QTI XR SmartVwr Misc driver support" + default n + help + This driver supports the misc chips power up such as + USB bridge chip, Display Port bridgechip, MIPI switches etc. + This driver initializes gpios, turns on and off gpios, and + enables/disables LDOs that are part of XR Smart Viewer + reference device. + +config TUSB1064_XR_MISC + tristate "I2C driver for TI TUSB1064 chip for XR" + default n + help + This i2c driver allows applications to communicate with TI + TUSB1064 USB redriver chip. This redriver chip could be configured + to USB3.1 mode, Display Port 4lane and USB2.0 Mode, and Display Port + 2-lane and USB 3.1 modes. This driver allows the XR smart viewer to + put in any one of the above three modes. + +config VXR200_XR_MISC + tristate "I2C driver for Synaptics VXR7200 chip for XR" + default n + help + This i2c driver allows applications to communicate with Synaptics + VXR7200 DP2DSI bridge chip. This driver enables the display data + from Display Port and move the data to DSI data path. Thus enabling + the display data from DP to be shown on the display of the XR smart + viewer reference device. + config SGI_GRU tristate "SGI GRU driver" depends on X86_UV && SMP diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 6494a66dd3ca4e42cba40b30d8daa14799c72a6f..033157242f5d21a90e77d3a4569619789e9c8630 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -62,6 +62,10 @@ obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o +obj-$(CONFIG_QCOM_XR_SMRTVWR_MISC) += qcom-xr-smrtvwr-misc.o +obj-$(CONFIG_TUSB1064_XR_MISC) += tusb1064.o +obj-$(CONFIG_VXR200_XR_MISC) += vxr7200.o + lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c index f53e217e963f57acdc6d707d9893da7729c5bad0..494e263daa748d30b9a284be67c0fd3c518eebc3 100644 --- a/drivers/misc/altera-stapl/altera.c +++ b/drivers/misc/altera-stapl/altera.c @@ -2176,8 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size, key_ptr = &p[note_strings + get_unaligned_be32( &p[note_table + (8 * i)])]; - if ((strncasecmp(key, key_ptr, strlen(key_ptr)) == 0) && - (key != NULL)) { + if (key && !strncasecmp(key, key_ptr, strlen(key_ptr))) { status = 0; value_ptr = &p[note_strings + diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index eb29113e0bac2437f1714af1e4189b74fe992b6f..b11737f7bdca32124d75ff150d1f56cf50706486 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -419,10 +419,9 @@ int enclosure_remove_device(struct enclosure_device *edev, struct device *dev) cdev = &edev->component[i]; if (cdev->dev == dev) { enclosure_remove_links(cdev); - device_del(&cdev->cdev); put_device(dev); cdev->dev = NULL; - return device_add(&cdev->cdev); + return 0; } } return -ENODEV; diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c index b9f0710ffa6b0f80f256994c968d783242723243..4007adc666f377d0ef4ddbf4f8bbdcb773abfa39 100644 --- a/drivers/misc/mic/card/mic_x100.c +++ b/drivers/misc/mic/card/mic_x100.c @@ -249,6 +249,9 @@ static int __init mic_probe(struct platform_device *pdev) mdrv->dev = &pdev->dev; snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name); + /* FIXME: use dma_set_mask_and_coherent() and check result */ + dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + mdev->mmio.pa = MIC_X100_MMIO_BASE; mdev->mmio.len = MIC_X100_MMIO_LEN; mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE, @@ -294,18 +297,6 @@ static void mic_platform_shutdown(struct platform_device *pdev) mic_remove(pdev); } -static u64 mic_dma_mask = DMA_BIT_MASK(64); - -static struct platform_device mic_platform_dev = { - .name = mic_driver_name, - .id = 0, - .num_resources = 0, - .dev = { - .dma_mask = &mic_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(64), - }, -}; - static struct platform_driver __refdata mic_platform_driver = { .probe = mic_probe, .remove = mic_remove, @@ -315,6 +306,8 @@ static struct platform_driver __refdata mic_platform_driver = { }, }; +static struct platform_device *mic_platform_dev; + static int __init mic_init(void) { int ret; @@ -328,9 +321,12 @@ static int __init mic_init(void) request_module("mic_x100_dma"); mic_init_card_debugfs(); - ret = platform_device_register(&mic_platform_dev); + + mic_platform_dev = platform_device_register_simple(mic_driver_name, + 0, NULL, 0); + ret = PTR_ERR_OR_ZERO(mic_platform_dev); if (ret) { - pr_err("platform_device_register ret %d\n", ret); + pr_err("platform_device_register_full ret %d\n", ret); goto cleanup_debugfs; } ret = platform_driver_register(&mic_platform_driver); @@ -341,7 +337,7 @@ static int __init mic_init(void) return ret; device_unregister: - platform_device_unregister(&mic_platform_dev); + platform_device_unregister(mic_platform_dev); cleanup_debugfs: mic_exit_card_debugfs(); done: @@ -351,7 +347,7 @@ static int __init mic_init(void) static void __exit mic_exit(void) { platform_driver_unregister(&mic_platform_driver); - platform_device_unregister(&mic_platform_dev); + platform_device_unregister(mic_platform_dev); mic_exit_card_debugfs(); } diff --git a/drivers/misc/qcom-xr-smrtvwr-misc.c b/drivers/misc/qcom-xr-smrtvwr-misc.c new file mode 100644 index 0000000000000000000000000000000000000000..fc8796fbea90ec8664a524c70f9b3c586d85dc7e --- /dev/null +++ b/drivers/misc/qcom-xr-smrtvwr-misc.c @@ -0,0 +1,159 @@ +/* Copyright (c) 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 +#include +#include +#include +#include +#include +#include +#include +#include + +struct qcom_xr_smrtvwr { + struct device *dev; +}; + + +static int qcom_xr_smrtvwr_probe(struct platform_device *pdev) +{ + int rc; + struct regulator *reg1, *reg2, *reg3; + int dp3p3_en_gpio = 142; + int wcd_en_gpio = 93; + int switch_gpio = 112; + int rgb_tck_oe_en_gpio = 108; + + reg1 = devm_regulator_get(&pdev->dev, "pm660l_l6"); + if (!IS_ERR(reg1)) { + regulator_set_load(reg1, 600000); + rc = regulator_enable(reg1); + if (rc < 0) { + pr_err("%s pm660l_l6 failed\n", __func__); + goto reg1_fail; + } + } + + reg2 = devm_regulator_get(&pdev->dev, "pm660_l6"); + if (!IS_ERR(reg2)) { + regulator_set_load(reg2, 600000); + rc = regulator_enable(reg2); + if (rc < 0) { + pr_err("%s pm660_l6 failed\n", __func__); + goto reg2_fail; + } + } + + reg3 = devm_regulator_get(&pdev->dev, "pm660_l7"); + if (!IS_ERR(reg3)) { + regulator_set_load(reg3, 600000); + rc = regulator_enable(reg3); + if (rc < 0) { + pr_err("%s pm660_l7 failed\n", __func__); + goto reg3_fail; + } + } + + rc = gpio_request(dp3p3_en_gpio, "ti-dp-3v3-en-gpio"); + if (rc) { + pr_err("%s dp3p3_en gpio request failed\n", __func__); + goto gpio3p3_fail; + } + rc = gpio_direction_output(dp3p3_en_gpio, 0); + if (rc) { + pr_err("%s dp3p3_en_gpio direction failed\n", __func__); + goto gpio3p3_fail; + } + gpio_set_value(dp3p3_en_gpio, 1); + msleep(20); + + rc = gpio_request(wcd_en_gpio, "wcd9340_en_gpio"); + if (rc) { + pr_err("%s wcd9340_en_gpio request failed\n", __func__); + goto gpiowcd_fail; + } + rc = gpio_direction_output(wcd_en_gpio, 0); + if (rc) { + pr_err("%s wcd9340_en_gpio direction failed\n", __func__); + goto gpiowcd_fail; + } + gpio_set_value(wcd_en_gpio, 1); + msleep(20); + + rc = gpio_request(switch_gpio, "1p8_en_gpio"); + if (rc) { + pr_err("%s 1p8_switch_gpio request failed\n", __func__); + goto gpio_switch_fail; + } + rc = gpio_direction_output(switch_gpio, 0); + if (rc) { + pr_err("%s 1p8_switch_gpio direction failed\n", __func__); + goto gpio_switch_fail; + } + gpio_set_value(switch_gpio, 1); + msleep(20); + + rc = gpio_request(rgb_tck_oe_en_gpio, "rgb_tck_oe_en_gpio"); + if (rc) { + pr_err("%s rgb_tck_oe_en_gpio request failed\n", __func__); + goto gpio_oe_en_fail; + } + rc = gpio_direction_output(rgb_tck_oe_en_gpio, 0); + if (rc) { + pr_err("%s rgb_tck_oe_en_gpio direction failed\n", __func__); + goto gpio_oe_en_fail; + } + gpio_set_value(rgb_tck_oe_en_gpio, 0); + msleep(20); + + pr_debug("%s success\n", __func__); + return 0; + +gpio_oe_en_fail: + gpio_free(rgb_tck_oe_en_gpio); +gpio_switch_fail: + gpio_free(switch_gpio); +gpiowcd_fail: + gpio_free(wcd_en_gpio); +gpio3p3_fail: + gpio_free(dp3p3_en_gpio); +reg3_fail: + devm_regulator_put(reg3); +reg2_fail: + devm_regulator_put(reg2); +reg1_fail: + devm_regulator_put(reg1); + + return rc; +} + +static const struct of_device_id qcom_xr_smrtvwr_match_table[] = { + { .compatible = "qcom,xr-smrtvwr-misc", }, + {} +}; + +MODULE_DEVICE_TABLE(of, qcom_xr_smrtvwr_match_table); + +static struct platform_driver qcom_xr_smrtvwr_driver = { + .driver = { + .name = "qcom-xr-smrtvwr-misc", + .of_match_table = qcom_xr_smrtvwr_match_table, + }, + .probe = qcom_xr_smrtvwr_probe, +}; + +module_platform_driver(qcom_xr_smrtvwr_driver); + +MODULE_DESCRIPTION("QTI XR SMRTVWR MISC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index 6956f7e7d43921ec80f5e450a471429bc21f55fc..ca5f0102daef413cc0edea634ecbe15f77a2090e 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -70,7 +70,7 @@ xpc_get_rsvd_page_pa(int nasid) unsigned long rp_pa = nasid; /* seed with nasid */ size_t len = 0; size_t buf_len = 0; - void *buf = buf; + void *buf = NULL; void *buf_base = NULL; enum xp_retval (*get_partition_rsvd_page_pa) (void *, u64 *, unsigned long *, size_t *) = diff --git a/drivers/misc/tusb1064.c b/drivers/misc/tusb1064.c new file mode 100644 index 0000000000000000000000000000000000000000..234e21a3abdad2b6e16733d3ad3083e4fee8b107 --- /dev/null +++ b/drivers/misc/tusb1064.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct tusb1064 { + struct device *dev; + struct device_node *host_node; + u8 i2c_addr; + u32 dp_3v3_en; + struct i2c_client *i2c_client; + bool power_on; +}; + +static struct tusb1064 *pdata; +static bool standalone_mode; + +static int tusb1064_read(struct i2c_client *client, u8 reg, char *buf, u32 size) +{ + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = ®, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = size, + .buf = buf, + } + }; + + if (i2c_transfer(client->adapter, msg, 2) != 2) { + pr_err("%s i2c read failed\n", __func__); + return -EIO; + } + pr_debug("%s, reg:%x buf[0]:%x\n", __func__, reg, buf[0]); + + return 0; +} + +static int tusb1064_write(struct i2c_client *client, u8 reg, u8 val) +{ + u8 buf[2] = {reg, val}; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = buf, + }; + + pr_debug("%s, reg:%x, val:%x\n", __func__, reg, val); + if (i2c_transfer(client->adapter, &msg, 1) < 1) { + pr_err("i2c write failed\n"); + return -EIO; + } + return 0; +} + +void tusb1064_flip(bool flip) +{ + if (pdata) { + if (flip) { + pr_debug("%s flipping the switch\n", __func__); + /*AUXn->SBU2, AUXp->SBU1*/ + tusb1064_write(pdata->i2c_client, 0x13, 0x2F); + } else { + pr_debug("%s not flipping the switch\n", __func__); + /*AUXn->SBU2, AUXp->SBU1*/ + tusb1064_write(pdata->i2c_client, 0x13, 0x1F); + } + } +} +EXPORT_SYMBOL(tusb1064_flip); + +static int tusb1064_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + char buf[2]; + + if (!client || !client->dev.of_node) { + pr_err("%s invalid input\n", __func__); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + pr_err("%s device doesn't support I2C\n", __func__); + return -ENODEV; + } + + pdata = devm_kzalloc(&client->dev, + sizeof(struct tusb1064), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->dev = &client->dev; + pdata->i2c_client = client; + pr_debug("%s I2C address is %x\n", __func__, client->addr); + + i2c_set_clientdata(client, pdata); + dev_set_drvdata(&client->dev, pdata); + + tusb1064_read(pdata->i2c_client, 0x0A, buf, 2); + tusb1064_read(pdata->i2c_client, 0x13, buf, 2); + /*Enable 4-lane DP with FLip and enable EQ_OVERRIDe*/ + /*tusb1064_write(pdata, 0x0A, 0x13); */ + /*written usb sideEnable 4-lane DP with FLip and enable EQ_OVERRIDe */ + /*tusb1064_write(pdata, 0x0A, 0x12); */ + + if (standalone_mode) { + /*Enable 3.1 USB, no DP */ + if (tusb1064_write(pdata->i2c_client, 0x0A, 0x01) < 0) + goto fail; + } else { + /*Enable 4-lane DP with Flip and enable EQ_OVERRIDe */ + if (tusb1064_write(pdata->i2c_client, 0x0A, 0x02) < 0) + goto fail; + + pr_debug("%s setting SBU1 to AUXN, SBU2 to AUXP\n", __func__); + /*AUXn->SBU2, AUXp->SBU1 */ + if (tusb1064_write(pdata->i2c_client, 0x13, 0x1F) < 0) + goto fail; + //tusb1064_write(pdata, 0x13, 0x01);//AUXn->SBU1, AUXp->SBU2 + + /*Enable 4-lane DP */ + if (tusb1064_write(pdata->i2c_client, 0x10, 0x55) < 0) + goto fail; + /*Enable 4-lane DP */ + if (tusb1064_write(pdata->i2c_client, 0x11, 0x55) < 0) + goto fail; + //pr_err("setting SBU1 to AUXp and SBU2 to AUXN\n"); + //tusb1064_write(pdata, 0x13, 0x8F);//Enable 4-lane DP + } + tusb1064_read(pdata->i2c_client, 0x0A, buf, 2); + tusb1064_read(pdata->i2c_client, 0x13, buf, 2); + tusb1064_read(pdata->i2c_client, 0x10, buf, 2); + tusb1064_read(pdata->i2c_client, 0x11, buf, 2); + + pr_debug("%s probe successfully\n", __func__); + return 0; +fail: + devm_kfree(&client->dev, pdata); + return -EINVAL; +} + +static int tusb1064_remove(struct i2c_client *client) +{ + struct tusb1064 *pdata = i2c_get_clientdata(client); + + if (pdata) + devm_kfree(&client->dev, pdata); + return 0; +} + +static void tusb1064_shutdown(struct i2c_client *client) +{ + dev_info(&(client->dev), "shutdown"); +} + +static int tusb1064_suspend(struct device *dev, pm_message_t state) +{ + dev_info(dev, "suspend"); + return 0; +} + +static int tusb1064_resume(struct device *dev) +{ + dev_info(dev, "resume"); + return 0; +} + +static const struct i2c_device_id tusb1064_id_table[] = { + {"tusb1064", 0}, + {} +}; + +static struct i2c_driver tusb1064_i2c_driver = { + .probe = tusb1064_probe, + .remove = tusb1064_remove, + .shutdown = tusb1064_shutdown, + .driver = { + .name = "tusb1064", + .owner = THIS_MODULE, + .suspend = tusb1064_suspend, + .resume = tusb1064_resume, + }, + .id_table = tusb1064_id_table, +}; + +static int __init tusb1064_init(void) +{ + char *cmdline; + + cmdline = strnstr(boot_command_line, + "msm_drm.dsi_display0=dsi_sim_vid_display", + strlen(boot_command_line)); + if (cmdline) { + pr_debug("%s tethered mode cmdline:%s\n", + __func__, cmdline); + standalone_mode = false; + } else { + pr_debug("%s standalone mode cmdline:%s\n", + __func__, cmdline); + standalone_mode = true; + } + + return 0; +} + +device_initcall(tusb1064_init); +module_i2c_driver(tusb1064_i2c_driver); +MODULE_DEVICE_TABLE(i2c, tusb1064_id_table); +MODULE_DESCRIPTION("TUSB1064 USB Bridge"); diff --git a/drivers/misc/vxr7200.c b/drivers/misc/vxr7200.c new file mode 100644 index 0000000000000000000000000000000000000000..ad1c82ce4ea6ff17003743242718f199e73711d5 --- /dev/null +++ b/drivers/misc/vxr7200.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct vxr7200 { + struct device *dev; + struct device_node *host_node; + + u8 i2c_addr; + int irq; + u32 vxr_3v3_en; + u32 led_5v_en; + u32 led_drive_en1; + u32 led_drive_en2; + u32 display_1v8_en; + u32 mipi_sw_1v8_en; + u32 display_res1; + u32 selab_gpio; + u32 oenab_gpio; + bool gpioInit; + + struct i2c_client *i2c_client; + + struct regulator *vddio; + struct regulator *lab; + struct regulator *ibb; + + bool power_on; +}; + +static bool dsi_way; + +static int vxr7200_read(struct vxr7200 *pdata, u8 *reg, u8 *buf, u32 size) +{ + struct i2c_client *client = pdata->i2c_client; + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 4, + .buf = reg, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = size, + .buf = buf, + } + }; + + if (i2c_transfer(client->adapter, msg, 2) != 2) { + pr_err("i2c read failed\n"); + return -EIO; + } + + return 0; +} + +static int turnGpio(struct vxr7200 *pdata, int gpio, char *name, bool on) +{ + int ret = -1; + + pr_info("%s vxr7200 gpio:%d, name:%s, on:%d\n", __func__, gpio, + name, on); + if (!pdata->gpioInit) { + ret = gpio_request(gpio, name); + if (ret) { + pr_err("vxr7200 %s gpio request failed\n", name); + goto error; + } + } + if (on) { + ret = gpio_direction_output(gpio, 0); + if (ret) { + pr_err("vxr7200 gpio direction failed\n"); + goto error; + } + gpio_set_value(gpio, 1); + pr_debug("%s vxr7200 gpio:%d set to high\n", __func__, gpio); + } else { + ret = gpio_direction_output(gpio, 1); + if (ret) { + pr_err("vxr7200 gpio direction failed\n"); + goto error; + } + gpio_set_value(gpio, 0); + pr_debug("%s vxr7200 gpio:%d set to low\n", __func__, gpio); + } + return 0; +error: + return -EINVAL; +} + +static void vxr7200_set_gpios(struct vxr7200 *pdata, bool turnOn) +{ + int rc; + + pr_debug("%s, turnOn:%d\n", __func__, turnOn); + if (pdata) { + rc = turnGpio(pdata, pdata->vxr_3v3_en, "vxr_3v3_en", turnOn); + if (rc) + goto gpio1Fail; + rc = turnGpio(pdata, pdata->led_5v_en, "led_5v_en", turnOn); + if (rc) + goto gpio2Fail; + rc = turnGpio(pdata, pdata->led_drive_en1, + "led_drive_en1", turnOn); + if (rc) + goto gpio3Fail; + rc = turnGpio(pdata, pdata->led_drive_en2, + "led_drive_en2", turnOn); + if (rc) + goto gpio4Fail; + rc = turnGpio(pdata, pdata->display_1v8_en, + "disp_1v8_en", turnOn); + if (rc) + goto gpio5Fail; + pdata->mipi_sw_1v8_en += 1100; + rc = turnGpio(pdata, pdata->mipi_sw_1v8_en, + "mipi_sw1v8_en", turnOn); + if (rc) + goto gpio6Fail; + rc = turnGpio(pdata, pdata->display_res1, + "display_res1", turnOn); + if (rc) + goto gpio7Fail; + } + +gpio7Fail: + gpio_free(pdata->display_res1); +gpio6Fail: + gpio_free(pdata->mipi_sw_1v8_en); +gpio5Fail: + gpio_free(pdata->display_1v8_en); +gpio4Fail: + gpio_free(pdata->led_drive_en2); +gpio3Fail: + gpio_free(pdata->led_drive_en1); +gpio2Fail: + gpio_free(pdata->led_5v_en); +gpio1Fail: + gpio_free(pdata->vxr_3v3_en); +} + +static void vxr7200_free_gpios(struct vxr7200 *pdata) +{ + if (pdata) { + gpio_free(pdata->vxr_3v3_en); + gpio_free(pdata->led_5v_en); + gpio_free(pdata->led_drive_en1); + gpio_free(pdata->led_drive_en2); + gpio_free(pdata->display_1v8_en); + gpio_free(pdata->mipi_sw_1v8_en); + gpio_free(pdata->display_res1); + } +} + + +static int vxr7200_parse_dt(struct device *dev, + struct vxr7200 *pdata) +{ + struct device_node *np = dev->of_node; + int rc = 0; + + pdata->vxr_3v3_en = + of_get_named_gpio(np, "qcom,vxr_3v3_en", 0); + if (!gpio_is_valid(pdata->vxr_3v3_en)) { + pr_err("vxr_3v3_en gpio not specified\n"); + rc = -EINVAL; + } + + pdata->led_5v_en = + of_get_named_gpio(np, "qcom,led-5v-en-gpio", 0); + if (!gpio_is_valid(pdata->led_5v_en)) { + pr_err("led_5v_en gpio not specified\n"); + rc = -EINVAL; + } + + pdata->led_drive_en1 = + of_get_named_gpio(np, "qcom,led-driver-en1-gpio", 0); + if (!gpio_is_valid(pdata->led_drive_en1)) { + pr_err("led_drive_en1 gpio not specified\n"); + rc = -EINVAL; + } + + pdata->led_drive_en2 = + of_get_named_gpio(np, "qcom,led-driver-en2-gpio", 0); + if (!gpio_is_valid(pdata->led_drive_en2)) { + pr_err("led_drive_en2 gpio not specified\n"); + rc = -EINVAL; + } + + pdata->display_1v8_en = + of_get_named_gpio(np, "qcom,1p8-en-gpio", 0); + if (!gpio_is_valid(pdata->display_1v8_en)) { + pr_err("display_1v8_en gpio not specified\n"); + rc = -EINVAL; + } + + pdata->mipi_sw_1v8_en = + of_get_named_gpio(np, "qcom,switch-power-gpio", 0); + if (!gpio_is_valid(pdata->mipi_sw_1v8_en)) { + pr_err("mipi_sw_1v8_en gpio not specified\n"); + rc = -EINVAL; + } + + pdata->display_res1 = + of_get_named_gpio(np, "qcom,platform-reset-gpio", 0); + if (!gpio_is_valid(pdata->display_res1)) { + pr_err("display_res1 gpio not specified\n"); + rc = -EINVAL; + } + + if (!rc) + vxr7200_set_gpios(pdata, true); + + pdata->selab_gpio = of_get_named_gpio(np, "qcom,selab-gpio", 0); + if (!gpio_is_valid(pdata->selab_gpio)) { + pr_err("selab_gpio gpio not specified\n"); + rc = -EINVAL; + goto gpio_selab_fail; + } else + turnGpio(pdata, pdata->selab_gpio, "selab_gpio", 0); + + pdata->oenab_gpio = of_get_named_gpio(np, "qcom,oenab-gpio", 0); + if (!gpio_is_valid(pdata->oenab_gpio)) { + pr_err("oenab_gpio gpio not specified\n"); + rc = -EINVAL; + goto gpio_oenab_fail; + } else + turnGpio(pdata, pdata->oenab_gpio, "oenab_gpio", 0); + + if (!pdata->gpioInit) + pdata->gpioInit = true; + + return rc; + +gpio_oenab_fail: + gpio_free(pdata->oenab_gpio); +gpio_selab_fail: + gpio_free(pdata->selab_gpio); + vxr7200_free_gpios(pdata); + return rc; +} + +static void vxr7200_display_pwr_enable_vregs(struct vxr7200 *pdata) +{ + int rc = 0; + + pdata->vddio = devm_regulator_get(pdata->dev, "pm660_l11"); + rc = PTR_RET(pdata->vddio); + if (rc) { + pr_err("Failed to get pm660_l11 regulator %s\n", __func__); + goto vddio_fail; + } + rc = regulator_set_load(pdata->vddio, 62000); + if (rc < 0) { + pr_err("Load setting failed for vddio %s\n", __func__); + goto vddio_fail; + } + rc = regulator_set_voltage(pdata->vddio, 1800000, 1800000); + if (rc) { + pr_err("Set voltage(vddio) fail, rc=%d %s\n", rc, __func__); + goto vddio_fail; + } + rc = regulator_enable(pdata->vddio); + if (rc) { + pr_err("enable failed for vddio, rc=%d %s\n", rc, __func__); + goto vddio_fail; + } + + pdata->lab = devm_regulator_get(pdata->dev, "lcdb_ldo"); + rc = PTR_RET(pdata->lab); + if (rc) { + pr_err("Failed to get lcdb_ldo_vreg regulator %s\n", __func__); + goto lab_fail; + } + rc = regulator_set_load(pdata->lab, 100000); + if (rc < 0) { + pr_err("Load Setting failed for lab %s\n", __func__); + goto lab_fail; + } + rc = regulator_set_voltage(pdata->lab, 4600000, 6000000); + if (rc) { + pr_err("Set voltage(lab) fail, rc=%d %s\n", rc, __func__); + goto lab_fail; + } + rc = regulator_enable(pdata->lab); + if (rc) { + pr_err("enable failed for lab, rc=%d %s\n", rc, __func__); + goto lab_fail; + } + + pdata->ibb = devm_regulator_get(pdata->dev, "lcdb_ncp"); + rc = PTR_RET(pdata->ibb); + if (rc) { + pr_err("Failed to get lcdb_ncp_vreg regulator %s\n", __func__); + goto ibb_fail; + } + rc = regulator_set_load(pdata->ibb, 100000); + if (rc < 0) { + pr_err("Load Setting failed for ibb %s\n", __func__); + goto ibb_fail; + } + rc = regulator_set_voltage(pdata->ibb, 4600000, 6000000); + if (rc) { + pr_err("Set voltage(ibb) fail, rc=%d %s\n", rc, __func__); + goto ibb_fail; + } + rc = regulator_enable(pdata->ibb); + if (rc) { + pr_err("enable failed for ibb, rc=%d %s\n", rc, __func__); + goto ibb_fail; + } + + return; + +ibb_fail: + devm_regulator_put(pdata->ibb); + (void)regulator_set_load(pdata->ibb, 100); + (void)regulator_set_voltage(pdata->ibb, 0, 6000000); + +lab_fail: + (void)regulator_set_voltage(pdata->lab, 0, 6000000); + (void)regulator_set_load(pdata->lab, 100); + devm_regulator_put(pdata->lab); + +vddio_fail: + (void)regulator_set_load(pdata->vddio, 100); + (void)regulator_set_voltage(pdata->vddio, 0, 1800000); + devm_regulator_put(pdata->vddio); +} + +static int vxr7200_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int rc; + struct vxr7200 *pdata; + u8 reg[4] = {0x00, 0x20, 0x01, 0x60}; + u8 buf[4] = {0x00, 0x0, 0x0, 0x0}; + + if (!client || !client->dev.of_node) { + pr_err("%s invalid input\n", __func__); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + pr_err("%s device doesn't support I2C\n", __func__); + return -ENODEV; + } + + if (dsi_way) + return -EINVAL; + + pdata = devm_kzalloc(&client->dev, + sizeof(struct vxr7200), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->gpioInit = false; + + rc = vxr7200_parse_dt(&client->dev, pdata); + if (rc) { + pr_err("%s failed to parse device tree\n", __func__); + goto err_dt_parse; + } + pdata->dev = &client->dev; + pdata->i2c_client = client; + + vxr7200_display_pwr_enable_vregs(pdata); + + i2c_set_clientdata(client, pdata); + dev_set_drvdata(&client->dev, pdata); + + //vxr7200_write(pdata, 0x0A, 0x02);//Enable 4-lane DP + vxr7200_read(pdata, reg, buf, 4);//Enable 4-lane DP + +err_dt_parse: + devm_kfree(&client->dev, pdata); + + return rc; +} + +static int vxr7200_remove(struct i2c_client *client) +{ + struct vxr7200 *pdata = i2c_get_clientdata(client); + + if (pdata) + devm_kfree(&client->dev, pdata); + return 0; +} + + +static void vxr7200_shutdown(struct i2c_client *client) +{ + dev_info(&(client->dev), "shutdown"); +} + +static int vxr7200_pm_freeze(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct vxr7200 *pdata = i2c_get_clientdata(client); + + dev_info(dev, "freeze"); + vxr7200_set_gpios(pdata, false); + return 0; +} +static int vxr7200_pm_restore(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct vxr7200 *pdata = i2c_get_clientdata(client); + + dev_info(dev, "restore"); + vxr7200_set_gpios(pdata, true); + return 0; +} +static int vxr7200_pm_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct vxr7200 *pdata = i2c_get_clientdata(client); + + dev_info(dev, "suspend"); + vxr7200_set_gpios(pdata, false); + return 0; +} + +static int vxr7200_pm_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct vxr7200 *pdata = i2c_get_clientdata(client); + + dev_info(dev, "resume"); + vxr7200_set_gpios(pdata, true); + return 0; +} + +static const struct dev_pm_ops vxr7200_dev_pm_ops = { + .suspend = vxr7200_pm_suspend, + .resume = vxr7200_pm_resume, + .freeze = vxr7200_pm_freeze, + .restore = vxr7200_pm_restore, + .thaw = vxr7200_pm_restore, + .poweroff = vxr7200_pm_suspend, +}; + +static const struct i2c_device_id vxr7200_id_table[] = { + {"vxr7200", 0}, + {} +}; + +static struct i2c_driver vxr7200_i2c_driver = { + .probe = vxr7200_probe, + .remove = vxr7200_remove, + .shutdown = vxr7200_shutdown, + .driver = { + .name = "vxr7200", + .owner = THIS_MODULE, + .pm = &vxr7200_dev_pm_ops, + }, + .id_table = vxr7200_id_table, +}; + +static int __init vxr7200_init(void) +{ + char *cmdline; + + cmdline = strnstr(boot_command_line, + "msm_drm.dsi_display0=dsi_sim_vid_display", + strlen(boot_command_line)); + if (cmdline) { + pr_debug("%s DSI SIM mode, going to dp init cmdline:%s\n", + __func__, cmdline); + dsi_way = false; + } else { + pr_debug("%s DSI WAY, going to dsi init cmdline:%s\n", + __func__, cmdline); + dsi_way = true; + } + + return 0; + +} + +device_initcall(vxr7200_init); +module_i2c_driver(vxr7200_i2c_driver); +MODULE_DEVICE_TABLE(i2c, vxr7200_id_table); +MODULE_DESCRIPTION("VXR7200 DP2DSI Bridge"); diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index c2df68e958b3364dab3876986b756130219402ed..279d5da6e54b0f7642c7543935e635b73a81aa90 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1157,17 +1157,22 @@ static void mmc_spi_initsequence(struct mmc_spi_host *host) * SPI protocol. Another is that when chipselect is released while * the card returns BUSY status, the clock must issue several cycles * with chipselect high before the card will stop driving its output. + * + * SPI_CS_HIGH means "asserted" here. In some cases like when using + * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically + * inverted by gpiolib, so if we want to ascertain to drive it high + * we should toggle the default with an XOR as we do here. */ - host->spi->mode |= SPI_CS_HIGH; + host->spi->mode ^= SPI_CS_HIGH; if (spi_setup(host->spi) != 0) { /* Just warn; most cards work without it. */ dev_warn(&host->spi->dev, "can't change chip-select polarity\n"); - host->spi->mode &= ~SPI_CS_HIGH; + host->spi->mode ^= SPI_CS_HIGH; } else { mmc_spi_readbytes(host, 18); - host->spi->mode &= ~SPI_CS_HIGH; + host->spi->mode ^= SPI_CS_HIGH; if (spi_setup(host->spi) != 0) { /* Wot, we can't get the same setup we had before? */ dev_err(&host->spi->dev, diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 009242bcc7be5b966e634a6fb00d4ee8fa9dd65b..65c0742356b99d52154de4cba808b8d76d7f3a49 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1700,6 +1700,36 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) if (mmc_pdata(host)->init_card) mmc_pdata(host)->init_card(card); + else if (card->type == MMC_TYPE_SDIO || + card->type == MMC_TYPE_SD_COMBO) { + struct device_node *np = mmc_dev(mmc)->of_node; + + /* + * REVISIT: should be moved to sdio core and made more + * general e.g. by expanding the DT bindings of child nodes + * to provide a mechanism to provide this information: + * Documentation/devicetree/bindings/mmc/mmc-card.txt + */ + + np = of_get_compatible_child(np, "ti,wl1251"); + if (np) { + /* + * We have TI wl1251 attached to MMC3. Pass this + * information to the SDIO core because it can't be + * probed by normal methods. + */ + + dev_info(host->dev, "found wl1251\n"); + card->quirks |= MMC_QUIRK_NONSTD_SDIO; + card->cccr.wide_bus = 1; + card->cis.vendor = 0x104c; + card->cis.device = 0x9066; + card->cis.blksize = 512; + card->cis.max_dtr = 24000000; + card->ocr = 0x80; + of_node_put(np); + } + } } static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 159f6f64c68e78fb11cd86c9472df97aae9e6ad8..ed6473731b458af3fd1a83fee78c69205fa37562 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -90,7 +90,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ; sdhci_get_of_property(pdev); - mmc_of_parse(host->mmc); + res = mmc_of_parse(host->mmc); + if (res) + goto err; /* * Supply the existing CAPS, but clear the UHS modes. This diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 6f11cd95bb5fb50a81c7ac5c4df33f4d969eea71..225ecab7eccc1b0b259ad364ec27a4be46b2fe90 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -637,8 +637,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { - host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST; - host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; + host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; + host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; } if (of_device_is_compatible(np, "fsl,p5040-esdhc") || diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 088a3ae0dff063225e2e695c2c71249626828960..ec19490452951fcea7895dc41287f889fc930c9f 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -174,7 +174,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50; if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104) misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104; - if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50) + if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50) clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE; } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 50f6b00deb021d4c8a0e9f4a889d529c02f0ec9b..1ef8bf9f4b1a81bb445434908fa0ec65a03506b5 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1929,9 +1929,7 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) ctrl_2 |= SDHCI_CTRL_UHS_SDR104; else if (timing == MMC_TIMING_UHS_SDR12) ctrl_2 |= SDHCI_CTRL_UHS_SDR12; - else if (timing == MMC_TIMING_SD_HS || - timing == MMC_TIMING_MMC_HS || - timing == MMC_TIMING_UHS_SDR25) + else if (timing == MMC_TIMING_UHS_SDR25) ctrl_2 |= SDHCI_CTRL_UHS_SDR25; else if (timing == MMC_TIMING_UHS_SDR50) ctrl_2 |= SDHCI_CTRL_UHS_SDR50; @@ -2580,7 +2578,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) spin_lock_irqsave(&host->lock, flags); if (!host->tuning_done) { - pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); + pr_debug(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_EXEC_TUNING; @@ -4220,11 +4218,13 @@ int sdhci_setup_host(struct sdhci_host *host) if (host->ops->get_min_clock) mmc->f_min = host->ops->get_min_clock(host); else if (host->version >= SDHCI_SPEC_300) { - if (host->clk_mul) { - mmc->f_min = (host->max_clk * host->clk_mul) / 1024; + if (host->clk_mul) max_clk = host->max_clk * host->clk_mul; - } else - mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; + /* + * Divided Clock Mode minimum clock rate is always less than + * Programmable Clock Mode minimum clock rate. + */ + mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 0fc1f73b0d2378e720dff9491686cc8bc9c9e2d3..3e025766181b9ae8100fdfa555f7ff1e7589d489 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -1076,7 +1076,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host, tmio_mmc_ops.start_signal_voltage_switch = _host->start_signal_voltage_switch; mmc->ops = &tmio_mmc_ops; - mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; + mmc->caps |= MMC_CAP_ERASE | MMC_CAP_4_BIT_DATA | pdata->capabilities; mmc->caps2 |= pdata->capabilities2; mmc->max_segs = 32; mmc->max_blk_size = 512; diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index dd506987653703624c1a37f9d98ce93ff0690113..4a7da5fde7148deca9e12253f8dd3ea0879f97f5 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c @@ -595,6 +595,26 @@ static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, return 0; } +/* + * The purpose of this function is to ensure a memcpy_toio() with byte writes + * only. Its structure is inspired from the ARM implementation of _memcpy_toio() + * which also does single byte writes but cannot be used here as this is just an + * implementation detail and not part of the API. Not mentioning the comment + * stating that _memcpy_toio() should be optimized. + */ +static void spear_smi_memcpy_toio_b(volatile void __iomem *dest, + const void *src, size_t len) +{ + const unsigned char *from = src; + + while (len) { + len--; + writeb(*from, dest); + from++; + dest++; + } +} + static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank, void __iomem *dest, const void *src, size_t len) { @@ -617,7 +637,23 @@ static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank, ctrlreg1 = readl(dev->io_base + SMI_CR1); writel((ctrlreg1 | WB_MODE) & ~SW_MODE, dev->io_base + SMI_CR1); - memcpy_toio(dest, src, len); + /* + * In Write Burst mode (WB_MODE), the specs states that writes must be: + * - incremental + * - of the same size + * The ARM implementation of memcpy_toio() will optimize the number of + * I/O by using as much 4-byte writes as possible, surrounded by + * 2-byte/1-byte access if: + * - the destination is not 4-byte aligned + * - the length is not a multiple of 4-byte. + * Avoid this alternance of write access size by using our own 'byte + * access' helper if at least one of the two conditions above is true. + */ + if (IS_ALIGNED(len, sizeof(u32)) && + IS_ALIGNED((uintptr_t)dest, sizeof(u32))) + memcpy_toio(dest, src, len); + else + spear_smi_memcpy_toio_b(dest, src, len); writel(ctrlreg1, dev->io_base + SMI_CR1); diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c42523b7d5eddb63cd6637a6fd9834ec02b2b085..63a9b53a65ed0596ecfb005af6778ab1e05f6140 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1046,7 +1046,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); - int ret; + ssize_t ret; dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index b44c8d348e78ec0b19c884178e54c83a0967dc90..e7b177c61642fda2f975d46f754125cca1dc15ed 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -73,7 +73,7 @@ static int self_check_seen(struct ubi_device *ubi, unsigned long *seen) return 0; for (pnum = 0; pnum < ubi->peb_count; pnum++) { - if (test_bit(pnum, seen) && ubi->lookuptbl[pnum]) { + if (!test_bit(pnum, seen) && ubi->lookuptbl[pnum]) { ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum); ret = -EINVAL; } @@ -1127,7 +1127,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, struct rb_node *tmp_rb; int ret, i, j, free_peb_count, used_peb_count, vol_count; int scrub_peb_count, erase_peb_count; - unsigned long *seen_pebs = NULL; + unsigned long *seen_pebs; fm_raw = ubi->fm_buf; memset(ubi->fm_buf, 0, ubi->fm_size); @@ -1141,7 +1141,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, dvbuf = new_fm_vbuf(ubi, UBI_FM_DATA_VOLUME_ID); if (!dvbuf) { ret = -ENOMEM; - goto out_kfree; + goto out_free_avbuf; } avhdr = ubi_get_vid_hdr(avbuf); @@ -1150,7 +1150,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, seen_pebs = init_seen(ubi); if (IS_ERR(seen_pebs)) { ret = PTR_ERR(seen_pebs); - goto out_kfree; + goto out_free_dvbuf; } spin_lock(&ubi->volumes_lock); @@ -1318,7 +1318,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avbuf); if (ret) { ubi_err(ubi, "unable to write vid_hdr to fastmap SB!"); - goto out_kfree; + goto out_free_seen; } for (i = 0; i < new_fm->used_blocks; i++) { @@ -1340,7 +1340,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, if (ret) { ubi_err(ubi, "unable to write vid_hdr to PEB %i!", new_fm->e[i]->pnum); - goto out_kfree; + goto out_free_seen; } } @@ -1350,7 +1350,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, if (ret) { ubi_err(ubi, "unable to write fastmap to PEB %i!", new_fm->e[i]->pnum); - goto out_kfree; + goto out_free_seen; } } @@ -1360,10 +1360,13 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ret = self_check_seen(ubi, seen_pebs); dbg_bld("fastmap written!"); -out_kfree: - ubi_free_vid_buf(avbuf); - ubi_free_vid_buf(dvbuf); +out_free_seen: free_seen(seen_pebs); +out_free_dvbuf: + ubi_free_vid_buf(dvbuf); +out_free_avbuf: + ubi_free_vid_buf(avbuf); + out: return ret; } diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 91d8a48e53c368dded18dd01b0a5cf8a9fd2f0b9..1f8fbd7776fb4da34a7fd938f0a43f9ddeabdec9 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -71,11 +71,6 @@ struct arp_pkt { }; #pragma pack() -static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb) -{ - return (struct arp_pkt *)skb_network_header(skb); -} - /* Forward declaration */ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], bool strict_match); @@ -574,10 +569,11 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip) spin_unlock(&bond->mode_lock); } -static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond) +static struct slave *rlb_choose_channel(struct sk_buff *skb, + struct bonding *bond, + const struct arp_pkt *arp) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - struct arp_pkt *arp = arp_pkt(skb); struct slave *assigned_slave, *curr_active_slave; struct rlb_client_info *client_info; u32 hash_index = 0; @@ -674,8 +670,12 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon */ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) { - struct arp_pkt *arp = arp_pkt(skb); struct slave *tx_slave = NULL; + struct arp_pkt *arp; + + if (!pskb_network_may_pull(skb, sizeof(*arp))) + return NULL; + arp = (struct arp_pkt *)skb_network_header(skb); /* Don't modify or load balance ARPs that do not originate locally * (e.g.,arrive via a bridge). @@ -685,7 +685,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) if (arp->op_code == htons(ARPOP_REPLY)) { /* the arp must be sent on the selected rx channel */ - tx_slave = rlb_choose_channel(skb, bond); + tx_slave = rlb_choose_channel(skb, bond, arp); if (tx_slave) ether_addr_copy(arp->mac_src, tx_slave->dev->dev_addr); netdev_dbg(bond->dev, "Server sent ARP Reply packet\n"); @@ -695,7 +695,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) * When the arp reply is received the entry will be updated * with the correct unicast address of the client. */ - rlb_choose_channel(skb, bond); + rlb_choose_channel(skb, bond, arp); /* The ARP reply packets must be delayed so that * they can cancel out the influence of the ARP request. @@ -1371,26 +1371,31 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) bool do_tx_balance = true; u32 hash_index = 0; const u8 *hash_start = NULL; - struct ipv6hdr *ip6hdr; skb_reset_mac_header(skb); eth_data = eth_hdr(skb); switch (ntohs(skb->protocol)) { case ETH_P_IP: { - const struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph; if (ether_addr_equal_64bits(eth_data->h_dest, mac_bcast) || - (iph->daddr == ip_bcast) || - (iph->protocol == IPPROTO_IGMP)) { + (!pskb_network_may_pull(skb, sizeof(*iph)))) { + do_tx_balance = false; + break; + } + iph = ip_hdr(skb); + if (iph->daddr == ip_bcast || iph->protocol == IPPROTO_IGMP) { do_tx_balance = false; break; } hash_start = (char *)&(iph->daddr); hash_size = sizeof(iph->daddr); - } break; - case ETH_P_IPV6: + } + case ETH_P_IPV6: { + const struct ipv6hdr *ip6hdr; + /* IPv6 doesn't really use broadcast mac address, but leave * that here just in case. */ @@ -1407,7 +1412,11 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) break; } - /* Additianally, DAD probes should not be tx-balanced as that + if (!pskb_network_may_pull(skb, sizeof(*ip6hdr))) { + do_tx_balance = false; + break; + } + /* Additionally, DAD probes should not be tx-balanced as that * will lead to false positives for duplicate addresses and * prevent address configuration from working. */ @@ -1417,17 +1426,26 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) break; } - hash_start = (char *)&(ipv6_hdr(skb)->daddr); - hash_size = sizeof(ipv6_hdr(skb)->daddr); + hash_start = (char *)&ip6hdr->daddr; + hash_size = sizeof(ip6hdr->daddr); break; - case ETH_P_IPX: - if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) { + } + case ETH_P_IPX: { + const struct ipxhdr *ipxhdr; + + if (pskb_network_may_pull(skb, sizeof(*ipxhdr))) { + do_tx_balance = false; + break; + } + ipxhdr = (struct ipxhdr *)skb_network_header(skb); + + if (ipxhdr->ipx_checksum != IPX_NO_CHECKSUM) { /* something is wrong with this packet */ do_tx_balance = false; break; } - if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) { + if (ipxhdr->ipx_type != IPX_TYPE_NCP) { /* The only protocol worth balancing in * this family since it has an "ARP" like * mechanism @@ -1436,9 +1454,11 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) break; } + eth_data = eth_hdr(skb); hash_start = (char *)eth_data->h_dest; hash_size = ETH_ALEN; break; + } case ETH_P_ARP: do_tx_balance = false; if (bond_info->rlb_enabled) diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index acb708fc14636e76959c068ec249682ac64564de..0a7d818a06f3f11f6fc3139ce6fd4aad145dc068 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -392,13 +392,12 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct mscan_regs __iomem *regs = priv->reg_base; struct net_device_stats *stats = &dev->stats; - int npackets = 0; - int ret = 1; + int work_done = 0; struct sk_buff *skb; struct can_frame *frame; u8 canrflg; - while (npackets < quota) { + while (work_done < quota) { canrflg = in_8(®s->canrflg); if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF))) break; @@ -419,18 +418,18 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) stats->rx_packets++; stats->rx_bytes += frame->can_dlc; - npackets++; + work_done++; netif_receive_skb(skb); } - if (!(in_8(®s->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) { - napi_complete(&priv->napi); - clear_bit(F_RX_PROGRESS, &priv->flags); - if (priv->can.state < CAN_STATE_BUS_OFF) - out_8(®s->canrier, priv->shadow_canrier); - ret = 0; + if (work_done < quota) { + if (likely(napi_complete_done(&priv->napi, work_done))) { + clear_bit(F_RX_PROGRESS, &priv->flags); + if (priv->can.state < CAN_STATE_BUS_OFF) + out_8(®s->canrier, priv->shadow_canrier); + } } - return ret; + return work_done; } static irqreturn_t mscan_isr(int irq, void *dev_id) diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index a2c4048c07bec8e7640c836c71848b427a314f52..453a2ea7895b19d8cc6ebbe9ad94c17297e3226e 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -344,9 +344,16 @@ static void slcan_transmit(struct work_struct *work) */ static void slcan_write_wakeup(struct tty_struct *tty) { - struct slcan *sl = tty->disc_data; + struct slcan *sl; + + rcu_read_lock(); + sl = rcu_dereference(tty->disc_data); + if (!sl) + goto out; schedule_work(&sl->tx_work); +out: + rcu_read_unlock(); } /* Send a can_frame to a TTY queue. */ @@ -613,6 +620,7 @@ static int slcan_open(struct tty_struct *tty) sl->tty = NULL; tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); + slc_free_netdev(sl->dev); free_netdev(sl->dev); err_exit: @@ -639,10 +647,11 @@ static void slcan_close(struct tty_struct *tty) return; spin_lock_bh(&sl->lock); - tty->disc_data = NULL; + rcu_assign_pointer(tty->disc_data, NULL); sl->tty = NULL; spin_unlock_bh(&sl->lock); + synchronize_rcu(); flush_work(&sl->tx_work); /* Flush network side */ diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index fdc61883a61533b0efff5419d5924197576aaea3..d8c104850f3682231d951bc3805ffcb87bc3fdb7 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -46,8 +46,8 @@ #define DRIVER_MODE_AMB 2 #define QUERY_FIRMWARE_TIMEOUT_MS 300 #define EUPGRADE 140 -#define TIME_OFFSET_MAX_THD 5 -#define TIME_OFFSET_MIN_THD -5 +#define TIME_OFFSET_MAX_THD 30 +#define TIME_OFFSET_MIN_THD -30 struct qti_can { struct net_device **netdev; @@ -326,7 +326,7 @@ static void qti_can_receive_frame(struct qti_can *priv_data, if (ts_offset_corrected > 0) { if (disp_disc_cntr == 1) { dev_info(&priv_data->spidev->dev, - "No of buff frames discarded is %lld\n", + "No of buff frames discarded is %d\n", buff_frames_disc_cntr); disp_disc_cntr = 0; } diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 014b9ae3dc17aebf47e9d3fddc032c542cf0b73e..a65203e6ea5f4a1f54d0f29790722f884d8a4d19 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -927,7 +927,7 @@ static int gs_usb_probe(struct usb_interface *intf, GS_USB_BREQ_HOST_FORMAT, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 1, - intf->altsetting[0].desc.bInterfaceNumber, + intf->cur_altsetting->desc.bInterfaceNumber, hconf, sizeof(*hconf), 1000); @@ -950,7 +950,7 @@ static int gs_usb_probe(struct usb_interface *intf, GS_USB_BREQ_DEVICE_CONFIG, USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 1, - intf->altsetting[0].desc.bInterfaceNumber, + intf->cur_altsetting->desc.bInterfaceNumber, dconf, sizeof(*dconf), 1000); diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index ebfbaf8597f407d248e405bf6d7010f9ed5c243e..3bbe85aae49bb1dfd4c862982f7b9af7665697ff 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -460,6 +460,18 @@ qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode) qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); break; + case PHY_INTERFACE_MODE_RGMII_ID: + /* RGMII_ID needs internal delay. This is enabled through + * PORT5_PAD_CTRL for all ports, rather than individual port + * registers + */ + qca8k_write(priv, reg, + QCA8K_PORT_PAD_RGMII_EN | + QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) | + QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY)); + qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, + QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); + break; case PHY_INTERFACE_MODE_SGMII: qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); break; diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h index 9c22bc3210cdf58236673bca717e3594feea8efa..db95168ca111d8d0a667996e538ceff585093c69 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -40,6 +40,7 @@ ((0x8 + (x & 0x3)) << 22) #define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) \ ((0x10 + (x & 0x3)) << 20) +#define QCA8K_MAX_DELAY 3 #define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) #define QCA8K_PORT_PAD_SGMII_EN BIT(7) #define QCA8K_REG_MODULE_EN 0x030 diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index bcd993140f841bb9956b355f0cfb8aa72608c2df..905911f78693a9ec1f104655657eb3b01be5fb29 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -199,6 +199,11 @@ static inline void comp_ctxt_release(struct ena_com_admin_queue *queue, static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *queue, u16 command_id, bool capture) { + if (unlikely(!queue->comp_ctx)) { + pr_err("Completion context is NULL\n"); + return NULL; + } + if (unlikely(command_id >= queue->q_depth)) { pr_err("command id is larger than the queue size. cmd_id: %u queue size %d\n", command_id, queue->q_depth); @@ -839,6 +844,24 @@ static int ena_com_get_feature(struct ena_com_dev *ena_dev, 0); } +static void ena_com_hash_key_fill_default_key(struct ena_com_dev *ena_dev) +{ + struct ena_admin_feature_rss_flow_hash_control *hash_key = + (ena_dev->rss).hash_key; + + netdev_rss_key_fill(&hash_key->key, sizeof(hash_key->key)); + /* The key is stored in the device in u32 array + * as well as the API requires the key to be passed in this + * format. Thus the size of our array should be divided by 4 + */ + hash_key->keys_num = sizeof(hash_key->key) / sizeof(u32); +} + +int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev) +{ + return ena_dev->rss.hash_func; +} + static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev) { struct ena_rss *rss = &ena_dev->rss; @@ -1967,7 +1990,7 @@ int ena_com_set_hash_function(struct ena_com_dev *ena_dev) if (unlikely(ret)) return ret; - if (get_resp.u.flow_hash_func.supported_func & (1 << rss->hash_func)) { + if (!(get_resp.u.flow_hash_func.supported_func & BIT(rss->hash_func))) { pr_err("Func hash %d isn't supported by device, abort\n", rss->hash_func); return -EPERM; @@ -2034,15 +2057,16 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev, switch (func) { case ENA_ADMIN_TOEPLITZ: - if (key_len > sizeof(hash_key->key)) { - pr_err("key len (%hu) is bigger than the max supported (%zu)\n", - key_len, sizeof(hash_key->key)); - return -EINVAL; + if (key) { + if (key_len != sizeof(hash_key->key)) { + pr_err("key len (%hu) doesn't equal the supported size (%zu)\n", + key_len, sizeof(hash_key->key)); + return -EINVAL; + } + memcpy(hash_key->key, key, key_len); + rss->hash_init_val = init_val; + hash_key->keys_num = key_len >> 2; } - - memcpy(hash_key->key, key, key_len); - rss->hash_init_val = init_val; - hash_key->keys_num = key_len >> 2; break; case ENA_ADMIN_CRC32: rss->hash_init_val = init_val; @@ -2052,6 +2076,7 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev, return -EINVAL; } + rss->hash_func = func; rc = ena_com_set_hash_function(ena_dev); /* Restore the old function */ @@ -2078,7 +2103,11 @@ int ena_com_get_hash_function(struct ena_com_dev *ena_dev, if (unlikely(rc)) return rc; - rss->hash_func = get_resp.u.flow_hash_func.selected_func; + /* ffs() returns 1 in case the lsb is set */ + rss->hash_func = ffs(get_resp.u.flow_hash_func.selected_func); + if (rss->hash_func) + rss->hash_func--; + if (func) *func = rss->hash_func; @@ -2365,6 +2394,8 @@ int ena_com_rss_init(struct ena_com_dev *ena_dev, u16 indr_tbl_log_size) if (unlikely(rc)) goto err_hash_key; + ena_com_hash_key_fill_default_key(ena_dev); + rc = ena_com_hash_ctrl_init(ena_dev); if (unlikely(rc)) goto err_hash_ctrl; diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h b/drivers/net/ethernet/amazon/ena/ena_com.h index 509d7b8e15ab9b96f067629455535052f68522d4..98b2ad20f599347bbf64a18a511745d13e9f29c6 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.h +++ b/drivers/net/ethernet/amazon/ena/ena_com.h @@ -41,6 +41,7 @@ #include #include #include +#include #include "ena_common_defs.h" #include "ena_admin_defs.h" @@ -622,6 +623,14 @@ int ena_com_rss_init(struct ena_com_dev *ena_dev, u16 log_size); */ void ena_com_rss_destroy(struct ena_com_dev *ena_dev); +/* ena_com_get_current_hash_function - Get RSS hash function + * @ena_dev: ENA communication layer struct + * + * Return the current hash function. + * @return: 0 or one of the ena_admin_hash_functions values. + */ +int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev); + /* ena_com_fill_hash_function - Fill RSS hash function * @ena_dev: ENA communication layer struct * @func: The hash function (Toeplitz or crc) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 67b2338f8fb34100df983fc11727d4e661548b24..0ef0a7b75751c1c156c96c1b9a230ca6fb292ee9 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -651,6 +651,28 @@ static u32 ena_get_rxfh_key_size(struct net_device *netdev) return ENA_HASH_KEY_SIZE; } +static int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir) +{ + struct ena_com_dev *ena_dev = adapter->ena_dev; + int i, rc; + + if (!indir) + return 0; + + rc = ena_com_indirect_table_get(ena_dev, indir); + if (rc) + return rc; + + /* Our internal representation of the indices is: even indices + * for Tx and uneven indices for Rx. We need to convert the Rx + * indices to be consecutive + */ + for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) + indir[i] = ENA_IO_RXQ_IDX_TO_COMBINED_IDX(indir[i]); + + return rc; +} + static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) { @@ -659,11 +681,25 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 func; int rc; - rc = ena_com_indirect_table_get(adapter->ena_dev, indir); + rc = ena_indirection_table_get(adapter, indir); if (rc) return rc; + /* We call this function in order to check if the device + * supports getting/setting the hash function. + */ rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func, key); + + if (rc) { + if (rc == -EOPNOTSUPP) { + key = NULL; + hfunc = NULL; + rc = 0; + } + + return rc; + } + if (rc) return rc; @@ -697,8 +733,8 @@ static int ena_set_rxfh(struct net_device *netdev, const u32 *indir, if (indir) { for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) { rc = ena_com_indirect_table_fill_entry(ena_dev, - ENA_IO_RXQ_IDX(indir[i]), - i); + i, + ENA_IO_RXQ_IDX(indir[i])); if (unlikely(rc)) { netif_err(adapter, drv, netdev, "Cannot fill indirect table (index is too large)\n"); @@ -715,6 +751,9 @@ static int ena_set_rxfh(struct net_device *netdev, const u32 *indir, } switch (hfunc) { + case ETH_RSS_HASH_NO_CHANGE: + func = ena_com_get_current_hash_function(ena_dev); + break; case ETH_RSS_HASH_TOP: func = ENA_ADMIN_TOEPLITZ; break; @@ -819,6 +858,7 @@ static const struct ethtool_ops ena_ethtool_ops = { .get_channels = ena_get_channels, .get_tunable = ena_get_tunable, .set_tunable = ena_set_tunable, + .get_ts_info = ethtool_op_get_ts_info, }; void ena_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 0780900b37c72b8e9d5bd73f0eb82c1d705ef356..da21886609e3061a45c76f1434e49de19c77c3cb 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -1105,8 +1105,8 @@ static int ena_io_poll(struct napi_struct *napi, int budget) struct ena_ring *tx_ring, *rx_ring; struct ena_eth_io_intr_reg intr_reg; - u32 tx_work_done; - u32 rx_work_done; + int tx_work_done; + int rx_work_done = 0; int tx_budget; int napi_comp_call = 0; int ret; @@ -1122,7 +1122,11 @@ static int ena_io_poll(struct napi_struct *napi, int budget) } tx_work_done = ena_clean_tx_irq(tx_ring, tx_budget); - rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget); + /* On netpoll the budget is zero and the handler should only clean the + * tx completions. + */ + if (likely(budget)) + rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget); if ((budget > rx_work_done) && (tx_budget > tx_work_done)) { napi_complete_done(napi, rx_work_done); @@ -1698,6 +1702,7 @@ static int ena_up(struct ena_adapter *adapter) err_setup_tx: ena_free_io_irq(adapter); err_req_irq: + ena_del_napi(adapter); return rc; } diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 008f2d594d402c6d6519a44c54a6e03bd52daeff..326c2e1437b322c659ad62e405be270ce4b99807 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -110,6 +110,8 @@ #define ENA_IO_TXQ_IDX(q) (2 * (q)) #define ENA_IO_RXQ_IDX(q) (2 * (q) + 1) +#define ENA_IO_TXQ_IDX_TO_COMBINED_IDX(q) ((q) / 2) +#define ENA_IO_RXQ_IDX_TO_COMBINED_IDX(q) (((q) - 1) / 2) #define ENA_MGMNT_IRQ_IDX 0 #define ENA_IO_IRQ_FIRST_IDX 1 diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index de4b5d267c30c4c17a9fb9c701503082019bed61..17c07837033f858d69fb1d484dea0ba73858ef87 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1711,7 +1711,7 @@ static int xgene_enet_probe(struct platform_device *pdev) int ret; ndev = alloc_etherdev_mqs(sizeof(struct xgene_enet_pdata), - XGENE_NUM_RX_RING, XGENE_NUM_TX_RING); + XGENE_NUM_TX_RING, XGENE_NUM_RX_RING); if (!ndev) return -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 17aa33c5567d66306a895e855fbff5486d79d5e0..d95dec59578615d040efb98c3b3990737e114d2b 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -1524,8 +1524,10 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) int ethaddr_bytes = ETH_ALEN; memset(ppattern + offset, 0xff, magicsync); - for (j = 0; j < magicsync; j++) - set_bit(len++, (unsigned long *) pmask); + for (j = 0; j < magicsync; j++) { + pmask[len >> 3] |= BIT(len & 7); + len++; + } for (j = 0; j < B44_MAX_PATTERNS; j++) { if ((B44_PATTERN_SIZE - len) >= ETH_ALEN) @@ -1537,7 +1539,8 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) for (k = 0; k< ethaddr_bytes; k++) { ppattern[offset + magicsync + (j * ETH_ALEN) + k] = macaddr[k]; - set_bit(len++, (unsigned long *) pmask); + pmask[len >> 3] |= BIT(len & 7); + len++; } } return len - 1; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 95874c10c23b63110f5caf07eb3682841c50cbda..6519dd33c7ca2139bfdffb6d35d3cbe81a11df57 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1773,7 +1773,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) priv->phy_interface = of_get_phy_mode(dn); /* Default to GMII interface mode */ - if (priv->phy_interface < 0) + if ((int)priv->phy_interface < 0) priv->phy_interface = PHY_INTERFACE_MODE_GMII; /* In the case of a fixed PHY, the DT node associated @@ -1983,6 +1983,9 @@ static int bcm_sysport_resume(struct device *d) umac_reset(priv); + /* Disable the UniMAC RX/TX */ + umac_enable_set(priv, CMD_RX_EN | CMD_TX_EN, 0); + /* We may have been suspended and never received a WOL event that * would turn off MPD detection, take care of that now */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 2ec1c43270b7c16a9328285cb3839f770676e80d..bb36312c96969d760cf848041927250d8496141b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -1112,7 +1112,7 @@ static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp) for (i = 0; i < E1H_FUNC_MAX / 2; i++) { u32 func_config = MF_CFG_RD(bp, - func_mf_config[BP_PORT(bp) + 2 * i]. + func_mf_config[BP_PATH(bp) + 2 * i]. config); func_num += ((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index ce8a777b1e975502912dcb5ae7396799b243f5c0..8d17d464c0677c55987b89735d687b6c26eec2b6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9995,10 +9995,18 @@ static void bnx2x_recovery_failed(struct bnx2x *bp) */ static void bnx2x_parity_recover(struct bnx2x *bp) { - bool global = false; u32 error_recovered, error_unrecovered; - bool is_parity; + bool is_parity, global = false; +#ifdef CONFIG_BNX2X_SRIOV + int vf_idx; + + for (vf_idx = 0; vf_idx < bp->requested_nr_virtfn; vf_idx++) { + struct bnx2x_virtf *vf = BP_VF(bp, vf_idx); + if (vf) + vf->state = VF_LOST; + } +#endif DP(NETIF_MSG_HW, "Handling parity\n"); while (1) { switch (bp->recovery_state) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index c6e059119b22e1b12351274973f2d86ee6ffc33e..e8a09d0afe1c966569badda753af625bf08af7cd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -2376,15 +2376,21 @@ static int bnx2x_set_pf_tx_switching(struct bnx2x *bp, bool enable) /* send the ramrod on all the queues of the PF */ for_each_eth_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; + int tx_idx; /* Set the appropriate Queue object */ q_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj; - /* Update the Queue state */ - rc = bnx2x_queue_state_change(bp, &q_params); - if (rc) { - BNX2X_ERR("Failed to configure Tx switching\n"); - return rc; + for (tx_idx = FIRST_TX_COS_INDEX; + tx_idx < fp->max_cos; tx_idx++) { + q_params.params.update.cid_index = tx_idx; + + /* Update the Queue state */ + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) { + BNX2X_ERR("Failed to configure Tx switching\n"); + return rc; + } } } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 888d0b6632e86f2f7ab7e2f9e605be87fa4c7061..7152a03e36070f7338b44b23b96b78b80a323afa 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -139,6 +139,7 @@ struct bnx2x_virtf { #define VF_ACQUIRED 1 /* VF acquired, but not initialized */ #define VF_ENABLED 2 /* VF Enabled */ #define VF_RESET 3 /* VF FLR'd, pending cleanup */ +#define VF_LOST 4 /* Recovery while VFs are loaded */ bool flr_clnup_stage; /* true during flr cleanup */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index c2d327d9dff0ce7b89d25b448b3a05b75ddcb69c..27142fb195b6fed7936fbcd83c09f320fd7276de 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -2095,6 +2095,18 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, { int i; + if (vf->state == VF_LOST) { + /* Just ack the FW and return if VFs are lost + * in case of parity error. VFs are supposed to be timedout + * on waiting for PF response. + */ + DP(BNX2X_MSG_IOV, + "VF 0x%x lost, not handling the request\n", vf->abs_vfid); + + storm_memset_vf_mbx_ack(bp, vf->abs_vfid); + return; + } + /* check if tlv type is known */ if (bnx2x_tlv_supported(mbx->first_tlv.tl.type)) { /* Lock the per vf op mutex and note the locker's identity. diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index fbe3c2c114f9344f6334e81a4900031289dd3455..736e550163e10e2b1b1faa446c5a7527ab28bbf8 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6439,13 +6439,13 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; if (netif_running(dev)) - bnxt_close_nic(bp, false, false); + bnxt_close_nic(bp, true, false); dev->mtu = new_mtu; bnxt_set_ring_params(bp); if (netif_running(dev)) - return bnxt_open_nic(bp, false, false); + return bnxt_open_nic(bp, true, false); return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index d1a2159e40d6b0ede468da60a4f480e6bf5a5d65..9627ed0b2f1c6a7b3c9f1a6095ccd6188e6eaf7c 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -2440,6 +2440,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) if (!is_offload(adapter)) return -EOPNOTSUPP; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; if (!(adapter->flags & FULL_INIT_DONE)) return -EIO; /* need the memory controllers */ if (copy_from_user(&t, useraddr, sizeof(t))) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 61c55621b958971a4f2cfeb612dafd3f4b68d1e0..c150521647172132200fd699d60e0bc5c05e45fd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -66,8 +66,7 @@ static void *seq_tab_start(struct seq_file *seq, loff_t *pos) static void *seq_tab_next(struct seq_file *seq, void *v, loff_t *pos) { v = seq_tab_get_idx(seq->private, *pos + 1); - if (v) - ++*pos; + ++(*pos); return v; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c index 60a26037a1c675453a8261822c113712c129874a..e58aae110ed2dca7b9b52c6080601cf365e48f50 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c @@ -682,8 +682,7 @@ static void *l2t_seq_start(struct seq_file *seq, loff_t *pos) static void *l2t_seq_next(struct seq_file *seq, void *v, loff_t *pos) { v = l2t_get_idx(seq, *pos); - if (v) - ++*pos; + ++(*pos); return v; } diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index a37481c04a87b6a16541e1d2786a2357a946d82d..9eb3071b69a42a49e7902a91b3744e0861374f47 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -718,6 +718,10 @@ static int adapter_up(struct adapter *adapter) if (adapter->flags & USING_MSIX) name_msix_vecs(adapter); + + /* Initialize hash mac addr list*/ + INIT_LIST_HEAD(&adapter->mac_hlist); + adapter->flags |= FULL_INIT_DONE; } @@ -743,8 +747,6 @@ static int adapter_up(struct adapter *adapter) enable_rx(adapter); t4vf_sge_start(adapter); - /* Initialize hash mac addr list*/ - INIT_LIST_HEAD(&adapter->mac_hlist); return 0; } diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c index 9a161e98152978fcfbafa51a959e214426a90bd9..24f69034f52c43862f203e0f0843c497f99fcee1 100644 --- a/drivers/net/ethernet/cirrus/ep93xx_eth.c +++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c @@ -780,6 +780,7 @@ static int ep93xx_eth_remove(struct platform_device *pdev) { struct net_device *dev; struct ep93xx_priv *ep; + struct resource *mem; dev = platform_get_drvdata(pdev); if (dev == NULL) @@ -795,8 +796,8 @@ static int ep93xx_eth_remove(struct platform_device *pdev) iounmap(ep->base_addr); if (ep->res != NULL) { - release_resource(ep->res); - kfree(ep->res); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(mem->start, resource_size(mem)); } free_netdev(dev); diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index b73d9ba9496c31718ab3d021b68153ce9ace5331..96290b83dfde977fe27fc9484e305ef284b8eed6 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1806,10 +1806,10 @@ static int enic_stop(struct net_device *netdev) } netif_carrier_off(netdev); - netif_tx_disable(netdev); if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) for (i = 0; i < enic->wq_count; i++) napi_disable(&enic->napi[enic_cq_wq(enic, i)]); + netif_tx_disable(netdev); if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) enic_dev_del_station_addr(enic); diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c index 8ed0fd8b1dda8301a57e4eb9607eeb9d7ccf9102..74cb9b3c2f41c3df07a422bc67deac837df43b0f 100644 --- a/drivers/net/ethernet/dec/tulip/dmfe.c +++ b/drivers/net/ethernet/dec/tulip/dmfe.c @@ -2225,15 +2225,16 @@ static int __init dmfe_init_module(void) if (cr6set) dmfe_cr6_user_set = cr6set; - switch(mode) { - case DMFE_10MHF: + switch (mode) { + case DMFE_10MHF: case DMFE_100MHF: case DMFE_10MFD: case DMFE_100MFD: case DMFE_1M_HPNA: dmfe_media_mode = mode; break; - default:dmfe_media_mode = DMFE_AUTO; + default: + dmfe_media_mode = DMFE_AUTO; break; } diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c index e750b5ddc0fbb34436f9df49e9cd62ebc5eb0700..5f79e2731b761640b2183f2fda10e2c4ca12cc4b 100644 --- a/drivers/net/ethernet/dec/tulip/uli526x.c +++ b/drivers/net/ethernet/dec/tulip/uli526x.c @@ -1813,8 +1813,8 @@ static int __init uli526x_init_module(void) if (cr6set) uli526x_cr6_user_set = cr6set; - switch (mode) { - case ULI526X_10MHF: + switch (mode) { + case ULI526X_10MHF: case ULI526X_100MHF: case ULI526X_10MFD: case ULI526X_100MFD: diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 1b07c6216e2a78fa3fbcc156f13f9ac594c57c1f..8df32398d3435b1341c533aa692db0bae612949c 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2470,15 +2470,15 @@ fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec) return -EINVAL; } - cycle = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr); + cycle = fec_enet_us_to_itr_clock(ndev, ec->rx_coalesce_usecs); if (cycle > 0xFFFF) { pr_err("Rx coalesced usec exceed hardware limitation\n"); return -EINVAL; } - cycle = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr); + cycle = fec_enet_us_to_itr_clock(ndev, ec->tx_coalesce_usecs); if (cycle > 0xFFFF) { - pr_err("Rx coalesced usec exceed hardware limitation\n"); + pr_err("Tx coalesced usec exceed hardware limitation\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c index 21dd5579130e66bccd895634f8626deb0a13acee..c30994a09a7c20d3c866b122659483f5ca6f4267 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.c +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c @@ -109,7 +109,7 @@ do { \ /* Interface Mode Register (IF_MODE) */ #define IF_MODE_MASK 0x00000003 /* 30-31 Mask on i/f mode bits */ -#define IF_MODE_XGMII 0x00000000 /* 30-31 XGMII (10G) interface */ +#define IF_MODE_10G 0x00000000 /* 30-31 10G interface */ #define IF_MODE_GMII 0x00000002 /* 30-31 GMII (1G) interface */ #define IF_MODE_RGMII 0x00000004 #define IF_MODE_RGMII_AUTO 0x00008000 @@ -438,7 +438,7 @@ static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg, tmp = 0; switch (phy_if) { case PHY_INTERFACE_MODE_XGMII: - tmp |= IF_MODE_XGMII; + tmp |= IF_MODE_10G; break; default: tmp |= IF_MODE_GMII; diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 60bd1b36df60650bed5ca6c4612ebd734f3b190b..b665d27f8e29991fd7654073787662891505db50 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -2688,13 +2688,17 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) skb_dirtytx = tx_queue->skb_dirtytx; while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) { + bool do_tstamp; + + do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && + priv->hwts_tx_en; frags = skb_shinfo(skb)->nr_frags; /* When time stamping, one additional TxBD must be freed. * Also, we need to dma_unmap_single() the TxPAL. */ - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) + if (unlikely(do_tstamp)) nr_txbds = frags + 2; else nr_txbds = frags + 1; @@ -2708,7 +2712,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) (lstatus & BD_LENGTH_MASK)) break; - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { + if (unlikely(do_tstamp)) { next = next_txbd(bdp, base, tx_ring_size); buflen = be16_to_cpu(next->length) + GMAC_FCB_LEN + GMAC_TXPAL_LEN; @@ -2718,7 +2722,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) dma_unmap_single(priv->dev, be32_to_cpu(bdp->bufPtr), buflen, DMA_TO_DEVICE); - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { + if (unlikely(do_tstamp)) { struct skb_shared_hwtstamps shhwtstamps; u64 *ns = (u64 *)(((uintptr_t)skb->data + 0x10) & ~0x7UL); diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c index e03b30c60dcfda168291ce7f3a93306b3f3748de..c82c85ef5fb3407d1a0016573b325dd39e068ffa 100644 --- a/drivers/net/ethernet/freescale/xgmac_mdio.c +++ b/drivers/net/ethernet/freescale/xgmac_mdio.c @@ -49,6 +49,7 @@ struct tgec_mdio_controller { struct mdio_fsl_priv { struct tgec_mdio_controller __iomem *mdio_base; bool is_little_endian; + bool has_a011043; }; static u32 xgmac_read32(void __iomem *regs, @@ -226,7 +227,8 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) return ret; /* Return all Fs if nothing was there */ - if (xgmac_read32(®s->mdio_stat, endian) & MDIO_STAT_RD_ER) { + if ((xgmac_read32(®s->mdio_stat, endian) & MDIO_STAT_RD_ER) && + !priv->has_a011043) { dev_err(&bus->dev, "Error while reading PHY%d reg at %d.%hhu\n", phy_id, dev_addr, regnum); @@ -274,6 +276,9 @@ static int xgmac_mdio_probe(struct platform_device *pdev) priv->is_little_endian = of_property_read_bool(pdev->dev.of_node, "little-endian"); + priv->has_a011043 = of_property_read_bool(pdev->dev.of_node, + "fsl,erratum-a011043"); + ret = of_mdiobus_register(bus, np); if (ret) { dev_err(&pdev->dev, "cannot register MDIO bus\n"); diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index 4436a0307f32e93015d1febb79c235867e415f37..0b3aa83f3fc1c711387c8ffda26d9f372c4591a2 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -455,9 +455,9 @@ static int hip04_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) skb_tx_timestamp(skb); hip04_set_xmit_desc(priv, phys); - priv->tx_head = TX_NEXT(tx_head); count++; netdev_sent_queue(ndev, skb->len); + priv->tx_head = TX_NEXT(tx_head); stats->tx_bytes += skb->len; stats->tx_packets++; diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index e69a6bed31a9554ed0d35e48c871cfa6615b680f..dd24c352b200083ca356eb831b865507ab357e57 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -929,7 +929,7 @@ static int hix5hd2_dev_probe(struct platform_device *pdev) goto err_free_mdio; priv->phy_mode = of_get_phy_mode(node); - if (priv->phy_mode < 0) { + if ((int)priv->phy_mode < 0) { netdev_err(ndev, "not find phy-mode\n"); ret = -EINVAL; goto err_mdiobus; diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 2dd17e01e3a7a29af302225f4c0a9636be580f56..3692adb8902d194ac23c6b4e861d508227ddf263 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -1476,7 +1476,7 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr, memset(pr, 0, sizeof(struct ehea_port_res)); - pr->tx_bytes = rx_bytes; + pr->tx_bytes = tx_bytes; pr->tx_packets = tx_packets; pr->rx_bytes = rx_bytes; pr->rx_packets = rx_packets; diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 068789e694c9b310ca6fd541a2be90f6c5059e36..93c29094ceff98be76b30b612f5b1bf52be1a43d 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -1370,8 +1370,8 @@ static inline int e100_load_ucode_wait(struct nic *nic) fw = e100_request_firmware(nic); /* If it's NULL, then no ucode is required */ - if (!fw || IS_ERR(fw)) - return PTR_ERR(fw); + if (IS_ERR_OR_NULL(fw)) + return PTR_ERR_OR_ZERO(fw); if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) netif_err(nic, probe, nic->netdev, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 8ad20b7852ed7794188c0d9764ffebd6e7381283..4c729faeb71322eaf4536bd92259c58abd643a7b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4804,7 +4804,7 @@ static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; struct hlist_node *node2; struct ixgbe_fdir_filter *filter; - u64 action; + u8 queue; spin_lock(&adapter->fdir_perfect_lock); @@ -4813,17 +4813,34 @@ static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter) hlist_for_each_entry_safe(filter, node2, &adapter->fdir_filter_list, fdir_node) { - action = filter->action; - if (action != IXGBE_FDIR_DROP_QUEUE && action != 0) - action = - (action >> ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF) - 1; + if (filter->action == IXGBE_FDIR_DROP_QUEUE) { + queue = IXGBE_FDIR_DROP_QUEUE; + } else { + u32 ring = ethtool_get_flow_spec_ring(filter->action); + u8 vf = ethtool_get_flow_spec_ring_vf(filter->action); + + if (!vf && (ring >= adapter->num_rx_queues)) { + e_err(drv, "FDIR restore failed without VF, ring: %u\n", + ring); + continue; + } else if (vf && + ((vf > adapter->num_vfs) || + ring >= adapter->num_rx_queues_per_pool)) { + e_err(drv, "FDIR restore failed with VF, vf: %hhu, ring: %u\n", + vf, ring); + continue; + } + + /* Map the ring onto the absolute queue index */ + if (!vf) + queue = adapter->rx_ring[ring]->reg_idx; + else + queue = ((vf - 1) * + adapter->num_rx_queues_per_pool) + ring; + } ixgbe_fdir_write_perfect_filter_82599(hw, - &filter->filter, - filter->sw_idx, - (action == IXGBE_FDIR_DROP_QUEUE) ? - IXGBE_FDIR_DROP_QUEUE : - adapter->rx_ring[action]->reg_idx); + &filter->filter, filter->sw_idx, queue); } spin_unlock(&adapter->fdir_perfect_lock); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 75607267e656f3e6ce700c69f053a259877dc238..7a763e85ff27e4c3db2eff88b1a29f38d1afa50f 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1885,11 +1885,6 @@ static int ixgbevf_write_uc_addr_list(struct net_device *netdev) struct ixgbe_hw *hw = &adapter->hw; int count = 0; - if ((netdev_uc_count(netdev)) > 10) { - pr_err("Too many unicast filters - No Space\n"); - return -ENOSPC; - } - if (!netdev_uc_empty(netdev)) { struct netdev_hw_addr *ha; diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index cb7c3ef971345fa2a3ed08bd2f7b23737e09d4ff..781642d47133dc62f4234ead36660ee38e79652c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -198,7 +198,7 @@ int mlx4_check_port_params(struct mlx4_dev *dev, for (i = 0; i < dev->caps.num_ports - 1; i++) { if (port_type[i] != port_type[i + 1]) { mlx4_err(dev, "Only same port types supported on this HCA, aborting\n"); - return -EINVAL; + return -EOPNOTSUPP; } } } @@ -207,7 +207,7 @@ int mlx4_check_port_params(struct mlx4_dev *dev, if (!(port_type[i] & dev->caps.supported_type[i+1])) { mlx4_err(dev, "Requested port type for port %d is not supported on this HCA\n", i + 1); - return -EINVAL; + return -EOPNOTSUPP; } } return 0; @@ -1122,8 +1122,7 @@ static int __set_port_type(struct mlx4_port_info *info, mlx4_err(mdev, "Requested port type for port %d is not supported on this HCA\n", info->port); - err = -EINVAL; - goto err_sup; + return -EOPNOTSUPP; } mlx4_stop_sense(mdev); @@ -1145,7 +1144,7 @@ static int __set_port_type(struct mlx4_port_info *info, for (i = 1; i <= mdev->caps.num_ports; i++) { if (mdev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) { mdev->caps.possible_type[i] = mdev->caps.port_type[i]; - err = -EINVAL; + err = -EOPNOTSUPP; } } } @@ -1171,7 +1170,7 @@ static int __set_port_type(struct mlx4_port_info *info, out: mlx4_start_sense(mdev); mutex_unlock(&priv->port_mutex); -err_sup: + return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index e42ece20cd0b1052a8c682673c666d19ac144496..e13a6cd5163f4df4e01f9f695513a71a9d50208a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1368,7 +1368,7 @@ static int mlx5e_get_module_info(struct net_device *netdev, break; case MLX5_MODULE_ID_SFP: modinfo->type = ETH_MODULE_SFF_8472; - modinfo->eeprom_len = MLX5_EEPROM_PAGE_LENGTH; + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; break; default: netdev_err(priv->netdev, "%s: cable type not recognized:0x%x\n", diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c index 9346f3985edf3c44ed80927d719bab5efe06057f..354338c8a510e1acb427f0bb23ab0004924c41c8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -125,7 +125,7 @@ void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type) if (!is_event_type_allowed((rsn >> MLX5_USER_INDEX_LEN), event_type)) { mlx5_core_warn(dev, "event 0x%.2x is not allowed on resource 0x%.8x\n", event_type, rsn); - return; + goto out; } switch (common->res) { @@ -139,7 +139,7 @@ void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type) default: mlx5_core_warn(dev, "invalid resource type for 0x%x\n", rsn); } - +out: mlx5_core_put_rsc(common); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index b2a745b579fd120d25ba6306e0ad761a65aed27c..fdc69218c8cacf1b5e31e45d647b70d9cb9bc717 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1873,7 +1873,7 @@ static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port, * Configures the ETS elements. */ #define MLXSW_REG_QEEC_ID 0x400D -#define MLXSW_REG_QEEC_LEN 0x1C +#define MLXSW_REG_QEEC_LEN 0x20 static const struct mlxsw_reg_info mlxsw_reg_qeec = { .id = MLXSW_REG_QEEC_ID, @@ -1918,6 +1918,15 @@ MLXSW_ITEM32(reg, qeec, element_index, 0x04, 0, 8); */ MLXSW_ITEM32(reg, qeec, next_element_index, 0x08, 0, 8); +/* reg_qeec_mise + * Min shaper configuration enable. Enables configuration of the min + * shaper on this ETS element + * 0 - Disable + * 1 - Enable + * Access: RW + */ +MLXSW_ITEM32(reg, qeec, mise, 0x0C, 31, 1); + enum { MLXSW_REG_QEEC_BYTES_MODE, MLXSW_REG_QEEC_PACKETS_MODE, @@ -1934,6 +1943,17 @@ enum { */ MLXSW_ITEM32(reg, qeec, pb, 0x0C, 28, 1); +/* The smallest permitted min shaper rate. */ +#define MLXSW_REG_QEEC_MIS_MIN 200000 /* Kbps */ + +/* reg_qeec_min_shaper_rate + * Min shaper information rate. + * For CPU port, can only be configured for port hierarchy. + * When in bytes mode, value is specified in units of 1000bps. + * Access: RW + */ +MLXSW_ITEM32(reg, qeec, min_shaper_rate, 0x0C, 0, 28); + /* reg_qeec_mase * Max shaper configuration enable. Enables configuration of the max * shaper on this ETS element. diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index 8dc1f0277117d9acf3618163ccdd9a4b87295fd4..d4747caf1e7cc981427bc3d51f1b7553040563e2 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -474,24 +474,6 @@ static int msg_enable; * chip is busy transferring packet data (RX/TX FIFO accesses). */ -/** - * ks_rdreg8 - read 8 bit register from device - * @ks : The chip information - * @offset: The register address - * - * Read a 8bit register from the chip, returning the result - */ -static u8 ks_rdreg8(struct ks_net *ks, int offset) -{ - u16 data; - u8 shift_bit = offset & 0x03; - u8 shift_data = (offset & 1) << 3; - ks->cmd_reg_cache = (u16) offset | (u16)(BE0 << shift_bit); - iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); - data = ioread16(ks->hw_addr); - return (u8)(data >> shift_data); -} - /** * ks_rdreg16 - read 16 bit register from device * @ks : The chip information @@ -502,27 +484,11 @@ static u8 ks_rdreg8(struct ks_net *ks, int offset) static u16 ks_rdreg16(struct ks_net *ks, int offset) { - ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02)); + ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02)); iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); return ioread16(ks->hw_addr); } -/** - * ks_wrreg8 - write 8bit register value to chip - * @ks: The chip information - * @offset: The register address - * @value: The value to write - * - */ -static void ks_wrreg8(struct ks_net *ks, int offset, u8 value) -{ - u8 shift_bit = (offset & 0x03); - u16 value_write = (u16)(value << ((offset & 1) << 3)); - ks->cmd_reg_cache = (u16)offset | (BE0 << shift_bit); - iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); - iowrite16(value_write, ks->hw_addr); -} - /** * ks_wrreg16 - write 16bit register value to chip * @ks: The chip information @@ -533,7 +499,7 @@ static void ks_wrreg8(struct ks_net *ks, int offset, u8 value) static void ks_wrreg16(struct ks_net *ks, int offset, u16 value) { - ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02)); + ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02)); iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); iowrite16(value, ks->hw_addr); } @@ -549,7 +515,7 @@ static inline void ks_inblk(struct ks_net *ks, u16 *wptr, u32 len) { len >>= 1; while (len--) - *wptr++ = (u16)ioread16(ks->hw_addr); + *wptr++ = be16_to_cpu(ioread16(ks->hw_addr)); } /** @@ -563,7 +529,7 @@ static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len) { len >>= 1; while (len--) - iowrite16(*wptr++, ks->hw_addr); + iowrite16(cpu_to_be16(*wptr++), ks->hw_addr); } static void ks_disable_int(struct ks_net *ks) @@ -642,8 +608,7 @@ static void ks_read_config(struct ks_net *ks) u16 reg_data = 0; /* Regardless of bus width, 8 bit read should always work.*/ - reg_data = ks_rdreg8(ks, KS_CCR) & 0x00FF; - reg_data |= ks_rdreg8(ks, KS_CCR+1) << 8; + reg_data = ks_rdreg16(ks, KS_CCR); /* addr/data bus are multiplexed */ ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED; @@ -747,7 +712,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len) /* 1. set sudo DMA mode */ ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI); - ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); /* 2. read prepend data */ /** @@ -764,7 +729,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len) ks_inblk(ks, buf, ALIGN(len, 4)); /* 4. reset sudo DMA Mode */ - ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); } /** @@ -866,14 +831,17 @@ static irqreturn_t ks_irq(int irq, void *pw) { struct net_device *netdev = pw; struct ks_net *ks = netdev_priv(netdev); + unsigned long flags; u16 status; + spin_lock_irqsave(&ks->statelock, flags); /*this should be the first in IRQ handler */ ks_save_cmd_reg(ks); status = ks_rdreg16(ks, KS_ISR); if (unlikely(!status)) { ks_restore_cmd_reg(ks); + spin_unlock_irqrestore(&ks->statelock, flags); return IRQ_NONE; } @@ -899,6 +867,7 @@ static irqreturn_t ks_irq(int irq, void *pw) ks->netdev->stats.rx_over_errors++; /* this should be the last in IRQ handler*/ ks_restore_cmd_reg(ks); + spin_unlock_irqrestore(&ks->statelock, flags); return IRQ_HANDLED; } @@ -968,6 +937,7 @@ static int ks_net_stop(struct net_device *netdev) /* shutdown RX/TX QMU */ ks_disable_qmu(ks); + ks_disable_int(ks); /* set powermode to soft power down to save power */ ks_set_powermode(ks, PMECR_PM_SOFTDOWN); @@ -997,13 +967,13 @@ static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len) ks->txh.txw[1] = cpu_to_le16(len); /* 1. set sudo-DMA mode */ - ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); /* 2. write status/lenth info */ ks_outblk(ks, ks->txh.txw, 4); /* 3. write pkt data */ ks_outblk(ks, (u16 *)pdata, ALIGN(len, 4)); /* 4. reset sudo-DMA mode */ - ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); /* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */ ks_wrreg16(ks, KS_TXQCR, TXQCR_METFE); /* 6. wait until TXQCR_METFE is auto-cleared */ @@ -1024,10 +994,9 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) { netdev_tx_t retv = NETDEV_TX_OK; struct ks_net *ks = netdev_priv(netdev); + unsigned long flags; - disable_irq(netdev->irq); - ks_disable_int(ks); - spin_lock(&ks->statelock); + spin_lock_irqsave(&ks->statelock, flags); /* Extra space are required: * 4 byte for alignment, 4 for status/length, 4 for CRC @@ -1041,9 +1010,7 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) dev_kfree_skb(skb); } else retv = NETDEV_TX_BUSY; - spin_unlock(&ks->statelock); - ks_enable_int(ks); - enable_irq(netdev->irq); + spin_unlock_irqrestore(&ks->statelock, flags); return retv; } diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 23821540ab078de3aafcb07c781e7f5ebc932299..254e6dbc4c6aa3da226f84f405c234e32c2b127e 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -50,6 +50,8 @@ static int sonic_open(struct net_device *dev) if (sonic_debug > 2) printk("sonic_open: initializing sonic driver.\n"); + spin_lock_init(&lp->lock); + for (i = 0; i < SONIC_NUM_RRS; i++) { struct sk_buff *skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); if (skb == NULL) { @@ -101,6 +103,24 @@ static int sonic_open(struct net_device *dev) return 0; } +/* Wait for the SONIC to become idle. */ +static void sonic_quiesce(struct net_device *dev, u16 mask) +{ + struct sonic_local * __maybe_unused lp = netdev_priv(dev); + int i; + u16 bits; + + for (i = 0; i < 1000; ++i) { + bits = SONIC_READ(SONIC_CMD) & mask; + if (!bits) + return; + if (irqs_disabled() || in_interrupt()) + udelay(20); + else + usleep_range(100, 200); + } + WARN_ONCE(1, "command deadline expired! 0x%04x\n", bits); +} /* * Close the SONIC device @@ -118,6 +138,9 @@ static int sonic_close(struct net_device *dev) /* * stop the SONIC, disable interrupts */ + SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); + sonic_quiesce(dev, SONIC_CR_ALL); + SONIC_WRITE(SONIC_IMR, 0); SONIC_WRITE(SONIC_ISR, 0x7fff); SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); @@ -157,6 +180,9 @@ static void sonic_tx_timeout(struct net_device *dev) * put the Sonic into software-reset mode and * disable all interrupts before releasing DMA buffers */ + SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); + sonic_quiesce(dev, SONIC_CR_ALL); + SONIC_WRITE(SONIC_IMR, 0); SONIC_WRITE(SONIC_ISR, 0x7fff); SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); @@ -194,8 +220,6 @@ static void sonic_tx_timeout(struct net_device *dev) * wake the tx queue * Concurrently with all of this, the SONIC is potentially writing to * the status flags of the TDs. - * Until some mutual exclusion is added, this code will not work with SMP. However, - * MIPS Jazz machines and m68k Macs were all uni-processor machines. */ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) @@ -203,7 +227,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) struct sonic_local *lp = netdev_priv(dev); dma_addr_t laddr; int length; - int entry = lp->next_tx; + int entry; + unsigned long flags; if (sonic_debug > 2) printk("sonic_send_packet: skb=%p, dev=%p\n", skb, dev); @@ -221,11 +246,15 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE); if (!laddr) { - printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name); - dev_kfree_skb(skb); - return NETDEV_TX_BUSY; + pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } + spin_lock_irqsave(&lp->lock, flags); + + entry = lp->next_tx; + sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */ sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */ sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */ @@ -235,10 +264,6 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) sonic_tda_put(dev, entry, SONIC_TD_LINK, sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL); - /* - * Must set tx_skb[entry] only after clearing status, and - * before clearing EOL and before stopping queue - */ wmb(); lp->tx_len[entry] = length; lp->tx_laddr[entry] = laddr; @@ -263,6 +288,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); + spin_unlock_irqrestore(&lp->lock, flags); + return NETDEV_TX_OK; } @@ -275,9 +302,21 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) struct net_device *dev = dev_id; struct sonic_local *lp = netdev_priv(dev); int status; + unsigned long flags; + + /* The lock has two purposes. Firstly, it synchronizes sonic_interrupt() + * with sonic_send_packet() so that the two functions can share state. + * Secondly, it makes sonic_interrupt() re-entrant, as that is required + * by macsonic which must use two IRQs with different priority levels. + */ + spin_lock_irqsave(&lp->lock, flags); + + status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT; + if (!status) { + spin_unlock_irqrestore(&lp->lock, flags); - if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT)) return IRQ_NONE; + } do { if (status & SONIC_INT_PKTRX) { @@ -292,11 +331,12 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) int td_status; int freed_some = 0; - /* At this point, cur_tx is the index of a TD that is one of: - * unallocated/freed (status set & tx_skb[entry] clear) - * allocated and sent (status set & tx_skb[entry] set ) - * allocated and not yet sent (status clear & tx_skb[entry] set ) - * still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear) + /* The state of a Transmit Descriptor may be inferred + * from { tx_skb[entry], td_status } as follows. + * { clear, clear } => the TD has never been used + * { set, clear } => the TD was handed to SONIC + * { set, set } => the TD was handed back + * { clear, set } => the TD is available for re-use */ if (sonic_debug > 2) @@ -398,10 +438,30 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) /* load CAM done */ if (status & SONIC_INT_LCD) SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */ - } while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT)); + + status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT; + } while (status); + + spin_unlock_irqrestore(&lp->lock, flags); + return IRQ_HANDLED; } +/* Return the array index corresponding to a given Receive Buffer pointer. */ +static int index_from_addr(struct sonic_local *lp, dma_addr_t addr, + unsigned int last) +{ + unsigned int i = last; + + do { + i = (i + 1) & SONIC_RRS_MASK; + if (addr == lp->rx_laddr[i]) + return i; + } while (i != last); + + return -ENOENT; +} + /* * We have a good packet(s), pass it/them up the network stack. */ @@ -421,6 +481,16 @@ static void sonic_rx(struct net_device *dev) status = sonic_rda_get(dev, entry, SONIC_RD_STATUS); if (status & SONIC_RCR_PRX) { + u32 addr = (sonic_rda_get(dev, entry, + SONIC_RD_PKTPTR_H) << 16) | + sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L); + int i = index_from_addr(lp, addr, entry); + + if (i < 0) { + WARN_ONCE(1, "failed to find buffer!\n"); + break; + } + /* Malloc up new buffer. */ new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); if (new_skb == NULL) { @@ -442,7 +512,7 @@ static void sonic_rx(struct net_device *dev) /* now we have a new skb to replace it, pass the used one up the stack */ dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE); - used_skb = lp->rx_skb[entry]; + used_skb = lp->rx_skb[i]; pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN); skb_trim(used_skb, pkt_len); used_skb->protocol = eth_type_trans(used_skb, dev); @@ -451,13 +521,13 @@ static void sonic_rx(struct net_device *dev) lp->stats.rx_bytes += pkt_len; /* and insert the new skb */ - lp->rx_laddr[entry] = new_laddr; - lp->rx_skb[entry] = new_skb; + lp->rx_laddr[i] = new_laddr; + lp->rx_skb[i] = new_skb; bufadr_l = (unsigned long)new_laddr & 0xffff; bufadr_h = (unsigned long)new_laddr >> 16; - sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l); - sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h); + sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l); + sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h); } else { /* This should only happen, if we enable accepting broken packets. */ lp->stats.rx_errors++; @@ -592,6 +662,7 @@ static int sonic_init(struct net_device *dev) */ SONIC_WRITE(SONIC_CMD, 0); SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); + sonic_quiesce(dev, SONIC_CR_ALL); /* * initialize the receive resource area diff --git a/drivers/net/ethernet/natsemi/sonic.h b/drivers/net/ethernet/natsemi/sonic.h index 07091dd27e5df2969592a3faa54f30fdad4a4844..7dcf913d7395a63eb4b72067f1822fc22c3c672e 100644 --- a/drivers/net/ethernet/natsemi/sonic.h +++ b/drivers/net/ethernet/natsemi/sonic.h @@ -109,6 +109,9 @@ #define SONIC_CR_TXP 0x0002 #define SONIC_CR_HTX 0x0001 +#define SONIC_CR_ALL (SONIC_CR_LCAM | SONIC_CR_RRRA | \ + SONIC_CR_RXEN | SONIC_CR_TXP) + /* * SONIC data configuration bits */ @@ -273,8 +276,9 @@ #define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ #define SONIC_NUM_TDS 16 /* number of transmit descriptors */ -#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) -#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) +#define SONIC_RRS_MASK (SONIC_NUM_RRS - 1) +#define SONIC_RDS_MASK (SONIC_NUM_RDS - 1) +#define SONIC_TDS_MASK (SONIC_NUM_TDS - 1) #define SONIC_RBSIZE 1520 /* size of one resource buffer */ @@ -320,6 +324,7 @@ struct sonic_local { unsigned int next_tx; /* next free TD */ struct device *device; /* generic device */ struct net_device_stats stats; + spinlock_t lock; }; #define TX_TIMEOUT (3 * HZ) @@ -341,30 +346,30 @@ static void sonic_tx_timeout(struct net_device *dev); as far as we can tell. */ /* OpenBSD calls this "SWO". I'd like to think that sonic_buf_put() is a much better name. */ -static inline void sonic_buf_put(void* base, int bitmode, +static inline void sonic_buf_put(u16 *base, int bitmode, int offset, __u16 val) { if (bitmode) #ifdef __BIG_ENDIAN - ((__u16 *) base + (offset*2))[1] = val; + __raw_writew(val, base + (offset * 2) + 1); #else - ((__u16 *) base + (offset*2))[0] = val; + __raw_writew(val, base + (offset * 2) + 0); #endif else - ((__u16 *) base)[offset] = val; + __raw_writew(val, base + (offset * 1) + 0); } -static inline __u16 sonic_buf_get(void* base, int bitmode, +static inline __u16 sonic_buf_get(u16 *base, int bitmode, int offset) { if (bitmode) #ifdef __BIG_ENDIAN - return ((volatile __u16 *) base + (offset*2))[1]; + return __raw_readw(base + (offset * 2) + 1); #else - return ((volatile __u16 *) base + (offset*2))[0]; + return __raw_readw(base + (offset * 2) + 0); #endif else - return ((volatile __u16 *) base)[offset]; + return __raw_readw(base + (offset * 1) + 0); } /* Inlines that you should actually use for reading/writing DMA buffers */ diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 2f4a837f0d6adcb066d6deb952859d6a711026e4..dcd56ac6874823019b4559388da525af033df839 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1053,7 +1053,6 @@ static int pasemi_mac_phy_init(struct net_device *dev) dn = pci_device_to_OF_node(mac->pdev); phy_dn = of_parse_phandle(dn, "phy-handle", 0); - of_node_put(phy_dn); mac->link = 0; mac->speed = 0; @@ -1062,6 +1061,7 @@ static int pasemi_mac_phy_init(struct net_device *dev) phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII); + of_node_put(phy_dn); if (!phydev) { printk(KERN_ERR "%s: Could not attach to phy\n", dev->name); return -ENODEV; diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 715776e2cfe50dc12fc0c3eb7f32527825ac7c83..2d198f6ee21d9371ed14bf60f55bc1252c3db9c1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1328,10 +1328,9 @@ static void __qed_get_vport_pstats_addrlen(struct qed_hwfn *p_hwfn, } } -static void __qed_get_vport_pstats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack void +__qed_get_vport_pstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct eth_pstorm_per_queue_stat pstats; u32 pstats_addr = 0, pstats_len = 0; @@ -1351,10 +1350,9 @@ static void __qed_get_vport_pstats(struct qed_hwfn *p_hwfn, p_stats->tx_err_drop_pkts += HILO_64_REGPAIR(pstats.error_drop_pkts); } -static void __qed_get_vport_tstats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack void +__qed_get_vport_tstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct tstorm_per_port_stat tstats; u32 tstats_addr, tstats_len; @@ -1397,10 +1395,9 @@ static void __qed_get_vport_ustats_addrlen(struct qed_hwfn *p_hwfn, } } -static void __qed_get_vport_ustats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack +void __qed_get_vport_ustats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct eth_ustorm_per_queue_stat ustats; u32 ustats_addr = 0, ustats_len = 0; @@ -1436,10 +1433,9 @@ static void __qed_get_vport_mstats_addrlen(struct qed_hwfn *p_hwfn, } } -static void __qed_get_vport_mstats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats, - u16 statistics_bin) +static noinline_for_stack void +__qed_get_vport_mstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, u16 statistics_bin) { struct eth_mstorm_per_queue_stat mstats; u32 mstats_addr = 0, mstats_len = 0; @@ -1463,9 +1459,9 @@ static void __qed_get_vport_mstats(struct qed_hwfn *p_hwfn, HILO_64_REGPAIR(mstats.tpa_coalesced_bytes); } -static void __qed_get_vport_port_stats(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - struct qed_eth_stats *p_stats) +static noinline_for_stack void +__qed_get_vport_port_stats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats) { struct port_stats port_stats; int j; diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index c653b97d84d5bd911cf20dc44f5ff635c33d53da..f2cb77c3b19924597f379b52b670bdef259a1124 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -2752,6 +2752,9 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) int err; for (i = 0; i < qdev->num_large_buffers; i++) { + lrg_buf_cb = &qdev->lrg_buf[i]; + memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb)); + skb = netdev_alloc_skb(qdev->ndev, qdev->lrg_buffer_len); if (unlikely(!skb)) { @@ -2762,11 +2765,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) ql_free_large_buffers(qdev); return -ENOMEM; } else { - - lrg_buf_cb = &qdev->lrg_buf[i]; - memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb)); lrg_buf_cb->index = i; - lrg_buf_cb->skb = skb; /* * We save some space to copy the ethhdr from first * buffer @@ -2788,6 +2787,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) return -ENOMEM; } + lrg_buf_cb->skb = skb; dma_unmap_addr_set(lrg_buf_cb, mapaddr, map); dma_unmap_len_set(lrg_buf_cb, maplen, qdev->lrg_buffer_len - diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index a496390b8632fa3f9dfa9f5ca18bf64d0b9e7f31..07f9067affc65ea4d73543c18016174217c1971a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -2043,6 +2043,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev, break; } entry += p_hdr->size; + cond_resched(); } p_dev->ahw->reset.seq_index = index; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index 0844b7c7576709c8a271142fd85f41b8007fc108..5174e0bd75d1ebbdbc5d93569ea865629d68f96a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -703,6 +703,7 @@ static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter, addr += 16; reg_read -= 16; ret += 16; + cond_resched(); } out: mutex_unlock(&adapter->ahw->mem_lock); @@ -1383,6 +1384,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) buf_offset += entry->hdr.cap_size; entry_offset += entry->hdr.offset; buffer = fw_dump->data + buf_offset; + cond_resched(); } fw_dump->clr = 1; diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 21f546587e3d55e36fa306afc463fd0e2a8fbf00..31583d6f044f4f8548e729c034d9e9bfb85907b6 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -438,7 +438,6 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event) u16 signature = 0; u16 spi_config; u16 wrbuf_space = 0; - static u16 reset_count; if (event == QCASPI_EVENT_CPUON) { /* Read signature twice, if not valid @@ -491,13 +490,13 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event) qca->sync = QCASPI_SYNC_RESET; qca->stats.trig_reset++; - reset_count = 0; + qca->reset_count = 0; break; case QCASPI_SYNC_RESET: - reset_count++; + qca->reset_count++; netdev_dbg(qca->net_dev, "sync: waiting for CPU on, count %u.\n", - reset_count); - if (reset_count >= QCASPI_RESET_TIMEOUT) { + qca->reset_count); + if (qca->reset_count >= QCASPI_RESET_TIMEOUT) { /* reset did not seem to take place, try again */ qca->sync = QCASPI_SYNC_UNKNOWN; qca->stats.reset_timeout++; diff --git a/drivers/net/ethernet/qualcomm/qca_spi.h b/drivers/net/ethernet/qualcomm/qca_spi.h index 6e31a0e744a45b48fda518489504a447a7cc6d94..c48c314ca4dfadaa130f94231f10967a42d9d5f5 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.h +++ b/drivers/net/ethernet/qualcomm/qca_spi.h @@ -97,6 +97,7 @@ struct qcaspi { unsigned int intr_req; unsigned int intr_svc; + u16 reset_count; #ifdef CONFIG_DEBUG_FS struct dentry *device_root; diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 49300194d3f9f38a1b2f1e944810c0eb93ac1f34..6f8d4810ce9791a34d01125b39aa8d0dc1b2714e 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2929,12 +2929,16 @@ static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev) struct device_node *np = dev->of_node; struct sh_eth_plat_data *pdata; const char *mac_addr; + int ret; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; - pdata->phy_interface = of_get_phy_mode(np); + ret = of_get_phy_mode(np); + if (ret < 0) + return NULL; + pdata->phy_interface = ret; mac_addr = of_get_mac_address(np); if (mac_addr) diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 323b3ac16bc0e3ae283621fb97a3006e3217546a..d0cf971aa4ebe7233e550350100746281c7e1533 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -948,7 +948,7 @@ static void smc911x_phy_configure(struct work_struct *work) if (lp->ctl_rspeed != 100) my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF); - if (!lp->ctl_rfduplx) + if (!lp->ctl_rfduplx) my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); /* Update our Auto-Neg Advertisement Register */ diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 6d2de4e01f6d00404bde51f3816ba2271adff865..27c49d400bcd31828998252e24b41dc3be89925b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -326,8 +326,8 @@ struct dma_features { unsigned int enh_desc; }; -/* GMAC TX FIFO is 8K, Rx FIFO is 16K */ -#define BUF_SIZE_16KiB 16384 +/* RX Buffer size must be multiple of 4/8/16 bytes */ +#define BUF_SIZE_16KiB 16368 #define BUF_SIZE_8KiB 8192 #define BUF_SIZE_4KiB 4096 #define BUF_SIZE_2KiB 2048 @@ -354,7 +354,7 @@ struct dma_features { struct stmmac_desc_ops { /* DMA RX descriptor ring initialization */ void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode, - int end); + int end, int bfsize); /* DMA TX descriptor ring initialization */ void (*init_tx_desc) (struct dma_desc *p, int mode, int end); diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h index 1d181e205d6ecbb49c5d173fcb6f3ea5bfe6fe40..f9cbba2d2cc0f2653fbf46b84b6ff2624452beb0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h +++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h @@ -33,11 +33,14 @@ /* Specific functions used for Ring mode */ /* Enhanced descriptors */ -static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end) +static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end, + int bfsize) { - p->des1 |= cpu_to_le32(((BUF_SIZE_8KiB - 1) - << ERDES1_BUFFER2_SIZE_SHIFT) - & ERDES1_BUFFER2_SIZE_MASK); + if (bfsize == BUF_SIZE_16KiB) + p->des1 |= cpu_to_le32((BUF_SIZE_8KiB + << ERDES1_BUFFER2_SIZE_SHIFT) + & ERDES1_BUFFER2_SIZE_MASK); + if (end) p->des1 |= cpu_to_le32(ERDES1_END_RING); @@ -63,11 +66,15 @@ static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len) } /* Normal descriptors */ -static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end) +static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end, int bfsize) { - p->des1 |= cpu_to_le32(((BUF_SIZE_2KiB - 1) - << RDES1_BUFFER2_SIZE_SHIFT) - & RDES1_BUFFER2_SIZE_MASK); + if (bfsize >= BUF_SIZE_2KiB) { + int bfsize2; + + bfsize2 = min(bfsize - BUF_SIZE_2KiB + 1, BUF_SIZE_2KiB - 1); + p->des1 |= cpu_to_le32((bfsize2 << RDES1_BUFFER2_SIZE_SHIFT) + & RDES1_BUFFER2_SIZE_MASK); + } if (end) p->des1 |= cpu_to_le32(RDES1_END_RING); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index 866444b6c82faa773b622c861bb000e544a05d7a..11a4a81b0397cd3ce02550af97f85cd0256744f4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c @@ -203,7 +203,7 @@ static int ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac) struct device *dev = &gmac->pdev->dev; gmac->phy_mode = of_get_phy_mode(dev->of_node); - if (gmac->phy_mode < 0) { + if ((int)gmac->phy_mode < 0) { dev_err(dev, "missing phy mode property\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index f356a44bcb8112e629f52bd4547e71638d29855a..6704d3e0392dc9a0a8cf989206c451a36382f453 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -280,7 +280,7 @@ static int meson8b_dwmac_probe(struct platform_device *pdev) dwmac->pdev = pdev; dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node); - if (dwmac->phy_mode < 0) { + if ((int)dwmac->phy_mode < 0) { dev_err(&pdev->dev, "missing phy-mode property\n"); ret = -EINVAL; goto err_remove_config_dt; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c index 62ccbd47c1db2b60319051718a51fe159d2e7a54..fc1fa0f9f338713da5c6fcfdd19062ced459a91f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c @@ -53,7 +53,7 @@ static int sun7i_gmac_init(struct platform_device *pdev, void *priv) * rate, which then uses the auto-reparenting feature of the * clock driver, and enabling/disabling the clock. */ - if (gmac->interface == PHY_INTERFACE_MODE_RGMII) { + if (phy_interface_mode_is_rgmii(gmac->interface)) { clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE); clk_prepare_enable(gmac->tx_clk); gmac->clk_enabled = 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index f46f2bfc2cc096a1aeb4268b415cfd4735c4d12a..4216c0a5eaf5a64a180729a3ee2cacab4dd4e805 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -168,7 +168,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw, } /* Handle multiple unicast addresses */ - if (netdev_uc_count(dev) > GMAC_MAX_PERFECT_ADDRESSES) { + if (netdev_uc_count(dev) > hw->unicast_filter_entries) { /* Switch to promiscuous mode if more than 128 addrs * are required */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index 3f5056858535a98215583da1cd59b24dd9255db6..a90b02926e4df498699deb28572afe55d39a6b77 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -289,7 +289,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats) } static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, - int mode, int end) + int mode, int end, int bfsize) { p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR); diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index 77dc5842bd0b366a0de1e6d5664ed026a55fa6c5..47f4fe50c8486f344c635a84718fe71e4a8ce720 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -269,15 +269,19 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, } static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, - int mode, int end) + int mode, int end, int bfsize) { + int bfsize1; + p->des0 |= cpu_to_le32(RDES0_OWN); - p->des1 |= cpu_to_le32((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK); + + bfsize1 = min(bfsize, BUF_SIZE_8KiB); + p->des1 |= cpu_to_le32(bfsize1 & ERDES1_BUFFER1_SIZE_MASK); if (mode == STMMAC_CHAIN_MODE) ehn_desc_rx_set_on_chain(p); else - ehn_desc_rx_set_on_ring(p, end); + ehn_desc_rx_set_on_ring(p, end, bfsize); if (disable_rx_ic) p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC); diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index 01f8f2e94c0fb974b7f0230c74fca83e929a2312..5a06a5a1f6ea77e0f957c91d1182ff6787c2d6e8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -137,15 +137,19 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, } static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode, - int end) + int end, int bfsize) { + int bfsize1; + p->des0 |= cpu_to_le32(RDES0_OWN); - p->des1 |= cpu_to_le32((BUF_SIZE_2KiB - 1) & RDES1_BUFFER1_SIZE_MASK); + + bfsize1 = min(bfsize, BUF_SIZE_2KiB - 1); + p->des1 |= cpu_to_le32(bfsize1 & RDES1_BUFFER1_SIZE_MASK); if (mode == STMMAC_CHAIN_MODE) ndesc_rx_set_on_chain(p, end); else - ndesc_rx_set_on_ring(p, end); + ndesc_rx_set_on_ring(p, end, bfsize); if (disable_rx_ic) p->des1 |= cpu_to_le32(RDES1_DISABLE_IC); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 2c04a0739fd646340063e2820dfbde33da8fac86..8c1a5361f661df9dfd87dc8eccd4eb498012a5b1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -55,7 +55,7 @@ #include #include "dwmac1000.h" -#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES) +#define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16) #define TSO_MAX_BUFF_SIZE (SZ_16K - 1) /* Module parameters */ @@ -929,7 +929,9 @@ static int stmmac_set_bfsize(int mtu, int bufsize) { int ret = bufsize; - if (mtu >= BUF_SIZE_4KiB) + if (mtu >= BUF_SIZE_8KiB) + ret = BUF_SIZE_16KiB; + else if (mtu >= BUF_SIZE_4KiB) ret = BUF_SIZE_8KiB; else if (mtu >= BUF_SIZE_2KiB) ret = BUF_SIZE_4KiB; @@ -956,11 +958,11 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) if (priv->extend_desc) priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic, priv->use_riwt, priv->mode, - (i == DMA_RX_SIZE - 1)); + (i == DMA_RX_SIZE - 1), priv->dma_buf_sz); else priv->hw->desc->init_rx_desc(&priv->dma_rx[i], priv->use_riwt, priv->mode, - (i == DMA_RX_SIZE - 1)); + (i == DMA_RX_SIZE - 1), priv->dma_buf_sz); for (i = 0; i < DMA_TX_SIZE; i++) if (priv->extend_desc) priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, @@ -2479,7 +2481,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) wmb(); if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) - priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0); + priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0, priv->dma_buf_sz); else priv->hw->desc->set_rx_owner(p); @@ -2499,8 +2501,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) */ static int stmmac_rx(struct stmmac_priv *priv, int limit) { - unsigned int entry = priv->cur_rx; - unsigned int next_entry; + unsigned int next_entry = priv->cur_rx; unsigned int count = 0; int coe = priv->hw->rx_csum; @@ -2516,10 +2517,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true); } while (count < limit) { - int status; + int entry, status; struct dma_desc *p; struct dma_desc *np; + entry = next_entry; + if (priv->extend_desc) p = (struct dma_desc *)(priv->dma_erx + entry); else @@ -2584,7 +2587,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) priv->dev->name, frame_len, priv->dma_buf_sz); priv->dev->stats.rx_length_errors++; - break; + continue; } /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 @@ -2615,7 +2618,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) dev_warn(priv->device, "packet dropped\n"); priv->dev->stats.rx_dropped++; - break; + continue; } dma_sync_single_for_cpu(priv->device, @@ -2638,7 +2641,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) pr_err("%s: Inconsistent Rx chain\n", priv->dev->name); priv->dev->stats.rx_dropped++; - break; + continue; } prefetch(skb->data - NET_IP_ALIGN); priv->rx_skbuff[entry] = NULL; @@ -2672,7 +2675,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) priv->dev->stats.rx_packets++; priv->dev->stats.rx_bytes += frame_len; } - entry = next_entry; } stmmac_rx_refill(priv); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c index 3eb281d1db08a94ff76a3d3d21df367966a036d6..23133080903706d3c10426585536af471b135886 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c @@ -158,7 +158,7 @@ static int stmmac_enable(struct ptp_clock_info *ptp, /* structure describing a PTP hardware clock */ static struct ptp_clock_info stmmac_ptp_clock_ops = { .owner = THIS_MODULE, - .name = "stmmac_ptp_clock", + .name = "stmmac ptp", .max_adj = 62500000, .n_alarm = 0, .n_ext_ts = 0, diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 892b06852e150384a2140fb5b03b8cd749054e03..687f0c20b47f1fd0f2abe74a228b423fb6e79fe9 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -773,8 +773,8 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id) { struct cpsw_common *cpsw = dev_id; - cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX); writel(0, &cpsw->wr_regs->rx_en); + cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX); if (cpsw->quirk_irq) { disable_irq_nosync(cpsw->irqs_table[0]); diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index bbc983b04561ffab6f29cb0e0fc0a52560153256..3511d40ba3f1101bb02cd4e8f66ee0b12347937b 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -148,6 +148,9 @@ static int fjes_acpi_add(struct acpi_device *device) /* create platform_device */ plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource, ARRAY_SIZE(fjes_resource)); + if (IS_ERR(plat_dev)) + return PTR_ERR(plat_dev); + device->driver_data = plat_dev; return 0; diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 7e1df403a37da0b3e7be90d907d5716472dba3be..a9e8a7356c41d617a256ad365701ac236fe038ff 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -42,7 +42,6 @@ struct pdp_ctx { struct hlist_node hlist_addr; union { - u64 tid; struct { u64 tid; u16 flow; @@ -678,10 +677,13 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, if (err < 0) goto out_err; - if (!data[IFLA_GTP_PDP_HASHSIZE]) + if (!data[IFLA_GTP_PDP_HASHSIZE]) { hashsize = 1024; - else + } else { hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]); + if (!hashsize) + hashsize = 1024; + } err = gtp_hashtable_new(gtp, hashsize); if (err < 0) @@ -782,11 +784,13 @@ static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize) { int i; - gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL); + gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, + GFP_KERNEL | __GFP_NOWARN); if (gtp->addr_hash == NULL) return -ENOMEM; - gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL); + gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, + GFP_KERNEL | __GFP_NOWARN); if (gtp->tid_hash == NULL) goto err1; @@ -834,7 +838,9 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp, return -ENOENT; } - if (sock0->sk->sk_protocol != IPPROTO_UDP) { + if (sock0->sk->sk_protocol != IPPROTO_UDP || + sock0->sk->sk_type != SOCK_DGRAM || + (sock0->sk->sk_family != AF_INET && sock0->sk->sk_family != AF_INET6)) { netdev_dbg(dev, "socket fd=%d not UDP\n", fd_gtp0); err = -EINVAL; goto err1; @@ -1221,43 +1227,46 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb, struct netlink_callback *cb) { struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp; + int i, j, bucket = cb->args[0], skip = cb->args[1]; struct net *net = sock_net(skb->sk); - struct gtp_net *gn = net_generic(net, gtp_net_id); - unsigned long tid = cb->args[1]; - int i, k = cb->args[0], ret; struct pdp_ctx *pctx; + struct gtp_net *gn; + + gn = net_generic(net, gtp_net_id); if (cb->args[4]) return 0; + rcu_read_lock(); list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) { if (last_gtp && last_gtp != gtp) continue; else last_gtp = NULL; - for (i = k; i < gtp->hash_size; i++) { - hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) { - if (tid && tid != pctx->u.tid) - continue; - else - tid = 0; - - ret = gtp_genl_fill_info(skb, - NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, - cb->nlh->nlmsg_type, pctx); - if (ret < 0) { + for (i = bucket; i < gtp->hash_size; i++) { + j = 0; + hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], + hlist_tid) { + if (j >= skip && + gtp_genl_fill_info(skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + cb->nlh->nlmsg_type, pctx)) { cb->args[0] = i; - cb->args[1] = pctx->u.tid; + cb->args[1] = j; cb->args[2] = (unsigned long)gtp; goto out; } + j++; } + skip = 0; } + bucket = 0; } cb->args[4] = 1; out: + rcu_read_unlock(); return skb->len; } diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 470b3dcd54e5ba844aa64a11eeee3b0551d1b235..03c96a6cbafd8d64a85cf7f312d051705beb0d2c 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -665,10 +665,10 @@ static void sixpack_close(struct tty_struct *tty) { struct sixpack *sp; - write_lock_bh(&disc_data_lock); + write_lock_irq(&disc_data_lock); sp = tty->disc_data; tty->disc_data = NULL; - write_unlock_bh(&disc_data_lock); + write_unlock_irq(&disc_data_lock); if (!sp) return; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index e0a6b1a0ca887a53279d5690de6f14f628b0bf1f..088fe5d34f50002e7006cde7551bbd68eac691e7 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -783,10 +783,10 @@ static void mkiss_close(struct tty_struct *tty) { struct mkiss *ax; - write_lock_bh(&disc_data_lock); + write_lock_irq(&disc_data_lock); ax = tty->disc_data; tty->disc_data = NULL; - write_unlock_bh(&disc_data_lock); + write_unlock_irq(&disc_data_lock); if (!ax) return; diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index c747ab65266559fdb6dff77eb8078a4885c9a7ef..6c0982a39486a95f331994db88405a80ca9daff1 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -251,6 +251,7 @@ void ipvlan_process_multicast(struct work_struct *work) } else { kfree_skb(skb); } + cond_resched(); } } @@ -443,19 +444,21 @@ static int ipvlan_process_outbound(struct sk_buff *skb) struct ethhdr *ethh = eth_hdr(skb); int ret = NET_XMIT_DROP; - /* In this mode we dont care about multicast and broadcast traffic */ - if (is_multicast_ether_addr(ethh->h_dest)) { - pr_warn_ratelimited("Dropped {multi|broad}cast of type= [%x]\n", - ntohs(skb->protocol)); - kfree_skb(skb); - goto out; - } - /* The ipvlan is a pseudo-L2 device, so the packets that we receive * will have L2; which need to discarded and processed further * in the net-ns of the main-device. */ if (skb_mac_header_was_set(skb)) { + /* In this mode we dont care about + * multicast and broadcast traffic */ + if (is_multicast_ether_addr(ethh->h_dest)) { + pr_debug_ratelimited( + "Dropped {multi|broad}cast of type=[%x]\n", + ntohs(skb->protocol)); + kfree_skb(skb); + goto out; + } + skb_pull(skb, sizeof(*ethh)); skb->mac_header = (typeof(skb->mac_header))~0U; skb_reset_network_header(skb); diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 72fb55ca27f32aec1dcb0b7378c6209a655ae190..72f37e546ed242dd0bc244d593557a4d2bbfe2ce 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -217,7 +217,6 @@ static void ipvlan_uninit(struct net_device *dev) static int ipvlan_open(struct net_device *dev) { struct ipvl_dev *ipvlan = netdev_priv(dev); - struct net_device *phy_dev = ipvlan->phy_dev; struct ipvl_addr *addr; if (ipvlan->port->mode == IPVLAN_MODE_L3 || @@ -229,7 +228,7 @@ static int ipvlan_open(struct net_device *dev) list_for_each_entry(addr, &ipvlan->addrs, anode) ipvlan_ht_addr_add(ipvlan, addr); - return dev_uc_add(phy_dev, phy_dev->dev_addr); + return 0; } static int ipvlan_stop(struct net_device *dev) @@ -241,8 +240,6 @@ static int ipvlan_stop(struct net_device *dev) dev_uc_unsync(phy_dev, dev); dev_mc_unsync(phy_dev, dev); - dev_uc_del(phy_dev, phy_dev->dev_addr); - list_for_each_entry(addr, &ipvlan->addrs, anode) ipvlan_ht_addr_del(addr); diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index a48ed0873cc72383da8b2e5a42b54143b6a10222..8c64b06cb98c886484135e08410df1ed01c8c6fb 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2871,6 +2871,11 @@ static void macsec_dev_set_rx_mode(struct net_device *dev) dev_uc_sync(real_dev, dev); } +static sci_t dev_to_sci(struct net_device *dev, __be16 port) +{ + return make_sci(dev->dev_addr, port); +} + static int macsec_set_mac_address(struct net_device *dev, void *p) { struct macsec_dev *macsec = macsec_priv(dev); @@ -2892,6 +2897,7 @@ static int macsec_set_mac_address(struct net_device *dev, void *p) out: ether_addr_copy(dev->dev_addr, addr->sa_data); + macsec->secy.sci = dev_to_sci(dev, MACSEC_PORT_ES); return 0; } @@ -2976,6 +2982,7 @@ static const struct device_type macsec_type = { static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = { [IFLA_MACSEC_SCI] = { .type = NLA_U64 }, + [IFLA_MACSEC_PORT] = { .type = NLA_U16 }, [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 }, [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 }, [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 }, @@ -3160,11 +3167,6 @@ static bool sci_exists(struct net_device *dev, sci_t sci) return false; } -static sci_t dev_to_sci(struct net_device *dev, __be16 port) -{ - return make_sci(dev->dev_addr, port); -} - static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len) { struct macsec_dev *macsec = macsec_priv(dev); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index b1dcc7448b4ffd8f9efa51b263e98c008c06e3ac..2948816214304f3490fec720d2cd7a756036d7f9 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -309,6 +309,8 @@ static void macvlan_process_broadcast(struct work_struct *w) if (src) dev_put(src->dev); kfree_skb(skb); + + cond_resched(); } } @@ -487,10 +489,11 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) const struct macvlan_dev *dest; if (vlan->mode == MACVLAN_MODE_BRIDGE) { - const struct ethhdr *eth = (void *)skb->data; + const struct ethhdr *eth = skb_eth_hdr(skb); /* send to other bridge ports directly */ if (is_multicast_ether_addr(eth->h_dest)) { + skb_reset_mac_header(skb); macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE); goto xmit_world; } diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index eb51672106811e35ee0a7b3f0578560e16bc3670..3ab2eb677a599d9bb6aba0750f808ea73d639bca 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -67,11 +67,11 @@ static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) do { s = read_seqcount_begin(&fp->seqcount); /* Issue callback if user registered it. */ - if (fp->link_update) { + if (fp->link_update) fp->link_update(fp->phydev->attached_dev, &fp->status); - fixed_phy_update(fp); - } + /* Check the GPIO for change in status */ + fixed_phy_update(fp); state = fp->status; } while (read_seqcount_retry(&fp->seqcount, s)); diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c index 46fe1ae919a30a9a9b7644b5862f4a5bfa0b56ef..51ce3ea17fb37f0533bb1dae3ad76e5797d24976 100644 --- a/drivers/net/phy/mdio-bcm-iproc.c +++ b/drivers/net/phy/mdio-bcm-iproc.c @@ -188,6 +188,23 @@ static int iproc_mdio_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +int iproc_mdio_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iproc_mdio_priv *priv = platform_get_drvdata(pdev); + + /* restore the mii clock configuration */ + iproc_mdio_config_clk(priv->base); + + return 0; +} + +static const struct dev_pm_ops iproc_mdio_pm_ops = { + .resume = iproc_mdio_resume +}; +#endif /* CONFIG_PM_SLEEP */ + static const struct of_device_id iproc_mdio_of_match[] = { { .compatible = "brcm,iproc-mdio", }, { /* sentinel */ }, @@ -198,6 +215,9 @@ static struct platform_driver iproc_mdio_driver = { .driver = { .name = "iproc-mdio", .of_match_table = iproc_mdio_of_match, +#ifdef CONFIG_PM_SLEEP + .pm = &iproc_mdio_pm_ops, +#endif }, .probe = iproc_mdio_probe, .remove = iproc_mdio_remove, diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 5fde8e335f13980a647695ffb574ea92500682bb..82a4487bc66e5a4897832632466d5c3bd19d5827 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -463,7 +463,8 @@ int phy_ethtool_ksettings_get(struct phy_device *phydev, cmd->base.port = PORT_BNC; else cmd->base.port = PORT_MII; - + cmd->base.transceiver = phy_is_internal(phydev) ? + XCVR_INTERNAL : XCVR_EXTERNAL; cmd->base.phy_address = phydev->mdio.addr; cmd->base.autoneg = phydev->autoneg; cmd->base.eth_tp_mdix_ctrl = phydev->mdix; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 5c2c72b1ef8b44c78c24065469ce173d9d144d24..2f55873060220aa44df7d5141a108092ab345b10 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -95,7 +95,7 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) * MDIO bus driver and clock gated at this point. */ if (!netdev) - return !phydev->suspended; + goto out; /* Don't suspend PHY if the attached netdev parent may wakeup. * The parent may point to a PCI device, as in tg3 driver. @@ -110,7 +110,8 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) if (device_may_wakeup(&netdev->dev)) return false; - return true; +out: + return !phydev->suspended; } static int mdio_bus_phy_suspend(struct device *dev) @@ -128,6 +129,8 @@ static int mdio_bus_phy_suspend(struct device *dev) if (!mdio_bus_phy_may_suspend(phydev)) return 0; + phydev->suspended_by_mdio_bus = true; + return phy_suspend(phydev); } @@ -136,9 +139,11 @@ static int mdio_bus_phy_resume(struct device *dev) struct phy_device *phydev = to_phy_device(dev); int ret; - if (!mdio_bus_phy_may_suspend(phydev)) + if (!phydev->suspended_by_mdio_bus) goto no_resume; + phydev->suspended_by_mdio_bus = false; + ret = phy_resume(phydev); if (ret < 0) return ret; @@ -324,8 +329,8 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, mdiodev->device_free = phy_mdio_device_free; mdiodev->device_remove = phy_mdio_device_remove; - dev->speed = 0; - dev->duplex = -1; + dev->speed = SPEED_UNKNOWN; + dev->duplex = DUPLEX_UNKNOWN; dev->pause = 0; dev->asym_pause = 0; dev->link = 1; diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c index 6d8e06e05882415fab7ff8b6217ddde02c415963..a27ecd6662ceece5c006528332825e8c78220024 100644 --- a/drivers/net/ppp/ppp_async.c +++ b/drivers/net/ppp/ppp_async.c @@ -878,15 +878,15 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2); if (!skb) goto nomem; - ap->rpkt = skb; - } - if (skb->len == 0) { - /* Try to get the payload 4-byte aligned. - * This should match the - * PPP_ALLSTATIONS/PPP_UI/compressed tests in - * process_input_packet, but we do not have - * enough chars here to test buf[1] and buf[2]. - */ + ap->rpkt = skb; + } + if (skb->len == 0) { + /* Try to get the payload 4-byte aligned. + * This should match the + * PPP_ALLSTATIONS/PPP_UI/compressed tests in + * process_input_packet, but we do not have + * enough chars here to test buf[1] and buf[2]. + */ if (buf[0] != PPP_ALLSTATIONS) skb_reserve(skb, 2 + (buf[0] & 1)); } diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index ddceed3c5a4aa6d247b21850d28ba8326da8df5c..a516470da015311d73f4d54fd85f921b308565c4 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -232,7 +232,7 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, register struct cstate *cs = lcs->next; register unsigned long deltaS, deltaA; register short changes = 0; - int hlen; + int nlen, hlen; unsigned char new_seq[16]; register unsigned char *cp = new_seq; struct iphdr *ip; @@ -248,6 +248,8 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, return isize; ip = (struct iphdr *) icp; + if (ip->version != 4 || ip->ihl < 5) + return isize; /* Bail if this packet isn't TCP, or is an IP fragment */ if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) { @@ -258,10 +260,14 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, comp->sls_o_tcp++; return isize; } - /* Extract TCP header */ + nlen = ip->ihl * 4; + if (isize < nlen + sizeof(*th)) + return isize; - th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4); - hlen = ip->ihl*4 + th->doff*4; + th = (struct tcphdr *)(icp + nlen); + if (th->doff < sizeof(struct tcphdr) / 4) + return isize; + hlen = nlen + th->doff * 4; /* Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or * some other control bit is set). Also uncompressible if diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 7ec96c3e38a63f1c5ebc6747111c19eb81b96311..cc841126147ec36327912ad2fb254fb378d62e86 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -452,9 +452,16 @@ static void slip_transmit(struct work_struct *work) */ static void slip_write_wakeup(struct tty_struct *tty) { - struct slip *sl = tty->disc_data; + struct slip *sl; + + rcu_read_lock(); + sl = rcu_dereference(tty->disc_data); + if (!sl) + goto out; schedule_work(&sl->tx_work); +out: + rcu_read_unlock(); } static void sl_tx_timeout(struct net_device *dev) @@ -861,7 +868,6 @@ static int slip_open(struct tty_struct *tty) tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); sl_free_netdev(sl->dev); - free_netdev(sl->dev); err_exit: rtnl_unlock(); @@ -887,10 +893,11 @@ static void slip_close(struct tty_struct *tty) return; spin_lock_bh(&sl->lock); - tty->disc_data = NULL; + rcu_assign_pointer(tty->disc_data, NULL); sl->tty = NULL; spin_unlock_bh(&sl->lock); + synchronize_rcu(); flush_work(&sl->tx_work); /* VSV = very important to remove timers */ diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index fd2573cca803b90211865e480062ab84934a3524..d0c18e3557f1c8272f82f3bf46bf51f141d028a2 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2216,6 +2216,8 @@ team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = { [TEAM_ATTR_OPTION_CHANGED] = { .type = NLA_FLAG }, [TEAM_ATTR_OPTION_TYPE] = { .type = NLA_U8 }, [TEAM_ATTR_OPTION_DATA] = { .type = NLA_BINARY }, + [TEAM_ATTR_OPTION_PORT_IFINDEX] = { .type = NLA_U32 }, + [TEAM_ATTR_OPTION_ARRAY_INDEX] = { .type = NLA_U32 }, }; static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 134c59c9c20dccfcf4d5e852fac0cdc61a7a439a..fbd8ffe34e878ef5c73d4c4e65611f11ab7dcbdd 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1106,6 +1106,13 @@ static void tun_net_init(struct net_device *dev) } } +static bool tun_sock_writeable(struct tun_struct *tun, struct tun_file *tfile) +{ + struct sock *sk = tfile->socket.sk; + + return (tun->dev->flags & IFF_UP) && sock_writeable(sk); +} + /* Character device part */ /* Poll */ @@ -1128,10 +1135,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table *wait) if (!skb_array_empty(&tfile->tx_array)) mask |= POLLIN | POLLRDNORM; - if (tun->dev->flags & IFF_UP && - (sock_writeable(sk) || - (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) && - sock_writeable(sk)))) + /* Make sure SOCKWQ_ASYNC_NOSPACE is set if not writable to + * guarantee EPOLLOUT to be raised by either here or + * tun_sock_write_space(). Then process could get notification + * after it writes to a down device and meets -EIO. + */ + if (tun_sock_writeable(tun, tfile) || + (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) && + tun_sock_writeable(tun, tfile))) mask |= POLLOUT | POLLWRNORM; if (tun->dev->reg_state != NETREG_REGISTERED) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 32a24932715a07b247790a46332c6658429ca96c..075d7e50a52e9a135e57404f9fd78de204774b0f 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include "lan78xx.h" @@ -442,7 +443,7 @@ static int lan78xx_read_stats(struct lan78xx_net *dev, } } else { netdev_warn(dev->net, - "Failed to read stat ret = 0x%x", ret); + "Failed to read stat ret = %d", ret); } kfree(stats); @@ -1769,6 +1770,7 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev) dev->mdiobus->read = lan78xx_mdiobus_read; dev->mdiobus->write = lan78xx_mdiobus_write; dev->mdiobus->name = "lan78xx-mdiobus"; + dev->mdiobus->parent = &dev->udev->dev; snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", dev->udev->bus->busnum, dev->udev->devnum); @@ -2412,11 +2414,6 @@ static int lan78xx_stop(struct net_device *net) return 0; } -static int lan78xx_linearize(struct sk_buff *skb) -{ - return skb_linearize(skb); -} - static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev, struct sk_buff *skb, gfp_t flags) { @@ -2427,8 +2424,10 @@ static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev, return NULL; } - if (lan78xx_linearize(skb) < 0) + if (skb_linearize(skb)) { + dev_kfree_skb_any(skb); return NULL; + } tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN_MASK_) | TX_CMD_A_FCS_; @@ -3299,6 +3298,19 @@ static void lan78xx_tx_timeout(struct net_device *net) tasklet_schedule(&dev->bh); } +static netdev_features_t lan78xx_features_check(struct sk_buff *skb, + struct net_device *netdev, + netdev_features_t features) +{ + if (skb->len + TX_OVERHEAD > MAX_SINGLE_PACKET_SIZE) + features &= ~NETIF_F_GSO_MASK; + + features = vlan_features_check(skb, features); + features = vxlan_features_check(skb, features); + + return features; +} + static const struct net_device_ops lan78xx_netdev_ops = { .ndo_open = lan78xx_open, .ndo_stop = lan78xx_stop, @@ -3312,6 +3324,7 @@ static const struct net_device_ops lan78xx_netdev_ops = { .ndo_set_features = lan78xx_set_features, .ndo_vlan_rx_add_vid = lan78xx_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = lan78xx_vlan_rx_kill_vid, + .ndo_features_check = lan78xx_features_check, }; static void lan78xx_stat_monitor(unsigned long param) @@ -3383,6 +3396,7 @@ static int lan78xx_probe(struct usb_interface *intf, if (netdev->mtu > (dev->hard_mtu - netdev->hard_header_len)) netdev->mtu = dev->hard_mtu - netdev->hard_header_len; + netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER); dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0; dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index de7b431fdd6b5ce182e8dca6dc4f677fe9bab38b..97f6b8130db3376c419c942a1fc8d119071bde92 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -951,6 +951,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */ {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ + {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e preproduction config */ {QMI_FIXED_INTF(0x413c, 0x81e0, 0)}, /* Dell Wireless 5821e with eSIM support*/ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 15dc70c11857978b9b11e38b7a993560522b5dbe..6e74965d26a0a34fd68597b137f91f6e24ec6ca2 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -3423,7 +3423,10 @@ static void r8153_init(struct r8152 *tp) if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & AUTOLOAD_DONE) break; + msleep(20); + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + break; } for (i = 0; i < 500; i++) { @@ -3447,7 +3450,10 @@ static void r8153_init(struct r8152 *tp) ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK; if (ocp_data == PHY_STAT_LAN_ON) break; + msleep(20); + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + break; } usb_disable_lpm(tp->udev); @@ -4365,6 +4371,9 @@ static int rtl8152_probe(struct usb_interface *intf, return -ENODEV; } + if (intf->cur_altsetting->desc.bNumEndpoints < 3) + return -ENODEV; + usb_reset_device(udev); netdev = alloc_etherdev(sizeof(struct r8152)); if (!netdev) { @@ -4438,6 +4447,11 @@ static int rtl8152_probe(struct usb_interface *intf, intf->needs_remote_wakeup = 1; + if (!rtl_can_wakeup(tp)) + __rtl_set_wol(tp, 0); + else + tp->saved_wolopts = __rtl_get_wol(tp); + tp->rtl_ops.init(tp); queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0); set_ethernet_addr(tp); @@ -4451,10 +4465,6 @@ static int rtl8152_probe(struct usb_interface *intf, goto out1; } - if (!rtl_can_wakeup(tp)) - __rtl_set_wol(tp, 0); - - tp->saved_wolopts = __rtl_get_wol(tp); if (tp->saved_wolopts) device_set_wakeup_enable(&udev->dev, true); else diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 340bd98b8dbd74a77df759b84c133c02867bcc2e..987bb1db8265d339fac547dc0ec76b9abac6a33b 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2104,7 +2104,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) df = htons(IP_DF); - tos = ip_tunnel_ecn_encap(tos, old_iph, skb); + tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); err = vxlan_build_skb(skb, &rt->dst, sizeof(struct iphdr), vni, md, flags, udp_sum); @@ -2163,7 +2163,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (!info) udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); - tos = ip_tunnel_ecn_encap(tos, old_iph, skb); + tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb); ttl = ttl ? : ip6_dst_hoplimit(ndst); skb_scrub_packet(skb, xnet); err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr), diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index b2c1e872d5ed5d6348fa118a8378856bef8813b5..87bf05a81db50f88f07b2a2eb1f56d5d4f3d506c 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -77,7 +77,7 @@ static struct ucc_tdm_info utdm_primary_info = { }, }; -static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM]; +static struct ucc_tdm_info utdm_info[UCC_MAX_NUM]; static int uhdlc_init(struct ucc_hdlc_private *priv) { @@ -209,6 +209,11 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) ret = -ENOMEM; goto free_riptr; } + if (riptr != (u16)riptr || tiptr != (u16)tiptr) { + dev_err(priv->dev, "MURAM allocation out of addressable range\n"); + ret = -ENOMEM; + goto free_tiptr; + } /* Set RIPTR, TIPTR */ iowrite16be(riptr, &priv->ucc_pram->riptr); diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index e7bbdb7af53ac7dcbdd21d12705613054efe8626..97968e6a6a4ebef00859a9d1f96e67c8c4eb289a 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -261,7 +261,7 @@ struct port { struct hss_plat_info *plat; buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; struct desc *desc_tab; /* coherent */ - u32 desc_tab_phys; + dma_addr_t desc_tab_phys; unsigned int id; unsigned int clock_type, clock_rate, loopback; unsigned int initialized, carrier; @@ -861,7 +861,7 @@ static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_dropped++; return NETDEV_TX_OK; } - memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); + memcpy_swab32(mem, (u32 *)((uintptr_t)skb->data & ~3), bytes / 4); dev_kfree_skb(skb); #endif diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 421ac5f856994731fc7a0f3752c32dcebda15bf1..79fd891509479e33629c4ca494c46b5fc5a09d43 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -711,7 +711,7 @@ static netdev_tx_t sdla_transmit(struct sk_buff *skb, spin_lock_irqsave(&sdla_lock, flags); SDLA_WINDOW(dev, addr); - pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK)); + pbuf = (void *)(dev->mem_start + (addr & SDLA_ADDR_MASK)); __sdla_write(dev, pbuf->buf_addr, skb->data, skb->len); SDLA_WINDOW(dev, addr); pbuf->opp_flag = 1; diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c index b0dba35a8ad2ae94e4cf89d78767156616fee59c..dc6fe93ce71f65e9e60491fbf4cc45ecde6174a2 100644 --- a/drivers/net/wimax/i2400m/op-rfkill.c +++ b/drivers/net/wimax/i2400m/op-rfkill.c @@ -147,6 +147,7 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, error_alloc: d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n", wimax_dev, state, result); + kfree(cmd); return result; } diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 7a60d2e652dad6be1cab67ef64b708355e982ded..e492c7f0d311ac86b0864d09f992db774fea9c60 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -255,7 +255,8 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, if (flags & AR5523_CMD_FLAG_MAGIC) hdr->magic = cpu_to_be32(1 << 24); - memcpy(hdr + 1, idata, ilen); + if (ilen) + memcpy(hdr + 1, idata, ilen); cmd->odata = odata; cmd->olen = olen; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index d84a362a084ac2a85ce49e46eaf766313fc9b2e1..d96e062647fd909eabed3e59fe4ab924d5f9440f 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1765,6 +1765,11 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n"); + ath10k_pci_irq_disable(ar); + ath10k_pci_irq_sync(ar); + napi_synchronize(&ar->napi); + napi_disable(&ar->napi); + /* Most likely the device has HTT Rx ring configured. The only way to * prevent the device from accessing (and possible corrupting) host * memory is to reset the chip now. @@ -1778,10 +1783,6 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) */ ath10k_pci_safe_chip_reset(ar); - ath10k_pci_irq_disable(ar); - ath10k_pci_irq_sync(ar); - napi_synchronize(&ar->napi); - napi_disable(&ar->napi); ath10k_pci_flush(ar); spin_lock_irqsave(&ar_pci->ps_lock, flags); diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 9852c5d51139ebdaabcd943463afd258a818bde1..beeb6be06939b11ed7be80233470c1d5fc9d49ae 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -99,6 +99,8 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, info = IEEE80211_SKB_CB(msdu); memset(&info->status, 0, sizeof(info->status)); + info->status.rates[0].idx = -1; + trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) { diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c index 6e236a4854311cc972b97ccda8e782392bf9a2e3..71b4888b30e717fd590288f530e64837aec44afd 100644 --- a/drivers/net/wireless/ath/ath9k/dynack.c +++ b/drivers/net/wireless/ath/ath9k/dynack.c @@ -300,9 +300,9 @@ void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an) an->ackto = ackto; - spin_lock(&da->qlock); + spin_lock_bh(&da->qlock); list_add_tail(&an->list, &da->nodes); - spin_unlock(&da->qlock); + spin_unlock_bh(&da->qlock); } EXPORT_SYMBOL(ath_dynack_node_init); @@ -316,9 +316,9 @@ void ath_dynack_node_deinit(struct ath_hw *ah, struct ath_node *an) { struct ath_dynack *da = &ah->dynack; - spin_lock(&da->qlock); + spin_lock_bh(&da->qlock); list_del(&an->list); - spin_unlock(&da->qlock); + spin_unlock_bh(&da->qlock); } EXPORT_SYMBOL(ath_dynack_node_deinit); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index f15589c70284bd56e3ec09821153b13d51624cf7..b5e12be73f2b3da695401d50e24c192ad1c93be2 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1213,7 +1213,7 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context) static int send_eject_command(struct usb_interface *interface) { struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *iface_desc = &interface->altsetting[0]; + struct usb_host_interface *iface_desc = interface->cur_altsetting; struct usb_endpoint_descriptor *endpoint; unsigned char *cmd; u8 bulk_out_ep; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index f333ef1e3e7b4171cbe0ff37a21c43f87f4937b3..52b42ecee6212c282fe1064179a213ce65af8447 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -972,6 +972,8 @@ 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; + bool is_phyerr; if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { ath_err(common, "Corrupted RX frame, dropping (len: %d)\n", @@ -981,11 +983,24 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, rxstatus = (struct ath_htc_rx_status *)skb->data; - if (be16_to_cpu(rxstatus->rs_datalen) - - (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { + rs_datalen = be16_to_cpu(rxstatus->rs_datalen); + if (unlikely(rs_datalen - + (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0)) { ath_err(common, "Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n", - rxstatus->rs_datalen, skb->len); + rs_datalen, skb->len); + goto rx_next; + } + + is_phyerr = rxstatus->rs_status & ATH9K_RXERR_PHY; + /* + * Discard zero-length packets and packets smaller than an ACK + * which are not PHY_ERROR (short radar pulses have a length of 3) + */ + if (unlikely(!rs_datalen || (rs_datalen < 10 && !is_phyerr))) { + ath_warn(common, + "Short RX data len, dropping (dlen: %d)\n", + rs_datalen); goto rx_next; } @@ -1010,7 +1025,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, * Process PHY errors and return so that the packet * can be dropped. */ - if (rx_stats.rs_status & ATH9K_RXERR_PHY) { + if (unlikely(is_phyerr)) { /* TODO: Not using DFS processing now. */ if (ath_cmn_process_fft(&priv->spec_priv, hdr, &rx_stats, rx_status->mactime)) { diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index 83770d2ea057875ddd75ffb312e9b2f3d28e5e9f..9da8bd7927022c88868b5c5b6931872295a514cf 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -1304,8 +1304,9 @@ static void handle_irq_ucode_debug(struct b43legacy_wldev *dev) } /* Interrupt handler bottom-half */ -static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev) +static void b43legacy_interrupt_tasklet(unsigned long data) { + struct b43legacy_wldev *dev = (struct b43legacy_wldev *)data; u32 reason; u32 dma_reason[ARRAY_SIZE(dev->dma_reason)]; u32 merged_dma_reason = 0; @@ -3775,7 +3776,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev, b43legacy_set_status(wldev, B43legacy_STAT_UNINIT); wldev->bad_frames_preempt = modparam_bad_frames_preempt; tasklet_init(&wldev->isr_tasklet, - (void (*)(unsigned long))b43legacy_interrupt_tasklet, + b43legacy_interrupt_tasklet, (unsigned long)wldev); if (modparam_pio) wldev->__using_pio = true; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index de52d826eb248353e40d1c70cd91156def639df4..998a4bd6db78a919e615a99f079f4625b1c2cd32 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1921,6 +1921,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) BRCMF_SDIO_FT_NORMAL)) { rd->len = 0; brcmu_pkt_buf_free_skb(pkt); + continue; } bus->sdcnt.rx_readahead_cnt++; if (rd->len != roundup(rd_new.len, 16)) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index acf513fd9e6d5aeef3170aa68f1497f228198477..31727f34381fe8e7e34f63974a5ea955596282d1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -438,6 +438,7 @@ brcmf_usbdev_qinit(struct list_head *q, int qsize) usb_free_urb(req->urb); list_del(q->next); } + kfree(reqs); return NULL; } @@ -1330,7 +1331,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) goto fail; } - desc = &intf->altsetting[0].desc; + desc = &intf->cur_altsetting->desc; if ((desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || (desc->bInterfaceSubClass != 2) || (desc->bInterfaceProtocol != 0xff)) { @@ -1343,7 +1344,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) num_of_eps = desc->bNumEndpoints; for (ep = 0; ep < num_of_eps; ep++) { - endpoint = &intf->altsetting[0].endpoint[ep].desc; + endpoint = &intf->cur_altsetting->endpoint[ep].desc; endpoint_num = usb_endpoint_num(endpoint); if (!usb_endpoint_xfer_bulk(endpoint)) continue; diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 04939e576ee022ceec788224da8a177dd89a890d..a8d470010f5ea231abb67ce2e6fd81d210ef70b8 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -7796,16 +7796,8 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { case AIROGVLIST: ridcode = RID_APLIST; break; case AIROGDRVNAM: ridcode = RID_DRVNAME; break; case AIROGEHTENC: ridcode = RID_ETHERENCAP; break; - case AIROGWEPKTMP: ridcode = RID_WEP_TEMP; - /* Only super-user can read WEP keys */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - break; - case AIROGWEPKNV: ridcode = RID_WEP_PERM; - /* Only super-user can read WEP keys */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - break; + case AIROGWEPKTMP: ridcode = RID_WEP_TEMP; break; + case AIROGWEPKNV: ridcode = RID_WEP_PERM; break; case AIROGSTAT: ridcode = RID_STATUS; break; case AIROGSTATSD32: ridcode = RID_STATSDELTA; break; case AIROGSTATSC32: ridcode = RID_STATS; break; @@ -7819,7 +7811,13 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { return -EINVAL; } - if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL) + if (ridcode == RID_WEP_TEMP || ridcode == RID_WEP_PERM) { + /* Only super-user can read WEP keys */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + } + + if ((iobuf = kzalloc(RIDSIZE, GFP_KERNEL)) == NULL) return -ENOMEM; PC4500_readrid(ai,ridcode,iobuf,RIDSIZE, 1); diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index dc49be308170300dc173bf5b008c5151c4e66a05..607369dede2dd003edfce434791de1d0484e2477 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -2155,8 +2155,8 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv) mhi_ctrl->iova_stop = pci_priv->smmu_iova_start + pci_priv->smmu_iova_len; } else { - mhi_ctrl->iova_start = memblock_start_of_DRAM(); - mhi_ctrl->iova_stop = memblock_end_of_DRAM(); + mhi_ctrl->iova_start = 0; + mhi_ctrl->iova_stop = (dma_addr_t)U64_MAX; } mhi_ctrl->link_status = cnss_mhi_link_status; diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index bfa542c8d6f1a2b4f98ac2c419326ceb3ac7a17d..86c84b11218db1a78bf605843806ee08f3006adf 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -3220,8 +3220,9 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) } } -static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) +static void ipw2100_irq_tasklet(unsigned long data) { + struct ipw2100_priv *priv = (struct ipw2100_priv *)data; struct net_device *dev = priv->net_dev; unsigned long flags; u32 inta, tmp; @@ -6029,7 +6030,7 @@ static void ipw2100_rf_kill(struct work_struct *work) spin_unlock_irqrestore(&priv->low_lock, flags); } -static void ipw2100_irq_tasklet(struct ipw2100_priv *priv); +static void ipw2100_irq_tasklet(unsigned long data); static const struct net_device_ops ipw2100_netdev_ops = { .ndo_open = ipw2100_open, @@ -6158,7 +6159,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); INIT_DELAYED_WORK(&priv->scan_event, ipw2100_scan_event); - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + tasklet_init(&priv->irq_tasklet, ipw2100_irq_tasklet, (unsigned long)priv); /* NOTE: We do not start the deferred work for status checks yet */ diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index bfd68612a535d6a8ec39307492131521e489c677..48edb2b6eb7d5c229567d0cbf396b4b641b27f7e 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -1968,8 +1968,9 @@ static void notify_wx_assoc_event(struct ipw_priv *priv) wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); } -static void ipw_irq_tasklet(struct ipw_priv *priv) +static void ipw_irq_tasklet(unsigned long data) { + struct ipw_priv *priv = (struct ipw_priv *)data; u32 inta, inta_mask, handled = 0; unsigned long flags; int rc = 0; @@ -10705,7 +10706,7 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate); #endif /* CONFIG_IPW2200_QOS */ - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + tasklet_init(&priv->irq_tasklet, ipw_irq_tasklet, (unsigned long)priv); return ret; diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c index 466912eb2d874a667fff2394022a748f943d3712..d853ccbf74cb28d510c5299cbca1e73dc72b7123 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c @@ -1399,8 +1399,9 @@ il3945_dump_nic_error_log(struct il_priv *il) } static void -il3945_irq_tasklet(struct il_priv *il) +il3945_irq_tasklet(unsigned long data) { + struct il_priv *il = (struct il_priv *)data; u32 inta, handled = 0; u32 inta_fh; unsigned long flags; @@ -3432,7 +3433,7 @@ il3945_setup_deferred_work(struct il_priv *il) setup_timer(&il->watchdog, il_bg_watchdog, (unsigned long)il); tasklet_init(&il->irq_tasklet, - (void (*)(unsigned long))il3945_irq_tasklet, + il3945_irq_tasklet, (unsigned long)il); } diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index a91d170a614b63181d6ca2c45a7038da2cb4fb4c..6c2dcd236713691d80df038741fe0b95b48ce0de 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -4361,8 +4361,9 @@ il4965_synchronize_irq(struct il_priv *il) } static void -il4965_irq_tasklet(struct il_priv *il) +il4965_irq_tasklet(unsigned long data) { + struct il_priv *il = (struct il_priv *)data; u32 inta, handled = 0; u32 inta_fh; unsigned long flags; @@ -6260,7 +6261,7 @@ il4965_setup_deferred_work(struct il_priv *il) setup_timer(&il->watchdog, il_bg_watchdog, (unsigned long)il); tasklet_init(&il->irq_tasklet, - (void (*)(unsigned long))il4965_irq_tasklet, + il4965_irq_tasklet, (unsigned long)il); } diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index 140b6ea8f7cc48c9e3ea3908a3c274359ac9eaba..db2373fe8ac32cca27b665a54eed035f29616396 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -717,7 +717,7 @@ il_eeprom_init(struct il_priv *il) u32 gp = _il_rd(il, CSR_EEPROM_GP); int sz; int ret; - u16 addr; + int addr; /* allocate eeprom */ sz = il->cfg->eeprom_size; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c index 1bbd17ada974723623acc6b1da53b77131f6121b..20e16c423990162798874847678af389e043fb05 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c @@ -185,6 +185,9 @@ void iwl_leds_init(struct iwl_priv *priv) priv->led.name = kasprintf(GFP_KERNEL, "%s-led", wiphy_name(priv->hw->wiphy)); + if (!priv->led.name) + return; + priv->led.brightness_set = iwl_led_brightness_set; priv->led.blink_set = iwl_led_blink_set; priv->led.max_brightness = 1; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 2ec3a91a0f6b618b60ceb832641f59f425d64d14..bba7ace1a744da0ee35ba877209db4e503508e1a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -106,12 +106,12 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) int i; struct iwl_rss_config_cmd cmd = { .flags = cpu_to_le32(IWL_RSS_ENABLE), - .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | - IWL_RSS_HASH_TYPE_IPV4_UDP | - IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | - IWL_RSS_HASH_TYPE_IPV6_TCP | - IWL_RSS_HASH_TYPE_IPV6_UDP | - IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, + .hash_mask = BIT(IWL_RSS_HASH_TYPE_IPV4_TCP) | + BIT(IWL_RSS_HASH_TYPE_IPV4_UDP) | + BIT(IWL_RSS_HASH_TYPE_IPV4_PAYLOAD) | + BIT(IWL_RSS_HASH_TYPE_IPV6_TCP) | + BIT(IWL_RSS_HASH_TYPE_IPV6_UDP) | + BIT(IWL_RSS_HASH_TYPE_IPV6_PAYLOAD), }; if (mvm->trans->num_rx_queues == 1) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c index 1e51fbe95f7c96c8cacd82d669a395f559de69bc..73c351a6418750684e60945ba0192c5fa41a7386 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c @@ -109,6 +109,9 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm) mvm->led.name = kasprintf(GFP_KERNEL, "%s-led", wiphy_name(mvm->hw->wiphy)); + if (!mvm->led.name) + return -ENOMEM; + mvm->led.brightness_set = iwl_led_brightness_set; mvm->led.max_brightness = 1; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 92557cd31a397bb2f1d8dd8fc6548935d651b39d..d91ab2b8d6671c9cf3e2b6d16b76ad3ab1e20b5b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -805,6 +805,21 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, !ieee80211_is_action(hdr->frame_control))) sta = NULL; + /* If there is no sta, and it's not offchannel - send through AP */ + if (info->control.vif->type == NL80211_IFTYPE_STATION && + info->hw_queue != IWL_MVM_OFFCHANNEL_QUEUE && !sta) { + struct iwl_mvm_vif *mvmvif = + iwl_mvm_vif_from_mac80211(info->control.vif); + u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id); + + if (ap_sta_id < IWL_MVM_STATION_COUNT) { + /* mac80211 holds rcu read lock */ + sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]); + if (IS_ERR_OR_NULL(sta)) + goto drop; + } + } + if (sta) { if (iwl_mvm_defer_tx(mvm, sta, skb)) return; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index b78e60eb600f1c54ad64e15bf3e67d4ea5e9c645..d0aa4d0a5537ecfb36fded81201cae5e213cfaca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -62,6 +62,7 @@ * (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 "iwl-trans.h" @@ -289,7 +290,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data; hdr = (struct ieee80211_hdr *)(pkt->data + sizeof(*rx_res)); len = le16_to_cpu(rx_res->byte_count); - rx_pkt_status = le32_to_cpup((__le32 *) + rx_pkt_status = get_unaligned_le32((__le32 *) (pkt->data + sizeof(*rx_res) + len)); /* Dont use dev_alloc_skb(), we'll have enough headroom once diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index c2bbc8c17beb98687a699d91ef6e4ae34293752d..bc06d87a0106cf0016562b94d912e1d230c34529 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -810,12 +810,12 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE; rx_status->flag |= RX_FLAG_AMPDU_DETAILS; - rx_status->ampdu_reference = mvm->ampdu_ref; /* toggle is switched whenever new aggregation starts */ if (toggle_bit != mvm->ampdu_toggle) { mvm->ampdu_ref++; mvm->ampdu_toggle = toggle_bit; } + rx_status->ampdu_reference = mvm->ampdu_ref; } rcu_read_lock(); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index c5203568a47ac171c6105d1a233cf8e37ed742e9..f0f205c3aadb72b16ce679563f8f538cb89d914f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -736,7 +736,8 @@ static struct thermal_zone_device_ops tzone_ops = { static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) { int i; - char name[] = "iwlwifi"; + char name[16]; + static atomic_t counter = ATOMIC_INIT(0); if (!iwl_mvm_is_tt_in_fw(mvm)) { mvm->tz_device.tzone = NULL; @@ -746,6 +747,7 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); + sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF); mvm->tz_device.tzone = thermal_zone_device_register(name, IWL_MAX_DTS_TRIPS, IWL_WRITABLE_TRIPS_MSK, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index a2ebe46bcfc5b89267d2ea77a92a0012230b3fc5..395bbe2c0f983a5767842ba944e8ac48b8fb6966 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -898,9 +898,13 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) return err; } def_rxq = trans_pcie->rxq; - if (!rba->alloc_wq) + if (!rba->alloc_wq) { rba->alloc_wq = alloc_workqueue("rb_allocator", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!rba->alloc_wq) + return -ENOMEM; + } + INIT_WORK(&rba->rx_alloc, iwl_pcie_rx_allocator_work); cancel_work_sync(&rba->rx_alloc); diff --git a/drivers/net/wireless/intersil/hostap/hostap_ap.c b/drivers/net/wireless/intersil/hostap/hostap_ap.c index c995ace153ee6ecd53dff68145543889f6bbb424..30171d4c471873027cec73310b45adf0a70eff3e 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_ap.c +++ b/drivers/net/wireless/intersil/hostap/hostap_ap.c @@ -2570,7 +2570,7 @@ static int prism2_hostapd_add_sta(struct ap_data *ap, sta->supported_rates[0] = 2; if (sta->tx_supp_rates & WLAN_RATE_2M) sta->supported_rates[1] = 4; - if (sta->tx_supp_rates & WLAN_RATE_5M5) + if (sta->tx_supp_rates & WLAN_RATE_5M5) sta->supported_rates[2] = 11; if (sta->tx_supp_rates & WLAN_RATE_11M) sta->supported_rates[3] = 22; diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c index bca6935a94db9a4bd767bfa0b7d2d7c82cd6b60c..4e91c74fcfad9ef107529a34516927f6e131c6f5 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c @@ -1351,7 +1351,8 @@ static int ezusb_init(struct hermes *hw) int retval; BUG_ON(in_interrupt()); - BUG_ON(!upriv); + if (!upriv) + return -EINVAL; upriv->reply_count = 0; /* Write the MAGIC number on the simulated registers to keep @@ -1601,9 +1602,9 @@ static int ezusb_probe(struct usb_interface *interface, /* set up the endpoint information */ /* check out the endpoints */ - iface_desc = &interface->altsetting[0].desc; + iface_desc = &interface->cur_altsetting->desc; for (i = 0; i < iface_desc->bNumEndpoints; ++i) { - ep = &interface->altsetting[0].endpoint[i].desc; + ep = &interface->cur_altsetting->endpoint[i].desc; if (usb_endpoint_is_bulk_in(ep)) { /* we found a bulk in endpoint */ diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c index 7ff2efadcecadc2001f9aad585be526635cdcaaa..ece6d72cf90c8a33b378f64b395db0c67476ef27 100644 --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c @@ -272,6 +272,10 @@ add_ie_rates(u8 *tlv, const u8 *ie, int *nrates) int hw, ap, ap_max = ie[1]; u8 hw_rate; + if (ap_max > MAX_RATES) { + lbs_deb_assoc("invalid rates\n"); + return tlv; + } /* Advance past IE header */ ie += 2; @@ -1789,6 +1793,9 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, struct cmd_ds_802_11_ad_hoc_join cmd; u8 preamble = RADIO_PREAMBLE_SHORT; int ret = 0; + int hw, i; + u8 rates_max; + u8 *rates; lbs_deb_enter(LBS_DEB_CFG80211); @@ -1849,9 +1856,14 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, if (!rates_eid) { lbs_add_rates(cmd.bss.rates); } else { - int hw, i; - u8 rates_max = rates_eid[1]; - u8 *rates = cmd.bss.rates; + rates_max = rates_eid[1]; + if (rates_max > MAX_RATES) { + lbs_deb_join("invalid rates"); + rcu_read_unlock(); + ret = -EINVAL; + goto out; + } + rates = cmd.bss.rates; for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { u8 hw_rate = lbs_rates[hw].bitrate / 5; for (i = 0; i < rates_max; i++) { diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index 06a57c70899202ce1a7818e952d02a3967cf08c7..44da911c9a1a8682ee6e3eb5ba75f597881f7936 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -1229,6 +1229,10 @@ static int if_sdio_probe(struct sdio_func *func, spin_lock_init(&card->lock); card->workqueue = alloc_workqueue("libertas_sdio", WQ_MEM_RECLAIM, 0); + if (unlikely(!card->workqueue)) { + ret = -ENOMEM; + goto err_queue; + } INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); init_waitqueue_head(&card->pwron_waitq); @@ -1282,6 +1286,7 @@ static int if_sdio_probe(struct sdio_func *func, lbs_remove_card(priv); free: destroy_workqueue(card->workqueue); +err_queue: while (card->packets) { packet = card->packets; card->packets = card->packets->next; diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c index 909ac3685010f116d160063a5e95ebcb2f34f358..2b193f1257a5ac6271af561573dba23449d26863 100644 --- a/drivers/net/wireless/marvell/libertas_tf/cmd.c +++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c @@ -69,7 +69,7 @@ static void lbtf_geo_init(struct lbtf_private *priv) break; } - for (ch = priv->range.start; ch < priv->range.end; ch++) + for (ch = range->start; ch < range->end; ch++) priv->channels[CHAN_TO_IDX(ch)].flags = 0; } diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index cb681b265b10806447bd56ea60a5c01e7c36fb56..d0743bd25ba95973bfcb1ee1f0c86aeab744b791 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -632,8 +632,11 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) skb_put(skb, MAX_EVENT_SIZE); if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, - PCI_DMA_FROMDEVICE)) + PCI_DMA_FROMDEVICE)) { + kfree_skb(skb); + kfree(card->evtbd_ring_vbase); return -1; + } buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); @@ -973,8 +976,10 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter) } skb_put(skb, MWIFIEX_UPLD_SIZE); if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, - PCI_DMA_FROMDEVICE)) + PCI_DMA_FROMDEVICE)) { + kfree_skb(skb); return -1; + } card->cmdrsp_buf = skb; diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 828c6f5eb83c853b73d44cd9326ad2904136e409..5fde2e2f1fea873f6b3d69907a7456f731d73370 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2878,6 +2878,13 @@ mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, vs_param_set->header.len = cpu_to_le16((((u16) priv->vs_ie[id].ie[1]) & 0x00FF) + 2); + if (le16_to_cpu(vs_param_set->header.len) > + MWIFIEX_MAX_VSIE_LEN) { + mwifiex_dbg(priv->adapter, ERROR, + "Invalid param length!\n"); + break; + } + memcpy(vs_param_set->ie, priv->vs_ie[id].ie, le16_to_cpu(vs_param_set->header.len)); *buffer += le16_to_cpu(vs_param_set->header.len) + diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 478885afb6c6bd6f1553ad07207356e6b778700d..f2d10ba19920834826d91128977fcb61756f16ce 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -271,6 +271,15 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, "11D: skip setting domain info in FW\n"); return 0; } + + if (country_ie_len > + (IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) { + rcu_read_unlock(); + mwifiex_dbg(priv->adapter, ERROR, + "11D: country_ie_len overflow!, deauth AP\n"); + return -EINVAL; + } + memcpy(priv->adapter->country_code, &country_ie[2], 2); domain_info->country_code[0] = country_ie[2]; @@ -314,8 +323,9 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, priv->scan_block = false; if (bss) { - if (adapter->region_code == 0x00) - mwifiex_process_country_ie(priv, bss); + if (adapter->region_code == 0x00 && + mwifiex_process_country_ie(priv, bss)) + return -EINVAL; /* Allocate and fill new bss descriptor */ bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index df9704de07150d82887de1db36c99fd15d3933f7..c6fc09d1746241ca331f42879d31da25902d5f6b 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -917,59 +917,117 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, switch (*pos) { case WLAN_EID_SUPP_RATES: + if (pos[1] > 32) + return; sta_ptr->tdls_cap.rates_len = pos[1]; for (i = 0; i < pos[1]; i++) sta_ptr->tdls_cap.rates[i] = pos[i + 2]; break; case WLAN_EID_EXT_SUPP_RATES: + if (pos[1] > 32) + return; basic = sta_ptr->tdls_cap.rates_len; + if (pos[1] > 32 - basic) + return; for (i = 0; i < pos[1]; i++) sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2]; sta_ptr->tdls_cap.rates_len += pos[1]; break; case WLAN_EID_HT_CAPABILITY: - memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos, + if (pos > end - sizeof(struct ieee80211_ht_cap) - 2) + return; + if (pos[1] != sizeof(struct ieee80211_ht_cap)) + return; + /* copy the ie's value into ht_capb*/ + memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2, sizeof(struct ieee80211_ht_cap)); sta_ptr->is_11n_enabled = 1; break; case WLAN_EID_HT_OPERATION: - memcpy(&sta_ptr->tdls_cap.ht_oper, pos, + if (pos > end - + sizeof(struct ieee80211_ht_operation) - 2) + return; + if (pos[1] != sizeof(struct ieee80211_ht_operation)) + return; + /* copy the ie's value into ht_oper*/ + memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2, sizeof(struct ieee80211_ht_operation)); break; case WLAN_EID_BSS_COEX_2040: + if (pos > end - 3) + return; + if (pos[1] != 1) + return; sta_ptr->tdls_cap.coex_2040 = pos[2]; break; case WLAN_EID_EXT_CAPABILITY: + if (pos > end - sizeof(struct ieee_types_header)) + return; + if (pos[1] < sizeof(struct ieee_types_header)) + return; + if (pos[1] > 8) + return; memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos, sizeof(struct ieee_types_header) + min_t(u8, pos[1], 8)); break; case WLAN_EID_RSN: + if (pos > end - sizeof(struct ieee_types_header)) + return; + if (pos[1] < sizeof(struct ieee_types_header)) + return; + if (pos[1] > IEEE_MAX_IE_SIZE - + sizeof(struct ieee_types_header)) + return; memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos, sizeof(struct ieee_types_header) + min_t(u8, pos[1], IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header))); break; case WLAN_EID_QOS_CAPA: + if (pos > end - 3) + return; + if (pos[1] != 1) + return; sta_ptr->tdls_cap.qos_info = pos[2]; break; case WLAN_EID_VHT_OPERATION: - if (priv->adapter->is_hw_11ac_capable) - memcpy(&sta_ptr->tdls_cap.vhtoper, pos, + if (priv->adapter->is_hw_11ac_capable) { + if (pos > end - + sizeof(struct ieee80211_vht_operation) - 2) + return; + if (pos[1] != + sizeof(struct ieee80211_vht_operation)) + return; + /* copy the ie's value into vhtoper*/ + memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2, sizeof(struct ieee80211_vht_operation)); + } break; case WLAN_EID_VHT_CAPABILITY: if (priv->adapter->is_hw_11ac_capable) { - memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos, + if (pos > end - + sizeof(struct ieee80211_vht_cap) - 2) + return; + if (pos[1] != sizeof(struct ieee80211_vht_cap)) + return; + /* copy the ie's value into vhtcap*/ + memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2, sizeof(struct ieee80211_vht_cap)); sta_ptr->is_11ac_enabled = 1; } break; case WLAN_EID_AID: - if (priv->adapter->is_hw_11ac_capable) + if (priv->adapter->is_hw_11ac_capable) { + if (pos > end - 4) + return; + if (pos[1] != 2) + return; sta_ptr->tdls_cap.aid = le16_to_cpu(*(__le16 *)(pos + 2)); + } + break; default: break; } diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index 9843560e784fe3e1d5df757607bdea4e96ff2581..c93fcafbcc7a61493a30fe90c2dc41782deb71e4 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -980,6 +980,10 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, "WMM Parameter Set Count: %d\n", wmm_param_ie->qos_info_bitmap & mask); + if (wmm_param_ie->vend_hdr.len + 2 > + sizeof(struct ieee_types_wmm_parameter)) + break; + memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. wmm_ie, wmm_param_ie, wmm_param_ie->vend_hdr.len + 2); diff --git a/drivers/net/wireless/mediatek/mt7601u/phy.c b/drivers/net/wireless/mediatek/mt7601u/phy.c index ca09a5d4305efff5972028e38e429774aeb93976..71a47459bf8a88ca24ae6c621c69ca22626a33a8 100644 --- a/drivers/net/wireless/mediatek/mt7601u/phy.c +++ b/drivers/net/wireless/mediatek/mt7601u/phy.c @@ -221,7 +221,7 @@ int mt7601u_wait_bbp_ready(struct mt7601u_dev *dev) do { val = mt7601u_bbp_rr(dev, MT_BBP_REG_VERSION); - if (val && ~val) + if (val && val != 0xff) break; } while (--i); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 08d587a342d32c8e2111e10955519009d9718ca6..9143b173935dab56a6c88d70ba8c2212e76a7a62 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1348,6 +1348,7 @@ struct rtl8xxxu_fileops { u8 has_s0s1:1; u8 has_tx_report:1; u8 gen2_thermal_meter:1; + u8 needs_full_init:1; u32 adda_1t_init; u32 adda_1t_path_on; u32 adda_2t_path_on_a; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index 02b8ddd98a95d207323dcac13d514c0b987c5afe..f51ee88d692b127f4f61fb6d16d722c5f05ec81b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -1673,6 +1673,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = { .has_s0s1 = 1, .has_tx_report = 1, .gen2_thermal_meter = 1, + .needs_full_init = 1, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index e78545d4add3ce2bf779406fe1f1fdf29afef803..18d5984b78dab364af5b5dbf3b4726be43a0353f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -3905,6 +3905,9 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) else macpower = true; + if (fops->needs_full_init) + macpower = false; + ret = fops->power_on(priv); if (ret < 0) { dev_warn(dev, "%s: Failed power on\n", __func__); @@ -5419,6 +5422,7 @@ static int rtl8xxxu_submit_int_urb(struct ieee80211_hw *hw) ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { usb_unanchor_urb(urb); + usb_free_urb(urb); goto error; } @@ -5886,7 +5890,7 @@ static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv, u8 dir, xtype, num; int ret = 0; - host_interface = &interface->altsetting[0]; + host_interface = interface->cur_altsetting; interface_desc = &host_interface->desc; endpoints = interface_desc->bNumEndpoints; diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index e15b462d096bf30fb6ea5148108d108da766cf77..21b7cb845bf40f4e38238a52823f7844c80c0479 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -1095,13 +1095,15 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) return ret; } -static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) +static void _rtl_pci_irq_tasklet(unsigned long data) { + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; _rtl_pci_tx_chk_waitq(hw); } -static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) +static void _rtl_pci_prepare_bcn_tasklet(unsigned long data) { + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -1223,10 +1225,10 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, /*task */ tasklet_init(&rtlpriv->works.irq_tasklet, - (void (*)(unsigned long))_rtl_pci_irq_tasklet, + _rtl_pci_irq_tasklet, (unsigned long)hw); tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, - (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, + _rtl_pci_prepare_bcn_tasklet, (unsigned long)hw); INIT_WORK(&rtlpriv->works.lps_change_work, rtl_lps_change_work_callback); diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index 6ee6bf8e7eafd86b45feca53ff742307c704821f..ab53cf42cf425a19bb80463fb4a9897d586555ff 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -427,7 +427,7 @@ int rtl_regd_init(struct ieee80211_hw *hw, struct wiphy *wiphy = hw->wiphy; struct country_code_to_enum_rd *country = NULL; - if (wiphy == NULL || &rtlpriv->regd == NULL) + if (!wiphy) return -EINVAL; /* init country_code from efuse channel plan */ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index ae8f055483facb429618afb07284953ec6fd9d77..39a6bd314ca3b4826fbca427cae677912f62cc7d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -1576,6 +1576,8 @@ static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) * This is maybe necessary: * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb); */ + dev_kfree_skb(skb); + return true; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c index d91f8bbfe7a0799aba518625725a102305d7d219..2c23c9edab5c43384e7538cf9baa5196ca0026c2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c @@ -1209,6 +1209,7 @@ void rtl92de_enable_interrupt(struct ieee80211_hw *hw) rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; } void rtl92de_disable_interrupt(struct ieee80211_hw *hw) @@ -1218,7 +1219,7 @@ void rtl92de_disable_interrupt(struct ieee80211_hw *hw) rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); - synchronize_irq(rtlpci->pdev->irq); + rtlpci->irq_enabled = false; } static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw) @@ -1389,7 +1390,7 @@ void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw) bcn_interval = mac->beacon_interval; atim_window = 2; - /*rtl92de_disable_interrupt(hw); */ + rtl92de_disable_interrupt(hw); rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); @@ -1409,9 +1410,9 @@ void rtl92de_set_beacon_interval(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, "beacon_interval:%d\n", bcn_interval); - /* rtl92de_disable_interrupt(hw); */ + rtl92de_disable_interrupt(hw); rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - /* rtl92de_enable_interrupt(hw); */ + rtl92de_enable_interrupt(hw); } void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c index 1ebfee18882fb4f1bf8cd31ed303bd98e96542ab..63cad2f875b83731e1458a875561940c23cf599e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c @@ -243,6 +243,7 @@ static struct rtl_hal_ops rtl8192de_hal_ops = { .led_control = rtl92de_led_control, .set_desc = rtl92de_set_desc, .get_desc = rtl92de_get_desc, + .is_tx_desc_closed = rtl92de_is_tx_desc_closed, .tx_polling = rtl92de_tx_polling, .enable_hw_sec = rtl92de_enable_hw_security_config, .set_key = rtl92de_set_key, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c index e998e98d74cb220f981abcff483f664f13b313bc..bddf57cb47f01ab9e68c8cf5692f302f4563d210 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c @@ -843,13 +843,15 @@ u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name) break; } } else { - struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; switch (desc_name) { case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); + ret = GET_RX_DESC_OWN(p_desc); break; case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); + ret = GET_RX_DESC_PKT_LEN(p_desc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_DESC_BUFF_ADDR(p_desc); break; default: RT_ASSERT(false, "ERR rxdesc :%d not process\n", @@ -860,6 +862,23 @@ u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name) return ret; } +bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + u8 *entry = (u8 *)(&ring->desc[ring->idx]); + u8 own = (u8)rtl92de_get_desc(entry, true, HW_DESC_OWN); + + /* a beacon packet will only use the first + * descriptor by defaut, and the own bit may not + * be cleared by the hardware + */ + if (own) + return false; + return true; +} + void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h index 194d99f8bacf1504312efa2dd0b6ab1580f66f15..d061f33b9f68614e24508d1af09a1284c0bf5d99 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h @@ -740,6 +740,8 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, u8 desc_name, u8 *val); u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name); +bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index); void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool b_firstseg, bool b_lastseg, diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index ae0c48f3c2bc0924bd1f6aa154f48a1f503510bc..1f02461de261ce3417145d4d22bf52aaa936362f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -1088,8 +1088,10 @@ int rtl_usb_probe(struct usb_interface *intf, rtlpriv->hw = hw; rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), GFP_KERNEL); - if (!rtlpriv->usb_data) + if (!rtlpriv->usb_data) { + ieee80211_free_hw(hw); return -ENOMEM; + } /* this spin lock must be initialized early */ spin_lock_init(&rtlpriv->locks.usb_lock); @@ -1152,6 +1154,7 @@ int rtl_usb_probe(struct usb_interface *intf, _rtl_usb_io_handler_release(hw); usb_put_dev(udev); complete(&rtlpriv->firmware_loading_complete); + kfree(rtlpriv->usb_data); return -ENODEV; } EXPORT_SYMBOL(rtl_usb_probe); diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index dbb23899ddcb336827a3b0e5b255db9e16d2604d..891295ebd875a5fecf885e2719fe39029e90eaed 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -199,6 +199,7 @@ void rsi_mac80211_detach(struct rsi_hw *adapter) ieee80211_stop_queues(hw); ieee80211_unregister_hw(hw); ieee80211_free_hw(hw); + adapter->hw = NULL; } rsi_remove_dbgfs(adapter); diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index ef5d394f185bfb46cc24c9170eecf4f6cee4dab8..974387ad1e8c57c62c7edf93307cc6b3a259723f 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -103,7 +103,7 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface, __le16 buffer_size; int ii, bep_found = 0; - iface_desc = &(interface->altsetting[0]); + iface_desc = interface->cur_altsetting; for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) { endpoint = &(iface_desc->endpoint[ii].desc); diff --git a/drivers/net/wireless/st/cw1200/fwio.c b/drivers/net/wireless/st/cw1200/fwio.c index 30e7646d04affac71a3f3a1ad65702883fef5bef..16be7fa82a233bee067fcf8cbec42bd39156106c 100644 --- a/drivers/net/wireless/st/cw1200/fwio.c +++ b/drivers/net/wireless/st/cw1200/fwio.c @@ -323,12 +323,12 @@ int cw1200_load_firmware(struct cw1200_common *priv) goto out; } - priv->hw_type = cw1200_get_hw_type(val32, &major_revision); - if (priv->hw_type < 0) { + ret = cw1200_get_hw_type(val32, &major_revision); + if (ret < 0) { pr_err("Can't deduce hardware type.\n"); - ret = -ENOTSUPP; goto out; } + priv->hw_type = ret; /* Set DPLL Reg value, and read back to confirm writes work */ ret = cw1200_reg_write_32(priv, ST90TDS_TSET_GEN_R_W_REG_ID, diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c index 01ca1d57b3d92074d2953195b9776b368f653ead..213e5022ab93c74c0f47719d165905bba9b14d44 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c @@ -1272,7 +1272,7 @@ static void print_id(struct usb_device *udev) static int eject_installer(struct usb_interface *intf) { struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_interface *iface_desc = &intf->altsetting[0]; + struct usb_host_interface *iface_desc = intf->cur_altsetting; struct usb_endpoint_descriptor *endpoint; unsigned char *cmd; u8 bulk_out_ep; diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 06a157c63416acf434b5a0a6cdb21fc9d2b5a8d1..7eab97585f22bf68852d7b89ef0755cd76123ab9 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -238,8 +238,10 @@ static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id) if (r == -EREMOTEIO) { phy->hard_fault = r; - skb = NULL; - } else if (r < 0) { + if (info->mode == NXP_NCI_MODE_FW) + nxp_nci_fw_recv_frame(phy->ndev, NULL); + } + if (r < 0) { nfc_err(&client->dev, "Read failed with error %d\n", r); goto exit_irq_handled; } diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index f837c39a801709a8a9be3f8c58cf74baf2ca196e..0f6905123b0a2d237a341c308d6286c455d699e4 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -240,6 +240,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) out: gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity); + usleep_range(10000, 15000); } static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode) diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 12e819ddf17a708c94ab0c122ac852f0199c85aa..3afc53ff7369c09aed3cb3c1fc4c3ba72706ba0a 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -704,7 +704,7 @@ static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, target->nfcid1_len != 10) return -EOPNOTSUPP; - return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, + return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, PN544_RF_READER_CMD_ACTIVATE_NEXT, target->nfcid1, target->nfcid1_len, NULL); } else if (target->supported_protocols & (NFC_PROTO_JEWEL_MASK | diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c index 3cd995de1bbb58f94245204d83920faaa3161821..151b220381f957084e6a319db25e274691812fd5 100644 --- a/drivers/nfc/port100.c +++ b/drivers/nfc/port100.c @@ -573,7 +573,7 @@ static void port100_tx_update_payload_len(void *_frame, int len) { struct port100_frame *frame = _frame; - frame->datalen = cpu_to_le16(le16_to_cpu(frame->datalen) + len); + le16_add_cpu(&frame->datalen, len); } static bool port100_rx_frame_is_valid(void *_frame) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 8705bfe7bb73162c15a3feedabc79ca68d1102a2..9561a247d0dc7843dabbf984f38ca564d30e1dad 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1043,7 +1043,7 @@ static int nvme_pr_reserve(struct block_device *bdev, u64 key, static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new, enum pr_type type, bool abort) { - u32 cdw10 = nvme_pr_type(type) << 8 | abort ? 2 : 1; + u32 cdw10 = nvme_pr_type(type) << 8 | (abort ? 2 : 1); return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire); } @@ -1055,7 +1055,7 @@ static int nvme_pr_clear(struct block_device *bdev, u64 key) static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type) { - u32 cdw10 = nvme_pr_type(type) << 8 | key ? 1 << 3 : 0; + u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 1 << 3 : 0); return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); } diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 1ac4cec5f4f7c83471cc7e15dd75d4f6bfd67d1f..e2bce9385eda6f35c9894f56bf481ab6e32568bc 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1863,7 +1863,7 @@ static int nvme_pci_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val) static int nvme_pci_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val) { - *val = readq(to_nvme_dev(ctrl)->bar + off); + *val = lo_hi_readq(to_nvme_dev(ctrl)->bar + off); return 0; } diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig old mode 100644 new mode 100755 index 0a963b17910528768eaa3562209bb906a3fa1a5c..000a96a0379b5541f75a969e12f97fdbe7ee9d62 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -133,4 +133,8 @@ config OF_BATTERYDATA help OpenFirmware BatteryData accessors +config OF_DMA_DEFAULT_COHERENT + # arches should select this if DMA is coherent by default for OF devices + bool + endif # OF diff --git a/drivers/of/address.c b/drivers/of/address.c index 2c1b08ab7a6a0080f83621d14a56aa1ada1190ee..b87b3cdefc6d2a391a110ec981c6423fd77a5cee 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -929,12 +929,16 @@ EXPORT_SYMBOL_GPL(of_dma_get_range); * @np: device node * * It returns true if "dma-coherent" property was found - * for this device in DT. + * for this device in the DT, or if DMA is coherent by + * default for OF devices on the current platform. */ bool of_dma_is_coherent(struct device_node *np) { struct device_node *node = of_node_get(np); + if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT)) + return true; + while (node) { if (of_property_read_bool(node, "dma-coherent")) { of_node_put(node); diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 262281bd68fa3c4d39e13f52eeafea1948d1bd22..1e70851b1530844bd978c7f2f0a8c9dedd596430 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -353,7 +353,7 @@ struct phy_device *of_phy_get_and_connect(struct net_device *dev, struct phy_device *phy; iface = of_get_phy_mode(np); - if (iface < 0) + if ((int)iface < 0) return NULL; phy_np = of_parse_phandle(np, "phy-handle", 0); diff --git a/drivers/parport/share.c b/drivers/parport/share.c index daa2eb3050df3fd0d5fb184a5cf5a5aab1a07bc2..a7ceed7182acbeb1c2605ef130955fd53cd0d6ec 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -230,6 +230,18 @@ static int port_check(struct device *dev, void *dev_drv) return 0; } +/* + * Iterates through all the devices connected to the bus and return 1 + * if the device is a parallel port. + */ + +static int port_detect(struct device *dev, void *dev_drv) +{ + if (is_parport(dev)) + return 1; + return 0; +} + /** * parport_register_driver - register a parallel port device driver * @drv: structure describing the driver @@ -282,6 +294,15 @@ int __parport_register_driver(struct parport_driver *drv, struct module *owner, if (ret) return ret; + /* + * check if bus has any parallel port registered, if + * none is found then load the lowlevel driver. + */ + ret = bus_for_each_dev(&parport_bus_type, NULL, NULL, + port_detect); + if (!ret) + get_lowlevel_driver(); + mutex_lock(®istration_lock); if (drv->match_port) bus_for_each_dev(&parport_bus_type, NULL, drv, diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c index 9397c46671062b011e6a6f9f523f9d2d0b95c1c4..f011a8780ff53f5dabc9f318542a3d3b5067be68 100644 --- a/drivers/pci/host/pci-keystone-dw.c +++ b/drivers/pci/host/pci-keystone-dw.c @@ -502,7 +502,7 @@ void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie) /* Disable Link training */ val = ks_dw_app_readl(ks_pcie, CMD_STATUS); val &= ~LTSSM_EN_VAL; - ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val); + ks_dw_app_writel(ks_pcie, CMD_STATUS, val); /* Initiate Link Training */ val = ks_dw_app_readl(ks_pcie, CMD_STATUS); diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 1d32fe2d97aa7cfefc136301ef07a8ebdaf4e53b..9ec3cb628b0b6a11bc81589aef3452a792bc1f58 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -181,6 +181,7 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset) failed2: sysfs_remove_link(&dev->dev.kobj, buf); failed1: + pci_stop_and_remove_bus_device(virtfn); pci_dev_put(dev); mutex_lock(&iov->dev->sriov->lock); pci_stop_and_remove_bus_device(virtfn); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 37f393f27efc730707b217feee8415fbd42de046..55ca14fbdd2a273fedabd134337f1a0b0d82334b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -230,7 +230,7 @@ u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag) return 0; mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; - if (flag) + if (flag & PCI_MSIX_ENTRY_CTRL_MASKBIT) mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; writel(mask_bits, pci_msix_desc_addr(desc) + PCI_MSIX_ENTRY_VECTOR_CTRL); diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c index bab8ac63c4f3e0e3682d9c30d7b8b8370a6a86da..3008bba360f354216e4aba113005ca8a43abd80c 100644 --- a/drivers/pci/pcie/ptm.c +++ b/drivers/pci/pcie/ptm.c @@ -29,7 +29,7 @@ static void pci_ptm_info(struct pci_dev *dev) snprintf(clock_desc, sizeof(clock_desc), ">254ns"); break; default: - snprintf(clock_desc, sizeof(clock_desc), "%udns", + snprintf(clock_desc, sizeof(clock_desc), "%uns", dev->ptm_granularity); break; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f474899073e039f515331d2ad9bcbc8350f4dad2..496296bc358160f2d70307919937a11f27fb3f56 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4446,7 +4446,7 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) #define INTEL_BSPR_REG_BPPD (1 << 9) /* Upstream Peer Decode Configuration Register */ -#define INTEL_UPDCR_REG 0x1114 +#define INTEL_UPDCR_REG 0x1014 /* 5:0 Peer Decode Enable bits */ #define INTEL_UPDCR_REG_MASK 0x3f diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index f30ca75b5b6c7e20055e881776c44eaf50acbe0a..e631636a0aa50be62b5c70b918e0c3e291c1c643 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1833,12 +1833,18 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) /* restore size and flags */ list_for_each_entry(fail_res, &fail_head, list) { struct resource *res = fail_res->res; + int idx; res->start = fail_res->start; res->end = fail_res->end; res->flags = fail_res->flags; - if (fail_res->dev->subordinate) - res->flags = 0; + + if (pci_is_bridge(fail_res->dev)) { + idx = res - &fail_res->dev->resource[0]; + if (idx >= PCI_BRIDGE_RESOURCES && + idx <= PCI_BRIDGE_RESOURCE_END) + res->flags = 0; + } } free_list(&fail_head); @@ -1904,12 +1910,18 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) /* restore size and flags */ list_for_each_entry(fail_res, &fail_head, list) { struct resource *res = fail_res->res; + int idx; res->start = fail_res->start; res->end = fail_res->end; res->flags = fail_res->flags; - if (fail_res->dev->subordinate) - res->flags = 0; + + if (pci_is_bridge(fail_res->dev)) { + idx = res - &fail_res->dev->resource[0]; + if (idx >= PCI_BRIDGE_RESOURCES && + idx <= PCI_BRIDGE_RESOURCE_END) + res->flags = 0; + } } free_list(&fail_head); diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index fc5b18d3db20eff75041cb4351009fbd0eacd17c..1e945aa77734b3ac948fe8d7937abc8a6e380e1c 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -204,7 +204,6 @@ struct byt_gpio { struct platform_device *pdev; struct pinctrl_dev *pctl_dev; struct pinctrl_desc pctl_desc; - raw_spinlock_t lock; const struct byt_pinctrl_soc_data *soc_data; struct byt_community *communities_copy; struct byt_gpio_pin_context *saved_context; @@ -715,6 +714,8 @@ static const struct byt_pinctrl_soc_data *byt_soc_data[] = { NULL, }; +static DEFINE_RAW_SPINLOCK(byt_lock); + static struct byt_community *byt_get_community(struct byt_gpio *vg, unsigned int pin) { @@ -856,7 +857,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg, unsigned long flags; int i; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); for (i = 0; i < group.npins; i++) { void __iomem *padcfg0; @@ -876,7 +877,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg, writel(value, padcfg0); } - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); } static void byt_set_group_mixed_mux(struct byt_gpio *vg, @@ -886,7 +887,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg, unsigned long flags; int i; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); for (i = 0; i < group.npins; i++) { void __iomem *padcfg0; @@ -906,7 +907,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg, writel(value, padcfg0); } - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); } static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, @@ -955,11 +956,17 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset) unsigned long flags; u32 value; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); value = readl(reg); - value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); + + /* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */ + if (value & BYT_DIRECT_IRQ_EN) + /* nothing to do */ ; + else + value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); + writel(value, reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); } static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, @@ -971,7 +978,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, u32 value, gpio_mux; unsigned long flags; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); /* * In most cases, func pin mux 000 means GPIO function. @@ -993,7 +1000,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, "pin %u forcibly re-configured as GPIO\n", offset); } - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); pm_runtime_get(&vg->pdev->dev); @@ -1021,7 +1028,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, unsigned long flags; u32 value; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); value = readl(val_reg); value &= ~BYT_DIR_MASK; @@ -1038,7 +1045,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, "Potential Error: Setting GPIO with direct_irq_en to output"); writel(value, val_reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); return 0; } @@ -1107,11 +1114,11 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, u32 conf, pull, val, debounce; u16 arg = 0; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); conf = readl(conf_reg); pull = conf & BYT_PULL_ASSIGN_MASK; val = readl(val_reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); switch (param) { case PIN_CONFIG_BIAS_DISABLE: @@ -1138,9 +1145,9 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, if (!(conf & BYT_DEBOUNCE_EN)) return -EINVAL; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); debounce = readl(db_reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); switch (debounce & BYT_DEBOUNCE_PULSE_MASK) { case BYT_DEBOUNCE_PULSE_375US: @@ -1192,7 +1199,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, u32 conf, val, debounce; int i, ret = 0; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); conf = readl(conf_reg); val = readl(val_reg); @@ -1300,7 +1307,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, if (!ret) writel(conf, conf_reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); return ret; } @@ -1325,9 +1332,9 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset) unsigned long flags; u32 val; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); val = readl(reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); return !!(val & BYT_LEVEL); } @@ -1342,13 +1349,13 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) if (!reg) return; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); old_val = readl(reg); if (value) writel(old_val | BYT_LEVEL, reg); else writel(old_val & ~BYT_LEVEL, reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); } static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) @@ -1361,9 +1368,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) if (!reg) return -EINVAL; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); value = readl(reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); if (!(value & BYT_OUTPUT_EN)) return GPIOF_DIR_OUT; @@ -1406,14 +1413,14 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) const char *label; unsigned int pin; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); pin = vg->soc_data->pins[i].number; reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); if (!reg) { seq_printf(s, "Could not retrieve pin %i conf0 reg\n", pin); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); continue; } conf0 = readl(reg); @@ -1422,11 +1429,11 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) if (!reg) { seq_printf(s, "Could not retrieve pin %i val reg\n", pin); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); continue; } val = readl(reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); comm = byt_get_community(vg, pin); if (!comm) { @@ -1510,9 +1517,9 @@ static void byt_irq_ack(struct irq_data *d) if (!reg) return; - raw_spin_lock(&vg->lock); + raw_spin_lock(&byt_lock); writel(BIT(offset % 32), reg); - raw_spin_unlock(&vg->lock); + raw_spin_unlock(&byt_lock); } static void byt_irq_mask(struct irq_data *d) @@ -1536,7 +1543,7 @@ static void byt_irq_unmask(struct irq_data *d) if (!reg) return; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); value = readl(reg); switch (irqd_get_trigger_type(d)) { @@ -1557,7 +1564,7 @@ static void byt_irq_unmask(struct irq_data *d) writel(value, reg); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); } static int byt_irq_type(struct irq_data *d, unsigned int type) @@ -1571,7 +1578,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type) if (!reg || offset >= vg->chip.ngpio) return -EINVAL; - raw_spin_lock_irqsave(&vg->lock, flags); + raw_spin_lock_irqsave(&byt_lock, flags); value = readl(reg); WARN(value & BYT_DIRECT_IRQ_EN, @@ -1593,7 +1600,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type) else if (type & IRQ_TYPE_LEVEL_MASK) irq_set_handler_locked(d, handle_level_irq); - raw_spin_unlock_irqrestore(&vg->lock, flags); + raw_spin_unlock_irqrestore(&byt_lock, flags); return 0; } @@ -1629,9 +1636,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) continue; } - raw_spin_lock(&vg->lock); + raw_spin_lock(&byt_lock); pending = readl(reg); - raw_spin_unlock(&vg->lock); + raw_spin_unlock(&byt_lock); for_each_set_bit(pin, &pending, 32) { virq = irq_find_mapping(vg->chip.irqdomain, base + pin); generic_handle_irq(virq); @@ -1833,8 +1840,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev) return PTR_ERR(vg->pctl_dev); } - raw_spin_lock_init(&vg->lock); - ret = byt_gpio_probe(vg); if (ret) { pinctrl_unregister(vg->pctl_dev); @@ -1852,8 +1857,11 @@ static int byt_gpio_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct byt_gpio *vg = platform_get_drvdata(pdev); + unsigned long flags; int i; + raw_spin_lock_irqsave(&byt_lock, flags); + for (i = 0; i < vg->soc_data->npins; i++) { void __iomem *reg; u32 value; @@ -1874,6 +1882,7 @@ static int byt_gpio_suspend(struct device *dev) vg->saved_context[i].val = value; } + raw_spin_unlock_irqrestore(&byt_lock, flags); return 0; } @@ -1881,8 +1890,11 @@ static int byt_gpio_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct byt_gpio *vg = platform_get_drvdata(pdev); + unsigned long flags; int i; + raw_spin_lock_irqsave(&byt_lock, flags); + for (i = 0; i < vg->soc_data->npins; i++) { void __iomem *reg; u32 value; @@ -1920,6 +1932,7 @@ static int byt_gpio_resume(struct device *dev) } } + raw_spin_unlock_irqrestore(&byt_lock, flags); return 0; } #endif diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c index db3fb235cd6b7b897653c0de60307312f7ecb109..906e04433bfc8b2087378af1e8d88abf06ffd43a 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c @@ -762,12 +762,23 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) return ret; } - ret = gpiochip_add_pin_range(&pctrl->chip, - dev_name(pctrl->dev), - 0, 0, pctrl->chip.ngpio); - if (ret) { - dev_err(pctrl->dev, "failed to add pin range\n"); - goto unregister_gpiochip; + /* + * For DeviceTree-supported systems, the gpio core checks the + * pinctrl's device node for the "gpio-ranges" property. + * If it is present, it takes care of adding the pin ranges + * for the driver. In this case the driver can skip ahead. + * + * In order to remain compatible with older, existing DeviceTree + * files which don't set the "gpio-ranges" property or systems that + * utilize ACPI the driver has to call gpiochip_add_pin_range(). + */ + if (!of_property_read_bool(pctrl->dev->of_node, "gpio-ranges")) { + ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), + 0, 0, pctrl->chip.ngpio); + if (ret) { + dev_err(pctrl->dev, "failed to add pin range\n"); + goto unregister_gpiochip; + } } platform_set_drvdata(pdev, pctrl); diff --git a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c index 3d92f827da7a83fc08a0d24e86347004ff01ba0b..0839b70a30ee695270e8cca21338391fc16495f7 100644 --- a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c +++ b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c @@ -495,8 +495,10 @@ static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d) return -ENODEV; eint_data = devm_kzalloc(dev, sizeof(*eint_data), GFP_KERNEL); - if (!eint_data) + if (!eint_data) { + of_node_put(eint_np); return -ENOMEM; + } eint_data->drvdata = d; @@ -508,12 +510,14 @@ static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d) irq = irq_of_parse_and_map(eint_np, i); if (!irq) { dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i); + of_node_put(eint_np); return -ENXIO; } eint_data->parents[i] = irq; irq_set_chained_handler_and_data(irq, handlers[i], eint_data); } + of_node_put(eint_np); bank = d->pin_banks; for (i = 0; i < d->nr_banks; ++i, ++bank) { diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c index 43407ab248f5121d0ca5625112592a32a9f1a968..0cd9f3a7bb11adf35521480ee05184a5651b6089 100644 --- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c +++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c @@ -713,6 +713,7 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) { dev_err(dev, "could not allocate memory for wkup eint data\n"); + of_node_put(eint0_np); return -ENOMEM; } data->drvdata = d; @@ -723,6 +724,7 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d) irq = irq_of_parse_and_map(eint0_np, i); if (!irq) { dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i); + of_node_put(eint0_np); return -ENXIO; } @@ -730,6 +732,7 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d) s3c64xx_eint0_handlers[i], data); } + of_node_put(eint0_np); bank = d->pin_banks; for (i = 0; i < d->nr_banks; ++i, ++bank) { diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 620727fabe6437feb63f6d4b24f11949616131f4..6b77a1bb5b20b0bae478f5bbc5b8d9b8c1db588a 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -281,6 +281,7 @@ static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev, &reserved_maps, num_maps); if (ret < 0) { samsung_dt_free_map(pctldev, *map, *num_maps); + of_node_put(np); return ret; } } @@ -770,8 +771,10 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions( if (!of_get_child_count(cfg_np)) { ret = samsung_pinctrl_create_function(dev, drvdata, cfg_np, func); - if (ret < 0) + if (ret < 0) { + of_node_put(cfg_np); return ERR_PTR(ret); + } if (ret > 0) { ++func; ++func_cnt; @@ -782,8 +785,11 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions( for_each_child_of_node(cfg_np, func_np) { ret = samsung_pinctrl_create_function(dev, drvdata, func_np, func); - if (ret < 0) + if (ret < 0) { + of_node_put(func_np); + of_node_put(cfg_np); return ERR_PTR(ret); + } if (ret > 0) { ++func; ++func_cnt; diff --git a/drivers/pinctrl/sh-pfc/pfc-emev2.c b/drivers/pinctrl/sh-pfc/pfc-emev2.c index 1cbbe04d7df657e8fa11bfddc93433739a9a73ec..eafd8edbcbe95b7ec9ac64ab723dc9443af8016d 100644 --- a/drivers/pinctrl/sh-pfc/pfc-emev2.c +++ b/drivers/pinctrl/sh-pfc/pfc-emev2.c @@ -1263,6 +1263,14 @@ static const char * const dtv_groups[] = { "dtv_b", }; +static const char * const err_rst_reqb_groups[] = { + "err_rst_reqb", +}; + +static const char * const ext_clki_groups[] = { + "ext_clki", +}; + static const char * const iic0_groups[] = { "iic0", }; @@ -1285,6 +1293,10 @@ static const char * const lcd_groups[] = { "yuv3", }; +static const char * const lowpwr_groups[] = { + "lowpwr", +}; + static const char * const ntsc_groups[] = { "ntsc_clk", "ntsc_data", @@ -1298,6 +1310,10 @@ static const char * const pwm1_groups[] = { "pwm1", }; +static const char * const ref_clko_groups[] = { + "ref_clko", +}; + static const char * const sd_groups[] = { "sd_cki", }; @@ -1391,13 +1407,17 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(cam), SH_PFC_FUNCTION(cf), SH_PFC_FUNCTION(dtv), + SH_PFC_FUNCTION(err_rst_reqb), + SH_PFC_FUNCTION(ext_clki), SH_PFC_FUNCTION(iic0), SH_PFC_FUNCTION(iic1), SH_PFC_FUNCTION(jtag), SH_PFC_FUNCTION(lcd), + SH_PFC_FUNCTION(lowpwr), SH_PFC_FUNCTION(ntsc), SH_PFC_FUNCTION(pwm0), SH_PFC_FUNCTION(pwm1), + SH_PFC_FUNCTION(ref_clko), SH_PFC_FUNCTION(sd), SH_PFC_FUNCTION(sdi0), SH_PFC_FUNCTION(sdi1), diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c index 35f436bcb849185a559f4ad4095b6914d5163f4c..e9739dbcb356e90b9e19538886f6acf732eb1e06 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c @@ -1982,7 +1982,7 @@ static const unsigned int gether_gmii_pins[] = { */ 185, 186, 187, 188, 189, 190, 191, 192, 174, 161, 204, 171, 170, 169, 168, 167, 166, 173, 172, 176, 184, 183, 203, - 205, 163, 206, 207, + 205, 163, 206, 207, 158, }; static const unsigned int gether_gmii_mux[] = { ET_ERXD0_MARK, ET_ERXD1_MARK, ET_ERXD2_MARK, ET_ERXD3_MARK, @@ -2154,6 +2154,7 @@ static const unsigned int lcd0_data24_1_mux[] = { LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK, LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK, LCD0_D8_MARK, LCD0_D9_MARK, LCD0_D10_MARK, LCD0_D11_MARK, + LCD0_D12_MARK, LCD0_D13_MARK, LCD0_D14_MARK, LCD0_D15_MARK, LCD0_D16_MARK, LCD0_D17_MARK, LCD0_D18_PORT163_MARK, LCD0_D19_PORT162_MARK, LCD0_D20_PORT161_MARK, LCD0_D21_PORT158_MARK, LCD0_D22_PORT160_MARK, LCD0_D23_PORT159_MARK, diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c index 18ef7042b3d1b04761b2e194d11601a1f1d20fe6..771689a41dbf8a7de35d87de50f709e683467a3c 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c @@ -2324,7 +2324,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_ATAG0_A, 0, FN_REMOCON_B, 0, /* IP0_11_8 [4] */ FN_SD1_DAT2_A, FN_MMC_D2, 0, FN_BS, - FN_ATADIR0_A, 0, FN_SDSELF_B, 0, + FN_ATADIR0_A, 0, FN_SDSELF_A, 0, FN_PWM4_B, 0, 0, 0, 0, 0, 0, 0, /* IP0_7_5 [3] */ @@ -2366,7 +2366,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_TS_SDAT0_A, 0, 0, 0, 0, 0, 0, 0, /* IP1_10_8 [3] */ - FN_SD1_CLK_B, FN_MMC_D6, 0, FN_A24, + FN_SD1_CD_A, FN_MMC_D6, 0, FN_A24, FN_DREQ1_A, 0, FN_HRX0_B, FN_TS_SPSYNC0_A, /* IP1_7_5 [3] */ FN_A23, FN_HTX0_B, FN_TX2_B, FN_DACK2_A, diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index baa98d7fe947347ef46b2fba22247507dabbc3da..dd350e2961423b3bc1a533a2968fd55b468caa66 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -3136,8 +3136,7 @@ static const unsigned int qspi_data4_b_pins[] = { RCAR_GP_PIN(6, 4), }; static const unsigned int qspi_data4_b_mux[] = { - SPCLK_B_MARK, MOSI_IO0_B_MARK, MISO_IO1_B_MARK, - IO2_B_MARK, IO3_B_MARK, SSL_B_MARK, + MOSI_IO0_B_MARK, MISO_IO1_B_MARK, IO2_B_MARK, IO3_B_MARK, }; /* - SCIF0 ------------------------------------------------------------------ */ static const unsigned int scif0_data_pins[] = { @@ -4265,17 +4264,14 @@ static const unsigned int vin1_b_data18_pins[] = { }; static const unsigned int vin1_b_data18_mux[] = { /* B */ - VI1_DATA0_B_MARK, VI1_DATA1_B_MARK, VI1_DATA2_B_MARK, VI1_DATA3_B_MARK, VI1_DATA4_B_MARK, VI1_DATA5_B_MARK, VI1_DATA6_B_MARK, VI1_DATA7_B_MARK, /* G */ - VI1_G0_B_MARK, VI1_G1_B_MARK, VI1_G2_B_MARK, VI1_G3_B_MARK, VI1_G4_B_MARK, VI1_G5_B_MARK, VI1_G6_B_MARK, VI1_G7_B_MARK, /* R */ - VI1_R0_B_MARK, VI1_R1_B_MARK, VI1_R2_B_MARK, VI1_R3_B_MARK, VI1_R4_B_MARK, VI1_R5_B_MARK, VI1_R6_B_MARK, VI1_R7_B_MARK, @@ -5082,7 +5078,7 @@ static const char * const scifb2_groups[] = { "scifb2_data_b", "scifb2_clk_b", "scifb2_ctrl_b", - "scifb0_data_c", + "scifb2_data_c", "scifb2_clk_c", "scifb2_data_d", }; diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7792.c b/drivers/pinctrl/sh-pfc/pfc-r8a7792.c index 21badb6166b9299c088449c2c21b6d5f9fa0350a..97998929db938abc26bae606778786779b1e5649 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7792.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7792.c @@ -1863,6 +1863,7 @@ static const char * const vin1_groups[] = { "vin1_data8", "vin1_data24_b", "vin1_data20_b", + "vin1_data18_b", "vin1_data16_b", "vin1_sync", "vin1_field", diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c index ef093ac0cf2fbcd60287eeb3d2de25e5557486f1..fe8c9c24634d8ea42d97c9dca8b39bf2a11e2f38 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c @@ -4826,7 +4826,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_AVB_MDC, FN_SSI_SDATA6_B, 0, 0, } }, { PINMUX_CFG_REG_VAR("IPSR9", 0xE6060044, 32, - 1, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3) { + 1, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3) { /* IP9_31 [1] */ 0, 0, /* IP9_30_28 [3] */ diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7264.c b/drivers/pinctrl/sh-pfc/pfc-sh7264.c index e1c34e19222ee7bcf12d3a98f348b9d749b312fe..3ddb9565ed8044486308ef1abe631568ffec55bd 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7264.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7264.c @@ -500,17 +500,15 @@ enum { SD_WP_MARK, SD_CLK_MARK, SD_CMD_MARK, CRX0_MARK, CRX1_MARK, CTX0_MARK, CTX1_MARK, + CRX0_CRX1_MARK, CTX0_CTX1_MARK, PWM1A_MARK, PWM1B_MARK, PWM1C_MARK, PWM1D_MARK, PWM1E_MARK, PWM1F_MARK, PWM1G_MARK, PWM1H_MARK, PWM2A_MARK, PWM2B_MARK, PWM2C_MARK, PWM2D_MARK, PWM2E_MARK, PWM2F_MARK, PWM2G_MARK, PWM2H_MARK, IERXD_MARK, IETXD_MARK, - CRX0_CRX1_MARK, WDTOVF_MARK, - CRX0X1_MARK, - /* DMAC */ TEND0_MARK, DACK0_MARK, DREQ0_MARK, TEND1_MARK, DACK1_MARK, DREQ1_MARK, @@ -998,12 +996,12 @@ static const u16 pinmux_data[] = { PINMUX_DATA(PJ3_DATA, PJ3MD_00), PINMUX_DATA(CRX1_MARK, PJ3MD_01), - PINMUX_DATA(CRX0X1_MARK, PJ3MD_10), + PINMUX_DATA(CRX0_CRX1_MARK, PJ3MD_10), PINMUX_DATA(IRQ1_PJ_MARK, PJ3MD_11), PINMUX_DATA(PJ2_DATA, PJ2MD_000), PINMUX_DATA(CTX1_MARK, PJ2MD_001), - PINMUX_DATA(CRX0_CRX1_MARK, PJ2MD_010), + PINMUX_DATA(CTX0_CTX1_MARK, PJ2MD_010), PINMUX_DATA(CS2_MARK, PJ2MD_011), PINMUX_DATA(SCK0_MARK, PJ2MD_100), PINMUX_DATA(LCD_M_DISP_MARK, PJ2MD_101), @@ -1248,6 +1246,7 @@ static const struct pinmux_func pinmux_func_gpios[] = { GPIO_FN(CTX1), GPIO_FN(CRX1), GPIO_FN(CTX0), + GPIO_FN(CTX0_CTX1), GPIO_FN(CRX0), GPIO_FN(CRX0_CRX1), diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7269.c b/drivers/pinctrl/sh-pfc/pfc-sh7269.c index a50d22bef1f444517523c6bce95dc091a7d42b9a..3df0c0d139d08f6bd889084373ecd81610f5b618 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7269.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7269.c @@ -740,13 +740,12 @@ enum { CRX0_MARK, CTX0_MARK, CRX1_MARK, CTX1_MARK, CRX2_MARK, CTX2_MARK, - CRX0_CRX1_MARK, - CRX0_CRX1_CRX2_MARK, - CTX0CTX1CTX2_MARK, + CRX0_CRX1_MARK, CTX0_CTX1_MARK, + CRX0_CRX1_CRX2_MARK, CTX0_CTX1_CTX2_MARK, CRX1_PJ22_MARK, CTX1_PJ23_MARK, CRX2_PJ20_MARK, CTX2_PJ21_MARK, - CRX0CRX1_PJ22_MARK, - CRX0CRX1CRX2_PJ20_MARK, + CRX0_CRX1_PJ22_MARK, CTX0_CTX1_PJ23_MARK, + CRX0_CRX1_CRX2_PJ20_MARK, CTX0_CTX1_CTX2_PJ21_MARK, /* VDC */ DV_CLK_MARK, @@ -824,6 +823,7 @@ static const u16 pinmux_data[] = { PINMUX_DATA(CS3_MARK, PC8MD_001), PINMUX_DATA(TXD7_MARK, PC8MD_010), PINMUX_DATA(CTX1_MARK, PC8MD_011), + PINMUX_DATA(CTX0_CTX1_MARK, PC8MD_100), PINMUX_DATA(PC7_DATA, PC7MD_000), PINMUX_DATA(CKE_MARK, PC7MD_001), @@ -836,11 +836,12 @@ static const u16 pinmux_data[] = { PINMUX_DATA(CAS_MARK, PC6MD_001), PINMUX_DATA(SCK7_MARK, PC6MD_010), PINMUX_DATA(CTX0_MARK, PC6MD_011), + PINMUX_DATA(CTX0_CTX1_CTX2_MARK, PC6MD_100), PINMUX_DATA(PC5_DATA, PC5MD_000), PINMUX_DATA(RAS_MARK, PC5MD_001), PINMUX_DATA(CRX0_MARK, PC5MD_011), - PINMUX_DATA(CTX0CTX1CTX2_MARK, PC5MD_100), + PINMUX_DATA(CTX0_CTX1_CTX2_MARK, PC5MD_100), PINMUX_DATA(IRQ0_PC_MARK, PC5MD_101), PINMUX_DATA(PC4_DATA, PC4MD_00), @@ -1292,30 +1293,32 @@ static const u16 pinmux_data[] = { PINMUX_DATA(LCD_DATA23_PJ23_MARK, PJ23MD_010), PINMUX_DATA(LCD_TCON6_MARK, PJ23MD_011), PINMUX_DATA(IRQ3_PJ_MARK, PJ23MD_100), - PINMUX_DATA(CTX1_MARK, PJ23MD_101), + PINMUX_DATA(CTX1_PJ23_MARK, PJ23MD_101), + PINMUX_DATA(CTX0_CTX1_PJ23_MARK, PJ23MD_110), PINMUX_DATA(PJ22_DATA, PJ22MD_000), PINMUX_DATA(DV_DATA22_MARK, PJ22MD_001), PINMUX_DATA(LCD_DATA22_PJ22_MARK, PJ22MD_010), PINMUX_DATA(LCD_TCON5_MARK, PJ22MD_011), PINMUX_DATA(IRQ2_PJ_MARK, PJ22MD_100), - PINMUX_DATA(CRX1_MARK, PJ22MD_101), - PINMUX_DATA(CRX0_CRX1_MARK, PJ22MD_110), + PINMUX_DATA(CRX1_PJ22_MARK, PJ22MD_101), + PINMUX_DATA(CRX0_CRX1_PJ22_MARK, PJ22MD_110), PINMUX_DATA(PJ21_DATA, PJ21MD_000), PINMUX_DATA(DV_DATA21_MARK, PJ21MD_001), PINMUX_DATA(LCD_DATA21_PJ21_MARK, PJ21MD_010), PINMUX_DATA(LCD_TCON4_MARK, PJ21MD_011), PINMUX_DATA(IRQ1_PJ_MARK, PJ21MD_100), - PINMUX_DATA(CTX2_MARK, PJ21MD_101), + PINMUX_DATA(CTX2_PJ21_MARK, PJ21MD_101), + PINMUX_DATA(CTX0_CTX1_CTX2_PJ21_MARK, PJ21MD_110), PINMUX_DATA(PJ20_DATA, PJ20MD_000), PINMUX_DATA(DV_DATA20_MARK, PJ20MD_001), PINMUX_DATA(LCD_DATA20_PJ20_MARK, PJ20MD_010), PINMUX_DATA(LCD_TCON3_MARK, PJ20MD_011), PINMUX_DATA(IRQ0_PJ_MARK, PJ20MD_100), - PINMUX_DATA(CRX2_MARK, PJ20MD_101), - PINMUX_DATA(CRX0CRX1CRX2_PJ20_MARK, PJ20MD_110), + PINMUX_DATA(CRX2_PJ20_MARK, PJ20MD_101), + PINMUX_DATA(CRX0_CRX1_CRX2_PJ20_MARK, PJ20MD_110), PINMUX_DATA(PJ19_DATA, PJ19MD_000), PINMUX_DATA(DV_DATA19_MARK, PJ19MD_001), @@ -1666,12 +1669,24 @@ static const struct pinmux_func pinmux_func_gpios[] = { GPIO_FN(WDTOVF), /* CAN */ + GPIO_FN(CTX2), + GPIO_FN(CRX2), GPIO_FN(CTX1), GPIO_FN(CRX1), GPIO_FN(CTX0), GPIO_FN(CRX0), + GPIO_FN(CTX0_CTX1), GPIO_FN(CRX0_CRX1), + GPIO_FN(CTX0_CTX1_CTX2), GPIO_FN(CRX0_CRX1_CRX2), + GPIO_FN(CTX2_PJ21), + GPIO_FN(CRX2_PJ20), + GPIO_FN(CTX1_PJ23), + GPIO_FN(CRX1_PJ22), + GPIO_FN(CTX0_CTX1_PJ23), + GPIO_FN(CRX0_CRX1_PJ22), + GPIO_FN(CTX0_CTX1_CTX2_PJ21), + GPIO_FN(CRX0_CRX1_CRX2_PJ20), /* DMAC */ GPIO_FN(TEND0), @@ -2119,7 +2134,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG("PCIOR0", 0xfffe3852, 16, 1) { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PC8_IN, PC8_OUT, PC7_IN, PC7_OUT, PC6_IN, PC6_OUT, diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index d25e6f674d0aba84cdb3ca7ba9b555eba0729f13..6dca760f9f280dd5997cfb266a535aeeac814e03 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c @@ -3086,6 +3086,7 @@ static const unsigned int tpu4_to2_mux[] = { }; static const unsigned int tpu4_to3_pins[] = { /* TO */ + PIN_NUMBER(6, 26), }; static const unsigned int tpu4_to3_mux[] = { TPU4TO3_MARK, @@ -3366,7 +3367,8 @@ static const char * const fsic_groups[] = { "fsic_sclk_out", "fsic_data_in", "fsic_data_out", - "fsic_spdif", + "fsic_spdif_0", + "fsic_spdif_1", }; static const char * const fsid_groups[] = { diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7734.c b/drivers/pinctrl/sh-pfc/pfc-sh7734.c index 33232041ee86dd3ea34afef3f7f98850f43ceba8..c691e5e9d9dea56d2a16dcc416cd53c0d6d4ec4a 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7734.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7734.c @@ -1453,7 +1453,7 @@ static const struct pinmux_func pinmux_func_gpios[] = { GPIO_FN(ET0_ETXD2_A), GPIO_FN(EX_CS5), GPIO_FN(SD1_CMD_A), GPIO_FN(ATADIR), GPIO_FN(QSSL_B), GPIO_FN(ET0_ETXD3_A), - GPIO_FN(RD_WR), GPIO_FN(TCLK1_B), + GPIO_FN(RD_WR), GPIO_FN(TCLK0), GPIO_FN(CAN_CLK_B), GPIO_FN(ET0_ETXD4), GPIO_FN(EX_WAIT0), GPIO_FN(TCLK1_B), GPIO_FN(EX_WAIT1), GPIO_FN(SD1_DAT0_A), GPIO_FN(DREQ2), GPIO_FN(CAN1_TX_C), GPIO_FN(ET0_LINK_C), GPIO_FN(ET0_ETXD5_A), @@ -1949,7 +1949,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* IP3_20 [1] */ FN_EX_WAIT0, FN_TCLK1_B, /* IP3_19_18 [2] */ - FN_RD_WR, FN_TCLK1_B, 0, 0, + FN_RD_WR, FN_TCLK0, FN_CAN_CLK_B, FN_ET0_ETXD4, /* IP3_17_15 [3] */ FN_EX_CS5, FN_SD1_CMD_A, FN_ATADIR, FN_QSSL_B, FN_ET0_ETXD3_A, 0, 0, 0, @@ -2231,13 +2231,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_LCD_CL1_B, 0, 0, /* IP10_5_3 [3] */ FN_SSI_WS23, FN_VI1_5_B, FN_TX1_D, FN_HSCK0_C, FN_FALE_B, - FN_LCD_DON_B, 0, 0, 0, + FN_LCD_DON_B, 0, 0, /* IP10_2_0 [3] */ FN_SSI_SCK23, FN_VI1_4_B, FN_RX1_D, FN_FCLE_B, FN_LCD_DATA15_B, 0, 0, 0 } }, { PINMUX_CFG_REG_VAR("IPSR11", 0xFFFC0048, 32, - 3, 1, 2, 2, 2, 3, 3, 1, 2, 3, 3, 1, 1, 1, 1) { + 3, 1, 2, 3, 2, 2, 3, 3, 1, 2, 3, 3, 1, 1, 1, 1) { /* IP11_31_29 [3] */ 0, 0, 0, 0, 0, 0, 0, 0, /* IP11_28 [1] */ diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c index 4300a558d0f39a4d15e7743368bc2a3a68e98b8e..d02214a3f8e3f39d999b0d87b18d2070f1edbbdf 100644 --- a/drivers/platform/mips/cpu_hwmon.c +++ b/drivers/platform/mips/cpu_hwmon.c @@ -155,7 +155,7 @@ static int __init loongson_hwmon_init(void) cpu_hwmon_dev = hwmon_device_register(NULL); if (IS_ERR(cpu_hwmon_dev)) { - ret = -ENOMEM; + ret = PTR_ERR(cpu_hwmon_dev); pr_err("hwmon_device_register fail!\n"); goto fail_hwmon_device_register; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 23e0bf70c9d8f402ae373358205b242d40d70e55..4b6922b7c6bf27754d286e79cb969cf3df727ea2 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -629,75 +629,74 @@ static void ipa3_get_usb_ep_info( ) { int ep_index = -1, i; + int pair_id = 0; - ep_info->num_ep_pairs = 0; for (i = 0; i < ep_info->max_ep_pairs; i++) { pair_info[i].consumer_pipe_num = -1; pair_info[i].producer_pipe_num = -1; pair_info[i].ep_id = -1; } - ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_PROD); - if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) { - pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index; - ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_CONS); - if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) { - pair_info[ep_info->num_ep_pairs].producer_pipe_num = - ep_index; - pair_info[ep_info->num_ep_pairs].ep_id = - IPA_USB1_EP_ID; + if ((!ep_info->teth_prot_valid) || (ep_info->teth_prot_valid && + ep_info->teth_prot == IPA_PROT_RMNET_CV2X)) { + ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_PROD); - IPADBG("ep_pair_info consumer_pipe_num %d", - pair_info[ep_info->num_ep_pairs]. - consumer_pipe_num); - IPADBG(" producer_pipe_num %d ep_id %d\n", - pair_info[ep_info->num_ep_pairs]. - producer_pipe_num, - pair_info[ep_info->num_ep_pairs].ep_id); - ep_info->num_ep_pairs++; - } else { - pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1; - IPADBG("ep_pair_info consumer_pipe_num %d", - pair_info[ep_info->num_ep_pairs]. - consumer_pipe_num); - IPADBG(" producer_pipe_num %d ep_id %d\n", - pair_info[ep_info->num_ep_pairs]. - producer_pipe_num, - pair_info[ep_info->num_ep_pairs].ep_id); + if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) { + pair_info[pair_id].consumer_pipe_num = ep_index; + ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_CONS); + + if ((ep_index != -1) && + (ipa3_ctx->ep[ep_index].valid)) { + pair_info[pair_id].producer_pipe_num = ep_index; + pair_info[pair_id].ep_id = IPA_USB1_EP_ID; + + IPADBG("ep_pair_info consumer_pipe_num %d", + pair_info[pair_id].consumer_pipe_num); + IPADBG(" producer_pipe_num %d ep_id %d\n", + pair_info[pair_id].producer_pipe_num, + pair_info[pair_id].ep_id); + pair_id++; + } else { + pair_info[pair_id].consumer_pipe_num = -1; + IPADBG("ep_pair_info consumer_pipe_num %d", + pair_info[pair_id].consumer_pipe_num); + IPADBG(" producer_pipe_num %d ep_id %d\n", + pair_info[pair_id].producer_pipe_num, + pair_info[pair_id].ep_id); + } } } + if ((!ep_info->teth_prot_valid) || (ep_info->teth_prot_valid && + ep_info->teth_prot == IPA_PROT_RMNET)) { + ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); - ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); + if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) { + pair_info[pair_id].consumer_pipe_num = ep_index; + ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_CONS); - if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) { - pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index; - ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_CONS); - if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) { - pair_info[ep_info->num_ep_pairs].producer_pipe_num = - ep_index; - pair_info[ep_info->num_ep_pairs].ep_id = - IPA_USB0_EP_ID; + if ((ep_index != -1) && + (ipa3_ctx->ep[ep_index].valid)) { + pair_info[pair_id].producer_pipe_num = ep_index; + pair_info[pair_id].ep_id = IPA_USB0_EP_ID; - IPADBG("ep_pair_info consumer_pipe_num %d", - pair_info[ep_info->num_ep_pairs]. - consumer_pipe_num); - IPADBG(" producer_pipe_num %d ep_id %d\n", - pair_info[ep_info->num_ep_pairs]. - producer_pipe_num, - pair_info[ep_info->num_ep_pairs].ep_id); - ep_info->num_ep_pairs++; - } else { - pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1; - IPADBG("ep_pair_info consumer_pipe_num %d", - pair_info[ep_info->num_ep_pairs]. - consumer_pipe_num); - IPADBG(" producer_pipe_num %d ep_id %d\n", - pair_info[ep_info->num_ep_pairs]. - producer_pipe_num, - pair_info[ep_info->num_ep_pairs].ep_id); + IPADBG("ep_pair_info consumer_pipe_num %d", + pair_info[pair_id].consumer_pipe_num); + IPADBG(" producer_pipe_num %d ep_id %d\n", + pair_info[pair_id].producer_pipe_num, + pair_info[pair_id].ep_id); + pair_id++; + } else { + pair_info[pair_id].consumer_pipe_num = -1; + IPADBG("ep_pair_info consumer_pipe_num %d", + pair_info[pair_id].consumer_pipe_num); + IPADBG(" producer_pipe_num %d ep_id %d\n", + pair_info[pair_id].producer_pipe_num, + pair_info[pair_id].ep_id); + } } } + ep_info->num_ep_pairs = pair_id; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index e5b7d419e11b8088236440cd7b3c76fda93cf08d..a9c1899662a4ce2987a19b6a2f329a69388bbd2f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -798,6 +798,13 @@ int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params, IPADBG("ep configuration successful\n"); } else { IPADBG("Skipping endpoint configuration.\n"); + if (IPA_CLIENT_IS_PROD(ipa3_ctx->ep[ipa_ep_idx].client) && + ipa3_ctx->ep[ipa_ep_idx].client == IPA_CLIENT_USB_PROD) + if (ipa3_cfg_ep_seq(ipa_ep_idx, + ¶ms->ipa_ep_cfg.seq)) { + IPAERR("fail to configure USB pipe seq\n"); + goto ipa_cfg_ep_fail; + } } out_params->clnt_hdl = ipa_ep_idx; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 50dc080bd949ba65a4e9cdcc92e79f3945589444..672f721fa395ae38fe264de4afe020122aa44163 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -32,6 +32,8 @@ #define IPA_READ_WRITE_MODE 0664 #define IPA_WRITE_ONLY_MODE 0220 +#define DEBUG_BUF_MAX_LEN(nbytes) (nbytes < IPA_MAX_MSG_LEN ? 1 : 0) + struct ipa3_debugfs_file { const char *name; umode_t mode; @@ -392,26 +394,34 @@ static ssize_t ipa3_read_hdr(struct file *file, char __user *ubuf, size_t count, ipa3_hdr_l2_type_name[entry->type]); if (entry->is_hdr_proc_ctx) { - nbytes += scnprintf( - dbg_buff + nbytes, - IPA_MAX_MSG_LEN - nbytes, - "phys_base=0x%pa ", - &entry->phys_base); + if (DEBUG_BUF_MAX_LEN(nbytes)) { + nbytes += scnprintf( + dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "phys_base=0x%pa ", + &entry->phys_base); + } } else { - nbytes += scnprintf( - dbg_buff + nbytes, - IPA_MAX_MSG_LEN - nbytes, - "ofst=%u ", - entry->offset_entry->offset >> 2); + if (DEBUG_BUF_MAX_LEN(nbytes)) { + nbytes += scnprintf( + dbg_buff + nbytes, + IPA_MAX_MSG_LEN - nbytes, + "ofst=%u ", + entry->offset_entry->offset >> 2); + } } for (i = 0; i < entry->hdr_len; i++) { - scnprintf(dbg_buff + nbytes + i * 2, - IPA_MAX_MSG_LEN - nbytes - i * 2, - "%02x", entry->hdr[i]); + if (DEBUG_BUF_MAX_LEN(nbytes + i * 2)) { + scnprintf(dbg_buff + nbytes + i * 2, + IPA_MAX_MSG_LEN - nbytes - i * 2, + "%02x", entry->hdr[i]); + } + } + if (DEBUG_BUF_MAX_LEN(nbytes + entry->hdr_len * 2)) { + scnprintf(dbg_buff + nbytes + entry->hdr_len * 2, + IPA_MAX_MSG_LEN - nbytes - entry->hdr_len * 2, + "\n"); } - scnprintf(dbg_buff + nbytes + entry->hdr_len * 2, - IPA_MAX_MSG_LEN - nbytes - entry->hdr_len * 2, - "\n"); pr_err("%s", dbg_buff); } mutex_unlock(&ipa3_ctx->lock); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index ed3089cd1b28fffc183aed67316c5a76cd2ca9a7..4c639596c60eb62f4f109cce79d014d3049f1379 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1967,6 +1967,8 @@ int ipa3_clear_endpoint_delay(u32 clnt_hdl); */ int ipa3_cfg_ep(u32 clnt_hdl, const struct ipa_ep_cfg *ipa_ep_cfg); +int ipa3_cfg_ep_seq(u32 clnt_hdl, const struct ipa_ep_cfg_seq *seq_cfg); + int ipa3_cfg_ep_nat(u32 clnt_hdl, const struct ipa_ep_cfg_nat *ipa_ep_cfg); int ipa3_cfg_ep_conn_track(u32 clnt_hdl, diff --git a/drivers/platform/msm/ipa/test/ipa_ut_framework.c b/drivers/platform/msm/ipa/test/ipa_ut_framework.c index dad3ec9fc2f3ed91358ce8e4aedd14e2625a353c..1db9ce94a474639041caed15277470d9e507cf8f 100644 --- a/drivers/platform/msm/ipa/test/ipa_ut_framework.c +++ b/drivers/platform/msm/ipa/test/ipa_ut_framework.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-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 @@ -439,9 +439,11 @@ static ssize_t ipa_ut_dbgfs_meta_test_read(struct file *file, for (i = 0 ; i < suite->tests_cnt ; i++) { if (!suite->tests[i].run_in_regression) continue; - nbytes += scnprintf(buf + nbytes, - IPA_UT_DEBUG_READ_BUF_SIZE - nbytes, - "\t\t%s\n", suite->tests[i].name); + if (nbytes < IPA_UT_DEBUG_READ_BUF_SIZE) { + nbytes += scnprintf(buf + nbytes, + IPA_UT_DEBUG_READ_BUF_SIZE - nbytes, + "\t\t%s\n", suite->tests[i].name); + } } } diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index fe419935041c14a9148a93353f068eb7a318b549..bee2115ecf10145edaf47638f9a6abc30b07d0dc 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -570,7 +570,7 @@ static ssize_t show_hdmi_source(struct device *dev, return scnprintf(buf, PAGE_SIZE, "input [gpu] unknown\n"); } - pr_err("alienware-wmi: unknown HDMI source status: %d\n", out_data); + pr_err("alienware-wmi: unknown HDMI source status: %u\n", status); return scnprintf(buf, PAGE_SIZE, "input gpu [unknown]\n"); } diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index aede41a92cacb29834080012b0a6c65e9c37f53f..4ae758c3d8ba531e57b6dbf355063a3e22a2dcb8 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -461,13 +461,7 @@ static void kbd_led_update(struct work_struct *work) asus = container_of(work, struct asus_wmi, kbd_led_work); - /* - * bits 0-2: level - * bit 7: light on/off - */ - if (asus->kbd_led_wk > 0) - ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F); - + ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F); asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL); } diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 05dc16b477f0d0837c03b3aa418fc49750673175..f065529390fe43413ee2eb899bdde1ea9df0a3c8 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -308,7 +308,7 @@ static int __init hp_wmi_bios_2008_later(void) static int __init hp_wmi_bios_2009_later(void) { - int state = 0; + u8 state[128]; int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state, sizeof(state), sizeof(state)); if (!ret) diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c index 4adf2ba021ceb2a2f99510d4ed28bfbae51617c4..043de9d039d54432b88e477addddb831c65bfd3d 100644 --- a/drivers/power/supply/ltc2941-battery-gauge.c +++ b/drivers/power/supply/ltc2941-battery-gauge.c @@ -364,7 +364,7 @@ static int ltc294x_i2c_remove(struct i2c_client *client) { struct ltc294x_info *info = i2c_get_clientdata(client); - cancel_delayed_work(&info->work); + cancel_delayed_work_sync(&info->work); power_supply_unregister(info->supply); return 0; } diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 77b6885d031771e4c3c35878912387a3f0383723..8560189f8027fa0e2e2b50b3847e22507fc77f24 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -774,14 +774,14 @@ __power_supply_register(struct device *parent, } spin_lock_init(&psy->changed_lock); - rc = device_init_wakeup(dev, ws); - if (rc) - goto wakeup_init_failed; - rc = device_add(dev); if (rc) goto device_add_failed; + rc = device_init_wakeup(dev, ws); + if (rc) + goto wakeup_init_failed; + rc = psy_register_thermal(psy); if (rc) goto register_thermal_failed; @@ -812,8 +812,8 @@ __power_supply_register(struct device *parent, psy_unregister_thermal(psy); register_thermal_failed: device_del(dev); -device_add_failed: wakeup_init_failed: +device_add_failed: check_supplies_failed: dev_set_name_failed: put_device(dev); diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 42bbc4c757a8102dcf9351b3228317fe2d763a74..7e5aacf0d9d07defb0a6990b2db43fe8bd924af6 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -2670,7 +2670,7 @@ static void clear_cycle_counter(struct fg_chip *chip) } rc = fg_sram_write(chip, CYCLE_COUNT_WORD, CYCLE_COUNT_OFFSET, (u8 *)&chip->cyc_ctr.count, - sizeof(chip->cyc_ctr.count) / sizeof(u8 *), + sizeof(chip->cyc_ctr.count) / (sizeof(u8 *)), FG_IMA_DEFAULT); if (rc < 0) pr_err("failed to clear cycle counter rc=%d\n", rc); diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 5208b3f80ad85cd4838e5529a9eb3064c520a496..239003807c085c1d1b4c0de8380c9e6dc34c3f0b 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -205,6 +205,12 @@ EXPORT_SYMBOL_GPL(pwm_lpss_probe); int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) { + int i; + + for (i = 0; i < lpwm->info->npwm; i++) { + if (pwm_is_enabled(&lpwm->chip.pwms[i])) + pm_runtime_put(lpwm->chip.dev); + } return pwmchip_remove(&lpwm->chip); } EXPORT_SYMBOL_GPL(pwm_lpss_remove); diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index f58a4867b5194e0bb41fdf9f4fd33a8a9a605ddc..a196439ee14c7287fc21e26f95672579b36357c3 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -320,11 +320,6 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->period != channel->state.period || state->duty_cycle != channel->state.duty_cycle || state->polarity != channel->state.polarity) { - if (channel->state.enabled) { - meson_pwm_disable(meson, pwm->hwpwm); - channel->state.enabled = false; - } - if (state->polarity != channel->state.polarity) { if (state->polarity == PWM_POLARITY_NORMAL) meson->inverter_mask |= BIT(pwm->hwpwm); diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 5ad42f33e70c11d8efd0ef4a545f01bf948e3c76..2e15acf13893d98cde13b1bc972a9ef4e33ca370 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c @@ -337,6 +337,11 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) static int pwm_omap_dmtimer_remove(struct platform_device *pdev) { struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev); + int ret; + + ret = pwmchip_remove(&omap->chip); + if (ret) + return ret; if (pm_runtime_active(&omap->dm_timer_pdev->dev)) omap->pdata->stop(omap->dm_timer); @@ -345,7 +350,7 @@ static int pwm_omap_dmtimer_remove(struct platform_device *pdev) mutex_destroy(&omap->mutex); - return pwmchip_remove(&omap->chip); + return 0; } static const struct of_device_id pwm_omap_dmtimer_of_match[] = { diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c index ef989a15aefc41b47aebfced74795d88a7cb88ce..b29fc258eeba4becb609d6e2063af1ebf5022e91 100644 --- a/drivers/rapidio/rio_cm.c +++ b/drivers/rapidio/rio_cm.c @@ -1215,7 +1215,9 @@ static int riocm_ch_listen(u16 ch_id) riocm_debug(CHOP, "(ch_%d)", ch_id); ch = riocm_get_channel(ch_id); - if (!ch || !riocm_cmp_exch(ch, RIO_CM_CHAN_BOUND, RIO_CM_LISTEN)) + if (!ch) + return -EINVAL; + if (!riocm_cmp_exch(ch, RIO_CM_CHAN_BOUND, RIO_CM_LISTEN)) ret = -EINVAL; riocm_put_channel(ch); return ret; diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 0f97514e347430b53277f1a42f7ddf1fe7b8e71b..c9f20e1394e3b233306f5902f5d1d823fecaac2b 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -1099,23 +1099,6 @@ static struct ab8500_regulator_info .update_val_idle = 0x82, .update_val_normal = 0x02, }, - [AB8505_LDO_USB] = { - .desc = { - .name = "LDO-USB", - .ops = &ab8500_regulator_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8505_LDO_USB, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_3300000_voltage, - }, - .update_bank = 0x03, - .update_reg = 0x82, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - }, [AB8505_LDO_AUDIO] = { .desc = { .name = "LDO-AUDIO", diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c56a99f10228ca0097f0af8ec322ac49992b0e5c..0d8130450dd362d7045160dd32e9fd56a00194ee 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -4859,7 +4859,7 @@ static int __init regulator_init(void) /* init early to allow our consumers to complete system booting */ core_initcall(regulator_init); -static int regulator_late_cleanup(struct device *dev, void *data) +static int __init regulator_late_cleanup(struct device *dev, void *data) { struct regulator_dev *rdev = dev_to_rdev(dev); const struct regulator_ops *ops = rdev->desc->ops; @@ -4908,8 +4908,17 @@ static int regulator_late_cleanup(struct device *dev, void *data) return 0; } -static void regulator_init_complete_work_function(struct work_struct *work) +static int __init regulator_init_complete(void) { + /* + * Since DT doesn't provide an idiomatic mechanism for + * enabling full constraints and since it's much more natural + * with DT to provide them just assume that a DT enabled + * system has full constraints. + */ + if (of_have_populated_dt()) + has_full_constraints = true; + /* * Regulators may had failed to resolve their input supplies * when were registered, either because the input supply was @@ -4927,35 +4936,6 @@ static void regulator_init_complete_work_function(struct work_struct *work) */ class_for_each_device(®ulator_class, NULL, NULL, regulator_late_cleanup); -} - -static DECLARE_DELAYED_WORK(regulator_init_complete_work, - regulator_init_complete_work_function); - -static int __init regulator_init_complete(void) -{ - /* - * Since DT doesn't provide an idiomatic mechanism for - * enabling full constraints and since it's much more natural - * with DT to provide them just assume that a DT enabled - * system has full constraints. - */ - if (of_have_populated_dt()) - has_full_constraints = true; - - /* - * We punt completion for an arbitrary amount of time since - * systems like distros will load many drivers from userspace - * so consumers might not always be ready yet, this is - * particularly an issue with laptops where this might bounce - * the display off then on. Ideally we'd get a notification - * from userspace when this happens but we don't so just wait - * a bit and hope we waited long enough. It'd be better if - * we'd only do this on systems that need it, and a kernel - * command line option might be useful. - */ - schedule_delayed_work(®ulator_init_complete_work, - msecs_to_jiffies(30000)); return 0; } diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index 5e941db5ccafb2c2bff40ed04bce76c8012787e9..c7e70cfb581fe696171d4deae07ae77352168f3f 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -299,7 +299,10 @@ static int max8907_regulator_probe(struct platform_device *pdev) memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc)); /* Backwards compatibility with MAX8907B; SD1 uses different voltages */ - regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val); + ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val); + if (ret) + return ret; + if ((val & MAX8907_II2RR_VERSION_MASK) == MAX8907_II2RR_VERSION_REV_B) { pmic->desc[MAX8907_SD1].min_uV = 637500; @@ -336,14 +339,20 @@ static int max8907_regulator_probe(struct platform_device *pdev) } if (pmic->desc[i].ops == &max8907_ldo_ops) { - regmap_read(config.regmap, pmic->desc[i].enable_reg, + ret = regmap_read(config.regmap, pmic->desc[i].enable_reg, &val); + if (ret) + return ret; + if ((val & MAX8907_MASK_LDO_SEQ) != MAX8907_MASK_LDO_SEQ) pmic->desc[i].ops = &max8907_ldo_hwctl_ops; } else if (pmic->desc[i].ops == &max8907_out5v_ops) { - regmap_read(config.regmap, pmic->desc[i].enable_reg, + ret = regmap_read(config.regmap, pmic->desc[i].enable_reg, &val); + if (ret) + return ret; + if ((val & (MAX8907_MASK_OUT5V_VINEN | MAX8907_MASK_OUT5V_ENSRC)) != MAX8907_MASK_OUT5V_ENSRC) diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c index 6c4afc73ecac3d7cb47d1a87da60b95f14ba9370..d229245d2b5e854c349adf37cd3e6d1b36e55b0a 100644 --- a/drivers/regulator/pv88060-regulator.c +++ b/drivers/regulator/pv88060-regulator.c @@ -135,7 +135,7 @@ static int pv88060_set_current_limit(struct regulator_dev *rdev, int min, int i; /* search for closest to maximum */ - for (i = info->n_current_limits; i >= 0; i--) { + for (i = info->n_current_limits - 1; i >= 0; i--) { if (min <= info->current_limits[i] && max >= info->current_limits[i]) { return regmap_update_bits(rdev->regmap, diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index 954a20eeb26f89362be0a4274d364b22a8db3783..a40ecfb77210721cf4484c266ab3bdf06399bf8c 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -279,7 +279,7 @@ static int pv88080_set_current_limit(struct regulator_dev *rdev, int min, int i; /* search for closest to maximum */ - for (i = info->n_current_limits; i >= 0; i--) { + for (i = info->n_current_limits - 1; i >= 0; i--) { if (min <= info->current_limits[i] && max >= info->current_limits[i]) { return regmap_update_bits(rdev->regmap, diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c index 42164117535298bc011378bad23f221e8063c566..789652c9b01423f69eb4c77ab78837466b063d76 100644 --- a/drivers/regulator/pv88090-regulator.c +++ b/drivers/regulator/pv88090-regulator.c @@ -157,7 +157,7 @@ static int pv88090_set_current_limit(struct regulator_dev *rdev, int min, int i; /* search for closest to maximum */ - for (i = info->n_current_limits; i >= 0; i--) { + for (i = info->n_current_limits - 1; i >= 0; i--) { if (min <= info->current_limits[i] && max >= info->current_limits[i]) { return regmap_update_bits(rdev->regmap, diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index dfa8d50a5d741461ba24895a4d628bd6cc9b2c72..28646e4cf3bae98fe1b24a2eb9f3451faae1d37a 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -589,7 +589,7 @@ static int rk808_regulator_dt_parse_pdata(struct device *dev, } if (!pdata->dvs_gpio[i]) { - dev_warn(dev, "there is no dvs%d gpio\n", i); + dev_info(dev, "there is no dvs%d gpio\n", i); continue; } diff --git a/drivers/regulator/rn5t618-regulator.c b/drivers/regulator/rn5t618-regulator.c index 9c930eb68cda69bf6ad87cec1d302b2c7f83e9ba..ffc34e1ee35ddd75ae75962ef7c36c2b9b480c63 100644 --- a/drivers/regulator/rn5t618-regulator.c +++ b/drivers/regulator/rn5t618-regulator.c @@ -127,6 +127,7 @@ static struct platform_driver rn5t618_regulator_driver = { module_platform_driver(rn5t618_regulator_driver); +MODULE_ALIAS("platform:rn5t618-regulator"); MODULE_AUTHOR("Beniamino Galvani "); MODULE_DESCRIPTION("RN5T618 regulator driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c index 6dbf3cf3951e2863f4a2ba9cc8e1e3ae11c1c566..12d26261394f13995fd8e2e326195ca7c2bc35d7 100644 --- a/drivers/regulator/tps65086-regulator.c +++ b/drivers/regulator/tps65086-regulator.c @@ -89,8 +89,8 @@ static const struct regulator_linear_range tps65086_buck345_25mv_ranges[] = { static const struct regulator_linear_range tps65086_ldoa1_ranges[] = { REGULATOR_LINEAR_RANGE(1350000, 0x0, 0x0, 0), REGULATOR_LINEAR_RANGE(1500000, 0x1, 0x7, 100000), - REGULATOR_LINEAR_RANGE(2300000, 0x8, 0xA, 100000), - REGULATOR_LINEAR_RANGE(2700000, 0xB, 0xD, 150000), + REGULATOR_LINEAR_RANGE(2300000, 0x8, 0xB, 100000), + REGULATOR_LINEAR_RANGE(2850000, 0xC, 0xD, 150000), REGULATOR_LINEAR_RANGE(3300000, 0xE, 0xE, 0), }; diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 5a5bc4bb08d26ee78926aacaa906010cc1f426c2..df591435d12a376f051e79e670ade55ab6ef1b7a 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -327,8 +327,8 @@ static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev) } /* Current limit options */ -static u16 wm831x_dcdc_ilim[] = { - 125, 250, 375, 500, 625, 750, 875, 1000 +static const unsigned int wm831x_dcdc_ilim[] = { + 125000, 250000, 375000, 500000, 625000, 750000, 875000, 1000000 }; static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev, diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index c6bfb3496684efde7dc55d777e392445490db585..b99780574044a50d852825972f962ab8683a68a8 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1488,7 +1488,7 @@ static int __init remoteproc_init(void) return 0; } -module_init(remoteproc_init); +subsys_initcall(remoteproc_init); static void __exit remoteproc_exit(void) { diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 466bf7f9a285a5c455a26d199083384d93a4e121..7da2a1fb50f8999dd7df52eb056a83fee0b2a1c6 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -116,12 +116,14 @@ static int pm80x_rtc_read_time(struct device *dev, struct rtc_time *tm) unsigned char buf[4]; unsigned long ticks, base, data; regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); - base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + base = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); /* load 32-bit read-only counter */ regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; ticks = base + data; dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); @@ -144,7 +146,8 @@ static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm) /* load 32-bit read-only counter */ regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; base = ticks - data; dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); @@ -165,11 +168,13 @@ static int pm80x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) int ret; regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); - base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + base = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); regmap_raw_read(info->map, PM800_RTC_EXPIRE1_1, buf, 4); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; ticks = base + data; dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); @@ -192,12 +197,14 @@ static int pm80x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_ALARM1_EN, 0); regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); - base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + base = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); /* load 32-bit read-only counter */ regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; ticks = base + data; dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 166faae3a59cd10441e68bfe4f69f3adefdaee57..7d3e5168fcefcdb1ad637e9091cb16e3e2893e20 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -115,11 +115,13 @@ static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm) pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; + base = ((unsigned long)buf[1] << 24) | (buf[3] << 16) | + (buf[5] << 8) | buf[7]; /* load 32-bit read-only counter */ pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; ticks = base + data; dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); @@ -145,7 +147,8 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm) /* load 32-bit read-only counter */ pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; base = ticks - data; dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); @@ -170,10 +173,12 @@ static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; + base = ((unsigned long)buf[1] << 24) | (buf[3] << 16) | + (buf[5] << 8) | buf[7]; pm860x_bulk_read(info->i2c, PM8607_RTC_EXPIRE1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; ticks = base + data; dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); @@ -198,11 +203,13 @@ static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; + base = ((unsigned long)buf[1] << 24) | (buf[3] << 16) | + (buf[5] << 8) | buf[7]; /* load 32-bit read-only counter */ pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); - data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; ticks = base + data; dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", base, data, ticks); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index c554e529fc4e0af49ad9ae2339ff808357c1d27e..b962dbe51750d41d540c4b5e37c5c40a87a24306 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -730,7 +730,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) rtc_cmos_int_handler = cmos_interrupt; retval = request_irq(rtc_irq, rtc_cmos_int_handler, - IRQF_SHARED, dev_name(&cmos_rtc.rtc->dev), + 0, dev_name(&cmos_rtc.rtc->dev), cmos_rtc.rtc); if (retval < 0) { dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 5c18ac7394c42a4cae30046ec30a1240ea66997a..c911f2db0af5ea3b01e44286c61a34f476144bf0 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -58,7 +58,8 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) "%s: raw read data - counters=%02x,%02x,%02x,%02x\n", __func__, buf[0], buf[1], buf[2], buf[3]); - time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + time = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | + (buf[1] << 8) | buf[0]; rtc_time_to_tm(time, tm); diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index e5ad527cb75e369945a7a533105d6d0d8573ac10..a8c2d38b24112f53b9e7561c9843ab3deca86db7 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -105,7 +105,7 @@ static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm) if (!hym8563->valid) { dev_warn(&client->dev, "no valid clock/calendar values available\n"); - return -EPERM; + return -EINVAL; } ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf); diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c index db984d4bf9526bbc78e501ff8da6a7036801872b..4cce5bd448f65f0cb54259ead69ff008d5a12e54 100644 --- a/drivers/rtc/rtc-max8997.c +++ b/drivers/rtc/rtc-max8997.c @@ -221,7 +221,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) out: mutex_unlock(&info->lock); - return 0; + return ret; } static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info) diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c index 2f1772a358ca50342d4375de3e69f2fba451ceaf..18a6f15e313d8b33ae6ae2905ea6b364e9ede701 100644 --- a/drivers/rtc/rtc-mc146818-lib.c +++ b/drivers/rtc/rtc-mc146818-lib.c @@ -82,7 +82,7 @@ unsigned int mc146818_get_time(struct rtc_time *time) time->tm_year += real_year - 72; #endif - if (century) + if (century > 20) time->tm_year += (century - 19) * 100; /* diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c index c1c5c4e3b3b4715ea250a5b16bfaa49e2ebd688b..c981301efbe5e8c8cf309854cd415260eb93f6be 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c @@ -132,7 +132,8 @@ static int msm6242_read_time(struct device *dev, struct rtc_time *tm) msm6242_read(priv, MSM6242_SECOND1); tm->tm_min = msm6242_read(priv, MSM6242_MINUTE10) * 10 + msm6242_read(priv, MSM6242_MINUTE1); - tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 + + tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10) & + MSM6242_HOUR10_HR_MASK) * 10 + msm6242_read(priv, MSM6242_HOUR1); tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 + msm6242_read(priv, MSM6242_DAY1); diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index 1a61fa56f3ad77bad999d234778e8d953fc1ad5a..494a7fbd512b7bec00035d6e1e09dcdc4e24768d 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -55,6 +55,14 @@ #define RTC_AL_SEC 0x0018 +#define RTC_AL_SEC_MASK 0x003f +#define RTC_AL_MIN_MASK 0x003f +#define RTC_AL_HOU_MASK 0x001f +#define RTC_AL_DOM_MASK 0x001f +#define RTC_AL_DOW_MASK 0x0007 +#define RTC_AL_MTH_MASK 0x000f +#define RTC_AL_YEA_MASK 0x007f + #define RTC_PDN2 0x002e #define RTC_PDN2_PWRON_ALARM BIT(4) @@ -111,7 +119,7 @@ static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data) irqen = irqsta & ~RTC_IRQ_EN_AL; mutex_lock(&rtc->lock); if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, - irqen) < 0) + irqen) == 0) mtk_rtc_write_trigger(rtc); mutex_unlock(&rtc->lock); @@ -233,12 +241,12 @@ static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM); mutex_unlock(&rtc->lock); - tm->tm_sec = data[RTC_OFFSET_SEC]; - tm->tm_min = data[RTC_OFFSET_MIN]; - tm->tm_hour = data[RTC_OFFSET_HOUR]; - tm->tm_mday = data[RTC_OFFSET_DOM]; - tm->tm_mon = data[RTC_OFFSET_MTH]; - tm->tm_year = data[RTC_OFFSET_YEAR]; + tm->tm_sec = data[RTC_OFFSET_SEC] & RTC_AL_SEC_MASK; + tm->tm_min = data[RTC_OFFSET_MIN] & RTC_AL_MIN_MASK; + tm->tm_hour = data[RTC_OFFSET_HOUR] & RTC_AL_HOU_MASK; + tm->tm_mday = data[RTC_OFFSET_DOM] & RTC_AL_DOM_MASK; + tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_AL_MTH_MASK; + tm->tm_year = data[RTC_OFFSET_YEAR] & RTC_AL_YEA_MASK; tm->tm_year += RTC_MIN_YEAR_OFFSET; tm->tm_mon--; @@ -259,14 +267,25 @@ static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) tm->tm_year -= RTC_MIN_YEAR_OFFSET; tm->tm_mon++; - data[RTC_OFFSET_SEC] = tm->tm_sec; - data[RTC_OFFSET_MIN] = tm->tm_min; - data[RTC_OFFSET_HOUR] = tm->tm_hour; - data[RTC_OFFSET_DOM] = tm->tm_mday; - data[RTC_OFFSET_MTH] = tm->tm_mon; - data[RTC_OFFSET_YEAR] = tm->tm_year; - mutex_lock(&rtc->lock); + ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC, + data, RTC_OFFSET_COUNT); + if (ret < 0) + goto exit; + + data[RTC_OFFSET_SEC] = ((data[RTC_OFFSET_SEC] & ~(RTC_AL_SEC_MASK)) | + (tm->tm_sec & RTC_AL_SEC_MASK)); + data[RTC_OFFSET_MIN] = ((data[RTC_OFFSET_MIN] & ~(RTC_AL_MIN_MASK)) | + (tm->tm_min & RTC_AL_MIN_MASK)); + data[RTC_OFFSET_HOUR] = ((data[RTC_OFFSET_HOUR] & ~(RTC_AL_HOU_MASK)) | + (tm->tm_hour & RTC_AL_HOU_MASK)); + data[RTC_OFFSET_DOM] = ((data[RTC_OFFSET_DOM] & ~(RTC_AL_DOM_MASK)) | + (tm->tm_mday & RTC_AL_DOM_MASK)); + data[RTC_OFFSET_MTH] = ((data[RTC_OFFSET_MTH] & ~(RTC_AL_MTH_MASK)) | + (tm->tm_mon & RTC_AL_MTH_MASK)); + data[RTC_OFFSET_YEAR] = ((data[RTC_OFFSET_YEAR] & ~(RTC_AL_YEA_MASK)) | + (tm->tm_year & RTC_AL_YEA_MASK)); + if (alm->enabled) { ret = regmap_bulk_write(rtc->regmap, rtc->addr_base + RTC_AL_SEC, diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index a4b8b603c807da32671788d6d62edc860ccd6e39..533fb7027f0cc26bfe9b9dc49b63ee1d52a92783 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -563,7 +563,6 @@ static int pcf8563_probe(struct i2c_client *client, struct pcf8563 *pcf8563; int err; unsigned char buf; - unsigned char alm_pending; dev_dbg(&client->dev, "%s\n", __func__); @@ -587,13 +586,13 @@ static int pcf8563_probe(struct i2c_client *client, return err; } - err = pcf8563_get_alarm_mode(client, NULL, &alm_pending); - if (err) { - dev_err(&client->dev, "%s: read error\n", __func__); + /* Clear flags and disable interrupts */ + buf = 0; + err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf); + if (err < 0) { + dev_err(&client->dev, "%s: write error\n", __func__); return err; } - if (alm_pending) - pcf8563_set_alarm_mode(client, 0); pcf8563->rtc = devm_rtc_device_register(&client->dev, pcf8563_driver.driver.name, diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 5309edcee7b7cad5fb76c98bcda2240287df5137..3b619b7b2c530a0a8680bf610b868d0d088b8ec4 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -213,7 +213,8 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) } } - secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); + secs = value[0] | (value[1] << 8) | (value[2] << 16) | + ((unsigned long)value[3] << 24); rtc_time_to_tm(secs, tm); @@ -294,7 +295,8 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) return rc; } - secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); + secs = value[0] | (value[1] << 8) | (value[2] << 16) | + ((unsigned long)value[3] << 24); rtc_time_to_tm(secs, &alarm->time); diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 9082476b51db9122a8a41186e7e40e1a97172368..4e9f794176d3511fc461af23b00aea5b174fb6c7 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -302,8 +302,10 @@ static void * cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset) { struct ccwdev_iter *iter; + loff_t p = *offset; - if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) + (*offset)++; + if (p >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) return NULL; iter = it; if (iter->devno == __MAX_SUBCHANNEL) { @@ -313,7 +315,6 @@ cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset) return NULL; } else iter->devno++; - (*offset)++; return iter; } diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index b6caad0fee24cd5fe28e8213ff400c0f121e5a82..c53ea0ac5f460350f412dd5e324703f0502f79c5 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -93,11 +93,9 @@ void zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req) memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); - if (req->fsf_command != FSF_QTCB_FCP_CMND) { - rec->pl_len = q_head->log_length; - zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start, - rec->pl_len, "fsf_res", req->req_id); - } + rec->pl_len = q_head->log_length; + zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start, + rec->pl_len, "fsf_res", req->req_id); debug_event(dbf->hba, level, rec, sizeof(*rec)); spin_unlock_irqrestore(&dbf->hba_lock, flags); diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index cc62d8cc8cfdd3bbbfcb078c9e5352d7fe4c1d56..d5214c4eb9ddb87f970a4048b6644242a4da7e97 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -178,9 +178,6 @@ static int zfcp_erp_handle_failed(int want, struct zfcp_adapter *adapter, adapter, ZFCP_STATUS_COMMON_ERP_FAILED); } break; - default: - need = 0; - break; } return need; diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 64ab9eaec428c53f853ae4ef5e8e749f3ac6c188..def3208dd2905501dda2f78b809b8c781b9553a3 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -2321,7 +2321,7 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period, * At some speeds, we only support * ST transfers. */ - if ((syncrate->sxfr_u2 & ST_SXFR) != 0) + if ((syncrate->sxfr_u2 & ST_SXFR) != 0) *ppr_options &= ~MSG_EXT_PPR_DT_REQ; break; } diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index a59ad94ea52b371272d4878b857f5efa532c4c16..9dc4b689f94b0cebda1d2c55d6c97e1d8a500191 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -753,7 +753,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev) atari_scsi_template.sg_tablesize = SG_ALL; } else { atari_scsi_template.can_queue = 1; - atari_scsi_template.sg_tablesize = SG_NONE; + atari_scsi_template.sg_tablesize = 1; } if (setup_can_queue > 0) @@ -762,8 +762,8 @@ static int __init atari_scsi_probe(struct platform_device *pdev) if (setup_cmd_per_lun > 0) atari_scsi_template.cmd_per_lun = setup_cmd_per_lun; - /* Leave sg_tablesize at 0 on a Falcon! */ - if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0) + /* Don't increase sg_tablesize on Falcon! */ + if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize > 0) atari_scsi_template.sg_tablesize = setup_sg_tablesize; if (setup_hostid >= 0) { diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index d0a504af5b4f836df14dcbd04908b62a237d2ce0..0a70d54a4df68e572a98d7efa3f555fc072e84a6 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -283,8 +283,10 @@ bfad_im_get_stats(struct Scsi_Host *shost) rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa), fcstats, bfad_hcb_comp, &fcomp); spin_unlock_irqrestore(&bfad->bfad_lock, flags); - if (rc != BFA_STATUS_OK) + if (rc != BFA_STATUS_OK) { + kfree(fcstats); return NULL; + } wait_for_completion(&fcomp.comp); diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 133901fd3e35f2b02194481c3a93f7b9b1097c1c..6d1f8b22bd830e2fe28f419954667af04e7c0224 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -915,12 +915,12 @@ void bnx2i_free_hba(struct bnx2i_hba *hba) INIT_LIST_HEAD(&hba->ep_ofld_list); INIT_LIST_HEAD(&hba->ep_active_list); INIT_LIST_HEAD(&hba->ep_destroy_list); - pci_dev_put(hba->pcidev); if (hba->regview) { pci_iounmap(hba->pcidev, hba->regview); hba->regview = NULL; } + pci_dev_put(hba->pcidev); bnx2i_free_mp_bdt(hba); bnx2i_release_free_cid_que(hba); iscsi_host_free(shost); diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c index be5ee2d37815510226627261955f75d842711fd6..957767d383610a081dd0349713e425c7d200cb15 100644 --- a/drivers/scsi/csiostor/csio_lnode.c +++ b/drivers/scsi/csiostor/csio_lnode.c @@ -301,6 +301,7 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) struct fc_fdmi_port_name *port_name; uint8_t buf[64]; uint8_t *fc4_type; + unsigned long flags; if (fdmi_req->wr_status != FW_SUCCESS) { csio_ln_dbg(ln, "WR error:%x in processing fdmi rhba cmd\n", @@ -377,13 +378,13 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) len = (uint32_t)(pld - (uint8_t *)cmd); /* Submit FDMI RPA request */ - spin_lock_irq(&hw->lock); + spin_lock_irqsave(&hw->lock, flags); if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_done, FCOE_CT, &fdmi_req->dma_buf, len)) { CSIO_INC_STATS(ln, n_fdmi_err); csio_ln_dbg(ln, "Failed to issue fdmi rpa req\n"); } - spin_unlock_irq(&hw->lock); + spin_unlock_irqrestore(&hw->lock, flags); } /* @@ -404,6 +405,7 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) struct fc_fdmi_rpl *reg_pl; struct fs_fdmi_attrs *attrib_blk; uint8_t buf[64]; + unsigned long flags; if (fdmi_req->wr_status != FW_SUCCESS) { csio_ln_dbg(ln, "WR error:%x in processing fdmi dprt cmd\n", @@ -483,13 +485,13 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) attrib_blk->numattrs = htonl(numattrs); /* Submit FDMI RHBA request */ - spin_lock_irq(&hw->lock); + spin_lock_irqsave(&hw->lock, flags); if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_rhba_cbfn, FCOE_CT, &fdmi_req->dma_buf, len)) { CSIO_INC_STATS(ln, n_fdmi_err); csio_ln_dbg(ln, "Failed to issue fdmi rhba req\n"); } - spin_unlock_irq(&hw->lock); + spin_unlock_irqrestore(&hw->lock, flags); } /* @@ -504,6 +506,7 @@ csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) void *cmd; struct fc_fdmi_port_name *port_name; uint32_t len; + unsigned long flags; if (fdmi_req->wr_status != FW_SUCCESS) { csio_ln_dbg(ln, "WR error:%x in processing fdmi dhba cmd\n", @@ -534,13 +537,13 @@ csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) len += sizeof(*port_name); /* Submit FDMI request */ - spin_lock_irq(&hw->lock); + spin_lock_irqsave(&hw->lock, flags); if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dprt_cbfn, FCOE_CT, &fdmi_req->dma_buf, len)) { CSIO_INC_STATS(ln, n_fdmi_err); csio_ln_dbg(ln, "Failed to issue fdmi dprt req\n"); } - spin_unlock_irq(&hw->lock); + spin_unlock_irqrestore(&hw->lock, flags); } /** diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c index 894d97e4ace511167afda84f0b45c5b940eaf787..5db57671fa280aedc4fcd2fb531d30dd3f41171c 100644 --- a/drivers/scsi/csiostor/csio_scsi.c +++ b/drivers/scsi/csiostor/csio_scsi.c @@ -1383,7 +1383,7 @@ csio_device_reset(struct device *dev, return -EINVAL; /* Delete NPIV lnodes */ - csio_lnodes_exit(hw, 1); + csio_lnodes_exit(hw, 1); /* Block upper IOs */ csio_lnodes_block_request(hw); diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index e974106f2bb504195b4b73f94df26ea2b3136e88..3d6e653f51470af857c5fd6632bd31e425fff5c7 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -121,7 +121,8 @@ static inline void cxgbi_device_destroy(struct cxgbi_device *cdev) "cdev 0x%p, p# %u.\n", cdev, cdev->nports); cxgbi_hbas_remove(cdev); cxgbi_device_portmap_cleanup(cdev); - cxgbi_ppm_release(cdev->cdev2ppm(cdev)); + if (cdev->cdev2ppm) + cxgbi_ppm_release(cdev->cdev2ppm(cdev)); if (cdev->pmap.max_connect) cxgbi_free_big_mem(cdev->pmap.port_csk); kfree(cdev); diff --git a/drivers/scsi/esas2r/esas2r_flash.c b/drivers/scsi/esas2r/esas2r_flash.c index 7bd376d95ed5225e0490ce4939775aa609eea74f..b02ac389e6c6050fc92696d480131db15678ebb4 100644 --- a/drivers/scsi/esas2r/esas2r_flash.c +++ b/drivers/scsi/esas2r/esas2r_flash.c @@ -1197,6 +1197,7 @@ bool esas2r_nvram_read_direct(struct esas2r_adapter *a) if (!esas2r_read_flash_block(a, a->nvram, FLS_OFFSET_NVR, sizeof(struct esas2r_sas_nvram))) { esas2r_hdebug("NVRAM read failed, using defaults"); + up(&a->nvram_semaphore); return false; } diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index c056b8111ad2705f71147813e0ad51b1a0b2ca68..7bf6102b4c3d52396014391cc5929f54b1f2c155 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -445,6 +445,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) return SCSI_MLQUEUE_HOST_BUSY; + if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET))) + return SCSI_MLQUEUE_HOST_BUSY; + rport = starget_to_rport(scsi_target(sc->device)); ret = fc_remote_port_chkready(rport); if (ret) { diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c index 9795d6f3e1974e47e98f6d28ef80f1e4f282e528..c5b89a003d2ab0c80082b55d9665a5647d662eff 100644 --- a/drivers/scsi/fnic/vnic_dev.c +++ b/drivers/scsi/fnic/vnic_dev.c @@ -445,26 +445,26 @@ int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) int vnic_dev_hang_notify(struct vnic_dev *vdev) { - u64 a0, a1; + u64 a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait); } int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) { - u64 a0, a1; + u64 a[2] = {}; int wait = 1000; int err, i; for (i = 0; i < ETH_ALEN; i++) mac_addr[i] = 0; - err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); + err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a[0], &a[1], wait); if (err) return err; for (i = 0; i < ETH_ALEN; i++) - mac_addr[i] = ((u8 *)&a0)[i]; + mac_addr[i] = ((u8 *)&a)[i]; return 0; } @@ -489,38 +489,32 @@ void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) { - u64 a0 = 0, a1 = 0; + u64 a[2] = {}; int wait = 1000; int err; int i; for (i = 0; i < ETH_ALEN; i++) - ((u8 *)&a0)[i] = addr[i]; + ((u8 *)&a)[i] = addr[i]; - err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); + err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a[0], &a[1], wait); if (err) - printk(KERN_ERR - "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], - err); + pr_err("Can't add addr [%pM], %d\n", addr, err); } void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) { - u64 a0 = 0, a1 = 0; + u64 a[2] = {}; int wait = 1000; int err; int i; for (i = 0; i < ETH_ALEN; i++) - ((u8 *)&a0)[i] = addr[i]; + ((u8 *)&a)[i] = addr[i]; - err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); + err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a[0], &a[1], wait); if (err) - printk(KERN_ERR - "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], - err); + pr_err("Can't del addr [%pM], %d\n", addr, err); } int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index d60564397be548e584e6777cb01ebf17c7f8bcac..60c3e2bf8761993c0d25fab6424cb0261c1cba89 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -882,6 +882,10 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session) { struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = cls_session->dd_data; + + if (WARN_ON_ONCE(session->leadconn)) + return; iscsi_tcp_r2tpool_free(cls_session->dd_data); iscsi_session_teardown(cls_session); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 16ca31ad5ec0abba2d0b08ad1d337ff8afcbbd9a..d0a86ef806522ac0b217e1a7a6e3e2312ef4204e 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2506,7 +2506,7 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) /* lport lock ? */ if (!lport || lport->state == LPORT_ST_DISABLED) { - FC_LPORT_DBG(lport, "Receiving frames for an lport that " + FC_LIBFC_DBG("Receiving frames for an lport that " "has not been initialized correctly\n"); fc_frame_free(fp); return; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 2ffe10453e30478aa333bda92fb39d8f07bbb8c6..c4336b01db23ca6f0aa0e9f5857979fbf3bdcc87 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1982,7 +1982,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc); - spin_lock(&session->frwd_lock); + spin_lock_bh(&session->frwd_lock); task = (struct iscsi_task *)sc->SCp.ptr; if (!task) { /* @@ -2109,7 +2109,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) done: if (task) task->last_timeout = jiffies; - spin_unlock(&session->frwd_lock); + spin_unlock_bh(&session->frwd_lock); ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? "timer reset" : "shutdown or nh"); return rc; diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 60de66252fa2b9ea168648c5097da7f8ae7f49ae..b200edc665a58f83c560213175f3bc6e26a192d0 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -97,12 +97,21 @@ static int sas_get_port_device(struct asd_sas_port *port) else dev->dev_type = SAS_SATA_DEV; dev->tproto = SAS_PROTOCOL_SATA; - } else { + } else if (port->oob_mode == SAS_OOB_MODE) { struct sas_identify_frame *id = (struct sas_identify_frame *) dev->frame_rcvd; dev->dev_type = id->dev_type; dev->iproto = id->initiator_bits; dev->tproto = id->target_bits; + } else { + /* If the oob mode is OOB_NOT_CONNECTED, the port is + * disconnected due to race with PHY down. We cannot + * continue to discover this port + */ + sas_put_device(dev); + pr_warn("Port %016llx is disconnected when discovering\n", + SAS_ADDR(port->attached_sas_addr)); + return -ENODEV; } sas_init_dev(dev); diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index b484859464f6b2695fe41d24a5cfecf8e8824c49..f0f6d71d28b81f29783a879fdd9bca013ec142a4 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -878,7 +878,8 @@ struct lpfc_hba { struct list_head port_list; struct lpfc_vport *pport; /* physical lpfc_vport pointer */ uint16_t max_vpi; /* Maximum virtual nports */ -#define LPFC_MAX_VPI 0xFFFF /* Max number of VPI supported */ +#define LPFC_MAX_VPI 0xFF /* Max number VPI supported 0 - 0xff */ +#define LPFC_MAX_VPORTS 0x100 /* Max vports per port, with pport */ uint16_t max_vports; /* * For IOV HBAs max_vpi can change * after a reset. max_vports is max diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index cf15b9754402b7e11e27bc7a06f8a139766a6f37..aa0435b1ea1e7d5294c2877dc3d6affab72b95ea 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1214,6 +1214,9 @@ lpfc_get_hba_info(struct lpfc_hba *phba, max_vpi = (bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config) > 0) ? (bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config) - 1) : 0; + /* Limit the max we support */ + if (max_vpi > LPFC_MAX_VPI) + max_vpi = LPFC_MAX_VPI; if (mvpi) *mvpi = max_vpi; if (avpi) @@ -1229,8 +1232,13 @@ lpfc_get_hba_info(struct lpfc_hba *phba, *axri = pmb->un.varRdConfig.avail_xri; if (mvpi) *mvpi = pmb->un.varRdConfig.max_vpi; - if (avpi) - *avpi = pmb->un.varRdConfig.avail_vpi; + if (avpi) { + /* avail_vpi is only valid if link is up and ready */ + if (phba->link_state == LPFC_HBA_READY) + *avpi = pmb->un.varRdConfig.avail_vpi; + else + *avpi = pmb->un.varRdConfig.max_vpi; + } } mempool_free(pmboxq, phba->mbox_mem_pool); diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 05dcc2abd541a2c8900a58f8bc1f494710e68b5e..99f06ac7bf4c501ee67ef050c33279c2a86c225e 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -4352,12 +4352,6 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, phba->mbox_ext_buf_ctx.seqNum++; nemb_tp = phba->mbox_ext_buf_ctx.nembType; - dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); - if (!dd_data) { - rc = -ENOMEM; - goto job_error; - } - pbuf = (uint8_t *)dmabuf->virt; size = job->request_payload.payload_len; sg_copy_to_buffer(job->request_payload.sg_list, @@ -4394,6 +4388,13 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, "2968 SLI_CONFIG ext-buffer wr all %d " "ebuffers received\n", phba->mbox_ext_buf_ctx.numBuf); + + dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); + if (!dd_data) { + rc = -ENOMEM; + goto job_error; + } + /* mailbox command structure for base driver */ pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmboxq) { @@ -4441,6 +4442,8 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, return SLI_CONFIG_HANDLED; job_error: + if (pmboxq) + mempool_free(pmboxq, phba->mbox_mem_pool); lpfc_bsg_dma_page_free(phba, dmabuf); kfree(dd_data); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 3702497b5b169804fbc7e5e065edc048c11ae89e..4901bf24916b5c6ea26158f1ddac6d9a9d4b108b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -3863,7 +3863,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, mempool_free(mbox, phba->mbox_mem_pool); } out: - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { + if (ndlp && NLP_CHK_NODE_ACT(ndlp) && shost) { spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI); spin_unlock_irq(shost->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2f80b2c0409e0dd6139258ae593dade68f014ab2..8c640bcf107bd808fbd3e4c0f4e95fc87deb9298 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -6973,6 +6973,9 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) bf_get(lpfc_mbx_rd_conf_xri_base, rd_config); phba->sli4_hba.max_cfg_param.max_vpi = bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config); + /* Limit the max we support */ + if (phba->sli4_hba.max_cfg_param.max_vpi > LPFC_MAX_VPORTS) + phba->sli4_hba.max_cfg_param.max_vpi = LPFC_MAX_VPORTS; phba->sli4_hba.max_cfg_param.vpi_base = bf_get(lpfc_mbx_rd_conf_vpi_base, rd_config); phba->sli4_hba.max_cfg_param.max_rpi = diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 21ec7b5b6c85c79181e4b05cee468d1a760000b9..fefef2884d590a47f6c4c4e59207effd63449ff8 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -454,8 +454,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * single discovery thread, this will cause a huge delay in * discovery. Also this will cause multiple state machines * running in parallel for this node. + * This only applies to a fabric environment. */ - if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) { + if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) && + (vport->fc_flag & FC_FABRIC)) { /* software abort outstanding PLOGI */ lpfc_els_abort(phba, ndlp); } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e1e0feb2500312d63ccce377014e278d5582ace7..cbe808e83f477a4e17e852beb105129fde7a0892 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -11962,13 +11962,19 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; /* Setting active mailbox pointer need to be in sync to flag clear */ phba->sli.mbox_active = NULL; + if (bf_get(lpfc_trailer_consumed, mcqe)) + lpfc_sli4_mq_release(phba->sli4_hba.mbx_wq); spin_unlock_irqrestore(&phba->hbalock, iflags); /* Wake up worker thread to post the next pending mailbox command */ lpfc_worker_wake_up(phba); + return workposted; + out_no_mqe_complete: + spin_lock_irqsave(&phba->hbalock, iflags); if (bf_get(lpfc_trailer_consumed, mcqe)) lpfc_sli4_mq_release(phba->sli4_hba.mbx_wq); - return workposted; + spin_unlock_irqrestore(&phba->hbalock, iflags); + return false; } /** @@ -15989,6 +15995,13 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) static void __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) { + /* + * if the rpi value indicates a prior unreg has already + * been done, skip the unreg. + */ + if (rpi == LPFC_RPI_ALLOC_ERROR) + return; + if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) { phba->sli4_hba.rpi_count--; phba->sli4_hba.max_cfg_param.rpi_used--; diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 5648d30c737682329b1739b60f89c734ebbd97c1..5aa60bbbd09adad846b9dc8170b12643935acfc7 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -378,7 +378,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev) mac_scsi_template.can_queue = setup_can_queue; if (setup_cmd_per_lun > 0) mac_scsi_template.cmd_per_lun = setup_cmd_per_lun; - if (setup_sg_tablesize >= 0) + if (setup_sg_tablesize > 0) mac_scsi_template.sg_tablesize = setup_sg_tablesize; if (setup_hostid >= 0) mac_scsi_template.this_id = setup_hostid & 7; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index c5cc002dfdd5caaffaeafd83ddfa0c43c4bf57be..9fa6a560b16294a788639929850b29576412779a 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3694,12 +3694,12 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) /* * The cur_state should not last for more than max_wait secs */ - for (i = 0; i < max_wait; i++) { + for (i = 0; i < max_wait * 50; i++) { curr_abs_state = instance->instancet-> read_fw_status_reg(instance->reg_set); if (abs_state == curr_abs_state) { - msleep(1000); + msleep(20); } else break; } @@ -3978,7 +3978,8 @@ dcmd_timeout_ocr_possible(struct megasas_instance *instance) { if (!instance->ctrl_context) return KILL_ADAPTER; else if (instance->unload || - test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) + test_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, + &instance->reset_flags)) return IGNORE_TIMEOUT; else return INITIATE_OCR; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index fe1a20973e477716ed27afb25314acc4d6217eff..874e5a7f79988ea884992c4aafb568284b8e349c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -3438,6 +3438,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) if (instance->requestorId && !instance->skip_heartbeat_timer_del) del_timer_sync(&instance->sriov_heartbeat_timer); set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + set_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, &instance->reset_flags); atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_POLLING); instance->instancet->disable_intr(instance); msleep(1000); @@ -3594,7 +3595,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL); } out: - clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + clear_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, &instance->reset_flags); mutex_unlock(&instance->reset_mutex); return retval; } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index e3bee04c1eb18a24f7e9b8a250042138e5660fb5..034653d9336576dab5d8bff11bbd303e824d793d 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h @@ -93,6 +93,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE { #define MEGASAS_FP_CMD_LEN 16 #define MEGASAS_FUSION_IN_RESET 0 +#define MEGASAS_FUSION_OCR_NOT_POSSIBLE 1 #define THRESHOLD_REPLY_COUNT 50 #define JBOD_MAPS_COUNT 2 diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 26cdc127ac89cf022490e8d87584f0542babfa04..90a87e59ff602ecf22feee43ebf642b37b8cdde8 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -1465,7 +1465,8 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, " for diag buffers, requested size(%d)\n", ioc->name, __func__, request_data_sz); mpt3sas_base_free_smid(ioc, smid); - return -ENOMEM; + rc = -ENOMEM; + goto out; } ioc->diag_buffer[buffer_type] = request_data; ioc->diag_buffer_sz[buffer_type] = request_data_sz; diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9edd61c063a1ab695511541f2c422b3817f9de55..df5f0bc295875dd6b98ace76cd853880c2be3db2 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -2368,6 +2368,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("task 0x%p done with io_status 0x%x" " resp 0x%x stat 0x%x but aborted by upper layer!\n", t, status, ts->resp, ts->stat)); + if (t->slow_task) + complete(&t->slow_task->completion); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 5c3dfd92ea02447c20bbbc387cf409b98fe583d7..33f4181ba9f76838171c9bc015bfa9eee6bdee43 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -682,7 +682,8 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, break; } else { /* Make sure FC side is not in reset */ - qla2x00_wait_for_hba_online(vha); + WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) != + QLA_SUCCESS); /* Issue MPI reset */ scsi_block_requests(vha->host); diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 33e4dceb895f2c4a0961ad071aa2d1267b898f5b..09f7a8cfed4d0580324f363d52368fecb0d2af83 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -336,6 +336,8 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); if (!req_sg_cnt) { + dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); rval = -ENOMEM; goto done_free_fcport; } @@ -343,6 +345,8 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); if (!rsp_sg_cnt) { + dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); rval = -ENOMEM; goto done_free_fcport; } @@ -1740,8 +1744,8 @@ qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) uint16_t nextlid = 0; uint32_t tot_dsds; srb_t *sp = NULL; - uint32_t req_data_len = 0; - uint32_t rsp_data_len = 0; + uint32_t req_data_len; + uint32_t rsp_data_len; /* Check the type of the adapter */ if (!IS_BIDI_CAPABLE(ha)) { @@ -1846,6 +1850,9 @@ qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) goto done_unmap_sg; } + req_data_len = bsg_job->request_payload.payload_len; + rsp_data_len = bsg_job->reply_payload.payload_len; + if (req_data_len != rsp_data_len) { rval = EXT_STATUS_BUSY; ql_log(ql_log_warn, vha, 0x70aa, @@ -1853,10 +1860,6 @@ qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) goto done_unmap_sg; } - req_data_len = bsg_job->request_payload.payload_len; - rsp_data_len = bsg_job->reply_payload.payload_len; - - /* Alloc SRB structure */ sp = qla2x00_get_sp(vha, &(vha->bidir_fcport), GFP_KERNEL); if (!sp) { diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f0fcff032f8ac4c80c1f5fb1841c75e6d5eb54ea..17b1525d492bf698808add278c568cf330a45527 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -973,8 +973,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) ql_dbg(ql_dbg_async, vha, 0x5011, "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", mb[1], mb[2], mb[3]); - - qlt_async_event(mb[0], vha, mb); break; } @@ -995,8 +993,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(VP_CONFIG_OK, &vha->vp_flags); - - qlt_async_event(mb[0], vha, mb); break; case MBA_RSCN_UPDATE: /* State Change Registration */ diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index bf29ad454118301a34bfa030444637363bfb0a28..9bbea422391745652816fa32d023b89f2466043b 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -5723,9 +5723,8 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr, mcp->mb[7] = LSW(MSD(req_dma)); mcp->mb[8] = MSW(addr); /* Setting RAM ID to valid */ - mcp->mb[10] |= BIT_7; /* For MCTP RAM ID is 0x40 */ - mcp->mb[10] |= 0x40; + mcp->mb[10] = BIT_7 | 0x40; mcp->out_mb |= MBX_10|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1| MBX_0; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 54380b434b304eddde918a94ee833e18be6a35f6..104e13ae342881363cde621e06e9646b925de330 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1600,8 +1600,7 @@ qla82xx_get_bootld_offset(struct qla_hw_data *ha) return (u8 *)&ha->hablob->fw->data[offset]; } -static __le32 -qla82xx_get_fw_size(struct qla_hw_data *ha) +static u32 qla82xx_get_fw_size(struct qla_hw_data *ha) { struct qla82xx_uri_data_desc *uri_desc = NULL; @@ -1612,7 +1611,7 @@ qla82xx_get_fw_size(struct qla_hw_data *ha) return cpu_to_le32(uri_desc->size); } - return cpu_to_le32(*(u32 *)&ha->hablob->fw->data[FW_SIZE_OFFSET]); + return get_unaligned_le32(&ha->hablob->fw->data[FW_SIZE_OFFSET]); } static u8 * @@ -1803,7 +1802,7 @@ qla82xx_fw_load_from_blob(struct qla_hw_data *ha) } flashaddr = FLASH_ADDR_START; - size = (__force u32)qla82xx_get_fw_size(ha) / 8; + size = qla82xx_get_fw_size(ha) / 8; ptr64 = (u64 *)qla82xx_get_fw_offs(ha); for (i = 0; i < size; i++) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3bae56b202f8789ef0e994c879502fd75abade11..65bbca715f57db0f14b0f1d5c0ae7a1a5fc44844 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -451,6 +451,12 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) goto fail; } if (ql2xmultique_tag) { + ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1); + if (unlikely(!ha->wq)) { + ql_log(ql_log_warn, vha, 0x01e0, + "Failed to alloc workqueue.\n"); + goto fail; + } /* create a request queue for IO */ options |= BIT_7; req = qla25xx_create_req_que(ha, options, 0, 0, -1, @@ -458,9 +464,8 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) if (!req) { ql_log(ql_log_warn, vha, 0x00e0, "Failed to create request queue.\n"); - goto fail; + goto fail2; } - ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1); vha->req = ha->req_q_map[req]; options |= BIT_1; for (ques = 1; ques < ha->max_rsp_queues; ques++) { @@ -468,7 +473,7 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) if (!ret) { ql_log(ql_log_warn, vha, 0x00e8, "Failed to create response queue.\n"); - goto fail2; + goto fail3; } } ha->flags.cpu_affinity_enabled = 1; @@ -482,11 +487,13 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) ha->max_rsp_queues, ha->max_req_queues); } return 0; -fail2: + +fail3: qla25xx_delete_queues(vha); - destroy_workqueue(ha->wq); - ha->wq = NULL; vha->req = ha->req_q_map[0]; +fail2: + destroy_workqueue(ha->wq); + ha->wq = NULL; fail: ha->mqenable = 0; kfree(ha->req_q_map); @@ -6055,8 +6062,7 @@ qla2x00_module_init(void) /* Initialize target kmem_cache and mem_pools */ ret = qlt_init(); if (ret < 0) { - kmem_cache_destroy(srb_cachep); - return ret; + goto destroy_cache; } else if (ret > 0) { /* * If initiator mode is explictly disabled by qlt_init(), @@ -6075,11 +6081,10 @@ qla2x00_module_init(void) qla2xxx_transport_template = fc_attach_transport(&qla2xxx_transport_functions); if (!qla2xxx_transport_template) { - kmem_cache_destroy(srb_cachep); ql_log(ql_log_fatal, NULL, 0x0002, "fc_attach_transport failed...Failing load!.\n"); - qlt_exit(); - return -ENODEV; + ret = -ENODEV; + goto qlt_exit; } apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops); @@ -6091,27 +6096,37 @@ qla2x00_module_init(void) qla2xxx_transport_vport_template = fc_attach_transport(&qla2xxx_transport_vport_functions); if (!qla2xxx_transport_vport_template) { - kmem_cache_destroy(srb_cachep); - qlt_exit(); - fc_release_transport(qla2xxx_transport_template); ql_log(ql_log_fatal, NULL, 0x0004, "fc_attach_transport vport failed...Failing load!.\n"); - return -ENODEV; + ret = -ENODEV; + goto unreg_chrdev; } ql_log(ql_log_info, NULL, 0x0005, "QLogic Fibre Channel HBA Driver: %s.\n", qla2x00_version_str); ret = pci_register_driver(&qla2xxx_pci_driver); if (ret) { - kmem_cache_destroy(srb_cachep); - qlt_exit(); - fc_release_transport(qla2xxx_transport_template); - fc_release_transport(qla2xxx_transport_vport_template); ql_log(ql_log_fatal, NULL, 0x0006, "pci_register_driver failed...ret=%d Failing load!.\n", ret); + goto release_vport_transport; } return ret; + +release_vport_transport: + fc_release_transport(qla2xxx_transport_vport_template); + +unreg_chrdev: + if (apidev_major >= 0) + unregister_chrdev(apidev_major, QLA2XXX_APIDEV); + fc_release_transport(qla2xxx_transport_template); + +qlt_exit: + qlt_exit(); + +destroy_cache: + kmem_cache_destroy(srb_cachep); + return ret; } /** diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d13e91e164258ccce111edd643dd57526c88a0f4..b889caa556a0bc8a55a642e9c85ad4bf76e05e87 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -5893,7 +5893,6 @@ static void qlt_abort_work(struct qla_tgt *tgt, struct qla_hw_data *ha = vha->hw; struct qla_tgt_sess *sess = NULL; unsigned long flags = 0, flags2 = 0; - uint32_t be_s_id; uint8_t s_id[3]; int rc; @@ -5906,8 +5905,7 @@ static void qlt_abort_work(struct qla_tgt *tgt, s_id[1] = prm->abts.fcp_hdr_le.s_id[1]; s_id[2] = prm->abts.fcp_hdr_le.s_id[0]; - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, - (unsigned char *)&be_s_id); + sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); if (!sess) { spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); @@ -6343,7 +6341,8 @@ qlt_enable_vha(struct scsi_qla_host *vha) set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); qla2xxx_wake_dpc(base_vha); - qla2x00_wait_for_hba_online(base_vha); + WARN_ON_ONCE(qla2x00_wait_for_hba_online(base_vha) != + QLA_SUCCESS); } } EXPORT_SYMBOL(qlt_enable_vha); @@ -6373,7 +6372,9 @@ static void qlt_disable_vha(struct scsi_qla_host *vha) set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); - qla2x00_wait_for_hba_online(vha); + if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) + ql_dbg(ql_dbg_tgt, vha, 0xe081, + "qla2x00_wait_for_hba_online() failed\n"); } /* diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index c291fdff1b338a2ff0ec50930f82298dab279e07..ea3b77ba12a2179f49e3697e1d3000a39022a439 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -641,9 +641,6 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma) != QLA_SUCCESS) { - dma_free_coherent(&ha->pdev->dev, - sizeof(struct addr_ctrl_blk), - init_fw_cb, init_fw_cb_dma); goto exit_init_fw_cb; } diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index d220b4f691c77df079e692ac1a71f47983802a92..3fda5836aac69178a7ae5b5560c615bf8151ec27 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -4150,7 +4150,7 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues, ha->queues_dma); - if (ha->fw_dump) + if (ha->fw_dump) vfree(ha->fw_dump); ha->queues_len = 0; @@ -4285,7 +4285,6 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) return QLA_SUCCESS; mem_alloc_error_exit: - qla4xxx_mem_free(ha); return QLA_ERROR; } diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 2b0e61557317f4ab44b4e76c135ed908746a6c54..d7118d3767c35cc69a97eb304def3b886106af5f 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -4953,6 +4953,11 @@ static int __init scsi_debug_init(void) return -EINVAL; } + if (sdebug_num_tgts < 0) { + pr_err("num_tgts must be >= 0\n"); + return -EINVAL; + } + if (sdebug_guard > 1) { pr_err("guard must be 0 or 1\n"); return -EINVAL; diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index 0ff083bbf5b1f00b6651fc1f256ab890d533dadb..22472d140ef7c6bce8955edbc37d1c9270eee10a 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c @@ -21,7 +21,7 @@ #include #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) -#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9]) +#define SERVICE_ACTION32(cdb) (get_unaligned_be16(&cdb[8])) static const char * scsi_trace_misc(struct trace_seq *, unsigned char *, int); @@ -30,15 +30,18 @@ static const char * scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p); - sector_t lba = 0, txlen = 0; + u32 lba = 0, txlen; lba |= ((cdb[1] & 0x1F) << 16); lba |= (cdb[2] << 8); lba |= cdb[3]; - txlen = cdb[4]; + /* + * From SBC-2: a TRANSFER LENGTH field set to zero specifies that 256 + * logical blocks shall be read (READ(6)) or written (WRITE(6)). + */ + txlen = cdb[4] ? cdb[4] : 256; - trace_seq_printf(p, "lba=%llu txlen=%llu", - (unsigned long long)lba, (unsigned long long)txlen); + trace_seq_printf(p, "lba=%u txlen=%u", lba, txlen); trace_seq_putc(p, 0); return ret; @@ -48,17 +51,12 @@ static const char * scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p); - sector_t lba = 0, txlen = 0; + u32 lba, txlen; - lba |= (cdb[2] << 24); - lba |= (cdb[3] << 16); - lba |= (cdb[4] << 8); - lba |= cdb[5]; - txlen |= (cdb[7] << 8); - txlen |= cdb[8]; + lba = get_unaligned_be32(&cdb[2]); + txlen = get_unaligned_be16(&cdb[7]); - trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", - (unsigned long long)lba, (unsigned long long)txlen, + trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen, cdb[1] >> 5); if (cdb[0] == WRITE_SAME) @@ -73,19 +71,12 @@ static const char * scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p); - sector_t lba = 0, txlen = 0; - - lba |= (cdb[2] << 24); - lba |= (cdb[3] << 16); - lba |= (cdb[4] << 8); - lba |= cdb[5]; - txlen |= (cdb[6] << 24); - txlen |= (cdb[7] << 16); - txlen |= (cdb[8] << 8); - txlen |= cdb[9]; - - trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", - (unsigned long long)lba, (unsigned long long)txlen, + u32 lba, txlen; + + lba = get_unaligned_be32(&cdb[2]); + txlen = get_unaligned_be32(&cdb[6]); + + trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen, cdb[1] >> 5); trace_seq_putc(p, 0); @@ -96,23 +87,13 @@ static const char * scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p); - sector_t lba = 0, txlen = 0; - - lba |= ((u64)cdb[2] << 56); - lba |= ((u64)cdb[3] << 48); - lba |= ((u64)cdb[4] << 40); - lba |= ((u64)cdb[5] << 32); - lba |= (cdb[6] << 24); - lba |= (cdb[7] << 16); - lba |= (cdb[8] << 8); - lba |= cdb[9]; - txlen |= (cdb[10] << 24); - txlen |= (cdb[11] << 16); - txlen |= (cdb[12] << 8); - txlen |= cdb[13]; - - trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", - (unsigned long long)lba, (unsigned long long)txlen, + u64 lba; + u32 txlen; + + lba = get_unaligned_be64(&cdb[2]); + txlen = get_unaligned_be32(&cdb[10]); + + trace_seq_printf(p, "lba=%llu txlen=%u protect=%u", lba, txlen, cdb[1] >> 5); if (cdb[0] == WRITE_SAME_16) @@ -127,8 +108,8 @@ static const char * scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p), *cmd; - sector_t lba = 0, txlen = 0; - u32 ei_lbrt = 0; + u64 lba; + u32 ei_lbrt, txlen; switch (SERVICE_ACTION32(cdb)) { case READ_32: @@ -148,26 +129,12 @@ scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len) goto out; } - lba |= ((u64)cdb[12] << 56); - lba |= ((u64)cdb[13] << 48); - lba |= ((u64)cdb[14] << 40); - lba |= ((u64)cdb[15] << 32); - lba |= (cdb[16] << 24); - lba |= (cdb[17] << 16); - lba |= (cdb[18] << 8); - lba |= cdb[19]; - ei_lbrt |= (cdb[20] << 24); - ei_lbrt |= (cdb[21] << 16); - ei_lbrt |= (cdb[22] << 8); - ei_lbrt |= cdb[23]; - txlen |= (cdb[28] << 24); - txlen |= (cdb[29] << 16); - txlen |= (cdb[30] << 8); - txlen |= cdb[31]; - - trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u", - cmd, (unsigned long long)lba, - (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt); + lba = get_unaligned_be64(&cdb[12]); + ei_lbrt = get_unaligned_be32(&cdb[20]); + txlen = get_unaligned_be32(&cdb[28]); + + trace_seq_printf(p, "%s_32 lba=%llu txlen=%u protect=%u ei_lbrt=%u", + cmd, lba, txlen, cdb[10] >> 5, ei_lbrt); if (SERVICE_ACTION32(cdb) == WRITE_SAME_32) trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1); @@ -182,7 +149,7 @@ static const char * scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p); - unsigned int regions = cdb[7] << 8 | cdb[8]; + unsigned int regions = get_unaligned_be16(&cdb[7]); trace_seq_printf(p, "regions=%u", (regions - 8) / 16); trace_seq_putc(p, 0); @@ -194,8 +161,8 @@ static const char * scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p), *cmd; - sector_t lba = 0; - u32 alloc_len = 0; + u64 lba; + u32 alloc_len; switch (SERVICE_ACTION16(cdb)) { case SAI_READ_CAPACITY_16: @@ -209,21 +176,10 @@ scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) goto out; } - lba |= ((u64)cdb[2] << 56); - lba |= ((u64)cdb[3] << 48); - lba |= ((u64)cdb[4] << 40); - lba |= ((u64)cdb[5] << 32); - lba |= (cdb[6] << 24); - lba |= (cdb[7] << 16); - lba |= (cdb[8] << 8); - lba |= cdb[9]; - alloc_len |= (cdb[10] << 24); - alloc_len |= (cdb[11] << 16); - alloc_len |= (cdb[12] << 8); - alloc_len |= cdb[13]; - - trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, - (unsigned long long)lba, alloc_len); + lba = get_unaligned_be64(&cdb[2]); + alloc_len = get_unaligned_be32(&cdb[10]); + + trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, lba, alloc_len); out: trace_seq_putc(p, 0); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index c39551b32e941e60713de3e88d45f9ea25917b73..fff9c4d0f7c805a41c495cfaddc784197406bbc3 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -37,6 +37,8 @@ #define ISCSI_TRANSPORT_VERSION "2.0-870" +#define ISCSI_SEND_MAX_ALLOWED 10 + static int dbg_session; module_param_named(debug_session, dbg_session, int, S_IRUGO | S_IWUSR); @@ -2962,6 +2964,24 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev) return err; } +static int iscsi_session_has_conns(int sid) +{ + struct iscsi_cls_conn *conn; + unsigned long flags; + int found = 0; + + spin_lock_irqsave(&connlock, flags); + list_for_each_entry(conn, &connlist, conn_list) { + if (iscsi_conn_get_sid(conn) == sid) { + found = 1; + break; + } + } + spin_unlock_irqrestore(&connlock, flags); + + return found; +} + static int iscsi_set_iface_params(struct iscsi_transport *transport, struct iscsi_uevent *ev, uint32_t len) @@ -3536,10 +3556,12 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) break; case ISCSI_UEVENT_DESTROY_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); - if (session) - transport->destroy_session(session); - else + if (!session) err = -EINVAL; + else if (iscsi_session_has_conns(ev->u.d_session.sid)) + err = -EBUSY; + else + transport->destroy_session(session); break; case ISCSI_UEVENT_UNBIND_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); @@ -3694,6 +3716,7 @@ iscsi_if_rx(struct sk_buff *skb) struct nlmsghdr *nlh; struct iscsi_uevent *ev; uint32_t group; + int retries = ISCSI_SEND_MAX_ALLOWED; nlh = nlmsg_hdr(skb); if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) || @@ -3724,6 +3747,10 @@ iscsi_if_rx(struct sk_buff *skb) break; err = iscsi_if_send_reply(group, nlh->nlmsg_seq, nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); + if (err == -EAGAIN && --retries < 0) { + printk(KERN_WARNING "Send reply failed, error %d\n", err); + break; + } } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH); skb_pull(skb, rlen); } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index f50c74156992b1bdacc9065fa49dbcca4814fa6d..1c4a14d68165b1488833ec93ebbdeaedd9a94877 100755 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1930,8 +1930,10 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer u8 type; int ret = 0; - if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) + if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) { + sdkp->protection_type = 0; return ret; + } type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 3c4c07038948d5cef306f500630d4f3d48ca36b5..6f75693cf7d28ee8689979b6814e27b36afc6dd4 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -419,7 +419,7 @@ static struct scsi_host_template sun3_scsi_template = { .eh_bus_reset_handler = sun3scsi_bus_reset, .can_queue = 16, .this_id = 7, - .sg_tablesize = SG_NONE, + .sg_tablesize = 1, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, @@ -440,7 +440,7 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) sun3_scsi_template.can_queue = setup_can_queue; if (setup_cmd_per_lun > 0) sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun; - if (setup_sg_tablesize >= 0) + if (setup_sg_tablesize > 0) sun3_scsi_template.sg_tablesize = setup_sg_tablesize; if (setup_hostid >= 0) sun3_scsi_template.this_id = setup_hostid & 7; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 080fbedfefe41669e19d37592211360b14c3ec3a..95e1b259082048a5090a144a0cf92af03796a2ec 100755 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3792,10 +3792,10 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, goto out_unlock; } - hba->dev_cmd.query.descriptor = NULL; *buf_len = be16_to_cpu(response->upiu_res.length); out_unlock: + hba->dev_cmd.query.descriptor = NULL; mutex_unlock(&hba->dev_cmd.lock); if (has_read_lock) up_read(&hba->lock); @@ -8112,7 +8112,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) hba->dev_info.f_power_on_wp_en = flag; /* Add required well known logical units to scsi mid layer */ - if (ufshcd_scsi_add_wlus(hba)) + ret = ufshcd_scsi_add_wlus(hba); + if (ret) goto out; /* Initialize devfreq after UFS device is detected */ diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 0aaf429f31d571f569fe0916b52d10cf3dadfd49..b5a7107a9c0a926842f29f3a8cd06013ce3bbbd5 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -152,8 +152,10 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) if (err < 0) goto err0; gc = gpio_to_chip(err); - if (WARN_ON(!gc)) + if (WARN_ON(!gc)) { + err = -ENODEV; goto err0; + } if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) { pr_debug("%s: tried to get a non-qe pin\n", __func__); diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index cbf1734d9ead44b2c0eb83909a3c742b293dcd9a..6a6fc8c0c67f6c44f6c8bb419280815310f03f73 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -274,6 +274,16 @@ config MSM_GLADIATOR_ERP If unsure, say N. +config SDX_EXT_IPC + tristate "QCOM external ipc driver" + help + This enables the module to help modem communicate with external + Application processor connected to Qualcomm Technologies, Inc + modem chipset. The modem and APQ can understand each other's + state by reading ipc gpios. + + If unsure, say N. + config PANIC_ON_GLADIATOR_ERROR depends on MSM_GLADIATOR_ERP bool "Panic on GLADIATOR error report" diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 1dda5d1010d55413a22be005daabb910f5a15a8e..c61594bbf991f47d27492ccb478d1bb59ce00aae 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-msa.o pil-q6v5-mss.o obj-$(CONFIG_MSM_BGCOM) += bgcom_spi.o obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o +obj-$(CONFIG_SDX_EXT_IPC) += sdx_ext_ipc.o ifdef CONFIG_MSM_SUBSYSTEM_RESTART obj-y += subsystem_notif.o diff --git a/drivers/soc/qcom/bgcom_interface.c b/drivers/soc/qcom/bgcom_interface.c index 5118318c77992682de6125009cc9e243e3c64cc7..7880457b7bd3f92a0ab6b886d65a29d602d0b766 100644 --- a/drivers/soc/qcom/bgcom_interface.c +++ b/drivers/soc/qcom/bgcom_interface.c @@ -73,6 +73,7 @@ struct bgdaemon_priv { bool pending_bg_twm_wear_load; struct workqueue_struct *bgdaemon_wq; struct work_struct bgdaemon_load_twm_bg_work; + bool bg_twm_wear_load; }; struct bg_event { @@ -132,6 +133,7 @@ static void bgcom_load_twm_bg_work(struct work_struct *work) dev->pil_h = NULL; bg_soft_reset(); } else { + dev->bg_twm_wear_load = true; dev->pil_h = subsystem_get_with_fwname("bg-wear", "bg-twm-wear"); if (!dev->pil_h) @@ -425,7 +427,7 @@ static long bg_com_ioctl(struct file *filp, ret = -EFAULT; break; } - + dev->bg_twm_wear_load = false; dev->pil_h = subsystem_get_with_fwname("bg-wear", "bg-wear"); if (!dev->pil_h) { pr_err("failed to load bg-wear\n"); @@ -624,7 +626,10 @@ static int ssr_bg_cb(struct notifier_block *this, } break; case SUBSYS_AFTER_POWERUP: - bge.e_type = BG_AFTER_POWER_UP; + if (dev->bg_twm_wear_load) + bge.e_type = TWM_BG_AFTER_POWER_UP; + else + bge.e_type = BG_AFTER_POWER_UP; bgdaemon_ldowork(DISABLE_LDO03); bgdaemon_ldowork(DISABLE_LDO09); bgcom_set_spi_state(BGCOM_SPI_FREE); diff --git a/drivers/soc/qcom/sdx_ext_ipc.c b/drivers/soc/qcom/sdx_ext_ipc.c new file mode 100644 index 0000000000000000000000000000000000000000..dadc63cfca9f0fdd74ebbde7454ddd17d720aedf --- /dev/null +++ b/drivers/soc/qcom/sdx_ext_ipc.c @@ -0,0 +1,268 @@ +/* Copyright (c) 2019-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 +#include +#include +#include +#include +#include + + +enum subsys_policies { + SUBSYS_PANIC = 0, + SUBSYS_NOP, +}; + +static const char * const policies[] = { + [SUBSYS_PANIC] = "PANIC", + [SUBSYS_NOP] = "NOP", +}; + +enum gpios { + AP2MDM_STATUS = 0, + MDM2AP_STATUS, + MDM2AP_STATUS2, + NUM_GPIOS, +}; + +static const char * const gpio_map[] = { + [AP2MDM_STATUS] = "qcom,ap2mdm-status-gpio", + [MDM2AP_STATUS] = "qcom,mdm2ap-status-gpio", + [MDM2AP_STATUS2] = "qcom,mdm2ap-status2-gpio", +}; + +struct gpio_cntrl { + unsigned int gpios[NUM_GPIOS]; + int status_irq; + int policy; + struct device *dev; + struct mutex policy_lock; + struct notifier_block panic_blk; +}; + +static ssize_t policy_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int ret; + struct gpio_cntrl *mdm = dev_get_drvdata(dev); + + mutex_lock(&mdm->policy_lock); + ret = scnprintf(buf, strlen(policies[mdm->policy]) + 1, + policies[mdm->policy]); + mutex_unlock(&mdm->policy_lock); + + return ret; +} + +static ssize_t policy_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gpio_cntrl *mdm = dev_get_drvdata(dev); + const char *p; + int i, orig_count = count; + + p = memchr(buf, '\n', count); + if (p) + count = p - buf; + + for (i = 0; i < ARRAY_SIZE(policies); i++) + if (!strncasecmp(buf, policies[i], count)) { + mutex_lock(&mdm->policy_lock); + mdm->policy = i; + mutex_unlock(&mdm->policy_lock); + return orig_count; + } + return -EPERM; +} +static DEVICE_ATTR_RW(policy); + +static irqreturn_t ap_status_change(int irq, void *dev_id) +{ + struct gpio_cntrl *mdm = dev_id; + int state; + struct gpio_desc *gp_status = gpio_to_desc(mdm->gpios[AP2MDM_STATUS]); + int active_low = 0; + + if (gp_status) + active_low = gpiod_is_active_low(gp_status); + + state = gpio_get_value(mdm->gpios[AP2MDM_STATUS]); + if ((!active_low && !state) || (active_low && state)) { + if (mdm->policy) + dev_info(mdm->dev, "Host undergoing SSR, leaving SDX as it is\n"); + else + panic("Host undergoing SSR, panicking SDX\n"); + } else + dev_info(mdm->dev, "HOST booted\n"); + + return IRQ_HANDLED; +} + +static void remove_ipc(struct gpio_cntrl *mdm) +{ + int i; + + for (i = 0; i < NUM_GPIOS; ++i) { + if (gpio_is_valid(mdm->gpios[i])) + gpio_free(mdm->gpios[i]); + } +} + +static int setup_ipc(struct gpio_cntrl *mdm) +{ + int i, val, ret, irq; + struct device_node *node; + + node = mdm->dev->of_node; + for (i = 0; i < ARRAY_SIZE(gpio_map); i++) { + val = of_get_named_gpio(node, gpio_map[i], 0); + if (val >= 0) + mdm->gpios[i] = val; + } + + ret = gpio_request(mdm->gpios[AP2MDM_STATUS], "AP2MDM_STATUS"); + if (ret) { + dev_err(mdm->dev, "Failed to configure AP2MDM_STATUS gpio\n"); + return ret; + } + gpio_direction_input(mdm->gpios[AP2MDM_STATUS]); + + ret = gpio_request(mdm->gpios[MDM2AP_STATUS], "MDM2AP_STATUS"); + if (ret) { + dev_err(mdm->dev, "Failed to configure MDM2AP_STATUS gpio\n"); + return ret; + } + gpio_direction_output(mdm->gpios[MDM2AP_STATUS], 1); + + ret = gpio_request(mdm->gpios[MDM2AP_STATUS2], "MDM2AP_STATUS2"); + if (ret) { + dev_err(mdm->dev, "Failed to configure MDM2AP_STATUS2 gpio\n"); + return ret; + } + gpio_direction_output(mdm->gpios[MDM2AP_STATUS2], 0); + + irq = gpio_to_irq(mdm->gpios[AP2MDM_STATUS]); + if (irq < 0) { + dev_err(mdm->dev, "bad AP2MDM_STATUS IRQ resource\n"); + return irq; + } + mdm->status_irq = irq; + + return 0; +} + +static int sdx_ext_ipc_panic(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct gpio_cntrl *mdm = container_of(this, + struct gpio_cntrl, panic_blk); + + gpio_set_value(mdm->gpios[MDM2AP_STATUS], 0); + + return NOTIFY_DONE; +} + +static int sdx_ext_ipc_probe(struct platform_device *pdev) +{ + int ret; + struct device_node *node; + struct gpio_cntrl *mdm; + + node = pdev->dev.of_node; + mdm = devm_kzalloc(&pdev->dev, sizeof(*mdm), GFP_KERNEL); + if (!mdm) + return -ENOMEM; + + mdm->dev = &pdev->dev; + ret = setup_ipc(mdm); + if (ret) { + dev_err(mdm->dev, "Error setting up gpios\n"); + devm_kfree(&pdev->dev, mdm); + return ret; + } + + mdm->panic_blk.notifier_call = sdx_ext_ipc_panic; + atomic_notifier_chain_register(&panic_notifier_list, &mdm->panic_blk); + + mutex_init(&mdm->policy_lock); + mdm->policy = SUBSYS_PANIC; + + ret = device_create_file(mdm->dev, &dev_attr_policy); + if (ret) { + dev_err(mdm->dev, "cannot create sysfs attribute\n"); + goto sys_fail; + } + + platform_set_drvdata(pdev, mdm); + + ret = devm_request_irq(mdm->dev, mdm->status_irq, ap_status_change, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "ap status", mdm); + if (ret < 0) { + dev_err(mdm->dev, "%s: AP2MDM_STATUS IRQ#%d request failed,\n", + __func__, mdm->status_irq); + goto irq_fail; + } + irq_set_irq_wake(mdm->status_irq, 1); + return 0; + +irq_fail: + device_remove_file(mdm->dev, &dev_attr_policy); +sys_fail: + atomic_notifier_chain_unregister(&panic_notifier_list, &mdm->panic_blk); + remove_ipc(mdm); + devm_kfree(&pdev->dev, mdm); + return ret; +} + +static int sdx_ext_ipc_remove(struct platform_device *pdev) +{ + struct gpio_cntrl *mdm; + + mdm = dev_get_drvdata(&pdev->dev); + disable_irq_wake(mdm->status_irq); + atomic_notifier_chain_unregister(&panic_notifier_list, &mdm->panic_blk); + remove_ipc(mdm); + device_remove_file(mdm->dev, &dev_attr_policy); + return 0; +} + +static const struct of_device_id sdx_ext_ipc_of_match[] = { + { .compatible = "qcom,sdx-ext-ipc"}, + { .compatible = "qcom,sa415m-ccard"}, + {}, +}; + +static struct platform_driver sdx_ext_ipc_driver = { + .probe = sdx_ext_ipc_probe, + .remove = sdx_ext_ipc_remove, + .driver = { + .name = "sdx-ext-ipc", + .owner = THIS_MODULE, + .of_match_table = sdx_ext_ipc_of_match, + }, +}; + +static int __init sdx_ext_ipc_register(void) +{ + return platform_driver_register(&sdx_ext_ipc_driver); +} +subsys_initcall(sdx_ext_ipc_register); + +static void __exit sdx_ext_ipc_unregister(void) +{ + platform_driver_unregister(&sdx_ext_ipc_driver); +} +module_exit(sdx_ext_ipc_unregister); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 5b18f6ffa45c798a9c8d138a4f0fb647551b4932..cd61c883c19f52a8b2e9d4d68a634d3f5fb14510 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -134,7 +134,7 @@ void __init tegra_init_apbmisc(void) apbmisc.flags = IORESOURCE_MEM; /* strapping options */ - if (tegra_get_chip_id() == TEGRA124) { + if (of_machine_is_compatible("nvidia,tegra124")) { straps.start = 0x7000e864; straps.end = 0x7000e867; } else { diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c index 5bb376009d98b78bd0dbf6da3e8f0853f9e6528e..fc33bfdc957ccab18d6960320316484db439d1b2 100644 --- a/drivers/soc/ti/wkup_m3_ipc.c +++ b/drivers/soc/ti/wkup_m3_ipc.c @@ -377,6 +377,8 @@ static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc) ret = rproc_boot(m3_ipc->rproc); if (ret) dev_err(dev, "rproc_boot failed\n"); + else + m3_ipc_state = m3_ipc; do_exit(0); } @@ -463,8 +465,6 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev) goto err_put_rproc; } - m3_ipc_state = m3_ipc; - return 0; err_put_rproc: diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 44be6b593b30dc65a1ae955716c2e11b0bca806a..938840af9c504fdfafd171cddb99517cb6bb6310 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -315,7 +315,6 @@ struct atmel_spi { struct atmel_spi_dma dma; bool keep_cs; - bool cs_active; u32 fifo_size; }; @@ -1209,10 +1208,8 @@ static int atmel_spi_setup(struct spi_device *spi) as = spi_master_get_devdata(spi->master); /* see notes above re chipselect */ - if (!atmel_spi_is_v2(as) - && spi->chip_select == 0 - && (spi->mode & SPI_CS_HIGH)) { - dev_dbg(&spi->dev, "setup: can't be active-high\n"); + if (!as->use_cs_gpios && (spi->mode & SPI_CS_HIGH)) { + dev_warn(&spi->dev, "setup: non GPIO CS can't be active-high\n"); return -EINVAL; } @@ -1406,11 +1403,9 @@ static int atmel_spi_one_transfer(struct spi_master *master, &msg->transfers)) { as->keep_cs = true; } else { - as->cs_active = !as->cs_active; - if (as->cs_active) - cs_activate(as, msg->spi); - else - cs_deactivate(as, msg->spi); + cs_deactivate(as, msg->spi); + udelay(10); + cs_activate(as, msg->spi); } } @@ -1433,7 +1428,6 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, atmel_spi_lock(as); cs_activate(as, spi); - as->cs_active = true; as->keep_cs = false; msg->status = 0; diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 5c89bbb05441bd3c8076e8359019811585a97a3a..e075712c501e87abc98fe66a75527c446ffd6f0f 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -416,7 +416,18 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS); master->bits_per_word_mask = SPI_BPW_MASK(8); - master->num_chipselect = -1; + /* even though the driver never officially supported native CS + * allow a single native CS for legacy DT support purposes when + * no cs-gpio is configured. + * Known limitations for native cs are: + * * multiple chip-selects: cs0-cs2 are all simultaniously asserted + * whenever there is a transfer - this even includes SPI_NO_CS + * * SPI_CS_HIGH: is ignores - cs are always asserted low + * * cs_change: cs is deasserted after each spi_transfer + * * cs_delay_usec: cs is always deasserted one SCK cycle after + * a spi_transfer + */ + master->num_chipselect = 1; master->transfer_one = bcm2835aux_spi_transfer_one; master->handle_err = bcm2835aux_spi_handle_err; master->prepare_message = bcm2835aux_spi_prepare_message; diff --git a/drivers/spi/spi-cavium-thunderx.c b/drivers/spi/spi-cavium-thunderx.c index 87793770624086892d57515605f5931e6939bd94..828fbbebc3c48d861d026288920d52e842cb88c4 100644 --- a/drivers/spi/spi-cavium-thunderx.c +++ b/drivers/spi/spi-cavium-thunderx.c @@ -81,6 +81,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev, error: clk_disable_unprepare(p->clk); + pci_release_regions(pdev); spi_master_put(master); return ret; } @@ -95,6 +96,7 @@ static void thunderx_spi_remove(struct pci_dev *pdev) return; clk_disable_unprepare(p->clk); + pci_release_regions(pdev); /* Put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); } diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 8b290d9d7935044640da36688e82fd01e90bf114..5419de19859a0230729cf7c382113770893d1ce1 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -408,7 +408,6 @@ static int fsl_spi_do_one_msg(struct spi_master *master, } m->status = status; - spi_finalize_current_message(master); if (status || !cs_change) { ndelay(nsecs); @@ -416,6 +415,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master, } fsl_spi_setup_transfer(spi, NULL); + spi_finalize_current_message(master); return 0; } diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 7a37090dabbea55308b555d03f19dd56c4c3c15c..2e65b70c78792022cd202280395a88e3b66ac208 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -673,6 +673,8 @@ static int img_spfi_probe(struct platform_device *pdev) dma_release_channel(spfi->tx_ch); if (spfi->rx_ch) dma_release_channel(spfi->rx_ch); + spfi->tx_ch = NULL; + spfi->rx_ch = NULL; dev_warn(spfi->dev, "Failed to get DMA channels, falling back to PIO mode\n"); } else { master->dma_tx = spfi->tx_ch; diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 6dd195b94c57872615b44c7854d4fb6ec2d2e62c..2f84d7653afd484af1b9bcdc73704949103bd421 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1529,7 +1529,13 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) } ssp->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ssp->clk)) + return NULL; + ssp->irq = platform_get_irq(pdev, 0); + if (ssp->irq < 0) + return NULL; + ssp->type = type; ssp->pdev = pdev; ssp->port_id = pxa2xx_spi_get_port_id(adev); diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index e54b59638458232bf576b4e71b3f0e3450b384df..710adbc2485f56b37419752cbb33563712bf8aad 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -385,6 +385,7 @@ static int spi_st_probe(struct platform_device *pdev) return 0; clk_disable: + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(spi_st->clk); put_master: spi_master_put(master); @@ -396,6 +397,8 @@ static int spi_st_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct spi_st *spi_st = spi_master_get_devdata(master); + pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(spi_st->clk); pinctrl_pm_select_sleep_state(&pdev->dev); diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 705f515863d4f18a4cf5867e4d4c906b9c29f2c7..e37712bed0b2dee024bfd2fb55822d43379284a1 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } + + tspi->cur_tx_pos += written_words * tspi->bytes_per_word; } else { + unsigned int write_bytes; max_n_32bit = min(tspi->curr_dma_words, tx_empty_count); written_words = max_n_32bit; nbytes = written_words * tspi->bytes_per_word; + if (nbytes > t->len - tspi->cur_pos) + nbytes = t->len - tspi->cur_pos; + write_bytes = nbytes; for (count = 0; count < max_n_32bit; count++) { u32 x = 0; @@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } + + tspi->cur_tx_pos += write_bytes; } - tspi->cur_tx_pos += written_words * tspi->bytes_per_word; + return written_words; } @@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( for (i = 0; len && (i < 4); i++, len--) *rx_buf++ = (x >> i*8) & 0xFF; } - tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; read_words += tspi->curr_dma_words; + tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; + u8 bytes_per_word = tspi->bytes_per_word; + unsigned int read_bytes; + len = rx_full_count * bytes_per_word; + if (len > t->len - tspi->cur_pos) + len = t->len - tspi->cur_pos; + read_bytes = len; for (count = 0; count < rx_full_count; count++) { u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask; - for (i = 0; (i < tspi->bytes_per_word); i++) + for (i = 0; len && (i < bytes_per_word); i++, len--) *rx_buf++ = (x >> (i*8)) & 0xFF; } - tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word; read_words += rx_full_count; + tspi->cur_rx_pos += read_bytes; } + return read_words; } @@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len); + tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; + unsigned int write_bytes; + if (consume > t->len - tspi->cur_pos) + consume = t->len - tspi->cur_pos; + write_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = 0; @@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tspi->tx_dma_buf[count] = x; } + + tspi->cur_tx_pos += write_bytes; } - tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys, @@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len); + tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; + unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; + unsigned int read_bytes; + if (consume > t->len - tspi->cur_pos) + consume = t->len - tspi->cur_pos; + read_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = tspi->rx_dma_buf[count] & rx_mask; - for (i = 0; (i < tspi->bytes_per_word); i++) + for (i = 0; consume && (i < tspi->bytes_per_word); + i++, consume--) *rx_buf++ = (x >> (i*8)) & 0xFF; } + + tspi->cur_rx_pos += read_bytes; } - tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, @@ -730,6 +759,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, if (tspi->is_packed) command1 |= SPI_PACKED; + else + command1 &= ~SPI_PACKED; command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN); tspi->cur_direction = 0; diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index af2880d0c1126a53a91def75effb6a8061d84ac9..cf2a329fd8958e76abd08ecb6519ada69760d784 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1078,7 +1078,7 @@ static int tegra_slink_probe(struct platform_device *pdev) ret = clk_enable(tspi->clk); if (ret < 0) { dev_err(&pdev->dev, "Clock enable failed %d\n", ret); - goto exit_free_master; + goto exit_clk_unprepare; } spi_irq = platform_get_irq(pdev, 0); @@ -1151,6 +1151,8 @@ static int tegra_slink_probe(struct platform_device *pdev) free_irq(spi_irq, tspi); exit_clk_disable: clk_disable(tspi->clk); +exit_clk_unprepare: + clk_unprepare(tspi->clk); exit_free_master: spi_master_put(master); return ret; @@ -1164,6 +1166,7 @@ static int tegra_slink_remove(struct platform_device *pdev) free_irq(tspi->irq, tspi); clk_disable(tspi->clk); + clk_unprepare(tspi->clk); if (tspi->tx_dma_chan) tegra_slink_deinit_dma_param(tspi, false); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 0602366e646968d23baa1edd7d956f3515907d03..4f1b6aac93b1293e2155ce2472ed69acd1844896 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -663,6 +663,9 @@ static int spidev_release(struct inode *inode, struct file *filp) if (dofree) kfree(spidev); } +#ifdef CONFIG_SPI_SLAVE + spi_slave_abort(spidev->spi); +#endif mutex_unlock(&device_list_lock); return 0; diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 2c1b6de30da8c4d74e085aaeac64d1c376c53a9f..385e14269870da4d1ca35af7e774bd138421f153 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -45,8 +45,8 @@ #define PCI171X_RANGE_UNI BIT(4) #define PCI171X_RANGE_GAIN(x) (((x) & 0x7) << 0) #define PCI171X_MUX_REG 0x04 /* W: A/D multiplexor control */ -#define PCI171X_MUX_CHANH(x) (((x) & 0xf) << 8) -#define PCI171X_MUX_CHANL(x) (((x) & 0xf) << 0) +#define PCI171X_MUX_CHANH(x) (((x) & 0xff) << 8) +#define PCI171X_MUX_CHANL(x) (((x) & 0xff) << 0) #define PCI171X_MUX_CHAN(x) (PCI171X_MUX_CHANH(x) | PCI171X_MUX_CHANL(x)) #define PCI171X_STATUS_REG 0x06 /* R: status register */ #define PCI171X_STATUS_IRQ BIT(11) /* 1=IRQ occurred */ diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index e5b948405fd9c78ddf47f7f62b087dc802dbef25..a09631f9d8135a9b2c92695092cb426eb18f75dd 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -632,6 +632,11 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, dma_alloc_coherent(&pcidev->dev, DMA_BUFFER_SIZE, &devpriv->dio_buffer_phys_addr[i], GFP_KERNEL); + if (!devpriv->dio_buffer[i]) { + dev_warn(dev->class_dev, + "failed to allocate DMA buffer\n"); + return -ENOMEM; + } } /* allocate dma descriptors */ devpriv->dma_desc = dma_alloc_coherent(&pcidev->dev, @@ -639,6 +644,11 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, NUM_DMA_DESCRIPTORS, &devpriv->dma_desc_phys_addr, GFP_KERNEL); + if (!devpriv->dma_desc) { + dev_warn(dev->class_dev, + "failed to allocate DMA descriptors\n"); + return -ENOMEM; + } if (devpriv->dma_desc_phys_addr & 0xf) { dev_warn(dev->class_dev, " dma descriptors not quad-word aligned (bug)\n"); diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index fe03a41dc5cf52a61d4051e0611f5e4b4b28dd21..12056eb3cbe814c054b7810c8886b8f0e1ed6196 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -4945,7 +4945,10 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev, case NI_RTSI_OUTPUT_G_SRC0: case NI_RTSI_OUTPUT_G_GATE0: case NI_RTSI_OUTPUT_RGOUT0: - case NI_RTSI_OUTPUT_RTSI_BRD_0: + case NI_RTSI_OUTPUT_RTSI_BRD(0): + case NI_RTSI_OUTPUT_RTSI_BRD(1): + case NI_RTSI_OUTPUT_RTSI_BRD(2): + case NI_RTSI_OUTPUT_RTSI_BRD(3): return 1; case NI_RTSI_OUTPUT_RTSI_OSC: return (devpriv->is_m_series) ? 1 : 0; @@ -4966,11 +4969,18 @@ static int ni_set_rtsi_routing(struct comedi_device *dev, devpriv->rtsi_trig_a_output_reg |= NISTC_RTSI_TRIG(chan, src); ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg, NISTC_RTSI_TRIGA_OUT_REG); - } else if (chan < 8) { + } else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) { devpriv->rtsi_trig_b_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan); devpriv->rtsi_trig_b_output_reg |= NISTC_RTSI_TRIG(chan, src); ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg, NISTC_RTSI_TRIGB_OUT_REG); + } else if (chan != NISTC_RTSI_TRIG_OLD_CLK_CHAN) { + /* probably should never reach this, since the + * ni_valid_rtsi_output_source above errors out if chan is too + * high + */ + dev_err(dev->class_dev, "%s: unknown rtsi channel\n", __func__); + return -EINVAL; } return 2; } @@ -4986,12 +4996,12 @@ static unsigned int ni_get_rtsi_routing(struct comedi_device *dev, } else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) { return NISTC_RTSI_TRIG_TO_SRC(chan, devpriv->rtsi_trig_b_output_reg); - } else { - if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) - return NI_RTSI_OUTPUT_RTSI_OSC; - dev_err(dev->class_dev, "bug! should never get here?\n"); - return 0; + } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { + return NI_RTSI_OUTPUT_RTSI_OSC; } + + dev_err(dev->class_dev, "%s: unknown rtsi channel\n", __func__); + return -EINVAL; } static int ni_rtsi_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index d9ba8c0f1353b37aba2c6b8b66ec56a63a04632d..ece713d026607464547856be86c1511f06efc68c 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -766,7 +766,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, fbdefio->deferred_io = fbtft_deferred_io; fb_deferred_io_init(info); - strncpy(info->fix.id, dev->driver->name, 16); + snprintf(info->fix.id, sizeof(info->fix.id), "%s", dev->driver->name); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.xpanstep = 0; diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index aa6508b44fab27f805bcd629c8815a9d0b8bf413..ed7c32542cb3cbd0e38c022e336cfee3b03bac4b 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -90,8 +90,8 @@ void gb_audio_manager_remove_all(void) list_for_each_entry_safe(module, next, &modules_list, list) { list_del(&module->list); - kobject_put(&module->kobj); ida_simple_remove(&module_id, module->id); + kobject_put(&module->kobj); } is_empty = list_empty(&modules_list); diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 9f01427f35f919c9074988852f331d0d1333fa3f..1cb82cc28aa765f01d5d1faadb5d1190bc15de0e 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1102,21 +1102,21 @@ static void gb_lights_channel_release(struct gb_channel *channel) static void gb_lights_light_release(struct gb_light *light) { int i; - int count; light->ready = false; - count = light->channels_count; - if (light->has_flash) gb_lights_light_v4l2_unregister(light); + light->has_flash = false; - for (i = 0; i < count; i++) { + for (i = 0; i < light->channels_count; i++) gb_lights_channel_release(&light->channels[i]); - light->channels_count--; - } + light->channels_count = 0; + kfree(light->channels); + light->channels = NULL; kfree(light->name); + light->name = NULL; } static void gb_lights_release(struct gb_lights *glights) diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 0ccf192b9a0325c35abcbbf85f0d2663d8f80875..5950225e45d150e357e35c3eaef908c8516608d1 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -35,6 +35,8 @@ static int adt7316_i2c_read(void *client, u8 reg, u8 *data) return ret; } + *data = ret; + return 0; } diff --git a/drivers/staging/media/pulse8-cec/pulse8-cec.c b/drivers/staging/media/pulse8-cec/pulse8-cec.c index 1732c3857b8eaada9a37d647a58ccffc20cee711..2785cc03c5298bfcf535119edf500b7cf4641f58 100644 --- a/drivers/staging/media/pulse8-cec/pulse8-cec.c +++ b/drivers/staging/media/pulse8-cec/pulse8-cec.c @@ -580,7 +580,7 @@ static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) else pulse8->config_pending = true; mutex_unlock(&pulse8->config_lock); - return err; + return log_addr == CEC_LOG_ADDR_INVALID ? 0 : err; } static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 7f51024dc5ebbae80609cfd5e6df5c5af6f4c9ce..e87b9ed4f37ded292589d8142093c5162bc17bc4 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -451,7 +451,9 @@ static int aim_probe(struct most_interface *iface, int channel_id, c->devno = MKDEV(major, current_minor); cdev_init(&c->cdev, &channel_fops); c->cdev.owner = THIS_MODULE; - cdev_add(&c->cdev, c->devno, 1); + retval = cdev_add(&c->cdev, c->devno, 1); + if (retval < 0) + goto err_free_c; c->iface = iface; c->cfg = cfg; c->channel_id = channel_id; @@ -487,6 +489,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, list_del(&c->list); error_alloc_kfifo: cdev_del(&c->cdev); +err_free_c: kfree(c); error_alloc_channel: ida_simple_remove(&minor_id, current_minor); diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 4659a6450c04f1c30c0695f473ba9875c0c08bbc..6b18afb62145a515fdee23d9ce8f79be824cc274 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -87,6 +87,11 @@ static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) unsigned int payload_len = skb->len - ETH_HLEN; unsigned int mdp_len = payload_len + MDP_HDR_LEN; + if (mdp_len < skb->len) { + pr_err("drop: too large packet! (%u)\n", skb->len); + return -EINVAL; + } + if (mbo->buffer_length < mdp_len) { pr_err("drop: too small buffer! (%d for %d)\n", mbo->buffer_length, mdp_len); @@ -134,6 +139,11 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) u8 *buff = mbo->virt_address; unsigned int mep_len = skb->len + MEP_HDR_LEN; + if (mep_len < skb->len) { + pr_err("drop: too large packet! (%u)\n", skb->len); + return -EINVAL; + } + if (mbo->buffer_length < mep_len) { pr_err("drop: too small buffer! (%d for %d)\n", mbo->buffer_length, mep_len); diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 0f8b8e0bffdf9826a6f6e8e7b226a9ac6ab53268..dedc313e9dea7edc19e13b31f9f5099557b6639b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -805,7 +805,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN); memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN); - if (psta->qos_option) + if (psta && psta->qos_option) qos_option = true; } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { @@ -813,7 +813,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN); memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN); - if (psta->qos_option) + if (psta && psta->qos_option) qos_option = true; } else { RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv))); diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index c7bf8ab26192fc2c400f1405a7db3d76b0b7d570..50793c9df1b3711f54b435336ff8fef8e5d53473 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -2052,7 +2052,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) struct ieee_param *param; uint ret = 0; - if (p->length < sizeof(struct ieee_param) || !p->pointer) { + if (!p->pointer || p->length != sizeof(struct ieee_param)) { ret = -EINVAL; goto out; } @@ -2859,7 +2859,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) goto out; } - if (!p->pointer) { + if (!p->pointer || p->length != sizeof(struct ieee_param)) { ret = -EINVAL; goto out; } diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index d4a7d740fc620188e75034276374b823dd05c304..537a99eba6af8ec489bce60dc442d2a69eb15051 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -45,6 +45,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ + {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */ {} /* Terminating entry */ @@ -78,7 +79,7 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) phost_conf = pusbd->actconfig; pconf_desc = &phost_conf->desc; - phost_iface = &usb_intf->altsetting[0]; + phost_iface = usb_intf->cur_altsetting; piface_desc = &phost_iface->desc; pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 5fe95937d8113e9eb3a6c4073806f6b541ef8bd3..6ec379056650411025ebcdc3e758aa2eadbab59b 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -1509,7 +1509,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN); struct usb_device *udev = priv->udev; int pend; - int status; + int status, rt = -1; struct urb *tx_urb = NULL, *tx_urb_zero = NULL; unsigned int idx_pipe; @@ -1653,8 +1653,10 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) } if (bSend0Byte) { tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC); - if (!tx_urb_zero) - return -ENOMEM; + if (!tx_urb_zero) { + rt = -ENOMEM; + goto error; + } usb_fill_bulk_urb(tx_urb_zero, udev, usb_sndbulkpipe(udev, idx_pipe), &zero, 0, tx_zero_isr, dev); @@ -1664,7 +1666,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status); - return -1; + goto error; } } netif_trans_update(dev); @@ -1675,7 +1677,12 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status); - return -1; + +error: + dev_kfree_skb_any(skb); + usb_free_urb(tx_urb); + usb_free_urb(tx_urb_zero); + return rt; } static short rtl8192_usb_initendpoints(struct net_device *dev) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 897d4621a5ce760a07ca91a24080228a2cb91349..d0ba42dfafebfdedbdb7a55c87063ccd7b1f652b 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -275,7 +275,7 @@ static uint r8712_usb_dvobj_init(struct _adapter *padapter) pdvobjpriv->padapter = padapter; padapter->EepromAddressSize = 6; - phost_iface = &pintf->altsetting[0]; + phost_iface = pintf->cur_altsetting; piface_desc = &phost_iface->desc; pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; if (pusbd->speed == USB_SPEED_HIGH) { diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 4832666cc580eca1b417f4132a115f244b1b0363..0578bf82f557cbe9a998624f2c597146883ca984 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -62,6 +62,8 @@ #define RATE_AUTO 12 #define MAX_RATE 12 +#define VNT_B_RATES (BIT(RATE_1M) | BIT(RATE_2M) |\ + BIT(RATE_5M) | BIT(RATE_11M)) /* * device specific @@ -269,6 +271,7 @@ struct vnt_private { u8 mac_hw; /* netdev */ struct usb_device *usb; + struct usb_interface *intf; u64 tsf_time; u8 rx_rate; diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 655f0002f8808a6d4527dd23f35987d8c014bda2..7b73fa2f883404b4b05e2db08af246e4bf31918b 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -140,7 +140,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, vnt_rf_rssi_to_dbm(priv, *rssi, &rx_dbm); - priv->bb_pre_ed_rssi = (u8)rx_dbm + 1; + priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1; priv->current_rssi = priv->bb_pre_ed_rssi; frame = skb_data + 8; diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 73538fb4e4e2f80760022b1cde45dca9eaf5171b..b554e881e67f3d792cb73fd3274bbacd64985e58 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -107,9 +107,11 @@ static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr) info->status.rates[0].count = tx_retry; - if (!(tsr & (TSR_TMO | TSR_RETRYTMO))) { + if (!(tsr & TSR_TMO)) { info->status.rates[0].idx = idx; - info->flags |= IEEE80211_TX_STAT_ACK; + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + info->flags |= IEEE80211_TX_STAT_ACK; } ieee80211_tx_status_irqsafe(priv->hw, context->skb); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index b1955378852a01caa5599cc67ca6474d0abf6724..b93773af20318564b7ef98bb9d2f500049b999ed 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -972,6 +972,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) priv = hw->priv; priv->hw = hw; priv->usb = udev; + priv->intf = intf; vnt_set_options(priv); @@ -994,6 +995,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS); ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS); ieee80211_hw_set(priv->hw, SUPPORTS_PS); + ieee80211_hw_set(priv->hw, PS_NULLFUNC_STACK); priv->hw->max_signal = 100; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index aa59e7f14ab30c74a68c862b6b260d28b19c8949..5ccb9eb7ff1c12134553044bc589bd8779a27d81 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -277,11 +277,9 @@ static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, PK_TYPE_11B, &buf->b); /* Get Duration and TimeStamp */ - if (ieee80211_is_pspoll(hdr->frame_control)) { - __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15)); - - buf->duration_a = dur; - buf->duration_b = dur; + if (ieee80211_is_nullfunc(hdr->frame_control)) { + buf->duration_a = hdr->duration_id; + buf->duration_b = hdr->duration_id; } else { buf->duration_a = vnt_get_duration_le(priv, tx_context->pkt_type, need_ack); @@ -370,10 +368,8 @@ static u16 vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context, tx_context->pkt_type, &buf->ab); /* Get Duration and TimeStampOff */ - if (ieee80211_is_pspoll(hdr->frame_control)) { - __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15)); - - buf->duration = dur; + if (ieee80211_is_nullfunc(hdr->frame_control)) { + buf->duration = hdr->duration_id; } else { buf->duration = vnt_get_duration_le(priv, tx_context->pkt_type, need_ack); @@ -816,10 +812,14 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) if (info->band == NL80211_BAND_5GHZ) { pkt_type = PK_TYPE_11A; } else { - if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - pkt_type = PK_TYPE_11GB; - else - pkt_type = PK_TYPE_11GA; + if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + if (priv->basic_rates & VNT_B_RATES) + pkt_type = PK_TYPE_11GB; + else + pkt_type = PK_TYPE_11GA; + } else { + pkt_type = PK_TYPE_11A; + } } } else { pkt_type = PK_TYPE_11B; diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 95faaeb7432a043b488734a26a01913f2020cad7..4dc3521932ba79a4f24affa24e2de9f741ff9603 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -110,6 +110,7 @@ void vnt_run_command(struct work_struct *work) if (vnt_init(priv)) { /* If fail all ends TODO retry */ dev_err(&priv->usb->dev, "failed to start\n"); + usb_set_intfdata(priv->intf, NULL); ieee80211_free_hw(priv->hw); return; } diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index f815f9d5045f342049dfa3a9b4b510ec5191692a..08e2bbd9772f8927f466c7103fdf90671828d791 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -938,7 +938,7 @@ int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) } } - return 0; + return result; } /*---------------------------------------------------------------- diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index f0d97305575d75ceed1719289dbd042ad760b782..aa3f98994c7d63f815df8c37c9a84c932abe53ed 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -74,7 +74,7 @@ static int chap_check_algorithm(const char *a_str) if (!token) goto out; - if (!strncmp(token, "5", 1)) { + if (!strcmp(token, "5")) { pr_debug("Selected MD5 Algorithm\n"); kfree(orig); return CHAP_DIGEST_MD5; diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c index cb6497ce4b61a81cbb9eba00bd79d0ecbc08f847..6e75095af6818ad1ea034f09da7227f7fa6d8937 100644 --- a/drivers/target/target_core_fabric_lib.c +++ b/drivers/target/target_core_fabric_lib.c @@ -130,7 +130,7 @@ static int srp_get_pr_transport_id( memset(buf + 8, 0, leading_zero_bytes); rc = hex2bin(buf + 8 + leading_zero_bytes, p, count); if (rc < 0) { - pr_debug("hex2bin failed for %s: %d\n", __func__, rc); + pr_debug("hex2bin failed for %s: %d\n", p, rc); return rc; } diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 872a8ca986424d01088e8aa483f5b229a8932542..27cedf54e0ece5a7de0487812add68c7a91d24d3 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -846,7 +846,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, load = 0; total_load += load; - if (trace_thermal_power_cpu_limit_enabled() && load_cpu) + if (load_cpu) load_cpu[i] = load; i++; diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 34169c32d4956ffe8bb146ab0ae66a8f4ebbdbf2..ea9558679634b3128c33e71ef38389ae7baad86c 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -348,7 +348,8 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) u32 raw; for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { - raw = readl(mt->thermal_base + conf->msr[i]); + raw = readl(mt->thermal_base + + conf->msr[conf->bank_data[bank->id].sensors[i]]); temp = raw_to_mcelsius(mt, conf->bank_data[bank->id].sensors[i], @@ -485,7 +486,8 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, for (i = 0; i < conf->bank_data[num].num_sensors; i++) writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]], - mt->thermal_base + conf->adcpnp[i]); + mt->thermal_base + + conf->adcpnp[conf->bank_data[num].sensors[i]]); writel((1 << conf->bank_data[num].num_sensors) - 1, mt->thermal_base + TEMP_MONCTL0); diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index b05dc508662795639d391aee29ed568c2e2fe75e..8bab8b00d47d658190dad693fbf4cb798e7de7c1 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c @@ -120,6 +120,14 @@ static int hvterm_raw_get_chars(uint32_t vtermno, char *buf, int count) return got; } +/** + * hvterm_raw_put_chars: send characters to firmware for given vterm adapter + * @vtermno: The virtual terminal number. + * @buf: The characters to send. Because of the underlying hypercall in + * hvc_put_chars(), this buffer must be at least 16 bytes long, even if + * you are sending fewer chars. + * @count: number of chars to send. + */ static int hvterm_raw_put_chars(uint32_t vtermno, const char *buf, int count) { struct hvterm_priv *pv = hvterm_privs[vtermno]; @@ -232,6 +240,7 @@ static const struct hv_ops hvterm_hvsi_ops = { static void udbg_hvc_putc(char c) { int count = -1; + unsigned char bounce_buffer[16]; if (!hvterm_privs[0]) return; @@ -242,7 +251,12 @@ static void udbg_hvc_putc(char c) do { switch(hvterm_privs[0]->proto) { case HV_PROTOCOL_RAW: - count = hvterm_raw_put_chars(0, &c, 1); + /* + * hvterm_raw_put_chars requires at least a 16-byte + * buffer, so go via the bounce buffer + */ + bounce_buffer[0] = c; + count = hvterm_raw_put_chars(0, bounce_buffer, 1); break; case HV_PROTOCOL_HVSI: count = hvterm_hvsi_put_chars(0, &c, 1); diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c index df0204b6148fb03efd3a348b96345ad84db3285a..4417f75684221a09ac4209f817e77f2a970748f9 100644 --- a/drivers/tty/ipwireless/hardware.c +++ b/drivers/tty/ipwireless/hardware.c @@ -1515,6 +1515,8 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw) sizeof(struct ipw_setup_get_version_query_packet), ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP, TL_SETUP_SIGNO_GET_VERSION_QRY); + if (!ver_packet) + return; ver_packet->header.length = sizeof(struct tl_setup_get_version_qry); /* diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 8d6253903f24f8fff57d797e23303e74a296325a..0c12dec110bc414f125a7dad747d796d4f3adedd 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -614,7 +614,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, } /* no data */ - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { ret = -EAGAIN; break; } @@ -681,7 +681,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, if (tbuf) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { error = -EAGAIN; break; } diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 345111467b85026ead297b67f27a70cbf67a867d..ee0e07b4a13d0c28e3be90ade952059ce4f9e572 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -1080,7 +1080,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, pMsg = remove_msg(pInfo, pClient); if (pMsg == NULL) { /* no messages available. */ - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { ret = -EAGAIN; goto unlock; } diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 86c0bc074afbf4ec319641aad12fa3df94bae545..a75a6e1eb5105a8c2d197247aa5bceda86d39003 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1732,7 +1732,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, down_read(&tty->termios_rwsem); - while (1) { + do { /* * When PARMRK is set, each input char may take up to 3 chars * in the read buf; reduce the buffer space avail by 3x @@ -1774,7 +1774,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, fp += n; count -= n; rcvd += n; - } + } while (!test_bit(TTY_LDISC_CHANGING, &tty->flags)); tty->receive_room = room; @@ -2241,7 +2241,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, break; if (!timeout) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { retval = -EAGAIN; break; } @@ -2395,7 +2395,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, } if (!nr) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { retval = -EAGAIN; break; } diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index e10f1244409b344b850ffbbd4af5757a66c875f1..2fa92ec1d1cc699fc082f64783407af0b04f1d3f 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -119,7 +119,7 @@ static int bcm2835aux_serial_remove(struct platform_device *pdev) { struct bcm2835aux_data *data = platform_get_drvdata(pdev); - serial8250_unregister_port(data->uart.port.line); + serial8250_unregister_port(data->line); clk_disable_unprepare(data->clk); return 0; diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index e8819aa20415603c80547e382838a8fa3ce54792..c4e9eba360238dc1db8068db2ee8a23faeaeae60 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -181,7 +181,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up) struct hlist_head *h; struct hlist_node *n; struct irq_info *i; - int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0; + int ret; mutex_lock(&hash_mutex); @@ -216,9 +216,8 @@ static int serial_link_irq_chain(struct uart_8250_port *up) INIT_LIST_HEAD(&up->list); i->head = &up->list; spin_unlock_irq(&i->lock); - irq_flags |= up->port.irqflags; ret = request_irq(up->port.irq, serial8250_interrupt, - irq_flags, "serial", i); + up->port.irqflags, "serial", i); if (ret < 0) serial_do_unlink(i, up); } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8f12333245867032a86e40a3d4ab9bdf1667b7e5..c7a7574172faea0b89a290aa2fadffe6e02d6716 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2199,6 +2199,10 @@ int serial8250_do_startup(struct uart_port *port) } } + /* Check if we need to have shared IRQs */ + if (port->irq && (up->port.flags & UPF_SHARE_IRQ)) + up->port.irqflags |= IRQF_SHARED; + if (port->irq) { unsigned char iir1; /* diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 2d8089fc21397080e8b2dbd7a4984badc1062769..f6586a8681b9b3154dc64e1fd6ce974d0663187c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -811,10 +811,8 @@ __acquires(&uap->port.lock) if (!uap->using_tx_dma) return; - /* Avoid deadlock with the DMA engine callback */ - spin_unlock(&uap->port.lock); - dmaengine_terminate_all(uap->dmatx.chan); - spin_lock(&uap->port.lock); + dmaengine_terminate_async(uap->dmatx.chan); + if (uap->dmatx.queued) { dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1, DMA_TO_DEVICE); diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index d4462512605b5cbc58d053a3183d332db9a8d9ee..246f4aab74075aaaa2c163bf3a93111204a18bb6 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -289,6 +289,10 @@ static void ar933x_uart_set_termios(struct uart_port *port, ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, AR933X_UART_CS_HOST_INT_EN); + /* enable RX and TX ready overide */ + ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, + AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE); + /* reenable the UART */ ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S, @@ -421,6 +425,10 @@ static int ar933x_uart_startup(struct uart_port *port) ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, AR933X_UART_CS_HOST_INT_EN); + /* enable RX and TX ready overide */ + ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, + AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE); + /* Enable RX interrupts */ up->ier = AR933X_UART_INT_RX_VALID; ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 578242239daada7832bd877b78107cc59687a297..4a7eb85f7c8577556927fc99ff822697975c399f 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -501,7 +501,8 @@ static void atmel_stop_tx(struct uart_port *port) atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask); if (atmel_uart_is_half_duplex(port)) - atmel_start_rx(port); + if (!atomic_read(&atmel_port->tasklet_shutdown)) + atmel_start_rx(port); } @@ -2200,27 +2201,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, mode |= ATMEL_US_USMODE_NORMAL; } - /* set the mode, clock divisor, parity, stop bits and data size */ - atmel_uart_writel(port, ATMEL_US_MR, mode); - - /* - * when switching the mode, set the RTS line state according to the - * new mode, otherwise keep the former state - */ - if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) { - unsigned int rts_state; - - if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) { - /* let the hardware control the RTS line */ - rts_state = ATMEL_US_RTSDIS; - } else { - /* force RTS line to low level */ - rts_state = ATMEL_US_RTSEN; - } - - atmel_uart_writel(port, ATMEL_US_CR, rts_state); - } - /* * Set the baud rate: * Fractional baudrate allows to setup output frequency more @@ -2247,6 +2227,28 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, quot = cd | fp << ATMEL_US_FP_OFFSET; atmel_uart_writel(port, ATMEL_US_BRGR, quot); + + /* set the mode, clock divisor, parity, stop bits and data size */ + atmel_uart_writel(port, ATMEL_US_MR, mode); + + /* + * when switching the mode, set the RTS line state according to the + * new mode, otherwise keep the former state + */ + if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) { + unsigned int rts_state; + + if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) { + /* let the hardware control the RTS line */ + rts_state = ATMEL_US_RTSDIS; + } else { + /* force RTS line to low level */ + rts_state = ATMEL_US_RTSEN; + } + + atmel_uart_writel(port, ATMEL_US_CR, rts_state); + } + atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 800996522fdc284031a89532dd4ca33817b21dfd..5b6093dc3ff2647b56e10d955fdd5503d9fc699d 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -346,8 +346,8 @@ static void lpuart_dma_tx(struct lpuart_port *sport) } sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl, - sport->dma_tx_nents, - DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); + ret, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT); if (!sport->dma_tx_desc) { dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); dev_err(dev, "Cannot prepare TX slave DMA!\n"); diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 91d2ddd6ef881b81115c8efd86672e0ff096ea21..180b77334fdd8dd3e88f83d2731776e8b8448e8b 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1244,6 +1244,9 @@ static int ifx_spi_spi_remove(struct spi_device *spi) struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); /* stop activity */ tasklet_kill(&ifx_dev->io_work_tasklet); + + pm_runtime_disable(&spi->dev); + /* free irq */ free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev); free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 0d82be145c680a33b4ce7529b381364585d9f7ec..325c38c9b45162c39a4d2384f895999ff356f4c0 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -532,7 +532,7 @@ static void imx_dma_tx(struct imx_port *sport) sport->tx_bytes = uart_circ_chars_pending(xmit); - if (xmit->tail < xmit->head) { + if (xmit->tail < xmit->head || xmit->head == 0) { sport->dma_tx_nents = 1; sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes); } else { @@ -548,7 +548,7 @@ static void imx_dma_tx(struct imx_port *sport) dev_err(dev, "DMA mapping error for TX.\n"); return; } - desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents, + desc = dmaengine_prep_slave_sg(chan, sgl, ret, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!desc) { dma_unmap_sg(dev, sgl, sport->dma_tx_nents, @@ -1943,7 +1943,7 @@ imx_console_setup(struct console *co, char *options) retval = clk_prepare(sport->clk_per); if (retval) - clk_disable_unprepare(sport->clk_ipg); + clk_unprepare(sport->clk_ipg); error_console: return retval; diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 7700e8a0435fc1ddef665341e5c5c6b14367728c..2c13cff1a74244ee245ae1a8c0fae56fae60ab20 100755 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1006,6 +1006,7 @@ static unsigned int msm_get_mctrl(struct uart_port *port) static void msm_reset(struct uart_port *port) { struct msm_port *msm_port = UART_TO_MSM(port); + unsigned int mr; /* reset everything */ msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); @@ -1013,7 +1014,10 @@ static void msm_reset(struct uart_port *port) msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); - msm_write(port, UART_CR_CMD_SET_RFR, UART_CR); + msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR); + mr = msm_read(port, UART_MR1); + mr &= ~UART_MR1_RX_RDY_CTL; + msm_write(port, mr, UART_MR1); /* Disable DM modes */ if (msm_port->is_uartdm) @@ -1616,6 +1620,7 @@ static void __msm_console_write(struct uart_port *port, const char *s, int num_newlines = 0; bool replaced = false; void __iomem *tf; + int locked = 1; if (is_uartdm) tf = port->membase + UARTDM_TF; @@ -1628,7 +1633,13 @@ static void __msm_console_write(struct uart_port *port, const char *s, num_newlines++; count += num_newlines; - spin_lock(&port->lock); + if (port->sysrq) + locked = 0; + else if (oops_in_progress) + locked = spin_trylock(&port->lock); + else + spin_lock(&port->lock); + if (is_uartdm) msm_reset_dm_count(port, count); @@ -1666,7 +1677,9 @@ static void __msm_console_write(struct uart_port *port, const char *s, writel_relaxed_no_log(*buffer, tf); i += num_chars; } - spin_unlock(&port->lock); + + if (locked) + spin_unlock(&port->lock); } static void msm_console_write(struct console *co, const char *s, diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index 401c983ec5f3651bc442b315566fc4dfc63ed627..a10e4aa9e18eaffb59e1df06ec47a4ff7865b867 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -581,7 +581,7 @@ static int mvebu_uart_probe(struct platform_device *pdev) port->membase = devm_ioremap_resource(&pdev->dev, reg); if (IS_ERR(port->membase)) - return -PTR_ERR(port->membase); + return PTR_ERR(port->membase); data = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_uart_data), GFP_KERNEL); diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 42caccb5e87eeabf732872225ef1527f427acea6..30b577384a1d0c3952563e60d0b0d1680e857410 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -252,6 +252,7 @@ struct eg20t_port { struct dma_chan *chan_rx; struct scatterlist *sg_tx_p; int nent; + int orig_nent; struct scatterlist sg_rx; int tx_dma_use; void *rx_buf_virt; @@ -806,9 +807,10 @@ static void pch_dma_tx_complete(void *arg) } xmit->tail &= UART_XMIT_SIZE - 1; async_tx_ack(priv->desc_tx); - dma_unmap_sg(port->dev, sg, priv->nent, DMA_TO_DEVICE); + dma_unmap_sg(port->dev, sg, priv->orig_nent, DMA_TO_DEVICE); priv->tx_dma_use = 0; priv->nent = 0; + priv->orig_nent = 0; kfree(priv->sg_tx_p); pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT); } @@ -1033,6 +1035,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) dev_err(priv->port.dev, "%s:dma_map_sg Failed\n", __func__); return 0; } + priv->orig_nent = num; priv->nent = nent; for (i = 0; i < nent; i++, sg++) { diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 48afdffaae16afdb1cac0111a9c1f8a3c2ee8fe3..9ab13210f8abc0028904b527fb2899390d5be530 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1109,7 +1109,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) if (!uport) goto out; - if (uport->type != PORT_UNKNOWN) + if (uport->type != PORT_UNKNOWN && uport->ops->break_ctl) uport->ops->break_ctl(uport, break_state); ret = 0; out: @@ -2798,6 +2798,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) if (uport->cons && uport->dev) of_console_check(uport->dev->of_node, uport->cons->name, uport->line); + tty_port_link_device(port, drv->tty_driver, uport->line); uart_configure_port(drv, state, uport); port->console = uart_console(uport); diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 033856287ca21268ded24f646fc04d4f0354715c..ea8b591dd46f48b2edc0658a7af31f2af1eb9c00 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -293,13 +293,8 @@ static void stm32_transmit_chars(struct uart_port *port) return; } - if (uart_tx_stopped(port)) { - stm32_stop_tx(port); - return; - } - - if (uart_circ_empty(xmit)) { - stm32_stop_tx(port); + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); return; } @@ -312,7 +307,7 @@ static void stm32_transmit_chars(struct uart_port *port) uart_write_wakeup(port); if (uart_circ_empty(xmit)) - stm32_stop_tx(port); + stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); } static irqreturn_t stm32_interrupt(int irq, void *ptr) diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index e645ee1cfd989563c5e58d09b287c683873f447a..7446ce29f677074cf7a06c7ae3241740c81b25bc 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -1349,10 +1349,10 @@ static void throttle(struct tty_struct * tty) DBGINFO(("%s throttle\n", info->device_name)); if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (C_CRTSCTS(tty)) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals &= ~SerialSignal_RTS; - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } } @@ -1374,10 +1374,10 @@ static void unthrottle(struct tty_struct * tty) else send_xchar(tty, START_CHAR(tty)); } - if (C_CRTSCTS(tty)) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals |= SerialSignal_RTS; - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } } @@ -2576,8 +2576,8 @@ static void change_params(struct slgt_info *info) info->read_status_mask = IRQ_RXOVER; if (I_INPCK(info->port.tty)) info->read_status_mask |= MASK_PARITY | MASK_FRAMING; - if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) - info->read_status_mask |= MASK_BREAK; + if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) + info->read_status_mask |= MASK_BREAK; if (I_IGNPAR(info->port.tty)) info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING; if (I_IGNBRK(info->port.tty)) { @@ -3208,7 +3208,7 @@ static int tiocmset(struct tty_struct *tty, info->signals &= ~SerialSignal_DTR; spin_lock_irqsave(&info->lock,flags); - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); return 0; } @@ -3219,7 +3219,7 @@ static int carrier_raised(struct tty_port *port) struct slgt_info *info = container_of(port, struct slgt_info, port); spin_lock_irqsave(&info->lock,flags); - get_signals(info); + get_signals(info); spin_unlock_irqrestore(&info->lock,flags); return (info->signals & SerialSignal_DCD) ? 1 : 0; } @@ -3234,7 +3234,7 @@ static void dtr_rts(struct tty_port *port, int on) info->signals |= SerialSignal_RTS | SerialSignal_DTR; else info->signals &= ~(SerialSignal_RTS | SerialSignal_DTR); - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index dec156586de1bdfcf9ed1439523a884267ff02df..2f6df8d74b4aa8ed40de35da7baf0d5f537b73b1 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -1467,10 +1467,10 @@ static void throttle(struct tty_struct * tty) if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (C_CRTSCTS(tty)) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals &= ~SerialSignal_RTS; - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } } @@ -1496,10 +1496,10 @@ static void unthrottle(struct tty_struct * tty) send_xchar(tty, START_CHAR(tty)); } - if (C_CRTSCTS(tty)) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals |= SerialSignal_RTS; - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } } @@ -2485,7 +2485,7 @@ static void isr_io_pin( SLMP_INFO *info, u16 status ) if (status & SerialSignal_CTS) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("CTS tx start..."); - info->port.tty->hw_stopped = 0; + info->port.tty->hw_stopped = 0; tx_start(info); info->pending_bh |= BH_TRANSMIT; return; @@ -2494,7 +2494,7 @@ static void isr_io_pin( SLMP_INFO *info, u16 status ) if (!(status & SerialSignal_CTS)) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("CTS tx stop..."); - info->port.tty->hw_stopped = 1; + info->port.tty->hw_stopped = 1; tx_stop(info); } } @@ -2821,8 +2821,8 @@ static void change_params(SLMP_INFO *info) info->read_status_mask2 = OVRN; if (I_INPCK(info->port.tty)) info->read_status_mask2 |= PE | FRME; - if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) - info->read_status_mask1 |= BRKD; + if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) + info->read_status_mask1 |= BRKD; if (I_IGNPAR(info->port.tty)) info->ignore_status_mask2 |= PE | FRME; if (I_IGNBRK(info->port.tty)) { @@ -3192,7 +3192,7 @@ static int tiocmget(struct tty_struct *tty) unsigned long flags; spin_lock_irqsave(&info->lock,flags); - get_signals(info); + get_signals(info); spin_unlock_irqrestore(&info->lock,flags); result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS : 0) | @@ -3230,7 +3230,7 @@ static int tiocmset(struct tty_struct *tty, info->serial_signals &= ~SerialSignal_DTR; spin_lock_irqsave(&info->lock,flags); - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); return 0; @@ -3242,7 +3242,7 @@ static int carrier_raised(struct tty_port *port) unsigned long flags; spin_lock_irqsave(&info->lock,flags); - get_signals(info); + get_signals(info); spin_unlock_irqrestore(&info->lock,flags); return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; @@ -3258,7 +3258,7 @@ static void dtr_rts(struct tty_port *port, int on) info->serial_signals |= SerialSignal_RTS | SerialSignal_DTR; else info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); - set_signals(info); + set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 547bd21379e2bbc0475d2a89bd4f62bc8df32513..89fada4cc1c50e84b4a10d11dd6fd2ed53061daf 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -544,7 +544,6 @@ void __handle_sysrq(int key, bool check_mask) */ orig_log_level = console_loglevel; console_loglevel = CONSOLE_LOGLEVEL_DEFAULT; - pr_info("SysRq : "); op_p = __sysrq_get_key_op(key); if (op_p) { @@ -553,14 +552,15 @@ void __handle_sysrq(int key, bool check_mask) * should not) and is the invoked operation enabled? */ if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { - pr_cont("%s\n", op_p->action_msg); + pr_info("%s\n", op_p->action_msg); console_loglevel = orig_log_level; op_p->handler(key); } else { - pr_cont("This sysrq operation is disabled.\n"); + pr_info("This sysrq operation is disabled.\n"); + console_loglevel = orig_log_level; } } else { - pr_cont("HELP : "); + pr_info("HELP : "); /* Only print the help msg once per handler */ for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) { if (sysrq_key_table[i]) { diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 3eb3f2a03bbb9e95cf68f6e75c473a5dd906a723..706faca834f2710996a79d74b7433e75a128f539 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -348,6 +348,11 @@ int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { int ret; + /* Kindly asking blocked readers to release the read side */ + set_bit(TTY_LDISC_CHANGING, &tty->flags); + wake_up_interruptible_all(&tty->read_wait); + wake_up_interruptible_all(&tty->write_wait); + ret = __tty_ldisc_lock(tty, timeout); if (!ret) return -EBUSY; @@ -358,6 +363,8 @@ int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) void tty_ldisc_unlock(struct tty_struct *tty) { clear_bit(TTY_LDISC_HALTED, &tty->flags); + /* Can be cleared here - ldisc_unlock will wake up writers firstly */ + clear_bit(TTY_LDISC_CHANGING, &tty->flags); __tty_ldisc_unlock(tty); } diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index e8a917a23ed912542127ffff53c5658f8f36ef83..b4e7a7317713b202276e36053d470a9358cea0c7 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1460,7 +1460,7 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev)) kbd_rawcode(value); - if (event_type == EV_KEY) + if (event_type == EV_KEY && event_code <= KEY_MAX) kbd_keycode(event_code, value, HW_RAW(handle->dev)); spin_unlock(&kbd_event_lock); diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 368ce1803e8f229e3cfc0be9ddd405d52b34e6f1..1edc1a36db4acaf01d03552e4b13d88e08b38be7 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ static volatile int sel_start = -1; /* cleared by clear_selection */ static int sel_end; static int sel_buffer_lth; static char *sel_buffer; +static DEFINE_MUTEX(sel_lock); /* clear_selection, highlight and highlight_pointer can be called from interrupt (via scrollback/front) */ @@ -156,14 +158,14 @@ static int store_utf8(u16 c, char *p) * The entire selection process is managed under the console_lock. It's * a lot under the lock but its hardly a performance path */ -int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) +static int __set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) { struct vc_data *vc = vc_cons[fg_console].d; int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp; int i, ps, pe, multiplier; u16 c; - int mode; + int mode, ret = 0; poke_blanked_console(); @@ -324,7 +326,21 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t } } sel_buffer_lth = bp - sel_buffer; - return 0; + + return ret; +} + +int set_selection(const struct tiocl_selection __user *v, struct tty_struct *tty) +{ + int ret; + + mutex_lock(&sel_lock); + console_lock(); + ret = __set_selection(v, tty); + console_unlock(); + mutex_unlock(&sel_lock); + + return ret; } /* Insert the contents of the selection buffer into the @@ -341,6 +357,7 @@ int paste_selection(struct tty_struct *tty) unsigned int count; struct tty_ldisc *ld; DECLARE_WAITQUEUE(wait, current); + int ret = 0; console_lock(); poke_blanked_console(); @@ -352,10 +369,17 @@ int paste_selection(struct tty_struct *tty) tty_buffer_lock_exclusive(&vc->port); add_wait_queue(&vc->paste_wait, &wait); + mutex_lock(&sel_lock); while (sel_buffer && sel_buffer_lth > pasted) { set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + ret = -EINTR; + break; + } if (tty_throttled(tty)) { + mutex_unlock(&sel_lock); schedule(); + mutex_lock(&sel_lock); continue; } __set_current_state(TASK_RUNNING); @@ -364,10 +388,11 @@ int paste_selection(struct tty_struct *tty) count); pasted += count; } + mutex_unlock(&sel_lock); remove_wait_queue(&vc->paste_wait, &wait); __set_current_state(TASK_RUNNING); tty_buffer_unlock_exclusive(&vc->port); tty_ldisc_deref(ld); - return 0; + return ret; } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 232cb0a760b907c9f7da4f1ee3e7ffb927cd5f89..c1d3b685a5877e4309ffa1734b34494e44eb55f1 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2690,9 +2690,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) switch (type) { case TIOCL_SETSEL: - console_lock(); ret = set_selection((struct tiocl_selection __user *)(p+1), tty); - console_unlock(); break; case TIOCL_PASTESEL: ret = paste_selection(tty); diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 638eb9bbd59fa609f0cb7d05b89d8c4fbfbaff60..e8efb270dc8f960d8d694caa86a1ded60017bb5a 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -850,58 +850,49 @@ int vt_ioctl(struct tty_struct *tty, case VT_RESIZEX: { - struct vt_consize __user *vtconsize = up; - ushort ll,cc,vlin,clin,vcol,ccol; + struct vt_consize v; if (!perm) return -EPERM; - if (!access_ok(VERIFY_READ, vtconsize, - sizeof(struct vt_consize))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&v, up, sizeof(struct vt_consize))) + return -EFAULT; /* FIXME: Should check the copies properly */ - __get_user(ll, &vtconsize->v_rows); - __get_user(cc, &vtconsize->v_cols); - __get_user(vlin, &vtconsize->v_vlin); - __get_user(clin, &vtconsize->v_clin); - __get_user(vcol, &vtconsize->v_vcol); - __get_user(ccol, &vtconsize->v_ccol); - vlin = vlin ? vlin : vc->vc_scan_lines; - if (clin) { - if (ll) { - if (ll != vlin/clin) { - /* Parameters don't add up */ - ret = -EINVAL; - break; - } - } else - ll = vlin/clin; + if (!v.v_vlin) + v.v_vlin = vc->vc_scan_lines; + if (v.v_clin) { + int rows = v.v_vlin/v.v_clin; + if (v.v_rows != rows) { + if (v.v_rows) /* Parameters don't add up */ + return -EINVAL; + v.v_rows = rows; + } } - if (vcol && ccol) { - if (cc) { - if (cc != vcol/ccol) { - ret = -EINVAL; - break; - } - } else - cc = vcol/ccol; + if (v.v_vcol && v.v_ccol) { + int cols = v.v_vcol/v.v_ccol; + if (v.v_cols != cols) { + if (v.v_cols) + return -EINVAL; + v.v_cols = cols; + } } - if (clin > 32) { - ret = -EINVAL; - break; - } - + if (v.v_clin > 32) + return -EINVAL; + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *vcp; + if (!vc_cons[i].d) continue; console_lock(); - if (vlin) - vc_cons[i].d->vc_scan_lines = vlin; - if (clin) - vc_cons[i].d->vc_font.height = clin; - vc_cons[i].d->vc_resize_user = 1; - vc_resize(vc_cons[i].d, cc, ll); + vcp = vc_cons[i].d; + if (vcp) { + if (v.v_vlin) + vcp->vc_scan_lines = v.v_vlin; + if (v.v_clin) + vcp->vc_font.height = v.v_clin; + vcp->vc_resize_user = 1; + vc_resize(vcp, v.v_cols, v.v_rows); + } console_unlock(); } break; diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c index e1134a4d97f3fd0005e30dc29e9acf9da77e0e46..a00b4aee6c799cd12b8273db0101990c6437033a 100644 --- a/drivers/uio/uio_dmem_genirq.c +++ b/drivers/uio/uio_dmem_genirq.c @@ -135,11 +135,13 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) if (irq_on) { if (test_and_clear_bit(0, &priv->flags)) enable_irq(dev_info->irq); + spin_unlock_irqrestore(&priv->lock, flags); } else { - if (!test_and_set_bit(0, &priv->flags)) + if (!test_and_set_bit(0, &priv->flags)) { + spin_unlock_irqrestore(&priv->lock, flags); disable_irq(dev_info->irq); + } } - spin_unlock_irqrestore(&priv->lock, flags); return 0; } diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index df67815f74e68020076c8b59bcecc8ba0bf3782d..127fcaf13856c4392b85721a6f83ec410576813e 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -2167,10 +2167,11 @@ static void uea_intr(struct urb *urb) /* * Start the modem : init the data and start kernel thread */ -static int uea_boot(struct uea_softc *sc) +static int uea_boot(struct uea_softc *sc, struct usb_interface *intf) { - int ret, size; struct intr_pkt *intr; + int ret = -ENOMEM; + int size; uea_enters(INS_TO_USBDEV(sc)); @@ -2195,6 +2196,11 @@ static int uea_boot(struct uea_softc *sc) if (UEA_CHIP_VERSION(sc) == ADI930) load_XILINX_firmware(sc); + if (intf->cur_altsetting->desc.bNumEndpoints < 1) { + ret = -ENODEV; + goto err0; + } + intr = kmalloc(size, GFP_KERNEL); if (!intr) goto err0; @@ -2206,8 +2212,7 @@ static int uea_boot(struct uea_softc *sc) usb_fill_int_urb(sc->urb_int, sc->usb_dev, usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE), intr, size, uea_intr, sc, - sc->usb_dev->actconfig->interface[0]->altsetting[0]. - endpoint[0].desc.bInterval); + intf->cur_altsetting->endpoint[0].desc.bInterval); ret = usb_submit_urb(sc->urb_int, GFP_KERNEL); if (ret < 0) { @@ -2222,6 +2227,7 @@ static int uea_boot(struct uea_softc *sc) sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm"); if (IS_ERR(sc->kthread)) { uea_err(INS_TO_USBDEV(sc), "failed to create thread\n"); + ret = PTR_ERR(sc->kthread); goto err2; } @@ -2236,7 +2242,7 @@ static int uea_boot(struct uea_softc *sc) kfree(intr); err0: uea_leaves(INS_TO_USBDEV(sc)); - return -ENOMEM; + return ret; } /* @@ -2597,7 +2603,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, if (ret < 0) goto error; - ret = uea_boot(sc); + ret = uea_boot(sc, intf); if (ret < 0) goto error_rm_grp; diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 111b0e0b8698b76d0de983e856c89dadea92734e..2178fe7a417b9e6e3085257515b438d2fa9d9a26 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -37,6 +37,7 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd); struct ehci_ci_priv { struct regulator *reg_vbus; + bool enabled; }; static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable) @@ -48,7 +49,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable) int ret = 0; int port = HCS_N_PORTS(ehci->hcs_params); - if (priv->reg_vbus) { + if (priv->reg_vbus && enable != priv->enabled) { if (port > 1) { dev_warn(dev, "Not support multi-port regulator control\n"); @@ -64,6 +65,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable) enable ? "enable" : "disable", ret); return ret; } + priv->enabled = enable; } if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) { diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 217a479165e03eb8276b9eaa09579f4558355a89..09337a973335c7ca3490788f36763aa6502a2c24 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -1098,7 +1098,7 @@ static int wdm_post_reset(struct usb_interface *intf) rv = recover_from_urb_loss(desc); mutex_unlock(&desc->wlock); mutex_unlock(&desc->rlock); - return 0; + return rv; } static struct usb_driver wdm_driver = { diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 79ae360e7742ff2e91869b808315ac8d5948822a..dcaf82dc87fdff6af1bf47a462eaa80fe40f4295 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -198,9 +198,58 @@ static const unsigned short super_speed_maxpacket_maxes[4] = { [USB_ENDPOINT_XFER_INT] = 1024, }; -static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, - int asnum, struct usb_host_interface *ifp, int num_ep, - unsigned char *buffer, int size) +static bool endpoint_is_duplicate(struct usb_endpoint_descriptor *e1, + struct usb_endpoint_descriptor *e2) +{ + if (e1->bEndpointAddress == e2->bEndpointAddress) + return true; + + if (usb_endpoint_xfer_control(e1) || usb_endpoint_xfer_control(e2)) { + if (usb_endpoint_num(e1) == usb_endpoint_num(e2)) + return true; + } + + return false; +} + +/* + * Check for duplicate endpoint addresses in other interfaces and in the + * altsetting currently being parsed. + */ +static bool config_endpoint_is_duplicate(struct usb_host_config *config, + int inum, int asnum, struct usb_endpoint_descriptor *d) +{ + struct usb_endpoint_descriptor *epd; + struct usb_interface_cache *intfc; + struct usb_host_interface *alt; + int i, j, k; + + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intfc = config->intf_cache[i]; + + for (j = 0; j < intfc->num_altsetting; ++j) { + alt = &intfc->altsetting[j]; + + if (alt->desc.bInterfaceNumber == inum && + alt->desc.bAlternateSetting != asnum) + continue; + + for (k = 0; k < alt->desc.bNumEndpoints; ++k) { + epd = &alt->endpoint[k].desc; + + if (endpoint_is_duplicate(epd, d)) + return true; + } + } + } + + return false; +} + +static int usb_parse_endpoint(struct device *ddev, int cfgno, + struct usb_host_config *config, int inum, int asnum, + struct usb_host_interface *ifp, int num_ep, + unsigned char *buffer, int size) { unsigned char *buffer0 = buffer; struct usb_endpoint_descriptor *d; @@ -237,13 +286,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, goto skip_to_next_endpoint_or_interface_descriptor; /* Check for duplicate endpoint addresses */ - for (i = 0; i < ifp->desc.bNumEndpoints; ++i) { - if (ifp->endpoint[i].desc.bEndpointAddress == - d->bEndpointAddress) { - dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n", - cfgno, inum, asnum, d->bEndpointAddress); - goto skip_to_next_endpoint_or_interface_descriptor; - } + if (config_endpoint_is_duplicate(config, inum, asnum, d)) { + dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n", + cfgno, inum, asnum, d->bEndpointAddress); + goto skip_to_next_endpoint_or_interface_descriptor; } endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints]; @@ -341,12 +387,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, endpoint->desc.wMaxPacketSize = cpu_to_le16(8); } - /* Validate the wMaxPacketSize field */ + /* + * Validate the wMaxPacketSize field. + * Some devices have isochronous endpoints in altsetting 0; + * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0 + * (see the end of section 5.6.3), so don't warn about them. + */ maxp = usb_endpoint_maxp(&endpoint->desc); - if (maxp == 0) { - dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n", + if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) { + dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n", cfgno, inum, asnum, d->bEndpointAddress); - goto skip_to_next_endpoint_or_interface_descriptor; } /* Find the highest legal maxpacket size for this endpoint */ @@ -517,8 +567,8 @@ static int usb_parse_interface(struct device *ddev, int cfgno, if (((struct usb_descriptor_header *) buffer)->bDescriptorType == USB_DT_INTERFACE) break; - retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt, - num_ep, buffer, size); + retval = usb_parse_endpoint(ddev, cfgno, config, inum, asnum, + alt, num_ep, buffer, size); if (retval < 0) return retval; ++n; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 06a8f645106bf0d958959e55be70f4ac89042f7f..059e71d71b6661f63f8fc91471a9638b81bf6c04 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -754,8 +754,15 @@ static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) intf = usb_ifnum_to_if(dev, ifnum); if (!intf) err = -ENOENT; - else + else { + unsigned int old_suppress; + + /* suppress uevents while claiming interface */ + old_suppress = dev_get_uevent_suppress(&intf->dev); + dev_set_uevent_suppress(&intf->dev, 1); err = usb_driver_claim_interface(&usbfs_driver, intf, ps); + dev_set_uevent_suppress(&intf->dev, old_suppress); + } if (err == 0) set_bit(ifnum, &ps->ifclaimed); return err; @@ -775,7 +782,13 @@ static int releaseintf(struct usb_dev_state *ps, unsigned int ifnum) if (!intf) err = -ENOENT; else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { + unsigned int old_suppress; + + /* suppress uevents while releasing interface */ + old_suppress = dev_get_uevent_suppress(&intf->dev); + dev_set_uevent_suppress(&intf->dev, 1); usb_driver_release_interface(&usbfs_driver, intf); + dev_set_uevent_suppress(&intf->dev, old_suppress); err = 0; } return err; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1b307de2d4896fd681bf83846d97beb652cceff1..25379bd6b46475fbde896585569b0e0035c14274 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -965,13 +965,17 @@ int usb_remove_device(struct usb_device *udev) { struct usb_hub *hub; struct usb_interface *intf; + int ret; if (!udev->parent) /* Can't remove a root hub */ return -EINVAL; hub = usb_hub_to_struct_hub(udev->parent); intf = to_usb_interface(hub->intfdev); - usb_autopm_get_interface(intf); + ret = usb_autopm_get_interface(intf); + if (ret < 0) + return ret; + set_bit(udev->portnum, hub->removed_bits); hub_port_logical_disconnect(hub, udev->portnum); usb_autopm_put_interface(intf); @@ -1173,6 +1177,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) * PORT_OVER_CURRENT is not. So check for any of them. */ if (udev || (portstatus & USB_PORT_STAT_CONNECTION) || + (portchange & USB_PORT_STAT_C_CONNECTION) || (portstatus & USB_PORT_STAT_OVERCURRENT) || (portchange & USB_PORT_STAT_C_OVERCURRENT)) set_bit(port1, hub->change_bits); @@ -1197,11 +1202,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) #ifdef CONFIG_PM udev->reset_resume = 1; #endif - /* Don't set the change_bits when the device - * was powered off. - */ - if (test_bit(port1, hub->power_bits)) - set_bit(port1, hub->change_bits); } else { /* The power session is gone; tell hub_wq */ @@ -5655,7 +5655,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) /** * usb_reset_device - warn interface drivers and perform a USB port reset - * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) + * @udev: device to reset (not in NOTATTACHED state) * * Warns all drivers bound to registered interfaces (using their pre_reset * method), performs the port reset, and then lets the drivers know that @@ -5683,8 +5683,7 @@ int usb_reset_device(struct usb_device *udev) struct usb_host_config *config = udev->actconfig; struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); - if (udev->state == USB_STATE_NOTATTACHED || - udev->state == USB_STATE_SUSPENDED) { + if (udev->state == USB_STATE_NOTATTACHED) { dev_dbg(&udev->dev, "device reset not allowed in state %d\n", udev->state); return -EINVAL; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 460c855be0d020bd21d3cc024d0a33d705b0d59d..53c1f6e604b152923bf323317d270b05da6c20dd 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -179,7 +179,10 @@ static int usb_port_runtime_resume(struct device *dev) if (!port_dev->is_superspeed && peer) pm_runtime_get_sync(&peer->dev); - usb_autopm_get_interface(intf); + retval = usb_autopm_get_interface(intf); + if (retval < 0) + return retval; + retval = usb_hub_set_port_power(hdev, hub, port1, true); msleep(hub_power_on_good_delay(hub)); if (udev && !retval) { @@ -232,7 +235,10 @@ static int usb_port_runtime_suspend(struct device *dev) if (usb_port_block_power_off) return -EBUSY; - usb_autopm_get_interface(intf); + retval = usb_autopm_get_interface(intf); + if (retval < 0) + return retval; + retval = usb_hub_set_port_power(hdev, hub, port1, false); usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); if (!port_dev->is_superspeed) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 19e819aa2419acfacaf2a0e60be92bbc640536ca..64c03e871f2d1d70f781acffbff4f7d8ff64c69c 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -86,6 +86,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Logitech PTZ Pro Camera */ { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Logitech Screen Share */ + { USB_DEVICE(0x046d, 0x086c), .driver_info = USB_QUIRK_NO_LPM }, + /* Logitech Quickcam Fusion */ { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -291,6 +294,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* 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 */ }; diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 5133ab9652290f40ecfac9ced36258ad02b43b5d..7b81bcfa19cb04fd2897637e0624e76b18048796 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -40,6 +40,7 @@ void usb_init_urb(struct urb *urb) if (urb) { memset(urb, 0, sizeof(*urb)); kref_init(&urb->kref); + INIT_LIST_HEAD(&urb->urb_list); INIT_LIST_HEAD(&urb->anchor_list); } } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 9e3cfae241a1d51c14b984cdb01771b9209a481e..6b4bba80884669ee622207894cb398f6796dfe3a 100755 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -24,17 +25,6 @@ #include #include "u_os_desc.h" -#define SSUSB_GADGET_VBUS_DRAW 900 /* in mA */ -#define SSUSB_GADGET_VBUS_DRAW_UNITS 8 -#define HSUSB_GADGET_VBUS_DRAW_UNITS 2 - -/* - * Based on enumerated USB speed, draw power with set_config and resume - * HSUSB: 500mA, SSUSB: 900mA - */ -#define USB_VBUS_DRAW(speed)\ - (speed == USB_SPEED_SUPER ?\ - SSUSB_GADGET_VBUS_DRAW : CONFIG_USB_GADGET_VBUS_DRAW) /* disable LPM by default */ static bool disable_l1_for_hs; @@ -568,16 +558,22 @@ EXPORT_SYMBOL(usb_func_ep_queue); static u8 encode_bMaxPower(enum usb_device_speed speed, struct usb_configuration *c) { - unsigned int val = CONFIG_USB_GADGET_VBUS_DRAW; + unsigned val; - switch (speed) { - case USB_SPEED_SUPER: - /* with super-speed report 900mA */ - val = SSUSB_GADGET_VBUS_DRAW; - return (u8)(val / SSUSB_GADGET_VBUS_DRAW_UNITS); - default: - return DIV_ROUND_UP(val, HSUSB_GADGET_VBUS_DRAW_UNITS); - } + if (c->MaxPower) + val = c->MaxPower; + else + val = CONFIG_USB_GADGET_VBUS_DRAW; + if (!val) + return 0; + if (speed < USB_SPEED_SUPER) + return min(val, 500U) / 2; + else + /* + * USB 3.x supports up to 900mA, but since 900 isn't divisible + * by 8 the integral division will effectively cap to 896mA. + */ + return min(val, 900U) / 8; } static int config_buf(struct usb_configuration *config, @@ -896,6 +892,7 @@ static int set_config(struct usb_composite_dev *cdev, struct usb_gadget *gadget = cdev->gadget; struct usb_configuration *c = NULL; int result = -EINVAL; + unsigned power = gadget_is_otg(gadget) ? 8 : 100; int tmp; if (number) { @@ -927,6 +924,7 @@ static int set_config(struct usb_composite_dev *cdev, if (!c) goto done; + place_marker("M - USB Device is enumerated"); usb_gadget_set_state(gadget, USB_STATE_CONFIGURED); cdev->config = c; c->num_ineps_used = 0; @@ -984,8 +982,14 @@ static int set_config(struct usb_composite_dev *cdev, } } + /* when we return, be sure our power usage is valid */ + power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW; + if (gadget->speed < USB_SPEED_SUPER) + power = min(power, 500U); + else + power = min(power, 900U); done: - usb_gadget_vbus_draw(gadget, USB_VBUS_DRAW(gadget->speed)); + usb_gadget_vbus_draw(gadget, power); if (result >= 0 && cdev->delayed_status) result = USB_GADGET_DELAYED_STATUS; return result; @@ -2485,6 +2489,7 @@ void composite_resume(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; + unsigned maxpower; int ret; unsigned long flags; @@ -2492,6 +2497,7 @@ void composite_resume(struct usb_gadget *gadget) * suspend/resume callbacks? */ DBG(cdev, "resume\n"); + place_marker("M - USB device is resumed"); if (cdev->driver->resume) cdev->driver->resume(cdev); @@ -2525,7 +2531,14 @@ void composite_resume(struct usb_gadget *gadget) f->resume(f); } - usb_gadget_vbus_draw(gadget, USB_VBUS_DRAW(gadget->speed)); + maxpower = cdev->config->MaxPower ? + cdev->config->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW; + if (gadget->speed < USB_SPEED_SUPER) + maxpower = min(maxpower, 500U); + else + maxpower = min(maxpower, 900U); + + usb_gadget_vbus_draw(gadget, maxpower); } spin_unlock_irqrestore(&cdev->lock, flags); diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 92127aba8404647d90d00c2a26a31ae09cc60bdc..1a7ebc533fd0e0f833021a1bfdb97c937693ee8f 100755 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -18,8 +18,6 @@ #include #endif -#include - #ifdef CONFIG_USB_CONFIGFS_F_ACC extern int acc_ctrlrequest(struct usb_composite_dev *cdev, const struct usb_ctrlrequest *ctrl); @@ -1460,7 +1458,6 @@ static void android_work(struct work_struct *data) kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, configured); pr_info("%s: sent uevent %s\n", __func__, configured[0]); - place_marker("M - USB enumeration complete"); uevent_sent = true; } diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index 6207b572cee66bf997c1a6349d83de36e1537b51..a3a4e5da90f7c1bdf1fa6ad56a53ae3fec1369ef 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c @@ -56,6 +56,7 @@ struct f_ecm { struct usb_ep *notify; struct usb_request *notify_req; u8 notify_state; + atomic_t notify_count; bool is_open; /* FIXME is_open needs some irq-ish locking @@ -384,7 +385,7 @@ static void ecm_do_notify(struct f_ecm *ecm) int status; /* notification already in flight? */ - if (!req) + if (atomic_read(&ecm->notify_count)) return; event = req->buf; @@ -424,10 +425,10 @@ static void ecm_do_notify(struct f_ecm *ecm) event->bmRequestType = 0xA1; event->wIndex = cpu_to_le16(ecm->ctrl_id); - ecm->notify_req = NULL; + atomic_inc(&ecm->notify_count); status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC); if (status < 0) { - ecm->notify_req = req; + atomic_dec(&ecm->notify_count); DBG(cdev, "notify --> %d\n", status); } } @@ -452,17 +453,19 @@ static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req) switch (req->status) { case 0: /* no fault */ + atomic_dec(&ecm->notify_count); break; case -ECONNRESET: case -ESHUTDOWN: + atomic_set(&ecm->notify_count, 0); ecm->notify_state = ECM_NOTIFY_NONE; break; default: DBG(cdev, "event %02x --> %d\n", event->bNotificationType, req->status); + atomic_dec(&ecm->notify_count); break; } - ecm->notify_req = req; ecm_do_notify(ecm); } @@ -625,8 +628,12 @@ static void ecm_disable(struct usb_function *f) DBG(cdev, "ecm deactivated\n"); - if (ecm->port.in_ep->enabled) + if (ecm->port.in_ep->enabled) { gether_disconnect(&ecm->port); + } else { + ecm->port.in_ep->desc = NULL; + ecm->port.out_ep->desc = NULL; + } usb_ep_disable(ecm->notify); ecm->notify->desc = NULL; @@ -918,6 +925,11 @@ static void ecm_unbind(struct usb_configuration *c, struct usb_function *f) usb_free_all_descriptors(f); + if (atomic_read(&ecm->notify_count)) { + usb_ep_dequeue(ecm->notify, ecm->notify_req); + atomic_set(&ecm->notify_count, 0); + } + kfree(ecm->notify_req->buf); usb_ep_free_request(ecm->notify, ecm->notify_req); opts->bound = false; diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index fa1544be495c3daff8748f6974683413d85e4241..7c6db0d76ef7ae186168bf586e3b03d12ed825f8 100755 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1296,6 +1296,7 @@ static int ffs_aio_cancel(struct kiocb *kiocb) { struct ffs_io_data *io_data = kiocb->private; struct ffs_epfile *epfile = kiocb->ki_filp->private_data; + unsigned long flags; int value; ENTER(); @@ -1303,14 +1304,14 @@ static int ffs_aio_cancel(struct kiocb *kiocb) ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); - spin_lock_irq(&epfile->ffs->eps_lock); + spin_lock_irqsave(&epfile->ffs->eps_lock, flags); if (likely(io_data && io_data->ep && io_data->req)) value = usb_ep_dequeue(io_data->ep, io_data->req); else value = -EINVAL; - spin_unlock_irq(&epfile->ffs->eps_lock); + spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags); ffs_log("exit: value %d", value); diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index f252d323d8c16f9d761f00d2f6c8687a1636dab8..2524146037f000ffae04e041f84799f71bfbe78c 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -73,6 +73,7 @@ static int gsi_alloc_trb_buffer(struct f_gsi *gsi); static void gsi_free_trb_buffer(struct f_gsi *gsi); static struct gsi_ctrl_pkt *gsi_ctrl_pkt_alloc(unsigned int len, gfp_t flags); static void gsi_ctrl_pkt_free(struct gsi_ctrl_pkt *pkt); +static int gsi_ctrl_send_cpkt_tomodem(struct f_gsi *gsi, void *buf, size_t len); static inline bool is_ext_prot_ether(int prot_id) { @@ -740,6 +741,12 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) ipa_out_channel_out_params.db_reg_phs_addr_msb; } + /* Send 0 byte packet to QTI only if DTR linetstate is HIGH already */ + if (gsi->rmnet_dtr_status && + (gsi->prot_id == USB_PROT_RMNET_IPA || + gsi->prot_id == USB_PROT_RMNET_V2X_IPA)) + gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0); + return ret; end_xfer_ep_out: @@ -2220,6 +2227,14 @@ gsi_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) queue_work(gsi->c_port.uevent_wq, &gsi->c_port.uevent_work); + /* Send 0 byte packet to QTI only if IPA connect is done */ + if (gsi->rmnet_dtr_status) { + if (gsi->prot_id == USB_PROT_RMNET_ETHER) + gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0); + else if (gsi->d_port.in_channel_handle != -EINVAL) + gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0); + } + value = 0; break; case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) @@ -2624,10 +2639,7 @@ static int gsi_set_alt(struct usb_function *f, unsigned int intf, if (gsi->prot_id == USB_PROT_DIAG_IPA || gsi->prot_id == USB_PROT_DPL_ETHER || gsi->prot_id == USB_PROT_GPS_CTRL || - gsi->prot_id == USB_PROT_MBIM_IPA || - gsi->prot_id == USB_PROT_RMNET_IPA || - gsi->prot_id == USB_PROT_RMNET_V2X_IPA || - gsi->prot_id == USB_PROT_RMNET_ETHER) + gsi->prot_id == USB_PROT_MBIM_IPA) gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0); if (gsi->c_port.uevent_wq) diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 373c31a7c703cfd387d7bb9ac9947f881414c571..f48b08ef31a2191f57248382dc1e0226daf9e6fa 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -57,6 +57,7 @@ struct f_ncm { struct usb_ep *notify; struct usb_request *notify_req; u8 notify_state; + atomic_t notify_count; bool is_open; const struct ndp_parser_opts *parser_opts; @@ -551,7 +552,7 @@ static void ncm_do_notify(struct f_ncm *ncm) int status; /* notification already in flight? */ - if (!req) + if (atomic_read(&ncm->notify_count)) return; event = req->buf; @@ -591,7 +592,8 @@ static void ncm_do_notify(struct f_ncm *ncm) event->bmRequestType = 0xA1; event->wIndex = cpu_to_le16(ncm->ctrl_id); - ncm->notify_req = NULL; + atomic_inc(&ncm->notify_count); + /* * In double buffering if there is a space in FIFO, * completion callback can be called right after the call, @@ -601,7 +603,7 @@ static void ncm_do_notify(struct f_ncm *ncm) status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC); spin_lock(&ncm->lock); if (status < 0) { - ncm->notify_req = req; + atomic_dec(&ncm->notify_count); DBG(cdev, "notify --> %d\n", status); } } @@ -636,17 +638,19 @@ static void ncm_notify_complete(struct usb_ep *ep, struct usb_request *req) case 0: VDBG(cdev, "Notification %02x sent\n", event->bNotificationType); + atomic_dec(&ncm->notify_count); break; case -ECONNRESET: case -ESHUTDOWN: + atomic_set(&ncm->notify_count, 0); ncm->notify_state = NCM_NOTIFY_NONE; break; default: DBG(cdev, "event %02x --> %d\n", event->bNotificationType, req->status); + atomic_dec(&ncm->notify_count); break; } - ncm->notify_req = req; ncm_do_notify(ncm); spin_unlock(&ncm->lock); } @@ -1716,6 +1720,11 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) ncm_string_defs[0].id = 0; usb_free_all_descriptors(f); + if (atomic_read(&ncm->notify_count)) { + usb_ep_dequeue(ncm->notify, ncm->notify_req); + atomic_set(&ncm->notify_count, 0); + } + kfree(ncm->notify_req->buf); usb_ep_free_request(ncm->notify, ncm->notify_req); diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index 24bc2d4d96b26aa916760295705de042eda3fc18..7d6e8ea4447968532012be5fd9535e578ba27f06 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -710,6 +710,7 @@ static void rndis_disable(struct usb_function *f) gether_disconnect(&rndis->port); usb_ep_disable(rndis->notify); + rndis->notify->desc = NULL; } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 64909f37f4c51bbb132f8c428e764dcb2f2800e5..1c40ae82bdabf1f719b91cc48813e94a84475369 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -720,8 +720,10 @@ static int gs_start_io(struct gs_port *port) port->n_read = 0; started = gs_start_rx(port); - /* unblock any pending writes into our circular buffer */ if (started) { + gs_start_tx(port); + /* Unblock any pending writes into our circular buffer, in case + * we didn't in gs_start_tx() */ tty_wakeup(port->port.tty); } else { gs_free_requests(ep, head, &port->read_allocated); @@ -1400,8 +1402,10 @@ int gserial_alloc_line(unsigned char *line_num) __func__, port_num, PTR_ERR(tty_dev)); ret = PTR_ERR(tty_dev); + mutex_lock(&ports[port_num].lock); port = ports[port_num].port; ports[port_num].port = NULL; + mutex_unlock(&ports[port_num].lock); gserial_free_port(port); goto err; } diff --git a/drivers/usb/gadget/legacy/cdc2.c b/drivers/usb/gadget/legacy/cdc2.c index 51c08682de846a1dbb264dad9aa5bfeaba99a759..5ee25beb52f0d38c0bbe183bb3e3540fc06032d5 100644 --- a/drivers/usb/gadget/legacy/cdc2.c +++ b/drivers/usb/gadget/legacy/cdc2.c @@ -229,7 +229,7 @@ static struct usb_composite_driver cdc_driver = { .name = "g_cdc", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = cdc_bind, .unbind = cdc_unbind, }; diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c index 6da7316f8e87d73d7edb8a8215ac886db381c9bc..54ee4e31645b92bbc2cf94167542eb512c26c967 100644 --- a/drivers/usb/gadget/legacy/g_ffs.c +++ b/drivers/usb/gadget/legacy/g_ffs.c @@ -153,7 +153,7 @@ static struct usb_composite_driver gfs_driver = { .name = DRIVER_NAME, .dev = &gfs_dev_desc, .strings = gfs_dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = gfs_bind, .unbind = gfs_unbind, }; diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c index a70a406580eae509839f58c6c91447402f51601d..3b7fc5c7e9c3a97df557f022b4bb79f277daaaa6 100644 --- a/drivers/usb/gadget/legacy/multi.c +++ b/drivers/usb/gadget/legacy/multi.c @@ -486,7 +486,7 @@ static struct usb_composite_driver multi_driver = { .name = "g_multi", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = multi_bind, .unbind = multi_unbind, .needs_serial = 1, diff --git a/drivers/usb/gadget/legacy/ncm.c b/drivers/usb/gadget/legacy/ncm.c index 0aba68253e3d61d544b6180baec6c0b0b7b1336f..2fb4a847dd5262a9fe3c0c2a291abc3933faa6b4 100644 --- a/drivers/usb/gadget/legacy/ncm.c +++ b/drivers/usb/gadget/legacy/ncm.c @@ -203,7 +203,7 @@ static struct usb_composite_driver ncm_driver = { .name = "g_ncm", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = gncm_bind, .unbind = gncm_unbind, }; diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index 39b7136d31d9c7b5be3263bb2ed2070dd3b2f537..9e246d2e55ca3cf563590c030650d2fdf59a0aa9 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c @@ -2200,8 +2200,6 @@ static int gr_probe(struct platform_device *pdev) return -ENOMEM; } - spin_lock(&dev->lock); - /* Inside lock so that no gadget can use this udc until probe is done */ retval = usb_add_gadget_udc(dev->dev, &dev->gadget); if (retval) { @@ -2210,15 +2208,21 @@ static int gr_probe(struct platform_device *pdev) } dev->added = 1; + spin_lock(&dev->lock); + retval = gr_udc_init(dev); - if (retval) + if (retval) { + spin_unlock(&dev->lock); goto out; - - gr_dfs_create(dev); + } /* Clear all interrupt enables that might be left on since last boot */ gr_disable_interrupts_and_pullup(dev); + spin_unlock(&dev->lock); + + gr_dfs_create(dev); + retval = gr_request_irq(dev, dev->irq); if (retval) { dev_err(dev->dev, "Failed to request irq %d\n", dev->irq); @@ -2247,8 +2251,6 @@ static int gr_probe(struct platform_device *pdev) dev_info(dev->dev, "regs: %p, irq %d\n", dev->regs, dev->irq); out: - spin_unlock(&dev->lock); - if (retval) gr_remove(pdev); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 484d9d7a0eb421fe66b7aeff43af52d58f3a2164..3144fd96ad8202b87b97c1a9e10b7c9d0712d589 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -40,6 +40,10 @@ /*-------------------------------------------------------------------------*/ +/* PID Codes that are used here, from EHCI specification, Table 3-16. */ +#define PID_CODE_IN 1 +#define PID_CODE_SETUP 2 + /* fill a qtd, returning how much of the buffer we were able to queue up */ static int @@ -203,7 +207,7 @@ static int qtd_copy_status ( int status = -EINPROGRESS; /* count IN/OUT bytes, not SETUP (even short packets) */ - if (likely (QTD_PID (token) != 2)) + if (likely(QTD_PID(token) != PID_CODE_SETUP)) urb->actual_length += length - QTD_LENGTH (token); /* don't modify error codes */ @@ -219,6 +223,13 @@ static int qtd_copy_status ( if (token & QTD_STS_BABBLE) { /* FIXME "must" disable babbling device's port too */ status = -EOVERFLOW; + /* + * When MMF is active and PID Code is IN, queue is halted. + * EHCI Specification, Table 4-13. + */ + } else if ((token & QTD_STS_MMF) && + (QTD_PID(token) == PID_CODE_IN)) { + status = -EPROTO; /* CERR nonzero + halt --> stall */ } else if (QTD_CERR(token)) { status = -EPIPE; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 8679875026484d8a5e5d45a830d58b7f1a811d70..d3d65f037ea1dcbd2319eab7071071a9c8c445d3 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -732,7 +732,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, struct xhci_bus_state *bus_state, __le32 __iomem **port_array, u16 wIndex, u32 raw_port_status, - unsigned long flags) + unsigned long *flags) __releases(&xhci->lock) __acquires(&xhci->lock) { @@ -764,6 +764,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, status |= USB_PORT_STAT_C_BH_RESET << 16; if ((raw_port_status & PORT_CEC)) status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; + + /* USB3 remote wake resume signaling completed */ + if (bus_state->port_remote_wakeup & (1 << wIndex) && + (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME && + (raw_port_status & PORT_PLS_MASK) != XDEV_RECOVERY) { + bus_state->port_remote_wakeup &= ~(1 << wIndex); + usb_hcd_end_port_resume(&hcd->self, wIndex); + } } if (hcd->speed < HCD_USB3) { @@ -814,12 +822,12 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, xhci_set_link_state(xhci, port_array, wIndex, XDEV_U0); - spin_unlock_irqrestore(&xhci->lock, flags); + spin_unlock_irqrestore(&xhci->lock, *flags); time_left = wait_for_completion_timeout( &bus_state->rexit_done[wIndex], msecs_to_jiffies( XHCI_MAX_REXIT_TIMEOUT_MS)); - spin_lock_irqsave(&xhci->lock, flags); + spin_lock_irqsave(&xhci->lock, *flags); if (time_left) { slot_id = xhci_find_slot_id_by_port(hcd, @@ -1112,7 +1120,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; } status = xhci_get_port_status(hcd, bus_state, port_array, - wIndex, temp, flags); + wIndex, temp, &flags); if (status == 0xffffffff) goto error; @@ -1132,7 +1140,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } port_li = readl(port_array[wIndex] + PORTLI); status = xhci_get_ext_port_status(temp, port_li); - put_unaligned_le32(cpu_to_le32(status), &buf[4]); + put_unaligned_le32(status, &buf[4]); } break; case SetPortFeature: diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6b71b45a5edc9546e52ed4d102089970c3ea4aee..ea9c2e5f7b3c40d6c117d27dafabb1049b91aa0c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1532,13 +1532,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* Allow 3 retries for everything but isoc, set CErr = 3 */ if (!usb_endpoint_xfer_isoc(&ep->desc)) err_count = 3; - /* Some devices get this wrong */ - if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH) - max_packet = 512; - if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_FULL - && max_packet < 8) - max_packet = 8; + /* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */ + if (usb_endpoint_xfer_bulk(&ep->desc)) { + if (udev->speed == USB_SPEED_HIGH) + max_packet = 512; + if (udev->speed == USB_SPEED_FULL) { + max_packet = rounddown_pow_of_two(max_packet); + max_packet = clamp_val(max_packet, 8, 64); + } + } /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */ if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) @@ -2071,10 +2074,14 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) kfree(xhci->port_array); kfree(xhci->rh_bw); kfree(xhci->ext_caps); + kfree(xhci->usb2_rhub.psi); + kfree(xhci->usb3_rhub.psi); xhci->usb2_ports = NULL; xhci->usb3_ports = NULL; xhci->port_array = NULL; + xhci->usb2_rhub.psi = NULL; + xhci->usb3_rhub.psi = NULL; xhci->rh_bw = NULL; xhci->ext_caps = NULL; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 3e6c4372848ccbfd816a85271c0512700142a221..adf21ac76e34789723e231901a6bd6a1bfcc6a57 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -53,6 +53,7 @@ #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8 #define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 #define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 +#define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 @@ -170,7 +171,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) { + pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_CML_XHCI)) { xhci->quirks |= XHCI_PME_STUCK_QUIRK; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && @@ -470,6 +472,18 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) retval = xhci_resume(xhci, hibernated); return retval; } + +static void xhci_pci_shutdown(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + + xhci_shutdown(hcd); + + /* Yet another workaround for spurious wakeups at shutdown with HSW */ + if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) + pci_set_power_state(pdev, PCI_D3hot); +} #endif /* CONFIG_PM */ /*-------------------------------------------------------------------------*/ @@ -507,6 +521,7 @@ static int __init xhci_pci_init(void) #ifdef CONFIG_PM xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend; xhci_pci_hc_driver.pci_resume = xhci_pci_resume; + xhci_pci_hc_driver.shutdown = xhci_pci_shutdown; #endif return pci_register_driver(&xhci_pci_driver); } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fd2bcff0ec5791a599632376e318dda6d87e8ce6..b5cf5bd1b6d8dc59c9d9ad4dc0fd0e83676a329c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1599,9 +1599,6 @@ static void handle_port_status(struct xhci_hcd *xhci, usb_hcd_resume_root_hub(hcd); } - if (hcd->speed >= HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE) - bus_state->port_remote_wakeup &= ~(1 << faked_port_index); - if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { xhci_dbg(xhci, "port resume event for port %d\n", port_id); @@ -1620,6 +1617,7 @@ static void handle_port_status(struct xhci_hcd *xhci, bus_state->port_remote_wakeup |= 1 << faked_port_index; xhci_test_and_clear_bit(xhci, port_array, faked_port_index, PORT_PLC); + usb_hcd_start_port_resume(&hcd->self, faked_port_index); xhci_set_link_state(xhci, port_array, faked_port_index, XDEV_U0); /* Need to wait until the next link state change @@ -1657,8 +1655,6 @@ static void handle_port_status(struct xhci_hcd *xhci, if (slot_id && xhci->devs[slot_id]) xhci_ring_device(xhci, slot_id); if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { - bus_state->port_remote_wakeup &= - ~(1 << faked_port_index); xhci_test_and_clear_bit(xhci, port_array, faked_port_index, PORT_PLC); usb_wakeup_notification(hcd->self.root_hub, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c old mode 100644 new mode 100755 index 919e0b85ba621dda996aabf55ba1ccd6ffbd7e05..0fcc23bda949e350bdde3a8e207decb4c93efc0f --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -801,11 +801,8 @@ void xhci_shutdown(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_shutdown completed - status = %x", readl(&xhci->op_regs->status)); - - /* Yet another workaround for spurious wakeups at shutdown with HSW */ - if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) - pci_set_power_state(to_pci_dev(hcd->self.sysdev), PCI_D3hot); } +EXPORT_SYMBOL_GPL(xhci_shutdown); #ifdef CONFIG_PM static void xhci_save_registers(struct xhci_hcd *xhci) @@ -976,7 +973,7 @@ static bool xhci_pending_portevent(struct xhci_hcd *xhci) int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) { int rc = 0; - unsigned int delay = XHCI_MAX_HALT_USEC; + unsigned int delay = XHCI_MAX_HALT_USEC * 2; struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 016f7a1099c9402a46b3ef2862b6527ba6a59382..6c0cfaa0c6d4c06afd943cebc571332977f7f84d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -316,6 +316,7 @@ struct xhci_op_regs { #define XDEV_U3 (0x3 << 5) #define XDEV_INACTIVE (0x6 << 5) #define XDEV_POLLING (0x7 << 5) +#define XDEV_RECOVERY (0x8 << 5) #define XDEV_COMP_MODE (0xa << 5) #define XDEV_RESUME (0xf << 5) /* true: port has power (see HCC_PPC) */ @@ -1880,6 +1881,7 @@ int xhci_run(struct usb_hcd *hcd); void xhci_stop(struct usb_hcd *hcd); void xhci_shutdown(struct usb_hcd *hcd); int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); +void xhci_shutdown(struct usb_hcd *hcd); void xhci_init_driver(struct hc_driver *drv, const struct xhci_driver_overrides *over); diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index f0c071da68d196b7ac9cadafa327cd28d28a9f9b..7fb0590187d409a0b8405a9b6550756f226dfa14 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -685,7 +685,7 @@ static int adu_probe(struct usb_interface *interface, init_waitqueue_head(&dev->read_wait); init_waitqueue_head(&dev->write_wait); - iface_desc = &interface->altsetting[0]; + iface_desc = &interface->cur_altsetting[0]; /* set up the endpoint information */ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 9a67ae39185b8963caadd66e2edfb5117f5c4f17..9cf8a9b163361200f4522f3fe271db848dc7bd9a 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -342,7 +342,7 @@ static int idmouse_probe(struct usb_interface *interface, int result; /* check if we have gotten the data or the hid interface */ - iface_desc = &interface->altsetting[0]; + iface_desc = interface->cur_altsetting; if (iface_desc->desc.bInterfaceClass != 0x0A) return -ENODEV; diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 80b37d214bebf0ba896ad2de9ca2c4d86b4a3132..bd1a8dc285f5fdcec81c029f354ba2e758d531be 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1036,12 +1036,18 @@ static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg mutex_lock(&rp->fetch_lock); spin_lock_irqsave(&rp->b_lock, flags); - mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE); - kfree(rp->b_vec); - rp->b_vec = vec; - rp->b_size = size; - rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0; - rp->cnt_lost = 0; + if (rp->mmap_active) { + mon_free_buff(vec, size/CHUNK_SIZE); + kfree(vec); + ret = -EBUSY; + } else { + mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE); + kfree(rp->b_vec); + rp->b_vec = vec; + rp->b_size = size; + rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0; + rp->cnt_lost = 0; + } spin_unlock_irqrestore(&rp->b_lock, flags); mutex_unlock(&rp->fetch_lock); } @@ -1213,13 +1219,21 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait) static void mon_bin_vma_open(struct vm_area_struct *vma) { struct mon_reader_bin *rp = vma->vm_private_data; + unsigned long flags; + + spin_lock_irqsave(&rp->b_lock, flags); rp->mmap_active++; + spin_unlock_irqrestore(&rp->b_lock, flags); } static void mon_bin_vma_close(struct vm_area_struct *vma) { + unsigned long flags; + struct mon_reader_bin *rp = vma->vm_private_data; + spin_lock_irqsave(&rp->b_lock, flags); rp->mmap_active--; + spin_unlock_irqrestore(&rp->b_lock, flags); } /* @@ -1231,16 +1245,12 @@ static int mon_bin_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) unsigned long offset, chunk_idx; struct page *pageptr; - mutex_lock(&rp->fetch_lock); offset = vmf->pgoff << PAGE_SHIFT; - if (offset >= rp->b_size) { - mutex_unlock(&rp->fetch_lock); + if (offset >= rp->b_size) return VM_FAULT_SIGBUS; - } chunk_idx = offset / CHUNK_SIZE; pageptr = rp->b_vec[chunk_idx].pg; get_page(pageptr); - mutex_unlock(&rp->fetch_lock); vmf->page = pageptr; return 0; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 579aa9accafc65f73581d4cc0c93e4886205196f..c232229162e0c239c83b8b19e2b86f41c2f093b4 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1832,6 +1832,9 @@ static const struct attribute_group musb_attr_group = { #define MUSB_QUIRK_B_INVALID_VBUS_91 (MUSB_DEVCTL_BDEVICE | \ (2 << MUSB_DEVCTL_VBUS_SHIFT) | \ MUSB_DEVCTL_SESSION) +#define MUSB_QUIRK_B_DISCONNECT_99 (MUSB_DEVCTL_BDEVICE | \ + (3 << MUSB_DEVCTL_VBUS_SHIFT) | \ + MUSB_DEVCTL_SESSION) #define MUSB_QUIRK_A_DISCONNECT_19 ((3 << MUSB_DEVCTL_VBUS_SHIFT) | \ MUSB_DEVCTL_SESSION) @@ -1854,6 +1857,11 @@ static void musb_pm_runtime_check_session(struct musb *musb) s = MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV | 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; case MUSB_QUIRK_B_INVALID_VBUS_91: if (musb->quirk_retries--) { musb_dbg(musb, @@ -2309,6 +2317,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_platform_disable(musb); musb_generic_disable(musb); + /* MUSB_POWER_SOFTCONN might be already set, JZ4740 does this. */ + musb_writeb(musb->mregs, MUSB_POWER, 0); + /* Init IRQ workqueue before request_irq */ INIT_DELAYED_WORK(&musb->irq_work, musb_irq_work); INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 512108e22d2bd8afe9f96642dfeac16c5115df7a..1dc35ab31275324391ab53592f9699fa1f3dfa10 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -399,7 +399,7 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb, controller->controller.channel_abort = dma_channel_abort; if (request_irq(irq, dma_controller_irq, 0, - dev_name(musb->controller), &controller->controller)) { + dev_name(musb->controller), controller)) { dev_err(dev, "request_irq %d failed!\n", irq); musb_dma_controller_destroy(&controller->controller); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e8be8e39ab8fbd2d5b03a6fdc98dc3d78b00512e..457ad33f4caa802b7719bd791e6d44ddbdbd6907 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -388,8 +388,6 @@ static const struct musb_platform_ops omap2430_ops = { .init = omap2430_musb_init, .exit = omap2430_musb_exit, - .set_vbus = omap2430_musb_set_vbus, - .enable = omap2430_musb_enable, .disable = omap2430_musb_disable, diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index fc2f0654846e28893caff56bed1b1e955db329e4..409ddc5149a7846d98bc17af9c4eefc487bab28a 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -27,7 +27,7 @@ config AB8500_USB in host mode, low speed. config FSL_USB2_OTG - bool "Freescale USB OTG Transceiver Driver" + tristate "Freescale USB OTG Transceiver Driver" depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM=y && PM depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y' select USB_PHY diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index a72e8d670adc846b225d5cfd6fc27b43f5bc9bea..cf0b67433ac951669413a44068e4cf3610b9584c 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -422,7 +422,7 @@ static int twl6030_usb_remove(struct platform_device *pdev) { struct twl6030_usb *twl = platform_get_drvdata(pdev); - cancel_delayed_work(&twl->get_status_work); + cancel_delayed_work_sync(&twl->get_status_work); twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index b8620aa6b72e603abeeb85216438d6b0077abb30..8424c165f732aeb67748753375d43c8c16981c74 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -163,11 +163,12 @@ struct usbhs_priv; #define VBSTS (1 << 7) /* VBUS_0 and VBUSIN_0 Input Status */ #define VALID (1 << 3) /* USB Request Receive */ -#define DVSQ_MASK (0x3 << 4) /* Device State */ +#define DVSQ_MASK (0x7 << 4) /* Device State */ #define POWER_STATE (0 << 4) #define DEFAULT_STATE (1 << 4) #define ADDRESS_STATE (2 << 4) #define CONFIGURATION_STATE (3 << 4) +#define SUSPENDED_STATE (4 << 4) #define CTSQ_MASK (0x7) /* Control Transfer Stage */ #define IDLE_SETUP_STAGE 0 /* Idle stage or setup stage */ diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 6898ca1ef98c097a8e8f2b98fbf080797bb041bd..b0397bcfe1f615ee050c7eed0ab13848dfd533e2 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -465,12 +465,18 @@ static int usbhsg_irq_dev_state(struct usbhs_priv *priv, { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct device *dev = usbhsg_gpriv_to_dev(gpriv); + int state = usbhs_status_get_device_state(irq_state); gpriv->gadget.speed = usbhs_bus_get_speed(priv); - dev_dbg(dev, "state = %x : speed : %d\n", - usbhs_status_get_device_state(irq_state), - gpriv->gadget.speed); + dev_dbg(dev, "state = %x : speed : %d\n", state, gpriv->gadget.speed); + + if (gpriv->gadget.speed != USB_SPEED_UNKNOWN && + (state & SUSPENDED_STATE)) { + if (gpriv->driver && gpriv->driver->suspend) + gpriv->driver->suspend(&gpriv->gadget); + usb_gadget_set_state(&gpriv->gadget, USB_STATE_SUSPENDED); + } return 0; } diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 9a2c0c76d11b3f5d7427ab39ad570ba1d64b7275..0291dc7cd284d12ef7e119350ee5d16d2bd8fb2d 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -555,9 +555,13 @@ static int ch341_tiocmget(struct tty_struct *tty) static int ch341_reset_resume(struct usb_serial *serial) { struct usb_serial_port *port = serial->port[0]; - struct ch341_private *priv = usb_get_serial_port_data(port); + struct ch341_private *priv; int ret; + priv = usb_get_serial_port_data(port); + if (!priv) + return 0; + /* reconfigure ch341 serial port after bus-reset */ ch341_configure(serial->dev, priv); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index de61271f2ba3a16279cca85251cfbce61ccd398e..191588006e0e3e834c339171f93bd968ce83bddf 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -572,6 +572,7 @@ static void edge_interrupt_callback(struct urb *urb) struct usb_serial_port *port; unsigned char *data = urb->transfer_buffer; int length = urb->actual_length; + unsigned long flags; int bytes_avail; int position; int txCredits; @@ -603,7 +604,7 @@ static void edge_interrupt_callback(struct urb *urb) if (length > 1) { bytes_avail = data[0] | (data[1] << 8); if (bytes_avail) { - spin_lock(&edge_serial->es_lock); + spin_lock_irqsave(&edge_serial->es_lock, flags); edge_serial->rxBytesAvail += bytes_avail; dev_dbg(dev, "%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d\n", @@ -626,7 +627,8 @@ static void edge_interrupt_callback(struct urb *urb) edge_serial->read_in_progress = false; } } - spin_unlock(&edge_serial->es_lock); + spin_unlock_irqrestore(&edge_serial->es_lock, + flags); } } /* grab the txcredits for the ports if available */ @@ -638,10 +640,12 @@ static void edge_interrupt_callback(struct urb *urb) if (txCredits) { port = edge_serial->serial->port[portNumber]; edge_port = usb_get_serial_port_data(port); - if (edge_port->open) { - spin_lock(&edge_port->ep_lock); + if (edge_port && edge_port->open) { + spin_lock_irqsave(&edge_port->ep_lock, + flags); edge_port->txCredits += txCredits; - spin_unlock(&edge_port->ep_lock); + spin_unlock_irqrestore(&edge_port->ep_lock, + flags); dev_dbg(dev, "%s - txcredits for port%d = %d\n", __func__, portNumber, edge_port->txCredits); @@ -682,6 +686,7 @@ static void edge_bulk_in_callback(struct urb *urb) int retval; __u16 raw_data_length; int status = urb->status; + unsigned long flags; if (status) { dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n", @@ -701,7 +706,7 @@ static void edge_bulk_in_callback(struct urb *urb) usb_serial_debug_data(dev, __func__, raw_data_length, data); - spin_lock(&edge_serial->es_lock); + spin_lock_irqsave(&edge_serial->es_lock, flags); /* decrement our rxBytes available by the number that we just got */ edge_serial->rxBytesAvail -= raw_data_length; @@ -725,7 +730,7 @@ static void edge_bulk_in_callback(struct urb *urb) edge_serial->read_in_progress = false; } - spin_unlock(&edge_serial->es_lock); + spin_unlock_irqrestore(&edge_serial->es_lock, flags); } @@ -1662,7 +1667,8 @@ static void edge_break(struct tty_struct *tty, int break_state) static void process_rcvd_data(struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength) { - struct device *dev = &edge_serial->serial->dev->dev; + struct usb_serial *serial = edge_serial->serial; + struct device *dev = &serial->dev->dev; struct usb_serial_port *port; struct edgeport_port *edge_port; __u16 lastBufferLength; @@ -1767,11 +1773,10 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, /* spit this data back into the tty driver if this port is open */ - if (rxLen) { - port = edge_serial->serial->port[ - edge_serial->rxPort]; + if (rxLen && edge_serial->rxPort < serial->num_ports) { + port = serial->port[edge_serial->rxPort]; edge_port = usb_get_serial_port_data(port); - if (edge_port->open) { + if (edge_port && edge_port->open) { dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n", __func__, rxLen, edge_serial->rxPort); @@ -1779,8 +1784,8 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, rxLen); edge_port->port->icount.rx += rxLen; } - buffer += rxLen; } + buffer += rxLen; break; case EXPECT_HDR3: /* Expect 3rd byte of status header */ @@ -1815,6 +1820,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, __u8 code = edge_serial->rxStatusCode; /* switch the port pointer to the one being currently talked about */ + if (edge_serial->rxPort >= edge_serial->serial->num_ports) + return; port = edge_serial->serial->port[edge_serial->rxPort]; edge_port = usb_get_serial_port_data(port); if (edge_port == NULL) { @@ -2852,16 +2859,18 @@ static int edge_startup(struct usb_serial *serial) response = 0; if (edge_serial->is_epic) { + struct usb_host_interface *alt; + + alt = serial->interface->cur_altsetting; + /* EPIC thing, set up our interrupt polling now and our read * urb, so that the device knows it really is connected. */ interrupt_in_found = bulk_in_found = bulk_out_found = false; - for (i = 0; i < serial->interface->altsetting[0] - .desc.bNumEndpoints; ++i) { + for (i = 0; i < alt->desc.bNumEndpoints; ++i) { struct usb_endpoint_descriptor *endpoint; int buffer_size; - endpoint = &serial->interface->altsetting[0]. - endpoint[i].desc; + endpoint = &alt->endpoint[i].desc; buffer_size = usb_endpoint_maxp(endpoint); if (!interrupt_in_found && (usb_endpoint_is_int_in(endpoint))) { diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 73956d48a0c57bb5566fb0c1b47a581e438bb4a1..1347c77facd0f734e2e2a644acef660c7c637ade 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -49,9 +49,10 @@ static int buffer_size; static int xbof = -1; static int ir_startup (struct usb_serial *serial); -static int ir_open(struct tty_struct *tty, struct usb_serial_port *port); -static int ir_prepare_write_buffer(struct usb_serial_port *port, - void *dest, size_t size); +static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static int ir_write_room(struct tty_struct *tty); +static void ir_write_bulk_callback(struct urb *urb); static void ir_process_read_urb(struct urb *urb); static void ir_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); @@ -81,8 +82,9 @@ static struct usb_serial_driver ir_device = { .num_ports = 1, .set_termios = ir_set_termios, .attach = ir_startup, - .open = ir_open, - .prepare_write_buffer = ir_prepare_write_buffer, + .write = ir_write, + .write_room = ir_write_room, + .write_bulk_callback = ir_write_bulk_callback, .process_read_urb = ir_process_read_urb, }; @@ -198,6 +200,9 @@ static int ir_startup(struct usb_serial *serial) { struct usb_irda_cs_descriptor *irda_desc; + if (serial->num_bulk_in < 1 || serial->num_bulk_out < 1) + return -ENODEV; + irda_desc = irda_usb_find_class_desc(serial, 0); if (!irda_desc) { dev_err(&serial->dev->dev, @@ -252,35 +257,102 @@ static int ir_startup(struct usb_serial *serial) return 0; } -static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) +static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { - int i; + struct urb *urb = NULL; + unsigned long flags; + int ret; - for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) - port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET; + if (port->bulk_out_size == 0) + return -EINVAL; - /* Start reading from the device */ - return usb_serial_generic_open(tty, port); -} + if (count == 0) + return 0; -static int ir_prepare_write_buffer(struct usb_serial_port *port, - void *dest, size_t size) -{ - unsigned char *buf = dest; - int count; + count = min(count, port->bulk_out_size - 1); + + spin_lock_irqsave(&port->lock, flags); + if (__test_and_clear_bit(0, &port->write_urbs_free)) { + urb = port->write_urbs[0]; + port->tx_bytes += count; + } + spin_unlock_irqrestore(&port->lock, flags); + + if (!urb) + return 0; /* * The first byte of the packet we send to the device contains an - * inbound header which indicates an additional number of BOFs and + * outbound header which indicates an additional number of BOFs and * a baud rate change. * * See section 5.4.2.2 of the USB IrDA spec. */ - *buf = ir_xbof | ir_baud; + *(u8 *)urb->transfer_buffer = ir_xbof | ir_baud; + + memcpy(urb->transfer_buffer + 1, buf, count); + + urb->transfer_buffer_length = count + 1; + urb->transfer_flags = URB_ZERO_PACKET; + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + dev_err(&port->dev, "failed to submit write urb: %d\n", ret); + + spin_lock_irqsave(&port->lock, flags); + __set_bit(0, &port->write_urbs_free); + port->tx_bytes -= count; + spin_unlock_irqrestore(&port->lock, flags); + + return ret; + } + + return count; +} + +static void ir_write_bulk_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + int status = urb->status; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + __set_bit(0, &port->write_urbs_free); + port->tx_bytes -= urb->transfer_buffer_length - 1; + spin_unlock_irqrestore(&port->lock, flags); + + switch (status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + dev_dbg(&port->dev, "write urb stopped: %d\n", status); + return; + case -EPIPE: + dev_err(&port->dev, "write urb stopped: %d\n", status); + return; + default: + dev_err(&port->dev, "nonzero write-urb status: %d\n", status); + break; + } + + usb_serial_port_softint(port); +} + +static int ir_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + int count = 0; + + if (port->bulk_out_size == 0) + return 0; + + if (test_bit(0, &port->write_urbs_free)) + count = port->bulk_out_size - 1; - count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1, - &port->lock); - return count + 1; + return count; } static void ir_process_read_urb(struct urb *urb) @@ -333,34 +405,34 @@ static void ir_set_termios(struct tty_struct *tty, switch (baud) { case 2400: - ir_baud = USB_IRDA_BR_2400; + ir_baud = USB_IRDA_LS_2400; break; case 9600: - ir_baud = USB_IRDA_BR_9600; + ir_baud = USB_IRDA_LS_9600; break; case 19200: - ir_baud = USB_IRDA_BR_19200; + ir_baud = USB_IRDA_LS_19200; break; case 38400: - ir_baud = USB_IRDA_BR_38400; + ir_baud = USB_IRDA_LS_38400; break; case 57600: - ir_baud = USB_IRDA_BR_57600; + ir_baud = USB_IRDA_LS_57600; break; case 115200: - ir_baud = USB_IRDA_BR_115200; + ir_baud = USB_IRDA_LS_115200; break; case 576000: - ir_baud = USB_IRDA_BR_576000; + ir_baud = USB_IRDA_LS_576000; break; case 1152000: - ir_baud = USB_IRDA_BR_1152000; + ir_baud = USB_IRDA_LS_1152000; break; case 4000000: - ir_baud = USB_IRDA_BR_4000000; + ir_baud = USB_IRDA_LS_4000000; break; default: - ir_baud = USB_IRDA_BR_9600; + ir_baud = USB_IRDA_LS_9600; baud = 9600; } diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 185ef1d8c6cdef360fde6f11e9b3d89da21b5b6f..e08755e9b6129e42761a9a28b8fb672319f9e8cf 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -567,6 +567,8 @@ static void usa49_glocont_callback(struct urb *urb) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; p_priv = usb_get_serial_port_data(port); + if (!p_priv) + continue; if (p_priv->resend_cont) { dev_dbg(&port->dev, "%s - sending setup\n", __func__); @@ -968,6 +970,8 @@ static void usa67_glocont_callback(struct urb *urb) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; p_priv = usb_get_serial_port_data(port); + if (!p_priv) + continue; if (p_priv->resend_cont) { dev_dbg(&port->dev, "%s - sending setup\n", __func__); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 64bf258e7e00b2e260f77a1cdea9282cf920967d..9606dde3194cbc0b437cf170cf5e4eb8736a8f53 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -116,7 +116,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), requesttype, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, - 0, 0, buffer, 1, 0); + 0, 0, buffer, 1, USB_CTRL_SET_TIMEOUT); kfree(buffer); if (retval < 0) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 084332a5855e0ff08ea9cf5f3f28d2921c35a94a..5ea4cd10abc7655e98faa6eacac5ee1bb147c37c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -566,6 +566,9 @@ static void option_instat_callback(struct urb *urb); /* Interface is reserved */ #define RSVD(ifnum) ((BIT(ifnum) & 0xff) << 0) +/* Device needs ZLP */ +#define ZLP BIT(17) + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, @@ -1167,6 +1170,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1102, 0xff), /* Telit ME910 (ECM) */ .driver_info = NCTRL(0) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x110a, 0xff), /* Telit ME910G1 */ + .driver_info = NCTRL(0) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), @@ -1191,6 +1196,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff), /* Telit LN940 (MBIM) */ .driver_info = NCTRL(0) }, + { USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */ + .driver_info = NCTRL(0) | ZLP }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), .driver_info = RSVD(1) }, @@ -2095,6 +2102,9 @@ static int option_attach(struct usb_serial *serial) if (!(device_flags & NCTRL(iface_desc->bInterfaceNumber))) data->use_send_setup = 1; + if (device_flags & ZLP) + data->use_zlp = 1; + spin_lock_init(&data->susp_lock); usb_set_serial_data(serial, data); diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 1d17779b22038cf78a78029fe81feb127201c628..19952ccd028a93a759d7203037ec0ceb47c4fdd5 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -872,7 +872,10 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch) u8 newMSR = (u8) *ch; unsigned long flags; + /* May be called from qt2_process_read_urb() for an unbound port. */ port_priv = usb_get_serial_port_data(port); + if (!port_priv) + return; spin_lock_irqsave(&port_priv->lock, flags); port_priv->shadowMSR = newMSR; @@ -900,7 +903,10 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch) unsigned long flags; u8 newLSR = (u8) *ch; + /* May be called from qt2_process_read_urb() for an unbound port. */ port_priv = usb_get_serial_port_data(port); + if (!port_priv) + return; if (newLSR & UART_LSR_BI) newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI); diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index 51124211140395c627869f9bff9dd14e9aa1565b..15e05ebf37ac475d09edda610028ac7db3d94a37 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -89,6 +89,8 @@ DEVICE(moto_modem, MOTO_IDS); #define MOTOROLA_TETRA_IDS() \ { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \ { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \ + { USB_DEVICE(0x0cad, 0x9013) }, /* MTP3xxx */ \ + { USB_DEVICE(0x0cad, 0x9015) }, /* MTP85xx */ \ { USB_DEVICE(0x0cad, 0x9016) } /* TPG2200 */ DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index a894c0fdc04b7c49138da5f46a6e4ace56c893ab..8a24a11b7ffcc36207b69352e0d65f4d2b109df0 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1351,6 +1351,9 @@ static int usb_serial_register(struct usb_serial_driver *driver) return -EINVAL; } + /* Prevent individual ports from being unbound. */ + driver->driver.suppress_bind_attrs = true; + usb_serial_operations_init(driver); /* Add this device to our list of devices */ diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 44b25c08c68a15aa7db54056621576313a6bff48..1d0e2853834614f1afe7de14c850dc2bbb961ada 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -35,6 +35,7 @@ struct usb_wwan_intf_private { spinlock_t susp_lock; unsigned int suspended:1; unsigned int use_send_setup:1; + unsigned int use_zlp:1; int in_flight; unsigned int open_ports; void *private; diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 3dfdfc81254b827cc2e1f04feb926d0ad9666cf0..93c696e2131f8d7bca1bddf04755abd96955dff1 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -495,6 +495,7 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, void (*callback) (struct urb *)) { struct usb_serial *serial = port->serial; + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); struct urb *urb; urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ @@ -505,6 +506,9 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); + if (intfdata->use_zlp && dir == USB_DIR_OUT) + urb->transfer_flags |= URB_ZERO_PACKET; + return urb; } diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 597bc550034f911e5ae1f9ae1080834d04c3cbd0..d022b5ff4cd092235365ec8233bf58e26dba1e75 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -46,6 +46,7 @@ struct uas_dev_info { struct scsi_cmnd *cmnd[MAX_CMNDS]; spinlock_t lock; struct work_struct work; + struct work_struct scan_work; /* for async scanning */ }; enum { @@ -115,6 +116,17 @@ static void uas_do_work(struct work_struct *work) spin_unlock_irqrestore(&devinfo->lock, flags); } +static void uas_scan_work(struct work_struct *work) +{ + struct uas_dev_info *devinfo = + container_of(work, struct uas_dev_info, scan_work); + struct Scsi_Host *shost = usb_get_intfdata(devinfo->intf); + + dev_dbg(&devinfo->intf->dev, "starting scan\n"); + scsi_scan_host(shost); + dev_dbg(&devinfo->intf->dev, "scan complete\n"); +} + static void uas_add_work(struct uas_cmd_info *cmdinfo) { struct scsi_pointer *scp = (void *)cmdinfo; @@ -832,6 +844,10 @@ static int uas_slave_configure(struct scsi_device *sdev) sdev->wce_default_on = 1; } + /* Some disks cannot handle READ_CAPACITY_16 */ + if (devinfo->flags & US_FL_NO_READ_CAPACITY_16) + sdev->no_read_capacity_16 = 1; + /* * Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. @@ -840,6 +856,12 @@ static int uas_slave_configure(struct scsi_device *sdev) if (devinfo->flags & US_FL_FIX_CAPACITY) sdev->fix_capacity = 1; + /* + * in some cases we have to guess + */ + if (devinfo->flags & US_FL_CAPACITY_HEURISTICS) + sdev->guess_capacity = 1; + /* * Some devices don't like MODE SENSE with page=0x3f, * which is the command used for checking if a device @@ -979,6 +1001,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) init_usb_anchor(&devinfo->data_urbs); spin_lock_init(&devinfo->lock); INIT_WORK(&devinfo->work, uas_do_work); + INIT_WORK(&devinfo->scan_work, uas_scan_work); result = uas_configure_endpoints(devinfo); if (result) @@ -995,7 +1018,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) if (result) goto free_streams; - scsi_scan_host(shost); + /* Submit the delayed_work for SCSI-device scanning */ + schedule_work(&devinfo->scan_work); + return result; free_streams: @@ -1163,6 +1188,12 @@ static void uas_disconnect(struct usb_interface *intf) usb_kill_anchored_urbs(&devinfo->data_urbs); uas_zap_pending(devinfo, DID_NO_CONNECT); + /* + * Prevent SCSI scanning (if it hasn't started yet) + * or wait for the SCSI-scanning routine to stop. + */ + cancel_work_sync(&devinfo->scan_work); + scsi_remove_host(shost); uas_free_streams(devinfo); scsi_host_put(shost); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 3ebf6307217c10d47e19ebc33ebfe638b09f0e0c..a52ae34fb1c3faa0b7e93034ddc9943aa6a15110 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1277,6 +1277,12 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, USB_SC_RBC, USB_PR_BULK, NULL, 0 ), +UNUSUAL_DEV(0x090c, 0x1000, 0x1100, 0x1100, + "Samsung", + "Flash Drive FIT", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64), + /* aeb */ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, "Feiya", diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index f15aa47c54a9dccc6238faed23d6de6b8f43cfb5..0eb8c67ee13821f34e7b9c44c55eb9f8b330c116 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -163,12 +163,15 @@ UNUSUAL_DEV(0x2537, 0x1068, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_UAS), -/* Reported-by: Takeo Nakayama */ +/* + * Initially Reported-by: Takeo Nakayama + * UAS Ignore Reported by Steven Ellis + */ UNUSUAL_DEV(0x357d, 0x7788, 0x0000, 0x9999, "JMicron", "JMS566", USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_REPORT_OPCODES), + US_FL_NO_REPORT_OPCODES | US_FL_IGNORE_UAS), /* Reported-by: Hans de Goede */ UNUSUAL_DEV(0x4971, 0x1012, 0x0000, 0x9999, diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c index 5943deeec115492b6e48840dadcba093b2ab140d..a4f65aacf3356daf75dbee6b800b930a2b5f2e4a 100644 --- a/drivers/usb/usbip/vhci_rx.c +++ b/drivers/usb/usbip/vhci_rx.c @@ -90,16 +90,21 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0); /* recv transfer buffer */ - if (usbip_recv_xbuff(ud, urb) < 0) - return; + if (usbip_recv_xbuff(ud, urb) < 0) { + urb->status = -EPROTO; + goto error; + } /* recv iso_packet_descriptor */ - if (usbip_recv_iso(ud, urb) < 0) - return; + if (usbip_recv_iso(ud, urb) < 0) { + urb->status = -EPROTO; + goto error; + } /* restore the padding in iso packets */ usbip_pad_iso(ud, urb); +error: if (usbip_dbg_flag_vhci_rx) usbip_dump_urb(urb); diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index da3f0ed18c769344eee4107b3d7e774e448fe184..c94167d8717895d5545e875c0ab57a7daafbe9f7 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -729,6 +729,7 @@ static long vfio_pci_ioctl(void *device_data, { void __iomem *io; size_t size; + u16 orig_cmd; info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); info.flags = 0; @@ -744,15 +745,23 @@ static long vfio_pci_ioctl(void *device_data, break; } - /* Is it really there? */ + /* + * Is it really there? Enable memory decode for + * implicit access in pci_map_rom(). + */ + pci_read_config_word(pdev, PCI_COMMAND, &orig_cmd); + pci_write_config_word(pdev, PCI_COMMAND, + orig_cmd | PCI_COMMAND_MEMORY); + io = pci_map_rom(pdev, &size); - if (!io || !size) { + if (io) { + info.flags = VFIO_REGION_INFO_FLAG_READ; + pci_unmap_rom(pdev, io); + } else { info.size = 0; - break; } - pci_unmap_rom(pdev, io); - info.flags = VFIO_REGION_INFO_FLAG_READ; + pci_write_config_word(pdev, PCI_COMMAND, orig_cmd); break; } case VFIO_PCI_VGA_REGION_INDEX: diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 1c46045b0e7fc6b2e8ef421853742851aa880d7e..94594dc63c4173ad79b08ac70f5f31542422d499 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -297,8 +297,8 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, irq = pci_irq_vector(pdev, vector); if (vdev->ctx[vector].trigger) { - free_irq(irq, vdev->ctx[vector].trigger); irq_bypass_unregister_producer(&vdev->ctx[vector].producer); + free_irq(irq, vdev->ctx[vector].trigger); kfree(vdev->ctx[vector].name); eventfd_ctx_put(vdev->ctx[vector].trigger); vdev->ctx[vector].trigger = NULL; diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index dd8798bf88e7c0b9095248227368c7a981f8d562..861f43f8f9ceab0fb9b86145c7a1b14191da191f 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -914,11 +914,7 @@ static int vhost_net_release(struct inode *inode, struct file *f) static struct socket *get_raw_socket(int fd) { - struct { - struct sockaddr_ll sa; - char buf[MAX_ADDR_LEN]; - } uaddr; - int uaddr_len = sizeof uaddr, r; + int r; struct socket *sock = sockfd_lookup(fd, &r); if (!sock) @@ -930,12 +926,7 @@ static struct socket *get_raw_socket(int fd) goto err; } - r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, - &uaddr_len, 0); - if (r) - goto err; - - if (uaddr.sa.sll_family != AF_PACKET) { + if (sock->sk->sk_family != AF_PACKET) { r = -EPFNOSUPPORT; goto err; } diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index a775493b7b67dacf1934357e996cbc69d8be22f4..2e37097916b5b1df76a471b83446205083d62c85 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -399,7 +399,9 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work) len = pkt->len; /* Only accept correctly addressed packets */ - if (le64_to_cpu(pkt->hdr.src_cid) == vsock->guest_cid) + if (le64_to_cpu(pkt->hdr.src_cid) == vsock->guest_cid && + le64_to_cpu(pkt->hdr.dst_cid) == + vhost_transport_get_local_cid()) virtio_transport_recv_pkt(pkt); else virtio_transport_free_pkt(pkt); diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index 60d6c2ac87aa526b77d308532dc7289ddef85ab5..1771220b2437f601082c6689b33c91544f483d2e 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -200,7 +200,7 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl) LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE); if (ret < 0) goto out_i2c_err; - return bl->props.brightness; + return 0; out_i2c_err: dev_err(pchip->dev, "i2c failed to access\n"); @@ -277,7 +277,7 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl) LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE); if (ret < 0) goto out_i2c_err; - return bl->props.brightness; + return 0; out_i2c_err: dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index dda1c4b3a2294dfbe8d26284c3173ae5eeac1dca..42c0a26646f66fbbfe020a4a3253ce524aab6533 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1323,6 +1323,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) static int vgacon_resize(struct vc_data *c, unsigned int width, unsigned int height, unsigned int user) { + if ((width << 1) * height > vga_vram_size) + return -EINVAL; + if (width % 2 || width > screen_info.orig_video_cols || height > (screen_info.orig_video_lines * vga_default_font_height)/ c->vc_font.height) diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c index 59abdc6a97f668ed1b67e6bd9e958b74479bd99e..314b7eceb81c5a3549da9718e6fe1749a615db9f 100644 --- a/drivers/video/fbdev/chipsfb.c +++ b/drivers/video/fbdev/chipsfb.c @@ -350,7 +350,7 @@ static void init_chips(struct fb_info *p, unsigned long addr) static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) { struct fb_info *p; - unsigned long addr, size; + unsigned long addr; unsigned short cmd; int rc = -ENODEV; @@ -362,7 +362,6 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) goto err_disable; addr = pci_resource_start(dp, 0); - size = pci_resource_len(dp, 0); if (addr == 0) goto err_disable; diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c index 34869b8c6f836f98c7e97f8e4870e44d76cc53b0..55da18f8b6b0da35689ff2bab66cd3c8982adc6a 100644 --- a/drivers/video/fbdev/msm/mdp3_ctrl.c +++ b/drivers/video/fbdev/msm/mdp3_ctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2019, 2020, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-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 @@ -1325,19 +1325,37 @@ int mdp3_ctrl_reset(struct msm_fb_data_type *mfd) /*Map the splash addr for VIDEO mode panel before smmu attach*/ if ((mfd->panel.type == MIPI_VIDEO_PANEL) && (mdp3_session->in_splash_screen)) { + rc = mdss_smmu_set_attribute(MDSS_IOMMU_DOMAIN_UNSECURE, + EARLY_MAP, 1); + if (rc) { + pr_err("mdp3 set attribute failed for early map\n"); + goto reset_error; + } + rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P); + if (IS_ERR_VALUE((unsigned long)rc)) { + pr_err("mdp3 iommu attach failed\n"); + goto reset_error; + } rc = mdss_smmu_map(MDSS_IOMMU_DOMAIN_UNSECURE, mdp3_res->splash_mem_addr, mdp3_res->splash_mem_addr, mdp3_res->splash_mem_size, IOMMU_READ | IOMMU_NOEXEC); - } + if (rc) + pr_err("iommu memory mapping failed ret=%d\n", rc); + else + pr_info("iommu map passed for PA=VA\n"); - rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P); - if (rc) { - pr_err("fail to attach dma iommu\n"); - if (mdp3_res->idle_pc) - mdp3_clk_enable(0, 0); - goto reset_error; + rc = mdss_smmu_set_attribute(MDSS_IOMMU_DOMAIN_UNSECURE, + EARLY_MAP, 0); + } else { + rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P); + if (rc) { + pr_err("fail to attach dma iommu\n"); + if (mdp3_res->idle_pc) + mdp3_clk_enable(0, 0); + goto reset_error; + } } vsync_client = mdp3_dma->vsync_client; @@ -1737,7 +1755,7 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) static bool splash_done; struct mdss_panel_data *panel; - int rc; + int stride, rc; pr_debug("mdp3_ctrl_pan_display\n"); if (!mfd || !mfd->mdp.private1) @@ -1790,9 +1808,21 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) if (IS_ERR_VALUE(rc)) goto pan_error; } - rc = mdp3_session->dma->update(mdp3_session->dma, - (void *)(int)(mfd->iova + offset), - mdp3_session->intf, NULL); + if (mdp3_ctrl_get_intf_type(mfd) == + MDP3_DMA_OUTPUT_SEL_SPI_CMD) { + stride = fbi->fix.line_length; + pr_debug("addr = %x, smemlen = %d, stride = %d, offset = %x\n", + (int)mfd->iova, (int)fbi->fix.smem_len, + stride, (int)offset); + rc = mdss_spi_panel_kickoff(mdp3_session->panel, + (mfd->fbi->screen_base + offset), + (int)fbi->fix.smem_len, + stride); + } else { + rc = mdp3_session->dma->update(mdp3_session->dma, + (void *)(int)(mfd->iova + offset), + mdp3_session->intf, NULL); + } /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, @@ -1831,8 +1861,13 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) mdp3_session->vsync_before_commit = 0; if (!splash_done || mdp3_session->esd_recovery == true) { - if (panel && panel->set_backlight) - panel->set_backlight(panel, panel->panel_info.bl_max); + if (panel && panel->set_backlight) { + if (mfd->bl_level > 0) + panel->set_backlight(panel, mfd->bl_level); + else + panel->set_backlight(panel, + panel->panel_info.bl_max); + } splash_done = true; mdp3_session->esd_recovery = false; } diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index c3a2dfdd7792939aab7f6b7d1f1fd18c86c88141..73f0cd961b0ce3541dded020208bb591c6ac627b 100755 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -435,6 +435,11 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) return rc; } + if (pinfo->skip_panel_reset && !pinfo->cont_splash_enabled) { + pr_debug("%s: skip_panel_reset is set\n", __func__); + return 0; + } + pr_debug("%s: enable = %d\n", __func__, enable); if (enable) { @@ -3002,6 +3007,9 @@ static int mdss_panel_parse_dt(struct device_node *np, pinfo->mipi.force_clk_lane_hs = of_property_read_bool(np, "qcom,mdss-dsi-force-clock-lane-hs"); + pinfo->skip_panel_reset = + of_property_read_bool(np, "qcom,mdss-skip-panel-reset"); + rc = mdss_dsi_parse_panel_features(np, ctrl_pdata); if (rc) { pr_err("%s: failed to parse panel features\n", __func__); diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 0c71e24f3d1107089d5cae3badc00e798fdb9931..d1bce4653cd9da9980c6f0d9a16901c28e3ce72e 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -1914,7 +1914,10 @@ static int mdss_fb_blank_blank(struct msm_fb_data_type *mfd, if (mfd->disp_thread) mdss_fb_stop_disp_thread(mfd); mutex_lock(&mfd->bl_lock); - current_bl = mfd->bl_level; + if (mfd->unset_bl_level != U32_MAX) + current_bl = mfd->unset_bl_level; + else + current_bl = mfd->bl_level; mfd->allow_bl_update = true; mdss_fb_set_backlight(mfd, 0); mfd->allow_bl_update = false; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 0fa242eb11227d838648957744fa21a2fd1af426..e79ae1d0e6e83064a41c076f3a345ab10d5b6805 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-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 @@ -774,6 +774,12 @@ struct mdss_panel_info { /* persistence mode on/off */ bool persist_mode; + /* + * Skip panel reset during panel on/off. + * Set for some in-cell panels + */ + bool skip_panel_reset; + /* HDR properties of display panel*/ struct mdss_panel_hdr_properties hdr_properties; }; diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.c b/drivers/video/fbdev/msm/mdss_spi_panel.c index e95dcd533a4eb55822507adf282c9394d9caa79d..b111fe487da3a7a0a01c677b79462426b7c12d44 100644 --- a/drivers/video/fbdev/msm/mdss_spi_panel.c +++ b/drivers/video/fbdev/msm/mdss_spi_panel.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018,2020, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, 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 @@ -415,7 +415,7 @@ static void enable_spi_panel_te_irq(struct spi_panel_data *ctrl_pdata, } int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata, - char *buf, int len, int dma_stride) + char __iomem *buf, int len, int dma_stride) { struct spi_panel_data *ctrl_pdata = NULL; char *tx_buf; @@ -1122,10 +1122,10 @@ static void mdss_spi_panel_bklt_pwm(struct spi_panel_data *ctrl, int level) if (level == 0) { if (ctrl->pwm_enabled) { - ret = pwm_config_us(ctrl->pwm_bl, level, - ctrl->pwm_period); + ret = pwm_config(ctrl->pwm_bl, 0, + ctrl->pwm_period * NSEC_PER_USEC); if (ret) - pr_err("%s: pwm_config_us() failed err=%d.\n", + pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret); pwm_disable(ctrl->pwm_bl); } diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.h b/drivers/video/fbdev/msm/mdss_spi_panel.h index 80b7ea894ce3a7af47564327c5168f60c1e53cdc..2521e40896697f2ae9eab147980f61e1632f7c61 100644 --- a/drivers/video/fbdev/msm/mdss_spi_panel.h +++ b/drivers/video/fbdev/msm/mdss_spi_panel.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, 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 @@ -121,7 +121,7 @@ struct spi_panel_data { }; int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata, - char *buf, int len, int stride); + char __iomem *buf, int len, int stride); int is_spi_panel_continuous_splash_on(struct mdss_panel_data *pdata); void mdp3_spi_vsync_enable(struct mdss_panel_data *pdata, struct mdp3_notification *vsync_client); @@ -130,7 +130,7 @@ void mdp3_check_spi_panel_status(struct work_struct *work, #else static inline int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata, - char *buf, int len, int stride){ + char __iomem *buf, int len, int stride){ return 0; } static inline int is_spi_panel_continuous_splash_on( diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c index d059d04c63acd7bc118bbc0ec02fc3cb1dfa41f8..20195d3dbf088c87195c2976f09acefb1f5895da 100644 --- a/drivers/video/fbdev/pxa168fb.c +++ b/drivers/video/fbdev/pxa168fb.c @@ -769,8 +769,8 @@ static int pxa168fb_probe(struct platform_device *pdev) failed_free_clk: clk_disable_unprepare(fbi->clk); failed_free_fbmem: - dma_free_coherent(fbi->dev, info->fix.smem_len, - info->screen_base, fbi->fb_start_dma); + dma_free_wc(fbi->dev, info->fix.smem_len, + info->screen_base, fbi->fb_start_dma); failed_free_info: kfree(info); @@ -804,7 +804,7 @@ static int pxa168fb_remove(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); - dma_free_wc(fbi->dev, PAGE_ALIGN(info->fix.smem_len), + dma_free_wc(fbi->dev, info->fix.smem_len, info->screen_base, info->fix.smem_start); clk_disable_unprepare(fbi->clk); diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 111a0ab6280a06ebb719f8dd13e4f57df1ba7447..ce7c4a269f770e8eab84094bbd1fac7807e4a47b 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -1036,12 +1036,12 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, if (ptr[0] & 0x10) frame->active_aspect = ptr[1] & 0xf; if (ptr[0] & 0x8) { - frame->top_bar = (ptr[5] << 8) + ptr[6]; - frame->bottom_bar = (ptr[7] << 8) + ptr[8]; + frame->top_bar = (ptr[6] << 8) | ptr[5]; + frame->bottom_bar = (ptr[8] << 8) | ptr[7]; } if (ptr[0] & 0x4) { - frame->left_bar = (ptr[9] << 8) + ptr[10]; - frame->right_bar = (ptr[11] << 8) + ptr[12]; + frame->left_bar = (ptr[10] << 8) | ptr[9]; + frame->right_bar = (ptr[12] << 8) | ptr[11]; } frame->scan_mode = ptr[0] & 0x3; diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 30076956a09629333f414771b6d64d0a8889db9f..4e64a3befa350013b0785610418f732fe499e1aa 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -482,6 +482,17 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, get_page(newpage); /* balloon reference */ + /* + * When we migrate a page to a different zone and adjusted the + * managed page count when inflating, we have to fixup the count of + * both involved zones. + */ + if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM) && + page_zone(page) != page_zone(newpage)) { + adjust_managed_page_count(page, 1); + adjust_managed_page_count(newpage, -1); + } + /* balloon's page migration 1st step -- inflate "newpage" */ spin_lock_irqsave(&vb_dev_info->pages_lock, flags); balloon_page_insert(vb_dev_info, newpage); diff --git a/drivers/vme/bridges/vme_fake.c b/drivers/vme/bridges/vme_fake.c index 30b3acc9383309509862e0d1b942c22bc82a5361..e81ec763b5555026f9bcc395d620199f9fd58079 100644 --- a/drivers/vme/bridges/vme_fake.c +++ b/drivers/vme/bridges/vme_fake.c @@ -418,8 +418,9 @@ static void fake_lm_check(struct fake_driver *bridge, unsigned long long addr, } } -static u8 fake_vmeread8(struct fake_driver *bridge, unsigned long long addr, - u32 aspace, u32 cycle) +static noinline_for_stack u8 fake_vmeread8(struct fake_driver *bridge, + unsigned long long addr, + u32 aspace, u32 cycle) { u8 retval = 0xff; int i; @@ -450,8 +451,9 @@ static u8 fake_vmeread8(struct fake_driver *bridge, unsigned long long addr, return retval; } -static u16 fake_vmeread16(struct fake_driver *bridge, unsigned long long addr, - u32 aspace, u32 cycle) +static noinline_for_stack u16 fake_vmeread16(struct fake_driver *bridge, + unsigned long long addr, + u32 aspace, u32 cycle) { u16 retval = 0xffff; int i; @@ -482,8 +484,9 @@ static u16 fake_vmeread16(struct fake_driver *bridge, unsigned long long addr, return retval; } -static u32 fake_vmeread32(struct fake_driver *bridge, unsigned long long addr, - u32 aspace, u32 cycle) +static noinline_for_stack u32 fake_vmeread32(struct fake_driver *bridge, + unsigned long long addr, + u32 aspace, u32 cycle) { u32 retval = 0xffffffff; int i; @@ -613,8 +616,9 @@ static ssize_t fake_master_read(struct vme_master_resource *image, void *buf, return retval; } -static void fake_vmewrite8(struct fake_driver *bridge, u8 *buf, - unsigned long long addr, u32 aspace, u32 cycle) +static noinline_for_stack void fake_vmewrite8(struct fake_driver *bridge, + u8 *buf, unsigned long long addr, + u32 aspace, u32 cycle) { int i; unsigned long long start, end, offset; @@ -643,8 +647,9 @@ static void fake_vmewrite8(struct fake_driver *bridge, u8 *buf, } -static void fake_vmewrite16(struct fake_driver *bridge, u16 *buf, - unsigned long long addr, u32 aspace, u32 cycle) +static noinline_for_stack void fake_vmewrite16(struct fake_driver *bridge, + u16 *buf, unsigned long long addr, + u32 aspace, u32 cycle) { int i; unsigned long long start, end, offset; @@ -673,8 +678,9 @@ static void fake_vmewrite16(struct fake_driver *bridge, u16 *buf, } -static void fake_vmewrite32(struct fake_driver *bridge, u32 *buf, - unsigned long long addr, u32 aspace, u32 cycle) +static noinline_for_stack void fake_vmewrite32(struct fake_driver *bridge, + u32 *buf, unsigned long long addr, + u32 aspace, u32 cycle) { int i; unsigned long long start, end, offset; diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c index 7386111220d58480c298f1612305410485eedc2f..daeb645fcea8a1af32138e85c44482a403f1df8c 100644 --- a/drivers/watchdog/da9062_wdt.c +++ b/drivers/watchdog/da9062_wdt.c @@ -126,13 +126,6 @@ static int da9062_wdt_stop(struct watchdog_device *wdd) struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd); int ret; - ret = da9062_reset_watchdog_timer(wdt); - if (ret) { - dev_err(wdt->hw->dev, "Failed to ping the watchdog (err = %d)\n", - ret); - return ret; - } - ret = regmap_update_bits(wdt->hw->regmap, DA9062AA_CONTROL_D, DA9062AA_TWDSCALE_MASK, diff --git a/drivers/watchdog/rn5t618_wdt.c b/drivers/watchdog/rn5t618_wdt.c index 0805ee2acd7a94bb913472f5bd33bea5d95bc0c8..7aa8bf2d0f917cca219c1828b9490b9f2d8f40d5 100644 --- a/drivers/watchdog/rn5t618_wdt.c +++ b/drivers/watchdog/rn5t618_wdt.c @@ -193,6 +193,7 @@ static struct platform_driver rn5t618_wdt_driver = { module_platform_driver(rn5t618_wdt_driver); +MODULE_ALIAS("platform:rn5t618-wdt"); MODULE_AUTHOR("Beniamino Galvani "); MODULE_DESCRIPTION("RN5T618 watchdog driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index 0da9943d405f8ff89efc87a0cf6df5ff43df9d6f..c310e841561cbb1b15d03e498a764f25e1b9e1c5 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -392,7 +392,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) memset(&r, 0, sizeof(r)); r.start = gas->address; - r.end = r.start + gas->access_width - 1; + r.end = r.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1; if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { r.flags = IORESOURCE_MEM; } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 731cf54f75c6585b40d28b8d398187a00ced2d2c..05f9f5983ee17db92e0392e0727cddc7335fe251 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -403,7 +403,8 @@ static struct notifier_block xen_memory_nb = { #else static enum bp_state reserve_additional_memory(void) { - balloon_stats.target_pages = balloon_stats.current_pages; + balloon_stats.target_pages = balloon_stats.current_pages + + balloon_stats.target_unpopulated; return BP_ECANCELED; } #endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */ diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index f4e59c445964d57e11a400eccde3c14526cc5a42..17054d695411788da16eb4fd4f5ea08d1c9d4ad2 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -53,7 +53,7 @@ static int vcpu_online(unsigned int cpu) } static void vcpu_hotplug(unsigned int cpu) { - if (!cpu_possible(cpu)) + if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) return; switch (vcpu_online(cpu)) { diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c index 08cb419eb4e63c90f30ea7cdb541d31c14da2391..5f6b77ea34fb5b5ddef4d4fb5e3ba722194ded6f 100644 --- a/drivers/xen/preempt.c +++ b/drivers/xen/preempt.c @@ -37,7 +37,9 @@ asmlinkage __visible void xen_maybe_preempt_hcall(void) * cpu. */ __this_cpu_write(xen_in_preemptible_hcall, false); - _cond_resched(); + local_irq_enable(); + cond_resched(); + local_irq_disable(); __this_cpu_write(xen_in_preemptible_hcall, true); } } diff --git a/firmware/Makefile b/firmware/Makefile index e297e1b52636dadb9bf3f3acb2102c079e73e0e6..03232621cc087b4a5ee2a6f11c2f15b135e2b5a4 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -156,7 +156,7 @@ quiet_cmd_fwbin = MK_FW $@ PROGBITS=$(if $(CONFIG_ARM),%,@)progbits; \ echo "/* Generated by firmware/Makefile */" > $@;\ echo " .section .rodata" >>$@;\ - echo " .p2align $${ASM_ALIGN}" >>$@;\ + echo " .p2align 4" >>$@;\ echo "_fw_$${FWSTR}_bin:" >>$@;\ echo " .incbin \"$(2)\"" >>$@;\ echo "_fw_end:" >>$@;\ diff --git a/fs/afs/super.c b/fs/afs/super.c index fbdb022b75a27be11b5699203f8c04e32c499cf6..65389394e2028c36c2558aea4cb0c8098417fe6f 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -317,6 +317,7 @@ static int afs_fill_super(struct super_block *sb, /* fill in the superblock */ sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; + sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_magic = AFS_FS_MAGIC; sb->s_op = &afs_super_ops; sb->s_bdi = &as->volume->bdi; diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 2e1f50e467f15a736a8e99d291c2e3ebb6cab104..02f0d373adbf79819bb633fbd73609fd81011825 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -469,9 +469,10 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, */ flags &= ~AUTOFS_EXP_LEAVES; found = should_expire(expired, mnt, timeout, how); - if (!found || found != expired) - /* Something has changed, continue */ + if (found != expired) { // something has changed, continue + dput(found); goto next; + } if (expired != dentry) dput(dentry); diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index ff0b0be92d6122402f02c039eed8e4599fdce4df..a3de11d52ad0098c850b722cc7b0a910bcc1cce0 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -265,16 +265,17 @@ static inline void thresh_exec_hook(struct __btrfs_workqueue *wq) } } -static void run_ordered_work(struct __btrfs_workqueue *wq) +static void run_ordered_work(struct __btrfs_workqueue *wq, + struct btrfs_work *self) { struct list_head *list = &wq->ordered_list; struct btrfs_work *work; spinlock_t *lock = &wq->list_lock; unsigned long flags; + void *wtag; + bool free_self = false; while (1) { - void *wtag; - spin_lock_irqsave(lock, flags); if (list_empty(list)) break; @@ -300,16 +301,47 @@ static void run_ordered_work(struct __btrfs_workqueue *wq) list_del(&work->ordered_list); spin_unlock_irqrestore(lock, flags); - /* - * We don't want to call the ordered free functions with the - * lock held though. Save the work as tag for the trace event, - * because the callback could free the structure. - */ - wtag = work; - work->ordered_free(work); - trace_btrfs_all_work_done(wq->fs_info, wtag); + if (work == self) { + /* + * This is the work item that the worker is currently + * executing. + * + * The kernel workqueue code guarantees non-reentrancy + * of work items. I.e., if a work item with the same + * address and work function is queued twice, the second + * execution is blocked until the first one finishes. A + * work item may be freed and recycled with the same + * work function; the workqueue code assumes that the + * original work item cannot depend on the recycled work + * item in that case (see find_worker_executing_work()). + * + * Note that the work of one Btrfs filesystem may depend + * on the work of another Btrfs filesystem via, e.g., a + * loop device. Therefore, we must not allow the current + * work item to be recycled until we are really done, + * otherwise we break the above assumption and can + * deadlock. + */ + free_self = true; + } else { + /* + * We don't want to call the ordered free functions with + * the lock held though. Save the work as tag for the + * trace event, because the callback could free the + * structure. + */ + wtag = work; + work->ordered_free(work); + trace_btrfs_all_work_done(wq->fs_info, wtag); + } } spin_unlock_irqrestore(lock, flags); + + if (free_self) { + wtag = self; + self->ordered_free(self); + trace_btrfs_all_work_done(wq->fs_info, wtag); + } } static void normal_work_helper(struct btrfs_work *work) @@ -337,7 +369,7 @@ static void normal_work_helper(struct btrfs_work *work) work->func(work); if (need_order) { set_bit(WORK_DONE_BIT, &work->flags); - run_ordered_work(wq); + run_ordered_work(wq, work); } if (!need_order) trace_btrfs_all_work_done(wq->fs_info, wtag); diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 3faccbf35e9f4c68dca0e626ee48423b8f22a392..b5ebb43b1824fd1275893a00a584565731716158 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -331,26 +331,6 @@ struct tree_mod_elem { struct tree_mod_root old_root; }; -static inline void tree_mod_log_read_lock(struct btrfs_fs_info *fs_info) -{ - read_lock(&fs_info->tree_mod_log_lock); -} - -static inline void tree_mod_log_read_unlock(struct btrfs_fs_info *fs_info) -{ - read_unlock(&fs_info->tree_mod_log_lock); -} - -static inline void tree_mod_log_write_lock(struct btrfs_fs_info *fs_info) -{ - write_lock(&fs_info->tree_mod_log_lock); -} - -static inline void tree_mod_log_write_unlock(struct btrfs_fs_info *fs_info) -{ - write_unlock(&fs_info->tree_mod_log_lock); -} - /* * Pull a new tree mod seq number for our operation. */ @@ -370,14 +350,12 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info) u64 btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, struct seq_list *elem) { - tree_mod_log_write_lock(fs_info); - spin_lock(&fs_info->tree_mod_seq_lock); + write_lock(&fs_info->tree_mod_log_lock); if (!elem->seq) { elem->seq = btrfs_inc_tree_mod_seq(fs_info); list_add_tail(&elem->list, &fs_info->tree_mod_seq_list); } - spin_unlock(&fs_info->tree_mod_seq_lock); - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); return elem->seq; } @@ -396,7 +374,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, if (!seq_putting) return; - spin_lock(&fs_info->tree_mod_seq_lock); + write_lock(&fs_info->tree_mod_log_lock); list_del(&elem->list); elem->seq = 0; @@ -407,29 +385,27 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, * blocker with lower sequence number exists, we * cannot remove anything from the log */ - spin_unlock(&fs_info->tree_mod_seq_lock); + write_unlock(&fs_info->tree_mod_log_lock); return; } min_seq = cur_elem->seq; } } - spin_unlock(&fs_info->tree_mod_seq_lock); /* * anything that's lower than the lowest existing (read: blocked) * sequence number can be removed from the tree. */ - tree_mod_log_write_lock(fs_info); tm_root = &fs_info->tree_mod_log; for (node = rb_first(tm_root); node; node = next) { next = rb_next(node); tm = container_of(node, struct tree_mod_elem, node); - if (tm->seq > min_seq) + if (tm->seq >= min_seq) continue; rb_erase(node, tm_root); kfree(tm); } - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); } /* @@ -440,7 +416,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, * for root replace operations, or the logical address of the affected * block for all other operations. * - * Note: must be called with write lock (tree_mod_log_write_lock). + * Note: must be called with write lock for fs_info::tree_mod_log_lock. */ static noinline int __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) @@ -480,7 +456,7 @@ __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) * Determines if logging can be omitted. Returns 1 if it can. Otherwise, it * returns zero with the tree_mod_log_lock acquired. The caller must hold * this until all tree mod log insertions are recorded in the rb tree and then - * call tree_mod_log_write_unlock() to release. + * write unlock fs_info::tree_mod_log_lock. */ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) { @@ -490,9 +466,9 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, if (eb && btrfs_header_level(eb) == 0) return 1; - tree_mod_log_write_lock(fs_info); + write_lock(&fs_info->tree_mod_log_lock); if (list_empty(&(fs_info)->tree_mod_seq_list)) { - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); return 1; } @@ -556,7 +532,7 @@ tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, } ret = __tree_mod_log_insert(fs_info, tm); - tree_mod_log_write_unlock(fs_info); + write_unlock(&eb->fs_info->tree_mod_log_lock); if (ret) kfree(tm); @@ -620,7 +596,7 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, ret = __tree_mod_log_insert(fs_info, tm); if (ret) goto free_tms; - tree_mod_log_write_unlock(fs_info); + write_unlock(&eb->fs_info->tree_mod_log_lock); kfree(tm_list); return 0; @@ -631,7 +607,7 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, kfree(tm_list[i]); } if (locked) - tree_mod_log_write_unlock(fs_info); + write_unlock(&eb->fs_info->tree_mod_log_lock); kfree(tm_list); kfree(tm); @@ -712,7 +688,7 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, if (!ret) ret = __tree_mod_log_insert(fs_info, tm); - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); if (ret) goto free_tms; kfree(tm_list); @@ -739,7 +715,7 @@ __tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq, struct tree_mod_elem *cur = NULL; struct tree_mod_elem *found = NULL; - tree_mod_log_read_lock(fs_info); + read_lock(&fs_info->tree_mod_log_lock); tm_root = &fs_info->tree_mod_log; node = tm_root->rb_node; while (node) { @@ -767,7 +743,7 @@ __tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq, break; } } - tree_mod_log_read_unlock(fs_info); + read_unlock(&fs_info->tree_mod_log_lock); return found; } @@ -848,7 +824,7 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, goto free_tms; } - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); kfree(tm_list); return 0; @@ -860,7 +836,7 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, kfree(tm_list[i]); } if (locked) - tree_mod_log_write_unlock(fs_info); + write_unlock(&fs_info->tree_mod_log_lock); kfree(tm_list); return ret; @@ -920,7 +896,7 @@ tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) goto free_tms; ret = __tree_mod_log_free_eb(fs_info, tm_list, nritems); - tree_mod_log_write_unlock(fs_info); + write_unlock(&eb->fs_info->tree_mod_log_lock); if (ret) goto free_tms; kfree(tm_list); @@ -1271,7 +1247,7 @@ __tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, unsigned long p_size = sizeof(struct btrfs_key_ptr); n = btrfs_header_nritems(eb); - tree_mod_log_read_lock(fs_info); + read_lock(&fs_info->tree_mod_log_lock); while (tm && tm->seq >= time_seq) { /* * all the operations are recorded with the operator used for @@ -1326,7 +1302,7 @@ __tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, if (tm->logical != first_tm->logical) break; } - tree_mod_log_read_unlock(fs_info); + read_unlock(&fs_info->tree_mod_log_lock); btrfs_set_header_nritems(eb, n); } diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index a423c36bcd72b30705a0655efe6627d406da82c8..2bc37d03d4075f01438cfabcbfae1eefd3927499 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -851,14 +851,12 @@ struct btrfs_fs_info { struct list_head delayed_iputs; struct mutex cleaner_delayed_iput_mutex; - /* this protects tree_mod_seq_list */ - spinlock_t tree_mod_seq_lock; atomic64_t tree_mod_seq; - struct list_head tree_mod_seq_list; - /* this protects tree_mod_log */ + /* this protects tree_mod_log and tree_mod_seq_list */ rwlock_t tree_mod_log_lock; struct rb_root tree_mod_log; + struct list_head tree_mod_seq_list; atomic_t nr_async_submits; atomic_t async_submit_draining; diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index 74c17db7520146f0c2b00dda6f76f6af33efdb79..c1ca4ce11e69e3ba182261b804f37f2c72aafcf6 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -279,7 +279,7 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, if (head->is_data) return; - spin_lock(&fs_info->tree_mod_seq_lock); + read_lock(&fs_info->tree_mod_log_lock); if (!list_empty(&fs_info->tree_mod_seq_list)) { struct seq_list *elem; @@ -287,7 +287,7 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, struct seq_list, list); seq = elem->seq; } - spin_unlock(&fs_info->tree_mod_seq_lock); + read_unlock(&fs_info->tree_mod_log_lock); ref = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node, list); @@ -315,7 +315,7 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, struct seq_list *elem; int ret = 0; - spin_lock(&fs_info->tree_mod_seq_lock); + read_lock(&fs_info->tree_mod_log_lock); if (!list_empty(&fs_info->tree_mod_seq_list)) { elem = list_first_entry(&fs_info->tree_mod_seq_list, struct seq_list, list); @@ -329,7 +329,7 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, } } - spin_unlock(&fs_info->tree_mod_seq_lock); + read_unlock(&fs_info->tree_mod_log_lock); return ret; } diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8c4120be2d5bab7fd2b83b767a5d7e7e1c20dcea..1ed918c635178253c93b8172fc4f8554396cf38a 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1712,8 +1712,8 @@ static void end_workqueue_fn(struct btrfs_work *work) bio->bi_error = end_io_wq->error; bio->bi_private = end_io_wq->private; bio->bi_end_io = end_io_wq->end_io; - kmem_cache_free(btrfs_end_io_wq_cache, end_io_wq); bio_endio(bio); + kmem_cache_free(btrfs_end_io_wq_cache, end_io_wq); } static int cleaner_kthread(void *arg) @@ -2104,7 +2104,7 @@ static void free_root_extent_buffers(struct btrfs_root *root) } /* helper to cleanup tree roots */ -static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root) +static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root) { free_root_extent_buffers(info->tree_root); @@ -2113,7 +2113,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root) free_root_extent_buffers(info->csum_root); free_root_extent_buffers(info->quota_root); free_root_extent_buffers(info->uuid_root); - if (chunk_root) + if (free_chunk_root) free_root_extent_buffers(info->chunk_root); free_root_extent_buffers(info->free_space_root); } @@ -2519,7 +2519,6 @@ int open_ctree(struct super_block *sb, spin_lock_init(&fs_info->delayed_iput_lock); spin_lock_init(&fs_info->defrag_inodes_lock); spin_lock_init(&fs_info->free_chunk_lock); - spin_lock_init(&fs_info->tree_mod_seq_lock); spin_lock_init(&fs_info->super_lock); spin_lock_init(&fs_info->qgroup_op_lock); spin_lock_init(&fs_info->buffer_lock); @@ -2980,6 +2979,7 @@ int open_ctree(struct super_block *sb, /* do not make disk changes in broken FS or nologreplay is given */ if (btrfs_super_log_root(disk_super) != 0 && !btrfs_test_opt(tree_root->fs_info, NOLOGREPLAY)) { + btrfs_info(fs_info, "start tree-log replay"); ret = btrfs_replay_log(fs_info, fs_devices); if (ret) { err = ret; @@ -3136,7 +3136,7 @@ int open_ctree(struct super_block *sb, btrfs_free_block_groups(fs_info); fail_tree_roots: - free_root_pointers(fs_info, 1); + free_root_pointers(fs_info, true); invalidate_inode_pages2(fs_info->btree_inode->i_mapping); fail_sb_buffer: @@ -3165,7 +3165,7 @@ int open_ctree(struct super_block *sb, if (!btrfs_test_opt(tree_root->fs_info, USEBACKUPROOT)) goto fail_tree_roots; - free_root_pointers(fs_info, 0); + free_root_pointers(fs_info, false); /* don't use the log in recovery mode, it won't be valid */ btrfs_set_super_log_root(disk_super, 0); @@ -3862,7 +3862,7 @@ void close_ctree(struct btrfs_root *root) btrfs_stop_all_workers(fs_info); clear_bit(BTRFS_FS_OPEN, &fs_info->flags); - free_root_pointers(fs_info, 1); + free_root_pointers(fs_info, true); iput(fs_info->btree_inode); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 84051b229fd2a1bcace618a751ffda7db211fa2a..6e0b6bc8ae9f505df65117e33dc6a028b41f0448 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4049,6 +4049,14 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, */ scanned = 1; index = 0; + + /* + * If we're looping we could run into a page that is locked by a + * writer and that writer could be waiting on writeback for a + * page in our current bio, and thus deadlock, so flush the + * write bio here. + */ + flush_write_bio(data); goto retry; } @@ -4983,12 +4991,14 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, return eb; eb = alloc_dummy_extent_buffer(fs_info, start, nodesize); if (!eb) - return NULL; + return ERR_PTR(-ENOMEM); eb->fs_info = fs_info; again: ret = radix_tree_preload(GFP_NOFS); - if (ret) + if (ret) { + exists = ERR_PTR(ret); goto free_eb; + } spin_lock(&fs_info->buffer_lock); ret = radix_tree_insert(&fs_info->buffer_radix, start >> PAGE_SHIFT, eb); diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 26f9ac719d20b4bff1a6b0a456ca45dd1752b4c7..4f59b4089eb01a3f870992d1e516550019e0f1a1 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -227,6 +227,17 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em) struct extent_map *merge = NULL; struct rb_node *rb; + /* + * We can't modify an extent map that is in the tree and that is being + * used by another task, as it can cause that other task to see it in + * inconsistent state during the merging. We always have 1 reference for + * the tree and 1 for this task (which is unpinning the extent map or + * clearing the logging flag), so anything > 2 means it's being used by + * other tasks too. + */ + if (atomic_read(&em->refs) > 2) + return; + if (em->start != 0) { rb = rb_prev(&em->rb_node); if (rb) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 6cdf27325576b21031ce9d8d494d363d29318ca2..03661b744eaf019c8e4c6ef5644f3b6e4915c010 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1555,6 +1555,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, break; } + only_release_metadata = false; sector_offset = pos & (root->sectorsize - 1); reserve_bytes = round_up(write_bytes + sector_offset, root->sectorsize); @@ -1704,7 +1705,6 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, EXTENT_NORESERVE, NULL, NULL, GFP_NOFS); - only_release_metadata = false; } btrfs_drop_pages(pages, num_pages); diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 69a3c11af9d45d8a89bf25785d51a62dafb7b301..a84a1ceb260af102475c1f0934d3600246ba8e6e 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -391,6 +391,12 @@ static int io_ctl_prepare_pages(struct btrfs_io_ctl *io_ctl, struct inode *inode if (uptodate && !PageUptodate(page)) { btrfs_readpage(NULL, page); lock_page(page); + if (page->mapping != inode->i_mapping) { + btrfs_err(BTRFS_I(inode)->root->fs_info, + "free space cache page truncated"); + io_ctl_drop_pages(io_ctl); + return -EIO; + } if (!PageUptodate(page)) { btrfs_err(BTRFS_I(inode)->root->fs_info, "error reading free space cache"); diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index d27014b8bf72739cecceeae2d0bb6c756f34c6b5..075b59516c8c06b7f3dcb8c57585acf81a2c04e8 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -159,6 +159,7 @@ static void start_caching(struct btrfs_root *root) spin_lock(&root->ino_cache_lock); root->ino_cache_state = BTRFS_CACHE_FINISHED; spin_unlock(&root->ino_cache_lock); + wake_up(&root->ino_cache_wait); return; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1b1a9e35e0829eef005da6c5221f2b3a79b84213..250c8403ec67a43eb332d11dd0e54c4320a0817c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5576,7 +5576,6 @@ static void inode_tree_del(struct inode *inode) spin_unlock(&root->inode_lock); if (empty && btrfs_root_refs(&root->root_item) == 0) { - synchronize_srcu(&root->fs_info->subvol_srcu); spin_lock(&root->inode_lock); empty = RB_EMPTY_ROOT(&root->inode_tree); spin_unlock(&root->inode_lock); @@ -9597,9 +9596,8 @@ static int btrfs_rename_exchange(struct inode *old_dir, return -EXDEV; /* close the race window with snapshot create/destroy ioctl */ - if (old_ino == BTRFS_FIRST_FREE_OBJECTID) - down_read(&root->fs_info->subvol_sem); - if (new_ino == BTRFS_FIRST_FREE_OBJECTID) + if (old_ino == BTRFS_FIRST_FREE_OBJECTID || + new_ino == BTRFS_FIRST_FREE_OBJECTID) down_read(&dest->fs_info->subvol_sem); /* @@ -9616,6 +9614,9 @@ static int btrfs_rename_exchange(struct inode *old_dir, goto out_notrans; } + if (dest != root) + btrfs_record_root_in_trans(trans, dest); + /* * We need to find a free sequence number both in the source and * in the destination directory for the exchange. @@ -9782,9 +9783,8 @@ static int btrfs_rename_exchange(struct inode *old_dir, ret2 = btrfs_end_transaction(trans, root); ret = ret ? ret : ret2; out_notrans: - if (new_ino == BTRFS_FIRST_FREE_OBJECTID) - up_read(&dest->fs_info->subvol_sem); - if (old_ino == BTRFS_FIRST_FREE_OBJECTID) + if (new_ino == BTRFS_FIRST_FREE_OBJECTID || + old_ino == BTRFS_FIRST_FREE_OBJECTID) up_read(&root->fs_info->subvol_sem); return ret; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a67143c579aa3f8b5eb3dd9630f1610fba29dfb4..eefe103c65daaea6226eae1bf60b2e195760e597 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -610,12 +610,18 @@ static noinline int create_subvol(struct inode *dir, btrfs_i_size_write(dir, dir->i_size + namelen * 2); ret = btrfs_update_inode(trans, root, dir); - BUG_ON(ret); + if (ret) { + btrfs_abort_transaction(trans, ret); + goto fail; + } ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, objectid, root->root_key.objectid, btrfs_ino(dir), index, name, namelen); - BUG_ON(ret); + if (ret) { + btrfs_abort_transaction(trans, ret); + goto fail; + } ret = btrfs_uuid_tree_add(trans, root->fs_info->uuid_root, root_item->uuid, BTRFS_UUID_KEY_SUBVOL, diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index b2d1e95de7be7e9a9691408aa0e4e357703b6bcd..7dc2284017fab754318c24de33c46f9d14760baf 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -837,10 +837,15 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) } btrfs_start_ordered_extent(inode, ordered, 1); end = ordered->file_offset; + /* + * If the ordered extent had an error save the error but don't + * exit without waiting first for all other ordered extents in + * the range to complete. + */ if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)) ret = -EIO; btrfs_put_ordered_extent(ordered); - if (ret || end == 0 || end == start) + if (end == 0 || end == start) break; end--; } diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c index 94441fdb1ecf133605d30dfd065702d4601d794f..0d1565d712314e07d2776bc92602cec37f4883b8 100644 --- a/fs/btrfs/reada.c +++ b/fs/btrfs/reada.c @@ -734,21 +734,19 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info, static void reada_start_machine_worker(struct btrfs_work *work) { struct reada_machine_work *rmw; - struct btrfs_fs_info *fs_info; int old_ioprio; rmw = container_of(work, struct reada_machine_work, work); - fs_info = rmw->fs_info; - - kfree(rmw); old_ioprio = IOPRIO_PRIO_VALUE(task_nice_ioclass(current), task_nice_ioprio(current)); set_task_ioprio(current, BTRFS_IOPRIO_READA); - __reada_start_machine(fs_info); + __reada_start_machine(rmw->fs_info); set_task_ioprio(current, old_ioprio); - atomic_dec(&fs_info->reada_works_cnt); + atomic_dec(&rmw->fs_info->reada_works_cnt); + + kfree(rmw); } static void __reada_start_machine(struct btrfs_fs_info *fs_info) diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index b0c3a6afe6643a5aec3e104c612e152af7109ee0..b106d365257d3c1167a73da492dbc6c1858a0ada 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -4587,6 +4587,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) reloc_root->root_key.offset); if (IS_ERR(fs_root)) { err = PTR_ERR(fs_root); + list_add_tail(&reloc_root->root_list, &reloc_roots); goto out_free; } diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index d9e49705a28999beb6a94f2379028ba4a01d528d..edfc7ba38b33e44fa16cd48d3b1c5549929bf410 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -36,6 +36,14 @@ #include "transaction.h" #include "compression.h" +/* + * Maximum number of references an extent can have in order for us to attempt to + * issue clone operations instead of write operations. This currently exists to + * avoid hitting limitations of the backreference walking code (taking a lot of + * time and using too much memory for extents with large number of references). + */ +#define SEND_MAX_EXTENT_REFS 64 + /* * A fs_path is a helper to dynamically build path names with unknown size. * It reallocates the internal buffer on demand. @@ -1327,6 +1335,7 @@ static int find_extent_clone(struct send_ctx *sctx, struct clone_root *cur_clone_root; struct btrfs_key found_key; struct btrfs_path *tmp_path; + struct btrfs_extent_item *ei; int compressed; u32 i; @@ -1376,7 +1385,6 @@ static int find_extent_clone(struct send_ctx *sctx, ret = extent_from_logical(fs_info, disk_byte, tmp_path, &found_key, &flags); up_read(&fs_info->commit_root_sem); - btrfs_release_path(tmp_path); if (ret < 0) goto out; @@ -1385,6 +1393,21 @@ static int find_extent_clone(struct send_ctx *sctx, goto out; } + ei = btrfs_item_ptr(tmp_path->nodes[0], tmp_path->slots[0], + struct btrfs_extent_item); + /* + * Backreference walking (iterate_extent_inodes() below) is currently + * too expensive when an extent has a large number of references, both + * in time spent and used memory. So for now just fallback to write + * operations instead of clone operations when an extent has more than + * a certain amount of references. + */ + if (btrfs_extent_refs(tmp_path->nodes[0], ei) > SEND_MAX_EXTENT_REFS) { + ret = -ENOENT; + goto out; + } + btrfs_release_path(tmp_path); + /* * Setup the clone roots. */ diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index a7b69deb6d707b4b5d6a2f318ddd639a31c97004..9286603a6a98b9bd41ec6ee41f95b1469087e1e1 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1809,6 +1809,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) } if (btrfs_super_log_root(fs_info->super_copy) != 0) { + btrfs_warn(fs_info, + "mount required to replay tree-log, cannot remount read-write"); ret = -EINVAL; goto restore; } @@ -2164,7 +2166,15 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) */ thresh = 4 * 1024 * 1024; - if (!mixed && total_free_meta - thresh < block_rsv->size) + /* + * We only want to claim there's no available space if we can no longer + * allocate chunks for our metadata profile and our global reserve will + * not fit in the free metadata space. If we aren't ->full then we + * still can allocate chunks and thus are fine using the currently + * calculated f_bavail. + */ + if (!mixed && block_rsv->space_info->full && + total_free_meta - thresh < block_rsv->size) buf->f_bavail = 0; buf->f_type = BTRFS_SUPER_MAGIC; diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c index bf62ad919a95db4725483000b6110b6e20890214..9edc2674b8a7098b53a4282a3d0fdd4b816a33b9 100644 --- a/fs/btrfs/tests/btrfs-tests.c +++ b/fs/btrfs/tests/btrfs-tests.c @@ -112,7 +112,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void) spin_lock_init(&fs_info->qgroup_op_lock); spin_lock_init(&fs_info->super_lock); spin_lock_init(&fs_info->fs_roots_radix_lock); - spin_lock_init(&fs_info->tree_mod_seq_lock); mutex_init(&fs_info->qgroup_ioctl_lock); mutex_init(&fs_info->qgroup_rescan_lock); rwlock_init(&fs_info->tree_mod_log_lock); diff --git a/fs/btrfs/tests/free-space-tree-tests.c b/fs/btrfs/tests/free-space-tree-tests.c index a724d9a79bd20b63f6f4a589803637fc31a0f2be..5e3b875d87e2fee4ba9e081629ca915600ebe84c 100644 --- a/fs/btrfs/tests/free-space-tree-tests.c +++ b/fs/btrfs/tests/free-space-tree-tests.c @@ -476,9 +476,9 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize, root->node = alloc_test_extent_buffer(root->fs_info, nodesize, nodesize); - if (!root->node) { - test_msg("Couldn't allocate dummy buffer\n"); - ret = -ENOMEM; + if (IS_ERR(root->node)) { + test_msg("couldn't allocate dummy buffer\n"); + ret = PTR_ERR(root->node); goto out; } btrfs_set_header_level(root->node, 0); diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c index 9c6666692341aac6180bca2c2e0f1a20bb23dfd8..e0aa6b9786fa4f6c81ac89bebd6cacc469335ece 100644 --- a/fs/btrfs/tests/qgroup-tests.c +++ b/fs/btrfs/tests/qgroup-tests.c @@ -488,9 +488,9 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) */ root->node = alloc_test_extent_buffer(root->fs_info, nodesize, nodesize); - if (!root->node) { + if (IS_ERR(root->node)) { test_msg("Couldn't allocate dummy buffer\n"); - ret = -ENOMEM; + ret = PTR_ERR(root->node); goto out; } btrfs_set_header_level(root->node, 0); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index fd6c74662e9aef2409cb6e48a77b8d94329a1227..31df020634cdd1a271b721b1ff7c9896ff93dcce 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1917,6 +1917,14 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_transaction *prev_trans = NULL; int ret; + /* + * Some places just start a transaction to commit it. We need to make + * sure that if this commit fails that the abort code actually marks the + * transaction as failed, so set trans->dirty to make the abort code do + * the right thing. + */ + trans->dirty = true; + /* Stop the commit early if ->aborted is set */ if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { ret = cur_trans->aborted; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 65e1eaa5df8422bf4019d7f2c65923ec54526fef..f79682937faf469a90b8526467a903ab62005bbe 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4443,13 +4443,8 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, struct btrfs_file_extent_item); if (btrfs_file_extent_type(leaf, extent) == - BTRFS_FILE_EXTENT_INLINE) { - len = btrfs_file_extent_inline_len(leaf, - path->slots[0], - extent); - ASSERT(len == i_size); + BTRFS_FILE_EXTENT_INLINE) return 0; - } len = btrfs_file_extent_num_bytes(leaf, extent); /* Last extent goes beyond i_size, no need to log a hole. */ @@ -5702,9 +5697,28 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); if (IS_ERR(wc.replay_dest)) { ret = PTR_ERR(wc.replay_dest); + + /* + * We didn't find the subvol, likely because it was + * deleted. This is ok, simply skip this log and go to + * the next one. + * + * We need to exclude the root because we can't have + * other log replays overwriting this log as we'll read + * it back in a few more times. This will keep our + * block from being modified, and we'll just bail for + * each subsequent pass. + */ + if (ret == -ENOENT) + ret = btrfs_pin_extent_for_log_replay(fs_info->extent_root, + log->node->start, + log->node->len); free_extent_buffer(log->node); free_extent_buffer(log->commit_root); kfree(log); + + if (!ret) + goto next; btrfs_handle_fs_error(fs_info, ret, "Couldn't read target root for tree log recovery."); goto error; @@ -5736,7 +5750,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) &root->highest_objectid); } - key.offset = found_key.offset - 1; wc.replay_dest->log_root = NULL; free_extent_buffer(log->node); free_extent_buffer(log->commit_root); @@ -5744,9 +5757,10 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) if (ret) goto error; - +next: if (found_key.offset == 0) break; + key.offset = found_key.offset - 1; } btrfs_release_path(path); diff --git a/fs/btrfs/uuid-tree.c b/fs/btrfs/uuid-tree.c index 83bb2f2aa83c14ecf452762533ec16f283d3450d..ee1c76cf8886a9ca0af1415560ad1e82d806ae39 100644 --- a/fs/btrfs/uuid-tree.c +++ b/fs/btrfs/uuid-tree.c @@ -335,6 +335,8 @@ int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info, } if (ret < 0 && ret != -ENOENT) goto out; + key.offset++; + goto again_search_slot; } item_size -= sizeof(subid_le); offset += sizeof(subid_le); diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 663d66828cca9f43aad990d29c927cf98a484917..96c1b847def6031b0b6d53545b1e9dc40c834899 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -312,7 +312,6 @@ struct btrfs_bio { u64 map_type; /* get from map_lookup->type */ bio_end_io_t *end_io; struct bio *orig_bio; - unsigned long flags; void *private; atomic_t error; int max_errors; diff --git a/fs/char_dev.c b/fs/char_dev.c index a112a4745d8b37919b6344c8dd336c500d84075a..23e0477edf7d64212cd4714e25b6e7a2ffbc3df5 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -336,7 +336,7 @@ static struct kobject *cdev_get(struct cdev *p) if (owner && !try_module_get(owner)) return NULL; - kobj = kobject_get(&p->kobj); + kobj = kobject_get_unless_zero(&p->kobj); if (!kobj) module_put(owner); return kobj; diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 15bac390dff945d7fa5d785f666b2b0291fb9f65..10aedc2a4c2dca122d6e50392b60dd9ea493684c 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -603,7 +603,7 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) *pmode |= (S_IXUGO & (*pbits_to_set)); - cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode); + cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode); return; } @@ -632,7 +632,7 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, if (mode & S_IXUGO) *pace_flags |= SET_FILE_EXEC_RIGHTS; - cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n", + cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n", mode, *pace_flags); return; } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d4f8bb315c61283efff797a6281863566e35b622..a605ec927a2b5139b2dcc064e6d8c935a3912006 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -885,6 +885,7 @@ cifs_demultiplex_thread(void *p) mempool_resize(cifs_req_poolp, length + cifs_min_rcv); set_freezable(); + allow_kernel_signal(SIGKILL); while (server->tcpStatus != CifsExiting) { if (try_to_freeze()) continue; @@ -2221,7 +2222,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) task = xchg(&server->tsk, NULL); if (task) - force_sig(SIGKILL, task); + send_sig(SIGKILL, task, 1); } static struct TCP_Server_Info * @@ -2926,8 +2927,10 @@ match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data) { struct cifs_sb_info *old = CIFS_SB(sb); struct cifs_sb_info *new = mnt_data->cifs_sb; - bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH; - bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH; + bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && + old->prepath; + bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && + new->prepath; if (old_set && new_set && !strcmp(new->prepath, old->prepath)) return 1; @@ -3398,7 +3401,7 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, cifs_sb->mnt_gid = pvolume_info->linux_gid; cifs_sb->mnt_file_mode = pvolume_info->file_mode; cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; - cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n", + cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n", cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); cifs_sb->actimeo = pvolume_info->actimeo; diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index d6475dcce9dfbd7a377c35a7dd832e3b658cdb5a..0262c8f7e7c76274c37f808778cb9be541b9004a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -551,7 +551,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, if (server->ops->close) server->ops->close(xid, tcon, &fid); cifs_del_pending_open(&open); - fput(file); rc = -ENOMEM; } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1c3f262d9c4d4643693b8287e6538381d849cff3..09d83275c20ba00a70fb7e0c96f7daf6f01b8900 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -312,9 +312,6 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, INIT_LIST_HEAD(&fdlocks->locks); fdlocks->cfile = cfile; cfile->llist = fdlocks; - cifs_down_write(&cinode->lock_sem); - list_add(&fdlocks->llist, &cinode->llist); - up_write(&cinode->lock_sem); cfile->count = 1; cfile->pid = current->tgid; @@ -338,6 +335,10 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, oplock = 0; } + cifs_down_write(&cinode->lock_sem); + list_add(&fdlocks->llist, &cinode->llist); + up_write(&cinode->lock_sem); + spin_lock(&tcon->open_file_lock); if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock) oplock = fid->pending_open->oplock; @@ -721,6 +722,13 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; + /* O_SYNC also has bit for O_DSYNC so following check picks up either */ + if (cfile->f_flags & O_SYNC) + create_options |= CREATE_WRITE_THROUGH; + + if (cfile->f_flags & O_DIRECT) + create_options |= CREATE_NO_BUFFER; + if (server->ops->get_lease_key) server->ops->get_lease_key(inode, &cfile->fid); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b1c0961e6b3f2086a135e87a868a5b827dc85b09..dfa85ad5b481464c23cbbce7852b01f8681fb0b6 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1573,7 +1573,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) struct TCP_Server_Info *server; char *full_path; - cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n", + cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n", mode, inode); cifs_sb = CIFS_SB(inode->i_sb); @@ -1990,6 +1990,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) struct inode *inode = d_inode(dentry); struct super_block *sb = dentry->d_sb; char *full_path = NULL; + int count = 0; if (inode == NULL) return -ENOENT; @@ -2011,15 +2012,18 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) full_path, inode, inode->i_count.counter, dentry, cifs_get_time(dentry), jiffies); +again: if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); else rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid, NULL); - + if (rc == -EAGAIN && count++ < 10) + goto again; out: kfree(full_path); free_xid(xid); + return rc; } diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 41f1a5dd33a53ade4cb4cb43d0bf92c167fcb6b8..4dcce3f034f4863e10a4fb810d0f09131130f9a3 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -69,7 +69,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, goto out; - if (oparms->tcon->use_resilient) { + if (oparms->tcon->use_resilient) { nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */ nr_ioctl_req.Reserved = 0; rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid, diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 9994d15a32fcf8e33a8f04a259c5da12921fed4a..7b7b47e26dbd41113d6035ae7380a6598987a058 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -617,10 +617,10 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) spin_lock(&cifs_tcp_ses_lock); list_for_each(tmp, &server->smb_ses_list) { ses = list_entry(tmp, struct cifs_ses, smb_ses_list); + list_for_each(tmp1, &ses->tcon_list) { tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); - cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks); spin_lock(&tcon->open_file_lock); list_for_each(tmp2, &tcon->openFileList) { cfile = list_entry(tmp2, struct cifsFileInfo, @@ -632,6 +632,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) continue; cifs_dbg(FYI, "file id match, oplock break\n"); + cifs_stats_inc( + &tcon->stats.cifs_stats.num_oplock_brks); cinode = CIFS_I(d_inode(cfile->dentry)); spin_lock(&cfile->file_info_lock); if (!CIFS_CACHE_WRITE(cinode) && @@ -664,9 +666,6 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) return true; } spin_unlock(&tcon->open_file_lock); - spin_unlock(&cifs_tcp_ses_lock); - cifs_dbg(FYI, "No matching file for oplock break\n"); - return true; } } spin_unlock(&cifs_tcp_ses_lock); diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 5255deac86b2e8c5f1444c33c577a4a36fd7e686..e8dc28dbe563e88079a7f994d160873c31b1433e 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -247,9 +247,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) */ mutex_lock(&tcon->ses->session_mutex); rc = cifs_negotiate_protocol(0, tcon->ses); - if (!rc && tcon->ses->need_reconnect) + if (!rc && tcon->ses->need_reconnect) { rc = cifs_setup_session(0, tcon->ses, nls_codepage); - + if ((rc == -EACCES) && !tcon->retry) { + rc = -EHOSTDOWN; + mutex_unlock(&tcon->ses->session_mutex); + goto failed; + } + } if (rc || !tcon->need_reconnect) { mutex_unlock(&tcon->ses->session_mutex); goto out; @@ -291,6 +296,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) case SMB2_SET_INFO: rc = -EAGAIN; } +failed: unload_nls(nls_codepage); return rc; } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 5b832e83772a691698d1a5aae4e916a1f391d0e2..02ac9067a35424610f39a05307e842ce92f25533 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1585,9 +1585,10 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, #endif case FICLONE: + goto do_ioctl; case FICLONERANGE: case FIDEDUPERANGE: - goto do_ioctl; + goto found_handler; case FIBMAP: case FIGETBSZ: diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 30e4e01db35a3bca724e50361cf5f4f1c14559c6..b14bb2c4604263e0d9be31bc1ad14545959a15b7 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -800,6 +800,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) dlm_delete_debug_file(ls); + idr_destroy(&ls->ls_recover_idr); kfree(ls->ls_recover_buf); /* diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index 7cd24bccd4fe56aab54db611c4587a8bdc51a7e8..37be29f21d04df27c08840b6c7b45346834c006d 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c @@ -38,10 +38,8 @@ int __init dlm_memory_init(void) void dlm_memory_exit(void) { - if (lkb_cache) - kmem_cache_destroy(lkb_cache); - if (rsb_cache) - kmem_cache_destroy(rsb_cache); + kmem_cache_destroy(lkb_cache); + kmem_cache_destroy(rsb_cache); } char *dlm_allocate_lvb(struct dlm_ls *ls) @@ -86,8 +84,7 @@ void dlm_free_lkb(struct dlm_lkb *lkb) struct dlm_user_args *ua; ua = lkb->lkb_ua; if (ua) { - if (ua->lksb.sb_lvbptr) - kfree(ua->lksb.sb_lvbptr); + kfree(ua->lksb.sb_lvbptr); kfree(ua); } } diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 57f2aacec97f59df9cf39f7dd5308a8d075f4547..bb0d307deadd321d0571d88a6a11f03ceac0d9bb 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -25,6 +25,7 @@ #include "lvb_table.h" #include "user.h" #include "ast.h" +#include "config.h" static const char name_prefix[] = "dlm"; static const struct file_operations device_fops; @@ -402,7 +403,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - error = dlm_new_lockspace(params->name, NULL, params->flags, + error = dlm_new_lockspace(params->name, dlm_config.ci_cluster_name, params->flags, DLM_USER_LVB_LEN, NULL, NULL, NULL, &lockspace); if (error) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index cb77e7ee2c9f0a5064b3857fa3a1dd0a9614961e..ff6cf23be8a21d6e546e5062c878aced73b7ef69 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -339,8 +339,10 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct extent_crypt_result ecr; int rc = 0; - BUG_ON(!crypt_stat || !crypt_stat->tfm - || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)); + if (!crypt_stat || !crypt_stat->tfm + || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) + return -EINVAL; + if (unlikely(ecryptfs_verbosity > 0)) { ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n", crypt_stat->key_size); diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index fa218cd64f746d2c924a786edc1c6052911c1732..b134315fb69d060974a252a1ccd2191a9be865c3 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1335,7 +1335,7 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, printk(KERN_WARNING "Tag 1 packet contains key larger " "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES"); rc = -EINVAL; - goto out; + goto out_free; } memcpy((*new_auth_tok)->session_key.encrypted_key, &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2))); diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 4f457d5c49331cb7b813b5c9ca4257bd59ce5c3b..26464f9d9b769dc4250d40e923dd4f73e7ee6e74 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -397,6 +397,7 @@ int __init ecryptfs_init_messaging(void) * ecryptfs_message_buf_len), GFP_KERNEL); if (!ecryptfs_msg_ctx_arr) { + kfree(ecryptfs_daemon_hash); rc = -ENOMEM; printk(KERN_ERR "%s: Failed to allocate memory\n", __func__); goto out; diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 7a7bba7c2328480a74bba77cfc31716d4568713e..1730122b10e06109ef9d2a05f7b1e656a3492594 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -146,6 +146,7 @@ static struct dentry *reconnect_one(struct vfsmount *mnt, tmp = lookup_one_len_unlocked(nbuf, parent, strlen(nbuf)); if (IS_ERR(tmp)) { dprintk("%s: lookup failed: %d\n", __func__, PTR_ERR(tmp)); + err = PTR_ERR(tmp); goto out_err; } if (tmp != dentry) { @@ -506,26 +507,33 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, * inode is actually connected to the parent. */ err = exportfs_get_name(mnt, target_dir, nbuf, result); - if (!err) { - inode_lock(target_dir->d_inode); - nresult = lookup_one_len(nbuf, target_dir, - strlen(nbuf)); - inode_unlock(target_dir->d_inode); - if (!IS_ERR(nresult)) { - if (nresult->d_inode) { - dput(result); - result = nresult; - } else - dput(nresult); - } + if (err) { + dput(target_dir); + goto err_result; } + inode_lock(target_dir->d_inode); + nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf)); + if (!IS_ERR(nresult)) { + if (unlikely(nresult->d_inode != result->d_inode)) { + dput(nresult); + nresult = ERR_PTR(-ESTALE); + } + } + inode_unlock(target_dir->d_inode); /* * At this point we are done with the parent, but it's pinned * by the child dentry anyway. */ dput(target_dir); + if (IS_ERR(nresult)) { + err = PTR_ERR(nresult); + goto err_result; + } + dput(result); + result = nresult; + /* * And finally make sure the dentry is actually acceptable * to NFSD. diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 85449a6ddc564dfcba455febf406e0587210fce5..fe664949d442831d97e92eb897983da4a4eab085 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -697,10 +697,13 @@ static int ext2_get_blocks(struct inode *inode, if (!partial) { count++; mutex_unlock(&ei->truncate_mutex); - if (err) - goto cleanup; goto got_it; } + + if (err) { + mutex_unlock(&ei->truncate_mutex); + goto cleanup; + } } /* diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 6fcb29b393d3cb56538383b94b741c33a49d68eb..186912c9bf565c129d9d3bda98443e1c55471783 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1047,9 +1047,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) if (EXT2_BLOCKS_PER_GROUP(sb) == 0) goto cantfind_ext2; - sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) - - le32_to_cpu(es->s_first_data_block) - 1) - / EXT2_BLOCKS_PER_GROUP(sb)) + 1; + sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) - + le32_to_cpu(es->s_first_data_block) - 1) + / EXT2_BLOCKS_PER_GROUP(sb)) + 1; db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) / EXT2_DESC_PER_BLOCK(sb); sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL); diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 2455fe1446d626efd83d8a0fb4a4cb28d561cd31..de601f3c023d8b01fcc06f3ca5a209fe9d325e06 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -279,6 +279,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, ext4_group_t ngroups = ext4_get_groups_count(sb); struct ext4_group_desc *desc; struct ext4_sb_info *sbi = EXT4_SB(sb); + struct buffer_head *bh_p; if (block_group >= ngroups) { ext4_error(sb, "block_group >= groups_count - block_group = %u," @@ -289,7 +290,14 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb); offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1); - if (!sbi->s_group_desc[group_desc]) { + bh_p = sbi_array_rcu_deref(sbi, s_group_desc, group_desc); + /* + * sbi_array_rcu_deref returns with rcu unlocked, this is ok since + * the pointer being dereferenced won't be dereferenced again. By + * looking at the usage in add_new_gdb() the value isn't modified, + * just the pointer, and so it remains valid. + */ + if (!bh_p) { ext4_error(sb, "Group descriptor not loaded - " "block_group = %u, group_desc = %u, desc = %u", block_group, group_desc, offset); @@ -297,10 +305,10 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, } desc = (struct ext4_group_desc *)( - (__u8 *)sbi->s_group_desc[group_desc]->b_data + + (__u8 *)bh_p->b_data + offset * EXT4_DESC_SIZE(sb)); if (bh) - *bh = sbi->s_group_desc[group_desc]; + *bh = bh_p; return desc; } diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 9aa4a18b95fa5bffef267fcf8638710ca7c18b86..022d67f5424f57302fe93c5900e547e3169bd01c 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -75,6 +75,11 @@ int __ext4_check_dir_entry(const char *function, unsigned int line, error_msg = "rec_len is too small for name_len"; else if (unlikely(((char *) de - buf) + rlen > size)) error_msg = "directory entry overrun"; + else if (unlikely(((char *) de - buf) + rlen > + size - EXT4_DIR_REC_LEN(1) && + ((char *) de - buf) + rlen != size)) { + error_msg = "directory entry too close to block end"; + } else if (unlikely(le32_to_cpu(de->inode) > le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))) error_msg = "inode out of bounds"; @@ -119,12 +124,14 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) if (err != ERR_BAD_DX_DIR) { return err; } - /* - * We don't set the inode dirty flag since it's not - * critical that it get flushed back to the disk. - */ - ext4_clear_inode_flag(file_inode(file), - EXT4_INODE_INDEX); + /* Can we just clear INDEX flag to ignore htree information? */ + if (!ext4_has_metadata_csum(sb)) { + /* + * We don't set the inode dirty flag since it's not + * critical that it gets flushed back to the disk. + */ + ext4_clear_inode_flag(inode, EXT4_INODE_INDEX); + } } if (ext4_has_inline_data(inode)) { diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 2255c07402306ed3512639e2dcf2bd3426a98123..9261599849ef3b8a847d1f13064fe0f56f6a8bc2 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1366,7 +1366,7 @@ struct ext4_sb_info { loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ struct buffer_head * s_sbh; /* Buffer containing the super block */ struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */ - struct buffer_head **s_group_desc; + struct buffer_head * __rcu *s_group_desc; unsigned int s_mount_opt; unsigned int s_mount_opt2; unsigned int s_mount_flags; @@ -1426,7 +1426,7 @@ struct ext4_sb_info { #endif /* for buddy allocator */ - struct ext4_group_info ***s_group_info; + struct ext4_group_info ** __rcu *s_group_info; struct inode *s_buddy_cache; spinlock_t s_md_lock; unsigned short *s_mb_offsets; @@ -1474,7 +1474,7 @@ struct ext4_sb_info { unsigned int s_extent_max_zeroout_kb; unsigned int s_log_groups_per_flex; - struct flex_groups *s_flex_groups; + struct flex_groups * __rcu *s_flex_groups; ext4_group_t s_flex_groups_allocated; /* workqueue for reserved extent conversions (buffered io) */ @@ -1513,8 +1513,11 @@ struct ext4_sb_info { struct ratelimit_state s_warning_ratelimit_state; struct ratelimit_state s_msg_ratelimit_state; - /* Barrier between changing inodes' journal flags and writepages ops. */ - struct percpu_rw_semaphore s_journal_flag_rwsem; + /* + * Barrier between writepages ops and changing any inode's JOURNAL_DATA + * or EXTENTS flag. + */ + struct percpu_rw_semaphore s_writepages_rwsem; }; static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) @@ -1539,6 +1542,23 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); } +/* + * Returns: sbi->field[index] + * Used to access an array element from the following sbi fields which require + * rcu protection to avoid dereferencing an invalid pointer due to reassignment + * - s_group_desc + * - s_group_info + * - s_flex_group + */ +#define sbi_array_rcu_deref(sbi, field, index) \ +({ \ + typeof(*((sbi)->field)) _v; \ + rcu_read_lock(); \ + _v = ((typeof(_v)*)rcu_dereference((sbi)->field))[index]; \ + rcu_read_unlock(); \ + _v; \ +}) + /* * Inode dynamic state flags */ @@ -2367,8 +2387,11 @@ void ext4_insert_dentry(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_iget() should have caught this... */ + WARN_ON_ONCE(ext4_has_feature_metadata_csum(inode->i_sb)); ext4_clear_inode_flag(inode, EXT4_INODE_INDEX); + } } static const unsigned char ext4_filetype_table[] = { DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK @@ -2544,6 +2567,7 @@ extern int ext4_generic_delete_entry(handle_t *handle, extern bool ext4_empty_dir(struct inode *inode); /* resize.c */ +extern void ext4_kvfree_array_rcu(void *to_free); extern int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input); extern int ext4_group_extend(struct super_block *sb, @@ -2784,13 +2808,13 @@ static inline struct ext4_group_info *ext4_get_group_info(struct super_block *sb, ext4_group_t group) { - struct ext4_group_info ***grp_info; + struct ext4_group_info **grp_info; long indexv, indexh; BUG_ON(group >= EXT4_SB(sb)->s_groups_count); - grp_info = EXT4_SB(sb)->s_group_info; indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb)); indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1); - return grp_info[indexv][indexh]; + grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv); + return grp_info[indexh]; } /* @@ -2840,7 +2864,7 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) !inode_is_locked(inode)); down_write(&EXT4_I(inode)->i_data_sem); if (newsize > EXT4_I(inode)->i_disksize) - EXT4_I(inode)->i_disksize = newsize; + WRITE_ONCE(EXT4_I(inode)->i_disksize, newsize); up_write(&EXT4_I(inode)->i_data_sem); } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index e37e5f1435b94f2af6c12a4e5dc710db69c8fa44..358ad1f5704f6e1d840fb69433b75eb7894ca91f 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -331,11 +331,13 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) percpu_counter_inc(&sbi->s_freeinodes_counter); if (sbi->s_log_groups_per_flex) { - ext4_group_t f = ext4_flex_group(sbi, block_group); + struct flex_groups *fg; - atomic_inc(&sbi->s_flex_groups[f].free_inodes); + fg = sbi_array_rcu_deref(sbi, s_flex_groups, + ext4_flex_group(sbi, block_group)); + atomic_inc(&fg->free_inodes); if (is_directory) - atomic_dec(&sbi->s_flex_groups[f].used_dirs); + atomic_dec(&fg->used_dirs); } BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata"); fatal = ext4_handle_dirty_metadata(handle, NULL, bh2); @@ -376,12 +378,13 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g, int flex_size, struct orlov_stats *stats) { struct ext4_group_desc *desc; - struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups; if (flex_size > 1) { - stats->free_inodes = atomic_read(&flex_group[g].free_inodes); - stats->free_clusters = atomic64_read(&flex_group[g].free_clusters); - stats->used_dirs = atomic_read(&flex_group[g].used_dirs); + struct flex_groups *fg = sbi_array_rcu_deref(EXT4_SB(sb), + s_flex_groups, g); + stats->free_inodes = atomic_read(&fg->free_inodes); + stats->free_clusters = atomic64_read(&fg->free_clusters); + stats->used_dirs = atomic_read(&fg->used_dirs); return; } @@ -988,7 +991,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, if (sbi->s_log_groups_per_flex) { ext4_group_t f = ext4_flex_group(sbi, group); - atomic_inc(&sbi->s_flex_groups[f].used_dirs); + atomic_inc(&sbi_array_rcu_deref(sbi, s_flex_groups, + f)->used_dirs); } } if (ext4_has_group_desc_csum(sb)) { @@ -1011,7 +1015,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, if (sbi->s_log_groups_per_flex) { flex_group = ext4_flex_group(sbi, group); - atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes); + atomic_dec(&sbi_array_rcu_deref(sbi, s_flex_groups, + flex_group)->free_inodes); } inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb); diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index f786e254dbb455a35134db2b74298efdb9cc1c41..7e777624072a4ca1baf11014ad6a75c9df225710 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1431,7 +1431,7 @@ int htree_inlinedir_to_tree(struct file *dir_file, err = ext4_htree_store_dirent(dir_file, hinfo->hash, hinfo->minor_hash, de, &tmp_str); if (err) { - count = err; + ret = err; goto out; } count++; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c7b58657bfb17883b63308d0b56757a9aee06ddc..fd545f362c3ab48c64dab2b92108bd237ec3e9b5 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2492,7 +2492,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, * truncate are avoided by checking i_size under i_data_sem. */ disksize = ((loff_t)mpd->first_page) << PAGE_SHIFT; - if (disksize > EXT4_I(inode)->i_disksize) { + if (disksize > READ_ONCE(EXT4_I(inode)->i_disksize)) { int err2; loff_t i_size; @@ -2659,7 +2659,7 @@ static int ext4_writepages(struct address_space *mapping, struct blk_plug plug; bool give_up_on_write = false; - percpu_down_read(&sbi->s_journal_flag_rwsem); + percpu_down_read(&sbi->s_writepages_rwsem); trace_ext4_writepages(inode, wbc); if (dax_mapping(mapping)) { @@ -2860,7 +2860,7 @@ static int ext4_writepages(struct address_space *mapping, out_writepages: trace_ext4_writepages_result(inode, wbc, ret, nr_to_write - wbc->nr_to_write); - percpu_up_read(&sbi->s_journal_flag_rwsem); + percpu_up_read(&sbi->s_writepages_rwsem); return ret; } @@ -4660,6 +4660,18 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ret = -EFSCORRUPTED; goto bad_inode; } + /* + * If dir_index is not enabled but there's dir with INDEX flag set, + * we'd normally treat htree data as empty space. But with metadata + * checksumming that corrupts checksums so forbid that. + */ + if (!ext4_has_feature_dir_index(sb) && ext4_has_metadata_csum(sb) && + ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) { + EXT4_ERROR_INODE(inode, + "iget: Dir with htree data on filesystem without dir_index feature."); + ret = -EFSCORRUPTED; + goto bad_inode; + } ei->i_disksize = inode->i_size; #ifdef CONFIG_QUOTA ei->i_reserved_quota = 0; @@ -5146,11 +5158,15 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode) offset = inode->i_size & (PAGE_SIZE - 1); /* - * All buffers in the last page remain valid? Then there's nothing to - * do. We do the check mainly to optimize the common PAGE_SIZE == - * blocksize case + * If the page is fully truncated, we don't need to wait for any commit + * (and we even should not as __ext4_journalled_invalidatepage() may + * strip all buffers from the page but keep the page dirty which can then + * confuse e.g. concurrent ext4_writepage() seeing dirty page without + * buffers). Also we don't need to wait for any commit if all buffers in + * the page remain valid. This is most beneficial for the common case of + * blocksize == PAGESIZE. */ - if (offset > PAGE_SIZE - i_blocksize(inode)) + if (!offset || offset > (PAGE_SIZE - i_blocksize(inode))) return; while (1) { page = find_lock_page(inode->i_mapping, @@ -5538,10 +5554,25 @@ static int ext4_expand_extra_isize(struct inode *inode, { struct ext4_inode *raw_inode; struct ext4_xattr_ibody_header *header; + unsigned int inode_size = EXT4_INODE_SIZE(inode->i_sb); + struct ext4_inode_info *ei = EXT4_I(inode); if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) return 0; + /* this was checked at iget time, but double check for good measure */ + if ((EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > inode_size) || + (ei->i_extra_isize & 3)) { + EXT4_ERROR_INODE(inode, "bad extra_isize %u (inode size %u)", + ei->i_extra_isize, + EXT4_INODE_SIZE(inode->i_sb)); + return -EFSCORRUPTED; + } + if ((new_extra_isize < ei->i_extra_isize) || + (new_extra_isize < 4) || + (new_extra_isize > inode_size - EXT4_GOOD_OLD_INODE_SIZE)) + return -EINVAL; /* Should never happen */ + raw_inode = ext4_raw_inode(&iloc); header = IHDR(inode, raw_inode); @@ -5727,7 +5758,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) } } - percpu_down_write(&sbi->s_journal_flag_rwsem); + percpu_down_write(&sbi->s_writepages_rwsem); jbd2_journal_lock_updates(journal); /* @@ -5744,7 +5775,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) err = jbd2_journal_flush(journal); if (err < 0) { jbd2_journal_unlock_updates(journal); - percpu_up_write(&sbi->s_journal_flag_rwsem); + percpu_up_write(&sbi->s_writepages_rwsem); ext4_inode_resume_unlocked_dio(inode); return err; } @@ -5753,7 +5784,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) ext4_set_aops(inode); jbd2_journal_unlock_updates(journal); - percpu_up_write(&sbi->s_journal_flag_rwsem); + percpu_up_write(&sbi->s_writepages_rwsem); if (val) up_write(&EXT4_I(inode)->i_mmap_sem); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 3d6f73e38873ebb735a2f4815db33d1e4c09a4c4..471686ea3e18b5f5ee22fedd82b9c4c71eb75b52 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2377,7 +2377,7 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups) { struct ext4_sb_info *sbi = EXT4_SB(sb); unsigned size; - struct ext4_group_info ***new_groupinfo; + struct ext4_group_info ***old_groupinfo, ***new_groupinfo; size = (ngroups + EXT4_DESC_PER_BLOCK(sb) - 1) >> EXT4_DESC_PER_BLOCK_BITS(sb); @@ -2390,13 +2390,16 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups) ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group"); return -ENOMEM; } - if (sbi->s_group_info) { - memcpy(new_groupinfo, sbi->s_group_info, + rcu_read_lock(); + old_groupinfo = rcu_dereference(sbi->s_group_info); + if (old_groupinfo) + memcpy(new_groupinfo, old_groupinfo, sbi->s_group_info_size * sizeof(*sbi->s_group_info)); - kvfree(sbi->s_group_info); - } - sbi->s_group_info = new_groupinfo; + rcu_read_unlock(); + rcu_assign_pointer(sbi->s_group_info, new_groupinfo); sbi->s_group_info_size = size / sizeof(*sbi->s_group_info); + if (old_groupinfo) + ext4_kvfree_array_rcu(old_groupinfo); ext4_debug("allocated s_groupinfo array for %d meta_bg's\n", sbi->s_group_info_size); return 0; @@ -2408,6 +2411,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, { int i; int metalen = 0; + int idx = group >> EXT4_DESC_PER_BLOCK_BITS(sb); struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_group_info **meta_group_info; struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); @@ -2426,12 +2430,12 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, "for a buddy group"); goto exit_meta_group_info; } - sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] = - meta_group_info; + rcu_read_lock(); + rcu_dereference(sbi->s_group_info)[idx] = meta_group_info; + rcu_read_unlock(); } - meta_group_info = - sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)]; + meta_group_info = sbi_array_rcu_deref(sbi, s_group_info, idx); i = group & (EXT4_DESC_PER_BLOCK(sb) - 1); meta_group_info[i] = kmem_cache_zalloc(cachep, GFP_NOFS); @@ -2479,8 +2483,13 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, exit_group_info: /* If a meta_group_info table has been allocated, release it now */ if (group % EXT4_DESC_PER_BLOCK(sb) == 0) { - kfree(sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)]); - sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] = NULL; + struct ext4_group_info ***group_info; + + rcu_read_lock(); + group_info = rcu_dereference(sbi->s_group_info); + kfree(group_info[idx]); + group_info[idx] = NULL; + rcu_read_unlock(); } exit_meta_group_info: return -ENOMEM; @@ -2493,6 +2502,7 @@ static int ext4_mb_init_backend(struct super_block *sb) struct ext4_sb_info *sbi = EXT4_SB(sb); int err; struct ext4_group_desc *desc; + struct ext4_group_info ***group_info; struct kmem_cache *cachep; err = ext4_mb_alloc_groupinfo(sb, ngroups); @@ -2527,11 +2537,16 @@ static int ext4_mb_init_backend(struct super_block *sb) while (i-- > 0) kmem_cache_free(cachep, ext4_get_group_info(sb, i)); i = sbi->s_group_info_size; + rcu_read_lock(); + group_info = rcu_dereference(sbi->s_group_info); while (i-- > 0) - kfree(sbi->s_group_info[i]); + kfree(group_info[i]); + rcu_read_unlock(); iput(sbi->s_buddy_cache); err_freesgi: - kvfree(sbi->s_group_info); + rcu_read_lock(); + kvfree(rcu_dereference(sbi->s_group_info)); + rcu_read_unlock(); return -ENOMEM; } @@ -2720,7 +2735,7 @@ int ext4_mb_release(struct super_block *sb) ext4_group_t ngroups = ext4_get_groups_count(sb); ext4_group_t i; int num_meta_group_infos; - struct ext4_group_info *grinfo; + struct ext4_group_info *grinfo, ***group_info; struct ext4_sb_info *sbi = EXT4_SB(sb); struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); @@ -2738,9 +2753,12 @@ int ext4_mb_release(struct super_block *sb) num_meta_group_infos = (ngroups + EXT4_DESC_PER_BLOCK(sb) - 1) >> EXT4_DESC_PER_BLOCK_BITS(sb); + rcu_read_lock(); + group_info = rcu_dereference(sbi->s_group_info); for (i = 0; i < num_meta_group_infos; i++) - kfree(sbi->s_group_info[i]); - kvfree(sbi->s_group_info); + kfree(group_info[i]); + kvfree(group_info); + rcu_read_unlock(); } kfree(sbi->s_mb_offsets); kfree(sbi->s_mb_maxs); @@ -2999,7 +3017,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, ext4_group_t flex_group = ext4_flex_group(sbi, ac->ac_b_ex.fe_group); atomic64_sub(ac->ac_b_ex.fe_len, - &sbi->s_flex_groups[flex_group].free_clusters); + &sbi_array_rcu_deref(sbi, s_flex_groups, + flex_group)->free_clusters); } err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); @@ -4890,7 +4909,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, if (sbi->s_log_groups_per_flex) { ext4_group_t flex_group = ext4_flex_group(sbi, block_group); atomic64_add(count_clusters, - &sbi->s_flex_groups[flex_group].free_clusters); + &sbi_array_rcu_deref(sbi, s_flex_groups, + flex_group)->free_clusters); } if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE)) @@ -5035,7 +5055,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, if (sbi->s_log_groups_per_flex) { ext4_group_t flex_group = ext4_flex_group(sbi, block_group); atomic64_add(EXT4_NUM_B2C(sbi, blocks_freed), - &sbi->s_flex_groups[flex_group].free_clusters); + &sbi_array_rcu_deref(sbi, s_flex_groups, + flex_group)->free_clusters); } ext4_mb_unload_buddy(&e4b); diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index 364ea4d4a94377d2763f0abc66298a323e5b14ef..bce2d696d6b9c656f55d01d072c741209c343596 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -434,6 +434,7 @@ static int free_ext_block(handle_t *handle, struct inode *inode) int ext4_ext_migrate(struct inode *inode) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); handle_t *handle; int retval = 0, i; __le32 *i_data; @@ -458,6 +459,8 @@ int ext4_ext_migrate(struct inode *inode) */ return retval; + percpu_down_write(&sbi->s_writepages_rwsem); + /* * Worst case we can touch the allocation bitmaps, a bgd * block, and a block to link in the orphan list. We do need @@ -468,7 +471,7 @@ int ext4_ext_migrate(struct inode *inode) if (IS_ERR(handle)) { retval = PTR_ERR(handle); - return retval; + goto out_unlock; } goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) * EXT4_INODES_PER_GROUP(inode->i_sb)) + 1; @@ -479,7 +482,7 @@ int ext4_ext_migrate(struct inode *inode) if (IS_ERR(tmp_inode)) { retval = PTR_ERR(tmp_inode); ext4_journal_stop(handle); - return retval; + goto out_unlock; } i_size_write(tmp_inode, i_size_read(inode)); /* @@ -521,7 +524,7 @@ int ext4_ext_migrate(struct inode *inode) */ ext4_orphan_del(NULL, tmp_inode); retval = PTR_ERR(handle); - goto out; + goto out_tmp_inode; } ei = EXT4_I(inode); @@ -602,10 +605,11 @@ int ext4_ext_migrate(struct inode *inode) /* Reset the extent details */ ext4_ext_tree_init(handle, tmp_inode); ext4_journal_stop(handle); -out: +out_tmp_inode: unlock_new_inode(tmp_inode); iput(tmp_inode); - +out_unlock: + percpu_up_write(&sbi->s_writepages_rwsem); return retval; } @@ -615,7 +619,8 @@ int ext4_ext_migrate(struct inode *inode) int ext4_ind_migrate(struct inode *inode) { struct ext4_extent_header *eh; - struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + struct ext4_super_block *es = sbi->s_es; struct ext4_inode_info *ei = EXT4_I(inode); struct ext4_extent *ex; unsigned int i, len; @@ -639,9 +644,13 @@ int ext4_ind_migrate(struct inode *inode) if (test_opt(inode->i_sb, DELALLOC)) ext4_alloc_da_blocks(inode); + percpu_down_write(&sbi->s_writepages_rwsem); + handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); - if (IS_ERR(handle)) - return PTR_ERR(handle); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); + goto out_unlock; + } down_write(&EXT4_I(inode)->i_data_sem); ret = ext4_ext_check_inode(inode); @@ -676,5 +685,7 @@ int ext4_ind_migrate(struct inode *inode) errout: ext4_journal_stop(handle); up_write(&EXT4_I(inode)->i_data_sem); +out_unlock: + percpu_up_write(&sbi->s_writepages_rwsem); return ret; } diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index c2e830a6206d083d8928f96c53d3bf8e2ee326a8..fb1ad9510c5f6d67e2bc1e38224f68d3e81bd2a2 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -119,10 +119,10 @@ void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp, { __ext4_warning(sb, function, line, "%s", msg); __ext4_warning(sb, function, line, - "MMP failure info: last update time: %llu, last update " - "node: %s, last update device: %s", - (long long unsigned int) le64_to_cpu(mmp->mmp_time), - mmp->mmp_nodename, mmp->mmp_bdevname); + "MMP failure info: last update time: %llu, last update node: %.*s, last update device: %.*s", + (unsigned long long)le64_to_cpu(mmp->mmp_time), + (int)sizeof(mmp->mmp_nodename), mmp->mmp_nodename, + (int)sizeof(mmp->mmp_bdevname), mmp->mmp_bdevname); } /* @@ -153,6 +153,7 @@ static int kmmpd(void *data) mmp_check_interval = max(EXT4_MMP_CHECK_MULT * mmp_update_interval, EXT4_MMP_MIN_CHECK_INTERVAL); mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval); + BUILD_BUG_ON(sizeof(mmp->mmp_bdevname) < BDEVNAME_SIZE); bdevname(bh->b_bdev, mmp->mmp_bdevname); memcpy(mmp->mmp_nodename, init_utsname()->nodename, @@ -377,7 +378,8 @@ int ext4_multi_mount_protect(struct super_block *sb, /* * Start a kernel thread to update the MMP block periodically. */ - EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%s", + EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%.*s", + (int)sizeof(mmp->mmp_bdevname), bdevname(bh->b_bdev, mmp->mmp_bdevname)); if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) { diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 50e12c9120585d3e6b4f42ff64684cab3f9b66af..7f3015a509f88efcc207e9104874ad505b693ee0 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1406,6 +1406,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir, /* * We deal with the read-ahead logic here. */ + cond_resched(); if (ra_ptr >= ra_max) { /* Refill the readahead buffer */ ra_ptr = 0; @@ -2108,6 +2109,13 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, retval = ext4_dx_add_entry(handle, &fname, dir, inode); if (!retval || (retval != ERR_BAD_DX_DIR)) goto out; + /* Can we just ignore htree data? */ + if (ext4_has_metadata_csum(sb)) { + EXT4_ERROR_INODE(dir, + "Directory has corrupted htree index."); + retval = -EFSCORRUPTED; + goto out; + } ext4_clear_inode_flag(dir, EXT4_INODE_INDEX); dx_fallback++; ext4_mark_inode_dirty(handle, dir); @@ -2681,7 +2689,7 @@ bool ext4_empty_dir(struct inode *inode) { unsigned int offset; struct buffer_head *bh; - struct ext4_dir_entry_2 *de, *de1; + struct ext4_dir_entry_2 *de; struct super_block *sb; if (ext4_has_inline_data(inode)) { @@ -2706,19 +2714,25 @@ bool ext4_empty_dir(struct inode *inode) return true; de = (struct ext4_dir_entry_2 *) bh->b_data; - de1 = ext4_next_entry(de, sb->s_blocksize); - if (le32_to_cpu(de->inode) != inode->i_ino || - le32_to_cpu(de1->inode) == 0 || - strcmp(".", de->name) || strcmp("..", de1->name)) { - ext4_warning_inode(inode, "directory missing '.' and/or '..'"); + if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, + 0) || + le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) { + ext4_warning_inode(inode, "directory missing '.'"); brelse(bh); return true; } - offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) + - ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize); - de = ext4_next_entry(de1, sb->s_blocksize); + offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); + de = ext4_next_entry(de, sb->s_blocksize); + if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, + offset) || + le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) { + ext4_warning_inode(inode, "directory missing '..'"); + brelse(bh); + return true; + } + offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); while (offset < inode->i_size) { - if ((void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { + if (!(offset & (sb->s_blocksize - 1))) { unsigned int lblock; brelse(bh); lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb); @@ -2729,12 +2743,11 @@ bool ext4_empty_dir(struct inode *inode) } if (IS_ERR(bh)) return true; - de = (struct ext4_dir_entry_2 *) bh->b_data; } + de = (struct ext4_dir_entry_2 *) (bh->b_data + + (offset & (sb->s_blocksize - 1))); if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, offset)) { - de = (struct ext4_dir_entry_2 *)(bh->b_data + - sb->s_blocksize); offset = (offset | (sb->s_blocksize - 1)) + 1; continue; } @@ -2743,7 +2756,6 @@ bool ext4_empty_dir(struct inode *inode) return false; } offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); - de = ext4_next_entry(de, sb->s_blocksize); } brelse(bh); return true; @@ -3038,18 +3050,17 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) if (IS_DIRSYNC(dir)) ext4_handle_sync(handle); - if (inode->i_nlink == 0) { - ext4_warning_inode(inode, "Deleting file '%.*s' with no links", - dentry->d_name.len, dentry->d_name.name); - set_nlink(inode, 1); - } retval = ext4_delete_entry(handle, dir, de, bh); if (retval) goto end_unlink; dir->i_ctime = dir->i_mtime = ext4_current_time(dir); ext4_update_dx_flag(dir); ext4_mark_inode_dirty(handle, dir); - drop_nlink(inode); + if (inode->i_nlink == 0) + ext4_warning_inode(inode, "Deleting file '%.*s' with no links", + dentry->d_name.len, dentry->d_name.name); + else + drop_nlink(inode); if (!inode->i_nlink) ext4_orphan_add(handle, inode); inode->i_ctime = ext4_current_time(inode); diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 55bda9fac2f92109326fcfa2131b1fe2332ca831..c1b02899cfc2945cd181ae405e1169d18d95a278 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -471,18 +471,27 @@ int ext4_bio_write_page(struct ext4_io_submit *io, if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) { gfp_t gfp_flags = GFP_NOFS; + /* + * Since bounce page allocation uses a mempool, we can only use + * a waiting mask (i.e. request guaranteed allocation) on the + * first page of the bio. Otherwise it can deadlock. + */ + if (io->io_bio) + gfp_flags = GFP_NOWAIT | __GFP_NOWARN; retry_encrypt: if (!fscrypt_using_hardware_encryption(inode)) data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0, page->index, gfp_flags); if (IS_ERR(data_page)) { ret = PTR_ERR(data_page); - if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { - if (io->io_bio) { + if (ret == -ENOMEM && + (io->io_bio || wbc->sync_mode == WB_SYNC_ALL)) { + gfp_flags = GFP_NOFS; + if (io->io_bio) ext4_io_submit(io); - congestion_wait(BLK_RW_ASYNC, HZ/50); - } - gfp_flags |= __GFP_NOFAIL; + else + gfp_flags |= __GFP_NOFAIL; + congestion_wait(BLK_RW_ASYNC, HZ/50); goto retry_encrypt; } data_page = NULL; diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index aef2a24dc9f941d8e3aeed67bcdc20a20bf5f521..845d9841c91c244fcdea7e77eed5e40b5e726178 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -16,6 +16,33 @@ #include "ext4_jbd2.h" +struct ext4_rcu_ptr { + struct rcu_head rcu; + void *ptr; +}; + +static void ext4_rcu_ptr_callback(struct rcu_head *head) +{ + struct ext4_rcu_ptr *ptr; + + ptr = container_of(head, struct ext4_rcu_ptr, rcu); + kvfree(ptr->ptr); + kfree(ptr); +} + +void ext4_kvfree_array_rcu(void *to_free) +{ + struct ext4_rcu_ptr *ptr = kzalloc(sizeof(*ptr), GFP_KERNEL); + + if (ptr) { + ptr->ptr = to_free; + call_rcu(&ptr->rcu, ext4_rcu_ptr_callback); + return; + } + synchronize_rcu(); + kvfree(to_free); +} + int ext4_resize_begin(struct super_block *sb) { struct ext4_sb_info *sbi = EXT4_SB(sb); @@ -541,8 +568,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb, brelse(gdb); goto out; } - memcpy(gdb->b_data, sbi->s_group_desc[j]->b_data, - gdb->b_size); + memcpy(gdb->b_data, sbi_array_rcu_deref(sbi, + s_group_desc, j)->b_data, gdb->b_size); set_buffer_uptodate(gdb); err = ext4_handle_dirty_metadata(handle, NULL, gdb); @@ -849,13 +876,15 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, } brelse(dind); - o_group_desc = EXT4_SB(sb)->s_group_desc; + rcu_read_lock(); + o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc); memcpy(n_group_desc, o_group_desc, EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); + rcu_read_unlock(); n_group_desc[gdb_num] = gdb_bh; - EXT4_SB(sb)->s_group_desc = n_group_desc; + rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc); EXT4_SB(sb)->s_gdb_count++; - kvfree(o_group_desc); + ext4_kvfree_array_rcu(o_group_desc); le16_add_cpu(&es->s_reserved_gdt_blocks, -1); err = ext4_handle_dirty_super(handle, sb); @@ -903,9 +932,11 @@ static int add_new_gdb_meta_bg(struct super_block *sb, return err; } - o_group_desc = EXT4_SB(sb)->s_group_desc; + rcu_read_lock(); + o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc); memcpy(n_group_desc, o_group_desc, EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); + rcu_read_unlock(); n_group_desc[gdb_num] = gdb_bh; BUFFER_TRACE(gdb_bh, "get_write_access"); @@ -916,9 +947,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb, return err; } - EXT4_SB(sb)->s_group_desc = n_group_desc; + rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc); EXT4_SB(sb)->s_gdb_count++; - kvfree(o_group_desc); + ext4_kvfree_array_rcu(o_group_desc); return err; } @@ -1180,7 +1211,8 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb, * use non-sparse filesystems anymore. This is already checked above. */ if (gdb_off) { - gdb_bh = sbi->s_group_desc[gdb_num]; + gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, + gdb_num); BUFFER_TRACE(gdb_bh, "get_write_access"); err = ext4_journal_get_write_access(handle, gdb_bh); @@ -1262,7 +1294,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb, /* * get_write_access() has been called on gdb_bh by ext4_add_new_desc(). */ - gdb_bh = sbi->s_group_desc[gdb_num]; + gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, gdb_num); /* Update group descriptor block for new group */ gdp = (struct ext4_group_desc *)(gdb_bh->b_data + gdb_off * EXT4_DESC_SIZE(sb)); @@ -1390,11 +1422,14 @@ static void ext4_update_super(struct super_block *sb, percpu_counter_read(&sbi->s_freeclusters_counter)); if (ext4_has_feature_flex_bg(sb) && sbi->s_log_groups_per_flex) { ext4_group_t flex_group; + struct flex_groups *fg; + flex_group = ext4_flex_group(sbi, group_data[0].group); + fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group); atomic64_add(EXT4_NUM_B2C(sbi, free_blocks), - &sbi->s_flex_groups[flex_group].free_clusters); + &fg->free_clusters); atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count, - &sbi->s_flex_groups[flex_group].free_inodes); + &fg->free_inodes); } /* @@ -1489,7 +1524,8 @@ static int ext4_flex_group_add(struct super_block *sb, for (; gdb_num <= gdb_num_end; gdb_num++) { struct buffer_head *gdb_bh; - gdb_bh = sbi->s_group_desc[gdb_num]; + gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, + gdb_num); if (old_gdb == gdb_bh->b_blocknr) continue; update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 90a1bbb1b3842627206cab6a3febf2ad47c94ecf..38f2e5fea5fa2fb67fcc37614d67b0a50014ec28 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -826,6 +826,8 @@ static void ext4_put_super(struct super_block *sb) { struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; + struct buffer_head **group_desc; + struct flex_groups **flex_groups; int aborted = 0; int i, err; @@ -857,15 +859,23 @@ static void ext4_put_super(struct super_block *sb) if (!(sb->s_flags & MS_RDONLY)) ext4_commit_super(sb, 1); + rcu_read_lock(); + group_desc = rcu_dereference(sbi->s_group_desc); for (i = 0; i < sbi->s_gdb_count; i++) - brelse(sbi->s_group_desc[i]); - kvfree(sbi->s_group_desc); - kvfree(sbi->s_flex_groups); + brelse(group_desc[i]); + kvfree(group_desc); + flex_groups = rcu_dereference(sbi->s_flex_groups); + if (flex_groups) { + for (i = 0; i < sbi->s_flex_groups_allocated; i++) + kvfree(flex_groups[i]); + kvfree(flex_groups); + } + rcu_read_unlock(); percpu_counter_destroy(&sbi->s_freeclusters_counter); percpu_counter_destroy(&sbi->s_freeinodes_counter); percpu_counter_destroy(&sbi->s_dirs_counter); percpu_counter_destroy(&sbi->s_dirtyclusters_counter); - percpu_free_rwsem(&sbi->s_journal_flag_rwsem); + percpu_free_rwsem(&sbi->s_writepages_rwsem); brelse(sbi->s_sbh); #ifdef CONFIG_QUOTA for (i = 0; i < EXT4_MAXQUOTAS; i++) @@ -2116,8 +2126,8 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup) { struct ext4_sb_info *sbi = EXT4_SB(sb); - struct flex_groups *new_groups; - int size; + struct flex_groups **old_groups, **new_groups; + int size, i, j; if (!sbi->s_log_groups_per_flex) return 0; @@ -2126,22 +2136,37 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup) if (size <= sbi->s_flex_groups_allocated) return 0; - size = roundup_pow_of_two(size * sizeof(struct flex_groups)); - new_groups = ext4_kvzalloc(size, GFP_KERNEL); + new_groups = ext4_kvzalloc(roundup_pow_of_two(size * + sizeof(*sbi->s_flex_groups)), GFP_KERNEL); if (!new_groups) { - ext4_msg(sb, KERN_ERR, "not enough memory for %d flex groups", - size / (int) sizeof(struct flex_groups)); + ext4_msg(sb, KERN_ERR, + "not enough memory for %d flex group pointers", size); return -ENOMEM; } - - if (sbi->s_flex_groups) { - memcpy(new_groups, sbi->s_flex_groups, - (sbi->s_flex_groups_allocated * - sizeof(struct flex_groups))); - kvfree(sbi->s_flex_groups); + for (i = sbi->s_flex_groups_allocated; i < size; i++) { + new_groups[i] = ext4_kvzalloc(roundup_pow_of_two( + sizeof(struct flex_groups)), + GFP_KERNEL); + if (!new_groups[i]) { + for (j = sbi->s_flex_groups_allocated; j < i; j++) + kvfree(new_groups[j]); + kvfree(new_groups); + ext4_msg(sb, KERN_ERR, + "not enough memory for %d flex groups", size); + return -ENOMEM; + } } - sbi->s_flex_groups = new_groups; - sbi->s_flex_groups_allocated = size / sizeof(struct flex_groups); + rcu_read_lock(); + old_groups = rcu_dereference(sbi->s_flex_groups); + if (old_groups) + memcpy(new_groups, old_groups, + (sbi->s_flex_groups_allocated * + sizeof(struct flex_groups *))); + rcu_read_unlock(); + rcu_assign_pointer(sbi->s_flex_groups, new_groups); + sbi->s_flex_groups_allocated = size; + if (old_groups) + ext4_kvfree_array_rcu(old_groups); return 0; } @@ -2149,6 +2174,7 @@ static int ext4_fill_flex_info(struct super_block *sb) { struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_group_desc *gdp = NULL; + struct flex_groups *fg; ext4_group_t flex_group; int i, err; @@ -2166,12 +2192,11 @@ static int ext4_fill_flex_info(struct super_block *sb) gdp = ext4_get_group_desc(sb, i, NULL); flex_group = ext4_flex_group(sbi, i); - atomic_add(ext4_free_inodes_count(sb, gdp), - &sbi->s_flex_groups[flex_group].free_inodes); + fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group); + atomic_add(ext4_free_inodes_count(sb, gdp), &fg->free_inodes); atomic64_add(ext4_free_group_clusters(sb, gdp), - &sbi->s_flex_groups[flex_group].free_clusters); - atomic_add(ext4_used_dirs_count(sb, gdp), - &sbi->s_flex_groups[flex_group].used_dirs); + &fg->free_clusters); + atomic_add(ext4_used_dirs_count(sb, gdp), &fg->used_dirs); } return 1; @@ -2750,17 +2775,11 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) return 0; } -#ifndef CONFIG_QUOTA - if (ext4_has_feature_quota(sb) && !readonly) { +#if !IS_ENABLED(CONFIG_QUOTA) || !IS_ENABLED(CONFIG_QFMT_V2) + if (!readonly && (ext4_has_feature_quota(sb) || + ext4_has_feature_project(sb))) { ext4_msg(sb, KERN_ERR, - "Filesystem with quota feature cannot be mounted RDWR " - "without CONFIG_QUOTA"); - return 0; - } - if (ext4_has_feature_project(sb) && !readonly) { - ext4_msg(sb, KERN_ERR, - "Filesystem with project quota feature cannot be mounted RDWR " - "without CONFIG_QUOTA"); + "The kernel was not built with CONFIG_QUOTA and CONFIG_QFMT_V2"); return 0; } #endif /* CONFIG_QUOTA */ @@ -3349,6 +3368,40 @@ int ext4_calculate_overhead(struct super_block *sb) return 0; } +static void ext4_clamp_want_extra_isize(struct super_block *sb) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_super_block *es = sbi->s_es; + unsigned def_extra_isize = sizeof(struct ext4_inode) - + EXT4_GOOD_OLD_INODE_SIZE; + + if (sbi->s_inode_size == EXT4_GOOD_OLD_INODE_SIZE) { + sbi->s_want_extra_isize = 0; + return; + } + if (sbi->s_want_extra_isize < 4) { + sbi->s_want_extra_isize = def_extra_isize; + if (ext4_has_feature_extra_isize(sb)) { + if (sbi->s_want_extra_isize < + le16_to_cpu(es->s_want_extra_isize)) + sbi->s_want_extra_isize = + le16_to_cpu(es->s_want_extra_isize); + if (sbi->s_want_extra_isize < + le16_to_cpu(es->s_min_extra_isize)) + sbi->s_want_extra_isize = + le16_to_cpu(es->s_min_extra_isize); + } + } + /* Check if enough inode space is available */ + if ((sbi->s_want_extra_isize > sbi->s_inode_size) || + (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize > + sbi->s_inode_size)) { + sbi->s_want_extra_isize = def_extra_isize; + ext4_msg(sb, KERN_INFO, + "required extra inode space not available"); + } +} + static void ext4_set_resv_clusters(struct super_block *sb) { ext4_fsblk_t resv_clusters; @@ -3382,9 +3435,10 @@ static void ext4_set_resv_clusters(struct super_block *sb) static int ext4_fill_super(struct super_block *sb, void *data, int silent) { char *orig_data = kstrdup(data, GFP_KERNEL); - struct buffer_head *bh; + struct buffer_head *bh, **group_desc; struct ext4_super_block *es = NULL; struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); + struct flex_groups **flex_groups; ext4_fsblk_t block; ext4_fsblk_t sb_block = get_sb_block(&data); ext4_fsblk_t logical_sb_block; @@ -3934,9 +3988,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; } } - sbi->s_group_desc = ext4_kvmalloc(db_count * + rcu_assign_pointer(sbi->s_group_desc, + ext4_kvmalloc(db_count * sizeof(struct buffer_head *), - GFP_KERNEL); + GFP_KERNEL)); if (sbi->s_group_desc == NULL) { ext4_msg(sb, KERN_ERR, "not enough memory"); ret = -ENOMEM; @@ -3946,14 +4001,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) bgl_lock_init(sbi->s_blockgroup_lock); for (i = 0; i < db_count; i++) { + struct buffer_head *bh; + block = descriptor_loc(sb, logical_sb_block, i); - sbi->s_group_desc[i] = sb_bread_unmovable(sb, block); - if (!sbi->s_group_desc[i]) { + bh = sb_bread_unmovable(sb, block); + if (!bh) { ext4_msg(sb, KERN_ERR, "can't read group descriptor %d", i); db_count = i; goto failed_mount2; } + rcu_read_lock(); + rcu_dereference(sbi->s_group_desc)[i] = bh; + rcu_read_unlock(); } sbi->s_gdb_count = db_count; if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) { @@ -4165,29 +4225,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY)) sb->s_flags |= MS_RDONLY; - /* determine the minimum size of new large inodes, if present */ - if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) { - sbi->s_want_extra_isize = sizeof(struct ext4_inode) - - EXT4_GOOD_OLD_INODE_SIZE; - if (ext4_has_feature_extra_isize(sb)) { - if (sbi->s_want_extra_isize < - le16_to_cpu(es->s_want_extra_isize)) - sbi->s_want_extra_isize = - le16_to_cpu(es->s_want_extra_isize); - if (sbi->s_want_extra_isize < - le16_to_cpu(es->s_min_extra_isize)) - sbi->s_want_extra_isize = - le16_to_cpu(es->s_min_extra_isize); - } - } - /* Check if enough inode space is available */ - if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize > - sbi->s_inode_size) { - sbi->s_want_extra_isize = sizeof(struct ext4_inode) - - EXT4_GOOD_OLD_INODE_SIZE; - ext4_msg(sb, KERN_INFO, "required extra inode space not" - "available"); - } + ext4_clamp_want_extra_isize(sb); ext4_set_resv_clusters(sb); @@ -4226,7 +4264,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0, GFP_KERNEL); if (!err) - err = percpu_init_rwsem(&sbi->s_journal_flag_rwsem); + err = percpu_init_rwsem(&sbi->s_writepages_rwsem); if (err) { ext4_msg(sb, KERN_ERR, "insufficient memory"); @@ -4314,13 +4352,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ext4_unregister_li_request(sb); failed_mount6: ext4_mb_release(sb); - if (sbi->s_flex_groups) - kvfree(sbi->s_flex_groups); + rcu_read_lock(); + flex_groups = rcu_dereference(sbi->s_flex_groups); + if (flex_groups) { + for (i = 0; i < sbi->s_flex_groups_allocated; i++) + kvfree(flex_groups[i]); + kvfree(flex_groups); + } + rcu_read_unlock(); percpu_counter_destroy(&sbi->s_freeclusters_counter); percpu_counter_destroy(&sbi->s_freeinodes_counter); percpu_counter_destroy(&sbi->s_dirs_counter); percpu_counter_destroy(&sbi->s_dirtyclusters_counter); - percpu_free_rwsem(&sbi->s_journal_flag_rwsem); + percpu_free_rwsem(&sbi->s_writepages_rwsem); failed_mount5: ext4_ext_release(sb); ext4_release_system_zone(sb); @@ -4347,9 +4391,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (sbi->s_mmp_tsk) kthread_stop(sbi->s_mmp_tsk); failed_mount2: + rcu_read_lock(); + group_desc = rcu_dereference(sbi->s_group_desc); for (i = 0; i < db_count; i++) - brelse(sbi->s_group_desc[i]); - kvfree(sbi->s_group_desc); + brelse(group_desc[i]); + kvfree(group_desc); + rcu_read_unlock(); failed_mount: if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); @@ -4963,6 +5010,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; } + ext4_clamp_want_extra_isize(sb); + if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^ test_opt(sb, JOURNAL_CHECKSUM)) { ext4_msg(sb, KERN_ERR, "changing journal_checksum " diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e0ffff64285caddc2e08cd5d2cf3cb3fdfc18aaa..20402f4cd1feb81fc31cffeea19a7b954eb60bdc 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2118,7 +2118,7 @@ static int __write_data_page(struct page *page, bool *submitted, loff_t i_size = i_size_read(inode); const pgoff_t end_index = ((unsigned long long) i_size) >> PAGE_SHIFT; - loff_t psize = (page->index + 1) << PAGE_SHIFT; + loff_t psize = (loff_t)(page->index + 1) << PAGE_SHIFT; unsigned offset = 0; bool need_balance_fs = false; int err = 0; diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 96019fc4f6fd9dfd6c23df3d2b0d0d65f714498b..e21905089e16a18680706593dfaee2c5b3261f18 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1137,7 +1137,7 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode, } dn.ofs_in_node++; i++; - new_size = (dst + i) << PAGE_SHIFT; + new_size = (loff_t)(dst + i) << PAGE_SHIFT; if (dst_inode->i_size < new_size) f2fs_i_size_write(dst_inode, new_size); } while (--ilen && (do_replace[i] || blkaddr[i] == NULL_ADDR)); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index eea5bc2a9aae33517db37dfaf0b63d629beab32b..7e2ef060d07f8c3a9df677465a1e411d02531bfc 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -736,6 +736,13 @@ static struct inode *fat_alloc_inode(struct super_block *sb) return NULL; init_rwsem(&ei->truncate_lock); + /* Zeroing to allow iput() even if partial initialized inode. */ + ei->mmu_private = 0; + ei->i_start = 0; + ei->i_logstart = 0; + ei->i_attrs = 0; + ei->i_pos = 0; + return &ei->vfs_inode; } @@ -1367,16 +1374,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, return 0; } -static void fat_dummy_inode_init(struct inode *inode) -{ - /* Initialize this dummy inode to work as no-op. */ - MSDOS_I(inode)->mmu_private = 0; - MSDOS_I(inode)->i_start = 0; - MSDOS_I(inode)->i_logstart = 0; - MSDOS_I(inode)->i_attrs = 0; - MSDOS_I(inode)->i_pos = 0; -} - static int fat_read_root(struct inode *inode) { struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); @@ -1821,13 +1818,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, fat_inode = new_inode(sb); if (!fat_inode) goto out_fail; - fat_dummy_inode_init(fat_inode); sbi->fat_inode = fat_inode; fsinfo_inode = new_inode(sb); if (!fsinfo_inode) goto out_fail; - fat_dummy_inode_init(fsinfo_inode); fsinfo_inode->i_ino = MSDOS_FSINFO_INO; sbi->fsinfo_inode = fsinfo_inode; insert_inode_hash(fsinfo_inode); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 108329e70307f54958f61ef9d7c709876fe02066..a24f5a9750ddfbdfefbd375509ff9094b4a1cffb 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -234,7 +234,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) kfree(forget); if (ret == -ENOMEM) goto out; - if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) + if (ret || fuse_invalid_attr(&outarg.attr) || + (outarg.attr.mode ^ inode->i_mode) & S_IFMT) goto invalid; forget_all_cached_acls(inode); @@ -343,6 +344,12 @@ int fuse_valid_type(int m) S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); } +bool fuse_invalid_attr(struct fuse_attr *attr) +{ + return !fuse_valid_type(attr->mode) || + attr->size > LLONG_MAX; +} + int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, struct fuse_entry_out *outarg, struct inode **inode) { @@ -374,7 +381,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name err = -EIO; if (!outarg->nodeid) goto out_put_forget; - if (!fuse_valid_type(outarg->attr.mode)) + if (fuse_invalid_attr(&outarg->attr)) goto out_put_forget; *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, @@ -498,7 +505,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, goto out_free_ff; err = -EIO; - if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) + if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) || + fuse_invalid_attr(&outentry.attr)) goto out_free_ff; ff->fh = outopen.fh; @@ -606,7 +614,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, goto out_put_forget_req; err = -EIO; - if (invalid_nodeid(outarg.nodeid)) + if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr)) goto out_put_forget_req; if ((outarg.attr.mode ^ mode) & S_IFMT) @@ -879,7 +887,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, spin_lock(&fc->lock); fi->attr_version = ++fc->attr_version; - inc_nlink(inode); + if (likely(inode->i_nlink < UINT_MAX)) + inc_nlink(inode); spin_unlock(&fc->lock); fuse_invalidate_attr(inode); fuse_update_ctime(inode); @@ -959,7 +968,8 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, args.out.args[0].value = &outarg; err = fuse_simple_request(fc, &args); if (!err) { - if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { + if (fuse_invalid_attr(&outarg.attr) || + (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { make_bad_inode(inode); err = -EIO; } else { @@ -1267,7 +1277,7 @@ static int fuse_direntplus_link(struct file *file, if (invalid_nodeid(o->nodeid)) return -EIO; - if (!fuse_valid_type(o->attr.mode)) + if (fuse_invalid_attr(&o->attr)) return -EIO; fc = get_fuse_conn(dir); @@ -1744,7 +1754,8 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, goto error; } - if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { + if (fuse_invalid_attr(&outarg.attr) || + (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { make_bad_inode(inode); err = -EIO; goto error; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 2c1e88c35a07f147f8811a6ebf37b8f737749bb5..c8d9c6620090d9ba13997a566624de7db4cf5b06 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -912,6 +912,8 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc); */ int fuse_valid_type(int m); +bool fuse_invalid_attr(struct fuse_attr *attr); + /** * Is current process allowed to perform filesystem operation? */ diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index bd6202b70447c8edbdfa1e1339d341d605d61c0e..daad7b04f88c06d4084669f6d276c181f6dc9bf2 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1248,7 +1248,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry, if (!(*opened & FILE_OPENED)) return finish_no_open(file, d); dput(d); - return 0; + return excl && (flags & O_CREAT) ? -EEXIST : 0; } BUG_ON(d != NULL); diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 4d5a5a4cc017cd4cf9b21627be97ba7189e9b1a2..addb0784dd1c4a824fb9100ec8c971975613d300 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -168,7 +168,7 @@ void __jbd2_log_wait_for_space(journal_t *journal) "journal space in %s\n", __func__, journal->j_devname); WARN_ON(1); - jbd2_journal_abort(journal, 0); + jbd2_journal_abort(journal, -EIO); } write_lock(&journal->j_state_lock); } else { diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 10ec276761913727ca98cf3c703d394d5beb2fc8..1d06f81ee8b4706c4a9c75a60f9d8a7435b0ffcc 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -722,7 +722,6 @@ void jbd2_journal_commit_transaction(journal_t *journal) submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); } cond_resched(); - stats.run.rs_blocks_logged += bufs; /* Force a new descriptor to be generated next time round the loop. */ @@ -780,7 +779,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) err = journal_submit_commit_record(journal, commit_transaction, &cbh, crc32_sum); if (err) - __jbd2_journal_abort_hard(journal); + jbd2_journal_abort(journal, err); } blk_finish_plug(&plug); @@ -809,6 +808,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) if (unlikely(!buffer_uptodate(bh))) err = -EIO; jbd2_unfile_log_bh(bh); + stats.run.rs_blocks_logged++; /* * The list contains temporary buffer heads created by @@ -854,6 +854,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile"); clear_buffer_jwrite(bh); jbd2_unfile_log_bh(bh); + stats.run.rs_blocks_logged++; __brelse(bh); /* One for getblk */ /* AKPM: bforget here */ } @@ -871,10 +872,11 @@ void jbd2_journal_commit_transaction(journal_t *journal) err = journal_submit_commit_record(journal, commit_transaction, &cbh, crc32_sum); if (err) - __jbd2_journal_abort_hard(journal); + jbd2_journal_abort(journal, err); } if (cbh) err = journal_wait_on_commit_record(journal, cbh); + stats.run.rs_blocks_logged++; if (jbd2_has_feature_async_commit(journal) && journal->j_flags & JBD2_BARRIER) { blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL); @@ -967,29 +969,33 @@ void jbd2_journal_commit_transaction(journal_t *journal) * it. */ /* - * A buffer which has been freed while still being journaled by - * a previous transaction. - */ - if (buffer_freed(bh)) { + * A buffer which has been freed while still being journaled + * by a previous transaction, refile the buffer to BJ_Forget of + * the running transaction. If the just committed transaction + * contains "add to orphan" operation, we can completely + * invalidate the buffer now. We are rather through in that + * since the buffer may be still accessible when blocksize < + * pagesize and it is attached to the last partial page. + */ + if (buffer_freed(bh) && !jh->b_next_transaction) { + struct address_space *mapping; + + clear_buffer_freed(bh); + clear_buffer_jbddirty(bh); + /* - * If the running transaction is the one containing - * "add to orphan" operation (b_next_transaction != - * NULL), we have to wait for that transaction to - * commit before we can really get rid of the buffer. - * So just clear b_modified to not confuse transaction - * credit accounting and refile the buffer to - * BJ_Forget of the running transaction. If the just - * committed transaction contains "add to orphan" - * operation, we can completely invalidate the buffer - * now. We are rather through in that since the - * buffer may be still accessible when blocksize < - * pagesize and it is attached to the last partial - * page. + * Block device buffers need to stay mapped all the + * time, so it is enough to clear buffer_jbddirty and + * buffer_freed bits. For the file mapping buffers (i.e. + * journalled data) we need to unmap buffer and clear + * more bits. We also need to be careful about the check + * because the data page mapping can get cleared under + * out hands, which alse need not to clear more bits + * because the page and buffers will be freed and can + * never be reused once we are done with them. */ - jh->b_modified = 0; - if (!jh->b_next_transaction) { - clear_buffer_freed(bh); - clear_buffer_jbddirty(bh); + mapping = READ_ONCE(bh->b_page->mapping); + if (mapping && !sb_is_blkdev_sb(mapping->host->i_sb)) { clear_buffer_mapped(bh); clear_buffer_new(bh); clear_buffer_req(bh); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 3cbcf649ac660bd6193c87cb5ffa449be0561fd3..efc8cfd0607301673af51a3404b8732cf26918b5 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1670,6 +1670,11 @@ int jbd2_journal_load(journal_t *journal) journal->j_devname); return -EFSCORRUPTED; } + /* + * clear JBD2_ABORT flag initialized in journal_init_common + * here to update log tail information with the newest seq. + */ + journal->j_flags &= ~JBD2_ABORT; /* OK, we've finished with the dynamic journal bits: * reinitialise the dynamic contents of the superblock in memory @@ -1677,7 +1682,6 @@ int jbd2_journal_load(journal_t *journal) if (journal_reset(journal)) goto recovery_error; - journal->j_flags &= ~JBD2_ABORT; journal->j_flags |= JBD2_LOADED; return 0; @@ -2096,12 +2100,10 @@ static void __journal_abort_soft (journal_t *journal, int errno) __jbd2_journal_abort_hard(journal); - if (errno) { - jbd2_journal_update_sb_errno(journal); - write_lock(&journal->j_state_lock); - journal->j_flags |= JBD2_REC_ERR; - write_unlock(&journal->j_state_lock); - } + jbd2_journal_update_sb_errno(journal); + write_lock(&journal->j_state_lock); + journal->j_flags |= JBD2_REC_ERR; + write_unlock(&journal->j_state_lock); } /** @@ -2143,11 +2145,6 @@ static void __journal_abort_soft (journal_t *journal, int errno) * failure to disk. ext3_error, for example, now uses this * functionality. * - * Errors which originate from within the journaling layer will NOT - * supply an errno; a null errno implies that absolutely no further - * writes are done to the journal (unless there are any already in - * progress). - * */ void jbd2_journal_abort(journal_t *journal, int errno) diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 799f96c67211d8b179aa668b369880133bc60277..8de458d64134a77799f7f8c7441c07f13cf789c1 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1037,8 +1037,8 @@ static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh, /* For undo access buffer must have data copied */ if (undo && !jh->b_committed_data) goto out; - if (jh->b_transaction != handle->h_transaction && - jh->b_next_transaction != handle->h_transaction) + if (READ_ONCE(jh->b_transaction) != handle->h_transaction && + READ_ONCE(jh->b_next_transaction) != handle->h_transaction) goto out; /* * There are two reasons for the barrier here: @@ -2213,14 +2213,16 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, return -EBUSY; } /* - * OK, buffer won't be reachable after truncate. We just set - * j_next_transaction to the running transaction (if there is - * one) and mark buffer as freed so that commit code knows it - * should clear dirty bits when it is done with the buffer. + * OK, buffer won't be reachable after truncate. We just clear + * b_modified to not confuse transaction credit accounting, and + * set j_next_transaction to the running transaction (if there + * is one) and mark buffer as freed so that commit code knows + * it should clear dirty bits when it is done with the buffer. */ set_buffer_freed(bh); if (journal->j_running_transaction && buffer_jbddirty(bh)) jh->b_next_transaction = journal->j_running_transaction; + jh->b_modified = 0; jbd2_journal_put_journal_head(jh); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); @@ -2446,8 +2448,8 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh) * our jh reference and thus __jbd2_journal_file_buffer() must not * take a new one. */ - jh->b_transaction = jh->b_next_transaction; - jh->b_next_transaction = NULL; + WRITE_ONCE(jh->b_transaction, jh->b_next_transaction); + WRITE_ONCE(jh->b_next_transaction, NULL); if (buffer_freed(bh)) jlist = BJ_Forget; else if (jh->b_modified) diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 4d973524c887990fd0ba4727362e8a70917783a4..224ef034004b7d28a5fcdcc9d1aefe100b92ff7a 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -1928,8 +1928,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * header ? */ if (tlck->type & tlckTRUNCATE) { - /* This odd declaration suppresses a bogus gcc warning */ - pxd_t pxd = pxd; /* truncated extent of xad */ + pxd_t pxd; /* truncated extent of xad */ int twm; /* diff --git a/fs/locks.c b/fs/locks.c index 22c5b4aa49611ac46cb50dbf4fc8ef25ec500b34..8252647c6084f58963141fdb4dc5db22e0c11d4c 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2681,7 +2681,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, } if (inode) { /* userspace relies on this representation of dev_t */ - seq_printf(f, "%d %02x:%02x:%ld ", fl_pid, + seq_printf(f, "%d %02x:%02x:%lu ", fl_pid, MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev), inode->i_ino); } else { diff --git a/fs/namei.c b/fs/namei.c index 8369bd0339f448b5d3c474b8b7ca12cb5628dd22..60937b87f779f669ae7ea77b36f1bfacee0d14c8 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1110,7 +1110,8 @@ static int may_linkat(struct path *link) * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory * should be allowed, or not, on files that already * exist. - * @dir: the sticky parent directory + * @dir_mode: mode bits of directory + * @dir_uid: owner of directory * @inode: the inode of the file to open * * Block an O_CREAT open of a FIFO (or a regular file) when: @@ -1126,18 +1127,18 @@ static int may_linkat(struct path *link) * * Returns 0 if the open is allowed, -ve on error. */ -static int may_create_in_sticky(struct dentry * const dir, +static int may_create_in_sticky(umode_t dir_mode, kuid_t dir_uid, struct inode * const inode) { if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) || (!sysctl_protected_regular && S_ISREG(inode->i_mode)) || - likely(!(dir->d_inode->i_mode & S_ISVTX)) || - uid_eq(inode->i_uid, dir->d_inode->i_uid) || + likely(!(dir_mode & S_ISVTX)) || + uid_eq(inode->i_uid, dir_uid) || uid_eq(current_fsuid(), inode->i_uid)) return 0; - if (likely(dir->d_inode->i_mode & 0002) || - (dir->d_inode->i_mode & 0020 && + if (likely(dir_mode & 0002) || + (dir_mode & 0020 && ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) || (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) { return -EACCES; @@ -1468,7 +1469,7 @@ static int follow_dotdot_rcu(struct nameidata *nd) nd->path.dentry = parent; nd->seq = seq; if (unlikely(!path_connected(&nd->path))) - return -ENOENT; + return -ECHILD; break; } else { struct mount *mnt = real_mount(nd->path.mnt); @@ -3379,6 +3380,8 @@ static int do_last(struct nameidata *nd, int *opened) { struct dentry *dir = nd->path.dentry; + kuid_t dir_uid = nd->inode->i_uid; + umode_t dir_mode = nd->inode->i_mode; int open_flag = op->open_flag; bool will_truncate = (open_flag & O_TRUNC) != 0; bool got_write = false; @@ -3521,7 +3524,7 @@ static int do_last(struct nameidata *nd, error = -EISDIR; if (d_is_dir(nd->path.dentry)) goto out; - error = may_create_in_sticky(dir, + error = may_create_in_sticky(dir_mode, dir_uid, d_backing_inode(nd->path.dentry)); if (unlikely(error)) goto out; diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index b1daeafbea9206eb6cd04114f1350faa4b2af72a..c3428767332c27e6abf5415e619bf3ce889dd865 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -89,7 +89,7 @@ config NFS_V4 config NFS_SWAP bool "Provide swap over NFS support" default n - depends on NFS_FS + depends on NFS_FS && SWAP select SUNRPC_SWAP help This option enables swapon to work on files located on NFS mounts. diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 9d7537446260b58aebfca9368c026b42eefa1082..0d4a56c77a1a98b82b0801959b12128b59c30a47 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -419,7 +419,7 @@ static bool referring_call_exists(struct nfs_client *clp, uint32_t nrclists, struct referring_call_list *rclists) { - bool status = 0; + bool status = false; int i, j; struct nfs4_session *session; struct nfs4_slot_table *tbl; diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 9a8830a0f31f953dcd50e2f6b54de32fed7da760..014039618cff052c0a74b9cb1b2dfd58deb64e00 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -234,6 +234,8 @@ static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation spin_lock(&delegation->lock); if (delegation->inode != NULL) inode = igrab(delegation->inode); + if (!inode) + set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags); spin_unlock(&delegation->lock); return inode; } @@ -867,10 +869,11 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp) list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { list_for_each_entry_rcu(delegation, &server->delegations, super_list) { - if (test_bit(NFS_DELEGATION_RETURNING, - &delegation->flags)) - continue; - if (test_bit(NFS_DELEGATION_NEED_RECLAIM, + if (test_bit(NFS_DELEGATION_INODE_FREEING, + &delegation->flags) || + test_bit(NFS_DELEGATION_RETURNING, + &delegation->flags) || + test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0) continue; if (!nfs_sb_active(server->super)) @@ -975,10 +978,11 @@ void nfs_reap_expired_delegations(struct nfs_client *clp) list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { list_for_each_entry_rcu(delegation, &server->delegations, super_list) { - if (test_bit(NFS_DELEGATION_RETURNING, - &delegation->flags)) - continue; - if (test_bit(NFS_DELEGATION_TEST_EXPIRED, + if (test_bit(NFS_DELEGATION_INODE_FREEING, + &delegation->flags) || + test_bit(NFS_DELEGATION_RETURNING, + &delegation->flags) || + test_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags) == 0) continue; if (!nfs_sb_active(server->super)) diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 2c6cb7fb7d5ee1c4c288d1486e782b028b15184b..f72095bf9e1074ac505ca81136c6055a8950187e 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -33,6 +33,7 @@ enum { NFS_DELEGATION_RETURNING, NFS_DELEGATION_REVOKED, NFS_DELEGATION_TEST_EXPIRED, + NFS_DELEGATION_INODE_FREEING, }; int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 1e5321d1ed2265f3d78b4e76192d6305ef4ba6ff..2517fcd423b68eac7dabf4ce8c8bbd364e4eb0b8 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -57,7 +57,7 @@ static void nfs_readdir_clear_array(struct page*); const struct file_operations nfs_dir_operations = { .llseek = nfs_llseek_dir, .read = generic_read_dir, - .iterate_shared = nfs_readdir, + .iterate = nfs_readdir, .open = nfs_opendir, .release = nfs_closedir, .fsync = nfs_fsync_dir, @@ -145,7 +145,6 @@ struct nfs_cache_array_entry { }; struct nfs_cache_array { - atomic_t refcount; int size; int eof_index; u64 last_cookie; @@ -170,6 +169,17 @@ typedef struct { unsigned int eof:1; } nfs_readdir_descriptor_t; +static +void nfs_readdir_init_array(struct page *page) +{ + struct nfs_cache_array *array; + + array = kmap_atomic(page); + memset(array, 0, sizeof(struct nfs_cache_array)); + array->eof_index = -1; + kunmap_atomic(array); +} + /* * The caller is responsible for calling nfs_readdir_release_array(page) */ @@ -201,18 +211,10 @@ void nfs_readdir_clear_array(struct page *page) int i; array = kmap_atomic(page); - if (atomic_dec_and_test(&array->refcount)) - for (i = 0; i < array->size; i++) - kfree(array->array[i].string.name); - kunmap_atomic(array); -} - -static bool grab_page(struct page *page) -{ - struct nfs_cache_array *array = kmap_atomic(page); - bool res = atomic_inc_not_zero(&array->refcount); + for (i = 0; i < array->size; i++) + kfree(array->array[i].string.name); + array->size = 0; kunmap_atomic(array); - return res; } /* @@ -287,7 +289,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri desc->cache_entry_index = index; return 0; out_eof: - desc->eof = 1; + desc->eof = true; return -EBADCOOKIE; } @@ -341,7 +343,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des if (array->eof_index >= 0) { status = -EBADCOOKIE; if (*desc->dir_cookie == array->last_cookie) - desc->eof = 1; + desc->eof = true; } out: return status; @@ -653,6 +655,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, int status = -ENOMEM; unsigned int array_size = ARRAY_SIZE(pages); + nfs_readdir_init_array(page); + entry.prev_cookie = 0; entry.cookie = desc->last_cookie; entry.eof = 0; @@ -673,9 +677,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, status = PTR_ERR(array); goto out_label_free; } - memset(array, 0, sizeof(struct nfs_cache_array)); - atomic_set(&array->refcount, 1); - array->eof_index = -1; status = nfs_readdir_alloc_pages(pages, array_size); if (status < 0) @@ -730,6 +731,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) unlock_page(page); return 0; error: + nfs_readdir_clear_array(page); unlock_page(page); return ret; } @@ -737,7 +739,6 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) static void cache_page_release(nfs_readdir_descriptor_t *desc) { - nfs_readdir_clear_array(desc->page); put_page(desc->page); desc->page = NULL; } @@ -745,33 +746,34 @@ void cache_page_release(nfs_readdir_descriptor_t *desc) static struct page *get_cache_page(nfs_readdir_descriptor_t *desc) { - struct page *page; - - for (;;) { - page = read_cache_page(desc->file->f_mapping, + return read_cache_page(desc->file->f_mapping, desc->page_index, (filler_t *)nfs_readdir_filler, desc); - if (IS_ERR(page) || grab_page(page)) - break; - put_page(page); - } - return page; } /* * Returns 0 if desc->dir_cookie was found on page desc->page_index + * and locks the page to prevent removal from the page cache. */ static -int find_cache_page(nfs_readdir_descriptor_t *desc) +int find_and_lock_cache_page(nfs_readdir_descriptor_t *desc) { int res; desc->page = get_cache_page(desc); if (IS_ERR(desc->page)) return PTR_ERR(desc->page); - - res = nfs_readdir_search_array(desc); + res = lock_page_killable(desc->page); if (res != 0) - cache_page_release(desc); + goto error; + res = -EAGAIN; + if (desc->page->mapping != NULL) { + res = nfs_readdir_search_array(desc); + if (res == 0) + return 0; + } + unlock_page(desc->page); +error: + cache_page_release(desc); return res; } @@ -786,7 +788,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) desc->last_cookie = 0; } do { - res = find_cache_page(desc); + res = find_and_lock_cache_page(desc); } while (res == -EAGAIN); return res; } @@ -815,7 +817,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc) ent = &array->array[i]; if (!dir_emit(desc->ctx, ent->string.name, ent->string.len, nfs_compat_user_ino64(ent->ino), ent->d_type)) { - desc->eof = 1; + desc->eof = true; break; } desc->ctx->pos++; @@ -827,11 +829,10 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc) ctx->duped = 1; } if (array->eof_index >= 0) - desc->eof = 1; + desc->eof = true; nfs_readdir_release_array(desc->page); out: - cache_page_release(desc); dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (unsigned long long)*desc->dir_cookie, res); return res; @@ -877,13 +878,13 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc) status = nfs_do_filldir(desc); + out_release: + nfs_readdir_clear_array(desc->page); + cache_page_release(desc); out: dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status); return status; - out_release: - cache_page_release(desc); - goto out; } /* The file offset position represents the dirent entry number. A @@ -928,7 +929,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) if (res == -EBADCOOKIE) { res = 0; /* This means either end of directory */ - if (*desc->dir_cookie && desc->eof == 0) { + if (*desc->dir_cookie && !desc->eof) { /* Or that the server has 'lost' a cookie */ res = uncached_readdir(desc); if (res == 0) @@ -948,6 +949,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) break; res = nfs_do_filldir(desc); + unlock_page(desc->page); + cache_page_release(desc); if (res < 0) break; } while (!desc->eof); @@ -960,11 +963,13 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) { + struct inode *inode = file_inode(filp); struct nfs_open_dir_context *dir_ctx = filp->private_data; dfprintk(FILE, "NFS: llseek dir(%pD2, %lld, %d)\n", filp, offset, whence); + inode_lock(inode); switch (whence) { case 1: offset += filp->f_pos; @@ -972,13 +977,16 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) if (offset >= 0) break; default: - return -EINVAL; + offset = -EINVAL; + goto out; } if (offset != filp->f_pos) { filp->f_pos = offset; dir_ctx->dir_cookie = 0; dir_ctx->duped = 0; } +out: + inode_unlock(inode); return offset; } diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 1ec6dd4f3e2e4c034c4888c9417c1aa453f0ca51..3ee60c5332179b38c7b0b5f284f2c5293a98267c 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -847,7 +847,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, spin_lock(&nn->nfs_client_lock); list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { - if (nfs4_cb_match_client(addr, clp, minorversion) == false) + if (!nfs4_cb_match_client(addr, clp, minorversion)) continue; if (!nfs4_has_session(clp)) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ca4249ae644f293389bcea1bd85f11732440555d..632d3c3f8dfb35cda4bf70d15ce82d1c9c86cf48 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2916,6 +2916,11 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, exception.retry = 1; continue; } + if (status == -NFS4ERR_EXPIRED) { + nfs4_schedule_lease_recovery(server->nfs_client); + exception.retry = 1; + continue; + } if (status == -EAGAIN) { /* We must have found a delegation */ exception.retry = 1; diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0e008db16b169c998875cdbebc08385cdb0ff4d3..c3abf92adfb7d05fbaa23d9f4c3bce89cb36b8ad 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1436,7 +1436,7 @@ pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, if ((range->iomode == IOMODE_RW && ls_range->iomode != IOMODE_RW) || (range->iomode != ls_range->iomode && - strict_iomode == true) || + strict_iomode) || !pnfs_lseg_range_intersecting(ls_range, range)) return 0; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 42c31587a936c97b91ca87ae49fb750969ee3f47..4c21e572f2d9e67c82491a3d6d7ff9a0ee6f7854 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1928,7 +1928,7 @@ static int nfs_parse_devname(const char *dev_name, /* kill possible hostname list: not supported */ comma = strchr(dev_name, ','); if (comma != NULL && comma < end) - *comma = 0; + len = comma - dev_name; } if (len > maxnamlen) diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index 64813697f4c4e26f02b245e83df6008ba7b7d801..f6cc2fddb78bd92a9a3da593a47ba805b393677d 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c @@ -680,7 +680,7 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task) /* Client gets 2 lease periods to return it */ cutoff = ktime_add_ns(task->tk_start, - nn->nfsd4_lease * NSEC_PER_SEC * 2); + (u64)nn->nfsd4_lease * NSEC_PER_SEC * 2); if (ktime_before(now, cutoff)) { rpc_delay(task, HZ/100); /* 10 mili-seconds */ diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 66eaeb1e8c2ce75559d4b03c36ab7a16bda56af5..dc9586feab31791d30fbc362496cafb1203ff699 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -661,7 +661,7 @@ struct cld_net { struct cld_upcall { struct list_head cu_list; struct cld_net *cu_net; - struct task_struct *cu_task; + struct completion cu_done; struct cld_msg cu_msg; }; @@ -670,23 +670,18 @@ __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) { int ret; struct rpc_pipe_msg msg; + struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_msg); memset(&msg, 0, sizeof(msg)); msg.data = cmsg; msg.len = sizeof(*cmsg); - /* - * Set task state before we queue the upcall. That prevents - * wake_up_process in the downcall from racing with schedule. - */ - set_current_state(TASK_UNINTERRUPTIBLE); ret = rpc_queue_upcall(pipe, &msg); if (ret < 0) { - set_current_state(TASK_RUNNING); goto out; } - schedule(); + wait_for_completion(&cup->cu_done); if (msg.errno < 0) ret = msg.errno; @@ -753,7 +748,7 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) if (copy_from_user(&cup->cu_msg, src, mlen) != 0) return -EFAULT; - wake_up_process(cup->cu_task); + complete(&cup->cu_done); return mlen; } @@ -768,7 +763,7 @@ cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) if (msg->errno >= 0) return; - wake_up_process(cup->cu_task); + complete(&cup->cu_done); } static const struct rpc_pipe_ops cld_upcall_ops = { @@ -899,7 +894,7 @@ alloc_cld_upcall(struct cld_net *cn) goto restart_search; } } - new->cu_task = current; + init_completion(&new->cu_done); new->cu_msg.cm_vers = CLD_UPCALL_VERSION; put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid); new->cu_net = cn; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 032fcae3a94fe6309a601d89357a847bcc3eeb23..4509c76716e36dfae94f6be372ff16b86f2b8f65 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3067,12 +3067,17 @@ static bool replay_matches_cache(struct svc_rqst *rqstp, (bool)seq->cachethis) return false; /* - * If there's an error than the reply can have fewer ops than - * the call. But if we cached a reply with *more* ops than the - * call you're sending us now, then this new call is clearly not - * really a replay of the old one: + * If there's an error then the reply can have fewer ops than + * the call. */ - if (slot->sl_opcnt < argp->opcnt) + if (slot->sl_opcnt < argp->opcnt && !slot->sl_status) + return false; + /* + * But if we cached a reply with *more* ops than the call you're + * sending us now, then this new call is clearly not really a + * replay of the old one: + */ + if (slot->sl_opcnt > argp->opcnt) return false; /* This is the only check explicitly called by spec: */ if (!same_creds(&rqstp->rq_cred, &slot->sl_cred)) @@ -6029,7 +6034,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, } if (fl_flags & FL_SLEEP) { - nbl->nbl_time = jiffies; + nbl->nbl_time = get_seconds(); spin_lock(&nn->blocked_locks_lock); list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked); list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru); diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 133d8bf62a5cdae4d0e9d1ec4466eee31d63991b..7872b1ead88584134550e843ec8117933302d643 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -591,7 +591,7 @@ static inline bool nfsd4_stateid_generation_after(stateid_t *a, stateid_t *b) struct nfsd4_blocked_lock { struct list_head nbl_list; struct list_head nbl_lru; - unsigned long nbl_time; + time_t nbl_time; struct file_lock nbl_lock; struct knfsd_fh nbl_fh; struct nfsd4_callback nbl_cb; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8f0b19a3ca810993d02eb20fb160b2da017dcd59..b8cd100cfcd6dd3d79766671d938d7894a45ba41 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -395,10 +395,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, bool get_write_count; bool size_change = (iap->ia_valid & ATTR_SIZE); - if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) + if (iap->ia_valid & ATTR_SIZE) { accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; - if (iap->ia_valid & ATTR_SIZE) ftype = S_IFREG; + } + + /* + * If utimes(2) and friends are called with times not NULL, we should + * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission + * will return EACCESS, when the caller's effective UID does not match + * the owner of the file, and the caller is not privileged. In this + * situation, we should return EPERM(notify_change will return this). + */ + if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) { + accmode |= NFSD_MAY_OWNER_OVERRIDE; + if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET))) + accmode |= NFSD_MAY_WRITE; + } /* Callers that do fh_verify should do the fh_want_write: */ get_write_count = !fhp->fh_dentry; diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index ee8dbbae78b6aa3040b7f24fb214ffbc9174271c..6dc714a56c37ab0b855887e1ee680e3e73ffb260 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -338,8 +338,8 @@ int ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh) down_read(&OCFS2_I(inode)->ip_xattr_sem); acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh); up_read(&OCFS2_I(inode)->ip_xattr_sem); - if (IS_ERR(acl) || !acl) - return PTR_ERR(acl); + if (IS_ERR_OR_NULL(acl)) + return PTR_ERR_OR_ZERO(acl); ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); if (ret) return ret; diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 13cf69aa4cae8e69d74d612e931fb803d8b787ef..733c051353059dd6182f0efc7dc3e5758b096061 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1080,6 +1080,14 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed) ocfs2_clear_journal_error(osb->sb, journal->j_journal, osb->slot_num); + if (replayed) { + jbd2_journal_lock_updates(journal->j_journal); + status = jbd2_journal_flush(journal->j_journal); + jbd2_journal_unlock_updates(journal->j_journal); + if (status < 0) + mlog_errno(status); + } + status = ocfs2_journal_toggle_dirty(osb, 1, replayed); if (status < 0) { mlog_errno(status); diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 497a4171ef61f6209a32303530b79c72439962cf..bfb50fc51528ffbf9d7c20c7b8b9872475991029 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -637,9 +637,11 @@ static inline void ocfs2_update_inode_fsync_trans(handle_t *handle, { struct ocfs2_inode_info *oi = OCFS2_I(inode); - oi->i_sync_tid = handle->h_transaction->t_tid; - if (datasync) - oi->i_datasync_tid = handle->h_transaction->t_tid; + if (!is_handle_aborted(handle)) { + oi->i_sync_tid = handle->h_transaction->t_tid; + if (datasync) + oi->i_datasync_tid = handle->h_transaction->t_tid; + } } #endif /* OCFS2_JOURNAL_H */ diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 87e577a49b0d567550e09912c179a719a7ee692c..542fa21aeaa9092ef90d214a60f5886b9edac535 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -714,7 +714,7 @@ static int ocfs2_release_dquot(struct dquot *dquot) mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ - if (atomic_read(&dquot->dq_count) > 1) + if (dquot_is_busy(dquot)) goto out; /* Running from downconvert thread? Postpone quota processing to wq */ if (current == osb->dc_task) { diff --git a/fs/open.c b/fs/open.c index 2ff88766123750a3ae2cee33ddeea13b9323067a..f2b82c462fbba52c27beea607b929ef2892ab8c4 100644 --- a/fs/open.c +++ b/fs/open.c @@ -837,9 +837,6 @@ static int do_dentry_open(struct file *f, * the return value of d_splice_alias(), then the caller needs to perform dput() * on it after finish_open(). * - * On successful return @file is a fully instantiated open file. After this, if - * an error occurs in ->atomic_open(), it needs to clean up with fput(). - * * Returns zero on success or -errno if the open failed. */ int finish_open(struct file *file, struct dentry *dentry, diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c index 0748a26598fca1e39379c1104061392e96592b2b..7d7df003f9d8d5350b9ce0c1baee873b19407bfb 100644 --- a/fs/orangefs/orangefs-debugfs.c +++ b/fs/orangefs/orangefs-debugfs.c @@ -304,6 +304,7 @@ static void *help_start(struct seq_file *m, loff_t *pos) static void *help_next(struct seq_file *m, void *v, loff_t *pos) { + (*pos)++; gossip_debug(GOSSIP_DEBUGFS_DEBUG, "help_next: start\n"); return NULL; diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 8e151fb9bb766b6bbafaebaa4cefb9339a8089cf..9d5dd6260061c9da230e360576793cb1bdb94fef 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -321,6 +321,17 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, prz = cxt->przs[cxt->dump_write_cnt]; + /* + * Since this is a new crash dump, we need to reset the buffer in + * case it still has an old dump present. Without this, the new dump + * will get appended, which would seriously confuse anything trying + * to check dump file contents. Specifically, ramoops_read_kmsg_hdr() + * expects to find a dump header in the beginning of buffer data, so + * we must to reset the buffer values, in order to ensure that the + * header will be written to the beginning of the buffer. + */ + persistent_ram_zap(prz); + hlen = ramoops_write_kmsg_hdr(prz, compressed); if (size + hlen > prz->buffer_size) size = prz->buffer_size - hlen; diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index f9246ac4eef81493ddbd87237158f6aa423b339f..82a5ecbe2da96c852d1d97b92d79f405e5c78806 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -479,7 +479,7 @@ int dquot_release(struct dquot *dquot) mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ - if (atomic_read(&dquot->dq_count) > 1) + if (dquot_is_busy(dquot)) goto out_dqlock; mutex_lock(&dqopt->dqio_mutex); if (dqopt->ops[dquot->dq_id.type]->release_dqblk) { @@ -611,7 +611,7 @@ EXPORT_SYMBOL(dquot_scan_active); /* Write all dquot structures to quota files */ int dquot_writeback_dquots(struct super_block *sb, int type) { - struct list_head *dirty; + struct list_head dirty; struct dquot *dquot; struct quota_info *dqopt = sb_dqopt(sb); int cnt; @@ -624,9 +624,10 @@ int dquot_writeback_dquots(struct super_block *sb, int type) if (!sb_has_quota_active(sb, cnt)) continue; spin_lock(&dq_list_lock); - dirty = &dqopt->info[cnt].dqi_dirty_list; - while (!list_empty(dirty)) { - dquot = list_first_entry(dirty, struct dquot, + /* Move list away to avoid livelock. */ + list_replace_init(&dqopt->info[cnt].dqi_dirty_list, &dirty); + while (!list_empty(&dirty)) { + dquot = list_first_entry(&dirty, struct dquot, dq_dirty); /* Dirty and inactive can be only bad dquot... */ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { @@ -2848,68 +2849,73 @@ EXPORT_SYMBOL(dquot_quotactl_sysfile_ops); static int do_proc_dqstats(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - unsigned int type = (int *)table->data - dqstats.stat; + unsigned int type = (unsigned long *)table->data - dqstats.stat; + s64 value = percpu_counter_sum(&dqstats.counter[type]); + + /* Filter negative values for non-monotonic counters */ + if (value < 0 && (type == DQST_ALLOC_DQUOTS || + type == DQST_FREE_DQUOTS)) + value = 0; /* Update global table */ - dqstats.stat[type] = - percpu_counter_sum_positive(&dqstats.counter[type]); - return proc_dointvec(table, write, buffer, lenp, ppos); + dqstats.stat[type] = value; + return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); } static struct ctl_table fs_dqstats_table[] = { { .procname = "lookups", .data = &dqstats.stat[DQST_LOOKUPS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "drops", .data = &dqstats.stat[DQST_DROPS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "reads", .data = &dqstats.stat[DQST_READS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "writes", .data = &dqstats.stat[DQST_WRITES], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "cache_hits", .data = &dqstats.stat[DQST_CACHE_HITS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "allocated_dquots", .data = &dqstats.stat[DQST_ALLOC_DQUOTS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "free_dquots", .data = &dqstats.stat[DQST_FREE_DQUOTS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "syncs", .data = &dqstats.stat[DQST_SYNCS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, diff --git a/fs/readdir.c b/fs/readdir.c index 9d0212c374d6db316dcafcd278e5b511a1eec6d2..1059f2a9be0b20d6cfa24c014dfd482469398f81 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -63,6 +63,40 @@ int iterate_dir(struct file *file, struct dir_context *ctx) } EXPORT_SYMBOL(iterate_dir); +/* + * POSIX says that a dirent name cannot contain NULL or a '/'. + * + * It's not 100% clear what we should really do in this case. + * The filesystem is clearly corrupted, but returning a hard + * error means that you now don't see any of the other names + * either, so that isn't a perfect alternative. + * + * And if you return an error, what error do you use? Several + * filesystems seem to have decided on EUCLEAN being the error + * code for EFSCORRUPTED, and that may be the error to use. Or + * just EIO, which is perhaps more obvious to users. + * + * In order to see the other file names in the directory, the + * caller might want to make this a "soft" error: skip the + * entry, and return the error at the end instead. + * + * Note that this should likely do a "memchr(name, 0, len)" + * check too, since that would be filesystem corruption as + * well. However, that case can't actually confuse user space, + * which has to do a strlen() on the name anyway to find the + * filename length, and the above "soft error" worry means + * that it's probably better left alone until we have that + * issue clarified. + */ +static int verify_dirent_name(const char *name, int len) +{ + if (!len) + return -EIO; + if (memchr(name, '/', len)) + return -EIO; + return 0; +} + /* * Traditional linux readdir() handling.. * @@ -172,6 +206,9 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2, sizeof(long)); + buf->error = verify_dirent_name(name, namlen); + if (unlikely(buf->error)) + return buf->error; buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; @@ -258,6 +295,9 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, sizeof(u64)); + buf->error = verify_dirent_name(name, namlen); + if (unlikely(buf->error)) + return buf->error; buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index bd4c727f4610be5425a1845d874b5c8a20e5e379..9531b6c18ac7bf4b944e75bd58a0c0ecbb40783a 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -2102,6 +2102,15 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, goto out_inserted_sd; } + /* + * Mark it private if we're creating the privroot + * or something under it. + */ + if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root) { + inode->i_flags |= S_PRIVATE; + inode->i_opflags &= ~IOP_XATTR; + } + if (reiserfs_posixacl(inode->i_sb)) { reiserfs_write_unlock(inode->i_sb); retval = reiserfs_inherit_default_acl(th, dir, dentry, inode); @@ -2116,8 +2125,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, reiserfs_warning(inode->i_sb, "jdm-13090", "ACLs aren't enabled in the fs, " "but vfs thinks they are!"); - } else if (IS_PRIVATE(dir)) - inode->i_flags |= S_PRIVATE; + } if (security->name) { reiserfs_write_unlock(inode->i_sb); diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 1ec728cf82d13751348762f35ba5ec7acb657d39..1c900f322089810e9ff929b414400a6009141cc9 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -377,10 +377,13 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, /* * Propagate the private flag so we know we're - * in the priv tree + * in the priv tree. Also clear IOP_XATTR + * since we don't have xattrs on xattr files. */ - if (IS_PRIVATE(dir)) + if (IS_PRIVATE(dir)) { inode->i_flags |= S_PRIVATE; + inode->i_opflags &= ~IOP_XATTR; + } } reiserfs_write_unlock(dir->i_sb); if (retval == IO_ERROR) { diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h index d920a646b578404689c3f0305119e370853baed2..3e78a394fdb84aa00851912ec5ccf12d2ffda90d 100644 --- a/fs/reiserfs/reiserfs.h +++ b/fs/reiserfs/reiserfs.h @@ -1167,6 +1167,8 @@ static inline int bmap_would_wrap(unsigned bmap_nr) return bmap_nr > ((1LL << 16) - 1); } +extern const struct xattr_handler *reiserfs_xattr_handlers[]; + /* * this says about version of key of all items (but stat data) the * object consists of diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index a97e352d05d3b5492b800ab280966d4a00911eab..5f5fff0688776c40ba8258065b588f00e13dd26c 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -2249,7 +2249,8 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, /* also releases the path */ unfix_nodes(&s_ins_balance); #ifdef REISERQUOTA_DEBUG - reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, + if (inode) + reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, "reiserquota insert_item(): freeing %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(ih)); #endif diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index dec6c93044fa3bcfc3b1b740aa3a599d19592170..677608a89b08d381ce8995ff209a015b0dd27c3a 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -599,6 +599,7 @@ static void reiserfs_put_super(struct super_block *s) reiserfs_write_unlock(s); mutex_destroy(&REISERFS_SB(s)->lock); destroy_workqueue(REISERFS_SB(s)->commit_wq); + kfree(REISERFS_SB(s)->s_jdev); kfree(s->s_fs_info); s->s_fs_info = NULL; } @@ -1927,7 +1928,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) if (!sbi->s_jdev) { SWARN(silent, s, "", "Cannot allocate memory for " "journal device name"); - goto error; + goto error_unlocked; } } #ifdef CONFIG_QUOTA @@ -2026,6 +2027,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) if (replay_only(s)) goto error_unlocked; + s->s_xattr = reiserfs_xattr_handlers; + if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) { SWARN(silent, s, "clm-7000", "Detected readonly device, marking FS readonly"); @@ -2215,6 +2218,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) kfree(qf_names[j]); } #endif + kfree(sbi->s_jdev); kfree(sbi); s->s_fs_info = NULL; diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 9e313fc7fdc7076c08f2ac1753f895d45b034de7..07900105523f0208f63100e4fb9d66d918f1adfb 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -121,13 +121,13 @@ static struct dentry *open_xa_root(struct super_block *sb, int flags) struct dentry *xaroot; if (d_really_is_negative(privroot)) - return ERR_PTR(-ENODATA); + return ERR_PTR(-EOPNOTSUPP); inode_lock_nested(d_inode(privroot), I_MUTEX_XATTR); xaroot = dget(REISERFS_SB(sb)->xattr_root); if (!xaroot) - xaroot = ERR_PTR(-ENODATA); + xaroot = ERR_PTR(-EOPNOTSUPP); else if (d_really_is_negative(xaroot)) { int err = -ENODATA; @@ -318,8 +318,12 @@ static int reiserfs_for_each_xattr(struct inode *inode, out_dir: dput(dir); out: - /* -ENODATA isn't an error */ - if (err == -ENODATA) + /* + * -ENODATA: this object doesn't have any xattrs + * -EOPNOTSUPP: this file system doesn't have xattrs enabled on disk. + * Neither are errors + */ + if (err == -ENODATA || err == -EOPNOTSUPP) err = 0; return err; } @@ -609,6 +613,10 @@ int reiserfs_xattr_set(struct inode *inode, const char *name, int error, error2; size_t jbegin_count = reiserfs_xattr_nblocks(inode, buffer_size); + /* Check before we start a transaction and then do nothing. */ + if (!d_really_is_positive(REISERFS_SB(inode->i_sb)->priv_root)) + return -EOPNOTSUPP; + if (!(flags & XATTR_REPLACE)) jbegin_count += reiserfs_xattr_jcreate_nblocks(inode); @@ -831,8 +839,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) if (d_really_is_negative(dentry)) return -EINVAL; - if (!dentry->d_sb->s_xattr || - get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1) + if (get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1) return -EOPNOTSUPP; dir = open_xa_dir(d_inode(dentry), XATTR_REPLACE); @@ -872,6 +879,7 @@ static int create_privroot(struct dentry *dentry) } d_inode(dentry)->i_flags |= S_PRIVATE; + d_inode(dentry)->i_opflags &= ~IOP_XATTR; reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " "storage.\n", PRIVROOT_NAME); @@ -885,7 +893,7 @@ static int create_privroot(struct dentry *dentry) { return 0; } #endif /* Actual operations that are exported to VFS-land */ -static const struct xattr_handler *reiserfs_xattr_handlers[] = { +const struct xattr_handler *reiserfs_xattr_handlers[] = { #ifdef CONFIG_REISERFS_FS_XATTR &reiserfs_xattr_user_handler, &reiserfs_xattr_trusted_handler, @@ -956,8 +964,10 @@ int reiserfs_lookup_privroot(struct super_block *s) if (!IS_ERR(dentry)) { REISERFS_SB(s)->priv_root = dentry; d_set_d_op(dentry, &xattr_lookup_poison_ops); - if (d_really_is_positive(dentry)) + if (d_really_is_positive(dentry)) { d_inode(dentry)->i_flags |= S_PRIVATE; + d_inode(dentry)->i_opflags &= ~IOP_XATTR; + } } else err = PTR_ERR(dentry); inode_unlock(d_inode(s->s_root)); @@ -986,7 +996,6 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) } if (d_really_is_positive(privroot)) { - s->s_xattr = reiserfs_xattr_handlers; inode_lock(d_inode(privroot)); if (!REISERFS_SB(s)->xattr_root) { struct dentry *dentry; diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index d92a1dc6ee70f66ea8f95838598a859365e5cf64..1f1fdfd3bc5ccebe19031d5fac830372b495e73b 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -316,10 +316,8 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, * would be useless since permissions are ignored, and a pain because * it introduces locking cycles */ - if (IS_PRIVATE(dir)) { - inode->i_flags |= S_PRIVATE; + if (IS_PRIVATE(inode)) goto apply_umask; - } err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); if (err) diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index b4fbeefba246adf8eec82f45cf0692ec9f22e660..5ef0d1d6074313899732f58ca1921fa5bca08f74 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -721,6 +721,7 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu, int err, page_idx, page_cnt, ret = 0, n = 0; int allocate = bu->buf ? 0 : 1; loff_t isize; + gfp_t ra_gfp_mask = readahead_gfp_mask(mapping) & ~__GFP_FS; err = ubifs_tnc_get_bu_keys(c, bu); if (err) @@ -782,8 +783,9 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu, if (page_offset > end_index) break; - page = find_or_create_page(mapping, page_offset, - GFP_NOFS | __GFP_COLD); + page = pagecache_get_page(mapping, page_offset, + FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT, + ra_gfp_mask); if (!page) break; if (!PageUptodate(page)) diff --git a/fs/udf/super.c b/fs/udf/super.c index 03369a89600e0852de37aca7dc206848a0c4f6b6..4abdba453885e14ee92b823f77c4186b1fb9def8 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -2460,17 +2460,29 @@ static unsigned int udf_count_free_table(struct super_block *sb, static unsigned int udf_count_free(struct super_block *sb) { unsigned int accum = 0; - struct udf_sb_info *sbi; + struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map; + unsigned int part = sbi->s_partition; + int ptype = sbi->s_partmaps[part].s_partition_type; + + if (ptype == UDF_METADATA_MAP25) { + part = sbi->s_partmaps[part].s_type_specific.s_metadata. + s_phys_partition_ref; + } else if (ptype == UDF_VIRTUAL_MAP15 || ptype == UDF_VIRTUAL_MAP20) { + /* + * Filesystems with VAT are append-only and we cannot write to + * them. Let's just report 0 here. + */ + return 0; + } - sbi = UDF_SB(sb); if (sbi->s_lvid_bh) { struct logicalVolIntegrityDesc *lvid = (struct logicalVolIntegrityDesc *) sbi->s_lvid_bh->b_data; - if (le32_to_cpu(lvid->numOfPartitions) > sbi->s_partition) { + if (le32_to_cpu(lvid->numOfPartitions) > part) { accum = le32_to_cpu( - lvid->freeSpaceTable[sbi->s_partition]); + lvid->freeSpaceTable[part]); if (accum == 0xFFFFFFFF) accum = 0; } @@ -2479,7 +2491,7 @@ static unsigned int udf_count_free(struct super_block *sb) if (accum) return accum; - map = &sbi->s_partmaps[sbi->s_partition]; + map = &sbi->s_partmaps[part]; if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { accum += udf_count_free_bitmap(sb, map->s_uspace.s_bitmap); diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index d34085bf4a40be82acc56017e210b3e946e1a56d..9ca8809ee3d0cf216e3c03d46bd1b3f54e97b039 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5688,7 +5688,7 @@ __xfs_bunmapi( * Make sure we don't touch multiple AGF headers out of order * in a single transaction, as that could cause AB-BA deadlocks. */ - if (!wasdel) { + if (!wasdel && !isrt) { agno = XFS_FSB_TO_AGNO(mp, del.br_startblock); if (prev_agno != NULLAGNUMBER && prev_agno > agno) break; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 33c9a3aae9483d3beee28e3739af1feb61e43c66..7bfcd09d446b79c22e30f261b14a583f195a5914 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1540,6 +1540,8 @@ xlog_alloc_log( if (iclog->ic_bp) xfs_buf_free(iclog->ic_bp); kmem_free(iclog); + if (prev_iclog == log->l_iclog) + break; } spinlock_destroy(&log->l_icloglock); xfs_buf_free(log->l_xbuf); diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c index f82d79a8c694a8f32427b8d0e2923dbde1670d88..a7c3da09b72f9c0384080903332aaee243b5c2c1 100644 --- a/fs/xfs/xfs_quotaops.c +++ b/fs/xfs/xfs_quotaops.c @@ -214,6 +214,9 @@ xfs_fs_rm_xquota( if (XFS_IS_QUOTA_ON(mp)) return -EINVAL; + if (uflags & ~(FS_USER_QUOTA | FS_GROUP_QUOTA | FS_PROJ_QUOTA)) + return -EINVAL; + if (uflags & FS_USER_QUOTA) flags |= XFS_DQ_USER; if (uflags & FS_GROUP_QUOTA) diff --git a/gen_headers_arm.bp b/gen_headers_arm.bp new file mode 100644 index 0000000000000000000000000000000000000000..e8d2f2fa21b5f29cc824dd2b237cee8e0b4651e5 --- /dev/null +++ b/gen_headers_arm.bp @@ -0,0 +1,976 @@ +// ***** DO NOT EDIT ***** +// This file is generated by kernel_headers.py + +gen_headers_srcs_arm = [ + "arch/arm/include/uapi/asm/Kbuild", + "include/uapi/asm-generic/Kbuild.asm", + "Makefile", + "arch/arm/tools/syscall.tbl", + "include/uapi/**/*.h", + "arch/arm/include/uapi/**/*.h", +] + +gen_headers_exclude_srcs_arm = [ + "include/uapi/linux/a.out.h", + "include/uapi/drm/armada_drm.h", + "include/uapi/drm/etnaviv_drm.h", + "include/uapi/drm/omap_drm.h", + "include/uapi/drm/vgem_drm.h", + "include/uapi/linux/auto_dev-ioctl.h", + "include/uapi/linux/batman_adv.h", + "include/uapi/linux/bcache.h", + "include/uapi/linux/btrfs_tree.h", + "include/uapi/linux/cryptouser.h", + "include/uapi/linux/dma-buf.h", + "include/uapi/linux/hash_info.h", + "include/uapi/linux/kcm.h", + "include/uapi/linux/kcov.h", + "include/uapi/linux/kfd_ioctl.h", + "include/uapi/linux/lightnvm.h", + "include/uapi/linux/module.h", + "include/uapi/linux/nilfs2_api.h", + "include/uapi/linux/nilfs2_ondisk.h", + "include/uapi/linux/nsfs.h", + "include/uapi/linux/pr.h", + "include/uapi/linux/qrtr.h", + "include/uapi/linux/stm.h", + "include/uapi/linux/tee.h", + "include/uapi/linux/userio.h", + "include/uapi/linux/wil6210_uapi.h", + "include/uapi/rdma/qedr-abi.h", + "include/uapi/video/adf.h", + "include/uapi/linux/cifs/cifs_mount.h", + "include/uapi/linux/genwqe/genwqe_card.h", + "include/uapi/linux/netfilter/xt_HARDIDLETIMER.h", + "include/uapi/linux/usb/f_accessory.h", + "include/uapi/linux/usb/f_mtp.h", +] + +gen_headers_out_arm = [ + + // Matching generated-y: + + "asm/unistd-common.h", + "asm/unistd-oabi.h", + "asm/unistd-eabi.h", + + // Matching mandatory-y: + + "asm/bitsperlong.h", + "asm/errno.h", + "asm/ioctl.h", + "asm/ipcbuf.h", + "asm/msgbuf.h", + "asm/param.h", + "asm/poll.h", + "asm/resource.h", + "asm/sembuf.h", + "asm/shmbuf.h", + "asm/siginfo.h", + "asm/socket.h", + "asm/sockios.h", + "asm/termbits.h", + "asm/termios.h", + + // From include/uapi/**/*.h + + "asm-generic/auxvec.h", + "asm-generic/bitsperlong.h", + "asm-generic/errno-base.h", + "asm-generic/errno.h", + "asm-generic/fcntl.h", + "asm-generic/int-l64.h", + "asm-generic/int-ll64.h", + "asm-generic/ioctl.h", + "asm-generic/ioctls.h", + "asm-generic/ipcbuf.h", + "asm-generic/kvm_para.h", + "asm-generic/mman-common.h", + "asm-generic/mman.h", + "asm-generic/msgbuf.h", + "asm-generic/param.h", + "asm-generic/poll.h", + "asm-generic/posix_types.h", + "asm-generic/resource.h", + "asm-generic/sembuf.h", + "asm-generic/setup.h", + "asm-generic/shmbuf.h", + "asm-generic/shmparam.h", + "asm-generic/siginfo.h", + "asm-generic/signal-defs.h", + "asm-generic/signal.h", + "asm-generic/socket.h", + "asm-generic/sockios.h", + "asm-generic/stat.h", + "asm-generic/statfs.h", + "asm-generic/swab.h", + "asm-generic/termbits.h", + "asm-generic/termios.h", + "asm-generic/types.h", + "asm-generic/ucontext.h", + "asm-generic/unistd.h", + "drm/amdgpu_drm.h", + "drm/drm.h", + "drm/drm_fourcc.h", + "drm/drm_mode.h", + "drm/drm_sarea.h", + "drm/exynos_drm.h", + "drm/i810_drm.h", + "drm/i915_drm.h", + "drm/mga_drm.h", + "drm/msm_drm.h", + "drm/msm_drm_pp.h", + "drm/nouveau_drm.h", + "drm/qxl_drm.h", + "drm/r128_drm.h", + "drm/radeon_drm.h", + "drm/savage_drm.h", + "drm/sde_drm.h", + "drm/sis_drm.h", + "drm/tegra_drm.h", + "drm/vc4_drm.h", + "drm/via_drm.h", + "drm/virtgpu_drm.h", + "drm/vmwgfx_drm.h", + "linux/acct.h", + "linux/adb.h", + "linux/adfs_fs.h", + "linux/affs_hardblocks.h", + "linux/agpgart.h", + "linux/aio_abi.h", + "linux/am437x-vpfe.h", + "linux/apm_bios.h", + "linux/arcfb.h", + "linux/atalk.h", + "linux/atm.h", + "linux/atm_eni.h", + "linux/atm_he.h", + "linux/atm_idt77105.h", + "linux/atm_nicstar.h", + "linux/atm_tcp.h", + "linux/atm_zatm.h", + "linux/atmapi.h", + "linux/atmarp.h", + "linux/atmbr2684.h", + "linux/atmclip.h", + "linux/atmdev.h", + "linux/atmioc.h", + "linux/atmlec.h", + "linux/atmmpc.h", + "linux/atmppp.h", + "linux/atmsap.h", + "linux/atmsvc.h", + "linux/audit.h", + "linux/auto_fs.h", + "linux/auto_fs4.h", + "linux/auxvec.h", + "linux/ax25.h", + "linux/b1lli.h", + "linux/batterydata-interface.h", + "linux/baycom.h", + "linux/bcm933xx_hcs.h", + "linux/bfs_fs.h", + "linux/bgcom_interface.h", + "linux/binfmts.h", + "linux/blkpg.h", + "linux/blktrace_api.h", + "linux/bpf.h", + "linux/bpf_common.h", + "linux/bpf_perf_event.h", + "linux/bpqether.h", + "linux/bsg.h", + "linux/bt-bmc.h", + "linux/btrfs.h", + "linux/can.h", + "linux/capability.h", + "linux/capi.h", + "linux/cciss_defs.h", + "linux/cciss_ioctl.h", + "linux/cdrom.h", + "linux/cgroupstats.h", + "linux/chio.h", + "linux/cm4000_cs.h", + "linux/cn_proc.h", + "linux/coda.h", + "linux/coda_psdev.h", + "linux/coff.h", + "linux/connector.h", + "linux/const.h", + "linux/coresight-stm.h", + "linux/cramfs_fs.h", + "linux/cuda.h", + "linux/cyclades.h", + "linux/cycx_cfm.h", + "linux/dcbnl.h", + "linux/dccp.h", + "linux/devlink.h", + "linux/dlm.h", + "linux/dlm_device.h", + "linux/dlm_netlink.h", + "linux/dlm_plock.h", + "linux/dlmconstants.h", + "linux/dm-ioctl.h", + "linux/dm-log-userspace.h", + "linux/dn.h", + "linux/dqblk_xfs.h", + "linux/edd.h", + "linux/efs_fs_sb.h", + "linux/elf-em.h", + "linux/elf-fdpic.h", + "linux/elf.h", + "linux/elfcore.h", + "linux/errno.h", + "linux/errqueue.h", + "linux/esoc_ctrl.h", + "linux/ethtool.h", + "linux/eventpoll.h", + "linux/fadvise.h", + "linux/falloc.h", + "linux/fanotify.h", + "linux/fb.h", + "linux/fcntl.h", + "linux/fd.h", + "linux/fdreg.h", + "linux/fib_rules.h", + "linux/fiemap.h", + "linux/filter.h", + "linux/fips_status.h", + "linux/firewire-cdev.h", + "linux/firewire-constants.h", + "linux/flat.h", + "linux/fou.h", + "linux/fs.h", + "linux/fsl_hypervisor.h", + "linux/fuse.h", + "linux/futex.h", + "linux/gameport.h", + "linux/gen_stats.h", + "linux/genetlink.h", + "linux/gfs2_ondisk.h", + "linux/gigaset_dev.h", + "linux/gpio.h", + "linux/gsmmux.h", + "linux/gtp.h", + "linux/hbtp_input.h", + "linux/hdlc.h", + "linux/hdlcdrv.h", + "linux/hdreg.h", + "linux/hid.h", + "linux/hiddev.h", + "linux/hidraw.h", + "linux/hpet.h", + "linux/hsr_netlink.h", + "linux/hw_breakpoint.h", + "linux/hyperv.h", + "linux/hysdn_if.h", + "linux/i2c-dev.h", + "linux/i2c.h", + "linux/i2o-dev.h", + "linux/i8k.h", + "linux/icmp.h", + "linux/icmpv6.h", + "linux/if.h", + "linux/if_addr.h", + "linux/if_addrlabel.h", + "linux/if_alg.h", + "linux/if_arcnet.h", + "linux/if_arp.h", + "linux/if_bonding.h", + "linux/if_bridge.h", + "linux/if_cablemodem.h", + "linux/if_eql.h", + "linux/if_ether.h", + "linux/if_fc.h", + "linux/if_fddi.h", + "linux/if_frad.h", + "linux/if_hippi.h", + "linux/if_infiniband.h", + "linux/if_link.h", + "linux/if_ltalk.h", + "linux/if_macsec.h", + "linux/if_packet.h", + "linux/if_phonet.h", + "linux/if_plip.h", + "linux/if_ppp.h", + "linux/if_pppol2tp.h", + "linux/if_pppolac.h", + "linux/if_pppopns.h", + "linux/if_pppox.h", + "linux/if_slip.h", + "linux/if_team.h", + "linux/if_tun.h", + "linux/if_tunnel.h", + "linux/if_vlan.h", + "linux/if_x25.h", + "linux/igmp.h", + "linux/ila.h", + "linux/in.h", + "linux/in6.h", + "linux/in_route.h", + "linux/inet_diag.h", + "linux/inotify.h", + "linux/input-event-codes.h", + "linux/input.h", + "linux/ioctl.h", + "linux/ion.h", + "linux/ip.h", + "linux/ip6_tunnel.h", + "linux/ip_vs.h", + "linux/ipa_qmi_service_v01.h", + "linux/ipc.h", + "linux/ipmi.h", + "linux/ipmi_msgdefs.h", + "linux/ipsec.h", + "linux/ipv6.h", + "linux/ipv6_route.h", + "linux/ipx.h", + "linux/irda.h", + "linux/irqnr.h", + "linux/isdn.h", + "linux/isdn_divertif.h", + "linux/isdn_ppp.h", + "linux/isdnif.h", + "linux/iso_fs.h", + "linux/ivtv.h", + "linux/ivtvfb.h", + "linux/ixjuser.h", + "linux/jffs2.h", + "linux/joystick.h", + "linux/kcmp.h", + "linux/kd.h", + "linux/kdev_t.h", + "linux/kernel-page-flags.h", + "linux/kernel.h", + "linux/kernelcapi.h", + "linux/kexec.h", + "linux/keyboard.h", + "linux/keyctl.h", + "linux/kvm.h", + "linux/kvm_para.h", + "linux/l2tp.h", + "linux/libc-compat.h", + "linux/limits.h", + "linux/lirc.h", + "linux/llc.h", + "linux/loop.h", + "linux/lp.h", + "linux/lwtunnel.h", + "linux/magic.h", + "linux/major.h", + "linux/map_to_7segment.h", + "linux/matroxfb.h", + "linux/mdio.h", + "linux/mdss_rotator.h", + "linux/media-bus-format.h", + "linux/media.h", + "linux/mei.h", + "linux/membarrier.h", + "linux/memfd.h", + "linux/mempolicy.h", + "linux/meye.h", + "linux/mhi.h", + "linux/mic_common.h", + "linux/mic_ioctl.h", + "linux/mii.h", + "linux/minix_fs.h", + "linux/mman.h", + "linux/mmtimer.h", + "linux/mpls.h", + "linux/mpls_iptunnel.h", + "linux/mqueue.h", + "linux/mroute.h", + "linux/mroute6.h", + "linux/msdos_fs.h", + "linux/msg.h", + "linux/msm-core-interface.h", + "linux/msm_dsps.h", + "linux/msm_ion.h", + "linux/msm_ipa.h", + "linux/msm_ipc.h", + "linux/msm_kgsl.h", + "linux/msm_mdp.h", + "linux/msm_mdp_ext.h", + "linux/msm_rmnet.h", + "linux/msm_rotator.h", + "linux/msm_vidc_dec.h", + "linux/msm_vidc_enc.h", + "linux/mtio.h", + "linux/n_r3964.h", + "linux/nbd.h", + "linux/ncp.h", + "linux/ncp_fs.h", + "linux/ncp_mount.h", + "linux/ncp_no.h", + "linux/ndctl.h", + "linux/neighbour.h", + "linux/net.h", + "linux/net_dropmon.h", + "linux/net_map.h", + "linux/net_namespace.h", + "linux/net_tstamp.h", + "linux/netconf.h", + "linux/netdevice.h", + "linux/netfilter.h", + "linux/netfilter_arp.h", + "linux/netfilter_bridge.h", + "linux/netfilter_decnet.h", + "linux/netfilter_ipv4.h", + "linux/netfilter_ipv6.h", + "linux/netlink.h", + "linux/netlink_diag.h", + "linux/netrom.h", + "linux/nfc.h", + "linux/nfs.h", + "linux/nfs2.h", + "linux/nfs3.h", + "linux/nfs4.h", + "linux/nfs4_mount.h", + "linux/nfs_fs.h", + "linux/nfs_idmap.h", + "linux/nfs_mount.h", + "linux/nfsacl.h", + "linux/nl80211.h", + "linux/nubus.h", + "linux/nvme_ioctl.h", + "linux/nvram.h", + "linux/okl4-link-shbuf.h", + "linux/omap3isp.h", + "linux/omapfb.h", + "linux/oom.h", + "linux/openvswitch.h", + "linux/packet_diag.h", + "linux/param.h", + "linux/parport.h", + "linux/patchkey.h", + "linux/pci.h", + "linux/pci_regs.h", + "linux/perf_event.h", + "linux/personality.h", + "linux/pfkeyv2.h", + "linux/pg.h", + "linux/phantom.h", + "linux/phonet.h", + "linux/pkt_cls.h", + "linux/pkt_sched.h", + "linux/pktcdvd.h", + "linux/pmu.h", + "linux/poll.h", + "linux/posix_acl.h", + "linux/posix_acl_xattr.h", + "linux/posix_types.h", + "linux/ppdev.h", + "linux/ppp-comp.h", + "linux/ppp-ioctl.h", + "linux/ppp_defs.h", + "linux/pps.h", + "linux/prctl.h", + "linux/psci.h", + "linux/ptp_clock.h", + "linux/ptrace.h", + "linux/qbt1000.h", + "linux/qcedev.h", + "linux/qcota.h", + "linux/qg-profile.h", + "linux/qg.h", + "linux/qnx4_fs.h", + "linux/qnxtypes.h", + "linux/qrng.h", + "linux/qseecom.h", + "linux/quota.h", + "linux/radeonfb.h", + "linux/random.h", + "linux/raw.h", + "linux/rds.h", + "linux/reboot.h", + "linux/reiserfs_fs.h", + "linux/reiserfs_xattr.h", + "linux/resource.h", + "linux/rfkill.h", + "linux/rio_cm_cdev.h", + "linux/rio_mport_cdev.h", + "linux/rmnet_data.h", + "linux/rmnet_ipa_fd_ioctl.h", + "linux/romfs_fs.h", + "linux/rose.h", + "linux/route.h", + "linux/rtc.h", + "linux/rtnetlink.h", + "linux/scc.h", + "linux/sched.h", + "linux/scif_ioctl.h", + "linux/screen_info.h", + "linux/sctp.h", + "linux/sdla.h", + "linux/seccomp.h", + "linux/securebits.h", + "linux/seemp_api.h", + "linux/seemp_param_id.h", + "linux/selinux_netlink.h", + "linux/sem.h", + "linux/serial.h", + "linux/serial_core.h", + "linux/serial_reg.h", + "linux/serio.h", + "linux/shm.h", + "linux/signal.h", + "linux/signalfd.h", + "linux/smcinvoke.h", + "linux/smiapp.h", + "linux/snmp.h", + "linux/sock_diag.h", + "linux/socket.h", + "linux/sockev.h", + "linux/sockios.h", + "linux/sonet.h", + "linux/sonypi.h", + "linux/sound.h", + "linux/soundcard.h", + "linux/spcom.h", + "linux/stat.h", + "linux/stddef.h", + "linux/string.h", + "linux/suspend_ioctls.h", + "linux/swab.h", + "linux/sync_file.h", + "linux/synclink.h", + "linux/sysctl.h", + "linux/sysinfo.h", + "linux/target_core_user.h", + "linux/taskstats.h", + "linux/tcp.h", + "linux/tcp_metrics.h", + "linux/telephony.h", + "linux/termios.h", + "linux/thermal.h", + "linux/time.h", + "linux/times.h", + "linux/timex.h", + "linux/tiocl.h", + "linux/tipc.h", + "linux/tipc_config.h", + "linux/tipc_netlink.h", + "linux/toshiba.h", + "linux/tty.h", + "linux/tty_flags.h", + "linux/types.h", + "linux/udf_fs_i.h", + "linux/udp.h", + "linux/uhid.h", + "linux/uinput.h", + "linux/uio.h", + "linux/ultrasound.h", + "linux/un.h", + "linux/unistd.h", + "linux/unix_diag.h", + "linux/usbdevice_fs.h", + "linux/usbip.h", + "linux/userfaultfd.h", + "linux/utime.h", + "linux/utsname.h", + "linux/uuid.h", + "linux/uvcvideo.h", + "linux/v4l2-common.h", + "linux/v4l2-controls.h", + "linux/v4l2-dv-timings.h", + "linux/v4l2-mediabus.h", + "linux/v4l2-subdev.h", + "linux/veth.h", + "linux/vfio.h", + "linux/vhost.h", + "linux/videodev2.h", + "linux/virtio_9p.h", + "linux/virtio_balloon.h", + "linux/virtio_blk.h", + "linux/virtio_config.h", + "linux/virtio_console.h", + "linux/virtio_gpu.h", + "linux/virtio_ids.h", + "linux/virtio_input.h", + "linux/virtio_net.h", + "linux/virtio_pci.h", + "linux/virtio_ring.h", + "linux/virtio_rng.h", + "linux/virtio_scsi.h", + "linux/virtio_types.h", + "linux/virtio_vsock.h", + "linux/vm_bms.h", + "linux/vm_sockets.h", + "linux/vt.h", + "linux/vtpm_proxy.h", + "linux/wait.h", + "linux/wanrouter.h", + "linux/watchdog.h", + "linux/wimax.h", + "linux/wireless.h", + "linux/x25.h", + "linux/xattr.h", + "linux/xfrm.h", + "linux/xilinx-v4l2-controls.h", + "linux/zorro.h", + "linux/zorro_ids.h", + "media/cam_cpas.h", + "media/cam_defs.h", + "media/cam_fd.h", + "media/cam_icp.h", + "media/cam_isp.h", + "media/cam_isp_ife.h", + "media/cam_isp_vfe.h", + "media/cam_jpeg.h", + "media/cam_lrme.h", + "media/cam_req_mgr.h", + "media/cam_sensor.h", + "media/cam_sync.h", + "media/msm_cam_sensor.h", + "media/msm_camera.h", + "media/msm_camsensor_sdk.h", + "media/msm_fd.h", + "media/msm_isp.h", + "media/msm_jpeg.h", + "media/msm_jpeg_dma.h", + "media/msm_media_info.h", + "media/msm_sde_rotator.h", + "media/msm_vidc.h", + "media/msm_vidc_private.h", + "media/msmb_camera.h", + "media/msmb_generic_buf_mgr.h", + "media/msmb_isp.h", + "media/msmb_ispif.h", + "media/msmb_pproc.h", + "media/msmb_qca.h", + "media/radio-iris-commands.h", + "media/radio-iris.h", + "miniISP/miniISP_ioctl.h", + "misc/cxl.h", + "mtd/inftl-user.h", + "mtd/mtd-abi.h", + "mtd/mtd-user.h", + "mtd/nftl-user.h", + "mtd/ubi-user.h", + "rdma/cxgb3-abi.h", + "rdma/cxgb4-abi.h", + "rdma/ib_user_cm.h", + "rdma/ib_user_mad.h", + "rdma/ib_user_sa.h", + "rdma/ib_user_verbs.h", + "rdma/mlx4-abi.h", + "rdma/mlx5-abi.h", + "rdma/mthca-abi.h", + "rdma/nes-abi.h", + "rdma/ocrdma-abi.h", + "rdma/rdma_netlink.h", + "rdma/rdma_user_cm.h", + "rdma/rdma_user_rxe.h", + "scsi/cxlflash_ioctl.h", + "scsi/scsi_bsg_fc.h", + "scsi/scsi_ioctl.h", + "scsi/scsi_netlink.h", + "scsi/scsi_netlink_fc.h", + "scsi/sg.h", + "sound/asequencer.h", + "sound/asoc.h", + "sound/asound.h", + "sound/asound_fm.h", + "sound/compress_offload.h", + "sound/compress_params.h", + "sound/emu10k1.h", + "sound/firewire.h", + "sound/hdsp.h", + "sound/hdspm.h", + "sound/sb16_csp.h", + "sound/sfnt_info.h", + "sound/snd_sst_tokens.h", + "sound/tlv.h", + "sound/usb_stream.h", + "video/edid.h", + "video/msm_hdmi_hdcp_mgr.h", + "video/msm_hdmi_modes.h", + "video/sisfb.h", + "video/uvesafb.h", + "xen/evtchn.h", + "xen/gntalloc.h", + "xen/gntdev.h", + "xen/privcmd.h", + "linux/android/binder.h", + "linux/byteorder/big_endian.h", + "linux/byteorder/little_endian.h", + "linux/caif/caif_socket.h", + "linux/caif/if_caif.h", + "linux/can/bcm.h", + "linux/can/error.h", + "linux/can/gw.h", + "linux/can/netlink.h", + "linux/can/raw.h", + "linux/dvb/audio.h", + "linux/dvb/ca.h", + "linux/dvb/dmx.h", + "linux/dvb/frontend.h", + "linux/dvb/net.h", + "linux/dvb/osd.h", + "linux/dvb/version.h", + "linux/dvb/video.h", + "linux/hdlc/ioctl.h", + "linux/hsi/cs-protocol.h", + "linux/hsi/hsi_char.h", + "linux/iio/events.h", + "linux/iio/types.h", + "linux/isdn/capicmd.h", + "linux/mfd/msm-adie-codec.h", + "linux/mmc/core.h", + "linux/mmc/ioctl.h", + "linux/mmc/mmc.h", + "linux/netfilter/nf_conntrack_common.h", + "linux/netfilter/nf_conntrack_ftp.h", + "linux/netfilter/nf_conntrack_sctp.h", + "linux/netfilter/nf_conntrack_tcp.h", + "linux/netfilter/nf_conntrack_tuple_common.h", + "linux/netfilter/nf_log.h", + "linux/netfilter/nf_nat.h", + "linux/netfilter/nf_tables.h", + "linux/netfilter/nf_tables_compat.h", + "linux/netfilter/nfnetlink.h", + "linux/netfilter/nfnetlink_acct.h", + "linux/netfilter/nfnetlink_compat.h", + "linux/netfilter/nfnetlink_conntrack.h", + "linux/netfilter/nfnetlink_cthelper.h", + "linux/netfilter/nfnetlink_cttimeout.h", + "linux/netfilter/nfnetlink_log.h", + "linux/netfilter/nfnetlink_queue.h", + "linux/netfilter/x_tables.h", + "linux/netfilter/xt_AUDIT.h", + "linux/netfilter/xt_CHECKSUM.h", + "linux/netfilter/xt_CLASSIFY.h", + "linux/netfilter/xt_CONNMARK.h", + "linux/netfilter/xt_CONNSECMARK.h", + "linux/netfilter/xt_CT.h", + "linux/netfilter/xt_DSCP.h", + "linux/netfilter/xt_HMARK.h", + "linux/netfilter/xt_IDLETIMER.h", + "linux/netfilter/xt_LED.h", + "linux/netfilter/xt_LOG.h", + "linux/netfilter/xt_MARK.h", + "linux/netfilter/xt_NFLOG.h", + "linux/netfilter/xt_NFQUEUE.h", + "linux/netfilter/xt_RATEEST.h", + "linux/netfilter/xt_SECMARK.h", + "linux/netfilter/xt_SYNPROXY.h", + "linux/netfilter/xt_TCPMSS.h", + "linux/netfilter/xt_TCPOPTSTRIP.h", + "linux/netfilter/xt_TEE.h", + "linux/netfilter/xt_TPROXY.h", + "linux/netfilter/xt_addrtype.h", + "linux/netfilter/xt_bpf.h", + "linux/netfilter/xt_cgroup.h", + "linux/netfilter/xt_cluster.h", + "linux/netfilter/xt_comment.h", + "linux/netfilter/xt_connbytes.h", + "linux/netfilter/xt_connlabel.h", + "linux/netfilter/xt_connlimit.h", + "linux/netfilter/xt_connmark.h", + "linux/netfilter/xt_conntrack.h", + "linux/netfilter/xt_cpu.h", + "linux/netfilter/xt_dccp.h", + "linux/netfilter/xt_devgroup.h", + "linux/netfilter/xt_dscp.h", + "linux/netfilter/xt_ecn.h", + "linux/netfilter/xt_esp.h", + "linux/netfilter/xt_hashlimit.h", + "linux/netfilter/xt_helper.h", + "linux/netfilter/xt_ipcomp.h", + "linux/netfilter/xt_iprange.h", + "linux/netfilter/xt_ipvs.h", + "linux/netfilter/xt_l2tp.h", + "linux/netfilter/xt_length.h", + "linux/netfilter/xt_limit.h", + "linux/netfilter/xt_mac.h", + "linux/netfilter/xt_mark.h", + "linux/netfilter/xt_multiport.h", + "linux/netfilter/xt_nfacct.h", + "linux/netfilter/xt_osf.h", + "linux/netfilter/xt_owner.h", + "linux/netfilter/xt_physdev.h", + "linux/netfilter/xt_pkttype.h", + "linux/netfilter/xt_policy.h", + "linux/netfilter/xt_quota.h", + "linux/netfilter/xt_rateest.h", + "linux/netfilter/xt_realm.h", + "linux/netfilter/xt_recent.h", + "linux/netfilter/xt_rpfilter.h", + "linux/netfilter/xt_sctp.h", + "linux/netfilter/xt_set.h", + "linux/netfilter/xt_socket.h", + "linux/netfilter/xt_state.h", + "linux/netfilter/xt_statistic.h", + "linux/netfilter/xt_string.h", + "linux/netfilter/xt_tcpmss.h", + "linux/netfilter/xt_tcpudp.h", + "linux/netfilter/xt_time.h", + "linux/netfilter/xt_u32.h", + "linux/netfilter_arp/arp_tables.h", + "linux/netfilter_arp/arpt_mangle.h", + "linux/netfilter_bridge/ebt_802_3.h", + "linux/netfilter_bridge/ebt_among.h", + "linux/netfilter_bridge/ebt_arp.h", + "linux/netfilter_bridge/ebt_arpreply.h", + "linux/netfilter_bridge/ebt_ip.h", + "linux/netfilter_bridge/ebt_ip6.h", + "linux/netfilter_bridge/ebt_limit.h", + "linux/netfilter_bridge/ebt_log.h", + "linux/netfilter_bridge/ebt_mark_m.h", + "linux/netfilter_bridge/ebt_mark_t.h", + "linux/netfilter_bridge/ebt_nat.h", + "linux/netfilter_bridge/ebt_nflog.h", + "linux/netfilter_bridge/ebt_pkttype.h", + "linux/netfilter_bridge/ebt_redirect.h", + "linux/netfilter_bridge/ebt_stp.h", + "linux/netfilter_bridge/ebt_vlan.h", + "linux/netfilter_bridge/ebtables.h", + "linux/netfilter_ipv4/ip_tables.h", + "linux/netfilter_ipv4/ipt_CLUSTERIP.h", + "linux/netfilter_ipv4/ipt_ECN.h", + "linux/netfilter_ipv4/ipt_LOG.h", + "linux/netfilter_ipv4/ipt_NATTYPE.h", + "linux/netfilter_ipv4/ipt_REJECT.h", + "linux/netfilter_ipv4/ipt_TTL.h", + "linux/netfilter_ipv4/ipt_ah.h", + "linux/netfilter_ipv4/ipt_ecn.h", + "linux/netfilter_ipv4/ipt_ttl.h", + "linux/netfilter_ipv6/ip6_tables.h", + "linux/netfilter_ipv6/ip6t_HL.h", + "linux/netfilter_ipv6/ip6t_LOG.h", + "linux/netfilter_ipv6/ip6t_NPT.h", + "linux/netfilter_ipv6/ip6t_REJECT.h", + "linux/netfilter_ipv6/ip6t_ah.h", + "linux/netfilter_ipv6/ip6t_frag.h", + "linux/netfilter_ipv6/ip6t_hl.h", + "linux/netfilter_ipv6/ip6t_ipv6header.h", + "linux/netfilter_ipv6/ip6t_mh.h", + "linux/netfilter_ipv6/ip6t_opts.h", + "linux/netfilter_ipv6/ip6t_rt.h", + "linux/nfc/nfcinfo.h", + "linux/nfsd/cld.h", + "linux/nfsd/debug.h", + "linux/nfsd/export.h", + "linux/nfsd/nfsfh.h", + "linux/nfsd/stats.h", + "linux/raid/md_p.h", + "linux/raid/md_u.h", + "linux/spi/spidev.h", + "linux/sunrpc/debug.h", + "linux/tc_act/tc_bpf.h", + "linux/tc_act/tc_connmark.h", + "linux/tc_act/tc_csum.h", + "linux/tc_act/tc_defact.h", + "linux/tc_act/tc_gact.h", + "linux/tc_act/tc_ife.h", + "linux/tc_act/tc_ipt.h", + "linux/tc_act/tc_mirred.h", + "linux/tc_act/tc_nat.h", + "linux/tc_act/tc_pedit.h", + "linux/tc_act/tc_skbedit.h", + "linux/tc_act/tc_skbmod.h", + "linux/tc_act/tc_tunnel_key.h", + "linux/tc_act/tc_vlan.h", + "linux/tc_ematch/tc_em_cmp.h", + "linux/tc_ematch/tc_em_meta.h", + "linux/tc_ematch/tc_em_nbyte.h", + "linux/tc_ematch/tc_em_text.h", + "linux/usb/audio.h", + "linux/usb/cdc-wdm.h", + "linux/usb/cdc.h", + "linux/usb/ch11.h", + "linux/usb/ch9.h", + "linux/usb/functionfs.h", + "linux/usb/g_printer.h", + "linux/usb/gadgetfs.h", + "linux/usb/midi.h", + "linux/usb/tmc.h", + "linux/usb/usb_ctrl_qti.h", + "linux/usb/video.h", + "linux/wimax/i2400m.h", + "rdma/hfi/hfi1_user.h", + "scsi/fc/fc_els.h", + "scsi/fc/fc_fs.h", + "scsi/fc/fc_gs.h", + "scsi/fc/fc_ns.h", + "scsi/ufs/ioctl.h", + "scsi/ufs/ufs.h", + "linux/mfd/wcd9xxx/wcd9320_registers.h", + "linux/mfd/wcd9xxx/wcd9xxx_registers.h", + "linux/netfilter/ipset/ip_set.h", + "linux/netfilter/ipset/ip_set_bitmap.h", + "linux/netfilter/ipset/ip_set_hash.h", + "linux/netfilter/ipset/ip_set_list.h", + + // From arch/arm/include/uapi/**/*.h + + "asm/auxvec.h", + "asm/byteorder.h", + "asm/fcntl.h", + "asm/hwcap.h", + "asm/ioctls.h", + "asm/kvm.h", + "asm/kvm_para.h", + "asm/mman.h", + "asm/perf_regs.h", + "asm/posix_types.h", + "asm/ptrace.h", + "asm/setup.h", + "asm/sigcontext.h", + "asm/signal.h", + "asm/stat.h", + "asm/statfs.h", + "asm/swab.h", + "asm/types.h", + "asm/unistd.h", +] + +genrule { + // This module generates the gen_headers_.bp file + // (i.e., a new version of this file) so that it can be + // checked later to ensure that it matches the checked- + // in version (this file). + name: "qti_generate_gen_headers_arm", + srcs: gen_headers_srcs_arm, + exclude_srcs: gen_headers_exclude_srcs_arm, + tool_files: ["kernel_headers.py"], + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm/include/uapi/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild.asm) " + + "blueprints " + + "# $(in)", + out: ["gen_headers_arm.bp"], +} + +genrule { + name: "qti_generate_kernel_headers_arm", + tools: ["headers_install.sh"], + tool_files: [ + "kernel_headers.py", + "arch/arm/tools/syscallhdr.sh", + ], + srcs: gen_headers_srcs_arm +[ + "gen_headers_arm.bp", + ":qti_generate_gen_headers_arm", + ], + exclude_srcs: gen_headers_exclude_srcs_arm, + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm/include/uapi/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild.asm) " + + "headers " + + "--old_gen_headers_bp $(location gen_headers_arm.bp) " + + "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm) " + + "--version_makefile $(location Makefile) " + + "--arch_syscall_tool $(location arch/arm/tools/syscallhdr.sh) " + + "--arch_syscall_tbl $(location arch/arm/tools/syscall.tbl) " + + "--headers_install $(location headers_install.sh) " + + "--include_uapi $(locations include/uapi/**/*.h)", + out: ["linux/version.h"] + gen_headers_out_arm, +} diff --git a/gen_headers_arm64.bp b/gen_headers_arm64.bp new file mode 100644 index 0000000000000000000000000000000000000000..5060c14f9d0ad15c7e7e423e09656d350cbc764e --- /dev/null +++ b/gen_headers_arm64.bp @@ -0,0 +1,970 @@ +// ***** DO NOT EDIT ***** +// This file is generated by kernel_headers.py + +gen_headers_srcs_arm64 = [ + "arch/arm64/include/uapi/asm/Kbuild", + "include/uapi/asm-generic/Kbuild.asm", + "Makefile", + "include/uapi/**/*.h", + "arch/arm64/include/uapi/**/*.h", +] + +gen_headers_exclude_srcs_arm64 = [ + "include/uapi/linux/a.out.h", + "include/uapi/linux/kvm_para.h", + "include/uapi/drm/armada_drm.h", + "include/uapi/drm/etnaviv_drm.h", + "include/uapi/drm/omap_drm.h", + "include/uapi/drm/vgem_drm.h", + "include/uapi/linux/auto_dev-ioctl.h", + "include/uapi/linux/batman_adv.h", + "include/uapi/linux/bcache.h", + "include/uapi/linux/btrfs_tree.h", + "include/uapi/linux/cryptouser.h", + "include/uapi/linux/dma-buf.h", + "include/uapi/linux/hash_info.h", + "include/uapi/linux/kcm.h", + "include/uapi/linux/kcov.h", + "include/uapi/linux/kfd_ioctl.h", + "include/uapi/linux/lightnvm.h", + "include/uapi/linux/module.h", + "include/uapi/linux/nilfs2_api.h", + "include/uapi/linux/nilfs2_ondisk.h", + "include/uapi/linux/nsfs.h", + "include/uapi/linux/pr.h", + "include/uapi/linux/qrtr.h", + "include/uapi/linux/stm.h", + "include/uapi/linux/tee.h", + "include/uapi/linux/userio.h", + "include/uapi/linux/wil6210_uapi.h", + "include/uapi/rdma/qedr-abi.h", + "include/uapi/video/adf.h", + "include/uapi/linux/cifs/cifs_mount.h", + "include/uapi/linux/genwqe/genwqe_card.h", + "include/uapi/linux/netfilter/xt_HARDIDLETIMER.h", + "include/uapi/linux/usb/f_accessory.h", + "include/uapi/linux/usb/f_mtp.h", +] + +gen_headers_out_arm64 = [ + + // Matching generic-y: + + "asm/kvm_para.h", + + // Matching mandatory-y: + + "asm/errno.h", + "asm/ioctl.h", + "asm/ioctls.h", + "asm/ipcbuf.h", + "asm/mman.h", + "asm/msgbuf.h", + "asm/poll.h", + "asm/resource.h", + "asm/sembuf.h", + "asm/shmbuf.h", + "asm/socket.h", + "asm/sockios.h", + "asm/swab.h", + "asm/termbits.h", + "asm/termios.h", + "asm/types.h", + + // From include/uapi/**/*.h + + "asm-generic/auxvec.h", + "asm-generic/bitsperlong.h", + "asm-generic/errno-base.h", + "asm-generic/errno.h", + "asm-generic/fcntl.h", + "asm-generic/int-l64.h", + "asm-generic/int-ll64.h", + "asm-generic/ioctl.h", + "asm-generic/ioctls.h", + "asm-generic/ipcbuf.h", + "asm-generic/kvm_para.h", + "asm-generic/mman-common.h", + "asm-generic/mman.h", + "asm-generic/msgbuf.h", + "asm-generic/param.h", + "asm-generic/poll.h", + "asm-generic/posix_types.h", + "asm-generic/resource.h", + "asm-generic/sembuf.h", + "asm-generic/setup.h", + "asm-generic/shmbuf.h", + "asm-generic/shmparam.h", + "asm-generic/siginfo.h", + "asm-generic/signal-defs.h", + "asm-generic/signal.h", + "asm-generic/socket.h", + "asm-generic/sockios.h", + "asm-generic/stat.h", + "asm-generic/statfs.h", + "asm-generic/swab.h", + "asm-generic/termbits.h", + "asm-generic/termios.h", + "asm-generic/types.h", + "asm-generic/ucontext.h", + "asm-generic/unistd.h", + "drm/amdgpu_drm.h", + "drm/drm.h", + "drm/drm_fourcc.h", + "drm/drm_mode.h", + "drm/drm_sarea.h", + "drm/exynos_drm.h", + "drm/i810_drm.h", + "drm/i915_drm.h", + "drm/mga_drm.h", + "drm/msm_drm.h", + "drm/msm_drm_pp.h", + "drm/nouveau_drm.h", + "drm/qxl_drm.h", + "drm/r128_drm.h", + "drm/radeon_drm.h", + "drm/savage_drm.h", + "drm/sde_drm.h", + "drm/sis_drm.h", + "drm/tegra_drm.h", + "drm/vc4_drm.h", + "drm/via_drm.h", + "drm/virtgpu_drm.h", + "drm/vmwgfx_drm.h", + "linux/acct.h", + "linux/adb.h", + "linux/adfs_fs.h", + "linux/affs_hardblocks.h", + "linux/agpgart.h", + "linux/aio_abi.h", + "linux/am437x-vpfe.h", + "linux/apm_bios.h", + "linux/arcfb.h", + "linux/atalk.h", + "linux/atm.h", + "linux/atm_eni.h", + "linux/atm_he.h", + "linux/atm_idt77105.h", + "linux/atm_nicstar.h", + "linux/atm_tcp.h", + "linux/atm_zatm.h", + "linux/atmapi.h", + "linux/atmarp.h", + "linux/atmbr2684.h", + "linux/atmclip.h", + "linux/atmdev.h", + "linux/atmioc.h", + "linux/atmlec.h", + "linux/atmmpc.h", + "linux/atmppp.h", + "linux/atmsap.h", + "linux/atmsvc.h", + "linux/audit.h", + "linux/auto_fs.h", + "linux/auto_fs4.h", + "linux/auxvec.h", + "linux/ax25.h", + "linux/b1lli.h", + "linux/batterydata-interface.h", + "linux/baycom.h", + "linux/bcm933xx_hcs.h", + "linux/bfs_fs.h", + "linux/bgcom_interface.h", + "linux/binfmts.h", + "linux/blkpg.h", + "linux/blktrace_api.h", + "linux/bpf.h", + "linux/bpf_common.h", + "linux/bpf_perf_event.h", + "linux/bpqether.h", + "linux/bsg.h", + "linux/bt-bmc.h", + "linux/btrfs.h", + "linux/can.h", + "linux/capability.h", + "linux/capi.h", + "linux/cciss_defs.h", + "linux/cciss_ioctl.h", + "linux/cdrom.h", + "linux/cgroupstats.h", + "linux/chio.h", + "linux/cm4000_cs.h", + "linux/cn_proc.h", + "linux/coda.h", + "linux/coda_psdev.h", + "linux/coff.h", + "linux/connector.h", + "linux/const.h", + "linux/coresight-stm.h", + "linux/cramfs_fs.h", + "linux/cuda.h", + "linux/cyclades.h", + "linux/cycx_cfm.h", + "linux/dcbnl.h", + "linux/dccp.h", + "linux/devlink.h", + "linux/dlm.h", + "linux/dlm_device.h", + "linux/dlm_netlink.h", + "linux/dlm_plock.h", + "linux/dlmconstants.h", + "linux/dm-ioctl.h", + "linux/dm-log-userspace.h", + "linux/dn.h", + "linux/dqblk_xfs.h", + "linux/edd.h", + "linux/efs_fs_sb.h", + "linux/elf-em.h", + "linux/elf-fdpic.h", + "linux/elf.h", + "linux/elfcore.h", + "linux/errno.h", + "linux/errqueue.h", + "linux/esoc_ctrl.h", + "linux/ethtool.h", + "linux/eventpoll.h", + "linux/fadvise.h", + "linux/falloc.h", + "linux/fanotify.h", + "linux/fb.h", + "linux/fcntl.h", + "linux/fd.h", + "linux/fdreg.h", + "linux/fib_rules.h", + "linux/fiemap.h", + "linux/filter.h", + "linux/fips_status.h", + "linux/firewire-cdev.h", + "linux/firewire-constants.h", + "linux/flat.h", + "linux/fou.h", + "linux/fs.h", + "linux/fsl_hypervisor.h", + "linux/fuse.h", + "linux/futex.h", + "linux/gameport.h", + "linux/gen_stats.h", + "linux/genetlink.h", + "linux/gfs2_ondisk.h", + "linux/gigaset_dev.h", + "linux/gpio.h", + "linux/gsmmux.h", + "linux/gtp.h", + "linux/hbtp_input.h", + "linux/hdlc.h", + "linux/hdlcdrv.h", + "linux/hdreg.h", + "linux/hid.h", + "linux/hiddev.h", + "linux/hidraw.h", + "linux/hpet.h", + "linux/hsr_netlink.h", + "linux/hw_breakpoint.h", + "linux/hyperv.h", + "linux/hysdn_if.h", + "linux/i2c-dev.h", + "linux/i2c.h", + "linux/i2o-dev.h", + "linux/i8k.h", + "linux/icmp.h", + "linux/icmpv6.h", + "linux/if.h", + "linux/if_addr.h", + "linux/if_addrlabel.h", + "linux/if_alg.h", + "linux/if_arcnet.h", + "linux/if_arp.h", + "linux/if_bonding.h", + "linux/if_bridge.h", + "linux/if_cablemodem.h", + "linux/if_eql.h", + "linux/if_ether.h", + "linux/if_fc.h", + "linux/if_fddi.h", + "linux/if_frad.h", + "linux/if_hippi.h", + "linux/if_infiniband.h", + "linux/if_link.h", + "linux/if_ltalk.h", + "linux/if_macsec.h", + "linux/if_packet.h", + "linux/if_phonet.h", + "linux/if_plip.h", + "linux/if_ppp.h", + "linux/if_pppol2tp.h", + "linux/if_pppolac.h", + "linux/if_pppopns.h", + "linux/if_pppox.h", + "linux/if_slip.h", + "linux/if_team.h", + "linux/if_tun.h", + "linux/if_tunnel.h", + "linux/if_vlan.h", + "linux/if_x25.h", + "linux/igmp.h", + "linux/ila.h", + "linux/in.h", + "linux/in6.h", + "linux/in_route.h", + "linux/inet_diag.h", + "linux/inotify.h", + "linux/input-event-codes.h", + "linux/input.h", + "linux/ioctl.h", + "linux/ion.h", + "linux/ip.h", + "linux/ip6_tunnel.h", + "linux/ip_vs.h", + "linux/ipa_qmi_service_v01.h", + "linux/ipc.h", + "linux/ipmi.h", + "linux/ipmi_msgdefs.h", + "linux/ipsec.h", + "linux/ipv6.h", + "linux/ipv6_route.h", + "linux/ipx.h", + "linux/irda.h", + "linux/irqnr.h", + "linux/isdn.h", + "linux/isdn_divertif.h", + "linux/isdn_ppp.h", + "linux/isdnif.h", + "linux/iso_fs.h", + "linux/ivtv.h", + "linux/ivtvfb.h", + "linux/ixjuser.h", + "linux/jffs2.h", + "linux/joystick.h", + "linux/kcmp.h", + "linux/kd.h", + "linux/kdev_t.h", + "linux/kernel-page-flags.h", + "linux/kernel.h", + "linux/kernelcapi.h", + "linux/kexec.h", + "linux/keyboard.h", + "linux/keyctl.h", + "linux/kvm.h", + "linux/l2tp.h", + "linux/libc-compat.h", + "linux/limits.h", + "linux/lirc.h", + "linux/llc.h", + "linux/loop.h", + "linux/lp.h", + "linux/lwtunnel.h", + "linux/magic.h", + "linux/major.h", + "linux/map_to_7segment.h", + "linux/matroxfb.h", + "linux/mdio.h", + "linux/mdss_rotator.h", + "linux/media-bus-format.h", + "linux/media.h", + "linux/mei.h", + "linux/membarrier.h", + "linux/memfd.h", + "linux/mempolicy.h", + "linux/meye.h", + "linux/mhi.h", + "linux/mic_common.h", + "linux/mic_ioctl.h", + "linux/mii.h", + "linux/minix_fs.h", + "linux/mman.h", + "linux/mmtimer.h", + "linux/mpls.h", + "linux/mpls_iptunnel.h", + "linux/mqueue.h", + "linux/mroute.h", + "linux/mroute6.h", + "linux/msdos_fs.h", + "linux/msg.h", + "linux/msm-core-interface.h", + "linux/msm_dsps.h", + "linux/msm_ion.h", + "linux/msm_ipa.h", + "linux/msm_ipc.h", + "linux/msm_kgsl.h", + "linux/msm_mdp.h", + "linux/msm_mdp_ext.h", + "linux/msm_rmnet.h", + "linux/msm_rotator.h", + "linux/msm_vidc_dec.h", + "linux/msm_vidc_enc.h", + "linux/mtio.h", + "linux/n_r3964.h", + "linux/nbd.h", + "linux/ncp.h", + "linux/ncp_fs.h", + "linux/ncp_mount.h", + "linux/ncp_no.h", + "linux/ndctl.h", + "linux/neighbour.h", + "linux/net.h", + "linux/net_dropmon.h", + "linux/net_map.h", + "linux/net_namespace.h", + "linux/net_tstamp.h", + "linux/netconf.h", + "linux/netdevice.h", + "linux/netfilter.h", + "linux/netfilter_arp.h", + "linux/netfilter_bridge.h", + "linux/netfilter_decnet.h", + "linux/netfilter_ipv4.h", + "linux/netfilter_ipv6.h", + "linux/netlink.h", + "linux/netlink_diag.h", + "linux/netrom.h", + "linux/nfc.h", + "linux/nfs.h", + "linux/nfs2.h", + "linux/nfs3.h", + "linux/nfs4.h", + "linux/nfs4_mount.h", + "linux/nfs_fs.h", + "linux/nfs_idmap.h", + "linux/nfs_mount.h", + "linux/nfsacl.h", + "linux/nl80211.h", + "linux/nubus.h", + "linux/nvme_ioctl.h", + "linux/nvram.h", + "linux/okl4-link-shbuf.h", + "linux/omap3isp.h", + "linux/omapfb.h", + "linux/oom.h", + "linux/openvswitch.h", + "linux/packet_diag.h", + "linux/param.h", + "linux/parport.h", + "linux/patchkey.h", + "linux/pci.h", + "linux/pci_regs.h", + "linux/perf_event.h", + "linux/personality.h", + "linux/pfkeyv2.h", + "linux/pg.h", + "linux/phantom.h", + "linux/phonet.h", + "linux/pkt_cls.h", + "linux/pkt_sched.h", + "linux/pktcdvd.h", + "linux/pmu.h", + "linux/poll.h", + "linux/posix_acl.h", + "linux/posix_acl_xattr.h", + "linux/posix_types.h", + "linux/ppdev.h", + "linux/ppp-comp.h", + "linux/ppp-ioctl.h", + "linux/ppp_defs.h", + "linux/pps.h", + "linux/prctl.h", + "linux/psci.h", + "linux/ptp_clock.h", + "linux/ptrace.h", + "linux/qbt1000.h", + "linux/qcedev.h", + "linux/qcota.h", + "linux/qg-profile.h", + "linux/qg.h", + "linux/qnx4_fs.h", + "linux/qnxtypes.h", + "linux/qrng.h", + "linux/qseecom.h", + "linux/quota.h", + "linux/radeonfb.h", + "linux/random.h", + "linux/raw.h", + "linux/rds.h", + "linux/reboot.h", + "linux/reiserfs_fs.h", + "linux/reiserfs_xattr.h", + "linux/resource.h", + "linux/rfkill.h", + "linux/rio_cm_cdev.h", + "linux/rio_mport_cdev.h", + "linux/rmnet_data.h", + "linux/rmnet_ipa_fd_ioctl.h", + "linux/romfs_fs.h", + "linux/rose.h", + "linux/route.h", + "linux/rtc.h", + "linux/rtnetlink.h", + "linux/scc.h", + "linux/sched.h", + "linux/scif_ioctl.h", + "linux/screen_info.h", + "linux/sctp.h", + "linux/sdla.h", + "linux/seccomp.h", + "linux/securebits.h", + "linux/seemp_api.h", + "linux/seemp_param_id.h", + "linux/selinux_netlink.h", + "linux/sem.h", + "linux/serial.h", + "linux/serial_core.h", + "linux/serial_reg.h", + "linux/serio.h", + "linux/shm.h", + "linux/signal.h", + "linux/signalfd.h", + "linux/smcinvoke.h", + "linux/smiapp.h", + "linux/snmp.h", + "linux/sock_diag.h", + "linux/socket.h", + "linux/sockev.h", + "linux/sockios.h", + "linux/sonet.h", + "linux/sonypi.h", + "linux/sound.h", + "linux/soundcard.h", + "linux/spcom.h", + "linux/stat.h", + "linux/stddef.h", + "linux/string.h", + "linux/suspend_ioctls.h", + "linux/swab.h", + "linux/sync_file.h", + "linux/synclink.h", + "linux/sysctl.h", + "linux/sysinfo.h", + "linux/target_core_user.h", + "linux/taskstats.h", + "linux/tcp.h", + "linux/tcp_metrics.h", + "linux/telephony.h", + "linux/termios.h", + "linux/thermal.h", + "linux/time.h", + "linux/times.h", + "linux/timex.h", + "linux/tiocl.h", + "linux/tipc.h", + "linux/tipc_config.h", + "linux/tipc_netlink.h", + "linux/toshiba.h", + "linux/tty.h", + "linux/tty_flags.h", + "linux/types.h", + "linux/udf_fs_i.h", + "linux/udp.h", + "linux/uhid.h", + "linux/uinput.h", + "linux/uio.h", + "linux/ultrasound.h", + "linux/un.h", + "linux/unistd.h", + "linux/unix_diag.h", + "linux/usbdevice_fs.h", + "linux/usbip.h", + "linux/userfaultfd.h", + "linux/utime.h", + "linux/utsname.h", + "linux/uuid.h", + "linux/uvcvideo.h", + "linux/v4l2-common.h", + "linux/v4l2-controls.h", + "linux/v4l2-dv-timings.h", + "linux/v4l2-mediabus.h", + "linux/v4l2-subdev.h", + "linux/veth.h", + "linux/vfio.h", + "linux/vhost.h", + "linux/videodev2.h", + "linux/virtio_9p.h", + "linux/virtio_balloon.h", + "linux/virtio_blk.h", + "linux/virtio_config.h", + "linux/virtio_console.h", + "linux/virtio_gpu.h", + "linux/virtio_ids.h", + "linux/virtio_input.h", + "linux/virtio_net.h", + "linux/virtio_pci.h", + "linux/virtio_ring.h", + "linux/virtio_rng.h", + "linux/virtio_scsi.h", + "linux/virtio_types.h", + "linux/virtio_vsock.h", + "linux/vm_bms.h", + "linux/vm_sockets.h", + "linux/vt.h", + "linux/vtpm_proxy.h", + "linux/wait.h", + "linux/wanrouter.h", + "linux/watchdog.h", + "linux/wimax.h", + "linux/wireless.h", + "linux/x25.h", + "linux/xattr.h", + "linux/xfrm.h", + "linux/xilinx-v4l2-controls.h", + "linux/zorro.h", + "linux/zorro_ids.h", + "media/cam_cpas.h", + "media/cam_defs.h", + "media/cam_fd.h", + "media/cam_icp.h", + "media/cam_isp.h", + "media/cam_isp_ife.h", + "media/cam_isp_vfe.h", + "media/cam_jpeg.h", + "media/cam_lrme.h", + "media/cam_req_mgr.h", + "media/cam_sensor.h", + "media/cam_sync.h", + "media/msm_cam_sensor.h", + "media/msm_camera.h", + "media/msm_camsensor_sdk.h", + "media/msm_fd.h", + "media/msm_isp.h", + "media/msm_jpeg.h", + "media/msm_jpeg_dma.h", + "media/msm_media_info.h", + "media/msm_sde_rotator.h", + "media/msm_vidc.h", + "media/msm_vidc_private.h", + "media/msmb_camera.h", + "media/msmb_generic_buf_mgr.h", + "media/msmb_isp.h", + "media/msmb_ispif.h", + "media/msmb_pproc.h", + "media/msmb_qca.h", + "media/radio-iris-commands.h", + "media/radio-iris.h", + "miniISP/miniISP_ioctl.h", + "misc/cxl.h", + "mtd/inftl-user.h", + "mtd/mtd-abi.h", + "mtd/mtd-user.h", + "mtd/nftl-user.h", + "mtd/ubi-user.h", + "rdma/cxgb3-abi.h", + "rdma/cxgb4-abi.h", + "rdma/ib_user_cm.h", + "rdma/ib_user_mad.h", + "rdma/ib_user_sa.h", + "rdma/ib_user_verbs.h", + "rdma/mlx4-abi.h", + "rdma/mlx5-abi.h", + "rdma/mthca-abi.h", + "rdma/nes-abi.h", + "rdma/ocrdma-abi.h", + "rdma/rdma_netlink.h", + "rdma/rdma_user_cm.h", + "rdma/rdma_user_rxe.h", + "scsi/cxlflash_ioctl.h", + "scsi/scsi_bsg_fc.h", + "scsi/scsi_ioctl.h", + "scsi/scsi_netlink.h", + "scsi/scsi_netlink_fc.h", + "scsi/sg.h", + "sound/asequencer.h", + "sound/asoc.h", + "sound/asound.h", + "sound/asound_fm.h", + "sound/compress_offload.h", + "sound/compress_params.h", + "sound/emu10k1.h", + "sound/firewire.h", + "sound/hdsp.h", + "sound/hdspm.h", + "sound/sb16_csp.h", + "sound/sfnt_info.h", + "sound/snd_sst_tokens.h", + "sound/tlv.h", + "sound/usb_stream.h", + "video/edid.h", + "video/msm_hdmi_hdcp_mgr.h", + "video/msm_hdmi_modes.h", + "video/sisfb.h", + "video/uvesafb.h", + "xen/evtchn.h", + "xen/gntalloc.h", + "xen/gntdev.h", + "xen/privcmd.h", + "linux/android/binder.h", + "linux/byteorder/big_endian.h", + "linux/byteorder/little_endian.h", + "linux/caif/caif_socket.h", + "linux/caif/if_caif.h", + "linux/can/bcm.h", + "linux/can/error.h", + "linux/can/gw.h", + "linux/can/netlink.h", + "linux/can/raw.h", + "linux/dvb/audio.h", + "linux/dvb/ca.h", + "linux/dvb/dmx.h", + "linux/dvb/frontend.h", + "linux/dvb/net.h", + "linux/dvb/osd.h", + "linux/dvb/version.h", + "linux/dvb/video.h", + "linux/hdlc/ioctl.h", + "linux/hsi/cs-protocol.h", + "linux/hsi/hsi_char.h", + "linux/iio/events.h", + "linux/iio/types.h", + "linux/isdn/capicmd.h", + "linux/mfd/msm-adie-codec.h", + "linux/mmc/core.h", + "linux/mmc/ioctl.h", + "linux/mmc/mmc.h", + "linux/netfilter/nf_conntrack_common.h", + "linux/netfilter/nf_conntrack_ftp.h", + "linux/netfilter/nf_conntrack_sctp.h", + "linux/netfilter/nf_conntrack_tcp.h", + "linux/netfilter/nf_conntrack_tuple_common.h", + "linux/netfilter/nf_log.h", + "linux/netfilter/nf_nat.h", + "linux/netfilter/nf_tables.h", + "linux/netfilter/nf_tables_compat.h", + "linux/netfilter/nfnetlink.h", + "linux/netfilter/nfnetlink_acct.h", + "linux/netfilter/nfnetlink_compat.h", + "linux/netfilter/nfnetlink_conntrack.h", + "linux/netfilter/nfnetlink_cthelper.h", + "linux/netfilter/nfnetlink_cttimeout.h", + "linux/netfilter/nfnetlink_log.h", + "linux/netfilter/nfnetlink_queue.h", + "linux/netfilter/x_tables.h", + "linux/netfilter/xt_AUDIT.h", + "linux/netfilter/xt_CHECKSUM.h", + "linux/netfilter/xt_CLASSIFY.h", + "linux/netfilter/xt_CONNMARK.h", + "linux/netfilter/xt_CONNSECMARK.h", + "linux/netfilter/xt_CT.h", + "linux/netfilter/xt_DSCP.h", + "linux/netfilter/xt_HMARK.h", + "linux/netfilter/xt_IDLETIMER.h", + "linux/netfilter/xt_LED.h", + "linux/netfilter/xt_LOG.h", + "linux/netfilter/xt_MARK.h", + "linux/netfilter/xt_NFLOG.h", + "linux/netfilter/xt_NFQUEUE.h", + "linux/netfilter/xt_RATEEST.h", + "linux/netfilter/xt_SECMARK.h", + "linux/netfilter/xt_SYNPROXY.h", + "linux/netfilter/xt_TCPMSS.h", + "linux/netfilter/xt_TCPOPTSTRIP.h", + "linux/netfilter/xt_TEE.h", + "linux/netfilter/xt_TPROXY.h", + "linux/netfilter/xt_addrtype.h", + "linux/netfilter/xt_bpf.h", + "linux/netfilter/xt_cgroup.h", + "linux/netfilter/xt_cluster.h", + "linux/netfilter/xt_comment.h", + "linux/netfilter/xt_connbytes.h", + "linux/netfilter/xt_connlabel.h", + "linux/netfilter/xt_connlimit.h", + "linux/netfilter/xt_connmark.h", + "linux/netfilter/xt_conntrack.h", + "linux/netfilter/xt_cpu.h", + "linux/netfilter/xt_dccp.h", + "linux/netfilter/xt_devgroup.h", + "linux/netfilter/xt_dscp.h", + "linux/netfilter/xt_ecn.h", + "linux/netfilter/xt_esp.h", + "linux/netfilter/xt_hashlimit.h", + "linux/netfilter/xt_helper.h", + "linux/netfilter/xt_ipcomp.h", + "linux/netfilter/xt_iprange.h", + "linux/netfilter/xt_ipvs.h", + "linux/netfilter/xt_l2tp.h", + "linux/netfilter/xt_length.h", + "linux/netfilter/xt_limit.h", + "linux/netfilter/xt_mac.h", + "linux/netfilter/xt_mark.h", + "linux/netfilter/xt_multiport.h", + "linux/netfilter/xt_nfacct.h", + "linux/netfilter/xt_osf.h", + "linux/netfilter/xt_owner.h", + "linux/netfilter/xt_physdev.h", + "linux/netfilter/xt_pkttype.h", + "linux/netfilter/xt_policy.h", + "linux/netfilter/xt_quota.h", + "linux/netfilter/xt_rateest.h", + "linux/netfilter/xt_realm.h", + "linux/netfilter/xt_recent.h", + "linux/netfilter/xt_rpfilter.h", + "linux/netfilter/xt_sctp.h", + "linux/netfilter/xt_set.h", + "linux/netfilter/xt_socket.h", + "linux/netfilter/xt_state.h", + "linux/netfilter/xt_statistic.h", + "linux/netfilter/xt_string.h", + "linux/netfilter/xt_tcpmss.h", + "linux/netfilter/xt_tcpudp.h", + "linux/netfilter/xt_time.h", + "linux/netfilter/xt_u32.h", + "linux/netfilter_arp/arp_tables.h", + "linux/netfilter_arp/arpt_mangle.h", + "linux/netfilter_bridge/ebt_802_3.h", + "linux/netfilter_bridge/ebt_among.h", + "linux/netfilter_bridge/ebt_arp.h", + "linux/netfilter_bridge/ebt_arpreply.h", + "linux/netfilter_bridge/ebt_ip.h", + "linux/netfilter_bridge/ebt_ip6.h", + "linux/netfilter_bridge/ebt_limit.h", + "linux/netfilter_bridge/ebt_log.h", + "linux/netfilter_bridge/ebt_mark_m.h", + "linux/netfilter_bridge/ebt_mark_t.h", + "linux/netfilter_bridge/ebt_nat.h", + "linux/netfilter_bridge/ebt_nflog.h", + "linux/netfilter_bridge/ebt_pkttype.h", + "linux/netfilter_bridge/ebt_redirect.h", + "linux/netfilter_bridge/ebt_stp.h", + "linux/netfilter_bridge/ebt_vlan.h", + "linux/netfilter_bridge/ebtables.h", + "linux/netfilter_ipv4/ip_tables.h", + "linux/netfilter_ipv4/ipt_CLUSTERIP.h", + "linux/netfilter_ipv4/ipt_ECN.h", + "linux/netfilter_ipv4/ipt_LOG.h", + "linux/netfilter_ipv4/ipt_NATTYPE.h", + "linux/netfilter_ipv4/ipt_REJECT.h", + "linux/netfilter_ipv4/ipt_TTL.h", + "linux/netfilter_ipv4/ipt_ah.h", + "linux/netfilter_ipv4/ipt_ecn.h", + "linux/netfilter_ipv4/ipt_ttl.h", + "linux/netfilter_ipv6/ip6_tables.h", + "linux/netfilter_ipv6/ip6t_HL.h", + "linux/netfilter_ipv6/ip6t_LOG.h", + "linux/netfilter_ipv6/ip6t_NPT.h", + "linux/netfilter_ipv6/ip6t_REJECT.h", + "linux/netfilter_ipv6/ip6t_ah.h", + "linux/netfilter_ipv6/ip6t_frag.h", + "linux/netfilter_ipv6/ip6t_hl.h", + "linux/netfilter_ipv6/ip6t_ipv6header.h", + "linux/netfilter_ipv6/ip6t_mh.h", + "linux/netfilter_ipv6/ip6t_opts.h", + "linux/netfilter_ipv6/ip6t_rt.h", + "linux/nfc/nfcinfo.h", + "linux/nfsd/cld.h", + "linux/nfsd/debug.h", + "linux/nfsd/export.h", + "linux/nfsd/nfsfh.h", + "linux/nfsd/stats.h", + "linux/raid/md_p.h", + "linux/raid/md_u.h", + "linux/spi/spidev.h", + "linux/sunrpc/debug.h", + "linux/tc_act/tc_bpf.h", + "linux/tc_act/tc_connmark.h", + "linux/tc_act/tc_csum.h", + "linux/tc_act/tc_defact.h", + "linux/tc_act/tc_gact.h", + "linux/tc_act/tc_ife.h", + "linux/tc_act/tc_ipt.h", + "linux/tc_act/tc_mirred.h", + "linux/tc_act/tc_nat.h", + "linux/tc_act/tc_pedit.h", + "linux/tc_act/tc_skbedit.h", + "linux/tc_act/tc_skbmod.h", + "linux/tc_act/tc_tunnel_key.h", + "linux/tc_act/tc_vlan.h", + "linux/tc_ematch/tc_em_cmp.h", + "linux/tc_ematch/tc_em_meta.h", + "linux/tc_ematch/tc_em_nbyte.h", + "linux/tc_ematch/tc_em_text.h", + "linux/usb/audio.h", + "linux/usb/cdc-wdm.h", + "linux/usb/cdc.h", + "linux/usb/ch11.h", + "linux/usb/ch9.h", + "linux/usb/functionfs.h", + "linux/usb/g_printer.h", + "linux/usb/gadgetfs.h", + "linux/usb/midi.h", + "linux/usb/tmc.h", + "linux/usb/usb_ctrl_qti.h", + "linux/usb/video.h", + "linux/wimax/i2400m.h", + "rdma/hfi/hfi1_user.h", + "scsi/fc/fc_els.h", + "scsi/fc/fc_fs.h", + "scsi/fc/fc_gs.h", + "scsi/fc/fc_ns.h", + "scsi/ufs/ioctl.h", + "scsi/ufs/ufs.h", + "linux/mfd/wcd9xxx/wcd9320_registers.h", + "linux/mfd/wcd9xxx/wcd9xxx_registers.h", + "linux/netfilter/ipset/ip_set.h", + "linux/netfilter/ipset/ip_set_bitmap.h", + "linux/netfilter/ipset/ip_set_hash.h", + "linux/netfilter/ipset/ip_set_list.h", + + // From arch/arm64/include/uapi/**/*.h + + "asm/auxvec.h", + "asm/bitsperlong.h", + "asm/byteorder.h", + "asm/fcntl.h", + "asm/hwcap.h", + "asm/kvm.h", + "asm/param.h", + "asm/perf_regs.h", + "asm/posix_types.h", + "asm/ptrace.h", + "asm/setup.h", + "asm/sigcontext.h", + "asm/siginfo.h", + "asm/signal.h", + "asm/stat.h", + "asm/statfs.h", + "asm/ucontext.h", + "asm/unistd.h", +] + +genrule { + // This module generates the gen_headers_.bp file + // (i.e., a new version of this file) so that it can be + // checked later to ensure that it matches the checked- + // in version (this file). + name: "qti_generate_gen_headers_arm64", + srcs: gen_headers_srcs_arm64, + exclude_srcs: gen_headers_exclude_srcs_arm64, + tool_files: ["kernel_headers.py"], + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm64 " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm64/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm64/include/uapi/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild.asm) " + + "blueprints " + + "# $(in)", + out: ["gen_headers_arm64.bp"], +} + +genrule { + name: "qti_generate_kernel_headers_arm64", + tools: ["headers_install.sh"], + tool_files: [ + "kernel_headers.py", + ], + srcs: gen_headers_srcs_arm64 +[ + "gen_headers_arm64.bp", + ":qti_generate_gen_headers_arm64", + ], + exclude_srcs: gen_headers_exclude_srcs_arm64, + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm64 " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm64/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm64/include/uapi/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild.asm) " + + "headers " + + "--old_gen_headers_bp $(location gen_headers_arm64.bp) " + + "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm64) " + + "--version_makefile $(location Makefile) " + + "--headers_install $(location headers_install.sh) " + + "--include_uapi $(locations include/uapi/**/*.h)", + out: ["linux/version.h"] + gen_headers_out_arm64, +} diff --git a/include/Kbuild b/include/Kbuild deleted file mode 100644 index 9205b04e508704d8db2f153f48ad9e0fc2e3e2a6..0000000000000000000000000000000000000000 --- a/include/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# Top-level Makefile calls into asm-$(ARCH) -# List only non-arch directories below - -ifneq ($(VSERVICES_SUPPORT), "") -header-y += vservices/ -endif diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 1d798abae710b38ba4af4511e7ae654cfdf3151b..f502d257d494463ce74aeb47b5412ab587ec6c77 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -551,6 +551,8 @@ typedef u64 acpi_integer; #define ACPI_VALIDATE_RSDP_SIG(a) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8)) #define ACPI_MAKE_RSDP_SIG(dest) (memcpy (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8)) +#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1)) + /******************************************************************************* * * Miscellaneous constants diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm deleted file mode 100644 index d2ee86b4c091c7bcde862f8b34cb822570468d98..0000000000000000000000000000000000000000 --- a/include/asm-generic/Kbuild.asm +++ /dev/null @@ -1 +0,0 @@ -include include/uapi/asm-generic/Kbuild.asm diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 961156ae8d510e3d558725f00f39396e35941b8d..0acf72e98c90daebdcb0a061bc75ce5d7f438649 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -125,6 +125,12 @@ struct drm_display_info { */ unsigned int bpc; + /** + * @bpc: Maximum bits per color channel for YCbCr420 modes. + * Used by HDMI and DP outputs. + */ + unsigned int y420_bpc; + /** * @subpixel_order: Subpixel order of LCD panels. */ @@ -133,6 +139,8 @@ struct drm_display_info { #define DRM_COLOR_FORMAT_RGB444 (1<<0) #define DRM_COLOR_FORMAT_YCRCB444 (1<<1) #define DRM_COLOR_FORMAT_YCRCB422 (1<<2) +#define DRM_COLOR_FORMAT_DC_RGB444 (1<<3) +#define DRM_COLOR_FORMAT_DC_YCRCB444 (1<<4) /** * @color_formats: HDMI Color formats, selects between RGB and YCrCb diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 003207670597095a7a5e7b3b06b177992fbd6e40..c0542de64690aa83224f7ec55b3a568ded937c11 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -312,7 +312,7 @@ struct drm_dp_resource_status_notify { struct drm_dp_query_payload_ack_reply { u8 port_number; - u8 allocated_pbn; + u16 allocated_pbn; }; struct drm_dp_sideband_msg_req_body { diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index b5c134a16ecb35a78b823a5eabc40cbf3ddbe2cf..c363e3b6b3d504ac0181538f90ea83b048ac2d4b 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -458,6 +458,7 @@ struct edid *drm_edid_duplicate(const struct edid *edid); int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); u8 drm_match_cea_mode(const struct drm_display_mode *to_match); +u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match); enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code); bool drm_detect_hdmi_monitor(struct edid *edid); bool drm_detect_monitor_audio(struct edid *edid); diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 9934d91619c1823c80d277a50cc025873903b3a1..2e44dadfdc84aa006a62d724a3a9b615dd1333f3 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -405,6 +405,8 @@ struct drm_display_mode { * Field for setting the HDMI picture aspect ratio of a mode. */ enum hdmi_picture_aspect picture_aspect_ratio; + + u32 vic_id; }; #define obj_to_mode(x) container_of(x, struct drm_display_mode, base) diff --git a/include/dt-bindings/reset/amlogic,meson8b-reset.h b/include/dt-bindings/reset/amlogic,meson8b-reset.h index 614aff2c7affe914bf12cb841656f1eb1342aa6e..a03e86fe2c5709b1c1e70253b115a5ee2f2bfb26 100644 --- a/include/dt-bindings/reset/amlogic,meson8b-reset.h +++ b/include/dt-bindings/reset/amlogic,meson8b-reset.h @@ -95,9 +95,9 @@ #define RESET_VD_RMEM 64 #define RESET_AUDIN 65 #define RESET_DBLK 66 -#define RESET_PIC_DC 66 -#define RESET_PSC 66 -#define RESET_NAND 66 +#define RESET_PIC_DC 67 +#define RESET_PSC 68 +#define RESET_NAND 69 #define RESET_GE2D 70 #define RESET_PARSER_REG 71 #define RESET_PARSER_FETCH 72 diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 719eb97217a3c0c01ebac427ed5fd11e7c2b45bf..5670bb9788bb4f45c3bd7d0d1e585389e60fba57 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -77,7 +77,7 @@ static inline bool has_acpi_companion(struct device *dev) static inline void acpi_preset_companion(struct device *dev, struct acpi_device *parent, u64 addr) { - ACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, NULL)); + ACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, false)); } static inline const char *acpi_dev_name(struct acpi_device *adev) diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h index a270f25ee7c7c49890e2b902ceaccd80a5a05aa2..1a527e40d601d62ab1625e423efb3a7afe19e04d 100644 --- a/include/linux/ahci_platform.h +++ b/include/linux/ahci_platform.h @@ -23,6 +23,8 @@ struct ahci_host_priv; struct platform_device; struct scsi_host_template; +int ahci_platform_enable_phys(struct ahci_host_priv *hpriv); +void ahci_platform_disable_phys(struct ahci_host_priv *hpriv); int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv); diff --git a/include/linux/atalk.h b/include/linux/atalk.h index af43ed404ff4da91696de592da9023351b7f6809..4be0e14b38fc0d416ff1ad9f9d3d8658e133df0a 100644 --- a/include/linux/atalk.h +++ b/include/linux/atalk.h @@ -107,7 +107,7 @@ static __inline__ struct elapaarp *aarp_hdr(struct sk_buff *skb) #define AARP_RESOLVE_TIME (10 * HZ) extern struct datalink_proto *ddp_dl, *aarp_dl; -extern void aarp_proto_init(void); +extern int aarp_proto_init(void); /* Inter module exports */ diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index dec03c0dbc214f216b57a7081e65b197855d61bb..26347cc717e88be5757364777a05d56f5c23cac5 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -85,6 +85,14 @@ * contain all bit positions from 0 to 'bits' - 1. */ +/* + * Allocation and deallocation of bitmap. + * Provided in lib/bitmap.c to avoid circular dependency. + */ +extern unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags); +extern unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags); +extern void bitmap_free(const unsigned long *bitmap); + /* * lib/bitmap.c provides these functions: */ diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 76ad8a957ffaea95cb8eaec411b190e18961b885..cee74a52b9eb84503dcdebed8c8b68230ad55fe7 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -3,7 +3,8 @@ #include #include -#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) +#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long)) extern unsigned int __sw_hweight8(unsigned int w); extern unsigned int __sw_hweight16(unsigned int w); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 8647e7fb6261f3a00b721e8e200d1aa933b9243a..aed328d15f99635d41638c73aaf18e95496c155d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -281,6 +281,7 @@ struct queue_limits { unsigned int max_sectors; unsigned int max_segment_size; unsigned int physical_block_size; + unsigned int logical_block_size; unsigned int alignment_offset; unsigned int io_min; unsigned int io_opt; @@ -290,7 +291,6 @@ struct queue_limits { unsigned int discard_granularity; unsigned int discard_alignment; - unsigned short logical_block_size; unsigned short max_segments; unsigned short max_integrity_segments; @@ -1011,7 +1011,7 @@ extern void blk_queue_max_discard_sectors(struct request_queue *q, unsigned int max_discard_sectors); extern void blk_queue_max_write_same_sectors(struct request_queue *q, unsigned int max_write_same_sectors); -extern void blk_queue_logical_block_size(struct request_queue *, unsigned short); +extern void blk_queue_logical_block_size(struct request_queue *, unsigned int); extern void blk_queue_physical_block_size(struct request_queue *, unsigned int); extern void blk_queue_alignment_offset(struct request_queue *q, unsigned int alignment); @@ -1237,7 +1237,7 @@ static inline unsigned int queue_max_segment_size(struct request_queue *q) return q->limits.max_segment_size; } -static inline unsigned short queue_logical_block_size(struct request_queue *q) +static inline unsigned queue_logical_block_size(struct request_queue *q) { int retval = 512; @@ -1247,7 +1247,7 @@ static inline unsigned short queue_logical_block_size(struct request_queue *q) return retval; } -static inline unsigned short bdev_logical_block_size(struct block_device *bdev) +static inline unsigned int bdev_logical_block_size(struct block_device *bdev) { return queue_logical_block_size(bdev_get_queue(bdev)); } diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h index ace92fce296d107e38b0e53dfb03e8165e45742e..ed3bb3d0561fc8906b4f40f90b3e4d696abb8df7 100644 --- a/include/linux/bpf-cgroup.h +++ b/include/linux/bpf-cgroup.h @@ -13,27 +13,42 @@ struct sk_buff; extern struct static_key_false cgroup_bpf_enabled_key; #define cgroup_bpf_enabled static_branch_unlikely(&cgroup_bpf_enabled_key) +struct bpf_prog_list { + struct list_head node; + struct bpf_prog *prog; +}; + +struct bpf_prog_array; + struct cgroup_bpf { - /* - * Store two sets of bpf_prog pointers, one for programs that are - * pinned directly to this cgroup, and one for those that are effective - * when this cgroup is accessed. + /* array of effective progs in this cgroup */ + struct bpf_prog_array __rcu *effective[MAX_BPF_ATTACH_TYPE]; + + /* attached progs to this cgroup and attach flags + * when flags == 0 or BPF_F_ALLOW_OVERRIDE the progs list will + * have either zero or one element + * when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS */ - struct bpf_prog *prog[MAX_BPF_ATTACH_TYPE]; - struct bpf_prog *effective[MAX_BPF_ATTACH_TYPE]; - bool disallow_override[MAX_BPF_ATTACH_TYPE]; + struct list_head progs[MAX_BPF_ATTACH_TYPE]; + u32 flags[MAX_BPF_ATTACH_TYPE]; + + /* temp storage for effective prog array used by prog_attach/detach */ + struct bpf_prog_array __rcu *inactive; }; void cgroup_bpf_put(struct cgroup *cgrp); -void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent); +int cgroup_bpf_inherit(struct cgroup *cgrp); -int __cgroup_bpf_update(struct cgroup *cgrp, struct cgroup *parent, - struct bpf_prog *prog, enum bpf_attach_type type, - bool overridable); +int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 flags); +int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 flags); -/* Wrapper for __cgroup_bpf_update() protected by cgroup_mutex */ -int cgroup_bpf_update(struct cgroup *cgrp, struct bpf_prog *prog, - enum bpf_attach_type type, bool overridable); +/* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */ +int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 flags); +int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 flags); int __cgroup_bpf_run_filter(struct sock *sk, struct sk_buff *skb, @@ -66,8 +81,7 @@ int __cgroup_bpf_run_filter(struct sock *sk, struct cgroup_bpf {}; static inline void cgroup_bpf_put(struct cgroup *cgrp) {} -static inline void cgroup_bpf_inherit(struct cgroup *cgrp, - struct cgroup *parent) {} +static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; } #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; }) #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; }) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index cd6aaf08324d0ab9c68f79493b42c4a96c01dd9a..30b808f166fc879a0713d6e87f6de5d1bed96a5f 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -241,6 +241,58 @@ typedef unsigned long (*bpf_ctx_copy_t)(void *dst, const void *src, u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size, void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy); +/* an array of programs to be executed under rcu_lock. + * + * Typical usage: + * ret = BPF_PROG_RUN_ARRAY(&bpf_prog_array, ctx, BPF_PROG_RUN); + * + * the structure returned by bpf_prog_array_alloc() should be populated + * with program pointers and the last pointer must be NULL. + * The user has to keep refcnt on the program and make sure the program + * is removed from the array before bpf_prog_put(). + * The 'struct bpf_prog_array *' should only be replaced with xchg() + * since other cpus are walking the array of pointers in parallel. + */ +struct bpf_prog_array { + struct rcu_head rcu; + struct bpf_prog *progs[0]; +}; + +struct bpf_prog_array __rcu *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags); +void bpf_prog_array_free(struct bpf_prog_array __rcu *progs); + +void bpf_prog_array_delete_safe(struct bpf_prog_array __rcu *progs, + struct bpf_prog *old_prog); +int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array, + struct bpf_prog *exclude_prog, + struct bpf_prog *include_prog, + struct bpf_prog_array **new_array); + +#define __BPF_PROG_RUN_ARRAY(array, ctx, func, check_non_null) \ + ({ \ + struct bpf_prog **_prog, *__prog; \ + struct bpf_prog_array *_array; \ + u32 _ret = 1; \ + rcu_read_lock(); \ + _array = rcu_dereference(array); \ + if (unlikely(check_non_null && !_array))\ + goto _out; \ + _prog = _array->progs; \ + while ((__prog = READ_ONCE(*_prog))) { \ + _ret &= func(__prog, ctx); \ + _prog++; \ + } \ +_out: \ + rcu_read_unlock(); \ + _ret; \ + }) + +#define BPF_PROG_RUN_ARRAY(array, ctx, func) \ + __BPF_PROG_RUN_ARRAY(array, ctx, func, false) + +#define BPF_PROG_RUN_ARRAY_CHECK(array, ctx, func) \ + __BPF_PROG_RUN_ARRAY(array, ctx, func, true) + #ifdef CONFIG_BPF_SYSCALL DECLARE_PER_CPU(int, bpf_prog_active); diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index f7178f44825bf35c1adc07e0635ee16543a44227..d2a4979506397fae6d55d2db065c337a2bac291d 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -17,6 +17,7 @@ #include #include #include +#include #include /* @@ -81,6 +82,36 @@ struct can_priv { #define get_can_dlc(i) (min_t(__u8, (i), CAN_MAX_DLC)) #define get_canfd_dlc(i) (min_t(__u8, (i), CANFD_MAX_DLC)) +/* Check for outgoing skbs that have not been created by the CAN subsystem */ +static inline bool can_skb_headroom_valid(struct net_device *dev, + struct sk_buff *skb) +{ + /* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */ + if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv))) + return false; + + /* af_packet does not apply CAN skb specific settings */ + if (skb->ip_summed == CHECKSUM_NONE) { + /* init headroom */ + can_skb_prv(skb)->ifindex = dev->ifindex; + can_skb_prv(skb)->skbcnt = 0; + + skb->ip_summed = CHECKSUM_UNNECESSARY; + + /* preform proper loopback on capable devices */ + if (dev->flags & IFF_ECHO) + skb->pkt_type = PACKET_LOOPBACK; + else + skb->pkt_type = PACKET_HOST; + + skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + } + + return true; +} + /* Drop a given socketbuffer if it does not contain a valid CAN frame. */ static inline bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb) @@ -98,6 +129,9 @@ static inline bool can_dropped_invalid_skb(struct net_device *dev, } else goto inval_skb; + if (!can_skb_headroom_valid(dev, skb)) + goto inval_skb; + return false; inval_skb: diff --git a/include/linux/cec-funcs.h b/include/linux/cec-funcs.h index 138bbf721e70cae221544a4dbcd7a3f6175d54cd..a844749a285599186f9df892afefcc3942d55b02 100644 --- a/include/linux/cec-funcs.h +++ b/include/linux/cec-funcs.h @@ -956,7 +956,8 @@ static inline void cec_msg_give_deck_status(struct cec_msg *msg, msg->len = 3; msg->msg[1] = CEC_MSG_GIVE_DECK_STATUS; msg->msg[2] = status_req; - msg->reply = reply ? CEC_MSG_DECK_STATUS : 0; + msg->reply = (reply && status_req != CEC_OP_STATUS_REQ_OFF) ? + CEC_MSG_DECK_STATUS : 0; } static inline void cec_ops_give_deck_status(const struct cec_msg *msg, @@ -1060,7 +1061,8 @@ static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg, msg->len = 3; msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS; msg->msg[2] = status_req; - msg->reply = reply ? CEC_MSG_TUNER_DEVICE_STATUS : 0; + msg->reply = (reply && status_req != CEC_OP_STATUS_REQ_OFF) ? + CEC_MSG_TUNER_DEVICE_STATUS : 0; } static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg, diff --git a/include/linux/clk/msm-clk.h b/include/linux/clk/msm-clk.h index baa8e5255a3dc2ae61ae8cbf62a6a88e8c80a758..f4425381b3441ec889cc0fedcb3b25a3e0ec0e6c 100644 --- a/include/linux/clk/msm-clk.h +++ b/include/linux/clk/msm-clk.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2009, 2012-2017, 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 @@ -55,6 +55,11 @@ int clk_reset(struct clk *clk, enum clk_reset_action action); /* Set clock-specific configuration parameters */ int clk_set_flags(struct clk *clk, unsigned long flags); +/* Set clock duty-cycle as a ratio of numerator/denominator for the desired + * duty cycle + */ +int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator); + /* returns the mux selection index associated with a particular parent */ int parent_to_src_sel(struct clk_src *parents, int num_parents, struct clk *p); diff --git a/include/linux/device.h b/include/linux/device.h index f43db28d94532b599582621c1cc8963e6731e3ec..5ab43f42b0c04e9c42ad1e9a511e8af156c54d68 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -684,7 +684,8 @@ extern unsigned long devm_get_free_pages(struct device *dev, gfp_t gfp_mask, unsigned int order); extern void devm_free_pages(struct device *dev, unsigned long addr); -void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); +void __iomem *devm_ioremap_resource(struct device *dev, + const struct resource *res); /* allows to add/remove a custom action to devres stack */ int devm_add_action(struct device *dev, void (*action)(void *), void *data); diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h index ae72202f5434677da103096935827c03b6432767..9e9408dc590fde910fc8dd19ce804c9c1eb4f1e5 100644 --- a/include/linux/diagchar.h +++ b/include/linux/diagchar.h @@ -148,7 +148,7 @@ * a new RANGE of SSIDs to the msg_mask_tbl. */ #define MSG_MASK_TBL_CNT 26 -#define APPS_EVENT_LAST_ID 0xCB9 +#define APPS_EVENT_LAST_ID 0xCC1 #define MSG_SSID_0 0 #define MSG_SSID_0_LAST 132 @@ -925,7 +925,7 @@ static const uint32_t msg_bld_masks_25[] = { /* LOG CODES */ static const uint32_t log_code_last_tbl[] = { 0x0, /* EQUIP ID 0 */ - 0x1CCA, /* EQUIP ID 1 */ + 0x1CD6, /* EQUIP ID 1 */ 0x0, /* EQUIP ID 2 */ 0x0, /* EQUIP ID 3 */ 0x4910, /* EQUIP ID 4 */ diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 69935e6694faf4ed6934fe435c839503bbe42146..c336f933b84fa3eccf5458940ad2da98b5570161 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -689,8 +689,7 @@ static inline unsigned int dma_get_max_seg_size(struct device *dev) return SZ_64K; } -static inline unsigned int dma_set_max_seg_size(struct device *dev, - unsigned int size) +static inline int dma_set_max_seg_size(struct device *dev, unsigned int size) { if (dev->dma_parms) { dev->dma_parms->max_segment_size = size; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index cc535a478bae6d6e5834371f70f25a0cb9dbc981..710f269764dc710f8c958666afc563bbb375665b 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1358,8 +1358,11 @@ static inline int dma_get_slave_caps(struct dma_chan *chan, static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx) { struct dma_slave_caps caps; + int ret; - dma_get_slave_caps(tx->chan, &caps); + ret = dma_get_slave_caps(tx->chan, &caps); + if (ret) + return ret; if (caps.descriptor_reuse) { tx->flags |= DMA_CTRL_REUSE; diff --git a/include/linux/filter.h b/include/linux/filter.h index 0837d904405a3704f40ae60203e48faa8c639288..69e8e1951eb2483928ae6f7c0e8105bc62c7b09c 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -423,7 +423,7 @@ struct sk_filter { struct bpf_prog *prog; }; -#define BPF_PROG_RUN(filter, ctx) (*filter->bpf_func)(ctx, filter->insnsi) +#define BPF_PROG_RUN(filter, ctx) (*(filter)->bpf_func)(ctx, (filter)->insnsi) #define BPF_SKB_CB_LEN QDISC_CB_PRIV_LEN diff --git a/include/linux/hid.h b/include/linux/hid.h index c43f58e38a7cd97ff505e854698f60eab4c40cb6..877bb9aaca18e9cfd09dce3f9b717aaec8a6f5cf 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -454,7 +454,7 @@ struct hid_report_enum { }; #define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */ -#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */ +#define HID_MAX_BUFFER_SIZE 8192 /* 8kb */ #define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ #define HID_OUTPUT_FIFO_SIZE 64 @@ -524,10 +524,12 @@ struct hid_device { /* device report descriptor */ * battery is non-NULL. */ struct power_supply *battery; + __s32 battery_capacity; __s32 battery_min; __s32 battery_max; __s32 battery_report_type; __s32 battery_report_id; + bool battery_reported; #endif unsigned int status; /* see STAT flags above */ diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 9523c6030ffe5f60ad4a54e7f302e055feddad34..2869fb1f85a506e070a7ce177ef4f0adb657eef7 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -419,12 +419,18 @@ extern u64 hrtimer_get_next_event(void); extern bool hrtimer_active(const struct hrtimer *timer); -/* - * Helper function to check, whether the timer is on one of the queues +/** + * hrtimer_is_queued = check, whether the timer is on one of the queues + * @timer: Timer to check + * + * Returns: True if the timer is queued, false otherwise + * + * The function can be used lockless, but it gives only a current snapshot. */ -static inline int hrtimer_is_queued(struct hrtimer *timer) +static inline bool hrtimer_is_queued(struct hrtimer *timer) { - return timer->state & HRTIMER_STATE_ENQUEUED; + /* The READ_ONCE pairs with the update functions of timer->state */ + return !!(READ_ONCE(timer->state) & HRTIMER_STATE_ENQUEUED); } /* diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 548fd535fd02399634bace0607471d07b973d8dc..d433f5e292c9fb9ff3175120000cc8dd4e4f4f84 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -28,6 +28,14 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb) return (struct ethhdr *)skb_mac_header(skb); } +/* Prefer this version in TX path, instead of + * skb_reset_mac_header() + eth_hdr() + */ +static inline struct ethhdr *skb_eth_hdr(const struct sk_buff *skb) +{ + return (struct ethhdr *)skb->data; +} + static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) { return (struct ethhdr *)skb_inner_mac_header(skb); diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index d073470cb342586810f34cc5cfedde3a373f5dcf..344eb873f6f5e3d2024c058d555a795fcf1e8e9b 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1560,7 +1560,7 @@ static inline int jbd2_space_needed(journal_t *journal) static inline unsigned long jbd2_log_space_left(journal_t *journal) { /* Allow for rounding errors */ - unsigned long free = journal->j_free - 32; + long free = journal->j_free - 32; if (journal->j_committing_transaction) { unsigned long committing = atomic_read(&journal-> @@ -1569,7 +1569,7 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal) /* Transaction + control blocks */ free -= committing + (committing >> JBD2_CONTROL_BLOCKS_SHIFT); } - return free; + return max_t(long, free, 0); } /* diff --git a/include/linux/libata.h b/include/linux/libata.h index df58b01e6962c29b2c67d0c8f51cdc9a258ca6ee..cdfb67b22317bb42448ee6bf042b008c74b343ea 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1222,6 +1222,7 @@ struct pci_bits { }; extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits); +extern void ata_pci_shutdown_one(struct pci_dev *pdev); extern void ata_pci_remove_one(struct pci_dev *pdev); #ifdef CONFIG_PM diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h index 8850e243c9406f6c2b622faea3ab82286d886708..bd0a55821177a3a210be8b1abec86626915ca3bb 100644 --- a/include/linux/libfdt_env.h +++ b/include/linux/libfdt_env.h @@ -6,6 +6,9 @@ #include +#define INT32_MAX S32_MAX +#define UINT32_MAX U32_MAX + typedef __be16 fdt16_t; typedef __be32 fdt32_t; typedef __be64 fdt64_t; diff --git a/include/linux/list_nulls.h b/include/linux/list_nulls.h index 87ff4f58a2f0182ec0586c0dee923bc30e004149..9e20bf7f46a202072c4afadc19c7228720ef0824 100644 --- a/include/linux/list_nulls.h +++ b/include/linux/list_nulls.h @@ -71,10 +71,10 @@ static inline void hlist_nulls_add_head(struct hlist_nulls_node *n, struct hlist_nulls_node *first = h->first; n->next = first; - n->pprev = &h->first; + WRITE_ONCE(n->pprev, &h->first); h->first = n; if (!is_a_nulls(first)) - first->pprev = &n->next; + WRITE_ONCE(first->pprev, &n->next); } static inline void __hlist_nulls_del(struct hlist_nulls_node *n) @@ -84,13 +84,13 @@ static inline void __hlist_nulls_del(struct hlist_nulls_node *n) WRITE_ONCE(*pprev, next); if (!is_a_nulls(next)) - next->pprev = pprev; + WRITE_ONCE(next->pprev, pprev); } static inline void hlist_nulls_del(struct hlist_nulls_node *n) { __hlist_nulls_del(n); - n->pprev = LIST_POISON2; + WRITE_ONCE(n->pprev, LIST_POISON2); } /** diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 20ee90c47cd50972c5b69e9a9aac82d6658bb4e4..6dd276227217e8f41c6993e5c9bad6e5bd57f224 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -7909,8 +7909,6 @@ struct mlx5_ifc_query_lag_out_bits { u8 syndrome[0x20]; - u8 reserved_at_40[0x40]; - struct mlx5_ifc_lagc_bits ctx; }; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 85a43db6d8c6d82ca927ea2076ea28d41f0ac5a3..6b543191d7088bb228a866fc1c80dfeacf80845a 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -520,9 +520,9 @@ struct platform_device_id { #define MDIO_MODULE_PREFIX "mdio:" -#define MDIO_ID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d" +#define MDIO_ID_FMT "%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u" #define MDIO_ID_ARGS(_id) \ - (_id)>>31, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1, \ + ((_id)>>31) & 1, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1, \ ((_id)>>27) & 1, ((_id)>>26) & 1, ((_id)>>25) & 1, ((_id)>>24) & 1, \ ((_id)>>23) & 1, ((_id)>>22) & 1, ((_id)>>21) & 1, ((_id)>>20) & 1, \ ((_id)>>19) & 1, ((_id)>>18) & 1, ((_id)>>17) & 1, ((_id)>>16) & 1, \ diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 13f8052b9ff929a6a1809fbadd5a1424fa8304e2..13ddba5e531d35d7efb8e729cc32a5f017985910 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -392,7 +392,7 @@ static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd) return mtd->dev.of_node; } -static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) +static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) { return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c2bc0dad45ecea027e9d87ff4a9f619aff71e231..a79980ab05069272e8a5aae31bb443d59a697cdb 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1730,6 +1730,11 @@ struct net_device { unsigned char if_port; unsigned char dma; + /* Note : dev->mtu is often read without holding a lock. + * Writers usually hold RTNL. + * It is recommended to use READ_ONCE() to annotate the reads, + * and to use WRITE_ONCE() to annotate the writes. + */ unsigned int mtu; unsigned short type; unsigned short hard_header_len; diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index 83b9a2e0d8d46a64dfe0faeda4b67ea6ce972677..e3a91b24a31cc2d88dd5b53943a6c383eb12ccad 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -537,13 +537,6 @@ ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr) sizeof(*addr)); } -/* Calculate the bytes required to store the inclusive range of a-b */ -static inline int -bitmap_bytes(u32 a, u32 b) -{ - return 4 * ((((b - a + 8) / 8) + 3) / 4); -} - #include #include diff --git a/include/linux/phy.h b/include/linux/phy.h index 867110c9d707934c183590ca2469aae594940518..8eafced47540d561a966e4e16d6082c38c8011a8 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -333,6 +333,7 @@ struct phy_c45_device_ids { * is_pseudo_fixed_link: Set to true if this phy is an Ethernet switch, etc. * has_fixups: Set to true if this phy has fixups/quirks. * suspended: Set to true if this phy has been suspended successfully. + * suspended_by_mdio_bus: Set to true if this phy was suspended by MDIO bus. * state: state of the PHY for management purposes * dev_flags: Device-specific flags used by the PHY driver. * link_timeout: The number of timer firings to wait before the @@ -369,6 +370,7 @@ struct phy_device { bool is_pseudo_fixed_link; bool has_fixups; bool suspended; + bool suspended_by_mdio_bus; enum phy_state state; diff --git a/include/linux/platform_data/dma-imx-sdma.h b/include/linux/platform_data/dma-imx-sdma.h index 2d08816720f6d6be449db87ae8238144f85923bf..5bb0a119f39a32e9925962c9dd029be3d64c203c 100644 --- a/include/linux/platform_data/dma-imx-sdma.h +++ b/include/linux/platform_data/dma-imx-sdma.h @@ -50,7 +50,10 @@ struct sdma_script_start_addrs { /* End of v2 array */ s32 zcanfd_2_mcu_addr; s32 zqspi_2_mcu_addr; + s32 mcu_2_ecspi_addr; /* End of v3 array */ + s32 mcu_2_zqspi_addr; + /* End of v4 array */ }; /** diff --git a/include/linux/poll.h b/include/linux/poll.h index 37b057b63b465afa0edf3e372cb561d7670a3089..4bee398ed2facd9655c48f3b5ffbf442335aa1ee 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -14,7 +14,11 @@ extern struct ctl_table epoll_table[]; /* for sysctl */ /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating additional memory. */ +#ifdef __clang__ +#define MAX_STACK_ALLOC 768 +#else #define MAX_STACK_ALLOC 832 +#endif #define FRONTEND_STACK_ALLOC 256 #define SELECT_STACK_ALLOC FRONTEND_STACK_ALLOC #define POLL_STACK_ALLOC FRONTEND_STACK_ALLOC diff --git a/include/linux/quota.h b/include/linux/quota.h index 55107a8ff8877f270b02fc67a689eac992f2ea74..23eb8ea07def3cffbb4c54a57a1f1296e3eb2ded 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -263,7 +263,7 @@ enum { }; struct dqstats { - int stat[_DQST_DQSTAT_LAST]; + unsigned long stat[_DQST_DQSTAT_LAST]; struct percpu_counter counter[_DQST_DQSTAT_LAST]; }; diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 87733344768c4a53bed321f6d1449d8bfc779527..0a60fe354bc54ff02d6b3f503c991ce5125b15d1 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -54,6 +54,16 @@ static inline struct dquot *dqgrab(struct dquot *dquot) atomic_inc(&dquot->dq_count); return dquot; } + +static inline bool dquot_is_busy(struct dquot *dquot) +{ + if (test_bit(DQ_MOD_B, &dquot->dq_flags)) + return true; + if (atomic_read(&dquot->dq_count) > 1) + return true; + return false; +} + void dqput(struct dquot *dquot); int dquot_scan_active(struct super_block *sb, int (*fn)(struct dquot *dquot, unsigned long priv), diff --git a/include/linux/rculist_nulls.h b/include/linux/rculist_nulls.h index 2720b2fbfb86d67d6e0243e7369d6adf47333401..4d71e3687d1ed7068e3b77617af610e0932bbd34 100644 --- a/include/linux/rculist_nulls.h +++ b/include/linux/rculist_nulls.h @@ -33,7 +33,7 @@ static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n) { if (!hlist_nulls_unhashed(n)) { __hlist_nulls_del(n); - n->pprev = NULL; + WRITE_ONCE(n->pprev, NULL); } } @@ -65,7 +65,7 @@ static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n) static inline void hlist_nulls_del_rcu(struct hlist_nulls_node *n) { __hlist_nulls_del(n); - n->pprev = LIST_POISON2; + WRITE_ONCE(n->pprev, LIST_POISON2); } /** @@ -93,10 +93,47 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n, struct hlist_nulls_node *first = h->first; n->next = first; - n->pprev = &h->first; + WRITE_ONCE(n->pprev, &h->first); rcu_assign_pointer(hlist_nulls_first_rcu(h), n); if (!is_a_nulls(first)) - first->pprev = &n->next; + WRITE_ONCE(first->pprev, &n->next); +} + +/** + * hlist_nulls_add_tail_rcu + * @n: the element to add to the hash list. + * @h: the list to add to. + * + * Description: + * Adds the specified element to the specified hlist_nulls, + * while permitting racing traversals. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_nulls_add_head_rcu() + * or hlist_nulls_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_nulls_for_each_entry_rcu(), used to prevent memory-consistency + * problems on Alpha CPUs. Regardless of the type of CPU, the + * list-traversal primitive must be guarded by rcu_read_lock(). + */ +static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n, + struct hlist_nulls_head *h) +{ + struct hlist_nulls_node *i, *last = NULL; + + /* Note: write side code, so rcu accessors are not needed. */ + for (i = h->first; !is_a_nulls(i); i = i->next) + last = i; + + if (last) { + n->next = last->next; + n->pprev = &last->next; + rcu_assign_pointer(hlist_next_rcu(last), n); + } else { + hlist_nulls_add_head_rcu(n, h); + } } /** diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index d8ecefaf63ca0ed956d82afbffedc2debe569311..3f6b8b9ef49da3258c53e0eae4660b150fe5bc25 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -38,14 +38,11 @@ enum ab8505_regulator_id { AB8505_LDO_AUX6, AB8505_LDO_INTCORE, AB8505_LDO_ADC, - AB8505_LDO_USB, AB8505_LDO_AUDIO, AB8505_LDO_ANAMIC1, AB8505_LDO_ANAMIC2, AB8505_LDO_AUX8, AB8505_LDO_ANA, - AB8505_SYSCLKREQ_2, - AB8505_SYSCLKREQ_4, AB8505_NUM_REGULATORS, }; diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index a40c4c9d3fcf1e3165656cfc8f44349ab54b4383..c7bafc70291aed1a9dced4e9442c931a5ccb04ca 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -482,7 +482,7 @@ static inline unsigned int regulator_get_mode(struct regulator *regulator) static inline int regulator_set_load(struct regulator *regulator, int load_uA) { - return REGULATOR_MODE_NORMAL; + return 0; } static inline int regulator_allow_bypass(struct regulator *regulator, diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index c7dff69a41035aa263f9b9581cb85ff9dc74e90f..695bb3670167cd14ec025b235042981e096793a2 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -162,6 +162,7 @@ struct uart_port { struct console *cons; /* struct console, if any */ #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ) unsigned long sysrq; /* sysrq timeout */ + unsigned int sysrq_ch; /* char for sysrq */ #endif /* flags must be updated while holding port mutex */ @@ -471,8 +472,42 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) } return 0; } +static inline int +uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) +{ + if (port->sysrq) { + if (ch && time_before(jiffies, port->sysrq)) { + port->sysrq_ch = ch; + port->sysrq = 0; + return 1; + } + port->sysrq = 0; + } + return 0; +} +static inline void +uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) +{ + int sysrq_ch; + + sysrq_ch = port->sysrq_ch; + port->sysrq_ch = 0; + + spin_unlock_irqrestore(&port->lock, irqflags); + + if (sysrq_ch) + handle_sysrq(sysrq_ch); +} #else -#define uart_handle_sysrq_char(port,ch) ({ (void)port; 0; }) +static inline int +uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) { return 0; } +static inline int +uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) { return 0; } +static inline void +uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) +{ + spin_unlock_irqrestore(&port->lock, irqflags); +} #endif /* diff --git a/include/linux/signal.h b/include/linux/signal.h index 5308304993bea584105a9747d85c9abcbadcc5da..ffa58ff53e22580146988c6540d628780cb3ed2c 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -313,6 +313,9 @@ extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping); extern void exit_signals(struct task_struct *tsk); extern void kernel_sigaction(int, __sighandler_t); +#define SIG_KTHREAD ((__force __sighandler_t)2) +#define SIG_KTHREAD_KERNEL ((__force __sighandler_t)3) + static inline void allow_signal(int sig) { /* @@ -320,7 +323,17 @@ static inline void allow_signal(int sig) * know it'll be handled, so that they don't get converted to * SIGKILL or just silently dropped. */ - kernel_sigaction(sig, (__force __sighandler_t)2); + kernel_sigaction(sig, SIG_KTHREAD); +} + +static inline void allow_kernel_signal(int sig) +{ + /* + * Kernel threads handle their own signals. Let the signal code + * know signals sent by the kernel will be handled, so that they + * don't get silently dropped. + */ + kernel_sigaction(sig, SIG_KTHREAD_KERNEL); } static inline void disallow_signal(int sig) diff --git a/include/linux/time.h b/include/linux/time.h index 4cea09d9420803469a991cf7038864a92982b0c0..60fd505592418cc0c9bb863f7b8905a1eed7dcc2 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -275,4 +275,16 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) a->tv_nsec = ns; } +/** + * time_between32 - check if a 32-bit timestamp is within a given time range + * @t: the time which may be within [l,h] + * @l: the lower bound of the range + * @h: the higher bound of the range + * + * time_before32(t, l, h) returns true if @l <= @t <= @h. All operands are + * treated as 32-bit integers. + * + * Equivalent to !(time_before32(@t, @l) || time_after32(@t, @h)). + */ +#define time_between32(t, l, h) ((u32)(h) - (u32)(l) >= (u32)(t) - (u32)(l)) #endif diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 751a510c4bf8af2c3d583121832207444e23d767..25b777be5dc1c8e79e12b41c8829bde83e286315 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -274,14 +274,37 @@ struct trace_event_call { #ifdef CONFIG_PERF_EVENTS int perf_refcount; struct hlist_head __percpu *perf_events; - struct bpf_prog *prog; - struct perf_event *bpf_prog_owner; + struct bpf_prog_array __rcu *prog_array; int (*perf_perm)(struct trace_event_call *, struct perf_event *); #endif }; +#ifdef CONFIG_PERF_EVENTS +static inline bool bpf_prog_array_valid(struct trace_event_call *call) +{ + /* + * This inline function checks whether call->prog_array + * is valid or not. The function is called in various places, + * outside rcu_read_lock/unlock, as a heuristic to speed up execution. + * + * If this function returns true, and later call->prog_array + * becomes false inside rcu_read_lock/unlock region, + * we bail out then. If this function return false, + * there is a risk that we might miss a few events if the checking + * were delayed until inside rcu_read_lock/unlock region and + * call->prog_array happened to become non-NULL then. + * + * Here, READ_ONCE() is used instead of rcu_access_pointer(). + * rcu_access_pointer() requires the actual definition of + * "struct bpf_prog_array" while READ_ONCE() only needs + * a declaration of the same type. + */ + return !!READ_ONCE(call->prog_array); +} +#endif + static inline const char * trace_event_name(struct trace_event_call *call) { @@ -432,12 +455,23 @@ trace_trigger_soft_disabled(struct trace_event_file *file) } #ifdef CONFIG_BPF_EVENTS -unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx); +unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx); +int perf_event_attach_bpf_prog(struct perf_event *event, struct bpf_prog *prog); +void perf_event_detach_bpf_prog(struct perf_event *event); #else -static inline unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx) +static inline unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx) { return 1; } + +static inline int +perf_event_attach_bpf_prog(struct perf_event *event, struct bpf_prog *prog) +{ + return -EOPNOTSUPP; +} + +static inline void perf_event_detach_bpf_prog(struct perf_event *event) { } + #endif enum { @@ -508,6 +542,7 @@ perf_trace_buf_submit(void *raw_data, int size, int rctx, u16 type, { perf_tp_event(type, count, raw_data, size, regs, head, rctx, task); } + #endif #endif /* _LINUX_TRACE_EVENT_H */ diff --git a/include/linux/tty.h b/include/linux/tty.h index bcfeb9e568f0ae2a6ef7d1135532e268ac318f9f..6f841149c3f443688fea29a60702da41af11d833 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -360,6 +360,7 @@ struct tty_file_private { #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ #define TTY_HUPPED 18 /* Post driver->hangup() */ #define TTY_HUPPING 19 /* Hangup in progress */ +#define TTY_LDISC_CHANGING 20 /* Change pending - non-block IO */ #define TTY_LDISC_HALTED 22 /* Line discipline is halted */ /* Values for tty->flow_change */ @@ -377,6 +378,12 @@ static inline void tty_set_flow_change(struct tty_struct *tty, int val) smp_mb(); } +static inline bool tty_io_nonblock(struct tty_struct *tty, struct file *file) +{ + return file->f_flags & O_NONBLOCK || + test_bit(TTY_LDISC_CHANGING, &tty->flags); +} + static inline bool tty_io_error(struct tty_struct *tty) { return test_bit(TTY_IO_ERROR, &tty->flags); diff --git a/include/linux/usb/irda.h b/include/linux/usb/irda.h index e345ceaf72d690de32fa7e495406d8ec04fb5437..9dc46010a0670d4334247f8b57b9ce765d4940e3 100644 --- a/include/linux/usb/irda.h +++ b/include/linux/usb/irda.h @@ -118,11 +118,22 @@ struct usb_irda_cs_descriptor { * 6 - 115200 bps * 7 - 576000 bps * 8 - 1.152 Mbps - * 9 - 5 mbps + * 9 - 4 Mbps * 10..15 - Reserved */ #define USB_IRDA_STATUS_LINK_SPEED 0x0f +#define USB_IRDA_LS_NO_CHANGE 0 +#define USB_IRDA_LS_2400 1 +#define USB_IRDA_LS_9600 2 +#define USB_IRDA_LS_19200 3 +#define USB_IRDA_LS_38400 4 +#define USB_IRDA_LS_57600 5 +#define USB_IRDA_LS_115200 6 +#define USB_IRDA_LS_576000 7 +#define USB_IRDA_LS_1152000 8 +#define USB_IRDA_LS_4000000 9 + /* The following is a 4-bit value used only for * outbound header: * diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h index 3f284bc031809f6cef05a36360f2c54ca2879ad9..5650c1628383057034cbdff2504376a156aeb8f8 100644 --- a/include/math-emu/soft-fp.h +++ b/include/math-emu/soft-fp.h @@ -138,7 +138,7 @@ do { \ _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \ } while (0) -#define _FP_ROUND_ZERO(wc, X) 0 +#define _FP_ROUND_ZERO(wc, X) (void)0 #define _FP_ROUND_PINF(wc, X) \ do { \ diff --git a/include/media/davinci/vpbe.h b/include/media/davinci/vpbe.h index 4376beeb28c2c9b2db4efe2dbb0a8869bd6ecd93..5d8ceeddc7973bdf52d371547ed00c0a113bb6ed 100644 --- a/include/media/davinci/vpbe.h +++ b/include/media/davinci/vpbe.h @@ -96,7 +96,7 @@ struct vpbe_config { struct encoder_config_info *ext_encoders; /* amplifier information goes here */ struct amp_config_info *amp; - int num_outputs; + unsigned int num_outputs; /* Order is venc outputs followed by LCD and then external encoders */ struct vpbe_output *outputs; }; diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 8ffa94009d1a956d19894e84eee28ea75f3ae101..76002416cead9be57a9dbe5e0a21a18251e4fe22 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -268,7 +268,7 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev *sd, struct v4l2_subdev *__sd; \ \ __v4l2_device_call_subdevs_p(v4l2_dev, __sd, \ - !(grpid) || __sd->grp_id == (grpid), o, f , \ + (grpid) == 0 || __sd->grp_id == (grpid), o, f , \ ##args); \ } while (0) @@ -280,7 +280,7 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev *sd, ({ \ struct v4l2_subdev *__sd; \ __v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, \ - !(grpid) || __sd->grp_id == (grpid), o, f , \ + (grpid) == 0 || __sd->grp_id == (grpid), o, f , \ ##args); \ }) @@ -294,8 +294,8 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev *sd, struct v4l2_subdev *__sd; \ \ __v4l2_device_call_subdevs_p(v4l2_dev, __sd, \ - !(grpmsk) || (__sd->grp_id & (grpmsk)), o, f , \ - ##args); \ + (grpmsk) == 0 || (__sd->grp_id & (grpmsk)), o, \ + f , ##args); \ } while (0) /* @@ -308,8 +308,8 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev *sd, ({ \ struct v4l2_subdev *__sd; \ __v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, \ - !(grpmsk) || (__sd->grp_id & (grpmsk)), o, f , \ - ##args); \ + (grpmsk) == 0 || (__sd->grp_id & (grpmsk)), o, \ + f , ##args); \ }) /* diff --git a/include/media/v4l2-rect.h b/include/media/v4l2-rect.h index d2125f0cc7cd5e3e5ea699d278fec33ed9d97e6e..1584c760b9937f50417a05fd41e2d61161a605e8 100644 --- a/include/media/v4l2-rect.h +++ b/include/media/v4l2-rect.h @@ -75,10 +75,10 @@ static inline void v4l2_rect_map_inside(struct v4l2_rect *r, r->left = boundary->left; if (r->top < boundary->top) r->top = boundary->top; - if (r->left + r->width > boundary->width) - r->left = boundary->width - r->width; - if (r->top + r->height > boundary->height) - r->top = boundary->height - r->height; + if (r->left + r->width > boundary->left + boundary->width) + r->left = boundary->left + boundary->width - r->width; + if (r->top + r->height > boundary->top + boundary->height) + r->top = boundary->top + boundary->height - r->height; } /** diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index dc9c526b508e0bb8fedf873b4045f471fab0ef60..fbbe3e8fa2ba2efb11dff2a7e480f0059c736151 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -73,6 +73,9 @@ /* Indicate backport support for DH IE creation/update*/ #define CFG80211_EXTERNAL_DH_UPDATE_SUPPORT 1 +/* Indicate backport support for supported AKM advertisement per interface*/ +#define CFG80211_IFTYPE_AKM_SUITES_SUPPORT 1 + /** * DOC: Introduction * @@ -3556,6 +3559,21 @@ struct wiphy_iftype_ext_capab { u8 extended_capabilities_len; }; +/** + * struct wiphy_iftype_akm_suites - This structure encapsulates supported akm + * suites for interface types defined in @iftypes_mask. Each type in the + * @iftypes_mask must be unique across all instances of iftype_akm_suites. + * + * @iftypes_mask: bitmask of interfaces types + * @akm_suites: points to an array of supported akm suites + * @n_akm_suites: number of supported AKM suites + */ +struct wiphy_iftype_akm_suites { + u16 iftypes_mask; + const u32 *akm_suites; + int n_akm_suites; +}; + /** * struct wiphy - wireless hardware description * @reg_notifier: the driver's regulatory notification callback, @@ -3568,6 +3586,12 @@ struct wiphy_iftype_ext_capab { * @signal_type: signal type reported in &struct cfg80211_bss. * @cipher_suites: supported cipher suites * @n_cipher_suites: number of supported cipher suites + * @iftype_akm_suites: array of supported akm suites info per interface type. + * Note that the bits in @iftypes_mask inside this structure cannot + * overlap (i.e. only one occurrence of each type is allowed across all + * instances of iftype_akm_suites). + * @num_iftype_akm_suites: number of interface types for which supported akm + * suites are specified separately. * @retry_short: Retry limit for short frames (dot11ShortRetryLimit) * @retry_long: Retry limit for long frames (dot11LongRetryLimit) * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold); @@ -3754,6 +3778,9 @@ struct wiphy { int n_cipher_suites; const u32 *cipher_suites; + const struct wiphy_iftype_akm_suites *iftype_akm_suites; + unsigned int num_iftype_akm_suites; + u8 retry_short; u8 retry_long; u32 frag_threshold; @@ -4444,6 +4471,17 @@ static inline const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type, const u8 *ies, int len); +/** + * cfg80211_send_layer2_update - send layer 2 update frame + * + * @dev: network device + * @addr: STA MAC address + * + * Wireless drivers can use this function to update forwarding tables in bridge + * devices upon STA association. + */ +void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr); + /** * DOC: Regulatory enforcement infrastructure * diff --git a/include/net/dst.h b/include/net/dst.h index ddcff17615da6ccf46271a61e2cdcb82d923938d..e57e8fb9a43d335209a7bc03ae7bf6803d506e13 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -110,7 +110,7 @@ struct dst_entry { struct dst_metrics { u32 metrics[RTAX_MAX]; atomic_t refcnt; -}; +} __aligned(4); /* Low pointer bits contain DST_METRICS_FLAGS */ extern const struct dst_metrics dst_default_metrics; u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 8dbfdf728cd8ce901b3b05f0e58b4eeee25051fe..b4eee186b60261391654a00ad53b31120b7e447a 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -93,6 +93,7 @@ struct fib_rules_ops { [FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \ [FRA_PRIORITY] = { .type = NLA_U32 }, \ [FRA_FWMARK] = { .type = NLA_U32 }, \ + [FRA_TUN_ID] = { .type = NLA_U64 }, \ [FRA_FWMASK] = { .type = NLA_U32 }, \ [FRA_TABLE] = { .type = NLA_U32 }, \ [FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \ diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h index 1505cf7a4aafa4bbdb395f0e6ecefc34dd9022a5..7a85a4ef6868e47a9e84022dbc893b858e3d1a62 100644 --- a/include/net/flow_dissector.h +++ b/include/net/flow_dissector.h @@ -4,6 +4,7 @@ #include #include #include +#include #include /** @@ -204,4 +205,12 @@ static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissec return ((char *)target_container) + flow_dissector->offset[key_id]; } +static inline void +flow_dissector_init_keys(struct flow_dissector_key_control *key_control, + struct flow_dissector_key_basic *key_basic) +{ + memset(key_control, 0, sizeof(*key_control)); + memset(key_basic, 0, sizeof(*key_basic)); +} + #endif diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 0574493e38993e7a0675b0bf6e3b9b58b5552f18..fc445e7ccadf4466743f42a85cbd6bbd43512e99 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -98,12 +98,18 @@ struct inet_bind_hashbucket { struct hlist_head chain; }; -/* - * Sockets can be hashed in established or listening table +/* Sockets can be hashed in established or listening table. + * We must use different 'nulls' end-of-chain value for all hash buckets : + * A socket might transition from ESTABLISH to LISTEN state without + * RCU grace period. A lookup in ehash table needs to handle this case. */ +#define LISTENING_NULLS_BASE (1U << 29) struct inet_listen_hashbucket { spinlock_t lock; - struct hlist_head head; + union { + struct hlist_head head; + struct hlist_nulls_head nulls_head; + }; }; /* This is for listening sockets, thus all sockets which possess wildcards. */ diff --git a/include/net/ip.h b/include/net/ip.h index db6e110237ec1727a140c7283b5ae41111a8d632..06ad4246c3217e2d9804908c43aabd71fabb8308 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -623,4 +623,9 @@ extern int sysctl_icmp_msgs_burst; int ip_misc_proc_init(void); #endif +static inline bool inetdev_valid_mtu(unsigned int mtu) +{ + return likely(mtu >= IPV4_MIN_MTU); +} + #endif /* _IP_H */ diff --git a/include/net/neighbour.h b/include/net/neighbour.h index d770d1377abd74169e4273b624488a538bb2131d..7618427a285fbc95b64d34330b0a7cc55468b5c6 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -455,7 +455,7 @@ static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb do { seq = read_seqbegin(&hh->hh_lock); - hh_len = hh->hh_len; + hh_len = READ_ONCE(hh->hh_len); if (likely(hh_len <= HH_DATA_MOD)) { hh_alen = HH_DATA_MOD; diff --git a/include/net/sock.h b/include/net/sock.h index 646cc97c9d20b727a369113384c517796d218101..7a57d6f55f1f33af40f2339683b60bfcd97c74e1 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -662,6 +662,11 @@ static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_h hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list); } +static inline void __sk_nulls_add_node_tail_rcu(struct sock *sk, struct hlist_nulls_head *list) +{ + hlist_nulls_add_tail_rcu(&sk->sk_nulls_node, list); +} + static inline void sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) { sock_hold(sk); diff --git a/include/net/tcp.h b/include/net/tcp.h index 709ec9515dfc36cc237cd3e0f8d9e5dff7bc4fc6..92a5e83964014bc5d218dd4b8c718030bdc53bcc 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -510,19 +510,27 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb); */ static inline void tcp_synq_overflow(const struct sock *sk) { - unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; + unsigned long last_overflow = READ_ONCE(tcp_sk(sk)->rx_opt.ts_recent_stamp); unsigned long now = jiffies; - if (time_after(now, last_overflow + HZ)) - tcp_sk(sk)->rx_opt.ts_recent_stamp = now; + if (!time_between32(now, last_overflow, last_overflow + HZ)) + WRITE_ONCE(tcp_sk(sk)->rx_opt.ts_recent_stamp, now); } /* syncookies: no recent synqueue overflow on this listening socket? */ static inline bool tcp_synq_no_recent_overflow(const struct sock *sk) { - unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; + unsigned long last_overflow = READ_ONCE(tcp_sk(sk)->rx_opt.ts_recent_stamp); - return time_after(jiffies, last_overflow + TCP_SYNCOOKIE_VALID); + /* If last_overflow <= jiffies <= last_overflow + TCP_SYNCOOKIE_VALID, + * then we're under synflood. However, we have to use + * 'last_overflow - HZ' as lower bound. That's because a concurrent + * tcp_synq_overflow() could update .ts_recent_stamp after we read + * jiffies but before we store .ts_recent_stamp into last_overflow, + * which could lead to rejecting a valid syncookie. + */ + return !time_between32(jiffies, last_overflow - HZ, + last_overflow + TCP_SYNCOOKIE_VALID); } static inline u32 tcp_cookie_time(void) diff --git a/include/scsi/fc/Kbuild b/include/scsi/fc/Kbuild deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 9e1aa1a82affa229203d11a67cfc0864fb6e43fa..1bf6f0fc92d1908844d5ef0f39d6534c7c60fde4 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -93,9 +93,9 @@ struct snd_rawmidi_substream { struct list_head list; /* list of all substream for given stream */ int stream; /* direction */ int number; /* substream number */ - unsigned int opened: 1, /* open flag */ - append: 1, /* append flag (merge more streams) */ - active_sensing: 1; /* send active sensing when close */ + bool opened; /* open flag */ + bool append; /* append flag (merge more streams) */ + bool active_sensing; /* send active sensing when close */ int use_count; /* use counter (for output) */ size_t bytes; struct snd_rawmidi *rmidi; diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h old mode 100644 new mode 100755 index be3d8b29405bb7d9ee7add112a74ecb00e5ebed3..2b5c0e27a94d3a081602a0f825193b1de56cf168 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -1793,6 +1793,27 @@ TRACE_EVENT(sched_get_nr_running_avg, __field( int, iowait_avg ) __field( unsigned int, max_nr ) __field( unsigned int, big_max_nr ) + __array( char, comm, TASK_COMM_LEN ) + __field( pid_t, pid ) + __field( pid_t, cur_pid ) + __field( u64, wallclock ) + __field( u64, mark_start ) + __field( u64, delta_m ) + __field( u64, win_start ) + __field( u64, delta ) + __field( u64, irqtime ) + __field( int, evt ) + __field(unsigned int, demand ) + __field(unsigned int, sum ) + __field( int, cpu ) + __field( u64, cs ) + __field( u64, ps ) + __field( u64, util ) + __field( u32, curr_window ) + __field( u32, prev_window ) + __field( u64, nt_cs ) + __field( u64, nt_ps ) + __field( u32, active_windows ) ), TP_fast_assign( @@ -1803,9 +1824,20 @@ TRACE_EVENT(sched_get_nr_running_avg, __entry->big_max_nr = big_max_nr; ), - TP_printk("avg=%d big_avg=%d iowait_avg=%d max_nr=%u big_max_nr=%u", + TP_printk("avg=%d big_avg=%d iowait_avg=%d max_nr=%u big_max_nr=%u" + " wc %llu ws %llu delta %llu event %d cpu %d cur_pid %d task %d (%s) ms %llu delta %llu demand %u sum %u irqtime %llu" + " cs %llu ps %llu util %llu cur_window %u prev_window %u active_wins %u", __entry->avg, __entry->big_avg, __entry->iowait_avg, - __entry->max_nr, __entry->big_max_nr) + __entry->max_nr, __entry->big_max_nr, + __entry->wallclock, __entry->win_start, __entry->delta, + __entry->evt, __entry->cpu, __entry->cur_pid, + __entry->pid, __entry->comm, __entry->mark_start, + __entry->delta_m, __entry->demand, + __entry->sum, __entry->irqtime, + __entry->cs, __entry->ps, __entry->util, + __entry->curr_window, __entry->prev_window, + __entry->active_windows + ) ); TRACE_EVENT(core_ctl_eval_need, diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index d6be935caa501f9f260ef0e86d9dc603801a7042..ecd1a0f7bd3ec4a3535f18229fc42f12977f1c69 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -63,7 +63,11 @@ TRACE_EVENT(xen_mc_callback, TP_PROTO(xen_mc_callback_fn_t fn, void *data), TP_ARGS(fn, data), TP_STRUCT__entry( - __field(xen_mc_callback_fn_t, fn) + /* + * Use field_struct to avoid is_signed_type() + * comparison of a function pointer. + */ + __field_struct(xen_mc_callback_fn_t, fn) __field(void *, data) ), TP_fast_assign( diff --git a/include/trace/perf.h b/include/trace/perf.h index 04fe68bbe7679f48ef5e58b883b7780a5b6fbbfd..14f127b6acf540861ec68c3ed348b81d6ae5f233 100644 --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -34,7 +34,6 @@ perf_trace_##call(void *__data, proto) \ struct trace_event_call *event_call = __data; \ struct trace_event_data_offsets_##call __maybe_unused __data_offsets;\ struct trace_event_raw_##call *entry; \ - struct bpf_prog *prog = event_call->prog; \ struct pt_regs *__regs; \ u64 __count = 1; \ struct task_struct *__task = NULL; \ @@ -46,8 +45,9 @@ perf_trace_##call(void *__data, proto) \ __data_size = trace_event_get_offsets_##call(&__data_offsets, args); \ \ head = this_cpu_ptr(event_call->perf_events); \ - if (!prog && __builtin_constant_p(!__task) && !__task && \ - hlist_empty(head)) \ + if (!bpf_prog_array_valid(event_call) && \ + __builtin_constant_p(!__task) && !__task && \ + hlist_empty(head)) \ return; \ \ __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\ diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild deleted file mode 100644 index 96815bd434ffa0a4d964ae645644de7f89080756..0000000000000000000000000000000000000000 --- a/include/uapi/Kbuild +++ /dev/null @@ -1,17 +0,0 @@ -# UAPI Header export list -# Top-level Makefile calls into asm-$(ARCH) -# List only non-arch directories below - - -header-y += asm-generic/ -header-y += linux/ -header-y += sound/ -header-y += mtd/ -header-y += rdma/ -header-y += video/ -header-y += drm/ -header-y += xen/ -header-y += scsi/ -header-y += misc/ -header-y += media/ -header-y += miniISP/ diff --git a/include/uapi/asm-generic/Kbuild b/include/uapi/asm-generic/Kbuild deleted file mode 100644 index b73de7bb7a62ae9eff4d0445ae848c5d9b94999d..0000000000000000000000000000000000000000 --- a/include/uapi/asm-generic/Kbuild +++ /dev/null @@ -1,36 +0,0 @@ -# UAPI Header export list -header-y += auxvec.h -header-y += bitsperlong.h -header-y += errno-base.h -header-y += errno.h -header-y += fcntl.h -header-y += int-l64.h -header-y += int-ll64.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman-common.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += shmparam.h -header-y += siginfo.h -header-y += signal-defs.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h diff --git a/include/uapi/asm-generic/Kbuild.asm b/include/uapi/asm-generic/Kbuild.asm index fcd50b759217615088767688661c4ece3259b5cf..21381449d98a88f0b5f68942b307128a4269926a 100644 --- a/include/uapi/asm-generic/Kbuild.asm +++ b/include/uapi/asm-generic/Kbuild.asm @@ -1,49 +1,33 @@ -# -# Headers that are optional in usr/include/asm/ -# -opt-header += kvm.h -opt-header += kvm_para.h -opt-header += a.out.h - # # Headers that are mandatory in usr/include/asm/ # -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h - -header-y += $(foreach hdr,$(opt-header), \ - $(if \ - $(wildcard \ - $(srctree)/arch/$(SRCARCH)/include/uapi/asm/$(hdr) \ - $(srctree)/arch/$(SRCARCH)/include/asm/$(hdr) \ - ), \ - $(hdr) \ - )) +mandatory-y += auxvec.h +mandatory-y += bitsperlong.h +mandatory-y += byteorder.h +mandatory-y += errno.h +mandatory-y += fcntl.h +mandatory-y += ioctl.h +mandatory-y += ioctls.h +mandatory-y += ipcbuf.h +mandatory-y += mman.h +mandatory-y += msgbuf.h +mandatory-y += param.h +mandatory-y += poll.h +mandatory-y += posix_types.h +mandatory-y += ptrace.h +mandatory-y += resource.h +mandatory-y += sembuf.h +mandatory-y += setup.h +mandatory-y += shmbuf.h +mandatory-y += sigcontext.h +mandatory-y += siginfo.h +mandatory-y += signal.h +mandatory-y += socket.h +mandatory-y += sockios.h +mandatory-y += stat.h +mandatory-y += statfs.h +mandatory-y += swab.h +mandatory-y += termbits.h +mandatory-y += termios.h +mandatory-y += types.h +mandatory-y += unistd.h diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild index 999c120d6425a8150a96399a88ee1a9e2e052caa..74758ea994640c0f50a517af4de9a6857a0d18bf 100644 --- a/include/uapi/drm/Kbuild +++ b/include/uapi/drm/Kbuild @@ -1,24 +1,5 @@ # UAPI Header export list -header-y += drm.h -header-y += drm_fourcc.h -header-y += drm_mode.h -header-y += drm_sarea.h -header-y += amdgpu_drm.h -header-y += exynos_drm.h -header-y += i810_drm.h -header-y += i915_drm.h -header-y += mga_drm.h -header-y += nouveau_drm.h -header-y += qxl_drm.h -header-y += r128_drm.h -header-y += radeon_drm.h -header-y += savage_drm.h -header-y += sis_drm.h -header-y += tegra_drm.h -header-y += via_drm.h -header-y += vmwgfx_drm.h -header-y += msm_drm.h -header-y += vc4_drm.h -header-y += virtgpu_drm.h -header-y += sde_drm.h -header-y += msm_drm_pp.h +no-export-headers += armada_drm.h +no-export-headers += etnaviv_drm.h +no-export-headers += omap_drm.h +no-export-headers += vgem_drm.h diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 9c927a539b1e5328be19756382003c2e92434277..b420f2acbb3eef28e63705b2bbc3664a7f9f8917 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -78,7 +78,29 @@ extern "C" { #define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) #define DRM_MODE_FLAG_SEAMLESS (1<<19) #define DRM_MODE_FLAG_SUPPORTS_RGB (1<<20) -#define DRM_MODE_FLAG_SUPPORTS_YUV (1<<21) +#define DRM_MODE_FLAG_SUPPORTS_YUV422 (1<<21) +#define DRM_MODE_FLAG_SUPPORTS_YUV420 (1<<22) + + +/* Picture aspect ratio options */ +#define DRM_MODE_PICTURE_ASPECT_NONE 0 +#define DRM_MODE_PICTURE_ASPECT_4_3 1 +#define DRM_MODE_PICTURE_ASPECT_16_9 2 +#define DRM_MODE_PICTURE_ASPECT_64_27 3 +#define DRM_MODE_PICTURE_ASPECT_256_135 4 + +/* Aspect ratio flag bitmask (4 bits 27:24) */ +#define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<24) +#define DRM_MODE_FLAG_PIC_AR_NONE \ + (DRM_MODE_PICTURE_ASPECT_NONE<<24) +#define DRM_MODE_FLAG_PIC_AR_4_3 \ + (DRM_MODE_PICTURE_ASPECT_4_3<<24) +#define DRM_MODE_FLAG_PIC_AR_16_9 \ + (DRM_MODE_PICTURE_ASPECT_16_9<<24) +#define DRM_MODE_FLAG_PIC_AR_64_27 \ + (DRM_MODE_PICTURE_ASPECT_64_27<<24) +#define DRM_MODE_FLAG_PIC_AR_256_135 \ + (DRM_MODE_PICTURE_ASPECT_256_135<<24) /* DPMS flags */ /* bit compatible with the xorg definitions. */ @@ -94,11 +116,6 @@ extern "C" { #define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ #define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ -/* Picture aspect ratio options */ -#define DRM_MODE_PICTURE_ASPECT_NONE 0 -#define DRM_MODE_PICTURE_ASPECT_4_3 1 -#define DRM_MODE_PICTURE_ASPECT_16_9 2 - /* Dithering mode options */ #define DRM_MODE_DITHERING_OFF 0 #define DRM_MODE_DITHERING_ON 1 diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index c2882c2dd5741e69986eff7fc80c4664ee9fb946..887860917481a4598f3805d116ceb642e68f5311 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -1,520 +1,47 @@ # UAPI Header export list -header-y += android/ -header-y += byteorder/ -header-y += can/ -header-y += caif/ -header-y += dvb/ -header-y += hdlc/ -header-y += hsi/ -header-y += iio/ -header-y += isdn/ -header-y += mmc/ -header-y += nfsd/ -header-y += raid/ -header-y += spi/ -header-y += sunrpc/ -header-y += tc_act/ -header-y += tc_ematch/ -header-y += netfilter/ -header-y += netfilter_arp/ -header-y += netfilter_bridge/ -header-y += netfilter_ipv4/ -header-y += netfilter_ipv6/ -header-y += usb/ -header-y += wimax/ -header-y += mfd/ -header-y += msm_ipa.h -genhdr-y += version.h -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h \ - $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h),) -header-y += a.out.h +ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h),) +no-export-headers += a.out.h endif -header-y += acct.h -header-y += adb.h -header-y += adfs_fs.h -header-y += affs_hardblocks.h -header-y += agpgart.h -header-y += aio_abi.h -header-y += am437x-vpfe.h -header-y += apm_bios.h -header-y += arcfb.h -header-y += atalk.h -header-y += atmapi.h -header-y += atmarp.h -header-y += atmbr2684.h -header-y += atmclip.h -header-y += atmdev.h -header-y += atm_eni.h -header-y += atm.h -header-y += atm_he.h -header-y += atm_idt77105.h -header-y += atmioc.h -header-y += atmlec.h -header-y += atmmpc.h -header-y += atm_nicstar.h -header-y += atmppp.h -header-y += atmsap.h -header-y += atmsvc.h -header-y += atm_tcp.h -header-y += atm_zatm.h -header-y += audit.h -header-y += auto_fs4.h -header-y += auto_fs.h -header-y += auxvec.h -header-y += ax25.h -header-y += b1lli.h -header-y += batterydata-interface.h -header-y += baycom.h -header-y += bcm933xx_hcs.h -header-y += bfs_fs.h -header-y += binfmts.h -header-y += blkpg.h -header-y += blktrace_api.h -header-y += bpf_common.h -header-y += bpf_perf_event.h -header-y += bpf.h -header-y += bpqether.h -header-y += bsg.h -header-y += bt-bmc.h -header-y += btrfs.h -header-y += can.h -header-y += capability.h -header-y += capi.h -header-y += cciss_defs.h -header-y += cciss_ioctl.h -header-y += cdrom.h -header-y += cgroupstats.h -header-y += chio.h -header-y += cm4000_cs.h -header-y += cn_proc.h -header-y += coda.h -header-y += coda_psdev.h -header-y += coff.h -header-y += connector.h -header-y += const.h -header-y += coresight-stm.h -header-y += cramfs_fs.h -header-y += cuda.h -header-y += cyclades.h -header-y += cycx_cfm.h -header-y += dcbnl.h -header-y += dccp.h -header-y += devlink.h -header-y += dlmconstants.h -header-y += dlm_device.h -header-y += dlm.h -header-y += dlm_netlink.h -header-y += dlm_plock.h -header-y += dm-ioctl.h -header-y += dm-log-userspace.h -header-y += dn.h -header-y += dqblk_xfs.h -header-y += edd.h -header-y += efs_fs_sb.h -header-y += elfcore.h -header-y += elf-em.h -header-y += elf-fdpic.h -header-y += elf.h -header-y += errno.h -header-y += errqueue.h -header-y += esoc_ctrl.h -header-y += ethtool.h -header-y += eventpoll.h -header-y += fadvise.h -header-y += falloc.h -header-y += fanotify.h -header-y += fb.h -header-y += fcntl.h -header-y += fd.h -header-y += fdreg.h -header-y += fib_rules.h -header-y += fiemap.h -header-y += filter.h -header-y += fips_status.h -header-y += firewire-cdev.h -header-y += firewire-constants.h -header-y += flat.h -header-y += fou.h -header-y += fs.h -header-y += fsl_hypervisor.h -header-y += fuse.h -header-y += futex.h -header-y += gameport.h -header-y += genetlink.h -header-y += gen_stats.h -header-y += gfs2_ondisk.h -header-y += gigaset_dev.h -header-y += gpio.h -header-y += gsmmux.h -header-y += gtp.h header-y += hbtp_input.h -header-y += hdlcdrv.h -header-y += hdlc.h -header-y += hdreg.h -header-y += hiddev.h -header-y += hid.h -header-y += hidraw.h -header-y += hpet.h -header-y += hsr_netlink.h -header-y += hyperv.h -header-y += hysdn_if.h -header-y += i2c-dev.h -header-y += i2c.h -header-y += i2o-dev.h -header-y += i8k.h -header-y += icmp.h -header-y += icmpv6.h -header-y += if_addr.h -header-y += if_addrlabel.h -header-y += if_alg.h -header-y += if_arcnet.h -header-y += if_arp.h -header-y += if_bonding.h -header-y += if_bridge.h -header-y += if_cablemodem.h -header-y += if_eql.h -header-y += if_ether.h -header-y += if_fc.h -header-y += if_fddi.h -header-y += if_frad.h -header-y += if.h -header-y += if_hippi.h -header-y += if_infiniband.h -header-y += if_link.h -header-y += if_ltalk.h -header-y += if_macsec.h -header-y += if_packet.h -header-y += if_phonet.h -header-y += if_plip.h -header-y += if_ppp.h -header-y += if_pppol2tp.h -header-y += if_pppox.h -header-y += if_slip.h -header-y += if_team.h -header-y += if_tun.h -header-y += if_tunnel.h -header-y += if_vlan.h -header-y += if_x25.h -header-y += igmp.h -header-y += ila.h -header-y += in6.h -header-y += inet_diag.h -header-y += in.h -header-y += inotify.h -header-y += input.h -header-y += input-event-codes.h -header-y += in_route.h -header-y += ioctl.h -header-y += ion.h -header-y += ip6_tunnel.h -header-y += ipc.h -header-y += ip.h -header-y += ipmi.h -header-y += ipmi_msgdefs.h -header-y += ipsec.h -header-y += ipv6.h -header-y += ipv6_route.h -header-y += ip_vs.h -header-y += ipx.h -header-y += irda.h -header-y += irqnr.h -header-y += isdn_divertif.h -header-y += isdn.h -header-y += isdnif.h -header-y += isdn_ppp.h -header-y += iso_fs.h -header-y += ivtvfb.h -header-y += ivtv.h -header-y += ixjuser.h -header-y += jffs2.h -header-y += joystick.h -header-y += kcmp.h -header-y += kdev_t.h -header-y += kd.h -header-y += kernelcapi.h -header-y += kernel.h -header-y += kernel-page-flags.h -header-y += kexec.h -header-y += keyboard.h -header-y += keyctl.h +header-y += qbt1000.h -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h \ - $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h),) -header-y += kvm.h +ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h),) +no-export-headers += kvm.h endif - -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h \ - $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h),) -header-y += kvm_para.h +ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h),) +no-export-headers += kvm_para.h endif -header-y += hw_breakpoint.h -header-y += l2tp.h -header-y += libc-compat.h -header-y += lirc.h -header-y += limits.h -header-y += llc.h -header-y += loop.h -header-y += lp.h -header-y += lwtunnel.h -header-y += magic.h -header-y += major.h -header-y += map_to_7segment.h -header-y += matroxfb.h -header-y += mdio.h -header-y += mdss_rotator.h -header-y += media.h -header-y += media-bus-format.h -header-y += mei.h -header-y += membarrier.h -header-y += memfd.h -header-y += mempolicy.h -header-y += meye.h +no-export-headers += auto_dev-ioctl.h +no-export-headers += batman_adv.h +no-export-headers += bcache.h +no-export-headers += btrfs_tree.h +no-export-headers += cryptouser.h +no-export-headers += dma-buf.h +no-export-headers += hash_info.h +no-export-headers += kcm.h +no-export-headers += kcov.h +no-export-headers += kfd_ioctl.h +no-export-headers += lightnvm.h +no-export-headers += module.h +no-export-headers += nilfs2_api.h +no-export-headers += nilfs2_ondisk.h +no-export-headers += nsfs.h +no-export-headers += pr.h +no-export-headers += qrtr.h +no-export-headers += stm.h +no-export-headers += tee.h +no-export-headers += userio.h +no-export-headers += wil6210_uapi.h + header-y += mhi.h -header-y += mic_common.h -header-y += mic_ioctl.h -header-y += mii.h -header-y += minix_fs.h -header-y += mman.h -header-y += mmtimer.h -header-y += mpls.h -header-y += mpls_iptunnel.h -header-y += mqueue.h -header-y += mroute6.h -header-y += mroute.h -header-y += msdos_fs.h -header-y += msg.h -header-y += msm_ion.h -header-y += msm_ipc.h -header-y += msm_kgsl.h -header-y += msm_mdp.h -header-y += msm_mdp_ext.h -header-y += msm_rmnet.h -header-y += mtio.h -header-y += nbd.h -header-y += ncp_fs.h -header-y += ncp.h -header-y += ncp_mount.h -header-y += ncp_no.h -header-y += ndctl.h -header-y += neighbour.h -header-y += netconf.h -header-y += netdevice.h -header-y += net_dropmon.h -header-y += netfilter_arp.h -header-y += netfilter_bridge.h -header-y += netfilter_decnet.h -header-y += netfilter.h -header-y += netfilter_ipv4.h -header-y += netfilter_ipv6.h -header-y += net.h -header-y += netlink_diag.h -header-y += netlink.h -header-y += netrom.h -header-y += net_map.h -header-y += net_namespace.h -header-y += net_tstamp.h -header-y += nfc.h -header-y += nfs2.h -header-y += nfs3.h -header-y += nfs4.h -header-y += nfs4_mount.h -header-y += nfsacl.h -header-y += nfs_fs.h -header-y += nfs.h -header-y += nfs_idmap.h -header-y += nfs_mount.h -header-y += nl80211.h -header-y += n_r3964.h -header-y += nubus.h -header-y += nvme_ioctl.h -header-y += nvram.h -header-y += omap3isp.h -header-y += omapfb.h -header-y += oom.h -header-y += openvswitch.h -header-y += packet_diag.h -header-y += param.h -header-y += parport.h -header-y += patchkey.h -header-y += pci.h -header-y += pci_regs.h -header-y += perf_event.h -header-y += personality.h -header-y += pfkeyv2.h -header-y += pg.h -header-y += phantom.h -header-y += phonet.h -header-y += pktcdvd.h -header-y += pkt_cls.h -header-y += pkt_sched.h -header-y += pmu.h -header-y += poll.h -header-y += posix_acl.h -header-y += posix_acl_xattr.h -header-y += posix_types.h -header-y += ppdev.h -header-y += ppp-comp.h -header-y += ppp_defs.h -header-y += ppp-ioctl.h -header-y += pps.h -header-y += prctl.h -header-y += psci.h -header-y += ptp_clock.h -header-y += ptrace.h -header-y += qbt1000.h -header-y += qcedev.h -header-y += qcota.h -header-y += qg.h -header-y += qg-profile.h -header-y += qnx4_fs.h -header-y += qnxtypes.h -header-y += qrng.h -header-y += qseecom.h -header-y += quota.h -header-y += radeonfb.h -header-y += random.h -header-y += raw.h -header-y += rds.h -header-y += reboot.h -header-y += reiserfs_fs.h -header-y += reiserfs_xattr.h -header-y += resource.h -header-y += rfkill.h -header-y += rio_cm_cdev.h -header-y += rio_mport_cdev.h -header-y += romfs_fs.h -header-y += rmnet_data.h -header-y += rose.h -header-y += route.h -header-y += rtc.h -header-y += rtnetlink.h -header-y += scc.h -header-y += sched.h -header-y += scif_ioctl.h -header-y += screen_info.h -header-y += sctp.h -header-y += sdla.h -header-y += seccomp.h -header-y += securebits.h -header-y += seemp_api.h -header-y += seemp_param_id.h -header-y += selinux_netlink.h -header-y += sem.h -header-y += serial_core.h -header-y += serial.h -header-y += serial_reg.h -header-y += serio.h -header-y += shm.h -header-y += signalfd.h -header-y += signal.h -header-y += smcinvoke.h -header-y += smiapp.h -header-y += snmp.h -header-y += sock_diag.h -header-y += socket.h header-y += sockev.h -header-y += sockios.h -header-y += sonet.h -header-y += sonypi.h -header-y += soundcard.h -header-y += sound.h -header-y += spcom.h -header-y += stat.h -header-y += stddef.h -header-y += string.h -header-y += suspend_ioctls.h -header-y += swab.h -header-y += synclink.h -header-y += sync_file.h -header-y += sysctl.h -header-y += sysinfo.h -header-y += target_core_user.h -header-y += taskstats.h -header-y += tcp.h -header-y += tcp_metrics.h -header-y += telephony.h -header-y += termios.h -header-y += thermal.h -header-y += time.h -header-y += times.h -header-y += timex.h -header-y += tiocl.h -header-y += tipc_config.h -header-y += tipc_netlink.h -header-y += tipc.h -header-y += toshiba.h -header-y += tty_flags.h -header-y += tty.h -header-y += types.h -header-y += udf_fs_i.h -header-y += udp.h -header-y += uhid.h -header-y += uinput.h -header-y += uio.h -header-y += ultrasound.h -header-y += un.h -header-y += unistd.h -header-y += unix_diag.h -header-y += usbdevice_fs.h -header-y += usbip.h -header-y += utime.h -header-y += utsname.h -header-y += uuid.h -header-y += uvcvideo.h -header-y += v4l2-common.h -header-y += v4l2-controls.h -header-y += v4l2-dv-timings.h -header-y += v4l2-mediabus.h -header-y += v4l2-subdev.h -header-y += msm_vidc_dec.h -header-y += msm_vidc_enc.h -header-y += veth.h -header-y += vfio.h -header-y += vhost.h -header-y += videodev2.h -header-y += virtio_9p.h -header-y += virtio_balloon.h -header-y += virtio_blk.h -header-y += virtio_config.h -header-y += virtio_console.h -header-y += virtio_gpu.h -header-y += virtio_ids.h -header-y += virtio_input.h -header-y += virtio_net.h -header-y += virtio_pci.h -header-y += virtio_ring.h -header-y += virtio_rng.h -header-y += virtio_scsi.h -header-y += virtio_types.h -header-y += virtio_vsock.h -header-y += vm_bms.h -header-y += vm_sockets.h -header-y += vt.h -header-y += vtpm_proxy.h -header-y += wait.h -header-y += wanrouter.h -header-y += watchdog.h -header-y += wimax.h -header-y += wireless.h -header-y += x25.h -header-y += xattr.h -header-y += xfrm.h -header-y += xilinx-v4l2-controls.h -header-y += zorro.h -header-y += zorro_ids.h -header-y += userfaultfd.h -header-y += ipa_qmi_service_v01.h -header-y += msm_ipa.h -header-y += rmnet_ipa_fd_ioctl.h -header-y += msm_dsps.h -header-y += msm-core-interface.h -header-y += msm_rotator.h -header-y += bgcom_interface.h header-y += nfc/ +header-y += seemp_api.h +header-y += seemp_param_id.h ifneq ($(VSERVICES_SUPPORT), "") include include/linux/Kbuild.vservices diff --git a/include/uapi/linux/android/Kbuild b/include/uapi/linux/android/Kbuild deleted file mode 100644 index ca011eec252a8c2fd962e24ca6542a771dcf9284..0000000000000000000000000000000000000000 --- a/include/uapi/linux/android/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += binder.h diff --git a/include/uapi/linux/bgcom_interface.h b/include/uapi/linux/bgcom_interface.h index b2ac56d5753553c78bc7f36debb325ae586c6c1d..17130ec116b0f8af85a63af1abfa8e8f5feb94e3 100644 --- a/include/uapi/linux/bgcom_interface.h +++ b/include/uapi/linux/bgcom_interface.h @@ -44,6 +44,7 @@ enum bg_event_type { MODEM_AFTER_POWER_UP, ADSP_BEFORE_POWER_DOWN, ADSP_AFTER_POWER_UP, + TWM_BG_AFTER_POWER_UP, }; #define REG_READ \ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index a339bea1f4c806c7a3ed126d8e2365f69bfd4ac4..67d7d771a944897e0e87d4f4670c781550fbc295 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -109,11 +109,47 @@ enum bpf_attach_type { #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE -/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command - * to the given target_fd cgroup the descendent cgroup will be able to - * override effective bpf program that was inherited from this cgroup +/* cgroup-bpf attach flags used in BPF_PROG_ATTACH command + * + * NONE(default): No further bpf programs allowed in the subtree. + * + * BPF_F_ALLOW_OVERRIDE: If a sub-cgroup installs some bpf program, + * the program in this cgroup yields to sub-cgroup program. + * + * BPF_F_ALLOW_MULTI: If a sub-cgroup installs some bpf program, + * that cgroup program gets run in addition to the program in this cgroup. + * + * Only one program is allowed to be attached to a cgroup with + * NONE or BPF_F_ALLOW_OVERRIDE flag. + * Attaching another program on top of NONE or BPF_F_ALLOW_OVERRIDE will + * release old program and attach the new one. Attach flags has to match. + * + * Multiple programs are allowed to be attached to a cgroup with + * BPF_F_ALLOW_MULTI flag. They are executed in FIFO order + * (those that were attached first, run first) + * The programs of sub-cgroup are executed first, then programs of + * this cgroup and then programs of parent cgroup. + * When children program makes decision (like picking TCP CA or sock bind) + * parent program has a chance to override it. + * + * A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups. + * A cgroup with NONE doesn't allow any programs in sub-cgroups. + * Ex1: + * cgrp1 (MULTI progs A, B) -> + * cgrp2 (OVERRIDE prog C) -> + * cgrp3 (MULTI prog D) -> + * cgrp4 (OVERRIDE prog E) -> + * cgrp5 (NONE prog F) + * the event in cgrp5 triggers execution of F,D,A,B in that order. + * if prog F is detached, the execution is E,D,A,B + * if prog F and D are detached, the execution is E,A,B + * if prog F, E and D are detached, the execution is C,A,B + * + * All eligible programs are executed regardless of return code from + * earlier programs. */ #define BPF_F_ALLOW_OVERRIDE (1U << 0) +#define BPF_F_ALLOW_MULTI (1U << 1) #define BPF_PSEUDO_MAP_FD 1 diff --git a/include/uapi/linux/byteorder/Kbuild b/include/uapi/linux/byteorder/Kbuild deleted file mode 100644 index 619225b9ff2ef8d610f5ac6160d51e93561e1ef2..0000000000000000000000000000000000000000 --- a/include/uapi/linux/byteorder/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += big_endian.h -header-y += little_endian.h diff --git a/include/uapi/linux/caif/Kbuild b/include/uapi/linux/caif/Kbuild deleted file mode 100644 index 43396612d3a322dae3cb99f00719bfb15001c476..0000000000000000000000000000000000000000 --- a/include/uapi/linux/caif/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += caif_socket.h -header-y += if_caif.h diff --git a/include/uapi/linux/can/Kbuild b/include/uapi/linux/can/Kbuild deleted file mode 100644 index 21c91bf25a298c9090d103e1fe41406e72a7ae20..0000000000000000000000000000000000000000 --- a/include/uapi/linux/can/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += bcm.h -header-y += error.h -header-y += gw.h -header-y += netlink.h -header-y += raw.h diff --git a/include/uapi/linux/cifs/Kbuild b/include/uapi/linux/cifs/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..c922dbeb0ef44be1e46380ccec79dd663e34802f --- /dev/null +++ b/include/uapi/linux/cifs/Kbuild @@ -0,0 +1,2 @@ +# UAPI Header export list +no-export-headers += cifs_mount.h diff --git a/include/uapi/linux/dvb/Kbuild b/include/uapi/linux/dvb/Kbuild deleted file mode 100644 index d40942cfc627f43b4b0da73a925d72264f778be0..0000000000000000000000000000000000000000 --- a/include/uapi/linux/dvb/Kbuild +++ /dev/null @@ -1,9 +0,0 @@ -# UAPI Header export list -header-y += audio.h -header-y += ca.h -header-y += dmx.h -header-y += frontend.h -header-y += net.h -header-y += osd.h -header-y += version.h -header-y += video.h diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 8c5335bde212dbe173bfb3226bd5cbde4e79f8a0..5dd3332ebc66a6be2bfd3613b2ab114cf4c3bd9f 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -1687,6 +1687,8 @@ enum ethtool_reset_flags { * %ethtool_link_mode_bit_indices for the link modes, and other * link features that the link partner advertised through * autonegotiation; 0 if unknown or not applicable. Read-only. + * @transceiver: Used to distinguish different possible PHY types, + * reported consistently by PHYLIB. Read-only. * * If autonegotiation is disabled, the speed and @duplex represent the * fixed link mode and are writable if the driver supports multiple @@ -1738,7 +1740,9 @@ struct ethtool_link_settings { __u8 eth_tp_mdix; __u8 eth_tp_mdix_ctrl; __s8 link_mode_masks_nwords; - __u32 reserved[8]; + __u8 transceiver; + __u8 reserved1[3]; + __u32 reserved[7]; __u32 link_mode_masks[0]; /* layout of link_mode_masks fields: * __u32 map_supported[link_mode_masks_nwords]; diff --git a/include/uapi/linux/genwqe/Kbuild b/include/uapi/linux/genwqe/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..b50fc2179a2ed3adb2b03e30024980ea90ac3ac9 --- /dev/null +++ b/include/uapi/linux/genwqe/Kbuild @@ -0,0 +1,2 @@ +# UAPI Header export list +no-export-headers += genwqe_card.h diff --git a/include/uapi/linux/hdlc/Kbuild b/include/uapi/linux/hdlc/Kbuild deleted file mode 100644 index 8c1d2cb75e330ae605277aa70ec44415a53f3428..0000000000000000000000000000000000000000 --- a/include/uapi/linux/hdlc/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += ioctl.h diff --git a/include/uapi/linux/hsi/Kbuild b/include/uapi/linux/hsi/Kbuild deleted file mode 100644 index a16a00544258c2e99e46fd1632548f79d875075f..0000000000000000000000000000000000000000 --- a/include/uapi/linux/hsi/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += hsi_char.h cs-protocol.h diff --git a/include/uapi/linux/iio/Kbuild b/include/uapi/linux/iio/Kbuild deleted file mode 100644 index 86f76d84c44f41fec38b49b8f1fa4d11dadfd648..0000000000000000000000000000000000000000 --- a/include/uapi/linux/iio/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += events.h -header-y += types.h diff --git a/include/uapi/linux/isdn/Kbuild b/include/uapi/linux/isdn/Kbuild deleted file mode 100644 index 89e52850bf29c400d72541991b4877a9d499581d..0000000000000000000000000000000000000000 --- a/include/uapi/linux/isdn/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += capicmd.h diff --git a/include/uapi/linux/mmc/Kbuild b/include/uapi/linux/mmc/Kbuild deleted file mode 100644 index ce4e88593605e4cc3f6ef6dbfd6193253be479ed..0000000000000000000000000000000000000000 --- a/include/uapi/linux/mmc/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += core.h -header-y += core.h -header-y += ioctl.h -header-y += mmc.h -header-y += mmc.h diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 864943fe9260b337c819f9aa0b8d1591aaf7be4f..078672b09c5605a6f1b5ed50d417cc00a80c457d 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -1838,6 +1838,12 @@ enum ipa_peripheral_ep_type { IPA_DATA_EP_TYP_BAM_DMUX, }; +enum ipa_data_ep_prot_type { + IPA_PROT_RMNET = 0, + IPA_PROT_RMNET_CV2X = 1, + IPA_PROT_MAX +}; + struct ipa_ep_pair_info { uint32_t consumer_pipe_num; uint32_t producer_pipe_num; @@ -1852,6 +1858,8 @@ struct ipa_ep_pair_info { * @num_ep_pairs: number of ep_pairs - o/p param * @ep_pair_size: sizeof(ipa_ep_pair_info) * max_ep_pairs * @info: structure contains ep pair info + * @teth_prot : RMNET/CV2X --i/p param + * @teth_prot_valid - validity of i/p param protocol */ struct ipa_ioc_get_ep_info { enum ipa_peripheral_ep_type ep_type; @@ -1859,6 +1867,8 @@ struct ipa_ioc_get_ep_info { uint8_t num_ep_pairs; uint32_t ep_pair_size; uintptr_t info; + enum ipa_data_ep_prot_type teth_prot; + uint8_t teth_prot_valid; }; /** diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild index 03f194aeadc51b56d468236c9bba67afbe0b86bd..6b00ca2211263eb0d3c2c0fcb45055271677ed93 100644 --- a/include/uapi/linux/netfilter/Kbuild +++ b/include/uapi/linux/netfilter/Kbuild @@ -1,89 +1,2 @@ # UAPI Header export list -header-y += ipset/ -header-y += nf_conntrack_common.h -header-y += nf_conntrack_ftp.h -header-y += nf_conntrack_sctp.h -header-y += nf_conntrack_tcp.h -header-y += nf_conntrack_tuple_common.h -header-y += nf_log.h -header-y += nf_tables.h -header-y += nf_tables_compat.h -header-y += nf_nat.h -header-y += nfnetlink.h -header-y += nfnetlink_acct.h -header-y += nfnetlink_compat.h -header-y += nfnetlink_conntrack.h -header-y += nfnetlink_cthelper.h -header-y += nfnetlink_cttimeout.h -header-y += nfnetlink_log.h -header-y += nfnetlink_queue.h -header-y += x_tables.h -header-y += xt_AUDIT.h -header-y += xt_CHECKSUM.h -header-y += xt_CLASSIFY.h -header-y += xt_CONNMARK.h -header-y += xt_CONNSECMARK.h -header-y += xt_CT.h -header-y += xt_DSCP.h -header-y += xt_HMARK.h -header-y += xt_IDLETIMER.h -header-y += xt_LED.h -header-y += xt_LOG.h -header-y += xt_MARK.h -header-y += xt_NFLOG.h -header-y += xt_NFQUEUE.h -header-y += xt_RATEEST.h -header-y += xt_SECMARK.h -header-y += xt_SYNPROXY.h -header-y += xt_TCPMSS.h -header-y += xt_TCPOPTSTRIP.h -header-y += xt_TEE.h -header-y += xt_TPROXY.h -header-y += xt_addrtype.h -header-y += xt_bpf.h -header-y += xt_cgroup.h -header-y += xt_cluster.h -header-y += xt_comment.h -header-y += xt_connbytes.h -header-y += xt_connlabel.h -header-y += xt_connlimit.h -header-y += xt_connmark.h -header-y += xt_conntrack.h -header-y += xt_cpu.h -header-y += xt_dccp.h -header-y += xt_devgroup.h -header-y += xt_dscp.h -header-y += xt_ecn.h -header-y += xt_esp.h -header-y += xt_hashlimit.h -header-y += xt_helper.h -header-y += xt_ipcomp.h -header-y += xt_iprange.h -header-y += xt_ipvs.h -header-y += xt_l2tp.h -header-y += xt_length.h -header-y += xt_limit.h -header-y += xt_mac.h -header-y += xt_mark.h -header-y += xt_multiport.h -header-y += xt_nfacct.h -header-y += xt_osf.h -header-y += xt_owner.h -header-y += xt_physdev.h -header-y += xt_pkttype.h -header-y += xt_policy.h -header-y += xt_quota.h -header-y += xt_rateest.h -header-y += xt_realm.h -header-y += xt_recent.h -header-y += xt_rpfilter.h -header-y += xt_sctp.h -header-y += xt_set.h -header-y += xt_socket.h -header-y += xt_state.h -header-y += xt_statistic.h -header-y += xt_string.h -header-y += xt_tcpmss.h -header-y += xt_tcpudp.h -header-y += xt_time.h -header-y += xt_u32.h +no-export-headers += xt_HARDIDLETIMER.h diff --git a/include/uapi/linux/netfilter/ipset/Kbuild b/include/uapi/linux/netfilter/ipset/Kbuild deleted file mode 100644 index d2680423d9abbe0a3e4bd755f0c27e4eb66dacad..0000000000000000000000000000000000000000 --- a/include/uapi/linux/netfilter/ipset/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += ip_set.h -header-y += ip_set_bitmap.h -header-y += ip_set_hash.h -header-y += ip_set_list.h diff --git a/include/uapi/linux/netfilter/xt_sctp.h b/include/uapi/linux/netfilter/xt_sctp.h index 58ffcfb7978e7ebaac2973784498e3cbf1c6e8d9..c2b0886c7c2500ced2cfafbfeadc954acb2fd2d0 100644 --- a/include/uapi/linux/netfilter/xt_sctp.h +++ b/include/uapi/linux/netfilter/xt_sctp.h @@ -40,19 +40,19 @@ struct xt_sctp_info { #define SCTP_CHUNKMAP_SET(chunkmap, type) \ do { \ (chunkmap)[type / bytes(__u32)] |= \ - 1 << (type % bytes(__u32)); \ + 1u << (type % bytes(__u32)); \ } while (0) #define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \ do { \ (chunkmap)[type / bytes(__u32)] &= \ - ~(1 << (type % bytes(__u32))); \ + ~(1u << (type % bytes(__u32))); \ } while (0) #define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \ ({ \ ((chunkmap)[type / bytes (__u32)] & \ - (1 << (type % bytes (__u32)))) ? 1: 0; \ + (1u << (type % bytes (__u32)))) ? 1: 0; \ }) #define SCTP_CHUNKMAP_RESET(chunkmap) \ diff --git a/include/uapi/linux/netfilter_arp/Kbuild b/include/uapi/linux/netfilter_arp/Kbuild deleted file mode 100644 index 62d5637cc0ac5c40cbca78d70b1fb3184cd31427..0000000000000000000000000000000000000000 --- a/include/uapi/linux/netfilter_arp/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += arp_tables.h -header-y += arpt_mangle.h diff --git a/include/uapi/linux/netfilter_bridge/Kbuild b/include/uapi/linux/netfilter_bridge/Kbuild deleted file mode 100644 index 0fbad8ef96de9ecd00262800e4dda07564bbb13b..0000000000000000000000000000000000000000 --- a/include/uapi/linux/netfilter_bridge/Kbuild +++ /dev/null @@ -1,18 +0,0 @@ -# UAPI Header export list -header-y += ebt_802_3.h -header-y += ebt_among.h -header-y += ebt_arp.h -header-y += ebt_arpreply.h -header-y += ebt_ip.h -header-y += ebt_ip6.h -header-y += ebt_limit.h -header-y += ebt_log.h -header-y += ebt_mark_m.h -header-y += ebt_mark_t.h -header-y += ebt_nat.h -header-y += ebt_nflog.h -header-y += ebt_pkttype.h -header-y += ebt_redirect.h -header-y += ebt_stp.h -header-y += ebt_vlan.h -header-y += ebtables.h diff --git a/include/uapi/linux/netfilter_ipv4/Kbuild b/include/uapi/linux/netfilter_ipv4/Kbuild deleted file mode 100644 index 7391cdcbce6cb2b482397db56cb5925512d82a26..0000000000000000000000000000000000000000 --- a/include/uapi/linux/netfilter_ipv4/Kbuild +++ /dev/null @@ -1,11 +0,0 @@ -# UAPI Header export list -header-y += ip_tables.h -header-y += ipt_CLUSTERIP.h -header-y += ipt_ECN.h -header-y += ipt_LOG.h -header-y += ipt_REJECT.h -header-y += ipt_TTL.h -header-y += ipt_ah.h -header-y += ipt_ecn.h -header-y += ipt_ttl.h -header-y += ipt_NATTYPE.h diff --git a/include/uapi/linux/netfilter_ipv6/Kbuild b/include/uapi/linux/netfilter_ipv6/Kbuild deleted file mode 100644 index 75a668ca2353ad9abfa07bbbd6e515aa49ec37fb..0000000000000000000000000000000000000000 --- a/include/uapi/linux/netfilter_ipv6/Kbuild +++ /dev/null @@ -1,13 +0,0 @@ -# UAPI Header export list -header-y += ip6_tables.h -header-y += ip6t_HL.h -header-y += ip6t_LOG.h -header-y += ip6t_NPT.h -header-y += ip6t_REJECT.h -header-y += ip6t_ah.h -header-y += ip6t_frag.h -header-y += ip6t_hl.h -header-y += ip6t_ipv6header.h -header-y += ip6t_mh.h -header-y += ip6t_opts.h -header-y += ip6t_rt.h diff --git a/include/uapi/linux/nfsd/Kbuild b/include/uapi/linux/nfsd/Kbuild deleted file mode 100644 index c11bc404053c121fc82604514fd24e6506e1717f..0000000000000000000000000000000000000000 --- a/include/uapi/linux/nfsd/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += cld.h -header-y += debug.h -header-y += export.h -header-y += nfsfh.h -header-y += stats.h diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 31817b823944877fecab0df99ff22c6825d52f44..17f163578d7fc6ce1718df8314d371d00c4470d1 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2191,6 +2191,80 @@ enum nl80211_commands { * may offload authentication processing to user space if this capability * is indicated in the respective requests from the user space. * + * @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this + * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED. + * + * @NL80211_ATTR_TXQ_STATS: TXQ statistics (nested attribute, see &enum + * nl80211_txq_stats) + * @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy. + * The smaller of this and the memory limit is enforced. + * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the + * TXQ queues for this phy. The smaller of this and the packet limit is + * enforced. + * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes + * a flow is assigned on each round of the DRR scheduler. + * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION). Can be set + * only if %NL80211_STA_FLAG_WME is set. + * + * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include + * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing + * measurement (FTM) responder functionality and containing parameters as + * possible, see &enum nl80211_ftm_responder_attr + * + * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder + * statistics, see &enum nl80211_ftm_responder_stats. + * + * @NL80211_ATTR_TIMEOUT: Timeout for the given operation in milliseconds (u32), + * if the attribute is not given no timeout is requested. Note that 0 is an + * invalid value. + * + * @NL80211_ATTR_PEER_MEASUREMENTS: peer measurements request (and result) + * data, uses nested attributes specified in + * &enum nl80211_peer_measurement_attrs. + * This is also used for capability advertisement in the wiphy information, + * with the appropriate sub-attributes. + * + * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime + * scheduler. + * + * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for + * station associated with the AP. See &enum nl80211_tx_power_setting for + * possible values. + * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This + * allows to set Tx power for a station. If this attribute is not included, + * the default per-interface tx power setting will be overriding. Driver + * should be picking up the lowest tx power, either tx power per-interface + * or per-station. + * + * @NL80211_ATTR_SAE_PASSWORD: attribute for passing SAE password material. It + * is used with %NL80211_CMD_CONNECT to provide password for offloading + * SAE authentication for WPA3-Personal networks. + * + * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support. + * + * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection + * functionality. + * + * @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz + * channel(s) that are allowed to be used for EDMG transmissions. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. (u8 attribute) + * @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations. (u8 attribute) + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. + * + * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key + * (u16). + * + * @NL80211_ATTR_HE_BSS_COLOR: nested attribute for BSS Color Settings. + * + * @NL80211_ATTR_IFTYPE_AKM_SUITES: nested array attribute, with each entry + * using attributes from &enum nl80211_iftype_akm_attributes. This + * attribute is sent in a response to %NL80211_CMD_GET_WIPHY indicating + * supported AKM suites capability per interface. AKMs advertised in + * %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not + * advertised for a specific interface type. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2620,6 +2694,45 @@ enum nl80211_attrs { NL80211_ATTR_EXTERNAL_AUTH_ACTION, NL80211_ATTR_EXTERNAL_AUTH_SUPPORT, + NL80211_ATTR_NSS, + NL80211_ATTR_ACK_SIGNAL, + + NL80211_ATTR_CONTROL_PORT_OVER_NL80211, + + NL80211_ATTR_TXQ_STATS, + NL80211_ATTR_TXQ_LIMIT, + NL80211_ATTR_TXQ_MEMORY_LIMIT, + NL80211_ATTR_TXQ_QUANTUM, + + NL80211_ATTR_HE_CAPABILITY, + + NL80211_ATTR_FTM_RESPONDER, + + NL80211_ATTR_FTM_RESPONDER_STATS, + + NL80211_ATTR_TIMEOUT, + + NL80211_ATTR_PEER_MEASUREMENTS, + + NL80211_ATTR_AIRTIME_WEIGHT, + NL80211_ATTR_STA_TX_POWER_SETTING, + NL80211_ATTR_STA_TX_POWER, + + NL80211_ATTR_SAE_PASSWORD, + + NL80211_ATTR_TWT_RESPONDER, + + NL80211_ATTR_HE_OBSS_PD, + + NL80211_ATTR_WIPHY_EDMG_CHANNELS, + NL80211_ATTR_WIPHY_EDMG_BW_CONFIG, + + NL80211_ATTR_VLAN_ID, + + NL80211_ATTR_HE_BSS_COLOR, + + NL80211_ATTR_IFTYPE_AKM_SUITES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -5578,4 +5691,28 @@ enum nl80211_external_auth_action { NL80211_EXTERNAL_AUTH_ABORT, }; +/** + * enum nl80211_iftype_akm_attributes - interface type AKM attributes + * @__NL80211_IFTYPE_AKM_ATTR_INVALID: Invalid + * + * @NL80211_IFTYPE_AKM_ATTR_IFTYPES: nested attribute containing a flag + * attribute for each interface type that supports AKM suites specified in + * %NL80211_IFTYPE_AKM_ATTR_SUITES + * @NL80211_IFTYPE_AKM_ATTR_SUITES: an array of u32. Used to indicate supported + * AKM suites for the specified interface types. + * + * @__NL80211_IFTYPE_AKM_ATTR_LAST: Internal + * @NL80211_IFTYPE_AKM_ATTR_MAX: highest interface type AKM attribute. + */ +enum nl80211_iftype_akm_attributes { + __NL80211_IFTYPE_AKM_ATTR_INVALID, + + NL80211_IFTYPE_AKM_ATTR_IFTYPES, + NL80211_IFTYPE_AKM_ATTR_SUITES, + + /* keep last */ + __NL80211_IFTYPE_AKM_ATTR_LAST, + NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/uapi/linux/qrtr.h b/include/uapi/linux/qrtr.h index 66c0748d26e2b3e9412424bad66011b23ec0f876..4b25d2fc65aa7096f93da5d63c98107ca32068ad 100644 --- a/include/uapi/linux/qrtr.h +++ b/include/uapi/linux/qrtr.h @@ -3,10 +3,45 @@ #include +#define QRTR_NODE_BCAST 0xffffffffu +#define QRTR_PORT_CTRL 0xfffffffeu + struct sockaddr_qrtr { __kernel_sa_family_t sq_family; __u32 sq_node; __u32 sq_port; }; +enum qrtr_pkt_type { + QRTR_TYPE_DATA = 1, + QRTR_TYPE_HELLO = 2, + QRTR_TYPE_BYE = 3, + QRTR_TYPE_NEW_SERVER = 4, + QRTR_TYPE_DEL_SERVER = 5, + QRTR_TYPE_DEL_CLIENT = 6, + QRTR_TYPE_RESUME_TX = 7, + QRTR_TYPE_EXIT = 8, + QRTR_TYPE_PING = 9, + QRTR_TYPE_NEW_LOOKUP = 10, + QRTR_TYPE_DEL_LOOKUP = 11, +}; + +struct qrtr_ctrl_pkt { + __le32 cmd; + + union { + struct { + __le32 service; + __le32 instance; + __le32 node; + __le32 port; + } server; + + struct { + __le32 node; + __le32 port; + } client; + }; +} __packed; + #endif /* _LINUX_QRTR_H */ diff --git a/include/uapi/linux/raid/Kbuild b/include/uapi/linux/raid/Kbuild deleted file mode 100644 index e2c3d25405d7e20de2dc708088b0399350bd861f..0000000000000000000000000000000000000000 --- a/include/uapi/linux/raid/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += md_p.h -header-y += md_u.h diff --git a/include/uapi/linux/spi/Kbuild b/include/uapi/linux/spi/Kbuild deleted file mode 100644 index 0cc747eff165543ce28d45b23f676ca754bc9984..0000000000000000000000000000000000000000 --- a/include/uapi/linux/spi/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += spidev.h diff --git a/include/uapi/linux/sunrpc/Kbuild b/include/uapi/linux/sunrpc/Kbuild deleted file mode 100644 index 8e02e47c20fb65cbc59ec3ae70bd23bb92af7386..0000000000000000000000000000000000000000 --- a/include/uapi/linux/sunrpc/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += debug.h diff --git a/include/uapi/linux/tc_act/Kbuild b/include/uapi/linux/tc_act/Kbuild deleted file mode 100644 index e3db7403296fdf8a7f72ec44523acea9ba8b0b9b..0000000000000000000000000000000000000000 --- a/include/uapi/linux/tc_act/Kbuild +++ /dev/null @@ -1,15 +0,0 @@ -# UAPI Header export list -header-y += tc_csum.h -header-y += tc_defact.h -header-y += tc_gact.h -header-y += tc_ipt.h -header-y += tc_mirred.h -header-y += tc_nat.h -header-y += tc_pedit.h -header-y += tc_skbedit.h -header-y += tc_vlan.h -header-y += tc_bpf.h -header-y += tc_connmark.h -header-y += tc_ife.h -header-y += tc_tunnel_key.h -header-y += tc_skbmod.h diff --git a/include/uapi/linux/tc_ematch/Kbuild b/include/uapi/linux/tc_ematch/Kbuild deleted file mode 100644 index 53fca39255351730cfd7384d4ca4ccefbb6414c1..0000000000000000000000000000000000000000 --- a/include/uapi/linux/tc_ematch/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += tc_em_cmp.h -header-y += tc_em_meta.h -header-y += tc_em_nbyte.h -header-y += tc_em_text.h diff --git a/include/uapi/linux/usb/Kbuild b/include/uapi/linux/usb/Kbuild index ba153d582422657d884d663ca4c76beb8c678ae4..e511bf63ff7b84602a75ee58a8facb593633a423 100644 --- a/include/uapi/linux/usb/Kbuild +++ b/include/uapi/linux/usb/Kbuild @@ -1,13 +1,3 @@ # UAPI Header export list -header-y += audio.h -header-y += cdc.h -header-y += cdc-wdm.h -header-y += ch11.h -header-y += ch9.h -header-y += functionfs.h -header-y += g_printer.h -header-y += gadgetfs.h -header-y += midi.h -header-y += tmc.h -header-y += usb_ctrl_qti.h -header-y += video.h +no-export-headers += f_accessory.h +no-export-headers += f_mtp.h diff --git a/include/uapi/linux/wimax/Kbuild b/include/uapi/linux/wimax/Kbuild deleted file mode 100644 index 1c97be49971ff377b152af80aca7e51e6c59a9a2..0000000000000000000000000000000000000000 --- a/include/uapi/linux/wimax/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += i2400m.h diff --git a/include/uapi/misc/Kbuild b/include/uapi/misc/Kbuild deleted file mode 100644 index e96cae7d58c9f758baf4846bfa5bc9cf3d6eee3f..0000000000000000000000000000000000000000 --- a/include/uapi/misc/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# misc Header export list -header-y += cxl.h diff --git a/include/uapi/mtd/Kbuild b/include/uapi/mtd/Kbuild deleted file mode 100644 index 5a691e10cd0ecd35db2260c7417145dd5a588aad..0000000000000000000000000000000000000000 --- a/include/uapi/mtd/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += inftl-user.h -header-y += mtd-abi.h -header-y += mtd-user.h -header-y += nftl-user.h -header-y += ubi-user.h diff --git a/include/uapi/rdma/Kbuild b/include/uapi/rdma/Kbuild index f14ab7ff5fee75769c1b187ab371831866d38dae..c2a45be46f9f11d0a27aa5d2ae4cb5807bf109f4 100644 --- a/include/uapi/rdma/Kbuild +++ b/include/uapi/rdma/Kbuild @@ -1,16 +1,2 @@ # UAPI Header export list -header-y += ib_user_cm.h -header-y += ib_user_mad.h -header-y += ib_user_sa.h -header-y += ib_user_verbs.h -header-y += rdma_netlink.h -header-y += rdma_user_cm.h -header-y += hfi/ -header-y += rdma_user_rxe.h -header-y += cxgb3-abi.h -header-y += cxgb4-abi.h -header-y += mlx4-abi.h -header-y += mlx5-abi.h -header-y += mthca-abi.h -header-y += nes-abi.h -header-y += ocrdma-abi.h +no-export-headers += qedr-abi.h diff --git a/include/uapi/rdma/hfi/Kbuild b/include/uapi/rdma/hfi/Kbuild deleted file mode 100644 index ef23c294fc71f96fcc432fcfcbdfc60b2f2673aa..0000000000000000000000000000000000000000 --- a/include/uapi/rdma/hfi/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += hfi1_user.h diff --git a/include/uapi/scsi/Kbuild b/include/uapi/scsi/Kbuild deleted file mode 100644 index 9a0da849dab72fa1c69fb0eb49c5db112334ab04..0000000000000000000000000000000000000000 --- a/include/uapi/scsi/Kbuild +++ /dev/null @@ -1,9 +0,0 @@ -# UAPI Header export list -header-y += fc/ -header-y += ufs/ -header-y += scsi_bsg_fc.h -header-y += sg.h -header-y += scsi_ioctl.h -header-y += scsi_netlink.h -header-y += scsi_netlink_fc.h -header-y += cxlflash_ioctl.h diff --git a/include/uapi/scsi/fc/Kbuild b/include/uapi/scsi/fc/Kbuild deleted file mode 100644 index 5ead9fac265c31e26872e8bd991a2e2c81a7064d..0000000000000000000000000000000000000000 --- a/include/uapi/scsi/fc/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += fc_els.h -header-y += fc_fs.h -header-y += fc_gs.h -header-y += fc_ns.h diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild deleted file mode 100644 index 9578d8bdbf31fe5f1675704bc6fad8b090b96b31..0000000000000000000000000000000000000000 --- a/include/uapi/sound/Kbuild +++ /dev/null @@ -1,16 +0,0 @@ -# UAPI Header export list -header-y += asequencer.h -header-y += asoc.h -header-y += asound.h -header-y += asound_fm.h -header-y += compress_offload.h -header-y += compress_params.h -header-y += emu10k1.h -header-y += firewire.h -header-y += hdsp.h -header-y += hdspm.h -header-y += sb16_csp.h -header-y += sfnt_info.h -header-y += tlv.h -header-y += usb_stream.h -header-y += snd_sst_tokens.h diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h index 20431fef76a2a73df1c2552716d98ccdc7064e62..fad6e6ffbc243ab62ad0102e829257cb656d9a2b 100644 --- a/include/uapi/sound/compress_params.h +++ b/include/uapi/sound/compress_params.h @@ -409,6 +409,13 @@ struct snd_dec_aptx { __u32 nap; }; +/** struct snd_dec_dsd - codec for DSD format + * @blk_size - dsd channel block size + */ +struct snd_dec_dsd { + __u32 blk_size; +}; + /** struct snd_dec_pcm - codec options for PCM format * @num_channels: Number of channels * @ch_map: Channel map for the above corresponding channels @@ -435,6 +442,7 @@ union snd_codec_options { struct snd_dec_aptx aptx_dec; struct snd_dec_pcm pcm_dec; struct snd_dec_amrwb_plus amrwbplus; + struct snd_dec_dsd dsd_dec; }; /** struct snd_codec_desc - description of codec capabilities diff --git a/include/uapi/video/Kbuild b/include/uapi/video/Kbuild index b98fa51b0862ccda19e82823a4f59f9995026c1f..35ee3b6436801cba28069e3f9ec81892eff752a6 100644 --- a/include/uapi/video/Kbuild +++ b/include/uapi/video/Kbuild @@ -1,6 +1,2 @@ # UAPI Header export list -header-y += edid.h -header-y += msm_hdmi_hdcp_mgr.h -header-y += msm_hdmi_modes.h -header-y += sisfb.h -header-y += uvesafb.h +no-export-headers += adf.h diff --git a/include/uapi/xen/Kbuild b/include/uapi/xen/Kbuild deleted file mode 100644 index 5c459628e8c7492c7eaea4bf6cc75e6976438e82..0000000000000000000000000000000000000000 --- a/include/uapi/xen/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += evtchn.h -header-y += gntalloc.h -header-y += gntdev.h -header-y += privcmd.h diff --git a/include/video/Kbuild b/include/video/Kbuild deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/ipc/sem.c b/ipc/sem.c index 10b94bc59d4a5ffaa85a89152ac02a1f806db054..5cd9d802592fc0136ba190480b1851e98018b054 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -2159,11 +2159,9 @@ void exit_sem(struct task_struct *tsk) ipc_assert_locked_object(&sma->sem_perm); list_del(&un->list_id); - /* we are the last process using this ulp, acquiring ulp->lock - * isn't required. Besides that, we are also protected against - * IPC_RMID as we hold sma->sem_perm lock now - */ + spin_lock(&ulp->lock); list_del_rcu(&un->list_proc); + spin_unlock(&ulp->lock); /* perform adjustments registered in un */ for (i = 0; i < sma->sem_nsems; i++) { diff --git a/kernel/audit.c b/kernel/audit.c index 194fa1adc453bde25ba7f8cf4a21958e343ad271..f98476d68a0fb4ef515000611f91464b46f0ace9 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -756,13 +756,11 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature audit_log_end(ab); } -static int audit_set_feature(struct sk_buff *skb) +static int audit_set_feature(struct audit_features *uaf) { - struct audit_features *uaf; int i; BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > ARRAY_SIZE(audit_feature_names)); - uaf = nlmsg_data(nlmsg_hdr(skb)); /* if there is ever a version 2 we should handle that here */ @@ -832,6 +830,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 seq; void *data; + int data_len; int err; struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; @@ -855,6 +854,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) } seq = nlh->nlmsg_seq; data = nlmsg_data(nlh); + data_len = nlmsg_len(nlh); switch (msg_type) { case AUDIT_GET: { @@ -876,7 +876,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct audit_status s; memset(&s, 0, sizeof(s)); /* guard against past and future API changes */ - memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); + memcpy(&s, data, min_t(size_t, sizeof(s), data_len)); if (s.mask & AUDIT_STATUS_ENABLED) { err = audit_set_enabled(s.enabled); if (err < 0) @@ -941,7 +941,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return err; break; case AUDIT_SET_FEATURE: - err = audit_set_feature(skb); + if (data_len < sizeof(struct audit_features)) + return -EINVAL; + err = audit_set_feature(data); if (err) return err; break; @@ -953,6 +955,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = audit_filter(msg_type, AUDIT_FILTER_USER); if (err == 1) { /* match or error */ + char *str = data; + err = 0; if (msg_type == AUDIT_USER_TTY) { err = tty_audit_push(); @@ -961,19 +965,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) } mutex_unlock(&audit_cmd_mutex); audit_log_common_recv_msg(&ab, msg_type); - if (msg_type != AUDIT_USER_TTY) + if (msg_type != AUDIT_USER_TTY) { + /* ensure NULL termination */ + str[data_len - 1] = '\0'; audit_log_format(ab, " msg='%.*s'", AUDIT_MESSAGE_TEXT_MAX, - (char *)data); - else { - int size; - + str); + } else { audit_log_format(ab, " data="); - size = nlmsg_len(nlh); - if (size > 0 && - ((unsigned char *)data)[size - 1] == '\0') - size--; - audit_log_n_untrustedstring(ab, data, size); + if (data_len > 0 && str[data_len - 1] == '\0') + data_len--; + audit_log_n_untrustedstring(ab, str, data_len); } audit_set_portid(ab, NETLINK_CB(skb).portid); audit_log_end(ab); @@ -982,7 +984,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) break; case AUDIT_ADD_RULE: case AUDIT_DEL_RULE: - if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) + if (data_len < sizeof(struct audit_rule_data)) return -EINVAL; if (audit_enabled == AUDIT_LOCKED) { audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); @@ -991,7 +993,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return -EPERM; } err = audit_rule_change(msg_type, NETLINK_CB(skb).portid, - seq, data, nlmsg_len(nlh)); + seq, data, data_len); break; case AUDIT_LIST_RULES: err = audit_list_rules_send(skb, seq); @@ -1005,7 +1007,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case AUDIT_MAKE_EQUIV: { void *bufp = data; u32 sizes[2]; - size_t msglen = nlmsg_len(nlh); + size_t msglen = data_len; char *old, *new; err = -EINVAL; @@ -1081,7 +1083,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) memset(&s, 0, sizeof(s)); /* guard against past and future API changes */ - memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); + memcpy(&s, data, min_t(size_t, sizeof(s), data_len)); /* check if new data is valid */ if ((s.enabled != 0 && s.enabled != 1) || (s.log_passwd != 0 && s.log_passwd != 1)) diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index f036b6ada6efcc7cc75ae03543c81b2948877471..712469a3103ac7040539cb835eabf70a4c8008f8 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -365,12 +365,12 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent) struct dentry *d = kern_path_locked(watch->path, parent); if (IS_ERR(d)) return PTR_ERR(d); - inode_unlock(d_backing_inode(parent->dentry)); if (d_is_positive(d)) { /* update watch filter fields */ watch->dev = d->d_sb->s_dev; watch->ino = d_backing_inode(d)->i_ino; } + inode_unlock(d_backing_inode(parent->dentry)); dput(d); return 0; } diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 42b7251c597fb492261c1cc4b4df134fa4a9a03d..a71ff9965cba671865a82defdc98686be864b284 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -434,6 +434,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, bufp = data->buf; for (i = 0; i < data->field_count; i++) { struct audit_field *f = &entry->rule.fields[i]; + u32 f_val; err = -EINVAL; @@ -442,12 +443,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, goto exit_free; f->type = data->fields[i]; - f->val = data->values[i]; + f_val = data->values[i]; /* Support legacy tests for a valid loginuid */ - if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { + if ((f->type == AUDIT_LOGINUID) && (f_val == AUDIT_UID_UNSET)) { f->type = AUDIT_LOGINUID_SET; - f->val = 0; + f_val = 0; entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; } @@ -463,7 +464,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_SUID: case AUDIT_FSUID: case AUDIT_OBJ_UID: - f->uid = make_kuid(current_user_ns(), f->val); + f->uid = make_kuid(current_user_ns(), f_val); if (!uid_valid(f->uid)) goto exit_free; break; @@ -472,11 +473,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_SGID: case AUDIT_FSGID: case AUDIT_OBJ_GID: - f->gid = make_kgid(current_user_ns(), f->val); + f->gid = make_kgid(current_user_ns(), f_val); if (!gid_valid(f->gid)) goto exit_free; break; case AUDIT_ARCH: + f->val = f_val; entry->rule.arch_f = f; break; case AUDIT_SUBJ_USER: @@ -489,11 +491,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_OBJ_TYPE: case AUDIT_OBJ_LEV_LOW: case AUDIT_OBJ_LEV_HIGH: - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; - + } + entry->rule.buflen += f_val; + f->lsm_str = str; err = security_audit_rule_init(f->type, f->op, str, (void **)&f->lsm_rule); /* Keep currently invalid fields around in case they @@ -502,68 +506,71 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, pr_warn("audit rule for LSM \'%s\' is invalid\n", str); err = 0; - } - if (err) { - kfree(str); + } else if (err) goto exit_free; - } else - f->lsm_str = str; break; case AUDIT_WATCH: - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; - - err = audit_to_watch(&entry->rule, str, f->val, f->op); + } + err = audit_to_watch(&entry->rule, str, f_val, f->op); if (err) { kfree(str); goto exit_free; } + entry->rule.buflen += f_val; break; case AUDIT_DIR: - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; - + } err = audit_make_tree(&entry->rule, str, f->op); kfree(str); if (err) goto exit_free; + entry->rule.buflen += f_val; break; case AUDIT_INODE: + f->val = f_val; err = audit_to_inode(&entry->rule, f); if (err) goto exit_free; break; case AUDIT_FILTERKEY: - if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN) + if (entry->rule.filterkey || f_val > AUDIT_MAX_KEY_LEN) goto exit_free; - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; + } + entry->rule.buflen += f_val; entry->rule.filterkey = str; break; case AUDIT_EXE: - if (entry->rule.exe || f->val > PATH_MAX) + if (entry->rule.exe || f_val > PATH_MAX) goto exit_free; - str = audit_unpack_string(&bufp, &remain, f->val); + str = audit_unpack_string(&bufp, &remain, f_val); if (IS_ERR(str)) { err = PTR_ERR(str); goto exit_free; } - entry->rule.buflen += f->val; - - audit_mark = audit_alloc_mark(&entry->rule, str, f->val); + audit_mark = audit_alloc_mark(&entry->rule, str, f_val); if (IS_ERR(audit_mark)) { kfree(str); err = PTR_ERR(audit_mark); goto exit_free; } + entry->rule.buflen += f_val; entry->rule.exe = audit_mark; break; + default: + f->val = f_val; + break; } } diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index a44a7e4c23d20469381afde1062e8e6a415a939a..54c47a93e86e76e692f8e79e478c75eb61a59052 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -27,129 +27,361 @@ void cgroup_bpf_put(struct cgroup *cgrp) { unsigned int type; - for (type = 0; type < ARRAY_SIZE(cgrp->bpf.prog); type++) { - struct bpf_prog *prog = cgrp->bpf.prog[type]; + for (type = 0; type < ARRAY_SIZE(cgrp->bpf.progs); type++) { + struct list_head *progs = &cgrp->bpf.progs[type]; + struct bpf_prog_list *pl, *tmp; - if (prog) { - bpf_prog_put(prog); + list_for_each_entry_safe(pl, tmp, progs, node) { + list_del(&pl->node); + bpf_prog_put(pl->prog); + kfree(pl); static_branch_dec(&cgroup_bpf_enabled_key); } + bpf_prog_array_free(cgrp->bpf.effective[type]); } } +/* count number of elements in the list. + * it's slow but the list cannot be long + */ +static u32 prog_list_length(struct list_head *head) +{ + struct bpf_prog_list *pl; + u32 cnt = 0; + + list_for_each_entry(pl, head, node) { + if (!pl->prog) + continue; + cnt++; + } + return cnt; +} + +/* if parent has non-overridable prog attached, + * disallow attaching new programs to the descendent cgroup. + * if parent has overridable or multi-prog, allow attaching + */ +static bool hierarchy_allows_attach(struct cgroup *cgrp, + enum bpf_attach_type type, + u32 new_flags) +{ + struct cgroup *p; + + p = cgroup_parent(cgrp); + if (!p) + return true; + do { + u32 flags = p->bpf.flags[type]; + u32 cnt; + + if (flags & BPF_F_ALLOW_MULTI) + return true; + cnt = prog_list_length(&p->bpf.progs[type]); + WARN_ON_ONCE(cnt > 1); + if (cnt == 1) + return !!(flags & BPF_F_ALLOW_OVERRIDE); + p = cgroup_parent(p); + } while (p); + return true; +} + +/* compute a chain of effective programs for a given cgroup: + * start from the list of programs in this cgroup and add + * all parent programs. + * Note that parent's F_ALLOW_OVERRIDE-type program is yielding + * to programs in this cgroup + */ +static int compute_effective_progs(struct cgroup *cgrp, + enum bpf_attach_type type, + struct bpf_prog_array __rcu **array) +{ + struct bpf_prog_array __rcu *progs; + struct bpf_prog_list *pl; + struct cgroup *p = cgrp; + int cnt = 0; + + /* count number of effective programs by walking parents */ + do { + if (cnt == 0 || (p->bpf.flags[type] & BPF_F_ALLOW_MULTI)) + cnt += prog_list_length(&p->bpf.progs[type]); + p = cgroup_parent(p); + } while (p); + + progs = bpf_prog_array_alloc(cnt, GFP_KERNEL); + if (!progs) + return -ENOMEM; + + /* populate the array with effective progs */ + cnt = 0; + p = cgrp; + do { + if (cnt == 0 || (p->bpf.flags[type] & BPF_F_ALLOW_MULTI)) + list_for_each_entry(pl, + &p->bpf.progs[type], node) { + if (!pl->prog) + continue; + rcu_dereference_protected(progs, 1)-> + progs[cnt++] = pl->prog; + } + p = cgroup_parent(p); + } while (p); + + *array = progs; + return 0; +} + +static void activate_effective_progs(struct cgroup *cgrp, + enum bpf_attach_type type, + struct bpf_prog_array __rcu *array) +{ + struct bpf_prog_array __rcu *old_array; + + old_array = xchg(&cgrp->bpf.effective[type], array); + /* free prog array after grace period, since __cgroup_bpf_run_*() + * might be still walking the array + */ + bpf_prog_array_free(old_array); +} + /** * cgroup_bpf_inherit() - inherit effective programs from parent * @cgrp: the cgroup to modify - * @parent: the parent to inherit from */ -void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent) +int cgroup_bpf_inherit(struct cgroup *cgrp) { - unsigned int type; +/* has to use marco instead of const int, since compiler thinks + * that array below is variable length + */ +#define NR ARRAY_SIZE(cgrp->bpf.effective) + struct bpf_prog_array __rcu *arrays[NR] = {}; + int i; - for (type = 0; type < ARRAY_SIZE(cgrp->bpf.effective); type++) { - struct bpf_prog *e; + for (i = 0; i < NR; i++) + INIT_LIST_HEAD(&cgrp->bpf.progs[i]); - e = rcu_dereference_protected(parent->bpf.effective[type], - lockdep_is_held(&cgroup_mutex)); - rcu_assign_pointer(cgrp->bpf.effective[type], e); - cgrp->bpf.disallow_override[type] = parent->bpf.disallow_override[type]; - } + for (i = 0; i < NR; i++) + if (compute_effective_progs(cgrp, i, &arrays[i])) + goto cleanup; + + for (i = 0; i < NR; i++) + activate_effective_progs(cgrp, i, arrays[i]); + + return 0; +cleanup: + for (i = 0; i < NR; i++) + bpf_prog_array_free(arrays[i]); + return -ENOMEM; } +#define BPF_CGROUP_MAX_PROGS 64 + /** - * __cgroup_bpf_update() - Update the pinned program of a cgroup, and + * __cgroup_bpf_attach() - Attach the program to a cgroup, and * propagate the change to descendants * @cgrp: The cgroup which descendants to traverse - * @parent: The parent of @cgrp, or %NULL if @cgrp is the root - * @prog: A new program to pin - * @type: Type of pinning operation (ingress/egress) - * - * Each cgroup has a set of two pointers for bpf programs; one for eBPF - * programs it owns, and which is effective for execution. - * - * If @prog is not %NULL, this function attaches a new program to the cgroup - * and releases the one that is currently attached, if any. @prog is then made - * the effective program of type @type in that cgroup. - * - * If @prog is %NULL, the currently attached program of type @type is released, - * and the effective program of the parent cgroup (if any) is inherited to - * @cgrp. - * - * Then, the descendants of @cgrp are walked and the effective program for - * each of them is set to the effective program of @cgrp unless the - * descendant has its own program attached, in which case the subbranch is - * skipped. This ensures that delegated subcgroups with own programs are left - * untouched. + * @prog: A program to attach + * @type: Type of attach operation * * Must be called with cgroup_mutex held. */ -int __cgroup_bpf_update(struct cgroup *cgrp, struct cgroup *parent, - struct bpf_prog *prog, enum bpf_attach_type type, - bool new_overridable) +int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 flags) { - struct bpf_prog *old_prog, *effective = NULL; - struct cgroup_subsys_state *pos; - bool overridable = true; - - if (parent) { - overridable = !parent->bpf.disallow_override[type]; - effective = rcu_dereference_protected(parent->bpf.effective[type], - lockdep_is_held(&cgroup_mutex)); - } + struct list_head *progs = &cgrp->bpf.progs[type]; + struct bpf_prog *old_prog = NULL; + struct cgroup_subsys_state *css; + struct bpf_prog_list *pl; + bool pl_was_allocated; + u32 old_flags; + int err; - if (prog && effective && !overridable) - /* if parent has non-overridable prog attached, disallow - * attaching new programs to descendent cgroup - */ + if ((flags & BPF_F_ALLOW_OVERRIDE) && (flags & BPF_F_ALLOW_MULTI)) + /* invalid combination */ + return -EINVAL; + + if (!hierarchy_allows_attach(cgrp, type, flags)) return -EPERM; - if (prog && effective && overridable != new_overridable) - /* if parent has overridable prog attached, only - * allow overridable programs in descendent cgroup + if (!list_empty(progs) && cgrp->bpf.flags[type] != flags) + /* Disallow attaching non-overridable on top + * of existing overridable in this cgroup. + * Disallow attaching multi-prog if overridable or none */ return -EPERM; - old_prog = cgrp->bpf.prog[type]; + if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS) + return -E2BIG; - if (prog) { - overridable = new_overridable; - effective = prog; - if (old_prog && - cgrp->bpf.disallow_override[type] == new_overridable) - /* disallow attaching non-overridable on top - * of existing overridable in this cgroup - * and vice versa - */ - return -EPERM; - } + if (flags & BPF_F_ALLOW_MULTI) { + list_for_each_entry(pl, progs, node) + if (pl->prog == prog) + /* disallow attaching the same prog twice */ + return -EINVAL; - if (!prog && !old_prog) - /* report error when trying to detach and nothing is attached */ - return -ENOENT; + pl = kmalloc(sizeof(*pl), GFP_KERNEL); + if (!pl) + return -ENOMEM; + pl_was_allocated = true; + pl->prog = prog; + list_add_tail(&pl->node, progs); + } else { + if (list_empty(progs)) { + pl = kmalloc(sizeof(*pl), GFP_KERNEL); + if (!pl) + return -ENOMEM; + pl_was_allocated = true; + list_add_tail(&pl->node, progs); + } else { + pl = list_first_entry(progs, typeof(*pl), node); + old_prog = pl->prog; + pl_was_allocated = false; + } + pl->prog = prog; + } - cgrp->bpf.prog[type] = prog; + old_flags = cgrp->bpf.flags[type]; + cgrp->bpf.flags[type] = flags; - css_for_each_descendant_pre(pos, &cgrp->self) { - struct cgroup *desc = container_of(pos, struct cgroup, self); + /* allocate and recompute effective prog arrays */ + css_for_each_descendant_pre(css, &cgrp->self) { + struct cgroup *desc = container_of(css, struct cgroup, self); - /* skip the subtree if the descendant has its own program */ - if (desc->bpf.prog[type] && desc != cgrp) { - pos = css_rightmost_descendant(pos); - } else { - rcu_assign_pointer(desc->bpf.effective[type], - effective); - desc->bpf.disallow_override[type] = !overridable; - } + err = compute_effective_progs(desc, type, &desc->bpf.inactive); + if (err) + goto cleanup; } - if (prog) - static_branch_inc(&cgroup_bpf_enabled_key); + /* all allocations were successful. Activate all prog arrays */ + css_for_each_descendant_pre(css, &cgrp->self) { + struct cgroup *desc = container_of(css, struct cgroup, self); + + activate_effective_progs(desc, type, desc->bpf.inactive); + desc->bpf.inactive = NULL; + } + static_branch_inc(&cgroup_bpf_enabled_key); if (old_prog) { bpf_prog_put(old_prog); static_branch_dec(&cgroup_bpf_enabled_key); } return 0; + +cleanup: + /* oom while computing effective. Free all computed effective arrays + * since they were not activated + */ + css_for_each_descendant_pre(css, &cgrp->self) { + struct cgroup *desc = container_of(css, struct cgroup, self); + + bpf_prog_array_free(desc->bpf.inactive); + desc->bpf.inactive = NULL; + } + + /* and cleanup the prog list */ + pl->prog = old_prog; + if (pl_was_allocated) { + list_del(&pl->node); + kfree(pl); + } + return err; +} + +/** + * __cgroup_bpf_detach() - Detach the program from a cgroup, and + * propagate the change to descendants + * @cgrp: The cgroup which descendants to traverse + * @prog: A program to detach or NULL + * @type: Type of detach operation + * + * Must be called with cgroup_mutex held. + */ +int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 unused_flags) +{ + struct list_head *progs = &cgrp->bpf.progs[type]; + u32 flags = cgrp->bpf.flags[type]; + struct bpf_prog *old_prog = NULL; + struct cgroup_subsys_state *css; + struct bpf_prog_list *pl; + int err; + + if (flags & BPF_F_ALLOW_MULTI) { + if (!prog) + /* to detach MULTI prog the user has to specify valid FD + * of the program to be detached + */ + return -EINVAL; + } else { + if (list_empty(progs)) + /* report error when trying to detach and nothing is attached */ + return -ENOENT; + } + + if (flags & BPF_F_ALLOW_MULTI) { + /* find the prog and detach it */ + list_for_each_entry(pl, progs, node) { + if (pl->prog != prog) + continue; + old_prog = prog; + /* mark it deleted, so it's ignored while + * recomputing effective + */ + pl->prog = NULL; + break; + } + if (!old_prog) + return -ENOENT; + } else { + /* to maintain backward compatibility NONE and OVERRIDE cgroups + * allow detaching with invalid FD (prog==NULL) + */ + pl = list_first_entry(progs, typeof(*pl), node); + old_prog = pl->prog; + pl->prog = NULL; + } + + /* allocate and recompute effective prog arrays */ + css_for_each_descendant_pre(css, &cgrp->self) { + struct cgroup *desc = container_of(css, struct cgroup, self); + + err = compute_effective_progs(desc, type, &desc->bpf.inactive); + if (err) + goto cleanup; + } + + /* all allocations were successful. Activate all prog arrays */ + css_for_each_descendant_pre(css, &cgrp->self) { + struct cgroup *desc = container_of(css, struct cgroup, self); + + activate_effective_progs(desc, type, desc->bpf.inactive); + desc->bpf.inactive = NULL; + } + + /* now can actually delete it from this cgroup list */ + list_del(&pl->node); + kfree(pl); + if (list_empty(progs)) + /* last program was detached, reset flags to zero */ + cgrp->bpf.flags[type] = 0; + + bpf_prog_put(old_prog); + static_branch_dec(&cgroup_bpf_enabled_key); + return 0; + +cleanup: + /* oom while computing effective. Free all computed effective arrays + * since they were not activated + */ + css_for_each_descendant_pre(css, &cgrp->self) { + struct cgroup *desc = container_of(css, struct cgroup, self); + + bpf_prog_array_free(desc->bpf.inactive); + desc->bpf.inactive = NULL; + } + + /* and restore back old_prog */ + pl->prog = old_prog; + return err; } /** @@ -171,35 +403,25 @@ int __cgroup_bpf_run_filter(struct sock *sk, struct sk_buff *skb, enum bpf_attach_type type) { - struct bpf_prog *prog; + unsigned int offset = skb->data - skb_network_header(skb); + struct sock *save_sk; struct cgroup *cgrp; - int ret = 0; + int ret; if (!sk || !sk_fullsock(sk)) return 0; - if (sk->sk_family != AF_INET && - sk->sk_family != AF_INET6) + if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6) return 0; cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data); - - rcu_read_lock(); - - prog = rcu_dereference(cgrp->bpf.effective[type]); - if (prog) { - unsigned int offset = skb->data - skb_network_header(skb); - struct sock *save_sk = skb->sk; - - skb->sk = sk; - __skb_push(skb, offset); - ret = bpf_prog_run_save_cb(prog, skb) == 1 ? 0 : -EPERM; - __skb_pull(skb, offset); - skb->sk = save_sk; - } - - rcu_read_unlock(); - - return ret; + save_sk = skb->sk; + skb->sk = sk; + __skb_push(skb, offset); + ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], skb, + bpf_prog_run_save_cb); + __skb_pull(skb, offset); + skb->sk = save_sk; + return ret == 1 ? 0 : -EPERM; } EXPORT_SYMBOL(__cgroup_bpf_run_filter); diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index b373c78a77077233ce47e8d1cc76662fefd7bcf6..8def8ae931d9c33bce4a990261ea65d8060d08d5 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1069,6 +1069,118 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err) } EXPORT_SYMBOL_GPL(bpf_prog_select_runtime); +static unsigned int __bpf_prog_ret1(const struct sk_buff *ctx, + const struct bpf_insn *insn) +{ + return 1; +} + +static struct bpf_prog_dummy { + struct bpf_prog prog; +} dummy_bpf_prog = { + .prog = { + .bpf_func = __bpf_prog_ret1, + }, +}; + +/* to avoid allocating empty bpf_prog_array for cgroups that + * don't have bpf program attached use one global 'empty_prog_array' + * It will not be modified the caller of bpf_prog_array_alloc() + * (since caller requested prog_cnt == 0) + * that pointer should be 'freed' by bpf_prog_array_free() + */ +static struct { + struct bpf_prog_array hdr; + struct bpf_prog *null_prog; +} empty_prog_array = { + .null_prog = NULL, +}; + +struct bpf_prog_array __rcu *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags) +{ + if (prog_cnt) + return kzalloc(sizeof(struct bpf_prog_array) + + sizeof(struct bpf_prog *) * (prog_cnt + 1), + flags); + + return &empty_prog_array.hdr; +} + +void bpf_prog_array_free(struct bpf_prog_array __rcu *progs) +{ + if (!progs || + progs == (struct bpf_prog_array __rcu *)&empty_prog_array.hdr) + return; + kfree_rcu(progs, rcu); +} + +void bpf_prog_array_delete_safe(struct bpf_prog_array __rcu *progs, + struct bpf_prog *old_prog) +{ + struct bpf_prog **prog = progs->progs; + + for (; *prog; prog++) + if (*prog == old_prog) { + WRITE_ONCE(*prog, &dummy_bpf_prog.prog); + break; + } +} + +int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array, + struct bpf_prog *exclude_prog, + struct bpf_prog *include_prog, + struct bpf_prog_array **new_array) +{ + int new_prog_cnt, carry_prog_cnt = 0; + struct bpf_prog **existing_prog; + struct bpf_prog_array *array; + int new_prog_idx = 0; + + /* Figure out how many existing progs we need to carry over to + * the new array. + */ + if (old_array) { + existing_prog = old_array->progs; + for (; *existing_prog; existing_prog++) { + if (*existing_prog != exclude_prog && + *existing_prog != &dummy_bpf_prog.prog) + carry_prog_cnt++; + if (*existing_prog == include_prog) + return -EEXIST; + } + } + + /* How many progs (not NULL) will be in the new array? */ + new_prog_cnt = carry_prog_cnt; + if (include_prog) + new_prog_cnt += 1; + + /* Do we have any prog (not NULL) in the new array? */ + if (!new_prog_cnt) { + *new_array = NULL; + return 0; + } + + /* +1 as the end of prog_array is marked with NULL */ + array = bpf_prog_array_alloc(new_prog_cnt + 1, GFP_KERNEL); + if (!array) + return -ENOMEM; + + /* Fill in the new prog array */ + if (carry_prog_cnt) { + existing_prog = old_array->progs; + for (; *existing_prog; existing_prog++) + if (*existing_prog != exclude_prog && + *existing_prog != &dummy_bpf_prog.prog) + array->progs[new_prog_idx++] = *existing_prog; + } + if (include_prog) + array->progs[new_prog_idx++] = include_prog; + array->progs[new_prog_idx] = NULL; + *new_array = array; + return 0; +} + static void bpf_prog_free_deferred(struct work_struct *work) { struct bpf_prog_aux *aux; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 85ea5983d8751a1116990c38381a29b726a04d07..42af9fa43bf1c8c8f1f94996c0e9174693dbc751 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -894,6 +894,9 @@ static int bpf_obj_get(const union bpf_attr *attr) #define BPF_PROG_ATTACH_LAST_FIELD attach_flags +#define BPF_F_ATTACH_MASK \ + (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI) + static int bpf_prog_attach(const union bpf_attr *attr) { struct bpf_prog *prog; @@ -906,7 +909,7 @@ static int bpf_prog_attach(const union bpf_attr *attr) if (CHECK_ATTR(BPF_PROG_ATTACH)) return -EINVAL; - if (attr->attach_flags & ~BPF_F_ALLOW_OVERRIDE) + if (attr->attach_flags & ~BPF_F_ATTACH_MASK) return -EINVAL; switch (attr->attach_type) { @@ -923,8 +926,8 @@ static int bpf_prog_attach(const union bpf_attr *attr) return PTR_ERR(cgrp); } - ret = cgroup_bpf_update(cgrp, prog, attr->attach_type, - attr->attach_flags & BPF_F_ALLOW_OVERRIDE); + ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type, + attr->attach_flags); if (ret) bpf_prog_put(prog); cgroup_put(cgrp); @@ -941,6 +944,8 @@ static int bpf_prog_attach(const union bpf_attr *attr) static int bpf_prog_detach(const union bpf_attr *attr) { + enum bpf_prog_type ptype; + struct bpf_prog *prog; struct cgroup *cgrp; int ret; @@ -953,18 +958,25 @@ static int bpf_prog_detach(const union bpf_attr *attr) switch (attr->attach_type) { case BPF_CGROUP_INET_INGRESS: case BPF_CGROUP_INET_EGRESS: - cgrp = cgroup_get_from_fd(attr->target_fd); - if (IS_ERR(cgrp)) - return PTR_ERR(cgrp); - - ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false); - cgroup_put(cgrp); + ptype = BPF_PROG_TYPE_CGROUP_SKB; break; default: return -EINVAL; } + cgrp = cgroup_get_from_fd(attr->target_fd); + if (IS_ERR(cgrp)) + return PTR_ERR(cgrp); + + prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype); + if (IS_ERR(prog)) + prog = NULL; + + ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0); + if (prog) + bpf_prog_put(prog); + cgroup_put(cgrp); return ret; } #endif /* CONFIG_CGROUP_BPF */ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 195303305e3ff37840a9849825408f1e1ac9b70a..e3311fe8f526ef0e1d199794b8c28c02df45d07d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2020,6 +2020,9 @@ static int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask) if (ret) goto destroy_root; + ret = cgroup_bpf_inherit(root_cgrp); + WARN_ON_ONCE(ret); + trace_cgroup_setup_root(root); /* @@ -5400,6 +5403,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent) cgrp->self.parent = &parent->self; cgrp->root = root; cgrp->level = level; + ret = cgroup_bpf_inherit(cgrp); + if (ret) + goto out_idr_free; for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) cgrp->ancestor_ids[tcgrp->level] = tcgrp->id; @@ -5436,9 +5442,6 @@ static struct cgroup *cgroup_create(struct cgroup *parent) goto out_idr_free; } - if (parent) - cgroup_bpf_inherit(cgrp, parent); - cgroup_propagate_control(cgrp); return cgrp; @@ -6485,6 +6488,10 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd) return; } + /* Don't associate the sock with unrelated interrupted task's cgroup. */ + if (in_interrupt()) + return; + rcu_read_lock(); while (true) { @@ -6657,14 +6664,23 @@ static __init int cgroup_namespaces_init(void) subsys_initcall(cgroup_namespaces_init); #ifdef CONFIG_CGROUP_BPF -int cgroup_bpf_update(struct cgroup *cgrp, struct bpf_prog *prog, - enum bpf_attach_type type, bool overridable) +int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 flags) +{ + int ret; + + mutex_lock(&cgroup_mutex); + ret = __cgroup_bpf_attach(cgrp, prog, type, flags); + mutex_unlock(&cgroup_mutex); + return ret; +} +int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + enum bpf_attach_type type, u32 flags) { - struct cgroup *parent = cgroup_parent(cgrp); int ret; mutex_lock(&cgroup_mutex); - ret = __cgroup_bpf_update(cgrp, parent, prog, type, overridable); + ret = __cgroup_bpf_detach(cgrp, prog, type, flags); mutex_unlock(&cgroup_mutex); return ret; } diff --git a/kernel/cgroup_pids.c b/kernel/cgroup_pids.c index a57242e0d5a69fa26642c78132e4f8675aba6f9f..b8b898e21c1999cf18d7ca6eebd965a3477bfe49 100644 --- a/kernel/cgroup_pids.c +++ b/kernel/cgroup_pids.c @@ -48,7 +48,7 @@ struct pids_cgroup { * %PIDS_MAX = (%PID_MAX_LIMIT + 1). */ atomic64_t counter; - int64_t limit; + atomic64_t limit; /* Handle for "pids.events" */ struct cgroup_file events_file; @@ -76,8 +76,8 @@ pids_css_alloc(struct cgroup_subsys_state *parent) if (!pids) return ERR_PTR(-ENOMEM); - pids->limit = PIDS_MAX; atomic64_set(&pids->counter, 0); + atomic64_set(&pids->limit, PIDS_MAX); atomic64_set(&pids->events_limit, 0); return &pids->css; } @@ -149,13 +149,14 @@ static int pids_try_charge(struct pids_cgroup *pids, int num) for (p = pids; parent_pids(p); p = parent_pids(p)) { int64_t new = atomic64_add_return(num, &p->counter); + int64_t limit = atomic64_read(&p->limit); /* * Since new is capped to the maximum number of pid_t, if * p->limit is %PIDS_MAX then we know that this test will never * fail. */ - if (new > p->limit) + if (new > limit) goto revert; } @@ -280,7 +281,7 @@ static ssize_t pids_max_write(struct kernfs_open_file *of, char *buf, * Limit updates don't need to be mutex'd, since it isn't * critical that any racing fork()s follow the new limit. */ - pids->limit = limit; + atomic64_set(&pids->limit, limit); return nbytes; } @@ -288,7 +289,7 @@ static int pids_max_show(struct seq_file *sf, void *v) { struct cgroup_subsys_state *css = seq_css(sf); struct pids_cgroup *pids = css_pids(css); - int64_t limit = pids->limit; + int64_t limit = atomic64_read(&pids->limit); if (limit >= PIDS_MAX) seq_printf(sf, "%s\n", PIDS_MAX_STR); diff --git a/kernel/cpu.c b/kernel/cpu.c index 81a78c22bbc9d0d1d21ebbe16dcaa2349d6ba83c..9f4c88f9b1b3f4951649f5330e4a6ceefcb573f7 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -522,8 +522,7 @@ static int bringup_wait_for_ap(unsigned int cpu) if (WARN_ON_ONCE((!cpu_online(cpu)))) return -ECANCELED; - /* Unpark the stopper thread and the hotplug thread of the target cpu */ - stop_machine_unpark(cpu); + /* Unpark the hotplug thread of the target cpu */ kthread_unpark(st->thread); /* @@ -1130,8 +1129,8 @@ void notify_cpu_starting(unsigned int cpu) /* * Called from the idle task. Wake up the controlling task which brings the - * stopper and the hotplug thread of the upcoming CPU up and then delegates - * the rest of the online bringup to the hotplug thread. + * hotplug thread of the upcoming CPU up and then delegates the rest of the + * online bringup to the hotplug thread. */ void cpuhp_online_idle(enum cpuhp_state state) { @@ -1141,6 +1140,12 @@ void cpuhp_online_idle(enum cpuhp_state state) if (state != CPUHP_AP_ONLINE_IDLE) return; + /* + * Unpart the stopper thread before we start the idle loop (and start + * scheduling); this ensures the stopper task is always available. + */ + stop_machine_unpark(smp_processor_id()); + st->state = CPUHP_AP_ONLINE_IDLE; complete(&st->done); } diff --git a/kernel/cred.c b/kernel/cred.c index 0966fab0f48bfd1eaad539826c91b9ea1a64e38d..d63a2d861ac2ee2abd45c2535a6a09d98d336788 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -219,7 +219,7 @@ struct cred *cred_alloc_blank(void) new->magic = CRED_MAGIC; #endif - if (security_cred_alloc_blank(new, GFP_KERNEL) < 0) + if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0) goto error; return new; @@ -278,7 +278,7 @@ struct cred *prepare_creds(void) new->security = NULL; #endif - if (security_prepare_creds(new, old, GFP_KERNEL) < 0) + if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0) goto error; validate_creds(new); return new; @@ -653,7 +653,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) #ifdef CONFIG_SECURITY new->security = NULL; #endif - if (security_prepare_creds(new, old, GFP_KERNEL) < 0) + if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0) goto error; put_cred(old); diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 12076ffe8daf94cd27bb3b38a4ceb39b8274447f..15880fcb6af407b0619222a47bb14f0c2a48fc29 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -2628,7 +2628,7 @@ static int kdb_per_cpu(int argc, const char **argv) diag = kdbgetularg(argv[3], &whichcpu); if (diag) return diag; - if (!cpu_online(whichcpu)) { + if (whichcpu >= nr_cpu_ids || !cpu_online(whichcpu)) { kdb_printf("cpu %ld is not online\n", whichcpu); return KDB_BADCPUNUM; } diff --git a/kernel/events/core.c b/kernel/events/core.c index 1aa14fbe2a1dd35429b65964df5e0219aad54584..d4a26b3cd7110800dfb5eef7135a6e93eb6ca888 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4800,6 +4800,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) if (perf_event_check_period(event, value)) return -EINVAL; + if (!event->attr.freq && (value & (1ULL << 63))) + return -EINVAL; + event_function_call(event, __perf_event_period, &value); return 0; @@ -5476,7 +5479,15 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) */ user_lock_limit *= num_online_cpus(); - user_locked = atomic_long_read(&user->locked_vm) + user_extra; + user_locked = atomic_long_read(&user->locked_vm); + + /* + * sysctl_perf_event_mlock may have changed, so that + * user->locked_vm > user_lock_limit + */ + if (user_locked > user_lock_limit) + user_locked = user_lock_limit; + user_locked += user_extra; if (user_locked > user_lock_limit) extra = user_locked - user_lock_limit; @@ -7877,11 +7888,9 @@ void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx, struct pt_regs *regs, struct hlist_head *head, struct task_struct *task) { - struct bpf_prog *prog = call->prog; - - if (prog) { + if (bpf_prog_array_valid(call)) { *(struct pt_regs **)raw_data = regs; - if (!trace_call_bpf(prog, raw_data) || hlist_empty(head)) { + if (!trace_call_bpf(call, raw_data) || hlist_empty(head)) { perf_swevent_put_recursion_context(rctx); return; } @@ -8067,6 +8076,7 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) { bool is_kprobe, is_tracepoint; struct bpf_prog *prog; + int ret; if (event->attr.type == PERF_TYPE_HARDWARE || event->attr.type == PERF_TYPE_SOFTWARE) @@ -8075,9 +8085,6 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) if (event->attr.type != PERF_TYPE_TRACEPOINT) return -EINVAL; - if (event->tp_event->prog) - return -EEXIST; - is_kprobe = event->tp_event->flags & TRACE_EVENT_FL_UKPROBE; is_tracepoint = event->tp_event->flags & TRACE_EVENT_FL_TRACEPOINT; if (!is_kprobe && !is_tracepoint) @@ -8103,26 +8110,20 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) return -EACCES; } } - event->tp_event->prog = prog; - event->tp_event->bpf_prog_owner = event; - return 0; + ret = perf_event_attach_bpf_prog(event, prog); + if (ret) + bpf_prog_put(prog); + return ret; } static void perf_event_free_bpf_prog(struct perf_event *event) { - struct bpf_prog *prog; - - perf_event_free_bpf_handler(event); - - if (!event->tp_event) + if (event->attr.type != PERF_TYPE_TRACEPOINT) { + perf_event_free_bpf_handler(event); return; - - prog = event->tp_event->prog; - if (prog && event->tp_event->bpf_prog_owner == event) { - event->tp_event->prog = NULL; - bpf_prog_put(prog); } + perf_event_detach_bpf_prog(event); } #else diff --git a/kernel/locking/spinlock_debug.c b/kernel/locking/spinlock_debug.c old mode 100644 new mode 100755 index c18dadd02af4d38e100323f46854648559b1de66..8ab57cce761ad26fef3464efa35066b238d376d9 --- a/kernel/locking/spinlock_debug.c +++ b/kernel/locking/spinlock_debug.c @@ -53,19 +53,19 @@ EXPORT_SYMBOL(__rwlock_init); static void spin_dump(raw_spinlock_t *lock, const char *msg) { - struct task_struct *owner = NULL; + struct task_struct *owner = READ_ONCE(lock->owner); - if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) - owner = lock->owner; + if (owner == SPINLOCK_OWNER_INIT) + owner = NULL; printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n", msg, raw_smp_processor_id(), current->comm, task_pid_nr(current)); printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, " ".owner_cpu: %d\n", - lock, lock->magic, + lock, READ_ONCE(lock->magic), owner ? owner->comm : "", owner ? task_pid_nr(owner) : -1, - lock->owner_cpu); + READ_ONCE(lock->owner_cpu)); #ifdef CONFIG_DEBUG_SPINLOCK_BITE_ON_BUG msm_trigger_wdog_bite(); #elif defined(CONFIG_DEBUG_SPINLOCK_PANIC_ON_BUG) @@ -87,16 +87,16 @@ static void spin_bug(raw_spinlock_t *lock, const char *msg) static inline void debug_spin_lock_before(raw_spinlock_t *lock) { - SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); - SPIN_BUG_ON(lock->owner == current, lock, "recursion"); - SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), + SPIN_BUG_ON(READ_ONCE(lock->magic) != SPINLOCK_MAGIC, lock, "bad magic"); + SPIN_BUG_ON(READ_ONCE(lock->owner) == current, lock, "recursion"); + SPIN_BUG_ON(READ_ONCE(lock->owner_cpu) == raw_smp_processor_id(), lock, "cpu recursion"); } static inline void debug_spin_lock_after(raw_spinlock_t *lock) { - lock->owner_cpu = raw_smp_processor_id(); - lock->owner = current; + WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id()); + WRITE_ONCE(lock->owner, current); } static inline void debug_spin_unlock(raw_spinlock_t *lock) @@ -106,8 +106,8 @@ static inline void debug_spin_unlock(raw_spinlock_t *lock) SPIN_BUG_ON(lock->owner != current, lock, "wrong owner"); SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), lock, "wrong CPU"); - lock->owner = SPINLOCK_OWNER_INIT; - lock->owner_cpu = -1; + WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT); + WRITE_ONCE(lock->owner_cpu, -1); } /* @@ -195,8 +195,8 @@ static inline void debug_write_lock_before(rwlock_t *lock) static inline void debug_write_lock_after(rwlock_t *lock) { - lock->owner_cpu = raw_smp_processor_id(); - lock->owner = current; + WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id()); + WRITE_ONCE(lock->owner, current); } static inline void debug_write_unlock(rwlock_t *lock) @@ -205,8 +205,8 @@ static inline void debug_write_unlock(rwlock_t *lock) RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner"); RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), lock, "wrong CPU"); - lock->owner = SPINLOCK_OWNER_INIT; - lock->owner_cpu = -1; + WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT); + WRITE_ONCE(lock->owner_cpu, -1); } void do_raw_write_lock(rwlock_t *lock) diff --git a/kernel/module.c b/kernel/module.c index ee3c9f14e796d01d27426cdcc5a5889da9e6e73d..5eb3bf76d54bb55e42570affa8cf28c063b4bc50 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -995,6 +995,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); free_module(mod); + /* someone could wait for the module in add_unformed_module() */ + wake_up_all(&module_wq); return 0; out: mutex_unlock(&module_mutex); diff --git a/kernel/padata.c b/kernel/padata.c index 63449fc584daf673aa95ad45f03192808fb64073..286c5142a0f7456345c60662f1bd765148ea1cf4 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -34,6 +34,8 @@ #define MAX_OBJ_NUM 1000 +static void padata_free_pd(struct parallel_data *pd); + static int padata_index_to_cpu(struct parallel_data *pd, int cpu_index) { int cpu, target_cpu; @@ -301,6 +303,7 @@ static void padata_serial_worker(struct work_struct *serial_work) struct padata_serial_queue *squeue; struct parallel_data *pd; LIST_HEAD(local_list); + int cnt; local_bh_disable(); squeue = container_of(serial_work, struct padata_serial_queue, work); @@ -310,6 +313,8 @@ static void padata_serial_worker(struct work_struct *serial_work) list_replace_init(&squeue->serial.list, &local_list); spin_unlock(&squeue->serial.lock); + cnt = 0; + while (!list_empty(&local_list)) { struct padata_priv *padata; @@ -319,9 +324,12 @@ static void padata_serial_worker(struct work_struct *serial_work) list_del_init(&padata->list); padata->serial(padata); - atomic_dec(&pd->refcnt); + cnt++; } local_bh_enable(); + + if (atomic_sub_and_test(cnt, &pd->refcnt)) + padata_free_pd(pd); } /** @@ -444,7 +452,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst, setup_timer(&pd->timer, padata_reorder_timer, (unsigned long)pd); atomic_set(&pd->seq_nr, -1); atomic_set(&pd->reorder_objects, 0); - atomic_set(&pd->refcnt, 0); + atomic_set(&pd->refcnt, 1); pd->pinst = pinst; spin_lock_init(&pd->lock); @@ -469,31 +477,6 @@ static void padata_free_pd(struct parallel_data *pd) kfree(pd); } -/* Flush all objects out of the padata queues. */ -static void padata_flush_queues(struct parallel_data *pd) -{ - int cpu; - struct padata_parallel_queue *pqueue; - struct padata_serial_queue *squeue; - - for_each_cpu(cpu, pd->cpumask.pcpu) { - pqueue = per_cpu_ptr(pd->pqueue, cpu); - flush_work(&pqueue->work); - } - - del_timer_sync(&pd->timer); - - if (atomic_read(&pd->reorder_objects)) - padata_reorder(pd); - - for_each_cpu(cpu, pd->cpumask.cbcpu) { - squeue = per_cpu_ptr(pd->squeue, cpu); - flush_work(&squeue->work); - } - - BUG_ON(atomic_read(&pd->refcnt) != 0); -} - static void __padata_start(struct padata_instance *pinst) { pinst->flags |= PADATA_INIT; @@ -507,10 +490,6 @@ static void __padata_stop(struct padata_instance *pinst) pinst->flags &= ~PADATA_INIT; synchronize_rcu(); - - get_online_cpus(); - padata_flush_queues(pinst->pd); - put_online_cpus(); } /* Replace the internal control structure with a new one. */ @@ -531,8 +510,8 @@ static void padata_replace(struct padata_instance *pinst, if (!cpumask_equal(pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu)) notification_mask |= PADATA_CPU_SERIAL; - padata_flush_queues(pd_old); - padata_free_pd(pd_old); + if (atomic_dec_and_test(&pd_old->refcnt)) + padata_free_pd(pd_old); if (notification_mask) blocking_notifier_call_chain(&pinst->cpumask_change_notifier, diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 4f0f0604f1c4f581f635284f65665adc34fccf3e..5dfac92521faa0d8843ea7662d4d7be671d94222 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -732,8 +732,15 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, * We have found the zone. Now walk the radix tree to find the leaf node * for our PFN. */ + + /* + * If the zone we wish to scan is the the current zone and the + * pfn falls into the current node then we do not need to walk + * the tree. + */ node = bm->cur.node; - if (((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn) + if (zone == bm->cur.zone && + ((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn) goto node_found; node = zone->rtree; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 40e7d106cf85ea16a5777964d8fbb17f036f4cca..dc669e370ee58a0c2d8ece4670ce36dd7426260b 100755 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4748,20 +4748,28 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer) if (++count > 3) { u64 new, old = ktime_to_ns(cfs_b->period); - new = (old * 147) / 128; /* ~115% */ - new = min(new, max_cfs_quota_period); - - cfs_b->period = ns_to_ktime(new); - - /* since max is 1s, this is limited to 1e9^2, which fits in u64 */ - cfs_b->quota *= new; - cfs_b->quota = div64_u64(cfs_b->quota, old); - - pr_warn_ratelimited( - "cfs_period_timer[cpu%d]: period too short, scaling up (new cfs_period_us %lld, cfs_quota_us = %lld)\n", - smp_processor_id(), - div_u64(new, NSEC_PER_USEC), - div_u64(cfs_b->quota, NSEC_PER_USEC)); + /* + * Grow period by a factor of 2 to avoid losing precision. + * Precision loss in the quota/period ratio can cause __cfs_schedulable + * to fail. + */ + new = old * 2; + if (new < max_cfs_quota_period) { + cfs_b->period = ns_to_ktime(new); + cfs_b->quota *= 2; + + pr_warn_ratelimited( + "cfs_period_timer[cpu%d]: period too short, scaling up (new cfs_period_us = %lld, cfs_quota_us = %lld)\n", + smp_processor_id(), + div_u64(new, NSEC_PER_USEC), + div_u64(cfs_b->quota, NSEC_PER_USEC)); + } else { + pr_warn_ratelimited( + "cfs_period_timer[cpu%d]: period too short, but cannot scale up without losing precision (cfs_period_us = %lld, cfs_quota_us = %lld)\n", + smp_processor_id(), + div_u64(old, NSEC_PER_USEC), + div_u64(cfs_b->quota, NSEC_PER_USEC)); + } /* reset count so we don't come right back in here */ count = 0; diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index 5fdbc2353f30d1498cad3ef4843ab20ded6a1285..e2a69e8de898270f420827f685effea4c0585737 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -185,7 +185,8 @@ static void group_init(struct psi_group *group) for_each_possible_cpu(cpu) seqcount_init(&per_cpu_ptr(group->pcpu, cpu)->seq); - group->avg_next_update = sched_clock() + psi_period; + group->avg_last_update = sched_clock(); + group->avg_next_update = group->avg_last_update + psi_period; INIT_DELAYED_WORK(&group->avgs_work, psi_avgs_work); mutex_init(&group->avgs_lock); /* Init trigger-related members */ @@ -481,7 +482,7 @@ static u64 window_update(struct psi_window *win, u64 now, u64 value) u32 remaining; remaining = win->size - elapsed; - growth += div_u64(win->prev_growth * remaining, win->size); + growth += div64_u64(win->prev_growth * remaining, win->size); } return growth; @@ -1198,7 +1199,10 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf, if (static_branch_likely(&psi_disabled)) return -EOPNOTSUPP; - buf_size = min(nbytes, (sizeof(buf) - 1)); + if (!nbytes) + return -EINVAL; + + buf_size = min(nbytes, sizeof(buf)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; diff --git a/kernel/signal.c b/kernel/signal.c index 77d638270c43f312da92d7aeb17d7949e9178e25..0ee539608d39081c57f5989d0bd02c23fd472ff6 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -83,6 +83,11 @@ static int sig_task_ignored(struct task_struct *t, int sig, bool force) handler == SIG_DFL && !(force && sig_kernel_only(sig))) return 1; + /* Only allow kernel generated signals to this kthread */ + if (unlikely((t->flags & PF_KTHREAD) && + (handler == SIG_KTHREAD_KERNEL) && !force)) + return true; + return sig_handler_ignored(handler, sig); } @@ -372,27 +377,32 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi { struct sigqueue *q = NULL; struct user_struct *user; + int sigpending; /* * Protect access to @t credentials. This can go away when all * callers hold rcu read lock. + * + * NOTE! A pending signal will hold on to the user refcount, + * and we get/put the refcount only when the sigpending count + * changes from/to zero. */ rcu_read_lock(); - user = get_uid(__task_cred(t)->user); - atomic_inc(&user->sigpending); + user = __task_cred(t)->user; + sigpending = atomic_inc_return(&user->sigpending); + if (sigpending == 1) + get_uid(user); rcu_read_unlock(); - if (override_rlimit || - atomic_read(&user->sigpending) <= - task_rlimit(t, RLIMIT_SIGPENDING)) { + if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) { q = kmem_cache_alloc(sigqueue_cachep, flags); } else { print_dropped_signal(sig); } if (unlikely(q == NULL)) { - atomic_dec(&user->sigpending); - free_uid(user); + if (atomic_dec_and_test(&user->sigpending)) + free_uid(user); } else { INIT_LIST_HEAD(&q->list); q->flags = 0; @@ -406,8 +416,8 @@ static void __sigqueue_free(struct sigqueue *q) { if (q->flags & SIGQUEUE_PREALLOC) return; - atomic_dec(&q->user->sigpending); - free_uid(q->user); + if (atomic_dec_and_test(&q->user->sigpending)) + free_uid(q->user); kmem_cache_free(sigqueue_cachep, q); } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0dc8c07eb51d77f182e42ebb284416ba62053d9d..f3a22c903ddbf432145e70b52a9c6ea0a93cdcda 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1573,7 +1573,7 @@ static struct ctl_table vm_table[] = { .procname = "drop_caches", .data = &sysctl_drop_caches, .maxlen = sizeof(int), - .mode = 0644, + .mode = 0200, .proc_handler = drop_caches_sysctl_handler, .extra1 = &one, .extra2 = &four, diff --git a/kernel/taskstats.c b/kernel/taskstats.c index cbb387a265db01a7bde8d6576316cdeffa6f1103..23df1fbad4b4ed47e74fdea8de3f9fd1991775b0 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -559,25 +559,33 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk) { struct signal_struct *sig = tsk->signal; - struct taskstats *stats; + struct taskstats *stats_new, *stats; - if (sig->stats || thread_group_empty(tsk)) - goto ret; + /* Pairs with smp_store_release() below. */ + stats = smp_load_acquire(&sig->stats); + if (stats || thread_group_empty(tsk)) + return stats; /* No problem if kmem_cache_zalloc() fails */ - stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); + stats_new = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); spin_lock_irq(&tsk->sighand->siglock); - if (!sig->stats) { - sig->stats = stats; - stats = NULL; + stats = sig->stats; + if (!stats) { + /* + * Pairs with smp_store_release() above and order the + * kmem_cache_zalloc(). + */ + smp_store_release(&sig->stats, stats_new); + stats = stats_new; + stats_new = NULL; } spin_unlock_irq(&tsk->sighand->siglock); - if (stats) - kmem_cache_free(taskstats_cache, stats); -ret: - return sig->stats; + if (stats_new) + kmem_cache_free(taskstats_cache, stats_new); + + return stats; } /* Send pid data out on exit */ diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 8a6970ed783f7ad0388b506c23492bee8a65b5dd..fd3155978575a408c141f6d05f7fb0252c9db43a 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -272,8 +272,15 @@ static void clocksource_watchdog(unsigned long data) next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask); if (next_cpu >= nr_cpu_ids) next_cpu = cpumask_first(cpu_online_mask); - watchdog_timer.expires += WATCHDOG_INTERVAL; - add_timer_on(&watchdog_timer, next_cpu); + + /* + * Arm timer if not already pending: could race with concurrent + * pair clocksource_stop_watchdog() clocksource_start_watchdog(). + */ + if (!timer_pending(&watchdog_timer)) { + watchdog_timer.expires += WATCHDOG_INTERVAL; + add_timer_on(&watchdog_timer, next_cpu); + } out: spin_unlock(&watchdog_lock); } diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c old mode 100644 new mode 100755 index d471752c373be833ad8f296f654e5cbfc683b2b5..049ed34257e34ef5fb7e4e40f858731f9a7d4e38 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -844,7 +844,8 @@ static int enqueue_hrtimer(struct hrtimer *timer, base->cpu_base->active_bases |= 1 << base->index; - timer->state |= HRTIMER_STATE_ENQUEUED; + /* Pairs with the lockless read in hrtimer_is_queued() */ + WRITE_ONCE(timer->state, HRTIMER_STATE_ENQUEUED); return timerqueue_add(&base->active, &timer->node); } @@ -864,9 +865,12 @@ static void __remove_hrtimer(struct hrtimer *timer, u8 newstate, int reprogram) { struct hrtimer_cpu_base *cpu_base = base->cpu_base; + unsigned int state = timer->state; - if (!(timer->state & HRTIMER_STATE_ENQUEUED)) + if (!(state & HRTIMER_STATE_ENQUEUED)) goto out; + /* Pairs with the lockless read in hrtimer_is_queued() */ + WRITE_ONCE(timer->state, newstate); if (!timerqueue_del(&base->active, &timer->node)) cpu_base->active_bases &= ~(1 << base->index); @@ -898,8 +902,9 @@ static void __remove_hrtimer(struct hrtimer *timer, static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart) { - if (hrtimer_is_queued(timer)) { - u8 state = timer->state; + u8 state = timer->state; + + if (state & HRTIMER_STATE_ENQUEUED) { int reprogram; /* diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index c7aab158ea81463d76632855277d251d8995ac3b..afdb7e702a98d8d93b2deb9a4de1f7208f56dab4 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -17,7 +17,7 @@ /** * trace_call_bpf - invoke BPF program - * @prog: BPF program + * @call: tracepoint event * @ctx: opaque context pointer * * kprobe handlers execute BPF programs via this helper. @@ -29,7 +29,7 @@ * 1 - store kprobe event into ring buffer * Other values are reserved and currently alias to 1 */ -unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx) +unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx) { unsigned int ret; @@ -49,9 +49,22 @@ unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx) goto out; } - rcu_read_lock(); - ret = BPF_PROG_RUN(prog, ctx); - rcu_read_unlock(); + /* + * Instead of moving rcu_read_lock/rcu_dereference/rcu_read_unlock + * to all call sites, we did a bpf_prog_array_valid() there to check + * whether call->prog_array is empty or not, which is + * a heurisitc to speed up execution. + * + * If bpf_prog_array_valid() fetched prog_array was + * non-NULL, we go into trace_call_bpf() and do the actual + * proper rcu_dereference() under RCU lock. + * If it turns out that prog_array is NULL then, we bail out. + * For the opposite, if the bpf_prog_array_valid() fetched pointer + * was NULL, you'll skip the prog_array with the risk of missing + * out of events when it was updated in between this and the + * rcu_dereference() which is accepted risk. + */ + ret = BPF_PROG_RUN_ARRAY_CHECK(call->prog_array, ctx, BPF_PROG_RUN); out: __this_cpu_dec(bpf_prog_active); @@ -663,6 +676,65 @@ static const struct bpf_verifier_ops perf_event_prog_ops = { .convert_ctx_access = pe_prog_convert_ctx_access, }; +static DEFINE_MUTEX(bpf_event_mutex); + +int perf_event_attach_bpf_prog(struct perf_event *event, + struct bpf_prog *prog) +{ + struct bpf_prog_array __rcu *old_array; + struct bpf_prog_array *new_array; + int ret = -EEXIST; + + mutex_lock(&bpf_event_mutex); + + if (event->prog) + goto out; + + old_array = rcu_dereference_protected(event->tp_event->prog_array, + lockdep_is_held(&bpf_event_mutex)); + ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array); + if (ret < 0) + goto out; + + /* set the new array to event->tp_event and set event->prog */ + event->prog = prog; + rcu_assign_pointer(event->tp_event->prog_array, new_array); + bpf_prog_array_free(old_array); + +out: + mutex_unlock(&bpf_event_mutex); + return ret; +} + +void perf_event_detach_bpf_prog(struct perf_event *event) +{ + struct bpf_prog_array __rcu *old_array; + struct bpf_prog_array *new_array; + int ret; + + mutex_lock(&bpf_event_mutex); + + if (!event->prog) + goto out; + + old_array = rcu_dereference_protected(event->tp_event->prog_array, + lockdep_is_held(&bpf_event_mutex)); + + ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array); + if (ret < 0) { + bpf_prog_array_delete_safe(old_array, event->prog); + } else { + rcu_assign_pointer(event->tp_event->prog_array, new_array); + bpf_prog_array_free(old_array); + } + + bpf_prog_put(event->prog); + event->prog = NULL; + +out: + mutex_unlock(&bpf_event_mutex); +} + static struct bpf_prog_type_list perf_event_tl = { .ops = &perf_event_prog_ops, .type = BPF_PROG_TYPE_PERF_EVENT, diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 26f10d234292e0dc598edb57765af83e9428611b..3126dbc29dc7899668427577b55073ee6be96b9a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -610,8 +610,7 @@ static int function_stat_show(struct seq_file *m, void *v) } #ifdef CONFIG_FUNCTION_GRAPH_TRACER - avg = rec->time; - do_div(avg, rec->counter); + avg = div64_ul(rec->time, rec->counter); if (tracing_thresh && (avg < tracing_thresh)) goto out; #endif @@ -637,7 +636,8 @@ static int function_stat_show(struct seq_file *m, void *v) * Divide only 1000 for ns^2 -> us^2 conversion. * trace_print_graph_duration will divide 1000 again. */ - do_div(stddev, rec->counter * (rec->counter - 1) * 1000); + stddev = div64_ul(stddev, + rec->counter * (rec->counter - 1) * 1000); } trace_seq_init(&s); @@ -5457,9 +5457,10 @@ static void *fpid_next(struct seq_file *m, void *v, loff_t *pos) struct trace_array *tr = m->private; struct trace_pid_list *pid_list = rcu_dereference_sched(tr->function_pids); - if (v == FTRACE_NO_PIDS) + if (v == FTRACE_NO_PIDS) { + (*pos)++; return NULL; - + } return trace_pid_next(pid_list, v, pos); } diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index 7e6971ba95417e257cce8d433b5b7d9b15b26793..8a88e85c8c6156befc51d5ca591b5b8d3553beaf 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -126,9 +126,10 @@ static void *trigger_next(struct seq_file *m, void *t, loff_t *pos) { struct trace_event_file *event_file = event_file_data(m->private); - if (t == SHOW_AVAILABLE_TRIGGERS) + if (t == SHOW_AVAILABLE_TRIGGERS) { + (*pos)++; return NULL; - + } return seq_list_next(t, &event_file->triggers, pos); } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 3b4cd44ad32311647b35bb17f165945199c9e86b..c49f0465e966d899e762d0a0b73b3cadac9bf3e6 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1142,13 +1142,12 @@ static void kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs) { struct trace_event_call *call = &tk->tp.call; - struct bpf_prog *prog = call->prog; struct kprobe_trace_entry_head *entry; struct hlist_head *head; int size, __size, dsize; int rctx; - if (prog && !trace_call_bpf(prog, regs)) + if (bpf_prog_array_valid(call) && !trace_call_bpf(call, regs)) return; head = this_cpu_ptr(call->perf_events); @@ -1178,13 +1177,12 @@ kretprobe_perf_func(struct trace_kprobe *tk, struct kretprobe_instance *ri, struct pt_regs *regs) { struct trace_event_call *call = &tk->tp.call; - struct bpf_prog *prog = call->prog; struct kretprobe_trace_entry_head *entry; struct hlist_head *head; int size, __size, dsize; int rctx; - if (prog && !trace_call_bpf(prog, regs)) + if (bpf_prog_array_valid(call) && !trace_call_bpf(call, regs)) return; head = this_cpu_ptr(call->perf_events); diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 9d4399b553a3c1e05387b55ec861214e86efa7ed..6403f45da9d5fe339a6f6faac54634e35a7d9eb5 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c @@ -625,7 +625,7 @@ static void start_wakeup_tracer(struct trace_array *tr) if (ret) { pr_info("wakeup trace: Couldn't activate tracepoint" " probe to kernel_sched_migrate_task\n"); - return; + goto fail_deprobe_sched_switch; } wakeup_reset(tr); @@ -643,6 +643,8 @@ static void start_wakeup_tracer(struct trace_array *tr) printk(KERN_ERR "failed to start wakeup tracer\n"); return; +fail_deprobe_sched_switch: + unregister_trace_sched_switch(probe_wakeup_sched_switch, NULL); fail_deprobe_wake_new: unregister_trace_sched_wakeup_new(probe_wakeup, NULL); fail_deprobe: diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index 2a1abbaca10ec96126f3d8e380244214f77ee2a8..5d2c08efd12f806945397bfdb2bb74ab4d29fd3f 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -201,6 +201,11 @@ check_stack(unsigned long ip, unsigned long *stack) local_irq_restore(flags); } +/* Some archs may not define MCOUNT_INSN_SIZE */ +#ifndef MCOUNT_INSN_SIZE +# define MCOUNT_INSN_SIZE 0 +#endif + static void stack_trace_call(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct pt_regs *pt_regs) diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c index 413ff108fbd058ec26a46af5c7ff322a705cc8ea..d19f2191960eaa8d8bf49ab47af5b66e5d13831f 100644 --- a/kernel/trace/trace_stat.c +++ b/kernel/trace/trace_stat.c @@ -277,18 +277,22 @@ static int tracing_stat_init(void) d_tracing = tracing_init_dentry(); if (IS_ERR(d_tracing)) - return 0; + return -ENODEV; stat_dir = tracefs_create_dir("trace_stat", d_tracing); - if (!stat_dir) + if (!stat_dir) { pr_warn("Could not create tracefs 'trace_stat' entry\n"); + return -ENOMEM; + } return 0; } static int init_stat_file(struct stat_session *session) { - if (!stat_dir && tracing_stat_init()) - return -ENODEV; + int ret; + + if (!stat_dir && (ret = tracing_stat_init())) + return ret; session->file = tracefs_create_file(session->ts->name, 0644, stat_dir, @@ -301,7 +305,7 @@ static int init_stat_file(struct stat_session *session) int register_stat_tracer(struct tracer_stat *trace) { struct stat_session *session, *node; - int ret; + int ret = -EINVAL; if (!trace) return -EINVAL; @@ -312,17 +316,15 @@ int register_stat_tracer(struct tracer_stat *trace) /* Already registered? */ mutex_lock(&all_stat_sessions_mutex); list_for_each_entry(node, &all_stat_sessions, session_list) { - if (node->ts == trace) { - mutex_unlock(&all_stat_sessions_mutex); - return -EINVAL; - } + if (node->ts == trace) + goto out; } - mutex_unlock(&all_stat_sessions_mutex); + ret = -ENOMEM; /* Init the session */ session = kzalloc(sizeof(*session), GFP_KERNEL); if (!session) - return -ENOMEM; + goto out; session->ts = trace; INIT_LIST_HEAD(&session->session_list); @@ -331,15 +333,16 @@ int register_stat_tracer(struct tracer_stat *trace) ret = init_stat_file(session); if (ret) { destroy_session(session); - return ret; + goto out; } + ret = 0; /* Register */ - mutex_lock(&all_stat_sessions_mutex); list_add_tail(&session->session_list, &all_stat_sessions); + out: mutex_unlock(&all_stat_sessions_mutex); - return 0; + return ret; } void unregister_stat_tracer(struct tracer_stat *trace) diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index fa5fe2192c28d528e973ed823d08890012be22b5..7e6c2e466fb03b14368b227f40dd91cc2fc0e80f 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -564,6 +564,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) struct syscall_metadata *sys_data; struct syscall_trace_enter *rec; struct hlist_head *head; + bool valid_prog_array; int syscall_nr; int rctx; int size; @@ -579,7 +580,8 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) return; head = this_cpu_ptr(sys_data->enter_event->perf_events); - if (hlist_empty(head)) + valid_prog_array = bpf_prog_array_valid(sys_data->enter_event); + if (!valid_prog_array && hlist_empty(head)) return; /* get the size after alignment with the u32 buffer size field */ @@ -638,6 +640,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) struct syscall_metadata *sys_data; struct syscall_trace_exit *rec; struct hlist_head *head; + bool valid_prog_array; int syscall_nr; int rctx; int size; @@ -653,7 +656,8 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) return; head = this_cpu_ptr(sys_data->exit_event->perf_events); - if (hlist_empty(head)) + valid_prog_array = bpf_prog_array_valid(sys_data->exit_event); + if (!valid_prog_array && hlist_empty(head)) return; /* We can probably do that at build time */ diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 255a82488fe2981c9e929ca5d36307e10a48d99b..3fd4ec0a685c64412a3808cf11ad78e09ac5303d 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -1119,13 +1119,12 @@ static void __uprobe_perf_func(struct trace_uprobe *tu, { struct trace_event_call *call = &tu->tp.call; struct uprobe_trace_entry_head *entry; - struct bpf_prog *prog = call->prog; struct hlist_head *head; void *data; int size, esize; int rctx; - if (prog && !trace_call_bpf(prog, regs)) + if (bpf_prog_array_valid(call) && !trace_call_bpf(call, regs)) return; esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu)); diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index 305039b122fafba242f73b5982289ce4a12a6e20..35b2ba07f3c6f08a8487c588f13758156e047e42 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -90,8 +90,8 @@ static int tracing_map_cmp_atomic64(void *val_a, void *val_b) #define DEFINE_TRACING_MAP_CMP_FN(type) \ static int tracing_map_cmp_##type(void *val_a, void *val_b) \ { \ - type a = *(type *)val_a; \ - type b = *(type *)val_b; \ + type a = (type)(*(u64 *)val_a); \ + type b = (type)(*(u64 *)val_b); \ \ return (a > b) ? 1 : ((a < b) ? -1 : 0); \ } diff --git a/kernel/workqueue.c b/kernel/workqueue.c index e14c995214e4b2240a24a8e21e37fbc699a2fa4f..ac381bff69df7d2ef9c537ee936cae0a6cb375af 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1414,14 +1414,16 @@ static void __queue_work(int cpu, struct workqueue_struct *wq, WARN_ON_ONCE(!is_chained_work(wq))) return; retry: - if (req_cpu == WORK_CPU_UNBOUND) - cpu = wq_select_unbound_cpu(raw_smp_processor_id()); - /* pwq which will be used unless @work is executing elsewhere */ - if (!(wq->flags & WQ_UNBOUND)) - pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); - else + if (wq->flags & WQ_UNBOUND) { + if (req_cpu == WORK_CPU_UNBOUND) + cpu = wq_select_unbound_cpu(raw_smp_processor_id()); pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu)); + } else { + if (req_cpu == WORK_CPU_UNBOUND) + cpu = raw_smp_processor_id(); + pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); + } /* * If @work was previously on a different pool, it might still be @@ -2376,8 +2378,14 @@ static int rescuer_thread(void *__rescuer) */ if (need_to_create_worker(pool)) { spin_lock(&wq_mayday_lock); - get_pwq(pwq); - list_move_tail(&pwq->mayday_node, &wq->maydays); + /* + * Queue iff we aren't racing destruction + * and somebody else hasn't queued it already. + */ + if (wq->rescuer && list_empty(&pwq->mayday_node)) { + get_pwq(pwq); + list_add_tail(&pwq->mayday_node, &wq->maydays); + } spin_unlock(&wq_mayday_lock); } } @@ -4077,9 +4085,29 @@ void destroy_workqueue(struct workqueue_struct *wq) struct pool_workqueue *pwq; int node; + /* + * Remove it from sysfs first so that sanity check failure doesn't + * lead to sysfs name conflicts. + */ + workqueue_sysfs_unregister(wq); + /* drain it before proceeding with destruction */ drain_workqueue(wq); + /* kill rescuer, if sanity checks fail, leave it w/o rescuer */ + if (wq->rescuer) { + struct worker *rescuer = wq->rescuer; + + /* this prevents new queueing */ + spin_lock_irq(&wq_mayday_lock); + wq->rescuer = NULL; + spin_unlock_irq(&wq_mayday_lock); + + /* rescuer will empty maydays list before exiting */ + kthread_stop(rescuer->task); + kfree(rescuer); + } + /* sanity checks */ mutex_lock(&wq->mutex); for_each_pwq(pwq, wq) { @@ -4109,11 +4137,6 @@ void destroy_workqueue(struct workqueue_struct *wq) list_del_rcu(&wq->list); mutex_unlock(&wq_pool_mutex); - workqueue_sysfs_unregister(wq); - - if (wq->rescuer) - kthread_stop(wq->rescuer->task); - if (!(wq->flags & WQ_UNBOUND)) { /* * The base ref is never dropped on per-cpu pwqs. Directly @@ -4390,7 +4413,8 @@ static void show_pwq(struct pool_workqueue *pwq) pr_info(" pwq %d:", pool->id); pr_cont_pool_info(pool); - pr_cont(" active=%d/%d%s\n", pwq->nr_active, pwq->max_active, + pr_cont(" active=%d/%d refcnt=%d%s\n", + pwq->nr_active, pwq->max_active, pwq->refcnt, !list_empty(&pwq->mayday_node) ? " MAYDAY" : ""); hash_for_each(pool->busy_hash, bkt, worker, hentry) { diff --git a/kernel_headers.py b/kernel_headers.py new file mode 100644 index 0000000000000000000000000000000000000000..d36ca87d8cb43b29c954ddf1c4c3f59edce33a77 --- /dev/null +++ b/kernel_headers.py @@ -0,0 +1,1076 @@ +# Copyright 2019 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Generates gen_headers_.bp or generates/checks kernel headers.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import argparse +import filecmp +import os +import re +import subprocess +import sys + + +def gen_version_h(verbose, gen_dir, version_makefile): + """Generate linux/version.h + + Scan the version_makefile for the version info, and then generate + linux/version.h in the gen_dir as done in kernel Makefile function + filechk_version.h + + Args: + verbose: Set True to print progress messages. + gen_dir: Where to place the generated files. + version_makefile: The makefile that contains version info. + Return: + If version info not found, False. Otherwise, True. + """ + + version_re = re.compile(r'VERSION\s*=\s*(\d+)') + patchlevel_re = re.compile(r'PATCHLEVEL\s*=\s*(\d+)') + sublevel_re = re.compile(r'SUBLEVEL\s*=\s*(\d+)') + + version_str = None + patchlevel_str = None + sublevel_str = None + + if verbose: + print('gen_version_h: processing [%s]' % version_makefile) + + with open(version_makefile, 'r') as f: + while not version_str or not patchlevel_str or not sublevel_str: + line = f.readline() + + if not line: + print( + 'error: gen_version_h: failed to parse kernel version from %s' % + version_makefile) + return False + + line = line.rstrip() + + if verbose: + print('gen_version_h: line is %s' % line) + + if not version_str: + match = version_re.match(line) + if match: + if verbose: + print('gen_version_h: matched version [%s]' % line) + version_str = match.group(1) + continue + + if not patchlevel_str: + match = patchlevel_re.match(line) + if match: + if verbose: + print('gen_version_h: matched patchlevel [%s]' % line) + patchlevel_str = match.group(1) + continue + + if not sublevel_str: + match = sublevel_re.match(line) + if match: + if verbose: + print('gen_version_h: matched sublevel [%s]' % line) + sublevel_str = match.group(1) + continue + + version = int(version_str) + patchlevel = int(patchlevel_str) + sublevel = int(sublevel_str) + + if verbose: + print( + 'gen_version_h: found kernel version %d.%d.%d' % + (version, patchlevel, sublevel)) + + version_h = os.path.join(gen_dir, 'linux', 'version.h') + + with open(version_h, 'w') as f: + # This code must match the code in Makefile in the make function + # filechk_version.h + version_code = (version << 16) + (patchlevel << 8) + sublevel + f.write('#define LINUX_VERSION_CODE %d\n' % version_code) + f.write( + '#define KERNEL_VERSION(a,b,c) ' + + '(((a) << 16) + ((b) << 8) + (c))\n') + + return True + + +def scan_arch_kbuild(verbose, arch_asm_kbuild, asm_generic_kbuild, arch_include_uapi): + """Scan arch_asm_kbuild for generated headers. + + This function processes the Kbuild file to scan for three types of files that + need to be generated. The first type are syscall generated headers, which are + identified by adding to the generated-y make variable. The second type are + generic headers, which are arch-specific headers that simply wrap the + asm-generic counterpart, and are identified by adding to the generic-y make + variable. The third type are mandatory headers that should be present in the + /usr/include/asm folder. + + Args: + verbose: Set True to print progress messages. + arch_asm_kbuild: The Kbuild file containing lists of headers to generate. + asm_generic_kbuild: The Kbuild file containing lists of mandatory headers. + arch_include_uapi: Headers in /arch//include/uapi directory + Return: + Two lists of discovered headers, one for generated and one for generic. + """ + + generated_y_re = re.compile(r'generated-y\s*\+=\s*(\S+)') + generic_y_re = re.compile(r'generic-y\s*\+=\s*(\S+)') + mandatory_y_re = re.compile(r'mandatory-y\s*\+=\s*(\S+)') + + # This loop parses arch_asm_kbuild for various kinds of headers to generate. + + if verbose: + print('scan_arch_kbuild: processing [%s]' % arch_asm_kbuild) + + generated_list = [] + generic_list = [] + arch_include_uapi_list = [os.path.basename(x) for x in arch_include_uapi] + mandatory_pre_list = [] + mandatory_list = [] + + + with open(arch_asm_kbuild, 'r') as f: + while True: + line = f.readline() + + if not line: + break + + line = line.rstrip() + + if verbose: + print('scan_arch_kbuild: line is %s' % line) + + match = generated_y_re.match(line) + + if match: + if verbose: + print('scan_arch_kbuild: matched [%s]' % line) + generated_list.append(match.group(1)) + continue + + match = generic_y_re.match(line) + + if match: + if verbose: + print('scan_arch_kbuild: matched [%s]' % line) + generic_list.append(match.group(1)) + continue + + # This loop parses asm_generic_kbuild for various kinds of headers to generate. + + if verbose: + print('scan_arch_kbuild: processing [%s]' % asm_generic_kbuild) + + with open(asm_generic_kbuild, 'r') as f: + while True: + line = f.readline() + + if not line: + break + + line = line.rstrip() + + if verbose: + print('scan_arch_kbuild: line is %s' % line) + + match = mandatory_y_re.match(line) + + if match: + if verbose: + print('scan_arch_kbuild: matched [%s]' % line) + mandatory_pre_list.append(match.group(1)) + continue + + # Mandatory headers need to be generated if they are not already generated. + comb_list = generic_list + generated_list + arch_include_uapi_list + mandatory_list = [x for x in mandatory_pre_list if x not in comb_list] + if verbose: + print("generic") + for x in generic_list: + print(x) + print("generated") + for x in generated_list: + print(x) + print("mandatory") + for x in mandatory_list: + print(x) + print("arch_include_uapi_list") + for x in arch_include_uapi_list: + print(x) + + return (generated_list, generic_list, mandatory_list) + + +def gen_arch_headers( + verbose, gen_dir, arch_asm_kbuild, asm_generic_kbuild, arch_syscall_tool, arch_syscall_tbl, arch_include_uapi): + """Process arch-specific and asm-generic uapi/asm/Kbuild to generate headers. + + The function consists of a call to scan_arch_kbuild followed by three loops. + The first loop generates headers found and placed in the generated_list by + scan_arch_kbuild. The second loop generates headers found and placed in the + generic_list by the scan_arch_kbuild. The third loop generates headers found + in mandatory_list by scan_arch_kbuild. + + The function does some parsing of file names and tool invocations. If that + parsing fails for some reason (e.g., we don't know how to generate the + header) or a tool invocation fails, then this function will count that as + an error but keep processing. In the end, the function returns the number of + errors encountered. + + Args: + verbose: Set True to print progress messages. + gen_dir: Where to place the generated files. + arch_asm_kbuild: The Kbuild file containing lists of headers to generate. + asm_generic_kbuild: The Kbuild file containing lists of mandatory headers. + arch_syscall_tool: The arch script that generates syscall headers, or None. + arch_syscall_tbl: The arch script that defines syscall vectors, or None. + arch_include_uapi: Headers in arch//include/uapi directory. + Return: + The number of parsing errors encountered. + """ + + error_count = 0 + + # First generate the lists + + (generated_list, generic_list, mandatory_list) = scan_arch_kbuild(verbose, arch_asm_kbuild, asm_generic_kbuild ,arch_include_uapi) + + # Now we're at the first loop, which is able to generate syscall headers + # found in the first loop, and placed in generated_list. It's okay for this + # list to be empty. In that case, of course, the loop does nothing. + + abi_re = re.compile(r'unistd-(\S+)\.h') + + for generated in generated_list: + gen_h = os.path.join(gen_dir, 'asm', generated) + match = abi_re.match(generated) + + if match: + abi = match.group(1) + + cmd = [ + '/bin/bash', + arch_syscall_tool, + arch_syscall_tbl, + gen_h, + abi, + '', + '__NR_SYSCALL_BASE', + ] + + if verbose: + print('gen_arch_headers: cmd is %s' % cmd) + + result = subprocess.call(cmd) + + if result != 0: + print('error: gen_arch_headers: cmd %s failed %d' % (cmd, result)) + error_count += 1 + else: + print('error: gen_arch_headers: syscall header has bad filename: %s' % generated) + error_count += 1 + + # Now we're at the second loop, which generates wrappers from arch-specific + # headers listed in generic_list to the corresponding asm-generic header. + + for generic in generic_list: + wrap_h = os.path.join(gen_dir, 'asm', generic) + with open(wrap_h, 'w') as f: + f.write('#include \n' % generic) + + # Now we're at the third loop, which generates wrappers from asm + # headers listed in mandatory_list to the corresponding asm-generic header. + + for mandatory in mandatory_list: + wrap_h = os.path.join(gen_dir, 'asm', mandatory) + with open(wrap_h, 'w') as f: + f.write('#include \n' % mandatory) + return error_count + + +def run_headers_install(verbose, gen_dir, headers_install, prefix, h): + """Process a header through the headers_install script. + + The headers_install script does some processing of a header so that it is + appropriate for inclusion in a userland program. This function invokes that + script for one header file. + + The input file is a header file found in the directory named by prefix. This + function stips the prefix from the header to generate the name of the + processed header. + + Args: + verbose: Set True to print progress messages. + gen_dir: Where to place the generated files. + headers_install: The script that munges the header. + prefix: The prefix to strip from h to generate the output filename. + h: The input header to process. + Return: + If parsing or the tool fails, False. Otherwise, True + """ + + if not h.startswith(prefix): + print('error: expected prefix [%s] on header [%s]' % (prefix, h)) + return False + + out_h = os.path.join(gen_dir, h[len(prefix):]) + (out_h_dirname, out_h_basename) = os.path.split(out_h) + h_dirname = os.path.dirname(h) + + cmd = [headers_install, out_h_dirname, h_dirname, out_h_basename] + + if verbose: + print('run_headers_install: cmd is %s' % cmd) + + result = subprocess.call(cmd) + + if result != 0: + print('error: run_headers_install: cmd %s failed %d' % (cmd, result)) + return False + + return True + + +def glob_headers(prefix, rel_glob, excludes): + """Recursively scan the a directory for headers. + + This function recursively scans the directory identified by prefix for + headers. We don't yet have a new enough version of python3 to use the + better glob function, so right now we assume the glob is '**/*.h'. + + The function filters out any files that match the items in excludes. + + Args: + prefix: The directory to recursively scan for headers. + rel_glob: The shell-style glob that identifies the header pattern. + excludes: A list of headers to exclude from the glob. + Return: + A list of headers discovered with excludes excluded. + """ + + # If we had python 3.5+, we could use the fancy new glob.glob. + # full_glob = os.path.join(prefix, rel_glob) + # full_srcs = glob.glob(full_glob, recursive=True) + + full_dirs = [prefix] + full_srcs = [] + + while full_dirs: + full_dir = full_dirs.pop(0) + items = sorted(os.listdir(full_dir)) + + for item in items: + full_item = os.path.join(full_dir, item) + + if os.path.isdir(full_item): + full_dirs.append(full_item) + continue + + if full_item in excludes: + continue + + if full_item.endswith('.h'): + full_srcs.append(full_item) + + return full_srcs + + +def find_out(verbose, module_dir, prefix, rel_glob, excludes, outs): + """Build a list of outputs for the genrule that creates kernel headers. + + This function scans for headers in the source tree and produces a list of + output (generated) headers. + + Args: + verbose: Set True to print progress messages. + module_dir: The root directory of the kernel source. + prefix: The prefix with in the kernel source tree to search for headers. + rel_glob: The pattern to use when matching headers under prefix. + excludes: A list of files to exclude from the glob. + outs: The list to populdate with the headers that will be generated. + Return: + The number of errors encountered. + """ + + # Turn prefix, which is relative to the soong module, to a full prefix that + # is relative to the Android source tree. + + full_prefix = os.path.join(module_dir, prefix) + + # Convert the list of excludes, which are relative to the soong module, to a + # set of excludes (for easy hashing), relative to the Android source tree. + + full_excludes = set() + + if excludes: + for exclude in excludes: + full_exclude = os.path.join(full_prefix, exclude) + full_excludes.add(full_exclude) + + # Glob those headers. + + full_srcs = glob_headers(full_prefix, rel_glob, full_excludes) + + # Now convert the file names, which are relative to the Android source tree, + # to be relative to the gen dir. This means stripping off the module prefix + # and the directory within this module. + + module_dir_sep = module_dir + os.sep + prefix_sep = prefix + os.sep + + if verbose: + print('find_out: module_dir_sep [%s]' % module_dir_sep) + print('find_out: prefix_sep [%s]' % prefix_sep) + + error_count = 0 + + for full_src in full_srcs: + if verbose: + print('find_out: full_src [%s]' % full_src) + + if not full_src.startswith(module_dir_sep): + print('error: expected %s to start with %s' % (full_src, module_dir_sep)) + error_count += 1 + continue + + local_src = full_src[len(module_dir_sep):] + + if verbose: + print('find_out: local_src [%s]' % local_src) + + if not local_src.startswith(prefix_sep): + print('error: expected %s to start with %s' % (local_src, prefix_sep)) + error_count += 1 + continue + + # After stripping the module directory and the prefix, we're left with the + # name of a header that we'll generate, relative to the base of of a the + # the include path. + + local_out = local_src[len(prefix_sep):] + + if verbose: + print('find_out: local_out [%s]' % local_out) + + outs.append(local_out) + + return error_count + +def scan_no_export_headers(verbose, module_dir, prefix): + """Scan include/uapi kbuild for no-export-headers + + This function processes the Kbuild file to scan for no-export files that + should not export to usr/include/uapi which is identified by adding + to the no-export-headers make variable. + + Args: + verbose: Set True to print progress messages. + module_dir: The root directory of the kernel source. + prefix: The prefix with in the kernel source tree to search for headers. + Return: + lists of no-export-headers. + """ + + no_export_headers_re = re.compile(r'no-export-headers\s*\+=\s*(\S+)') + header_re = re.compile(r'include/uapi/') + full_dirs_ = os.path.join(module_dir, prefix) + full_dirs = [full_dirs_] + + if verbose: + print('scan_no_export_headers: processing [%s]' % full_dirs) + + full_srcs = [] + no_export_headers_lists = [] + + while full_dirs: + full_dir = full_dirs.pop(0) + items = sorted(os.listdir(full_dir)) + + for item in items: + full_item = os.path.join(full_dir, item) + + if os.path.isdir(full_item): + full_dirs.append(full_item) + continue + + if (full_item.find('Kbuild') != -1): + full_srcs.append(full_item) + + for full_src in full_srcs: + with open(full_src, 'r') as f: + while True: + line = f.readline() + + if not line: + break + + line = line.rstrip() + + match = no_export_headers_re.match(line) + + if match: + if verbose: + print('scan_no_export_headers: matched [%s]' % line) + + if (match.group(1) == "kvm.h" or + match.group(1) == "kvm_para.h" or + match.group(1) == "a.out.h"): + continue + + (full_src_dir_name, full_src_base_name) = full_src.split('include/uapi/') + no_export_header_file_name = os.path.join(os.path.dirname(full_src_base_name),match.group(1)) + + if verbose: + print('scan_no_export_headers: no_export_header_file_name = ',no_export_header_file_name) + + no_export_headers_lists.append(no_export_header_file_name) + continue + + if verbose: + for x in no_export_headers_lists: + print('scan_no_export_headers: no_export_headers_lists [%s]' % x) + + return no_export_headers_lists + +def gen_blueprints( + verbose, header_arch, gen_dir, arch_asm_kbuild, asm_generic_kbuild, module_dir, + rel_arch_asm_kbuild, rel_asm_generic_kbuild, arch_include_uapi, techpack_include_uapi): + """Generate a blueprints file containing modules that invoke this script. + + This function generates a blueprints file that contains modules that + invoke this script to generate kernel headers. We generate the blueprints + file as needed, but we don't actually use the generated file. The blueprints + file that we generate ends up in the out directory, and we can use it to + detect if the checked-in version of the file (in the source directory) is out + of date. This pattern occurs in the Android source tree in several places. + + Args: + verbose: Set True to print progress messages. + header_arch: The arch for which to generate headers. + gen_dir: Where to place the generated files. + arch_asm_kbuild: The Kbuild file containing lists of headers to generate. + asm_generic_kbuild: The Kbuild file containing lists of mandatory headers. + module_dir: The root directory of the kernel source. + rel_arch_asm_kbuild: arch_asm_kbuild relative to module_dir. + Return: + The number of errors encountered. + """ + error_count = 0 + + # The old and new blueprints files. We generate the new one, but we need to + # refer to the old one in the modules that we generate. + old_gen_headers_bp = 'gen_headers_%s.bp' % header_arch + new_gen_headers_bp = os.path.join(gen_dir, old_gen_headers_bp) + + # Tools and tool files. + headers_install_sh = 'headers_install.sh' + kernel_headers_py = 'kernel_headers.py' + arm_syscall_tool = 'arch/arm/tools/syscallhdr.sh' + + # Sources + makefile = 'Makefile' + arm_syscall_tbl = 'arch/arm/tools/syscall.tbl' + rel_glob = '**/*.h' + generic_prefix = 'include/uapi' + arch_prefix = os.path.join('arch', header_arch, generic_prefix) + generic_src = os.path.join(generic_prefix, rel_glob) + arch_src = os.path.join(arch_prefix, rel_glob) + techpack_src = os.path.join('techpack/*',generic_prefix, '*',rel_glob) + + # Excluded sources, architecture specific. + exclude_srcs = [] + + if header_arch == "arm": + exclude_srcs = ['linux/a.out.h'] + + if header_arch == "arm64": + exclude_srcs = ['linux/a.out.h', 'linux/kvm_para.h'] + + no_export_headers_lists = scan_no_export_headers(verbose, module_dir, generic_prefix) + + for no_export_headers_list in no_export_headers_lists: + exclude_srcs.append(no_export_headers_list) + + if verbose: + for x in exclude_srcs: + print('gen_blueprints : exclude_srcs [%s]' % x) + + # Scan the arch_asm_kbuild file for files that need to be generated and those + # that are generic (i.e., need to be wrapped). + + (generated_list, generic_list, mandatory_list) = scan_arch_kbuild(verbose, + arch_asm_kbuild, asm_generic_kbuild, arch_include_uapi) + + generic_out = [] + error_count += find_out( + verbose, module_dir, generic_prefix, rel_glob, exclude_srcs, generic_out) + + arch_out = [] + error_count += find_out( + verbose, module_dir, arch_prefix, rel_glob, None, arch_out) + + techpack_out = [x.split('include/uapi/')[1] for x in techpack_include_uapi] + + if error_count != 0: + return error_count + + # Generate the blueprints file. + + if verbose: + print('gen_blueprints: generating %s' % new_gen_headers_bp) + + with open(new_gen_headers_bp, 'w') as f: + f.write('// ***** DO NOT EDIT *****\n') + f.write('// This file is generated by %s\n' % kernel_headers_py) + f.write('\n') + f.write('gen_headers_srcs_%s = [\n' % header_arch) + f.write(' "%s",\n' % rel_arch_asm_kbuild) + f.write(' "%s",\n' % rel_asm_generic_kbuild) + f.write(' "%s",\n' % makefile) + + if header_arch == "arm": + f.write(' "%s",\n' % arm_syscall_tbl) + + f.write(' "%s",\n' % generic_src) + f.write(' "%s",\n' % arch_src) + f.write(']\n') + f.write('\n') + + if exclude_srcs: + f.write('gen_headers_exclude_srcs_%s = [\n' % header_arch) + for h in exclude_srcs: + f.write(' "%s",\n' % os.path.join(generic_prefix, h)) + f.write(']\n') + f.write('\n') + + f.write('gen_headers_out_%s = [\n' % header_arch) + + if generated_list: + f.write('\n') + f.write(' // Matching generated-y:\n') + f.write('\n') + for h in generated_list: + f.write(' "asm/%s",\n' % h) + + if generic_list: + f.write('\n') + f.write(' // Matching generic-y:\n') + f.write('\n') + for h in generic_list: + f.write(' "asm/%s",\n' % h) + + if mandatory_list: + f.write('\n') + f.write(' // Matching mandatory-y:\n') + f.write('\n') + for h in mandatory_list: + f.write(' "asm/%s",\n' % h) + + if generic_out: + f.write('\n') + f.write(' // From %s\n' % generic_src) + f.write('\n') + for h in generic_out: + f.write(' "%s",\n' % h) + + if arch_out: + f.write('\n') + f.write(' // From %s\n' % arch_src) + f.write('\n') + for h in arch_out: + f.write(' "%s",\n' % h) + + if techpack_out: + f.write('\n') + f.write(' // From %s\n' % techpack_src) + f.write('\n') + for h in techpack_out: + f.write(' "%s",\n' % h) + + f.write(']\n') + f.write('\n') + + gen_blueprints_module_name = 'qti_generate_gen_headers_%s' % header_arch + + f.write('genrule {\n') + f.write(' // This module generates the gen_headers_.bp file\n') + f.write(' // (i.e., a new version of this file) so that it can be\n') + f.write(' // checked later to ensure that it matches the checked-\n') + f.write(' // in version (this file).\n') + f.write(' name: "%s",\n' % gen_blueprints_module_name) + f.write(' srcs: gen_headers_srcs_%s,\n' % header_arch) + if exclude_srcs: + f.write(' exclude_srcs: gen_headers_exclude_srcs_%s,\n' % header_arch) + + f.write(' tool_files: ["kernel_headers.py"],\n') + f.write(' cmd: "python3 $(location kernel_headers.py) " +\n') + f.write(' kernel_headers_verbose +\n') + f.write(' "--header_arch %s " +\n' % header_arch) + f.write(' "--gen_dir $(genDir) " +\n') + f.write(' "--arch_asm_kbuild $(location %s) " +\n' % rel_arch_asm_kbuild) + f.write(' "--arch_include_uapi $(locations %s) " +\n' % arch_src) + f.write(' "--asm_generic_kbuild $(location %s) " +\n' % rel_asm_generic_kbuild) + f.write(' "blueprints " +\n') + f.write(' "# $(in)",\n') + f.write(' out: ["gen_headers_%s.bp"],\n' % header_arch) + f.write('}\n') + f.write('\n') + + f.write('genrule {\n') + f.write(' name: "qti_generate_kernel_headers_%s",\n' % header_arch) + f.write(' tools: ["%s"],\n' % headers_install_sh) + f.write(' tool_files: [\n') + f.write(' "%s",\n' % kernel_headers_py) + + if header_arch == "arm": + f.write(' "%s",\n' % arm_syscall_tool) + + f.write(' ],\n') + f.write(' srcs: gen_headers_srcs_%s +[\n' % header_arch) + f.write(' "%s",\n' % old_gen_headers_bp) + f.write(' ":%s",\n' % gen_blueprints_module_name) + f.write(' ],\n') + + if exclude_srcs: + f.write(' exclude_srcs: gen_headers_exclude_srcs_%s,\n' % header_arch) + + f.write(' cmd: "python3 $(location %s) " +\n' % kernel_headers_py) + f.write(' kernel_headers_verbose +\n') + f.write(' "--header_arch %s " +\n' % header_arch) + f.write(' "--gen_dir $(genDir) " +\n') + f.write(' "--arch_asm_kbuild $(location %s) " +\n' % rel_arch_asm_kbuild) + f.write(' "--arch_include_uapi $(locations %s) " +\n' % arch_src) + f.write(' "--asm_generic_kbuild $(location %s) " +\n' % rel_asm_generic_kbuild) + f.write(' "headers " +\n') + f.write(' "--old_gen_headers_bp $(location %s) " +\n' % old_gen_headers_bp) + f.write(' "--new_gen_headers_bp $(location :%s) " +\n' % gen_blueprints_module_name) + f.write(' "--version_makefile $(location %s) " +\n' % makefile) + + if header_arch == "arm": + f.write(' "--arch_syscall_tool $(location %s) " +\n' % arm_syscall_tool) + f.write(' "--arch_syscall_tbl $(location %s) " +\n' % arm_syscall_tbl) + + f.write(' "--headers_install $(location %s) " +\n' % headers_install_sh) + f.write(' "--include_uapi $(locations %s)",\n' % generic_src) + f.write(' out: ["linux/version.h"] + gen_headers_out_%s,\n' % header_arch) + f.write('}\n') + + return 0 + +def parse_bp_for_headers(file_name, headers): + parsing_headers = False + pattern = re.compile("gen_headers_out_[a-zA-Z0-9]+\s*=\s*\[\s*") + with open(file_name, 'r') as f: + for line in f: + line = line.strip() + if pattern.match(line): + parsing_headers = True + continue + + if line.find("]") != -1 and parsing_headers: + break + + if not parsing_headers: + continue + + if line.find("//") == 0: + continue + + headers.add(line[1:-2]) + +def headers_diff(old_file, new_file): + old_headers = set() + new_headers = set() + diff_detected = False + + parse_bp_for_headers(old_file, old_headers) + parse_bp_for_headers(new_file, new_headers) + + diff = old_headers - new_headers + if len(diff): + diff_detected = True + print("Headers to remove:") + for x in diff: + print("\t{}".format(x)) + + diff = new_headers - old_headers + if len(diff): + diff_detected = True + print("Headers to add:") + for x in diff: + print("\t{}".format(x)) + + return diff_detected + +def gen_headers( + verbose, header_arch, gen_dir, arch_asm_kbuild, asm_generic_kbuild, module_dir, + old_gen_headers_bp, new_gen_headers_bp, version_makefile, + arch_syscall_tool, arch_syscall_tbl, headers_install, include_uapi, + arch_include_uapi, techpack_include_uapi): + """Generate the kernel headers. + + This script generates the version.h file, the arch-specific headers including + syscall-related generated files and wrappers around generic files, and uses + the headers_install tool to process other generic uapi and arch-specific uapi + files. + + Args: + verbose: Set True to print progress messages. + header_arch: The arch for which to generate headers. + gen_dir: Where to place the generated files. + arch_asm_kbuild: The Kbuild file containing lists of headers to generate. + asm_generic_kbuild: The Kbuild file containing mandatory headers. + module_dir: The root directory of the kernel source. + old_gen_headers_bp: The old gen_headers_.bp file to check. + new_gen_headers_bp: The new gen_headers_.bp file to check. + version_makefile: The kernel Makefile that contains version info. + arch_syscall_tool: The arch script that generates syscall headers. + arch_syscall_tbl: The arch script that defines syscall vectors. + headers_install: The headers_install tool to process input headers. + include_uapi: The list of include/uapi header files. + arch_include_uapi: The list of arch//include/uapi header files. + Return: + The number of errors encountered. + """ + + if headers_diff(old_gen_headers_bp, new_gen_headers_bp): + print('error: gen_headers blueprints file is out of date, suggested fix:') + print('#######Please add or remove the above mentioned headers from %s' % (old_gen_headers_bp)) + print('then re-run the build') + return 1 + + error_count = 0 + + if not gen_version_h(verbose, gen_dir, version_makefile): + error_count += 1 + + error_count += gen_arch_headers( + verbose, gen_dir, arch_asm_kbuild, asm_generic_kbuild, arch_syscall_tool, arch_syscall_tbl ,arch_include_uapi) + + uapi_include_prefix = os.path.join(module_dir, 'include', 'uapi') + os.sep + + arch_uapi_include_prefix = os.path.join( + module_dir, 'arch', header_arch, 'include', 'uapi') + os.sep + + for h in include_uapi: + if not run_headers_install( + verbose, gen_dir, headers_install, + uapi_include_prefix, h): + error_count += 1 + + for h in arch_include_uapi: + if not run_headers_install( + verbose, gen_dir, headers_install, + arch_uapi_include_prefix, h): + error_count += 1 + + for h in techpack_include_uapi: + techpack_uapi_include_prefix = os.path.join(h.split('/include/uapi')[0], 'include', 'uapi') + os.sep + if not run_headers_install( + verbose, gen_dir, headers_install, + techpack_uapi_include_prefix, h): + error_count += 1 + + return error_count + +def extract_techpack_uapi_headers(verbose, module_dir): + + """EXtract list of uapi headers from techpack/* directories. We need to export + these headers to userspace. + + Args: + verbose: Verbose option is provided to script + module_dir: Base directory + Returs: + List of uapi headers + """ + + techpack_subdir = [] + techpack_dir = os.path.join(module_dir,'techpack') + techpack_uapi = [] + techpack_uapi_sub = [] + + #get list of techpack directories under techpack/ + if os.path.isdir(techpack_dir): + items = sorted(os.listdir(techpack_dir)) + for x in items: + p = os.path.join(techpack_dir, x) + if os.path.isdir(p): + techpack_subdir.append(p) + + #Print list of subdirs obtained + if (verbose): + for x in techpack_subdir: + print(x) + + #For every subdirectory get list of .h files under include/uapi and append to techpack_uapi list + for x in techpack_subdir: + techpack_uapi_path = os.path.join(x, 'include/uapi') + if (os.path.isdir(techpack_uapi_path)): + techpack_uapi_sub = [] + find_out(verbose, x, 'include/uapi', '**/*.h', None, techpack_uapi_sub) + tmp = [os.path.join(techpack_uapi_path, y) for y in techpack_uapi_sub] + techpack_uapi = techpack_uapi + tmp + + if (verbose): + for x in techpack_uapi: + print(x) + + return techpack_uapi + +def main(): + """Parse command line arguments and perform top level control.""" + + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + # Arguments that apply to every invocation of this script. + + parser.add_argument( + '--verbose', + action='store_true', + help='Print output that describes the workings of this script.') + parser.add_argument( + '--header_arch', + required=True, + help='The arch for which to generate headers.') + parser.add_argument( + '--gen_dir', + required=True, + help='Where to place the generated files.') + parser.add_argument( + '--arch_asm_kbuild', + required=True, + help='The Kbuild file containing lists of headers to generate.') + parser.add_argument( + '--asm_generic_kbuild', + required=True, + help='The Kbuild file containing lists of mandatory headers.') + parser.add_argument( + '--arch_include_uapi', + required=True, + nargs='*', + help='The list of arch//include/uapi header files.') + + # The modes. + + subparsers = parser.add_subparsers( + dest='mode', + help='Select mode') + parser_blueprints = subparsers.add_parser( + 'blueprints', + help='Generate the gen_headers_.bp file.') + parser_headers = subparsers.add_parser( + 'headers', + help='Check blueprints, then generate kernel headers.') + + # Arguments that apply to headers mode. + + parser_headers.add_argument( + '--old_gen_headers_bp', + required=True, + help='The old gen_headers_.bp file to check.') + parser_headers.add_argument( + '--new_gen_headers_bp', + required=True, + help='The new gen_headers_.bp file to check.') + parser_headers.add_argument( + '--version_makefile', + required=True, + help='The kernel Makefile that contains version info.') + parser_headers.add_argument( + '--arch_syscall_tool', + help='The arch script that generates syscall headers, if applicable.') + parser_headers.add_argument( + '--arch_syscall_tbl', + help='The arch script that defines syscall vectors, if applicable.') + parser_headers.add_argument( + '--headers_install', + required=True, + help='The headers_install tool to process input headers.') + parser_headers.add_argument( + '--include_uapi', + required=True, + nargs='*', + help='The list of include/uapi header files.') + + args = parser.parse_args() + + if args.verbose: + print('mode [%s]' % args.mode) + print('header_arch [%s]' % args.header_arch) + print('gen_dir [%s]' % args.gen_dir) + print('arch_asm_kbuild [%s]' % args.arch_asm_kbuild) + print('asm_generic_kbuild [%s]' % args.asm_generic_kbuild) + + # Extract the module_dir from args.arch_asm_kbuild and rel_arch_asm_kbuild. + + rel_arch_asm_kbuild = os.path.join( + 'arch', args.header_arch, 'include/uapi/asm/Kbuild') + + suffix = os.sep + rel_arch_asm_kbuild + + if not args.arch_asm_kbuild.endswith(suffix): + print('error: expected %s to end with %s' % (args.arch_asm_kbuild, suffix)) + return 1 + + module_dir = args.arch_asm_kbuild[:-len(suffix)] + + rel_asm_generic_kbuild = os.path.join('include/uapi/asm-generic', os.path.basename(args.asm_generic_kbuild)) + + + if args.verbose: + print('module_dir [%s]' % module_dir) + + techpack_include_uapi = [] + + + if args.mode == 'blueprints': + return gen_blueprints( + args.verbose, args.header_arch, args.gen_dir, args.arch_asm_kbuild, + args.asm_generic_kbuild, module_dir, rel_arch_asm_kbuild, rel_asm_generic_kbuild, args.arch_include_uapi, techpack_include_uapi) + + if args.mode == 'headers': + if args.verbose: + print('old_gen_headers_bp [%s]' % args.old_gen_headers_bp) + print('new_gen_headers_bp [%s]' % args.new_gen_headers_bp) + print('version_makefile [%s]' % args.version_makefile) + print('arch_syscall_tool [%s]' % args.arch_syscall_tool) + print('arch_syscall_tbl [%s]' % args.arch_syscall_tbl) + print('headers_install [%s]' % args.headers_install) + + return gen_headers( + args.verbose, args.header_arch, args.gen_dir, args.arch_asm_kbuild, + args.asm_generic_kbuild, module_dir, args.old_gen_headers_bp, args.new_gen_headers_bp, + args.version_makefile, args.arch_syscall_tool, args.arch_syscall_tbl, + args.headers_install, args.include_uapi, args.arch_include_uapi, techpack_include_uapi) + + print('error: unknown mode: %s' % args.mode) + return 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/lib/bitmap.c b/lib/bitmap.c index 0b66f0e5eb6bb172ae240fe59dd1eec0d9065493..a44b20a829dd4e0db808b1c03a386d4a4514cfe5 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -1212,3 +1213,22 @@ void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int n } EXPORT_SYMBOL(bitmap_copy_le); #endif + +unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags) +{ + return kmalloc_array(BITS_TO_LONGS(nbits), sizeof(unsigned long), + flags); +} +EXPORT_SYMBOL(bitmap_alloc); + +unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags) +{ + return bitmap_alloc(nbits, flags | __GFP_ZERO); +} +EXPORT_SYMBOL(bitmap_zalloc); + +void bitmap_free(const unsigned long *bitmap) +{ + kfree(bitmap); +} +EXPORT_SYMBOL(bitmap_free); diff --git a/lib/devres.c b/lib/devres.c index cb1464c411a2b4fa88778343bf33208ccd8dae76..38912892053c027d9150aa147cd61d93b4795767 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -131,7 +131,8 @@ EXPORT_SYMBOL(devm_iounmap); * if (IS_ERR(base)) * return PTR_ERR(base); */ -void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res) +void __iomem *devm_ioremap_resource(struct device *dev, + const struct resource *res) { resource_size_t size; const char *name; diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 8971370bfb1619eb9d3acd332045129542092ee0..4435bec55fb5927601be28a6eb9539fefbbf8714 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -435,6 +435,7 @@ void debug_dma_dump_mappings(struct device *dev) } spin_unlock_irqrestore(&bucket->lock, flags); + cond_resched(); } } EXPORT_SYMBOL(debug_dma_dump_mappings); diff --git a/lib/kfifo.c b/lib/kfifo.c index 90ba1eb1df06e5283a2dad9132b53346f5106812..a94227c5555109bfcfc14ab9a750cd0761680470 100644 --- a/lib/kfifo.c +++ b/lib/kfifo.c @@ -82,7 +82,8 @@ int __kfifo_init(struct __kfifo *fifo, void *buffer, { size /= esize; - size = roundup_pow_of_two(size); + if (!is_power_of_2(size)) + size = rounddown_pow_of_two(size); fifo->in = 0; fifo->out = 0; diff --git a/lib/raid6/unroll.awk b/lib/raid6/unroll.awk index c6aa03631df86d7837ea56d28d6059799803ef5b..0809805a7e231809387902b825fb2d89e7c43bd0 100644 --- a/lib/raid6/unroll.awk +++ b/lib/raid6/unroll.awk @@ -13,7 +13,7 @@ BEGIN { for (i = 0; i < rep; ++i) { tmp = $0 gsub(/\$\$/, i, tmp) - gsub(/\$\#/, n, tmp) + gsub(/\$#/, n, tmp) gsub(/\$\*/, "$", tmp) print tmp } diff --git a/lib/scatterlist.c b/lib/scatterlist.c index a854cc39f084f735b4d4f88880b548d7625dbe93..ef8c14a56d0a74584d432a63a06817eb334b622d 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -317,7 +317,7 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, if (prv) table->nents = ++table->orig_nents; - return -ENOMEM; + return -ENOMEM; } sg_init_table(sg, alloc_size); diff --git a/lib/stackdepot.c b/lib/stackdepot.c index f87d138e96724a43d219231bb98d6b1a863a0f0a..759ff419fe61f886345832899f7d2b00db98a2c7 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -92,15 +92,19 @@ static bool init_stack_slab(void **prealloc) return true; if (stack_slabs[depot_index] == NULL) { stack_slabs[depot_index] = *prealloc; + *prealloc = NULL; } else { - stack_slabs[depot_index + 1] = *prealloc; + /* If this is the last depot slab, do not touch the next one. */ + if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) { + stack_slabs[depot_index + 1] = *prealloc; + *prealloc = NULL; + } /* * This smp_store_release pairs with smp_load_acquire() from * |next_slab_inited| above and in depot_save_stack(). */ smp_store_release(&next_slab_inited, 1); } - *prealloc = NULL; return true; } diff --git a/lib/test_kasan.c b/lib/test_kasan.c index 7cde4c1e859a3e4284cefd90205cab844a6ca2a7..c0b65e0947bfa0be64c3eaf9a00a64ec822011a2 100644 --- a/lib/test_kasan.c +++ b/lib/test_kasan.c @@ -125,6 +125,7 @@ static noinline void __init kmalloc_oob_krealloc_more(void) if (!ptr1 || !ptr2) { pr_err("Allocation failed\n"); kfree(ptr1); + kfree(ptr2); return; } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index c319cd97a33d83f846dda4f2b908bb6c91455b0e..fad4a0ca903c4a60f55e40cdf2bb35c7acd7f374 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2096,7 +2096,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) unsigned long flags; pgoff_t end; - VM_BUG_ON_PAGE(is_huge_zero_page(page), page); + VM_BUG_ON_PAGE(is_huge_zero_page(head), head); VM_BUG_ON_PAGE(!PageLocked(page), page); VM_BUG_ON_PAGE(!PageSwapBacked(page), page); VM_BUG_ON_PAGE(!PageCompound(page), page); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0ec91c8270f3e9357c2be03f65c33ea687e041f9..6fb0a4d64cc389db6f621289fe82ae39330ef590 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5755,6 +5755,10 @@ void mem_cgroup_sk_alloc(struct sock *sk) return; } + /* Do not associate the sock with unrelated interrupted task's memcg. */ + if (in_interrupt()) + return; + rcu_read_lock(); memcg = mem_cgroup_from_task(current); if (memcg == root_mem_cgroup) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index beb7c334c1a46b62dc56654ac24252ab8311d4aa..af2d00035fcc017c4346065788a0dc477ff91690 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2762,6 +2762,9 @@ int mpol_parse_str(char *str, struct mempolicy **mpol) char *flags = strchr(str, '='); int err = 1; + if (flags) + *flags++ = '\0'; /* terminate mode string */ + if (nodelist) { /* NUL-terminate mode or flags string */ *nodelist++ = '\0'; @@ -2772,9 +2775,6 @@ int mpol_parse_str(char *str, struct mempolicy **mpol) } else nodes_clear(nodes); - if (flags) - *flags++ = '\0'; /* terminate mode string */ - for (mode = 0; mode < MPOL_MAX; mode++) { if (!strcmp(str, policy_modes[mode])) { break; diff --git a/mm/mmap.c b/mm/mmap.c index 206f00d160b31b94453f3ab04192c34bc1374bb2..ddfff14bb63fc0cb50f6ee07c09e9bc1dcf0833b 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -88,12 +88,6 @@ static void unmap_region(struct mm_struct *mm, * MAP_PRIVATE r: (no) no r: (yes) yes r: (no) yes r: (no) yes * w: (no) no w: (no) no w: (copy) copy w: (no) no * x: (no) no x: (no) yes x: (no) yes x: (yes) yes - * - * On arm64, PROT_EXEC has the following behaviour for both MAP_SHARED and - * MAP_PRIVATE: - * r: (no) no - * w: (no) no - * x: (yes) yes */ pgprot_t protection_map[16] = { __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, diff --git a/mm/page-writeback.c b/mm/page-writeback.c index f683f30e964c384b7436a42457d16694fb914e05..21a12577b287a6321faff0c72ecfca23312c6fc2 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -200,11 +200,11 @@ static void wb_min_max_ratio(struct bdi_writeback *wb, if (this_bw < tot_bw) { if (min) { min *= this_bw; - do_div(min, tot_bw); + min = div64_ul(min, tot_bw); } if (max < 100) { max *= this_bw; - do_div(max, tot_bw); + max = div64_ul(max, tot_bw); } } diff --git a/mm/page_io.c b/mm/page_io.c index efe6fd67cb0ee53b80ee557dc488d2fba22dd128..83e5613082cff45039c7d6b10776230879837a35 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -337,10 +338,19 @@ int swap_readpage(struct page *page) struct bio *bio; int ret = 0; struct swap_info_struct *sis = page_swap_info(page); + unsigned long pflags; VM_BUG_ON_PAGE(!PageSwapCache(page), page); VM_BUG_ON_PAGE(!PageLocked(page), page); VM_BUG_ON_PAGE(PageUptodate(page), page); + + /* + * Count submission time as memory stall. When the device is congested, + * or the submitting cgroup IO-throttled, submission can be a + * significant part of overall IO time. + */ + psi_memstall_enter(&pflags); + if (frontswap_load(page) == 0) { SetPageUptodate(page); unlock_page(page); @@ -354,7 +364,7 @@ int swap_readpage(struct page *page) ret = mapping->a_ops->readpage(swap_file, page); if (!ret) count_vm_event(PSWPIN); - return ret; + goto out; } ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); @@ -365,7 +375,7 @@ int swap_readpage(struct page *page) } count_vm_event(PSWPIN); - return 0; + goto out; } ret = 0; @@ -379,6 +389,7 @@ int swap_readpage(struct page *page) count_vm_event(PSWPIN); submit_bio(bio); out: + psi_memstall_leave(&pflags); return ret; } diff --git a/mm/shmem.c b/mm/shmem.c index f4af71c39674deb0696636c093d46cea83c1f5a7..f42d87319d6d031eb57f08a94d36a5bec0d0e180 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2695,7 +2695,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, } shmem_falloc.waitq = &shmem_falloc_waitq; - shmem_falloc.start = unmap_start >> PAGE_SHIFT; + shmem_falloc.start = (u64)unmap_start >> PAGE_SHIFT; shmem_falloc.next = (unmap_end + 1) >> PAGE_SHIFT; spin_lock(&inode->i_lock); inode->i_private = &shmem_falloc; diff --git a/mm/slub.c b/mm/slub.c index fc12c5b1637caa941faeb31c60f83b83254b07fa..8ea555d24ec8326d67696c3f34cbdadaab8b1703 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3127,6 +3127,15 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size, void *object = c->freelist; if (unlikely(!object)) { + /* + * We may have removed an object from c->freelist using + * the fastpath in the previous iteration; in that case, + * c->tid has not been bumped yet. + * Since ___slab_alloc() may reenable interrupts while + * allocating memory, we should bump c->tid now. + */ + c->tid = next_tid(c->tid); + /* * Invoking slow path likely have side-effect * of re-populating per CPU c->freelist diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index b0ca307369504061e7a0776f4af88d4409daf19d..ffe8c4341ec9bc2bf9b193a009c3c4cf9ffb6da6 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -2158,6 +2158,11 @@ int zs_page_migrate(struct address_space *mapping, struct page *newpage, zs_pool_dec_isolated(pool); } + if (page_zone(newpage) != page_zone(page)) { + dec_zone_page_state(page, NR_ZSPAGES); + inc_zone_page_state(newpage, NR_ZSPAGES); + } + reset_page(page); put_page(page); page = newpage; diff --git a/net/6lowpan/nhc.c b/net/6lowpan/nhc.c index 7008d53e455c5254db5879bb044b0a4b6d706775..e61679bf09085f291c75bbca67939cd747f4e28e 100644 --- a/net/6lowpan/nhc.c +++ b/net/6lowpan/nhc.c @@ -18,7 +18,7 @@ #include "nhc.h" static struct rb_root rb_root = RB_ROOT; -static struct lowpan_nhc *lowpan_nexthdr_nhcs[NEXTHDR_MAX]; +static struct lowpan_nhc *lowpan_nexthdr_nhcs[NEXTHDR_MAX + 1]; static DEFINE_SPINLOCK(lowpan_nhc_lock); static int lowpan_nhc_insert(struct lowpan_nhc *nhc) diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index cc15579780669a613165336387a3f8eabc669dec..ecdfeaafba9c7a274320e1c5f2fa1b3144654bc5 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -109,6 +109,7 @@ int vlan_check_real_dev(struct net_device *real_dev, void vlan_setup(struct net_device *dev); int register_vlan_dev(struct net_device *dev); void unregister_vlan_dev(struct net_device *dev, struct list_head *head); +void vlan_dev_uninit(struct net_device *dev); bool vlan_dev_inherit_address(struct net_device *dev, struct net_device *real_dev); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index d06d15db3232ef106ba3e4781925edcda070cca6..892929d43898190e3ab52fa62e6d77d1d2720ced 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -610,7 +610,8 @@ static int vlan_dev_init(struct net_device *dev) return 0; } -static void vlan_dev_uninit(struct net_device *dev) +/* Note: this function might be called multiple times for the same device. */ +void vlan_dev_uninit(struct net_device *dev) { struct vlan_priority_tci_mapping *pm; struct vlan_dev_priv *vlan = vlan_dev_priv(dev); diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 1270207f3d7c9dd6fde0e1f7839acfe18a4d82c9..214cc068ffc2edade56783df6a2f15891fe7cfaa 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -92,11 +92,13 @@ static int vlan_changelink(struct net_device *dev, struct ifla_vlan_flags *flags; struct ifla_vlan_qos_mapping *m; struct nlattr *attr; - int rem; + int rem, err; if (data[IFLA_VLAN_FLAGS]) { flags = nla_data(data[IFLA_VLAN_FLAGS]); - vlan_dev_change_flags(dev, flags->flags, flags->mask); + err = vlan_dev_change_flags(dev, flags->flags, flags->mask); + if (err) + return err; } if (data[IFLA_VLAN_INGRESS_QOS]) { nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) { @@ -107,7 +109,9 @@ static int vlan_changelink(struct net_device *dev, if (data[IFLA_VLAN_EGRESS_QOS]) { nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) { m = nla_data(attr); - vlan_dev_set_egress_priority(dev, m->from, m->to); + err = vlan_dev_set_egress_priority(dev, m->from, m->to); + if (err) + return err; } } return 0; @@ -153,10 +157,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev, return -EINVAL; err = vlan_changelink(dev, tb, data); - if (err < 0) - return err; - - return register_vlan_dev(dev); + if (!err) + err = register_vlan_dev(dev); + if (err) + vlan_dev_uninit(dev); + return err; } static inline size_t vlan_qos_map_size(unsigned int n) diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 8ad3ec2610b6499b92b2f3bc97ac02d2d043dd45..b9e85a4751a6bdb7b96300cddf6c47b189230e34 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -879,15 +879,24 @@ static struct notifier_block aarp_notifier = { static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; -void __init aarp_proto_init(void) +int __init aarp_proto_init(void) { + int rc; + aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); - if (!aarp_dl) + if (!aarp_dl) { printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); + return -ENOMEM; + } setup_timer(&aarp_timer, aarp_expire_timeout, 0); aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; add_timer(&aarp_timer); - register_netdevice_notifier(&aarp_notifier); + rc = register_netdevice_notifier(&aarp_notifier); + if (rc) { + del_timer_sync(&aarp_timer); + unregister_snap_client(aarp_dl); + } + return rc; } /* Remove the AARP entries associated with a device. */ diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index d74092cc639a2071bcf5d820f138e0dc1880dba7..93209c009df58f24d62a629050f75e98a0bda888 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1911,9 +1911,6 @@ static unsigned char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B }; EXPORT_SYMBOL(atrtr_get_dev); EXPORT_SYMBOL(atalk_find_dev_addr); -static const char atalk_err_snap[] __initconst = - KERN_CRIT "Unable to register DDP with SNAP.\n"; - /* Called by proto.c on kernel start up */ static int __init atalk_init(void) { @@ -1928,17 +1925,23 @@ static int __init atalk_init(void) goto out_proto; ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); - if (!ddp_dl) - printk(atalk_err_snap); + if (!ddp_dl) { + pr_crit("Unable to register DDP with SNAP.\n"); + rc = -ENOMEM; + goto out_sock; + } dev_add_pack(<alk_packet_type); dev_add_pack(&ppptalk_packet_type); rc = register_netdevice_notifier(&ddp_notifier); if (rc) - goto out_sock; + goto out_snap; + + rc = aarp_proto_init(); + if (rc) + goto out_dev; - aarp_proto_init(); rc = atalk_proc_init(); if (rc) goto out_aarp; @@ -1952,11 +1955,13 @@ static int __init atalk_init(void) atalk_proc_exit(); out_aarp: aarp_cleanup_module(); +out_dev: unregister_netdevice_notifier(&ddp_notifier); -out_sock: +out_snap: dev_remove_pack(&ppptalk_packet_type); dev_remove_pack(<alk_packet_type); unregister_snap_client(ddp_dl); +out_sock: sock_unregister(PF_APPLETALK); out_proto: proto_unregister(&ddp_proto); diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 780700fcbe63eb7f3811559f2d9cfe6546847c25..2b663622bdb450f47d9112980fbd85479f53e7c5 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -149,7 +150,7 @@ static void batadv_iv_ogm_orig_free(struct batadv_orig_node *orig_node) * Return: 0 on success, a negative error code otherwise. */ static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node, - int max_if_num) + unsigned int max_if_num) { void *data_ptr; size_t old_size; @@ -193,7 +194,8 @@ static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node, */ static void batadv_iv_ogm_drop_bcast_own_entry(struct batadv_orig_node *orig_node, - int max_if_num, int del_if_num) + unsigned int max_if_num, + unsigned int del_if_num) { size_t chunk_size; size_t if_offset; @@ -231,7 +233,8 @@ batadv_iv_ogm_drop_bcast_own_entry(struct batadv_orig_node *orig_node, */ static void batadv_iv_ogm_drop_bcast_own_sum_entry(struct batadv_orig_node *orig_node, - int max_if_num, int del_if_num) + unsigned int max_if_num, + unsigned int del_if_num) { size_t if_offset; void *data_ptr; @@ -268,7 +271,8 @@ batadv_iv_ogm_drop_bcast_own_sum_entry(struct batadv_orig_node *orig_node, * Return: 0 on success, a negative error code otherwise. */ static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node, - int max_if_num, int del_if_num) + unsigned int max_if_num, + unsigned int del_if_num) { spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); @@ -302,7 +306,8 @@ static struct batadv_orig_node * batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr) { struct batadv_orig_node *orig_node; - int size, hash_added; + int hash_added; + size_t size; orig_node = batadv_orig_hash_find(bat_priv, addr); if (orig_node) @@ -366,14 +371,18 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) unsigned char *ogm_buff; u32 random_seqno; + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + /* randomize initial seqno to avoid collision */ get_random_bytes(&random_seqno, sizeof(random_seqno)); atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno); hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN; ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC); - if (!ogm_buff) + if (!ogm_buff) { + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); return -ENOMEM; + } hard_iface->bat_iv.ogm_buff = ogm_buff; @@ -385,35 +394,59 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) batadv_ogm_packet->reserved = 0; batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); + return 0; } static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) { + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + kfree(hard_iface->bat_iv.ogm_buff); hard_iface->bat_iv.ogm_buff = NULL; + + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); } static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) { struct batadv_ogm_packet *batadv_ogm_packet; - unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; + void *ogm_buff; - batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + + ogm_buff = hard_iface->bat_iv.ogm_buff; + if (!ogm_buff) + goto unlock; + + batadv_ogm_packet = ogm_buff; ether_addr_copy(batadv_ogm_packet->orig, hard_iface->net_dev->dev_addr); ether_addr_copy(batadv_ogm_packet->prev_sender, hard_iface->net_dev->dev_addr); + +unlock: + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); } static void batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) { struct batadv_ogm_packet *batadv_ogm_packet; - unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; + void *ogm_buff; - batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + + ogm_buff = hard_iface->bat_iv.ogm_buff; + if (!ogm_buff) + goto unlock; + + batadv_ogm_packet = ogm_buff; batadv_ogm_packet->ttl = BATADV_TTL; + +unlock: + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); } /* when do we schedule our own ogm to be sent */ @@ -898,7 +931,7 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface) u32 i; size_t word_index; u8 *w; - int if_num; + unsigned int if_num; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -919,7 +952,11 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface) } } -static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) +/** + * batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer + * @hard_iface: interface whose ogm buffer should be transmitted + */ +static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff; @@ -930,8 +967,10 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) u16 tvlv_len = 0; unsigned long send_time; - if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) || - (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)) + lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex); + + /* interface already disabled by batadv_iv_ogm_iface_disable */ + if (!*ogm_buff) return; /* the interface gets activated here to avoid race conditions between @@ -1000,6 +1039,17 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) batadv_hardif_put(primary_if); } +static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) +{ + if (hard_iface->if_status == BATADV_IF_NOT_IN_USE || + hard_iface->if_status == BATADV_IF_TO_BE_REMOVED) + return; + + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + batadv_iv_ogm_schedule_buff(hard_iface); + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); +} + /** * batadv_iv_ogm_orig_update - use OGM to update corresponding data in an * originator @@ -1028,7 +1078,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, struct batadv_neigh_node *tmp_neigh_node = NULL; struct batadv_neigh_node *router = NULL; struct batadv_orig_node *orig_node_tmp; - int if_num; + unsigned int if_num; u8 sum_orig, sum_neigh; u8 *neigh_addr; u8 tq_avg; @@ -1186,7 +1236,7 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, u8 total_count; u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; - int if_num; + unsigned int if_num; unsigned int tq_asym_penalty, inv_asym_penalty; unsigned int combined_tq; unsigned int tq_iface_penalty; @@ -1227,7 +1277,7 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, orig_node->last_seen = jiffies; /* find packet count of corresponding one hop neighbor */ - spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); + spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock); if_num = if_incoming->if_num; orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num]; neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing); @@ -1237,7 +1287,7 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, } else { neigh_rq_count = 0; } - spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); + spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock); /* pay attention to not get a value bigger than 100 % */ if (orig_eq_count > neigh_rq_count) @@ -1705,9 +1755,9 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, if (is_my_orig) { unsigned long *word; - int offset; + size_t offset; s32 bit_pos; - s16 if_num; + unsigned int if_num; u8 *weight; orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv, @@ -2473,12 +2523,22 @@ batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1, return ret; } -static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface) +static void batadv_iv_iface_enabled(struct batadv_hard_iface *hard_iface) { /* begin scheduling originator messages on that interface */ batadv_iv_ogm_schedule(hard_iface); } +/** + * batadv_iv_init_sel_class - initialize GW selection class + * @bat_priv: the bat priv with all the soft interface information + */ +static void batadv_iv_init_sel_class(struct batadv_priv *bat_priv) +{ + /* set default TQ difference threshold to 20 */ + atomic_set(&bat_priv->gw.sel_class, 20); +} + static struct batadv_gw_node * batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv) { @@ -2803,8 +2863,8 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb, static struct batadv_algo_ops batadv_batman_iv __read_mostly = { .name = "BATMAN_IV", .iface = { - .activate = batadv_iv_iface_activate, .enable = batadv_iv_ogm_iface_enable, + .enabled = batadv_iv_iface_enabled, .disable = batadv_iv_ogm_iface_disable, .update_mac = batadv_iv_ogm_iface_update_mac, .primary_set = batadv_iv_ogm_primary_iface_set, @@ -2827,6 +2887,7 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = { .del_if = batadv_iv_ogm_orig_del_if, }, .gw = { + .init_sel_class = batadv_iv_init_sel_class, .get_best_gw_node = batadv_iv_gw_get_best_gw_node, .is_eligible = batadv_iv_gw_is_eligible, #ifdef CONFIG_BATMAN_ADV_DEBUGFS diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 4348118e7eac96a2f2e874e1e65f4da4affd96ee..18fa602e5fc6176e81ae5541ed7b7894e482daae 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c @@ -19,7 +19,6 @@ #include "main.h" #include -#include #include #include #include @@ -623,11 +622,11 @@ static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1, int ret = 0; ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); - if (WARN_ON(!ifinfo1)) + if (!ifinfo1) goto err_ifinfo1; ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); - if (WARN_ON(!ifinfo2)) + if (!ifinfo2) goto err_ifinfo2; ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput; @@ -649,11 +648,11 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, bool ret = false; ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); - if (WARN_ON(!ifinfo1)) + if (!ifinfo1) goto err_ifinfo1; ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); - if (WARN_ON(!ifinfo2)) + if (!ifinfo2) goto err_ifinfo2; threshold = ifinfo1->bat_v.throughput / 4; @@ -668,6 +667,16 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, return ret; } +/** + * batadv_v_init_sel_class - initialize GW selection class + * @bat_priv: the bat priv with all the soft interface information + */ +static void batadv_v_init_sel_class(struct batadv_priv *bat_priv) +{ + /* set default throughput difference threshold to 5Mbps */ + atomic_set(&bat_priv->gw.sel_class, 50); +} + static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv, char *buff, size_t count) { @@ -805,7 +814,7 @@ static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv, } orig_gw = batadv_gw_node_get(bat_priv, orig_node); - if (!orig_node) + if (!orig_gw) goto out; if (batadv_v_gw_throughput_get(orig_gw, &orig_throughput) < 0) @@ -1054,6 +1063,7 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = { .dump = batadv_v_orig_dump, }, .gw = { + .init_sel_class = batadv_v_init_sel_class, .store_sel_class = batadv_v_store_sel_class, .show_sel_class = batadv_v_show_sel_class, .get_best_gw_node = batadv_v_gw_get_best_gw_node, @@ -1094,9 +1104,6 @@ int batadv_v_mesh_init(struct batadv_priv *bat_priv) if (ret < 0) return ret; - /* set default throughput difference threshold to 5Mbps */ - atomic_set(&bat_priv->gw.sel_class, 50); - return 0; } diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index 5d79004de25c9f11ccc229632c55b262b571e899..62df763b2aae5fd37b62ffd754eabaa6f56de02f 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c @@ -19,6 +19,7 @@ #include "main.h" #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -100,8 +102,12 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) */ return 0; } - if (!ret) - return sinfo.expected_throughput / 100; + if (ret) + goto default_throughput; + if (!(sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))) + goto default_throughput; + + return sinfo.expected_throughput / 100; } /* unsupported WiFi driver version */ @@ -185,6 +191,7 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh) struct sk_buff *skb; int probe_len, i; int elp_skb_len; + void *tmp; /* this probing routine is for Wifi neighbours only */ if (!batadv_is_wifi_netdev(hard_iface->net_dev)) @@ -216,7 +223,8 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh) * the packet to be exactly of that size to make the link * throughput estimation effective. */ - skb_put(skb, probe_len - hard_iface->bat_v.elp_skb->len); + tmp = skb_put(skb, probe_len - hard_iface->bat_v.elp_skb->len); + memset(tmp, 0, probe_len - hard_iface->bat_v.elp_skb->len); batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "Sending unicast (probe) ELP packet on interface %s to %pM\n", @@ -327,21 +335,23 @@ static void batadv_v_elp_periodic_work(struct work_struct *work) */ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface) { + static const size_t tvlv_padding = sizeof(__be32); struct batadv_elp_packet *elp_packet; unsigned char *elp_buff; u32 random_seqno; size_t size; int res = -ENOMEM; - size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN; + size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN + tvlv_padding; hard_iface->bat_v.elp_skb = dev_alloc_skb(size); if (!hard_iface->bat_v.elp_skb) goto out; skb_reserve(hard_iface->bat_v.elp_skb, ETH_HLEN + NET_IP_ALIGN); - elp_buff = skb_put(hard_iface->bat_v.elp_skb, BATADV_ELP_HLEN); + elp_buff = skb_put(hard_iface->bat_v.elp_skb, + BATADV_ELP_HLEN + tvlv_padding); elp_packet = (struct batadv_elp_packet *)elp_buff; - memset(elp_packet, 0, BATADV_ELP_HLEN); + memset(elp_packet, 0, BATADV_ELP_HLEN + tvlv_padding); elp_packet->packet_type = BATADV_ELP; elp_packet->version = BATADV_COMPAT_VERSION; diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index f435435b447e09e1d9aec773134d244104577d92..b0cae59bd327c3443c15e3053c16dec1ca1f3916 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -127,22 +129,19 @@ static void batadv_v_ogm_send_to_if(struct sk_buff *skb, } /** - * batadv_v_ogm_send - periodic worker broadcasting the own OGM - * @work: work queue item + * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM + * @bat_priv: the bat priv with all the soft interface information */ -static void batadv_v_ogm_send(struct work_struct *work) +static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv) { struct batadv_hard_iface *hard_iface; - struct batadv_priv_bat_v *bat_v; - struct batadv_priv *bat_priv; struct batadv_ogm2_packet *ogm_packet; struct sk_buff *skb, *skb_tmp; unsigned char *ogm_buff, *pkt_buff; int ogm_buff_len; u16 tvlv_len = 0; - bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); - bat_priv = container_of(bat_v, struct batadv_priv, bat_v); + lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex); if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) goto out; @@ -209,6 +208,23 @@ static void batadv_v_ogm_send(struct work_struct *work) return; } +/** + * batadv_v_ogm_send() - periodic worker broadcasting the own OGM + * @work: work queue item + */ +static void batadv_v_ogm_send(struct work_struct *work) +{ + struct batadv_priv_bat_v *bat_v; + struct batadv_priv *bat_priv; + + bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); + bat_priv = container_of(bat_v, struct batadv_priv, bat_v); + + mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); + batadv_v_ogm_send_softif(bat_priv); + mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); +} + /** * batadv_v_ogm_iface_enable - prepare an interface for B.A.T.M.A.N. V * @hard_iface: the interface to prepare @@ -235,11 +251,15 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface) struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface); struct batadv_ogm2_packet *ogm_packet; + mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); if (!bat_priv->bat_v.ogm_buff) - return; + goto unlock; ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff; ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr); + +unlock: + mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); } /** @@ -827,6 +847,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv) atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno); INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send); + mutex_init(&bat_priv->bat_v.ogm_buff_mutex); + return 0; } @@ -838,7 +860,11 @@ void batadv_v_ogm_free(struct batadv_priv *bat_priv) { cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq); + mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); + kfree(bat_priv->bat_v.ogm_buff); bat_priv->bat_v.ogm_buff = NULL; bat_priv->bat_v.ogm_buff_len = 0; + + mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); } diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index b4ffba7dd58331bcba72e045cbe5b63d99c405f1..e0ab277db5036bad4bd00a4706c741c94099ace6 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@ -18,6 +18,7 @@ #include "debugfs.h" #include "main.h" +#include #include #include #include @@ -339,6 +340,25 @@ int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface) return -ENOMEM; } +/** + * batadv_debugfs_rename_hardif() - Fix debugfs path for renamed hardif + * @hard_iface: hard interface which was renamed + */ +void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface) +{ + const char *name = hard_iface->net_dev->name; + struct dentry *dir; + struct dentry *d; + + dir = hard_iface->debug_dir; + if (!dir) + return; + + d = debugfs_rename(dir->d_parent, dir, dir->d_parent, name); + if (!d) + pr_err("Can't rename debugfs dir to %s\n", name); +} + /** * batadv_debugfs_del_hardif - delete the base directory for a hard interface * in debugfs. @@ -403,6 +423,26 @@ int batadv_debugfs_add_meshif(struct net_device *dev) return -ENOMEM; } +/** + * batadv_debugfs_rename_meshif() - Fix debugfs path for renamed softif + * @dev: net_device which was renamed + */ +void batadv_debugfs_rename_meshif(struct net_device *dev) +{ + struct batadv_priv *bat_priv = netdev_priv(dev); + const char *name = dev->name; + struct dentry *dir; + struct dentry *d; + + dir = bat_priv->debug_dir; + if (!dir) + return; + + d = debugfs_rename(dir->d_parent, dir, dir->d_parent, name); + if (!d) + pr_err("Can't rename debugfs dir to %s\n", name); +} + void batadv_debugfs_del_meshif(struct net_device *dev) { struct batadv_priv *bat_priv = netdev_priv(dev); diff --git a/net/batman-adv/debugfs.h b/net/batman-adv/debugfs.h index e49121ee55f696547ddc9774ba6c425af2d49b57..59a0d6d70ecd4d0b49e15138306acc371da2d8b7 100644 --- a/net/batman-adv/debugfs.h +++ b/net/batman-adv/debugfs.h @@ -29,8 +29,10 @@ struct net_device; void batadv_debugfs_init(void); void batadv_debugfs_destroy(void); int batadv_debugfs_add_meshif(struct net_device *dev); +void batadv_debugfs_rename_meshif(struct net_device *dev); void batadv_debugfs_del_meshif(struct net_device *dev); int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface); +void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface); void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface); #else @@ -48,6 +50,10 @@ static inline int batadv_debugfs_add_meshif(struct net_device *dev) return 0; } +static inline void batadv_debugfs_rename_meshif(struct net_device *dev) +{ +} + static inline void batadv_debugfs_del_meshif(struct net_device *dev) { } @@ -58,6 +64,11 @@ int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface) return 0; } +static inline +void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface) +{ +} + static inline void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface) { diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index df7c6a08018854e9a4a54a3dbcbe59c826b395e0..83c7009b0da1401f80ff381bf0d45af68d235c99 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -242,6 +242,7 @@ static u32 batadv_hash_dat(const void *data, u32 size) u32 hash = 0; const struct batadv_dat_entry *dat = data; const unsigned char *key; + __be16 vid; u32 i; key = (const unsigned char *)&dat->ip; @@ -251,7 +252,8 @@ static u32 batadv_hash_dat(const void *data, u32 size) hash ^= (hash >> 6); } - key = (const unsigned char *)&dat->vid; + vid = htons(dat->vid); + key = (__force const unsigned char *)&vid; for (i = 0; i < sizeof(dat->vid); i++) { hash += key[i]; hash += (hash << 10); @@ -1023,8 +1025,9 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, skb_reset_mac_header(skb_new); skb_new->protocol = eth_type_trans(skb_new, bat_priv->soft_iface); - bat_priv->stats.rx_packets++; - bat_priv->stats.rx_bytes += skb->len + ETH_HLEN + hdr_size; + batadv_inc_counter(bat_priv, BATADV_CNT_RX); + batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, + skb->len + ETH_HLEN + hdr_size); bat_priv->soft_iface->last_rx = jiffies; netif_rx(skb_new); diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index a06b6041f3e0d9de16e274b64bc415a28e315f52..fef21f75892e46041cf8dc83a61dde691fa3686a 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -232,8 +232,10 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, spin_unlock_bh(&chain->lock); err: - if (!ret) + if (!ret) { kfree(frag_entry_new); + kfree_skb(skb); + } return ret; } @@ -305,7 +307,7 @@ batadv_frag_merge_packets(struct hlist_head *chain) * * There are three possible outcomes: 1) Packet is merged: Return true and * set *skb to merged packet; 2) Packet is buffered: Return true and set *skb - * to NULL; 3) Error: Return false and leave skb as is. + * to NULL; 3) Error: Return false and free skb. * * Return: true when packet is merged or buffered, false when skb is not not * used. @@ -330,9 +332,9 @@ bool batadv_frag_skb_buffer(struct sk_buff **skb, goto out_err; out: - *skb = skb_out; ret = true; out_err: + *skb = skb_out; return ret; } @@ -482,12 +484,20 @@ int batadv_frag_send_packet(struct sk_buff *skb, */ if (skb->priority >= 256 && skb->priority <= 263) frag_header.priority = skb->priority - 256; + else + frag_header.priority = 0; ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr); ether_addr_copy(frag_header.dest, orig_node->orig); /* Eat and send fragments from the tail of skb */ while (skb->len > max_fragment_size) { + /* The initial check in this function should cover this case */ + if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) { + ret = -1; + goto out; + } + skb_fragment = batadv_frag_create(skb, &frag_header, mtu); if (!skb_fragment) goto out; @@ -505,12 +515,6 @@ int batadv_frag_send_packet(struct sk_buff *skb, } frag_header.no++; - - /* The initial check in this function should cover this case */ - if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) { - ret = -1; - goto out; - } } /* Make room for the fragment header. */ diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index ed9aaf30fbcfd2c5a3f2e3f022798047e96fba55..3bd7ed6b6b3e12e01b296e024937e93be3dcd009 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,9 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @orig_node: originator announcing gateway capabilities * @gateway: announced bandwidth information + * + * Has to be called with the appropriate locks being acquired + * (gw.list_lock). */ static void batadv_gw_node_add(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, @@ -332,6 +336,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, { struct batadv_gw_node *gw_node; + lockdep_assert_held(&bat_priv->gw.list_lock); + if (gateway->bandwidth_down == 0) return; @@ -346,10 +352,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); - spin_lock_bh(&bat_priv->gw.list_lock); kref_get(&gw_node->refcount); hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); - spin_unlock_bh(&bat_priv->gw.list_lock); batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n", @@ -404,11 +408,14 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv, { struct batadv_gw_node *gw_node, *curr_gw = NULL; + spin_lock_bh(&bat_priv->gw.list_lock); gw_node = batadv_gw_node_get(bat_priv, orig_node); if (!gw_node) { batadv_gw_node_add(bat_priv, orig_node, gateway); + spin_unlock_bh(&bat_priv->gw.list_lock); goto out; } + spin_unlock_bh(&bat_priv->gw.list_lock); if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) && (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))) diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 21184810d89f69e372673aff221a74382945491d..3e3f91ab694fb8e61ecb4df356e72334b56e0fbe 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c @@ -253,6 +253,11 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, */ void batadv_gw_init(struct batadv_priv *bat_priv) { + if (bat_priv->algo_ops->gw.init_sel_class) + bat_priv->algo_ops->gw.init_sel_class(bat_priv); + else + atomic_set(&bat_priv->gw.sel_class, 1); + batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, NULL, BATADV_TVLV_GW, 1, BATADV_TVLV_HANDLER_OGM_CIFNOTFND); diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 8f7883b7d717a94dc2f4de678b2744524e0f124d..f528761674df9f4b84fd29aebfef80a62097268e 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -539,6 +540,11 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, hard_iface->soft_iface = soft_iface; bat_priv = netdev_priv(hard_iface->soft_iface); + if (bat_priv->num_ifaces >= UINT_MAX) { + ret = -ENOSPC; + goto err_dev; + } + ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface, NULL, NULL); if (ret) @@ -591,6 +597,9 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, batadv_hardif_recalc_extra_skbroom(soft_iface); + if (bat_priv->algo_ops->iface.enabled) + bat_priv->algo_ops->iface.enabled(hard_iface); + out: return 0; @@ -646,7 +655,7 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface, batadv_hardif_recalc_extra_skbroom(hard_iface->soft_iface); /* nobody uses this interface anymore */ - if (!bat_priv->num_ifaces) { + if (bat_priv->num_ifaces == 0) { batadv_gw_check_client_stop(bat_priv); if (autodel == BATADV_IF_CLEANUP_AUTO) @@ -682,7 +691,7 @@ batadv_hardif_add_interface(struct net_device *net_dev) if (ret) goto free_if; - hard_iface->if_num = -1; + hard_iface->if_num = 0; hard_iface->net_dev = net_dev; hard_iface->soft_iface = NULL; hard_iface->if_status = BATADV_IF_NOT_IN_USE; @@ -694,6 +703,7 @@ batadv_hardif_add_interface(struct net_device *net_dev) INIT_LIST_HEAD(&hard_iface->list); INIT_HLIST_HEAD(&hard_iface->neigh_list); + mutex_init(&hard_iface->bat_iv.ogm_buff_mutex); spin_lock_init(&hard_iface->neigh_list_lock); kref_init(&hard_iface->refcount); @@ -750,6 +760,32 @@ void batadv_hardif_remove_interfaces(void) rtnl_unlock(); } +/** + * batadv_hard_if_event_softif() - Handle events for soft interfaces + * @event: NETDEV_* event to handle + * @net_dev: net_device which generated an event + * + * Return: NOTIFY_* result + */ +static int batadv_hard_if_event_softif(unsigned long event, + struct net_device *net_dev) +{ + struct batadv_priv *bat_priv; + + switch (event) { + case NETDEV_REGISTER: + batadv_sysfs_add_meshif(net_dev); + bat_priv = netdev_priv(net_dev); + batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS); + break; + case NETDEV_CHANGENAME: + batadv_debugfs_rename_meshif(net_dev); + break; + } + + return NOTIFY_DONE; +} + static int batadv_hard_if_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -758,12 +794,8 @@ static int batadv_hard_if_event(struct notifier_block *this, struct batadv_hard_iface *primary_if = NULL; struct batadv_priv *bat_priv; - if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) { - batadv_sysfs_add_meshif(net_dev); - bat_priv = netdev_priv(net_dev); - batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS); - return NOTIFY_DONE; - } + if (batadv_softif_is_valid(net_dev)) + return batadv_hard_if_event_softif(event, net_dev); hard_iface = batadv_hardif_get_by_netdev(net_dev); if (!hard_iface && (event == NETDEV_REGISTER || @@ -807,6 +839,9 @@ static int batadv_hard_if_event(struct notifier_block *this, if (hard_iface == primary_if) batadv_primary_if_update_addr(bat_priv, NULL); break; + case NETDEV_CHANGENAME: + batadv_debugfs_rename_hardif(hard_iface); + break; default: break; } diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 7c8d16086f0fddbcfb85b32e8bff9223befce0ab..8466f83fc32f61722be11e4aedbe4c109fd9c807 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -1495,7 +1495,7 @@ int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb) } int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, - int max_if_num) + unsigned int max_if_num) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct batadv_algo_ops *bao = bat_priv->algo_ops; @@ -1530,7 +1530,7 @@ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, } int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, - int max_if_num) + unsigned int max_if_num) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct batadv_hashtable *hash = bat_priv->orig_hash; diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index ebc56183f3581835c899272425a212ff092033b6..fab0b2cc141d9affdbcf68f1d0ce7aad753c3857 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -78,9 +78,9 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb); int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset); int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, - int max_if_num); + unsigned int max_if_num); int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, - int max_if_num); + unsigned int max_if_num); struct batadv_orig_node_vlan * batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node, unsigned short vid); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 8b98609ebc1eae44c5aa706662b321e8bfdbb7eb..19059ae26e5198f1cb1e3b7380e214e281600f49 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -930,7 +930,6 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, bool is4addr; unicast_packet = (struct batadv_unicast_packet *)skb->data; - unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR; /* the caller function should have already pulled 2 bytes */ @@ -951,9 +950,13 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size)) return NET_RX_DROP; + unicast_packet = (struct batadv_unicast_packet *)skb->data; + /* packet for me */ if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) { if (is4addr) { + unicast_4addr_packet = + (struct batadv_unicast_4addr_packet *)skb->data; subtype = unicast_4addr_packet->subtype; batadv_dat_inc_counter(bat_priv, subtype); @@ -1080,6 +1083,12 @@ int batadv_recv_frag_packet(struct sk_buff *skb, batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX); batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len); + /* batadv_frag_skb_buffer will always consume the skb and + * the caller should therefore never try to free the + * skb after this point + */ + ret = NET_RX_SUCCESS; + /* Add fragment to buffer and merge if possible. */ if (!batadv_frag_skb_buffer(&skb, orig_node_src)) goto out; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index a92512a46e91ec125283953059ed6de7928a27c1..99d2c453c872263fed60043abab3edcc60e2e58f 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -808,7 +808,6 @@ static int batadv_softif_init_late(struct net_device *dev) atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); #endif atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF); - atomic_set(&bat_priv->gw.sel_class, 20); atomic_set(&bat_priv->gw.bandwidth_down, 100); atomic_set(&bat_priv->gw.bandwidth_up, 20); atomic_set(&bat_priv->orig_interval, 1000); diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 1fab9bcf535d30d1fc6e9c7a958316bcf38882c1..d40d83949b0055e9e1b62e7cb1a3f8cc02562583 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -867,7 +867,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node, struct batadv_orig_node_vlan *vlan; u8 *tt_change_ptr; - rcu_read_lock(); + spin_lock_bh(&orig_node->vlan_list_lock); hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) { num_vlan++; num_entries += atomic_read(&vlan->tt.num_entries); @@ -905,7 +905,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node, *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; out: - rcu_read_unlock(); + spin_unlock_bh(&orig_node->vlan_list_lock); return tvlv_len; } @@ -936,15 +936,20 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, struct batadv_tvlv_tt_vlan_data *tt_vlan; struct batadv_softif_vlan *vlan; u16 num_vlan = 0; - u16 num_entries = 0; + u16 vlan_entries = 0; + u16 total_entries = 0; u16 tvlv_len; u8 *tt_change_ptr; int change_offset; - rcu_read_lock(); + spin_lock_bh(&bat_priv->softif_vlan_list_lock); hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { + vlan_entries = atomic_read(&vlan->tt.num_entries); + if (vlan_entries < 1) + continue; + num_vlan++; - num_entries += atomic_read(&vlan->tt.num_entries); + total_entries += vlan_entries; } change_offset = sizeof(**tt_data); @@ -952,7 +957,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, /* if tt_len is negative, allocate the space needed by the full table */ if (*tt_len < 0) - *tt_len = batadv_tt_len(num_entries); + *tt_len = batadv_tt_len(total_entries); tvlv_len = *tt_len; tvlv_len += change_offset; @@ -969,6 +974,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1); hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { + vlan_entries = atomic_read(&vlan->tt.num_entries); + if (vlan_entries < 1) + continue; + tt_vlan->vid = htons(vlan->vid); tt_vlan->crc = htonl(vlan->tt.crc); @@ -979,7 +988,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; out: - rcu_read_unlock(); + spin_unlock_bh(&bat_priv->softif_vlan_list_lock); return tvlv_len; } @@ -1539,6 +1548,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, * by a given originator * @entry: the TT global entry to check * @orig_node: the originator to search in the list + * @flags: a pointer to store TT flags for the given @entry received + * from @orig_node * * find out if an orig_node is already in the list of a tt_global_entry. * @@ -1546,7 +1557,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, */ static bool batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, - const struct batadv_orig_node *orig_node) + const struct batadv_orig_node *orig_node, + u8 *flags) { struct batadv_tt_orig_list_entry *orig_entry; bool found = false; @@ -1554,15 +1566,51 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node); if (orig_entry) { found = true; + + if (flags) + *flags = orig_entry->flags; + batadv_tt_orig_list_entry_put(orig_entry); } return found; } +/** + * batadv_tt_global_sync_flags - update TT sync flags + * @tt_global: the TT global entry to update sync flags in + * + * Updates the sync flag bits in the tt_global flag attribute with a logical + * OR of all sync flags from any of its TT orig entries. + */ +static void +batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global) +{ + struct batadv_tt_orig_list_entry *orig_entry; + const struct hlist_head *head; + u16 flags = BATADV_NO_FLAGS; + + rcu_read_lock(); + head = &tt_global->orig_list; + hlist_for_each_entry_rcu(orig_entry, head, list) + flags |= orig_entry->flags; + rcu_read_unlock(); + + flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK); + tt_global->common.flags = flags; +} + +/** + * batadv_tt_global_orig_entry_add - add or update a TT orig entry + * @tt_global: the TT global entry to add an orig entry in + * @orig_node: the originator to add an orig entry for + * @ttvn: translation table version number of this changeset + * @flags: TT sync flags + */ static void batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, - struct batadv_orig_node *orig_node, int ttvn) + struct batadv_orig_node *orig_node, int ttvn, + u8 flags) { struct batadv_tt_orig_list_entry *orig_entry; @@ -1574,7 +1622,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, * was added during a "temporary client detection" */ orig_entry->ttvn = ttvn; - goto out; + orig_entry->flags = flags; + goto sync_flags; } orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC); @@ -1586,6 +1635,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, batadv_tt_global_size_inc(orig_node, tt_global->common.vid); orig_entry->orig_node = orig_node; orig_entry->ttvn = ttvn; + orig_entry->flags = flags; kref_init(&orig_entry->refcount); kref_get(&orig_entry->refcount); @@ -1593,6 +1643,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, &tt_global->orig_list); atomic_inc(&tt_global->orig_list_count); +sync_flags: + batadv_tt_global_sync_flags(tt_global); out: if (orig_entry) batadv_tt_orig_list_entry_put(orig_entry); @@ -1656,7 +1708,9 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, ether_addr_copy(common->addr, tt_addr); common->vid = vid; - common->flags = flags; + if (!is_multicast_ether_addr(common->addr)) + common->flags = flags & (~BATADV_TT_SYNC_MASK); + tt_global_entry->roam_at = 0; /* node must store current time in case of roaming. This is * needed to purge this entry out on timeout (if nobody claims @@ -1698,7 +1752,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, if (!(common->flags & BATADV_TT_CLIENT_TEMP)) goto out; if (batadv_tt_global_entry_has_orig(tt_global_entry, - orig_node)) + orig_node, NULL)) goto out_remove; batadv_tt_global_del_orig_list(tt_global_entry); goto add_orig_entry; @@ -1716,10 +1770,11 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, } /* the change can carry possible "attribute" flags like the - * TT_CLIENT_WIFI, therefore they have to be copied in the + * TT_CLIENT_TEMP, therefore they have to be copied in the * client entry */ - common->flags |= flags; + if (!is_multicast_ether_addr(common->addr)) + common->flags |= flags & (~BATADV_TT_SYNC_MASK); /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only * one originator left in the list and we previously received a @@ -1736,7 +1791,8 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, } add_orig_entry: /* add the new orig_entry (if needed) or update it */ - batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); + batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn, + flags & BATADV_TT_SYNC_MASK); batadv_dbg(BATADV_DBG_TT, bat_priv, "Creating new global tt entry: %pM (vid: %d, via %pM)\n", @@ -1959,6 +2015,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, struct batadv_tt_orig_list_entry *orig, bool best) { + u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags; void *hdr; struct batadv_orig_node_vlan *vlan; u8 last_ttvn; @@ -1988,7 +2045,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) || nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) || nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) || - nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags)) + nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags)) goto nla_put_failure; if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) @@ -2602,6 +2659,7 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, unsigned short vid) { struct batadv_hashtable *hash = bat_priv->tt.global_hash; + struct batadv_tt_orig_list_entry *tt_orig; struct batadv_tt_common_entry *tt_common; struct batadv_tt_global_entry *tt_global; struct hlist_head *head; @@ -2640,8 +2698,9 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, /* find out if this global entry is announced by this * originator */ - if (!batadv_tt_global_entry_has_orig(tt_global, - orig_node)) + tt_orig = batadv_tt_global_orig_entry_find(tt_global, + orig_node); + if (!tt_orig) continue; /* use network order to read the VID: this ensures that @@ -2653,10 +2712,12 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, /* compute the CRC on flags that have to be kept in sync * among nodes */ - flags = tt_common->flags & BATADV_TT_SYNC_MASK; + flags = tt_orig->flags; crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags)); crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN); + + batadv_tt_orig_list_entry_put(tt_orig); } rcu_read_unlock(); } @@ -2834,23 +2895,46 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv, } /** - * batadv_tt_local_valid - verify that given tt entry is a valid one + * batadv_tt_local_valid() - verify local tt entry and get flags * @entry_ptr: to be checked local tt entry * @data_ptr: not used but definition required to satisfy the callback prototype + * @flags: a pointer to store TT flags for this client to + * + * Checks the validity of the given local TT entry. If it is, then the provided + * flags pointer is updated. * * Return: true if the entry is a valid, false otherwise. */ -static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr) +static bool batadv_tt_local_valid(const void *entry_ptr, + const void *data_ptr, + u8 *flags) { const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW) return false; + + if (flags) + *flags = tt_common_entry->flags; + return true; } +/** + * batadv_tt_global_valid() - verify global tt entry and get flags + * @entry_ptr: to be checked global tt entry + * @data_ptr: an orig_node object (may be NULL) + * @flags: a pointer to store TT flags for this client to + * + * Checks the validity of the given global TT entry. If it is, then the provided + * flags pointer is updated either with the common (summed) TT flags if data_ptr + * is NULL or the specific, per originator TT flags otherwise. + * + * Return: true if the entry is a valid, false otherwise. + */ static bool batadv_tt_global_valid(const void *entry_ptr, - const void *data_ptr) + const void *data_ptr, + u8 *flags) { const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; const struct batadv_tt_global_entry *tt_global_entry; @@ -2864,7 +2948,8 @@ static bool batadv_tt_global_valid(const void *entry_ptr, struct batadv_tt_global_entry, common); - return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node); + return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node, + flags); } /** @@ -2874,25 +2959,34 @@ static bool batadv_tt_global_valid(const void *entry_ptr, * @hash: hash table containing the tt entries * @tt_len: expected tvlv tt data buffer length in number of bytes * @tvlv_buff: pointer to the buffer to fill with the TT data - * @valid_cb: function to filter tt change entries + * @valid_cb: function to filter tt change entries and to return TT flags * @cb_data: data passed to the filter function as argument + * + * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb + * is not provided then this becomes a no-op. */ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, struct batadv_hashtable *hash, void *tvlv_buff, u16 tt_len, bool (*valid_cb)(const void *, - const void *), + const void *, + u8 *flags), void *cb_data) { struct batadv_tt_common_entry *tt_common_entry; struct batadv_tvlv_tt_change *tt_change; struct hlist_head *head; u16 tt_tot, tt_num_entries = 0; + u8 flags; + bool ret; u32 i; tt_tot = batadv_tt_entries(tt_len); tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff; + if (!valid_cb) + return; + rcu_read_lock(); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -2902,11 +2996,12 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, if (tt_tot == tt_num_entries) break; - if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) + ret = valid_cb(tt_common_entry, cb_data, &flags); + if (!ret) continue; ether_addr_copy(tt_change->addr, tt_common_entry->addr); - tt_change->flags = tt_common_entry->flags; + tt_change->flags = flags; tt_change->vid = htons(tt_common_entry->vid); memset(tt_change->reserved, 0, sizeof(tt_change->reserved)); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index b3dd1a381aad9b2bc970515a84648721be624403..c17b74e51fe9788c9ed8ea4b822bbbd079e13d8f 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include /* for linux/wait.h */ @@ -81,11 +82,13 @@ enum batadv_dhcp_recipient { * @ogm_buff: buffer holding the OGM packet * @ogm_buff_len: length of the OGM packet buffer * @ogm_seqno: OGM sequence number - used to identify each OGM + * @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */ struct batadv_hard_iface_bat_iv { unsigned char *ogm_buff; int ogm_buff_len; atomic_t ogm_seqno; + struct mutex ogm_buff_mutex; }; /** @@ -139,7 +142,7 @@ struct batadv_hard_iface_bat_v { */ struct batadv_hard_iface { struct list_head list; - s16 if_num; + unsigned int if_num; char if_status; struct net_device *net_dev; u8 num_bcasts; @@ -966,12 +969,14 @@ struct batadv_softif_vlan { * @ogm_buff: buffer holding the OGM packet * @ogm_buff_len: length of the OGM packet buffer * @ogm_seqno: OGM sequence number - used to identify each OGM + * @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len * @ogm_wq: workqueue used to schedule OGM transmissions */ struct batadv_priv_bat_v { unsigned char *ogm_buff; int ogm_buff_len; atomic_t ogm_seqno; + struct mutex ogm_buff_mutex; struct delayed_work ogm_wq; }; @@ -1060,7 +1065,7 @@ struct batadv_priv { atomic_t bcast_seqno; atomic_t bcast_queue_left; atomic_t batman_queue_left; - char num_ifaces; + unsigned int num_ifaces; struct kobject *mesh_obj; struct dentry *debug_dir; struct hlist_head forw_bat_list; @@ -1241,6 +1246,7 @@ struct batadv_tt_global_entry { * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client * @orig_node: pointer to orig node announcing this non-mesh client * @ttvn: translation table version number which added the non-mesh client + * @flags: per orig entry TT sync flags * @list: list node for batadv_tt_global_entry::orig_list * @refcount: number of contexts the object is used * @rcu: struct used for freeing in an RCU-safe manner @@ -1248,6 +1254,7 @@ struct batadv_tt_global_entry { struct batadv_tt_orig_list_entry { struct batadv_orig_node *orig_node; u8 ttvn; + u8 flags; struct hlist_node list; struct kref refcount; struct rcu_head rcu; @@ -1397,6 +1404,7 @@ struct batadv_forw_packet { * @activate: start routing mechanisms when hard-interface is brought up * (optional) * @enable: init routing info when hard-interface is enabled + * @enabled: notification when hard-interface was enabled (optional) * @disable: de-init routing info when hard-interface is disabled * @update_mac: (re-)init mac addresses of the protocol information * belonging to this hard-interface @@ -1405,6 +1413,7 @@ struct batadv_forw_packet { struct batadv_algo_iface_ops { void (*activate)(struct batadv_hard_iface *hard_iface); int (*enable)(struct batadv_hard_iface *hard_iface); + void (*enabled)(struct batadv_hard_iface *hard_iface); void (*disable)(struct batadv_hard_iface *hard_iface); void (*update_mac)(struct batadv_hard_iface *hard_iface); void (*primary_set)(struct batadv_hard_iface *hard_iface); @@ -1452,9 +1461,10 @@ struct batadv_algo_neigh_ops { */ struct batadv_algo_orig_ops { void (*free)(struct batadv_orig_node *orig_node); - int (*add_if)(struct batadv_orig_node *orig_node, int max_if_num); - int (*del_if)(struct batadv_orig_node *orig_node, int max_if_num, - int del_if_num); + int (*add_if)(struct batadv_orig_node *orig_node, + unsigned int max_if_num); + int (*del_if)(struct batadv_orig_node *orig_node, + unsigned int max_if_num, unsigned int del_if_num); #ifdef CONFIG_BATMAN_ADV_DEBUGFS void (*print)(struct batadv_priv *priv, struct seq_file *seq, struct batadv_hard_iface *hard_iface); @@ -1466,6 +1476,7 @@ struct batadv_algo_orig_ops { /** * struct batadv_algo_gw_ops - mesh algorithm callbacks (GW specific) + * @init_sel_class: initialize GW selection class (optional) * @store_sel_class: parse and stores a new GW selection class (optional) * @show_sel_class: prints the current GW selection class (optional) * @get_best_gw_node: select the best GW from the list of available nodes @@ -1476,6 +1487,7 @@ struct batadv_algo_orig_ops { * @dump: dump gateways to a netlink socket (optional) */ struct batadv_algo_gw_ops { + void (*init_sel_class)(struct batadv_priv *bat_priv); ssize_t (*store_sel_class)(struct batadv_priv *bat_priv, char *buff, size_t count); ssize_t (*show_sel_class)(struct batadv_priv *bat_priv, char *buff); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index bd41b78d131ddca4e3207352af24a6064b6ee855..1d085eed72d0c02a5614891bc73982f0d1ad521d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1054,8 +1054,10 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, if (!conn) return ERR_PTR(-ENOMEM); - if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) + if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) { + hci_conn_del(conn); return ERR_PTR(-EBUSY); + } conn->state = BT_CONNECT; set_bit(HCI_CONN_SCANNING, &conn->flags); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4bd72d2fe4150e116c95c4014870b37ac020d4c3..a70b078ceb3caf2d276e769e009d369c1c9c11ba 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4180,7 +4180,14 @@ static void hci_rx_work(struct work_struct *work) hci_send_to_sock(hdev, skb); } - if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { + /* If the device has been opened in HCI_USER_CHANNEL, + * the userspace has exclusive access to device. + * When device is HCI_INIT, we still need to process + * the data packets to the driver in order + * to complete its setup(). + */ + if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + !test_bit(HCI_INIT, &hdev->flags)) { kfree_skb(skb); continue; } diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 1015d9c8d97ddbe978ae7b54698b093f1961b958..4a89e121d6627bc50f691a0676711e686b3771bc 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -1093,6 +1093,14 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) instance_flags = get_adv_instance_flags(hdev, instance); + /* If instance already has the flags set skip adding it once + * again. + */ + if (adv_instance && eir_get_data(adv_instance->adv_data, + adv_instance->adv_data_len, EIR_FLAGS, + NULL)) + goto skip_flags; + /* The Add Advertising command allows userspace to set both the general * and limited discoverable flags. */ @@ -1125,6 +1133,7 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) } } +skip_flags: if (adv_instance) { memcpy(ptr, adv_instance->adv_data, adv_instance->adv_data_len); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index ca1836941f3c4ac12fcdaf48b4fb335d94f85415..44b3146c611753ee0808f57ddd4c0c5c94fe6f8d 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -826,6 +826,8 @@ static int hci_sock_release(struct socket *sock) if (!sk) return 0; + lock_sock(sk); + switch (hci_pi(sk)->channel) { case HCI_CHANNEL_MONITOR: atomic_dec(&monitor_promisc); @@ -873,6 +875,7 @@ static int hci_sock_release(struct socket *sock) skb_queue_purge(&sk->sk_receive_queue); skb_queue_purge(&sk->sk_write_queue); + release_sock(sk); sock_put(sk); return 0; } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 1306962a792afc2304df5899427c8b742bb96350..11012a50907083baff581241135b357b0857440d 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -4908,10 +4908,8 @@ void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", chan, result, local_amp_id, remote_amp_id); - if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { - l2cap_chan_unlock(chan); + if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) return; - } if (chan->state != BT_CONNECTED) { l2cap_do_create(chan, result, local_amp_id, remote_amp_id); diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 04eea2f4b80f2cbad170d4d636976d87fb419f09..bef3cca4d6b48681615a920bc6b1fb77eee25307 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -211,6 +211,12 @@ static int br_set_mac_address(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; + /* dev_set_mac_addr() can be called by a master device on bridge's + * NETDEV_UNREGISTER, but since it's being destroyed do nothing + */ + if (dev->reg_state != NETREG_REGISTERED) + return -EBUSY; + spin_lock_bh(&br->lock); if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { /* Mac address will be changed in br_stp_change_bridge_id(). */ diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 0c96773d182923784dde7eba8e9fad7840edb679..62e045c9d45294ccf6273267203840a903a3fc29 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -643,6 +643,9 @@ static unsigned int br_nf_forward_arp(void *priv, nf_bridge_pull_encap_header(skb); } + if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr)))) + return NF_DROP; + if (arp_hdr(skb)->ar_pln != 4) { if (IS_VLAN_ARP(skb)) nf_bridge_push_encap_header(skb); diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 4a47918b504f88fe9d94f703d58ea66756c9f156..1d850edecd7247faf5bbdb9006e70d40a60639db 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1894,7 +1894,7 @@ static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz) } static int ebt_buf_add(struct ebt_entries_buf_state *state, - void *data, unsigned int sz) + const void *data, unsigned int sz) { if (state->buf_kern_start == NULL) goto count_only; @@ -1928,7 +1928,7 @@ enum compat_mwt { EBT_COMPAT_TARGET, }; -static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, +static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt, enum compat_mwt compat_mwt, struct ebt_entries_buf_state *state, const unsigned char *base) @@ -2004,22 +2004,23 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, /* return size of all matches, watchers or target, including necessary * alignment and padding. */ -static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, +static int ebt_size_mwt(const struct compat_ebt_entry_mwt *match32, unsigned int size_left, enum compat_mwt type, struct ebt_entries_buf_state *state, const void *base) { + const char *buf = (const char *)match32; int growth = 0; - char *buf; if (size_left == 0) return 0; - buf = (char *) match32; - - while (size_left >= sizeof(*match32)) { + do { struct ebt_entry_match *match_kern; int ret; + if (size_left < sizeof(*match32)) + return -EINVAL; + match_kern = (struct ebt_entry_match *) state->buf_kern_start; if (match_kern) { char *tmp; @@ -2056,22 +2057,18 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, if (match_kern) match_kern->match_size = ret; - /* rule should have no remaining data after target */ - if (type == EBT_COMPAT_TARGET && size_left) - return -EINVAL; - match32 = (struct compat_ebt_entry_mwt *) buf; - } + } while (size_left); return growth; } /* called for all ebt_entry structures. */ -static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, +static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *base, unsigned int *total, struct ebt_entries_buf_state *state) { - unsigned int i, j, startoff, new_offset = 0; + unsigned int i, j, startoff, next_expected_off, new_offset = 0; /* stores match/watchers/targets & offset of next struct ebt_entry: */ unsigned int offsets[4]; unsigned int *offsets_update = NULL; @@ -2158,11 +2155,13 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, return ret; } - startoff = state->buf_user_offset - startoff; + next_expected_off = state->buf_user_offset - startoff; + if (next_expected_off != entry->next_offset) + return -EINVAL; - if (WARN_ON(*total < startoff)) + if (*total < entry->next_offset) return -EINVAL; - *total -= startoff; + *total -= entry->next_offset; return 0; } @@ -2183,7 +2182,9 @@ static int compat_copy_entries(unsigned char *data, unsigned int size_user, if (ret < 0) return ret; - WARN_ON(size_remaining); + if (size_remaining) + return -EINVAL; + return state->buf_kern_offset; } diff --git a/net/core/dev.c b/net/core/dev.c index 69ac821ad6f460db88bbca136ff03b4ca99e12a1..19f36d669e744ce6e4cb4546349b59ee11f30d9b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6716,7 +6716,8 @@ static int __dev_set_mtu(struct net_device *dev, int new_mtu) if (ops->ndo_change_mtu) return ops->ndo_change_mtu(dev, new_mtu); - dev->mtu = new_mtu; + /* Pairs with all the lockless reads of dev->mtu in the stack */ + WRITE_ONCE(dev->mtu, new_mtu); return 0; } diff --git a/net/core/ethtool.c b/net/core/ethtool.c old mode 100644 new mode 100755 index e5a221fa7553bb63af8f3c21d7613ca06b5eaa31..730f8dce33be280623668bb6fdc9e058a945d957 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -514,6 +514,8 @@ convert_link_ksettings_to_legacy_settings( = link_ksettings->base.eth_tp_mdix; legacy_settings->eth_tp_mdix_ctrl = link_ksettings->base.eth_tp_mdix_ctrl; + legacy_settings->transceiver + = link_ksettings->base.transceiver; return retval; } @@ -2425,7 +2427,7 @@ int ethtool_set_per_queue_coalesce(struct net_device *dev, return ret; } -static int ethtool_set_per_queue(struct net_device *dev, +static int noinline_for_stack ethtool_set_per_queue(struct net_device *dev, void __user *useraddr, u32 sub_cmd) { struct ethtool_per_queue_op per_queue_opt; diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 31c4041f758652b4583a84d70e16992ce515c392..955fc01a030abcad7f3273189fd28cb53a83fecc 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -714,7 +714,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, frh = nlmsg_data(nlh); frh->family = ops->family; - frh->table = rule->table; + frh->table = rule->table < 256 ? rule->table : RT_TABLE_COMPAT; if (nla_put_u32(skb, FRA_TABLE, rule->table)) goto nla_put_failure; if (nla_put_u32(skb, FRA_SUPPRESS_PREFIXLEN, rule->suppress_prefixlen)) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index df48cab7d66c194926ff503e831c6699b9794aed..0e831671634d5bac98a63fbde4f07c3bc316e44d 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1067,7 +1067,7 @@ static void neigh_update_hhs(struct neighbour *neigh) if (update) { hh = &neigh->hh; - if (hh->hh_len) { + if (READ_ONCE(hh->hh_len)) { write_seqlock_bh(&hh->hh_lock); update(hh, neigh->dev, neigh->ha); write_sequnlock_bh(&hh->hh_lock); @@ -1340,7 +1340,7 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) struct net_device *dev = neigh->dev; unsigned int seq; - if (dev->header_ops->cache && !neigh->hh.hh_len) + if (dev->header_ops->cache && !READ_ONCE(neigh->hh.hh_len)) neigh_hh_init(neigh); do { @@ -1855,8 +1855,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, goto nla_put_failure; { unsigned long now = jiffies; - unsigned int flush_delta = now - tbl->last_flush; - unsigned int rand_delta = now - tbl->last_rand; + long flush_delta = now - tbl->last_flush; + long rand_delta = now - tbl->last_rand; struct neigh_hash_table *nht; struct ndt_config ndc = { .ndtc_key_len = tbl->key_len, diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c index 2e4eef71471da4f426c60ebf119cc7d4886e1017..db65b0cdfc4c7312b69c425b9bea742e7a8a44b5 100644 --- a/net/core/netclassid_cgroup.c +++ b/net/core/netclassid_cgroup.c @@ -55,30 +55,60 @@ static void cgrp_css_free(struct cgroup_subsys_state *css) kfree(css_cls_state(css)); } +/* + * To avoid freezing of sockets creation for tasks with big number of threads + * and opened sockets lets release file_lock every 1000 iterated descriptors. + * New sockets will already have been created with new classid. + */ + +struct update_classid_context { + u32 classid; + unsigned int batch; +}; + +#define UPDATE_CLASSID_BATCH 1000 + static int update_classid_sock(const void *v, struct file *file, unsigned n) { int err; + struct update_classid_context *ctx = (void *)v; struct socket *sock = sock_from_file(file, &err); if (sock) { spin_lock(&cgroup_sk_update_lock); - sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, - (unsigned long)v); + sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, ctx->classid); spin_unlock(&cgroup_sk_update_lock); } + if (--ctx->batch == 0) { + ctx->batch = UPDATE_CLASSID_BATCH; + return n + 1; + } return 0; } +static void update_classid_task(struct task_struct *p, u32 classid) +{ + struct update_classid_context ctx = { + .classid = classid, + .batch = UPDATE_CLASSID_BATCH + }; + unsigned int fd = 0; + + do { + task_lock(p); + fd = iterate_fd(p->files, fd, update_classid_sock, &ctx); + task_unlock(p); + cond_resched(); + } while (fd); +} + static void cgrp_attach(struct cgroup_taskset *tset) { struct cgroup_subsys_state *css; struct task_struct *p; cgroup_taskset_for_each(p, css, tset) { - task_lock(p); - iterate_fd(p->files, 0, update_classid_sock, - (void *)(unsigned long)css_cls_state(css)->classid); - task_unlock(p); + update_classid_task(p, css_cls_state(css)->classid); } } @@ -100,10 +130,7 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, css_task_iter_start(css, &it); while ((p = css_task_iter_next(&it))) { - task_lock(p); - iterate_fd(p->files, 0, update_classid_sock, - (void *)(unsigned long)cs->classid); - task_unlock(p); + update_classid_task(p, cs->classid); cond_resched(); } css_task_iter_end(&it); diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index a6fc82704f0c1e7be03f72ed06990a776b58c8fd..b4318c1b5b96031941c00eea71665a8bf1f2fb59 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -255,6 +255,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write, return ret; } +# ifdef CONFIG_HAVE_EBPF_JIT static int proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, @@ -265,6 +266,7 @@ proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write, return proc_dointvec_minmax(table, write, buffer, lenp, ppos); } +# endif /* CONFIG_HAVE_EBPF_JIT */ static int proc_dolongvec_minmax_bpf_restricted(struct ctl_table *table, int write, diff --git a/net/core/utils.c b/net/core/utils.c index cf5622b9ccc44f065a2ac6ebafe707767f5fd633..3317f90b32eb097bed5603ee558ae67f0f4e77ad 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -316,6 +316,23 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, } EXPORT_SYMBOL(inet_proto_csum_replace4); +/** + * inet_proto_csum_replace16 - update layer 4 header checksum field + * @sum: Layer 4 header checksum field + * @skb: sk_buff for the packet + * @from: old IPv6 address + * @to: new IPv6 address + * @pseudohdr: True if layer 4 header checksum includes pseudoheader + * + * Update layer 4 header as per the update in IPv6 src/dst address. + * + * There is no need to update skb->csum in this function, because update in two + * fields a.) IPv6 src/dst address and b.) L4 header checksum cancels each other + * for skb->csum calculation. Whereas inet_proto_csum_replace4 function needs to + * update skb->csum, because update in 3 fields a.) IPv4 src/dst address, + * b.) IPv4 Header checksum and c.) L4 header checksum results in same diff as + * L4 Header checksum for skb->csum calculation. + */ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, const __be32 *from, const __be32 *to, bool pseudohdr) @@ -327,9 +344,6 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, if (skb->ip_summed != CHECKSUM_PARTIAL) { *sum = csum_fold(csum_partial(diff, sizeof(diff), ~csum_unfold(*sum))); - if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) - skb->csum = ~csum_partial(diff, sizeof(diff), - ~skb->csum); } else if (pseudohdr) *sum = ~csum_fold(csum_partial(diff, sizeof(diff), csum_unfold(*sum))); diff --git a/net/dccp/feat.c b/net/dccp/feat.c index f227f002c73d382fecd98c8857ce4c9139cb7a8a..db87d9f5801983913e66549e5d5911ead10f3ac1 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -738,7 +738,12 @@ static int __feat_register_sp(struct list_head *fn, u8 feat, u8 is_local, if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len)) return -ENOMEM; - return dccp_feat_push_change(fn, feat, is_local, mandatory, &fval); + if (dccp_feat_push_change(fn, feat, is_local, mandatory, &fval)) { + kfree(fval.sp.vec); + return -ENOMEM; + } + + return 0; } /** diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c index 0c90cacee7aa7fe3fd309f0e693999215da3cc28..8108741cf8fb42311b6a0ca89864b26357fd63b5 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c @@ -40,9 +40,6 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) struct dsa_slave_priv *p = netdev_priv(dev); u16 *phdr, hdr; - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - if (skb_cow_head(skb, 0) < 0) goto out_free; diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 24d7aff8db1ac8afda0d8537fe0b84fe316bde06..204aa0131fbe611aa4e4da2b4caec5b79ed8b84f 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -238,7 +238,12 @@ int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 eth->h_proto = type; memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); memcpy(eth->h_dest, neigh->ha, ETH_ALEN); - hh->hh_len = ETH_HLEN; + + /* Pairs with READ_ONCE() in neigh_resolve_output(), + * neigh_hh_output() and neigh_update_hhs(). + */ + smp_store_release(&hh->hh_len, ETH_HLEN); + return 0; } EXPORT_SYMBOL(eth_header_cache); diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 52694cb759b08be0885d0cba291f1eb13e5fa51a..aead5ac4dbf680be1bc1fd06e26dc3dcd384b3cf 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -281,6 +281,8 @@ static void send_hsr_supervision_frame(struct hsr_port *master, skb->dev->dev_addr, skb->len) <= 0) goto out; skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); if (hsrVer > 0) { hsr_tag = (typeof(hsr_tag)) skb_put(skb, sizeof(struct hsr_tag)); diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index f5b60388d02fa255eb20362872be62eb96ce73ea..4ff6e02d8b733335b8d85fedb19f7f5eaa546e4e 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -31,6 +31,8 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) rcu_read_lock(); /* hsr->node_db, hsr->ports */ port = hsr_port_get_rcu(skb->dev); + if (!port) + goto finish_pass; if (hsr_addr_is_self(port->hsr, eth_hdr(skb)->h_source)) { /* Directly kill frames sent by ourselves */ diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index c01df341b5f646cdcdfc0b69e181220857e2db48..5936bfafb1c433da5ca715fd022b693b04d3b8ad 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c @@ -633,7 +633,7 @@ int __init lowpan_net_frag_init(void) void lowpan_net_frag_exit(void) { - inet_frags_fini(&lowpan_frags); lowpan_frags_sysctl_unregister(); unregister_pernet_subsys(&lowpan_frags_ops); + inet_frags_fini(&lowpan_frags); } diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 35c4326684548d88f408f84ded46ce6ac2d04ebc..040983fc15da37583fb5822df3cad04e3884948d 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c @@ -30,7 +30,13 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { [IEEE802154_ATTR_HW_ADDR] = { .type = NLA_HW_ADDR, }, [IEEE802154_ATTR_PAN_ID] = { .type = NLA_U16, }, [IEEE802154_ATTR_CHANNEL] = { .type = NLA_U8, }, + [IEEE802154_ATTR_BCN_ORD] = { .type = NLA_U8, }, + [IEEE802154_ATTR_SF_ORD] = { .type = NLA_U8, }, + [IEEE802154_ATTR_PAN_COORD] = { .type = NLA_U8, }, + [IEEE802154_ATTR_BAT_EXT] = { .type = NLA_U8, }, + [IEEE802154_ATTR_COORD_REALIGN] = { .type = NLA_U8, }, [IEEE802154_ATTR_PAGE] = { .type = NLA_U8, }, + [IEEE802154_ATTR_DEV_TYPE] = { .type = NLA_U8, }, [IEEE802154_ATTR_COORD_SHORT_ADDR] = { .type = NLA_U16, }, [IEEE802154_ATTR_COORD_HW_ADDR] = { .type = NLA_HW_ADDR, }, [IEEE802154_ATTR_COORD_PAN_ID] = { .type = NLA_U16, }, diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index 0b331ed45d96bdb784b0983b4465bb6e04fc8f6a..b4926aac84cc69f3c378a3cfc0fbdc66256e98f8 100755 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -2799,6 +2799,33 @@ static void do_read_data(struct kthread_work *work) hdr->control_flag, hdr->src_node_id, hdr->src_port_id, hdr->dst_node_id, hdr->dst_port_id); + /** + * update forwarding port information as well in routing + * table which will help to cleanup clients/services + * running in modem when MSM goes down + */ + rport_ptr = ipc_router_get_rport_ref(hdr->src_node_id, + hdr->src_port_id); + if (!rport_ptr) { + rport_ptr = + ipc_router_create_rport(hdr->src_node_id, + hdr->src_port_id, + xprt_info); + if (!rport_ptr) { + IPC_RTR_ERR( + "%s: Rmt Prt %08x:%08x create failed\n", + __func__, hdr->src_node_id, + hdr->src_port_id); + } + } + /** + * just to fail safe check is added, if rport + * allocation failed above we still forward the + * packet to remote. + */ + if (rport_ptr) + kref_put(&rport_ptr->ref, + ipc_router_release_rport); forward_msg(xprt_info, pkt); goto read_next_pkt1; } diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 71bcab94c5c7b2310f54e9370514e9f301d51227..0a6f72763bebed5be0d012cb66f69a1973c33017 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1738,6 +1738,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) { unsigned char optbuf[sizeof(struct ip_options) + 40]; struct ip_options *opt = (struct ip_options *)optbuf; + int res; if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) return; @@ -1749,7 +1750,11 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) memset(opt, 0, sizeof(struct ip_options)); opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr); - if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL)) + rcu_read_lock(); + res = __ip_options_compile(dev_net(skb->dev), opt, skb, NULL); + rcu_read_unlock(); + + if (res) return; if (gateway) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 9155cc5aee2079d7796c7e4dd6152a80605af460..e831ff51ac5b4c820d6b2478c893910eab6f0a0c 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1386,11 +1386,6 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) } } -static bool inetdev_valid_mtu(unsigned int mtu) -{ - return mtu >= IPV4_MIN_MTU; -} - static void inetdev_send_gratuitous_arp(struct net_device *dev, struct in_device *in_dev) diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index 7efe740c06ebff66d5e50f1cc067bc5973fc58e3..4a5e55e94a9e56546729c41fcdeae10d69186dcb 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c @@ -60,7 +60,9 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version) } EXPORT_SYMBOL_GPL(gre_del_protocol); -/* Fills in tpi and returns header length to be pulled. */ +/* Fills in tpi and returns header length to be pulled. + * Note that caller must use pskb_may_pull() before pulling GRE header. + */ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, bool *csum_err, __be16 proto, int nhs) { @@ -114,8 +116,14 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header */ if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { + u8 _val, *val; + + val = skb_header_pointer(skb, nhs + hdr_len, + sizeof(_val), &_val); + if (!val) + return -EINVAL; tpi->proto = proto; - if ((*(u8 *)options & 0xF0) != 0x40) + if ((*val & 0xF0) != 0x40) hdr_len += 4; } tpi->hdr_len = hdr_len; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 8a94cbc1274b58a5483eea42f2a5b6c9d5bad2d4..5dab15856ccd92c634e90c00e212ec5cb3b008fc 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -256,10 +256,11 @@ bool icmp_global_allow(void) bool rc = false; /* Check if token bucket is empty and cannot be refilled - * without taking the spinlock. + * without taking the spinlock. The READ_ONCE() are paired + * with the following WRITE_ONCE() in this same function. */ - if (!icmp_global.credit) { - delta = min_t(u32, now - icmp_global.stamp, HZ); + if (!READ_ONCE(icmp_global.credit)) { + delta = min_t(u32, now - READ_ONCE(icmp_global.stamp), HZ); if (delta < HZ / 50) return false; } @@ -269,14 +270,14 @@ bool icmp_global_allow(void) if (delta >= HZ / 50) { incr = sysctl_icmp_msgs_per_sec * delta / HZ ; if (incr) - icmp_global.stamp = now; + WRITE_ONCE(icmp_global.stamp, now); } credit = min_t(u32, icmp_global.credit + incr, sysctl_icmp_msgs_burst); if (credit) { credit--; rc = true; } - icmp_global.credit = credit; + WRITE_ONCE(icmp_global.credit, credit); spin_unlock(&icmp_global.lock); return rc; } diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index e4d16fc5bbb3fec077f8e3bb3ff8811a66046edc..4273576e1475446bdcf75f7a295c5702f828dc1f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -868,12 +868,13 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, for (i = s_i; i < INET_LHTABLE_SIZE; i++) { struct inet_listen_hashbucket *ilb; + struct hlist_nulls_node *node; struct sock *sk; num = 0; ilb = &hashinfo->listening_hash[i]; spin_lock_bh(&ilb->lock); - sk_for_each(sk, &ilb->head) { + sk_nulls_for_each(sk, node, &ilb->nulls_head) { struct inet_sock *inet = inet_sk(sk); if (!net_eq(sock_net(sk), net)) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index b9bcf3db3af98c233db2c17e3c8714463ffd119c..4bf542f4d9809ba93a9248ecbfb32d9bab1e55a6 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -218,9 +218,10 @@ struct sock *__inet_lookup_listener(struct net *net, int score, hiscore = 0, matches = 0, reuseport = 0; bool exact_dif = inet_exact_dif_match(net, skb); struct sock *sk, *result = NULL; + struct hlist_nulls_node *node; u32 phash = 0; - sk_for_each_rcu(sk, &ilb->head) { + sk_nulls_for_each_rcu(sk, node, &ilb->nulls_head) { score = compute_score(sk, net, hnum, daddr, dif, exact_dif); if (score > hiscore) { reuseport = sk->sk_reuseport; @@ -441,10 +442,11 @@ static int inet_reuseport_add_sock(struct sock *sk, bool match_wildcard)) { struct inet_bind_bucket *tb = inet_csk(sk)->icsk_bind_hash; + const struct hlist_nulls_node *node; struct sock *sk2; kuid_t uid = sock_i_uid(sk); - sk_for_each_rcu(sk2, &ilb->head) { + sk_nulls_for_each_rcu(sk2, node, &ilb->nulls_head) { if (sk2 != sk && sk2->sk_family == sk->sk_family && ipv6_only_sock(sk2) == ipv6_only_sock(sk) && @@ -482,9 +484,9 @@ int __inet_hash(struct sock *sk, struct sock *osk, } if (IS_ENABLED(CONFIG_IPV6) && sk->sk_reuseport && sk->sk_family == AF_INET6) - hlist_add_tail_rcu(&sk->sk_node, &ilb->head); + __sk_nulls_add_node_tail_rcu(sk, &ilb->nulls_head); else - hlist_add_head_rcu(&sk->sk_node, &ilb->head); + __sk_nulls_add_node_rcu(sk, &ilb->nulls_head); sock_set_flag(sk, SOCK_RCU_FREE); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); unlock: @@ -527,10 +529,7 @@ void inet_unhash(struct sock *sk) spin_lock_bh(lock); if (rcu_access_pointer(sk->sk_reuseport_cb)) reuseport_detach_sock(sk); - if (listener) - done = __sk_del_node_init(sk); - else - done = __sk_nulls_del_node_init_rcu(sk); + done = __sk_nulls_del_node_init_rcu(sk); if (done) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); spin_unlock_bh(lock); @@ -666,7 +665,8 @@ void inet_hashinfo_init(struct inet_hashinfo *h) for (i = 0; i < INET_LHTABLE_SIZE; i++) { spin_lock_init(&h->listening_hash[i].lock); - INIT_HLIST_HEAD(&h->listening_hash[i].head); + INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].nulls_head, + i + LISTENING_NULLS_BASE); } } EXPORT_SYMBOL_GPL(inet_hashinfo_init); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4d3ef370df85f6fafec84071812cc01c08990969..8eaf20a6046d78372712961920696895324e4d6b 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1181,13 +1181,17 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, rt = *rtp; if (unlikely(!rt)) return -EFAULT; - /* - * We steal reference to this route, caller should not release it - */ - *rtp = NULL; + cork->fragsize = ip_sk_use_pmtu(sk) ? - dst_mtu(&rt->dst) : rt->dst.dev->mtu; + dst_mtu(&rt->dst) : READ_ONCE(rt->dst.dev->mtu); + + if (!inetdev_valid_mtu(cork->fragsize)) + return -ENETUNREACH; + cork->dst = &rt->dst; + /* We stole this route, caller should not release it. */ + *rtp = NULL; + cork->length = 0; cork->ttl = ipc->ttl; cork->tos = ipc->tos; diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index a4db2d79b913429c7a97e137bb33981a644a490a..65c47b1f0da47dbdd2a35e232a15b29487103595 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -1184,10 +1184,8 @@ int ip_tunnel_init(struct net_device *dev) iph->version = 4; iph->ihl = 5; - if (tunnel->collect_md) { - dev->features |= NETIF_F_NETNS_LOCAL; + if (tunnel->collect_md) netif_keep_dst(dev); - } return 0; } EXPORT_SYMBOL_GPL(ip_tunnel_init); diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 4e39c935e057ea793f971b8fdbc21de97d427e9e..ec417156f388e51422e7869ac01eed82ef1985c6 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -208,8 +208,17 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, int mtu; if (!dst) { - dev->stats.tx_carrier_errors++; - goto tx_error_icmp; + struct rtable *rt; + + fl->u.ip4.flowi4_oif = dev->ifindex; + fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; + rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); + if (IS_ERR(rt)) { + dev->stats.tx_carrier_errors++; + goto tx_error_icmp; + } + dst = &rt->dst; + skb_dst_set(skb, dst); } dst_hold(dst); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index d35815e5967b567356fa5db1f86f1be9ad30ac03..e02b8626519424d5cac93a5dda41f31145427ade 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -403,10 +403,11 @@ next: ; return 1; } -static inline int check_target(struct arpt_entry *e, const char *name) +static int check_target(struct arpt_entry *e, struct net *net, const char *name) { struct xt_entry_target *t = arpt_get_target(e); struct xt_tgchk_param par = { + .net = net, .table = name, .entryinfo = e, .target = t->u.kernel.target, @@ -418,8 +419,9 @@ static inline int check_target(struct arpt_entry *e, const char *name) return xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false); } -static inline int -find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, +static int +find_check_entry(struct arpt_entry *e, struct net *net, const char *name, + unsigned int size, struct xt_percpu_counter_alloc_state *alloc_state) { struct xt_entry_target *t; @@ -438,7 +440,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, } t->u.kernel.target = target; - ret = check_target(e, name); + ret = check_target(e, net, name); if (ret) goto err; return 0; @@ -513,12 +515,13 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, return 0; } -static inline void cleanup_entry(struct arpt_entry *e) +static void cleanup_entry(struct arpt_entry *e, struct net *net) { struct xt_tgdtor_param par; struct xt_entry_target *t; t = arpt_get_target(e); + par.net = net; par.target = t->u.kernel.target; par.targinfo = t->data; par.family = NFPROTO_ARP; @@ -531,7 +534,9 @@ static inline void cleanup_entry(struct arpt_entry *e) /* Checks and translates the user-supplied table segment (held in * newinfo). */ -static int translate_table(struct xt_table_info *newinfo, void *entry0, +static int translate_table(struct net *net, + struct xt_table_info *newinfo, + void *entry0, const struct arpt_replace *repl) { struct xt_percpu_counter_alloc_state alloc_state = { 0 }; @@ -597,7 +602,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, repl->name, repl->size, + ret = find_check_entry(iter, net, repl->name, repl->size, &alloc_state); if (ret != 0) break; @@ -608,7 +613,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, xt_entry_foreach(iter, entry0, newinfo->size) { if (i-- == 0) break; - cleanup_entry(iter); + cleanup_entry(iter, net); } return ret; } @@ -935,7 +940,7 @@ static int __do_replace(struct net *net, const char *name, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries; xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) - cleanup_entry(iter); + cleanup_entry(iter, net); xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, @@ -987,7 +992,7 @@ static int do_replace(struct net *net, const void __user *user, goto free_newinfo; } - ret = translate_table(newinfo, loc_cpu_entry, &tmp); + ret = translate_table(net, newinfo, loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; @@ -999,7 +1004,7 @@ static int do_replace(struct net *net, const void __user *user, free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - cleanup_entry(iter); + cleanup_entry(iter, net); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1164,7 +1169,8 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, } } -static int translate_compat_table(struct xt_table_info **pinfo, +static int translate_compat_table(struct net *net, + struct xt_table_info **pinfo, void **pentry0, const struct compat_arpt_replace *compatr) { @@ -1230,7 +1236,7 @@ static int translate_compat_table(struct xt_table_info **pinfo, repl.num_counters = 0; repl.counters = NULL; repl.size = newinfo->size; - ret = translate_table(newinfo, entry1, &repl); + ret = translate_table(net, newinfo, entry1, &repl); if (ret) goto free_newinfo; @@ -1283,7 +1289,7 @@ static int compat_do_replace(struct net *net, void __user *user, goto free_newinfo; } - ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp); + ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; @@ -1295,7 +1301,7 @@ static int compat_do_replace(struct net *net, void __user *user, free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - cleanup_entry(iter); + cleanup_entry(iter, net); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1522,7 +1528,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len return ret; } -static void __arpt_unregister_table(struct xt_table *table) +static void __arpt_unregister_table(struct net *net, struct xt_table *table) { struct xt_table_info *private; void *loc_cpu_entry; @@ -1534,7 +1540,7 @@ static void __arpt_unregister_table(struct xt_table *table) /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries; xt_entry_foreach(iter, loc_cpu_entry, private->size) - cleanup_entry(iter); + cleanup_entry(iter, net); if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); @@ -1559,7 +1565,7 @@ int arpt_register_table(struct net *net, loc_cpu_entry = newinfo->entries; memcpy(loc_cpu_entry, repl->entries, repl->size); - ret = translate_table(newinfo, loc_cpu_entry, repl); + ret = translate_table(net, newinfo, loc_cpu_entry, repl); if (ret != 0) goto out_free; @@ -1574,7 +1580,7 @@ int arpt_register_table(struct net *net, ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks)); if (ret != 0) { - __arpt_unregister_table(new_table); + __arpt_unregister_table(net, new_table); *res = NULL; } @@ -1589,7 +1595,7 @@ void arpt_unregister_table(struct net *net, struct xt_table *table, const struct nf_hook_ops *ops) { nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); - __arpt_unregister_table(table); + __arpt_unregister_table(net, table); } /* The built-in targets: standard (NULL) and error. */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2fd3998ec985bd8f136a9e4baabfcc7787e16d0b..3fabbb5616f825b34db834bc4d6cac3104892b40 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2330,9 +2330,11 @@ int tcp_disconnect(struct sock *sk, int flags) tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tp->snd_cwnd_cnt = 0; tp->window_clamp = 0; + tp->delivered = 0; tcp_set_ca_state(sk, TCP_CA_Open); tp->is_sack_reneg = 0; tcp_clear_retrans(tp); + tp->total_retrans = 0; inet_csk_delack_init(sk); /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 * issue in __tcp_select_window() @@ -2344,8 +2346,12 @@ int tcp_disconnect(struct sock *sk, int flags) dst_release(sk->sk_rx_dst); sk->sk_rx_dst = NULL; tcp_saved_syn_free(tp); + tp->segs_in = 0; + tp->segs_out = 0; tp->bytes_acked = 0; tp->bytes_received = 0; + tp->data_segs_in = 0; + tp->data_segs_out = 0; /* Clean up fastopen related fields */ tcp_free_fastopen_req(tp); diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c index 7e44d23b03281624f413dfe2e25ff422bf34c7af..3bfab2d415749040951e3a18de9a5c3bce2f013d 100644 --- a/net/ipv4/tcp_bbr.c +++ b/net/ipv4/tcp_bbr.c @@ -649,8 +649,7 @@ static void bbr_update_bw(struct sock *sk, const struct rate_sample *rs) * bandwidth sample. Delivered is in packets and interval_us in uS and * ratio will be <<1 for most connections. So delivered is first scaled. */ - bw = (u64)rs->delivered * BW_UNIT; - do_div(bw, rs->interval_us); + bw = div64_long((u64)rs->delivered * BW_UNIT, rs->interval_us); /* If this sample is application-limited, it is likely to have a very * low delivered count that represents application behavior rather than diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 82ed99740fe51aa8a412a8f9f453c0cdd38dd347..00771c262aa06243e3bece2f3c99b85accd26d5c 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -130,7 +130,8 @@ int sysctl_tcp_default_init_rwnd __read_mostly = TCP_INIT_CWND * 2; #define REXMIT_LOST 1 /* retransmit packets marked lost */ #define REXMIT_NEW 2 /* FRTO-style transmit of unsent/new packets */ -static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb) +static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb, + unsigned int len) { static bool __once __read_mostly; @@ -141,8 +142,9 @@ static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb) rcu_read_lock(); dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif); - pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n", - dev ? dev->name : "Unknown driver"); + if (!dev || len >= dev->mtu) + pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n", + dev ? dev->name : "Unknown driver"); rcu_read_unlock(); } } @@ -165,8 +167,10 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) if (len >= icsk->icsk_ack.rcv_mss) { icsk->icsk_ack.rcv_mss = min_t(unsigned int, len, tcp_sk(sk)->advmss); - if (unlikely(icsk->icsk_ack.rcv_mss != len)) - tcp_gro_dev_warn(sk, skb); + /* Account for possibly-removed options */ + if (unlikely(len > icsk->icsk_ack.rcv_mss + + MAX_TCP_OPTION_SPACE)) + tcp_gro_dev_warn(sk, skb, len); } else { /* Otherwise, we make more careful check taking into account, * that SACKs block is variable. @@ -920,9 +924,10 @@ static void tcp_update_reordering(struct sock *sk, const int metric, /* This must be called before lost_out is incremented */ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) { - if (!tp->retransmit_skb_hint || - before(TCP_SKB_CB(skb)->seq, - TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) + if ((!tp->retransmit_skb_hint && tp->retrans_out >= tp->lost_out) || + (tp->retransmit_skb_hint && + before(TCP_SKB_CB(skb)->seq, + TCP_SKB_CB(tp->retransmit_skb_hint)->seq))) tp->retransmit_skb_hint = skb; if (!tp->lost_out || @@ -1742,8 +1747,11 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb, } /* Ignore very old stuff early */ - if (!after(sp[used_sacks].end_seq, prior_snd_una)) + if (!after(sp[used_sacks].end_seq, prior_snd_una)) { + if (i == 0) + first_sack_index = -1; continue; + } used_sacks++; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f9ad41c82e3cdaa54c0cd23b6ff6e4c1629c7d4d..78a25d6adc9d1ff93834ff43da1abac11c228530 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1927,13 +1927,14 @@ static void *listening_get_next(struct seq_file *seq, void *cur) struct tcp_iter_state *st = seq->private; struct net *net = seq_file_net(seq); struct inet_listen_hashbucket *ilb; + struct hlist_nulls_node *node; struct sock *sk = cur; if (!sk) { get_head: ilb = &tcp_hashinfo.listening_hash[st->bucket]; spin_lock_bh(&ilb->lock); - sk = sk_head(&ilb->head); + sk = sk_nulls_head(&ilb->nulls_head); st->offset = 0; goto get_sk; } @@ -1941,9 +1942,9 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ++st->num; ++st->offset; - sk = sk_next(sk); + sk = sk_nulls_next(sk); get_sk: - sk_for_each_from(sk) { + sk_nulls_for_each_from(sk, node) { if (!net_eq(sock_net(sk), net)) continue; if (sk->sk_family == st->family) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index bcf39c143b6605e69ca4aa247f0eedc9530fe42c..a7c86c8eacf36c5d70895fff6853edd5a20a1b61 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -707,8 +707,9 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb min_t(unsigned int, eff_sacks, (remaining - TCPOLEN_SACK_BASE_ALIGNED) / TCPOLEN_SACK_PERBLOCK); - size += TCPOLEN_SACK_BASE_ALIGNED + - opts->num_sack_blocks * TCPOLEN_SACK_PERBLOCK; + if (likely(opts->num_sack_blocks)) + size += TCPOLEN_SACK_BASE_ALIGNED + + opts->num_sack_blocks * TCPOLEN_SACK_PERBLOCK; } return size; @@ -2232,6 +2233,14 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, if (tcp_small_queue_check(sk, skb, 0)) break; + /* Argh, we hit an empty skb(), presumably a thread + * is sleeping in sendmsg()/sk_stream_wait_memory(). + * We do not want to send a pure-ack packet and have + * a strange looking rtx queue with empty packet(s). + */ + if (TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) + break; + if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp))) break; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index d9629228d7a82ce4e29559068b39ea6bf52f4d2f..95ee069482d9b0cc62b7b699baa5ab1bd45bc80a 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -404,7 +404,7 @@ static void tcp_probe_timer(struct sock *sk) return; } - if (icsk->icsk_probes_out > max_probes) { + if (icsk->icsk_probes_out >= max_probes) { abort: tcp_write_err(sk); } else { /* Only send another probe if we didn't close things up. */ @@ -510,11 +510,12 @@ void tcp_retransmit_timer(struct sock *sk) goto out_reset_timer; } + __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPTIMEOUTS); if (tcp_write_timeout(sk)) goto out; if (icsk->icsk_retransmits == 0) { - int mib_idx; + int mib_idx = 0; if (icsk->icsk_ca_state == TCP_CA_Recovery) { if (tcp_is_sack(tp)) @@ -529,10 +530,9 @@ void tcp_retransmit_timer(struct sock *sk) mib_idx = LINUX_MIB_TCPSACKFAILURES; else mib_idx = LINUX_MIB_TCPRENOFAILURES; - } else { - mib_idx = LINUX_MIB_TCPTIMEOUTS; } - __NET_INC_STATS(sock_net(sk), mib_idx); + if (mib_idx) + __NET_INC_STATS(sock_net(sk), mib_idx); } tcp_enter_loss(sk); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 162b0e3c82a9218a601b0bc98c87d8157e3466c9..016efd37749f896a4e3085fb3017db6486c41d53 100755 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3236,6 +3236,10 @@ static void addrconf_dev_config(struct net_device *dev) (dev->type != ARPHRD_NONE) && (dev->type != ARPHRD_RAWIP)) { /* Alas, we support only Ethernet autoconfiguration. */ + idev = __in6_dev_get(dev); + if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP && + dev->flags & IFF_MULTICAST) + ipv6_mc_up(idev); return; } diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 02761c9fe43eb306fa1887e577130e5abd2aa2b8..d47cab6d7c6de1afc1a69fcf186cbad76025a504 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -133,9 +133,10 @@ struct sock *inet6_lookup_listener(struct net *net, int score, hiscore = 0, matches = 0, reuseport = 0; bool exact_dif = inet6_exact_dif_match(net, skb); struct sock *sk, *result = NULL; + struct hlist_nulls_node *node; u32 phash = 0; - sk_for_each(sk, &ilb->head) { + sk_nulls_for_each(sk, node, &ilb->nulls_head) { score = compute_score(sk, net, hnum, daddr, dif, exact_dif); if (score > hiscore) { reuseport = sk->sk_reuseport; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 7ba9a6ebf19d925b5b1486d650a002f0ab14057a..f03855d35bd47a6516c0d84b00d40c85258469bd 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -784,8 +784,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, found++; break; } - if (rt_can_ecmp) - fallback_ins = fallback_ins ?: ins; + fallback_ins = fallback_ins ?: ins; goto next_iter; } @@ -825,7 +824,9 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, } if (fallback_ins && !found) { - /* No ECMP-able route found, replace first non-ECMP one */ + /* No matching route with same ecmp-able-ness found, replace + * first matching route + */ ins = fallback_ins; iter = *ins; found++; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 00f4023fa1a2fc4e2921c84bc267cffd641dd868..92399181ba252e756c7102672f9e402804d1fdd8 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1863,10 +1863,8 @@ static int ip6_tnl_dev_init(struct net_device *dev) if (err) return err; ip6_tnl_link_config(t); - if (t->parms.collect_md) { - dev->features |= NETIF_F_NETNS_LOCAL; + if (t->parms.collect_md) netif_keep_dst(dev); - } return 0; } diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index c88505dad64c471bd7b3470a718b7e3afddc02bc..9fbb7353a0618285b6abee9a6b34543100deabcb 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -453,8 +453,17 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) int err = -1; int mtu; - if (!dst) - goto tx_err_link_failure; + if (!dst) { + fl->u.ip6.flowi6_oif = dev->ifindex; + fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; + dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); + if (dst->error) { + dst_release(dst); + dst = NULL; + goto tx_err_link_failure; + } + skb_dst_set(skb, dst); + } dst_hold(dst); dst = xfrm_lookup(t->net, dst, fl, NULL, 0); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 81fd35ed8732c9f936ce02e73f281ec617331e91..1080770b5eaf50bb8b4488e85a14e1c2bb094043 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -184,9 +184,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, retv = -EBUSY; break; } - } else if (sk->sk_protocol != IPPROTO_TCP) + } else if (sk->sk_protocol == IPPROTO_TCP) { + if (sk->sk_prot != &tcpv6_prot) { + retv = -EBUSY; + break; + } break; - + } else { + break; + } if (sk->sk_state != TCP_ESTABLISHED) { retv = -ENOTCONN; break; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 4aed9c45a91ade2eb68cf90f47bcb37d7bd0088b..3f488555999e3018cb81edadeb2d60ae4699c4fa 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -592,8 +592,8 @@ int __init ipv6_frag_init(void) void ipv6_frag_exit(void) { - inet_frags_fini(&ip6_frags); ip6_frags_sysctl_unregister(); unregister_pernet_subsys(&ip6_frags_ops); inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); + inet_frags_fini(&ip6_frags); } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 4f808aa7086091d1df252680f46d25f92066e4f4..c1f007aaa63731774ad857508f38680719aaba11 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3035,6 +3035,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg) */ 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/iucv/af_iucv.c b/net/iucv/af_iucv.c index c2dfc32eb9f21a2b15898f166ab13a297e989dea..02e10deef5b45fd700992748ef610793d58d86cf 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -2431,6 +2431,13 @@ static int afiucv_iucv_init(void) return err; } +static void afiucv_iucv_exit(void) +{ + device_unregister(af_iucv_dev); + driver_unregister(&af_iucv_driver); + pr_iucv->iucv_unregister(&af_iucv_handler, 0); +} + static int __init afiucv_init(void) { int err; @@ -2464,11 +2471,18 @@ static int __init afiucv_init(void) err = afiucv_iucv_init(); if (err) goto out_sock; - } else - register_netdevice_notifier(&afiucv_netdev_notifier); + } + + err = register_netdevice_notifier(&afiucv_netdev_notifier); + if (err) + goto out_notifier; + dev_add_pack(&iucv_packet_type); return 0; +out_notifier: + if (pr_iucv) + afiucv_iucv_exit(); out_sock: sock_unregister(PF_IUCV); out_proto: @@ -2482,12 +2496,11 @@ static int __init afiucv_init(void) static void __exit afiucv_exit(void) { if (pr_iucv) { - device_unregister(af_iucv_dev); - driver_unregister(&af_iucv_driver); - pr_iucv->iucv_unregister(&af_iucv_handler, 0); + afiucv_iucv_exit(); symbol_put(iucv_if); - } else - unregister_netdevice_notifier(&afiucv_netdev_notifier); + } + + unregister_netdevice_notifier(&afiucv_netdev_notifier); dev_remove_pack(&iucv_packet_type); sock_unregister(PF_IUCV); proto_unregister(&iucv_proto); diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index daa3209303119e27f52a42de29ef24750d915bd7..46a6a3c89efbdd81ee93e964880f9ae0e456a153 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1939,7 +1939,8 @@ static __net_exit void l2tp_exit_net(struct net *net) } rcu_read_unlock_bh(); - flush_workqueue(l2tp_wq); + if (l2tp_wq) + flush_workqueue(l2tp_wq); rcu_barrier(); } diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 789e66b0187a41db54127038a69657c018a9ae73..2a859f967c8af3b080fdbfbf62984abce8d69739 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -111,22 +111,26 @@ static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr) * * Send data via reliable llc2 connection. * Returns 0 upon success, non-zero if action did not succeed. + * + * This function always consumes a reference to the skb. */ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) { struct llc_sock* llc = llc_sk(sk); - int rc = 0; if (unlikely(llc_data_accept_state(llc->state) || llc->remote_busy_flag || llc->p_flag)) { long timeout = sock_sndtimeo(sk, noblock); + int rc; rc = llc_ui_wait_for_busy_core(sk, timeout); + if (rc) { + kfree_skb(skb); + return rc; + } } - if (unlikely(!rc)) - rc = llc_build_and_send_pkt(sk, skb); - return rc; + return llc_build_and_send_pkt(sk, skb); } static void llc_ui_sk_init(struct socket *sock, struct sock *sk) @@ -896,7 +900,7 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name); int flags = msg->msg_flags; int noblock = flags & MSG_DONTWAIT; - struct sk_buff *skb; + struct sk_buff *skb = NULL; size_t size = 0; int rc = -EINVAL, copied = 0, hdrlen; @@ -905,10 +909,10 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) lock_sock(sk); if (addr) { if (msg->msg_namelen < sizeof(*addr)) - goto release; + goto out; } else { if (llc_ui_addr_null(&llc->addr)) - goto release; + goto out; addr = &llc->addr; } /* must bind connection to sap if user hasn't done it. */ @@ -916,7 +920,7 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) /* bind to sap with null dev, exclusive. */ rc = llc_ui_autobind(sock, addr); if (rc) - goto release; + goto out; } hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr); size = hdrlen + len; @@ -925,12 +929,12 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) copied = size - hdrlen; rc = -EINVAL; if (copied < 0) - goto release; + goto out; release_sock(sk); skb = sock_alloc_send_skb(sk, size, noblock, &rc); lock_sock(sk); if (!skb) - goto release; + goto out; skb->dev = llc->dev; skb->protocol = llc_proto_type(addr->sllc_arphrd); skb_reserve(skb, hdrlen); @@ -940,29 +944,31 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (sk->sk_type == SOCK_DGRAM || addr->sllc_ua) { llc_build_and_send_ui_pkt(llc->sap, skb, addr->sllc_mac, addr->sllc_sap); + skb = NULL; goto out; } if (addr->sllc_test) { llc_build_and_send_test_pkt(llc->sap, skb, addr->sllc_mac, addr->sllc_sap); + skb = NULL; goto out; } if (addr->sllc_xid) { llc_build_and_send_xid_pkt(llc->sap, skb, addr->sllc_mac, addr->sllc_sap); + skb = NULL; goto out; } rc = -ENOPROTOOPT; if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua)) goto out; rc = llc_ui_send_data(sk, skb, noblock); + skb = NULL; out: - if (rc) { - kfree_skb(skb); -release: + kfree_skb(skb); + if (rc) dprintk("%s: failed sending from %02X to %02X: %d\n", __func__, llc->laddr.lsap, llc->daddr.lsap, rc); - } release_sock(sk); return rc ? : copied; } diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 94c78cc49d3e02acea615fd39cc7147158c52c36..1bdbd134bd7a8a7254a3ab5ac5bde26bf5fd88ff 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -55,6 +55,8 @@ int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ; * (executing it's actions and changing state), upper layer will be * indicated or confirmed, if needed. Returns 0 for success, 1 for * failure. The socket lock has to be held before calling this function. + * + * This function always consumes a reference to the skb. */ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) { @@ -62,12 +64,6 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) struct llc_sock *llc = llc_sk(skb->sk); struct llc_conn_state_ev *ev = llc_conn_ev(skb); - /* - * We have to hold the skb, because llc_conn_service will kfree it in - * the sending path and we need to look at the skb->cb, where we encode - * llc_conn_state_ev. - */ - skb_get(skb); ev->ind_prim = ev->cfm_prim = 0; /* * Send event to state machine @@ -75,21 +71,12 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) rc = llc_conn_service(skb->sk, skb); if (unlikely(rc != 0)) { printk(KERN_ERR "%s: llc_conn_service failed\n", __func__); - goto out_kfree_skb; - } - - if (unlikely(!ev->ind_prim && !ev->cfm_prim)) { - /* indicate or confirm not required */ - if (!skb->next) - goto out_kfree_skb; goto out_skb_put; } - if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */ - skb_get(skb); - switch (ev->ind_prim) { case LLC_DATA_PRIM: + skb_get(skb); llc_save_primitive(sk, skb, LLC_DATA_PRIM); if (unlikely(sock_queue_rcv_skb(sk, skb))) { /* @@ -106,6 +93,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) * skb->sk pointing to the newly created struct sock in * llc_conn_handler. -acme */ + skb_get(skb); skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_state_change(sk); break; @@ -121,7 +109,6 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) sk->sk_state_change(sk); } } - kfree_skb(skb); sock_put(sk); break; case LLC_RESET_PRIM: @@ -130,14 +117,11 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) * RESET is not being notified to upper layers for now */ printk(KERN_INFO "%s: received a reset ind!\n", __func__); - kfree_skb(skb); break; default: - if (ev->ind_prim) { + if (ev->ind_prim) printk(KERN_INFO "%s: received unknown %d prim!\n", __func__, ev->ind_prim); - kfree_skb(skb); - } /* No indication */ break; } @@ -179,15 +163,12 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) printk(KERN_INFO "%s: received a reset conf!\n", __func__); break; default: - if (ev->cfm_prim) { + if (ev->cfm_prim) printk(KERN_INFO "%s: received unknown %d prim!\n", __func__, ev->cfm_prim); - break; - } - goto out_skb_put; /* No confirmation */ + /* No confirmation */ + break; } -out_kfree_skb: - kfree_skb(skb); out_skb_put: kfree_skb(skb); return rc; diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c index 6daf391b3e847db42396caf9fbbfe7dca6440006..fc4d2bd8816f5aa95642b67d47e9cee3d77268e9 100644 --- a/net/llc/llc_if.c +++ b/net/llc/llc_if.c @@ -38,6 +38,8 @@ * closed and -EBUSY when sending data is not permitted in this state or * LLC has send an I pdu with p bit set to 1 and is waiting for it's * response. + * + * This function always consumes a reference to the skb. */ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) { @@ -46,20 +48,22 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) struct llc_sock *llc = llc_sk(sk); if (unlikely(llc->state == LLC_CONN_STATE_ADM)) - goto out; + goto out_free; rc = -EBUSY; if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */ llc->p_flag)) { llc->failed_data_req = 1; - goto out; + goto out_free; } ev = llc_conn_ev(skb); ev->type = LLC_CONN_EV_TYPE_PRIM; ev->prim = LLC_DATA_PRIM; ev->prim_type = LLC_PRIM_TYPE_REQ; skb->dev = llc->dev; - rc = llc_conn_state_process(sk, skb); -out: + return llc_conn_state_process(sk, skb); + +out_free: + kfree_skb(skb); return rc; } diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 204a8351efffc86f566e51b27f173c8bdee6c4cb..c29170e767a8ca3964c8958cc99db5893302b4f1 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -32,7 +32,7 @@ static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb) return LLC_PDU_IS_CMD(pdu) && /* command PDU */ LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID && - !pdu->dsap ? 0 : 1; /* NULL DSAP value */ + !pdu->dsap; /* NULL DSAP value */ } static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb) @@ -42,7 +42,7 @@ static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb) return LLC_PDU_IS_CMD(pdu) && /* command PDU */ LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST && - !pdu->dsap ? 0 : 1; /* NULL DSAP */ + !pdu->dsap; /* NULL DSAP */ } static int llc_station_ac_send_xid_r(struct sk_buff *skb) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3b2c4692d966fa5487a3bc09ae0815a8abf7a06a..88dd5d218fe30e5cbe7ce3a6f136560b83b1add9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1048,50 +1048,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) return 0; } -/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ -struct iapp_layer2_update { - u8 da[ETH_ALEN]; /* broadcast */ - u8 sa[ETH_ALEN]; /* STA addr */ - __be16 len; /* 6 */ - u8 dsap; /* 0 */ - u8 ssap; /* 0 */ - u8 control; - u8 xid_info[3]; -} __packed; - -static void ieee80211_send_layer2_update(struct sta_info *sta) -{ - struct iapp_layer2_update *msg; - struct sk_buff *skb; - - /* Send Level 2 Update Frame to update forwarding tables in layer 2 - * bridge devices */ - - skb = dev_alloc_skb(sizeof(*msg)); - if (!skb) - return; - msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg)); - - /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) - * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ - - eth_broadcast_addr(msg->da); - memcpy(msg->sa, sta->sta.addr, ETH_ALEN); - msg->len = htons(6); - msg->dsap = 0; - msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ - msg->control = 0xaf; /* XID response lsb.1111F101. - * F=0 (no poll command; unsolicited frame) */ - msg->xid_info[0] = 0x81; /* XID format identifier */ - msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ - msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ - - skb->dev = sta->sdata->dev; - skb->protocol = eth_type_trans(skb, sta->sdata->dev); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx_ni(skb); -} - static int sta_apply_auth_flags(struct ieee80211_local *local, struct sta_info *sta, u32 mask, u32 set) @@ -1401,7 +1357,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, struct sta_info *sta; struct ieee80211_sub_if_data *sdata; int err; - int layer2_update; if (params->vlan) { sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); @@ -1445,18 +1400,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, test_sta_flag(sta, WLAN_STA_ASSOC)) rate_control_rate_init(sta); - layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || - sdata->vif.type == NL80211_IFTYPE_AP; - err = sta_info_insert_rcu(sta); if (err) { rcu_read_unlock(); return err; } - if (layer2_update) - ieee80211_send_layer2_update(sta); - rcu_read_unlock(); return 0; @@ -1565,7 +1514,9 @@ static int ieee80211_change_station(struct wiphy *wiphy, atomic_inc(&sta->sdata->bss->num_mcast_sta); } - ieee80211_send_layer2_update(sta); + if (sta->sta_state == IEEE80211_STA_AUTHORIZED) + cfg80211_send_layer2_update(sta->sdata->dev, + sta->sta.addr); } err = sta_apply_parameters(local, sta, params); diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index b0acb2961e805df66dcc6a3be80c929f6bd21649..5f4c228b82e5635d64acf424aeca72671077411c 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -326,6 +326,9 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, u32 tx_time, estimated_retx; u64 result; + if (sta->mesh->plink_state != NL80211_PLINK_ESTAB) + return MAX_METRIC; + /* Try to get rate based on HW/SW RC algorithm. * Rate is returned in units of Kbps, correct this * to comply with airtime calculation units diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 593184d14b3ef69f86df63fb7feb7ed33185a310..e1b0e26c1f17476f2e89509c6d92d21460f7850f 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -547,7 +547,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) /* (re)Initialize group rate indexes */ for(j = 0; j < MAX_THR_RATES; j++) - tmp_group_tp_rate[j] = group; + tmp_group_tp_rate[j] = MCS_GROUP_RATES * group; for (i = 0; i < MCS_GROUP_RATES; i++) { if (!(mg->supported & BIT(i))) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3b423c50ec8fa5343e7dc90a760b4699a25bface..a6f265262f151a1773392f63b0333812341df444 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3205,9 +3205,18 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): /* process for all: mesh, mlme, ibss */ break; + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + if (is_multicast_ether_addr(mgmt->da) && + !is_broadcast_ether_addr(mgmt->da)) + return RX_DROP_MONITOR; + + /* process only for station/IBSS */ + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) + return RX_DROP_MONITOR; + break; case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): case cpu_to_le16(IEEE80211_STYPE_DISASSOC): if (is_multicast_ether_addr(mgmt->da) && !is_broadcast_ether_addr(mgmt->da)) @@ -3832,7 +3841,7 @@ void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata) lockdep_assert_held(&local->sta_mtx); - list_for_each_entry_rcu(sta, &local->sta_list, list) { + list_for_each_entry(sta, &local->sta_list, list) { if (sdata != sta->sdata && (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) continue; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8e8a185dbb9b13507e9909c1790946074d37e09d..c800bc7c517630f96fb4b5bf436a436b3cc3dd75 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1896,6 +1896,10 @@ int sta_info_move_state(struct sta_info *sta, ieee80211_check_fast_xmit(sta); ieee80211_check_fast_rx(sta); } + if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN || + sta->sdata->vif.type == NL80211_IFTYPE_AP) + cfg80211_send_layer2_update(sta->sdata->dev, + sta->sta.addr); break; default: break; diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index b3622823bad23b9a34a58b09fea1dd3e067bbcf2..ebd66e8f46b3f81b017719a99066c14e3f1fdebe 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -266,9 +266,21 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, if ((keyid >> 6) != key->conf.keyidx) return TKIP_DECRYPT_INVALID_KEYIDX; - if (rx_ctx->ctx.state != TKIP_STATE_NOT_INIT && - (iv32 < rx_ctx->iv32 || - (iv32 == rx_ctx->iv32 && iv16 <= rx_ctx->iv16))) + /* Reject replays if the received TSC is smaller than or equal to the + * last received value in a valid message, but with an exception for + * the case where a new key has been set and no valid frame using that + * key has yet received and the local RSC was initialized to 0. This + * exception allows the very first frame sent by the transmitter to be + * accepted even if that transmitter were to use TSC 0 (IEEE 802.11 + * described TSC to be initialized to 1 whenever a new key is taken into + * use). + */ + if (iv32 < rx_ctx->iv32 || + (iv32 == rx_ctx->iv32 && + (iv16 < rx_ctx->iv16 || + (iv16 == rx_ctx->iv16 && + (rx_ctx->iv32 || rx_ctx->iv16 || + rx_ctx->ctx.state != TKIP_STATE_NOT_INIT))))) return TKIP_DECRYPT_REPLAY; if (only_iv) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0bb144cc93ad1e4c6aff428e040e9fa206956946..9dff79418cd3504b0db57f58ed42ae72fbe8f03a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -943,16 +943,22 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, elem_parse_failed = true; break; case WLAN_EID_VHT_OPERATION: - if (elen >= sizeof(struct ieee80211_vht_operation)) + if (elen >= sizeof(struct ieee80211_vht_operation)) { elems->vht_operation = (void *)pos; - else - elem_parse_failed = true; + if (calc_crc) + crc = crc32_be(crc, pos - 2, elen + 2); + break; + } + elem_parse_failed = true; break; case WLAN_EID_OPMODE_NOTIF: - if (elen > 0) + if (elen > 0) { elems->opmode_notif = pos; - else - elem_parse_failed = true; + if (calc_crc) + crc = crc32_be(crc, pos - 2, elen + 2); + break; + } + elem_parse_failed = true; break; case WLAN_EID_MESH_ID: elems->mesh_id = pos; diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h index 2e8e7e5fb4a64344ccb8f80b03607cc9b7f81053..7536cdd2da28e46f15a42b4f69772d4989041fa1 100644 --- a/net/netfilter/ipset/ip_set_bitmap_gen.h +++ b/net/netfilter/ipset/ip_set_bitmap_gen.h @@ -66,9 +66,9 @@ mtype_destroy(struct ip_set *set) if (SET_WITH_TIMEOUT(set)) del_timer_sync(&map->gc); - ip_set_free(map->members); if (set->dsize && set->extensions & IPSET_EXT_DESTROY) mtype_ext_cleanup(set); + ip_set_free(map->members); ip_set_free(map); set->data = NULL; @@ -81,7 +81,7 @@ mtype_flush(struct ip_set *set) if (set->extensions & IPSET_EXT_DESTROY) mtype_ext_cleanup(set); - memset(map->members, 0, map->memsize); + bitmap_zero(map->members, map->elements); } static int diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c index 4783efff0bde6b7c70707c8153563669308d995a..a4c104a4977fd9fd129dfe0553f98328f09ac189 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c @@ -40,7 +40,7 @@ MODULE_ALIAS("ip_set_bitmap:ip"); /* Type structure */ struct bitmap_ip { - void *members; /* the set members */ + unsigned long *members; /* the set members */ u32 first_ip; /* host byte order, included in range */ u32 last_ip; /* host byte order, included in range */ u32 elements; /* number of max elements in the set */ @@ -222,7 +222,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map, u32 first_ip, u32 last_ip, u32 elements, u32 hosts, u8 netmask) { - map->members = ip_set_alloc(map->memsize); + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); if (!map->members) return false; map->first_ip = first_ip; @@ -315,7 +315,7 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], if (!map) return -ENOMEM; - map->memsize = bitmap_bytes(0, elements - 1); + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); set->variant = &bitmap_ip; if (!init_map_ip(set, map, first_ip, last_ip, elements, hosts, netmask)) { diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index 9a065f672d3a56f33a22e38937780ab59d318c13..8e58e7e349819c4f1bf71a5b0af1f6a6b93fea07 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c @@ -46,7 +46,7 @@ enum { /* Type structure */ struct bitmap_ipmac { - void *members; /* the set members */ + unsigned long *members; /* the set members */ u32 first_ip; /* host byte order, included in range */ u32 last_ip; /* host byte order, included in range */ u32 elements; /* number of max elements in the set */ @@ -299,7 +299,7 @@ static bool init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, u32 first_ip, u32 last_ip, u32 elements) { - map->members = ip_set_alloc(map->memsize); + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); if (!map->members) return false; map->first_ip = first_ip; @@ -363,7 +363,7 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[], if (!map) return -ENOMEM; - map->memsize = bitmap_bytes(0, elements - 1); + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); set->variant = &bitmap_ipmac; if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) { kfree(map); diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c index 7f0c733358a428225e15afe611aad1edcd52812a..6771b362a123ae8a66fad97b3188f75fe159fafb 100644 --- a/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/net/netfilter/ipset/ip_set_bitmap_port.c @@ -34,7 +34,7 @@ MODULE_ALIAS("ip_set_bitmap:port"); /* Type structure */ struct bitmap_port { - void *members; /* the set members */ + unsigned long *members; /* the set members */ u16 first_port; /* host byte order, included in range */ u16 last_port; /* host byte order, included in range */ u32 elements; /* number of max elements in the set */ @@ -207,7 +207,7 @@ static bool init_map_port(struct ip_set *set, struct bitmap_port *map, u16 first_port, u16 last_port) { - map->members = ip_set_alloc(map->memsize); + map->members = bitmap_zalloc(map->elements, GFP_KERNEL | __GFP_NOWARN); if (!map->members) return false; map->first_port = first_port; @@ -250,7 +250,7 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[], return -ENOMEM; map->elements = elements; - map->memsize = bitmap_bytes(0, map->elements); + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); set->variant = &bitmap_port; if (!init_map_port(set, map, first_port, last_port)) { kfree(map); diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index fa5229fd370372f74d270f3e39ec7dc0d8dfc52f..f64660e9ff8799028325d581ba03180f9fc6f228 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -1634,6 +1634,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb, struct ip_set *set; struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; int ret = 0; + u32 lineno; if (unlikely(protocol_failed(attr) || !attr[IPSET_ATTR_SETNAME] || @@ -1650,7 +1651,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb, return -IPSET_ERR_PROTOCOL; rcu_read_lock_bh(); - ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0); + ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0); rcu_read_unlock_bh(); /* Userspace can't trigger element to be re-added */ if (ret == -EAGAIN) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 2f1efcd33ae3cf407a888d9fc6d0288219066620..65695824e10c9e7ea3600ff7699ae51344f97a32 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -3403,6 +3403,9 @@ static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list) list_for_each_entry(net, net_exit_list, exit_list) ctnetlink_net_exit(net); + + /* wait for other cpus until they are done with ctnl_notifiers */ + synchronize_rcu(); } static struct pernet_operations ctnetlink_net_ops = { diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 3f499126727c8e9b4b9016a62938c4fea50b8903..8396dc8ee24748621b2590a7e660891a8f4b532b 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -711,6 +711,8 @@ static const struct nla_policy nfnl_cthelper_policy[NFCTH_MAX+1] = { [NFCTH_NAME] = { .type = NLA_NUL_STRING, .len = NF_CT_HELPER_NAME_LEN-1 }, [NFCTH_QUEUE_NUM] = { .type = NLA_U32, }, + [NFCTH_PRIV_DATA_LEN] = { .type = NLA_U32, }, + [NFCTH_STATUS] = { .type = NLA_U32, }, }; static const struct nfnl_callback nfnl_cthelper_cb[NFNL_MSG_CTHELPER_MAX] = { diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index a1a29cdc58fc0c86a05caefd483f4dfeac7bf1c3..140a9ae262ef8b9ca3d7f346a00f8efdebe54b74 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -735,6 +735,8 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) return hashlimit_mt_common(skb, par, hinfo, &info->cfg, 2); } +#define HASHLIMIT_MAX_SIZE 1048576 + static int hashlimit_mt_check_common(const struct xt_mtchk_param *par, struct xt_hashlimit_htable **hinfo, struct hashlimit_cfg2 *cfg, @@ -745,6 +747,14 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par, if (cfg->gc_interval == 0 || cfg->expire == 0) return -EINVAL; + if (cfg->size > HASHLIMIT_MAX_SIZE) { + cfg->size = HASHLIMIT_MAX_SIZE; + pr_info_ratelimited("size too large, truncated to %u\n", cfg->size); + } + if (cfg->max > HASHLIMIT_MAX_SIZE) { + cfg->max = HASHLIMIT_MAX_SIZE; + pr_info_ratelimited("max too large, truncated to %u\n", cfg->max); + } if (par->family == NFPROTO_IPV4) { if (cfg->srcmask > 32 || cfg->dstmask > 32) return -EINVAL; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 0254874364381f4fb8144ddee2da179268dbde03..205865292ba342ad67b0288ef1c398681e55f9cc 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1003,7 +1003,8 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, if (nlk->netlink_bind && groups) { int group; - for (group = 0; group < nlk->ngroups; group++) { + /* nl_groups is a u32, so cap the maximum groups we can bind */ + for (group = 0; group < BITS_PER_TYPE(u32); group++) { if (!test_bit(group, &groups)) continue; err = nlk->netlink_bind(net, group + 1); @@ -1022,7 +1023,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, netlink_insert(sk, nladdr->nl_pid) : netlink_autobind(sock); if (err) { - netlink_undo_bind(nlk->ngroups, groups, sk); + netlink_undo_bind(BITS_PER_TYPE(u32), groups, sk); return err; } } diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 5a58f9f380958f886de0f41bb0f34e07fb0502ae..291f24fef19aa1e58f1f9ec5b35413aabaffd384 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -193,13 +193,20 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, struct sk_buff *skb) { - u8 gate = hdev->pipes[pipe].gate; u8 status = NFC_HCI_ANY_OK; struct hci_create_pipe_resp *create_info; struct hci_delete_pipe_noti *delete_info; struct hci_all_pipe_cleared_noti *cleared_info; + u8 gate; - pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd); + pr_debug("from pipe %x cmd %x\n", pipe, cmd); + + if (pipe >= NFC_HCI_MAX_PIPES) { + status = NFC_HCI_ANY_E_NOK; + goto exit; + } + + gate = hdev->pipes[pipe].gate; switch (cmd) { case NFC_HCI_ADM_NOTIFY_PIPE_CREATED: @@ -387,8 +394,14 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, struct sk_buff *skb) { int r = 0; - u8 gate = hdev->pipes[pipe].gate; + u8 gate; + + if (pipe >= NFC_HCI_MAX_PIPES) { + pr_err("Discarded event %x to invalid pipe %x\n", event, pipe); + goto exit; + } + gate = hdev->pipes[pipe].gate; if (gate == NFC_HCI_INVALID_GATE) { pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); goto exit; diff --git a/net/nfc/nci/uart.c b/net/nfc/nci/uart.c index c468eabd69430b1687d0b68b086e4883afc74bf9..90268b6429077440f2fad2b2f3ba8b852dc6ed3e 100644 --- a/net/nfc/nci/uart.c +++ b/net/nfc/nci/uart.c @@ -348,7 +348,7 @@ static int nci_uart_default_recv_buf(struct nci_uart *nu, const u8 *data, nu->rx_packet_len = -1; nu->rx_skb = nci_skb_alloc(nu->ndev, NCI_MAX_PACKET_SIZE, - GFP_KERNEL); + GFP_ATOMIC); if (!nu->rx_skb) return -ENOMEM; } diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index d3c8dd5dc817b414a633ad73e69fd0cfb13113bf..e79a49fe61e88d4eff10132b281eaf51bdad2dd1 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -62,7 +62,10 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, .len = NFC_FIRMWARE_NAME_MAXSIZE }, + [NFC_ATTR_SE_INDEX] = { .type = NLA_U32 }, [NFC_ATTR_SE_APDU] = { .type = NLA_BINARY }, + [NFC_ATTR_VENDOR_ID] = { .type = NLA_U32 }, + [NFC_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 }, [NFC_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, }; diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 02d6f38f786960edaf2a9dca340221865314ce14..beb2897d8ddf5a436bc3cefb9d29a06d5fa643a0 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -709,6 +709,17 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key, } err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype); + if (err == NF_ACCEPT && + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) { + if (maniptype == NF_NAT_MANIP_SRC) + maniptype = NF_NAT_MANIP_DST; + else + maniptype = NF_NAT_MANIP_SRC; + + err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, + maniptype); + } + /* Mark NAT done if successful and update the flow key. */ if (err == NF_ACCEPT) ovs_nat_update_key(key, skb, maniptype); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e3f0a17bdbbcb29f5216a4e36c96fe23e54be80c..802fe548d621ebf25a18792dde1efc9fcfcab747 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -587,7 +587,8 @@ static int prb_calc_retire_blk_tmo(struct packet_sock *po, msec = 1; div = ecmd.base.speed / 1000; } - } + } else + return DEFAULT_PRB_RETIRE_TOV; mbits = (blk_size_in_bytes * 8) / (1024 * 1024); @@ -1331,15 +1332,21 @@ static void packet_sock_destruct(struct sock *sk) static bool fanout_flow_is_huge(struct packet_sock *po, struct sk_buff *skb) { - u32 rxhash; + u32 *history = po->rollover->history; + u32 victim, rxhash; int i, count = 0; rxhash = skb_get_hash(skb); for (i = 0; i < ROLLOVER_HLEN; i++) - if (po->rollover->history[i] == rxhash) + if (READ_ONCE(history[i]) == rxhash) count++; - po->rollover->history[prandom_u32() % ROLLOVER_HLEN] = rxhash; + victim = prandom_u32() % ROLLOVER_HLEN; + + /* Avoid dirtying the cache line if possible */ + if (READ_ONCE(history[victim]) != rxhash) + WRITE_ONCE(history[victim], rxhash); + return count > (ROLLOVER_HLEN >> 1); } @@ -3403,20 +3410,29 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, sock_recv_ts_and_drops(msg, sk, skb); if (msg->msg_name) { + int copy_len; + /* If the address length field is there to be filled * in, we fill it in now. */ if (sock->type == SOCK_PACKET) { __sockaddr_check_size(sizeof(struct sockaddr_pkt)); msg->msg_namelen = sizeof(struct sockaddr_pkt); + copy_len = msg->msg_namelen; } else { struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll; msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); + copy_len = msg->msg_namelen; + if (msg->msg_namelen < sizeof(struct sockaddr_ll)) { + memset(msg->msg_name + + offsetof(struct sockaddr_ll, sll_addr), + 0, sizeof(sll->sll_addr)); + msg->msg_namelen = sizeof(struct sockaddr_ll); + } } - memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, - msg->msg_namelen); + memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, copy_len); } if (pkt_sk(sk)->auxdata) { diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index ee930b3011ccf81190afea89dc522b4031fae49b..a419201a5cf4a0e9a298e4b6e3ed6b7c20efd688 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -26,18 +26,6 @@ #define QRTR_MIN_EPH_SOCKET 0x4000 #define QRTR_MAX_EPH_SOCKET 0x7fff -enum qrtr_pkt_type { - QRTR_TYPE_DATA = 1, - QRTR_TYPE_HELLO = 2, - QRTR_TYPE_BYE = 3, - QRTR_TYPE_NEW_SERVER = 4, - QRTR_TYPE_DEL_SERVER = 5, - QRTR_TYPE_DEL_CLIENT = 6, - QRTR_TYPE_RESUME_TX = 7, - QRTR_TYPE_EXIT = 8, - QRTR_TYPE_PING = 9, -}; - /** * struct qrtr_hdr - (I|R)PCrouter packet header * @version: protocol version @@ -61,8 +49,6 @@ struct qrtr_hdr { } __packed; #define QRTR_HDR_SIZE sizeof(struct qrtr_hdr) -#define QRTR_NODE_BCAST ((unsigned int)-1) -#define QRTR_PORT_CTRL ((unsigned int)-2) struct qrtr_sock { /* WARNING: sk must be the first member */ diff --git a/net/rds/ib_stats.c b/net/rds/ib_stats.c index 7e78dca1f252c671741443cdf660f38da6c575a0..aaf4b3d1020394987d5e02c1a7f658f826c9ce0a 100644 --- a/net/rds/ib_stats.c +++ b/net/rds/ib_stats.c @@ -42,7 +42,7 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_ib_statistics, rds_ib_stats); static const char *const rds_ib_stat_names[] = { "ib_connect_raced", "ib_listen_closed_stale", - "s_ib_evt_handler_call", + "ib_evt_handler_call", "ib_tasklet_call", "ib_tx_cq_event", "ib_tx_ring_full", diff --git a/net/rfkill/core.c b/net/rfkill/core.c index a9a7128f039e36547bf64f12d1f660d8ac934b26..fd25a94a63cc6dd3e1510308f30241b64ba19918 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -935,10 +935,13 @@ static void rfkill_sync_work(struct work_struct *work) int __must_check rfkill_register(struct rfkill *rfkill) { static unsigned long rfkill_no; - struct device *dev = &rfkill->dev; + struct device *dev; int error; - BUG_ON(!rfkill); + if (!rfkill) + return -EINVAL; + + dev = &rfkill->dev; mutex_lock(&rfkill_global_mutex); diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index f60e355765269e1192f6b464b7c735a26576d70c..d6a64771463ff3f1f6940ebcba71f188d477b308 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -401,6 +401,7 @@ enum rxrpc_call_flag { RXRPC_CALL_SEND_PING, /* A ping will need to be sent */ RXRPC_CALL_PINGING, /* Ping in process */ RXRPC_CALL_RETRANS_TIMEOUT, /* Retransmission due to timeout occurred */ + RXRPC_CALL_DISCONNECTED, /* The call has been disconnected */ }; /* diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 1ed18d8c9c9fa31ac46028089184519624625a51..88bcd146142fed055b773173ea18803a544b6ed0 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -464,7 +464,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn); - if (conn) + if (conn && !test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) rxrpc_disconnect_call(call); for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { @@ -539,6 +539,7 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu) { struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu); + rxrpc_put_connection(call->conn); rxrpc_put_peer(call->peer); kfree(call->rxtx_buffer); kfree(call->rxtx_annotations); @@ -560,7 +561,6 @@ void rxrpc_cleanup_call(struct rxrpc_call *call) ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); - ASSERTCMP(call->conn, ==, NULL); /* Clean up the Rx/Tx buffer */ for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index 0fce919bf47d0fec2ca70ac73916d06e4fa32b4e..dd41733f182a27e4d832ecf02e8872bdb5a6b166 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c @@ -736,9 +736,9 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call) struct rxrpc_channel *chan = &conn->channels[channel]; trace_rxrpc_client(conn, channel, rxrpc_client_chan_disconnect); - call->conn = NULL; spin_lock(&conn->channel_lock); + set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); /* Calls that have never actually been assigned a channel can simply be * discarded. If the conn didn't get used either, it will follow @@ -828,7 +828,6 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call) spin_unlock(&rxrpc_client_conn_cache_lock); out_2: spin_unlock(&conn->channel_lock); - rxrpc_put_connection(conn); _leave(""); return; diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index e1e83af478666be9e5f9373b64f0dcfab748e24d..e7c89b978587dd80c7e9293c6729d005a3a1c756 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c @@ -211,9 +211,8 @@ void rxrpc_disconnect_call(struct rxrpc_call *call) __rxrpc_disconnect_call(conn, call); spin_unlock(&conn->channel_lock); - call->conn = NULL; + set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); conn->idle_timestamp = jiffies; - rxrpc_put_connection(conn); } /* diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index a4380e182e6cda9c2415ac5ba03cf6b6c405aa93..f0ccc6a04c7ac20b8e20ea93106ed49a7fc6097d 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -582,8 +582,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb, immediate_ack, true, rxrpc_propose_ack_input_data); - if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) - rxrpc_notify_socket(call); + rxrpc_notify_socket(call); _leave(" [queued]"); } diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 59d32860331205a5b12e2c711250f478124bdd1c..d568c96f526234865336f555e3ce1429ef049c14 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c @@ -96,7 +96,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_call *call, */ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping) { - struct rxrpc_connection *conn = NULL; + struct rxrpc_connection *conn; struct rxrpc_ack_buffer *pkt; struct msghdr msg; struct kvec iov[2]; @@ -106,18 +106,14 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping) int ret; u8 reason; - spin_lock_bh(&call->lock); - if (call->conn) - conn = rxrpc_get_connection_maybe(call->conn); - spin_unlock_bh(&call->lock); - if (!conn) + if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) return -ECONNRESET; pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); - if (!pkt) { - rxrpc_put_connection(conn); + if (!pkt) return -ENOMEM; - } + + conn = call->conn; msg.msg_name = &call->peer->srx.transport; msg.msg_namelen = call->peer->srx.transport_len; @@ -204,7 +200,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping) } out: - rxrpc_put_connection(conn); kfree(pkt); return ret; } @@ -214,20 +209,18 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping) */ int rxrpc_send_abort_packet(struct rxrpc_call *call) { - struct rxrpc_connection *conn = NULL; + struct rxrpc_connection *conn; struct rxrpc_abort_buffer pkt; struct msghdr msg; struct kvec iov[1]; rxrpc_serial_t serial; int ret; - spin_lock_bh(&call->lock); - if (call->conn) - conn = rxrpc_get_connection_maybe(call->conn); - spin_unlock_bh(&call->lock); - if (!conn) + if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) return -ECONNRESET; + conn = call->conn; + msg.msg_name = &call->peer->srx.transport; msg.msg_namelen = call->peer->srx.transport_len; msg.msg_control = NULL; @@ -255,7 +248,6 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call) ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 1, sizeof(pkt)); - rxrpc_put_connection(conn); return ret; } @@ -400,6 +392,9 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb, } break; #endif + + default: + BUG(); } up_write(&conn->params.local->defrag_sem); diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index bf13b8470c9ad51783325d7f47c32414b07f0c40..80950a4384aa7c007d4b82a58512422e6964329f 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c @@ -148,6 +148,9 @@ void rxrpc_error_report(struct sock *sk) struct rxrpc_peer *peer; struct sk_buff *skb; + if (unlikely(!local)) + return; + _enter("%p{%d}", sk, local->debug_id); skb = sock_dequeue_err_skb(sk); diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index fc3650b0619242d8aed6a51604087ec8d4f8b57b..9b4c7c42c932d3fa323a2a649a9e29d425bdb9dc 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -332,7 +332,11 @@ static int __init mirred_init_module(void) return err; pr_info("Mirror/redirect action on\n"); - return tcf_register_action(&act_mirred_ops, &mirred_net_ops); + err = tcf_register_action(&act_mirred_ops, &mirred_net_ops); + if (err) + unregister_netdevice_notifier(&mirred_device_notifier); + + return err; } static void __exit mirred_cleanup_module(void) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index eee299bb6bcffbea0a20c2be595f3080e53dee1e..18904313bd4e6b7c0b286b33db0f89776a5c7b9b 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -141,6 +141,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp, if (!atomic_read(&head->ht.nelems)) return -1; + flow_dissector_init_keys(&skb_key.control, &skb_key.basic); fl_clear_masked_range(&skb_key, &head->mask); info = skb_tunnel_info(skb); @@ -364,6 +365,7 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { [TCA_FLOWER_KEY_TCP_DST_MASK] = { .type = NLA_U16 }, [TCA_FLOWER_KEY_UDP_SRC_MASK] = { .type = NLA_U16 }, [TCA_FLOWER_KEY_UDP_DST_MASK] = { .type = NLA_U16 }, + [TCA_FLOWER_FLAGS] = { .type = NLA_U32 }, }; static void fl_set_key_val(struct nlattr **tb, diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c index 61ddfbad2aaedea0c6e7a58098641dec3256c06d..fe29c576e4948c84fc9ef4719a7feb237ba6b5b9 100644 --- a/net/sched/cls_matchall.c +++ b/net/sched/cls_matchall.c @@ -111,6 +111,7 @@ static unsigned long mall_get(struct tcf_proto *tp, u32 handle) static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = { [TCA_MATCHALL_UNSPEC] = { .type = NLA_UNSPEC }, [TCA_MATCHALL_CLASSID] = { .type = NLA_U32 }, + [TCA_MATCHALL_FLAGS] = { .type = NLA_U32 }, }; static int mall_set_parms(struct net *net, struct tcf_proto *tp, diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 322438fb3ffcb426194be6c1dd05893b27cdf51c..8673f9817f91a5ca9a0cbd16725e113f2980c149 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h @@ -455,10 +455,8 @@ static u32 gen_tunnel(struct rsvp_head *data) static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = { [TCA_RSVP_CLASSID] = { .type = NLA_U32 }, - [TCA_RSVP_DST] = { .type = NLA_BINARY, - .len = RSVP_DST_LEN * sizeof(u32) }, - [TCA_RSVP_SRC] = { .type = NLA_BINARY, - .len = RSVP_DST_LEN * sizeof(u32) }, + [TCA_RSVP_DST] = { .len = RSVP_DST_LEN * sizeof(u32) }, + [TCA_RSVP_SRC] = { .len = RSVP_DST_LEN * sizeof(u32) }, [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) }, }; diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index db80a6440f37181431a546d7683cd3cfc87dda17..3e1695b66e3157f06dec4b4d66fe47646e3175de 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -301,12 +301,31 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, cp->fall_through = p->fall_through; cp->tp = tp; + if (tb[TCA_TCINDEX_HASH]) + cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); + + if (tb[TCA_TCINDEX_MASK]) + cp->mask = nla_get_u16(tb[TCA_TCINDEX_MASK]); + + if (tb[TCA_TCINDEX_SHIFT]) + cp->shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]); + + if (!cp->hash) { + /* Hash not specified, use perfect hash if the upper limit + * of the hashing index is below the threshold. + */ + if ((cp->mask >> cp->shift) < PERFECT_HASH_THRESHOLD) + cp->hash = (cp->mask >> cp->shift) + 1; + else + cp->hash = DEFAULT_HASH_SIZE; + } + if (p->perfect) { int i; if (tcindex_alloc_perfect_hash(cp) < 0) goto errout; - for (i = 0; i < cp->hash; i++) + for (i = 0; i < min(cp->hash, p->hash); i++) cp->perfect[i].res = p->perfect[i].res; balloc = 1; } @@ -321,15 +340,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, if (old_r) cr.res = r->res; - if (tb[TCA_TCINDEX_HASH]) - cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); - - if (tb[TCA_TCINDEX_MASK]) - cp->mask = nla_get_u16(tb[TCA_TCINDEX_MASK]); - - if (tb[TCA_TCINDEX_SHIFT]) - cp->shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]); - err = -EBUSY; /* Hash already allocated, make sure that we still meet the @@ -347,16 +357,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, if (tb[TCA_TCINDEX_FALL_THROUGH]) cp->fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]); - if (!cp->hash) { - /* Hash not specified, use perfect hash if the upper limit - * of the hashing index is below the threshold. - */ - if ((cp->mask >> cp->shift) < PERFECT_HASH_THRESHOLD) - cp->hash = (cp->mask >> cp->shift) + 1; - else - cp->hash = DEFAULT_HASH_SIZE; - } - if (!cp->perfect && !cp->h) cp->alloc_hash = cp->hash; diff --git a/net/sched/ematch.c b/net/sched/ematch.c index fbb7ebfc58c6761f6afb58e62646908b10e2bf09..d4d6f9c91e8c08d4607d3010274f802522e3ea32 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -242,6 +242,9 @@ static int tcf_em_validate(struct tcf_proto *tp, goto errout; if (em->ops->change) { + err = -EINVAL; + if (em_hdr->flags & TCF_EM_SIMPLE) + goto errout; err = em->ops->change(net, data, data_len, em); if (err < 0) goto errout; @@ -267,12 +270,12 @@ static int tcf_em_validate(struct tcf_proto *tp, } em->data = (unsigned long) v; } + em->datalen = data_len; } } em->matchid = em_hdr->matchid; em->flags = em_hdr->flags; - em->datalen = data_len; em->net = net; err = 0; diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index b57b4de730389cedf5e49b6bad9ea66b335ad724..9f53d4ec0e37ae42289b2215d7775e52abb6c504 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c @@ -697,6 +697,7 @@ static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = { [TCA_FQ_FLOW_MAX_RATE] = { .type = NLA_U32 }, [TCA_FQ_BUCKETS_LOG] = { .type = NLA_U32 }, [TCA_FQ_FLOW_REFILL_DELAY] = { .type = NLA_U32 }, + [TCA_FQ_ORPHAN_MASK] = { .type = NLA_U32 }, [TCA_FQ_LOW_RATE_THRESHOLD] = { .type = NLA_U32 }, }; @@ -736,7 +737,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) if (tb[TCA_FQ_QUANTUM]) { u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); - if (quantum > 0) + if (quantum > 0 && quantum <= (1 << 20)) q->quantum = quantum; else err = -EINVAL; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 95002e56fa48b6f28157f97e01cdc286f3de2e50..e06491314d592da355e09531405d48915a0fe01f 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -437,8 +437,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct netem_skb_cb *cb; struct sk_buff *skb2; struct sk_buff *segs = NULL; - unsigned int len = 0, last_len, prev_len = qdisc_pkt_len(skb); - int nb = 0; + unsigned int prev_len = qdisc_pkt_len(skb); int count = 1; int rc = NET_XMIT_SUCCESS; int rc_drop = NET_XMIT_DROP; @@ -495,6 +494,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, segs = netem_segment(skb, sch, to_free); if (!segs) return rc_drop; + qdisc_skb_cb(segs)->pkt_len = segs->len; } else { segs = skb; } @@ -510,6 +510,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) { qdisc_drop(skb, sch, to_free); + skb = NULL; goto finish_segs; } @@ -585,6 +586,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, finish_segs: if (segs) { + unsigned int len, last_len; + int nb; + + len = skb ? skb->len : 0; + nb = skb ? 1 : 0; + while (segs) { skb2 = segs->next; segs->next = NULL; @@ -600,9 +607,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, } segs = skb2; } - sch->q.qlen += nb; - if (nb > 1) - qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len); + /* Parent qdiscs accounted for 1 skb of size @prev_len */ + qdisc_tree_reduce_backlog(sch, -(nb - 1), -(len - prev_len)); + } else if (!skb) { + return NET_XMIT_DROP; } return NET_XMIT_SUCCESS; } diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index cdd67e04d7e92d73e2cc0352c7360bafb2e3ece5..7a1be3c1144ccb02a0e741af7746136df274e982 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -253,8 +253,14 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct prio_sched_data *q = qdisc_priv(sch); unsigned long band = arg - 1; - if (new == NULL) - new = &noop_qdisc; + if (!new) { + new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, + TC_H_MAKE(sch->handle, arg)); + if (!new) + new = &noop_qdisc; + else + qdisc_hash_add(new); + } *old = qdisc_replace(sch, new, &q->queues[band]); return 0; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 9cb06ca4eabae595b53864bbca64da80f7e341ce..446503d3b80c99d42f6bb9436e57b3278b3b8aa8 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -257,6 +257,7 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) addr->v4.sin_family = AF_INET; addr->v4.sin_port = 0; addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr; + memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); } /* Initialize sk->sk_rcv_saddr from sctp_addr. */ @@ -279,6 +280,7 @@ static void sctp_v4_from_addr_param(union sctp_addr *addr, addr->v4.sin_family = AF_INET; addr->v4.sin_port = port; addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; + memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); } /* Initialize an address parameter from a sctp_addr and return the length @@ -303,6 +305,7 @@ static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4, saddr->v4.sin_family = AF_INET; saddr->v4.sin_port = port; saddr->v4.sin_addr.s_addr = fl4->saddr; + memset(saddr->v4.sin_zero, 0, sizeof(saddr->v4.sin_zero)); } /* Compare two addresses exactly. */ @@ -325,6 +328,7 @@ static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port) addr->v4.sin_family = AF_INET; addr->v4.sin_addr.s_addr = htonl(INADDR_ANY); addr->v4.sin_port = port; + memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); } /* Is this a wildcard address? */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 8b4cf78987e479c45b8d2ea37cf23c183a13b515..1133fa0830f4ef16cf51e9ad31ad47280ec250de 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1321,8 +1321,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, /* Generate an INIT ACK chunk. */ new_obj = sctp_make_init_ack(asoc, chunk, GFP_ATOMIC, 0); - if (!new_obj) - goto nomem; + if (!new_obj) { + error = -ENOMEM; + break; + } sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(new_obj)); @@ -1344,7 +1346,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, if (!new_obj) { if (cmd->obj.chunk) sctp_chunk_free(cmd->obj.chunk); - goto nomem; + error = -ENOMEM; + break; } sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(new_obj)); @@ -1391,8 +1394,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, /* Generate a SHUTDOWN chunk. */ new_obj = sctp_make_shutdown(asoc, chunk); - if (!new_obj) - goto nomem; + if (!new_obj) { + error = -ENOMEM; + break; + } sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(new_obj)); break; @@ -1721,11 +1726,17 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, break; } - if (error) + if (error) { + cmd = sctp_next_cmd(commands); + while (cmd) { + if (cmd->verb == SCTP_CMD_REPLY) + sctp_chunk_free(cmd->obj.chunk); + cmd = sctp_next_cmd(commands); + } break; + } } -out: /* If this is in response to a received chunk, wait until * we are done with the packet to open the queue so that we don't * send multiple packets in response to a single request. @@ -1740,8 +1751,5 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sp->data_ready_signalled = 0; return error; -nomem: - error = -ENOMEM; - goto out; } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index bfd0686797104a6f79a12ba06a64887ad6e8957d..1a3c75347f483dc1bd6d075d7c1257f757633332 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -177,6 +177,16 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk, return 1; } +/* Check for format error in an ABORT chunk */ +static inline bool sctp_err_chunk_valid(struct sctp_chunk *chunk) +{ + struct sctp_errhdr *err; + + sctp_walk_errors(err, chunk->chunk_hdr); + + return (void *)err == (void *)chunk->chunk_end; +} + /********************************************************** * These are the state functions for handling chunk events. **********************************************************/ @@ -2159,6 +2169,9 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); + if (!sctp_err_chunk_valid(chunk)) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); } @@ -2201,6 +2214,9 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(struct net *net, sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); + if (!sctp_err_chunk_valid(chunk)) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + /* Stop the T2-shutdown timer. */ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); @@ -2466,6 +2482,9 @@ sctp_disposition_t sctp_sf_do_9_1_abort(struct net *net, sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); + if (!sctp_err_chunk_valid(chunk)) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); } @@ -2482,15 +2501,9 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net, /* See if we have an error cause code in the chunk. */ len = ntohs(chunk->chunk_hdr->length); - if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) { - - sctp_errhdr_t *err; - sctp_walk_errors(err, chunk->chunk_hdr); - if ((void *)err != (void *)chunk->chunk_end) - return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) error = ((sctp_errhdr_t *)chunk->skb->data)->cause; - } sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); /* ASSOC_FAILED will DELETE_TCB. */ diff --git a/net/socket.c b/net/socket.c index d2aa2fee9abb15795561dd7c6f29d40dbc7d79a8..be7831fd7d464ea1ac94f2b8ee590776ea2efed7 100644 --- a/net/socket.c +++ b/net/socket.c @@ -3212,6 +3212,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, case SIOCSARP: case SIOCGARP: case SIOCDARP: + case SIOCOUTQNSD: case SIOCATMARK: return sock_do_ioctl(net, sock, cmd, arg); } diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index b4b68c6e3f8be02591002a8744763bf828f786ba..d7775ca2fbb9514f6b20d985db1b69166985d120 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1180,6 +1180,7 @@ static int gss_proxy_save_rsc(struct cache_detail *cd, dprintk("RPC: No creds found!\n"); goto out; } else { + struct timespec64 boot; /* steal creds */ rsci.cred = ud->creds; @@ -1200,6 +1201,9 @@ static int gss_proxy_save_rsc(struct cache_detail *cd, &expiry, GFP_KERNEL); if (status) goto out; + + getboottime64(&boot); + expiry -= boot.tv_sec; } rsci.h.expiry_time = expiry; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index cdcc0fea9f5a19c3fad726ef845c27ab24092bb8..24e42919a4800fba1f5c4062e750ad001fe59854 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -54,9 +54,6 @@ static void cache_init(struct cache_head *h, struct cache_detail *detail) h->last_refresh = now; } -static inline int cache_is_valid(struct cache_head *h); -static void cache_fresh_locked(struct cache_head *head, time_t expiry, - struct cache_detail *detail); static void cache_fresh_unlocked(struct cache_head *head, struct cache_detail *detail); @@ -101,9 +98,6 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, if (cache_is_expired(detail, tmp)) { hlist_del_init(&tmp->cache_list); detail->entries --; - if (cache_is_valid(tmp) == -EAGAIN) - set_bit(CACHE_NEGATIVE, &tmp->flags); - cache_fresh_locked(tmp, 0, detail); freeme = tmp; break; } diff --git a/net/tipc/core.c b/net/tipc/core.c index 59980dea2ad7701f322e3f5daf8737f262b4a476..799900c0f2c9ff9b2e9f06658c26222bf5277a34 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -116,14 +116,6 @@ static int __init tipc_init(void) sysctl_tipc_rmem[1] = RCVBUF_DEF; sysctl_tipc_rmem[2] = RCVBUF_MAX; - err = tipc_netlink_start(); - if (err) - goto out_netlink; - - err = tipc_netlink_compat_start(); - if (err) - goto out_netlink_compat; - err = tipc_register_sysctl(); if (err) goto out_sysctl; @@ -144,8 +136,21 @@ static int __init tipc_init(void) if (err) goto out_bearer; + err = tipc_netlink_start(); + if (err) + goto out_netlink; + + err = tipc_netlink_compat_start(); + if (err) + goto out_netlink_compat; + pr_info("Started in single node mode\n"); return 0; + +out_netlink_compat: + tipc_netlink_stop(); +out_netlink: + tipc_bearer_cleanup(); out_bearer: unregister_pernet_device(&tipc_topsrv_net_ops); out_pernet_topsrv: @@ -155,22 +160,18 @@ static int __init tipc_init(void) out_pernet: tipc_unregister_sysctl(); out_sysctl: - tipc_netlink_compat_stop(); -out_netlink_compat: - tipc_netlink_stop(); -out_netlink: pr_err("Unable to start in single node mode\n"); return err; } static void __exit tipc_exit(void) { + tipc_netlink_compat_stop(); + tipc_netlink_stop(); tipc_bearer_cleanup(); unregister_pernet_device(&tipc_topsrv_net_ops); tipc_socket_stop(); unregister_pernet_device(&tipc_net_ops); - tipc_netlink_stop(); - tipc_netlink_compat_stop(); tipc_unregister_sysctl(); pr_info("Deactivated\n"); diff --git a/net/tipc/node.c b/net/tipc/node.c index db8fbc076e1a5e893a967be5fa27f450a6c69497..fe7b0ad1d6f321371a0e563d3be5810576f6beff 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -688,10 +688,10 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) { struct tipc_link_entry *le = &n->links[bearer_id]; + struct tipc_media_addr *maddr = NULL; struct tipc_link *l = le->link; - struct tipc_media_addr *maddr; - struct sk_buff_head xmitq; int old_bearer_id = bearer_id; + struct sk_buff_head xmitq; if (!l) return; @@ -713,7 +713,8 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) tipc_node_write_unlock(n); if (delete) tipc_mon_remove_peer(n->net, n->addr, old_bearer_id); - tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); + if (!skb_queue_empty(&xmitq)) + tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); tipc_sk_rcv(n->net, &le->inputq); } diff --git a/net/tipc/sysctl.c b/net/tipc/sysctl.c index 1a779b1e85100b501c1f0cde29cbfaa0d98fb4eb..40f6d82083d7bbcc3968b0091811519103fba497 100644 --- a/net/tipc/sysctl.c +++ b/net/tipc/sysctl.c @@ -37,6 +37,8 @@ #include +static int zero; +static int one = 1; static struct ctl_table_header *tipc_ctl_hdr; static struct ctl_table tipc_table[] = { @@ -45,14 +47,16 @@ static struct ctl_table tipc_table[] = { .data = &sysctl_tipc_rmem, .maxlen = sizeof(sysctl_tipc_rmem), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &one, }, { .procname = "named_timeout", .data = &sysctl_tipc_named_timeout, .maxlen = sizeof(sysctl_tipc_named_timeout), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, }, {} }; diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c index e9e91298c70de7bdab61b31b795df213c5a71461..3cedf2c2b60bd79c88c5d060f0b4596d94a8fe64 100644 --- a/net/wireless/ethtool.c +++ b/net/wireless/ethtool.c @@ -6,9 +6,13 @@ void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct wireless_dev *wdev = dev->ieee80211_ptr; + struct device *pdev = wiphy_dev(wdev->wiphy); - strlcpy(info->driver, wiphy_dev(wdev->wiphy)->driver->name, - sizeof(info->driver)); + if (pdev->driver) + strlcpy(info->driver, pdev->driver->name, + sizeof(info->driver)); + else + strlcpy(info->driver, "N/A", sizeof(info->driver)); strlcpy(info->version, init_utsname()->release, sizeof(info->version)); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3e9b1363271dc73ad121a30534aafcf7ab059bde..94b537f4430fe647b4421e41b75893257d192b53 100755 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -333,6 +333,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, + [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 }, [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, [NL80211_ATTR_PID] = { .type = NLA_U32 }, @@ -358,6 +359,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, + [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 }, + [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG }, [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, @@ -406,6 +409,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_MDID] = { .type = NLA_U16 }, [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 }, + [NL80211_ATTR_MAX_CRIT_PROT_DURATION] = { .type = NLA_U16 }, [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 }, [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, @@ -431,6 +436,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 }, [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 }, [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, + [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 }, [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN }, [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG }, [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 }, @@ -1371,6 +1377,46 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg, return 0; } +static int +nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev, + struct sk_buff *msg) +{ + int i; + struct nlattr *nested, *nested_akms; + const struct wiphy_iftype_akm_suites *iftype_akms; + + if (!rdev->wiphy.num_iftype_akm_suites || + !rdev->wiphy.iftype_akm_suites) + return 0; + + nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES); + if (!nested) + return -ENOBUFS; + + for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) { + nested_akms = nla_nest_start(msg, i + 1); + if (!nested_akms) + return -ENOBUFS; + + iftype_akms = &rdev->wiphy.iftype_akm_suites[i]; + + if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES, + iftype_akms->iftypes_mask)) + return -ENOBUFS; + + if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES, + sizeof(u32) * iftype_akms->n_akm_suites, + iftype_akms->akm_suites)) { + return -ENOBUFS; + } + nla_nest_end(msg, nested_akms); + } + + nla_nest_end(msg, nested); + + return 0; +} + struct nl80211_dump_wiphy_state { s64 filter_wiphy; long start; @@ -1671,6 +1717,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, CMD(add_tx_ts, ADD_TX_TS); CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST); CMD(update_connect_params, UPDATE_CONNECT_PARAMS); + CMD(update_ft_ies, UPDATE_FT_IES); } /* add into the if now */ #undef CMD @@ -1915,6 +1962,13 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, } } + state->split_start++; + break; + case 14: + + if (nl80211_put_iftype_akm_suites(rdev, msg)) + goto nla_put_failure; + /* done */ state->split_start = 0; break; @@ -8924,6 +8978,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) { if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) { + kzfree(connkeys); return -EINVAL; } connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT; diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index a0ff6b16fcb59c753973520572cda82579fce2e0..8be0578edfcc5f0fcf6fe2560458e370c7452260 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -537,6 +537,10 @@ static inline int rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed) { int ret; + + if (!rdev->ops->set_wiphy_params) + return -EOPNOTSUPP; + trace_rdev_set_wiphy_params(&rdev->wiphy, changed); ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); trace_rdev_return_int(&rdev->wiphy, ret); diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c5dd4fef04337921dced8959adda9cf81fe4ac1f..9588b72294098fd01d92e7bc0ba0c9035643935f 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1722,21 +1722,22 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) static void handle_channel_custom(struct wiphy *wiphy, struct ieee80211_channel *chan, - const struct ieee80211_regdomain *regd) + const struct ieee80211_regdomain *regd, + u32 min_bw) { u32 bw_flags = 0; const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; u32 bw; - for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) { + for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) { reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(chan->center_freq), regd, bw); if (!IS_ERR(reg_rule)) break; } - if (IS_ERR(reg_rule)) { + if (IS_ERR_OR_NULL(reg_rule)) { pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n", chan->center_freq); if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { @@ -1785,8 +1786,14 @@ static void handle_band_custom(struct wiphy *wiphy, if (!sband) return; + /* + * We currently assume that you always want at least 20 MHz, + * otherwise channel 12 might get enabled if this rule is + * compatible to US, which permits 2402 - 2472 MHz. + */ for (i = 0; i < sband->n_channels; i++) - handle_channel_custom(wiphy, &sband->channels[i], regd); + handle_channel_custom(wiphy, &sband->channels[i], regd, + MHZ_TO_KHZ(20)); } /* Used by drivers prior to wiphy registration */ diff --git a/net/wireless/util.c b/net/wireless/util.c old mode 100644 new mode 100755 index bc77b8754ff0d05e2109de0bff9c8eae893767f1..bdd0b62004f8807dc06c34af612926332aaa9e44 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -539,7 +539,7 @@ __frame_add_frag(struct sk_buff *skb, struct page *page, struct skb_shared_info *sh = skb_shinfo(skb); int page_offset; - page_ref_inc(page); + get_page(page); page_offset = ptr - page_address(page); skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size); } @@ -1770,3 +1770,48 @@ bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb) return false; } EXPORT_SYMBOL(cfg80211_is_gratuitous_arp_unsolicited_na); + +/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ +struct iapp_layer2_update { + u8 da[ETH_ALEN]; /* broadcast */ + u8 sa[ETH_ALEN]; /* STA addr */ + __be16 len; /* 6 */ + u8 dsap; /* 0 */ + u8 ssap; /* 0 */ + u8 control; + u8 xid_info[3]; +} __packed; + +void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr) +{ + struct iapp_layer2_update *msg; + struct sk_buff *skb; + + /* Send Level 2 Update Frame to update forwarding tables in layer 2 + * bridge devices */ + + skb = dev_alloc_skb(sizeof(*msg)); + if (!skb) + return; + msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg)); + + /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) + * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ + + eth_broadcast_addr(msg->da); + ether_addr_copy(msg->sa, addr); + msg->len = htons(6); + msg->dsap = 0; + msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ + msg->control = 0xaf; /* XID response lsb.1111F101. + * F=0 (no poll command; unsolicited frame) */ + msg->xid_info[0] = 0x81; /* XID format identifier */ + msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ + msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx_ni(skb); +} +EXPORT_SYMBOL(cfg80211_send_layer2_update); diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 6250b1cfcde58758bb480758d1c61217d37a7cd1..4bf0296a7c4330b65aef66094fcb10865addc128 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -659,7 +659,8 @@ struct iw_statistics *get_wireless_stats(struct net_device *dev) return NULL; } -static int iw_handler_get_iwstats(struct net_device * dev, +/* noinline to avoid a bogus warning with -O3 */ +static noinline int iw_handler_get_iwstats(struct net_device * dev, struct iw_request_info * info, union iwreq_data * wrqu, char * extra) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 770ababb8f928cf1b8055610ef359ebcc6c04a43..a8ca79810dcc6c44e42a96eb9b5b1e987838b83e 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -100,7 +100,7 @@ int x25_parse_address_block(struct sk_buff *skb, } len = *skb->data; - needed = 1 + (len >> 4) + (len & 0x0f); + needed = 1 + ((len >> 4) + (len & 0x0f) + 1) / 2; if (!pskb_may_pull(skb, needed)) { /* packet is too short to hold the addresses it claims @@ -288,7 +288,7 @@ static struct sock *x25_find_listener(struct x25_address *addr, sk_for_each(s, &x25_list) if ((!strcmp(addr->x25_addr, x25_sk(s)->source_addr.x25_addr) || - !strcmp(addr->x25_addr, + !strcmp(x25_sk(s)->source_addr.x25_addr, null_x25_address.x25_addr)) && s->sk_state == TCP_LISTEN) { /* @@ -684,11 +684,15 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; } - len = strlen(addr->sx25_addr.x25_addr); - for (i = 0; i < len; i++) { - if (!isdigit(addr->sx25_addr.x25_addr[i])) { - rc = -EINVAL; - goto out; + /* check for the null_x25_address */ + if (strcmp(addr->sx25_addr.x25_addr, null_x25_address.x25_addr)) { + + len = strlen(addr->sx25_addr.x25_addr); + for (i = 0; i < len; i++) { + if (!isdigit(addr->sx25_addr.x25_addr[i])) { + rc = -EINVAL; + goto out; + } } } @@ -760,6 +764,10 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, if (sk->sk_state == TCP_ESTABLISHED) goto out; + rc = -EALREADY; /* Do nothing if call is already in progress */ + if (sk->sk_state == TCP_SYN_SENT) + goto out; + sk->sk_state = TCP_CLOSE; sock->state = SS_UNCONNECTED; @@ -806,7 +814,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, /* Now the loop */ rc = -EINPROGRESS; if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) - goto out_put_neigh; + goto out; rc = x25_wait_for_connection_establishment(sk); if (rc) diff --git a/samples/bpf/trace_event_user.c b/samples/bpf/trace_event_user.c index 9a130d31ecf258b601d20e52367443a18f02c11c..6fbb5eb9daf3c83eeee0124432c8d866ce2a8491 100644 --- a/samples/bpf/trace_event_user.c +++ b/samples/bpf/trace_event_user.c @@ -33,9 +33,9 @@ static void print_ksym(__u64 addr) return; sym = ksym_search(addr); printf("%s;", sym->name); - if (!strcmp(sym->name, "sys_read")) + if (!strstr(sym->name, "sys_read")) sys_read_seen = true; - else if (!strcmp(sym->name, "sys_write")) + else if (!strstr(sym->name, "sys_write")) sys_write_seen = true; } diff --git a/samples/pktgen/functions.sh b/samples/pktgen/functions.sh index 205e4cde460120bdc10a4da237fbf4290849cb6b..065a7e296ee3142bdb344faf69a852fe140d8e5f 100644 --- a/samples/pktgen/functions.sh +++ b/samples/pktgen/functions.sh @@ -5,6 +5,8 @@ # Author: Jesper Dangaaard Brouer # License: GPL +set -o errexit + ## -- General shell logging cmds -- function err() { local exitcode=$1 @@ -58,6 +60,7 @@ function pg_set() { function proc_cmd() { local result local proc_file=$1 + local status=0 # after shift, the remaining args are contained in $@ shift local proc_ctrl=${PROC_DIR}/$proc_file @@ -73,13 +76,13 @@ function proc_cmd() { echo "cmd: $@ > $proc_ctrl" fi # Quoting of "$@" is important for space expansion - echo "$@" > "$proc_ctrl" - local status=$? + echo "$@" > "$proc_ctrl" || status=$? - result=$(grep "Result: OK:" $proc_ctrl) - # Due to pgctrl, cannot use exit code $? from grep - if [[ "$result" == "" ]]; then - grep "Result:" $proc_ctrl >&2 + if [[ "$proc_file" != "pgctrl" ]]; then + result=$(grep "Result: OK:" $proc_ctrl) || true + if [[ "$result" == "" ]]; then + grep "Result:" $proc_ctrl >&2 + fi fi if (( $status != 0 )); then err 5 "Write error($status) occurred cmd: \"$@ > $proc_ctrl\"" @@ -105,6 +108,8 @@ function pgset() { fi } +[[ $EUID -eq 0 ]] && trap 'pg_ctrl "reset"' EXIT + ## -- General shell tricks -- function root_check_run_with_sudo() { diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic index e4d017d5381949243337b78c56284bb52a43c610..95f7d80901524a4c966505397af6931f3e3316f3 100644 --- a/scripts/Makefile.asm-generic +++ b/scripts/Makefile.asm-generic @@ -15,7 +15,7 @@ _dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) # Stale wrappers when the corresponding files are removed from generic-y # need removing. -generated-y := $(generic-y) $(genhdr-y) $(generated-y) +generated-y := $(generic-y) $(generated-y) all-files := $(patsubst %, $(obj)/%, $(generated-y)) old-headers := $(wildcard $(obj)/*.h) unwanted := $(filter-out $(all-files),$(old-headers)) diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index 1106d6ca3a384baa81b077b599d83b8e9941108e..82abf5a09e5dce680e0d10c8d331fbc1e5e91ea1 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -1,33 +1,56 @@ # ========================================================================== # Installing headers # -# header-y - list files to be installed. They are preprocessed -# to remove __KERNEL__ section of the file -# genhdr-y - Same as header-y but in a generated/ directory +# All headers under include/uapi, include/generated/uapi, +# arch//include/uapi and arch//include/generated/uapi are +# exported. +# They are preprocessed to remove __KERNEL__ section of the file. # # ========================================================================== +PHONY := __headers +__headers: + +include scripts/Kbuild.include + +srcdir := $(srctree)/$(obj) +subdirs := $(patsubst $(srcdir)/%/.,%,$(wildcard $(srcdir)/*/.)) +# caller may set destination dir (when installing to asm/) +_dst := $(if $(dst),$(dst),$(obj)) + +# Recursion +__headers: $(subdirs) + +.PHONY: $(subdirs) +$(subdirs): + $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@ + +# Skip header install/check for include/uapi and arch/$(hdr-arch)/include/uapi. +# We have only sub-directories there. +skip-inst := $(if $(filter %/uapi,$(obj)),1) + +ifeq ($(skip-inst),) + # generated header directory gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) +# Kbuild file is optional kbuild-file := $(srctree)/$(obj)/Kbuild -include $(kbuild-file) - -# called may set destination dir (when installing to asm/) -_dst := $(if $(destination-y),$(destination-y),$(if $(dst),$(dst),$(obj))) +-include $(kbuild-file) old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild ifneq ($(wildcard $(old-kbuild-file)),) include $(old-kbuild-file) endif -include scripts/Kbuild.include - installdir := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst)) -header-y := $(sort $(header-y)) -subdirs := $(patsubst %/,%,$(filter %/, $(header-y))) -header-y := $(filter-out %/, $(header-y)) +gendir := $(objtree)/$(gen) +header-files := $(notdir $(wildcard $(srcdir)/*.h)) +header-files += $(notdir $(wildcard $(srcdir)/*.agh)) +header-files := $(filter-out $(no-export-headers), $(header-files)) +genhdr-files := $(notdir $(wildcard $(gendir)/*.h)) +genhdr-files := $(filter-out $(header-files), $(genhdr-files)) # files used to track state of install/check install-file := $(installdir)/.install @@ -35,36 +58,22 @@ check-file := $(installdir)/.check # generic-y list all files an architecture uses from asm-generic # Use this to build a list of headers which require a wrapper -wrapper-files := $(filter $(header-y), $(generic-y)) - -srcdir := $(srctree)/$(obj) -gendir := $(objtree)/$(gen) +generic-files := $(notdir $(wildcard $(srctree)/include/uapi/asm-generic/*.h)) +wrapper-files := $(filter $(generic-files), $(generic-y)) +wrapper-files := $(filter-out $(header-files), $(wrapper-files)) oldsrcdir := $(srctree)/$(subst /uapi,,$(obj)) # all headers files for this dir -header-y := $(filter-out $(generic-y), $(header-y)) -all-files := $(header-y) $(genhdr-y) $(wrapper-files) +all-files := $(header-files) $(genhdr-files) $(wrapper-files) output-files := $(addprefix $(installdir)/, $(all-files)) -input-files1 := $(foreach hdr, $(header-y), \ - $(if $(wildcard $(srcdir)/$(hdr)), \ - $(wildcard $(srcdir)/$(hdr))) \ - ) -input-files1-name := $(notdir $(input-files1)) -input-files2 := $(foreach hdr, $(header-y), \ - $(if $(wildcard $(srcdir)/$(hdr)),, \ - $(if $(wildcard $(oldsrcdir)/$(hdr)), \ - $(wildcard $(oldsrcdir)/$(hdr)), \ - $(error Missing UAPI file $(srcdir)/$(hdr))) \ - )) -input-files2-name := $(notdir $(input-files2)) -input-files3 := $(foreach hdr, $(genhdr-y), \ - $(if $(wildcard $(gendir)/$(hdr)), \ - $(wildcard $(gendir)/$(hdr)), \ - $(error Missing generated UAPI file $(gendir)/$(hdr)) \ - )) -input-files3-name := $(notdir $(input-files3)) +ifneq ($(mandatory-y),) +missing := $(filter-out $(all-files),$(mandatory-y)) +ifneq ($(missing),) +$(error Some mandatory headers ($(missing)) are missing in $(obj)) +endif +endif # Work out what needs to be removed oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h)) @@ -78,9 +87,8 @@ printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ file$(if $(word 2, $(all-files)),s)) cmd_install = \ - $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(input-files1-name); \ - $(CONFIG_SHELL) $< $(installdir) $(oldsrcdir) $(input-files2-name); \ - $(CONFIG_SHELL) $< $(installdir) $(gendir) $(input-files3-name); \ + $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(header-files); \ + $(CONFIG_SHELL) $< $(installdir) $(gendir) $(genhdr-files); \ for F in $(wrapper-files); do \ echo "\#include " > $(installdir)/$$F; \ done; \ @@ -98,21 +106,21 @@ quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files) $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \ touch $@ -PHONY += __headersinst __headerscheck - ifndef HDRCHECK # Rules for installing headers -__headersinst: $(subdirs) $(install-file) +__headers: $(install-file) @: targets += $(install-file) -$(install-file): scripts/headers_install.sh $(input-files1) $(input-files2) $(input-files3) FORCE +$(install-file): scripts/headers_install.sh \ + $(addprefix $(srcdir)/,$(header-files)) \ + $(addprefix $(gendir)/,$(genhdr-files)) FORCE $(if $(unwanted),$(call cmd,remove),) $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@))) $(call if_changed,install) else -__headerscheck: $(subdirs) $(check-file) +__headers: $(check-file) @: targets += $(check-file) @@ -121,11 +129,6 @@ $(check-file): scripts/headers_check.pl $(output-files) FORCE endif -# Recursion -.PHONY: $(subdirs) -$(subdirs): - $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@ - targets := $(wildcard $(sort $(targets))) cmd_files := $(wildcard \ $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) @@ -134,6 +137,8 @@ ifneq ($(cmd_files),) include $(cmd_files) endif +endif # skip-inst + .PHONY: $(PHONY) PHONY += FORCE FORCE: ; diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 2c8b8c662da599659fee6a7f13a569b22787a576..6402b0d36291414930932798347b1aa293f54057 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -498,6 +498,8 @@ static void build_initial_tok_table(void) table[pos] = table[i]; learn_symbol(table[pos].sym, table[pos].len); pos++; + } else { + free(table[i].sym); } } table_cnt = pos; diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 27aac273205bacf5456680a914a024bbf36960e0..fa423fcd1a9285b12c024b8829f26ace0f2a99a0 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -1238,7 +1238,7 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode) sym_calc_value(csym); if (mode == def_random) - has_changed = randomize_choice_values(csym); + has_changed |= randomize_choice_values(csym); else { set_all_choice_values(csym); has_changed = true; diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index ed29bad1f03a3cf33097332fc67940b15154b2b4..96420b6209631dbfda8d94d2d270634d2bf319da 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c @@ -201,6 +201,13 @@ static int expr_eq(struct expr *e1, struct expr *e2) { int res, old_count; + /* + * A NULL expr is taken to be yes, but there's also a different way to + * represent yes. expr_is_yes() checks for either representation. + */ + if (!e1 || !e2) + return expr_is_yes(e1) && expr_is_yes(e2); + if (e1->type != e2->type) return 0; switch (e1->type) { diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e5c4114330110aefff3e590b293900bd4ea622b9..3dda774eb94cb62093b8047c8e5e9852c34a8d8f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1159,6 +1159,15 @@ static const struct sectioncheck *section_mismatch( * refsymname = *.constprop.* * * Pattern 6: + * Hide section mismatch warnings for ELF local symbols. The goal + * is to eliminate false positive modpost warnings caused by + * compiler-generated ELF local symbol names such as ".LANCHOR1". + * Autogenerated symbol names bypass modpost's "Pattern 2" + * whitelisting, which relies on pattern-matching against symbol + * names to work. (One situation where gcc can autogenerate ELF + * local symbols is when "-fsection-anchors" is used.) + * + * Pattern 7: * With CONFIG_CFI_CLANG, clang appends .cfi to all indirectly called * functions and creates a function stub with the original name. This * stub is always placed in .text, even if the actual function with the @@ -1207,6 +1216,10 @@ static int secref_whitelist(const struct sectioncheck *mismatch, return 0; /* Check for pattern 6 */ + if (strstarts(fromsym, ".L")) + return 0; + + /* Check for pattern 7 */ if (match(fromsec, text_sections) && match(tosec, init_exit_sections) && match(tosym, cfi_symbols)) diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index e0c508203c9c9a2a963e457d4b7db01ad22b1b31..347f70607a3331a16dd67f8aba97be059a5dad8a 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -53,6 +53,10 @@ #define R_AARCH64_ABS64 257 #endif +#define R_ARM_PC24 1 +#define R_ARM_THM_CALL 10 +#define R_ARM_CALL 28 + static int fd_map; /* File descriptor for file being modified. */ static int mmap_failed; /* Boolean flag. */ static char gpfx; /* prefix for global symbol name (sometimes '_') */ @@ -375,6 +379,18 @@ is_mcounted_section_name(char const *const txtname) #define RECORD_MCOUNT_64 #include "recordmcount.h" +static int arm_is_fake_mcount(Elf32_Rel const *rp) +{ + switch (ELF32_R_TYPE(w(rp->r_info))) { + case R_ARM_THM_CALL: + case R_ARM_CALL: + case R_ARM_PC24: + return 0; + } + + return 1; +} + /* 64-bit EM_MIPS has weird ELF64_Rela.r_info. * http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf * We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40] @@ -464,6 +480,7 @@ do_file(char const *const fname) break; case EM_ARM: reltype = R_ARM_ABS32; altmcount = "__gnu_mcount_nc"; + is_fake_mcount32 = arm_is_fake_mcount; break; case EM_AARCH64: reltype = R_AARCH64_ABS64; diff --git a/security/keys/key.c b/security/keys/key.c index 7276d1a009d49ffef0b95084d953ee82b6a2f43f..280b4feccdc00804bea19b69d4065ebf443a7d74 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -296,6 +296,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->gid = gid; key->perm = perm; key->restrict_link = restrict_link; + key->last_used_at = ktime_get_real_seconds(); if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) key->flags |= 1 << KEY_FLAG_IN_QUOTA; diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 84d9a2e2bbafa87fefc13f3e1bdd4ef141afcbee..f11a4abe18fc4e873947547746ae8cfdcd550b89 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -867,7 +867,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, if (orig->ae.xp_node) { rc = avc_xperms_populate(node, orig->ae.xp_node); if (rc) { - kmem_cache_free(avc_node_cachep, node); + avc_node_kill(node); goto out_unlock; } } diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 963ff8009dcc8549dfa1c174cf8105a5c56d049c..1764b221d545d6c290fe5a6bdf678e00c0321872 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -105,7 +105,7 @@ struct security_class_mapping secclass_map[] = { { COMMON_IPC_PERMS, NULL } }, { "netlink_route_socket", { COMMON_SOCK_PERMS, - "nlmsg_read", "nlmsg_write", NULL } }, + "nlmsg_read", "nlmsg_write", "nlmsg_readpriv", NULL } }, { "netlink_tcpdiag_socket", { COMMON_SOCK_PERMS, "nlmsg_read", "nlmsg_write", NULL } }, diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index b8e98c111b2f07a24e6171af2817bc447ff9eada..576d5a8c9238f3eeec0be6dcdfc0730298b5a041 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -74,6 +74,7 @@ enum { }; #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) +extern int selinux_android_netlink_route; extern int selinux_policycap_netpeer; extern int selinux_policycap_openperm; extern int selinux_policycap_alwaysnetwork; @@ -262,6 +263,7 @@ extern struct vfsmount *selinuxfs_mount; extern void selnl_notify_setenforce(int val); extern void selnl_notify_policyload(u32 seqno); extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); +extern void selinux_nlmsg_init(void); #endif /* _SELINUX_SECURITY_H_ */ diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 2ca9cde939d44976365aa67fe72f51be9b92897d..697785cec7f6bb85abb0c591b3993c82e33f2597 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -193,3 +193,27 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) return err; } + +static void nlmsg_set_getlink_perm(u32 perm) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nlmsg_route_perms); i++) { + if (nlmsg_route_perms[i].nlmsg_type == RTM_GETLINK) { + nlmsg_route_perms[i].perm = perm; + break; + } + } +} + +/** + * Use nlmsg_readpriv as the permission for RTM_GETLINK messages if the + * netlink_route_getlink policy capability is set. Otherwise use nlmsg_read. + */ +void selinux_nlmsg_init(void) +{ + if (selinux_android_netlink_route) + nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READPRIV); + else + nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READ); +} diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index af9cc839856f65ad81f6e7267b431d97776dd518..62518b031e5e43229909937672bd608be565cd0e 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -2332,6 +2332,10 @@ int policydb_read(struct policydb *p, void *fp) p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); + if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE)) { + p->android_netlink_route = 1; + } + if (p->policyvers >= POLICYDB_VERSION_POLCAP) { rc = ebitmap_read(&p->policycaps, fp); if (rc) diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 725d5945a97e961f6fb6fde88eab0bba5f638345..0d511cf3c1e99af3d4996c71c758ff6d7509a580 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -227,6 +227,7 @@ struct genfs { /* The policy database */ struct policydb { int mls_enabled; + int android_netlink_route; /* symbol tables */ struct symtab symtab[SYM_NUM]; @@ -313,6 +314,7 @@ extern int policydb_write(struct policydb *p, void *fp); #define PERM_SYMTAB_SIZE 32 #define POLICYDB_CONFIG_MLS 1 +#define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE (1 << 31) /* the config flags related to unknown classes/perms are bits 2 and 3 */ #define REJECT_UNKNOWN 0x00000002 diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index a6b097098aba3920ee29a80af84b77dd44bdc436..b96d4466de4c1ec8648097235a4be5d0abd34f3e 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -70,6 +70,7 @@ #include "ebitmap.h" #include "audit.h" +int selinux_android_netlink_route; int selinux_policycap_netpeer; int selinux_policycap_openperm; int selinux_policycap_alwaysnetwork; @@ -1990,6 +1991,9 @@ static void security_load_policycaps(void) POLICYDB_CAPABILITY_OPENPERM); selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps, POLICYDB_CAPABILITY_ALWAYSNETWORK); + + selinux_android_netlink_route = policydb.android_netlink_route; + selinux_nlmsg_init(); } static int security_preserve_bools(struct policydb *p); diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index a04edff8b729ebf8fff761c8c3814f1ab66b4a80..ae50d59fb810fc429d1282fd5fe069caf610528a 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -74,8 +74,10 @@ static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) return 0; } v = i2c_smbus_read_byte_data(onyx->i2c, reg); - if (v < 0) + if (v < 0) { + *value = 0; return -1; + } *value = (u8)v; onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; return 0; diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c index 2045697f449d3f5ebe347572dc2dfba66b64568a..797d838a2f9eb4ef7c3ebb7d6e56858d8ac077a5 100644 --- a/sound/core/oss/linear.c +++ b/sound/core/oss/linear.c @@ -107,6 +107,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin, } } #endif + if (frames > dst_channels[0].frames) + frames = dst_channels[0].frames; convert(plugin, src_channels, dst_channels, frames); return frames; } diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c index 7915564bd39445fd45e8cff34330ea269c6e9476..3788906421a73d2b34979fbf4fbfbd33fc8010e8 100644 --- a/sound/core/oss/mulaw.c +++ b/sound/core/oss/mulaw.c @@ -269,6 +269,8 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin, } } #endif + if (frames > dst_channels[0].frames) + frames = dst_channels[0].frames; data = (struct mulaw_priv *)plugin->extra_data; data->func(plugin, src_channels, dst_channels, frames); return frames; diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c index c8171f5783c873c49eaa86d61420b99e30adfac8..72dea04197ef2ffd820cb8f36de4c25d09587f67 100644 --- a/sound/core/oss/route.c +++ b/sound/core/oss/route.c @@ -57,6 +57,8 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin, return -ENXIO; if (frames == 0) return 0; + if (frames > dst_channels[0].frames) + frames = dst_channels[0].frames; nsrcs = plugin->src_format.channels; ndsts = plugin->dst_format.channels; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 2bae2a365f399c75e07b61b1eb29f245a447d246..3640269732f5a3b80c1eefd7c4a1665158c54473 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1892,11 +1892,14 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime; unsigned long flags; - if (PCM_RUNTIME_CHECK(substream)) + if (snd_BUG_ON(!substream)) return; - runtime = substream->runtime; snd_pcm_stream_lock_irqsave(substream, flags); + if (PCM_RUNTIME_CHECK(substream)) + goto _unlock; + runtime = substream->runtime; + if (!snd_pcm_running(substream) || snd_pcm_update_hw_ptr0(substream, 1) < 0) goto _end; @@ -1907,6 +1910,7 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) #endif _end: kill_fasync(&runtime->fasync, SIGIO, POLL_IN); + _unlock: snd_pcm_stream_unlock_irqrestore(substream, flags); } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0a747df74102eae6f958c0c1235043e83abb8c14..0179ef50b6b6554e68a47088f2488eb561ceb8a8 100755 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -587,6 +587,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, LONG_MAX - runtime->buffer_size) runtime->boundary *= 2; + /* clear the buffer for avoiding possible kernel info leaks */ + if (runtime->dma_area && !substream->ops->copy) + memset(runtime->dma_area, 0, runtime->dma_bytes); + snd_pcm_timer_resolution_change(substream); snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index eee4ea17a8f52c66d371c1eedea28bafd7a37482..198eea5c8c2f07d265311f373e5764df8e852e08 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -564,7 +564,7 @@ static int update_timestamp_of_queue(struct snd_seq_event *event, event->queue = queue; event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK; if (real_time) { - event->time.time = snd_seq_timer_get_cur_time(q->timer); + event->time.time = snd_seq_timer_get_cur_time(q->timer, true); event->flags |= SNDRV_SEQ_TIME_STAMP_REAL; } else { event->time.tick = snd_seq_timer_get_cur_tick(q->timer); @@ -1639,7 +1639,7 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, tmr = queue->timer; status->events = queue->tickq->cells + queue->timeq->cells; - status->time = snd_seq_timer_get_cur_time(tmr); + status->time = snd_seq_timer_get_cur_time(tmr, true); status->tick = snd_seq_timer_get_cur_tick(tmr); status->running = tmr->running; diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 1a6dc4ff44a69bb53e4b8ab9009b957ea7fd8689..ea1aa079627618ffae4ca3924a15c941bf40e06f 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -261,6 +261,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) { unsigned long flags; struct snd_seq_event_cell *cell; + snd_seq_tick_time_t cur_tick; + snd_seq_real_time_t cur_time; if (q == NULL) return; @@ -277,17 +279,18 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) __again: /* Process tick queue... */ + cur_tick = snd_seq_timer_get_cur_tick(q->timer); for (;;) { - cell = snd_seq_prioq_cell_out(q->tickq, - &q->timer->tick.cur_tick); + cell = snd_seq_prioq_cell_out(q->tickq, &cur_tick); if (!cell) break; snd_seq_dispatch_event(cell, atomic, hop); } /* Process time queue... */ + cur_time = snd_seq_timer_get_cur_time(q->timer, false); for (;;) { - cell = snd_seq_prioq_cell_out(q->timeq, &q->timer->cur_time); + cell = snd_seq_prioq_cell_out(q->timeq, &cur_time); if (!cell) break; snd_seq_dispatch_event(cell, atomic, hop); @@ -415,6 +418,7 @@ int snd_seq_queue_check_access(int queueid, int client) int snd_seq_queue_set_owner(int queueid, int client, int locked) { struct snd_seq_queue *q = queueptr(queueid); + unsigned long flags; if (q == NULL) return -EINVAL; @@ -424,8 +428,10 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked) return -EPERM; } + spin_lock_irqsave(&q->owner_lock, flags); q->locked = locked ? 1 : 0; q->owner = client; + spin_unlock_irqrestore(&q->owner_lock, flags); queue_access_unlock(q); queuefree(q); @@ -564,15 +570,17 @@ void snd_seq_queue_client_termination(int client) unsigned long flags; int i; struct snd_seq_queue *q; + bool matched; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { if ((q = queueptr(i)) == NULL) continue; spin_lock_irqsave(&q->owner_lock, flags); - if (q->owner == client) + matched = (q->owner == client); + if (matched) q->klocked = 1; spin_unlock_irqrestore(&q->owner_lock, flags); - if (q->owner == client) { + if (matched) { if (q->timer->running) snd_seq_timer_stop(q->timer); snd_seq_timer_reset(q->timer); @@ -764,6 +772,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, int i, bpm; struct snd_seq_queue *q; struct snd_seq_timer *tmr; + bool locked; + int owner; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { if ((q = queueptr(i)) == NULL) @@ -775,9 +785,14 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, else bpm = 0; + spin_lock_irq(&q->owner_lock); + locked = q->locked; + owner = q->owner; + spin_unlock_irq(&q->owner_lock); + snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name); - snd_iprintf(buffer, "owned by client : %d\n", q->owner); - snd_iprintf(buffer, "lock status : %s\n", q->locked ? "Locked" : "Free"); + snd_iprintf(buffer, "owned by client : %d\n", owner); + snd_iprintf(buffer, "lock status : %s\n", locked ? "Locked" : "Free"); snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq)); snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq)); snd_iprintf(buffer, "timer state : %s\n", tmr->running ? "Running" : "Stopped"); diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index b80985fbc334cc6598d7ca2953d1ce79edb9f68b..bd5e5a5d52a8d459cc86a30e3c770a433918d9ad 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -436,14 +436,15 @@ int snd_seq_timer_continue(struct snd_seq_timer *tmr) } /* return current 'real' time. use timeofday() to get better granularity. */ -snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) +snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr, + bool adjust_ktime) { snd_seq_real_time_t cur_time; unsigned long flags; spin_lock_irqsave(&tmr->lock, flags); cur_time = tmr->cur_time; - if (tmr->running) { + if (adjust_ktime && tmr->running) { struct timespec64 tm; ktime_get_ts64(&tm); @@ -460,7 +461,13 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) high PPQ values) */ snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr) { - return tmr->tick.cur_tick; + snd_seq_tick_time_t cur_tick; + unsigned long flags; + + spin_lock_irqsave(&tmr->lock, flags); + cur_tick = tmr->tick.cur_tick; + spin_unlock_irqrestore(&tmr->lock, flags); + return cur_tick; } @@ -479,15 +486,19 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry, q = queueptr(idx); if (q == NULL) continue; - if ((tmr = q->timer) == NULL || - (ti = tmr->timeri) == NULL) { - queuefree(q); - continue; - } + mutex_lock(&q->timer_mutex); + tmr = q->timer; + if (!tmr) + goto unlock; + ti = tmr->timeri; + if (!ti) + goto unlock; snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name); resolution = snd_timer_resolution(ti) * tmr->ticks; snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000); snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base); +unlock: + mutex_unlock(&q->timer_mutex); queuefree(q); } } diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h index 9506b661fe5bfcf056c97799a39e1ba9dec8f029..5d47d559465e6b3f8211fc602b509368546a4d16 100644 --- a/sound/core/seq/seq_timer.h +++ b/sound/core/seq/seq_timer.h @@ -135,7 +135,8 @@ int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq); int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position); int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position); int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base); -snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr); +snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr, + bool adjust_ktime); snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr); extern int seq_default_timer_class; diff --git a/sound/core/timer.c b/sound/core/timer.c index 4eb085931d3f42dd2db6f544dc34d33faaf6f2cf..be9e517e264c3a4d06c456285d6b7f1960bb1a10 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -87,6 +87,9 @@ static LIST_HEAD(snd_timer_slave_list); /* lock for slave active lists */ static DEFINE_SPINLOCK(slave_active_lock); +#define MAX_SLAVE_INSTANCES 1000 +static int num_slaves; + static DEFINE_MUTEX(register_mutex); static int snd_timer_free(struct snd_timer *timer); @@ -265,6 +268,10 @@ int snd_timer_open(struct snd_timer_instance **ti, err = -EINVAL; goto unlock; } + if (num_slaves >= MAX_SLAVE_INSTANCES) { + err = -EBUSY; + goto unlock; + } timeri = snd_timer_instance_new(owner, NULL); if (!timeri) { err = -ENOMEM; @@ -274,6 +281,7 @@ int snd_timer_open(struct snd_timer_instance **ti, timeri->slave_id = tid->device; timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; list_add_tail(&timeri->open_list, &snd_timer_slave_list); + num_slaves++; err = snd_timer_check_slave(timeri); if (err < 0) { snd_timer_close_locked(timeri, &card_dev_to_put); @@ -363,6 +371,8 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri, struct snd_timer_instance *slave, *tmp; list_del(&timeri->open_list); + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) + num_slaves--; /* force to stop the timer */ snd_timer_stop(timeri); diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 172dacd925f5721c2726194ddb917aa612f4afc3..c182341c17149ed1c4d948b4b6030e9cdc5ed8ff 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -925,7 +925,7 @@ static void print_formats(struct snd_dummy *dummy, { int i; - for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { if (dummy->pcm_hw.formats & (1ULL << i)) snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); } diff --git a/sound/hda/hdmi_chmap.c b/sound/hda/hdmi_chmap.c index f21633cd9b38ea9a8f6a3c955f9209a8f66ecf2f..acbe61b8db7b26b9fa535fb41f3845b612ac0e19 100644 --- a/sound/hda/hdmi_chmap.c +++ b/sound/hda/hdmi_chmap.c @@ -249,7 +249,7 @@ void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen) for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) { if (spk_alloc & (1 << i)) - j += snprintf(buf + j, buflen - j, " %s", + j += scnprintf(buf + j, buflen - j, " %s", cea_speaker_allocation_names[i]); } buf[j] = '\0'; /* necessary when j == 0 */ diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 9d7582c90a95d90a66290c6e386aa4749b8ff056..c67d379cb6d6af911098a59a0662631fc3832713 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -293,7 +293,8 @@ static int snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev) } else { mpu_port[dev] = pnp_port_start(pdev, 0); if (mpu_irq[dev] >= 0 && - pnp_irq_valid(pdev, 0) && pnp_irq(pdev, 0) >= 0) { + pnp_irq_valid(pdev, 0) && + pnp_irq(pdev, 0) != (resource_size_t)-1) { mpu_irq[dev] = pnp_irq(pdev, 0); } else { mpu_irq[dev] = -1; /* disable interrupt */ diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 7ea201c05e5da6858b325ad13074749c768eb523..d0d6dfbfcfdf8731a76aeac7664dbd007ee970e4 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -42,6 +42,10 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev) { struct hda_codec *codec = container_of(dev, struct hda_codec, core); + /* ignore unsol events during shutdown */ + if (codec->bus->shutdown) + 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 1b5e217d1bb27e8b7675c5f273fc5c1a6e5b7f0b..2ad28ce7ff49751a96b202e90546d45b8aa7530c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4104,7 +4104,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen) for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++) if (pcm & (AC_SUPPCM_BITS_8 << i)) - j += snprintf(buf + j, buflen - j, " %d", bits[i]); + j += scnprintf(buf + j, buflen - j, " %d", bits[i]); buf[j] = '\0'; /* necessary when j == 0 */ } diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index c5e82329348b3d62101a5f433751986845f2e504..bd0e4710d15d7b6f18a71d601194212ac5355836 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -872,7 +872,7 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, return -EAGAIN; /* give a chance to retry */ } - dev_WARN(chip->card->dev, + dev_err(chip->card->dev, "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", bus->last_cmd[addr]); chip->single_cmd = 1; diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index b83feecf1e40c75d9c90f3df39d8858aef1f0cae..8f938699827036004532d377b35ae9aa3b27bfd8 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -171,11 +171,10 @@ struct azx { #define azx_bus(chip) (&(chip)->bus.core) #define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core) -#ifdef CONFIG_X86 -#define azx_snoop(chip) ((chip)->snoop) -#else -#define azx_snoop(chip) true -#endif +static inline bool azx_snoop(struct azx *chip) +{ + return !IS_ENABLED(CONFIG_X86) || chip->snoop; +} /* * macros for easy use diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index ba7fe9b6655c1f25279e5489081f34327f215d45..864cc8c9ada0ae6112445d3a6622f337067e778f 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -373,7 +373,7 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++) if (pcm & (1 << i)) - j += snprintf(buf + j, buflen - j, " %d", + j += scnprintf(buf + j, buflen - j, " %d", alsa_rates[i]); buf[j] = '\0'; /* necessary when j == 0 */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index f2f1d9fd848c84f90b553c650e0314eb53232fba..3234e9ca02cece8da7ac3324c5c4e21bdcbd79b6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1275,8 +1275,11 @@ static int azx_free(struct azx *chip) static int azx_dev_disconnect(struct snd_device *device) { struct azx *chip = device->device_data; + struct hdac_bus *bus = azx_bus(chip); chip->bus.shutdown = 1; + cancel_work_sync(&bus->unsol_work); + return 0; } diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index 9739fce9e032c3a2126a75b1148c21c5e3502bdd..f3ac19d33bd4df8ee773a8d34e9ec0b76be9bf60 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -221,7 +221,7 @@ static ssize_t init_verbs_show(struct device *dev, mutex_lock(&codec->user_mutex); for (i = 0; i < codec->init_verbs.used; i++) { struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); - len += snprintf(buf + len, PAGE_SIZE - len, + len += scnprintf(buf + len, PAGE_SIZE - len, "0x%02x 0x%03x 0x%04x\n", v->nid, v->verb, v->param); } @@ -271,7 +271,7 @@ static ssize_t hints_show(struct device *dev, mutex_lock(&codec->user_mutex); for (i = 0; i < codec->hints.used; i++) { struct hda_hint *hint = snd_array_elem(&codec->hints, i); - len += snprintf(buf + len, PAGE_SIZE - len, + len += scnprintf(buf + len, PAGE_SIZE - len, "%s = %s\n", hint->key, hint->val); } mutex_unlock(&codec->user_mutex); diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 475b2c6c43d61cdad5b07d3f65ae959088b6f0c6..bf7593f234f650aa6d65bf8100c5698c56326cba 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1300,13 +1300,14 @@ struct scp_msg { static void dspio_clear_response_queue(struct hda_codec *codec) { + unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned int dummy = 0; - int status = -1; + int status; /* clear all from the response queue */ do { status = dspio_read(codec, &dummy); - } while (status == 0); + } while (status == 0 && time_before(jiffies, timeout)); } static int dspio_get_response_data(struct hda_codec *codec) @@ -4424,12 +4425,14 @@ static void ca0132_process_dsp_response(struct hda_codec *codec, struct ca0132_spec *spec = codec->spec; codec_dbg(codec, "ca0132_process_dsp_response\n"); + snd_hda_power_up_pm(codec); if (spec->wait_scp) { if (dspio_get_response_data(codec) >= 0) spec->wait_scp = 0; } dspio_clear_response_queue(codec); + snd_hda_power_down_pm(codec); } static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 8557b94e462cb2fbd635e1d7ce9283f9b8cb7289..1e99500dbb6c827038b7aafbcb62ddcff9fc7dec 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -853,6 +853,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x21d2, "Lenovo T420s", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD), diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index e5c52ed9b6747003993d93ff4f1e2f1a760ced3e..8c06de37b467a6155ec5405e8f7240aff41aadcb 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -661,6 +661,7 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, unsigned long flags; unsigned char mclk_change; unsigned int i, old_rate; + bool call_set_rate = false; if (rate > ice->hw_rates->list[ice->hw_rates->count - 1]) return -EINVAL; @@ -684,7 +685,7 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, * setting clock rate for internal clock mode */ old_rate = ice->get_rate(ice); if (force || (old_rate != rate)) - ice->set_rate(ice, rate); + call_set_rate = true; else if (rate == ice->cur_rate) { spin_unlock_irqrestore(&ice->reg_lock, flags); return 0; @@ -692,12 +693,14 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, } ice->cur_rate = rate; + spin_unlock_irqrestore(&ice->reg_lock, flags); + + if (call_set_rate) + ice->set_rate(ice, rate); /* setting master clock */ mclk_change = ice->set_mclk(ice, rate); - spin_unlock_irqrestore(&ice->reg_lock, flags); - if (mclk_change && ice->gpio.i2s_mclk_changed) ice->gpio.i2s_mclk_changed(ice); if (ice->gpio.set_pro_rate) diff --git a/sound/sh/aica.c b/sound/sh/aica.c index fbbc252795599655bac0f795fbe47b607f18f8d8..2a127feb8e293750706bc7cb663f9c9b85df16bd 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -117,10 +117,10 @@ static void spu_memset(u32 toi, u32 what, int length) } /* spu_memload - write to SPU address space */ -static void spu_memload(u32 toi, void *from, int length) +static void spu_memload(u32 toi, const void *from, int length) { unsigned long flags; - u32 *froml = from; + const u32 *froml = from; u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi); int i; u32 val; diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 22aec9a1e9a4991026e98b40879e2064997b92a1..838d03a138ca2620f264579575ed953487431c17 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -25,6 +25,8 @@ config SND_ATMEL_SOC_DMA config SND_ATMEL_SOC_SSC_DMA tristate + select SND_ATMEL_SOC_DMA + select SND_ATMEL_SOC_PDC config SND_ATMEL_SOC_SSC tristate diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index 231ca935cdf3bdf22e7db0866a0dabfa61084e1e..c232c42ccead0e113bb0118db316ea9ee5f74d7e 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -380,6 +380,7 @@ static struct i2c_driver cs4349_i2c_driver = { .driver = { .name = "cs4349", .of_match_table = cs4349_of_match, + .pm = &cs4349_runtime_pm, }, .id_table = cs4349_i2c_id, .probe = cs4349_i2c_probe, diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 37722194b107e8a733bb124be480ff46b63749ef..6b22700842e2612478452f081c81a180c4d2ddf3 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -234,7 +234,7 @@ static const struct soc_enum es8328_rline_enum = ARRAY_SIZE(es8328_line_texts), es8328_line_texts); static const struct snd_kcontrol_new es8328_right_line_controls = - SOC_DAPM_ENUM("Route", es8328_lline_enum); + SOC_DAPM_ENUM("Route", es8328_rline_enum); /* Left Mixer */ static const struct snd_kcontrol_new es8328_left_mixer_controls[] = { diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 72b19e62f6267698aea45d2410d616d91c1825cb..c0807b82399a0e4238530fdb13685abb4a90621b 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1441,13 +1441,15 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) } pcm512x->sclk = devm_clk_get(dev, NULL); - if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err; + } if (!IS_ERR(pcm512x->sclk)) { ret = clk_prepare_enable(pcm512x->sclk); if (ret != 0) { dev_err(dev, "Failed to enable SCLK: %d\n", ret); - return ret; + goto err; } } diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 65ac4518ad06096e1ca8d04c539fc19ddf1b8f15..49ab26e69f2fc5b11397290ac89d11e60e0ced12 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -305,6 +305,7 @@ static bool rt5677_volatile_register(struct device *dev, unsigned int reg) case RT5677_I2C_MASTER_CTRL7: case RT5677_I2C_MASTER_CTRL8: case RT5677_HAP_GENE_CTRL2: + case RT5677_PWR_ANLG2: /* Modified by DSP firmware */ case RT5677_PWR_DSP_ST: case RT5677_PRIV_DATA: case RT5677_ASRC_22: diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index f0cb1c4afe3cec6429038af5eaee5e892c478917..c5a8d758f58b8a122c8d44583df9174770fd24a4 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -170,7 +170,7 @@ SOC_DOUBLE("Polarity Invert Switch", WM8737_ADC_CONTROL, 5, 6, 1, 0), SOC_SINGLE("3D Switch", WM8737_3D_ENHANCE, 0, 1, 0), SOC_SINGLE("3D Depth", WM8737_3D_ENHANCE, 1, 15, 0), SOC_ENUM("3D Low Cut-off", low_3d), -SOC_ENUM("3D High Cut-off", low_3d), +SOC_ENUM("3D High Cut-off", high_3d), SOC_SINGLE_TLV("3D ADC Volume", WM8737_3D_ENHANCE, 7, 1, 1, adc_tlv), SOC_SINGLE("Noise Gate Switch", WM8737_NOISE_GATE, 0, 1, 0), diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index fd2731d171dd02511ecb85d67a1189b509db4c71..0e8008d38161905e06bdd6a40fb96c84f3212ace 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2791,7 +2791,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, if (target % Fref == 0) { fll_div->theta = 0; - fll_div->lambda = 0; + fll_div->lambda = 1; } else { gcd_fll = gcd(target, fratio * Fref); @@ -2861,7 +2861,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, return -EINVAL; } - if (fll_div.theta || fll_div.lambda) + if (fll_div.theta) fll1 |= WM8962_FLL_FRAC; /* Stop the FLL while we reconfigure */ diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 624c209c94981696a4f91601ed52de75eb4068ab..d1935c5c3602b9c6ce3ed2fa3f7c6ad6a55476c4 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -882,14 +882,13 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, active_slots = hweight32(mcasp->tdm_mask[stream]); active_serializers = (channels + active_slots - 1) / active_slots; - if (active_serializers == 1) { + if (active_serializers == 1) active_slots = channels; - for (i = 0; i < total_slots; i++) { - if ((1 << i) & mcasp->tdm_mask[stream]) { - mask |= (1 << i); - if (--active_slots <= 0) - break; - } + for (i = 0; i < total_slots; i++) { + if ((1 << i) & mcasp->tdm_mask[stream]) { + mask |= (1 << i); + if (--active_slots <= 0) + break; } } } else { diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 8e525f7ac08d1e859ffbb76d1f73f441abef0e92..3d99a8579c99f8f75a092c72448e87e4820a65bf 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -119,7 +119,8 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) codec_dev = of_find_i2c_device_by_node(codec_np); if (!codec_dev) { dev_err(&pdev->dev, "failed to find codec platform device\n"); - return -EPROBE_DEFER; + ret = -EPROBE_DEFER; + goto fail; } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 07f91e918b2349b75271ac319f85e6416a4199e6..3d91cef3704a579773f502a1fde645208be4a6f7 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -114,46 +114,58 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) if (!cpu || !codec) { dev_err(dev, "Can't find cpu/codec DT node\n"); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto error; } link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); if (!link->cpu_of_node) { dev_err(card->dev, "error getting cpu phandle\n"); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto error; } link->codec_of_node = of_parse_phandle(codec, "sound-dai", 0); if (!link->codec_of_node) { dev_err(card->dev, "error getting codec phandle\n"); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto error; } ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); if (ret) { dev_err(card->dev, "error getting cpu dai name\n"); - return ERR_PTR(ret); + goto error; } ret = snd_soc_of_get_dai_name(codec, &link->codec_dai_name); if (ret) { dev_err(card->dev, "error getting codec dai name\n"); - return ERR_PTR(ret); + goto error; } link->platform_of_node = link->cpu_of_node; ret = of_property_read_string(np, "link-name", &link->name); if (ret) { dev_err(card->dev, "error getting codec dai_link name\n"); - return ERR_PTR(ret); + goto error; } link->stream_name = link->name; link->init = apq8016_sbc_dai_init; link++; + + of_node_put(cpu); + of_node_put(codec); } return data; + + error: + of_node_put(np); + of_node_put(cpu); + of_node_put(codec); + return ERR_PTR(ret); } static const struct snd_soc_dapm_widget apq8016_sbc_dapm_widgets[] = { diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1ed8c1683e8c6242a11aea1355cbbbcb4c316b5a..0b8e65d56a0cac8b9af129570d36be8399f652b8 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4382,7 +4382,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) continue; if (w->power) { dapm_seq_insert(w, &down_list, false); - w->power = 0; + w->new_power = 0; powerdown = 1; } } diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index fbaa1bb41102f45920f478008070ee53cdbbb6b4..00d7902ad427ae35c2a3502e3c43d7ae839a4a18 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -80,10 +80,9 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) unsigned int sync = 0; int enable; - trace_snd_soc_jack_report(jack, mask, status); - if (!jack) return; + trace_snd_soc_jack_report(jack, mask, status); dapm = &jack->card->dapm; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b396b475ec63312ca1b06ae2e3f9942e80de3463..d444dba25cddce2ba62cb8697e6a8f63ba740e0f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -73,8 +73,8 @@ static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) else codec_stream = &dai->driver->capture; - /* If the codec specifies any rate at all, it supports the stream. */ - return codec_stream->rates; + /* If the codec specifies any channels at all, it supports the stream */ + return codec_stream->channels_min; } /** @@ -2330,42 +2330,81 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, } EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); +static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, + int cmd, bool fe_first) +{ + struct snd_soc_pcm_runtime *fe = substream->private_data; + int ret; + + /* call trigger on the frontend before the backend. */ + if (fe_first) { + dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n", + fe->dai_link->name, cmd); + + ret = soc_pcm_trigger(substream, cmd); + if (ret < 0) + return ret; + + ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); + return ret; + } + + /* call trigger on the frontend after the backend. */ + ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); + if (ret < 0) + return ret; + + dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", + fe->dai_link->name, cmd); + + ret = soc_pcm_trigger(substream, cmd); + + return ret; +} + static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *fe = substream->private_data; - int stream = substream->stream, ret; + int stream = substream->stream; + int ret = 0; enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; switch (trigger) { case SND_SOC_DPCM_TRIGGER_PRE: - /* call trigger on the frontend before the backend. */ - - dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n", - fe->dai_link->name, cmd); - - ret = soc_pcm_trigger(substream, cmd); - if (ret < 0) { - dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret); - goto out; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = dpcm_dai_trigger_fe_be(substream, cmd, true); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = dpcm_dai_trigger_fe_be(substream, cmd, false); + break; + default: + ret = -EINVAL; + break; } - - ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); break; case SND_SOC_DPCM_TRIGGER_POST: - /* call trigger on the frontend after the backend. */ - - ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); - if (ret < 0) { - dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret); - goto out; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = dpcm_dai_trigger_fe_be(substream, cmd, false); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = dpcm_dai_trigger_fe_be(substream, cmd, true); + break; + default: + ret = -EINVAL; + break; } - - dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", - fe->dai_link->name, cmd); - - ret = soc_pcm_trigger(substream, cmd); break; case SND_SOC_DPCM_TRIGGER_BESPOKE: /* bespoke trigger() - handles both FE and BEs */ @@ -2374,10 +2413,6 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) fe->dai_link->name, cmd); ret = soc_pcm_bespoke_trigger(substream, cmd); - if (ret < 0) { - dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret); - goto out; - } break; default: dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd, @@ -2386,6 +2421,12 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) goto out; } + if (ret < 0) { + dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n", + cmd, ret); + goto out; + } + switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -3307,16 +3348,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, ssize_t offset = 0; /* FE state */ - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "[%s - %s]\n", fe->dai_link->name, stream ? "Capture" : "Playback"); - offset += snprintf(buf + offset, size - offset, "State: %s\n", + offset += scnprintf(buf + offset, size - offset, "State: %s\n", dpcm_state_string(fe->dpcm[stream].state)); if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "Hardware Params: " "Format = %s, Channels = %d, Rate = %d\n", snd_pcm_format_name(params_format(params)), @@ -3324,10 +3365,10 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, params_rate(params)); /* BEs state */ - offset += snprintf(buf + offset, size - offset, "Backends:\n"); + offset += scnprintf(buf + offset, size - offset, "Backends:\n"); if (list_empty(&fe->dpcm[stream].be_clients)) { - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " No active DSP links\n"); goto out; } @@ -3336,16 +3377,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be = dpcm->be; params = &dpcm->hw_params; - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "- %s\n", be->dai_link->name); - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " State: %s\n", dpcm_state_string(be->dpcm[stream].state)); if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " Hardware Params: " "Format = %s, Channels = %d, Rate = %d\n", snd_pcm_format_name(params_format(params)), diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 15c92400cea423a05f4011df56ae8045db2675f8..02c373c65e194918b976cef44c7d3bdef8aaa436 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -78,8 +78,8 @@ #define SUN4I_I2S_CLK_DIV_MCLK_MASK GENMASK(3, 0) #define SUN4I_I2S_CLK_DIV_MCLK(mclk) ((mclk) << 0) -#define SUN4I_I2S_RX_CNT_REG 0x28 -#define SUN4I_I2S_TX_CNT_REG 0x2c +#define SUN4I_I2S_TX_CNT_REG 0x28 +#define SUN4I_I2S_RX_CNT_REG 0x2c #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30 #define SUN4I_I2S_TX_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 503278656508ad6f13f99a70da795d496841d65d..e2cbdd080d33440ff7e20afd06369200447099f8 100755 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2995,7 +2995,9 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, (err = snd_usb_mixer_status_create(mixer)) < 0) goto _error; - snd_usb_mixer_apply_create_quirk(mixer); + err = snd_usb_mixer_apply_create_quirk(mixer); + if (err < 0) + goto _error; err = snd_device_new(chip->card, SNDRV_DEV_CODEC, mixer, &dev_ops); if (err < 0) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d32727c74a168779fc31f91302d408ab7d0f52e5..c892b4d1e733f7b061f7a983fd11025209eb944e 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3293,19 +3293,14 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), .ifnum = 0, .type = QUIRK_AUDIO_STANDARD_MIXER, }, - /* Capture */ - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE, - }, /* Playback */ { - .ifnum = 2, + .ifnum = 1, .type = QUIRK_AUDIO_FIXED_ENDPOINT, .data = &(const struct audioformat) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, - .iface = 2, + .iface = 1, .altsetting = 1, .altset_idx = 1, .attributes = UAC_EP_CS_ATTR_FILL_MAX | diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index da9fc08b20bb38d3a89d3b63d27c751027b7ae12..064f3485a977d4f9c44e2fdd1d415d3a4eb791c4 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1141,6 +1141,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */ + case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */ case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */ case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ @@ -1148,6 +1149,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */ case USB_ID(0x1de7, 0x0114): /* Phoenix Audio MT202pcs */ case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ + case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */ return true; } return false; diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 0b34dbc8f3020436d3e740bb61dea9f648a745ab..7dcb33d3886bc12e556f2751ac4ac8434290e52f 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -132,7 +132,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, info->num_dsps = 2; // 0: Prepad Data, 1: FPGA Code if (us428->chip_status & USX2Y_STAT_CHIP_INIT) info->chip_ready = 1; - info->version = USX2Y_DRIVER_VERSION; + info->version = USX2Y_DRIVER_VERSION; return 0; } diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h index f436d2420a18575095e66b7bfbf15b0abbe83fe8..115ecca5f8b9d38a537149da570016814f12121e 100644 --- a/tools/include/linux/string.h +++ b/tools/include/linux/string.h @@ -13,7 +13,15 @@ int strtobool(const char *s, bool *res); * However uClibc headers also define __GLIBC__ hence the hack below */ #if defined(__GLIBC__) && !defined(__UCLIBC__) +// pragma diagnostic was introduced in gcc 4.6 +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif extern size_t strlcpy(char *dest, const char *src, size_t size); +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic pop +#endif #endif char *str_error_r(int errnum, char *buf, size_t buflen); diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c index f99f49e4a31e65faba6bad4b1c82b99a01de7ded..21e714cf0126c8aa45c1617ca8f3ff13c82b2f51 100644 --- a/tools/lib/api/fs/fs.c +++ b/tools/lib/api/fs/fs.c @@ -194,6 +194,7 @@ static bool fs__env_override(struct fs *fs) size_t name_len = strlen(fs->name); /* name + "_PATH" + '\0' */ char upper_name[name_len + 5 + 1]; + memcpy(upper_name, fs->name, name_len); mem_toupper(upper_name, name_len); strcpy(&upper_name[name_len], "_PATH"); @@ -203,7 +204,8 @@ static bool fs__env_override(struct fs *fs) return false; fs->found = true; - strncpy(fs->path, override_path, sizeof(fs->path)); + strncpy(fs->path, override_path, sizeof(fs->path) - 1); + fs->path[sizeof(fs->path) - 1] = '\0'; return true; } diff --git a/tools/lib/string.c b/tools/lib/string.c index bd239bc1d557dbde447e8128ac7cd3163dc11a04..0e071c0bb09e3c8053a44f641123c5b239cd67ca 100644 --- a/tools/lib/string.c +++ b/tools/lib/string.c @@ -76,6 +76,10 @@ int strtobool(const char *s, bool *res) * If libc has strlcpy() then that version will override this * implementation: */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wignored-attributes" +#endif size_t __weak strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); @@ -87,3 +91,6 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size) } return ret; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 5e10ba796a6f4dede6f98d03d3b62cdeb35d14fa..569bceff5f51ba00dc1e8b2825cb5c86a125be8f 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1492,8 +1492,10 @@ static int copy_filter_type(struct event_filter *filter, if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) { /* Add trivial event */ arg = allocate_arg(); - if (arg == NULL) + if (arg == NULL) { + free(str); return -1; + } arg->type = FILTER_ARG_BOOLEAN; if (strcmp(str, "TRUE") == 0) @@ -1502,8 +1504,11 @@ static int copy_filter_type(struct event_filter *filter, arg->boolean.value = 0; filter_type = add_filter_type(filter, event->id); - if (filter_type == NULL) + if (filter_type == NULL) { + free(str); + free_arg(arg); return -1; + } filter_type->filter = arg; diff --git a/tools/objtool/arch/x86/lib/x86-opcode-map.txt b/tools/objtool/arch/x86/lib/x86-opcode-map.txt index 1754e094bc288014e1e173fe0858ebb6d9b5f1b3..82e105b284e01803a5c8520836ebf1dd7b591187 100644 --- a/tools/objtool/arch/x86/lib/x86-opcode-map.txt +++ b/tools/objtool/arch/x86/lib/x86-opcode-map.txt @@ -333,7 +333,7 @@ AVXcode: 1 06: CLTS 07: SYSRET (o64) 08: INVD -09: WBINVD +09: WBINVD | WBNOINVD (F3) 0a: 0b: UD2 (1B) 0c: @@ -364,7 +364,7 @@ AVXcode: 1 # a ModR/M byte. 1a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev 1b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv -1c: +1c: Grp20 (1A),(1C) 1d: 1e: 1f: NOP Ev @@ -792,6 +792,8 @@ f3: Grp17 (1A) f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v) f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v) f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v) +f8: MOVDIR64B Gv,Mdqq (66) | ENQCMD Gv,Mdqq (F2) | ENQCMDS Gv,Mdqq (F3) +f9: MOVDIRI My,Gy EndTable Table: 3-byte opcode 2 (0x0f 0x3a) @@ -907,7 +909,7 @@ EndTable GrpTable: Grp3_2 0: TEST Ev,Iz -1: +1: TEST Ev,Iz 2: NOT Ev 3: NEG Ev 4: MUL rAX,Ev @@ -943,9 +945,9 @@ GrpTable: Grp6 EndTable GrpTable: Grp7 -0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) -1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B) -2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) +0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) | PCONFIG (101),(11B) | ENCLV (000),(11B) +1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B) | ENCLS (111),(11B) +2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) | ENCLU (111),(11B) 3: LIDT Ms 4: SMSW Mw/Rv 5: rdpkru (110),(11B) | wrpkru (111),(11B) @@ -1011,7 +1013,7 @@ GrpTable: Grp15 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) 4: XSAVE 5: XRSTOR | lfence (11B) -6: XSAVEOPT | clwb (66) | mfence (11B) +6: XSAVEOPT | clwb (66) | mfence (11B) | TPAUSE Rd (66),(11B) | UMONITOR Rv (F3),(11B) | UMWAIT Rd (F2),(11B) 7: clflush | clflushopt (66) | sfence (11B) EndTable @@ -1042,6 +1044,10 @@ GrpTable: Grp19 6: vscatterpf1qps/d Wx (66),(ev) EndTable +GrpTable: Grp20 +0: cldemote Mb +EndTable + # AMD's Prefetch Group GrpTable: GrpP 0: PREFETCH diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6e88460cd13d3d65ad54f18470a1e8d7e445b06d..0abca8783bb3ce2459cb3fd1898df46e90e0fa92 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -671,6 +671,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) struct stat st; bool has_br_stack = false; int branch_mode = -1; + int last_key = 0; bool branch_call_mode = false; char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; const char * const report_usage[] = { @@ -956,7 +957,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) else use_browser = 0; - if (setup_sorting(session->evlist) < 0) { + if ((last_key != K_SWITCH_INPUT_DATA) && + (setup_sorting(session->evlist) < 0)) { if (sort_order) parse_options_usage(report_usage, options, "s", 1); if (field_order) @@ -1011,6 +1013,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) ret = __cmd_report(&report); if (ret == K_SWITCH_INPUT_DATA) { perf_session__delete(session); + last_key = K_SWITCH_INPUT_DATA; goto repeat; } else ret = 0; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index b0d005d295a90bf2b0484e8195b8f4b865a12416..de2ddfe0f7c3c04a167eae13ce76b236b85d701f 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -98,6 +98,7 @@ int test__task_exit(int subtest __maybe_unused) if (perf_evlist__mmap(evlist, 128, true) < 0) { pr_debug("failed to mmap events: %d (%s)\n", errno, str_error_r(errno, sbuf, sizeof(sbuf))); + err = -1; goto out_delete_evlist; } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a53fef0c673bbbfcf8669ffb66f5de079dbc7e18..ade6abda9f468d5103d9b5d7eec090a906d502cf 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2930,6 +2930,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, continue; } + actions->ms.map = map; top = pstack__peek(browser->pstack); if (top == &browser->hists->dso_filter) { /* diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 41e068e943499d2e7ce7a1794936eff09afd7077..fb4e1d2839c5f330239de8a4b67f6a52b7ab2765 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -317,21 +317,51 @@ bool die_is_func_def(Dwarf_Die *dw_die) dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL); } +/** + * die_entrypc - Returns entry PC (the lowest address) of a DIE + * @dw_die: a DIE + * @addr: where to store entry PC + * + * Since dwarf_entrypc() does not return entry PC if the DIE has only address + * range, we have to use this to retrieve the lowest address from the address + * range attribute. + */ +int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr) +{ + Dwarf_Addr base, end; + + if (!addr) + return -EINVAL; + + if (dwarf_entrypc(dw_die, addr) == 0) + return 0; + + return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0; +} + /** * die_is_func_instance - Ensure that this DIE is an instance of a subprogram * @dw_die: a DIE * * Ensure that this DIE is an instance (which has an entry address). - * This returns true if @dw_die is a function instance. If not, you need to - * call die_walk_instances() to find actual instances. + * This returns true if @dw_die is a function instance. If not, the @dw_die + * must be a prototype. You can use die_walk_instances() to find actual + * instances. **/ bool die_is_func_instance(Dwarf_Die *dw_die) { Dwarf_Addr tmp; + Dwarf_Attribute attr_mem; + int tag = dwarf_tag(dw_die); - /* Actually gcc optimizes non-inline as like as inlined */ - return !dwarf_func_inline(dw_die) && dwarf_entrypc(dw_die, &tmp) == 0; + if (tag != DW_TAG_subprogram && + tag != DW_TAG_inlined_subroutine) + return false; + + return dwarf_entrypc(dw_die, &tmp) == 0 || + dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL; } + /** * die_get_data_member_location - Get the data-member offset * @mb_die: a DIE of a member of a data structure @@ -608,6 +638,9 @@ static int __die_walk_instances_cb(Dwarf_Die *inst, void *data) Dwarf_Die *origin; int tmp; + if (!die_is_func_instance(inst)) + return DIE_FIND_CB_CONTINUE; + attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem); if (attr == NULL) return DIE_FIND_CB_CONTINUE; @@ -679,15 +712,14 @@ static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { fname = die_get_call_file(in_die); lineno = die_get_call_lineno(in_die); - if (fname && lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) { + if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) { lw->retval = lw->callback(fname, lineno, addr, lw->data); if (lw->retval != 0) return DIE_FIND_CB_END; } + if (!lw->recursive) + return DIE_FIND_CB_SIBLING; } - if (!lw->recursive) - /* Don't need to search recursively */ - return DIE_FIND_CB_SIBLING; if (addr) { fname = dwarf_decl_file(in_die); @@ -720,7 +752,7 @@ static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive, /* Handle function declaration line */ fname = dwarf_decl_file(sp_die); if (fname && dwarf_decl_line(sp_die, &lineno) == 0 && - dwarf_entrypc(sp_die, &addr) == 0) { + die_entrypc(sp_die, &addr) == 0) { lw.retval = callback(fname, lineno, addr, data); if (lw.retval != 0) goto done; @@ -734,6 +766,10 @@ static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data) { struct __line_walk_param *lw = data; + /* + * Since inlined function can include another inlined function in + * the same file, we need to walk in it recursively. + */ lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data); if (lw->retval != 0) return DWARF_CB_ABORT; @@ -758,11 +794,12 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) Dwarf_Lines *lines; Dwarf_Line *line; Dwarf_Addr addr; - const char *fname, *decf = NULL; + const char *fname, *decf = NULL, *inf = NULL; int lineno, ret = 0; int decl = 0, inl; Dwarf_Die die_mem, *cu_die; size_t nlines, i; + bool flag; /* Get the CU die */ if (dwarf_tag(rt_die) != DW_TAG_compile_unit) { @@ -793,6 +830,12 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) "Possible error in debuginfo.\n"); continue; } + /* Skip end-of-sequence */ + if (dwarf_lineendsequence(line, &flag) != 0 || flag) + continue; + /* Skip Non statement line-info */ + if (dwarf_linebeginstatement(line, &flag) != 0 || !flag) + continue; /* Filter lines based on address */ if (rt_die != cu_die) { /* @@ -802,13 +845,21 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) */ if (!dwarf_haspc(rt_die, addr)) continue; + if (die_find_inlinefunc(rt_die, addr, &die_mem)) { + /* Call-site check */ + inf = die_get_call_file(&die_mem); + if ((inf && !strcmp(inf, decf)) && + die_get_call_lineno(&die_mem) == lineno) + goto found; + dwarf_decl_line(&die_mem, &inl); if (inl != decl || decf != dwarf_decl_file(&die_mem)) continue; } } +found: /* Get source line */ fname = dwarf_linesrc(line, NULL, NULL); @@ -823,8 +874,9 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) */ if (rt_die != cu_die) /* - * Don't need walk functions recursively, because nested - * inlined functions don't have lines of the specified DIE. + * Don't need walk inlined functions recursively, because + * inner inlined functions don't have the lines of the + * specified function. */ ret = __die_walk_funclines(rt_die, false, callback, data); else { @@ -999,7 +1051,7 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die, bool first = true; const char *name; - ret = dwarf_entrypc(sp_die, &entry); + ret = die_entrypc(sp_die, &entry); if (ret) return ret; @@ -1062,7 +1114,7 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) bool first = true; const char *name; - ret = dwarf_entrypc(sp_die, &entry); + ret = die_entrypc(sp_die, &entry); if (ret) return ret; diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index 8ac53bf1ec4e4baef19c89f1d8c0968363a6ed74..ee15fac4e1d044dd1bcaa95c29499e0b253fb995 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -41,6 +41,9 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, /* Get DW_AT_linkage_name (should be NULL for C binary) */ const char *die_get_linkage_name(Dwarf_Die *dw_die); +/* Get the lowest PC in DIE (including range list) */ +int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr); + /* Ensure that this DIE is a subprogram and definition (not declaration) */ bool die_is_func_def(Dwarf_Die *dw_die); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 159d616e170b1c68600ab87ee01219df39b916ab..fdd7a1cb6be9509cea83df937676ede4c032ffd8 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -312,10 +312,10 @@ static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format) list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list) #define hists__for_each_format(hists, format) \ - perf_hpp_list__for_each_format((hists)->hpp_list, fmt) + perf_hpp_list__for_each_format((hists)->hpp_list, format) #define hists__for_each_sort_list(hists, format) \ - perf_hpp_list__for_each_sort_list((hists)->hpp_list, fmt) + perf_hpp_list__for_each_sort_list((hists)->hpp_list, format) extern struct perf_hpp_fmt perf_hpp__format[]; diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index 679d6e493962267f7b219b88c05d06c61ef1d2ea..e6324397b295b69ee8358c4c2421e00d8e0bd036 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h @@ -26,7 +26,7 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id); static inline const char *perf_reg_name(int id __maybe_unused) { - return NULL; + return "unknown"; } static inline int perf_reg_value(u64 *valp __maybe_unused, diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 0d9d6e0803b88b6fe3909c0b8b83f24fa47580f6..ffaa798df75e7dc952ca18f0cc566288bf9c903c 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -612,38 +612,26 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, const char *function, struct probe_trace_point *tp) { - Dwarf_Addr eaddr, highaddr; + Dwarf_Addr eaddr; GElf_Sym sym; const char *symbol; /* Verify the address is correct */ - if (dwarf_entrypc(sp_die, &eaddr) != 0) { - pr_warning("Failed to get entry address of %s\n", - dwarf_diename(sp_die)); - return -ENOENT; - } - if (dwarf_highpc(sp_die, &highaddr) != 0) { - pr_warning("Failed to get end address of %s\n", - dwarf_diename(sp_die)); - return -ENOENT; - } - if (paddr > highaddr) { - pr_warning("Offset specified is greater than size of %s\n", + if (!dwarf_haspc(sp_die, paddr)) { + pr_warning("Specified offset is out of %s\n", dwarf_diename(sp_die)); return -EINVAL; } - symbol = dwarf_diename(sp_die); + /* Try to get actual symbol name from symtab */ + symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); if (!symbol) { - /* Try to get the symbol name from symtab */ - symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); - if (!symbol) { - pr_warning("Failed to find symbol at 0x%lx\n", - (unsigned long)paddr); - return -ENOENT; - } - eaddr = sym.st_value; + pr_warning("Failed to find symbol at 0x%lx\n", + (unsigned long)paddr); + return -ENOENT; } + eaddr = sym.st_value; + tp->offset = (unsigned long)(paddr - eaddr); tp->address = (unsigned long)paddr; tp->symbol = strdup(symbol); @@ -764,6 +752,16 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data) return 0; } +/* Return innermost DIE */ +static int find_inner_scope_cb(Dwarf_Die *fn_die, void *data) +{ + struct find_scope_param *fsp = data; + + memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); + fsp->found = true; + return 1; +} + /* Find an appropriate scope fits to given conditions */ static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem) { @@ -775,8 +773,13 @@ static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem) .die_mem = die_mem, .found = false, }; + int ret; - cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp); + ret = cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, + &fsp); + if (!ret && !fsp.found) + cu_walk_functions_at(&pf->cu_die, pf->addr, + find_inner_scope_cb, &fsp); return fsp.found ? die_mem : NULL; } @@ -950,7 +953,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) ret = find_probe_point_lazy(in_die, pf); else { /* Get probe address */ - if (dwarf_entrypc(in_die, &addr) != 0) { + if (die_entrypc(in_die, &addr) != 0) { pr_warning("Failed to get entry address of %s.\n", dwarf_diename(in_die)); return -ENOENT; @@ -1002,7 +1005,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) param->retval = find_probe_point_by_line(pf); } else if (die_is_func_instance(sp_die)) { /* Instances always have the entry address */ - dwarf_entrypc(sp_die, &pf->addr); + die_entrypc(sp_die, &pf->addr); /* But in some case the entry address is 0 */ if (pf->addr == 0) { pr_debug("%s has no entry PC. Skipped\n", @@ -1414,6 +1417,18 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) return DIE_FIND_CB_END; } +static bool available_var_finder_overlap(struct available_var_finder *af) +{ + int i; + + for (i = 0; i < af->nvls; i++) { + if (af->pf.addr == af->vls[i].point.address) + return true; + } + return false; + +} + /* Add a found vars into available variables list */ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) { @@ -1424,6 +1439,14 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) Dwarf_Die die_mem; int ret; + /* + * For some reason (e.g. different column assigned to same address), + * this callback can be called with the address which already passed. + * Ignore it first. + */ + if (available_var_finder_overlap(af)) + return 0; + /* Check number of tevs */ if (af->nvls == af->max_vls) { pr_warning("Too many( > %d) probe point found.\n", af->max_vls); @@ -1567,7 +1590,7 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, /* Get function entry information */ func = basefunc = dwarf_diename(&spdie); if (!func || - dwarf_entrypc(&spdie, &baseaddr) != 0 || + die_entrypc(&spdie, &baseaddr) != 0 || dwarf_decl_line(&spdie, &baseline) != 0) { lineno = 0; goto post; @@ -1584,7 +1607,7 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr, &indie)) { /* There is an inline function */ - if (dwarf_entrypc(&indie, &_addr) == 0 && + if (die_entrypc(&indie, &_addr) == 0 && _addr == addr) { /* * addr is at an inline function entry. diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 842cf3fd923563d4b7178fd237f16e9be6b93213..d7e5c247c1034e6b0acc66e54d6d5394a8d90ec3 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c @@ -116,7 +116,6 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) return ret; } len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); - va_end(ap_saved); if (len > strbuf_avail(sb)) { pr_debug("this should not happen, your vsnprintf is broken"); va_end(ap_saved); diff --git a/tools/power/acpi/Makefile.config b/tools/power/acpi/Makefile.config index a1883bbb014478d9239d24fda259c61bde853b23..fb5559f9819aff8c9249a661854e202b718fe2a2 100644 --- a/tools/power/acpi/Makefile.config +++ b/tools/power/acpi/Makefile.config @@ -18,7 +18,7 @@ include $(srctree)/../../scripts/Makefile.include OUTPUT=$(srctree)/ ifeq ("$(origin O)", "command line") - OUTPUT := $(O)/power/acpi/ + OUTPUT := $(O)/tools/power/acpi/ endif #$(info Determined 'OUTPUT' to be $(OUTPUT)) diff --git a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c index ebeaba6571a380230f921f8209a8d3155baed40b..475e18e043187fd3132f7c82ddbc764cd6bfcb54 100644 --- a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c +++ b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c @@ -40,7 +40,6 @@ static cstate_t hsw_ext_cstates[HSW_EXT_CSTATE_COUNT] = { { .name = "PC9", .desc = N_("Processor Package C9"), - .desc = N_("Processor Package C2"), .id = PC9, .range = RANGE_PACKAGE, .get_count_percent = hsw_ext_get_count_percent, diff --git a/tools/testing/selftests/rseq/settings b/tools/testing/selftests/rseq/settings new file mode 100644 index 0000000000000000000000000000000000000000..e7b9417537fbc4626153b72e8f295ab4594c844b --- /dev/null +++ b/tools/testing/selftests/rseq/settings @@ -0,0 +1 @@ +timeout=0 diff --git a/tools/usb/usbip/src/usbip_network.c b/tools/usb/usbip/src/usbip_network.c index b4c37e76a6e08f7973bcf324dd87a612d621546d..187dfaa67d0a2d8e9b6f1b804eff87dc0de7b321 100644 --- a/tools/usb/usbip/src/usbip_network.c +++ b/tools/usb/usbip/src/usbip_network.c @@ -62,39 +62,39 @@ void usbip_setup_port_number(char *arg) info("using port %d (\"%s\")", usbip_port, usbip_port_string); } -void usbip_net_pack_uint32_t(int pack, uint32_t *num) +uint32_t usbip_net_pack_uint32_t(int pack, uint32_t num) { uint32_t i; if (pack) - i = htonl(*num); + i = htonl(num); else - i = ntohl(*num); + i = ntohl(num); - *num = i; + return i; } -void usbip_net_pack_uint16_t(int pack, uint16_t *num) +uint16_t usbip_net_pack_uint16_t(int pack, uint16_t num) { uint16_t i; if (pack) - i = htons(*num); + i = htons(num); else - i = ntohs(*num); + i = ntohs(num); - *num = i; + return i; } void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev) { - usbip_net_pack_uint32_t(pack, &udev->busnum); - usbip_net_pack_uint32_t(pack, &udev->devnum); - usbip_net_pack_uint32_t(pack, &udev->speed); + udev->busnum = usbip_net_pack_uint32_t(pack, udev->busnum); + udev->devnum = usbip_net_pack_uint32_t(pack, udev->devnum); + udev->speed = usbip_net_pack_uint32_t(pack, udev->speed); - usbip_net_pack_uint16_t(pack, &udev->idVendor); - usbip_net_pack_uint16_t(pack, &udev->idProduct); - usbip_net_pack_uint16_t(pack, &udev->bcdDevice); + udev->idVendor = usbip_net_pack_uint16_t(pack, udev->idVendor); + udev->idProduct = usbip_net_pack_uint16_t(pack, udev->idProduct); + udev->bcdDevice = usbip_net_pack_uint16_t(pack, udev->bcdDevice); } void usbip_net_pack_usb_interface(int pack __attribute__((unused)), @@ -141,6 +141,14 @@ ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen) return usbip_net_xmit(sockfd, buff, bufflen, 1); } +static inline void usbip_net_pack_op_common(int pack, + struct op_common *op_common) +{ + op_common->version = usbip_net_pack_uint16_t(pack, op_common->version); + op_common->code = usbip_net_pack_uint16_t(pack, op_common->code); + op_common->status = usbip_net_pack_uint32_t(pack, op_common->status); +} + int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status) { struct op_common op_common; @@ -152,7 +160,7 @@ int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status) op_common.code = code; op_common.status = status; - PACK_OP_COMMON(1, &op_common); + usbip_net_pack_op_common(1, &op_common); rc = usbip_net_send(sockfd, &op_common, sizeof(op_common)); if (rc < 0) { @@ -176,7 +184,7 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code) goto err; } - PACK_OP_COMMON(0, &op_common); + usbip_net_pack_op_common(0, &op_common); if (op_common.version != USBIP_VERSION) { dbg("version mismatch: %d %d", op_common.version, diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h index c1e875cf1078cbc364ca9981f0d310d60331cba7..573fa839b66b7cf6dee653203570655137b7862c 100644 --- a/tools/usb/usbip/src/usbip_network.h +++ b/tools/usb/usbip/src/usbip_network.h @@ -33,12 +33,6 @@ struct op_common { } __attribute__((packed)); -#define PACK_OP_COMMON(pack, op_common) do {\ - usbip_net_pack_uint16_t(pack, &(op_common)->version);\ - usbip_net_pack_uint16_t(pack, &(op_common)->code);\ - usbip_net_pack_uint32_t(pack, &(op_common)->status);\ -} while (0) - /* ---------------------------------------------------------------------- */ /* Dummy Code */ #define OP_UNSPEC 0x00 @@ -164,11 +158,11 @@ struct op_devlist_reply_extra { } while (0) #define PACK_OP_DEVLIST_REPLY(pack, reply) do {\ - usbip_net_pack_uint32_t(pack, &(reply)->ndev);\ + (reply)->ndev = usbip_net_pack_uint32_t(pack, (reply)->ndev);\ } while (0) -void usbip_net_pack_uint32_t(int pack, uint32_t *num); -void usbip_net_pack_uint16_t(int pack, uint16_t *num); +uint32_t usbip_net_pack_uint32_t(int pack, uint32_t num); +uint16_t usbip_net_pack_uint16_t(int pack, uint16_t num); void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev); void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c0dff5337a506b2b01dff8486cf0265aad294a23..4e4bb5dd2dcd57ef38b0c9701eedcd0db89aa948 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2045,12 +2045,12 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, if (slots->generation != ghc->generation) kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len); - if (unlikely(!ghc->memslot)) - return kvm_write_guest(kvm, ghc->gpa, data, len); - if (kvm_is_error_hva(ghc->hva)) return -EFAULT; + if (unlikely(!ghc->memslot)) + return kvm_write_guest(kvm, ghc->gpa, data, len); + r = __copy_to_user((void __user *)ghc->hva, data, len); if (r) return -EFAULT; @@ -2071,12 +2071,12 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, if (slots->generation != ghc->generation) kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len); - if (unlikely(!ghc->memslot)) - return kvm_read_guest(kvm, ghc->gpa, data, len); - if (kvm_is_error_hva(ghc->hva)) return -EFAULT; + if (unlikely(!ghc->memslot)) + return kvm_read_guest(kvm, ghc->gpa, data, len); + r = __copy_from_user(data, (void __user *)ghc->hva, len); if (r) return -EFAULT;