diff --git a/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt b/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt index 72e279abc8f69ccbce6cdb06e94a975585c2054f..531ff1f6e4face83fe9c63e38586c15ace103b14 100644 --- a/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt +++ b/Documentation/devicetree/bindings/arm/msm/mdm-modem.txt @@ -6,7 +6,7 @@ to be reset. Required Properties: - compatible: The bus devices need to be compatible with - "qcom,ext-mdm9x55", qcom,ext-sdx50m. + "qcom,ext-mdm9x55", qcom,ext-sdx50m, qcom,ext-sdxprairie. Required named gpio properties: - qcom,mdm2ap-errfatal-gpio: gpio for the external modem to indicate to the apps processor diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 562827c3402905c6e6c363b81eba0a9d1478bd6c..2dd881518a6d0cd066aec04f9095e59082b19992 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -175,6 +175,9 @@ compatible = "qcom,qcs403-iot" compatible = "qcom,sa8155-adp-star" compatible = "qcom,sa8155p-adp-star" compatible = "qcom,adp-star" +compatible = "qcom,sa8155-v2-adp-air" +compatible = "qcom,sa8155p-v2-adp-air" +compatible = "qcom,adp-air" compatible = "qcom,sdxprairie-rumi" compatible = "qcom,sdxprairie-mtp" compatible = "qcom,sdxprairie-cdp" diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index 837c33cd07481189a9a9dcfaf590703ff29f4890..34dff2203c0ab8384d4015180b47f97c349f5099 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -291,11 +291,6 @@ MHI netdev properties Value type: Definition: Interface name to be given so clients can identify it -- mhi,recycle-buf - Usage: optional - Value type: - Definition: Set true if interface support recycling buffers. - - aliases Usage: required Value type: diff --git a/Documentation/devicetree/bindings/clock/qcom,debugcc.txt b/Documentation/devicetree/bindings/clock/qcom,debugcc.txt index e8db516b35633cbafdaddd6fbc5f85cad55971cd..8e88ee435a10e9d1fddabcde79fa24bd8ffd2a27 100644 --- a/Documentation/devicetree/bindings/clock/qcom,debugcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,debugcc.txt @@ -5,7 +5,8 @@ Required properties : - compatible: Shall contain "qcom,debugcc-sm8150", "qcom,debugcc-qcs405", "qcom,debugcc-sm6150", - "qcom,debugcc-sdmmagpie". + "qcom,debugcc-sdmmagpie" + "qcom,debugcc-sdxprairie". - qcom,gcc: phandle to the GCC device node. - qcom,videocc: phandle to the Video CC device node. - qcom,camcc: phandle to the Camera CC device node. diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sdmmagpie.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sdmmagpie.txt deleted file mode 100644 index 968019c5ad99ac6bbc8cb62d5f4a3edde690ff9e..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sdmmagpie.txt +++ /dev/null @@ -1,63 +0,0 @@ -QTI PDC interrupt controller - -PDC is QTI's platform parent interrupt controller that serves as wakeup source. - -Newer QTI SOCs are replacing MPM (MSM sleep Power Manager) with PDC (Power -Domain Controller) to manage subsystem wakeups and resources during sleep. -This driver marks the wakeup interrupts in APSS PDC such that it monitors the -interrupts when the system is asleep, wakes up the APSS when one of these -interrupts occur and replays it to the subsystem interrupt controller after it -becomes operational. - -Earlier MPM architecture used arch-extension of GIC interrupt -controller to mark enabled wake-up interrupts and monitor these when the -system goes to sleep. Since the arch-extensions are no-longer available -on newer kernel versions, this driver is implemented as hierarchical irq -domain. GIC is parent interrupt controller at the highest level. -Platform interrupt controller PDC is next in hierarchy, followed by others. -This driver only configures the interrupts, does not handle them. - -PDC interrupt configuration involves programming of 2 set of registers: -IRQ_ENABLE_BANK - Enable the irq -IRQ_i_CFG - Configure the interrupt i - -Properties: - -- compatible: - Usage: required - Value type: - Definition: Should contain "qcom,pdc-" - -- reg: - Usage: required - Value type: - Definition: Specifies the base physical address for PDC hardware - block for DRV2. - -- interrupt-cells: - Usage: required - Value type: - Definition: Specifies the number of cells needed to encode an interrupt source. - Value must be 3. - The encoding of these cells are same as described in - Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt - -- interrupt-parent: - Usage: required - Value type: - Definition: Specifies the interrupt parent necessary for hierarchical domain to operate. - -- interrupt-controller: - Usage: required - Value type: - Definition: Identifies the node as an interrupt controller. - -Example: - -pdcgic: interrupt-controller@0xb220000{ - compatible = "qcom,pdc-sdmmagpie"; - reg = <0xb220000 0x30000>; - #interrupt-cells = <3>; - interrupt-parent = <&intc>; - interrupt-controller; -}; diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sm6150.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sm6150.txt deleted file mode 100644 index 4ee8ae29f7ea388ce6aa114bc63a3e6c2ca11a77..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sm6150.txt +++ /dev/null @@ -1,63 +0,0 @@ -QTI PDC interrupt controller - -PDC is QTI's platform parent interrupt controller that serves as wakeup source. - -Newer QTI SOCs are replacing MPM (MSM sleep Power Manager) with PDC (Power -Domain Controller) to manage subsystem wakeups and resources during sleep. -This driver marks the wakeup interrupts in APSS PDC such that it monitors the -interrupts when the system is asleep, wakes up the APSS when one of these -interrupts occur and replays it to the subsystem interrupt controller after it -becomes operational. - -Earlier MPM architecture used arch-extension of GIC interrupt -controller to mark enabled wake-up interrupts and monitor these when the -system goes to sleep. Since the arch-extensions are no-longer available -on newer kernel versions, this driver is implemented as hierarchical irq -domain. GIC is parent interrupt controller at the highest level. -Platform interrupt controller PDC is next in hierarchy, followed by others. -This driver only configures the interrupts, does not handle them. - -PDC interrupt configuration involves programming of 2 set of registers: -IRQ_ENABLE_BANK - Enable the irq -IRQ_i_CFG - Configure the interrupt i - -Properties: - -- compatible: - Usage: required - Value type: - Definition: Should contain "qcom,pdc-" - -- reg: - Usage: required - Value type: - Definition: Specifies the base physical address for PDC hardware - block for DRV2. - -- interrupt-cells: - Usage: required - Value type: - Definition: Specifies the number of cells needed to encode an interrupt source. - Value must be 3. - The encoding of these cells are same as described in - Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt - -- interrupt-parent: - Usage: required - Value type: - Definition: Specifies the interrupt parent necessary for hierarchical domain to operate. - -- interrupt-controller: - Usage: required - Value type: - Definition: Identifies the node as an interrupt controller. - -Example: - -pdcgic: interrupt-controller@0xb220000{ - compatible = "qcom,pdc-sm6150"; - reg = <0xb220000 0x30000>; - #interrupt-cells = <3>; - interrupt-parent = <&intc>; - interrupt-controller; -}; diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sm8150.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sm8150.txt deleted file mode 100644 index a254571874c2e2972bbbdf5e88cd95a6d807eebe..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sm8150.txt +++ /dev/null @@ -1,63 +0,0 @@ -QTI PDC interrupt controller - -PDC is QTI's platform parent interrupt controller that serves as wakeup source. - -Newer QTI SOCs are replacing MPM (MSM sleep Power Manager) with PDC (Power -Domain Controller) to manage subsystem wakeups and resources during sleep. -This driver marks the wakeup interrupts in APSS PDC such that it monitors the -interrupts when the system is asleep, wakes up the APSS when one of these -interrupts occur and replays it to the subsystem interrupt controller after it -becomes operational. - -Earlier MPM architecture used arch-extension of GIC interrupt -controller to mark enabled wake-up interrupts and monitor these when the -system goes to sleep. Since the arch-extensions are no-longer available -on newer kernel versions, this driver is implemented as hierarchical irq -domain. GIC is parent interrupt controller at the highest level. -Platform interrupt controller PDC is next in hierarchy, followed by others. -This driver only configures the interrupts, does not handle them. - -PDC interrupt configuration involves programming of 2 set of registers: -IRQ_ENABLE_BANK - Enable the irq -IRQ_i_CFG - Configure the interrupt i - -Properties: - -- compatible: - Usage: required - Value type: - Definition: Should contain "qcom,pdc-" - -- reg: - Usage: required - Value type: - Definition: Specifies the base physical address for PDC hardware - block for DRV2. - -- interrupt-cells: - Usage: required - Value type: - Definition: Specifies the number of cells needed to encode an interrupt source. - Value must be 3. - The encoding of these cells are same as described in - Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt - -- interrupt-parent: - Usage: required - Value type: - Definition: Specifies the interrupt parent necessary for hierarchical domain to operate. - -- interrupt-controller: - Usage: required - Value type: - Definition: Identifies the node as an interrupt controller. - -Example: - -pdcgic: interrupt-controller@0xb220000{ - compatible = "qcom,pdc-sm8150"; - reg = <0xb220000 0x30000>; - #interrupt-cells = <3>; - interrupt-parent = <&intc>; - interrupt-controller; -}; diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt index 8598d0c963836cb836b6e32d9e0c9746087688a7..e6c0b3e87b8f18c7a53a91d4bc25b2cde5aa8167 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt @@ -26,7 +26,12 @@ Properties: - compatible: Usage: required Value type: - Definition: Should contain "qcom,pdc-" + Definition: Should contain one of - + "qcom,pdc-sdm845", + "qcom,pdc-sdmmagpie", + "qcom,pdc-sm6150", + "qcom,pdc-sm8150", + "qcom,pdc-sdxprairie", - reg: Usage: required diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt index 26072d6fbca6466a1315044624aceb36f27809c0..bdc607626bff51934473cdda993d529f4b06147f 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt @@ -11,7 +11,8 @@ platforms. "qcom,msm8916-apcs-kpss-global", "qcom,msm8996-apcs-hmss-global", "qcom,sm8150-apcs-hmss-global", - "qcom,sm8150-spcs-global" + "qcom,sm8150-spcs-global", + "qcom,sdxprairie-apcs-gcc" - reg: Usage: required Value type: diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-csiphy.txt b/Documentation/devicetree/bindings/media/video/msm-cam-csiphy.txt index 249dd04cc6e26088b9ac2947b6a8600322af3f2a..0b00cc025f00c848b471a33b1a90861d9d2ce756 100644 --- a/Documentation/devicetree/bindings/media/video/msm-cam-csiphy.txt +++ b/Documentation/devicetree/bindings/media/video/msm-cam-csiphy.txt @@ -14,7 +14,8 @@ First Level Node - CSIPHY device Usage: required Value type: Definition: Should be "qcom,csiphy-v1.0", - "qcom,csiphy-v1.1", "qcom,csiphy-v2.0", "qcom,csiphy". + "qcom,csiphy-v1.1", "qcom,csiphy-v1.2", + "qcom,csiphy-v2.0", "qcom,csiphy". - cell-index: csiphy hardware core index Usage: required diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6150-pinctrl b/Documentation/devicetree/bindings/pinctrl/qcom,sm6150-pinctrl index 9787c416f8d903bb61e832dd474d95bc06d54865..a000b68d0d19c8fdf1bb5e3b2d7d627ad0c89e97 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6150-pinctrl +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6150-pinctrl @@ -111,7 +111,7 @@ to specify in a pin configuration subnode: qdss_tracectl_a, dac_calib13, qdss_traceclk_a, dac_calib14, dac_calib15, hdmi_rcv, dac_calib16, hdmi_cec, pwr_modem, dac_calib17, hdmi_ddc, pwr_nav, dac_calib18, pwr_crypto, - dac_calib19, hdmi_hot, dac_calib20, dac_calib21, pci_e0, + dac_calib19, hdmi_hot, dac_calib20, dac_calib21, pcie_ep, dac_calib22, dac_calib23, dac_calib24, tsif1_sync, dac_calib25, sd_write, tsif1_error, blsp_spi2, blsp_uart2, blsp_uim2, qdss_cti, blsp_i2c2, blsp_spi3, blsp_uart3, blsp_uim3, blsp_i2c3, @@ -133,10 +133,9 @@ to specify in a pin configuration subnode: sd_card, tsif2_data, sdc41, tsif2_sync, sdc40, mdp_vsync_p_b, ldo_en, mdp_vsync_s_b, ldo_update, blsp11_uart_tx_b, blsp11_uart_rx_b, blsp11_i2c_sda_b, prng_rosc, blsp11_i2c_scl_b, uim2, uim1, uim_batt, - pci_e2, pa_indicator, adsp_ext, ddr_bist, qdss_tracedata_11, - qdss_tracedata_12, modem_tsync, nav_dr, nav_pps, pci_e1, gsm_tx, - qspi_cs, ssbi2, ssbi1, mss_lte, qspi_clk, qspi0, qspi1, qspi2, qspi3, - gpio + pcie_clk, pa_indicator, adsp_ext, ddr_bist, qdss_tracedata_11, + qdss_tracedata_12, modem_tsync, nav_dr, nav_pps, gsm_tx, qspi_cs, + ssbi2, ssbi1, mss_lte, qspi_clk, qspi0, qspi1, qspi2, qspi3, gpio - bias-disable: Usage: optional diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt index b656f268c1a41fdaf8c246f25bcb5e1f8f50b4d2..b522f81fdc230b3e8c07b71531831ba714f2b737 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt @@ -368,6 +368,13 @@ First Level Node - FG Gen4 device decrease when the battery SOC is low but not converging to zero with battery voltage dropping rapidly below Vcutoff. +- qcom,five-pin-battery + Usage: optional + Value type: + Definition: A boolean property that when specified indicates that a + five pin battery is used. Based on this, time to full + calculations would use the Rbatt calculated properly. + ========================================================== Second Level Nodes - Peripherals managed by FG Gen4 driver ========================================================== diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt index af9ca37221ceac6f33872d9ae4fa438cab435259..a35af2dafdad6a78b989f7a519f4887203a50735 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt @@ -17,9 +17,15 @@ processor ID) and a string identifier. Value type: Definition: one entry specifying the smp2p notification interrupt -- qcom,ipc: +- mboxes: Usage: required Value type: + Definition: reference to the associated doorbell in APCS, as described + in mailbox/mailbox.txt + +- qcom,ipc: + Usage: required, unless mboxes is specified + Value type: Definition: three entries specifying the outgoing ipc bit used for signaling the remote end of the smp2p edge: - phandle to a syscon node representing the apcs registers diff --git a/Documentation/devicetree/bindings/usb/nxp5150a.txt b/Documentation/devicetree/bindings/usb/nxp5150a.txt new file mode 100644 index 0000000000000000000000000000000000000000..30e0cf29435c0a6d776c7b3f30ea848bf98854d4 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/nxp5150a.txt @@ -0,0 +1,21 @@ +NXP PTN5150A - CC Logic chip for USB Type-C applications + +Required properties: +- compatible: should contain "nxp,5150a" +- reg: The device 7-bit I2C address +- interrupts: interrupt number that is used for interrupts from the device. + +Optional properties: +- vbus-out-gpio: gpio for enabling VBUS output (e.g. when entering host mode) + +Example device node: + +&i2c4 { + nxp_5150a: nxp5150a@1d { + compatbile = "nxp,5150a"; + reg = <0x1d>; + interrupt-parent = <&msm_gpio>; + interrupts = <35 2>; + vbus-out-gpio = <&msm_gpio 3 1>; + }; +}; diff --git a/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt b/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt index d87ab9f6d9d545bf50fb863eeabd68ce999965f6..137a6a0a09b117b0a20b1171dede9d6c607f129b 100644 --- a/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt +++ b/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt @@ -115,6 +115,9 @@ Optional properties: microvolts or a value corresponding to voltage corner. - qcom,link-training-reset: This property indicates to start link training timer to reset the elastic buffer based on rx equalization value. + - extcon : phandle to external connector devices which provide type-C based + "USB-HOST" cable events. This phandle is used for notifying number + of lanes used in case of USB+DP concurrent mode to driver. Example: ssphy0: ssphy@f9b38000 { diff --git a/Documentation/hwmon/ina2xx b/Documentation/hwmon/ina2xx index cfd31d94c8727251179a0c2afcc4f9b2a4580156..f8bf14055c2f38593b78d3c74545835080ba0c91 100644 --- a/Documentation/hwmon/ina2xx +++ b/Documentation/hwmon/ina2xx @@ -32,7 +32,7 @@ Supported chips: Datasheet: Publicly available at the Texas Instruments website http://www.ti.com/ -Author: Lothar Felten +Author: Lothar Felten Description ----------- diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 579337f3fbf3455f24d74d4ff2a1397d0faeac88..23064e9f7f126f7996debf9e523a4ee37039af2b 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -133,14 +133,11 @@ min_adv_mss - INTEGER IP Fragmentation: -ipfrag_high_thresh - INTEGER - Maximum memory used to reassemble IP fragments. When - ipfrag_high_thresh bytes of memory is allocated for this purpose, - the fragment handler will toss packets until ipfrag_low_thresh - is reached. This also serves as a maximum limit to namespaces - different from the initial one. - -ipfrag_low_thresh - INTEGER +ipfrag_high_thresh - LONG INTEGER + Maximum memory used to reassemble IP fragments. + +ipfrag_low_thresh - LONG INTEGER + (Obsolete since linux-4.17) Maximum memory used to reassemble IP fragments before the kernel begins to remove incomplete fragment queues to free up resources. The kernel still accepts new fragments for defragmentation. diff --git a/Makefile b/Makefile index 0226b62da213f100da0bb832392147661b1f4ea5..c5e06ffdaa86755774c75b56ca800fc02720961f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 66 +SUBLEVEL = 74 EXTRAVERSION = NAME = Petit Gorille @@ -357,9 +357,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ else if [ -x /bin/bash ]; then echo /bin/bash; \ else echo sh; fi ; fi) -HOST_LFS_CFLAGS := $(shell getconf LFS_CFLAGS) -HOST_LFS_LDFLAGS := $(shell getconf LFS_LDFLAGS) -HOST_LFS_LIBS := $(shell getconf LFS_LIBS) +HOST_LFS_CFLAGS := $(shell getconf LFS_CFLAGS 2>/dev/null) +HOST_LFS_LDFLAGS := $(shell getconf LFS_LDFLAGS 2>/dev/null) +HOST_LFS_LIBS := $(shell getconf LFS_LIBS 2>/dev/null) HOSTCC = gcc HOSTCXX = g++ @@ -501,9 +501,13 @@ KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) endif RETPOLINE_CFLAGS_GCC := -mindirect-branch=thunk-extern -mindirect-branch-register +RETPOLINE_VDSO_CFLAGS_GCC := -mindirect-branch=thunk-inline -mindirect-branch-register RETPOLINE_CFLAGS_CLANG := -mretpoline-external-thunk +RETPOLINE_VDSO_CFLAGS_CLANG := -mretpoline RETPOLINE_CFLAGS := $(call cc-option,$(RETPOLINE_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_CFLAGS_CLANG))) +RETPOLINE_VDSO_CFLAGS := $(call cc-option,$(RETPOLINE_VDSO_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_VDSO_CFLAGS_CLANG))) export RETPOLINE_CFLAGS +export RETPOLINE_VDSO_CFLAGS ifeq ($(config-targets),1) # =========================================================================== diff --git a/arch/Kconfig b/arch/Kconfig index 226b692dca5a9f97c0aa98a0d62c42aee81fcc1c..0c9cdc875e95dcf1c67d095c7a6415cf60170a9a 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -336,6 +336,9 @@ config HAVE_ARCH_JUMP_LABEL config HAVE_RCU_TABLE_FREE bool +config HAVE_RCU_TABLE_INVALIDATE + bool + config ARCH_HAVE_NMI_SAFE_CMPXCHG bool diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index a48976dc9bcd0ad8638aadfd927e0480f3816c3e..918c3938ef6652a24c84edffeb5f3727afba23af 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -530,24 +530,19 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path, SYSCALL_DEFINE1(osf_utsname, char __user *, name) { int error; + char tmp[5 * 32]; down_read(&uts_sem); - error = -EFAULT; - if (copy_to_user(name + 0, utsname()->sysname, 32)) - goto out; - if (copy_to_user(name + 32, utsname()->nodename, 32)) - goto out; - if (copy_to_user(name + 64, utsname()->release, 32)) - goto out; - if (copy_to_user(name + 96, utsname()->version, 32)) - goto out; - if (copy_to_user(name + 128, utsname()->machine, 32)) - goto out; + memcpy(tmp + 0 * 32, utsname()->sysname, 32); + memcpy(tmp + 1 * 32, utsname()->nodename, 32); + memcpy(tmp + 2 * 32, utsname()->release, 32); + memcpy(tmp + 3 * 32, utsname()->version, 32); + memcpy(tmp + 4 * 32, utsname()->machine, 32); + up_read(&uts_sem); - error = 0; - out: - up_read(&uts_sem); - return error; + if (copy_to_user(name, tmp, sizeof(tmp))) + return -EFAULT; + return 0; } SYSCALL_DEFINE0(getpagesize) @@ -567,18 +562,21 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen) { int len, err = 0; char *kname; + char tmp[32]; - if (namelen > 32) + if (namelen < 0 || namelen > 32) namelen = 32; down_read(&uts_sem); kname = utsname()->domainname; len = strnlen(kname, namelen); - if (copy_to_user(name, kname, min(len + 1, namelen))) - err = -EFAULT; + len = min(len + 1, namelen); + memcpy(tmp, kname, len); up_read(&uts_sem); - return err; + if (copy_to_user(name, tmp, len)) + return -EFAULT; + return 0; } /* @@ -739,13 +737,14 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) }; unsigned long offset; const char *res; - long len, err = -EINVAL; + long len; + char tmp[__NEW_UTS_LEN + 1]; offset = command-1; if (offset >= ARRAY_SIZE(sysinfo_table)) { /* Digital UNIX has a few unpublished interfaces here */ printk("sysinfo(%d)", command); - goto out; + return -EINVAL; } down_read(&uts_sem); @@ -753,13 +752,11 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) len = strlen(res)+1; if ((unsigned long)len > (unsigned long)count) len = count; - if (copy_to_user(buf, res, len)) - err = -EFAULT; - else - err = 0; + memcpy(tmp, res, len); up_read(&uts_sem); - out: - return err; + if (copy_to_user(buf, tmp, len)) + return -EFAULT; + return 0; } SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 5c8caf85c35054722402d86f58033820d3de7640..8ff06609068038541f608df562170b3429193f6b 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -45,6 +45,9 @@ config ARC select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZMA +config ARCH_HAS_CACHE_LINE_SIZE + def_bool y + config MIGHT_HAVE_PCI bool diff --git a/arch/arc/Makefile b/arch/arc/Makefile index d37f49d6a27f40f65d3e34bd3e2df5343a97d1e4..6c1b20dd76ad902655d7317eb44580923d98c690 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -16,7 +16,7 @@ endif KBUILD_DEFCONFIG := nsim_700_defconfig -cflags-y += -fno-common -pipe -fno-builtin -D__linux__ +cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__ cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7 cflags-$(CONFIG_ISA_ARCV2) += -mcpu=archs @@ -140,16 +140,3 @@ dtbs: scripts archclean: $(Q)$(MAKE) $(clean)=$(boot) - -# Hacks to enable final link due to absence of link-time branch relexation -# and gcc choosing optimal(shorter) branches at -O3 -# -# vineetg Feb 2010: -mlong-calls switched off for overall kernel build -# However lib/decompress_inflate.o (.init.text) calls -# zlib_inflate_workspacesize (.text) causing relocation errors. -# Thus forcing all exten calls in this file to be long calls -export CFLAGS_decompress_inflate.o = -mmedium-calls -export CFLAGS_initramfs.o = -mmedium-calls -ifdef CONFIG_SMP -export CFLAGS_core.o = -mmedium-calls -endif diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig index a8242362e55199e550f4da319f1f5f2bd33f23c2..ece78630d71124cd1557cd987a3f6021c2383486 100644 --- a/arch/arc/configs/axs101_defconfig +++ b/arch/arc/configs/axs101_defconfig @@ -1,5 +1,4 @@ CONFIG_DEFAULT_HOSTNAME="ARCLinux" -# CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_CROSS_MEMORY_ATTACH is not set diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig index ef3c31cd77378c0fcfed9f4e97a05ba1460c5410..240c9251a7d4a19d7745fcb4aeafd1d26c657442 100644 --- a/arch/arc/configs/axs103_defconfig +++ b/arch/arc/configs/axs103_defconfig @@ -1,5 +1,4 @@ CONFIG_DEFAULT_HOSTNAME="ARCLinux" -# CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_CROSS_MEMORY_ATTACH is not set diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig index 1757ac9cecbc10fb189673d23a76ad5137e9ed9f..af54b96abee04a16c0eb65a2690c45c9edaee560 100644 --- a/arch/arc/configs/axs103_smp_defconfig +++ b/arch/arc/configs/axs103_smp_defconfig @@ -1,5 +1,4 @@ CONFIG_DEFAULT_HOSTNAME="ARCLinux" -# CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_CROSS_MEMORY_ATTACH is not set diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 8486f328cc5d2aea087812ab19be949001e64b73..ff7d3232764a29a41503a213d3bd385e232acf42 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -48,7 +48,9 @@ }) /* Largest line length for either L1 or L2 is 128 bytes */ -#define ARCH_DMA_MINALIGN 128 +#define SMP_CACHE_BYTES 128 +#define cache_line_size() SMP_CACHE_BYTES +#define ARCH_DMA_MINALIGN SMP_CACHE_BYTES extern void arc_cache_init(void); extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); diff --git a/arch/arc/include/asm/delay.h b/arch/arc/include/asm/delay.h index d5da2115d78a678e343da2abec51f6c8efbbe0a4..03d6bb0f4e13a2dd49708f12dfb6f2f4788bf8ae 100644 --- a/arch/arc/include/asm/delay.h +++ b/arch/arc/include/asm/delay.h @@ -17,8 +17,11 @@ #ifndef __ASM_ARC_UDELAY_H #define __ASM_ARC_UDELAY_H +#include #include /* HZ */ +extern unsigned long loops_per_jiffy; + static inline void __delay(unsigned long loops) { __asm__ __volatile__( diff --git a/arch/arc/include/asm/mach_desc.h b/arch/arc/include/asm/mach_desc.h index c28e6c347b4900217ad48053c69679bb3da8b607..871f3cb16af9f2ec58c76192ffc098d914588b9d 100644 --- a/arch/arc/include/asm/mach_desc.h +++ b/arch/arc/include/asm/mach_desc.h @@ -34,9 +34,7 @@ struct machine_desc { const char *name; const char **dt_compat; void (*init_early)(void); -#ifdef CONFIG_SMP void (*init_per_cpu)(unsigned int); -#endif void (*init_machine)(void); void (*init_late)(void); diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index 538b36afe89e7c9871e2c37d2322d839a9b27a26..62b185057c040157132386aaee6ff56eaaebcf25 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -31,10 +31,10 @@ void __init init_IRQ(void) /* a SMP H/w block could do IPI IRQ request here */ if (plat_smp_ops.init_per_cpu) plat_smp_ops.init_per_cpu(smp_processor_id()); +#endif if (machine_desc->init_per_cpu) machine_desc->init_per_cpu(smp_processor_id()); -#endif } /* diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 5ac3b547453fd5b4b5393fdc10dfff34a047941f..4674541eba3fd019a51aeb02db27b2bc04569412 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -47,7 +47,8 @@ SYSCALL_DEFINE0(arc_gettls) SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) { struct pt_regs *regs = current_pt_regs(); - int uval = -EFAULT; + u32 uval; + int ret; /* * This is only for old cores lacking LLOCK/SCOND, which by defintion @@ -60,23 +61,47 @@ SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) /* Z indicates to userspace if operation succeded */ regs->status32 &= ~STATUS_Z_MASK; - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; + ret = access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)); + if (!ret) + goto fail; +again: preempt_disable(); - if (__get_user(uval, uaddr)) - goto done; + ret = __get_user(uval, uaddr); + if (ret) + goto fault; - if (uval == expected) { - if (!__put_user(new, uaddr)) - regs->status32 |= STATUS_Z_MASK; - } + if (uval != expected) + goto out; -done: - preempt_enable(); + ret = __put_user(new, uaddr); + if (ret) + goto fault; + + regs->status32 |= STATUS_Z_MASK; +out: + preempt_enable(); return uval; + +fault: + preempt_enable(); + + if (unlikely(ret != -EFAULT)) + goto fail; + + down_read(¤t->mm->mmap_sem); + ret = fixup_user_fault(current, current->mm, (unsigned long) uaddr, + FAULT_FLAG_WRITE, NULL); + up_read(¤t->mm->mmap_sem); + + if (likely(!ret)) + goto again; + +fail: + force_sig(SIGSEGV, current); + return ret; } #ifdef CONFIG_ISA_ARCV2 diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index eee924dfffa6e1baf08221ee5e7e2cd23937d782..d14499500106df2fc25ac18d28425b62fa56086e 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -1035,7 +1035,7 @@ void flush_cache_mm(struct mm_struct *mm) void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr, unsigned long pfn) { - unsigned int paddr = pfn << PAGE_SHIFT; + phys_addr_t paddr = pfn << PAGE_SHIFT; u_vaddr &= PAGE_MASK; @@ -1055,8 +1055,9 @@ void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long u_vaddr) { /* TBD: do we really need to clear the kernel mapping */ - __flush_dcache_page(page_address(page), u_vaddr); - __flush_dcache_page(page_address(page), page_address(page)); + __flush_dcache_page((phys_addr_t)page_address(page), u_vaddr); + __flush_dcache_page((phys_addr_t)page_address(page), + (phys_addr_t)page_address(page)); } diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h index 0c7d11022d0f8875256e64162d2ee0f1f0aa85e1..4f6a1673b3a6eaacc80473108dec4cc8c1e4236c 100644 --- a/arch/arc/plat-eznps/include/plat/ctop.h +++ b/arch/arc/plat-eznps/include/plat/ctop.h @@ -21,6 +21,7 @@ #error "Incorrect ctop.h include" #endif +#include #include /* core auxiliary registers */ @@ -143,6 +144,15 @@ struct nps_host_reg_gim_p_int_dst { }; /* AUX registers definition */ +struct nps_host_reg_aux_dpc { + union { + struct { + u32 ien:1, men:1, hen:1, reserved:29; + }; + u32 value; + }; +}; + struct nps_host_reg_aux_udmc { union { struct { diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c index 2388de3d09ef9e71f710ec4625e20a9e85cbdc1e..ed0077ef666eb7bdb8930bb2b52eddbe46f0b946 100644 --- a/arch/arc/plat-eznps/mtm.c +++ b/arch/arc/plat-eznps/mtm.c @@ -15,6 +15,8 @@ */ #include +#include +#include #include #include #include @@ -157,10 +159,10 @@ void mtm_enable_core(unsigned int cpu) /* Verify and set the value of the mtm hs counter */ static int __init set_mtm_hs_ctr(char *ctr_str) { - long hs_ctr; + int hs_ctr; int ret; - ret = kstrtol(ctr_str, 0, &hs_ctr); + ret = kstrtoint(ctr_str, 0, &hs_ctr); if (ret || hs_ctr > MT_HS_CNT_MAX || hs_ctr < MT_HS_CNT_MIN) { pr_err("** Invalid @nps_mtm_hs_ctr [%d] needs to be [%d:%d] (incl)\n", diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi index 00da3f2c4072d4d6a3a370e88b1acfa046b58efd..4b57094a0356e1bb12c2aaef249228859344baea 100644 --- a/arch/arm/boot/dts/am3517.dtsi +++ b/arch/arm/boot/dts/am3517.dtsi @@ -87,6 +87,11 @@ }; }; +/* Table Table 5-79 of the TRM shows 480ab000 is reserved */ +&usb_otg_hs { + status = "disabled"; +}; + &iva { status = "disabled"; }; diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 2c6bf0684f5055bfe014bd4e433f4cd035e0924a..094fd0ea91a03d1889e7d6fa7c55a61859e3f269 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -535,6 +535,8 @@ touchscreen-size-x = <480>; touchscreen-size-y = <272>; + + wakeup-source; }; tlv320aic3106: tlv320aic3106@1b { diff --git a/arch/arm/boot/dts/armada-385-synology-ds116.dts b/arch/arm/boot/dts/armada-385-synology-ds116.dts index 31510eb56f108e8a8708bb6e4a513fb137982c13..874189b4d21866e38a8c8960a66b4ef5916efd7e 100644 --- a/arch/arm/boot/dts/armada-385-synology-ds116.dts +++ b/arch/arm/boot/dts/armada-385-synology-ds116.dts @@ -170,7 +170,7 @@ 3700 5 3900 6 4000 7>; - cooling-cells = <2>; + #cooling-cells = <2>; }; gpio-leds { diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 9a9902974b1b86d16c0a9e8280c0fa6da0de8222..8b2c65cd61a2951dd5e170b81c2230ce449d3cf0 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -216,7 +216,7 @@ reg = <0x18008000 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clock-frequency = <100000>; status = "disabled"; }; @@ -245,7 +245,7 @@ reg = <0x1800b000 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clock-frequency = <100000>; status = "disabled"; }; @@ -256,7 +256,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; linux,pci-domain = <0>; @@ -278,10 +278,10 @@ compatible = "brcm,iproc-msi"; msi-controller; interrupt-parent = <&gic>; - interrupts = , - , - , - ; + interrupts = , + , + , + ; }; }; @@ -291,7 +291,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; linux,pci-domain = <1>; @@ -313,10 +313,10 @@ compatible = "brcm,iproc-msi"; msi-controller; interrupt-parent = <&gic>; - interrupts = , - , - , - ; + interrupts = , + , + , + ; }; }; diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi index d5f5e92e74889d25fbbc0a853ef9d3e0ea6e7bae..1792192001a22da9e563963d7c715e019d5accde 100644 --- a/arch/arm/boot/dts/bcm-nsp.dtsi +++ b/arch/arm/boot/dts/bcm-nsp.dtsi @@ -391,7 +391,7 @@ reg = <0x38000 0x50>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clock-frequency = <100000>; dma-coherent; status = "disabled"; @@ -496,7 +496,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 131 IRQ_TYPE_NONE>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>; linux,pci-domain = <0>; @@ -519,10 +519,10 @@ compatible = "brcm,iproc-msi"; msi-controller; interrupt-parent = <&gic>; - interrupts = , - , - , - ; + interrupts = , + , + , + ; brcm,pcie-msi-inten; }; }; @@ -533,7 +533,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 137 IRQ_TYPE_NONE>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>; linux,pci-domain = <1>; @@ -556,10 +556,10 @@ compatible = "brcm,iproc-msi"; msi-controller; interrupt-parent = <&gic>; - interrupts = , - , - , - ; + interrupts = , + , + , + ; brcm,pcie-msi-inten; }; }; @@ -570,7 +570,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 143 IRQ_TYPE_NONE>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>; linux,pci-domain = <2>; @@ -593,10 +593,10 @@ compatible = "brcm,iproc-msi"; msi-controller; interrupt-parent = <&gic>; - interrupts = , - , - , - ; + interrupts = , + , + , + ; brcm,pcie-msi-inten; }; }; diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index 045b9bb857f9a030491bc3bdbf82ae67bb841b73..501877e87a5b8fb2f1eb7341211c6215c1aa8be8 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -365,7 +365,7 @@ i2c0: i2c@18009000 { compatible = "brcm,iproc-i2c"; reg = <0x18009000 0x50>; - interrupts = ; + interrupts = ; #address-cells = <1>; #size-cells = <0>; clock-frequency = <100000>; diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index 8a15f7193c829bcea8cda3553d0622a4c9222406..77dd62e260db682c457afc18d181d1b4466e685f 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -518,11 +518,7 @@ gpio-controller; #gpio-cells = <2>; reg = <0x226000 0x1000>; - interrupts = <42 IRQ_TYPE_EDGE_BOTH - 43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH - 45 IRQ_TYPE_EDGE_BOTH 46 IRQ_TYPE_EDGE_BOTH - 47 IRQ_TYPE_EDGE_BOTH 48 IRQ_TYPE_EDGE_BOTH - 49 IRQ_TYPE_EDGE_BOTH 50 IRQ_TYPE_EDGE_BOTH>; + interrupts = <42 43 44 45 46 47 48 49 50>; ti,ngpio = <144>; ti,davinci-gpio-unbanked = <0>; status = "disabled"; diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 02a136a4661aa1ed172e4926a7a8dabad9e271b9..a5bd8f0205e8e58f719a519685e8709df431bfc9 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -1818,7 +1818,7 @@ }; }; - dcan1: can@481cc000 { + dcan1: can@4ae3c000 { compatible = "ti,dra7-d_can"; ti,hwmods = "dcan1"; reg = <0x4ae3c000 0x2000>; @@ -1828,7 +1828,7 @@ status = "disabled"; }; - dcan2: can@481d0000 { + dcan2: can@48480000 { compatible = "ti,dra7-d_can"; ti,hwmods = "dcan2"; reg = <0x48480000 0x2000>; diff --git a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi index eeb7679fd348a4932d123a8bd7ec76fb5107cc63..849eb3443cde2712705bbbe6c74679ddb81095a8 100644 --- a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi +++ b/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi @@ -644,7 +644,7 @@ dsa,member = <0 0>; eeprom-length = <512>; interrupt-parent = <&gpio6>; - interrupts = <3 IRQ_TYPE_EDGE_FALLING>; + interrupts = <3 IRQ_TYPE_LEVEL_LOW>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi index 4d308d17f040c71157db72a8d81abf8de9dd4d8e..119b63ffb0fec4c55ef4c424343e032dd951da37 100644 --- a/arch/arm/boot/dts/imx7d.dtsi +++ b/arch/arm/boot/dts/imx7d.dtsi @@ -144,10 +144,14 @@ interrupt-names = "msi"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 2 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 3 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 4 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>; + /* + * Reference manual lists pci irqs incorrectly + * Real hardware ordering is same as imx6: D+MSI, C, B, A + */ + interrupt-map = <0 0 0 1 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX7D_PCIE_CTRL_ROOT_CLK>, <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>, <&clks IMX7D_PCIE_PHY_ROOT_CLK>; diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index 379b4a03cfe2f7b92b2c3bd630d204be12a337d9..2d20f60947b951bd1181cef7326a76f82213f45c 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -84,6 +84,7 @@ device_type = "cpu"; reg = <0xf01>; clocks = <&clockgen 1 0>; + #cooling-cells = <2>; }; }; diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 1853573235724419002fd7617ddb9bf0e9a20fc3..028cf4a5887fcecdff631a2c922e2eec0776258d 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -98,6 +98,7 @@ compatible = "arm,cortex-a7"; reg = <0x1>; operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; clock-frequency = <1300000000>; }; @@ -106,6 +107,7 @@ compatible = "arm,cortex-a7"; reg = <0x2>; operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; clock-frequency = <1300000000>; }; @@ -114,6 +116,7 @@ compatible = "arm,cortex-a7"; reg = <0x3>; operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; clock-frequency = <1300000000>; }; }; diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts index 8b93d37310f28ba4c10ad81d35f8419914ef4633..bad690b23081bba82637ad6f05122da34a71b0cc 100644 --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts @@ -314,7 +314,7 @@ &mmc2 { vmmc-supply = <&vsdio>; bus-width = <8>; - non-removable; + ti,non-removable; }; &mmc3 { diff --git a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts index 4dc0b347b1eed522e696ecb85b98f8a9f936ab74..c2dc9d09484abd41d43d13a7a70b0f986a926e19 100644 --- a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts +++ b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts @@ -189,6 +189,8 @@ regulator-max-microvolt = <2950000>; regulator-boot-on; + regulator-system-load = <200000>; + regulator-allow-set-load; }; l21 { diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index 92a9740c533f217a10cd6fb4421d2fc6871d015d..3b1db7b9ec502c444aedc438c89fda6777347ad6 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -206,6 +206,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x70>; + reset-gpio = <&gpio TEGRA_GPIO(BB, 0) GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index ca0f13cafe387e0a0009a8fd9ad97d87f8b2b62a..6e5a3d9c23e1027bd9a3c136b8610e9a641f6192 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -144,9 +144,11 @@ CONFIG_USB_STORAGE=y CONFIG_USB_CHIPIDEA=y CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_CHIPIDEA_ULPI=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_GADGET=y CONFIG_USB_ETH=m +CONFIG_USB_ULPI_BUS=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y diff --git a/arch/arm/configs/vendor/qcs405-perf_defconfig b/arch/arm/configs/vendor/qcs405-perf_defconfig index cac4e74b3625b4602033e92836f7279a781b9cf2..08207b7179780d0e9d1c4ef9d6961044cc220af6 100644 --- a/arch/arm/configs/vendor/qcs405-perf_defconfig +++ b/arch/arm/configs/vendor/qcs405-perf_defconfig @@ -241,6 +241,7 @@ CONFIG_PPP_SYNC_TTY=y CONFIG_USB_USBNET=y CONFIG_USB_NET_SMSC75XX=y CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m CONFIG_INPUT_KEYRESET=y @@ -419,6 +420,8 @@ CONFIG_MSM_SYSMON_QMI_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_QCOM_DCC_V2=y +CONFIG_ICNSS=y +CONFIG_ICNSS_QMI=y CONFIG_QCOM_BUS_SCALING=y CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y @@ -454,6 +457,7 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_ON_RECURSIVE_FAULT=y @@ -481,3 +485,4 @@ CONFIG_CRYPTO_CTR=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y +CONFIG_STACK_HASH_ORDER_SHIFT=12 diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index a1d99420a0b894c7b96fd571d551aa9b5c3044d9..77586c5754ff6e8d88dfd299ec2f8d269a30e350 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -252,6 +252,7 @@ CONFIG_PPP_SYNC_TTY=y CONFIG_USB_USBNET=y CONFIG_USB_NET_SMSC75XX=y CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m CONFIG_INPUT_KEYRESET=y @@ -444,6 +445,9 @@ CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_QCOM_DCC_V2=y +CONFIG_ICNSS=y +CONFIG_ICNSS_DEBUG=y +CONFIG_ICNSS_QMI=y CONFIG_QCOM_BUS_SCALING=y CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y diff --git a/arch/arm/configs/vendor/sdxprairie-perf_defconfig b/arch/arm/configs/vendor/sdxprairie-perf_defconfig index 0c264fcbdd6e7cff57f984f9af5a4b311cd24f73..a44167bf9afb5d5b6d245ee7a1da9337c80b6e90 100644 --- a/arch/arm/configs/vendor/sdxprairie-perf_defconfig +++ b/arch/arm/configs/vendor/sdxprairie-perf_defconfig @@ -272,10 +272,13 @@ CONFIG_RMNET_IPA3=y CONFIG_ECM_IPA=y CONFIG_RNDIS_IPA=y CONFIG_IPA_UT=y +CONFIG_MSM_CLK_AOP_QMP=y CONFIG_MSM_CLK_RPMH=y CONFIG_GCC_SDXPRAIRIE=y +CONFIG_DEBUGCC_SDXPRAIRIE=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MSM_QMP=y CONFIG_IOMMU_IO_PGTABLE_FAST=y CONFIG_ARM_SMMU=y CONFIG_IOMMU_DEBUG=y diff --git a/arch/arm/configs/vendor/sdxprairie_defconfig b/arch/arm/configs/vendor/sdxprairie_defconfig index a43bdd43db0607059056e0d11954628e128cd2d9..fca3d8349ba70808fecaa0937418ece9bc3fd1bc 100644 --- a/arch/arm/configs/vendor/sdxprairie_defconfig +++ b/arch/arm/configs/vendor/sdxprairie_defconfig @@ -262,10 +262,13 @@ CONFIG_RMNET_IPA3=y CONFIG_ECM_IPA=y CONFIG_RNDIS_IPA=y CONFIG_IPA_UT=y +CONFIG_MSM_CLK_AOP_QMP=y CONFIG_MSM_CLK_RPMH=y CONFIG_GCC_SDXPRAIRIE=y +CONFIG_DEBUGCC_SDXPRAIRIE=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MSM_QMP=y CONFIG_IOMMU_IO_PGTABLE_FAST=y CONFIG_ARM_SMMU=y CONFIG_IOMMU_DEBUG=y diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 25f12118c364839c7f8337852789a30c22655e8e..2f6ac1afa8046769e23f8118bad4babc22cc94ce 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -773,7 +773,7 @@ static struct gpiod_lookup_table mmc_gpios_table = { GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_CD_PIN, "cd", GPIO_ACTIVE_LOW), GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_WP_PIN, "wp", - GPIO_ACTIVE_LOW), + GPIO_ACTIVE_HIGH), }, }; diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index b529ba04ed16656aeefc80eb5a4bb95119b6753d..eafa26d9f692d5a1ac654bc4167497d68c44dd3e 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -209,6 +209,7 @@ static int __init exynos_pmu_irq_init(struct device_node *node, NULL); if (!domain) { iounmap(pmu_base_addr); + pmu_base_addr = NULL; return -ENOMEM; } diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c index a129aae7260286fcaf77bc110bce3dea71fb679e..909bb24937812028a706fe865de275b228d1f53d 100644 --- a/arch/arm/mach-hisi/hotplug.c +++ b/arch/arm/mach-hisi/hotplug.c @@ -148,13 +148,20 @@ static int hi3xxx_hotplug_init(void) struct device_node *node; node = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); - if (node) { - ctrl_base = of_iomap(node, 0); - id = HI3620_CTRL; - return 0; + if (!node) { + id = ERROR_CTRL; + return -ENOENT; } - id = ERROR_CTRL; - return -ENOENT; + + ctrl_base = of_iomap(node, 0); + of_node_put(node); + if (!ctrl_base) { + id = ERROR_CTRL; + return -ENOMEM; + } + + id = HI3620_CTRL; + return 0; } void hi3xxx_set_cpu(int cpu, bool enable) @@ -173,11 +180,15 @@ static bool hix5hd2_hotplug_init(void) struct device_node *np; np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl"); - if (np) { - ctrl_base = of_iomap(np, 0); - return true; - } - return false; + if (!np) + return false; + + ctrl_base = of_iomap(np, 0); + of_node_put(np); + if (!ctrl_base) + return false; + + return true; } void hix5hd2_set_cpu(int cpu, bool enable) @@ -219,10 +230,10 @@ void hip01_set_cpu(int cpu, bool enable) if (!ctrl_base) { np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl"); - if (np) - ctrl_base = of_iomap(np, 0); - else - BUG(); + BUG_ON(!np); + ctrl_base = of_iomap(np, 0); + of_node_put(np); + BUG_ON(!ctrl_base); } if (enable) { diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 27a78c80e5b17352aafc4924d04694217bfa5c15..73d5d72dfc3e520894a85875de94791fac84236d 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -116,8 +116,8 @@ void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr) PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu)); } -extern unsigned char mvebu_boot_wa_start; -extern unsigned char mvebu_boot_wa_end; +extern unsigned char mvebu_boot_wa_start[]; +extern unsigned char mvebu_boot_wa_end[]; /* * This function sets up the boot address workaround needed for SMP @@ -130,7 +130,7 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target, phys_addr_t resume_addr_reg) { void __iomem *sram_virt_base; - u32 code_len = &mvebu_boot_wa_end - &mvebu_boot_wa_start; + u32 code_len = mvebu_boot_wa_end - mvebu_boot_wa_start; mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE); mvebu_mbus_add_window_by_id(crypto_eng_target, crypto_eng_attribute, diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 69df3620eca5ce1720f88ab86cf5a36df891d7e7..1c73694c871ad8289b572056d5c3727f3ee22eb2 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -109,6 +109,45 @@ void omap5_erratum_workaround_801819(void) static inline void omap5_erratum_workaround_801819(void) { } #endif +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +/* + * Configure ACR and enable ACTLR[0] (Enable invalidates of BTB with + * ICIALLU) to activate the workaround for secondary Core. + * NOTE: it is assumed that the primary core's configuration is done + * by the boot loader (kernel will detect a misconfiguration and complain + * if this is not done). + * + * In General Purpose(GP) devices, ACR bit settings can only be done + * by ROM code in "secure world" using the smc call and there is no + * option to update the "firmware" on such devices. This also works for + * High security(HS) devices, as a backup option in case the + * "update" is not done in the "security firmware". + */ +static void omap5_secondary_harden_predictor(void) +{ + u32 acr, acr_mask; + + asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr)); + + /* + * ACTLR[0] (Enable invalidates of BTB with ICIALLU) + */ + acr_mask = BIT(0); + + /* Do we already have it done.. if yes, skip expensive smc */ + if ((acr & acr_mask) == acr_mask) + return; + + acr |= acr_mask; + omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr); + + pr_debug("%s: ARM ACR setup for CVE_2017_5715 applied on CPU%d\n", + __func__, smp_processor_id()); +} +#else +static inline void omap5_secondary_harden_predictor(void) { } +#endif + static void omap4_secondary_init(unsigned int cpu) { /* @@ -131,6 +170,8 @@ static void omap4_secondary_init(unsigned int cpu) set_cntfreq(); /* Configure ACR to disable streaming WA for 801819 */ omap5_erratum_workaround_801819(); + /* Enable ACR to allow for ICUALLU workaround */ + omap5_secondary_harden_predictor(); } /* diff --git a/arch/arm/mach-omap2/omap_hwmod_reset.c b/arch/arm/mach-omap2/omap_hwmod_reset.c index b68f9c0aff0b594d97af0c004c2525a7072197f0..d5ddba00bb7310bf0120902e2837dbddc4e90713 100644 --- a/arch/arm/mach-omap2/omap_hwmod_reset.c +++ b/arch/arm/mach-omap2/omap_hwmod_reset.c @@ -92,11 +92,13 @@ static void omap_rtc_wait_not_busy(struct omap_hwmod *oh) */ void omap_hwmod_rtc_unlock(struct omap_hwmod *oh) { - local_irq_disable(); + unsigned long flags; + + local_irq_save(flags); omap_rtc_wait_not_busy(oh); omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG); omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG); - local_irq_enable(); + local_irq_restore(flags); } /** @@ -110,9 +112,11 @@ void omap_hwmod_rtc_unlock(struct omap_hwmod *oh) */ void omap_hwmod_rtc_lock(struct omap_hwmod *oh) { - local_irq_disable(); + unsigned long flags; + + local_irq_save(flags); omap_rtc_wait_not_busy(oh); omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG); omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG); - local_irq_enable(); + local_irq_restore(flags); } diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 9c10248fadccc2d03ef3b3bcbddbe0b43347f158..4e8c2116808ecf3d36d36653184dc89d2941885e 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -185,7 +185,7 @@ static int pxa_irq_suspend(void) { int i; - for (i = 0; i < pxa_internal_irq_nr / 32; i++) { + for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) { void __iomem *base = irq_base(i); saved_icmr[i] = __raw_readl(base + ICMR); @@ -204,7 +204,7 @@ static void pxa_irq_resume(void) { int i; - for (i = 0; i < pxa_internal_irq_nr / 32; i++) { + for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) { void __iomem *base = irq_base(i); __raw_writel(saved_icmr[i], base + ICMR); diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index a4065966881ae44d318ec4193d7091269541970c..57f0bc4cd9b89889c3b6f80b17f41f3b5eb0def8 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -18,6 +18,7 @@ config ARCH_ROCKCHIP select ARM_GLOBAL_TIMER select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK select ZONE_DMA if ARM_LPAE + select PM help Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs containing the RK2928, RK30xx and RK31xx series. diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 8902e2d3e217948f38f879589a6915ee4ecef6a9..236bc6ef269e0ab3cb78fda9924df78b89ea63a4 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -795,19 +795,28 @@ static int __mark_rodata_ro(void *unused) return 0; } +static int kernel_set_to_readonly __read_mostly; + void mark_rodata_ro(void) { + kernel_set_to_readonly = 1; stop_machine(__mark_rodata_ro, NULL, NULL); } void set_kernel_text_rw(void) { + if (!kernel_set_to_readonly) + return; + set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false, current->active_mm); } void set_kernel_text_ro(void) { + if (!kernel_set_to_readonly) + return; + set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true, current->active_mm); } diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 52d1cd14fda45d961ece2d0c4d417d986a372de9..091e9a3c2dcb10d39ae877c2d586384b4ddc52fe 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -291,8 +291,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs) break; case KPROBE_REENTER: /* A nested probe was hit in FIQ, it is a BUG */ - pr_warn("Unrecoverable kprobe detected at %p.\n", - p->addr); + pr_warn("Unrecoverable kprobe detected.\n"); + dump_kprobe(p); /* fall through */ default: /* impossible cases */ diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index 1c98a87786ca768adb622f1720df442a272bfb75..a10d7187ad2c51ecc07f6dc2334d7cd5482cb35a 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -1517,7 +1517,6 @@ static bool check_test_results(void) print_registers(&result_regs); if (mem) { - pr_err("current_stack=%p\n", current_stack); pr_err("expected_memory:\n"); print_memory(expected_memory, mem_size); pr_err("result_memory:\n"); diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index fe09621bfb33f4bb1144fb30c02e0e1e0fffd02e..cdc9eaf788b88bf3ab9a2f345dd43abefac6e1d6 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -742,7 +742,6 @@ config NEED_PER_CPU_EMBED_FIRST_CHUNK config HOLES_IN_ZONE def_bool y - depends on NUMA source kernel/Kconfig.preempt source kernel/Kconfig.hz diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index fa90d3bfda7ea02b6be753ec7a5250ca34f393ef..3cf434661d3446d8b9e1aa777fa82163a269bacf 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -205,6 +205,7 @@ config ARCH_ROCKCHIP select GPIOLIB select PINCTRL select PINCTRL_ROCKCHIP + select PM select ROCKCHIP_TIMER help This enables support for the ARMv8 based Rockchip chipsets, diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-mali.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-mali.dtsi index f06cc234693b76511a27a33c140caf8c8a270c49..379abc3d82fe56836a2603a4e446eee3835895be 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-mali.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-mali.dtsi @@ -7,7 +7,7 @@ &apb { mali: gpu@c0000 { - compatible = "amlogic,meson-gxbb-mali", "arm,mali-450"; + compatible = "amlogic,meson-gxl-mali", "arm,mali-450"; reg = <0x0 0xc0000 0x0 0x40000>; interrupts = , , diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi index 35c8457e3d1f23d32c3db46cbf43f95a3e1ef795..0b72094bcf5a2f63ba4e6229b8f67e1084814496 100644 --- a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi @@ -118,7 +118,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 281 IRQ_TYPE_NONE>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>; linux,pci-domain = <0>; @@ -149,7 +149,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 305 IRQ_TYPE_NONE>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>; linux,pci-domain = <4>; @@ -566,7 +566,7 @@ reg = <0x66080000 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clock-frequency = <100000>; status = "disabled"; }; @@ -594,7 +594,7 @@ reg = <0x660b0000 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clock-frequency = <100000>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/broadcom/stingray/bcm958742k.dts b/arch/arm64/boot/dts/broadcom/stingray/bcm958742k.dts index eb6f08cdbd796c3d764393f9e2e70db2129b0e28..77efa28c4dd53db718b22e64569385f6d92c2feb 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/bcm958742k.dts +++ b/arch/arm64/boot/dts/broadcom/stingray/bcm958742k.dts @@ -43,6 +43,10 @@ enet-phy-lane-swap; }; +&sdio0 { + mmc-ddr-1_8v; +}; + &uart2 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/broadcom/stingray/bcm958742t.dts b/arch/arm64/boot/dts/broadcom/stingray/bcm958742t.dts index 5084b037320fd9cb65133ca929517062a245af3b..55ba495ef56e1f54b518483bc9e5369fcb03b441 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/bcm958742t.dts +++ b/arch/arm64/boot/dts/broadcom/stingray/bcm958742t.dts @@ -42,3 +42,7 @@ &gphy0 { enet-phy-lane-swap; }; + +&sdio0 { + mmc-ddr-1_8v; +}; diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi index e6f75c633623cf45b9efc67844149551eb343e83..2b76293b51c838d79c03589ec40ce5cdc9479a42 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi @@ -409,7 +409,7 @@ reg = <0x000b0000 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clock-frequency = <100000>; status = "disabled"; }; @@ -453,7 +453,7 @@ reg = <0x000e0000 0x100>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clock-frequency = <100000>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 030345c85044e64e5fd76cbb577ee52c4757d0bc..95a09fd21c113dd48efe1721dfb94148b3c9a428 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -32,11 +32,15 @@ ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) sm8150-qrd-overlay.dtbo \ sm8150-qrd-dvt-overlay.dtbo \ sa8155-adp-star-overlay.dtbo \ - sa8155p-adp-star-overlay.dtbo \ + sa8155p-adp-star-overlay.dtbo \ + sa8155-adp-air-overlay.dtbo \ + sa8155p-adp-air-overlay.dtbo \ sm8150-sdx50m-cdp-overlay.dtbo \ sm8150-sdx50m-mtp-overlay.dtbo \ sm8150-sdx50m-mtp-2.5k-panel-overlay.dtbo \ - sm8150-sdx50m-qrd-overlay.dtbo + sm8150-sdx50m-qrd-overlay.dtbo \ + sm8150-sdxprairie-cdp-overlay.dtbo \ + sm8150-sdxprairie-mtp-overlay.dtbo sm8150-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb sm8150-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb @@ -45,19 +49,25 @@ sm8150-qrd-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2. sm8150-qrd-dvt-overlay.dtbo-base := sm8150-v2.dtb sm8150p-v2.dtb sa8155-adp-star-overlay.dtbo-base := sa8155.dtb sa8155-v2.dtb sa8155p-adp-star-overlay.dtbo-base := sa8155p.dtb sa8155p-v2.dtb +sa8155-adp-air-overlay.dtbo-base := sa8155.dtb sa8155-v2.dtb +sa8155p-adp-air-overlay.dtbo-base := sa8155p.dtb sa8155p-v2.dtb sm8150-sdx50m-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb sm8150-sdx50m-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb sm8150-sdx50m-mtp-2.5k-panel-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb sm8150-sdx50m-qrd-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb +sm8150-sdxprairie-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb +sm8150-sdxprairie-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150p.dtb sm8150p-v2.dtb else dtb-$(CONFIG_ARCH_SM8150) += sm8150-rumi.dtb \ sm8150-mtp.dtb \ sm8150-cdp.dtb \ sm8150-qrd.dtb \ sa8155-adp-star.dtb \ - sa8155p-adp-star.dtb \ - sa8155-v2-adp-star.dtb \ - sa8155p-v2-adp-star.dtb \ + sa8155p-adp-star.dtb \ + sa8155-v2-adp-star.dtb \ + sa8155p-v2-adp-star.dtb \ + sa8155-v2-adp-air.dtb \ + sa8155p-v2-adp-air.dtb \ sm8150-v2-rumi.dtb \ sm8150-v2-mtp.dtb \ sm8150-v2-cdp.dtb \ diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi index 1d63e6b879de7cc51784077be9b138f9f5635c8e..b6b44fdf7face8b00690bede37d09d59debed242 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi @@ -187,7 +187,7 @@ led@6 { label = "apq8016-sbc:blue:bt"; gpios = <&pm8916_mpps 3 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "bt"; + linux,default-trigger = "bluetooth-power"; default-state = "off"; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi index 08ea46eb3b49f63cfa22a53324c9c19351a6c4a4..bcd6a2383927884f325f5fee3628617f0accbb57 100644 --- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi @@ -343,6 +343,16 @@ qcom,msm-dai-q6-dev-id = <16401>; }; + sb_9_rx: qcom,msm-dai-q6-sb-9-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16402>; + }; + + sb_9_tx: qcom,msm-dai-q6-sb-9-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16403>; + }; + bt_sco_rx: qcom,msm-dai-q6-bt-sco-rx { compatible = "qcom,msm-dai-q6-dev"; qcom,msm-dai-q6-dev-id = <12288>; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 61da6e65900b2414c09a8d257f891772556f3e8e..3cc449425a0388530a9e755808cbe6dddee38f89 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -1132,14 +1132,14 @@ port@0 { reg = <0>; - etf_out: endpoint { + etf_in: endpoint { slave-mode; remote-endpoint = <&funnel0_out>; }; }; port@1 { reg = <0>; - etf_in: endpoint { + etf_out: endpoint { remote-endpoint = <&replicator_in>; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts index a9ad2c5e99211c5f197bd74df618e1d530f495a7..b0c067b85a79232cab4e99c28b09f3c2536185ae 100644 --- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts @@ -15,6 +15,7 @@ #include "qcs403.dtsi" #include "qcs405-audio-overlay.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS403 EVB2 1000 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts index 852276034c230977694cf33b617b7f5daa5af3d5..13d3e94698dd639575c33f4b1ecde13a3b499ff4 100644 --- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts @@ -76,3 +76,7 @@ /delete-node/ cpuss-2-step; /delete-node/ cpuss-3-step; }; + +&qnand_1 { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi index 69683700a14e351777911a717476080c0cc56498..1f31215e4e65695abdb2761f333e5d9b50138a3a 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi @@ -103,7 +103,8 @@ <&wsa_cdc_dma_2_tx>, <&va_cdc_dma_0_tx>, <&va_cdc_dma_1_tx>, <&dai_pri_spdif_rx>, <&dai_pri_spdif_tx>, - <&dai_sec_spdif_rx>, <&dai_sec_spdif_tx>; + <&dai_sec_spdif_rx>, <&dai_sec_spdif_tx>, + <&sb_9_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", @@ -138,7 +139,8 @@ "msm-dai-cdc-dma-dev.45089", "msm-dai-cdc-dma-dev.45091", "msm-dai-q6-spdif.20480", "msm-dai-q6-spdif.20481", - "msm-dai-q6-spdif.20482", "msm-dai-q6-spdif.20483"; + "msm-dai-q6-spdif.20482", "msm-dai-q6-spdif.20483", + "msm-dai-q6-dev.16403"; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405-led-pca9956.dtsi b/arch/arm64/boot/dts/qcom/qcs405-circular-pca9956.dtsi similarity index 99% rename from arch/arm64/boot/dts/qcom/qcs405-led-pca9956.dtsi rename to arch/arm64/boot/dts/qcom/qcs405-circular-pca9956.dtsi index 332e805923a926c9595f4c228d9a73aa41568654..f7da0448d99c87d60db5c029e4c21b85f70a9402 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-led-pca9956.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-circular-pca9956.dtsi @@ -244,4 +244,3 @@ }; }; }; - diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts index 0a60f153abcd6239e28b697f35e2bcf9c0709baa..f00c5f55f2f6e4044ac39909b16b9bf64e1d3927 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts @@ -15,6 +15,7 @@ #include "qcs405.dtsi" #include "qcs405-wsa-audio-overlay.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 1000 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts index 8f22d4c3b334a594f8ebaa641387fa87bc2cb3c5..07f309571b3ceb28ca2b16b3a2582c2ca9da5128 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts @@ -16,6 +16,7 @@ #include "qcs405.dtsi" #include "qcs405-audio-overlay.dtsi" #include "qcs405-geni-ir-overlay.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 SPI IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts index 9ec18758df4dd289c25e4bad9b9310330a275716..a1814a55bcb32f8cd1193f564d01c211be9b7769 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts @@ -17,6 +17,7 @@ #include "qcs405-audio-overlay.dtsi" #include "qcs405-geni-ir-overlay.dtsi" #include "qcs405-pinctrl.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 sEVB/SLT IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts index 6bc5d84eb92214e68ef2e2031f026dbe89e49326..eb8311260a72e6e807fd8bf0c2cbc9ce58f8fd05 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts @@ -16,6 +16,7 @@ #include "qcs405.dtsi" #include "qcs405-audio-overlay.dtsi" #include "qcs405-geni-ir-overlay.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 DSI IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts index 695e0500101dd6e7e8c92bf1d1833880eda290b6..433728cb4d54ff83ac565696b35fd89572fa2de5 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts @@ -16,6 +16,7 @@ #include "qcs405.dtsi" #include "qcs405-audio-overlay.dtsi" #include "qcs405-geni-ir-overlay.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 RGB IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts index edd9d4d86dd0aa7a8f678ffeaa952685c23d61ba..6b5bb84799cddf1bb725a66c164b2b3a3684b173 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts @@ -16,6 +16,7 @@ #include "qcs405.dtsi" #include "qcs405-csra1-audio-overlay.dtsi" #include "qcs405-geni-ir-overlay.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 CSRA1 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts index ceac14d652d365a7bd5e653cd897b4dfc3eb56f5..02b537d433c3e112830aa9344d0cd22d90dd4b52 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts @@ -16,6 +16,7 @@ #include "qcs405.dtsi" #include "qcs405-csra6-audio-overlay.dtsi" #include "qcs405-geni-ir-overlay.dtsi" +#include "qcs405-linear-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 CSRA6 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts index ef26d1ae76d7fb7bd18a9eacdbfde15aaa509924..f08512ea1c58033d0b40bd3c6806227ed0a20740 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts @@ -16,6 +16,7 @@ #include "qcs405.dtsi" #include "qcs405-amic-audio-overlay.dtsi" #include "qcs405-geni-ir-overlay.dtsi" +#include "qcs405-circular-pca9956.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 AMIC IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-linear-pca9956.dtsi b/arch/arm64/boot/dts/qcom/qcs405-linear-pca9956.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..cc872d4b4ebc659585a8010f0c085dd4ac15e217 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-linear-pca9956.dtsi @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2018, 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. + */ + +&i2c_2 { + status = "ok"; + qcom,clk-freq-out = <100000>; + + /* PCA9956B LED Drivers */ + nxp-ledseg-i2c@65 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nxp,pca9956b"; + reg = <0x65>; + pca9956b,support_initialize = <1>; + pca9956b,mode1 = <0x09>; + pca9956b,mode2 = <0x05>; + + pca9956b,ledout0 = <0xAA>; + pca9956b,ledout1 = <0xAA>; + pca9956b,ledout2 = <0xAA>; + pca9956b,ledout3 = <0xFF>; + pca9956b,ledout4 = <0xFF>; + pca9956b,ledout5 = <0xFF>; + pca9956b,defaultiref = <0x2f>; + out0@0 { + label = "ledsec5_b"; + reg = <0x0>; + }; + out1@1 { + label = "ledsec5_g"; + reg = <0x1>; + }; + out2@2 { + label = "ledsec5_r"; + reg = <0x2>; + }; + out3@3 { + label = "ledsec6_b"; + reg = <0x3>; + }; + out4@4 { + label = "ledsec6_g"; + reg = <0x4>; + }; + out5@5 { + label = "ledsec6_r"; + reg = <0x5>; + }; + out6@6 { + label = "ledsec7_b"; + reg = <0x6>; + }; + out7@7 { + label = "ledsec7_g"; + reg = <0x7>; + }; + out8@8 { + label = "ledsec7_r"; + reg = <0x8>; + }; + out9@9 { + label = "ledsec8_b"; + reg = <0x9>; + }; + out10@10 { + label = "ledsec8_g"; + reg = <0xA>; + }; + out11@11 { + label = "ledsec8_r"; + reg = <0xB>; + }; + out12@12 { + label = "ledsec1_b"; + reg = <0xC>; + }; + out13@13 { + label = "ledsec1_g"; + reg = <0xD>; + }; + out14@14 { + label = "ledsec1_r"; + reg = <0xE>; + }; + out15@15 { + label = "ledsec2_b"; + reg = <0xF>; + }; + out16@16 { + label = "ledsec2_g"; + reg = <0x10>; + }; + out17@17 { + label = "ledsec2_r"; + reg = <0x11>; + }; + out18@18 { + label = "ledsec3_b"; + reg = <0x12>; + }; + out19@19 { + label = "ledsec3_g"; + reg = <0x13>; + }; + out20@20 { + label = "ledsec3_r"; + reg = <0x14>; + }; + out21@21 { + label = "ledsec4_b"; + reg = <0x15>; + }; + out22@22 { + label = "ledsec4_g"; + reg = <0x16>; + }; + out23@23 { + label = "ledsec4_r"; + reg = <0x17>; + }; + }; + + nxp-ledseg-i2c@15 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nxp,pca9956b"; + reg = <0x15>; + pca9956b,support_initialize = <1>; + pca9956b,mode1 = <0x09>; + pca9956b,mode2 = <0x05>; + + pca9956b,ledout0 = <0xAA>; + pca9956b,ledout1 = <0xAA>; + pca9956b,ledout2 = <0xAA>; + pca9956b,ledout3 = <0xFF>; + pca9956b,ledout4 = <0xFF>; + pca9956b,ledout5 = <0xFF>; + pca9956b,defaultiref = <0x2f>; + out0@0 { + label = "ledsec9_b"; + reg = <0x0>; + }; + out1@1 { + label = "ledsec9_g"; + reg = <0x1>; + }; + out2@2 { + label = "ledsec9_r"; + reg = <0x2>; + }; + out3@3 { + label = "ledsec10_b"; + reg = <0x3>; + }; + out4@4 { + label = "ledsec10_g"; + reg = <0x4>; + }; + out5@5 { + label = "ledsec10_r"; + reg = <0x5>; + }; + out6@6 { + label = "ledsec11_b"; + reg = <0x6>; + }; + out7@7 { + label = "ledsec11_g"; + reg = <0x7>; + }; + out8@8 { + label = "ledsec11_r"; + reg = <0x8>; + }; + out9@9 { + label = "ledsec12_b"; + reg = <0x9>; + }; + out10@10 { + label = "ledsec12_g"; + reg = <0xA>; + }; + out11@11 { + label = "ledsec12_r"; + reg = <0xB>; + }; + out12@12 { + label = "ledsec13_b"; + reg = <0xC>; + }; + out13@13 { + label = "ledsec13_g"; + reg = <0xD>; + }; + out14@14 { + label = "ledsec13_r"; + reg = <0xE>; + }; + out15@15 { + label = "ledsec14_b"; + reg = <0xF>; + }; + out16@16 { + label = "ledsec14_g"; + reg = <0x10>; + }; + out17@17 { + label = "ledsec14_r"; + reg = <0x11>; + }; + out18@18 { + label = "ledsec15_b"; + reg = <0x12>; + }; + out19@19 { + label = "ledsec15_g"; + reg = <0x13>; + }; + out20@20 { + label = "ledsec15_r"; + reg = <0x14>; + }; + out21@21 { + label = "ledsec16_b"; + reg = <0x15>; + }; + out22@22 { + label = "ledsec16_g"; + reg = <0x16>; + }; + out23@23 { + label = "ledsec16_r"; + reg = <0x17>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi index eb8e248170af8cd3ce1bc9367c24c6deb066b02c..24b50d4f4b582dc764286c42f4b65e6288c2a54f 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi @@ -988,6 +988,20 @@ }; }; + nxp_i2c_intr: nxp_i2c_intr { + mux { + pins = "gpio35"; + function = "gpio"; + }; + + config { + pins = "gpio35"; + drive-strength = <2>; + bias-pull-up; + input-enable; + }; + }; + usb3_id_det_default: usb2_id_det_default { config { pins = "gpio116"; diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index fd78a51bc15efe39bb56c2cf2b4d0f7ecf4cf457..91b9bcd0e14d337899b60eefd564904cc338b71d 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -1460,6 +1460,16 @@ dpdm-supply = <&usb2_phy0>; qcom,otg-enable; }; + + usb_typec: usb_typec@3d { + compatible = "nxp,5150a"; + reg = <0x3d>; + interrupt-parent = <&tlmm>; + interrupts = <35 IRQ_TYPE_LEVEL_LOW>; + pintctrl-names = "default"; + pinctrl-0 = <&nxp_i2c_intr>; + status = "disabled"; + }; }; &pms405_gpios { @@ -1501,29 +1511,3 @@ extcon = <&usb3_extcon>; }; -#include "qcs405-led-pca9956.dtsi" - -&soc { - i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */ - compatible = "qcom,i2c-msm-v2"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x78b6000 0x600>; - reg-names = "qup_phys_addr"; - interrupt-names = "qup_irq"; - interrupts = <0 96 0>; - dmas = <&dma_blsp1 10 64 0x20000020 0x20>, - <&dma_blsp1 11 32 0x20000020 0x20>; - dma-names = "tx", "rx"; - qcom,master-id = <86>; - qcom,clk-freq-out = <400000>; - qcom,clk-freq-in = <19200000>; - clock-names = "iface_clk", "core_clk"; - clocks = <&clock_gcc GCC_BLSP1_AHB_CLK>, - <&clock_gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>; - pinctrl-names = "i2c_active", "i2c_sleep"; - pinctrl-0 = <&i2c_2_active &pca9956b_reset_gpio>; - pinctrl-1 = <&i2c_2_sleep>; - status = "ok"; - }; -}; diff --git a/arch/arm64/boot/dts/qcom/qg-batterydata-mlp466076-3200mah.dtsi b/arch/arm64/boot/dts/qcom/qg-batterydata-mlp466076-3200mah.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..30a355683891f1d7a8e01738a15706813a596299 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qg-batterydata-mlp466076-3200mah.dtsi @@ -0,0 +1,1040 @@ + +/* Copyright (c) 2018, 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. + */ + +qcom,mlp466076_3200mAh { + /* mlp466076_3200mAh_averaged_MasterSlave_Sept28th2018 */ + qcom,max-voltage-uv = <4400000>; + qcom,fg-cc-cv-threshold-mv = <4390>; + qcom,fastchg-current-ma = <6000>; + qcom,batt-id-kohm = <133>; + qcom,battery-beta = <4250>; + qcom,battery-therm-kohm = <100>; + qcom,battery-type = + "mlp466076_3200mAh_averaged_MasterSlave_Sept28th2018"; + qcom,qg-batt-profile-ver = <100>; + + qcom,jeita-fcc-ranges = <0 150 650000 + 151 450 4875000 + 451 550 1625000>; + qcom,jeita-fv-ranges = <0 150 4150000 + 151 450 4400000 + 451 550 4150000>; + /* COLD = 0 DegC, HOT = 55 DegC */ + qcom,jeita-hard-thresholds = <0x5840 0x1810>; + /* COOL = 15 DegC, WARM = 45 DegC */ + qcom,jeita-soft-thresholds = <0x45f3 0x20c4>; + + qcom,fcc1-temp-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-data = <3205 3248 3306 3328 3328>; + }; + + qcom,fcc2-temp-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-data = <3118 3203 3253 3314 3327 3333>; + }; + + qcom,pc-temp-v1-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200>, + <9000 8800 8600 8400 8200>, + <8000 7800 7600 7400 7200>, + <7000 6800 6600 6400 6200>, + <6000 5800 5600 5400 5200>, + <5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200>, + <3000 2800 2600 2400 2200>, + <2000 1800 1600 1400 1200>, + <1000 900 800 700 600>, + <500 400 300 200 100>, + <0>; + qcom,lut-data = <43662 43765 43827 43854 43857>, + <43465 43592 43648 43679 43680>, + <43244 43371 43441 43477 43474>, + <43004 43143 43219 43263 43254>, + <42786 42919 42991 43039 43024>, + <42603 42692 42762 42806 42790>, + <42425 42464 42530 42568 42557>, + <42215 42239 42301 42330 42326>, + <41980 42016 42073 42096 42101>, + <41759 41797 41849 41866 41875>, + <41557 41584 41627 41642 41650>, + <41362 41378 41411 41424 41428>, + <41163 41178 41202 41209 41210>, + <40961 40977 41001 40999 40999>, + <40760 40772 40799 40794 40793>, + <40563 40570 40594 40597 40597>, + <40358 40372 40396 40405 40407>, + <40145 40178 40221 40225 40226>, + <39945 40002 40053 40053 40050>, + <39789 39854 39847 39858 39853>, + <39654 39711 39576 39612 39620>, + <39531 39519 39339 39375 39391>, + <39412 39263 39176 39190 39200>, + <39282 39052 39040 39032 39031>, + <39133 38917 38919 38892 38884>, + <38984 38816 38812 38767 38758>, + <38858 38736 38712 38655 38645>, + <38756 38672 38614 38553 38541>, + <38668 38609 38524 38459 38444>, + <38595 38544 38445 38374 38354>, + <38533 38483 38374 38297 38270>, + <38475 38429 38310 38226 38195>, + <38430 38379 38253 38166 38130>, + <38401 38330 38199 38107 38067>, + <38377 38287 38153 38049 38003>, + <38346 38242 38109 37990 37936>, + <38285 38194 38057 37927 37867>, + <38212 38141 37997 37860 37794>, + <38144 38070 37923 37783 37713>, + <38069 37964 37822 37685 37612>, + <37974 37836 37698 37571 37495>, + <37837 37691 37560 37439 37359>, + <37673 37537 37406 37289 37206>, + <37502 37409 37248 37138 37064>, + <37345 37284 37128 37023 36958>, + <37238 37184 37066 36969 36904>, + <37204 37151 37050 36949 36887>, + <37171 37121 37032 36932 36873>, + <37134 37087 36999 36898 36835>, + <37025 36967 36850 36728 36642>, + <36701 36632 36509 36379 36285>, + <36239 36167 36048 35916 35824>, + <35649 35576 35460 35327 35236>, + <34852 34778 34666 34533 34443>, + <33622 33561 33462 33330 33238>, + <30000 30000 30000 30000 30000>; + }; + + qcom,pc-temp-v2-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>, + <8800 8600 8400 8200 8000 7800>, + <7600 7400 7200 7000 6800 6600>, + <6400 6200 6000 5800 5600 5400>, + <5200 5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200 3000>, + <2800 2600 2400 2200 2000 1800>, + <1600 1400 1200 1000 900 800>, + <700 600 500 400 300 200>, + <100 0>; + qcom,lut-data = <43390 43645 43750 43815 43800 43795>, + <42983 43258 43441 43569 43578 43582>, + <42608 42904 43149 43327 43354 43366>, + <42270 42588 42877 43089 43129 43145>, + <41961 42304 42623 42856 42904 42921>, + <41683 42042 42377 42623 42676 42694>, + <41438 41791 42134 42391 42446 42463>, + <41238 41546 41897 42160 42215 42232>, + <41062 41317 41666 41934 41987 42003>, + <40846 41113 41438 41710 41760 41775>, + <40569 40968 41219 41489 41537 41550>, + <40319 40809 41018 41270 41319 41329>, + <40103 40562 40827 41057 41104 41111>, + <39844 40259 40633 40856 40895 40900>, + <39546 39953 40421 40658 40689 40693>, + <39304 39745 40200 40455 40490 40494>, + <39117 39574 39983 40245 40297 40302>, + <38956 39378 39768 40043 40107 40114>, + <38793 39156 39546 39861 39925 39933>, + <38644 38938 39315 39676 39735 39743>, + <38519 38742 39102 39446 39499 39505>, + <38411 38566 38911 39183 39234 39243>, + <38324 38421 38746 38973 39029 39041>, + <38257 38302 38600 38817 38875 38887>, + <38199 38211 38469 38683 38741 38752>, + <38146 38145 38351 38560 38617 38628>, + <38098 38091 38245 38450 38505 38515>, + <38052 38045 38150 38347 38400 38409>, + <38006 38004 38065 38253 38304 38311>, + <37961 37964 37993 38163 38214 38219>, + <37916 37925 37937 38080 38133 38135>, + <37869 37885 37889 38001 38057 38057>, + <37819 37842 37844 37926 37987 37985>, + <37765 37793 37800 37855 37919 37914>, + <37706 37743 37753 37784 37834 37819>, + <37641 37692 37702 37716 37722 37690>, + <37572 37633 37642 37647 37608 37564>, + <37495 37562 37573 37569 37511 37461>, + <37414 37476 37492 37486 37421 37368>, + <37330 37382 37399 37399 37334 37278>, + <37241 37277 37290 37309 37247 37186>, + <37150 37164 37167 37199 37139 37073>, + <37061 37043 37037 37065 37012 36948>, + <36974 36929 36917 36918 36864 36803>, + <36874 36836 36835 36850 36812 36762>, + <36760 36750 36766 36819 36788 36738>, + <36690 36703 36735 36797 36767 36721>, + <36594 36645 36672 36765 36742 36693>, + <36441 36551 36563 36683 36669 36598>, + <36215 36353 36313 36466 36433 36312>, + <35901 36016 35927 36050 36018 35886>, + <35430 35532 35419 35522 35495 35356>, + <34781 34891 34751 34850 34822 34674>, + <33883 34005 33839 33929 33926 33799>, + <32534 32590 32567 32727 32712 32584>, + <30011 30004 30001 30000 30000 29999>; + }; + + qcom,pc-temp-z1-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200>, + <9000 8800 8600 8400 8200>, + <8000 7800 7600 7400 7200>, + <7000 6800 6600 6400 6200>, + <6000 5800 5600 5400 5200>, + <5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200>, + <3000 2800 2600 2400 2200>, + <2000 1800 1600 1400 1200>, + <1000 900 800 700 600>, + <500 400 300 200 100>, + <0>; + qcom,lut-data = <13336 12737 12245 12063 12028>, + <13321 12715 12202 12029 11977>, + <13325 12709 12216 11985 11908>, + <13384 12694 12186 11976 11728>, + <13496 12676 12160 11969 11639>, + <13923 12659 12154 11893 11631>, + <14348 12649 12151 11776 11626>, + <14398 12645 12146 11753 11623>, + <14405 12639 12138 11752 11620>, + <14400 12606 12131 11751 11617>, + <14362 12571 12127 11749 11615>, + <14304 12567 12126 11745 11614>, + <14258 12571 12126 11742 11613>, + <14214 12572 12126 11740 11610>, + <14183 12588 12124 11738 11609>, + <14141 12697 12117 11737 11609>, + <14075 12810 12113 11737 11609>, + <14011 12906 12116 11737 11610>, + <13963 12974 12123 11738 11610>, + <13946 12991 12124 11740 11610>, + <13939 12997 12122 11742 11610>, + <13933 12991 12120 11744 11612>, + <13934 12994 12127 11747 11614>, + <13946 13005 12137 11750 11617>, + <13955 13003 12140 11754 11620>, + <13948 12997 12140 11759 11622>, + <13954 12995 12141 11762 11626>, + <13959 12996 12143 11764 11629>, + <13950 12997 12146 11765 11633>, + <13956 13000 12149 11768 11637>, + <13993 13006 12155 11775 11641>, + <14015 13018 12157 11780 11645>, + <14022 13035 12158 11783 11649>, + <14016 13041 12160 11786 11653>, + <14003 13041 12168 11789 11656>, + <13991 13044 12179 11793 11660>, + <13999 13058 12183 11799 11664>, + <14034 13080 12184 11809 11669>, + <14066 13093 12185 11817 11674>, + <14095 13109 12200 11820 11679>, + <14119 13123 12216 11822 11684>, + <14122 13124 12214 11823 11687>, + <14096 13124 12204 11830 11690>, + <14077 13123 12206 11831 11693>, + <14091 13131 12216 11832 11695>, + <14132 13134 12220 11839 11701>, + <14111 13151 12226 11842 11703>, + <14099 13131 12231 11845 11707>, + <14137 13170 12238 11848 11710>, + <14113 13167 12233 11864 11717>, + <14164 13173 12257 11862 11720>, + <14159 13211 12252 11883 11727>, + <14137 13247 12286 11882 11736>, + <14149 13284 12290 11888 11745>, + <14149 13284 12290 11888 11745>, + <14149 13284 12290 11888 11745>; + }; + + qcom,pc-temp-z2-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200>, + <9000 8800 8600 8400 8200>, + <8000 7800 7600 7400 7200>, + <7000 6800 6600 6400 6200>, + <6000 5800 5600 5400 5200>, + <5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200>, + <3000 2800 2600 2400 2200>, + <2000 1800 1600 1400 1200>, + <1000 900 800 700 600>, + <500 400 300 200 100>, + <0>; + qcom,lut-data = <9618 9833 10273 10587 10613>, + <9717 10071 10235 10423 10322>, + <9767 10199 10360 10416 10359>, + <10027 10256 10382 10432 10417>, + <10146 10256 10391 10426 10403>, + <9854 10234 10380 10416 10359>, + <9540 10218 10359 10403 10313>, + <9614 10214 10345 10400 10300>, + <9875 10209 10334 10415 10313>, + <9964 10204 10329 10423 10330>, + <9958 10204 10339 10396 10336>, + <9950 10208 10353 10348 10338>, + <9946 10211 10359 10338 10339>, + <9943 10216 10362 10358 10338>, + <9910 10210 10368 10373 10337>, + <9742 10146 10380 10369 10343>, + <9638 10109 10390 10356 10357>, + <9760 10123 10389 10353 10377>, + <9935 10139 10383 10357 10397>, + <9965 10142 10386 10365 10410>, + <9980 10142 10400 10404 10416>, + <10008 10144 10410 10463 10423>, + <9880 10150 10391 10527 10467>, + <9720 10157 10363 10588 10536>, + <9779 10171 10371 10588 10530>, + <9972 10186 10419 10538 10402>, + <10034 10188 10442 10493 10311>, + <10027 10183 10423 10474 10309>, + <10024 10181 10403 10462 10323>, + <10022 10188 10403 10460 10329>, + <10021 10197 10406 10460 10328>, + <10020 10201 10411 10461 10334>, + <10019 10205 10425 10482 10364>, + <9912 10208 10438 10519 10399>, + <9718 10212 10445 10557 10436>, + <9686 10216 10450 10599 10488>, + <9872 10220 10457 10630 10512>, + <10038 10226 10465 10653 10510>, + <9970 10229 10473 10670 10510>, + <9661 10232 10488 10685 10521>, + <9424 10234 10501 10695 10542>, + <9380 10229 10497 10686 10581>, + <9360 10221 10485 10657 10635>, + <9344 10401 10482 10661 10609>, + <9319 11186 10491 10661 10585>, + <9305 13142 10504 10625 10613>, + <9304 13559 10476 10620 10613>, + <9293 12008 10464 10612 10648>, + <9279 11863 10466 10654 10747>, + <9266 12115 10555 10704 10597>, + <9244 11992 10590 10647 10489>, + <9219 10653 10578 10583 10440>, + <9180 10297 10596 10530 10382>, + <9154 9949 10524 10471 10317>, + <9154 9949 10524 10471 10317>, + <9154 9949 10524 10471 10317>; + }; + + qcom,pc-temp-z3-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200>, + <9000 8800 8600 8400 8200>, + <8000 7800 7600 7400 7200>, + <7000 6800 6600 6400 6200>, + <6000 5800 5600 5400 5200>, + <5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200>, + <3000 2800 2600 2400 2200>, + <2000 1800 1600 1400 1200>, + <1000 900 800 700 600>, + <500 400 300 200 100>, + <0>; + qcom,lut-data = <19375 19363 19375 19346 19348>, + <19394 19375 19412 19383 19378>, + <19468 19500 19455 19415 19392>, + <19623 19565 19476 19435 19361>, + <19700 19580 19486 19440 19348>, + <19658 19588 19489 19420 19361>, + <19609 19591 19491 19387 19372>, + <19662 19591 19490 19383 19370>, + <19814 19591 19488 19389 19364>, + <19862 19588 19485 19390 19359>, + <19847 19579 19478 19384 19358>, + <19826 19569 19471 19377 19357>, + <19811 19561 19468 19374 19357>, + <19800 19556 19465 19374 19356>, + <19764 19563 19463 19374 19354>, + <19601 19599 19463 19372 19350>, + <19493 19623 19463 19370 19346>, + <19603 19630 19460 19369 19343>, + <19740 19634 19456 19368 19342>, + <19729 19629 19457 19367 19342>, + <19717 19622 19467 19370 19344>, + <19700 19624 19473 19373 19349>, + <19575 19644 19462 19377 19360>, + <19507 19655 19447 19383 19375>, + <19642 19654 19449 19389 19380>, + <19829 19652 19464 19402 19380>, + <19889 19647 19475 19411 19380>, + <19884 19641 19480 19408 19376>, + <19880 19639 19483 19403 19371>, + <19873 19638 19481 19398 19368>, + <19863 19638 19475 19393 19365>, + <19854 19636 19471 19388 19362>, + <19843 19634 19468 19385 19358>, + <19752 19632 19465 19381 19355>, + <19596 19631 19462 19379 19352>, + <19561 19629 19459 19378 19349>, + <19674 19626 19457 19377 19348>, + <19773 19619 19455 19377 19347>, + <19709 19612 19453 19377 19346>, + <19460 19605 19449 19376 19347>, + <19282 19598 19443 19373 19349>, + <19273 19594 19440 19370 19351>, + <19274 19589 19438 19367 19354>, + <19274 19383 19434 19366 19352>, + <19275 19258 19424 19363 19345>, + <19276 19257 19403 19344 19332>, + <19276 19257 19383 19344 19331>, + <19277 19258 19361 19345 19324>, + <19278 19258 19366 19342 19319>, + <19279 19258 19361 19347 19341>, + <19281 19258 19350 19351 19347>, + <19284 19259 19346 19357 19349>, + <19291 19260 19336 19360 19351>, + <19296 19262 19330 19362 19356>, + <19296 19262 19330 19362 19356>, + <19296 19262 19330 19362 19356>; + }; + + qcom,pc-temp-z4-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200>, + <9000 8800 8600 8400 8200>, + <8000 7800 7600 7400 7200>, + <7000 6800 6600 6400 6200>, + <6000 5800 5600 5400 5200>, + <5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200>, + <3000 2800 2600 2400 2200>, + <2000 1800 1600 1400 1200>, + <1000 900 800 700 600>, + <500 400 300 200 100>, + <0>; + qcom,lut-data = <15630 15273 15043 14960 14945>, + <15689 15382 15065 14963 14961>, + <15723 15346 15157 15020 14973>, + <15654 15257 15080 15001 14877>, + <15621 15154 14988 14931 14792>, + <15743 15055 14927 14858 14759>, + <15853 14981 14873 14788 14737>, + <15756 14922 14829 14752 14722>, + <15538 14876 14792 14733 14715>, + <15404 14844 14769 14721 14709>, + <15340 14819 14759 14716 14702>, + <15293 14799 14752 14713 14694>, + <15250 14783 14746 14708 14686>, + <15214 14773 14740 14701 14680>, + <15227 14774 14739 14695 14676>, + <15369 14801 14741 14692 14673>, + <15468 14820 14744 14690 14671>, + <15361 14830 14738 14688 14670>, + <15201 14832 14727 14685 14667>, + <15170 14815 14736 14690 14675>, + <15151 14789 14815 14750 14721>, + <15127 14804 14877 14806 14764>, + <15219 14885 14892 14809 14763>, + <15278 14938 14900 14802 14751>, + <15140 14940 14888 14791 14740>, + <14941 14935 14845 14762 14727>, + <14880 14921 14812 14737 14714>, + <14888 14894 14794 14726 14706>, + <14891 14871 14782 14720 14700>, + <14891 14857 14780 14716 14695>, + <14888 14844 14779 14715 14691>, + <14884 14834 14779 14714 14689>, + <14879 14825 14781 14714 14688>, + <14953 14818 14783 14714 14687>, + <15095 14813 14783 14718 14692>, + <15118 14807 14782 14727 14704>, + <14978 14801 14782 14731 14709>, + <14853 14795 14780 14732 14711>, + <14902 14789 14778 14733 14711>, + <15140 14785 14771 14729 14708>, + <15315 14780 14761 14722 14703>, + <15314 14769 14752 14717 14701>, + <15291 14758 14742 14712 14699>, + <15259 14934 14730 14706 14695>, + <15156 15013 14704 14693 14685>, + <15078 14949 14666 14661 14654>, + <15075 14945 14675 14647 14643>, + <15071 14942 14689 14634 14634>, + <15063 14935 14681 14635 14635>, + <15049 14927 14694 14647 14637>, + <15057 14938 14712 14649 14640>, + <15071 14942 14718 14646 14641>, + <15084 14949 14731 14644 14640>, + <15105 14958 14742 14645 14638>, + <15105 14958 14742 14645 14638>, + <15105 14958 14742 14645 14638>; + }; + + qcom,pc-temp-z5-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200>, + <9000 8800 8600 8400 8200>, + <8000 7800 7600 7400 7200>, + <7000 6800 6600 6400 6200>, + <6000 5800 5600 5400 5200>, + <5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200>, + <3000 2800 2600 2400 2200>, + <2000 1800 1600 1400 1200>, + <1000 900 800 700 600>, + <500 400 300 200 100>, + <0>; + qcom,lut-data = <12124 12072 13157 13174 13606>, + <12994 13000 14804 15085 15154>, + <13587 14583 15791 16396 16870>, + <13874 15964 16772 16919 15801>, + <13884 16939 17839 17371 16041>, + <13288 17849 18811 17290 17992>, + <12752 18889 19806 17211 20051>, + <13155 20252 21035 17957 20337>, + <14211 21670 22602 19862 19980>, + <14723 22477 23646 20935 19733>, + <14736 22953 24200 20677 20042>, + <14649 23096 24568 19994 20872>, + <14721 23386 24733 19863 21792>, + <14828 23940 25087 20680 22627>, + <14648 25256 25600 21530 22979>, + <13383 26083 27040 21835 22568>, + <12564 25447 28188 22062 21924>, + <14450 24954 27982 22511 21937>, + <16825 25408 27494 23231 22542>, + <16732 25757 28143 23429 22575>, + <16303 26250 33310 22605 21080>, + <15711 28817 36779 21685 19879>, + <13993 36697 31028 20502 19380>, + <16429 41291 22626 18349 18894>, + <23300 39174 21659 17982 18992>, + <29454 35310 22858 20629 20165>, + <31867 32664 24466 23458 21295>, + <32326 30650 27410 25252 22111>, + <32352 30008 30586 26767 23020>, + <31698 30713 32388 28065 24313>, + <30597 31769 33715 29167 26079>, + <29641 32615 34902 30229 27629>, + <28570 33593 36165 31554 29266>, + <25166 34668 36865 32469 30251>, + <20184 36022 36864 32454 29500>, + <18967 36995 36786 32263 28117>, + <21737 37027 36538 32001 27361>, + <24117 36857 35657 31514 25956>, + <22175 36546 34649 30833 24906>, + <15699 35485 33710 29804 25141>, + <11242 34238 32735 28436 25578>, + <10985 33611 31645 26834 26096>, + <10984 32850 30651 25139 26981>, + <10998 19087 30705 25214 25567>, + <11145 11243 30585 25077 23501>, + <11257 11255 29211 23396 23355>, + <11216 11222 22088 26638 26212>, + <11217 11211 16895 30416 25864>, + <11223 11229 17933 28658 22675>, + <11260 11323 17117 24401 28538>, + <11268 11309 15536 23343 28235>, + <11186 11276 14888 24817 26689>, + <11117 11246 13952 24826 26557>, + <11073 11186 13396 24230 27076>, + <11073 11186 13396 24230 27076>, + <11073 11186 13396 24230 27076>; + }; + + qcom,pc-temp-z6-lut { + qcom,lut-col-legend = <0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200>, + <9000 8800 8600 8400 8200>, + <8000 7800 7600 7400 7200>, + <7000 6800 6600 6400 6200>, + <6000 5800 5600 5400 5200>, + <5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200>, + <3000 2800 2600 2400 2200>, + <2000 1800 1600 1400 1200>, + <1000 900 800 700 600>, + <500 400 300 200 100>, + <0>; + qcom,lut-data = <16016 15401 15028 14870 14848>, + <15996 15430 15032 14874 14857>, + <16013 15428 15075 14902 14845>, + <16033 15402 15037 14897 14721>, + <16086 15344 14991 14863 14651>, + <16361 15274 14956 14789 14644>, + <16617 15223 14923 14701 14637>, + <16582 15181 14896 14678 14629>, + <16509 15146 14871 14671 14622>, + <16437 15116 14854 14665 14616>, + <16363 15091 14843 14658 14611>, + <16293 15068 14836 14652 14607>, + <16231 15048 14830 14648 14603>, + <16173 15033 14826 14645 14600>, + <16114 15039 14823 14642 14596>, + <16055 15104 14821 14639 14593>, + <16013 15166 14819 14636 14590>, + <15987 15206 14815 14635 14588>, + <15960 15231 14810 14633 14587>, + <15927 15226 14815 14636 14590>, + <15890 15215 14856 14663 14611>, + <15856 15224 14886 14690 14632>, + <15831 15272 14888 14694 14639>, + <15823 15302 14886 14695 14642>, + <15833 15304 14882 14695 14642>, + <15847 15302 14874 14690 14637>, + <15856 15296 14868 14684 14631>, + <15863 15284 14864 14679 14625>, + <15866 15276 14862 14675 14621>, + <15866 15272 14861 14671 14617>, + <15865 15269 14859 14668 14615>, + <15862 15267 14859 14666 14613>, + <15859 15265 14860 14665 14610>, + <15852 15265 14861 14664 14609>, + <15844 15268 14863 14666 14610>, + <15842 15271 14865 14670 14614>, + <15848 15272 14866 14673 14617>, + <15853 15272 14868 14675 14618>, + <15851 15272 14869 14676 14618>, + <15844 15275 14867 14675 14618>, + <15839 15279 14864 14672 14617>, + <15842 15282 14863 14669 14618>, + <15846 15284 14862 14667 14620>, + <15845 15274 14860 14666 14618>, + <15825 15253 14851 14661 14611>, + <15802 15242 14830 14638 14592>, + <15802 15243 14825 14633 14586>, + <15804 15246 14823 14629 14579>, + <15809 15251 14826 14629 14578>, + <15817 15257 14834 14638 14591>, + <15831 15272 14842 14644 14598>, + <15851 15287 14848 14648 14600>, + <15875 15306 14857 14652 14603>, + <15910 15332 14869 14657 14608>, + <15910 15332 14869 14657 14608>, + <15910 15332 14869 14657 14608>; + }; + + qcom,pc-temp-y1-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>, + <8800 8600 8400 8200 8000 7800>, + <7600 7400 7200 7000 6800 6600>, + <6400 6200 6000 5800 5600 5400>, + <5200 5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200 3000>, + <2800 2600 2400 2200 2000 1800>, + <1600 1400 1200 1000 900 800>, + <700 600 500 400 300 200>, + <100 0>; + qcom,lut-data = <7469 6760 6042 5497 5274 5198>, + <7455 6707 6039 5495 5279 5198>, + <7446 6674 6036 5493 5282 5198>, + <7441 6657 6033 5492 5283 5196>, + <7439 6651 6030 5492 5282 5194>, + <7438 6650 6029 5492 5281 5191>, + <7435 6671 6029 5490 5278 5188>, + <7457 6694 6031 5488 5274 5184>, + <7493 6691 6032 5488 5271 5182>, + <7523 6673 6036 5489 5269 5179>, + <7534 6667 6039 5489 5266 5178>, + <7533 6670 6042 5486 5262 5176>, + <7509 6674 6043 5484 5260 5175>, + <7462 6673 6041 5488 5259 5174>, + <7430 6668 6043 5496 5258 5173>, + <7429 6670 6047 5497 5257 5173>, + <7440 6686 6046 5494 5255 5172>, + <7451 6697 6045 5491 5254 5172>, + <7461 6689 6051 5490 5254 5171>, + <7470 6688 6064 5489 5254 5171>, + <7467 6709 6073 5490 5254 5172>, + <7453 6738 6074 5493 5256 5173>, + <7447 6737 6069 5494 5257 5174>, + <7466 6706 6057 5493 5258 5174>, + <7488 6684 6045 5492 5259 5175>, + <7488 6689 6045 5497 5260 5176>, + <7479 6704 6053 5504 5261 5179>, + <7481 6706 6065 5507 5263 5180>, + <7480 6690 6067 5505 5266 5180>, + <7474 6678 6068 5504 5269 5181>, + <7470 6685 6071 5506 5271 5183>, + <7475 6700 6068 5510 5272 5186>, + <7487 6701 6058 5510 5274 5188>, + <7506 6693 6054 5511 5278 5190>, + <7505 6688 6053 5514 5282 5193>, + <7479 6697 6054 5525 5287 5196>, + <7461 6709 6058 5534 5290 5198>, + <7474 6706 6065 5532 5290 5201>, + <7509 6692 6071 5525 5289 5204>, + <7535 6679 6068 5523 5290 5206>, + <7557 6670 6052 5530 5294 5207>, + <7562 6667 6053 5530 5299 5210>, + <7500 6668 6060 5522 5304 5215>, + <7457 6704 6072 5530 5307 5216>, + <7452 6712 6072 5531 5305 5219>, + <7456 6691 6057 5530 5309 5222>, + <7457 6715 6070 5540 5311 5222>, + <7463 6729 6073 5535 5310 5225>, + <7518 6729 6079 5539 5324 5221>, + <7582 6694 6086 5548 5318 5222>, + <7580 6700 6062 5567 5316 5228>, + <7670 6739 6071 5571 5325 5234>, + <7673 6736 6087 5567 5337 5241>, + <7747 6806 6107 5572 5339 5245>, + <7747 6806 6107 5572 5339 5245>, + <7747 6806 6107 5572 5339 5245>; + }; + + qcom,pc-temp-y2-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>, + <8800 8600 8400 8200 8000 7800>, + <7600 7400 7200 7000 6800 6600>, + <6400 6200 6000 5800 5600 5400>, + <5200 5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200 3000>, + <2800 2600 2400 2200 2000 1800>, + <1600 1400 1200 1000 900 800>, + <700 600 500 400 300 200>, + <100 0>; + qcom,lut-data = <9654 9670 10551 11010 11144 11132>, + <9654 9664 10572 11003 11122 11113>, + <9654 9666 10596 10986 11100 11091>, + <9655 9674 10618 10965 11080 11067>, + <9655 9685 10634 10947 11062 11042>, + <9655 9700 10639 10938 11050 11014>, + <9655 9826 10635 10918 11042 10979>, + <9655 9962 10629 10897 11034 10951>, + <9656 9921 10625 10894 11006 10941>, + <9656 9908 10620 10889 10959 10936>, + <9655 10020 10617 10888 10942 10937>, + <9655 10154 10637 10888 10942 10942>, + <9656 10128 10673 10889 10944 10946>, + <9655 9942 10721 10887 10956 10950>, + <9655 9749 10784 10886 10981 10953>, + <9655 9706 10811 10900 11006 10948>, + <9655 9705 10823 10951 11037 10930>, + <9655 9700 10828 11000 11067 10930>, + <9655 9692 10813 11041 11113 11023>, + <9655 9685 10791 11070 11148 11118>, + <9655 9680 10790 11066 11141 11127>, + <9655 9676 10807 11047 11122 11129>, + <9655 9674 10824 11039 11127 11139>, + <9654 9674 10780 11055 11159 11171>, + <9654 9673 10518 11070 11188 11189>, + <9654 9671 10349 11080 11202 11180>, + <9654 9669 10440 11101 11206 11175>, + <9654 9666 10556 11106 11215 11189>, + <9654 9665 10441 11109 11252 11206>, + <9654 9663 10297 11110 11284 11234>, + <9654 9661 10243 11114 11292 11309>, + <9654 9660 10211 11117 11300 11366>, + <9654 9659 10170 11102 11321 11364>, + <9654 9657 10101 11060 11352 11337>, + <9654 9656 9980 11044 11359 11314>, + <9654 9656 9877 11079 11336 11289>, + <9654 9655 9821 11113 11306 11280>, + <9654 9654 9774 11098 11289 11291>, + <9654 9654 9727 11051 11276 11300>, + <9654 9654 9699 11010 11276 11302>, + <9654 9654 9686 10969 11341 11310>, + <9654 9653 9680 10925 11388 11308>, + <9654 9653 9674 10873 11365 11311>, + <9654 9653 9668 10788 11287 11336>, + <9653 9653 9665 10704 11273 11333>, + <9653 9653 9663 10732 11295 11236>, + <9653 9653 9662 10795 11303 11164>, + <9653 9653 9661 10797 11232 11154>, + <9653 9653 9660 10768 11213 11165>, + <9652 9653 9659 10741 11214 11105>, + <9651 9653 9658 10661 11159 11059>, + <9650 9652 9657 10616 11088 11003>, + <9650 9651 9656 10566 10982 10904>, + <9648 9650 9655 10519 10871 10771>, + <9648 9650 9655 10519 10871 10771>, + <9648 9650 9655 10519 10871 10771>; + }; + + qcom,pc-temp-y3-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>, + <8800 8600 8400 8200 8000 7800>, + <7600 7400 7200 7000 6800 6600>, + <6400 6200 6000 5800 5600 5400>, + <5200 5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200 3000>, + <2800 2600 2400 2200 2000 1800>, + <1600 1400 1200 1000 900 800>, + <700 600 500 400 300 200>, + <100 0>; + qcom,lut-data = <14894 13675 13387 13307 13288 13282>, + <14761 13671 13390 13308 13286 13280>, + <14612 13660 13393 13309 13284 13279>, + <14466 13645 13396 13310 13283 13278>, + <14339 13628 13399 13311 13282 13278>, + <14251 13610 13402 13312 13282 13278>, + <14211 13592 13404 13313 13283 13278>, + <14196 13568 13406 13313 13284 13279>, + <14179 13541 13408 13314 13284 13279>, + <14129 13512 13411 13315 13283 13280>, + <14073 13500 13412 13316 13283 13280>, + <14057 13502 13412 13316 13285 13281>, + <14063 13505 13412 13317 13287 13281>, + <14032 13507 13410 13317 13288 13280>, + <13973 13505 13404 13318 13290 13280>, + <13957 13504 13396 13318 13290 13280>, + <13957 13504 13389 13319 13291 13282>, + <13959 13496 13381 13319 13291 13284>, + <13962 13479 13372 13318 13293 13287>, + <13967 13456 13362 13315 13295 13288>, + <13982 13429 13355 13311 13292 13285>, + <14014 13403 13350 13305 13285 13279>, + <14050 13387 13346 13301 13283 13277>, + <14095 13378 13340 13298 13282 13277>, + <14145 13378 13330 13297 13282 13277>, + <14193 13390 13318 13296 13281 13276>, + <14243 13411 13306 13296 13279 13276>, + <14295 13435 13293 13296 13279 13276>, + <14353 13462 13273 13296 13279 13276>, + <14413 13494 13260 13295 13280 13276>, + <14474 13533 13260 13295 13280 13275>, + <14537 13580 13261 13294 13281 13275>, + <14602 13634 13261 13294 13281 13276>, + <14670 13695 13261 13293 13282 13276>, + <14736 13767 13264 13293 13282 13276>, + <14799 13851 13282 13294 13280 13276>, + <14862 13945 13312 13294 13279 13275>, + <14926 14048 13331 13291 13279 13275>, + <14990 14162 13335 13284 13279 13275>, + <15053 14281 13336 13283 13278 13275>, + <15115 14406 13343 13290 13278 13275>, + <15180 14531 13361 13293 13278 13275>, + <15247 14652 13395 13294 13277 13275>, + <15325 14760 13446 13296 13277 13274>, + <15372 14809 13489 13296 13278 13275>, + <15544 14923 13525 13303 13280 13277>, + <15659 14973 13563 13309 13281 13280>, + <15786 14998 13617 13315 13286 13283>, + <15982 14992 13666 13319 13288 13283>, + <16341 15053 13698 13323 13286 13281>, + <16796 15132 13761 13324 13287 13281>, + <17451 15263 13864 13331 13289 13283>, + <18369 15740 13993 13343 13291 13285>, + <19582 16580 14194 13360 13296 13288>, + <19582 16580 14194 13360 13296 13288>, + <19582 16580 14194 13360 13296 13288>; + }; + + qcom,pc-temp-y4-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>, + <8800 8600 8400 8200 8000 7800>, + <7600 7400 7200 7000 6800 6600>, + <6400 6200 6000 5800 5600 5400>, + <5200 5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200 3000>, + <2800 2600 2400 2200 2000 1800>, + <1600 1400 1200 1000 900 800>, + <700 600 500 400 300 200>, + <100 0>; + qcom,lut-data = <17253 17133 16743 16577 16480 16460>, + <17386 17231 16792 16587 16483 16461>, + <17568 17323 16861 16596 16486 16461>, + <17760 17403 16932 16602 16488 16461>, + <17920 17464 16989 16607 16489 16461>, + <18007 17499 17012 16608 16489 16461>, + <18009 17502 17012 16606 16488 16461>, + <17988 17500 17010 16602 16487 16462>, + <17999 17543 17006 16600 16488 16463>, + <18041 17680 16996 16599 16491 16465>, + <17967 17812 16989 16599 16494 16467>, + <17844 17840 17026 16601 16497 16469>, + <17736 17724 17085 16607 16500 16472>, + <17602 17539 17128 16618 16505 16479>, + <17436 17339 17166 16635 16511 16487>, + <17320 17297 17151 16652 16520 16495>, + <17244 17301 17110 16668 16534 16503>, + <17191 17252 17064 16689 16553 16515>, + <17124 17151 17004 16737 16591 16542>, + <17061 17040 16905 16780 16622 16564>, + <17025 16955 16810 16741 16596 16545>, + <17000 16890 16734 16612 16522 16494>, + <16985 16845 16684 16548 16487 16471>, + <16978 16817 16665 16531 16476 16462>, + <16977 16803 16663 16522 16471 16460>, + <16983 16798 16662 16519 16472 16460>, + <16991 16794 16658 16518 16474 16461>, + <17001 16792 16662 16518 16477 16464>, + <17010 16794 16686 16521 16481 16468>, + <17020 16799 16701 16525 16486 16473>, + <17027 16808 16700 16529 16495 16481>, + <17033 16819 16703 16532 16507 16490>, + <17039 16831 16711 16532 16521 16502>, + <17046 16844 16721 16528 16536 16513>, + <17054 16856 16725 16523 16536 16511>, + <17064 16874 16716 16507 16502 16483>, + <17071 16892 16701 16493 16470 16463>, + <17073 16896 16700 16494 16460 16460>, + <17074 16895 16718 16497 16455 16458>, + <17078 16898 16740 16501 16456 16458>, + <17086 16907 16756 16509 16461 16460>, + <17100 16916 16766 16520 16461 16457>, + <17127 16927 16777 16533 16464 16458>, + <17151 16945 16788 16535 16451 16440>, + <17171 16968 16822 16535 16453 16444>, + <17277 17044 16856 16576 16475 16464>, + <17341 17101 16922 16610 16490 16483>, + <17410 17129 16953 16651 16514 16518>, + <17486 17107 17015 16692 16536 16519>, + <17605 17116 17023 16691 16503 16472>, + <17753 17101 17030 16669 16495 16475>, + <17998 17092 17063 16706 16514 16494>, + <18444 17292 17132 16776 16554 16536>, + <19473 17868 17327 16903 16672 16712>, + <19473 17868 17327 16903 16672 16712>, + <19473 17868 17327 16903 16672 16712>; + }; + + qcom,pc-temp-y5-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>, + <8800 8600 8400 8200 8000 7800>, + <7600 7400 7200 7000 6800 6600>, + <6400 6200 6000 5800 5600 5400>, + <5200 5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200 3000>, + <2800 2600 2400 2200 2000 1800>, + <1600 1400 1200 1000 900 800>, + <700 600 500 400 300 200>, + <100 0>; + qcom,lut-data = <10911 10298 14213 16701 17755 21052>, + <10898 10547 14445 16766 17305 19443>, + <10949 10923 14667 16781 16536 18148>, + <11030 11360 14873 16758 15705 17155>, + <11105 11790 15060 16708 15066 16451>, + <11140 12156 15225 16638 14868 16040>, + <11427 12622 15397 16476 14926 16016>, + <12770 12870 15521 16320 14987 16092>, + <13889 12496 15526 16267 14730 15883>, + <13648 12382 15474 16192 14147 15511>, + <12823 13043 15351 16067 14037 15384>, + <13350 13999 14703 15767 14366 15172>, + <14369 14322 14084 15374 14619 14868>, + <13835 13655 14198 14817 14642 14286>, + <12387 13207 14689 14237 14597 13690>, + <11862 13518 15158 14092 14432 13665>, + <11843 14013 15618 14088 14125 13889>, + <11872 14061 16032 14147 14029 14160>, + <11697 13724 16290 14567 14307 14509>, + <11496 13360 16491 15286 14746 14893>, + <11296 12874 16629 16221 15422 15320>, + <11018 12157 16685 17422 16386 15876>, + <10915 11509 16661 17766 16912 16362>, + <10937 11055 16364 17245 17282 17294>, + <10949 10862 15125 16788 17482 17704>, + <10928 10863 14139 16796 17047 17507>, + <10893 10892 13688 16847 16257 17185>, + <10862 10972 13103 16906 15960 16859>, + <10846 11049 11861 16955 16035 16391>, + <10863 11085 11085 16970 16245 16032>, + <10920 11156 11094 16960 16494 15813>, + <11002 11238 11065 16985 16807 15733>, + <11078 11244 11007 17138 17386 15954>, + <11131 11221 10960 17460 18188 16486>, + <11133 11274 11023 17775 18436 17083>, + <11097 11459 11423 18423 18423 17731>, + <11069 11605 11910 18965 18423 18211>, + <11060 11618 12071 17553 19122 18678>, + <11055 11604 12039 14324 19839 19105>, + <11037 11603 11978 13643 19020 19029>, + <11002 11612 11919 15021 17826 18387>, + <10971 11599 11823 15233 17990 17895>, + <10972 11465 11745 14656 16514 17780>, + <11158 11428 11876 14911 18206 19748>, + <11212 11498 11959 14662 17928 18323>, + <11369 11538 11852 15035 16485 16557>, + <11571 11627 12089 15093 15314 16819>, + <11625 11902 12653 15141 16476 16374>, + <11579 12519 13295 14848 16431 16247>, + <11380 12618 13272 15759 17268 17871>, + <11028 12392 13194 15990 18549 17841>, + <10501 11978 13207 15787 18547 18581>, + <10084 11290 12982 15884 18113 18317>, + <9775 10649 12845 16062 18034 18316>, + <9775 10649 12845 16062 18034 18316>, + <9775 10649 12845 16062 18034 18316>; + }; + + qcom,pc-temp-y6-lut { + qcom,lut-col-legend = <(-10) 0 10 25 40 50>; + qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>, + <8800 8600 8400 8200 8000 7800>, + <7600 7400 7200 7000 6800 6600>, + <6400 6200 6000 5800 5600 5400>, + <5200 5000 4800 4600 4400 4200>, + <4000 3800 3600 3400 3200 3000>, + <2800 2600 2400 2200 2000 1800>, + <1600 1400 1200 1000 900 800>, + <700 600 500 400 300 200>, + <100 0>; + qcom,lut-data = <7509 6257 5552 5162 5046 5022>, + <7463 6254 5559 5162 5046 5021>, + <7413 6247 5566 5163 5045 5020>, + <7363 6237 5570 5163 5044 5019>, + <7317 6225 5572 5162 5044 5018>, + <7278 6214 5572 5162 5043 5018>, + <7243 6201 5566 5160 5043 5018>, + <7222 6185 5556 5157 5042 5019>, + <7224 6169 5548 5155 5042 5019>, + <7201 6173 5539 5153 5042 5020>, + <7139 6196 5532 5152 5042 5020>, + <7087 6209 5536 5152 5044 5021>, + <7056 6178 5547 5152 5046 5022>, + <6999 6115 5554 5154 5048 5024>, + <6917 6048 5556 5158 5050 5025>, + <6873 6034 5546 5163 5053 5028>, + <6851 6036 5529 5167 5057 5031>, + <6842 6018 5510 5173 5063 5036>, + <6825 5983 5485 5185 5075 5045>, + <6811 5944 5450 5195 5085 5053>, + <6818 5914 5419 5182 5075 5045>, + <6840 5894 5395 5141 5049 5026>, + <6866 5889 5380 5120 5037 5018>, + <6900 5891 5370 5113 5033 5015>, + <6939 5897 5361 5110 5032 5014>, + <6977 5914 5357 5110 5032 5014>, + <7015 5942 5356 5110 5032 5015>, + <7055 5972 5354 5110 5032 5015>, + <7098 6006 5353 5112 5034 5016>, + <7142 6046 5355 5114 5036 5018>, + <7189 6091 5362 5117 5039 5020>, + <7238 6142 5372 5119 5043 5023>, + <7287 6197 5384 5120 5048 5027>, + <7337 6258 5398 5120 5054 5031>, + <7385 6325 5416 5120 5054 5030>, + <7432 6399 5439 5119 5044 5022>, + <7479 6479 5466 5117 5034 5017>, + <7525 6560 5497 5117 5032 5016>, + <7573 6645 5535 5117 5031 5016>, + <7622 6734 5578 5119 5031 5016>, + <7671 6829 5627 5130 5033 5017>, + <7725 6923 5681 5142 5034 5016>, + <7782 7014 5743 5151 5035 5017>, + <7845 7098 5815 5160 5032 5012>, + <7891 7143 5876 5164 5035 5014>, + <8048 7251 5926 5190 5043 5022>, + <8152 7306 5983 5210 5048 5029>, + <8272 7333 6038 5233 5060 5042>, + <8457 7327 6100 5254 5067 5042>, + <8797 7374 6135 5262 5057 5027>, + <9221 7430 6200 5263 5056 5028>, + <9832 7529 6307 5294 5065 5036>, + <10714 7994 6439 5339 5079 5051>, + <11882 8845 6653 5404 5118 5105>, + <11882 8845 6653 5404 5118 5105>, + <11882 8845 6653 5404 5118 5105>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa6155-pcie.dtsi b/arch/arm64/boot/dts/qcom/sa6155-pcie.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..44f9a761dfcfca2d999ca717f7e98617854dc47a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa6155-pcie.dtsi @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2018, 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 + +&soc { + pcie0: qcom,pcie@1c08000 { + compatible = "qcom,pci-msm"; + cell-index = <0>; + + reg = <0x1c08000 0x4000>, + <0x1c0e000 0x1000>, + <0x40000000 0xf1d>, + <0x40000f20 0xa8>, + <0x40001000 0x1000>, + <0x40100000 0x100000>, + <0x40200000 0x100000>, + <0x40300000 0x1fd00000>; + + reg-names = "parf", "phy", "dm_core", "elbi", + "iatu", "conf", "io", "bars"; + + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x40200000 0x40200000 0x0 0x100000>, + <0x02000000 0x0 0x40300000 0x40300000 0x0 0x1fd00000>; + interrupt-parent = <&pcie0>; + interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 + 36 37>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0xffffffff>; + interrupt-map = <0 0 0 0 &intc 0 141 0 + 0 0 0 1 &intc 0 149 0 + 0 0 0 2 &intc 0 150 0 + 0 0 0 3 &intc 0 151 0 + 0 0 0 4 &intc 0 152 0 + 0 0 0 5 &intc 0 140 0 + 0 0 0 6 &intc 0 768 0 + 0 0 0 7 &intc 0 769 0 + 0 0 0 8 &intc 0 770 0 + 0 0 0 9 &intc 0 771 0 + 0 0 0 10 &intc 0 772 0 + 0 0 0 11 &intc 0 773 0 + 0 0 0 12 &intc 0 774 0 + 0 0 0 13 &intc 0 775 0 + 0 0 0 14 &intc 0 776 0 + 0 0 0 15 &intc 0 777 0 + 0 0 0 16 &intc 0 778 0 + 0 0 0 17 &intc 0 779 0 + 0 0 0 18 &intc 0 780 0 + 0 0 0 19 &intc 0 781 0 + 0 0 0 20 &intc 0 782 0 + 0 0 0 21 &intc 0 783 0 + 0 0 0 22 &intc 0 784 0 + 0 0 0 23 &intc 0 785 0 + 0 0 0 24 &intc 0 786 0 + 0 0 0 25 &intc 0 787 0 + 0 0 0 26 &intc 0 788 0 + 0 0 0 27 &intc 0 789 0 + 0 0 0 28 &intc 0 790 0 + 0 0 0 29 &intc 0 791 0 + 0 0 0 30 &intc 0 792 0 + 0 0 0 31 &intc 0 793 0 + 0 0 0 32 &intc 0 794 0 + 0 0 0 33 &intc 0 795 0 + 0 0 0 34 &intc 0 796 0 + 0 0 0 35 &intc 0 797 0 + 0 0 0 36 &intc 0 798 0 + 0 0 0 37 &intc 0 799 0>; + + interrupt-names = "int_msi", "int_a", "int_b", "int_c", + "int_d", "int_global_int", + "msi_0", "msi_1", "msi_2", "msi_3", + "msi_4", "msi_5", "msi_6", "msi_7", + "msi_8", "msi_9", "msi_10", "msi_11", + "msi_12", "msi_13", "msi_14", "msi_15", + "msi_16", "msi_17", "msi_18", "msi_19", + "msi_20", "msi_21", "msi_22", "msi_23", + "msi_24", "msi_25", "msi_26", "msi_27", + "msi_28", "msi_29", "msi_30", "msi_31"; + + qcom,phy-sequence = <0x0800 0x01 0x0 + 0x0804 0x03 0x0 + 0x0034 0x18 0x0 + 0x0038 0x10 0x0 + 0x0294 0x06 0x0 + 0x00c8 0x01 0x0 + 0x0128 0x00 0x0 + 0x0144 0xff 0x0 + 0x0148 0x1f 0x0 + 0x0070 0x0f 0x0 + 0x0048 0x0f 0x0 + 0x0178 0x00 0x0 + 0x019c 0x01 0x0 + 0x018c 0x20 0x0 + 0x0184 0x0a 0x0 + 0x00b4 0x20 0x0 + 0x000c 0x09 0x0 + 0x00ac 0x04 0x0 + 0x00d0 0x82 0x0 + 0x00e4 0x03 0x0 + 0x00e0 0x55 0x0 + 0x00dc 0x55 0x0 + 0x0054 0x00 0x0 + 0x0050 0x0d 0x0 + 0x004c 0x04 0x0 + 0x0174 0x33 0x0 + 0x003c 0x02 0x0 + 0x0040 0x1f 0x0 + 0x0078 0x0b 0x0 + 0x0084 0x16 0x0 + 0x0090 0x28 0x0 + 0x010c 0x00 0x0 + 0x0108 0x80 0x0 + 0x0010 0x01 0x0 + 0x001c 0x31 0x0 + 0x0020 0x01 0x0 + 0x0014 0x02 0x0 + 0x0018 0x00 0x0 + 0x0024 0x2f 0x0 + 0x0028 0x19 0x0 + 0x0268 0x45 0x0 + 0x0194 0x06 0x0 + 0x024c 0x02 0x0 + 0x02ac 0x12 0x0 + 0x0510 0x1c 0x0 + 0x051c 0x14 0x0 + 0x04d8 0x01 0x0 + 0x04dc 0x00 0x0 + 0x04e0 0xdb 0x0 + 0x0448 0x4b 0x0 + 0x041c 0x04 0x0 + 0x0410 0x04 0x0 + 0x0074 0x19 0x0 + 0x0854 0x04 0x0 + 0x09ac 0x00 0x0 + 0x08a0 0x40 0x0 + 0x09e0 0x00 0x0 + 0x09dc 0x40 0x0 + 0x09a8 0x00 0x0 + 0x08a4 0x40 0x0 + 0x08a8 0x73 0x0 + 0x0518 0x99 0x0 + 0x0824 0x15 0x0 + 0x0828 0x0e 0x0 + 0x09b0 0x07 0x0 + 0x0800 0x00 0x0 + 0x0808 0x03 0x0>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_clkreq_default + &pcie0_perst_default + &pcie0_wake_default>; + + perst-gpio = <&tlmm 101 0>; + wake-gpio = <&tlmm 100 0>; + + gdsc-vdd-supply = <&pcie_0_gdsc>; + vreg-1.8-supply = <&L12A>; + vreg-0.9-supply = <&L5A>; + + vreg-cx-supply = <&VDD_CX_LEVEL>; + + qcom,vreg-1.8-voltage-level = <1800000 1800000 24000>; + qcom,vreg-0.9-voltage-level = <925000 925000 24000>; + qcom,vreg-cx-voltage-level = ; + + qcom,no-l0s-supported; + + qcom,max-link-speed = <0x2>; + + qcom,ep-latency = <10>; + + qcom,slv-addr-space-size = <0x20000000>; + + qcom,phy-status-offset = <0x974>; + qcom,phy-power-down-offset = <0x804>; + + qcom,boot-option = <0x1>; + + linux,pci-domain = <0>; + + qcom,msi-gicm-addr = <0x17a00040>; + qcom,msi-gicm-base = <0x320>; + + qcom,pcie-phy-ver = <0x10>; + qcom,use-19p2mhz-aux-clk; + + qcom,msm-bus,name = "pcie0"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <45 512 0 0>, + <45 512 500 800>; + + clocks = <&clock_gcc GCC_PCIE_0_PIPE_CLK>, + <&clock_rpmh RPMH_CXO_CLK>, + <&clock_gcc GCC_PCIE_0_AUX_CLK>, + <&clock_gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&clock_gcc GCC_PCIE_0_MSTR_AXI_CLK>, + <&clock_gcc GCC_PCIE_0_SLV_AXI_CLK>, + <&clock_gcc GCC_PCIE_0_CLKREF_CLK>, + <&clock_gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>, + <&clock_gcc GCC_PCIE0_PHY_REFGEN_CLK>, + <&clock_gcc GCC_PCIE_PHY_AUX_CLK>; + + clock-names = "pcie_0_pipe_clk", "pcie_0_ref_clk_src", + "pcie_0_aux_clk", "pcie_0_cfg_ahb_clk", + "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk", + "pcie_0_ldo", "pcie_0_slv_q2a_axi_clk", + "pcie_phy_refgen_clk", "pcie_phy_aux_clk"; + + max-clock-frequency-hz = <0>, <0>, <19200000>, <0>, <0>, <0>, + <0>, <0>, <0>, <0>, <100000000>, <0>; + + resets = <&clock_gcc GCC_PCIE_0_BCR>, + <&clock_gcc GCC_PCIE_0_PHY_BCR>; + + reset-names = "pcie_0_core_reset", + "pcie_0_phy_reset"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa6155.dtsi b/arch/arm64/boot/dts/qcom/sa6155.dtsi index 10d67f890e5c8f7307bfc9c9d4b00d5a9e494226..f9135335e30db4a5a37e3395d38f89d4a2bdae35 100644 --- a/arch/arm64/boot/dts/qcom/sa6155.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155.dtsi @@ -19,6 +19,10 @@ compatible = "qcom,sa6155"; qcom,msm-name = "SA6155"; qcom,msm-id = <384 0x10000>; + + aliases { + pci-domain0 = &pcie0; /* PCIe0 domain */ + }; }; &qusb_phy0 { @@ -232,3 +236,4 @@ &mdss_mdp { connectors = <&sde_rscc &dsi_dp1 &sde_wb>; }; +#include "sa6155-pcie.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sa6155p.dtsi b/arch/arm64/boot/dts/qcom/sa6155p.dtsi index c7b6136015c696670f009f584ae097d34421254f..ac7414621a6ac33a3ac3bb3f48d21222befb23b9 100644 --- a/arch/arm64/boot/dts/qcom/sa6155p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155p.dtsi @@ -19,6 +19,10 @@ model = "Qualcomm Technologies, Inc. SA6155P"; qcom,msm-name = "SA6155P"; qcom,msm-id = <377 0>; + + aliases { + pci-domain0 = &pcie0; /* PCIe0 domain */ + }; }; /* Delete second instance of pm6155 definitions for APQ version */ @@ -257,3 +261,4 @@ /* Audio device tree */ #include "sa6155-audio.dtsi" +#include "sa6155-pcie.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155-adp-star-overlay.dts index 611d29151e3777385286e9eb8188c4c176acfa2b..4dd522713b208e94605e1e694da277dd44285f4f 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-adp-star-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star-overlay.dts @@ -13,6 +13,8 @@ /dts-v1/; /plugin/; +#include + #include "sa8155-adp-star.dtsi" / { diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi index 69b5b38fb564b233bb5d1e2e8536f8e672613831..9ec9a6812cc5c9e207510bdc08d80af04a6cf7e0 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi @@ -14,6 +14,7 @@ #include #include "sa8155-pmic-overlay.dtsi" +#include "sm8150-camera-sensor-adp-star.dtsi" &qupv3_se0_spi { status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..267d6f7891d88b17913ad42426c6563311802198 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air-overlay.dts @@ -0,0 +1,23 @@ +/* Copyright (c) 2018, 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/; +/plugin/; + +#include "sa8155-adp-star.dtsi" + +/ { + model = "ADP-AIR"; + compatible = "qcom,sa8155-v2-adp-air", "qcom,sa8155", + "qcom,adp-air"; + qcom,board-id = <0X01000019 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air.dts b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air.dts new file mode 100644 index 0000000000000000000000000000000000000000..d95b90938884630270c3ad26d60857ffc3213eea --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2018, 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 "sa8155-v2.dtsi" +#include "sa8155-adp-star.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA8155 V2 ADP AIR"; + compatible = "qcom,sa8155-v2-adp-air", "qcom,sa8155", "qcom,adp-air"; + qcom,board-id = <0x01000019 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8155.dtsi b/arch/arm64/boot/dts/qcom/sa8155.dtsi index c87d88e815dc31eb6ab62deaf6aee4e37b6eacfc..758cd4ed05cbee2d6b7c27d05a0ef6688260b946 100644 --- a/arch/arm64/boot/dts/qcom/sa8155.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155.dtsi @@ -753,3 +753,104 @@ }; #include "sa8155-audio.dtsi" + +/* GPU frequency overrides */ +&soc { + gpu_opp_table_v2: gpu_opp_table_v2 { + compatible = "operating-points-v2"; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = ; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + opp-microvolt = ; + }; + + opp-585000000 { + opp-hz = /bits/ 64 <585000000>; + opp-microvolt = ; + }; + + opp-427000000 { + opp-hz = /bits/ 64 <427000000>; + opp-microvolt = ; + }; + + opp-345000000 { + opp-hz = /bits/ 64 <345000000>; + opp-microvolt = ; + }; + + opp-257000000 { + opp-hz = /bits/ 64 <257000000>; + opp-microvolt = ; + }; + + }; +}; + +/* GPU power level overrides */ +&msm_gpu { + qcom,gpu-pwrlevels { + compatible = "qcom,gpu-pwrlevels"; + + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <675000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <7>; + qcom,bus-max = <9>; + }; + + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <585000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <6>; + qcom,bus-max = <11>; + }; + + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <427000000>; + qcom,bus-freq = <6>; + qcom,bus-min = <5>; + qcom,bus-max = <9>; + }; + + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <345000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <8>; + }; + + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <257000000>; + qcom,bus-freq = <2>; + qcom,bus-min = <1>; + qcom,bus-max = <8>; + }; + + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <0>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp-star-overlay.dts index 298df1df8ad102bb57f18e4930c137032501b8ba..6c8c6688da1a511a4f3ea6291be5a5df90d5155e 100644 --- a/arch/arm64/boot/dts/qcom/sa8155p-adp-star-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sa8155p-adp-star-overlay.dts @@ -13,6 +13,8 @@ /dts-v1/; /plugin/; +#include + #include "sa8155-adp-star.dtsi" / { diff --git a/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..41a1132485de2da6b25e9856b80c269a76e1e5a4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air-overlay.dts @@ -0,0 +1,23 @@ +/* Copyright (c) 2018, 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/; +/plugin/; + +#include "sa8155-adp-star.dtsi" + +/ { + model = "ADP-AIR"; + compatible = "qcom,sa8155p-v2-adp-air", "qcom,sa8155p", + "qcom,adp-air"; + qcom,board-id = <0x01000019 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air.dts b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air.dts new file mode 100644 index 0000000000000000000000000000000000000000..8d270657542d1611aa48f7b1614c25f80d945870 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2018, 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 "sa8155p-v2.dtsi" +#include "sa8155-adp-star.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA8155P V2 ADP AIR"; + compatible = "qcom,sa8155p-v2-adp-air", "qcom,sa8155p", "qcom,adp-air"; + qcom,board-id = <0x01000019 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-audio-overlay.dtsi index a180cdd6fc2b9396018f4e17f54798cb0369fc18..fda04ff5a82c017c043fb89d79a866e49ca2da52 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-audio-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-audio-overlay.dtsi @@ -26,5 +26,6 @@ }; &sm6150_snd { - qcom,model = "sm6150-wcd9375-snd-card"; + qcom,wcn-btfm = <0>; + qcom,ext-disp-audio-rx = <0>; }; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..9d7ea5c890f6b165c769d96cac51979c94e42968 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi @@ -0,0 +1,887 @@ +/* + * Copyright (c) 2018, 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,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,cam_smmu { + compatible = "qcom,msm-cam-smmu"; + status = "ok"; + + msm_cam_smmu_ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x900 0x460>, + <&apps_smmu 0xD00 0x460>, + <&apps_smmu 0x880 0x460>, + <&apps_smmu 0xC80 0x460>, + <&apps_smmu 0x820 0x440>, + <&apps_smmu 0xC20 0x440>, + <&apps_smmu 0x920 0x460>, + <&apps_smmu 0xD20 0x460>, + <&apps_smmu 0x8A0 0x460>, + <&apps_smmu 0xCA0 0x460>, + <&apps_smmu 0x940 0x460>, + <&apps_smmu 0xD40 0x460>, + <&apps_smmu 0x8C0 0x460>, + <&apps_smmu 0xCC0 0x460>; + label = "ife"; + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm_cam_smmu_jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1280 0x20>, + <&apps_smmu 0x12A0 0x20>; + label = "jpeg"; + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm_cam_icp_fw { + compatible = "qcom,msm-cam-smmu-fw-dev"; + label="icp"; + memory-region = <&pil_camera_mem>; + }; + + msm_cam_smmu_icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1180 0x0>, + <&apps_smmu 0x11E0 0x0>, + <&apps_smmu 0x11A0 0x0>, + <&apps_smmu 0x1200 0x0>, + <&apps_smmu 0x1260 0x0>, + <&apps_smmu 0x1220 0x0>, + <&apps_smmu 0x1042 0x0>, + <&apps_smmu 0x1300 0x60>, + <&apps_smmu 0x1320 0x60>; + label = "icp"; + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 5MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x500000>; + iova-region-id = <0x0>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "ok"; + }; + + iova-mem-region-secondary-heap { + /* Secondary heap region is 1MB long */ + iova-region-name = "secheap"; + iova-region-start = <0xd800000>; + iova-region-len = <0x100000>; + iova-region-id = <0x4>; + status = "ok"; + }; + + iova-mem-region-io { + /* IO region is approximately 3 GB */ + iova-region-name = "io"; + iova-region-start = <0xda00000>; + iova-region-len = <0xace00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0xd900000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + }; + }; + + msm_cam_smmu_cpas_cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1000 0x0>; + label = "cpas-cdm0"; + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm_cam_smmu_secure { + compatible = "qcom,msm-cam-smmu-cb"; + label = "cam-secure"; + qcom,secure-cb; + }; + + msm_cam_smmu_fd { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x12C0 0x20>, + <&apps_smmu 0x12E0 0x20>; + label = "fd"; + fd_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm_cam_smmu_lrme { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x11C0 0x0>, + <&apps_smmu 0x1240 0x0>; + label = "lrme"; + lrme_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "ok"; + }; + /* IO region is approximately 3.3 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0xd800000>; + iova-region-len = <0xd2800000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc", + "fd", + "lrmecdm"; + status = "ok"; + }; + + qcom,cpas-cdm0@ac48000 { + cell-index = <0>; + compatible = "qcom,cam170-cpas-cdm0"; + label = "cpas-cdm"; + reg = <0xac48000 0x1000>; + reg-names = "cpas-cdm"; + reg-cam-base = <0x48000>; + interrupts = <0 468 0>; + interrupt-names = "cpas-cdm"; + regulator-names = "camss"; + camss-supply = <&titan_top_gdsc>; + clock-names = "cam_cc_cpas_slow_ahb_clk", + "cam_cc_cpas_ahb_clk"; + clocks = <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>; + clock-rates = <0 0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife"; + status = "ok"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + cam_csid0: qcom,csid0@acb3000 { + cell-index = <0>; + compatible = "qcom,csid175"; + reg-names = "csid"; + reg = <0xacb3000 0x1000>; + reg-cam-base = <0xb3000>; + interrupt-names = "csid"; + interrupts = <0 464 0>; + regulator-names = "camss", "ife0"; + camss-supply = <&titan_top_gdsc>; + ife0-supply = <&ife_0_gdsc>; + clock-names = + "ife_csid_clk_src", + "ife_csid_clk", + "cphy_rx_clk_src", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clocks = + <&clock_camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CSID_CLK>, + <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&clock_camcc CAM_CC_IFE_0_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CLK>, + <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; + clock-rates = + <300000000 0 0 0 380000000 0 0>, + <384000000 0 0 0 510000000 0 0>, + <400000000 0 0 0 637000000 0 0>, + <400000000 0 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + clock-control-debugfs = "true"; + status = "ok"; + }; + + cam_vfe0: qcom,vfe0@acaf000 { + cell-index = <0>; + compatible = "qcom,vfe175"; + reg-names = "ife"; + reg = <0xacaf000 0x5200>; + reg-cam-base = <0xaf000>; + interrupt-names = "ife"; + interrupts = <0 465 0>; + regulator-names = "camss", "ife0"; + camss-supply = <&titan_top_gdsc>; + ife0-supply = <&ife_0_gdsc>; + clock-names = + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clocks = + <&clock_camcc CAM_CC_IFE_0_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CLK>, + <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; + clock-rates = + <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&clock_camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <760000000>; + status = "ok"; + }; + + cam_csid1: qcom,csid1@acba000 { + cell-index = <1>; + compatible = "qcom,csid175"; + reg-names = "csid"; + reg = <0xacba000 0x1000>; + reg-cam-base = <0xba000>; + interrupt-names = "csid"; + interrupts = <0 466 0>; + regulator-names = "camss", "ife1"; + camss-supply = <&titan_top_gdsc>; + ife1-supply = <&ife_1_gdsc>; + clock-names = + "ife_csid_clk_src", + "ife_csid_clk", + "cphy_rx_clk_src", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clocks = + <&clock_camcc CAM_CC_IFE_1_CSID_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_1_CSID_CLK>, + <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_1_CPHY_RX_CLK>, + <&clock_camcc CAM_CC_IFE_1_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_1_CLK>, + <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; + clock-rates = + <300000000 0 0 0 380000000 0 0>, + <384000000 0 0 0 510000000 0 0>, + <400000000 0 0 0 637000000 0 0>, + <400000000 0 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + clock-control-debugfs = "true"; + status = "ok"; + }; + + cam_vfe1: qcom,vfe1@acb6000 { + cell-index = <1>; + compatible = "qcom,vfe175"; + reg-names = "ife"; + reg = <0xacb6000 0x5200>; + reg-cam-base = <0xb6000>; + interrupt-names = "ife"; + interrupts = <0 467 0>; + regulator-names = "camss", "ife1"; + camss-supply = <&titan_top_gdsc>; + ife1-supply = <&ife_1_gdsc>; + clock-names = + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clocks = + <&clock_camcc CAM_CC_IFE_1_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_1_CLK>, + <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; + clock-rates = + <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&clock_camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <760000000>; + status = "ok"; + }; + + cam_csid_lite0: qcom,csid-lite0@acc8000 { + cell-index = <2>; + compatible = "qcom,csid-lite175"; + reg-names = "csid-lite"; + reg = <0xacc8000 0x1000>; + reg-cam-base = <0xc8000>; + interrupt-names = "csid-lite"; + interrupts = <0 438 0>; + regulator-names = "camss"; + camss-supply = <&titan_top_gdsc>; + clock-names = + "ife_csid_clk_src", + "ife_csid_clk", + "cphy_rx_clk_src", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk"; + clocks = + <&clock_camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&clock_camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <300000000 0 0 0 320000000 0>, + <384000000 0 0 0 400000000 0>, + <400000000 0 0 0 480000000 0>, + <400000000 0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + clock-control-debugfs = "true"; + status = "ok"; + }; + + cam_vfe_lite0: qcom,vfe-lite0@acc4000 { + cell-index = <2>; + compatible = "qcom,vfe-lite175"; + reg-names = "ife-lite"; + reg = <0xacc4000 0x4000>; + reg-cam-base = <0xc4000>; + interrupt-names = "ife-lite"; + interrupts = <0 434 0>; + regulator-names = "camss"; + camss-supply = <&titan_top_gdsc>; + clock-names = + "ife_clk_src", + "ife_clk"; + clocks = + <&clock_camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <320000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + clock-control-debugfs = "true"; + status = "ok"; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,a5", + "qcom,ipe0", + "qcom,ipe1", + "qcom,bps"; + num-a5 = <1>; + num-ipe = <2>; + num-bps = <1>; + status = "ok"; + }; + + cam_a5: qcom,a5@ac00000 { + cell-index = <0>; + compatible = "qcom,cam-a5"; + reg = <0xac00000 0x6000>, + <0xac10000 0x8000>, + <0xac18000 0x3000>; + reg-names = "a5_qgic", "a5_sierra", "a5_csr"; + reg-cam-base = <0x00000 0x10000 0x18000>; + interrupts = <0 463 0>; + interrupt-names = "a5"; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = + "soc_fast_ahb", + "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clocks = + <&clock_camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&clock_camcc CAM_CC_ICP_AHB_CLK>, + <&clock_camcc CAM_CC_ICP_CLK_SRC>, + <&clock_camcc CAM_CC_ICP_CLK>; + + clock-rates = + <200000000 0 400000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs", "turbo"; + fw_name = "CAMERA_ICP.elf"; + ubwc-cfg = <0x73 0x1CF>; + status = "ok"; + }; + + cam_ipe0: qcom,ipe0 { + cell-index = <0>; + compatible = "qcom,cam-ipe"; + reg = <0xac87000 0x3000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; + regulator-names = "ipe0-vdd"; + ipe0-vdd-supply = <&ipe_0_gdsc>; + clock-names = + "ipe_0_ahb_clk", + "ipe_0_areg_clk", + "ipe_0_axi_clk", + "ipe_0_clk_src", + "ipe_0_clk"; + src-clock-name = "ipe_0_clk_src"; + clock-control-debugfs = "true"; + clocks = + <&clock_camcc CAM_CC_IPE_0_AHB_CLK>, + <&clock_camcc CAM_CC_IPE_0_AREG_CLK>, + <&clock_camcc CAM_CC_IPE_0_AXI_CLK>, + <&clock_camcc CAM_CC_IPE_0_CLK_SRC>, + <&clock_camcc CAM_CC_IPE_0_CLK>; + + clock-rates = + <0 0 0 340000000 0>, + <0 0 0 430000000 0>, + <0 0 0 520000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + status = "ok"; + }; + + cam_ipe1: qcom,ipe1 { + cell-index = <1>; + compatible = "qcom,cam-ipe"; + reg = <0xac91000 0x3000>; + reg-names = "ipe1_top"; + reg-cam-base = <0x91000>; + regulator-names = "ipe1-vdd"; + ipe1-vdd-supply = <&ipe_1_gdsc>; + clock-names = + "ipe_1_ahb_clk", + "ipe_1_areg_clk", + "ipe_1_axi_clk", + "ipe_1_clk_src", + "ipe_1_clk"; + src-clock-name = "ipe_1_clk_src"; + clock-control-debugfs = "true"; + clocks = + <&clock_camcc CAM_CC_IPE_1_AHB_CLK>, + <&clock_camcc CAM_CC_IPE_1_AREG_CLK>, + <&clock_camcc CAM_CC_IPE_1_AXI_CLK>, + <&clock_camcc CAM_CC_IPE_0_CLK_SRC>, + <&clock_camcc CAM_CC_IPE_1_CLK>; + + clock-rates = + <0 0 0 340000000 0>, + <0 0 0 430000000 0>, + <0 0 0 520000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + status = "ok"; + }; + + cam_bps: qcom,bps { + cell-index = <0>; + compatible = "qcom,cam-bps"; + reg = <0xac6f000 0x3000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; + regulator-names = "bps-vdd"; + bps-vdd-supply = <&bps_gdsc>; + clock-names = + "bps_ahb_clk", + "bps_areg_clk", + "bps_axi_clk", + "bps_clk_src", + "bps_clk"; + src-clock-name = "bps_clk_src"; + clock-control-debugfs = "true"; + clocks = + <&clock_camcc CAM_CC_BPS_AHB_CLK>, + <&clock_camcc CAM_CC_BPS_AREG_CLK>, + <&clock_camcc CAM_CC_BPS_AXI_CLK>, + <&clock_camcc CAM_CC_BPS_CLK_SRC>, + <&clock_camcc CAM_CC_BPS_CLK>; + + clock-rates = + <0 0 0 200000000 0>, + <0 0 0 400000000 0>, + <0 0 0 480000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + status = "ok"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "ok"; + }; + + cam_jpeg_enc: qcom,jpegenc@ac4e000 { + cell-index = <0>; + compatible = "qcom,cam_jpeg_enc"; + reg-names = "jpege_hw"; + reg = <0xac4e000 0x4000>; + reg-cam-base = <0x4e000>; + interrupt-names = "jpeg"; + interrupts = <0 474 0>; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = + "jpegenc_clk_src", + "jpegenc_clk"; + clocks = + <&clock_camcc CAM_CC_JPEG_CLK_SRC>, + <&clock_camcc CAM_CC_JPEG_CLK>; + + clock-rates = <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "nominal"; + status = "ok"; + }; + + cam_jpeg_dma: qcom,jpegdma@ac52000{ + cell-index = <0>; + compatible = "qcom,cam_jpeg_dma"; + reg-names = "jpegdma_hw"; + reg = <0xac52000 0x4000>; + reg-cam-base = <0x52000>; + interrupt-names = "jpegdma"; + interrupts = <0 475 0>; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = + "jpegdma_clk_src", + "jpegdma_clk"; + clocks = + <&clock_camcc CAM_CC_JPEG_CLK_SRC>, + <&clock_camcc CAM_CC_JPEG_CLK>; + + clock-rates = <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "nominal"; + status = "ok"; + }; + + qcom,cam-fd { + compatible = "qcom,cam-fd"; + compat-hw-name = "qcom,fd"; + num-fd = <1>; + status = "ok"; + }; + + cam_fd: qcom,fd@ac5a000 { + cell-index = <0>; + compatible = "qcom,fd501"; + reg-names = "fd_core", "fd_wrapper"; + reg = <0xac5a000 0x1000>, + <0xac5b000 0x400>; + reg-cam-base = <0x5a000 0x5b000>; + interrupt-names = "fd"; + interrupts = <0 462 0>; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = + "fd_core_clk_src", + "fd_core_clk", + "fd_core_uar_clk"; + clocks = + <&clock_camcc CAM_CC_FD_CORE_CLK_SRC>, + <&clock_camcc CAM_CC_FD_CORE_CLK>, + <&clock_camcc CAM_CC_FD_CORE_UAR_CLK>; + src-clock-name = "fd_core_clk_src"; + clock-control-debugfs = "true"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + clock-rates = + <380000000 0 0>, + <384000000 0 0>, + <480000000 0 0>, + <600000000 0 0>; + status = "ok"; + }; + + qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + arch-compat = "lrme"; + status = "ok"; + }; + + cam_lrme: qcom,lrme@ac6b000 { + cell-index = <0>; + compatible = "qcom,lrme"; + reg-names = "lrme"; + reg = <0xac6b000 0xa00>; + reg-cam-base = <0x6b000>; + interrupt-names = "lrme"; + interrupts = <0 476 0>; + regulator-names = "camss"; + camss-supply = <&titan_top_gdsc>; + clock-names = + "lrme_clk_src", + "lrme_clk"; + clocks = + <&clock_camcc CAM_CC_LRME_CLK_SRC>, + <&clock_camcc CAM_CC_LRME_CLK>; + clock-rates = + <240000000 0>, + <300000000 0>, + <320000000 0>, + <400000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "lrme_clk_src"; + status = "ok"; + }; + + qcom,cam-cpas@ac40000 { + cell-index = <0>; + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + status = "ok"; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg = <0xac40000 0x1000>, + <0xac42000 0x6000>; + reg-cam-base = <0x40000 0x42000>; + interrupt-names = "cpas_camnoc"; + interrupts = <0 459 0>; + camnoc-axi-min-ib-bw = <3000000000>; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = + "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "slow_ahb_clk_src", + "cpas_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk"; + clocks = + <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_HF_AXI_CLK>, + <&clock_gcc GCC_CAMERA_SF_AXI_CLK>, + <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>; + src-clock-name = "camnoc_axi_clk_src"; + clock-rates = + <0 0 0 0 0 0 0>, + <0 0 0 80000000 0 150000000 0>, + <0 0 0 80000000 0 240000000 0>, + <0 0 0 80000000 0 320000000 0>, + <0 0 0 80000000 0 400000000 0>, + <0 0 0 80000000 0 480000000 0>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <10>; + qcom,msm-bus,name = "cam_ahb"; + qcom,msm-bus,num-cases = <6>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + , + , + , + ; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "suspend", + "minsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = + "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "cci0", "cci1", + "csid0", "csid1", "csid2", "csid3", + "ife0", "ife1", "ife2", "ife3", + "ipe0", "ipe1", "cam-cdm-intf0", "cpas-cdm0", + "bps0", "icp0", "jpeg-dma0", "jpeg-enc0", + "fd0", "lrmecpas0"; + client-axi-port-names = + "cam_hf_1", "cam_hf_2", "cam_hf_1", "cam_hf_2", + "cam_sf_1", "cam_sf_1", + "cam_hf_1", "cam_hf_2", "cam_hf_1", "cam_hf_2", + "cam_hf_1", "cam_hf_2", "cam_hf_1", "cam_hf_2", + "cam_sf_1", "cam_sf_1", "cam_sf_1", "cam_sf_1", + "cam_sf_1", "cam_sf_1", "cam_sf_1", "cam_sf_1", + "cam_sf_1", "cam_sf_1"; + client-bus-camnoc-based; + qcom,axi-port-list { + qcom,axi-port1 { + qcom,axi-port-name = "cam_hf_1"; + qcom,axi-port-mnoc { + qcom,msm-bus,name = "cam_hf_1_mnoc"; + qcom,msm-bus-vector-dyn-vote; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + }; + qcom,axi-port-camnoc { + qcom,msm-bus,name = "cam_hf_1_camnoc"; + qcom,msm-bus-vector-dyn-vote; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + }; + }; + qcom,axi-port2 { + qcom,axi-port-name = "cam_hf_2"; + qcom,axi-port-mnoc { + qcom,msm-bus,name = "cam_hf_2_mnoc"; + qcom,msm-bus-vector-dyn-vote; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + }; + qcom,axi-port-camnoc { + qcom,msm-bus,name = "cam_hf_2_camnoc"; + qcom,msm-bus-vector-dyn-vote; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + }; + }; + qcom,axi-port3 { + qcom,axi-port-name = "cam_sf_1"; + qcom,axi-port-mnoc { + qcom,msm-bus,name = "cam_sf_1_mnoc"; + qcom,msm-bus-vector-dyn-vote; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + }; + qcom,axi-port-camnoc { + qcom,msm-bus,name = "cam_sf_1_camnoc"; + qcom,msm-bus-vector-dyn-vote; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-idp.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-idp.dtsi index 7f465facd2166591b746fb1d4dc73ff0cdfb60a0..1d211d014fbefb01cfd238487447ab27cefc1232 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-idp.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-idp.dtsi @@ -145,3 +145,24 @@ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs"; qcom,platform-reset-gpio = <&pm6150l_gpios 9 0>; }; + +&qupv3_se7_i2c { + status = "ok"; + st_fts@49 { + compatible = "st,fts"; + reg = <0x49>; + interrupt-parent = <&tlmm>; + interrupts = <9 0x2008>; + vdd-supply = <&pm6150_l10>; + avdd-supply = <&pm6150l_l7>; + pinctrl-names = "pmx_ts_active", "pmx_ts_suspend"; + pinctrl-0 = <&ts_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + st,irq-gpio = <&tlmm 9 0x2008>; + st,reset-gpio = <&tlmm 8 0x00>; + st,regulator_dvdd = "vdd"; + st,regulator_avdd = "avdd"; + st,x-flip; + st,y-flip; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi index 11d01c8c0e3a18e6c5cda39349744a689f49536e..fd79e378e2433bdb466e171f2c3df0b7b78e9b3b 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi @@ -867,11 +867,39 @@ }; }; + pmx_sde_te { + sde_te_active: sde_te_active { + mux { + pins = "gpio10"; + function = "mdp_vsync"; + }; + + config { + pins = "gpio10"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + }; + }; + + sde_te_suspend: sde_te_suspend { + mux { + pins = "gpio10"; + function = "mdp_vsync"; + }; + + config { + pins = "gpio10"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + }; + }; + }; + wsa_swr_clk_pin { wsa_swr_clk_sleep: wsa_swr_clk_sleep { mux { pins = "gpio49"; - function = "WSA_CLK"; + function = "wsa_clk"; }; config { @@ -884,7 +912,7 @@ wsa_swr_clk_active: wsa_swr_clk_active { mux { pins = "gpio49"; - function = "WSA_CLK"; + function = "wsa_clk"; }; config { @@ -899,7 +927,7 @@ wsa_swr_data_sleep: wsa_swr_data_sleep { mux { pins = "gpio50"; - function = "WSA_DATA"; + function = "wsa_data"; }; config { @@ -912,7 +940,7 @@ wsa_swr_data_active: wsa_swr_data_active { mux { pins = "gpio50"; - function = "WSA_DATA"; + function = "wsa_data"; }; config { @@ -1016,34 +1044,6 @@ }; }; - pmx_sde_te { - sde_te_active: sde_te_active { - mux { - pins = "gpio10"; - function = "mdp_vsync"; - }; - - config { - pins = "gpio10"; - drive-strength = <2>; /* 2 mA */ - bias-pull-down; /* PULL DOWN */ - }; - }; - - sde_te_suspend: sde_te_suspend { - mux { - pins = "gpio10"; - function = "mdp_vsync"; - }; - - config { - pins = "gpio10"; - drive-strength = <2>; /* 2 mA */ - bias-pull-down; /* PULL DOWN */ - }; - }; - }; - /* SDC pin type */ sdc1_clk_on: sdc1_clk_on { config { @@ -1181,5 +1181,63 @@ bias-disable; }; }; + + pmx_ts_active { + ts_active: ts_active { + mux { + pins = "gpio8", "gpio9"; + function = "gpio"; + }; + + config { + pins = "gpio8", "gpio9"; + drive-strength = <8>; + bias-pull-up; + }; + }; + }; + + pmx_ts_int_suspend { + ts_int_suspend: ts_int_suspend { + mux { + pins = "gpio9"; + function = "gpio"; + }; + + config { + pins = "gpio9"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + + pmx_ts_reset_suspend { + ts_reset_suspend: ts_reset_suspend { + mux { + pins = "gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio8"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + }; +}; + +&pm6150_gpios { + wcd934x_mclk { + wcd934x_mclk_default: wcd934x_mclk_default{ + pins = "gpio8"; + function = "func1"; + qcom,drive-strength = <2>; + power-source = <0>; + bias-disable; + output-low; + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi index 688682d0673843cc1a04d989329770df682158cc..2dc6877e76657c1646fb964ec60942648a1ecb7e 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi @@ -496,6 +496,8 @@ ; qcom,mode-threshold-currents = <0 1>; + pm6150_l17-parent-supply = <&pm6150_l11>; + L17A: pm6150_l17: regulator-pm6150-l17 { regulator-name = "pm6150_l17"; qcom,set = ; @@ -803,8 +805,8 @@ L2F: pm8009_l2: regulator-pm8009-l2 { regulator-name = "pm8009_l2"; qcom,set = ; - regulator-min-microvolt = <1040000>; - regulator-max-microvolt = <1040000>; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; }; }; @@ -872,8 +874,8 @@ L7F: pm8009_l7: regulator-pm8009-l7 { regulator-name = "pm8009_l7"; qcom,set = ; - regulator-min-microvolt = <1696000>; - regulator-max-microvolt = <1696000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-sde-display.dtsi index 95c5842c7643ee9421bedff51fe3a10a292267a3..9b5ab46429fc0244f5eccab6064a54822dfc314c 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-sde-display.dtsi @@ -87,8 +87,8 @@ qcom,panel-supply-entry@1 { reg = <1>; qcom,supply-name = "vdda-3p3"; - qcom,supply-min-voltage = <3008000>; - qcom,supply-max-voltage = <3008000>; + qcom,supply-min-voltage = <3000000>; + qcom,supply-max-voltage = <3000000>; qcom,supply-enable-load = <13200>; qcom,supply-disable-load = <80>; }; @@ -235,6 +235,15 @@ cell-index = <0>; label = "wb_display"; }; + + ext_disp: qcom,msm-ext-disp { + status = "disabled"; + compatible = "qcom,msm-ext-disp"; + + ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx { + compatible = "qcom,msm-ext-disp-audio-codec-rx"; + }; + }; }; &sde_dp { @@ -252,7 +261,7 @@ timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 13 05 04 1F 1E 05 05 03 02 04 00]; - qcom,display-topology = <1 1 1>; + qcom,display-topology = <2 2 1>; qcom,default-topology-index = <0>; }; }; @@ -265,7 +274,7 @@ timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 13 05 04 1F 1E 05 05 03 02 04 00]; - qcom,display-topology = <1 1 1>; + qcom,display-topology = <2 2 1>; qcom,default-topology-index = <0>; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-sde.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-sde.dtsi index d32e93de4aad5631a857a8ccbf7988d355f3a3b5..0e4f3e9bcefc07a507611bdbd5894cd98aab27db 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-sde.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-sde.dtsi @@ -383,9 +383,6 @@ qcom,mdss-rot-danger-lut = <0x0 0x0>; qcom,mdss-rot-safe-lut = <0x0000ffff 0x0000ffff>; - qcom,mdss-rot-qos-cpu-mask = <0xf>; - qcom,mdss-rot-qos-cpu-dma-latency = <75>; - qcom,mdss-default-ot-rd-limit = <32>; qcom,mdss-default-ot-wr-limit = <32>; @@ -442,7 +439,7 @@ qcom,ctrl-supply-entry@0 { reg = <0>; qcom,supply-name = "vdda-1p2"; - qcom,supply-min-voltage = <1232000>; + qcom,supply-min-voltage = <1144000>; qcom,supply-max-voltage = <1232000>; qcom,supply-enable-load = <21800>; qcom,supply-disable-load = <0>; @@ -491,7 +488,7 @@ qcom,ctrl-supply-entry@0 { reg = <0>; qcom,supply-name = "vdda-1p2"; - qcom,supply-min-voltage = <1232000>; + qcom,supply-min-voltage = <1144000>; qcom,supply-max-voltage = <1232000>; qcom,supply-enable-load = <21800>; qcom,supply-disable-load = <0>; @@ -538,7 +535,7 @@ qcom,phy-supply-entry@0 { reg = <0>; qcom,supply-name = "vdda-0p9"; - qcom,supply-min-voltage = <920000>; + qcom,supply-min-voltage = <824000>; qcom,supply-max-voltage = <920000>; qcom,supply-enable-load = <36000>; qcom,supply-disable-load = <0>; @@ -571,7 +568,7 @@ qcom,phy-supply-entry@0 { reg = <0>; qcom,supply-name = "vdda-0p9"; - qcom,supply-min-voltage = <920000>; + qcom,supply-min-voltage = <824000>; qcom,supply-max-voltage = <920000>; qcom,supply-enable-load = <36000>; qcom,supply-disable-load = <0>; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-thermal-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-thermal-overlay.dtsi index fe5a89d4ced9d496674b29b7d9548d9097d70782..f47d16937319f90936558fff5b4e5a3a6c7e578e 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-thermal-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-thermal-overlay.dtsi @@ -176,3 +176,7 @@ }; }; }; + +&mdss_mdp { + #cooling-cells = <2>; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.dtsi index 9a76c596e93ca28aa00de47b7e72bb5a24504d23..558f92e286f4b10825e7e9487aeedeaee209c59f 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.dtsi @@ -30,18 +30,20 @@ /* Clocks */ clock-names = "video_cc_mvsc_ctl_axi", "video_cc_mvs0_ctl_axi", "video_cc_mvs1_ctl_axi", "core_clk", "vcodec_clk", - "cvp_clk"; + "cvp_clk", "iface_clk"; clocks = <&clock_videocc VIDEO_CC_MVSC_CTL_AXI_CLK>, <&clock_videocc VIDEO_CC_MVS0_AXI_CLK>, <&clock_videocc VIDEO_CC_MVS1_AXI_CLK>, <&clock_videocc VIDEO_CC_MVSC_CORE_CLK>, <&clock_videocc VIDEO_CC_MVS0_CORE_CLK>, - <&clock_videocc VIDEO_CC_MVS1_CORE_CLK>; + <&clock_videocc VIDEO_CC_MVS1_CORE_CLK>, + <&clock_videocc VIDEO_CC_VENUS_AHB_CLK>; + qcom,proxy-clock-names = "video_cc_mvsc_ctl_axi", "video_cc_mvs0_ctl_axi", "video_cc_mvs1_ctl_axi", - "core_clk", "vcodec_clk", "cvp_clk"; + "core_clk", "vcodec_clk", "cvp_clk", "iface_clk"; - qcom,clock-configs = <0x0 0x0 0x0 0x1 0x1 0x1>; + qcom,clock-configs = <0x0 0x0 0x0 0x1 0x1 0x1 0x0>; qcom,allowed-clock-rates = <240000000 338000000 365000000 444000000 533000000>; @@ -76,7 +78,7 @@ non_secure_cb { compatible = "qcom,msm-vidc,context-bank"; label = "venus_ns"; - iommus = <&apps_smmu 0x2300 0x60>; + iommus = <&apps_smmu 0x1080 0x60>; buffer-types = <0xfff>; virtual-addr-pool = <0x25800000 0xba800000>; }; @@ -84,7 +86,7 @@ secure_non_pixel_cb { compatible = "qcom,msm-vidc,context-bank"; label = "venus_sec_non_pixel"; - iommus = <&apps_smmu 0x2304 0x60>; + iommus = <&apps_smmu 0x1084 0x60>; buffer-types = <0x480>; virtual-addr-pool = <0x1000000 0x24800000>; qcom,secure-context-bank; @@ -93,7 +95,7 @@ secure_bitstream_cb { compatible = "qcom,msm-vidc,context-bank"; label = "venus_sec_bitstream"; - iommus = <&apps_smmu 0x2301 0x4>; + iommus = <&apps_smmu 0x1081 0x4>; buffer-types = <0x241>; virtual-addr-pool = <0x0 0xe0000000>; qcom,secure-context-bank; @@ -102,7 +104,7 @@ secure_pixel_cb { compatible = "qcom,msm-vidc,context-bank"; label = "venus_sec_pixel"; - iommus = <&apps_smmu 0x2303 0x20>; + iommus = <&apps_smmu 0x1083 0x20>; buffer-types = <0x106>; virtual-addr-pool = <0x0 0xe0000000>; qcom,secure-context-bank; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 76da2075d1b19dbb40e1ec626b4916670f78e5ac..c3ecd422695b5fb6a9c39accee890da90b9efff5 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -46,6 +46,9 @@ sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ sdhc2 = &sdhc_2; /* SDC2 SD Card slot */ ufshc1 = &ufshc_mem; /* Embedded UFS slot */ + swr0 = &swr0; + swr1 = &swr1; + swr2 = &swr2; }; cpus { @@ -871,8 +874,10 @@ <0x18325800 0x1400>; reg-names = "osm_l3_base", "osm_pwrcl_base", "osm_perfcl_base"; + l3-devs = <&cpu0_cpu_l3_lat &cpu6_cpu_l3_lat + &cdsp_cdsp_l3_lat>; + #clock-cells = <1>; - status = "disabled"; }; cpucc_debug: syscon@182a0018 { @@ -975,6 +980,12 @@ clock-frequency = <32768>; }; + aop-msg-client { + compatible = "qcom,debugfs-qmp-client"; + mboxes = <&qmp_aop 0>; + mbox-names = "aop"; + }; + qcom,msm-rtb { compatible = "qcom,msm-rtb"; qcom,rtb-size = <0x100000>; @@ -1887,6 +1898,28 @@ }; }; + sdcc1_ice: sdcc1ice@7C8000 { + compatible = "qcom,ice"; + reg = <0x7C8000 0x8000>; + qcom,enable-ice-clk; + clock-names = "ice_core_clk_src", "ice_core_clk", + "bus_clk", "iface_clk"; + clocks = <&clock_gcc GCC_SDCC1_ICE_CORE_CLK_SRC>, + <&clock_gcc GCC_SDCC1_ICE_CORE_CLK>, + <&clock_gcc GCC_SDCC1_AHB_CLK>, + <&clock_gcc GCC_SDCC1_APPS_CLK>; + qcom,op-freq-hz = <300000000>, <0>, <0>, <0>; + qcom,msm-bus,name = "sdcc_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 757 0 0>, /* No vote */ + <1 757 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "MAX"; + qcom,instance-type = "sdcc"; + }; + sdhc_1: sdhci@7c4000 { compatible = "qcom,sdhci-msm-v5"; reg = <0x7c4000 0x1000>, <0x7c5000 0x1000>; @@ -1895,6 +1928,7 @@ interrupts = , ; interrupt-names = "hc_irq", "pwr_irq"; + sdhc-msm-crypto = <&sdcc1_ice>; qcom,bus-width = <8>; qcom,large-address-bus; @@ -1977,6 +2011,29 @@ clock-names = "iface_clk"; }; + ufs_ice: ufsice@1d90000 { + compatible = "qcom,ice"; + reg = <0x1d90000 0x8000>; + qcom,enable-ice-clk; + clock-names = "ufs_core_clk", "bus_clk", + "iface_clk", "ice_core_clk"; + clocks = <&clock_gcc GCC_UFS_PHY_AXI_CLK>, + <&clock_gcc GCC_UFS_MEM_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_AHB_CLK>, + <&clock_gcc GCC_UFS_PHY_ICE_CORE_CLK>; + qcom,op-freq-hz = <0>, <0>, <0>, <300000000>; + vdd-hba-supply = <&ufs_phy_gdsc>; + qcom,msm-bus,name = "ufs_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 650 0 0>, /* No vote */ + <1 650 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "MAX"; + qcom,instance-type = "ufs"; + }; + ufsphy_mem: ufsphy_mem@1d87000 { reg = <0x1d87000 0xddc>; /* PHY regs */ reg-names = "phy_mem"; @@ -2000,6 +2057,7 @@ interrupts = <0 265 0>; phys = <&ufsphy_mem>; phy-names = "ufsphy"; + ufs-qcom-crypto = <&ufs_ice>; lanes-per-direction = <1>; dev-ref-clk-freq = <0>; /* 19.2 MHz */ @@ -2446,201 +2504,6 @@ }; }; - ipa_smmu_ap: ipa_smmu_ap { - compatible = "qcom,ipa-smmu-ap-cb"; - qcom,smmu-s1-bypass; - iommus = <&apps_smmu 0x520 0x0>; - qcom,iova-mapping = <0x20000000 0x40000000>; - /* modem tables in IMEM */ - qcom,additional-mapping = <0x146bd000 0x146bd000 0x2000>; - }; - - ipa_smmu_wlan: ipa_smmu_wlan { - compatible = "qcom,ipa-smmu-wlan-cb"; - qcom,smmu-s1-bypass; - iommus = <&apps_smmu 0x521 0x0>; - /* ipa-uc ram */ - qcom,additional-mapping = <0x1e60000 0x1e60000 0x80000>; - }; - - ipa_smmu_uc: ipa_smmu_uc { - compatible = "qcom,ipa-smmu-uc-cb"; - qcom,smmu-s1-bypass; - iommus = <&apps_smmu 0x522 0x0>; - qcom,iova-mapping = <0x40400000 0x1fc00000>; - }; - - qcom,ipa_fws { - compatible = "qcom,pil-tz-generic"; - qcom,pas-id = <0xf>; - qcom,firmware-name = "ipa_fws"; - qcom,pil-force-shutdown; - memory-region = <&pil_ipa_fw_mem>; - }; - -}; - -#include "sdmmagpie-pinctrl.dtsi" -#include "sdmmagpie-gdsc.dtsi" -#include "sdmmagpie-bus.dtsi" -#include "sdmmagpie-qupv3.dtsi" -#include "sdmmagpie-vidc.dtsi" -#include "sdmmagpie-sde-pll.dtsi" -#include "sdmmagpie-sde.dtsi" - -&pcie_0_gdsc { - status = "ok"; -}; - -&pcie_tbu_gdsc { - status = "ok"; -}; - -&usb30_prim_gdsc { - status = "ok"; -}; - -&ufs_phy_gdsc { - status = "ok"; -}; - -&hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc { - status = "ok"; -}; - -&hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc { - status = "ok"; -}; - -&hlos1_vote_aggre_noc_mmu_tbu1_gdsc { - status = "ok"; -}; - -&hlos1_vote_aggre_noc_mmu_tbu2_gdsc { - status = "ok"; -}; - -&hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc { - status = "ok"; -}; - -&hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc { - status = "ok"; -}; - -&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc { - status = "ok"; -}; - -&bps_gdsc { - status = "ok"; -}; - -&ife_0_gdsc { - status = "ok"; -}; - -&ife_1_gdsc { - status = "ok"; -}; - -&ipe_0_gdsc { - status = "ok"; -}; - -&ipe_1_gdsc { - status = "ok"; -}; - -&titan_top_gdsc { - status = "ok"; -}; - -&mdss_core_gdsc { - status = "ok"; -}; - -&gpu_cx_gdsc { - parent-supply = <&VDD_CX_LEVEL>; - status = "ok"; -}; - -&gpu_gx_gdsc { - clock-names = "core_root_clk"; - clocks = <&clock_gpucc GPU_CC_GX_GFX3D_CLK_SRC>; - qcom,force-enable-root-clk; - parent-supply = <&VDD_GFX_LEVEL>; - qcom,reset-aon-logic; - status = "ok"; -}; - -&mvsc_gdsc { - clock-names = "ahb_clk"; - clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>; - status = "ok"; -}; - -&mvs0_gdsc { - clock-names = "ahb_clk"; - clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>; - qcom,support-hw-trigger; - status = "ok"; -}; - -&mvs1_gdsc { - clock-names = "ahb_clk"; - clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>; - qcom,support-hw-trigger; - status = "ok"; -}; - -&npu_core_gdsc { - clock-names = "ahb_clk"; - clocks = <&clock_gcc GCC_NPU_CFG_AHB_CLK>; - status = "ok"; -}; - -#include "sdmmagpie-ion.dtsi" -#include "msm-arm-smmu-sdmmagpie.dtsi" -#include "sdmmagpie-pm.dtsi" -#include "pm6150.dtsi" -#include "pm6150l.dtsi" -#include "pm8009.dtsi" -#include "sdmmagpie-regulator.dtsi" -#include "sdmmagpie-coresight.dtsi" -#include "sdmmagpie-usb.dtsi" -#include "sdmmagpie-thermal.dtsi" -#include "sdmmagpie-audio.dtsi" - -&usb0 { - extcon = <&pm6150_pdphy>, <&pm6150_charger>, <&eud>; -}; - -&pm6150_vadc { - rf_pa0_therm { - reg = ; - label = "rf_pa0_therm"; - qcom,ratiometric; - qcom,hw-settle-time = <200>; - qcom,pre-scaling = <1 1>; - }; - - rf_pa1_therm { - reg = ; - label = "rf_pa1_therm"; - qcom,ratiometric; - qcom,hw-settle-time = <200>; - qcom,pre-scaling = <1 1>; - }; - - quiet_therm { - reg = ; - label = "quiet_therm"; - qcom,ratiometric; - qcom,hw-settle-time = <200>; - qcom,pre-scaling = <1 1>; - }; - llcc_pmu: llcc-pmu@90cc000 { compatible = "qcom,qcom-llcc-pmu"; reg = <0x090cc000 0x300>; @@ -2915,6 +2778,219 @@ qcom,target-dev = <&npu_npu_ddr_bw>; qcom,count-unit = <0x10000>; }; + + ipa_smmu_ap: ipa_smmu_ap { + compatible = "qcom,ipa-smmu-ap-cb"; + qcom,smmu-s1-bypass; + iommus = <&apps_smmu 0x520 0x0>; + qcom,iova-mapping = <0x20000000 0x40000000>; + /* modem tables in IMEM */ + qcom,additional-mapping = <0x146bd000 0x146bd000 0x2000>; + }; + + ipa_smmu_wlan: ipa_smmu_wlan { + compatible = "qcom,ipa-smmu-wlan-cb"; + qcom,smmu-s1-bypass; + iommus = <&apps_smmu 0x521 0x0>; + /* ipa-uc ram */ + qcom,additional-mapping = <0x1e60000 0x1e60000 0x80000>; + }; + + ipa_smmu_uc: ipa_smmu_uc { + compatible = "qcom,ipa-smmu-uc-cb"; + qcom,smmu-s1-bypass; + iommus = <&apps_smmu 0x522 0x0>; + qcom,iova-mapping = <0x40400000 0x1fc00000>; + }; + + qcom,ipa_fws { + compatible = "qcom,pil-tz-generic"; + qcom,pas-id = <0xf>; + qcom,firmware-name = "ipa_fws"; + qcom,pil-force-shutdown; + memory-region = <&pil_ipa_fw_mem>; + }; + +}; + +#include "sdmmagpie-gdsc.dtsi" +#include "sdmmagpie-bus.dtsi" +#include "sdmmagpie-qupv3.dtsi" +#include "sdmmagpie-vidc.dtsi" +#include "sdmmagpie-sde-pll.dtsi" +#include "sdmmagpie-sde.dtsi" +#include "sdmmagpie-camera.dtsi" + +&pcie_0_gdsc { + status = "ok"; +}; + +&pcie_tbu_gdsc { + status = "ok"; +}; + +&usb30_prim_gdsc { + status = "ok"; +}; + +&ufs_phy_gdsc { + status = "ok"; +}; + +&hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc { + status = "ok"; +}; + +&hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc { + status = "ok"; +}; + +&hlos1_vote_aggre_noc_mmu_tbu1_gdsc { + status = "ok"; +}; + +&hlos1_vote_aggre_noc_mmu_tbu2_gdsc { + status = "ok"; +}; + +&hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc { + status = "ok"; +}; + +&hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc { + status = "ok"; +}; + +&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc { + status = "ok"; +}; + +&bps_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>; + qcom,support-hw-trigger; + status = "ok"; +}; + +&ife_0_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>; + status = "ok"; +}; + +&ife_1_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>; + status = "ok"; +}; + +&ipe_0_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>; + qcom,support-hw-trigger; + status = "ok"; +}; + +&ipe_1_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>; + qcom,support-hw-trigger; + status = "ok"; +}; + +&titan_top_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>; + status = "ok"; +}; + +&mdss_core_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_DISP_AHB_CLK>; + status = "ok"; +}; + +&gpu_cx_gdsc { + parent-supply = <&VDD_CX_LEVEL>; + status = "ok"; +}; + +&gpu_gx_gdsc { + clock-names = "core_root_clk"; + clocks = <&clock_gpucc GPU_CC_GX_GFX3D_CLK_SRC>; + qcom,force-enable-root-clk; + parent-supply = <&VDD_GFX_LEVEL>; + qcom,reset-aon-logic; + status = "ok"; +}; + +&mvsc_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>; + status = "ok"; +}; + +&mvs0_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>; + qcom,support-hw-trigger; + status = "ok"; +}; + +&mvs1_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_VIDEO_AHB_CLK>; + qcom,support-hw-trigger; + status = "ok"; +}; + +&npu_core_gdsc { + clock-names = "ahb_clk"; + clocks = <&clock_gcc GCC_NPU_CFG_AHB_CLK>; + status = "ok"; +}; + +#include "sdmmagpie-ion.dtsi" +#include "msm-arm-smmu-sdmmagpie.dtsi" +#include "sdmmagpie-pm.dtsi" +#include "pm6150.dtsi" +#include "pm6150l.dtsi" +#include "sdmmagpie-pinctrl.dtsi" +#include "pm8009.dtsi" +#include "sdmmagpie-regulator.dtsi" +#include "sdmmagpie-coresight.dtsi" +#include "sdmmagpie-usb.dtsi" +#include "sdmmagpie-thermal.dtsi" +#include "sdmmagpie-audio.dtsi" + +&usb0 { + extcon = <&pm6150_pdphy>, <&pm6150_charger>, <&eud>; +}; + +&pm6150_vadc { + rf_pa0_therm { + reg = ; + label = "rf_pa0_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + rf_pa1_therm { + reg = ; + label = "rf_pa1_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + quiet_therm { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; }; &pm6150_adc_tm { diff --git a/arch/arm64/boot/dts/qcom/sdx50m-external-soc.dtsi b/arch/arm64/boot/dts/qcom/sdx5xm-external-soc.dtsi similarity index 61% rename from arch/arm64/boot/dts/qcom/sdx50m-external-soc.dtsi rename to arch/arm64/boot/dts/qcom/sdx5xm-external-soc.dtsi index a7752caede0f8b348aab2d4a9516ee3bc4817a3f..0d0af328d7889bb4bbfe3b5ef3312a176a5bf994 100644 --- a/arch/arm64/boot/dts/qcom/sdx50m-external-soc.dtsi +++ b/arch/arm64/boot/dts/qcom/sdx5xm-external-soc.dtsi @@ -12,7 +12,6 @@ &soc { mdm3: qcom,mdm3 { - compatible = "qcom,ext-sdx50m"; cell-index = <0>; #address-cells = <0>; interrupt-parent = <&mdm3>; @@ -32,7 +31,29 @@ qcom,ssctl-instance-id = <0x10>; qcom,support-shutdown; qcom,pil-force-shutdown; + pinctrl-names = "default", "mdm_active", "mdm_suspend"; + pinctrl-0 = <&ap2mdm_pon_reset_default>; + pinctrl-1 = <&ap2mdm_active &mdm2ap_active>; + pinctrl-2 = <&ap2mdm_sleep &mdm2ap_sleep>; + interrupt-map = <0 &tlmm 53 0x3 + 1 &tlmm 135 0x3>; + qcom,mdm2ap-errfatal-gpio = <&tlmm 53 0x00>; + qcom,ap2mdm-errfatal-gpio = <&tlmm 141 0x00>; + qcom,mdm2ap-status-gpio = <&tlmm 142 0x00>; + qcom,ap2mdm-status-gpio = <&tlmm 135 0x00>; + qcom,ap2mdm-soft-reset-gpio = <&pm8150l_gpios 9 0>; qcom,esoc-skip-restart-for-mdm-crash; - status = "disabled"; + status = "ok"; + }; +}; + +&pm8150l_gpios { + ap2mdm_pon_reset { + ap2mdm_pon_reset_default: ap2mdm_pon_reset_default { + /* MDM PON conrol*/ + pins = "gpio9"; + function = "normal"; + power-source = <1>; /* 1.8V */ + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index 8fb9a18219b1e4d240fd88d5759ebed0fc3e8b2d..146f83d0d0a22d2390b11f8eb85a1ff80b70ff3a 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -28,10 +28,22 @@ #size-cells = <1>; ranges; + tz_mem: tz_region@8ff00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x8ff00000 0x100000>; + label = "tz_mem"; + }; + + smem_region: smem_region@8fe40000 { + no-map; + reg = <0x8fe40000 0xc0000>; + }; + peripheral2_mem: peripheral2_region@8fd00000 { compatible = "removed-dma-pool"; no-map; - reg = <0x8fd00000 0x300000>; + reg = <0x8fd00000 0x140000>; label = "peripheral2_mem"; }; @@ -260,6 +272,102 @@ qcom,throughput-threshold = <310 600 1000>; qcom,scaling-exceptions = <>; }; + + tcsr_mutex_block: syscon@1f40000 { + compatible = "syscon"; + reg = <0x1f40000 0x20000>; + }; + + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_block 0 0x1000>; + #hwlock-cells = <1>; + }; + + smem: qcom,smem { + compatible = "qcom,smem"; + memory-region = <&smem_region>; + hwlocks = <&tcsr_mutex 3>; + }; + + apcs_glb: mailbox@0x17811000 { + compatible = "qcom,sdxprairie-apcs-gcc"; + reg = <0x17811000 0xb9>; + #mbox-cells = <1>; + }; + + qcom,glink { + compatible = "qcom,glink"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + glink_modem: modem { + qcom,remote-pid = <1>; + transport = "smem"; + mboxes = <&apcs_glb 12>; + mbox-names = "mpss_smem"; + interrupts = ; + + label = "modem"; + qcom,glink-label = "mpss"; + + qcom,modem_qrtr { + qcom,glink-channels = "IPCRTR"; + qcom,intents = <0x800 5 + 0x2000 3 + 0x4400 2>; + }; + }; + }; + + qcom,glinkpkt { + compatible = "qcom,glinkpkt"; + + qcom,glinkpkt-at-mdm0 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DS"; + qcom,glinkpkt-dev-name = "at_mdm0"; + }; + + qcom,glinkpkt-data40-cntl { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA40_CNTL"; + qcom,glinkpkt-dev-name = "smdcntl8"; + }; + + qcom,glinkpkt-data1 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA1"; + qcom,glinkpkt-dev-name = "smd7"; + }; + + qcom,glinkpkt-data4 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA4"; + qcom,glinkpkt-dev-name = "smd8"; + }; + + qcom,glinkpkt-data11 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA11"; + qcom,glinkpkt-dev-name = "smd11"; + }; + }; + + qmp_aop: qcom,qmp-aop@c300000 { + compatible = "qcom,qmp-mbox"; + reg = <0xc310000 0x1000>, <0x17811008 0x4>; + reg-names = "msgram", "irq-reg-base"; + qcom,irq-mask = <0x1>; + interrupts = ; + + label = "aop"; + qcom,early-boot; + priority = <0>; + mbox-desc-offset = <0x0>; + #mbox-cells = <1>; + }; }; #include "sdxprairie-pinctrl.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.dtsi index 007d7d1a3bab96e2eb0d2fc750d0cec39b3493c8..d8f72d86318b150bcd105f231637d1b02ba14286 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.dtsi @@ -181,8 +181,8 @@ qcom,cdc-static-supplies = "cdc-vdd-ldo-rxtx", "cdc-vddpx-1", - "cdc-vdd-buck", "cdc-vdd-mic-bias"; + qcom,cdc-on-demand-supplies = "cdc-vdd-buck"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sm6150-bus.dtsi b/arch/arm64/boot/dts/qcom/sm6150-bus.dtsi index 06262c3108166c001229a0ed293f5d788b4bc0ba..cc73771442d125f146f49f7293945a70066f3ca8 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-bus.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-bus.dtsi @@ -316,7 +316,6 @@ qcom,qos-off = <4096>; qcom,base-offset = <16384>; qcom,sbm-offset = <0>; - qcom,bypass-qos-prg; qcom,bus-type = <1>; clocks = <>; }; @@ -367,7 +366,6 @@ qcom,qos-off = <128>; qcom,base-offset = <176128>; qcom,sbm-offset = <0>; - qcom,bypass-qos-prg; qcom,bus-type = <1>; clocks = <>; }; @@ -404,7 +402,6 @@ qcom,qos-off = <4096>; qcom,base-offset = <36864>; qcom,sbm-offset = <0>; - qcom,bypass-qos-prg; qcom,bus-type = <1>; clocks = <>; }; @@ -418,7 +415,6 @@ qcom,base-offset = <45056>; qcom,sbm-offset = <0>; qcom,bus-type = <1>; - qcom,bypass-qos-prg; clocks = <>; }; @@ -488,7 +484,7 @@ label = "mas-qhm-qspi"; qcom,buswidth = <4>; qcom,agg-ports = <1>; - qcom,qport = <19>; + qcom,qport = <18>; qcom,connections = <&slv_qns_a1noc_snoc>; qcom,bus-dev = <&fab_aggre1_noc>; qcom,bcms = <&bcm_cn1>; @@ -658,7 +654,7 @@ clocks = <&clock_gcc GCC_AGGRE_USB2_SEC_AXI_CLK>; clock-names = - "clk-usb3-sec-axi-no-rate"; + "clk-aggre-usb2-sec-axi-no-rate"; }; }; @@ -676,7 +672,7 @@ clocks = <&clock_gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>; clock-names = - "clk-usb3-sec-axi-no-rate"; + "clk-aggre-usb3-prim-axi-no-rate"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-idp.dtsi b/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-idp.dtsi index 6896e568e4272ceebdec3840249b9d7f74087127..1301850794aadc94e42679b4a55a7bd92b9b8415 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-idp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-idp.dtsi @@ -109,8 +109,21 @@ rgltr-load-current = <100000>; }; - actuator_front: qcom,actuator@1 { + actuator_rear_aux: qcom,actuator@1 { cell-index = <1>; + reg = <0x0>; + compatible = "qcom,actuator"; + cci-master = <1>; + cam_vaf-supply = <&pm6150_l19>; + regulator-names = "cam_vaf"; + rgltr-cntrl-support; + rgltr-min-voltage = <2800000>; + rgltr-max-voltage = <2800000>; + rgltr-load-current = <100000>; + }; + + actuator_front: qcom,actuator@2 { + cell-index = <2>; reg = <0x1>; compatible = "qcom,actuator"; cci-master = <1>; @@ -300,6 +313,7 @@ sensor-position-pitch = <0>; sensor-position-yaw = <180>; led-flash-src = <&led_flash_rear_aux>; + actuator-src = <&actuator_rear_aux>; eeprom-src = <&eeprom_rear_aux>; cam_vio-supply = <&pm6150_l13>; cam_vana-supply = <&camera_vana1_2_ldo>; @@ -375,4 +389,47 @@ clock-cntl-level = "turbo"; clock-rates = <24000000>; }; + + qcom,cam-sensor@3 { + cell-index = <3>; + compatible = "qcom,cam-sensor"; + reg = <0x3>; + csiphy-sd-index = <2>; + sensor-position-roll = <90>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + led-flash-src = <&led_flash_rear_aux>; + actuator-src = <&actuator_rear_aux>; + eeprom-src = <&eeprom_rear_aux>; + cam_vio-supply = <&pm6150_l13>; + cam_vana-supply = <&camera_vana0_ldo>; + cam_vdig-supply = <&camera_ldo>; + cam_clk-supply = <&titan_top_gdsc>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", + "cam_clk"; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000 2850000 1200000 0>; + rgltr-max-voltage = <1800000 2850000 1200000 0>; + rgltr-load-current = <105000 0 80000 0>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_rear2_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_rear2_suspend>; + gpios = <&tlmm 29 0>, + <&tlmm 45 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "turbo"; + clock-rates = <24000000>; + }; }; diff --git a/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-qrd.dtsi index 214e7ea2bcf32770ac28a386c68247716b63e91e..c3b5b219a6159ef5dd6a47bd3f67452857b771d1 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-camera-sensor-qrd.dtsi @@ -193,6 +193,7 @@ sensor-mode = <0>; cci-master = <0>; status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK1_CLK>; clock-names = "cam_clk"; clock-cntl-level = "turbo"; clock-rates = <24000000>; diff --git a/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi b/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi index 70a0a54950acfe5920b5d10eaf7885743840f53e..03164db8ca8eb5ee031f1014c9324b2e465d060d 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi @@ -46,8 +46,9 @@ "csi0phytimer_clk_src", "csi0phytimer_clk"; src-clock-name = "csi0phytimer_clk_src"; - clock-cntl-level = "turbo"; + clock-cntl-level = "svs_l1", "turbo"; clock-rates = + <0 0 0 0 269333333 0 269333333 0>, <0 0 0 0 384000000 0 269333333 0>; status = "ok"; }; @@ -81,8 +82,9 @@ "csi1phytimer_clk_src", "csi1phytimer_clk"; src-clock-name = "csi1phytimer_clk_src"; - clock-cntl-level = "turbo"; + clock-cntl-level = "svs_l1", "turbo"; clock-rates = + <0 0 0 0 269333333 0 269333333 0>, <0 0 0 0 384000000 0 269333333 0>; status = "ok"; @@ -117,8 +119,9 @@ "csi2phytimer_clk_src", "csi2phytimer_clk"; src-clock-name = "csi2phytimer_clk_src"; - clock-cntl-level = "turbo"; + clock-cntl-level = "svs_l1", "turbo"; clock-rates = + <0 0 0 0 269333333 0 269333333 0>, <0 0 0 0 384000000 0 269333333 0>; status = "ok"; }; @@ -891,6 +894,9 @@ cam_ipe0: qcom,ipe0 { cell-index = <0>; compatible = "qcom,cam-ipe"; + reg = <0xac87000 0x3000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; regulator-names = "ipe0-vdd"; ipe0-vdd-supply = <&ipe_0_gdsc>; clock-names = "ipe_0_ahb_clk", @@ -919,6 +925,9 @@ cam_bps: qcom,bps { cell-index = <0>; compatible = "qcom,cam-bps"; + reg = <0xac6f000 0x3000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; regulator-names = "bps-vdd"; bps-vdd-supply = <&bps_gdsc>; clock-names = "bps_ahb_clk", diff --git a/arch/arm64/boot/dts/qcom/sm6150-coresight.dtsi b/arch/arm64/boot/dts/qcom/sm6150-coresight.dtsi index 76312ea936ce4d5fface212e936fef0f0917ba82..49e99bfdee8a13925ee3fda18b6f120a4307c997 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-coresight.dtsi @@ -910,6 +910,7 @@ coresight-name = "coresight-tpdm-dcc"; + status = "disabled"; clocks = <&clock_aop QDSS_CLK>; clock-names = "apb_pclk"; diff --git a/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi b/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi index 3b6a61be4fabcfe41bc165dd58e692bf19a59faa..a9010fdb6b0db1296f1345e7fda8ace74cae5583 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi @@ -45,6 +45,15 @@ qcom,ion-heap-type = "HYP_CMA"; }; + qcom,ion-heap@14 { /* SECURE CARVEOUT HEAP */ + reg = <14>; + qcom,ion-heap-type = "SECURE_CARVEOUT"; + cdsp { + memory-region = <&cdsp_sec_mem>; + token = <0x20000000>; + }; + }; + qcom,ion-heap@9 { reg = <9>; qcom,ion-heap-type = "SYSTEM_SECURE"; diff --git a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi index 2b30158946bf74db68bb450f32a068e5054715e9..f7009460f6e185bd3d131036a465087421dd36f5 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi @@ -1082,6 +1082,47 @@ }; }; + pcie0 { + pcie0_clkreq_default: pcie0_clkreq_default { + mux { + pins = "gpio90"; + function = "pcie_clk"; + }; + + config { + pins = "gpio90"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie0_perst_default: pcie0_perst_default { + mux { + pins = "gpio101"; + function = "gpio"; + }; + + config { + pins = "gpio101"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + pcie0_wake_default: pcie0_wake_default { + mux { + pins = "gpio100"; + function = "gpio"; + }; + + config { + pins = "gpio100"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + pmx_ts_int_active { ts_int_active: ts_int_active { mux { diff --git a/arch/arm64/boot/dts/qcom/sm6150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm6150-qrd.dtsi index 6efcdcface298dfd75baffa2f1d785e2af379bfa..ef0ee2f73a7f3bd01593a2b4bb9026d62db63bf4 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-qrd.dtsi @@ -116,7 +116,6 @@ "die_temp", "conn_temp"; qcom,battery-data = <&mtp_batterydata>; - qcom,step-charging-enable; qcom,sw-jeita-enable; qcom,fcc-stepping-enable; qcom,sec-charger-config = <1>; diff --git a/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi b/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi index 6772c26d76899e038e99a35b8662006137e419bd..2d8e42ddc2a175782fbca055c6f7590d0da8c610 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi @@ -171,8 +171,10 @@ /* Primary USB port related QMP USB PHY */ usb_qmp_phy: ssphy@88e6000 { compatible = "qcom,usb-ssphy-qmp-usb3-or-dp"; - reg = <0x88e6000 0x1000>; - reg-names = "qmp_phy_base"; + reg = <0x88e6000 0x1000>, + <0x01fcb244 0x4>; + reg-names = "qmp_phy_base", + "vls_clamp_reg"; vdd-supply = <&pm6150_l4>; core-supply = <&pm6150_l11>; diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index 0178d0926f9292ed523f7ffe52acda8dcaf093ae..f19172b8142d2746a04e96300569607f8a8caba1 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -511,7 +511,7 @@ xbl_aop_mem: xbl_aop_mem@85e00000 { compatible = "removed-dma-pool"; no-map; - reg = <0x0 0x85e00000 0x0 0x1ff000>; + reg = <0x0 0x85e00000 0x0 0x140000>; }; sec_apps_mem: sec_apps_region@85fff000 { @@ -559,31 +559,31 @@ pil_cdsp_mem: cdsp_regions@93400000 { compatible = "removed-dma-pool"; no-map; - reg = <0 0x93400000 0 0x800000>; + reg = <0 0x93400000 0 0x1e00000>; }; - pil_adsp_mem: pil_adsp_region@93c00000 { + pil_adsp_mem: pil_adsp_region@95200000 { compatible = "removed-dma-pool"; no-map; - reg = <0 0x93c00000 0 0x1e00000>; + reg = <0 0x95200000 0 0x1e00000>; }; - pil_ipa_fw_mem: ips_fw_region@0x95a00000 { + pil_ipa_fw_mem: ips_fw_region@0x97000000 { compatible = "removed-dma-pool"; no-map; - reg = <0 0x95a00000 0 0x10000>; + reg = <0 0x97000000 0 0x10000>; }; - pil_ipa_gsi_mem: ipa_gsi_region@0x95a10000 { + pil_ipa_gsi_mem: ipa_gsi_region@0x97010000 { compatible = "removed-dma-pool"; no-map; - reg = <0 0x95a10000 0 0x5000>; + reg = <0 0x97010000 0 0x5000>; }; - pil_gpu_mem: gpu_region@0x95a15000 { + pil_gpu_mem: gpu_region@0x97015000 { compatible = "removed-dma-pool"; no-map; - reg = <0 0x95a15000 0 0x2000>; + reg = <0 0x97015000 0 0x2000>; }; qseecom_mem: qseecom_region@0x9e400000 { @@ -592,6 +592,12 @@ reg = <0 0x9e400000 0 0x1400000>; }; + cdsp_sec_mem: cdsp_sec_regions@0x9f800000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x9f800000 0x0 0xc00000>; + }; + adsp_mem: adsp_region { compatible = "shared-dma-pool"; alloc-ranges = <0 0x00000000 0 0xffffffff>; @@ -1702,6 +1708,10 @@ <&apps_smmu 0x0116 0x0011>; }; + qcom_msmhdcp: qcom,msm_hdcp { + compatible = "qcom,msm-hdcp"; + }; + qcom_crypto: qcrypto@1de0000 { compatible = "qcom,qcrypto"; reg = <0x1de0000 0x20000>, @@ -2057,6 +2067,23 @@ qcom,intents = <0x64 64>; }; + qcom,msm_cdsprm_rpmsg { + compatible = "qcom,msm-cdsprm-rpmsg"; + qcom,glink-channels = "cdsprmglink-apps-dsp"; + qcom,intents = <0x20 12>; + + qcom,cdsp-cdsp-l3-gov { + compatible = "qcom,cdsp-l3"; + qcom,target-dev = <&cdsp_cdsp_l3_lat>; + }; + + qcom,msm_cdsp_rm { + compatible = "qcom,msm-cdsp-rm"; + qcom,qos-latency-us = <44>; + qcom,qos-maxhold-ms = <20>; + }; + }; + qcom,cdsp_glink_ssr { qcom,glink-channels = "glink_ssr"; qcom,notify-edges = <&glink_modem>, @@ -3068,6 +3095,7 @@ }; &bps_gdsc { + qcom,support-hw-trigger; status = "ok"; }; @@ -3080,6 +3108,7 @@ }; &ipe_0_gdsc { + qcom,support-hw-trigger; status = "ok"; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-adp-star.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..9bac609b3b04157a7d589a17cb6b925eb52f4029 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-adp-star.dtsi @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018, 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. + */ + +&cam_cci0 { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + }; + + qcom,cam-sensor@0 { + cell-index = <0>; + compatible = "qcom,cam-sensor"; + reg = <0x0>; + csiphy-sd-index = <0>; + sensor-position-roll = <90>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&pm8150_1_s4>; + cam_bob-supply = <&pm8150_1_s4>; + cam_vana-supply = <&pm8150_1_s4>; + cam_vdig-supply = <&pm8150_1_s4>; + cam_clk-supply = <&titan_top_gdsc>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", + "cam_clk", "cam_bob"; + gpios = <&tlmm 13 0>, + <&tlmm 21 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0"; + sensor-mode = <0>; + cci-master = <0>; + status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "turbo"; + clock-rates = <24000000>; + }; + + qcom,cam-sensor@1 { + cell-index = <1>; + compatible = "qcom,cam-sensor"; + reg = <0x1>; + csiphy-sd-index = <1>; + sensor-position-roll = <90>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_bob-supply = <&pm8150_1_s4>; + cam_vdig-supply = <&pm8150_1_s4>; + cam_vio-supply = <&pm8150_1_s4>; + cam_vana-supply = <&pm8150_1_s4>; + cam_clk-supply = <&titan_top_gdsc>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", + "cam_clk", "cam_bob"; + gpios = <&tlmm 14 0>, + <&tlmm 22 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + sensor-mode = <0>; + cci-master = <0>; + status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "turbo"; + clock-rates = <24000000>; + }; + + qcom,cam-sensor@2 { + cell-index = <2>; + compatible = "qcom,cam-sensor"; + reg = <0x02>; + csiphy-sd-index = <2>; + sensor-position-roll = <90>; + sensor-position-pitch = <0>; + sensor-position-yaw = <0>; + cam_vio-supply = <&pm8150_1_s4>; + cam_bob-supply = <&pm8150_1_s4>; + cam_vana-supply = <&pm8150_1_s4>; + cam_vdig-supply = <&pm8150_1_s4>; + cam_clk-supply = <&titan_top_gdsc>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", + "cam_clk", "cam_bob"; + gpios = <&tlmm 15 0>, + <&tlmm 23 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "turbo"; + clock-rates = <24000000>; + }; + + qcom,cam-sensor@3 { + cell-index = <3>; + compatible = "qcom,cam-sensor"; + reg = <0x03>; + csiphy-sd-index = <3>; + sensor-position-roll = <270>; + sensor-position-pitch = <0>; + sensor-position-yaw = <0>; + cam_vio-supply = <&pm8150_1_s4>; + cam_bob-supply = <&pm8150_1_s4>; + cam_vana-supply = <&pm8150_1_s4>; + cam_vdig-supply = <&pm8150_1_s4>; + cam_clk-supply = <&titan_top_gdsc>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", + "cam_clk", "cam_bob"; + gpios = <&tlmm 16 0>, + <&tlmm 25 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "turbo"; + clock-rates = <24000000>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi index 42bf4d5e2c1b6db4df630bbcfef055328e003ca4..a42309e733a29a972f5bf87b60023f93b79d27b4 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi @@ -395,7 +395,7 @@ <&tlmm 26 0>; gpio-reset = <1>; gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 1>; + gpio-req-tbl-flags = <1 0 0>; gpio-req-tbl-label = "CAMIF_MCLK3", "CAM_RESET3", "IMG_START"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi b/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi index 4797ab43589792b4f906986e12e630a216344b74..aefe1cb43d3ea7dae7bf94f80a9ba538345aded8 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi @@ -733,10 +733,11 @@ <&clock_camcc CAM_CC_IFE_0_CLK>, <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; clock-rates = + <400000000 0 0 0 400000000 0 0>, <400000000 0 0 0 558000000 0 0>, <480000000 0 0 0 637000000 0 0>, <600000000 0 0 0 760000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; clock-control-debugfs = "true"; status = "ok"; @@ -745,9 +746,10 @@ cam_vfe0: qcom,vfe0@acaf000 { cell-index = <0>; compatible = "qcom,vfe175"; - reg-names = "ife"; - reg = <0xacaf000 0x4000>; - reg-cam-base = <0xaf000>; + reg-names = "ife", "cam_camnoc"; + reg = <0xacaf000 0x4000>, + <0xac42000 0x5000>; + reg-cam-base = <0xaf000 0x42000>; interrupt-names = "ife"; interrupts = <0 465 0>; regulator-names = "camss", "ife0"; @@ -762,10 +764,11 @@ <&clock_camcc CAM_CC_IFE_0_CLK>, <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; clock-rates = + <400000000 0 0>, <558000000 0 0>, <637000000 0 0>, <760000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_clk_src"; clock-control-debugfs = "true"; clock-names-option = "ife_dsp_clk"; @@ -802,10 +805,11 @@ <&clock_camcc CAM_CC_IFE_1_CLK>, <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; clock-rates = + <400000000 0 0 0 400000000 0 0>, <400000000 0 0 0 558000000 0 0>, <480000000 0 0 0 637000000 0 0>, <600000000 0 0 0 760000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; clock-control-debugfs = "true"; status = "ok"; @@ -814,9 +818,10 @@ cam_vfe1: qcom,vfe1@acb6000 { cell-index = <1>; compatible = "qcom,vfe175"; - reg-names = "ife"; - reg = <0xacb6000 0x4000>; - reg-cam-base = <0xb6000>; + reg-names = "ife", "cam_camnoc"; + reg = <0xacb6000 0x4000>, + <0xac42000 0x5000>; + reg-cam-base = <0xb6000 0x42000>; interrupt-names = "ife"; interrupts = <0 467 0>; regulator-names = "camss", "ife1"; @@ -831,10 +836,11 @@ <&clock_camcc CAM_CC_IFE_1_CLK>, <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; clock-rates = + <400000000 0 0>, <558000000 0 0>, <637000000 0 0>, <760000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_clk_src"; clock-control-debugfs = "true"; clock-names-option = "ife_dsp_clk"; @@ -868,10 +874,11 @@ <&clock_camcc CAM_CC_IFE_LITE_0_CLK_SRC>, <&clock_camcc CAM_CC_IFE_LITE_0_CLK>; clock-rates = + <400000000 0 0 0 320000000 0>, <400000000 0 0 0 400000000 0>, <480000000 0 0 0 480000000 0>, <600000000 0 0 0 600000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; clock-control-debugfs = "true"; status = "ok"; @@ -894,10 +901,11 @@ <&clock_camcc CAM_CC_IFE_LITE_0_CLK_SRC>, <&clock_camcc CAM_CC_IFE_LITE_0_CLK>; clock-rates = + <320000000 0>, <400000000 0>, <480000000 0>, <600000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_clk_src"; clock-control-debugfs = "true"; status = "ok"; @@ -928,10 +936,11 @@ <&clock_camcc CAM_CC_IFE_LITE_1_CLK_SRC>, <&clock_camcc CAM_CC_IFE_LITE_1_CLK>; clock-rates = + <400000000 0 0 0 320000000 0>, <400000000 0 0 0 400000000 0>, <480000000 0 0 0 480000000 0>, <600000000 0 0 0 600000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; clock-control-debugfs = "true"; status = "ok"; @@ -954,10 +963,11 @@ <&clock_camcc CAM_CC_IFE_LITE_1_CLK_SRC>, <&clock_camcc CAM_CC_IFE_LITE_1_CLK>; clock-rates = + <320000000 0>, <400000000 0>, <480000000 0>, <600000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; src-clock-name = "ife_clk_src"; clock-control-debugfs = "true"; status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index 2f7244fe585dc0f8dcf041ce971368c862e27f81..49372b527452e2adefa319c6a50371b26eaf4791 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -305,6 +305,7 @@ qcom,battery-data = <&mtp_batterydata>; qcom,hold-soc-while-full; qcom,linearize-soc; + qcom,five-pin-battery; /* ESR fast calibration */ qcom,fg-esr-timer-chg-fast = <0 7>; qcom,fg-esr-timer-dischg-fast = <0 7>; @@ -615,12 +616,12 @@ &pm8150b_charger { qcom,sec-charger-config = <3>; qcom,auto-recharge-soc = <98>; - io-channels = <&pm8150b_vadc ADC_USB_IN_V_16>, + io-channels = <&pm8150b_vadc ADC_MID_CHG_DIV6>, <&pm8150b_vadc ADC_USB_IN_I>, <&pm8150b_vadc ADC_SBUx>, <&pm8150b_vadc ADC_VPH_PWR>, <&pm8150b_vadc ADC_CHG_TEMP>; - io-channel-names = "usb_in_voltage", + io-channel-names = "mid_voltage", "usb_in_current", "sbux_res", "vph_voltage", diff --git a/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi index 40b8621dcc200b15b5c6b036849a984315892337..7f6e1623ff11aca2aea77b86af65d20417513634 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi @@ -104,3 +104,7 @@ &usb0 { extcon = <&pm8150b_pdphy>, <&eud>; }; + +&usb_qmp_dp_phy { + extcon = <&pm8150b_pdphy>; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index cc4217d391633f009c94206b950913de3ea33519..76dd5f9d644fb9f1c68cff491584b65cf1349bc6 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -49,6 +49,7 @@ qcom,battery-data = <&qrd_batterydata>; qcom,hold-soc-while-full; qcom,linearize-soc; + qcom,five-pin-battery; /* ESR fast calibration */ qcom,fg-esr-timer-chg-fast = <0 7>; qcom,fg-esr-timer-dischg-fast = <0 7>; @@ -563,12 +564,12 @@ &pm8150b_charger { qcom,sec-charger-config = <1>; qcom,auto-recharge-soc = <98>; - io-channels = <&pm8150b_vadc ADC_USB_IN_V_16>, + io-channels = <&pm8150b_vadc ADC_MID_CHG_DIV6>, <&pm8150b_vadc ADC_USB_IN_I>, <&pm8150b_vadc ADC_SBUx>, <&pm8150b_vadc ADC_VPH_PWR>, <&pm8150b_vadc ADC_CHG_TEMP>; - io-channel-names = "usb_in_voltage", + io-channel-names = "mid_voltage", "usb_in_current", "sbux_res", "vph_voltage", diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-cdp-overlay.dts index defed2390aae3b4b40afd07317a60db2538c33d2..5a76be032547e2ab095b816682065d8c5c81425c 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-cdp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-cdp-overlay.dts @@ -20,7 +20,7 @@ #include "sm8150-cdp.dtsi" -#include "sdx50m-external-soc.dtsi" +#include "sdx5xm-external-soc.dtsi" #include "sm8150-sdx50m.dtsi" #include "sm8150-cdp-audio-overlay.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts index 9f6e83451448a31903b3b3b187f9e73c52eced2a..0b6ea10948b27c7596ed3a10e054201d7af3a583 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts @@ -20,7 +20,7 @@ #include "sm8150-mtp.dtsi" -#include "sdx50m-external-soc.dtsi" +#include "sdx5xm-external-soc.dtsi" #include "sm8150-sdx50m.dtsi" #include "sm8150-mtp-audio-overlay.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts index 3270a735a803f76b454931da15d27ccde9cd20fc..fb74f162754f93c1e76e1f3e6e4a7e28932f2b07 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts @@ -20,7 +20,7 @@ #include "sm8150-mtp.dtsi" -#include "sdx50m-external-soc.dtsi" +#include "sdx5xm-external-soc.dtsi" #include "sm8150-sdx50m.dtsi" #include "sm8150-mtp-audio-overlay.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd-overlay.dts index 8d384978ba3a081832593f43e3fe4ddc88608b2d..24591dc16cea639d7660c1d04a0c3c9f3b4c4df6 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd-overlay.dts @@ -20,7 +20,7 @@ #include "sm8150-qrd.dtsi" -#include "sdx50m-external-soc.dtsi" +#include "sdx5xm-external-soc.dtsi" #include "sm8150-sdx50m.dtsi" #include "sm8150-sdx50m-audio-overlay.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi index 10f831205a19e7adc05773943c91a6b5a57eeb8d..f94c3a39b8c7a3d4636125b652371ede35882def 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi @@ -11,31 +11,8 @@ */ &mdm3 { - pinctrl-names = "default", "mdm_active", "mdm_suspend"; - pinctrl-0 = <&ap2mdm_pon_reset_default>; - pinctrl-1 = <&ap2mdm_active &mdm2ap_active>; - pinctrl-2 = <&ap2mdm_sleep &mdm2ap_sleep>; - interrupt-map = <0 &tlmm 53 0x3 - 1 &tlmm 135 0x3>; - qcom,mdm2ap-errfatal-gpio = <&tlmm 53 0x00>; - qcom,ap2mdm-errfatal-gpio = <&tlmm 141 0x00>; - qcom,mdm2ap-status-gpio = <&tlmm 142 0x00>; - qcom,ap2mdm-status-gpio = <&tlmm 135 0x00>; - qcom,ap2mdm-soft-reset-gpio = <&pm8150l_gpios 9 0>; + compatible = "qcom,ext-sdx50m"; qcom,mdm-link-info = "0305_01.01.00"; - qcom,esoc-skip-restart-for-mdm-crash; - status = "ok"; -}; - -&pm8150l_gpios { - ap2mdm_pon_reset { - ap2mdm_pon_reset_default: ap2mdm_pon_reset_default { - /* MDM PON conrol*/ - pins = "gpio9"; - function = "normal"; - power-source = <1>; /* 1.8V */ - }; - }; }; &wil6210 { diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdxprairie-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie-cdp-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..75b3fca5e9bd6202d3c906c116174becdba6a826 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie-cdp-overlay.dts @@ -0,0 +1,31 @@ +/* Copyright (c) 2018, 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/; +/plugin/; + +#include +#include +#include +#include + +#include "sm8150-cdp.dtsi" + +#include "sdx5xm-external-soc.dtsi" +#include "sm8150-sdxprairie.dtsi" +#include "sm8150-cdp-audio-overlay.dtsi" + +/ { + model = "SDXPRAIRIE CDP"; + compatible = "qcom,sm8150-cdp", "qcom,sm8150", "qcom,cdp"; + qcom,board-id = <1 3>; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdxprairie-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie-mtp-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..c70c4a92fe906569943deb746214db581744c475 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie-mtp-overlay.dts @@ -0,0 +1,31 @@ +/* Copyright (c) 2018, 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/; +/plugin/; + +#include +#include +#include +#include + +#include "sm8150-mtp.dtsi" + +#include "sdx5xm-external-soc.dtsi" +#include "sm8150-sdxprairie.dtsi" +#include "sm8150-mtp-audio-overlay.dtsi" + +/ { + model = "SDXPRAIRIE MTP"; + compatible = "qcom,sm8150-mtp", "qcom,sm8150", "qcom,mtp"; + qcom,board-id = <8 3>; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..f48bdb56af96feb95bcbff4d67d6c619dbb23dfa --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie.dtsi @@ -0,0 +1,17 @@ +/* Copyright (c) 2018, 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. + */ + +&mdm3 { + compatible = "qcom,ext-sdxprairie"; + qcom,mdm-link-info = "0306_01.01.00"; +}; + diff --git a/arch/arm64/boot/dts/qcom/sm8150-thermal.dtsi b/arch/arm64/boot/dts/qcom/sm8150-thermal.dtsi index 456ff38abd06f3b2b73873ae4923e5c12dde8c92..dddb1a95c555bbebbc900557baa8388d1e6cb0bf 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-thermal.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-thermal.dtsi @@ -493,1378 +493,14 @@ }; }; - aoss0-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-governor = "low_limits_floor"; - thermal-sensors = <&tsens0 0>; - tracks-low; - trips { - aoss0_trip: aoss0-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&aoss0_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&aoss0_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&aoss0_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-0-0-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-governor = "low_limits_floor"; - thermal-sensors = <&tsens0 1>; - tracks-low; - trips { - cpu00_trip: cpu00-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu00_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu00_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu00_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-0-1-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-governor = "low_limits_floor"; - thermal-sensors = <&tsens0 2>; - tracks-low; - trips { - cpu01_trip: cpu01-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu01_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu01_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu01_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-0-2-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-governor = "low_limits_floor"; - thermal-sensors = <&tsens0 3>; - tracks-low; - trips { - cpu02_trip: cpu02-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu02_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu02_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu02_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-0-3-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 4>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu03_trip: cpu03-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu03_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu03_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu03_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpuss-0-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 5>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpuss0_trip: cpuss0-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpuss0_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpuss-1-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 6>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpuss1_trip: cpuss1-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpuss1_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-0-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 7>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu10_trip: cpu10-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu10_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu10_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu10_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-1-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 8>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu11_trip: cpu11-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu11_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu11_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu11_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-2-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 9>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu12_trip: cpu12-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu12_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu12_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu12_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-3-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 10>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu13_trip: cpu13-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu13_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu13_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu13_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-4-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 11>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu14_trip: cpu14-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu14_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu14_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu14_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-5-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 12>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu15_trip: cpu15-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu15_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu15_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu15_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-6-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 13>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu16_trip: cpu16-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu16_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu16_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu16_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cpu-1-7-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 14>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cpu17_trip: cpu17-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cpu17_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cpu17_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cpu17_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - gpuss-0-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens0 15>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - gpuss0_trip: gpuss0-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&gpuss0_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - aoss-1-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens1 0>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - aoss1_trip: aoss1-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&aoss1_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&aoss1_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&aoss1_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cwlan-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens1 1>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - cwlan_trip: cwlan-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&cwlan_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&cwlan_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&cwlan_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - video-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens1 2>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - video_trip: video-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&video_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&video_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&video_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - ddr-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens1 3>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - ddr_trip: ddr-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&ddr_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&ddr_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&ddr_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - q6-hvx-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens1 4>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - q6_trip: q6-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&q6_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&q6_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&q6_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - camera-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&tsens1 5>; - thermal-governor = "low_limits_floor"; - tracks-low; - trips { - camera_trip: camera-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&camera_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&camera_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&camera_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - - cmpss-lowf { + cpu-1-4-lowf { polling-delay-passive = <0>; polling-delay = <0>; - thermal-sensors = <&tsens1 6>; + thermal-sensors = <&tsens0 11>; thermal-governor = "low_limits_floor"; tracks-low; trips { - cmpss_trip: cmpss-trip { + cpu14_trip: cpu14-trip { temperature = <5000>; hysteresis = <5000>; type = "passive"; @@ -1872,61 +508,61 @@ }; cooling-maps { cpu0_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&CPU0 1 1>; }; cpu1_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&CPU4 5 5>; }; cx_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&cx_cdev 0 0>; }; mx_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&mx_cdev 0 0>; }; ebi_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&ebi_cdev 0 0>; }; mmcx_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&mm_cx_cdev 0 0>; }; modem_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&modem_vdd 0 0>; }; adsp_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&adsp_vdd 0 0>; }; cdsp_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&cdsp_vdd 0 0>; }; slpi_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&slpi_vdd 0 0>; }; gpu_vdd_cdev { - trip = <&cmpss_trip>; + trip = <&cpu14_trip>; cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) (THERMAL_MAX_LIMIT-2)>; }; }; }; - mdm-core-lowf { + cpu-1-7-lowf { polling-delay-passive = <0>; polling-delay = <0>; - thermal-sensors = <&tsens1 7>; + thermal-sensors = <&tsens0 14>; thermal-governor = "low_limits_floor"; tracks-low; trips { - mdm_trip: mdm-trip { + cpu17_trip: cpu17-trip { temperature = <5000>; hysteresis = <5000>; type = "passive"; @@ -1934,61 +570,61 @@ }; cooling-maps { cpu0_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&CPU0 1 1>; }; cpu1_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&CPU4 5 5>; }; cx_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&cx_cdev 0 0>; }; mx_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&mx_cdev 0 0>; }; ebi_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&ebi_cdev 0 0>; }; mmcx_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&mm_cx_cdev 0 0>; }; modem_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&modem_vdd 0 0>; }; adsp_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&adsp_vdd 0 0>; }; cdsp_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&cdsp_vdd 0 0>; }; slpi_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&slpi_vdd 0 0>; }; gpu_vdd_cdev { - trip = <&mdm_trip>; + trip = <&cpu17_trip>; cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) (THERMAL_MAX_LIMIT-2)>; }; }; }; - npu-lowf { + gpuss-0-lowf { polling-delay-passive = <0>; polling-delay = <0>; - thermal-sensors = <&tsens1 8>; + thermal-sensors = <&tsens0 15>; thermal-governor = "low_limits_floor"; tracks-low; trips { - npu_trip: npu-trip { + gpuss0_trip: gpuss0-trip { temperature = <5000>; hysteresis = <5000>; type = "passive"; @@ -1996,61 +632,61 @@ }; cooling-maps { cpu0_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&CPU0 1 1>; }; cpu1_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&CPU4 5 5>; }; cx_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&cx_cdev 0 0>; }; mx_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&mx_cdev 0 0>; }; ebi_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&ebi_cdev 0 0>; }; mmcx_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&mm_cx_cdev 0 0>; }; modem_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&modem_vdd 0 0>; }; adsp_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&adsp_vdd 0 0>; }; cdsp_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&cdsp_vdd 0 0>; }; slpi_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&slpi_vdd 0 0>; }; gpu_vdd_cdev { - trip = <&npu_trip>; + trip = <&gpuss0_trip>; cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) (THERMAL_MAX_LIMIT-2)>; }; }; }; - mdm-vec-lowf { + camera-lowf { polling-delay-passive = <0>; polling-delay = <0>; - thermal-sensors = <&tsens1 9>; + thermal-sensors = <&tsens1 5>; thermal-governor = "low_limits_floor"; tracks-low; trips { - mdmv_trip: mdmv-trip { + camera_trip: camera-trip { temperature = <5000>; hysteresis = <5000>; type = "passive"; @@ -2058,47 +694,47 @@ }; cooling-maps { cpu0_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&CPU0 1 1>; }; cpu1_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&CPU4 5 5>; }; cx_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&cx_cdev 0 0>; }; mx_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&mx_cdev 0 0>; }; ebi_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&ebi_cdev 0 0>; }; mmcx_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&mm_cx_cdev 0 0>; }; modem_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&modem_vdd 0 0>; }; adsp_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&adsp_vdd 0 0>; }; cdsp_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&cdsp_vdd 0 0>; }; slpi_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&slpi_vdd 0 0>; }; gpu_vdd_cdev { - trip = <&mdmv_trip>; + trip = <&camera_trip>; cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) (THERMAL_MAX_LIMIT-2)>; }; @@ -2167,68 +803,6 @@ }; }; - gpuss-1-lowf { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-governor = "low_limits_floor"; - thermal-sensors = <&tsens1 11>; - tracks-low; - trips { - gpuss1_trip: gpuss1-trip { - temperature = <5000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - cooling-maps { - cpu0_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&CPU0 1 1>; - }; - cpu1_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&CPU4 5 5>; - }; - cx_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&cx_cdev 0 0>; - }; - mx_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&mx_cdev 0 0>; - }; - ebi_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&ebi_cdev 0 0>; - }; - mmcx_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&mm_cx_cdev 0 0>; - }; - modem_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&modem_vdd 0 0>; - }; - adsp_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&adsp_vdd 0 0>; - }; - cdsp_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&cdsp_vdd 0 0>; - }; - slpi_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&slpi_vdd 0 0>; - }; - gpu_vdd_cdev { - trip = <&gpuss1_trip>; - cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-2) - (THERMAL_MAX_LIMIT-2)>; - }; - }; - }; - gpuss-max-step { polling-delay-passive = <10>; polling-delay = <100>; diff --git a/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi b/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi index 1351a7e09ac5528cb8b63b0baca040169d29ef0d..2feaf41ec2562a09c5abad9efa2bf6f62c509847 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi @@ -295,7 +295,7 @@ USB3_DP_PCS_EQ_CONFIG1 0x0d 0 USB3_DP_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0xf8 0 USB3_DP_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x07 0 - USB3_DP_PCS_EQ_CONFIG5 0x52 0 + USB3_DP_PCS_EQ_CONFIG5 0x02 0 0xffffffff 0xffffffff 0x00>; qcom,qmp-phy-reg-offset = diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2-camera.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2-camera.dtsi index a0ccb00f9b538670154ea247444a2537a894651a..e92fd1b7c180e826a9c75c491f98e4599d962c45 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-v2-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-v2-camera.dtsi @@ -15,9 +15,10 @@ cam_vfe0: qcom,vfe0@acaf000 { cell-index = <0>; compatible = "qcom,vfe175"; - reg-names = "ife"; - reg = <0xacaf000 0x4000>; - reg-cam-base = <0xaf000>; + reg-names = "ife", "cam_camnoc"; + reg = <0xacaf000 0x4000>, + <0xac42000 0x5000>; + reg-cam-base = <0xaf000 0x42000>; interrupt-names = "ife"; interrupts = <0 465 0>; regulator-names = "camss", "ife0"; @@ -32,11 +33,13 @@ <&clock_camcc CAM_CC_IFE_0_CLK>, <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; clock-rates = + <400000000 0 0>, <558000000 0 0>, <637000000 0 0>, <847000000 0 0>, <950000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "nominal", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; src-clock-name = "ife_clk_src"; clock-control-debugfs = "true"; clock-names-option = "ife_dsp_clk"; @@ -73,11 +76,13 @@ <&clock_camcc CAM_CC_IFE_0_CLK>, <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; clock-rates = + <400000000 0 0 0 400000000 0 0>, <400000000 0 0 0 558000000 0 0>, <480000000 0 0 0 637000000 0 0>, <600000000 0 0 0 847000000 0 0>, <600000000 0 0 0 950000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "nominal", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; src-clock-name = "ife_csid_clk_src"; clock-control-debugfs = "true"; status = "ok"; @@ -86,9 +91,10 @@ cam_vfe1: qcom,vfe1@acb6000 { cell-index = <1>; compatible = "qcom,vfe175"; - reg-names = "ife"; - reg = <0xacb6000 0x4000>; - reg-cam-base = <0xb6000>; + reg-names = "ife", "cam_camnoc"; + reg = <0xacb6000 0x4000>, + <0xac42000 0x5000>; + reg-cam-base = <0xb6000 0x42000>; interrupt-names = "ife"; interrupts = <0 467 0>; regulator-names = "camss", "ife1"; @@ -103,11 +109,13 @@ <&clock_camcc CAM_CC_IFE_1_CLK>, <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; clock-rates = + <400000000 0 0>, <558000000 0 0>, <637000000 0 0>, <847000000 0 0>, <950000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "nominal", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; src-clock-name = "ife_clk_src"; clock-control-debugfs = "true"; clock-names-option = "ife_dsp_clk"; @@ -144,11 +152,13 @@ <&clock_camcc CAM_CC_IFE_1_CLK>, <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; clock-rates = + <400000000 0 0 0 400000000 0 0>, <400000000 0 0 0 558000000 0 0>, <480000000 0 0 0 637000000 0 0>, <600000000 0 0 0 847000000 0 0>, <600000000 0 0 0 950000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "nominal", "turbo"; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; src-clock-name = "ife_csid_clk_src"; clock-control-debugfs = "true"; status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi index c050284d4c4e1446947e46050c06d40dc5c31024..5b7e7d9f6837f12de36ca9bb1feb0c9951de7e2a 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi @@ -671,6 +671,18 @@ reg-names = "kgsl_gmu_reg", "kgsl_gmu_pdc_cfg", "kgsl_gmu_pdc_seq"; + + qcom,gpu-acd-table { + /* Corresponds to levels in the GPU perf table */ + qcom,acd-enable-by-level = <0x1e>; + qcom,acd-stride = <0x2>; + qcom,acd-num-levels = <0x4>; + + qcom,acd-data = <0xa02d5ffd 0x00007611 + 0xa02d5ffd 0x00006911 + 0xa02d5ffd 0x00006111 + 0x802d5ffd 0x00005411>; + }; }; /* NPU overrides */ diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 4aeaf5e535383a4d5ee6baa1791d6ed232c77eb7..70c6a32abb186642d9eafc8cdbd7381fcbb019c0 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -1293,13 +1293,6 @@ interrupts = <1 5 4>; }; - dsu_pmu@0 { - compatible = "arm,dsu-pmu"; - interrupts = ; - cpus = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, - <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>; - }; - qcom,msm-imem@146bf000 { compatible = "qcom,msm-imem"; reg = <0x146bf000 0x1000>; @@ -2308,7 +2301,7 @@ <0 0>, <0 0>, <37500000 300000000>, - <75000000 300000000>, + <37500000 300000000>, <0 0>, <0 0>, <0 0>, @@ -3146,10 +3139,10 @@ dcc: dcc_v2@10a2000 { compatible = "qcom,dcc-v2"; reg = <0x10a2000 0x1000>, - <0x10ae000 0x2000>; + <0x10ad000 0x3000>; reg-names = "dcc-base", "dcc-ram-base"; - dcc-ram-offset = <0x6000>; + dcc-ram-offset = <0x5000>; qcom,curr-link-list = <3>; qcom,link-list = , @@ -3673,7 +3666,7 @@ qcom,wlan-ramdump-dynamic = <0x400000>; mhi,max-channels = <30>; - mhi,timeout = <1000>; + mhi,timeout = <10000>; mhi_chan@0 { reg = <0>; diff --git a/arch/arm64/boot/dts/qcom/trinket-ion.dtsi b/arch/arm64/boot/dts/qcom/trinket-ion.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..7c35e6991afe6f9660aadef6bee721f8475d546d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/trinket-ion.dtsi @@ -0,0 +1,35 @@ +/* Copyright (c) 2018, 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,ion { + compatible = "qcom,msm-ion"; + #address-cells = <1>; + #size-cells = <0>; + + system_heap: qcom,ion-heap@25 { + reg = <25>; + qcom,ion-heap-type = "SYSTEM"; + }; + + qcom,ion-heap@27 { /* QSEECOM HEAP */ + reg = <27>; + memory-region = <&qseecom_mem>; + qcom,ion-heap-type = "DMA"; + }; + + qcom,ion-heap@9 { + reg = <9>; + qcom,ion-heap-type = "SYSTEM_SECURE"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/trinket.dtsi b/arch/arm64/boot/dts/qcom/trinket.dtsi index b9fa5e00df68bf3a0c6a872f018fff3c8ac7d2f1..48e87b492f1a3701c2d6ada8f2133f4e9b4e8942 100644 --- a/arch/arm64/boot/dts/qcom/trinket.dtsi +++ b/arch/arm64/boot/dts/qcom/trinket.dtsi @@ -256,6 +256,112 @@ }; soc: soc { }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hyp_region: hyp_region@25700000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x25700000 0 0x600000>; + }; + + xbl_aop_mem: xbl_aop_mem@25e00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x25e00000 0x0 0x140000>; + }; + + sec_apps_mem: sec_apps_region@25fff000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x25fff000 0x0 0x1000>; + }; + + smem_region: smem@26000000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x26000000 0x0 0x200000>; + }; + + removed_region: removed_region@26200000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x26200000 0 0x2d00000>; + }; + + pil_camera_mem: camera_region@2ab00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x2ab00000 0 0x500000>; + }; + + pil_modem_mem: modem_region@2b000000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x2b000000 0 0x7e00000>; + }; + + pil_video_mem: pil_video_region@32e00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x32e00000 0 0x500000>; + }; + + wlan_msa_mem: wlan_msa_region@33300000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x33300000 0 0x100000>; + }; + + pil_cdsp_mem: cdsp_regions@33400000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x33400000 0 0x800000>; + }; + + pil_adsp_mem: pil_adsp_region@33c00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x33c00000 0 0x1e00000>; + }; + + pil_ipa_fw_mem: ips_fw_region@35a00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x35a00000 0 0x10000>; + }; + + pil_ipa_gsi_mem: ipa_gsi_region@35a10000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x35a10000 0 0x5000>; + }; + + pil_gpu_mem: gpu_region@35a15000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x35a15000 0 0x2000>; + }; + + qseecom_mem: qseecom_region@3e400000 { + compatible = "shared-dma-pool"; + no-map; + reg = <0 0x3e400000 0 0x1400000>; + }; + + /* global autoconfigured region for contiguous allocations */ + linux,cma { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x00000000 0 0xffffffff>; + reusable; + alignment = <0 0x400000>; + size = <0 0x2000000>; + linux,cma-default; + }; + }; }; &soc { @@ -404,6 +510,12 @@ qcom,rtb-size = <0x100000>; }; + cpu_pmu: cpu-pmu { + compatible = "arm,armv8-pmuv3"; + qcom,irq-is-percpu; + interrupts = <1 6 4>; + }; + wdog: qcom,wdt@f017000 { compatible = "qcom,msm-watchdog"; reg = <0xf017000 0x1000>; @@ -517,3 +629,4 @@ }; }; #include "trinket-pinctrl.dtsi" +#include "trinket-ion.dtsi" diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index d70e409e2b0cbd7a2a1d07f2c84e86475fe8fd02..efac2202b16ec10301a40dea1b10ef464bad8e1a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -331,7 +331,7 @@ reg = <0x0 0xff120000 0x0 0x100>; interrupts = ; clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; - clock-names = "sclk_uart", "pclk_uart"; + clock-names = "baudclk", "apb_pclk"; dmas = <&dmac 4>, <&dmac 5>; #dma-cells = <2>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi index a29c279b6e8e4c484b14c77047d1b8436103f6b3..dba6f0ff810639c3f22f43f744c896617243562b 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi @@ -55,6 +55,7 @@ clocks = <&sys_clk 32>; enable-method = "psci"; operating-points-v2 = <&cluster0_opp>; + #cooling-cells = <2>; }; cpu2: cpu@100 { @@ -73,6 +74,7 @@ clocks = <&sys_clk 33>; enable-method = "psci"; operating-points-v2 = <&cluster1_opp>; + #cooling-cells = <2>; }; }; diff --git a/arch/arm64/configs/sa8155-perf_defconfig b/arch/arm64/configs/sa8155-perf_defconfig deleted file mode 120000 index 8fb0cc34e9acb07e55393536d8145670168b41ed..0000000000000000000000000000000000000000 --- a/arch/arm64/configs/sa8155-perf_defconfig +++ /dev/null @@ -1 +0,0 @@ -vendor/sa8155-perf_defconfig \ No newline at end of file diff --git a/arch/arm64/configs/sa8155_defconfig b/arch/arm64/configs/sa8155_defconfig deleted file mode 120000 index 005726151a08f9f0d914e8fd263611cb2ade3b59..0000000000000000000000000000000000000000 --- a/arch/arm64/configs/sa8155_defconfig +++ /dev/null @@ -1 +0,0 @@ -vendor/sa8155_defconfig \ No newline at end of file diff --git a/arch/arm64/configs/vendor/qcs405-perf_defconfig b/arch/arm64/configs/vendor/qcs405-perf_defconfig index ec0bddbaaeb422b44f4746796118300faafdb08a..6a3ae626c777288dc28a2948cef89963aef7acdd 100644 --- a/arch/arm64/configs/vendor/qcs405-perf_defconfig +++ b/arch/arm64/configs/vendor/qcs405-perf_defconfig @@ -315,6 +315,7 @@ CONFIG_FB=y CONFIG_FB_MSM=y CONFIG_FB_MSM_MDSS=y CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y CONFIG_FB_MSM_MDSS_SPI_PANEL=y CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y CONFIG_BACKLIGHT_LCD_SUPPORT=y @@ -351,6 +352,7 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_SERIAL=y CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_USB_TYPEC_MUX_NXP5150A=y CONFIG_NOP_USB_XCEIV=y CONFIG_MSM_SNPS_FEMTO_PHY=y CONFIG_USB_MSM_SSPHY=y @@ -467,6 +469,7 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y CONFIG_PAGE_POISONING=y @@ -498,3 +501,4 @@ CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_STACK_HASH_ORDER_SHIFT=12 diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 6520f3d01e641346cb2beb7ce085dd9c64316f32..f7895da9a1dec6befb0ea063bb328cfb604713f0 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -330,6 +330,7 @@ CONFIG_FB=y CONFIG_FB_MSM=y CONFIG_FB_MSM_MDSS=y CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y CONFIG_FB_MSM_MDSS_SPI_PANEL=y CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y @@ -367,6 +368,7 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_SERIAL=y CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_USB_TYPEC_MUX_NXP5150A=y CONFIG_NOP_USB_XCEIV=y CONFIG_MSM_SNPS_FEMTO_PHY=y CONFIG_USB_MSM_SSPHY=y diff --git a/arch/arm64/configs/vendor/sa8155-perf_defconfig b/arch/arm64/configs/vendor/sa8155-perf_defconfig index aadc30a38b098cbdc19329d65b19ab7d40b034e4..81c3270f6849a803a347991b6223fc1e545851be 100644 --- a/arch/arm64/configs/vendor/sa8155-perf_defconfig +++ b/arch/arm64/configs/vendor/sa8155-perf_defconfig @@ -76,6 +76,7 @@ CONFIG_SETEND_EMULATION=y CONFIG_RANDOMIZE_BASE=y # CONFIG_EFI is not set CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y CONFIG_PM_AUTOSLEEP=y diff --git a/arch/arm64/configs/vendor/sa8155_defconfig b/arch/arm64/configs/vendor/sa8155_defconfig index d1495301aad2d9d8aadba0f30d558993f371efa6..258973144d72f4f3108622b52c969cd74afd6d6a 100644 --- a/arch/arm64/configs/vendor/sa8155_defconfig +++ b/arch/arm64/configs/vendor/sa8155_defconfig @@ -82,6 +82,7 @@ CONFIG_SETEND_EMULATION=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y CONFIG_PM_AUTOSLEEP=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 93741d0675773b1dfb9862d9fb362d8639db2767..9f1aca1baad6415e7c217ef3987447b15779ea98 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -18,6 +18,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y @@ -52,6 +53,7 @@ CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y CONFIG_MODULE_SIG_SHA512=y CONFIG_PARTITION_ADVANCED=y +CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_ARCH_QCOM=y CONFIG_ARCH_SM6150=y CONFIG_ARCH_SDMMAGPIE=y @@ -103,10 +105,12 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y CONFIG_INET_DIAG_DESTROY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -168,6 +172,7 @@ CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y @@ -203,6 +208,7 @@ CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y CONFIG_BRIDGE_NF_EBTABLES=y CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y CONFIG_L2TP=y CONFIG_L2TP_V3=y CONFIG_L2TP_IP=y @@ -248,6 +254,7 @@ CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y 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 @@ -276,6 +283,8 @@ CONFIG_TUN=y CONFIG_SKY2=y CONFIG_RMNET=y CONFIG_SMSC911X=y +CONFIG_AT803X_PHY=y +CONFIG_MICREL_PHY=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y @@ -296,6 +305,7 @@ CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ST=y CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y CONFIG_TOUCHSCREEN_HIMAX_I2C=y CONFIG_TOUCHSCREEN_HIMAX_INCELL=y @@ -332,6 +342,7 @@ CONFIG_PM8150_PMIC_SIMULATOR=y CONFIG_PM8150B_PMIC_SIMULATOR=y CONFIG_PM8150L_PMIC_SIMULATOR=y CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_PTP_1588_CLOCK=y CONFIG_PINCTRL_SX150X=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_SDMMAGPIE=y @@ -519,6 +530,7 @@ CONFIG_MSM_GCC_SDMMAGPIE=y CONFIG_MSM_VIDEOCC_SDMMAGPIE=y CONFIG_MSM_NPUCC_SDMMAGPIE=y CONFIG_MSM_GPUCC_SDMMAGPIE=y +CONFIG_MSM_DEBUGCC_SDMMAGPIE=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_QCOM_APCS_IPC=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index 54f1ef8efa590ec7e80a928f3b93fa1812ef62a7..e3b10348d508f95823ce84f38562d513b83773f1 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -17,6 +17,8 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y +CONFIG_DEBUG_BLK_CGROUP=y CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y @@ -54,6 +56,7 @@ CONFIG_MODULE_SIG_SHA512=y # CONFIG_BLK_DEV_BSG is not set CONFIG_PARTITION_ADVANCED=y # CONFIG_IOSCHED_DEADLINE is not set +CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_ARCH_QCOM=y CONFIG_ARCH_SM6150=y CONFIG_ARCH_SDMMAGPIE=y @@ -70,6 +73,7 @@ CONFIG_ZSMALLOC=y CONFIG_SECCOMP=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set +CONFIG_PRINT_VMEMLAYOUT=y CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y @@ -107,10 +111,12 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y CONFIG_INET_DIAG_DESTROY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -172,6 +178,7 @@ CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y @@ -207,6 +214,7 @@ CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y CONFIG_BRIDGE_NF_EBTABLES=y CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y CONFIG_L2TP=y CONFIG_L2TP_DEBUGFS=y CONFIG_L2TP_V3=y @@ -255,6 +263,7 @@ CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y 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 @@ -283,6 +292,8 @@ CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y CONFIG_RMNET=y +CONFIG_AT803X_PHY=y +CONFIG_MICREL_PHY=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y @@ -304,6 +315,7 @@ CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ST=y CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y CONFIG_TOUCHSCREEN_HIMAX_I2C=y CONFIG_TOUCHSCREEN_HIMAX_INCELL=y @@ -343,6 +355,7 @@ CONFIG_PM8150_PMIC_SIMULATOR=y CONFIG_PM8150B_PMIC_SIMULATOR=y CONFIG_PM8150L_PMIC_SIMULATOR=y CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_PTP_1588_CLOCK=y CONFIG_PINCTRL_SX150X=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_SDMMAGPIE=y @@ -495,6 +508,7 @@ CONFIG_RTC_DRV_QPNP=y CONFIG_DMADEVICES=y CONFIG_QCOM_GPI_DMA=y CONFIG_QCOM_GPI_DMA_DEBUG=y +CONFIG_DEBUG_DMA_BUF_REF=y CONFIG_UIO=y CONFIG_UIO_MSM_SHAREDMEM=y CONFIG_STAGING=y @@ -537,6 +551,7 @@ CONFIG_MSM_GCC_SDMMAGPIE=y CONFIG_MSM_VIDEOCC_SDMMAGPIE=y CONFIG_MSM_NPUCC_SDMMAGPIE=y CONFIG_MSM_GPUCC_SDMMAGPIE=y +CONFIG_MSM_DEBUGCC_SDMMAGPIE=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_QCOM_APCS_IPC=y @@ -659,6 +674,7 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_MODULE_LOAD_INFO=y CONFIG_DEBUG_INFO=y CONFIG_PAGE_OWNER=y CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y @@ -705,6 +721,7 @@ CONFIG_IPC_LOGGING=y CONFIG_QCOM_RTB=y CONFIG_QCOM_RTB_SEPARATE_CPUS=y CONFIG_FUNCTION_TRACER=y +CONFIG_PREEMPTIRQ_EVENTS=y CONFIG_IRQSOFF_TRACER=y CONFIG_PREEMPT_TRACER=y CONFIG_BLK_DEV_IO_TRACE=y diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 2cb249ef4b0a54d68a00e7fa999608ff976cc733..7eb952410ac15b586d8c672ab9db2255ad1ba584 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -112,10 +112,12 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y CONFIG_INET_DIAG_DESTROY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -177,6 +179,7 @@ CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y @@ -212,6 +215,7 @@ CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y CONFIG_BRIDGE_NF_EBTABLES=y CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y CONFIG_L2TP=y CONFIG_L2TP_V3=y CONFIG_L2TP_IP=y @@ -602,7 +606,6 @@ CONFIG_PWM=y CONFIG_PWM_QTI_LPG=y CONFIG_QCOM_KGSL=y CONFIG_ARM_GIC_V3_ACL=y -CONFIG_ARM_DSU_PMU=y CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 11c301e30c9fecc37c5fa56553e27d9cb8055464..b3a4b14aaaf5aee4aa27314ef6f2245e27a4391f 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -119,10 +119,12 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y CONFIG_INET_DIAG_DESTROY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -184,6 +186,7 @@ CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y @@ -219,6 +222,7 @@ CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y CONFIG_BRIDGE_NF_EBTABLES=y CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y CONFIG_L2TP=y CONFIG_L2TP_DEBUGFS=y CONFIG_L2TP_V3=y @@ -630,7 +634,6 @@ CONFIG_PWM_QTI_LPG=y CONFIG_QCOM_KGSL=y CONFIG_ARM_GIC_V3_ACL=y CONFIG_PHY_XGENE=y -CONFIG_ARM_DSU_PMU=y CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h index ea9bb4e0e9bbd002e8dec644bcb03dbb25f55f72..e40f8a2df5457d63cbd81694b0545ea6bfb823cf 100644 --- a/arch/arm64/include/asm/cache.h +++ b/arch/arm64/include/asm/cache.h @@ -20,9 +20,14 @@ #define CTR_L1IP_SHIFT 14 #define CTR_L1IP_MASK 3 +#define CTR_DMINLINE_SHIFT 16 +#define CTR_IMINLINE_SHIFT 0 #define CTR_CWG_SHIFT 24 #define CTR_CWG_MASK 15 +#define CTR_CACHE_MINLINE_MASK \ + (0xf << CTR_DMINLINE_SHIFT | 0xf << CTR_IMINLINE_SHIFT) + #define CTR_L1IP(ctr) (((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK) #define ICACHE_POLICY_VPIPT 0 diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index ac16e2efb348226ec6ff4053de868e9325c81d1e..ab1149efda437496dc2f62ca8fe9fd73e3f00407 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -45,7 +45,8 @@ #define ARM64_HARDEN_BP_POST_GUEST_EXIT 25 #define ARM64_HW_DBM 26 #define ARM64_SSBD 27 +#define ARM64_MISMATCHED_CACHE_TYPE 28 -#define ARM64_NCAPS 28 +#define ARM64_NCAPS 29 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index e5df3fce00082a3aa6d1711188e6d1055012dc9d..2b55aee7c051844b7ac705f75b85c62301748697 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -42,6 +42,11 @@ void kvm_inject_vabt(struct kvm_vcpu *vcpu); void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); +static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu) +{ + return !(vcpu->arch.hcr_el2 & HCR_RW); +} + static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) { vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 57dde8be92a4bf294bf918877a6e7a6889e97ba9..145ab666f64df8e663ce1f9d8636d5cb52764215 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -17,8 +17,8 @@ */ #include -#include #include +#include #include #include #include @@ -47,12 +47,18 @@ is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope) } static bool -has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry, - int scope) +has_mismatched_cache_type(const struct arm64_cpu_capabilities *entry, + int scope) { + u64 mask = CTR_CACHE_MINLINE_MASK; + + /* Skip matching the min line sizes for cache type check */ + if (entry->capability == ARM64_MISMATCHED_CACHE_TYPE) + mask ^= arm64_ftr_reg_ctrel0.strict_mask; + WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); - return (read_cpuid_cachetype() & arm64_ftr_reg_ctrel0.strict_mask) != - (arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask); + return (read_cpuid_cachetype() & mask) != + (arm64_ftr_reg_ctrel0.sys_val & mask); } static int cpu_enable_trap_ctr_access(void *__unused) @@ -475,7 +481,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { { .desc = "Mismatched cache line size", .capability = ARM64_MISMATCHED_CACHE_LINE_SIZE, - .matches = has_mismatched_cache_line_size, + .matches = has_mismatched_cache_type, + .def_scope = SCOPE_LOCAL_CPU, + .enable = cpu_enable_trap_ctr_access, + }, + { + .desc = "Mismatched cache type", + .capability = ARM64_MISMATCHED_CACHE_TYPE, + .matches = has_mismatched_cache_type, .def_scope = SCOPE_LOCAL_CPU, .enable = cpu_enable_trap_ctr_access, }, diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 5e621db943c9326931f6b6a9be0cf75c46ce0b3d..85c5208034c179d915c2732b4e87cf0497cb9ba9 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -180,14 +180,14 @@ static const struct arm64_ftr_bits ftr_ctr[] = { ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 28, 1, 1), /* IDC */ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), /* CWG */ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 20, 4, 0), /* ERG */ - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */ + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DMINLINE_SHIFT, 4, 1), /* * Linux can handle differing I-cache policies. Userspace JITs will * make use of *minLine. * If we have differing I-cache policies, report it as the weakest - VIPT. */ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_EXACT, 14, 2, ICACHE_POLICY_VIPT), /* L1Ip */ - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* IminLine */ + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IMINLINE_SHIFT, 4, 0), ARM64_FTR_END, }; diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index d849d9804011df6eabb143ed68da8d260dd5074d..22a5921562c7f84b9e6d25b8e3479269720780fe 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -275,7 +275,7 @@ static int __kprobes reenter_kprobe(struct kprobe *p, break; case KPROBE_HIT_SS: case KPROBE_REENTER: - pr_warn("Unrecoverable kprobe detected at %p.\n", p->addr); + pr_warn("Unrecoverable kprobe detected.\n"); dump_kprobe(p); BUG(); break; diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index edaf346d13d5fe31f4ec1a10d5a9647e46d92274..34d915b6974be24747cefed9bbff8b6c04882444 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -274,19 +274,22 @@ static int ptrace_hbp_set_event(unsigned int note_type, switch (note_type) { case NT_ARM_HW_BREAK: - if (idx < ARM_MAX_BRP) { - tsk->thread.debug.hbp_break[idx] = bp; - err = 0; - } + if (idx >= ARM_MAX_BRP) + goto out; + idx = array_index_nospec(idx, ARM_MAX_BRP); + tsk->thread.debug.hbp_break[idx] = bp; + err = 0; break; case NT_ARM_HW_WATCH: - if (idx < ARM_MAX_WRP) { - tsk->thread.debug.hbp_watch[idx] = bp; - err = 0; - } + if (idx >= ARM_MAX_WRP) + goto out; + idx = array_index_nospec(idx, ARM_MAX_WRP); + tsk->thread.debug.hbp_watch[idx] = bp; + err = 0; break; } +out: return err; } diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 043f562dde165e2436686270c971a27d57f1d9de..f7a5b92bfceeadcb3010ba77a20a4e9aefea6f84 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -218,7 +218,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ -asmlinkage void secondary_start_kernel(void) +asmlinkage notrace void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu; diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 811f04c5760e40c5fd36adc6cb931921cbfa850a..76d27edf33cbffe4b30f72104554b5f1d32b8332 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -57,6 +57,45 @@ static u64 core_reg_offset_from_id(u64 id) return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); } +static int validate_core_offset(const struct kvm_one_reg *reg) +{ + u64 off = core_reg_offset_from_id(reg->id); + int size; + + switch (off) { + case KVM_REG_ARM_CORE_REG(regs.regs[0]) ... + KVM_REG_ARM_CORE_REG(regs.regs[30]): + case KVM_REG_ARM_CORE_REG(regs.sp): + case KVM_REG_ARM_CORE_REG(regs.pc): + case KVM_REG_ARM_CORE_REG(regs.pstate): + case KVM_REG_ARM_CORE_REG(sp_el1): + case KVM_REG_ARM_CORE_REG(elr_el1): + case KVM_REG_ARM_CORE_REG(spsr[0]) ... + KVM_REG_ARM_CORE_REG(spsr[KVM_NR_SPSR - 1]): + size = sizeof(__u64); + break; + + case KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]) ... + KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]): + size = sizeof(__uint128_t); + break; + + case KVM_REG_ARM_CORE_REG(fp_regs.fpsr): + case KVM_REG_ARM_CORE_REG(fp_regs.fpcr): + size = sizeof(__u32); + break; + + default: + return -EINVAL; + } + + if (KVM_REG_SIZE(reg->id) == size && + IS_ALIGNED(off, size / sizeof(__u32))) + return 0; + + return -EINVAL; +} + static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { /* @@ -76,6 +115,9 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs) return -ENOENT; + if (validate_core_offset(reg)) + return -EINVAL; + if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id))) return -EFAULT; @@ -98,6 +140,9 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs) return -ENOENT; + if (validate_core_offset(reg)) + return -EINVAL; + if (KVM_REG_SIZE(reg->id) > sizeof(tmp)) return -EINVAL; @@ -107,17 +152,25 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) } if (off == KVM_REG_ARM_CORE_REG(regs.pstate)) { - u32 mode = (*(u32 *)valp) & COMPAT_PSR_MODE_MASK; + u64 mode = (*(u64 *)valp) & COMPAT_PSR_MODE_MASK; switch (mode) { case COMPAT_PSR_MODE_USR: + if (!system_supports_32bit_el0()) + return -EINVAL; + break; case COMPAT_PSR_MODE_FIQ: case COMPAT_PSR_MODE_IRQ: case COMPAT_PSR_MODE_SVC: case COMPAT_PSR_MODE_ABT: case COMPAT_PSR_MODE_UND: + if (!vcpu_el1_is_32bit(vcpu)) + return -EINVAL; + break; case PSR_MODE_EL0t: case PSR_MODE_EL1t: case PSR_MODE_EL1h: + if (vcpu_el1_is_32bit(vcpu)) + return -EINVAL; break; default: err = -EINVAL; diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 0595236e2fa4dcc020d2e23eaa78482f919bdb5e..39d00f15bd46881e05eb54524f38805f9f771866 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -770,13 +770,14 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, size >> PAGE_SHIFT); return NULL; } - if (!coherent) - __dma_flush_area(page_to_virt(page), iosize); - addr = dma_common_contiguous_remap(page, size, VM_USERMAP, prot, __builtin_return_address(0)); - if (!addr) { + if (addr) { + memset(addr, 0, size); + if (!coherent) + __dma_flush_area(page_to_virt(page), iosize); + } else { iommu_dma_unmap_page(dev, *handle, iosize, 0, attrs); dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT); diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index cc1b7acea13e1527476267c12fd32cce3c8dd213..b89eec1ad6b37f3b848cfac09cd7c200faf228a4 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -288,11 +288,13 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) #endif /* CONFIG_NUMA */ #ifdef CONFIG_HAVE_ARCH_PFN_VALID -#define PFN_MASK ((1UL << (64 - PAGE_SHIFT)) - 1) - int pfn_valid(unsigned long pfn) { - return (pfn & PFN_MASK) == pfn && memblock_is_map_memory(pfn << PAGE_SHIFT); + phys_addr_t addr = pfn << PAGE_SHIFT; + + if ((addr >> PAGE_SHIFT) != pfn) + return 0; + return memblock_is_map_memory(addr); } EXPORT_SYMBOL(pfn_valid); #endif diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h index 8b707c249026032ac8bef80c6f1666c105d9b50d..12fe700632f458ea632a18bb9cdccd6660efd241 100644 --- a/arch/m68k/include/asm/mcf_pgalloc.h +++ b/arch/m68k/include/asm/mcf_pgalloc.h @@ -44,6 +44,7 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address) static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page, unsigned long address) { + pgtable_page_dtor(page); __free_page(page); } @@ -74,8 +75,9 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, return page; } -extern inline void pte_free(struct mm_struct *mm, struct page *page) +static inline void pte_free(struct mm_struct *mm, struct page *page) { + pgtable_page_dtor(page); __free_page(page); } diff --git a/arch/mips/Makefile b/arch/mips/Makefile index a96d97a806c9906e826ae8a1086be7eb7a8ff65f..5977884b008e6d798755dbf98ae5d29fda1b015c 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -155,15 +155,11 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap -cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ - -Wa,-mips32 -Wa,--trap -cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ - -Wa,-mips32r2 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap -modd-spreg -cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \ - -Wa,-mips64 -Wa,--trap -cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \ - -Wa,-mips64r2 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,--trap cflags-$(CONFIG_CPU_MIPS64_R6) += -march=mips64r6 -Wa,--trap cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap cflags-$(CONFIG_CPU_R5432) += $(call cc-option,-march=r5400,-march=r5000) \ diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index f206dafbb0a35f57ccd64bfbefd24bbe112ff4f7..26a058d58d37b2ae10ca634b8025d6a01d0b6346 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -40,6 +40,7 @@ static char ath79_sys_type[ATH79_SYS_TYPE_LEN]; static void ath79_restart(char *command) { + local_irq_disable(); ath79_device_reset_set(AR71XX_RESET_FULL_CHIP); for (;;) if (cpu_wait) diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 8c9cbf13d32a0a471bc6f2653bbb3c459b1b2c2c..6054d49e608eec038e1bbd49599bc783270aa09a 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -212,12 +212,6 @@ static int __init bcm47xx_cpu_fixes(void) */ if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706) cpu_wait = NULL; - - /* - * BCM47XX Erratum "R10: PCIe Transactions Periodically Fail" - * Enable ExternalSync for sync instruction to take effect - */ - set_c0_config7(MIPS_CONF7_ES); break; #endif } diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile index c22da16d67b82f7752f6ba39291e2acd4e18fb47..5c7bfa8478e7522a854c93f89e4990170e58eb3b 100644 --- a/arch/mips/boot/Makefile +++ b/arch/mips/boot/Makefile @@ -118,10 +118,12 @@ ifeq ($(ADDR_BITS),64) itb_addr_cells = 2 endif +targets += vmlinux.its.S + quiet_cmd_its_cat = CAT $@ - cmd_its_cat = cat $^ >$@ + cmd_its_cat = cat $(filter-out $(PHONY), $^) >$@ -$(obj)/vmlinux.its.S: $(addprefix $(srctree)/arch/mips/$(PLATFORM)/,$(ITS_INPUTS)) +$(obj)/vmlinux.its.S: $(addprefix $(srctree)/arch/mips/$(PLATFORM)/,$(ITS_INPUTS)) FORCE $(call if_changed,its_cat) quiet_cmd_cpp_its_S = ITS $@ diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 8505db478904b10855eabf266f75ff9dd93e3699..1d92efb82c3729173e01d64b660f961bc42dd9b8 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -322,6 +322,7 @@ static int __init octeon_ehci_device_init(void) return 0; pd = of_find_device_by_node(ehci_node); + of_node_put(ehci_node); if (!pd) return 0; @@ -384,6 +385,7 @@ static int __init octeon_ohci_device_init(void) return 0; pd = of_find_device_by_node(ohci_node); + of_node_put(ohci_node); if (!pd) return 0; diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c index 5ba6fcc26fa726aff50cc3a64315855eb935c1b0..94a78dbbc91f78acb51a8f092ae084646f1c2182 100644 --- a/arch/mips/generic/init.c +++ b/arch/mips/generic/init.c @@ -204,6 +204,7 @@ void __init arch_init_irq(void) "mti,cpu-interrupt-controller"); if (!cpu_has_veic && !intc_node) mips_cpu_irq_init(); + of_node_put(intc_node); irqchip_init(); } diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index cea8ad864b3f6f416cb45687bfbcb5bd882933a7..57b34257be2bf03826bbf332b4461e834e1f791d 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -141,14 +141,14 @@ static inline void * phys_to_virt(unsigned long address) /* * ISA I/O bus memory addresses are 1:1 with the physical address. */ -static inline unsigned long isa_virt_to_bus(volatile void * address) +static inline unsigned long isa_virt_to_bus(volatile void *address) { - return (unsigned long)address - PAGE_OFFSET; + return virt_to_phys(address); } -static inline void * isa_bus_to_virt(unsigned long address) +static inline void *isa_bus_to_virt(unsigned long address) { - return (void *)(address + PAGE_OFFSET); + return phys_to_virt(address); } #define isa_page_to_bus page_to_phys diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h index 441faa92c3cd488ac97685a1930597f7449a88f4..6e6c0fead776d22b94b444a7ff3c9af91daa9935 100644 --- a/arch/mips/include/asm/mach-ath79/ath79.h +++ b/arch/mips/include/asm/mach-ath79/ath79.h @@ -134,6 +134,7 @@ static inline u32 ath79_pll_rr(unsigned reg) static inline void ath79_reset_wr(unsigned reg, u32 val) { __raw_writel(val, ath79_reset_base + reg); + (void) __raw_readl(ath79_reset_base + reg); /* flush */ } static inline u32 ath79_reset_rr(unsigned reg) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 60c787d943b059ed33561bb127e60ce07ef0198c..a6810923b3f0214dfa36eab4a28320a65bba7790 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -680,8 +680,6 @@ #define MIPS_CONF7_WII (_ULCAST_(1) << 31) #define MIPS_CONF7_RPS (_ULCAST_(1) << 2) -/* ExternalSync */ -#define MIPS_CONF7_ES (_ULCAST_(1) << 8) #define MIPS_CONF7_IAR (_ULCAST_(1) << 10) #define MIPS_CONF7_AR (_ULCAST_(1) << 16) @@ -2747,7 +2745,6 @@ __BUILD_SET_C0(status) __BUILD_SET_C0(cause) __BUILD_SET_C0(config) __BUILD_SET_C0(config5) -__BUILD_SET_C0(config7) __BUILD_SET_C0(intcontrol) __BUILD_SET_C0(intctl) __BUILD_SET_C0(srsmap) diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 95b8c471f572b07d8d313fbadc96d5f1b71a035a..eb1f6030ab853d9990a6e59695db438c48c8bc70 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -141,7 +141,7 @@ struct mips_fpu_struct { #define NUM_DSP_REGS 6 -typedef __u32 dspreg_t; +typedef unsigned long dspreg_t; struct mips_dsp_state { dspreg_t dspr[NUM_DSP_REGS]; @@ -388,7 +388,20 @@ unsigned long get_wchan(struct task_struct *p); #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29]) #define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status) +#ifdef CONFIG_CPU_LOONGSON3 +/* + * Loongson-3's SFB (Store-Fill-Buffer) may buffer writes indefinitely when a + * tight read loop is executed, because reads take priority over writes & the + * hardware (incorrectly) doesn't ensure that writes will eventually occur. + * + * Since spin loops of any kind should have a cpu_relax() in them, force an SFB + * flush from cpu_relax() such that any pending writes will become visible as + * expected. + */ +#define cpu_relax() smp_mb() +#else #define cpu_relax() barrier() +#endif /* * Return_address is a replacement for __builtin_return_address(count) diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform index 28448d358c10d42c6ed5600ed3a5e5d67919e7e5..a2a5a85ea1f9360d3ff90e7e0419c423b6a0fbdf 100644 --- a/arch/mips/jz4740/Platform +++ b/arch/mips/jz4740/Platform @@ -1,4 +1,4 @@ platform-$(CONFIG_MACH_INGENIC) += jz4740/ cflags-$(CONFIG_MACH_INGENIC) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 load-$(CONFIG_MACH_INGENIC) += 0xffffffff80010000 -zload-$(CONFIG_MACH_INGENIC) += 0xffffffff80600000 +zload-$(CONFIG_MACH_INGENIC) += 0xffffffff81000000 diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index e058cd300713d19bf656bc243f3f6cec9728a962..efffdf2464ab76d85b7b5e35d089323c70f0164f 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -847,7 +847,7 @@ long arch_ptrace(struct task_struct *child, long request, goto out; } dregs = __get_dsp_regs(child); - tmp = (unsigned long) (dregs[addr - DSP_BASE]); + tmp = dregs[addr - DSP_BASE]; break; } case DSP_CONTROL: diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 89026d33a07bf7027400e56fa49fcb65da21ea60..6990240785f6c0cd8dbcfeaed237502739f82fe8 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -141,7 +141,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, goto out; } dregs = __get_dsp_regs(child); - tmp = (unsigned long) (dregs[addr - DSP_BASE]); + tmp = dregs[addr - DSP_BASE]; break; } case DSP_CONTROL: diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index 019035d7225c4fd942c96c6628b6605f8d2af1b4..8f845f6e5f4266568288969b9b19b7357b86598b 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include +#include #include /* Kernel-provided data used by the VDSO. */ @@ -128,12 +130,30 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) vvar_size = gic_size + PAGE_SIZE; size = vvar_size + image->size; + /* + * Find a region that's large enough for us to perform the + * colour-matching alignment below. + */ + if (cpu_has_dc_aliases) + size += shm_align_mask + 1; + base = get_unmapped_area(NULL, 0, size, 0, 0); if (IS_ERR_VALUE(base)) { ret = base; goto out; } + /* + * If we suffer from dcache aliasing, ensure that the VDSO data page + * mapping is coloured the same as the kernel's mapping of that memory. + * This ensures that when the kernel updates the VDSO data userland + * will observe it without requiring cache invalidations. + */ + if (cpu_has_dc_aliases) { + base = __ALIGN_MASK(base, shm_align_mask); + base += ((unsigned long)&vdso_data - gic_size) & shm_align_mask; + } + data_addr = base + gic_size; vdso_addr = data_addr + PAGE_SIZE; diff --git a/arch/mips/lib/multi3.c b/arch/mips/lib/multi3.c index 111ad475aa0cdd111ebe362af928414d9499f666..4c2483f410c26b5b65ded652c1b0694b06a9bf92 100644 --- a/arch/mips/lib/multi3.c +++ b/arch/mips/lib/multi3.c @@ -4,12 +4,12 @@ #include "libgcc.h" /* - * GCC 7 suboptimally generates __multi3 calls for mips64r6, so for that - * specific case only we'll implement it here. + * GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for + * that specific case only we implement that intrinsic here. * * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981 */ -#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ == 7) +#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8) /* multiply 64-bit values, low 64-bits returned */ static inline long long notrace dmulu(long long a, long long b) diff --git a/arch/mips/loongson64/common/cs5536/cs5536_ohci.c b/arch/mips/loongson64/common/cs5536/cs5536_ohci.c index f7c905e50dc415e21eb258b08a69cc61525bd67b..92dc6bafc1271795b3c66b7c21467f3c22214fd0 100644 --- a/arch/mips/loongson64/common/cs5536/cs5536_ohci.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_ohci.c @@ -138,7 +138,7 @@ u32 pci_ohci_read_reg(int reg) break; case PCI_OHCI_INT_REG: _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); - if ((lo & 0x00000f00) == CS5536_USB_INTR) + if (((lo >> PIC_YSEL_LOW_USB_SHIFT) & 0xf) == CS5536_USB_INTR) conf_data = 1; break; default: diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index e12dfa48b478dd3ec51369236bb84040c044bd82..a5893b2cdc0e051bb55f69a021c3d4a742309d7b 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -835,7 +835,8 @@ static void r4k_flush_icache_user_range(unsigned long start, unsigned long end) static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) { /* Catch bad driver code */ - BUG_ON(size == 0); + if (WARN_ON(size == 0)) + return; preempt_disable(); if (cpu_has_inclusive_pcaches) { @@ -871,7 +872,8 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) { /* Catch bad driver code */ - BUG_ON(size == 0); + if (WARN_ON(size == 0)) + return; preempt_disable(); if (cpu_has_inclusive_pcaches) { diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index 1b7160c79646be4e136d0f813b4b55c0bfd63827..b16e95a4e875fd742fbaf3ce9aaa3d63b2ba88ce 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S @@ -221,12 +221,6 @@ EXCEPTION_ENTRY(_data_page_fault_handler) l.addi r3,r1,0 // pt_regs /* r4 set be EXCEPTION_HANDLE */ // effective address of fault - /* - * __PHX__: TODO - * - * all this can be written much simpler. look at - * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part - */ #ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX l.lwz r6,PT_PC(r3) // address of an offending insn l.lwz r6,0(r6) // instruction that caused pf @@ -258,7 +252,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler) #else - l.lwz r6,PT_SR(r3) // SR + l.mfspr r6,r0,SPR_SR // SR l.andi r6,r6,SPR_SR_DSX // check for delay slot exception l.sfne r6,r0 // exception happened in delay slot l.bnf 7f diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S index 1e87913576e304e47ea7da5518436d3e0fe3f94e..90979acdf165b4d8ed74e02b9b1a049ac1f6c720 100644 --- a/arch/openrisc/kernel/head.S +++ b/arch/openrisc/kernel/head.S @@ -141,8 +141,7 @@ * r4 - EEAR exception EA * r10 - current pointing to current_thread_info struct * r12 - syscall 0, since we didn't come from syscall - * r13 - temp it actually contains new SR, not needed anymore - * r31 - handler address of the handler we'll jump to + * r30 - handler address of the handler we'll jump to * * handler has to save remaining registers to the exception * ksp frame *before* tainting them! @@ -178,6 +177,7 @@ /* r1 is KSP, r30 is __pa(KSP) */ ;\ tophys (r30,r1) ;\ l.sw PT_GPR12(r30),r12 ;\ + /* r4 use for tmp before EA */ ;\ l.mfspr r12,r0,SPR_EPCR_BASE ;\ l.sw PT_PC(r30),r12 ;\ l.mfspr r12,r0,SPR_ESR_BASE ;\ @@ -197,7 +197,10 @@ /* r12 == 1 if we come from syscall */ ;\ CLEAR_GPR(r12) ;\ /* ----- turn on MMU ----- */ ;\ - l.ori r30,r0,(EXCEPTION_SR) ;\ + /* Carry DSX into exception SR */ ;\ + l.mfspr r30,r0,SPR_SR ;\ + l.andi r30,r30,SPR_SR_DSX ;\ + l.ori r30,r30,(EXCEPTION_SR) ;\ l.mtspr r0,r30,SPR_ESR_BASE ;\ /* r30: EA address of handler */ ;\ LOAD_SYMBOL_2_GPR(r30,handler) ;\ diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index 8d8437169b5e7496b589e71c686c06348035fdbd..0d44e8007ad6e16f7cfcac027dabb89903f99d87 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c @@ -358,7 +358,7 @@ static inline int in_delay_slot(struct pt_regs *regs) return 0; } #else - return regs->sr & SPR_SR_DSX; + return mfspr(SPR_SR) & SPR_SR_DSX; #endif } diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h index af03359e6ac5685d6fa93361b5a0f4f4817a8cae..a82776592c8e5e8a346dadb8f753e18082bcccaf 100644 --- a/arch/parisc/include/asm/spinlock.h +++ b/arch/parisc/include/asm/spinlock.h @@ -20,7 +20,6 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x, { volatile unsigned int *a; - mb(); a = __ldcw_align(x); while (__ldcw(a) == 0) while (*a == 0) @@ -30,16 +29,15 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x, local_irq_disable(); } else cpu_relax(); - mb(); } static inline void arch_spin_unlock(arch_spinlock_t *x) { volatile unsigned int *a; - mb(); + a = __ldcw_align(x); - *a = 1; mb(); + *a = 1; } static inline int arch_spin_trylock(arch_spinlock_t *x) @@ -47,10 +45,8 @@ static inline int arch_spin_trylock(arch_spinlock_t *x) volatile unsigned int *a; int ret; - mb(); a = __ldcw_align(x); ret = __ldcw(a) != 0; - mb(); return ret; } diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 4886a6db42e98f2b1fc4c58916ee68dfc98df008..5f7e57fcaeef0333da7482f8af566a0e4da7fc00 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -629,12 +629,12 @@ cas_action: stw %r1, 4(%sr2,%r20) #endif /* The load and store could fail */ -1: ldw,ma 0(%r26), %r28 +1: ldw 0(%r26), %r28 sub,<> %r28, %r25, %r0 -2: stw,ma %r24, 0(%r26) +2: stw %r24, 0(%r26) /* Free lock */ sync - stw,ma %r20, 0(%sr2,%r20) + stw %r20, 0(%sr2,%r20) #if ENABLE_LWS_DEBUG /* Clear thread register indicator */ stw %r0, 4(%sr2,%r20) @@ -798,30 +798,30 @@ cas2_action: ldo 1(%r0),%r28 /* 8bit CAS */ -13: ldb,ma 0(%r26), %r29 +13: ldb 0(%r26), %r29 sub,= %r29, %r25, %r0 b,n cas2_end -14: stb,ma %r24, 0(%r26) +14: stb %r24, 0(%r26) b cas2_end copy %r0, %r28 nop nop /* 16bit CAS */ -15: ldh,ma 0(%r26), %r29 +15: ldh 0(%r26), %r29 sub,= %r29, %r25, %r0 b,n cas2_end -16: sth,ma %r24, 0(%r26) +16: sth %r24, 0(%r26) b cas2_end copy %r0, %r28 nop nop /* 32bit CAS */ -17: ldw,ma 0(%r26), %r29 +17: ldw 0(%r26), %r29 sub,= %r29, %r25, %r0 b,n cas2_end -18: stw,ma %r24, 0(%r26) +18: stw %r24, 0(%r26) b cas2_end copy %r0, %r28 nop @@ -829,10 +829,10 @@ cas2_action: /* 64bit CAS */ #ifdef CONFIG_64BIT -19: ldd,ma 0(%r26), %r29 +19: ldd 0(%r26), %r29 sub,*= %r29, %r25, %r0 b,n cas2_end -20: std,ma %r24, 0(%r26) +20: std %r24, 0(%r26) copy %r0, %r28 #else /* Compare first word */ @@ -851,7 +851,7 @@ cas2_action: cas2_end: /* Free lock */ sync - stw,ma %r20, 0(%sr2,%r20) + stw %r20, 0(%sr2,%r20) /* Enable interrupts */ ssm PSW_SM_I, %r0 /* Return to userspace, set no error */ diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h index 5a23010af600337b89887cab179cf2e9b1b385b0..1e7a33592e297aae7f6e5001c20d3b005eb6d81c 100644 --- a/arch/powerpc/include/asm/fadump.h +++ b/arch/powerpc/include/asm/fadump.h @@ -195,9 +195,6 @@ struct fadump_crash_info_header { struct cpumask online_mask; }; -/* Crash memory ranges */ -#define INIT_CRASHMEM_RANGES (INIT_MEMBLOCK_REGIONS + 2) - struct fad_crash_memory_ranges { unsigned long long base; unsigned long long size; diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 11f4bd07cce0ee0fde57d031634a3b6d2a3b1dda..565cead12be2fb3be3535a44d224a8ff9facc9b3 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -223,10 +223,17 @@ do { \ } \ } while (0) +/* + * This is a type: either unsigned long, if the argument fits into + * that type, or otherwise unsigned long long. + */ +#define __long_type(x) \ + __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) + #define __get_user_nocheck(x, ptr, size) \ ({ \ long __gu_err; \ - unsigned long __gu_val; \ + __long_type(*(ptr)) __gu_val; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ __chk_user_ptr(ptr); \ if (!is_kernel_addr((unsigned long)__gu_addr)) \ @@ -239,7 +246,7 @@ do { \ #define __get_user_check(x, ptr, size) \ ({ \ long __gu_err = -EFAULT; \ - unsigned long __gu_val = 0; \ + __long_type(*(ptr)) __gu_val = 0; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ might_fault(); \ if (access_ok(VERIFY_READ, __gu_addr, (size))) \ @@ -251,7 +258,7 @@ do { \ #define __get_user_nosleep(x, ptr, size) \ ({ \ long __gu_err; \ - unsigned long __gu_val; \ + __long_type(*(ptr)) __gu_val; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ __chk_user_ptr(ptr); \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index c09f0a6f84954260775a792c9b600d8a3210d2dd..f65bb53df43bf0e12ad586c1b049b0dc61f8aed1 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -1452,6 +1452,8 @@ TRAMP_REAL_BEGIN(stf_barrier_fallback) TRAMP_REAL_BEGIN(rfi_flush_fallback) SET_SCRATCH0(r13); GET_PACA(r13); + std r1,PACA_EXRFI+EX_R12(r13) + ld r1,PACAKSAVE(r13) std r9,PACA_EXRFI+EX_R9(r13) std r10,PACA_EXRFI+EX_R10(r13) std r11,PACA_EXRFI+EX_R11(r13) @@ -1486,12 +1488,15 @@ TRAMP_REAL_BEGIN(rfi_flush_fallback) ld r9,PACA_EXRFI+EX_R9(r13) ld r10,PACA_EXRFI+EX_R10(r13) ld r11,PACA_EXRFI+EX_R11(r13) + ld r1,PACA_EXRFI+EX_R12(r13) GET_SCRATCH0(r13); rfid TRAMP_REAL_BEGIN(hrfi_flush_fallback) SET_SCRATCH0(r13); GET_PACA(r13); + std r1,PACA_EXRFI+EX_R12(r13) + ld r1,PACAKSAVE(r13) std r9,PACA_EXRFI+EX_R9(r13) std r10,PACA_EXRFI+EX_R10(r13) std r11,PACA_EXRFI+EX_R11(r13) @@ -1526,6 +1531,7 @@ TRAMP_REAL_BEGIN(hrfi_flush_fallback) ld r9,PACA_EXRFI+EX_R9(r13) ld r10,PACA_EXRFI+EX_R10(r13) ld r11,PACA_EXRFI+EX_R11(r13) + ld r1,PACA_EXRFI+EX_R12(r13) GET_SCRATCH0(r13); hrfid diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index d0020bc1f2095c6d1433dc390d30aa327b99a9e6..5a6470383ca3968af8b3f5d3eb0856238d746435 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -47,8 +47,10 @@ static struct fadump_mem_struct fdm; static const struct fadump_mem_struct *fdm_active; static DEFINE_MUTEX(fadump_mutex); -struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES]; +struct fad_crash_memory_ranges *crash_memory_ranges; +int crash_memory_ranges_size; int crash_mem_ranges; +int max_crash_mem_ranges; /* Scan the Firmware Assisted dump configuration details. */ int __init early_init_dt_scan_fw_dump(unsigned long node, @@ -843,38 +845,88 @@ static int __init process_fadump(const struct fadump_mem_struct *fdm_active) return 0; } -static inline void fadump_add_crash_memory(unsigned long long base, - unsigned long long end) +static void free_crash_memory_ranges(void) +{ + kfree(crash_memory_ranges); + crash_memory_ranges = NULL; + crash_memory_ranges_size = 0; + max_crash_mem_ranges = 0; +} + +/* + * Allocate or reallocate crash memory ranges array in incremental units + * of PAGE_SIZE. + */ +static int allocate_crash_memory_ranges(void) +{ + struct fad_crash_memory_ranges *new_array; + u64 new_size; + + new_size = crash_memory_ranges_size + PAGE_SIZE; + pr_debug("Allocating %llu bytes of memory for crash memory ranges\n", + new_size); + + new_array = krealloc(crash_memory_ranges, new_size, GFP_KERNEL); + if (new_array == NULL) { + pr_err("Insufficient memory for setting up crash memory ranges\n"); + free_crash_memory_ranges(); + return -ENOMEM; + } + + crash_memory_ranges = new_array; + crash_memory_ranges_size = new_size; + max_crash_mem_ranges = (new_size / + sizeof(struct fad_crash_memory_ranges)); + return 0; +} + +static inline int fadump_add_crash_memory(unsigned long long base, + unsigned long long end) { if (base == end) - return; + return 0; + + if (crash_mem_ranges == max_crash_mem_ranges) { + int ret; + + ret = allocate_crash_memory_ranges(); + if (ret) + return ret; + } pr_debug("crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n", crash_mem_ranges, base, end - 1, (end - base)); crash_memory_ranges[crash_mem_ranges].base = base; crash_memory_ranges[crash_mem_ranges].size = end - base; crash_mem_ranges++; + return 0; } -static void fadump_exclude_reserved_area(unsigned long long start, +static int fadump_exclude_reserved_area(unsigned long long start, unsigned long long end) { unsigned long long ra_start, ra_end; + int ret = 0; ra_start = fw_dump.reserve_dump_area_start; ra_end = ra_start + fw_dump.reserve_dump_area_size; if ((ra_start < end) && (ra_end > start)) { if ((start < ra_start) && (end > ra_end)) { - fadump_add_crash_memory(start, ra_start); - fadump_add_crash_memory(ra_end, end); + ret = fadump_add_crash_memory(start, ra_start); + if (ret) + return ret; + + ret = fadump_add_crash_memory(ra_end, end); } else if (start < ra_start) { - fadump_add_crash_memory(start, ra_start); + ret = fadump_add_crash_memory(start, ra_start); } else if (ra_end < end) { - fadump_add_crash_memory(ra_end, end); + ret = fadump_add_crash_memory(ra_end, end); } } else - fadump_add_crash_memory(start, end); + ret = fadump_add_crash_memory(start, end); + + return ret; } static int fadump_init_elfcore_header(char *bufp) @@ -914,10 +966,11 @@ static int fadump_init_elfcore_header(char *bufp) * Traverse through memblock structure and setup crash memory ranges. These * ranges will be used create PT_LOAD program headers in elfcore header. */ -static void fadump_setup_crash_memory_ranges(void) +static int fadump_setup_crash_memory_ranges(void) { struct memblock_region *reg; unsigned long long start, end; + int ret; pr_debug("Setup crash memory ranges.\n"); crash_mem_ranges = 0; @@ -928,7 +981,9 @@ static void fadump_setup_crash_memory_ranges(void) * specified during fadump registration. We need to create a separate * program header for this chunk with the correct offset. */ - fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size); + ret = fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size); + if (ret) + return ret; for_each_memblock(memory, reg) { start = (unsigned long long)reg->base; @@ -948,8 +1003,12 @@ static void fadump_setup_crash_memory_ranges(void) } /* add this range excluding the reserved dump area. */ - fadump_exclude_reserved_area(start, end); + ret = fadump_exclude_reserved_area(start, end); + if (ret) + return ret; } + + return 0; } /* @@ -1072,6 +1131,7 @@ static int register_fadump(void) { unsigned long addr; void *vaddr; + int ret; /* * If no memory is reserved then we can not register for firmware- @@ -1080,7 +1140,9 @@ static int register_fadump(void) if (!fw_dump.reserve_dump_area_size) return -ENODEV; - fadump_setup_crash_memory_ranges(); + ret = fadump_setup_crash_memory_ranges(); + if (ret) + return ret; addr = be64_to_cpu(fdm.rmr_region.destination_address) + be64_to_cpu(fdm.rmr_region.source_len); /* Initialize fadump crash info header. */ @@ -1158,6 +1220,7 @@ void fadump_cleanup(void) } else if (fw_dump.dump_registered) { /* Un-register Firmware-assisted dump if it was registered. */ fadump_unregister_dump(&fdm); + free_crash_memory_ranges(); } } diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index 2694d078741d08c9f32a05c7ea6323867ddde63d..9dafd7af39b8f517b68ab254e1ec134fffd993e8 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c @@ -186,7 +186,12 @@ void __init reserve_crashkernel(void) (unsigned long)(crashk_res.start >> 20), (unsigned long)(memblock_phys_mem_size() >> 20)); - memblock_reserve(crashk_res.start, crash_size); + if (!memblock_is_region_memory(crashk_res.start, crash_size) || + memblock_reserve(crashk_res.start, crash_size)) { + pr_err("Failed to reserve memory for crashkernel!\n"); + crashk_res.start = crashk_res.end = 0; + return; + } } int overlaps_crashkernel(unsigned long start, unsigned long size) diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 377d1420bd0243cc593e010657ac25351d9770b3..58746328b9bd6df7854973b5bea9fff040b2835c 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -4356,6 +4356,8 @@ static int kvmppc_book3s_init_hv(void) pr_err("KVM-HV: Cannot determine method for accessing XICS\n"); return -ENODEV; } + /* presence of intc confirmed - node can be dropped again */ + of_node_put(np); } #endif diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c index 816055927ee47ba05db7e1d3675461de66052636..d735937d975c8dca1b32f021e04ecb5fb47e703c 100644 --- a/arch/powerpc/mm/mmu_context_iommu.c +++ b/arch/powerpc/mm/mmu_context_iommu.c @@ -130,6 +130,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, long i, j, ret = 0, locked_entries = 0; unsigned int pageshift; unsigned long flags; + unsigned long cur_ua; struct page *page = NULL; mutex_lock(&mem_list_mutex); @@ -178,7 +179,8 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, } for (i = 0; i < entries; ++i) { - if (1 != get_user_pages_fast(ua + (i << PAGE_SHIFT), + cur_ua = ua + (i << PAGE_SHIFT); + if (1 != get_user_pages_fast(cur_ua, 1/* pages */, 1/* iswrite */, &page)) { ret = -EFAULT; for (j = 0; j < i; ++j) @@ -197,7 +199,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, if (is_migrate_cma_page(page)) { if (mm_iommu_move_page_from_cma(page)) goto populate; - if (1 != get_user_pages_fast(ua + (i << PAGE_SHIFT), + if (1 != get_user_pages_fast(cur_ua, 1/* pages */, 1/* iswrite */, &page)) { ret = -EFAULT; @@ -211,20 +213,21 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, } populate: pageshift = PAGE_SHIFT; - if (PageCompound(page)) { + if (mem->pageshift > PAGE_SHIFT && PageCompound(page)) { pte_t *pte; struct page *head = compound_head(page); unsigned int compshift = compound_order(head); + unsigned int pteshift; local_irq_save(flags); /* disables as well */ - pte = find_linux_pte(mm->pgd, ua, NULL, &pageshift); - local_irq_restore(flags); + pte = find_linux_pte(mm->pgd, cur_ua, NULL, &pteshift); /* Double check it is still the same pinned page */ if (pte && pte_page(*pte) == head && - pageshift == compshift) - pageshift = max_t(unsigned int, pageshift, + pteshift == compshift + PAGE_SHIFT) + pageshift = max_t(unsigned int, pteshift, PAGE_SHIFT); + local_irq_restore(flags); } mem->pageshift = min(mem->pageshift, pageshift); mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT; diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 254634fb3fc75198b037c3a8e68da1baf16ac424..fee1e1f8c9d3a059db0144009cf523bc69c1854e 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -322,6 +322,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u64 imm64; u8 *func; u32 true_cond; + u32 tmp_idx; /* * addrs[] maps a BPF bytecode address into a real offset from @@ -681,11 +682,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, case BPF_STX | BPF_XADD | BPF_W: /* Get EA into TMP_REG_1 */ PPC_ADDI(b2p[TMP_REG_1], dst_reg, off); - /* error if EA is not word-aligned */ - PPC_ANDI(b2p[TMP_REG_2], b2p[TMP_REG_1], 0x03); - PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + 12); - PPC_LI(b2p[BPF_REG_0], 0); - PPC_JMP(exit_addr); + tmp_idx = ctx->idx * 4; /* load value from memory into TMP_REG_2 */ PPC_BPF_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0); /* add value from src_reg into this */ @@ -693,32 +690,16 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, /* store result back */ PPC_BPF_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]); /* we're done if this succeeded */ - PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (7*4)); - /* otherwise, let's try once more */ - PPC_BPF_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0); - PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg); - PPC_BPF_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]); - /* exit if the store was not successful */ - PPC_LI(b2p[BPF_REG_0], 0); - PPC_BCC(COND_NE, exit_addr); + PPC_BCC_SHORT(COND_NE, tmp_idx); break; /* *(u64 *)(dst + off) += src */ case BPF_STX | BPF_XADD | BPF_DW: PPC_ADDI(b2p[TMP_REG_1], dst_reg, off); - /* error if EA is not doubleword-aligned */ - PPC_ANDI(b2p[TMP_REG_2], b2p[TMP_REG_1], 0x07); - PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (3*4)); - PPC_LI(b2p[BPF_REG_0], 0); - PPC_JMP(exit_addr); - PPC_BPF_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0); - PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg); - PPC_BPF_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]); - PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (7*4)); + tmp_idx = ctx->idx * 4; PPC_BPF_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0); PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg); PPC_BPF_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]); - PPC_LI(b2p[BPF_REG_0], 0); - PPC_BCC(COND_NE, exit_addr); + PPC_BCC_SHORT(COND_NE, tmp_idx); break; /* diff --git a/arch/powerpc/platforms/85xx/t1042rdb_diu.c b/arch/powerpc/platforms/85xx/t1042rdb_diu.c index 58fa3d319f1c118247732b6d2e7e7583279ea450..dac36ba82fea8555576cd63c4d2e29c343b605da 100644 --- a/arch/powerpc/platforms/85xx/t1042rdb_diu.c +++ b/arch/powerpc/platforms/85xx/t1042rdb_diu.c @@ -9,8 +9,10 @@ * option) any later version. */ +#include #include #include +#include #include #include @@ -150,3 +152,5 @@ static int __init t1042rdb_diu_init(void) } early_initcall(t1042rdb_diu_init); + +MODULE_LICENSE("GPL"); diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 63f007f2de7eb295b9bb78821e2dca596a96e56f..4b95bdde22aa7874499a1a9b4e71c691798d72b1 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c @@ -427,8 +427,9 @@ static int get_mmio_atsd_reg(struct npu *npu) int i; for (i = 0; i < npu->mmio_atsd_count; i++) { - if (!test_and_set_bit_lock(i, &npu->mmio_atsd_usage)) - return i; + if (!test_bit(i, &npu->mmio_atsd_usage)) + if (!test_and_set_bit_lock(i, &npu->mmio_atsd_usage)) + return i; } return -ENOSPC; diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 65c79ecf5a4d685c3c2d5035a18b196bb9664f63..c8a743af6bf507d2a0f2d63e34bb20234a275d83 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -388,7 +388,7 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) /* Closed or other error drop */ if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && rc != OPAL_BUSY_EVENT) { - written = total_len; + written += total_len; break; } if (rc == OPAL_SUCCESS) { diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 677b29ef4532b15c8dfa2aec01b2405ced8454f3..ddef22e00ddd74e84e38ec2c6ec2193e36741112 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2787,7 +2787,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset, level_shift = entries_shift + 3; level_shift = max_t(unsigned, level_shift, PAGE_SHIFT); - if ((level_shift - 3) * levels + page_shift >= 60) + if ((level_shift - 3) * levels + page_shift >= 55) return -EINVAL; /* Allocate TCE table */ @@ -3286,12 +3286,49 @@ static void pnv_pci_ioda_create_dbgfs(void) #endif /* CONFIG_DEBUG_FS */ } +static void pnv_pci_enable_bridge(struct pci_bus *bus) +{ + struct pci_dev *dev = bus->self; + struct pci_bus *child; + + /* Empty bus ? bail */ + if (list_empty(&bus->devices)) + return; + + /* + * If there's a bridge associated with that bus enable it. This works + * around races in the generic code if the enabling is done during + * parallel probing. This can be removed once those races have been + * fixed. + */ + if (dev) { + int rc = pci_enable_device(dev); + if (rc) + pci_err(dev, "Error enabling bridge (%d)\n", rc); + pci_set_master(dev); + } + + /* Perform the same to child busses */ + list_for_each_entry(child, &bus->children, node) + pnv_pci_enable_bridge(child); +} + +static void pnv_pci_enable_bridges(void) +{ + struct pci_controller *hose; + + list_for_each_entry(hose, &hose_list, list_node) + pnv_pci_enable_bridge(hose->bus); +} + static void pnv_pci_ioda_fixup(void) { pnv_pci_ioda_setup_PEs(); pnv_pci_ioda_setup_iommu_api(); pnv_pci_ioda_create_dbgfs(); + pnv_pci_enable_bridges(); + #ifdef CONFIG_EEH eeh_init(); eeh_addr_cache_build(); diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 5e1ef915018208c3511ef0e91c0064c8c9474389..99d1152ae22413a5b8139ad9c9f0d9328a96d336 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -360,7 +360,7 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs) } savep = __va(regs->gpr[3]); - regs->gpr[3] = savep[0]; /* restore original r3 */ + regs->gpr[3] = be64_to_cpu(savep[0]); /* restore original r3 */ /* If it isn't an extended log we can use the per cpu 64bit buffer */ h = (struct rtas_error_log *)&savep[1]; @@ -371,7 +371,7 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs) int len, error_log_length; error_log_length = 8 + rtas_error_extended_log_length(h); - len = max_t(int, error_log_length, RTAS_ERROR_LOG_MAX); + len = min_t(int, error_log_length, RTAS_ERROR_LOG_MAX); memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX); memcpy(global_mce_data_buf, h, len); errhdr = (struct rtas_error_log *)global_mce_data_buf; diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index eb69a51862431cccc81034f1fb9a1c8decc906d2..280e964e1aa8873db4491f42df93ddc115e85509 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c @@ -196,7 +196,7 @@ static int mpic_msgr_probe(struct platform_device *dev) /* IO map the message register block. */ of_address_to_resource(np, 0, &rsrc); - msgr_block_addr = ioremap(rsrc.start, rsrc.end - rsrc.start); + msgr_block_addr = ioremap(rsrc.start, resource_size(&rsrc)); if (!msgr_block_addr) { dev_err(&dev->dev, "Failed to iomap MPIC message registers"); return -EFAULT; diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c index a4e903ed7e21c0ccc7ceb66944ac6b43662003ea..b429aceff050a7bfd6d7abcf68cd95c08d6238ba 100644 --- a/arch/s390/crypto/paes_s390.c +++ b/arch/s390/crypto/paes_s390.c @@ -212,7 +212,7 @@ static int cbc_paes_crypt(struct blkcipher_desc *desc, unsigned long modifier, walk->dst.virt.addr, walk->src.virt.addr, n); if (k) ret = blkcipher_walk_done(desc, walk, nbytes - k); - if (n < k) { + if (k < n) { if (__cbc_paes_set_key(ctx) != 0) return blkcipher_walk_done(desc, walk, -EIO); memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index de11ecc99c7c46cf967a96c573f1a6c6d2cafc46..9c9970a5dfb10798ddd459dbcff7beae2d9ea42c 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -262,7 +262,6 @@ struct qdio_outbuf_state { void *user; }; -#define QDIO_OUTBUF_STATE_FLAG_NONE 0x00 #define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01 #define CHSC_AC1_INITIATE_INPUTQ 0x80 diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 9f5ea9d870690aea40742e4d5b3181bb637623cc..9b0216d571adc04b6bb9876c14d756cb297a4bbc 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -404,11 +404,13 @@ static void *get_vmcoreinfo_old(unsigned long *size) if (copy_oldmem_kernel(nt_name, addr + sizeof(note), sizeof(nt_name) - 1)) return NULL; - if (strcmp(nt_name, "VMCOREINFO") != 0) + if (strcmp(nt_name, VMCOREINFO_NOTE_NAME) != 0) return NULL; vmcoreinfo = kzalloc_panic(note.n_descsz); - if (copy_oldmem_kernel(vmcoreinfo, addr + 24, note.n_descsz)) + if (copy_oldmem_kernel(vmcoreinfo, addr + 24, note.n_descsz)) { + kfree(vmcoreinfo); return NULL; + } *size = note.n_descsz; return vmcoreinfo; } @@ -418,15 +420,20 @@ static void *get_vmcoreinfo_old(unsigned long *size) */ static void *nt_vmcoreinfo(void *ptr) { + const char *name = VMCOREINFO_NOTE_NAME; unsigned long size; void *vmcoreinfo; vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size); - if (!vmcoreinfo) - vmcoreinfo = get_vmcoreinfo_old(&size); + if (vmcoreinfo) + return nt_init_name(ptr, 0, vmcoreinfo, size, name); + + vmcoreinfo = get_vmcoreinfo_old(&size); if (!vmcoreinfo) return ptr; - return nt_init_name(ptr, 0, vmcoreinfo, size, "VMCOREINFO"); + ptr = nt_init_name(ptr, 0, vmcoreinfo, size, name); + kfree(vmcoreinfo); + return ptr; } /* diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index a441cba8d165c5c034cfa5bb72628eaf885f1498..b0fad29c1427fccf76584e6d434ca83d6d877949 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -59,6 +59,8 @@ int stsi(void *sysinfo, int fc, int sel1, int sel2) } EXPORT_SYMBOL(stsi); +#ifdef CONFIG_PROC_FS + static bool convert_ext_name(unsigned char encoding, char *name, size_t len) { switch (encoding) { @@ -311,6 +313,8 @@ static int __init sysinfo_create_proc(void) } device_initcall(sysinfo_create_proc); +#endif /* CONFIG_PROC_FS */ + /* * Service levels interface. */ diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 4f1f5fc8139d881078720f42f4e6d907ee3fa342..061906f98dc5cc95cd3c965535d0dd9cb2083a9e 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -170,7 +170,8 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) return set_validity_icpt(scb_s, 0x0039U); /* copy only the wrapping keys */ - if (read_guest_real(vcpu, crycb_addr + 72, &vsie_page->crycb, 56)) + if (read_guest_real(vcpu, crycb_addr + 72, + vsie_page->crycb.dea_wrapping_key_mask, 56)) return set_validity_icpt(scb_s, 0x0035U); scb_s->ecb3 |= ecb3_flags; diff --git a/arch/s390/lib/mem.S b/arch/s390/lib/mem.S index e1fa974ac5005e7909996d9075fd30c13964cd8a..37e52118d7e9ef23ed28701f67a41514caf40605 100644 --- a/arch/s390/lib/mem.S +++ b/arch/s390/lib/mem.S @@ -17,7 +17,7 @@ ENTRY(memmove) ltgr %r4,%r4 lgr %r1,%r2 - bzr %r14 + jz .Lmemmove_exit aghi %r4,-1 clgr %r2,%r3 jnh .Lmemmove_forward @@ -36,6 +36,7 @@ ENTRY(memmove) .Lmemmove_forward_remainder: larl %r5,.Lmemmove_mvc ex %r4,0(%r5) +.Lmemmove_exit: BR_EX %r14 .Lmemmove_reverse: ic %r0,0(%r4,%r3) @@ -65,7 +66,7 @@ EXPORT_SYMBOL(memmove) */ ENTRY(memset) ltgr %r4,%r4 - bzr %r14 + jz .Lmemset_exit ltgr %r3,%r3 jnz .Lmemset_fill aghi %r4,-1 @@ -80,12 +81,13 @@ ENTRY(memset) .Lmemset_clear_remainder: larl %r3,.Lmemset_xc ex %r4,0(%r3) +.Lmemset_exit: BR_EX %r14 .Lmemset_fill: stc %r3,0(%r2) cghi %r4,1 lgr %r1,%r2 - ber %r14 + je .Lmemset_fill_exit aghi %r4,-2 srlg %r3,%r4,8 ltgr %r3,%r3 @@ -97,6 +99,7 @@ ENTRY(memset) .Lmemset_fill_remainder: larl %r3,.Lmemset_mvc ex %r4,0(%r3) +.Lmemset_fill_exit: BR_EX %r14 .Lmemset_xc: xc 0(1,%r1),0(%r1) @@ -111,7 +114,7 @@ EXPORT_SYMBOL(memset) */ ENTRY(memcpy) ltgr %r4,%r4 - bzr %r14 + jz .Lmemcpy_exit aghi %r4,-1 srlg %r5,%r4,8 ltgr %r5,%r5 @@ -120,6 +123,7 @@ ENTRY(memcpy) .Lmemcpy_remainder: larl %r5,.Lmemcpy_mvc ex %r4,0(%r5) +.Lmemcpy_exit: BR_EX %r14 .Lmemcpy_loop: mvc 0(256,%r1),0(%r3) diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 920d408945359351e20e2ae397598390a0ad2f27..290e71e57541cb4c7b1c512aff333797e31684ee 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -80,7 +80,7 @@ struct qin64 { struct dcss_segment { struct list_head list; char dcss_name[8]; - char res_name[15]; + char res_name[16]; unsigned long start_addr; unsigned long end; atomic_t ref_count; @@ -433,7 +433,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long memcpy(&seg->res_name, seg->dcss_name, 8); EBCASC(seg->res_name, 8); seg->res_name[8] = '\0'; - strncat(seg->res_name, " (DCSS)", 7); + strlcat(seg->res_name, " (DCSS)", sizeof(seg->res_name)); seg->res->name = seg->res_name; rc = seg->vm_segtype; if (rc == SEG_TYPE_SC || diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 242b78c0a9ec84ba7a956d197cdd887bf86c9ebd..40f1888bc4ab7d9504d47190ac36a1692aa3671b 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -486,6 +486,8 @@ static inline int do_exception(struct pt_regs *regs, int access) /* No reason to continue if interrupted by SIGKILL. */ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) { fault = VM_FAULT_SIGNAL; + if (flags & FAULT_FLAG_RETRY_NOWAIT) + goto out_up; goto out; } if (unlikely(fault & VM_FAULT_ERROR)) diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c index 382153ff17e30e5203b217654d6b25fa0ddd78e6..dc3cede7f2ec9df1a886fc3e92821f2b7f9c6195 100644 --- a/arch/s390/mm/page-states.c +++ b/arch/s390/mm/page-states.c @@ -271,7 +271,7 @@ void arch_set_page_states(int make_stable) list_for_each(l, &zone->free_area[order].free_list[t]) { page = list_entry(l, struct page, lru); if (make_stable) - set_page_stable_dat(page, 0); + set_page_stable_dat(page, order); else set_page_unused(page, order); } diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c index 334b6d103cbd191ce877f7a65b696d1384de96e2..29653f713162d3f2d2377ce55aef5f754f98452f 100644 --- a/arch/s390/mm/pgalloc.c +++ b/arch/s390/mm/pgalloc.c @@ -27,7 +27,7 @@ static struct ctl_table page_table_sysctl[] = { .data = &page_table_allocate_pgste, .maxlen = sizeof(int), .mode = S_IRUGO | S_IWUSR, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = &page_table_allocate_pgste_min, .extra2 = &page_table_allocate_pgste_max, }, diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 11cd151733d43a4a8e9d0c992a4005ca8dc1e509..6b1474fa99ab3f98f68227fa97fc4d0768445ac3 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -518,8 +518,6 @@ static void bpf_jit_epilogue(struct bpf_jit *jit) /* br %r1 */ _EMIT2(0x07f1); } else { - /* larl %r1,.+14 */ - EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14); /* ex 0,S390_lowcore.br_r1_tampoline */ EMIT4_DISP(0x44000000, REG_0, REG_0, offsetof(struct lowcore, br_r1_trampoline)); @@ -1403,6 +1401,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) goto free_addrs; } if (bpf_jit_prog(&jit, fp)) { + bpf_jit_binary_free(header); fp = orig_fp; goto free_addrs; } diff --git a/arch/s390/numa/numa.c b/arch/s390/numa/numa.c index 06a80434cfe63f69c7c7ff2e86caba734161484e..5bd374491f9461467790e1e0522f838827f094df 100644 --- a/arch/s390/numa/numa.c +++ b/arch/s390/numa/numa.c @@ -134,26 +134,14 @@ void __init numa_setup(void) { pr_info("NUMA mode: %s\n", mode->name); nodes_clear(node_possible_map); + /* Initially attach all possible CPUs to node 0. */ + cpumask_copy(&node_to_cpumask_map[0], cpu_possible_mask); if (mode->setup) mode->setup(); numa_setup_memory(); memblock_dump_all(); } -/* - * numa_init_early() - Initialization initcall - * - * This runs when only one CPU is online and before the first - * topology update is called for by the scheduler. - */ -static int __init numa_init_early(void) -{ - /* Attach all possible CPUs to node 0 for now. */ - cpumask_copy(&node_to_cpumask_map[0], cpu_possible_mask); - return 0; -} -early_initcall(numa_init_early); - /* * numa_init_late() - Initialization initcall * diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 0fe649c0d5423a2ed51fcff4dc7d011204fdf4e9..960c4a362d8cdeb525bf020729cd8007bfa836ec 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -420,6 +420,8 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) hwirq = 0; for_each_pci_msi_entry(msi, pdev) { rc = -EIO; + if (hwirq >= msi_vecs) + break; irq = irq_alloc_desc(0); /* Alloc irq on node 0 */ if (irq < 0) return -ENOMEM; diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 80ddc01f57ac347957a2e05348ada69ca47e226f..fcbc0c0aa087db6adfb91a4b40c6a666922ae96f 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -14,6 +14,7 @@ generic-y += local64.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h generic-y += module.h +generic-y += msi.h generic-y += preempt.h generic-y += rwsem.h generic-y += serial.h diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 990703b7cf4d7d47d26152e510706bc32528d488..4b7719b2a73c671d35412d27334c62001e32a866 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -204,23 +204,27 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, asmlinkage long sys_getdomainname(char __user *name, int len) { - int nlen, err; - + int nlen, err; + char tmp[__NEW_UTS_LEN + 1]; + if (len < 0) return -EINVAL; - down_read(&uts_sem); - + down_read(&uts_sem); + nlen = strlen(utsname()->domainname) + 1; err = -EINVAL; if (nlen > len) - goto out; + goto out_unlock; + memcpy(tmp, utsname()->domainname, nlen); - err = -EFAULT; - if (!copy_to_user(name, utsname()->domainname, nlen)) - err = 0; + up_read(&uts_sem); -out: + if (copy_to_user(name, tmp, nlen)) + return -EFAULT; + return 0; + +out_unlock: up_read(&uts_sem); return err; } diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 55416db482add475baf4c2fc312605577442470f..d79c1c74873cfdcf0ac3e26c521a4623508d14dc 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -527,23 +527,27 @@ extern void check_pending(int signum); SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len) { - int nlen, err; + int nlen, err; + char tmp[__NEW_UTS_LEN + 1]; if (len < 0) return -EINVAL; - down_read(&uts_sem); - + down_read(&uts_sem); + nlen = strlen(utsname()->domainname) + 1; err = -EINVAL; if (nlen > len) - goto out; + goto out_unlock; + memcpy(tmp, utsname()->domainname, nlen); + + up_read(&uts_sem); - err = -EFAULT; - if (!copy_to_user(name, utsname()->domainname, nlen)) - err = 0; + if (copy_to_user(name, tmp, nlen)) + return -EFAULT; + return 0; -out: +out_unlock: up_read(&uts_sem); return err; } diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 3b397081047af69a23b6672917e1706786d3134f..83aaf4888999281a3c20f19c014a13d7b7521d65 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -813,7 +813,7 @@ static void __init get_tick_patch(void) } } -static void init_tick_ops(struct sparc64_tick_ops *ops) +static void __init init_tick_ops(struct sparc64_tick_ops *ops) { unsigned long freq, quotient, tick; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1c63a4b5320da6139f5f334f967677c1165a7690..2af0af33362a6c8cf3f000da56af9679d1ce952e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -170,6 +170,7 @@ config X86 select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP select HAVE_RCU_TABLE_FREE + select HAVE_RCU_TABLE_INVALIDATE if HAVE_RCU_TABLE_FREE select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RELIABLE_STACKTRACE if X86_64 && UNWINDER_FRAME_POINTER && STACK_VALIDATION select HAVE_STACK_VALIDATION if X86_64 diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 98018a621f6b0c4d0dcc32fed7e5ac94c7d3cf93..3a250ca2406c0d606f6386cdded977b56ddccffc 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -104,9 +104,13 @@ define cmd_check_data_rel done endef +# We need to run two commands under "if_changed", so merge them into a +# single invocation. +quiet_cmd_check-and-link-vmlinux = LD $@ + cmd_check-and-link-vmlinux = $(cmd_check_data_rel); $(cmd_ld) + $(obj)/vmlinux: $(vmlinux-objs-y) FORCE - $(call if_changed,check_data_rel) - $(call if_changed,ld) + $(call if_changed,check-and-link-vmlinux) OBJCOPYFLAGS_vmlinux.bin := -R .comment -S $(obj)/vmlinux.bin: vmlinux FORCE diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 0fae7096ae23cc5372cc78fa43ebfaa84f0e66a7..164cd7529f0b080a0993797f9260ada24ca75d82 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -88,7 +88,7 @@ END(native_usergs_sysret64) .endm .macro TRACE_IRQS_IRETQ_DEBUG - bt $9, EFLAGS(%rsp) /* interrupts off? */ + btl $9, EFLAGS(%rsp) /* interrupts off? */ jnc 1f TRACE_IRQS_ON_DEBUG 1: @@ -630,7 +630,7 @@ retint_kernel: #ifdef CONFIG_PREEMPT /* Interrupts are off */ /* Check if we need preemption */ - bt $9, EFLAGS(%rsp) /* were interrupts off? */ + btl $9, EFLAGS(%rsp) /* were interrupts off? */ jnc 1f 0: cmpl $0, PER_CPU_VAR(__preempt_count) jnz 1f diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index f5c1007e2c408bf484ac816fd8ffe1f6bd506723..7faa3bab63452e4d76fd7fb5dc89f0778e64104d 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile @@ -74,9 +74,9 @@ $(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \ $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \ -fno-omit-frame-pointer -foptimize-sibling-calls \ - -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO + -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO $(RETPOLINE_VDSO_CFLAGS) -$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) $(CFL) +$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL) # # vDSO code runs in userspace and -pg doesn't help with profiling anyway. @@ -147,11 +147,13 @@ KBUILD_CFLAGS_32 := $(filter-out -mcmodel=kernel,$(KBUILD_CFLAGS_32)) KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32)) KBUILD_CFLAGS_32 := $(filter-out -mfentry,$(KBUILD_CFLAGS_32)) KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32)) +KBUILD_CFLAGS_32 := $(filter-out $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS_32)) KBUILD_CFLAGS_32 += -m32 -msoft-float -mregparm=0 -fpic KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector) KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls) KBUILD_CFLAGS_32 += -fno-omit-frame-pointer KBUILD_CFLAGS_32 += -DDISABLE_BRANCH_PROFILING +KBUILD_CFLAGS_32 += $(RETPOLINE_VDSO_CFLAGS) $(obj)/vdso32.so.dbg: KBUILD_CFLAGS = $(KBUILD_CFLAGS_32) $(obj)/vdso32.so.dbg: FORCE \ diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c index 786fd875de9287d8745bb7ec42d52fc7a2a4dac0..8c51844694e2f07f8351b27640a94bad7ab59c76 100644 --- a/arch/x86/events/amd/ibs.c +++ b/arch/x86/events/amd/ibs.c @@ -579,7 +579,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) { struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu); struct perf_event *event = pcpu->event; - struct hw_perf_event *hwc = &event->hw; + struct hw_perf_event *hwc; struct perf_sample_data data; struct perf_raw_record raw; struct pt_regs regs; @@ -602,6 +602,10 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) return 0; } + if (WARN_ON_ONCE(!event)) + goto fail; + + hwc = &event->hw; msr = hwc->config_base; buf = ibs_data.regs; rdmsrl(msr, *buf); diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 717c9219d00ec3fbdc6ebea65277bfc6025dc8fa..e5097dc85a06cf73d4da6b93aa3f5d34b9bdad6a 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2462,7 +2462,7 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs perf_callchain_store(entry, regs->ip); - if (!current->mm) + if (!nmi_uaccess_okay()) return; if (perf_callchain_user32(regs, entry)) diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index cf372b90557ed4e8a788c8f97b515ac956d2512e..a4170048a30bc32b75f976dc46cd85452b57de88 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -346,7 +346,7 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx) mask = x86_pmu.lbr_nr - 1; tos = task_ctx->tos; - for (i = 0; i < tos; i++) { + for (i = 0; i < task_ctx->valid_lbrs; i++) { lbr_idx = (tos - i) & mask; wrlbr_from(lbr_idx, task_ctx->lbr_from[i]); wrlbr_to (lbr_idx, task_ctx->lbr_to[i]); @@ -354,6 +354,15 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx) if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO) wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]); } + + for (; i < x86_pmu.lbr_nr; i++) { + lbr_idx = (tos - i) & mask; + wrlbr_from(lbr_idx, 0); + wrlbr_to(lbr_idx, 0); + if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO) + wrmsrl(MSR_LBR_INFO_0 + lbr_idx, 0); + } + wrmsrl(x86_pmu.lbr_tos, tos); task_ctx->lbr_stack_state = LBR_NONE; } @@ -361,7 +370,7 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx) static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx) { unsigned lbr_idx, mask; - u64 tos; + u64 tos, from; int i; if (task_ctx->lbr_callstack_users == 0) { @@ -371,13 +380,17 @@ static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx) mask = x86_pmu.lbr_nr - 1; tos = intel_pmu_lbr_tos(); - for (i = 0; i < tos; i++) { + for (i = 0; i < x86_pmu.lbr_nr; i++) { lbr_idx = (tos - i) & mask; - task_ctx->lbr_from[i] = rdlbr_from(lbr_idx); + from = rdlbr_from(lbr_idx); + if (!from) + break; + task_ctx->lbr_from[i] = from; task_ctx->lbr_to[i] = rdlbr_to(lbr_idx); if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO) rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]); } + task_ctx->valid_lbrs = i; task_ctx->tos = tos; task_ctx->lbr_stack_state = LBR_VALID; } @@ -531,7 +544,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) */ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) { - bool need_info = false; + bool need_info = false, call_stack = false; unsigned long mask = x86_pmu.lbr_nr - 1; int lbr_format = x86_pmu.intel_cap.lbr_format; u64 tos = intel_pmu_lbr_tos(); @@ -542,7 +555,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) if (cpuc->lbr_sel) { need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO); if (cpuc->lbr_sel->config & LBR_CALL_STACK) - num = tos; + call_stack = true; } for (i = 0; i < num; i++) { @@ -555,6 +568,13 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) from = rdlbr_from(lbr_idx); to = rdlbr_to(lbr_idx); + /* + * Read LBR call stack entries + * until invalid entry (0s) is detected. + */ + if (call_stack && !from) + break; + if (lbr_format == LBR_FORMAT_INFO && need_info) { u64 info; diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index dc4728eccfd86c4a2a97894f53b05b658a6e0155..c6698c63c047b170a17bf508071ba25218565464 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -646,6 +646,7 @@ struct x86_perf_task_context { u64 lbr_to[MAX_LBR_ENTRIES]; u64 lbr_info[MAX_LBR_ENTRIES]; int tos; + int valid_lbrs; int lbr_callstack_users; int lbr_stack_state; }; diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index e203169931c721b7958c940694458c11a270b982..6390bd8c141b44cd988dd21bc4b5b3efbbf1688b 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -14,6 +14,16 @@ #ifndef _ASM_X86_FIXMAP_H #define _ASM_X86_FIXMAP_H +/* + * Exposed to assembly code for setting up initial page tables. Cannot be + * calculated in assembly code (fixmap entries are an enum), but is sanity + * checked in the actual fixmap C code to make sure that the fixmap is + * covered fully. + */ +#define FIXMAP_PMD_NUM 2 +/* fixmap starts downwards from the 507th entry in level2_fixmap_pgt */ +#define FIXMAP_PMD_TOP 507 + #ifndef __ASSEMBLY__ #include #include diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index c14f2a74b2be7495f1ee00c92322a58cc43d10a6..15450a675031d3562b4a9da3d3b15816c11003fb 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -33,7 +33,8 @@ extern inline unsigned long native_save_fl(void) return flags; } -static inline void native_restore_fl(unsigned long flags) +extern inline void native_restore_fl(unsigned long flags); +extern inline void native_restore_fl(unsigned long flags) { asm volatile("push %0 ; popf" : /* no output */ diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 340070415c2c3a93b0305ed7624ceaa62bd4362f..90fef69e4c5a1e327e0aee654d0240f70a562ca9 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -200,6 +200,7 @@ enum mce_notifier_prios { MCE_PRIO_LOWEST = 0, }; +struct notifier_block; extern void mce_register_decode_chain(struct notifier_block *nb); extern void mce_unregister_decode_chain(struct notifier_block *nb); diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 9dc19b4a2a870398e57239c9af545924713b0b49..c5d4931d1ef9b97088dd13e5cf3fbd8a3ab12f5f 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_PGTABLE_3LEVEL_H #define _ASM_X86_PGTABLE_3LEVEL_H +#include + /* * Intel Physical Address Extension (PAE) Mode - three-level page * tables on PPro+ CPUs. @@ -147,10 +149,7 @@ static inline pte_t native_ptep_get_and_clear(pte_t *ptep) { pte_t res; - /* xchg acts as a barrier before the setting of the high bits */ - res.pte_low = xchg(&ptep->pte_low, 0); - res.pte_high = ptep->pte_high; - ptep->pte_high = 0; + res.pte = (pteval_t)atomic64_xchg((atomic64_t *)ptep, 0); return res; } diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 4ecb728319384759eeb9c96eb94bbec7faf79aba..ef938583147ea4d7775c23427f8b13e77ae1a21a 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -14,6 +14,7 @@ #include #include #include +#include extern p4d_t level4_kernel_pgt[512]; extern p4d_t level4_ident_pgt[512]; @@ -22,7 +23,7 @@ extern pud_t level3_ident_pgt[512]; extern pmd_t level2_kernel_pgt[512]; extern pmd_t level2_fixmap_pgt[512]; extern pmd_t level2_ident_pgt[512]; -extern pte_t level1_fixmap_pgt[512]; +extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM]; extern pgd_t init_top_pgt[]; #define swapper_pg_dir init_top_pgt diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 0e856c0628b350dd6d1aca368e213a927156da07..b12c8d70dd33d0044c60f2c324717d62d631e086 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -132,6 +132,8 @@ struct cpuinfo_x86 { /* Index into per_cpu list: */ u16 cpu_index; u32 microcode; + /* Address space bits used by the cache internally */ + u8 x86_cache_bits; } __randomize_layout; struct cpuid_regs { @@ -180,9 +182,9 @@ extern const struct seq_operations cpuinfo_op; extern void cpu_detect(struct cpuinfo_x86 *c); -static inline unsigned long l1tf_pfn_limit(void) +static inline unsigned long long l1tf_pfn_limit(void) { - return BIT(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT) - 1; + return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT); } extern void early_cpu_init(void); diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 875ca99b82eef003781464af111214392fdd0f5c..5f00ecb9d2515e693218d0e4a561824fe0279d94 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -175,8 +175,16 @@ struct tlb_state { * are on. This means that it may not match current->active_mm, * which will contain the previous user mm when we're in lazy TLB * mode even if we've already switched back to swapper_pg_dir. + * + * During switch_mm_irqs_off(), loaded_mm will be set to + * LOADED_MM_SWITCHING during the brief interrupts-off window + * when CR3 and loaded_mm would otherwise be inconsistent. This + * is for nmi_uaccess_okay()'s benefit. */ struct mm_struct *loaded_mm; + +#define LOADED_MM_SWITCHING ((struct mm_struct *)1) + u16 loaded_mm_asid; u16 next_asid; /* last user mm's ctx id */ @@ -246,6 +254,38 @@ struct tlb_state { }; DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); +/* + * Blindly accessing user memory from NMI context can be dangerous + * if we're in the middle of switching the current user task or + * switching the loaded mm. It can also be dangerous if we + * interrupted some kernel code that was temporarily using a + * different mm. + */ +static inline bool nmi_uaccess_okay(void) +{ + struct mm_struct *loaded_mm = this_cpu_read(cpu_tlbstate.loaded_mm); + struct mm_struct *current_mm = current->mm; + + VM_WARN_ON_ONCE(!loaded_mm); + + /* + * The condition we want to check is + * current_mm->pgd == __va(read_cr3_pa()). This may be slow, though, + * if we're running in a VM with shadow paging, and nmi_uaccess_okay() + * is supposed to be reasonably fast. + * + * Instead, we check the almost equivalent but somewhat conservative + * condition below, and we rely on the fact that switch_mm_irqs_off() + * sets loaded_mm to LOADED_MM_SWITCHING before writing to CR3. + */ + if (loaded_mm != current_mm) + return false; + + VM_WARN_ON_ONCE(current_mm->pgd != __va(read_cr3_pa())); + + return true; +} + /* Initialize cr4 shadow for this CPU. */ static inline void cr4_init_shadow(void) { diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h index 52250681f68c7410b30f42d9e424553aaed4f313..d92ccff4e615d5a868e5dd4e69834db1cf73420e 100644 --- a/arch/x86/include/asm/vgtod.h +++ b/arch/x86/include/asm/vgtod.h @@ -93,7 +93,7 @@ static inline unsigned int __getcpu(void) * * If RDPID is available, use it. */ - alternative_io ("lsl %[p],%[seg]", + alternative_io ("lsl %[seg],%[p]", ".byte 0xf3,0x0f,0xc7,0xf8", /* RDPID %eax/rax */ X86_FEATURE_RDPID, [p] "=a" (p), [seg] "r" (__PER_CPU_SEG)); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index d07addb99b7180d1aefba2c939cd421acabc1592..3e435f88621d2aa38708c1b2107b933aca62eaeb 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -652,6 +652,45 @@ EXPORT_SYMBOL_GPL(l1tf_mitigation); enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); +/* + * These CPUs all support 44bits physical address space internally in the + * cache but CPUID can report a smaller number of physical address bits. + * + * The L1TF mitigation uses the top most address bit for the inversion of + * non present PTEs. When the installed memory reaches into the top most + * address bit due to memory holes, which has been observed on machines + * which report 36bits physical address bits and have 32G RAM installed, + * then the mitigation range check in l1tf_select_mitigation() triggers. + * This is a false positive because the mitigation is still possible due to + * the fact that the cache uses 44bit internally. Use the cache bits + * instead of the reported physical bits and adjust them on the affected + * machines to 44bit if the reported bits are less than 44. + */ +static void override_cache_bits(struct cpuinfo_x86 *c) +{ + if (c->x86 != 6) + return; + + switch (c->x86_model) { + case INTEL_FAM6_NEHALEM: + case INTEL_FAM6_WESTMERE: + case INTEL_FAM6_SANDYBRIDGE: + case INTEL_FAM6_IVYBRIDGE: + case INTEL_FAM6_HASWELL_CORE: + case INTEL_FAM6_HASWELL_ULT: + case INTEL_FAM6_HASWELL_GT3E: + case INTEL_FAM6_BROADWELL_CORE: + case INTEL_FAM6_BROADWELL_GT3E: + case INTEL_FAM6_SKYLAKE_MOBILE: + case INTEL_FAM6_SKYLAKE_DESKTOP: + case INTEL_FAM6_KABYLAKE_MOBILE: + case INTEL_FAM6_KABYLAKE_DESKTOP: + if (c->x86_cache_bits < 44) + c->x86_cache_bits = 44; + break; + } +} + static void __init l1tf_select_mitigation(void) { u64 half_pa; @@ -659,6 +698,8 @@ static void __init l1tf_select_mitigation(void) if (!boot_cpu_has_bug(X86_BUG_L1TF)) return; + override_cache_bits(&boot_cpu_data); + switch (l1tf_mitigation) { case L1TF_MITIGATION_OFF: case L1TF_MITIGATION_FLUSH_NOWARN: @@ -678,14 +719,13 @@ static void __init l1tf_select_mitigation(void) return; #endif - /* - * This is extremely unlikely to happen because almost all - * systems have far more MAX_PA/2 than RAM can be fit into - * DIMM slots. - */ half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT; if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) { pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n"); + pr_info("You may make it effective by booting the kernel with mem=%llu parameter.\n", + half_pa); + pr_info("However, doing so will make a part of your RAM unusable.\n"); + pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html might help you decide.\n"); return; } diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index dd02ee4fa8cd9f4340d994e941156a279d048b46..7d2a7890a823eb7cabe8c274cb331dd348172058 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -890,6 +890,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) } } #endif + c->x86_cache_bits = c->x86_phys_bits; } static const __initconst struct x86_cpu_id cpu_no_speculation[] = { diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 278be092b3009e99d4aa6bb7dc81fa4f1622e398..574dcdc092abdcfadfe834424c3e079144ecc51f 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -150,6 +150,9 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_HYPERVISOR)) return false; + if (c->x86 != 6) + return false; + for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) { if (c->x86_model == spectre_bad_microcodes[i].model && c->x86_stepping == spectre_bad_microcodes[i].stepping) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 48179928ff38cf12476ce27cd096383aee1feb93..9d33dbf2489e2b6679131ecb3938aa4c382347f0 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -504,6 +504,7 @@ static enum ucode_state apply_microcode_amd(int cpu) struct microcode_amd *mc_amd; struct ucode_cpu_info *uci; struct ucode_patch *p; + enum ucode_state ret; u32 rev, dummy; BUG_ON(raw_smp_processor_id() != cpu); @@ -521,9 +522,8 @@ static enum ucode_state apply_microcode_amd(int cpu) /* need to apply patch? */ if (rev >= mc_amd->hdr.patch_id) { - c->microcode = rev; - uci->cpu_sig.rev = rev; - return UCODE_OK; + ret = UCODE_OK; + goto out; } if (__apply_microcode_amd(mc_amd)) { @@ -531,13 +531,21 @@ static enum ucode_state apply_microcode_amd(int cpu) cpu, mc_amd->hdr.patch_id); return UCODE_ERROR; } - pr_info("CPU%d: new patch_level=0x%08x\n", cpu, - mc_amd->hdr.patch_id); - uci->cpu_sig.rev = mc_amd->hdr.patch_id; - c->microcode = mc_amd->hdr.patch_id; + rev = mc_amd->hdr.patch_id; + ret = UCODE_UPDATED; + + pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev); - return UCODE_UPDATED; +out: + uci->cpu_sig.rev = rev; + c->microcode = rev; + + /* Update boot_cpu_data's revision too, if we're on the BSP: */ + if (c->cpu_index == boot_cpu_data.cpu_index) + boot_cpu_data.microcode = rev; + + return ret; } static int install_equiv_cpu_table(const u8 *buf) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 1c2cfa0644aa979c97cc01a42925a44c25f9f852..16936a24795c8457b789f7b428216cfc5bd1fb4e 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -190,8 +190,11 @@ static void save_microcode_patch(void *data, unsigned int size) p = memdup_patch(data, size); if (!p) pr_err("Error allocating buffer %p\n", data); - else + else { list_replace(&iter->plist, &p->plist); + kfree(iter->data); + kfree(iter); + } } } @@ -792,6 +795,7 @@ static enum ucode_state apply_microcode_intel(int cpu) struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct cpuinfo_x86 *c = &cpu_data(cpu); struct microcode_intel *mc; + enum ucode_state ret; static int prev_rev; u32 rev; @@ -814,9 +818,8 @@ static enum ucode_state apply_microcode_intel(int cpu) */ rev = intel_get_microcode_revision(); if (rev >= mc->hdr.rev) { - uci->cpu_sig.rev = rev; - c->microcode = rev; - return UCODE_OK; + ret = UCODE_OK; + goto out; } /* @@ -845,10 +848,17 @@ static enum ucode_state apply_microcode_intel(int cpu) prev_rev = rev; } + ret = UCODE_UPDATED; + +out: uci->cpu_sig.rev = rev; - c->microcode = rev; + c->microcode = rev; + + /* Update boot_cpu_data's revision too, if we're on the BSP: */ + if (c->cpu_index == boot_cpu_data.cpu_index) + boot_cpu_data.microcode = rev; - return UCODE_UPDATED; + return ret; } static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index a2d8a3908670993c898cd0d22cbdd6742e51b4da..224de37821e4ed74ae7d1a4a1f17f848b5584832 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -298,7 +299,10 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr) * We're not going to return, but we might be on an IST stack or * have very little stack space left. Rewind the stack and kill * the task. + * Before we rewind the stack, we have to tell KASAN that we're going to + * reuse the task stack and that existing poisons are invalid. */ + kasan_unpoison_task_stack(current); rewind_stack_do_exit(signr); } NOKPROBE_SYMBOL(oops_end); diff --git a/arch/x86/kernel/eisa.c b/arch/x86/kernel/eisa.c index f260e452e4f8726237618efe4b9526938d31d81d..e8c8c5d78dbdd38b1089f5dc87cf3450644fe487 100644 --- a/arch/x86/kernel/eisa.c +++ b/arch/x86/kernel/eisa.c @@ -7,11 +7,17 @@ #include #include +#include + static __init int eisa_bus_probe(void) { - void __iomem *p = ioremap(0x0FFFD9, 4); + void __iomem *p; + + if (xen_pv_domain() && !xen_initial_domain()) + return 0; - if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24)) + p = ioremap(0x0FFFD9, 4); + if (p && readl(p) == 'E' + ('I' << 8) + ('S' << 16) + ('A' << 24)) EISA_bus = 1; iounmap(p); return 0; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 7ba5d819ebe3b351ff4124ded8c598adfcb1a5f1..45b5c6c4a55edac132a855e47502eacb62225045 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -31,6 +31,7 @@ #include #include #include +#include /* * Manage page tables very early on. @@ -93,7 +94,8 @@ unsigned long __head __startup_64(unsigned long physaddr, pud[511] += load_delta; pmd = fixup_pointer(level2_fixmap_pgt, physaddr); - pmd[506] += load_delta; + for (i = FIXMAP_PMD_TOP; i > FIXMAP_PMD_TOP - FIXMAP_PMD_NUM; i--) + pmd[i] += load_delta; /* * Set up the identity mapping for the switchover. These diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 0f545b3cf926787bd986d763c843498540ef530d..8d59dfe629a96e8a53183cfb9cb4d867e039c520 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -24,6 +24,7 @@ #include "../entry/calling.h" #include #include +#include #ifdef CONFIG_PARAVIRT #include @@ -438,13 +439,20 @@ NEXT_PAGE(level2_kernel_pgt) KERNEL_IMAGE_SIZE/PMD_SIZE) NEXT_PAGE(level2_fixmap_pgt) - .fill 506,8,0 - .quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC - /* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */ - .fill 5,8,0 + .fill (512 - 4 - FIXMAP_PMD_NUM),8,0 + pgtno = 0 + .rept (FIXMAP_PMD_NUM) + .quad level1_fixmap_pgt + (pgtno << PAGE_SHIFT) - __START_KERNEL_map \ + + _PAGE_TABLE_NOENC; + pgtno = pgtno + 1 + .endr + /* 6 MB reserved space + a 2MB hole */ + .fill 4,8,0 NEXT_PAGE(level1_fixmap_pgt) + .rept (FIXMAP_PMD_NUM) .fill 512,8,0 + .endr #undef PMDS diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index f24cd9f1799a062a8df2c3c25bb164ba28537f89..928b0c6083c9cc5953fd5f47867ff218efaea910 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -532,7 +532,7 @@ static int bzImage64_cleanup(void *loader_data) static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len) { return verify_pefile_signature(kernel, kernel_len, - NULL, + VERIFY_USE_SECONDARY_KEYRING, VERIFYING_KEXEC_PE_SIGNATURE); } #endif diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 5b609e28ce3f40514be95ac47cddd5a0c4d77ab0..48703d430a2fb46470deef90963947c08e7ef945 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -143,6 +143,7 @@ static unsigned long kvm_get_tsc_khz(void) src = &hv_clock[cpu].pvti; tsc_khz = pvclock_tsc_khz(src); put_cpu(); + setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); return tsc_khz; } diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index fa093b77689f82ee547481067ba85026ebdfd29c..cbeecfcc66d68b3ae44eaa075ba7be9e49f1063b 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -370,6 +370,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) start_thread_common(regs, new_ip, new_sp, __USER_CS, __USER_DS, 0); } +EXPORT_SYMBOL_GPL(start_thread); #ifdef CONFIG_COMPAT void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 5ebb0dbcf4f7884bf12978c5817a0524d9f1313e..30447d210f37e272a08d7af707544ed2622ebf49 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -223,6 +223,11 @@ static void notrace start_secondary(void *unused) #ifdef CONFIG_X86_32 /* switch away from the initial page table */ load_cr3(swapper_pg_dir); + /* + * Initialize the CR4 shadow before doing anything that could + * try to read it. + */ + cr4_init_shadow(); __flush_tlb_all(); #endif load_current_idt(); diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c index 19afdbd7d0a77c8f5511cf2de616d24c5259dbae..5532d1be76879b452ca3c072de807eb4d9509b85 100644 --- a/arch/x86/kernel/tsc_msr.c +++ b/arch/x86/kernel/tsc_msr.c @@ -12,6 +12,7 @@ #include #include #include +#include #define MAX_NUM_FREQS 9 diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 00e2ae033a0f57b3980767c2beb5388043b35f2b..1dfb808abd23f4da506b17a79a0c8713051c1dbe 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -220,6 +220,17 @@ static const u64 shadow_acc_track_saved_bits_mask = PT64_EPT_READABLE_MASK | PT64_EPT_EXECUTABLE_MASK; static const u64 shadow_acc_track_saved_bits_shift = PT64_SECOND_AVAIL_BITS_SHIFT; +/* + * This mask must be set on all non-zero Non-Present or Reserved SPTEs in order + * to guard against L1TF attacks. + */ +static u64 __read_mostly shadow_nonpresent_or_rsvd_mask; + +/* + * The number of high-order 1 bits to use in the mask above. + */ +static const u64 shadow_nonpresent_or_rsvd_mask_len = 5; + static void mmu_spte_set(u64 *sptep, u64 spte); static void mmu_free_roots(struct kvm_vcpu *vcpu); @@ -308,9 +319,13 @@ static void mark_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, u64 gfn, { unsigned int gen = kvm_current_mmio_generation(vcpu); u64 mask = generation_mmio_spte_mask(gen); + u64 gpa = gfn << PAGE_SHIFT; access &= ACC_WRITE_MASK | ACC_USER_MASK; - mask |= shadow_mmio_value | access | gfn << PAGE_SHIFT; + mask |= shadow_mmio_value | access; + mask |= gpa | shadow_nonpresent_or_rsvd_mask; + mask |= (gpa & shadow_nonpresent_or_rsvd_mask) + << shadow_nonpresent_or_rsvd_mask_len; trace_mark_mmio_spte(sptep, gfn, access, gen); mmu_spte_set(sptep, mask); @@ -323,8 +338,14 @@ static bool is_mmio_spte(u64 spte) static gfn_t get_mmio_spte_gfn(u64 spte) { - u64 mask = generation_mmio_spte_mask(MMIO_GEN_MASK) | shadow_mmio_mask; - return (spte & ~mask) >> PAGE_SHIFT; + u64 mask = generation_mmio_spte_mask(MMIO_GEN_MASK) | shadow_mmio_mask | + shadow_nonpresent_or_rsvd_mask; + u64 gpa = spte & ~mask; + + gpa |= (spte >> shadow_nonpresent_or_rsvd_mask_len) + & shadow_nonpresent_or_rsvd_mask; + + return gpa >> PAGE_SHIFT; } static unsigned get_mmio_spte_access(u64 spte) @@ -381,7 +402,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, } EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes); -void kvm_mmu_clear_all_pte_masks(void) +static void kvm_mmu_reset_all_pte_masks(void) { shadow_user_mask = 0; shadow_accessed_mask = 0; @@ -391,6 +412,18 @@ void kvm_mmu_clear_all_pte_masks(void) shadow_mmio_mask = 0; shadow_present_mask = 0; shadow_acc_track_mask = 0; + + /* + * If the CPU has 46 or less physical address bits, then set an + * appropriate mask to guard against L1TF attacks. Otherwise, it is + * assumed that the CPU is not vulnerable to L1TF. + */ + if (boot_cpu_data.x86_phys_bits < + 52 - shadow_nonpresent_or_rsvd_mask_len) + shadow_nonpresent_or_rsvd_mask = + rsvd_bits(boot_cpu_data.x86_phys_bits - + shadow_nonpresent_or_rsvd_mask_len, + boot_cpu_data.x86_phys_bits - 1); } static int is_cpuid_PSE36(void) @@ -5473,7 +5506,7 @@ static void mmu_destroy_caches(void) int kvm_mmu_module_init(void) { - kvm_mmu_clear_all_pte_masks(); + kvm_mmu_reset_all_pte_masks(); pte_list_desc_cache = kmem_cache_create("pte_list_desc", sizeof(struct pte_list_desc), diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 282bbcbf3b6a999b449cf1705a27e53a16e4b480..f6bebcec60b4e507cb6a468ed2173c3d629d7b49 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -5067,8 +5067,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) clgi(); - local_irq_enable(); - /* * If this vCPU has touched SPEC_CTRL, restore the guest's value if * it's non-zero. Since vmentry is serialising on affected CPUs, there @@ -5077,6 +5075,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) */ x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl); + local_irq_enable(); + asm volatile ( "push %%" _ASM_BP "; \n\t" "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t" @@ -5199,12 +5199,12 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))) svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL); - x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl); - reload_tss(vcpu); local_irq_disable(); + x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl); + vcpu->arch.cr2 = svm->vmcb->save.cr2; vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax; vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index f015ca3997d9216c28c1db88b1e7e7cf0e6de64f..fd46d890296c9e98b472e79d55bbef8ca8c7b0f4 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -200,12 +200,14 @@ static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_ static const struct { const char *option; - enum vmx_l1d_flush_state cmd; + bool for_parse; } vmentry_l1d_param[] = { - {"auto", VMENTER_L1D_FLUSH_AUTO}, - {"never", VMENTER_L1D_FLUSH_NEVER}, - {"cond", VMENTER_L1D_FLUSH_COND}, - {"always", VMENTER_L1D_FLUSH_ALWAYS}, + [VMENTER_L1D_FLUSH_AUTO] = {"auto", true}, + [VMENTER_L1D_FLUSH_NEVER] = {"never", true}, + [VMENTER_L1D_FLUSH_COND] = {"cond", true}, + [VMENTER_L1D_FLUSH_ALWAYS] = {"always", true}, + [VMENTER_L1D_FLUSH_EPT_DISABLED] = {"EPT disabled", false}, + [VMENTER_L1D_FLUSH_NOT_REQUIRED] = {"not required", false}, }; #define L1D_CACHE_ORDER 4 @@ -289,8 +291,9 @@ static int vmentry_l1d_flush_parse(const char *s) if (s) { for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) { - if (sysfs_streq(s, vmentry_l1d_param[i].option)) - return vmentry_l1d_param[i].cmd; + if (vmentry_l1d_param[i].for_parse && + sysfs_streq(s, vmentry_l1d_param[i].option)) + return i; } } return -EINVAL; @@ -300,13 +303,13 @@ static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp) { int l1tf, ret; - if (!boot_cpu_has(X86_BUG_L1TF)) - return 0; - l1tf = vmentry_l1d_flush_parse(s); if (l1tf < 0) return l1tf; + if (!boot_cpu_has(X86_BUG_L1TF)) + return 0; + /* * Has vmx_init() run already? If not then this is the pre init * parameter parsing. In that case just store the value and let @@ -326,6 +329,9 @@ static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp) static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp) { + if (WARN_ON_ONCE(l1tf_vmx_mitigation >= ARRAY_SIZE(vmentry_l1d_param))) + return sprintf(s, "???\n"); + return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option); } @@ -743,17 +749,21 @@ struct vcpu_vmx { /* * loaded_vmcs points to the VMCS currently used in this vcpu. For a * non-nested (L1) guest, it always points to vmcs01. For a nested - * guest (L2), it points to a different VMCS. + * guest (L2), it points to a different VMCS. loaded_cpu_state points + * to the VMCS whose state is loaded into the CPU registers that only + * need to be switched when transitioning to/from the kernel; a NULL + * value indicates that host state is loaded. */ struct loaded_vmcs vmcs01; struct loaded_vmcs *loaded_vmcs; + struct loaded_vmcs *loaded_cpu_state; bool __launched; /* temporary, used in vmx_vcpu_run */ struct msr_autoload { struct vmx_msrs guest; struct vmx_msrs host; } msr_autoload; + struct { - int loaded; u16 fs_sel, gs_sel, ldt_sel; #ifdef CONFIG_X86_64 u16 ds_sel, es_sel; @@ -2330,10 +2340,11 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) struct vcpu_vmx *vmx = to_vmx(vcpu); int i; - if (vmx->host_state.loaded) + if (vmx->loaded_cpu_state) return; - vmx->host_state.loaded = 1; + vmx->loaded_cpu_state = vmx->loaded_vmcs; + /* * Set host fs and gs selectors. Unfortunately, 22.2.3 does not * allow segment selectors with cpl > 0 or ti == 1. @@ -2384,11 +2395,14 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) static void __vmx_load_host_state(struct vcpu_vmx *vmx) { - if (!vmx->host_state.loaded) + if (!vmx->loaded_cpu_state) return; + WARN_ON_ONCE(vmx->loaded_cpu_state != vmx->loaded_vmcs); + ++vmx->vcpu.stat.host_state_reload; - vmx->host_state.loaded = 0; + vmx->loaded_cpu_state = NULL; + #ifdef CONFIG_X86_64 if (is_long_mode(&vmx->vcpu)) rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); @@ -6951,8 +6965,8 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu) if (!static_cpu_has(X86_FEATURE_HYPERVISOR)) return kvm_skip_emulated_instruction(vcpu); else - return x86_emulate_instruction(vcpu, gpa, EMULTYPE_SKIP, - NULL, 0) == EMULATE_DONE; + return emulate_instruction(vcpu, EMULTYPE_SKIP) == + EMULATE_DONE; } ret = kvm_mmu_page_fault(vcpu, gpa, PFERR_RSVD_MASK, NULL, 0); @@ -7576,7 +7590,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu) /* CPL=0 must be checked manually. */ if (vmx_get_cpl(vcpu)) { - kvm_queue_exception(vcpu, UD_VECTOR); + kvm_inject_gp(vcpu, 0); return 1; } @@ -7640,7 +7654,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu) static int nested_vmx_check_permission(struct kvm_vcpu *vcpu) { if (vmx_get_cpl(vcpu)) { - kvm_queue_exception(vcpu, UD_VECTOR); + kvm_inject_gp(vcpu, 0); return 0; } @@ -8108,21 +8122,20 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) /* Emulate the VMPTRST instruction */ static int handle_vmptrst(struct kvm_vcpu *vcpu) { - unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); - u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO); - gva_t vmcs_gva; + unsigned long exit_qual = vmcs_readl(EXIT_QUALIFICATION); + u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO); + gpa_t current_vmptr = to_vmx(vcpu)->nested.current_vmptr; struct x86_exception e; + gva_t gva; if (!nested_vmx_check_permission(vcpu)) return 1; - if (get_vmx_mem_address(vcpu, exit_qualification, - vmx_instruction_info, true, &vmcs_gva)) + if (get_vmx_mem_address(vcpu, exit_qual, instr_info, true, &gva)) return 1; /* *_system ok, nested_vmx_check_permission has verified cpl=0 */ - if (kvm_write_guest_virt_system(vcpu, vmcs_gva, - (void *)&to_vmx(vcpu)->nested.current_vmptr, - sizeof(u64), &e)) { + if (kvm_write_guest_virt_system(vcpu, gva, (void *)¤t_vmptr, + sizeof(gpa_t), &e)) { kvm_inject_page_fault(vcpu, &e); return 1; } @@ -9171,9 +9184,6 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) * information but as all relevant affected CPUs have 32KiB L1D cache size * there is no point in doing so. */ -#define L1D_CACHE_ORDER 4 -static void *vmx_l1d_flush_pages; - static void vmx_l1d_flush(struct kvm_vcpu *vcpu) { int size = PAGE_SIZE << L1D_CACHE_ORDER; @@ -9942,8 +9952,8 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs) return; cpu = get_cpu(); - vmx->loaded_vmcs = vmcs; vmx_vcpu_put(vcpu); + vmx->loaded_vmcs = vmcs; vmx_vcpu_load(vcpu, cpu); vcpu->cpu = cpu; put_cpu(); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5c2c09f6c1c31310ad0e8ab9c124bb29540fb377..3856828ee1dc9c2fb2f670b2f4391ca3446947ae 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6194,20 +6194,22 @@ static void kvm_set_mmio_spte_mask(void) * Set the reserved bits and the present bit of an paging-structure * entry to generate page fault with PFER.RSV = 1. */ - /* Mask the reserved physical address bits. */ - mask = rsvd_bits(maxphyaddr, 51); + + /* + * Mask the uppermost physical address bit, which would be reserved as + * long as the supported physical address width is less than 52. + */ + mask = 1ull << 51; /* 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) + if (IS_ENABLED(CONFIG_X86_64) && maxphyaddr == 52) mask &= ~1ull; -#endif kvm_mmu_set_mmio_spte_mask(mask, mask); } diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index c8c6ad0d58b89c3621d0fcf11f45e00442ebf2a2..3f435d7fca5e62bc999e48c6a4f3e1c0fc86def9 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -7,6 +7,8 @@ #include #include +#include + /* * We rely on the nested NMI work to allow atomic faults from the NMI path; the * nested NMI paths are careful to preserve CR2. @@ -19,6 +21,9 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) if (__range_not_ok(from, n, TASK_SIZE)) return n; + if (!nmi_uaccess_okay()) + return n; + /* * Even though this function is typically called from NMI/IRQ context * disable pagefaults so that its behaviour is consistent even when diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index c2faff548f59a575024a62e4291bf567a8939dc3..794c35c4ca7360021a50c2a04d185eedbc577d52 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -317,8 +317,6 @@ static noinline int vmalloc_fault(unsigned long address) if (!(address >= VMALLOC_START && address < VMALLOC_END)) return -1; - WARN_ON_ONCE(in_nmi()); - /* * Synchronize this task's top level page-table * with the 'reference' page table. diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 37f60dfd7e4efbeb5f01ccceaaacef6b98537bf6..94b8d90830d10c65ab16c1993cfb4d6f054fb628 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -892,7 +892,7 @@ unsigned long max_swapfile_size(void) if (boot_cpu_has_bug(X86_BUG_L1TF)) { /* Limit the swap file size to MAX_PA/2 for L1TF workaround */ - unsigned long l1tf_limit = l1tf_pfn_limit() + 1; + unsigned long long l1tf_limit = l1tf_pfn_limit(); /* * We encode swap offsets also with 3 bits below those for pfn * which makes the usable limit higher. @@ -900,7 +900,7 @@ unsigned long max_swapfile_size(void) #if CONFIG_PGTABLE_LEVELS > 2 l1tf_limit <<= PAGE_SHIFT - SWP_OFFSET_FIRST_BIT; #endif - pages = min_t(unsigned long, l1tf_limit, pages); + pages = min_t(unsigned long long, l1tf_limit, pages); } return pages; } diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 5f4805d69aab2af70a9dcbe39877096cb9807fca..53f1c18b15bd361fa19fb75341a9e338b5301a3f 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -191,7 +191,7 @@ bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) /* If it's real memory always allow */ if (pfn_valid(pfn)) return true; - if (pfn > l1tf_pfn_limit() && !capable(CAP_SYS_ADMIN)) + if (pfn >= l1tf_pfn_limit() && !capable(CAP_SYS_ADMIN)) return false; return true; } diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c index 34a2a3bfde9c144623f4bfafbeb32404e4e3a21d..22cbad56acab8a698a0b0523745ea0be020cd0fc 100644 --- a/arch/x86/mm/numa_emulation.c +++ b/arch/x86/mm/numa_emulation.c @@ -61,7 +61,7 @@ static int __init emu_setup_memblk(struct numa_meminfo *ei, eb->nid = nid; if (emu_nid_to_phys[nid] == NUMA_NO_NODE) - emu_nid_to_phys[nid] = nid; + emu_nid_to_phys[nid] = pb->nid; pb->start += size; if (pb->start >= pb->end) { diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 2bdb8e8a9d7c85509d3ed2a70630e7a7c353c0eb..aafd4edfa2ac6416b4332fa171658dcf4428d85b 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -573,6 +573,15 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte) { unsigned long address = __fix_to_virt(idx); +#ifdef CONFIG_X86_64 + /* + * Ensure that the static initial page tables are covering the + * fixmap completely. + */ + BUILD_BUG_ON(__end_of_permanent_fixed_addresses > + (FIXMAP_PMD_NUM * PTRS_PER_PTE)); +#endif + if (idx >= __end_of_fixed_addresses) { BUG(); return; diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c index d6f11accd37a0590a7eb3ff22a8aa4ecedb7670b..60c48f5d6b0eede5ed2456a8196fc7d9e8187afe 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -162,7 +162,7 @@ static __init p4d_t *pti_user_pagetable_walk_p4d(unsigned long address) if (pgd_none(*pgd)) { unsigned long new_p4d_page = __get_free_page(gfp); - if (!new_p4d_page) + if (WARN_ON_ONCE(!new_p4d_page)) return NULL; set_pgd(pgd, __pgd(_KERNPG_TABLE | __pa(new_p4d_page))); @@ -181,13 +181,17 @@ static __init p4d_t *pti_user_pagetable_walk_p4d(unsigned long address) static __init pmd_t *pti_user_pagetable_walk_pmd(unsigned long address) { gfp_t gfp = (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO); - p4d_t *p4d = pti_user_pagetable_walk_p4d(address); + p4d_t *p4d; pud_t *pud; + p4d = pti_user_pagetable_walk_p4d(address); + if (!p4d) + return NULL; + BUILD_BUG_ON(p4d_large(*p4d) != 0); if (p4d_none(*p4d)) { unsigned long new_pud_page = __get_free_page(gfp); - if (!new_pud_page) + if (WARN_ON_ONCE(!new_pud_page)) return NULL; set_p4d(p4d, __p4d(_KERNPG_TABLE | __pa(new_pud_page))); @@ -201,7 +205,7 @@ static __init pmd_t *pti_user_pagetable_walk_pmd(unsigned long address) } if (pud_none(*pud)) { unsigned long new_pmd_page = __get_free_page(gfp); - if (!new_pmd_page) + if (WARN_ON_ONCE(!new_pmd_page)) return NULL; set_pud(pud, __pud(_KERNPG_TABLE | __pa(new_pmd_page))); @@ -220,12 +224,16 @@ static __init pmd_t *pti_user_pagetable_walk_pmd(unsigned long address) * * Returns a pointer to a PTE on success, or NULL on failure. */ -static __init pte_t *pti_user_pagetable_walk_pte(unsigned long address) +static pte_t *pti_user_pagetable_walk_pte(unsigned long address) { gfp_t gfp = (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO); - pmd_t *pmd = pti_user_pagetable_walk_pmd(address); + pmd_t *pmd; pte_t *pte; + pmd = pti_user_pagetable_walk_pmd(address); + if (!pmd) + return NULL; + /* We can't do anything sensible if we hit a large mapping. */ if (pmd_large(*pmd)) { WARN_ON(1); @@ -283,6 +291,10 @@ pti_clone_pmds(unsigned long start, unsigned long end, pmdval_t clear) p4d_t *p4d; pud_t *pud; + /* Overflow check */ + if (addr < start) + break; + pgd = pgd_offset_k(addr); if (WARN_ON(pgd_none(*pgd))) return; @@ -319,6 +331,9 @@ static void __init pti_clone_p4d(unsigned long addr) pgd_t *kernel_pgd; user_p4d = pti_user_pagetable_walk_p4d(addr); + if (!user_p4d) + return; + kernel_pgd = pgd_offset_k(addr); kernel_p4d = p4d_offset(kernel_pgd, addr); *user_p4d = *kernel_p4d; diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 0c936435ea9398727da162fd76c5ee4dc4a91892..83a3f4c935fc5ff00d6d408d8e709b92a86722fb 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -292,6 +292,10 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush); + /* Let nmi_uaccess_okay() know that we're changing CR3. */ + this_cpu_write(cpu_tlbstate.loaded_mm, LOADED_MM_SWITCHING); + barrier(); + if (need_flush) { this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id); this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen); @@ -322,6 +326,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, if (next != &init_mm) this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id); + /* Make sure we write CR3 before loaded_mm. */ + barrier(); + this_cpu_write(cpu_tlbstate.loaded_mm, next); this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid); } diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index b3526a98a5a51151f95d26932fe612a79373af7c..8ed11a5b1a9d8b2618ec43daeb264e1245205dce 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -425,14 +425,13 @@ static void xen_set_pud(pud_t *ptr, pud_t val) static void xen_set_pte_atomic(pte_t *ptep, pte_t pte) { trace_xen_mmu_set_pte_atomic(ptep, pte); - set_64bit((u64 *)ptep, native_pte_val(pte)); + __xen_set_pte(ptep, pte); } static void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { trace_xen_mmu_pte_clear(mm, addr, ptep); - if (!xen_batched_set_pte(ptep, native_make_pte(0))) - native_pte_clear(mm, addr, ptep); + __xen_set_pte(ptep, native_make_pte(0)); } static void xen_pmd_clear(pmd_t *pmdp) @@ -1543,7 +1542,7 @@ static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & pte_val_ma(pte)); #endif - native_set_pte(ptep, pte); + __xen_set_pte(ptep, pte); } /* Early in boot, while setting up the initial pagetable, assume @@ -1880,7 +1879,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) /* L3_k[511] -> level2_fixmap_pgt */ convert_pfn_mfn(level3_kernel_pgt); - /* L3_k[511][506] -> level1_fixmap_pgt */ + /* L3_k[511][508-FIXMAP_PMD_NUM ... 507] -> level1_fixmap_pgt */ convert_pfn_mfn(level2_fixmap_pgt); /* We get [511][511] and have Xen's version of level2_kernel_pgt */ @@ -1925,7 +1924,11 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); - set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO); + + for (i = 0; i < FIXMAP_PMD_NUM; i++) { + set_page_prot(level1_fixmap_pgt + i * PTRS_PER_PTE, + PAGE_KERNEL_RO); + } /* Pin down new L4 */ pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c index 7d00d4ad44d44d62f9a6a089a2c8d4a649e6aa08..95997e6c06960073c75b713cb2be76ec74c0886c 100644 --- a/arch/x86/xen/pmu.c +++ b/arch/x86/xen/pmu.c @@ -478,7 +478,7 @@ static void xen_convert_regs(const struct xen_pmu_regs *xen_regs, irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id) { int err, ret = IRQ_NONE; - struct pt_regs regs; + struct pt_regs regs = {0}; const struct xen_pmu_data *xenpmu_data = get_xenpmu_data(); uint8_t xenpmu_flags = get_xenpmu_flags(); diff --git a/arch/xtensa/include/asm/cacheasm.h b/arch/xtensa/include/asm/cacheasm.h index 2041abb10a2352a4b1f4323f3e1f0d9bdfff36ec..34545ecfdd6b7332df7fb486930f1f35c5532640 100644 --- a/arch/xtensa/include/asm/cacheasm.h +++ b/arch/xtensa/include/asm/cacheasm.h @@ -31,16 +31,32 @@ * */ - .macro __loop_cache_all ar at insn size line_width - movi \ar, 0 + .macro __loop_cache_unroll ar at insn size line_width max_immed + + .if (1 << (\line_width)) > (\max_immed) + .set _reps, 1 + .elseif (2 << (\line_width)) > (\max_immed) + .set _reps, 2 + .else + .set _reps, 4 + .endif + + __loopi \ar, \at, \size, (_reps << (\line_width)) + .set _index, 0 + .rep _reps + \insn \ar, _index << (\line_width) + .set _index, _index + 1 + .endr + __endla \ar, \at, _reps << (\line_width) + + .endm + - __loopi \ar, \at, \size, (4 << (\line_width)) - \insn \ar, 0 << (\line_width) - \insn \ar, 1 << (\line_width) - \insn \ar, 2 << (\line_width) - \insn \ar, 3 << (\line_width) - __endla \ar, \at, 4 << (\line_width) + .macro __loop_cache_all ar at insn size line_width max_immed + + movi \ar, 0 + __loop_cache_unroll \ar, \at, \insn, \size, \line_width, \max_immed .endm @@ -57,14 +73,9 @@ .endm - .macro __loop_cache_page ar at insn line_width + .macro __loop_cache_page ar at insn line_width max_immed - __loopi \ar, \at, PAGE_SIZE, 4 << (\line_width) - \insn \ar, 0 << (\line_width) - \insn \ar, 1 << (\line_width) - \insn \ar, 2 << (\line_width) - \insn \ar, 3 << (\line_width) - __endla \ar, \at, 4 << (\line_width) + __loop_cache_unroll \ar, \at, \insn, PAGE_SIZE, \line_width, \max_immed .endm @@ -72,7 +83,8 @@ .macro ___unlock_dcache_all ar at #if XCHAL_DCACHE_LINE_LOCKABLE && XCHAL_DCACHE_SIZE - __loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH + __loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE \ + XCHAL_DCACHE_LINEWIDTH 240 #endif .endm @@ -81,7 +93,8 @@ .macro ___unlock_icache_all ar at #if XCHAL_ICACHE_LINE_LOCKABLE && XCHAL_ICACHE_SIZE - __loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE XCHAL_ICACHE_LINEWIDTH + __loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE \ + XCHAL_ICACHE_LINEWIDTH 240 #endif .endm @@ -90,7 +103,8 @@ .macro ___flush_invalidate_dcache_all ar at #if XCHAL_DCACHE_SIZE - __loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH + __loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE \ + XCHAL_DCACHE_LINEWIDTH 240 #endif .endm @@ -99,7 +113,8 @@ .macro ___flush_dcache_all ar at #if XCHAL_DCACHE_SIZE - __loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH + __loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE \ + XCHAL_DCACHE_LINEWIDTH 240 #endif .endm @@ -108,8 +123,8 @@ .macro ___invalidate_dcache_all ar at #if XCHAL_DCACHE_SIZE - __loop_cache_all \ar \at dii __stringify(DCACHE_WAY_SIZE) \ - XCHAL_DCACHE_LINEWIDTH + __loop_cache_all \ar \at dii XCHAL_DCACHE_SIZE \ + XCHAL_DCACHE_LINEWIDTH 1020 #endif .endm @@ -118,8 +133,8 @@ .macro ___invalidate_icache_all ar at #if XCHAL_ICACHE_SIZE - __loop_cache_all \ar \at iii __stringify(ICACHE_WAY_SIZE) \ - XCHAL_ICACHE_LINEWIDTH + __loop_cache_all \ar \at iii XCHAL_ICACHE_SIZE \ + XCHAL_ICACHE_LINEWIDTH 1020 #endif .endm @@ -166,7 +181,7 @@ .macro ___flush_invalidate_dcache_page ar as #if XCHAL_DCACHE_SIZE - __loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH + __loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH 1020 #endif .endm @@ -175,7 +190,7 @@ .macro ___flush_dcache_page ar as #if XCHAL_DCACHE_SIZE - __loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH + __loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH 1020 #endif .endm @@ -184,7 +199,7 @@ .macro ___invalidate_dcache_page ar as #if XCHAL_DCACHE_SIZE - __loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH + __loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH 1020 #endif .endm @@ -193,7 +208,7 @@ .macro ___invalidate_icache_page ar as #if XCHAL_ICACHE_SIZE - __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH + __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH 1020 #endif .endm diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index f4bbb28026f8be3006890fe236989db791c79e1d..58709e89a8ed1f41ed7acaad204d4d91e973386a 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -78,23 +78,28 @@ static struct notifier_block iss_panic_block = { void __init platform_setup(char **p_cmdline) { + static void *argv[COMMAND_LINE_SIZE / sizeof(void *)] __initdata; + static char cmdline[COMMAND_LINE_SIZE] __initdata; int argc = simc_argc(); int argv_size = simc_argv_size(); if (argc > 1) { - void **argv = alloc_bootmem(argv_size); - char *cmdline = alloc_bootmem(argv_size); - int i; + if (argv_size > sizeof(argv)) { + pr_err("%s: command line too long: argv_size = %d\n", + __func__, argv_size); + } else { + int i; - cmdline[0] = 0; - simc_argv((void *)argv); + cmdline[0] = 0; + simc_argv((void *)argv); - for (i = 1; i < argc; ++i) { - if (i > 1) - strcat(cmdline, " "); - strcat(cmdline, argv[i]); + for (i = 1; i < argc; ++i) { + if (i > 1) + strcat(cmdline, " "); + strcat(cmdline, argv[i]); + } + *p_cmdline = cmdline; } - *p_cmdline = cmdline; } atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c index 5d53e504acae58d02fa3d8c0b5cef4b625e758aa..afbbe5750a1f85b635e7cd9a903314c0729c26d4 100644 --- a/block/bfq-cgroup.c +++ b/block/bfq-cgroup.c @@ -224,9 +224,9 @@ static void bfqg_and_blkg_get(struct bfq_group *bfqg) void bfqg_and_blkg_put(struct bfq_group *bfqg) { - bfqg_put(bfqg); - blkg_put(bfqg_to_blkg(bfqg)); + + bfqg_put(bfqg); } void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq, @@ -887,7 +887,8 @@ static ssize_t bfq_io_set_weight(struct kernfs_open_file *of, if (ret) return ret; - return bfq_io_set_weight_legacy(of_css(of), NULL, weight); + ret = bfq_io_set_weight_legacy(of_css(of), NULL, weight); + return ret ?: nbytes; } static int bfqg_print_stat(struct seq_file *sf, void *v) diff --git a/block/bio.c b/block/bio.c index 3a63aba1509dcbc36f3d4e16e10eebe40dc04ed6..dc247bbbe704d31617c33a3b16eeca366e2cd429 100644 --- a/block/bio.c +++ b/block/bio.c @@ -156,7 +156,7 @@ static void bio_put_slab(struct bio_set *bs) unsigned int bvec_nr_vecs(unsigned short idx) { - return bvec_slabs[idx].nr_vecs; + return bvec_slabs[--idx].nr_vecs; } void bvec_free(mempool_t *pool, struct bio_vec *bv, unsigned int idx) @@ -617,7 +617,6 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src) bio->bi_write_hint = bio_src->bi_write_hint; bio->bi_iter = bio_src->bi_iter; bio->bi_io_vec = bio_src->bi_io_vec; - bio->bi_dio_inode = bio_src->bi_dio_inode; bio_clone_crypt_key(bio, bio_src); bio_clone_blkcg_association(bio, bio_src); } diff --git a/block/blk-core.c b/block/blk-core.c index d21f176246b246acba0075087e7bebb7501c51e8..e57aed3f621147648dc3c2fa6c7fa6411ab7bcb7 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -671,9 +671,13 @@ void blk_cleanup_queue(struct request_queue *q) * make sure all in-progress dispatch are completed because * blk_freeze_queue() can only complete all requests, and * dispatch may still be in-progress since we dispatch requests - * from more than one contexts + * from more than one contexts. + * + * No need to quiesce queue if it isn't initialized yet since + * blk_freeze_queue() should be enough for cases of passthrough + * request. */ - if (q->mq_ops) + if (q->mq_ops && blk_queue_init_done(q)) blk_mq_quiesce_queue(q); /* for synchronous bio-based driver finish in-flight integrity i/o */ @@ -1027,6 +1031,7 @@ int blk_init_allocated_queue(struct request_queue *q) q->exit_rq_fn(q, q->fq->flush_rq); out_free_flush_queue: blk_free_flush_queue(q->fq); + q->fq = NULL; return -ENOMEM; } EXPORT_SYMBOL(blk_init_allocated_queue); @@ -1650,7 +1655,9 @@ bool bio_attempt_front_merge(struct request_queue *q, struct request *req, bio->bi_next = req->bio; req->bio = bio; +#ifdef CONFIG_PFK WARN_ON(req->__dun || bio->bi_iter.bi_dun); +#endif req->__sector = bio->bi_iter.bi_sector; req->__data_len += bio->bi_iter.bi_size; req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); @@ -1800,7 +1807,9 @@ void blk_init_request_from_bio(struct request *req, struct bio *bio) else req->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0); req->write_hint = bio->bi_write_hint; +#ifdef CONFIG_PFK req->__dun = bio->bi_iter.bi_dun; +#endif blk_rq_bio_prep(req->q, req, bio); } EXPORT_SYMBOL_GPL(blk_init_request_from_bio); @@ -2790,8 +2799,10 @@ bool blk_update_request(struct request *req, blk_status_t error, /* update sector only for requests with clear definition of sector */ if (!blk_rq_is_passthrough(req)) { req->__sector += total_bytes >> 9; +#ifdef CONFIG_PFK if (req->__dun) req->__dun += total_bytes >> 12; +#endif } /* mixed attributes always follow the first bio */ @@ -3155,7 +3166,9 @@ static void __blk_rq_prep_clone(struct request *dst, struct request *src) { dst->cpu = src->cpu; dst->__sector = blk_rq_pos(src); +#ifdef CONFIG_PFK dst->__dun = blk_rq_dun(src); +#endif dst->__data_len = blk_rq_bytes(src); if (src->rq_flags & RQF_SPECIAL_PAYLOAD) { dst->rq_flags |= RQF_SPECIAL_PAYLOAD; @@ -3468,9 +3481,11 @@ EXPORT_SYMBOL(blk_finish_plug); */ void blk_pm_runtime_init(struct request_queue *q, struct device *dev) { - /* not support for RQF_PM and ->rpm_status in blk-mq yet */ - if (q->mq_ops) + /* Don't enable runtime PM for blk-mq until it is ready */ + if (q->mq_ops) { + pm_runtime_disable(dev); return; + } q->dev = dev; q->rpm_status = RPM_ACTIVE; diff --git a/block/blk-merge.c b/block/blk-merge.c index 390f3464322d05de31583e27e8a2a9821afdfa46..079a3cf533f952dd143f3f54a32658e3791a0ba0 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -845,8 +845,10 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) enum elv_merge blk_try_merge(struct request *rq, struct bio *bio) { +#ifdef CONFIG_PFK if (blk_rq_dun(rq) || bio_dun(bio)) return ELEVATOR_NO_MERGE; +#endif if (req_op(rq) == REQ_OP_DISCARD && queue_max_discard_segments(rq->q) > 1) return ELEVATOR_DISCARD_MERGE; diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index eca011fdfa0ede407443c2de9c1e7d45787f4313..ae5d8f10a27c59a957911dd66fa9b68a7fc5c6e6 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -236,7 +236,8 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio) return e->type->ops.mq.bio_merge(hctx, bio); } - if (hctx->flags & BLK_MQ_F_SHOULD_MERGE) { + if ((hctx->flags & BLK_MQ_F_SHOULD_MERGE) && + !list_empty_careful(&ctx->rq_list)) { /* default per sw-queue merge */ spin_lock(&ctx->lock); ret = blk_mq_attempt_merge(q, ctx, bio); diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 6714507aa6c75b716d34a53c708952bf5d0ae619..3d2ab65d2dd15a012d3ff1efb71ad5b5aca6ddd5 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -416,8 +416,6 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, if (tdepth <= tags->nr_reserved_tags) return -EINVAL; - tdepth -= tags->nr_reserved_tags; - /* * If we are allowed to grow beyond the original size, allocate * a new set of tags before freeing the old one. @@ -437,7 +435,8 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, if (tdepth > 16 * BLKDEV_MAX_RQ) return -EINVAL; - new = blk_mq_alloc_rq_map(set, hctx->queue_num, tdepth, 0); + new = blk_mq_alloc_rq_map(set, hctx->queue_num, tdepth, + tags->nr_reserved_tags); if (!new) return -ENOMEM; ret = blk_mq_alloc_rqs(set, new, hctx->queue_num, tdepth); @@ -454,7 +453,8 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, * Don't need (or can't) update reserved tags here, they * remain static and should never need resizing. */ - sbitmap_queue_resize(&tags->bitmap_tags, tdepth); + sbitmap_queue_resize(&tags->bitmap_tags, + tdepth - tags->nr_reserved_tags); } return 0; diff --git a/block/blk-settings.c b/block/blk-settings.c index 8559e9563c5255f114309e95a9d09b71550d0af2..474b0b95fcd16e0069639bfc264637a601703a99 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -128,7 +128,7 @@ void blk_set_stacking_limits(struct queue_limits *lim) /* Inherit limits from component devices */ lim->max_segments = USHRT_MAX; - lim->max_discard_segments = 1; + lim->max_discard_segments = USHRT_MAX; lim->max_hw_sectors = UINT_MAX; lim->max_segment_size = UINT_MAX; lim->max_sectors = UINT_MAX; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 9f342ef1ad426fa7d60e00fffeb313409cbbb3f4..9c4f1c496c90c9af5d59bb94be5c24fe48c1debb 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -4741,12 +4741,13 @@ USEC_SHOW_FUNCTION(cfq_target_latency_us_show, cfqd->cfq_target_latency); static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ { \ struct cfq_data *cfqd = e->elevator_data; \ - unsigned int __data; \ + unsigned int __data, __min = (MIN), __max = (MAX); \ + \ cfq_var_store(&__data, (page)); \ - if (__data < (MIN)) \ - __data = (MIN); \ - else if (__data > (MAX)) \ - __data = (MAX); \ + if (__data < __min) \ + __data = __min; \ + else if (__data > __max) \ + __data = __max; \ if (__CONV) \ *(__PTR) = (u64)__data * NSEC_PER_MSEC; \ else \ @@ -4775,12 +4776,13 @@ STORE_FUNCTION(cfq_target_latency_store, &cfqd->cfq_target_latency, 1, UINT_MAX, static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ { \ struct cfq_data *cfqd = e->elevator_data; \ - unsigned int __data; \ + unsigned int __data, __min = (MIN), __max = (MAX); \ + \ cfq_var_store(&__data, (page)); \ - if (__data < (MIN)) \ - __data = (MIN); \ - else if (__data > (MAX)) \ - __data = (MAX); \ + if (__data < __min) \ + __data = __min; \ + else if (__data > __max) \ + __data = __max; \ *(__PTR) = (u64)__data * NSEC_PER_USEC; \ return count; \ } diff --git a/block/partitions/aix.c b/block/partitions/aix.c index 007f95eea0e1a9b6b79751ce6f109d151daa12f4..903f3ed175d0263344fe33ecbe19dfaeffcb202e 100644 --- a/block/partitions/aix.c +++ b/block/partitions/aix.c @@ -178,7 +178,7 @@ int aix_partition(struct parsed_partitions *state) u32 vgda_sector = 0; u32 vgda_len = 0; int numlvs = 0; - struct pvd *pvd; + struct pvd *pvd = NULL; struct lv_info { unsigned short pps_per_lv; unsigned short pps_found; @@ -232,10 +232,11 @@ int aix_partition(struct parsed_partitions *state) if (lvip[i].pps_per_lv) foundlvs += 1; } + /* pvd loops depend on n[].name and lvip[].pps_per_lv */ + pvd = alloc_pvd(state, vgda_sector + 17); } put_dev_sector(sect); } - pvd = alloc_pvd(state, vgda_sector + 17); if (pvd) { int numpps = be16_to_cpu(pvd->pp_count); int psn_part1 = be32_to_cpu(pvd->psn_part1); @@ -282,10 +283,14 @@ int aix_partition(struct parsed_partitions *state) next_lp_ix += 1; } for (i = 0; i < state->limit; i += 1) - if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) + if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) { + char tmp[sizeof(n[i].name) + 1]; // null char + + snprintf(tmp, sizeof(tmp), "%s", n[i].name); pr_warn("partition %s (%u pp's found) is " "not contiguous\n", - n[i].name, lvip[i].pps_found); + tmp, lvip[i].pps_found); + } kfree(pvd); } kfree(n); diff --git a/block/sed-opal.c b/block/sed-opal.c index 9ed51d0c6b1d171fc2eab785ef854b64f93721fe..4f5e70d4abc3cd282db163c6614b24c31a4c0fe5 100644 --- a/block/sed-opal.c +++ b/block/sed-opal.c @@ -877,7 +877,7 @@ static size_t response_get_string(const struct parsed_resp *resp, int n, return 0; } - if (n > resp->num) { + if (n >= resp->num) { pr_debug("Response has %d tokens. Can't access %d\n", resp->num, n); return 0; @@ -899,7 +899,7 @@ static u64 response_get_u64(const struct parsed_resp *resp, int n) return 0; } - if (n > resp->num) { + if (n >= resp->num) { pr_debug("Response has %d tokens. Can't access %d\n", resp->num, n); return 0; diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 0e1ea235c12a31363234964bac2482d4836a4928..4ba922ff3db6ba0c78ba040bc63a665da00af28f 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -230,7 +231,7 @@ int verify_pkcs7_signature(const void *data, size_t len, if (!trusted_keys) { trusted_keys = builtin_trusted_keys; - } else if (trusted_keys == (void *)1UL) { + } else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) { #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING trusted_keys = secondary_trusted_keys; #else diff --git a/crypto/Makefile b/crypto/Makefile index 2ae78fb2a39016dc11124c3bc2ea175ac6442e1f..59220c2264e1ba30012731fa99873a9d7193afcb 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -98,7 +98,7 @@ obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o CFLAGS_serpent_generic.o := $(call cc-option,-fsched-pressure) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 obj-$(CONFIG_CRYPTO_AES) += aes_generic.o -CFLAGS_aes_generic.o := $(call cc-ifversion, -ge, 0701, -Os) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83356 +CFLAGS_aes_generic.o := $(call cc-option,-fno-code-hoisting) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83356 obj-$(CONFIG_CRYPTO_AES_TI) += aes_ti.o obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o obj-$(CONFIG_CRYPTO_CAST_COMMON) += cast_common.o diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 4ee7c041bb82b7ea6e1133e03f5675479e0eb8a1..8882e90e868eade5b77fc310fb5238dd322e9f03 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -368,6 +368,7 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type)); strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", sizeof(rblkcipher.geniv)); + rblkcipher.geniv[sizeof(rblkcipher.geniv) - 1] = '\0'; rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; @@ -442,6 +443,7 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg) strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type)); strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", sizeof(rblkcipher.geniv)); + rblkcipher.geniv[sizeof(rblkcipher.geniv) - 1] = '\0'; rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; diff --git a/crypto/api.c b/crypto/api.c index 2a2479d168aacbe3e31799a2c713614b71e6805b..ff7a7852bb17acc90535be965727f42a2a9ef7e4 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -216,7 +216,7 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD); alg = crypto_alg_lookup(name, type, mask); - if (!alg) { + if (!alg && !(mask & CRYPTO_NOLOAD)) { request_module("crypto-%s", name); if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask & diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c index 1063b644efcdb3b2cbde33483207b7fc06e4eb5b..b2aa925a84bc512cabe5446c5c65e769fac1ff96 100644 --- a/crypto/asymmetric_keys/pkcs7_key_type.c +++ b/crypto/asymmetric_keys/pkcs7_key_type.c @@ -62,7 +62,7 @@ static int pkcs7_preparse(struct key_preparsed_payload *prep) return verify_pkcs7_signature(NULL, 0, prep->data, prep->datalen, - (void *)1UL, usage, + VERIFY_USE_SECONDARY_KEYRING, usage, pkcs7_view_content, prep); } diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index d84c6920ada9fe0b814df033b066edcb1e06e22a..830821f234d2805e9c3ecc8348a06ed0e6f47820 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -511,6 +511,7 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type)); strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "", sizeof(rblkcipher.geniv)); + rblkcipher.geniv[sizeof(rblkcipher.geniv) - 1] = '\0'; rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 30a5729565575f83cb02700ac2050f35abab5e5d..70a0f8b2f6c13a5416866141370d36a91dfbffda 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -2031,6 +2031,17 @@ static inline void acpi_ec_query_exit(void) } } +static const struct dmi_system_id acpi_ec_no_wakeup[] = { + { + .ident = "Thinkpad X1 Carbon 6th", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "Thinkpad X1 Carbon 6th"), + }, + }, + { }, +}; + int __init acpi_ec_init(void) { int result; @@ -2041,6 +2052,15 @@ int __init acpi_ec_init(void) if (result) return result; + /* + * Disable EC wakeup on following systems to prevent periodic + * wakeup from EC GPE. + */ + if (dmi_check_system(acpi_ec_no_wakeup)) { + ec_no_wakeup = true; + pr_debug("Disabling EC wakeup on suspend-to-idle\n"); + } + /* Drivers must be started after acpi_ec_query_init() */ dsdt_fail = acpi_bus_register_driver(&acpi_ec_driver); /* diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index d56822f58ab124143baef6fa2a5322db5dcef0f0..8260b90eb64b2e7e020f5e316eef5c0585d7ccb8 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -224,6 +224,8 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, const guid_t *guid; int rc, i; + if (cmd_rc) + *cmd_rc = -EINVAL; func = cmd; if (cmd == ND_CMD_CALL) { call_pkg = buf; @@ -314,6 +316,8 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, * If we return an error (like elsewhere) then caller wouldn't * be able to rely upon data returned to make calculation. */ + if (cmd_rc) + *cmd_rc = 0; return 0; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c0984d33c4c856dae04fc4eb7b111e24d287a120..2eddbb1fae6a0be9418002ff147968a24195ffb4 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1599,7 +1599,8 @@ static int acpi_add_single_object(struct acpi_device **child, * Note this must be done before the get power-/wakeup_dev-flags calls. */ if (type == ACPI_BUS_TYPE_DEVICE) - acpi_bus_get_status(device); + if (acpi_bus_get_status(device) < 0) + acpi_set_device_status(device, 0); acpi_bus_get_power_flags(device); acpi_bus_get_wakeup_device_flags(device); @@ -1677,7 +1678,7 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, * acpi_add_single_object updates this once we've an acpi_device * so that acpi_bus_get_status' quirk handling can be used. */ - *sta = 0; + *sta = ACPI_STA_DEFAULT; break; case ACPI_TYPE_PROCESSOR: *type = ACPI_BUS_TYPE_PROCESSOR; diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 4f382d51def11f4816694be6e7e02aa1598f720f..54debce30ee079a4a6925d3aa625769b911697c8 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -327,6 +327,34 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, return vma ? -ENOMEM : -ESRCH; } +static inline void binder_alloc_set_vma(struct binder_alloc *alloc, + struct vm_area_struct *vma) +{ + if (vma) + alloc->vma_vm_mm = vma->vm_mm; + /* + * If we see alloc->vma is not NULL, buffer data structures set up + * completely. Look at smp_rmb side binder_alloc_get_vma. + * We also want to guarantee new alloc->vma_vm_mm is always visible + * if alloc->vma is set. + */ + smp_wmb(); + alloc->vma = vma; +} + +static inline struct vm_area_struct *binder_alloc_get_vma( + struct binder_alloc *alloc) +{ + struct vm_area_struct *vma = NULL; + + if (alloc->vma) { + /* Look at description in binder_alloc_set_vma */ + smp_rmb(); + vma = alloc->vma; + } + return vma; +} + static struct binder_buffer *binder_alloc_new_buf_locked( struct binder_alloc *alloc, size_t data_size, @@ -343,7 +371,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( size_t size, data_offsets_size; int ret; - if (alloc->vma == NULL) { + if (!binder_alloc_get_vma(alloc)) { pr_err("%d: binder_alloc_buf, no vma\n", alloc->pid); return ERR_PTR(-ESRCH); @@ -714,9 +742,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, buffer->free = 1; binder_insert_free_buffer(alloc, buffer); alloc->free_async_space = alloc->buffer_size / 2; - barrier(); - alloc->vma = vma; - alloc->vma_vm_mm = vma->vm_mm; + binder_alloc_set_vma(alloc, vma); mmgrab(alloc->vma_vm_mm); return 0; @@ -743,10 +769,10 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) int buffers, page_count; struct binder_buffer *buffer; - BUG_ON(alloc->vma); - buffers = 0; mutex_lock(&alloc->mutex); + BUG_ON(alloc->vma); + while ((n = rb_first(&alloc->allocated_buffers))) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -889,7 +915,7 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc) */ void binder_alloc_vma_close(struct binder_alloc *alloc) { - WRITE_ONCE(alloc->vma, NULL); + binder_alloc_set_vma(alloc, NULL); } /** @@ -924,7 +950,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, index = page - alloc->pages; page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; - vma = alloc->vma; + vma = binder_alloc_get_vma(alloc); if (vma) { if (!mmget_not_zero(alloc->vma_vm_mm)) goto err_mmget; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 5ae268b8514e228b9b7830ad8346e029e7984f13..cda9a0b5bdaaa2c9783f460c8c8a1594e55cb1ae 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1135,10 +1136,12 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, /* get the slot number from the message */ pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; - if (pmp < EM_MAX_SLOTS) + if (pmp < EM_MAX_SLOTS) { + pmp = array_index_nospec(pmp, EM_MAX_SLOTS); emp = &pp->em_priv[pmp]; - else + } else { return -EINVAL; + } /* mask off the activity bits if we are in sw_activity * mode, user should turn off sw_activity before setting @@ -2093,7 +2096,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) struct ahci_host_priv *hpriv = ap->host->private_data; void __iomem *port_mmio = ahci_port_base(ap); struct ata_device *dev = ap->link.device; - u32 devslp, dm, dito, mdat, deto; + u32 devslp, dm, dito, mdat, deto, dito_conf; int rc; unsigned int err_mask; @@ -2117,8 +2120,15 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) return; } - /* device sleep was already enabled */ - if (devslp & PORT_DEVSLP_ADSE) + dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET; + dito = devslp_idle_timeout / (dm + 1); + if (dito > 0x3ff) + dito = 0x3ff; + + dito_conf = (devslp >> PORT_DEVSLP_DITO_OFFSET) & 0x3FF; + + /* device sleep was already enabled and same dito */ + if ((devslp & PORT_DEVSLP_ADSE) && (dito_conf == dito)) return; /* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */ @@ -2126,11 +2136,6 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) if (rc) return; - dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET; - dito = devslp_idle_timeout / (dm + 1); - if (dito > 0x3ff) - dito = 0x3ff; - /* Use the nominal value 10 ms if the read MDAT is zero, * the nominal value of DETO is 20 ms. */ @@ -2148,6 +2153,8 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) deto = 20; } + /* Make dito, mdat, deto bits to 0s */ + devslp &= ~GENMASK_ULL(24, 2); devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) | (mdat << PORT_DEVSLP_MDAT_OFFSET) | (deto << PORT_DEVSLP_DETO_OFFSET) | diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c index 5d4b72e21161a888c44997b448f602cef99a6709..569a4a662dcd4deb9d9edb0dbca4001f798bcab5 100644 --- a/drivers/ata/pata_ftide010.c +++ b/drivers/ata/pata_ftide010.c @@ -256,14 +256,12 @@ static struct ata_port_operations pata_ftide010_port_ops = { .qc_issue = ftide010_qc_issue, }; -static struct ata_port_info ftide010_port_info[] = { - { - .flags = ATA_FLAG_SLAVE_POSS, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - .pio_mask = ATA_PIO4, - .port_ops = &pata_ftide010_port_ops, - }, +static struct ata_port_info ftide010_port_info = { + .flags = ATA_FLAG_SLAVE_POSS, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .pio_mask = ATA_PIO4, + .port_ops = &pata_ftide010_port_ops, }; #if IS_ENABLED(CONFIG_SATA_GEMINI) @@ -349,6 +347,7 @@ static int pata_ftide010_gemini_cable_detect(struct ata_port *ap) } static int pata_ftide010_gemini_init(struct ftide010 *ftide, + struct ata_port_info *pi, bool is_ata1) { struct device *dev = ftide->dev; @@ -373,7 +372,13 @@ static int pata_ftide010_gemini_init(struct ftide010 *ftide, /* Flag port as SATA-capable */ if (gemini_sata_bridge_enabled(sg, is_ata1)) - ftide010_port_info[0].flags |= ATA_FLAG_SATA; + pi->flags |= ATA_FLAG_SATA; + + /* This device has broken DMA, only PIO works */ + if (of_machine_is_compatible("itian,sq201")) { + pi->mwdma_mask = 0; + pi->udma_mask = 0; + } /* * We assume that a simple 40-wire cable is used in the PATA mode. @@ -435,6 +440,7 @@ static int pata_ftide010_gemini_init(struct ftide010 *ftide, } #else static int pata_ftide010_gemini_init(struct ftide010 *ftide, + struct ata_port_info *pi, bool is_ata1) { return -ENOTSUPP; @@ -446,7 +452,7 @@ static int pata_ftide010_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - const struct ata_port_info pi = ftide010_port_info[0]; + struct ata_port_info pi = ftide010_port_info; const struct ata_port_info *ppi[] = { &pi, NULL }; struct ftide010 *ftide; struct resource *res; @@ -490,6 +496,7 @@ static int pata_ftide010_probe(struct platform_device *pdev) * are ATA0. This will also set up the cable types. */ ret = pata_ftide010_gemini_init(ftide, + &pi, (res->start == 0x63400000)); if (ret) goto err_dis_clk; diff --git a/drivers/base/core.c b/drivers/base/core.c index 9db30ee99917bfb245965149ef6656a14266e65c..b472de3ab925d3ac52162812e892c65adc40eb49 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2788,6 +2788,9 @@ void device_shutdown(void) { struct device *dev, *parent; + wait_for_device_probe(); + device_block_probing(); + spin_lock(&devices_kset->list_lock); /* * Walk the devices list backward, shutting down each in turn. diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 8e2e4757adcb02c9cd07a0b868a45e0bb3baa3eb..5a42ae4078c27febf8194901d8fa0e30b43bd1aa 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL_GPL(of_pm_clk_add_clk); int of_pm_clk_add_clks(struct device *dev) { struct clk **clks; - unsigned int i, count; + int i, count; int ret; if (!dev || !dev->of_node) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index de8566e5533499b6170c669a08c2aa8688e67057..c72071c300bbb74cdd4c7a7081f5b6f6a2c7b277 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1244,8 +1244,8 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long _drbd_start_io_acct(device, req); /* process discards always from our submitter thread */ - if ((bio_op(bio) & REQ_OP_WRITE_ZEROES) || - (bio_op(bio) & REQ_OP_DISCARD)) + if (bio_op(bio) == REQ_OP_WRITE_ZEROES || + bio_op(bio) == REQ_OP_DISCARD) goto queue_for_submitter_thread; if (rw == WRITE && req->private_bio && req->i.size diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 60c086a536094d4c19ad31a023d49274d54c3dd5..3d0287e212fe5fb1a2042909fc4a8891a3e21d66 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3462,6 +3462,9 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int (struct floppy_struct **)&outparam); if (ret) return ret; + memcpy(&inparam.g, outparam, + offsetof(struct floppy_struct, name)); + outparam = &inparam.g; break; case FDMSGON: UDP->flags |= FTD_MSG; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 6fb64e73bc9678e079a77823b5e4a3e31dba8dca..fe1414df0f3319cb201eb9fb63b14c4773c1c3fa 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -76,6 +76,7 @@ struct link_dead_args { #define NBD_HAS_CONFIG_REF 4 #define NBD_BOUND 5 #define NBD_DESTROY_ON_DISCONNECT 6 +#define NBD_DISCONNECT_ON_CLOSE 7 struct nbd_config { u32 flags; @@ -111,12 +112,16 @@ struct nbd_device { struct task_struct *task_setup; }; +#define NBD_CMD_REQUEUED 1 + struct nbd_cmd { struct nbd_device *nbd; + struct mutex lock; int index; int cookie; - struct completion send_complete; blk_status_t status; + unsigned long flags; + u32 cmd_cookie; }; #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -138,12 +143,42 @@ static void nbd_config_put(struct nbd_device *nbd); static void nbd_connect_reply(struct genl_info *info, int index); static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info); static void nbd_dead_link_work(struct work_struct *work); +static void nbd_disconnect_and_put(struct nbd_device *nbd); static inline struct device *nbd_to_dev(struct nbd_device *nbd) { return disk_to_dev(nbd->disk); } +static void nbd_requeue_cmd(struct nbd_cmd *cmd) +{ + struct request *req = blk_mq_rq_from_pdu(cmd); + + if (!test_and_set_bit(NBD_CMD_REQUEUED, &cmd->flags)) + blk_mq_requeue_request(req, true); +} + +#define NBD_COOKIE_BITS 32 + +static u64 nbd_cmd_handle(struct nbd_cmd *cmd) +{ + struct request *req = blk_mq_rq_from_pdu(cmd); + u32 tag = blk_mq_unique_tag(req); + u64 cookie = cmd->cmd_cookie; + + return (cookie << NBD_COOKIE_BITS) | tag; +} + +static u32 nbd_handle_to_tag(u64 handle) +{ + return (u32)handle; +} + +static u32 nbd_handle_to_cookie(u64 handle) +{ + return (u32)(handle >> NBD_COOKIE_BITS); +} + static const char *nbdcmd_to_ascii(int cmd) { switch (cmd) { @@ -304,6 +339,9 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, } config = nbd->config; + if (!mutex_trylock(&cmd->lock)) + return BLK_EH_RESET_TIMER; + if (config->num_connections > 1) { dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out, retrying\n"); @@ -326,7 +364,8 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, nbd_mark_nsock_dead(nbd, nsock, 1); mutex_unlock(&nsock->tx_lock); } - blk_mq_requeue_request(req, true); + mutex_unlock(&cmd->lock); + nbd_requeue_cmd(cmd); nbd_config_put(nbd); return BLK_EH_NOT_HANDLED; } @@ -336,6 +375,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, } set_bit(NBD_TIMEDOUT, &config->runtime_flags); cmd->status = BLK_STS_IOERR; + mutex_unlock(&cmd->lock); sock_shutdown(nbd); nbd_config_put(nbd); @@ -412,9 +452,9 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) struct iov_iter from; unsigned long size = blk_rq_bytes(req); struct bio *bio; + u64 handle; u32 type; u32 nbd_cmd_flags = 0; - u32 tag = blk_mq_unique_tag(req); int sent = nsock->sent, skip = 0; iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request)); @@ -456,6 +496,8 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) goto send_pages; } iov_iter_advance(&from, sent); + } else { + cmd->cmd_cookie++; } cmd->index = index; cmd->cookie = nsock->cookie; @@ -464,7 +506,8 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); request.len = htonl(size); } - memcpy(request.handle, &tag, sizeof(tag)); + handle = nbd_cmd_handle(cmd); + memcpy(request.handle, &handle, sizeof(handle)); dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)\n", cmd, nbdcmd_to_ascii(type), @@ -482,6 +525,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) nsock->pending = req; nsock->sent = sent; } + set_bit(NBD_CMD_REQUEUED, &cmd->flags); return BLK_STS_RESOURCE; } dev_err_ratelimited(disk_to_dev(nbd->disk), @@ -523,6 +567,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) */ nsock->pending = req; nsock->sent = sent; + set_bit(NBD_CMD_REQUEUED, &cmd->flags); return BLK_STS_RESOURCE; } dev_err(disk_to_dev(nbd->disk), @@ -555,10 +600,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) struct nbd_reply reply; struct nbd_cmd *cmd; struct request *req = NULL; + u64 handle; u16 hwq; u32 tag; struct kvec iov = {.iov_base = &reply, .iov_len = sizeof(reply)}; struct iov_iter to; + int ret = 0; reply.magic = 0; iov_iter_kvec(&to, READ | ITER_KVEC, &iov, 1, sizeof(reply)); @@ -576,8 +623,8 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) return ERR_PTR(-EPROTO); } - memcpy(&tag, reply.handle, sizeof(u32)); - + memcpy(&handle, reply.handle, sizeof(handle)); + tag = nbd_handle_to_tag(handle); hwq = blk_mq_unique_tag_to_hwq(tag); if (hwq < nbd->tag_set.nr_hw_queues) req = blk_mq_tag_to_rq(nbd->tag_set.tags[hwq], @@ -588,11 +635,25 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) return ERR_PTR(-ENOENT); } cmd = blk_mq_rq_to_pdu(req); + + mutex_lock(&cmd->lock); + if (cmd->cmd_cookie != nbd_handle_to_cookie(handle)) { + dev_err(disk_to_dev(nbd->disk), "Double reply on req %p, cmd_cookie %u, handle cookie %u\n", + req, cmd->cmd_cookie, nbd_handle_to_cookie(handle)); + ret = -ENOENT; + goto out; + } + if (test_bit(NBD_CMD_REQUEUED, &cmd->flags)) { + dev_err(disk_to_dev(nbd->disk), "Raced with timeout on req %p\n", + req); + ret = -ENOENT; + goto out; + } if (ntohl(reply.error)) { dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n", ntohl(reply.error)); cmd->status = BLK_STS_IOERR; - return cmd; + goto out; } dev_dbg(nbd_to_dev(nbd), "request %p: got reply\n", cmd); @@ -617,18 +678,18 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) if (nbd_disconnected(config) || config->num_connections <= 1) { cmd->status = BLK_STS_IOERR; - return cmd; + goto out; } - return ERR_PTR(-EIO); + ret = -EIO; + goto out; } dev_dbg(nbd_to_dev(nbd), "request %p: got %d bytes data\n", cmd, bvec.bv_len); } - } else { - /* See the comment in nbd_queue_rq. */ - wait_for_completion(&cmd->send_complete); } - return cmd; +out: + mutex_unlock(&cmd->lock); + return ret ? ERR_PTR(ret) : cmd; } static void recv_work(struct work_struct *work) @@ -791,7 +852,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index) */ blk_mq_start_request(req); if (unlikely(nsock->pending && nsock->pending != req)) { - blk_mq_requeue_request(req, true); + nbd_requeue_cmd(cmd); ret = 0; goto out; } @@ -804,7 +865,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index) dev_err_ratelimited(disk_to_dev(nbd->disk), "Request send failed, requeueing\n"); nbd_mark_nsock_dead(nbd, nsock, 1); - blk_mq_requeue_request(req, true); + nbd_requeue_cmd(cmd); ret = 0; } out: @@ -828,7 +889,8 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx, * that the server is misbehaving (or there was an error) before we're * done sending everything over the wire. */ - init_completion(&cmd->send_complete); + mutex_lock(&cmd->lock); + clear_bit(NBD_CMD_REQUEUED, &cmd->flags); /* We can be called directly from the user space process, which means we * could possibly have signals pending so our sendmsg will fail. In @@ -840,7 +902,7 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx, ret = BLK_STS_IOERR; else if (!ret) ret = BLK_STS_OK; - complete(&cmd->send_complete); + mutex_unlock(&cmd->lock); return ret; } @@ -1166,6 +1228,9 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, case NBD_SET_SOCK: return nbd_add_socket(nbd, arg, false); case NBD_SET_BLKSIZE: + if (!arg || !is_power_of_2(arg) || arg < 512 || + arg > PAGE_SIZE) + return -EINVAL; nbd_size_set(nbd, arg, div_s64(config->bytesize, arg)); return 0; @@ -1291,6 +1356,12 @@ static int nbd_open(struct block_device *bdev, fmode_t mode) static void nbd_release(struct gendisk *disk, fmode_t mode) { struct nbd_device *nbd = disk->private_data; + struct block_device *bdev = bdget_disk(disk, 0); + + if (test_bit(NBD_DISCONNECT_ON_CLOSE, &nbd->config->runtime_flags) && + bdev->bd_openers == 0) + nbd_disconnect_and_put(nbd); + nbd_config_put(nbd); nbd_put(nbd); } @@ -1438,6 +1509,8 @@ static int nbd_init_request(struct blk_mq_tag_set *set, struct request *rq, { struct nbd_cmd *cmd = blk_mq_rq_to_pdu(rq); cmd->nbd = set->driver_data; + cmd->flags = 0; + mutex_init(&cmd->lock); return 0; } @@ -1690,6 +1763,10 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) &config->runtime_flags); put_dev = true; } + if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) { + set_bit(NBD_DISCONNECT_ON_CLOSE, + &config->runtime_flags); + } } if (info->attrs[NBD_ATTR_SOCKETS]) { @@ -1734,6 +1811,16 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) return ret; } +static void nbd_disconnect_and_put(struct nbd_device *nbd) +{ + mutex_lock(&nbd->config_lock); + nbd_disconnect(nbd); + mutex_unlock(&nbd->config_lock); + if (test_and_clear_bit(NBD_HAS_CONFIG_REF, + &nbd->config->runtime_flags)) + nbd_config_put(nbd); +} + static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info) { struct nbd_device *nbd; @@ -1766,12 +1853,7 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info) nbd_put(nbd); return 0; } - mutex_lock(&nbd->config_lock); - nbd_disconnect(nbd); - mutex_unlock(&nbd->config_lock); - if (test_and_clear_bit(NBD_HAS_CONFIG_REF, - &nbd->config->runtime_flags)) - nbd_config_put(nbd); + nbd_disconnect_and_put(nbd); nbd_config_put(nbd); nbd_put(nbd); return 0; @@ -1782,7 +1864,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) struct nbd_device *nbd = NULL; struct nbd_config *config; int index; - int ret = -EINVAL; + int ret = 0; bool put_dev = false; if (!netlink_capable(skb, CAP_SYS_ADMIN)) @@ -1822,6 +1904,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) !nbd->task_recv) { dev_err(nbd_to_dev(nbd), "not configured, cannot reconfigure\n"); + ret = -EINVAL; goto out; } @@ -1846,6 +1929,14 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) &config->runtime_flags)) refcount_inc(&nbd->refs); } + + if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) { + set_bit(NBD_DISCONNECT_ON_CLOSE, + &config->runtime_flags); + } else { + clear_bit(NBD_DISCONNECT_ON_CLOSE, + &config->runtime_flags); + } } if (info->attrs[NBD_ATTR_SOCKETS]) { diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 531a0915066b313462d6208359ecea4102397215..11ec92e47455a3fafc4a853da977adb31ae2bde6 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -67,7 +67,7 @@ #include #include #include - +#include #include #define DRIVER_NAME "pktcdvd" @@ -2231,6 +2231,8 @@ static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor) { if (dev_minor >= MAX_WRITERS) return NULL; + + dev_minor = array_index_nospec(dev_minor, MAX_WRITERS); return pkt_devs[dev_minor]; } diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 2e35633ac188d401ffb38ea8d40787c309782cab..e3f8000bfbaf363a30654f4737430e66209c6232 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -314,6 +314,7 @@ static ssize_t backing_dev_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { char *file_name; + size_t sz; struct file *backing_dev = NULL; struct inode *inode; struct address_space *mapping; @@ -334,7 +335,11 @@ static ssize_t backing_dev_store(struct device *dev, goto out; } - strlcpy(file_name, buf, len); + strlcpy(file_name, buf, PATH_MAX); + /* ignore trailing newline */ + sz = strlen(file_name); + if (sz > 0 && file_name[sz - 1] == '\n') + file_name[sz - 1] = 0x00; backing_dev = filp_open(file_name, O_RDWR|O_LARGEFILE, 0); if (IS_ERR(backing_dev)) { diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 9520173e2776222624ace972dfc61a9181b0f64a..189615012860f868a32f3638578756f893edc47f 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -146,6 +146,7 @@ config BT_HCIUART_LL config BT_HCIUART_3WIRE bool "Three-wire UART (H5) protocol support" depends on BT_HCIUART + depends on BT_HCIUART_SERDEV help The HCI Three-wire UART Transport Layer makes it possible to user the Bluetooth HCI over a serial port interface. The HCI diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 819521d5895e1dd3b78105d0b7f52612358ed982..b8dffe937f4ff7df519ed2e106d6216cd910ffc3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -375,6 +375,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK }, /* Additional Realtek 8723DE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK }, /* Additional Realtek 8821AE Bluetooth devices */ diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 76960cef1a7056e86cd06b6f35713e375f07327a..8c399a5f4b9c345a6f4a434ca60c2a2299ceaa4b 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1313,14 +1313,19 @@ static int mhi_driver_probe(struct device *dev) bool auto_start = false; int ret; + /* bring device out of lpm */ + ret = mhi_device_get_sync(mhi_dev); + if (ret) + return ret; + ret = -EINVAL; if (ul_chan) { /* lpm notification require status_cb */ if (ul_chan->lpm_notify && !mhi_drv->status_cb) - return -EINVAL; + goto exit_probe; if (!ul_chan->offload_ch && !mhi_drv->ul_xfer_cb) - return -EINVAL; + goto exit_probe; ul_chan->xfer_cb = mhi_drv->ul_xfer_cb; mhi_dev->status_cb = mhi_drv->status_cb; @@ -1329,10 +1334,10 @@ static int mhi_driver_probe(struct device *dev) if (dl_chan) { if (dl_chan->lpm_notify && !mhi_drv->status_cb) - return -EINVAL; + goto exit_probe; if (!dl_chan->offload_ch && !mhi_drv->dl_xfer_cb) - return -EINVAL; + goto exit_probe; mhi_event = &mhi_cntrl->mhi_event[dl_chan->er_index]; @@ -1342,7 +1347,7 @@ static int mhi_driver_probe(struct device *dev) * cb whenever there are pending data */ if (mhi_event->cl_manage && !mhi_drv->status_cb) - return -EINVAL; + goto exit_probe; dl_chan->xfer_cb = mhi_drv->dl_xfer_cb; @@ -1356,6 +1361,9 @@ static int mhi_driver_probe(struct device *dev) if (!ret && auto_start) mhi_prepare_for_transfer(mhi_dev); +exit_probe: + mhi_device_put(mhi_dev); + return ret; } diff --git a/drivers/bus/mhi/devices/mhi_netdev.c b/drivers/bus/mhi/devices/mhi_netdev.c index c6ec258d43cbad53b24d288b23db517dbb9424ff..11b757ed0f4738c5a5a642eaf199cb47a4748374 100644 --- a/drivers/bus/mhi/devices/mhi_netdev.c +++ b/drivers/bus/mhi/devices/mhi_netdev.c @@ -89,31 +89,20 @@ struct mhi_stats { u32 alloc_failed; }; -/* important: do not exceed sk_buf->cb (48 bytes) */ -struct mhi_skb_priv { - void *buf; - size_t size; - struct mhi_netdev *mhi_netdev; -}; - struct mhi_netdev { int alias; struct mhi_device *mhi_dev; spinlock_t rx_lock; bool enabled; rwlock_t pm_lock; /* state change lock */ - int (*rx_queue)(struct mhi_netdev *, gfp_t); struct work_struct alloc_work; int wake; - struct sk_buff_head rx_allocated; - u32 mru; const char *interface_name; struct napi_struct napi; struct net_device *ndev; struct sk_buff *frag_skb; - bool recycle_buf; struct mhi_stats stats; struct dentry *dentry; @@ -149,23 +138,10 @@ static __be16 mhi_netdev_ip_type_trans(struct sk_buff *skb) return protocol; } -static void mhi_netdev_skb_destructor(struct sk_buff *skb) -{ - struct mhi_skb_priv *skb_priv = (struct mhi_skb_priv *)(skb->cb); - struct mhi_netdev *mhi_netdev = skb_priv->mhi_netdev; - - skb->data = skb->head; - skb_reset_tail_pointer(skb); - skb->len = 0; - MHI_ASSERT(skb->data != skb_priv->buf, "incorrect buf"); - skb_queue_tail(&mhi_netdev->rx_allocated, skb); -} - static int mhi_netdev_alloc_skb(struct mhi_netdev *mhi_netdev, gfp_t gfp_t) { u32 cur_mru = mhi_netdev->mru; struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct mhi_skb_priv *skb_priv; int ret; struct sk_buff *skb; int no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); @@ -183,18 +159,11 @@ static int mhi_netdev_alloc_skb(struct mhi_netdev *mhi_netdev, gfp_t gfp_t) goto error_queue; } - skb_priv = (struct mhi_skb_priv *)skb->cb; - skb_priv->buf = skb->data; - skb_priv->size = cur_mru; - skb_priv->mhi_netdev = mhi_netdev; skb->dev = mhi_netdev->ndev; - if (mhi_netdev->recycle_buf) - skb->destructor = mhi_netdev_skb_destructor; - spin_lock_bh(&mhi_netdev->rx_lock); - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb, - skb_priv->size, MHI_EOT); + ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb, cur_mru, + MHI_EOT); spin_unlock_bh(&mhi_netdev->rx_lock); if (ret) { @@ -209,7 +178,6 @@ static int mhi_netdev_alloc_skb(struct mhi_netdev *mhi_netdev, gfp_t gfp_t) return 0; error_queue: - skb->destructor = NULL; read_unlock_bh(&mhi_netdev->pm_lock); dev_kfree_skb_any(skb); @@ -240,66 +208,6 @@ static void mhi_netdev_alloc_work(struct work_struct *work) MSG_LOG("Exit with status:%d retry:%d\n", ret, retry); } -/* we will recycle buffers */ -static int mhi_netdev_skb_recycle(struct mhi_netdev *mhi_netdev, gfp_t gfp_t) -{ - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int no_tre; - int ret = 0; - struct sk_buff *skb; - struct mhi_skb_priv *skb_priv; - - read_lock_bh(&mhi_netdev->pm_lock); - if (!mhi_netdev->enabled) { - read_unlock_bh(&mhi_netdev->pm_lock); - return -EIO; - } - - no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - - spin_lock_bh(&mhi_netdev->rx_lock); - while (no_tre) { - skb = skb_dequeue(&mhi_netdev->rx_allocated); - - /* no free buffers to recycle, reschedule work */ - if (!skb) { - ret = -ENOMEM; - goto error_queue; - } - - skb_priv = (struct mhi_skb_priv *)(skb->cb); - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb, - skb_priv->size, MHI_EOT); - - /* failed to queue buffer */ - if (ret) { - MSG_ERR("Failed to queue skb, ret:%d\n", ret); - skb_queue_tail(&mhi_netdev->rx_allocated, skb); - goto error_queue; - } - - no_tre--; - } - -error_queue: - spin_unlock_bh(&mhi_netdev->rx_lock); - read_unlock_bh(&mhi_netdev->pm_lock); - - return ret; -} - -static void mhi_netdev_dealloc(struct mhi_netdev *mhi_netdev) -{ - struct sk_buff *skb; - - skb = skb_dequeue(&mhi_netdev->rx_allocated); - while (skb) { - skb->destructor = NULL; - kfree_skb(skb); - skb = skb_dequeue(&mhi_netdev->rx_allocated); - } -} - static int mhi_netdev_poll(struct napi_struct *napi, int budget) { struct net_device *dev = napi->dev; @@ -329,7 +237,7 @@ static int mhi_netdev_poll(struct napi_struct *napi, int budget) } /* queue new buffers */ - ret = mhi_netdev->rx_queue(mhi_netdev, GFP_ATOMIC); + ret = mhi_netdev_alloc_skb(mhi_netdev, GFP_ATOMIC); if (ret == -ENOMEM) { MSG_LOG("out of tre, queuing bg worker\n"); mhi_netdev->stats.alloc_failed++; @@ -390,12 +298,9 @@ static int mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev) struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; int res = 0; - struct mhi_skb_priv *tx_priv; MSG_VERB("Entered\n"); - tx_priv = (struct mhi_skb_priv *)(skb->cb); - tx_priv->mhi_netdev = mhi_netdev; read_lock_bh(&mhi_netdev->pm_lock); if (unlikely(!mhi_netdev->enabled)) { @@ -448,10 +353,9 @@ static int mhi_netdev_ioctl_extended(struct net_device *dev, struct ifreq *ifr) ext_cmd.u.data, mhi_dev->mtu); return -EINVAL; } - if (!mhi_netdev->recycle_buf) { - MSG_LOG("MRU change request to 0x%x\n", ext_cmd.u.data); - mhi_netdev->mru = ext_cmd.u.data; - } + + MSG_LOG("MRU change request to 0x%x\n", ext_cmd.u.data); + mhi_netdev->mru = ext_cmd.u.data; break; case RMNET_IOCTL_GET_SUPPORTED_FEATURES: ext_cmd.u.data = 0; @@ -611,8 +515,6 @@ static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev) MSG_ERR("Network device registration failed\n"); goto net_dev_reg_fail; } - - skb_queue_head_init(&mhi_netdev->rx_allocated); } write_lock_irq(&mhi_netdev->pm_lock); @@ -625,25 +527,6 @@ static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev) if (ret) schedule_work(&mhi_netdev->alloc_work); - /* if we recycle prepare one more set */ - if (mhi_netdev->recycle_buf) - for (; no_tre >= 0; no_tre--) { - struct sk_buff *skb = alloc_skb(mhi_netdev->mru, - GFP_KERNEL); - struct mhi_skb_priv *skb_priv; - - if (!skb) - break; - - skb_priv = (struct mhi_skb_priv *)skb->cb; - skb_priv->buf = skb->data; - skb_priv->size = mhi_netdev->mru; - skb_priv->mhi_netdev = mhi_netdev; - skb->dev = mhi_netdev->ndev; - skb->destructor = mhi_netdev_skb_destructor; - skb_queue_tail(&mhi_netdev->rx_allocated, skb); - } - napi_enable(&mhi_netdev->napi); MSG_LOG("Exited.\n"); @@ -731,11 +614,7 @@ static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev, mhi_netdev->frag_skb) { ret = mhi_netdev_process_fragment(mhi_netdev, skb); - /* recycle the skb */ - if (mhi_netdev->recycle_buf) - mhi_netdev_skb_destructor(skb); - else - dev_kfree_skb(skb); + dev_kfree_skb(skb); if (ret) return; @@ -791,9 +670,6 @@ static int mhi_netdev_debugfs_trigger_reset(void *data, u64 val) /* disable all hardware channels */ mhi_unprepare_from_transfer(mhi_dev); - /* clean up all alocated buffers */ - mhi_netdev_dealloc(mhi_netdev); - MSG_LOG("Restarting iface\n"); ret = mhi_netdev_enable_iface(mhi_netdev); @@ -905,7 +781,6 @@ static void mhi_netdev_remove(struct mhi_device *mhi_dev) napi_disable(&mhi_netdev->napi); netif_napi_del(&mhi_netdev->napi); - mhi_netdev_dealloc(mhi_netdev); unregister_netdev(mhi_netdev->ndev); free_netdev(mhi_netdev->ndev); flush_work(&mhi_netdev->alloc_work); @@ -946,11 +821,6 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev, if (ret) mhi_netdev->interface_name = mhi_netdev_driver.driver.name; - mhi_netdev->recycle_buf = of_property_read_bool(of_node, - "mhi,recycle-buf"); - mhi_netdev->rx_queue = mhi_netdev->recycle_buf ? - mhi_netdev_skb_recycle : mhi_netdev_alloc_skb; - spin_lock_init(&mhi_netdev->rx_lock); rwlock_init(&mhi_netdev->pm_lock); INIT_WORK(&mhi_netdev->alloc_work, mhi_netdev_alloc_work); diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index bfc566d3f31a40cf5b89d9284b2538644af68dee..8cfa10ab7abcb8cb0da9a9a62d7080b60f81683f 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2542,7 +2542,7 @@ static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, if (!CDROM_CAN(CDC_SELECT_DISC) || (arg == CDSL_CURRENT || arg == CDSL_NONE)) return cdi->ops->drive_status(cdi, CDSL_CURRENT); - if (((int)arg >= cdi->capacity)) + if (arg >= cdi->capacity) return -EINVAL; return cdrom_slot_status(cdi, arg); } diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 00fc37464eb8d541cf763a943298e59f85e789d0..e5673cf70aa2e4b2c977bbc64a4d14ae182f866b 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2228,6 +2228,9 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) ioctl.crc = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); + if (err) + pr_err("adsprpc: %s: releasing DSP process failed for %s, returned 0x%x", + __func__, current->comm, err); bail: return err; } @@ -2789,16 +2792,13 @@ static int fastrpc_file_free(struct fastrpc_file *fl) struct hlist_node *n = NULL; struct fastrpc_mmap *map = NULL, *lmap = NULL; struct fastrpc_perf *perf = NULL, *fperf = NULL; - int cid, err = 0; + int cid; if (!fl) return 0; cid = fl->cid; - err = fastrpc_release_current_dsp_process(fl); - if (err) - pr_err("adsprpc: %s: releasing DSP process failed for %s, returned 0x%x", - __func__, current->comm, err); + (void)fastrpc_release_current_dsp_process(fl); spin_lock(&fl->apps->hlock); hlist_del_init(&fl->hn); diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c index b3e86d8ad8621b68fdff70ee6b4472b60e5e5c0d..93f6ec39a28c9b152be7affefcf5caa73bdc69b3 100644 --- a/drivers/char/diag/diag_usb.c +++ b/drivers/char/diag/diag_usb.c @@ -520,6 +520,9 @@ int diag_usb_write(int id, unsigned char *buf, int len, int ctxt) usb_info = &diag_usb[id]; + if (!atomic_read(&usb_info->connected)) + return -ENOTCONN; + if (len > usb_info->max_size) { DIAG_LOG(DIAG_DEBUG_MUX, "len: %d, max_size: %d\n", len, usb_info->max_size); @@ -534,9 +537,11 @@ int diag_usb_write(int id, unsigned char *buf, int len, int ctxt) * trying to write more buffers than the max supported by * this particualar diag USB channel at any given instance, * or the previous write ptrs are stuck in the USB layer. + * Remove the buffer entry from the usb buf table for this case. */ pr_err_ratelimited("diag: In %s, cannot retrieve USB write ptrs for USB channel %s\n", __func__, usb_info->name); + diag_usb_buf_tbl_remove(usb_info, buf); return -ENOMEM; } diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c index 55a16b2a26e1a6d59af95270f01666012065244f..cd7c084e511708ace6db2beac2cf85ba6c01a901 100644 --- a/drivers/char/diag/diagfwd_bridge.c +++ b/drivers/char/diag/diagfwd_bridge.c @@ -29,6 +29,7 @@ #endif #include "diagfwd_mhi.h" #include "diag_dci.h" +#include "diag_ipc_logging.h" #ifdef CONFIG_MHI_BUS #define diag_mdm_init diag_mhi_init diff --git a/drivers/char/diag/diagfwd_mhi.c b/drivers/char/diag/diagfwd_mhi.c index 6c83706940ef8891051e4148f90073e6ae8d352b..ce732961f6a0284fe1a321876d723b6846bc57b6 100644 --- a/drivers/char/diag/diagfwd_mhi.c +++ b/drivers/char/diag/diagfwd_mhi.c @@ -83,7 +83,6 @@ struct diag_mhi_info diag_mhi[NUM_MHI_DEV] = { static int mhi_buf_tbl_add(struct diag_mhi_info *mhi_info, int type, void *buf, int len) { - unsigned long flags; struct diag_mhi_buf_tbl_t *item; struct diag_mhi_ch_t *ch = NULL; @@ -103,16 +102,14 @@ static int mhi_buf_tbl_add(struct diag_mhi_info *mhi_info, int type, return -EINVAL; } - item = kzalloc(sizeof(struct diag_mhi_buf_tbl_t), GFP_KERNEL); + item = kzalloc(sizeof(*item), GFP_ATOMIC); if (!item) return -ENOMEM; kmemleak_not_leak(item); - spin_lock_irqsave(&ch->lock, flags); item->buf = buf; item->len = len; list_add_tail(&item->link, &ch->buf_tbl); - spin_unlock_irqrestore(&ch->lock, flags); return 0; } @@ -166,7 +163,9 @@ static void mhi_buf_tbl_clear(struct diag_mhi_info *mhi_info) unsigned long flags; struct list_head *start, *temp; struct diag_mhi_buf_tbl_t *item = NULL; + struct diag_mhi_buf_tbl_t *tp = NULL, *tp_temp = NULL; struct diag_mhi_ch_t *ch = NULL; + unsigned char *buf; if (!mhi_info || !mhi_info->enabled) return; @@ -180,9 +179,17 @@ static void mhi_buf_tbl_clear(struct diag_mhi_info *mhi_info) item = list_entry(start, struct diag_mhi_buf_tbl_t, link); list_del(&item->link); + buf = item->buf; + list_for_each_entry_safe(tp, tp_temp, + &mhi_info->read_done_list, link) { + if (tp->buf == buf) { + list_del(&tp->link); + kfree(tp); + tp = NULL; + } + } diagmem_free(driver, item->buf, mhi_info->mempool); kfree(item); - } spin_unlock_irqrestore(&ch->lock, flags); } @@ -348,9 +355,9 @@ static void mhi_read_done_work_fn(struct work_struct *work) do { if (!(atomic_read(&(mhi_info->read_ch.opened)))) break; - spin_lock_irqsave(&mhi_info->lock, flags); + spin_lock_irqsave(&mhi_info->read_ch.lock, flags); if (list_empty(&mhi_info->read_done_list)) { - spin_unlock_irqrestore(&mhi_info->lock, flags); + spin_unlock_irqrestore(&mhi_info->read_ch.lock, flags); break; } tp = list_first_entry(&mhi_info->read_done_list, @@ -359,7 +366,7 @@ static void mhi_read_done_work_fn(struct work_struct *work) buf = tp->buf; len = tp->len; kfree(tp); - spin_unlock_irqrestore(&mhi_info->lock, flags); + spin_unlock_irqrestore(&mhi_info->read_ch.lock, flags); if (!buf) break; DIAG_LOG(DIAG_DEBUG_BRIDGE, @@ -373,12 +380,15 @@ static void mhi_read_done_work_fn(struct work_struct *work) if ((atomic_read(&(mhi_info->read_ch.opened)))) { err = diag_remote_dev_read_done(mhi_info->dev_id, buf, len); - if (err) + if (err) { mhi_buf_tbl_remove(mhi_info, TYPE_MHI_READ_CH, buf, len); + break; + } } else { mhi_buf_tbl_remove(mhi_info, TYPE_MHI_READ_CH, buf, len); + break; } } while (buf); } @@ -400,22 +410,26 @@ static void mhi_read_work_fn(struct work_struct *work) do { if (!(atomic_read(&(read_ch->opened)))) break; + spin_lock_irqsave(&read_ch->lock, flags); buf = diagmem_alloc(driver, DIAG_MDM_BUF_SIZE, mhi_info->mempool); - spin_unlock_irqrestore(&read_ch->lock, flags); - if (!buf) + if (!buf) { + spin_unlock_irqrestore(&read_ch->lock, flags); break; + } err = mhi_buf_tbl_add(mhi_info, TYPE_MHI_READ_CH, buf, DIAG_MDM_BUF_SIZE); - if (err) + if (err) { + spin_unlock_irqrestore(&read_ch->lock, flags); goto fail; + } DIAG_LOG(DIAG_DEBUG_BRIDGE, "queueing a read buf %pK, ch: %s\n", buf, mhi_info->name); - spin_lock_irqsave(&read_ch->lock, flags); + err = mhi_queue_transfer(mhi_info->mhi_dev, DMA_FROM_DEVICE, buf, DIAG_MDM_BUF_SIZE, mhi_flags); spin_unlock_irqrestore(&read_ch->lock, flags); @@ -475,12 +489,12 @@ static int mhi_write(int id, unsigned char *buf, int len, int ctxt) return -EIO; } + spin_lock_irqsave(&ch->lock, flags); err = mhi_buf_tbl_add(&diag_mhi[id], TYPE_MHI_WRITE_CH, buf, len); if (err) goto fail; - spin_lock_irqsave(&ch->lock, flags); err = mhi_queue_transfer(diag_mhi[id].mhi_dev, DMA_TO_DEVICE, buf, len, mhi_flags); spin_unlock_irqrestore(&ch->lock, flags); @@ -533,9 +547,11 @@ static void diag_mhi_read_cb(struct mhi_device *mhi_dev, struct mhi_result *result) { struct diag_mhi_info *mhi_info = NULL; - struct diag_mhi_buf_tbl_t *tp; + struct diag_mhi_buf_tbl_t *item = NULL; + struct diag_mhi_buf_tbl_t *tp = NULL, *temp = NULL; unsigned long flags; void *buf = NULL; + uint8_t queue_read = 0; if (!mhi_dev) return; @@ -548,18 +564,29 @@ static void diag_mhi_read_cb(struct mhi_device *mhi_dev, return; if (atomic_read(&mhi_info->read_ch.opened) && result->transaction_status != -ENOTCONN) { + spin_lock_irqsave(&mhi_info->read_ch.lock, flags); tp = kmalloc(sizeof(*tp), GFP_ATOMIC); if (!tp) { DIAG_LOG(DIAG_DEBUG_BRIDGE, "no mem for list\n"); + spin_unlock_irqrestore(&mhi_info->read_ch.lock, flags); return; } - tp->buf = buf; - tp->len = result->bytes_xferd; - spin_lock_irqsave(&mhi_info->lock, flags); - list_add_tail(&tp->link, &mhi_info->read_done_list); - spin_unlock_irqrestore(&mhi_info->lock, flags); - queue_work(mhi_info->mhi_wq, &(mhi_info->read_done_work)); + list_for_each_entry_safe(item, temp, + &mhi_info->read_ch.buf_tbl, link) { + if (item->buf == buf) { + tp->buf = buf; + tp->len = result->bytes_xferd; + list_add_tail(&tp->link, + &mhi_info->read_done_list); + queue_read = 1; + break; + } + } + spin_unlock_irqrestore(&mhi_info->read_ch.lock, flags); + if (queue_read) + queue_work(mhi_info->mhi_wq, + &(mhi_info->read_done_work)); } else { mhi_buf_tbl_remove(mhi_info, TYPE_MHI_READ_CH, buf, result->bytes_xferd); diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 6f2eaba1cd6a60f17597d6c7426287ccc228f811..932678617dfa7e212699cdd1afde16c5e480df26 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -184,6 +184,8 @@ struct ssif_addr_info { struct device *dev; struct i2c_client *client; + struct i2c_client *added_client; + struct mutex clients_mutex; struct list_head clients; @@ -1710,15 +1712,7 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) out: if (rv) { - /* - * Note that if addr_info->client is assigned, we - * leave it. The i2c client hangs around even if we - * return a failure here, and the failure here is not - * propagated back to the i2c code. This seems to be - * design intent, strange as it may be. But if we - * don't leave it, ssif_platform_remove will not remove - * the client like it should. - */ + addr_info->client = NULL; dev_err(&client->dev, "Unable to start IPMI SSIF: %d\n", rv); kfree(ssif_info); } @@ -1737,7 +1731,8 @@ static int ssif_adapter_handler(struct device *adev, void *opaque) if (adev->type != &i2c_adapter_type) return 0; - i2c_new_device(to_i2c_adapter(adev), &addr_info->binfo); + addr_info->added_client = i2c_new_device(to_i2c_adapter(adev), + &addr_info->binfo); if (!addr_info->adapter_name) return 1; /* Only try the first I2C adapter by default. */ @@ -2018,8 +2013,8 @@ static int ssif_platform_remove(struct platform_device *dev) return 0; mutex_lock(&ssif_infos_mutex); - if (addr_info->client) - i2c_unregister_device(addr_info->client); + if (addr_info->added_client) + i2c_unregister_device(addr_info->added_client); list_del(&addr_info->link); kfree(addr_info); diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index dba5259def6038645dbe24d95f0243c0b6282443..a2070ab86c824c402d142395f19389e578e205c3 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -369,10 +369,13 @@ static int tpm_validate_command(struct tpm_chip *chip, return -EINVAL; } -static int tpm_request_locality(struct tpm_chip *chip) +static int tpm_request_locality(struct tpm_chip *chip, unsigned int flags) { int rc; + if (flags & TPM_TRANSMIT_RAW) + return 0; + if (!chip->ops->request_locality) return 0; @@ -385,10 +388,13 @@ static int tpm_request_locality(struct tpm_chip *chip) return 0; } -static void tpm_relinquish_locality(struct tpm_chip *chip) +static void tpm_relinquish_locality(struct tpm_chip *chip, unsigned int flags) { int rc; + if (flags & TPM_TRANSMIT_RAW) + return; + if (!chip->ops->relinquish_locality) return; @@ -399,6 +405,28 @@ static void tpm_relinquish_locality(struct tpm_chip *chip) chip->locality = -1; } +static int tpm_cmd_ready(struct tpm_chip *chip, unsigned int flags) +{ + if (flags & TPM_TRANSMIT_RAW) + return 0; + + if (!chip->ops->cmd_ready) + return 0; + + return chip->ops->cmd_ready(chip); +} + +static int tpm_go_idle(struct tpm_chip *chip, unsigned int flags) +{ + if (flags & TPM_TRANSMIT_RAW) + return 0; + + if (!chip->ops->go_idle) + return 0; + + return chip->ops->go_idle(chip); +} + static ssize_t tpm_try_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, @@ -423,7 +451,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE | TSS2_RESMGR_TPM_RC_LAYER); - return bufsiz; + return sizeof(*header); } if (bufsiz > TPM_BUFSIZE) @@ -449,14 +477,15 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; - if (!(flags & TPM_TRANSMIT_RAW) && need_locality) { - rc = tpm_request_locality(chip); + if (need_locality) { + rc = tpm_request_locality(chip, flags); if (rc < 0) goto out_no_locality; } - if (chip->dev.parent) - pm_runtime_get_sync(chip->dev.parent); + rc = tpm_cmd_ready(chip, flags); + if (rc) + goto out; rc = tpm2_prepare_space(chip, space, ordinal, buf); if (rc) @@ -516,13 +545,16 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, } rc = tpm2_commit_space(chip, space, ordinal, buf, &len); + if (rc) + dev_err(&chip->dev, "tpm2_commit_space: error %d\n", rc); out: - if (chip->dev.parent) - pm_runtime_put_sync(chip->dev.parent); + rc = tpm_go_idle(chip, flags); + if (rc) + goto out; if (need_locality) - tpm_relinquish_locality(chip); + tpm_relinquish_locality(chip, flags); out_no_locality: if (chip->ops->clk_enable != NULL) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index b83b30a3eea5ef4e2de8b60a720d7dd571d45479..4bb9b4aa9b49c11a0e24c6a8d50351575609f015 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -511,9 +511,17 @@ extern const struct file_operations tpm_fops; extern const struct file_operations tpmrm_fops; extern struct idr dev_nums_idr; +/** + * enum tpm_transmit_flags + * + * @TPM_TRANSMIT_UNLOCKED: used to lock sequence of tpm_transmit calls. + * @TPM_TRANSMIT_RAW: prevent recursive calls into setup steps + * (go idle, locality,..). Always use with UNLOCKED + * as it will fail on double locking. + */ enum tpm_transmit_flags { - TPM_TRANSMIT_UNLOCKED = BIT(0), - TPM_TRANSMIT_RAW = BIT(1), + TPM_TRANSMIT_UNLOCKED = BIT(0), + TPM_TRANSMIT_RAW = BIT(1), }; ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index d26ea7513226c991eb3eeef3dfdbebadee8fa298..dabb2ae4e779a8cfe6360b3686380748922fe41e 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -39,7 +39,8 @@ static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space) for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) { if (space->session_tbl[i]) tpm2_flush_context_cmd(chip, space->session_tbl[i], - TPM_TRANSMIT_UNLOCKED); + TPM_TRANSMIT_UNLOCKED | + TPM_TRANSMIT_RAW); } } @@ -84,7 +85,7 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf, tpm_buf_append(&tbuf, &buf[*offset], body_size); rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 4, - TPM_TRANSMIT_UNLOCKED, NULL); + TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); @@ -133,7 +134,7 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, tpm_buf_append_u32(&tbuf, handle); rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0, - TPM_TRANSMIT_UNLOCKED, NULL); + TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); @@ -170,7 +171,8 @@ static void tpm2_flush_space(struct tpm_chip *chip) for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) if (space->context_tbl[i] && ~space->context_tbl[i]) tpm2_flush_context_cmd(chip, space->context_tbl[i], - TPM_TRANSMIT_UNLOCKED); + TPM_TRANSMIT_UNLOCKED | + TPM_TRANSMIT_RAW); tpm2_flush_sessions(chip, space); } @@ -377,7 +379,8 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp, return 0; out_no_slots: - tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_UNLOCKED); + tpm2_flush_context_cmd(chip, phandle, + TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW); dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__, phandle); return -ENOMEM; @@ -465,7 +468,8 @@ static int tpm2_save_space(struct tpm_chip *chip) return rc; tpm2_flush_context_cmd(chip, space->context_tbl[i], - TPM_TRANSMIT_UNLOCKED); + TPM_TRANSMIT_UNLOCKED | + TPM_TRANSMIT_RAW); space->context_tbl[i] = ~0; } diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index bb756ad7897e7ca2b445cfa37a16a3edfd7926a6..5c7ce5aaaf6fbbb4c0696b07876ece25e2070f2d 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -137,7 +137,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, } /** - * crb_go_idle - request tpm crb device to go the idle state + * __crb_go_idle - request tpm crb device to go the idle state * * @dev: crb device * @priv: crb private data @@ -151,7 +151,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, * * Return: 0 always */ -static int crb_go_idle(struct device *dev, struct crb_priv *priv) +static int __crb_go_idle(struct device *dev, struct crb_priv *priv) { if ((priv->flags & CRB_FL_ACPI_START) || (priv->flags & CRB_FL_CRB_SMC_START)) @@ -166,11 +166,20 @@ static int crb_go_idle(struct device *dev, struct crb_priv *priv) dev_warn(dev, "goIdle timed out\n"); return -ETIME; } + return 0; } +static int crb_go_idle(struct tpm_chip *chip) +{ + struct device *dev = &chip->dev; + struct crb_priv *priv = dev_get_drvdata(dev); + + return __crb_go_idle(dev, priv); +} + /** - * crb_cmd_ready - request tpm crb device to enter ready state + * __crb_cmd_ready - request tpm crb device to enter ready state * * @dev: crb device * @priv: crb private data @@ -183,7 +192,7 @@ static int crb_go_idle(struct device *dev, struct crb_priv *priv) * * Return: 0 on success -ETIME on timeout; */ -static int crb_cmd_ready(struct device *dev, struct crb_priv *priv) +static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv) { if ((priv->flags & CRB_FL_ACPI_START) || (priv->flags & CRB_FL_CRB_SMC_START)) @@ -201,6 +210,14 @@ static int crb_cmd_ready(struct device *dev, struct crb_priv *priv) return 0; } +static int crb_cmd_ready(struct tpm_chip *chip) +{ + struct device *dev = &chip->dev; + struct crb_priv *priv = dev_get_drvdata(dev); + + return __crb_cmd_ready(dev, priv); +} + static int __crb_request_locality(struct device *dev, struct crb_priv *priv, int loc) { @@ -393,6 +410,8 @@ static const struct tpm_class_ops tpm_crb = { .send = crb_send, .cancel = crb_cancel, .req_canceled = crb_req_canceled, + .go_idle = crb_go_idle, + .cmd_ready = crb_cmd_ready, .request_locality = crb_request_locality, .relinquish_locality = crb_relinquish_locality, .req_complete_mask = CRB_DRV_STS_COMPLETE, @@ -508,7 +527,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, * PTT HW bug w/a: wake up the device to access * possibly not retained registers. */ - ret = crb_cmd_ready(dev, priv); + ret = __crb_cmd_ready(dev, priv); if (ret) return ret; @@ -553,7 +572,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, if (!ret) priv->cmd_size = cmd_size; - crb_go_idle(dev, priv); + __crb_go_idle(dev, priv); __crb_relinquish_locality(dev, priv, 0); @@ -624,32 +643,7 @@ static int crb_acpi_add(struct acpi_device *device) chip->acpi_dev_handle = device->handle; chip->flags = TPM_CHIP_FLAG_TPM2; - rc = __crb_request_locality(dev, priv, 0); - if (rc) - return rc; - - rc = crb_cmd_ready(dev, priv); - if (rc) - goto out; - - pm_runtime_get_noresume(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - rc = tpm_chip_register(chip); - if (rc) { - crb_go_idle(dev, priv); - pm_runtime_put_noidle(dev); - pm_runtime_disable(dev); - goto out; - } - - pm_runtime_put_sync(dev); - -out: - __crb_relinquish_locality(dev, priv, 0); - - return rc; + return tpm_chip_register(chip); } static int crb_acpi_remove(struct acpi_device *device) @@ -659,52 +653,11 @@ static int crb_acpi_remove(struct acpi_device *device) tpm_chip_unregister(chip); - pm_runtime_disable(dev); - return 0; } -static int __maybe_unused crb_pm_runtime_suspend(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - struct crb_priv *priv = dev_get_drvdata(&chip->dev); - - return crb_go_idle(dev, priv); -} - -static int __maybe_unused crb_pm_runtime_resume(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - struct crb_priv *priv = dev_get_drvdata(&chip->dev); - - return crb_cmd_ready(dev, priv); -} - -static int __maybe_unused crb_pm_suspend(struct device *dev) -{ - int ret; - - ret = tpm_pm_suspend(dev); - if (ret) - return ret; - - return crb_pm_runtime_suspend(dev); -} - -static int __maybe_unused crb_pm_resume(struct device *dev) -{ - int ret; - - ret = crb_pm_runtime_resume(dev); - if (ret) - return ret; - - return tpm_pm_resume(dev); -} - static const struct dev_pm_ops crb_pm = { - SET_SYSTEM_SLEEP_PM_OPS(crb_pm_suspend, crb_pm_resume) - SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tpm_pm_suspend, tpm_pm_resume) }; static const struct acpi_device_id crb_device_ids[] = { diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index d5b44cadac5669f46d36c48cad26c998ae931167..c619e76ce827615caa2c47bd6d6abbb368f8a416 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -117,7 +117,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) /* Lock the adapter for the duration of the whole sequence. */ if (!tpm_dev.client->adapter->algo->master_xfer) return -EOPNOTSUPP; - i2c_lock_adapter(tpm_dev.client->adapter); + i2c_lock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); if (tpm_dev.chip_type == SLB9645) { /* use a combined read for newer chips @@ -192,7 +192,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) } out: - i2c_unlock_adapter(tpm_dev.client->adapter); + i2c_unlock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); /* take care of 'guard time' */ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); @@ -224,7 +224,7 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, if (!tpm_dev.client->adapter->algo->master_xfer) return -EOPNOTSUPP; - i2c_lock_adapter(tpm_dev.client->adapter); + i2c_lock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); /* prepend the 'register address' to the buffer */ tpm_dev.buf[0] = addr; @@ -243,7 +243,7 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, usleep_range(sleep_low, sleep_hi); } - i2c_unlock_adapter(tpm_dev.client->adapter); + i2c_unlock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); /* take care of 'guard time' */ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 8ab0bd8445f6d2ba818653d642bd32d4a97b8b20..b00388fc41c8d5f13c2203dea6be15ce0b647a72 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -188,6 +188,7 @@ static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { static int tpm_tis_spi_probe(struct spi_device *dev) { struct tpm_tis_spi_phy *phy; + int irq; phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy), GFP_KERNEL); @@ -200,7 +201,13 @@ static int tpm_tis_spi_probe(struct spi_device *dev) if (!phy->iobuf) return -ENOMEM; - return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops, + /* If the SPI device has an IRQ then use that */ + if (dev->irq > 0) + irq = dev->irq; + else + irq = -1; + + return tpm_tis_core_init(&dev->dev, &phy->priv, irq, &tpm_spi_phy_ops, NULL); } diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index fda42aba9d4177ca2e7d653a9b639dcdad464f71..a1b5935b5b9c64d2ba634ff2fe191238f61d7b97 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -177,8 +177,15 @@ static struct clk *_of_fixed_factor_clk_setup(struct device_node *node) clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags, mult, div); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + /* + * If parent clock is not registered, registration would fail. + * Clear OF_POPULATED flag so that clock registration can be + * attempted again from probe function. + */ + of_node_clear_flag(node, OF_POPULATED); return clk; + } ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); if (ret) { diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5708007fc729ac071b0b4dc00311a090d9bb1b58..e562c92b63c9a5836075044e95364f4444387d7c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3600,6 +3600,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, return clk; } +/* keep in sync with __clk_put */ void __clk_free_clk(struct clk *clk) { clk_prepare_lock(); @@ -4138,6 +4139,7 @@ int __clk_get(struct clk *clk) return 1; } +/* keep in sync with __clk_free_clk */ void __clk_put(struct clk *clk) { struct module *owner; @@ -4159,6 +4161,7 @@ void __clk_put(struct clk *clk) module_put(owner); + kfree_const(clk->con_id); kfree(clk); } diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 41c08fc892b97456bf8c9d3d7740337ee051638d..5cc5ff1b4e1f5cd5e1673e7b0fc4293a5af15d54 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -135,6 +135,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-anatop"); base = of_iomap(np, 0); + of_node_put(np); WARN_ON(!base); clks[IMX6UL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index ed70cbe590fdfd0ef4a96bbeeacb1ea37f62f6ae..89089ccf32c8d44da6fab0f080c958e274392abb 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -476,3 +476,11 @@ config GCC_SDXPRAIRIE SDXPRAIRIE devices. Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe, etc. + +config DEBUGCC_SDXPRAIRIE + tristate "SDXPRAIRIE Debug Clock Controller" + depends on COMMON_CLK_QCOM + help + Support for the debug clock controller on Qualcomm Technologies, Inc + SDXPRAIRIE devices. + Say Y if you want to support the clock measurement functionality. diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 59cfe7d30244c8dee53464a903901093a94796eb..25b3ccc4d284aa1e2cba11885e3df5aa638accee 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o obj-$(CONFIG_CLOCK_CPU_OSM) += clk-cpu-osm.o obj-$(CONFIG_CLOCK_CPU_QCS405) += clk-cpu-qcs405.o +obj-$(CONFIG_DEBUGCC_SDXPRAIRIE) += debugcc-sdxprairie.o obj-$(CONFIG_GCC_SDXPRAIRIE) += gcc-sdxprairie.o obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o diff --git a/drivers/clk/qcom/camcc-sdmmagpie.c b/drivers/clk/qcom/camcc-sdmmagpie.c index 50593202ec8b1980d354375f3a347032f84d9b17..d0ec6970970bd249250da875a542d6cfd13985ac 100644 --- a/drivers/clk/qcom/camcc-sdmmagpie.c +++ b/drivers/clk/qcom/camcc-sdmmagpie.c @@ -31,7 +31,7 @@ #include "clk-regmap.h" #include "common.h" #include "reset.h" -#include "vdd-level.h" +#include "vdd-level-sdmmagpie.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } @@ -188,7 +188,7 @@ static const struct parent_map cam_cc_parent_map_9[] = { }; static const char * const cam_cc_parent_names_9[] = { - "bi_tcxo", + "bi_tcxo_ao", "core_bi_pll_test_se", }; diff --git a/drivers/clk/qcom/camcc-sm8150.c b/drivers/clk/qcom/camcc-sm8150.c index 1f5bbfd8f1ddd0ca7462d9da5f0be03953df194d..e7d6885a7232c358dd0eae28dfb38386c3e60ab9 100644 --- a/drivers/clk/qcom/camcc-sm8150.c +++ b/drivers/clk/qcom/camcc-sm8150.c @@ -172,7 +172,7 @@ static const struct alpha_pll_config cam_cc_pll0_config = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000002, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00003100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; @@ -186,7 +186,7 @@ static const struct alpha_pll_config cam_cc_pll0_config_sm8150_v2 = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000000, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00003100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; @@ -214,10 +214,7 @@ static struct clk_alpha_pll cam_cc_pll0 = { }; static const struct clk_div_table post_div_table_trion_even[] = { - { 0x0, 1 }, { 0x1, 2 }, - { 0x3, 4 }, - { 0x7, 8 }, { } }; @@ -237,10 +234,7 @@ static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = { }; static const struct clk_div_table post_div_table_trion_odd[] = { - { 0x0, 1 }, { 0x3, 3 }, - { 0x5, 5 }, - { 0x7, 7 }, { } }; @@ -268,7 +262,7 @@ static const struct alpha_pll_config cam_cc_pll1_config = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000002, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00000100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; @@ -282,7 +276,7 @@ static const struct alpha_pll_config cam_cc_pll1_config_sm8150_v2 = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000000, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00000100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; @@ -333,6 +327,7 @@ static const struct alpha_pll_config cam_cc_pll2_config = { .test_ctl_val = 0x04000400, .test_ctl_hi_val = 0x00004000, .test_ctl_hi1_val = 0x00000000, + .user_ctl_val = 0x00000100, }; static struct clk_alpha_pll cam_cc_pll2 = { @@ -359,10 +354,7 @@ static struct clk_alpha_pll cam_cc_pll2 = { }; static const struct clk_div_table post_div_table_regera_main[] = { - { 0x0, 1 }, { 0x1, 2 }, - { 0x3, 4 }, - { 0x2, 8 }, { } }; @@ -390,7 +382,7 @@ static const struct alpha_pll_config cam_cc_pll3_config = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000002, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00000100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; @@ -404,7 +396,7 @@ static const struct alpha_pll_config cam_cc_pll3_config_sm8150_v2 = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000000, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00000100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; @@ -455,7 +447,7 @@ static const struct alpha_pll_config cam_cc_pll4_config = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000002, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00000100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; @@ -469,7 +461,7 @@ static const struct alpha_pll_config cam_cc_pll4_config_sm8150_v2 = { .test_ctl_val = 0x00000000, .test_ctl_hi_val = 0x00000000, .test_ctl_hi1_val = 0x00000020, - .user_ctl_val = 0x00000000, + .user_ctl_val = 0x00000100, .user_ctl_hi_val = 0x00000805, .user_ctl_hi1_val = 0x000000D0, }; diff --git a/drivers/clk/qcom/debugcc-sdxprairie.c b/drivers/clk/qcom/debugcc-sdxprairie.c new file mode 100644 index 0000000000000000000000000000000000000000..bcf993264bdf0a9a6e112797d8338fd4be73f90a --- /dev/null +++ b/drivers/clk/qcom/debugcc-sdxprairie.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2018, 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. + */ + +#define pr_fmt(fmt) "clk: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-debug.h" + +static struct measure_clk_data debug_mux_priv = { + .ctl_reg = 0x79004, + .status_reg = 0x79008, + .xo_div4_cbcr = 0x22010, +}; + +static const char *const debug_mux_parent_names[] = { + "gcc_ahb_pcie_link_clk", + "gcc_blsp1_ahb_clk", + "gcc_blsp1_qup1_i2c_apps_clk", + "gcc_blsp1_qup1_spi_apps_clk", + "gcc_blsp1_qup2_i2c_apps_clk", + "gcc_blsp1_qup2_spi_apps_clk", + "gcc_blsp1_qup3_i2c_apps_clk", + "gcc_blsp1_qup3_spi_apps_clk", + "gcc_blsp1_qup4_i2c_apps_clk", + "gcc_blsp1_qup4_spi_apps_clk", + "gcc_blsp1_sleep_clk", + "gcc_blsp1_uart1_apps_clk", + "gcc_blsp1_uart2_apps_clk", + "gcc_blsp1_uart3_apps_clk", + "gcc_blsp1_uart4_apps_clk", + "gcc_boot_rom_ahb_clk", + "gcc_ce1_ahb_clk", + "gcc_ce1_axi_clk", + "gcc_ce1_clk", + "gcc_cpuss_ahb_clk", + "gcc_cpuss_gnoc_clk", + "gcc_cpuss_rbcpr_clk", + "gcc_eth_axi_clk", + "gcc_eth_ptp_clk", + "gcc_eth_rgmii_clk", + "gcc_eth_slave_ahb_clk", + "gcc_gp1_clk", + "gcc_gp2_clk", + "gcc_gp3_clk", + "gcc_pcie_aux_clk", + "gcc_pcie_cfg_ahb_clk", + "gcc_pcie_mstr_axi_clk", + "gcc_pcie_pipe_clk", + "gcc_pcie_rchng_phy_clk", + "gcc_pcie_sleep_clk", + "gcc_pcie_slv_axi_clk", + "gcc_pcie_slv_q2a_axi_clk", + "gcc_pdm2_clk", + "gcc_pdm_ahb_clk", + "gcc_pdm_xo4_clk", + "gcc_sdcc1_ahb_clk", + "gcc_sdcc1_apps_clk", + "gcc_spmi_fetcher_ahb_clk", + "gcc_spmi_fetcher_clk", + "gcc_sys_noc_cpuss_ahb_clk", + "gcc_usb30_master_clk", + "gcc_usb30_mock_utmi_clk", + "gcc_usb30_mstr_axi_clk", + "gcc_usb30_sleep_clk", + "gcc_usb30_slv_ahb_clk", + "gcc_usb3_phy_aux_clk", + "gcc_usb3_phy_pipe_clk", + "gcc_usb_phy_cfg_ahb2phy_clk", + "gcc_xo_div4_clk", + "gcc_xo_pcie_link_clk", + "measure_only_bimc_clk", + "measure_only_ipa_2x_clk", + "measure_only_snoc_clk", +}; + +static struct clk_debug_mux gcc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0x79000, + .post_div_offset = 0x29000, + .cbcr_offset = 0x29004, + .src_sel_mask = 0x3FF, + .src_sel_shift = 0, + .post_div_mask = 0xF, + .post_div_shift = 0, + MUX_SRC_LIST( + { "gcc_ahb_pcie_link_clk", 0xCF, 4, GCC, + 0xCF, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_ahb_clk", 0x34, 4, GCC, + 0x34, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup1_i2c_apps_clk", 0x37, 4, GCC, + 0x37, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup1_spi_apps_clk", 0x36, 4, GCC, + 0x36, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup2_i2c_apps_clk", 0x3B, 4, GCC, + 0x3B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup2_spi_apps_clk", 0x3A, 4, GCC, + 0x3A, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup3_i2c_apps_clk", 0x3F, 4, GCC, + 0x3F, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup3_spi_apps_clk", 0x3E, 4, GCC, + 0x3E, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup4_i2c_apps_clk", 0x43, 4, GCC, + 0x43, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_qup4_spi_apps_clk", 0x42, 4, GCC, + 0x42, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_sleep_clk", 0x35, 4, GCC, + 0x35, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_uart1_apps_clk", 0x38, 4, GCC, + 0x38, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_uart2_apps_clk", 0x3C, 4, GCC, + 0x3C, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_uart3_apps_clk", 0x40, 4, GCC, + 0x40, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_blsp1_uart4_apps_clk", 0x44, 4, GCC, + 0x44, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_boot_rom_ahb_clk", 0x4B, 4, GCC, + 0x4B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_ce1_ahb_clk", 0x60, 4, GCC, + 0x60, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_ce1_axi_clk", 0x5F, 4, GCC, + 0x5F, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_ce1_clk", 0x5E, 4, GCC, + 0x5E, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_cpuss_ahb_clk", 0x74, 4, GCC, + 0x74, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_cpuss_gnoc_clk", 0x75, 4, GCC, + 0x75, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_cpuss_rbcpr_clk", 0x76, 4, GCC, + 0x76, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_eth_axi_clk", 0xCB, 4, GCC, + 0xCB, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_eth_ptp_clk", 0xFD, 4, GCC, + 0xFD, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_eth_rgmii_clk", 0xC9, 4, GCC, + 0xC9, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_eth_slave_ahb_clk", 0xCA, 4, GCC, + 0xCA, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_gp1_clk", 0x85, 4, GCC, + 0x85, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_gp2_clk", 0x86, 4, GCC, + 0x86, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_gp3_clk", 0x87, 4, GCC, + 0x87, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_aux_clk", 0x99, 4, GCC, + 0x99, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_cfg_ahb_clk", 0x98, 4, GCC, + 0x98, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_mstr_axi_clk", 0x97, 4, GCC, + 0x97, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_pipe_clk", 0x9A, 4, GCC, + 0x9A, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_rchng_phy_clk", 0xB9, 4, GCC, + 0xB9, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_sleep_clk", 0x9C, 4, GCC, + 0x9C, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_slv_axi_clk", 0x96, 4, GCC, + 0x96, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pcie_slv_q2a_axi_clk", 0x95, 4, GCC, + 0x95, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pdm2_clk", 0x48, 4, GCC, + 0x48, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pdm_ahb_clk", 0x46, 4, GCC, + 0x46, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_pdm_xo4_clk", 0x47, 4, GCC, + 0x47, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_sdcc1_ahb_clk", 0x33, 4, GCC, + 0x33, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_sdcc1_apps_clk", 0x32, 4, GCC, + 0x32, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_spmi_fetcher_ahb_clk", 0xB5, 4, GCC, + 0xB5, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_spmi_fetcher_clk", 0xB4, 4, GCC, + 0xB4, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_sys_noc_cpuss_ahb_clk", 0x10B, 4, GCC, + 0x10B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb30_master_clk", 0x28, 4, GCC, + 0x28, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb30_mock_utmi_clk", 0x2A, 4, GCC, + 0x2A, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb30_mstr_axi_clk", 0x4F, 4, GCC, + 0x4F, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb30_sleep_clk", 0x29, 4, GCC, + 0x29, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb30_slv_ahb_clk", 0x6B, 4, GCC, + 0x6B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb3_phy_aux_clk", 0x2B, 4, GCC, + 0x2B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb3_phy_pipe_clk", 0x2D, 4, GCC, + 0x2D, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_usb_phy_cfg_ahb2phy_clk", 0x31, 4, GCC, + 0x31, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_xo_div4_clk", 0x63, 4, GCC, + 0x63, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "gcc_xo_pcie_link_clk", 0x77, 4, GCC, + 0x77, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "measure_only_bimc_clk", 0x73, 4, GCC, + 0x73, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "measure_only_ipa_2x_clk", 0xAC, 4, GCC, + 0xAC, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + { "measure_only_snoc_clk", 0x109, 4, GCC, + 0x109, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 }, + ), + .hw.init = &(struct clk_init_data){ + .name = "gcc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = debug_mux_parent_names, + .num_parents = ARRAY_SIZE(debug_mux_parent_names), + .flags = CLK_IS_MEASURE, + }, +}; + +static const struct of_device_id clk_debug_match_table[] = { + { .compatible = "qcom,debugcc-sdxprairie" }, + { } +}; + +static int map_debug_bases(struct platform_device *pdev, char *base, int cc) +{ + if (!of_get_property(pdev->dev.of_node, base, NULL)) + return -ENODEV; + + gcc_debug_mux.regmap[cc] = + syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + base); + if (IS_ERR(gcc_debug_mux.regmap[cc])) { + pr_err("Failed to map %s (ret=%ld)\n", base, + PTR_ERR(gcc_debug_mux.regmap[cc])); + return PTR_ERR(gcc_debug_mux.regmap[cc]); + } + return 0; +} + +static int clk_debug_sdxprairie_probe(struct platform_device *pdev) +{ + struct clk *clk; + int ret = 0; + + clk = devm_clk_get(&pdev->dev, "xo_clk_src"); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get xo clock\n"); + return PTR_ERR(clk); + } + + debug_mux_priv.cxo = clk; + + gcc_debug_mux.regmap = devm_kcalloc(&pdev->dev, MAX_NUM_CC, + sizeof(*gcc_debug_mux.regmap), GFP_KERNEL); + if (!gcc_debug_mux.regmap) + return -ENOMEM; + + ret = map_debug_bases(pdev, "qcom,gcc", GCC); + if (ret) + return ret; + + clk = devm_clk_register(&pdev->dev, &gcc_debug_mux.hw); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Unable to register GCC debug mux\n"); + return PTR_ERR(clk); + } + + ret = clk_debug_measure_register(&gcc_debug_mux.hw); + if (ret) + dev_err(&pdev->dev, "Could not register Measure clock\n"); + + return ret; +} + +static struct platform_driver clk_debug_driver = { + .probe = clk_debug_sdxprairie_probe, + .driver = { + .name = "debugcc-sdxprairie", + .of_match_table = clk_debug_match_table, + .owner = THIS_MODULE, + }, +}; + +int __init clk_debug_sdxprairie_init(void) +{ + return platform_driver_register(&clk_debug_driver); +} +fs_initcall(clk_debug_sdxprairie_init); + +MODULE_DESCRIPTION("QTI DEBUG CC SDXPRAIRIE Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:debugcc-sdxprairie"); diff --git a/drivers/clk/qcom/dispcc-sdmmagpie.c b/drivers/clk/qcom/dispcc-sdmmagpie.c index 0e4095403746366ac509e322941b259805ccda16..a984da87cee14506887204d48104e9b7dd088e9e 100644 --- a/drivers/clk/qcom/dispcc-sdmmagpie.c +++ b/drivers/clk/qcom/dispcc-sdmmagpie.c @@ -32,7 +32,7 @@ #include "clk-regmap-divider.h" #include "common.h" #include "reset.h" -#include "vdd-level.h" +#include "vdd-level-sdmmagpie.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } @@ -93,6 +93,11 @@ static const char * const disp_cc_parent_names_2[] = { "core_bi_pll_test_se", }; +static const char * const disp_cc_parent_names_ao[] = { + "bi_tcxo_ao", + "core_bi_pll_test_se", +}; + static const struct parent_map disp_cc_parent_map_3[] = { { P_BI_TCXO, 0 }, { P_DISP_CC_PLL0_OUT_MAIN, 1 }, @@ -562,13 +567,9 @@ static struct clk_rcg2 disp_cc_xo_clk_src = { .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "disp_cc_xo_clk_src", - .parent_names = disp_cc_parent_names_2, + .parent_names = disp_cc_parent_names_ao, .num_parents = 2, .ops = &clk_rcg2_ops, - .vdd_class = &vdd_cx, - .num_rate_max = VDD_NUM, - .rate_max = (unsigned long[VDD_NUM]) { - [VDD_LOWER] = 19200000}, }, }; diff --git a/drivers/clk/qcom/gcc-sdmmagpie.c b/drivers/clk/qcom/gcc-sdmmagpie.c index f5c25883b1c2c901bc740b9fdd7aec2a4d3f4057..6309dd52837556583a629c25e9cabcffbe771167 100644 --- a/drivers/clk/qcom/gcc-sdmmagpie.c +++ b/drivers/clk/qcom/gcc-sdmmagpie.c @@ -31,7 +31,7 @@ #include "clk-branch.h" #include "clk-rcg.h" #include "clk-regmap.h" -#include "vdd-level.h" +#include "vdd-level-sdmmagpie.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } @@ -1504,7 +1504,7 @@ static struct clk_branch gcc_disp_gpll0_div_clk_src = { .hw.init = &(struct clk_init_data){ .name = "gcc_disp_gpll0_div_clk_src", .parent_names = (const char *[]){ - "gcc_gpll0_main_div_cdiv", + "gcc_pll0_main_div_cdiv", }, .num_parents = 1, .ops = &clk_branch2_ops, @@ -1646,7 +1646,7 @@ static struct clk_branch gcc_gpu_gpll0_div_clk_src = { .hw.init = &(struct clk_init_data){ .name = "gcc_gpu_gpll0_div_clk_src", .parent_names = (const char *[]){ - "gcc_gpll0_main_div_cdiv", + "gcc_pll0_main_div_cdiv", }, .num_parents = 1, .ops = &clk_branch2_ops, @@ -2674,6 +2674,7 @@ static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = { }; static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { + .halt_reg = 0x7701c, .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x7701c, @@ -2686,6 +2687,7 @@ static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { }; static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_reg = 0x77018, .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x77018, diff --git a/drivers/clk/qcom/gpucc-sdmmagpie.c b/drivers/clk/qcom/gpucc-sdmmagpie.c index 910da9fd166142b8417a199c17b31adba6457e39..4f68ec35ca479e4a6564c6fc818cc61e7ddb1f39 100644 --- a/drivers/clk/qcom/gpucc-sdmmagpie.c +++ b/drivers/clk/qcom/gpucc-sdmmagpie.c @@ -33,7 +33,7 @@ #include "clk-regmap.h" #include "common.h" #include "reset.h" -#include "vdd-level.h" +#include "vdd-level-sdmmagpie.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } diff --git a/drivers/clk/qcom/gpucc-sm6150.c b/drivers/clk/qcom/gpucc-sm6150.c index f56e68620ffe5e3084c3739bd4120ea3678b7cb7..84191466c5a9eea355555ca96e7f3e34a837e697 100644 --- a/drivers/clk/qcom/gpucc-sm6150.c +++ b/drivers/clk/qcom/gpucc-sm6150.c @@ -37,8 +37,6 @@ #define CX_GMU_CBCR_SLEEP_SHIFT 4 #define CX_GMU_CBCR_WAKE_MASK 0xf #define CX_GMU_CBCR_WAKE_SHIFT 8 -#define GFX3D_CRC_SID_FSM_CTRL 0x1024 -#define GFX3D_CRC_MND_CFG 0x1028 #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } @@ -51,10 +49,10 @@ enum { P_GPLL0_OUT_MAIN, P_GPLL0_OUT_MAIN_DIV, P_GPU_CC_PLL0_2X_CLK, - P_CRC_DIV_PLL0_OUT_AUX2, + P_GPU_CC_PLL0_OUT_AUX2, P_GPU_CC_PLL0_OUT_MAIN, P_GPU_CC_PLL1_OUT_AUX, - P_CRC_DIV_PLL1_OUT_AUX2, + P_GPU_CC_PLL1_OUT_AUX2, P_GPU_CC_PLL1_OUT_MAIN, }; @@ -79,9 +77,9 @@ static const char * const gpu_cc_parent_names_0[] = { static const struct parent_map gpu_cc_parent_map_1[] = { { P_BI_TCXO, 0 }, { P_GPU_CC_PLL0_2X_CLK, 1 }, - { P_CRC_DIV_PLL0_OUT_AUX2, 2 }, + { P_GPU_CC_PLL0_OUT_AUX2, 2 }, { P_GPU_CC_PLL1_OUT_AUX, 3 }, - { P_CRC_DIV_PLL1_OUT_AUX2, 4 }, + { P_GPU_CC_PLL1_OUT_AUX2, 4 }, { P_GPLL0_OUT_MAIN, 5 }, { P_CORE_BI_PLL_TEST_SE, 7 }, }; @@ -89,9 +87,9 @@ static const struct parent_map gpu_cc_parent_map_1[] = { static const char * const gpu_cc_parent_names_1[] = { "bi_tcxo", "gpu_cc_pll0_out_aux", - "crc_div_pll0_out_aux2", + "gpu_cc_pll0_out_aux2", "gpu_cc_pll1_out_aux", - "crc_div_pll1_out_aux2", + "gpu_cc_pll1_out_aux2", "gpll0_out_main", "core_bi_pll_test_se", }; @@ -191,38 +189,14 @@ static struct clk_rcg2 gpu_cc_gmu_clk_src = { }, }; -static struct clk_fixed_factor crc_div_pll0_out_aux2 = { - .mult = 1, - .div = 2, - .hw.init = &(struct clk_init_data){ - .name = "crc_div_pll0_out_aux2", - .parent_names = (const char *[]){ "gpu_cc_pll0_out_aux2" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor crc_div_pll1_out_aux2 = { - .mult = 1, - .div = 2, - .hw.init = &(struct clk_init_data){ - .name = "crc_div_pll1_out_aux2", - .parent_names = (const char *[]){ "gpu_cc_pll1_out_aux2" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { - F(290000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0), - F(435000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0), - F(550000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), - F(700000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), - F(745000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), - F(845000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), - F(895000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), + F(290000000, P_GPU_CC_PLL1_OUT_AUX2, 2, 0, 0), + F(435000000, P_GPU_CC_PLL1_OUT_AUX2, 2, 0, 0), + F(550000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(700000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(745000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(845000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(895000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), { } }; @@ -434,11 +408,6 @@ static struct clk_branch gpu_cc_ahb_clk = { }, }; -struct clk_hw *gpu_cc_sm6150_hws[] = { - [CRC_DIV_PLL0_OUT_AUX2] = &crc_div_pll0_out_aux2.hw, - [CRC_DIV_PLL1_OUT_AUX2] = &crc_div_pll1_out_aux2.hw, -}; - static struct clk_regmap *gpu_cc_sm6150_clocks[] = { [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr, @@ -470,8 +439,6 @@ static const struct qcom_cc_desc gpu_cc_sm6150_desc = { .config = &gpu_cc_sm6150_regmap_config, .clks = gpu_cc_sm6150_clocks, .num_clks = ARRAY_SIZE(gpu_cc_sm6150_clocks), - .hwclks = gpu_cc_sm6150_hws, - .num_hwclks = ARRAY_SIZE(gpu_cc_sm6150_hws), }; static const struct of_device_id gpu_cc_sm6150_match_table[] = { @@ -528,14 +495,6 @@ static int gpu_cc_sm6150_probe(struct platform_device *pdev) regmap_update_bits(regmap, gpu_cc_cx_gmu_clk.clkr.enable_reg, mask, value); - /* After POR, Clock Ramp Controller(CRC) will be in bypass mode. - * Software needs to do the following operation to enable the CRC - * for GFX3D clock and divide the input clock by div by 2. - */ - regmap_update_bits(regmap, GFX3D_CRC_MND_CFG, 0x00015011, 0x00015011); - regmap_update_bits(regmap, - GFX3D_CRC_SID_FSM_CTRL, 0x00800000, 0x00800000); - dev_info(&pdev->dev, "Registered GPU CC clocks\n"); return ret; diff --git a/drivers/clk/qcom/npucc-sdmmagpie.c b/drivers/clk/qcom/npucc-sdmmagpie.c index efa104d29189123363793478e3703d8e867b1183..85278488dcffeb62b426c834b134ca8486510e0c 100644 --- a/drivers/clk/qcom/npucc-sdmmagpie.c +++ b/drivers/clk/qcom/npucc-sdmmagpie.c @@ -34,7 +34,7 @@ #include "clk-branch.h" #include "reset.h" #include "clk-alpha-pll.h" -#include "vdd-level.h" +#include "vdd-level-sdmmagpie.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } diff --git a/drivers/clk/qcom/vdd-level-sdmmagpie.h b/drivers/clk/qcom/vdd-level-sdmmagpie.h new file mode 100644 index 0000000000000000000000000000000000000000..1a4c5ccedb3bd9693f4e7b93212e5cb69778437a --- /dev/null +++ b/drivers/clk/qcom/vdd-level-sdmmagpie.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, 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. + */ + +#ifndef __DRIVERS_CLK_QCOM_VDD_LEVEL_SDMMAGPIE_H +#define __DRIVERS_CLK_QCOM_VDD_LEVEL_SDMMAGPIE_H + +#include +#include + +enum vdd_levels { + VDD_NONE, + VDD_MIN, /* MIN SVS */ + VDD_LOWER, /* SVS2 */ + VDD_LOW, /* SVS */ + VDD_LOW_L1, /* SVSL1 */ + VDD_NOMINAL, /* NOM */ + VDD_HIGH, /* TURBO */ + VDD_NUM, +}; + +static int vdd_corner[] = { + RPMH_REGULATOR_LEVEL_OFF, /* VDD_NONE */ + RPMH_REGULATOR_LEVEL_MIN_SVS, /* VDD_MIN */ + RPMH_REGULATOR_LEVEL_LOW_SVS, /* VDD_LOWER */ + RPMH_REGULATOR_LEVEL_SVS, /* VDD_LOW */ + RPMH_REGULATOR_LEVEL_SVS_L1, /* VDD_LOW_L1 */ + RPMH_REGULATOR_LEVEL_NOM, /* VDD_NOMINAL */ + RPMH_REGULATOR_LEVEL_TURBO, /* VDD_HIGH */ +}; + +#endif diff --git a/drivers/clk/qcom/videocc-sdmmagpie.c b/drivers/clk/qcom/videocc-sdmmagpie.c index 8d2d57f3104d54b6c7fa6eb73853f02a6dd15d84..922ef26b32aeb632f5241f36a2f9dbccadf83df1 100644 --- a/drivers/clk/qcom/videocc-sdmmagpie.c +++ b/drivers/clk/qcom/videocc-sdmmagpie.c @@ -32,7 +32,7 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "clk-alpha-pll.h" -#include "vdd-level.h" +#include "vdd-level-sdmmagpie.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } @@ -68,7 +68,7 @@ static const struct parent_map video_cc_parent_map_2[] = { }; static const char * const video_cc_parent_names_2[] = { - "bi_tcxo", + "bi_tcxo_ao", "core_bi_pll_test_se", }; diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 6847120b61cdeff87b7de7995c412df5a7d6449c..3acf5f041e3c3cb0a2f17cbf4e8f3a14a4f1b586 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -630,7 +630,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT, RK3399_CLKSEL_CON(31), 0, 2, MFLAGS), COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT, - RK3399_CLKSEL_CON(30), 8, 2, MFLAGS, + RK3399_CLKSEL_CON(31), 2, 1, MFLAGS, RK3399_CLKGATE_CON(8), 12, GFLAGS), /* uart */ @@ -1522,6 +1522,7 @@ static const char *const rk3399_pmucru_critical_clocks[] __initconst = { "pclk_pmu_src", "fclk_cm0s_src_pmu", "clk_timer_src_pmu", + "pclk_rkpwm_pmu", }; static void __init rk3399_clk_init(struct device_node *np) diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c index 638ace64033b92a54b930c4bdf1be65550241099..6c933b0e29a3bfb384a9fb24c369d0ff1ef7fbd4 100644 --- a/drivers/clk/tegra/clk-bpmp.c +++ b/drivers/clk/tegra/clk-bpmp.c @@ -581,9 +581,15 @@ static struct clk_hw *tegra_bpmp_clk_of_xlate(struct of_phandle_args *clkspec, unsigned int id = clkspec->args[0], i; struct tegra_bpmp *bpmp = data; - for (i = 0; i < bpmp->num_clocks; i++) - if (bpmp->clocks[i]->id == id) - return &bpmp->clocks[i]->hw; + for (i = 0; i < bpmp->num_clocks; i++) { + struct tegra_bpmp_clk *clk = bpmp->clocks[i]; + + if (!clk) + continue; + + if (clk->id == id) + return &clk->hw; + } return NULL; } diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 43e14bb512c8da4cd2c0f8a73e37a1fe1205a170..6a16d22bc6043de0b01384e9623569244a1628f1 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -555,12 +555,20 @@ EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop); void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy) { - struct policy_dbs_info *policy_dbs = policy->governor_data; + struct policy_dbs_info *policy_dbs; + + /* Protect gov->gdbs_data against cpufreq_dbs_governor_exit() */ + mutex_lock(&gov_dbs_data_mutex); + policy_dbs = policy->governor_data; + if (!policy_dbs) + goto out; mutex_lock(&policy_dbs->update_mutex); cpufreq_policy_apply_limits(policy); gov_update_sample_delay(policy_dbs, 0); - mutex_unlock(&policy_dbs->update_mutex); + +out: + mutex_unlock(&gov_dbs_data_mutex); } EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits); diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index e7966e37a5aaeeb9fe259b5a2c3d460892b14e85..ecc6d755d3c1b9131f8c43e433229e96cf667c6a 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -350,10 +350,8 @@ static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, int ret = 0; if (keylen != 2 * AES_MIN_KEY_SIZE && keylen != 2 * AES_MAX_KEY_SIZE) { - crypto_ablkcipher_set_flags(ablkcipher, - CRYPTO_TFM_RES_BAD_KEY_LEN); dev_err(jrdev, "key size mismatch\n"); - return -EINVAL; + goto badkey; } memcpy(ctx->key, key, keylen); @@ -388,7 +386,7 @@ static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, return ret; badkey: crypto_ablkcipher_set_flags(ablkcipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return 0; + return -EINVAL; } /* diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 7ff4a25440acd9813d4fb19b9ef7355d6765451d..6f3f81bb880b505797bd69bd7288083c1ceef029 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -71,8 +71,8 @@ static void rsa_priv_f2_unmap(struct device *dev, struct rsa_edesc *edesc, dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); + dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL); } static void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc, @@ -90,8 +90,8 @@ static void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc, dma_unmap_single(dev, pdb->dp_dma, p_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->dq_dma, q_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); + dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL); } /* RSA Job Completion handler */ @@ -417,13 +417,13 @@ static int set_rsa_priv_f2_pdb(struct akcipher_request *req, goto unmap_p; } - pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_TO_DEVICE); + pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp1_dma)) { dev_err(dev, "Unable to map RSA tmp1 memory\n"); goto unmap_q; } - pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_TO_DEVICE); + pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp2_dma)) { dev_err(dev, "Unable to map RSA tmp2 memory\n"); goto unmap_tmp1; @@ -451,7 +451,7 @@ static int set_rsa_priv_f2_pdb(struct akcipher_request *req, return 0; unmap_tmp1: - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); unmap_q: dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE); unmap_p: @@ -504,13 +504,13 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req, goto unmap_dq; } - pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_TO_DEVICE); + pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp1_dma)) { dev_err(dev, "Unable to map RSA tmp1 memory\n"); goto unmap_qinv; } - pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_TO_DEVICE); + pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp2_dma)) { dev_err(dev, "Unable to map RSA tmp2 memory\n"); goto unmap_tmp1; @@ -538,7 +538,7 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req, return 0; unmap_tmp1: - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); unmap_qinv: dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE); unmap_dq: diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index d258953ff488331486334f8fc24a99c1bc5d0ca1..7fa1be1845535cb5b015fd35f8173cf0f080014c 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -190,7 +190,8 @@ static void caam_jr_dequeue(unsigned long devarg) BUG_ON(CIRC_CNT(head, tail + i, JOBR_DEPTH) <= 0); /* Unmap just-run descriptor so we can post-process */ - dma_unmap_single(dev, jrp->outring[hw_idx].desc, + dma_unmap_single(dev, + caam_dma_to_cpu(jrp->outring[hw_idx].desc), jrp->entinfo[sw_idx].desc_size, DMA_TO_DEVICE); diff --git a/drivers/crypto/cavium/nitrox/nitrox_dev.h b/drivers/crypto/cavium/nitrox/nitrox_dev.h index 9a476bb6d4c7eace932edb09b040098eccee7aa0..af596455b420f60d68096b8f2d4e9c71745785fc 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_dev.h +++ b/drivers/crypto/cavium/nitrox/nitrox_dev.h @@ -35,6 +35,7 @@ struct nitrox_cmdq { /* requests in backlog queues */ atomic_t backlog_count; + int write_idx; /* command size 32B/64B */ u8 instr_size; u8 qno; @@ -87,7 +88,7 @@ struct nitrox_bh { struct bh_data *slc; }; -/* NITROX-5 driver state */ +/* NITROX-V driver state */ #define NITROX_UCODE_LOADED 0 #define NITROX_READY 1 diff --git a/drivers/crypto/cavium/nitrox/nitrox_lib.c b/drivers/crypto/cavium/nitrox/nitrox_lib.c index 4fdc921ba611b94b9a8d14e3a657a63497a4cce9..9906c00866476a33c80ba740563d60afaaf05697 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_lib.c +++ b/drivers/crypto/cavium/nitrox/nitrox_lib.c @@ -36,6 +36,7 @@ static int cmdq_common_init(struct nitrox_cmdq *cmdq) cmdq->head = PTR_ALIGN(cmdq->head_unaligned, PKT_IN_ALIGN); cmdq->dma = PTR_ALIGN(cmdq->dma_unaligned, PKT_IN_ALIGN); cmdq->qsize = (qsize + PKT_IN_ALIGN); + cmdq->write_idx = 0; spin_lock_init(&cmdq->response_lock); spin_lock_init(&cmdq->cmdq_lock); diff --git a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c index 4addc238a6ef361db59cf49359d96ea8fae98f9a..4adf28176a4e439c79f238b1232e7361dfc6207d 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c +++ b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c @@ -43,6 +43,16 @@ * Invalid flag options in AES-CCM IV. */ +static inline int incr_index(int index, int count, int max) +{ + if ((index + count) >= max) + index = index + count - max; + else + index += count; + + return index; +} + /** * dma_free_sglist - unmap and free the sg lists. * @ndev: N5 device @@ -427,30 +437,29 @@ static void post_se_instr(struct nitrox_softreq *sr, struct nitrox_cmdq *cmdq) { struct nitrox_device *ndev = sr->ndev; - union nps_pkt_in_instr_baoff_dbell pkt_in_baoff_dbell; - u64 offset; + int idx; u8 *ent; spin_lock_bh(&cmdq->cmdq_lock); - /* get the next write offset */ - offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(cmdq->qno); - pkt_in_baoff_dbell.value = nitrox_read_csr(ndev, offset); + idx = cmdq->write_idx; /* copy the instruction */ - ent = cmdq->head + pkt_in_baoff_dbell.s.aoff; + ent = cmdq->head + (idx * cmdq->instr_size); memcpy(ent, &sr->instr, cmdq->instr_size); - /* flush the command queue updates */ - dma_wmb(); - sr->tstamp = jiffies; atomic_set(&sr->status, REQ_POSTED); response_list_add(sr, cmdq); + sr->tstamp = jiffies; + /* flush the command queue updates */ + dma_wmb(); /* Ring doorbell with count 1 */ writeq(1, cmdq->dbell_csr_addr); /* orders the doorbell rings */ mmiowb(); + cmdq->write_idx = incr_index(idx, 1, ndev->qlen); + spin_unlock_bh(&cmdq->cmdq_lock); } @@ -460,6 +469,9 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq) struct nitrox_softreq *sr, *tmp; int ret = 0; + if (!atomic_read(&cmdq->backlog_count)) + return 0; + spin_lock_bh(&cmdq->backlog_lock); list_for_each_entry_safe(sr, tmp, &cmdq->backlog_head, backlog) { @@ -467,7 +479,7 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq) /* submit until space available */ if (unlikely(cmdq_full(cmdq, ndev->qlen))) { - ret = -EBUSY; + ret = -ENOSPC; break; } /* delete from backlog list */ @@ -492,23 +504,20 @@ static int nitrox_enqueue_request(struct nitrox_softreq *sr) { struct nitrox_cmdq *cmdq = sr->cmdq; struct nitrox_device *ndev = sr->ndev; - int ret = -EBUSY; + + /* try to post backlog requests */ + post_backlog_cmds(cmdq); if (unlikely(cmdq_full(cmdq, ndev->qlen))) { if (!(sr->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) - return -EAGAIN; - + return -ENOSPC; + /* add to backlog list */ backlog_list_add(sr, cmdq); - } else { - ret = post_backlog_cmds(cmdq); - if (ret) { - backlog_list_add(sr, cmdq); - return ret; - } - post_se_instr(sr, cmdq); - ret = -EINPROGRESS; + return -EBUSY; } - return ret; + post_se_instr(sr, cmdq); + + return -EINPROGRESS; } /** @@ -625,11 +634,9 @@ int nitrox_process_se_request(struct nitrox_device *ndev, */ sr->instr.fdata[0] = *((u64 *)&req->gph); sr->instr.fdata[1] = 0; - /* flush the soft_req changes before posting the cmd */ - wmb(); ret = nitrox_enqueue_request(sr); - if (ret == -EAGAIN) + if (ret == -ENOSPC) goto send_fail; return ret; diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 08e7bdcaa6e318c5bae2290bf57ac3c1bae3d95e..085c229eab1de06b1eea7e3ac42255419d4a7b42 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -1351,7 +1351,7 @@ static int sahara_register_algs(struct sahara_dev *dev) err_sha_v3_algs: for (j = 0; j < k; j++) - crypto_unregister_ahash(&sha_v4_algs[j]); + crypto_unregister_ahash(&sha_v3_algs[j]); err_aes_algs: for (j = 0; j < i; j++) @@ -1367,7 +1367,7 @@ static void sahara_unregister_algs(struct sahara_dev *dev) for (i = 0; i < ARRAY_SIZE(aes_algs); i++) crypto_unregister_alg(&aes_algs[i]); - for (i = 0; i < ARRAY_SIZE(sha_v4_algs); i++) + for (i = 0; i < ARRAY_SIZE(sha_v3_algs); i++) crypto_unregister_ahash(&sha_v3_algs[i]); if (dev->version > SAHARA_VERSION_3) diff --git a/drivers/crypto/vmx/aes_cbc.c b/drivers/crypto/vmx/aes_cbc.c index 5285ece4f33a36df39bfd18068dd14ce6a1213db..b71895871be3f1f2ec0b15d19d4087a16f40016f 100644 --- a/drivers/crypto/vmx/aes_cbc.c +++ b/drivers/crypto/vmx/aes_cbc.c @@ -107,24 +107,23 @@ static int p8_aes_cbc_encrypt(struct blkcipher_desc *desc, ret = crypto_skcipher_encrypt(req); skcipher_request_zero(req); } else { - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - blkcipher_walk_init(&walk, dst, src, nbytes); ret = blkcipher_walk_virt(desc, &walk); while ((nbytes = walk.nbytes)) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); aes_p8_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->enc_key, walk.iv, 1); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, &walk, nbytes); } - - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); } return ret; @@ -147,24 +146,23 @@ static int p8_aes_cbc_decrypt(struct blkcipher_desc *desc, ret = crypto_skcipher_decrypt(req); skcipher_request_zero(req); } else { - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - blkcipher_walk_init(&walk, dst, src, nbytes); ret = blkcipher_walk_virt(desc, &walk); while ((nbytes = walk.nbytes)) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); aes_p8_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->dec_key, walk.iv, 0); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, &walk, nbytes); } - - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); } return ret; diff --git a/drivers/crypto/vmx/aes_ctr.c b/drivers/crypto/vmx/aes_ctr.c index 02ba5f2aa0e6e8d09b431d9ad0019fa4c1549f94..cd777c75291dfb72f6df5c2967909da694627b78 100644 --- a/drivers/crypto/vmx/aes_ctr.c +++ b/drivers/crypto/vmx/aes_ctr.c @@ -27,21 +27,23 @@ #include #include #include +#include + #include "aesp8-ppc.h" struct p8_aes_ctr_ctx { - struct crypto_blkcipher *fallback; + struct crypto_skcipher *fallback; struct aes_key enc_key; }; static int p8_aes_ctr_init(struct crypto_tfm *tfm) { const char *alg = crypto_tfm_alg_name(tfm); - struct crypto_blkcipher *fallback; + struct crypto_skcipher *fallback; struct p8_aes_ctr_ctx *ctx = crypto_tfm_ctx(tfm); - fallback = - crypto_alloc_blkcipher(alg, 0, CRYPTO_ALG_NEED_FALLBACK); + fallback = crypto_alloc_skcipher(alg, 0, + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(fallback)) { printk(KERN_ERR "Failed to allocate transformation for '%s': %ld\n", @@ -49,9 +51,9 @@ static int p8_aes_ctr_init(struct crypto_tfm *tfm) return PTR_ERR(fallback); } - crypto_blkcipher_set_flags( + crypto_skcipher_set_flags( fallback, - crypto_blkcipher_get_flags((struct crypto_blkcipher *)tfm)); + crypto_skcipher_get_flags((struct crypto_skcipher *)tfm)); ctx->fallback = fallback; return 0; @@ -62,7 +64,7 @@ static void p8_aes_ctr_exit(struct crypto_tfm *tfm) struct p8_aes_ctr_ctx *ctx = crypto_tfm_ctx(tfm); if (ctx->fallback) { - crypto_free_blkcipher(ctx->fallback); + crypto_free_skcipher(ctx->fallback); ctx->fallback = NULL; } } @@ -81,7 +83,7 @@ static int p8_aes_ctr_setkey(struct crypto_tfm *tfm, const u8 *key, pagefault_enable(); preempt_enable(); - ret += crypto_blkcipher_setkey(ctx->fallback, key, keylen); + ret += crypto_skcipher_setkey(ctx->fallback, key, keylen); return ret; } @@ -115,15 +117,14 @@ static int p8_aes_ctr_crypt(struct blkcipher_desc *desc, struct blkcipher_walk walk; struct p8_aes_ctr_ctx *ctx = crypto_tfm_ctx(crypto_blkcipher_tfm(desc->tfm)); - struct blkcipher_desc fallback_desc = { - .tfm = ctx->fallback, - .info = desc->info, - .flags = desc->flags - }; if (in_interrupt()) { - ret = crypto_blkcipher_encrypt(&fallback_desc, dst, src, - nbytes); + SKCIPHER_REQUEST_ON_STACK(req, ctx->fallback); + skcipher_request_set_tfm(req, ctx->fallback); + skcipher_request_set_callback(req, desc->flags, NULL, NULL); + skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); } else { blkcipher_walk_init(&walk, dst, src, nbytes); ret = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE); diff --git a/drivers/crypto/vmx/aes_xts.c b/drivers/crypto/vmx/aes_xts.c index 8bd9aff0f55fba6639b67147cf97c2fcfce12bfc..e9954a7d46944d36cd2aeffdfd8202b54c793d71 100644 --- a/drivers/crypto/vmx/aes_xts.c +++ b/drivers/crypto/vmx/aes_xts.c @@ -116,32 +116,39 @@ static int p8_aes_xts_crypt(struct blkcipher_desc *desc, ret = enc? crypto_skcipher_encrypt(req) : crypto_skcipher_decrypt(req); skcipher_request_zero(req); } else { + blkcipher_walk_init(&walk, dst, src, nbytes); + + ret = blkcipher_walk_virt(desc, &walk); + preempt_disable(); pagefault_disable(); enable_kernel_vsx(); - blkcipher_walk_init(&walk, dst, src, nbytes); - - ret = blkcipher_walk_virt(desc, &walk); iv = walk.iv; memset(tweak, 0, AES_BLOCK_SIZE); aes_p8_encrypt(iv, tweak, &ctx->tweak_key); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + while ((nbytes = walk.nbytes)) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); if (enc) aes_p8_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->enc_key, NULL, tweak); else aes_p8_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->dec_key, NULL, tweak); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, &walk, nbytes); } - - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); } return ret; } diff --git a/drivers/dax/device.c b/drivers/dax/device.c index 7b0bf825c4e73c588ff93183cf5315665d69e082..050e299129acf5167774fbd9d6569feabd58f685 100644 --- a/drivers/dax/device.c +++ b/drivers/dax/device.c @@ -188,14 +188,16 @@ static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma, /* prevent private mappings from being established */ if ((vma->vm_flags & VM_MAYSHARE) != VM_MAYSHARE) { - dev_info(dev, "%s: %s: fail, attempted private mapping\n", + dev_info_ratelimited(dev, + "%s: %s: fail, attempted private mapping\n", current->comm, func); return -EINVAL; } mask = dax_region->align - 1; if (vma->vm_start & mask || vma->vm_end & mask) { - dev_info(dev, "%s: %s: fail, unaligned vma (%#lx - %#lx, %#lx)\n", + dev_info_ratelimited(dev, + "%s: %s: fail, unaligned vma (%#lx - %#lx, %#lx)\n", current->comm, func, vma->vm_start, vma->vm_end, mask); return -EINVAL; @@ -203,13 +205,15 @@ static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma, if ((dax_region->pfn_flags & (PFN_DEV|PFN_MAP)) == PFN_DEV && (vma->vm_flags & VM_DONTCOPY) == 0) { - dev_info(dev, "%s: %s: fail, dax range requires MADV_DONTFORK\n", + dev_info_ratelimited(dev, + "%s: %s: fail, dax range requires MADV_DONTFORK\n", current->comm, func); return -EINVAL; } if (!vma_is_dax(vma)) { - dev_info(dev, "%s: %s: fail, vma is not DAX capable\n", + dev_info_ratelimited(dev, + "%s: %s: fail, vma is not DAX capable\n", current->comm, func); return -EINVAL; } diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index c5666c870b335df3cd6320e99ecac1bf478c50ee..6afdb9d727814c3d0d0a010366fe79c58c65e21d 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -522,7 +522,7 @@ static void devfreq_dev_release(struct device *dev) devfreq->profile->exit(devfreq->dev.parent); mutex_destroy(&devfreq->lock); - mutex_destroy(&devfreq->sysfs_lock); + mutex_destroy(&devfreq->event_lock); kfree(devfreq); } @@ -565,7 +565,7 @@ struct devfreq *devfreq_add_device(struct device *dev, } mutex_init(&devfreq->lock); - mutex_init(&devfreq->sysfs_lock); + mutex_init(&devfreq->event_lock); mutex_lock(&devfreq->lock); devfreq->dev.parent = dev; devfreq->dev.class = devfreq_class; @@ -777,14 +777,19 @@ EXPORT_SYMBOL(devm_devfreq_remove_device); */ int devfreq_suspend_device(struct devfreq *devfreq) { + int ret; + if (!devfreq) return -EINVAL; if (!devfreq->governor) return 0; - return devfreq->governor->event_handler(devfreq, + mutex_lock(&devfreq->event_lock); + ret = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_SUSPEND, NULL); + mutex_unlock(&devfreq->event_lock); + return ret; } EXPORT_SYMBOL(devfreq_suspend_device); @@ -798,14 +803,18 @@ EXPORT_SYMBOL(devfreq_suspend_device); */ int devfreq_resume_device(struct devfreq *devfreq) { + int ret; if (!devfreq) return -EINVAL; if (!devfreq->governor) return 0; - return devfreq->governor->event_handler(devfreq, + mutex_lock(&devfreq->event_lock); + ret = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_RESUME, NULL); + mutex_unlock(&devfreq->event_lock); + return ret; } EXPORT_SYMBOL(devfreq_resume_device); @@ -965,7 +974,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, goto out; } - mutex_lock(&df->sysfs_lock); + mutex_lock(&df->event_lock); if (df->governor) { ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL); if (ret) { @@ -991,7 +1000,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, } gov_stop_out: - mutex_unlock(&df->sysfs_lock); + mutex_unlock(&df->event_lock); out: mutex_unlock(&devfreq_list_lock); @@ -1086,10 +1095,10 @@ static ssize_t polling_interval_store(struct device *dev, if (ret != 1) return -EINVAL; - mutex_lock(&df->sysfs_lock); + mutex_lock(&df->event_lock); df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value); ret = count; - mutex_unlock(&df->sysfs_lock); + mutex_unlock(&df->event_lock); return ret; } @@ -1107,7 +1116,7 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, if (ret != 1) return -EINVAL; - mutex_lock(&df->sysfs_lock); + mutex_lock(&df->event_lock); mutex_lock(&df->lock); max = df->max_freq; if (value && max && value > max) { @@ -1120,7 +1129,7 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, ret = count; unlock: mutex_unlock(&df->lock); - mutex_unlock(&df->sysfs_lock); + mutex_unlock(&df->event_lock); return ret; } @@ -1136,7 +1145,7 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, if (ret != 1) return -EINVAL; - mutex_lock(&df->sysfs_lock); + mutex_lock(&df->event_lock); mutex_lock(&df->lock); min = df->min_freq; if (value && min && value < min) { @@ -1149,7 +1158,7 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, ret = count; unlock: mutex_unlock(&df->lock); - mutex_unlock(&df->sysfs_lock); + mutex_unlock(&df->event_lock); return ret; } diff --git a/drivers/devfreq/governor_gpubw_mon.c b/drivers/devfreq/governor_gpubw_mon.c index 9c24eef6a4976d049aa126ffde5a1ab172789c25..6c53704aac9c3d633e7ae58fc5e158f48e1dc1d5 100644 --- a/drivers/devfreq/governor_gpubw_mon.c +++ b/drivers/devfreq/governor_gpubw_mon.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, 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 @@ -24,6 +24,7 @@ #define HIST 5 #define TARGET 80 #define CAP 75 +#define WAIT_THRESHOLD 10 /* AB vote is in multiple of BW_STEP Mega bytes */ #define BW_STEP 160 @@ -65,7 +66,9 @@ static int devfreq_gpubw_get_target(struct devfreq *df, int result; int level = 0; int act_level; + int norm_max_cycles; int norm_cycles; + int wait_active_percent; int gpu_percent; /* * Normalized AB should at max usage be the gpu_bimc frequency in MHz. @@ -94,8 +97,12 @@ static int devfreq_gpubw_get_target(struct devfreq *df, if (priv->bus.total_time < LONG_FLOOR) return result; + norm_max_cycles = (unsigned int)(priv->bus.ram_time) / + (unsigned int) priv->bus.total_time; norm_cycles = (unsigned int)(priv->bus.ram_time + priv->bus.ram_wait) / (unsigned int) priv->bus.total_time; + wait_active_percent = (100 * (unsigned int)priv->bus.ram_wait) / + (unsigned int) priv->bus.ram_time; gpu_percent = (100 * (unsigned int)priv->bus.gpu_time) / (unsigned int) priv->bus.total_time; @@ -104,8 +111,8 @@ static int devfreq_gpubw_get_target(struct devfreq *df, * FAST hint. Otherwise check the current value against the current * cutoffs. */ - if (norm_cycles > priv->bus.max) { - _update_cutoff(priv, norm_cycles); + if (norm_max_cycles > priv->bus.max) { + _update_cutoff(priv, norm_max_cycles); bus_profile->flag = DEVFREQ_FLAG_FAST_HINT; } else { /* GPU votes for IB not AB so don't under vote the system */ @@ -114,7 +121,8 @@ static int devfreq_gpubw_get_target(struct devfreq *df, act_level = (act_level < 0) ? 0 : act_level; act_level = (act_level >= priv->bus.num) ? (priv->bus.num - 1) : act_level; - if (norm_cycles > priv->bus.up[act_level] && + if ((norm_cycles > priv->bus.up[act_level] || + wait_active_percent > WAIT_THRESHOLD) && gpu_percent > CAP) bus_profile->flag = DEVFREQ_FLAG_FAST_HINT; else if (norm_cycles < priv->bus.down[act_level] && level) diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index 01d2a750a6217c062daedbac6b44d0e59aafd2e2..219ae3b545dbab035d20ce628c7a025159f9e9bb 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -787,7 +787,7 @@ static struct dma_chan *k3_of_dma_simple_xlate(struct of_phandle_args *dma_spec, struct k3_dma_dev *d = ofdma->of_dma_data; unsigned int request = dma_spec->args[0]; - if (request > d->dma_requests) + if (request >= d->dma_requests) return NULL; return dma_get_slave_channel(&(d->chans[request].vc.chan)); diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index 3548caa9e9339f17208a62066ad055c842491e3b..75eef589d0ecbe717392df0e0a9ab352e24bdea9 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -898,6 +898,8 @@ static int mv_xor_v2_remove(struct platform_device *pdev) platform_msi_domain_free_irqs(&pdev->dev); + tasklet_kill(&xor_dev->irq_tasklet); + clk_disable_unprepare(xor_dev->clk); return 0; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 7432c8894e321c415bb3f6d18a3ff73e3b181e04..6afd42cfbf5d5014c069b1e750b741dc1dc9c31d 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2142,13 +2142,14 @@ static int pl330_terminate_all(struct dma_chan *chan) pm_runtime_get_sync(pl330->ddma.dev); spin_lock_irqsave(&pch->lock, flags); + spin_lock(&pl330->lock); _stop(pch->thread); - spin_unlock(&pl330->lock); - pch->thread->req[0].desc = NULL; pch->thread->req[1].desc = NULL; pch->thread->req_running = -1; + spin_unlock(&pl330->lock); + power_down = pch->active; pch->active = false; @@ -2923,7 +2924,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pd->src_addr_widths = PL330_DMA_BUSWIDTHS; pd->dst_addr_widths = PL330_DMA_BUSWIDTHS; pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); - pd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; + pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ? 1 : PL330_MAX_BURST); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 480072139b7aa00db3d27d9381c0e6eace04835e..80801c616395e144def7675192625a4dcf5788cf 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -215,6 +215,7 @@ const char * const edac_mem_types[] = { [MEM_LRDDR3] = "Load-Reduced DDR3 RAM", [MEM_DDR4] = "Unbuffered DDR4 RAM", [MEM_RDDR4] = "Registered DDR4 RAM", + [MEM_LRDDR4] = "Load-Reduced-DDR4-RAM", }; EXPORT_SYMBOL_GPL(edac_mem_types); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index c70ea82c815c90966e1cf22c3781d16f5eed6ce6..594ce6abd370085203184b038c690d1954373872 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -1097,14 +1097,14 @@ int __init edac_mc_sysfs_init(void) err = device_add(mci_pdev); if (err < 0) - goto out_dev_free; + goto out_put_device; edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); return 0; - out_dev_free: - kfree(mci_pdev); + out_put_device: + put_device(mci_pdev); out: return err; } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index c16c3b931b3d0ef9cd68b01e6d81de4987d5c794..6c7d5f20eacbd8c9652561f7edc1bebb801e6d73 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1177,15 +1177,14 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) rc = device_add(pvt->addrmatch_dev); if (rc < 0) - return rc; + goto err_put_addrmatch; if (!pvt->is_registered) { pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), GFP_KERNEL); if (!pvt->chancounts_dev) { - put_device(pvt->addrmatch_dev); - device_del(pvt->addrmatch_dev); - return -ENOMEM; + rc = -ENOMEM; + goto err_del_addrmatch; } pvt->chancounts_dev->type = &all_channel_counts_type; @@ -1199,9 +1198,18 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) rc = device_add(pvt->chancounts_dev); if (rc < 0) - return rc; + goto err_put_chancounts; } return 0; + +err_put_chancounts: + put_device(pvt->chancounts_dev); +err_del_addrmatch: + device_del(pvt->addrmatch_dev); +err_put_addrmatch: + put_device(pvt->addrmatch_dev); + + return rc; } static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) @@ -1211,11 +1219,11 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) edac_dbg(1, "\n"); if (!pvt->is_registered) { - put_device(pvt->chancounts_dev); device_del(pvt->chancounts_dev); + put_device(pvt->chancounts_dev); } - put_device(pvt->addrmatch_dev); device_del(pvt->addrmatch_dev); + put_device(pvt->addrmatch_dev); } /**************************************************************************** diff --git a/drivers/esoc/esoc-mdm-4x.c b/drivers/esoc/esoc-mdm-4x.c index bfa0658ea61603093ba0e0285b9d78397a656a3b..2ff2972d454bbae57eaf4e5a2c4ee7afc35142f2 100644 --- a/drivers/esoc/esoc-mdm-4x.c +++ b/drivers/esoc/esoc-mdm-4x.c @@ -1051,6 +1051,26 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm, return ret; } +static int sdxprairie_setup_hw(struct mdm_ctrl *mdm, + const struct mdm_ops *ops, + struct platform_device *pdev) +{ + int ret; + + /* Same configuration as that of sdx50, except for the name */ + ret = sdx50m_setup_hw(mdm, ops, pdev); + if (ret) { + dev_err(mdm->dev, "Hardware setup failed for sdxprairie\n"); + esoc_mdm_log("Hardware setup failed for sdxprairie\n"); + return ret; + } + + mdm->esoc->name = SDXPRAIRIE_LABEL; + esoc_mdm_log("Hardware setup done for sdxprairie\n"); + + return ret; +} + static struct esoc_clink_ops mdm_cops = { .cmd_exe = mdm_cmd_exe, .get_status = mdm_get_status, @@ -1070,11 +1090,19 @@ static struct mdm_ops sdx50m_ops = { .pon_ops = &sdx50m_pon_ops, }; +static struct mdm_ops sdxprairie_ops = { + .clink_ops = &mdm_cops, + .config_hw = sdxprairie_setup_hw, + .pon_ops = &sdx50m_pon_ops, +}; + static const struct of_device_id mdm_dt_match[] = { { .compatible = "qcom,ext-mdm9x55", .data = &mdm9x55_ops, }, { .compatible = "qcom,ext-sdx50m", .data = &sdx50m_ops, }, + { .compatible = "qcom,ext-sdxprairie", + .data = &sdxprairie_ops, }, {}, }; MODULE_DEVICE_TABLE(of, mdm_dt_match); diff --git a/drivers/esoc/esoc-mdm-drv.c b/drivers/esoc/esoc-mdm-drv.c index aef3a8b81ae25216eb033ada2f460855892bcf3b..2004cb4af74ea93587079b63fec9bef27720e7a4 100644 --- a/drivers/esoc/esoc-mdm-drv.c +++ b/drivers/esoc/esoc-mdm-drv.c @@ -518,6 +518,10 @@ static struct esoc_compat compat_table[] = { .name = "SDX50M", .data = NULL, }, + { + .name = "SDXPRAIRIE", + .data = NULL, + }, }; static struct esoc_drv esoc_ssr_drv = { diff --git a/drivers/esoc/esoc-mdm.h b/drivers/esoc/esoc-mdm.h index b6e1965b6889a9c8209034709cb4338e6649ad34..107fad66b1a330a94a1d152177d18107fb76bf40 100644 --- a/drivers/esoc/esoc-mdm.h +++ b/drivers/esoc/esoc-mdm.h @@ -31,6 +31,7 @@ #define MDM9x55_PCIE "PCIe" #define SDX50M_LABEL "SDX50M" #define SDX50M_PCIE "PCIe" +#define SDXPRAIRIE_LABEL "SDXPRAIRIE" #define MDM2AP_STATUS_TIMEOUT_MS 120000L #define MDM_MODEM_TIMEOUT 3000 #define DEF_RAMDUMP_TIMEOUT 120000 diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index e098d7a7138a595e643a70817ff84408e9075d51..97bd841334e40e5aabf3ed136b54eaac9ce753cc 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -433,8 +433,8 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id) return index; spin_lock_irqsave(&edev->lock, flags); - state = !!(edev->state & BIT(index)); + spin_unlock_irqrestore(&edev->lock, flags); /* * Call functions in a raw notifier chain for the specific one @@ -448,6 +448,7 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id) */ raw_notifier_call_chain(&edev->nh_all, state, edev); + spin_lock_irqsave(&edev->lock, flags); /* This could be in interrupt handler */ prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); if (!prop_buf) { diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 80d1a885def5c2dd8bd15591bcc7c62d9b2e3b8c..a7c522eac640feb84d25b436cf54461e797f8d10 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -259,7 +259,6 @@ void __init efi_init(void) reserve_regions(); efi_esrt_init(); - efi_memmap_unmap(); memblock_reserve(params.mmap & PAGE_MASK, PAGE_ALIGN(params.mmap_size + diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 86a1ad17a32e2cd4acf3fb64a774b7cfabc271f1..8995a48bd0676229f5d22396d75a2946fed5b721 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -122,11 +122,13 @@ static int __init arm_enable_runtime_services(void) { u64 mapsize; - if (!efi_enabled(EFI_BOOT)) { + if (!efi_enabled(EFI_BOOT) || !efi_enabled(EFI_MEMMAP)) { pr_info("EFI services will not be available.\n"); return 0; } + efi_memmap_unmap(); + if (efi_runtime_disabled()) { pr_info("EFI runtime services will be disabled.\n"); return 0; diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index c47e0c6ec00f858c0b9960f605974b4f2e4b1294..f3c28777b8c6fed9bb351ad1d93307b3651a8adb 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -333,7 +333,8 @@ void __init efi_esrt_init(void) end = esrt_data + size; pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end); - efi_mem_reserve(esrt_data, esrt_data_size); + if (md.type == EFI_BOOT_SERVICES_DATA) + efi_mem_reserve(esrt_data, esrt_data_size); pr_debug("esrt-init: loaded.\n"); err_memunmap: diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index e4b40f2b46274a0871d1cb881732e8358a324112..9c0f7cf920afe561a83b62ac5b5dfb279bae6c1a 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -246,6 +246,7 @@ static int vpd_section_destroy(struct vpd_section *sec) sysfs_remove_bin_file(vpd_kobj, &sec->bin_attr); kfree(sec->raw_name); memunmap(sec->baseaddr); + sec->enabled = false; } return 0; @@ -279,8 +280,10 @@ static int vpd_sections_init(phys_addr_t physaddr) ret = vpd_section_init("rw", &rw_vpd, physaddr + sizeof(struct vpd_cbmem) + header.ro_size, header.rw_size); - if (ret) + if (ret) { + vpd_section_destroy(&ro_vpd); return ret; + } } return 0; diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index e1037582e34d7f69da7b3e96586f288b1f723f0b..b2635326546e7d3ac2e675b01d21ad234e5cd52a 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -56,9 +56,9 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, rnd = fls(debounce) - 1; if (rnd && (debounce & BIT(rnd - 1))) - debounce = round_up(debounce, MEN_Z127_DB_MIN_US); + debounce = roundup(debounce, MEN_Z127_DB_MIN_US); else - debounce = round_down(debounce, MEN_Z127_DB_MIN_US); + debounce = rounddown(debounce, MEN_Z127_DB_MIN_US); if (debounce > MEN_Z127_DB_MAX_US) debounce = MEN_Z127_DB_MAX_US; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 4b80e996d976524398e6ad484dd2f552bcdbed65..1022fe8d09c79c1543b2bb7d6f677b148d779e05 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -497,9 +497,10 @@ static int ioh_gpio_probe(struct pci_dev *pdev, return 0; err_gpiochip_add: + chip = chip_save; while (--i >= 0) { - chip--; gpiochip_remove(&chip->gpio); + chip++; } kfree(chip_save); diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 6029899789f3dbcfa51e2227d6b94a115bf0a3e5..2943dfc4c470742511c190dedce079a10066ce94 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -662,6 +662,8 @@ static int pxa_gpio_probe(struct platform_device *pdev) pchip->irq0 = irq0; pchip->irq1 = irq1; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; gpio_reg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!gpio_reg_base) diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index fbaf974277dffd9c90e57f03037a4b3fe8fa6da5..1eb857e2f62f166339bce3ff3c673b7c256845f4 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -728,4 +728,4 @@ static int __init tegra_gpio_init(void) { return platform_driver_register(&tegra_gpio_driver); } -postcore_initcall(tegra_gpio_init); +subsys_initcall(tegra_gpio_init); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index d6f3d9ee1350e422e3f373427d55d6ce8b6be565..70b3c556f6cf29a377642299e93257f2ab489969 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -25,6 +25,7 @@ struct acpi_gpio_event { struct list_head node; + struct list_head initial_sync_list; acpi_handle handle; unsigned int pin; unsigned int irq; @@ -50,6 +51,9 @@ struct acpi_gpio_chip { struct list_head events; }; +static LIST_HEAD(acpi_gpio_initial_sync_list); +static DEFINE_MUTEX(acpi_gpio_initial_sync_list_lock); + static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) { if (!gc->parent) @@ -142,6 +146,21 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin) return gpiochip_get_desc(chip, offset); } +static void acpi_gpio_add_to_initial_sync_list(struct acpi_gpio_event *event) +{ + mutex_lock(&acpi_gpio_initial_sync_list_lock); + list_add(&event->initial_sync_list, &acpi_gpio_initial_sync_list); + mutex_unlock(&acpi_gpio_initial_sync_list_lock); +} + +static void acpi_gpio_del_from_initial_sync_list(struct acpi_gpio_event *event) +{ + mutex_lock(&acpi_gpio_initial_sync_list_lock); + if (!list_empty(&event->initial_sync_list)) + list_del_init(&event->initial_sync_list); + mutex_unlock(&acpi_gpio_initial_sync_list_lock); +} + static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) { struct acpi_gpio_event *event = data; @@ -193,7 +212,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, irq_handler_t handler = NULL; struct gpio_desc *desc; unsigned long irqflags; - int ret, pin, irq; + int ret, pin, irq, value; if (!acpi_gpio_get_irq_resource(ares, &agpio)) return AE_OK; @@ -228,6 +247,8 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, gpiod_direction_input(desc); + value = gpiod_get_value(desc); + ret = gpiochip_lock_as_irq(chip, pin); if (ret) { dev_err(chip->parent, "Failed to lock GPIO as interrupt\n"); @@ -269,6 +290,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, event->irq = irq; event->pin = pin; event->desc = desc; + INIT_LIST_HEAD(&event->initial_sync_list); ret = request_threaded_irq(event->irq, NULL, handler, irqflags, "ACPI:Event", event); @@ -283,6 +305,18 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, enable_irq_wake(irq); list_add_tail(&event->node, &acpi_gpio->events); + + /* + * Make sure we trigger the initial state of the IRQ when using RISING + * or FALLING. Note we run the handlers on late_init, the AML code + * may refer to OperationRegions from other (builtin) drivers which + * may be probed after us. + */ + if (handler == acpi_gpio_irq_handler && + (((irqflags & IRQF_TRIGGER_RISING) && value == 1) || + ((irqflags & IRQF_TRIGGER_FALLING) && value == 0))) + acpi_gpio_add_to_initial_sync_list(event); + return AE_OK; fail_free_event: @@ -355,6 +389,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) { struct gpio_desc *desc; + acpi_gpio_del_from_initial_sync_list(event); + if (irqd_is_wakeup_set(irq_get_irq_data(event->irq))) disable_irq_wake(event->irq); @@ -1210,3 +1246,21 @@ bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id) return con_id == NULL; } + +/* Sync the initial state of handlers after all builtin drivers have probed */ +static int acpi_gpio_initial_sync(void) +{ + struct acpi_gpio_event *event, *ep; + + mutex_lock(&acpi_gpio_initial_sync_list_lock); + list_for_each_entry_safe(event, ep, &acpi_gpio_initial_sync_list, + initial_sync_list) { + acpi_evaluate_object(event->handle, NULL, NULL, NULL); + list_del_init(&event->initial_sync_list); + } + mutex_unlock(&acpi_gpio_initial_sync_list_lock); + + return 0; +} +/* We must use _sync so that this runs after the first deferred_probe run */ +late_initcall_sync(acpi_gpio_initial_sync); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 3d4d0634c9ddd560797e2d85c71f271a83709d3e..7a3d9658d74c51074f4ea54bfb5863e39a7c168c 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -88,7 +88,7 @@ struct acpi_gpio_info { }; /* gpio suffixes used for ACPI and device tree lookup */ -static const char * const gpio_suffixes[] = { "gpios", "gpio" }; +static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; #ifdef CONFIG_OF_GPIO struct gpio_desc *of_find_gpio(struct device *dev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index fd435a96481c2f1c019bd4d2303ebbb9b590adad..e8d9479615c955ac2c624e12f41e89e4b081b371 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -715,12 +715,14 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, break; case CHIP_POLARIS10: if (type == CGS_UCODE_ID_SMU) { - if ((adev->pdev->device == 0x67df) && - ((adev->pdev->revision == 0xe0) || - (adev->pdev->revision == 0xe3) || - (adev->pdev->revision == 0xe4) || - (adev->pdev->revision == 0xe5) || - (adev->pdev->revision == 0xe7) || + if (((adev->pdev->device == 0x67df) && + ((adev->pdev->revision == 0xe0) || + (adev->pdev->revision == 0xe3) || + (adev->pdev->revision == 0xe4) || + (adev->pdev->revision == 0xe5) || + (adev->pdev->revision == 0xe7) || + (adev->pdev->revision == 0xef))) || + ((adev->pdev->device == 0x6fdf) && (adev->pdev->revision == 0xef))) { info->is_kicker = true; strcpy(fw_name, "amdgpu/polaris10_k_smc.bin"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 0f16986ec5bc44356c19e9a7988a57e4b35f05bb..4dd68d8213538e548a557cff6229261e75ee1306 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -500,6 +500,7 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, {0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, {0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, + {0x1002, 0x6FDF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, /* Polaris12 */ {0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, {0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 8c2204c7b3847c3ce18042b48d70516155b843e5..7ad8fa891ce6b97bac4390eb0bd377d4b280b1d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -134,6 +134,11 @@ psp_cmd_submit_buf(struct psp_context *psp, msleep(1); } + if (ucode) { + ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; + ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi; + } + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index 30b5500dc152140ca5ef49f3d6f217e04cdf2fc8..fa7b25e1e5d2990b7e2aa0e1e7ad6374dc3f2d34 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -172,6 +172,7 @@ enum AMDGPU_UCODE_ID { AMDGPU_UCODE_ID_SMC, AMDGPU_UCODE_ID_UVD, AMDGPU_UCODE_ID_VCE, + AMDGPU_UCODE_ID_VCN, AMDGPU_UCODE_ID_MAXIMUM, }; @@ -204,6 +205,9 @@ struct amdgpu_firmware_info { void *kaddr; /* ucode_size_bytes */ uint32_t ucode_size; + /* starting tmr mc address */ + uint32_t tmr_mc_addr_lo; + uint32_t tmr_mc_addr_hi; }; void amdgpu_ucode_print_mc_hdr(const struct common_firmware_header *hdr); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 308a9755eae39b2582bc20e00d8c6b3ce7e91e14..1612d8aa6ad609b03d29713ea620f65883c90677 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -93,9 +93,10 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) version_major, version_minor, family_id); - bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8) - + AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_HEAP_SIZE + bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_HEAP_SIZE + AMDGPU_VCN_SESSION_SIZE * 40; + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) + bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.vcpu_bo, &adev->vcn.gpu_addr, &adev->vcn.cpu_addr); @@ -191,11 +192,13 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev) unsigned offset; hdr = (const struct common_firmware_header *)adev->vcn.fw->data; - offset = le32_to_cpu(hdr->ucode_array_offset_bytes); - memcpy_toio(adev->vcn.cpu_addr, adev->vcn.fw->data + offset, - le32_to_cpu(hdr->ucode_size_bytes)); - size -= le32_to_cpu(hdr->ucode_size_bytes); - ptr += le32_to_cpu(hdr->ucode_size_bytes); + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { + offset = le32_to_cpu(hdr->ucode_array_offset_bytes); + memcpy_toio(adev->vcn.cpu_addr, adev->vcn.fw->data + offset, + le32_to_cpu(hdr->ucode_size_bytes)); + size -= le32_to_cpu(hdr->ucode_size_bytes); + ptr += le32_to_cpu(hdr->ucode_size_bytes); + } memset_io(ptr, 0, size); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index a7e54820a330d70fccf53584722f603fd07ea20c..85bcd236890ec3c2e390e3911834bcf24a5a3f46 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5479,6 +5479,11 @@ static int gfx_v8_0_set_powergating_state(void *handle, if (amdgpu_sriov_vf(adev)) return 0; + if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_SMG | + AMD_PG_SUPPORT_RLC_SMU_HS | + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GFX_DMG)) + adev->gfx.rlc.funcs->enter_safe_mode(adev); switch (adev->asic_type) { case CHIP_CARRIZO: case CHIP_STONEY: @@ -5527,7 +5532,11 @@ static int gfx_v8_0_set_powergating_state(void *handle, default: break; } - + if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_SMG | + AMD_PG_SUPPORT_RLC_SMU_HS | + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GFX_DMG)) + adev->gfx.rlc.funcs->exit_safe_mode(adev); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 1a30c54a0889f20e451389e495ba562d5549a1c0..3981915e2311f72735841088e939ee7898211954 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3113,7 +3113,7 @@ static void gfx_v9_0_enter_rlc_safe_mode(struct amdgpu_device *adev) /* wait for RLC_SAFE_MODE */ for (i = 0; i < adev->usec_timeout; i++) { - if (!REG_GET_FIELD(SOC15_REG_OFFSET(GC, 0, mmRLC_SAFE_MODE), RLC_SAFE_MODE, CMD)) + if (!REG_GET_FIELD(RREG32_SOC15(GC, 0, mmRLC_SAFE_MODE), RLC_SAFE_MODE, CMD)) break; udelay(1); } diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index 3bbf2ccfca89c547f5e37623acb62e12e6d3d512..c76073b422d6cd1ce6a0edb8783e95acc029dab9 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -1352,8 +1352,6 @@ static int kv_dpm_enable(struct amdgpu_device *adev) return ret; } - kv_update_current_ps(adev, adev->pm.dpm.boot_ps); - if (adev->irq.installed && amdgpu_is_internal_thermal_sensor(adev->pm.int_thermal_type)) { ret = kv_set_thermal_temperature_range(adev, KV_TEMP_RANGE_MIN, KV_TEMP_RANGE_MAX); @@ -3054,7 +3052,7 @@ static int kv_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - + amdgpu_pm_compute_clocks(adev); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c index f7cf994b1da2871a4437655f8306cf9bcb284468..86db90ff693a9df799725da38307440366da5cbc 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c @@ -78,6 +78,9 @@ psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type * case AMDGPU_UCODE_ID_VCE: *type = GFX_FW_TYPE_VCE; break; + case AMDGPU_UCODE_ID_VCN: + *type = GFX_FW_TYPE_VCN; + break; case AMDGPU_UCODE_ID_MAXIMUM: default: return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 6f1dea157a7753b70570e4a9d3d7064f1c4aeaa0..55613f425931ddfff43dc2370f55b5c97c0b48af 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -6884,7 +6884,6 @@ static int si_dpm_enable(struct amdgpu_device *adev) si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); si_thermal_start_thermal_controller(adev); - ni_update_current_ps(adev, boot_ps); return 0; } @@ -7758,7 +7757,7 @@ static int si_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - + amdgpu_pm_compute_clocks(adev); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 5183b46563f6cd4311b94cd2bd628f558427aec4..242dfb1433d263cb270a185b11c21486562bf489 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -899,7 +899,7 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { .emit_frame_size = 4 + /* vce_v3_0_emit_pipeline_sync */ 6, /* amdgpu_vce_ring_emit_fence x1 no user fence */ - .emit_ib_size = 5, /* vce_v3_0_ring_emit_ib */ + .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */ .emit_ib = amdgpu_vce_ring_emit_ib, .emit_fence = amdgpu_vce_ring_emit_fence, .test_ring = amdgpu_vce_ring_test_ring, @@ -923,7 +923,7 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { 6 + /* vce_v3_0_emit_vm_flush */ 4 + /* vce_v3_0_emit_pipeline_sync */ 6 + 6, /* amdgpu_vce_ring_emit_fence x2 vm fence */ - .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */ + .emit_ib_size = 5, /* vce_v3_0_ring_emit_ib */ .emit_ib = vce_v3_0_ring_emit_ib, .emit_vm_flush = vce_v3_0_emit_vm_flush, .emit_pipeline_sync = vce_v3_0_emit_pipeline_sync, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index a098712bdd2fff7291010b3536dfed0ad514eb69..f7b8caccab9fe1ab2d0c53eb8a9acdaaef98efa0 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -91,6 +91,16 @@ static int vcn_v1_0_sw_init(void *handle) if (r) return r; + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + const struct common_firmware_header *hdr; + hdr = (const struct common_firmware_header *)adev->vcn.fw->data; + adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN; + adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); + DRM_INFO("PSP loading VCN firmware\n"); + } + r = amdgpu_vcn_resume(adev); if (r) return r; @@ -248,26 +258,38 @@ static int vcn_v1_0_resume(void *handle) static void vcn_v1_0_mc_resume(struct amdgpu_device *adev) { uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4); - - WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, + uint32_t offset; + + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, + (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo)); + WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, + (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_hi)); + WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0, 0); + offset = 0; + } else { + WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, lower_32_bits(adev->vcn.gpu_addr)); - WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, + WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, upper_32_bits(adev->vcn.gpu_addr)); - WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0, - AMDGPU_UVD_FIRMWARE_OFFSET >> 3); + offset = size; + WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0, + AMDGPU_UVD_FIRMWARE_OFFSET >> 3); + } + WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE0, size); WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW, - lower_32_bits(adev->vcn.gpu_addr + size)); + lower_32_bits(adev->vcn.gpu_addr + offset)); WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH, - upper_32_bits(adev->vcn.gpu_addr + size)); + upper_32_bits(adev->vcn.gpu_addr + offset)); WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1, 0); WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_HEAP_SIZE); WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW, - lower_32_bits(adev->vcn.gpu_addr + size + AMDGPU_VCN_HEAP_SIZE)); + lower_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_HEAP_SIZE)); WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH, - upper_32_bits(adev->vcn.gpu_addr + size + AMDGPU_VCN_HEAP_SIZE)); + upper_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_HEAP_SIZE)); WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2, 0); WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_STACK_SIZE + (AMDGPU_VCN_SESSION_SIZE * 40)); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index c74cf22a1ed9d5d7d0c7c7e35e31786f6464161c..3ae88dcff08d1f9dc09b84993dafcec44f702cbf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -123,6 +123,8 @@ struct kfd_process *kfd_get_process(const struct task_struct *thread) return ERR_PTR(-EINVAL); process = find_process(thread); + if (!process) + return ERR_PTR(-EINVAL); return process; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c index 1dc31aa7278178010be505364a03f4d1ce4df2f0..12856de09f572b4a77be436b25364fca1e3be735 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c @@ -403,6 +403,49 @@ static const struct gpu_pt_config_reg DIDTConfig_Polaris12[] = { { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 17bca99e8ac825334c982122fec82f22ebac636c..7e2c341dfe5f52d756482b55acf552deaab79470 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -634,7 +634,8 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .vsync_irq = MALIDP500_DE_IRQ_VSYNC, }, .se_irq_map = { - .irq_mask = MALIDP500_SE_IRQ_CONF_MODE, + .irq_mask = MALIDP500_SE_IRQ_CONF_MODE | + MALIDP500_SE_IRQ_GLOBAL, .vsync_irq = 0, }, .dc_irq_map = { diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 94e7e3fa3408cf163fda7f81b40e76ca73ac4c96..16b8b310ae5c7036760b3d8b538b15b5f07bcfa6 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -23,6 +23,7 @@ /* Layer specific register offsets */ #define MALIDP_LAYER_FORMAT 0x000 +#define LAYER_FORMAT_MASK 0x3f #define MALIDP_LAYER_CONTROL 0x004 #define LAYER_ENABLE (1 << 0) #define LAYER_FLOWCFG_MASK 7 @@ -278,7 +279,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, dest_w = plane->state->crtc_w; dest_h = plane->state->crtc_h; - malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); + val = malidp_hw_read(mp->hwdev, mp->layer->base); + val = (val & ~LAYER_FORMAT_MASK) | ms->format; + malidp_hw_write(mp->hwdev, val, mp->layer->base); for (i = 0; i < ms->n_planes; i++) { /* calculate the offset for the layer's plane registers */ diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 79ce877bf45f258abb54359a1cb4322b8e27db15..3039936f8f3fc8a589f24cbb84a6e6566a39df6a 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -483,8 +483,9 @@ static irqreturn_t armada_drm_irq(int irq, void *arg) u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR); /* - * This is rediculous - rather than writing bits to clear, we - * have to set the actual status register value. This is racy. + * Reading the ISR appears to clear bits provided CLEAN_SPU_IRQ_ISR + * is set. Writing has some other effect to acknowledge the IRQ - + * without this, we only get a single IRQ. */ writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); @@ -1104,16 +1105,22 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, static int armada_drm_crtc_enable_vblank(struct drm_crtc *crtc) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); + unsigned long flags; + spin_lock_irqsave(&dcrtc->irq_lock, flags); armada_drm_crtc_enable_irq(dcrtc, VSYNC_IRQ_ENA); + spin_unlock_irqrestore(&dcrtc->irq_lock, flags); return 0; } static void armada_drm_crtc_disable_vblank(struct drm_crtc *crtc) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); + unsigned long flags; + spin_lock_irqsave(&dcrtc->irq_lock, flags); armada_drm_crtc_disable_irq(dcrtc, VSYNC_IRQ_ENA); + spin_unlock_irqrestore(&dcrtc->irq_lock, flags); } static const struct drm_crtc_funcs armada_crtc_funcs = { @@ -1221,6 +1228,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA); + readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR); writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc", diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h index 27319a8335e258cf12cb093c5c598523fbe307f3..345dc4d0851ef43bd73069679c3ec7fef8bfa073 100644 --- a/drivers/gpu/drm/armada/armada_hw.h +++ b/drivers/gpu/drm/armada/armada_hw.h @@ -160,6 +160,7 @@ enum { CFG_ALPHAM_GRA = 0x1 << 16, CFG_ALPHAM_CFG = 0x2 << 16, CFG_ALPHA_MASK = 0xff << 8, +#define CFG_ALPHA(x) ((x) << 8) CFG_PIXCMD_MASK = 0xff, }; diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index edc44910d79fc7c65bce893d31b2caf9ce1d34e4..2076346b09ee98759eafd674582890d3693924c3 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -28,6 +28,7 @@ struct armada_ovl_plane_properties { uint16_t contrast; uint16_t saturation; uint32_t colorkey_mode; + uint32_t colorkey_enable; }; struct armada_ovl_plane { @@ -59,11 +60,13 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE); spin_lock_irq(&dcrtc->irq_lock); - armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA, - CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, - dcrtc->base + LCD_SPU_DMA_CTRL1); - - armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG); + armada_updatel(prop->colorkey_mode, + CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, + dcrtc->base + LCD_SPU_DMA_CTRL1); + if (dcrtc->variant->has_spu_adv_reg) + armada_updatel(prop->colorkey_enable, + ADV_GRACOLORKEY | ADV_VIDCOLORKEY, + dcrtc->base + LCD_SPU_ADV_REG); spin_unlock_irq(&dcrtc->irq_lock); } @@ -339,8 +342,17 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane, dplane->prop.colorkey_vb |= K2B(val); update_attr = true; } else if (property == priv->colorkey_mode_prop) { - dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; - dplane->prop.colorkey_mode |= CFG_CKMODE(val); + if (val == CKMODE_DISABLE) { + dplane->prop.colorkey_mode = + CFG_CKMODE(CKMODE_DISABLE) | + CFG_ALPHAM_CFG | CFG_ALPHA(255); + dplane->prop.colorkey_enable = 0; + } else { + dplane->prop.colorkey_mode = + CFG_CKMODE(val) | + CFG_ALPHAM_GRA | CFG_ALPHA(0); + dplane->prop.colorkey_enable = ADV_GRACOLORKEY; + } update_attr = true; } else if (property == priv->brightness_prop) { dplane->prop.brightness = val - 256; @@ -470,7 +482,9 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) dplane->prop.colorkey_yr = 0xfefefe00; dplane->prop.colorkey_ug = 0x01010100; dplane->prop.colorkey_vb = 0x01010100; - dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); + dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) | + CFG_ALPHAM_GRA | CFG_ALPHA(0); + dplane->prop.colorkey_enable = ADV_GRACOLORKEY; dplane->prop.brightness = 0; dplane->prop.contrast = 0x4000; dplane->prop.saturation = 0x4000; diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index b2431aee788795cfa078dbf4b5515c75dbe1961c..f5091827628ab2ab9d6040b42786b5231cffa13e 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -424,6 +424,18 @@ static void adv7511_hpd_work(struct work_struct *work) else status = connector_status_disconnected; + /* + * The bridge resets its registers on unplug. So when we get a plug + * event and we're already supposed to be powered, cycle the bridge to + * restore its state. + */ + if (status == connector_status_connected && + adv7511->connector.status == connector_status_disconnected && + adv7511->powered) { + regcache_mark_dirty(adv7511->regmap); + adv7511_power_on(adv7511); + } + if (adv7511->connector.status != status) { adv7511->connector.status = status; drm_kms_helper_hotplug_event(adv7511->connector.dev); diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index 5131bfb94f065ceb20ba61713f990b76f11103cb..0cb69ee94ac16822965632f265202c8ffeea482a 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -788,6 +788,7 @@ static void sii8620_burst_rx_all(struct sii8620 *ctx) static void sii8620_fetch_edid(struct sii8620 *ctx) { u8 lm_ddc, ddc_cmd, int3, cbus; + unsigned long timeout; int fetched, i; int edid_len = EDID_LENGTH; u8 *edid; @@ -837,23 +838,31 @@ static void sii8620_fetch_edid(struct sii8620 *ctx) REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK ); - do { - int3 = sii8620_readb(ctx, REG_INTR3); + int3 = 0; + timeout = jiffies + msecs_to_jiffies(200); + for (;;) { cbus = sii8620_readb(ctx, REG_CBUS_STATUS); - - if (int3 & BIT_DDC_CMD_DONE) - break; - - if (!(cbus & BIT_CBUS_STATUS_CBUS_CONNECTED)) { + if (~cbus & BIT_CBUS_STATUS_CBUS_CONNECTED) { + kfree(edid); + edid = NULL; + goto end; + } + if (int3 & BIT_DDC_CMD_DONE) { + if (sii8620_readb(ctx, REG_DDC_DOUT_CNT) + >= FETCH_SIZE) + break; + } else { + int3 = sii8620_readb(ctx, REG_INTR3); + } + if (time_is_before_jiffies(timeout)) { + ctx->error = -ETIMEDOUT; + dev_err(ctx->dev, "timeout during EDID read\n"); kfree(edid); edid = NULL; goto end; } - } while (1); - - sii8620_readb(ctx, REG_DDC_STATUS); - while (sii8620_readb(ctx, REG_DDC_DOUT_CNT) < FETCH_SIZE) usleep_range(10, 20); + } sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE); if (fetched + FETCH_SIZE == EDID_LENGTH) { @@ -1036,23 +1045,23 @@ static void sii8620_set_format(struct sii8620 *ctx) BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED, ctx->use_packed_pixel ? ~0 : 0); } else { - if (ctx->use_packed_pixel) + if (ctx->use_packed_pixel) { sii8620_write_seq_static(ctx, REG_VID_MODE, BIT_VID_MODE_M1080P, REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1, REG_MHLTX_CTL6, 0x60 ); - else + } else { sii8620_write_seq_static(ctx, REG_VID_MODE, 0, REG_MHL_TOP_CTL, 1, REG_MHLTX_CTL6, 0xa0 ); + } } if (ctx->use_packed_pixel) - out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL) | - BIT_TPI_OUTPUT_CSCMODE709; + out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL); else out_fmt = VAL_TPI_FORMAT(RGB, FULL); @@ -1187,7 +1196,7 @@ static void sii8620_start_hdmi(struct sii8620 *ctx) int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3); int i; - for (i = 0; i < ARRAY_SIZE(clk_spec); ++i) + for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i) if (clk < clk_spec[i].max_clk) break; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a89fc651f3dfb244605924bb0f3e3e59bce4d7bc..448a5a36268060259ae3dbfb945cde9efd1ad4cb 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -122,6 +122,9 @@ static const struct edid_quirk { /* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */ { "CPT", 0x17df, EDID_QUIRK_FORCE_6BPC }, + /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */ + { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC }, + /* Belinea 10 15 55 */ { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 6be5b53c3b279f42ee6dbcc445173fa539721ce5..f905c214fdd0e65a2cf1911680f9cfd7abad25e1 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -261,7 +261,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, unsigned long val; val = readl(ctx->addr + DECON_WINCONx(win)); - val &= ~WINCONx_BPPMODE_MASK; + val &= WINCONx_ENWIN_F; switch (fb->format->format) { case DRM_FORMAT_XRGB1555: @@ -352,8 +352,8 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->addr + DECON_VIDOSDxB(win)); } - val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | - VIDOSD_Wx_ALPHA_B_F(0x0); + val = VIDOSD_Wx_ALPHA_R_F(0xff) | VIDOSD_Wx_ALPHA_G_F(0xff) | + VIDOSD_Wx_ALPHA_B_F(0xff); writel(val, ctx->addr + DECON_VIDOSDxC(win)); val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 0506b2b17ac1c45a1bea639cb37ed90075be3677..48f913d8208c45134e4f75977f49fb3928c5dd41 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -532,21 +532,25 @@ static int gsc_src_set_fmt(struct device *dev, u32 fmt) GSC_IN_CHROMA_ORDER_CRCB); break; case DRM_FORMAT_NV21: + cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_2P); + break; case DRM_FORMAT_NV61: - cfg |= (GSC_IN_CHROMA_ORDER_CRCB | - GSC_IN_YUV420_2P); + cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV422_2P); break; case DRM_FORMAT_YUV422: cfg |= GSC_IN_YUV422_3P; break; case DRM_FORMAT_YUV420: + cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_3P); + break; case DRM_FORMAT_YVU420: - cfg |= GSC_IN_YUV420_3P; + cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_3P); break; case DRM_FORMAT_NV12: + cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_2P); + break; case DRM_FORMAT_NV16: - cfg |= (GSC_IN_CHROMA_ORDER_CBCR | - GSC_IN_YUV420_2P); + cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV422_2P); break; default: dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt); @@ -806,18 +810,25 @@ static int gsc_dst_set_fmt(struct device *dev, u32 fmt) GSC_OUT_CHROMA_ORDER_CRCB); break; case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P); break; + case DRM_FORMAT_NV61: + cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV422_2P); + break; case DRM_FORMAT_YUV422: + cfg |= GSC_OUT_YUV422_3P; + break; case DRM_FORMAT_YUV420: + cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_3P); + break; case DRM_FORMAT_YVU420: - cfg |= GSC_OUT_YUV420_3P; + cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_3P); break; case DRM_FORMAT_NV12: + cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_2P); + break; case DRM_FORMAT_NV16: - cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | - GSC_OUT_YUV420_2P); + cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV422_2P); break; default: dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt); diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h index 4704a993cbb7f003a51b901ae9b291a9adc9fe09..16b39734115c93855d82a5de94e16cc5e2570940 100644 --- a/drivers/gpu/drm/exynos/regs-gsc.h +++ b/drivers/gpu/drm/exynos/regs-gsc.h @@ -138,6 +138,7 @@ #define GSC_OUT_YUV420_3P (3 << 4) #define GSC_OUT_YUV422_1P (4 << 4) #define GSC_OUT_YUV422_2P (5 << 4) +#define GSC_OUT_YUV422_3P (6 << 4) #define GSC_OUT_YUV444 (7 << 4) #define GSC_OUT_TILE_TYPE_MASK (1 << 2) #define GSC_OUT_TILE_C_16x8 (0 << 2) diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 9bf4045cd679ab6598494e13440e3b4f23d60c78..73c672fc17c4a548314269de4d82d081be249cd0 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -42,6 +42,8 @@ #include #include +#include + #include "i915_drv.h" #include "gvt.h" @@ -953,7 +955,8 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd, } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) { struct vfio_region_info info; struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; - int i, ret; + unsigned int i; + int ret; struct vfio_region_info_cap_sparse_mmap *sparse = NULL; size_t size; int nr_areas = 1; @@ -1030,6 +1033,10 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd, if (info.index >= VFIO_PCI_NUM_REGIONS + vgpu->vdev.num_regions) return -EINVAL; + info.index = + array_index_nospec(info.index, + VFIO_PCI_NUM_REGIONS + + vgpu->vdev.num_regions); i = info.index - VFIO_PCI_NUM_REGIONS; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 90359c7954c8d66532808e82f8116121ac576ca5..f354cfe63f7be34a398c57209dd7fb5a74c0e5fe 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -687,10 +687,10 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) switch (obj->base.write_domain) { case I915_GEM_DOMAIN_GTT: - if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) { + if (!HAS_LLC(dev_priv)) { intel_runtime_pm_get(dev_priv); spin_lock_irq(&dev_priv->uncore.lock); - POSTING_READ_FW(RING_ACTHD(dev_priv->engine[RCS]->mmio_base)); + POSTING_READ_FW(RING_HEAD(dev_priv->engine[RCS]->mmio_base)); spin_unlock_irq(&dev_priv->uncore.lock); intel_runtime_pm_put(dev_priv); } @@ -3608,7 +3608,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, return -EBUSY; } - if (i915_gem_valid_gtt_space(vma, cache_level)) + if (!i915_vma_is_closed(vma) && + i915_gem_valid_gtt_space(vma, cache_level)) continue; ret = i915_vma_unbind(vma); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 709efe2357eac9948ba71a76e11c02ace9f6ae4c..05ae8c4a8a1b615e272d4bb20d09b748f6b1e885 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -782,6 +782,9 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file I915_USERPTR_UNSYNCHRONIZED)) return -EINVAL; + if (!args->user_size) + return -EINVAL; + if (offset_in_page(args->user_ptr | args->user_size)) return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index be813b2738c1526bcd4a1b7395ef1453e279910f..2e706f1abe64f0da52a0f2406b1b308113a02b7c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8462,6 +8462,7 @@ enum skl_power_gate { #define TRANS_MSA_10_BPC (2<<5) #define TRANS_MSA_12_BPC (3<<5) #define TRANS_MSA_16_BPC (4<<5) +#define TRANS_MSA_CEA_RANGE (1<<3) /* LCPLL Control */ #define LCPLL_CTL _MMIO(0x130040) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 02d1a5eacb00ef5fa89deeaaa41318f81ebac902..76eed1fdac0960f19ccdefe91d6cb7dbe4da7358 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -430,6 +430,7 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) u64 start, end; int ret; + GEM_BUG_ON(i915_vma_is_closed(vma)); GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND)); GEM_BUG_ON(drm_mm_node_allocated(&vma->node)); @@ -590,7 +591,9 @@ static void i915_vma_destroy(struct i915_vma *vma) GEM_BUG_ON(i915_gem_active_isset(&vma->last_read[i])); GEM_BUG_ON(i915_gem_active_isset(&vma->last_fence)); + list_del(&vma->obj_link); list_del(&vma->vm_link); + if (!i915_vma_is_ggtt(vma)) i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm)); @@ -602,7 +605,6 @@ void i915_vma_close(struct i915_vma *vma) GEM_BUG_ON(i915_vma_is_closed(vma)); vma->flags |= I915_VMA_CLOSED; - list_del(&vma->obj_link); rb_erase(&vma->obj_node, &vma->obj->vma_tree); if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma)) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 5e5fe03b638cbf2ee17206ccd4c6ee985134645e..3a4a581345c431dd3f2ba7235103913c77101751 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1396,6 +1396,10 @@ void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state) WARN_ON(transcoder_is_dsi(cpu_transcoder)); temp = TRANS_MSA_SYNC_CLK; + + if (crtc_state->limited_color_range) + temp |= TRANS_MSA_CEA_RANGE; + switch (crtc_state->pipe_bpp) { case 18: temp |= TRANS_MSA_6_BPC; diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index 2fdf302ebdad096e39f1bf2e853313ffe14a0caa..8a541d0e3e80d512e8ab35f339743f99bce4cb9b 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c @@ -128,9 +128,7 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) kfree(rsc); - pm_runtime_forbid(&platdev->dev); - pm_runtime_set_active(&platdev->dev); - pm_runtime_enable(&platdev->dev); + pm_runtime_no_callbacks(&platdev->dev); return platdev; diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index beb9baaf2f2e4e573956f1ea842c2963dce95bd7..f71fef10ecc6180a3fc8835bb864dbf24771f705 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -75,7 +75,7 @@ static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon, lspcon_mode_name(mode)); wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode || - current_mode == DRM_LSPCON_MODE_INVALID, 100); + current_mode == DRM_LSPCON_MODE_INVALID, 400); if (current_mode != mode) DRM_DEBUG_KMS("LSPCON mode hasn't settled\n"); diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 56dd7a9a8e254a3e03e4bebb5fda75b8555abbba..dd5312b02a8d21749fb004d41db74ff4bc511b1a 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -612,6 +612,9 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(imx_ldb->regmap); } + /* disable LDB by resetting the control register to POR default */ + regmap_write(imx_ldb->regmap, IOMUXC_GPR2, 0); + imx_ldb->dev = dev; if (of_id) @@ -652,14 +655,14 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) if (ret || i < 0 || i > 1) return -EINVAL; + if (!of_device_is_available(child)) + continue; + if (dual && i > 0) { dev_warn(dev, "dual-channel mode, ignoring second output\n"); continue; } - if (!of_device_is_available(child)) - continue; - channel = &imx_ldb->channel[i]; channel->ldb = imx_ldb; channel->chno = i; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 430830d63a33dcd7aad0ecf17ed40b8cd5051162..2c6d19683688623652a5c24f4dbded829b2dd441 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -570,12 +570,16 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) nv_connector->edid = NULL; } - /* Outputs are only polled while runtime active, so acquiring a - * runtime PM ref here is unnecessary (and would deadlock upon - * runtime suspend because it waits for polling to finish). + /* Outputs are only polled while runtime active, so resuming the + * device here is unnecessary (and would deadlock upon runtime suspend + * because it waits for polling to finish). We do however, want to + * prevent the autosuspend timer from elapsing during this operation + * if possible. */ - if (!drm_kms_helper_is_poll_worker()) { - ret = pm_runtime_get_sync(connector->dev->dev); + if (drm_kms_helper_is_poll_worker()) { + pm_runtime_get_noresume(dev->dev); + } else { + ret = pm_runtime_get_sync(dev->dev); if (ret < 0 && ret != -EACCES) return conn_status; } @@ -653,10 +657,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) out: - if (!drm_kms_helper_is_poll_worker()) { - pm_runtime_mark_last_busy(connector->dev->dev); - pm_runtime_put_autosuspend(connector->dev->dev); - } + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); return conn_status; } @@ -1120,6 +1122,26 @@ nouveau_connector_hotplug(struct nvif_notify *notify) const struct nvif_notify_conn_rep_v0 *rep = notify->data; const char *name = connector->name; struct nouveau_encoder *nv_encoder; + int ret; + + ret = pm_runtime_get(drm->dev->dev); + if (ret == 0) { + /* We can't block here if there's a pending PM request + * running, as we'll deadlock nouveau_display_fini() when it + * calls nvif_put() on our nvif_notify struct. So, simply + * defer the hotplug event until the device finishes resuming + */ + NV_DEBUG(drm, "Deferring HPD on %s until runtime resume\n", + name); + schedule_work(&drm->hpd_work); + + pm_runtime_put_noidle(drm->dev->dev); + return NVIF_NOTIFY_KEEP; + } else if (ret != 1 && ret != -EACCES) { + NV_WARN(drm, "HPD on %s dropped due to RPM failure: %d\n", + name, ret); + return NVIF_NOTIFY_DROP; + } if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { NV_DEBUG(drm, "service %s\n", name); @@ -1137,6 +1159,8 @@ nouveau_connector_hotplug(struct nvif_notify *notify) drm_helper_hpd_irq_event(connector->dev); } + pm_runtime_mark_last_busy(drm->dev->dev); + pm_runtime_put_autosuspend(drm->dev->dev); return NVIF_NOTIFY_KEEP; } diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 963a4dba8213eb6080ff3713cbbdbb20ddb4b61e..9109b69cd052958bbc126b4bad4f490720e11f4a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -160,7 +160,11 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf, args.ustate = value; } + ret = pm_runtime_get_sync(drm->dev); + if (IS_ERR_VALUE(ret) && ret != -EACCES) + return ret; ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args)); + pm_runtime_put_autosuspend(drm->dev); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index caf53503c0f7a5cea1265c2b333212f76e3b9014..2612702c3a3ffd8daed50a1e253b11d96c71dab9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -356,8 +356,6 @@ nouveau_display_hpd_work(struct work_struct *work) pm_runtime_get_sync(drm->dev->dev); drm_helper_hpd_irq_event(drm->dev); - /* enable polling for external displays */ - drm_kms_helper_poll_enable(drm->dev); pm_runtime_mark_last_busy(drm->dev->dev); pm_runtime_put_sync(drm->dev->dev); @@ -380,15 +378,29 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, { struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb); struct acpi_bus_event *info = data; + int ret; if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) { if (info->type == ACPI_VIDEO_NOTIFY_PROBE) { - /* - * This may be the only indication we receive of a - * connector hotplug on a runtime suspended GPU, - * schedule hpd_work to check. - */ - schedule_work(&drm->hpd_work); + ret = pm_runtime_get(drm->dev->dev); + if (ret == 1 || ret == -EACCES) { + /* If the GPU is already awake, or in a state + * where we can't wake it up, it can handle + * it's own hotplug events. + */ + pm_runtime_put_autosuspend(drm->dev->dev); + } else if (ret == 0) { + /* This may be the only indication we receive + * of a connector hotplug on a runtime + * suspended GPU, schedule hpd_work to check. + */ + NV_DEBUG(drm, "ACPI requested connector reprobe\n"); + schedule_work(&drm->hpd_work); + pm_runtime_put_noidle(drm->dev->dev); + } else { + NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n", + ret); + } /* acpi-video should not generate keypresses for this */ return NOTIFY_BAD; @@ -412,6 +424,11 @@ nouveau_display_init(struct drm_device *dev) if (ret) return ret; + /* enable connector detection and polling for connectors without HPD + * support + */ + drm_kms_helper_poll_enable(dev); + /* enable hotplug interrupts */ drm_connector_list_iter_begin(dev, &conn_iter); nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { @@ -426,7 +443,7 @@ nouveau_display_init(struct drm_device *dev) } void -nouveau_display_fini(struct drm_device *dev, bool suspend) +nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) { struct nouveau_display *disp = nouveau_display(dev); struct nouveau_drm *drm = nouveau_drm(dev); @@ -451,6 +468,9 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) } drm_connector_list_iter_end(&conn_iter); + if (!runtime) + cancel_work_sync(&drm->hpd_work); + drm_kms_helper_poll_disable(dev); disp->fini(dev); } @@ -640,11 +660,11 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime) } } - nouveau_display_fini(dev, true); + nouveau_display_fini(dev, true, runtime); return 0; } - nouveau_display_fini(dev, true); + nouveau_display_fini(dev, true, runtime); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_framebuffer *nouveau_fb; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 34cd144681b9ba71a0e5fcc94a48ba8cdf4be517..5e7dae79c2ee3b763ae3c52965f3d7b8245a5c72 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -64,7 +64,7 @@ nouveau_display(struct drm_device *dev) int nouveau_display_create(struct drm_device *dev); void nouveau_display_destroy(struct drm_device *dev); int nouveau_display_init(struct drm_device *dev); -void nouveau_display_fini(struct drm_device *dev, bool suspend); +void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime); int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); int nouveau_display_vblank_enable(struct drm_device *, unsigned int); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 362a34cb435db7ad2b8dd5810c9dd25a0d5b744e..7d3c7bb0ebfa9985aeb7482948b41319a6dffaae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -546,7 +546,7 @@ nouveau_drm_unload(struct drm_device *dev) nouveau_debugfs_fini(drm); if (dev->mode_config.num_crtc) - nouveau_display_fini(dev, false); + nouveau_display_fini(dev, false, false); nouveau_display_destroy(dev); nouveau_bios_takedown(dev); @@ -848,8 +848,10 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) get_task_comm(tmpname, current); snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); - if (!(cli = kzalloc(sizeof(*cli), GFP_KERNEL))) - return ret; + if (!(cli = kzalloc(sizeof(*cli), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } ret = nouveau_cli_init(drm, name, cli); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 2170534101cafda1e66ccdf0ee5262a62fdde7bf..60ffb70bb9089c08040c8a2fe918cb471d998fb9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -599,7 +599,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, struct nouveau_bo *nvbo; uint32_t data; - if (unlikely(r->bo_index > req->nr_buffers)) { + if (unlikely(r->bo_index >= req->nr_buffers)) { NV_PRINTK(err, cli, "reloc bo index invalid\n"); ret = -EINVAL; break; @@ -609,7 +609,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, if (b->presumed.valid) continue; - if (unlikely(r->reloc_bo_index > req->nr_buffers)) { + if (unlikely(r->reloc_bo_index >= req->nr_buffers)) { NV_PRINTK(err, cli, "reloc container bo index invalid\n"); ret = -EINVAL; break; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 189ed80e21ffbd428174e458bb946f2880c3da57..fa1ead337c237cbca4fd53f6a84440ad9785bd59 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -23,6 +23,10 @@ #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER #include "priv.h" +#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) +#include +#endif + static int nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev) { @@ -105,6 +109,15 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) unsigned long pgsize_bitmap; int ret; +#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) + if (dev->archdata.mapping) { + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); + + arm_iommu_detach_device(dev); + arm_iommu_release_mapping(mapping); + } +#endif + if (!tdev->func->iommu_bit) return; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c index a188a3959f1ad33384fb266b967853a61bb4f973..6ad827b93ae19a5082ddec0e08dd627b568a2af0 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c @@ -823,7 +823,7 @@ static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx) int ret, i; ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id)); - if (ret < ARRAY_SIZE(id) || id[0] == 0x00) { + if (ret < 0 || ret < ARRAY_SIZE(id) || id[0] == 0x00) { dev_err(ctx->dev, "read id failed\n"); ctx->error = -EIO; return; diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index ace59651892fb636400088e2ac9136a0917d45dd..8d3c8070ed86238206f208f22cb84a10d90922cf 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -241,7 +241,6 @@ static int sun4i_drv_add_endpoints(struct device *dev, remote = of_graph_get_remote_port_parent(ep); if (!remote) { DRM_DEBUG_DRIVER("Error retrieving the output node\n"); - of_node_put(remote); continue; } @@ -255,11 +254,13 @@ static int sun4i_drv_add_endpoints(struct device *dev, if (of_graph_parse_endpoint(ep, &endpoint)) { DRM_DEBUG_DRIVER("Couldn't parse endpoint\n"); + of_node_put(remote); continue; } if (!endpoint.id) { DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n"); + of_node_put(remote); continue; } } diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 0598b4c18c253bb9f10076174a0b6c2774a86e87..75b1c8c03ce95eff8e9f824c1a161a70ffced508 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -470,7 +470,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, * unaligned offset is malformed and cause commands stream * corruption on the buffer address relocation. */ - if (offset & 3 || offset >= obj->gem.size) { + if (offset & 3 || offset > obj->gem.size) { err = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 2a75ab80527a954990c6ee2305883a97fa2ea41b..2c149b841cf1edcc4e86032a73753ffefad53d25 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -110,7 +110,7 @@ udl_fb_user_fb_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd); -int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, +int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, u32 byte_offset, u32 device_byte_offset, u32 byte_width, int *ident_ptr, int *sent_ptr); diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index d5583190f3e44de77560d76c2d5a5a4cf7db62de..491f1892b50e7995de815f44909f9cca6ebd07cd 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -90,7 +90,10 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, int bytes_identical = 0; struct urb *urb; int aligned_x; - int bpp = fb->base.format->cpp[0]; + int log_bpp; + + BUG_ON(!is_power_of_2(fb->base.format->cpp[0])); + log_bpp = __ffs(fb->base.format->cpp[0]); if (!fb->active_16) return 0; @@ -125,12 +128,12 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, for (i = y; i < y + height ; i++) { const int line_offset = fb->base.pitches[0] * i; - const int byte_offset = line_offset + (x * bpp); - const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); - if (udl_render_hline(dev, bpp, &urb, + const int byte_offset = line_offset + (x << log_bpp); + const int dev_byte_offset = (fb->base.width * i + x) << log_bpp; + if (udl_render_hline(dev, log_bpp, &urb, (char *) fb->obj->vmapping, &cmd, byte_offset, dev_byte_offset, - width * bpp, + width << log_bpp, &bytes_identical, &bytes_sent)) goto error; } @@ -149,7 +152,7 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, error: atomic_add(bytes_sent, &udl->bytes_sent); atomic_add(bytes_identical, &udl->bytes_identical); - atomic_add(width*height*bpp, &udl->bytes_rendered); + atomic_add((width * height) << log_bpp, &udl->bytes_rendered); end_cycles = get_cycles(); atomic_add(((unsigned int) ((end_cycles - start_cycles) >> 10)), /* Kcycles */ @@ -221,7 +224,7 @@ static int udl_fb_open(struct fb_info *info, int user) struct fb_deferred_io *fbdefio; - fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); + fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); if (fbdefio) { fbdefio->delay = DL_DEFIO_WRITE_DELAY; @@ -429,9 +432,11 @@ static void udl_fbdev_destroy(struct drm_device *dev, { drm_fb_helper_unregister_fbi(&ufbdev->helper); drm_fb_helper_fini(&ufbdev->helper); - drm_framebuffer_unregister_private(&ufbdev->ufb.base); - drm_framebuffer_cleanup(&ufbdev->ufb.base); - drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base); + if (ufbdev->ufb.obj) { + drm_framebuffer_unregister_private(&ufbdev->ufb.base); + drm_framebuffer_cleanup(&ufbdev->ufb.base); + drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base); + } } int udl_fbdev_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 0328b2c7b210a0331f8721e93c3b25124ad27daf..f8ea3c99b523234273f705a3884a383df0949ae1 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -169,18 +169,13 @@ static void udl_free_urb_list(struct drm_device *dev) struct list_head *node; struct urb_node *unode; struct urb *urb; - int ret; unsigned long flags; DRM_DEBUG("Waiting for completes and freeing all render urbs\n"); /* keep waiting and freeing, until we've got 'em all */ while (count--) { - - /* Getting interrupted means a leak, but ok at shutdown*/ - ret = down_interruptible(&udl->urbs.limit_sem); - if (ret) - break; + down(&udl->urbs.limit_sem); spin_lock_irqsave(&udl->urbs.lock, flags); @@ -204,17 +199,22 @@ static void udl_free_urb_list(struct drm_device *dev) static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) { struct udl_device *udl = dev->dev_private; - int i = 0; struct urb *urb; struct urb_node *unode; char *buf; + size_t wanted_size = count * size; spin_lock_init(&udl->urbs.lock); +retry: udl->urbs.size = size; INIT_LIST_HEAD(&udl->urbs.list); - while (i < count) { + sema_init(&udl->urbs.limit_sem, 0); + udl->urbs.count = 0; + udl->urbs.available = 0; + + while (udl->urbs.count * size < wanted_size) { unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); if (!unode) break; @@ -230,11 +230,16 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) } unode->urb = urb; - buf = usb_alloc_coherent(udl->udev, MAX_TRANSFER, GFP_KERNEL, + buf = usb_alloc_coherent(udl->udev, size, GFP_KERNEL, &urb->transfer_dma); if (!buf) { kfree(unode); usb_free_urb(urb); + if (size > PAGE_SIZE) { + size /= 2; + udl_free_urb_list(dev); + goto retry; + } break; } @@ -245,16 +250,14 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) list_add_tail(&unode->entry, &udl->urbs.list); - i++; + up(&udl->urbs.limit_sem); + udl->urbs.count++; + udl->urbs.available++; } - sema_init(&udl->urbs.limit_sem, i); - udl->urbs.count = i; - udl->urbs.available = i; - - DRM_DEBUG("allocated %d %d byte urbs\n", i, (int) size); + DRM_DEBUG("allocated %d %d byte urbs\n", udl->urbs.count, (int) size); - return i; + return udl->urbs.count; } struct urb *udl_get_urb(struct drm_device *dev) diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index b992644c17e6b565b414351b1e262d4b61c9f38d..f3331d33547a1708fc7be2ee4eaeda676da3ff13 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -83,12 +83,12 @@ static inline u16 pixel32_to_be16(const uint32_t pixel) ((pixel >> 8) & 0xf800)); } -static inline u16 get_pixel_val16(const uint8_t *pixel, int bpp) +static inline u16 get_pixel_val16(const uint8_t *pixel, int log_bpp) { - u16 pixel_val16 = 0; - if (bpp == 2) + u16 pixel_val16; + if (log_bpp == 1) pixel_val16 = *(const uint16_t *)pixel; - else if (bpp == 4) + else pixel_val16 = pixel32_to_be16(*(const uint32_t *)pixel); return pixel_val16; } @@ -125,8 +125,9 @@ static void udl_compress_hline16( const u8 *const pixel_end, uint32_t *device_address_ptr, uint8_t **command_buffer_ptr, - const uint8_t *const cmd_buffer_end, int bpp) + const uint8_t *const cmd_buffer_end, int log_bpp) { + const int bpp = 1 << log_bpp; const u8 *pixel = *pixel_start_ptr; uint32_t dev_addr = *device_address_ptr; uint8_t *cmd = *command_buffer_ptr; @@ -153,12 +154,12 @@ static void udl_compress_hline16( raw_pixels_count_byte = cmd++; /* we'll know this later */ raw_pixel_start = pixel; - cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL, - (unsigned long)(pixel_end - pixel) / bpp, - (unsigned long)(cmd_buffer_end - 1 - cmd) / 2) * bpp; + cmd_pixel_end = pixel + (min3(MAX_CMD_PIXELS + 1UL, + (unsigned long)(pixel_end - pixel) >> log_bpp, + (unsigned long)(cmd_buffer_end - 1 - cmd) / 2) << log_bpp); prefetch_range((void *) pixel, cmd_pixel_end - pixel); - pixel_val16 = get_pixel_val16(pixel, bpp); + pixel_val16 = get_pixel_val16(pixel, log_bpp); while (pixel < cmd_pixel_end) { const u8 *const start = pixel; @@ -170,7 +171,7 @@ static void udl_compress_hline16( pixel += bpp; while (pixel < cmd_pixel_end) { - pixel_val16 = get_pixel_val16(pixel, bpp); + pixel_val16 = get_pixel_val16(pixel, log_bpp); if (pixel_val16 != repeating_pixel_val16) break; pixel += bpp; @@ -179,10 +180,10 @@ static void udl_compress_hline16( if (unlikely(pixel > start + bpp)) { /* go back and fill in raw pixel count */ *raw_pixels_count_byte = (((start - - raw_pixel_start) / bpp) + 1) & 0xFF; + raw_pixel_start) >> log_bpp) + 1) & 0xFF; /* immediately after raw data is repeat byte */ - *cmd++ = (((pixel - start) / bpp) - 1) & 0xFF; + *cmd++ = (((pixel - start) >> log_bpp) - 1) & 0xFF; /* Then start another raw pixel span */ raw_pixel_start = pixel; @@ -192,14 +193,14 @@ static void udl_compress_hline16( if (pixel > raw_pixel_start) { /* finalize last RAW span */ - *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; + *raw_pixels_count_byte = ((pixel - raw_pixel_start) >> log_bpp) & 0xFF; } else { /* undo unused byte */ cmd--; } - *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; - dev_addr += ((pixel - cmd_pixel_start) / bpp) * 2; + *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) >> log_bpp) & 0xFF; + dev_addr += ((pixel - cmd_pixel_start) >> log_bpp) * 2; } if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) { @@ -222,19 +223,19 @@ static void udl_compress_hline16( * (that we can only write to, slowly, and can never read), and (optionally) * our shadow copy that tracks what's been sent to that hardware buffer. */ -int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, +int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, u32 byte_offset, u32 device_byte_offset, u32 byte_width, int *ident_ptr, int *sent_ptr) { const u8 *line_start, *line_end, *next_pixel; - u32 base16 = 0 + (device_byte_offset / bpp) * 2; + u32 base16 = 0 + (device_byte_offset >> log_bpp) * 2; struct urb *urb = *urb_ptr; u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; - BUG_ON(!(bpp == 2 || bpp == 4)); + BUG_ON(!(log_bpp == 1 || log_bpp == 2)); line_start = (u8 *) (front + byte_offset); next_pixel = line_start; @@ -244,7 +245,7 @@ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, udl_compress_hline16(&next_pixel, line_end, &base16, - (u8 **) &cmd, (u8 *) cmd_end, bpp); + (u8 **) &cmd, (u8 *) cmd_end, log_bpp); if (cmd >= cmd_end) { int len = cmd - (u8 *) urb->transfer_buffer; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 17590cb2b80d952b4479dc14b00b26c6db7ae379..502c7eb708c25914f142095a7a0c5a2182ce2226 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -329,6 +329,9 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0], vc4_state->crtc_h); + vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE && + vc4_state->y_scaling[0] == VC4_SCALING_NONE); + if (num_planes > 1) { vc4_state->is_yuv = true; @@ -344,24 +347,17 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) vc4_get_scaling_mode(vc4_state->src_h[1], vc4_state->crtc_h); - /* YUV conversion requires that scaling be enabled, - * even on a plane that's otherwise 1:1. Choose TPZ - * for simplicity. + /* YUV conversion requires that horizontal scaling be enabled, + * even on a plane that's otherwise 1:1. Looks like only PPF + * works in that case, so let's pick that one. */ - if (vc4_state->x_scaling[0] == VC4_SCALING_NONE) - vc4_state->x_scaling[0] = VC4_SCALING_TPZ; - if (vc4_state->y_scaling[0] == VC4_SCALING_NONE) - vc4_state->y_scaling[0] = VC4_SCALING_TPZ; + if (vc4_state->is_unity) + vc4_state->x_scaling[0] = VC4_SCALING_PPF; } else { vc4_state->x_scaling[1] = VC4_SCALING_NONE; vc4_state->y_scaling[1] = VC4_SCALING_NONE; } - vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE && - vc4_state->y_scaling[0] == VC4_SCALING_NONE && - vc4_state->x_scaling[1] == VC4_SCALING_NONE && - vc4_state->y_scaling[1] == VC4_SCALING_NONE); - /* No configuring scaling on the cursor plane, since it gets non-vblank-synced updates, and scaling requires requires LBM changes which have to be vblank-synced. @@ -639,7 +635,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane, vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5); } - if (!vc4_state->is_unity) { + if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || + vc4_state->x_scaling[1] != VC4_SCALING_NONE || + vc4_state->y_scaling[0] != VC4_SCALING_NONE || + vc4_state->y_scaling[1] != VC4_SCALING_NONE) { /* LBM Base Address. */ if (vc4_state->y_scaling[0] != VC4_SCALING_NONE || vc4_state->y_scaling[1] != VC4_SCALING_NONE) { diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index db509ab8874e58fd1f798da270fa8035ed4563d3..acd99783bbca1ca8fffc8e8ba5b6105e67cdc09e 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -686,7 +686,8 @@ void host1x_job_unpin(struct host1x_job *job) for (i = 0; i < job->num_unpins; i++) { struct host1x_job_unpin_data *unpin = &job->unpins[i]; - if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) { + if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && + unpin->size && host->domain) { iommu_unmap(host->domain, job->addr_phys[i], unpin->size); free_iova(&host->iova, diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 658fa2d3e40c260d051d4299bda4eddb0af5abeb..2c8411b8d050d6d758522a9866e1cd2d3dfebb7d 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -1401,6 +1401,8 @@ static int ipu_probe(struct platform_device *pdev) return -ENODEV; ipu->id = of_alias_get_id(np, "ipu"); + if (ipu->id < 0) + ipu->id = 0; if (of_device_is_compatible(np, "fsl,imx6qp-ipu") && IS_ENABLED(CONFIG_DRM)) { diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c index 24e12b87a0cbe387b24557a230a1ed1d05e150ca..2bc51d4d3f1e6adf923e01e69f4e3ec92ee186d2 100644 --- a/drivers/gpu/ipu-v3/ipu-csi.c +++ b/drivers/gpu/ipu-v3/ipu-csi.c @@ -316,13 +316,17 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code) /* * Fill a CSI bus config struct from mbus_config and mbus_framefmt. */ -static void fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg, +static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg, struct v4l2_mbus_config *mbus_cfg, struct v4l2_mbus_framefmt *mbus_fmt) { + int ret; + memset(csicfg, 0, sizeof(*csicfg)); - mbus_code_to_bus_cfg(csicfg, mbus_fmt->code); + ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code); + if (ret < 0) + return ret; switch (mbus_cfg->type) { case V4L2_MBUS_PARALLEL: @@ -353,6 +357,8 @@ static void fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg, /* will never get here, keep compiler quiet */ break; } + + return 0; } int ipu_csi_init_interface(struct ipu_csi *csi, @@ -362,8 +368,11 @@ int ipu_csi_init_interface(struct ipu_csi *csi, struct ipu_csi_bus_config cfg; unsigned long flags; u32 width, height, data = 0; + int ret; - fill_csi_bus_cfg(&cfg, mbus_cfg, mbus_fmt); + ret = fill_csi_bus_cfg(&cfg, mbus_cfg, mbus_fmt); + if (ret < 0) + return ret; /* set default sensor frame width and height */ width = mbus_fmt->width; @@ -584,11 +593,14 @@ int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc, struct ipu_csi_bus_config cfg; unsigned long flags; u32 temp; + int ret; if (vc > 3) return -EINVAL; - mbus_code_to_bus_cfg(&cfg, mbus_fmt->code); + ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code); + if (ret < 0) + return ret; spin_lock_irqsave(&csi->lock, flags); diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h index 9c1e798367b23ada33045134b420611a2853d5f5..06d87ac320d5b4be6ad5c8b475bde1baea35a62f 100644 --- a/drivers/gpu/msm/a6xx_reg.h +++ b/drivers/gpu/msm/a6xx_reg.h @@ -58,9 +58,11 @@ #define A6XX_CP_RB_RPTR 0x806 #define A6XX_CP_RB_WPTR 0x807 #define A6XX_CP_SQE_CNTL 0x808 +#define A6XX_CP_CP2GMU_STATUS 0x812 #define A6XX_CP_HW_FAULT 0x821 #define A6XX_CP_INTERRUPT_STATUS 0x823 -#define A6XX_CP_PROTECT_STATUS 0X824 +#define A6XX_CP_PROTECT_STATUS 0x824 +#define A6XX_CP_STATUS_1 0x825 #define A6XX_CP_SQE_INSTR_BASE_LO 0x830 #define A6XX_CP_SQE_INSTR_BASE_HI 0x831 #define A6XX_CP_MISC_CNTL 0x840 diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 91991593982923bcae150a448b04704b785615fc..efc240f3b64724149d30ff19dce79088571826d5 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -468,7 +468,8 @@ static const struct adreno_gpu_core adreno_gpulist[] = { .minor = 8, .patchid = ANY_ID, .features = ADRENO_64BIT | ADRENO_CONTENT_PROTECTION | - ADRENO_IOCOHERENT | ADRENO_PREEMPTION | ADRENO_GPMU, + ADRENO_IOCOHERENT | ADRENO_PREEMPTION | ADRENO_GPMU | + ADRENO_IFPC, .sqefw_name = "a630_sqe.fw", .zap_name = "a608_zap", .gpudev = &adreno_a6xx_gpudev, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index f4174e06fba23d1ef17a8d5e80166688d7cee438..205a742568c7eee2c60145a797d5fa18ce56935c 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -966,10 +966,6 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, if (of_property_read_u32(child, "qcom,bus-max", &level->bus_max)) level->bus_max = level->bus_freq; - - if (of_property_read_u32(child, "qcom,dvm-val", - &level->acd_dvm_val)) - level->acd_dvm_val = 0xFFFFFFFF; } return 0; diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 6ac1594cb047408bcac5a89527ad20da024d75d6..2840b4b2f73175b1d6e40371d77bdd03b1fcc3a1 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -836,7 +836,7 @@ static int a6xx_gmu_gfx_rail_on(struct kgsl_device *device) return a6xx_gmu_oob_set(adreno_dev, oob_boot_slumber); } -static bool idle_trandition_complete(unsigned int idle_level, +static bool idle_transition_complete(unsigned int idle_level, unsigned int gmu_power_reg, unsigned int sptprac_clk_reg) { @@ -860,7 +860,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - unsigned int reg, reg1; + unsigned int reg, reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8; unsigned long t; uint64_t ts1, ts2, ts3; @@ -876,7 +876,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct adreno_device *adreno_dev) gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, ®1); - if (idle_trandition_complete(gmu->idle_level, reg, reg1)) + if (idle_transition_complete(gmu->idle_level, reg, reg1)) return 0; /* Wait 100us to reduce unnecessary AHB bus traffic */ usleep_range(10, 100); @@ -888,13 +888,38 @@ static int a6xx_gmu_wait_for_lowest_idle(struct adreno_device *adreno_dev) gmu_core_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, ®); gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, ®1); - if (idle_trandition_complete(gmu->idle_level, reg, reg1)) + if (idle_transition_complete(gmu->idle_level, reg, reg1)) return 0; ts3 = read_AO_counter(device); - WARN(1, "Timeout waiting for lowest idle: %08x %llx %llx %llx %x\n", - reg, ts1, ts2, ts3, reg1); + /* Collect abort data to help with debugging */ + gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®2); + gmu_core_regread(device, A6XX_CP_STATUS_1, ®3); + gmu_core_regread(device, A6XX_GMU_RBBM_INT_UNMASKED_STATUS, ®4); + gmu_core_regread(device, A6XX_GMU_GMU_PWR_COL_KEEPALIVE, ®5); + gmu_core_regread(device, A6XX_CP_CP2GMU_STATUS, ®6); + gmu_core_regread(device, A6XX_CP_CONTEXT_SWITCH_CNTL, ®7); + gmu_core_regread(device, A6XX_GMU_AO_SPARE_CNTL, ®8); + + dev_err(&gmu->pdev->dev, + "----------------------[ GMU error ]----------------------\n"); + dev_err(&gmu->pdev->dev, + "Timeout waiting for lowest idle level %d\n", gmu->idle_level); + dev_err(&gmu->pdev->dev, + "Timestamps: %llx %llx %llx\n", ts1, ts2, ts3); + dev_err(&gmu->pdev->dev, + "RPMH_POWER_STATE=%x SPTPRAC_PWR_CLK_STATUS=%x\n", reg, reg1); + dev_err(&gmu->pdev->dev, + "CX_BUSY_STATUS=%x CP_STATUS_1=%x\n", reg2, reg3); + dev_err(&gmu->pdev->dev, + "RBBM_INT_UNMASKED_STATUS=%x PWR_COL_KEEPALIVE=%x\n", + reg4, reg5); + dev_err(&gmu->pdev->dev, + "CP2GMU_STATUS=%x CONTEXT_SWITCH_CNTL=%x AO_SPARE_CNTL=%x\n", + reg6, reg7, reg8); + + WARN_ON(1); return -ETIMEDOUT; } diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index dd798dc0c3b334884fde7d231fbca5e3d89206b0..e9f8947e9ffc4278c9a63cfc181775004c128816 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -38,6 +38,8 @@ MODULE_PARM_DESC(noacd, "Disable GPU ACD"); #define GMU_CONTEXT_KERNEL 1 #define GMU_KERNEL_ENTRIES 16 +#define GMU_CM3_CFG_NONMASKINTR_SHIFT 9 + struct gmu_iommu_context { const char *name; struct device *dev; @@ -80,6 +82,8 @@ struct gmu_iommu_context gmu_ctx[] = { static struct gmu_memdesc gmu_kmem_entries[GMU_KERNEL_ENTRIES]; static unsigned long gmu_kmem_bitmap; static unsigned int num_uncached_entries; + +static void gmu_snapshot(struct kgsl_device *device); static void gmu_remove(struct kgsl_device *device); static int _gmu_iommu_fault_handler(struct device *dev, @@ -540,9 +544,7 @@ static int gmu_dcvs_set(struct kgsl_device *device, dev_err_ratelimited(&gmu->pdev->dev, "Failed to set GPU perf idx %d, bw idx %d\n", req.freq, req.bw); - - adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); - adreno_dispatcher_schedule(device); + gmu_snapshot(device); } /* indicate actual clock change */ @@ -818,6 +820,38 @@ static void build_bwtable_cmd_cache(struct gmu_device *gmu) votes->cnoc_votes.cmd_data[i][j]; } +static int gmu_acd_probe(struct gmu_device *gmu, struct device_node *node) +{ + struct hfi_acd_table_cmd *cmd = &gmu->hfi.acd_tbl_cmd; + struct device_node *acd_node; + + acd_node = of_find_node_by_name(node, "qcom,gpu-acd-table"); + if (!acd_node) + return -ENODEV; + + cmd->hdr = 0xFFFFFFFF; + cmd->version = HFI_ACD_INIT_VERSION; + cmd->enable_by_level = 0; + cmd->stride = 0; + cmd->num_levels = 0; + + of_property_read_u32(acd_node, "qcom,acd-stride", &cmd->stride); + if (!cmd->stride || cmd->stride > MAX_ACD_STRIDE) + return -EINVAL; + + of_property_read_u32(acd_node, "qcom,acd-num-levels", &cmd->num_levels); + if (!cmd->num_levels || cmd->num_levels > MAX_ACD_NUM_LEVELS) + return -EINVAL; + + of_property_read_u32(acd_node, "qcom,acd-enable-by-level", + &cmd->enable_by_level); + if (hweight32(cmd->enable_by_level) != cmd->num_levels) + return -EINVAL; + + return of_property_read_u32_array(acd_node, "qcom,acd-data", + cmd->data, cmd->stride * cmd->num_levels); +} + /* * gmu_bus_vote_init - initialized RPMh votes needed for bw scaling by GMU. * @gmu: Pointer to GMU device @@ -894,6 +928,24 @@ static int gmu_rpmh_init(struct kgsl_device *device, return rpmh_arc_votes_init(device, gmu, &cx_arc, &mx_arc, GMU_ARC_VOTE); } +static void send_nmi_to_gmu(struct adreno_device *adreno_dev) +{ + /* Mask so there's no interrupt caused by NMI */ + adreno_write_gmureg(adreno_dev, + ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF); + + /* Make sure the interrupt is masked before causing it */ + wmb(); + adreno_write_gmureg(adreno_dev, + ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0); + adreno_write_gmureg(adreno_dev, + ADRENO_REG_GMU_CM3_CFG, + (1 << GMU_CM3_CFG_NONMASKINTR_SHIFT)); + + /* Make sure the NMI is invoked before we proceed*/ + wmb(); +} + static irqreturn_t gmu_irq_handler(int irq, void *data) { struct kgsl_device *device = data; @@ -915,6 +967,13 @@ static irqreturn_t gmu_irq_handler(int irq, void *data) ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, (mask | GMU_INT_WDOG_BITE)); + send_nmi_to_gmu(adreno_dev); + /* + * There is sufficient delay for the GMU to have finished + * handling the NMI before snapshot is taken, as the fault + * worker is scheduled below. + */ + dev_err_ratelimited(&gmu->pdev->dev, "GMU watchdog expired interrupt received\n"); adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); @@ -1321,7 +1380,6 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) int j = gmu->num_gpupwrlevels - 1 - i; gmu->gpu_freqs[i] = pwr->pwrlevels[j].gpu_freq; - gmu->acd_dvm_vals[i] = pwr->pwrlevels[j].acd_dvm_val; } /* Initializes GPU b/w levels configuration */ @@ -1354,10 +1412,15 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) gmu->idle_level = GPU_HW_ACTIVE; if (ADRENO_FEATURE(adreno_dev, ADRENO_ACD) && !noacd) { - ret = gmu_aop_mailbox_init(device, gmu); - if (ret) - dev_err(&gmu->pdev->dev, + if (!gmu_acd_probe(gmu, node)) { + /* Init the AOP mailbox if we have a valid ACD table */ + ret = gmu_aop_mailbox_init(device, gmu); + if (ret) + dev_err(&gmu->pdev->dev, "AOP mailbox init failed: %d\n", ret); + } else + dev_err(&gmu->pdev->dev, + "ACD probe failed: missing or invalid table\n"); } /* disable LM if the feature is not enabled */ @@ -1510,19 +1573,8 @@ static void gmu_snapshot(struct kgsl_device *device) struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - /* Mask so there's no interrupt caused by NMI */ - adreno_write_gmureg(adreno_dev, - ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF); - - /* Make sure the interrupt is masked before causing it */ - wmb(); - adreno_write_gmureg(adreno_dev, - ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0); - adreno_write_gmureg(adreno_dev, - ADRENO_REG_GMU_CM3_CFG, (1 << 9)); - + send_nmi_to_gmu(adreno_dev); /* Wait for the NMI to be handled */ - wmb(); udelay(100); kgsl_device_snapshot(device, NULL, true); diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h index aed3014d00537f7528a4fd828f8a487e2c52454f..cb211ee113eb2f70cc9cf7176d863816aeb7cfae 100644 --- a/drivers/gpu/msm/kgsl_gmu.h +++ b/drivers/gpu/msm/kgsl_gmu.h @@ -157,7 +157,6 @@ struct kgsl_mailbox { * @ccl: CNOC BW scaling client * @idle_level: Minimal GPU idle power level * @fault_count: GMU fault count - * @acd_dvm_vals: Table of DVM values that correspond to frequency levels * @mailbox: Messages to AOP for ACD enable/disable go through this */ struct gmu_device { @@ -190,7 +189,6 @@ struct gmu_device { unsigned int ccl; unsigned int idle_level; unsigned int fault_count; - unsigned int acd_dvm_vals[MAX_GX_LEVELS]; struct kgsl_mailbox mailbox; }; diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index 476eabee2b727153277753734aa8e5bab7b9a2a5..b83344457f5a101b1f735f5235aa71288f5b3ff0 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -500,7 +500,8 @@ static int hfi_send_dcvstbl(struct gmu_device *gmu) for (i = 0; i < gmu->num_gpupwrlevels; i++) { cmd.gx_votes[i].vote = gmu->rpmh_votes.gx_votes[i]; - cmd.gx_votes[i].acd = gmu->acd_dvm_vals[i]; + /* Hardcode this to the max threshold since it is not used */ + cmd.gx_votes[i].acd = 0xFFFFFFFF; /* Divide by 1000 to convert to kHz */ cmd.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000; } @@ -522,6 +523,15 @@ static int hfi_send_bwtbl(struct gmu_device *gmu) return hfi_send_generic_req(gmu, HFI_CMD_ID, cmd); } +static int hfi_send_acd_tbl(struct gmu_device *gmu) +{ + struct hfi_acd_table_cmd *cmd = &gmu->hfi.acd_tbl_cmd; + + cmd->hdr = CMD_MSG_HDR(H2F_MSG_ACD_TBL, sizeof(*cmd)); + + return hfi_send_generic_req(gmu, HFI_CMD_IDX, cmd); +} + static int hfi_send_test(struct gmu_device *gmu) { struct hfi_test_cmd cmd = { @@ -662,6 +672,20 @@ static int hfi_verify_fw_version(struct kgsl_device *device, return 0; } +static int hfi_send_acd_feature_ctrl(struct gmu_device *gmu, + struct adreno_device *adreno_dev) +{ + int ret = 0; + + if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag)) { + ret = hfi_send_acd_tbl(gmu); + if (!ret) + ret = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ACD, 1, 0); + } + + return ret; +} + int hfi_start(struct kgsl_device *device, struct gmu_device *gmu, uint32_t boot_state) { @@ -716,10 +740,10 @@ int hfi_start(struct kgsl_device *device, */ if (HFI_VER_MAJOR(&gmu->hfi) >= 2) { result = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ECP, 0, 0); - if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag)) - result |= hfi_send_feature_ctrl(gmu, - HFI_FEATURE_ACD, 1, 0); + if (result) + return result; + result = hfi_send_acd_feature_ctrl(gmu, adreno_dev); if (result) return result; diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h index 6573d8d631f6a592e24fb9d7f3be85f5094584bc..b5121d747165394a31a4fab0195e663a4869c1ef 100644 --- a/drivers/gpu/msm/kgsl_hfi.h +++ b/drivers/gpu/msm/kgsl_hfi.h @@ -176,6 +176,7 @@ enum hfi_msg_type { #define H2F_MSG_BW_VOTE_TBL 3 #define H2F_MSG_PERF_TBL 4 #define H2F_MSG_TEST 5 +#define H2F_MSG_ACD_TBL 7 #define H2F_MSG_START 10 #define H2F_MSG_FEATURE_CTRL 11 #define H2F_MSG_GET_VALUE 12 @@ -274,6 +275,20 @@ struct hfi_dcvstable_cmd { struct opp_desc cx_votes[MAX_CX_LEVELS]; }; +#define HFI_ACD_INIT_VERSION 1 +#define MAX_ACD_STRIDE 2 +#define MAX_ACD_NUM_LEVELS 6 + +/* H2F */ +struct hfi_acd_table_cmd { + uint32_t hdr; + uint32_t version; + uint32_t enable_by_level; + uint32_t stride; + uint32_t num_levels; + uint32_t data[MAX_ACD_NUM_LEVELS * MAX_ACD_STRIDE]; +}; + /* H2F */ struct hfi_test_cmd { uint32_t hdr; @@ -604,6 +619,7 @@ struct pending_cmd { * @seqnum: atomic counter that is incremented for each message sent. The * value of the counter is used as sequence number for HFI message * @bwtbl_cmd: HFI BW table buffer + * @acd_tbl_cmd: HFI table for ACD data */ struct kgsl_hfi { struct kgsl_device *kgsldev; @@ -613,6 +629,7 @@ struct kgsl_hfi { uint32_t version; atomic_t seqnum; struct hfi_bwtable_cmd bwtbl_cmd; + struct hfi_acd_table_cmd acd_tbl_cmd; }; struct gmu_device; diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index d0b0c8d59064c71c2989a22ab22f7c60b05c0e3b..e60f9a2efdc16dd7feb2b2d4c71c4452accfdd0c 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -2090,6 +2090,8 @@ kgsl_iommu_get_current_ttbr0(struct kgsl_mmu *mmu) { u64 val; struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); + struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; + /* * We cannot enable or disable the clocks in interrupt context, this * function is called from interrupt context if there is an axi error @@ -2097,9 +2099,11 @@ kgsl_iommu_get_current_ttbr0(struct kgsl_mmu *mmu) if (in_interrupt()) return 0; + if (ctx->regbase == NULL) + return 0; + kgsl_iommu_enable_clk(mmu); - val = KGSL_IOMMU_GET_CTX_REG_Q(&iommu->ctx[KGSL_IOMMU_CONTEXT_USER], - TTBR0); + val = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0); kgsl_iommu_disable_clk(mmu); return val; } diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 61fc16fa16b29ce93a827f92507fe6c3e9eb9972..421e8d2dd8a4cba1a815efa3f9eacff5c4f4cf89 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -107,14 +107,12 @@ struct kgsl_pwr_constraint { * @bus_freq: Bus bandwidth vote index * @bus_min: Min bus index @gpu_freq * @bus_max: Max bus index @gpu_freq - * @acd_dvm_val: Register setting for ACD */ struct kgsl_pwrlevel { unsigned int gpu_freq; unsigned int bus_freq; unsigned int bus_min; unsigned int bus_max; - unsigned int acd_dvm_val; }; struct kgsl_regulator { diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 461a5f1b220cb122ee8a0e28f391a5949dccb91a..4af9e4efc071d1eec08c63097c5bb66d3a349710 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -528,6 +528,7 @@ #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE 0x134a +#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A 0x094a #define USB_VENDOR_ID_HUION 0x256c #define USB_DEVICE_ID_HUION_TABLET 0x006e diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 3d121d8ee980b28458021e591129ae369c813721..5d2d746e35f60aabeb951d3cbd27316ee0fcde03 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -955,6 +955,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = sysfs_create_group(&hdev->dev.kobj, &ntrig_attribute_group); + if (ret) + hid_err(hdev, "cannot create sysfs group\n"); return 0; err_free: diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 90af938be5159ce57889004975a99d0623540b97..7ec886d4a332d3d1e2afb129a9681b7c7deb445f 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -99,6 +99,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL }, diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index c401b5b63f4c59c696acfcd21c6943b00b75ae54..4c72e68637c2831848df7c3fdaee8201b651f4d0 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -3212,8 +3212,14 @@ void wacom_setup_device_quirks(struct wacom *wacom) if (features->type >= INTUOSHT && features->type <= BAMBOO_PT) features->device_type |= WACOM_DEVICETYPE_PAD; - features->x_max = 4096; - features->y_max = 4096; + if (features->type == INTUOSHT2) { + features->x_max = features->x_max / 10; + features->y_max = features->y_max / 10; + } + else { + features->x_max = 4096; + features->y_max = 4096; + } } else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) { features->device_type |= WACOM_DEVICETYPE_PAD; diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 05964347008d9c51c1457b65ddd9ef0d1815f584..d96b09fea8358162df586a20f706ba88e2de5491 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -541,11 +541,8 @@ static void reset_channel_cb(void *arg) channel->onchannel_callback = NULL; } -static int vmbus_close_internal(struct vmbus_channel *channel) +void vmbus_reset_channel_cb(struct vmbus_channel *channel) { - struct vmbus_channel_close_channel *msg; - int ret; - /* * vmbus_on_event(), running in the per-channel tasklet, can race * with vmbus_close_internal() in the case of SMP guest, e.g., when @@ -555,6 +552,29 @@ static int vmbus_close_internal(struct vmbus_channel *channel) */ tasklet_disable(&channel->callback_event); + channel->sc_creation_callback = NULL; + + /* Stop the callback asap */ + if (channel->target_cpu != get_cpu()) { + put_cpu(); + smp_call_function_single(channel->target_cpu, reset_channel_cb, + channel, true); + } else { + reset_channel_cb(channel); + put_cpu(); + } + + /* Re-enable tasklet for use on re-open */ + tasklet_enable(&channel->callback_event); +} + +static int vmbus_close_internal(struct vmbus_channel *channel) +{ + struct vmbus_channel_close_channel *msg; + int ret; + + vmbus_reset_channel_cb(channel); + /* * In case a device driver's probe() fails (e.g., * util_probe() -> vmbus_open() returns -ENOMEM) and the device is @@ -568,16 +588,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) } channel->state = CHANNEL_OPEN_STATE; - channel->sc_creation_callback = NULL; - /* Stop callback and cancel the timer asap */ - if (channel->target_cpu != get_cpu()) { - put_cpu(); - smp_call_function_single(channel->target_cpu, reset_channel_cb, - channel, true); - } else { - reset_channel_cb(channel); - put_cpu(); - } /* Send a closing message */ @@ -620,8 +630,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); out: - /* re-enable tasklet for use on re-open */ - tasklet_enable(&channel->callback_event); return ret; } diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 1939c0ca374152d50a68dd0c6122464bef9c2691..1700b4e7758d473282a69bdc95b15f0aa0ed7585 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -881,6 +881,12 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) return; } + /* + * Before setting channel->rescind in vmbus_rescind_cleanup(), we + * should make sure the channel callback is not running any more. + */ + vmbus_reset_channel_cb(channel); + /* * Now wait for offer handling to complete. */ diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 8267439dd1eec0ac32ed217edda4ff324f8e57fe..d8101cd28dfa3ff6c27e1db7ee5f0b3ff2950f76 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -196,6 +196,10 @@ int hv_synic_alloc(void) return 0; err: + /* + * Any memory allocations that succeeded will be freed when + * the caller cleans up by calling hv_synic_free() + */ return -ENOMEM; } @@ -208,12 +212,10 @@ void hv_synic_free(void) struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - if (hv_cpu->synic_event_page) - free_page((unsigned long)hv_cpu->synic_event_page); - if (hv_cpu->synic_message_page) - free_page((unsigned long)hv_cpu->synic_message_page); - if (hv_cpu->post_msg_page) - free_page((unsigned long)hv_cpu->post_msg_page); + kfree(hv_cpu->clk_evt); + free_page((unsigned long)hv_cpu->synic_event_page); + free_page((unsigned long)hv_cpu->synic_message_page); + free_page((unsigned long)hv_cpu->post_msg_page); } kfree(hv_context.hv_numa_map); diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 9ef84998c7f382b114cd11d1c4ea04e7c916dda4..37db2eb66ed790624b0da69355d4414e24587269 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -303,14 +303,18 @@ static inline u16 volt2reg(int channel, long volt, u8 bypass_attn) return clamp_val(reg, 0, 1023) & (0xff << 2); } -static u16 adt7475_read_word(struct i2c_client *client, int reg) +static int adt7475_read_word(struct i2c_client *client, int reg) { - u16 val; + int val1, val2; - val = i2c_smbus_read_byte_data(client, reg); - val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8); + val1 = i2c_smbus_read_byte_data(client, reg); + if (val1 < 0) + return val1; + val2 = i2c_smbus_read_byte_data(client, reg + 1); + if (val2 < 0) + return val2; - return val; + return val1 | (val2 << 8); } static void adt7475_write_word(struct i2c_client *client, int reg, u16 val) diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index e9e6aeabbf842ffd941e0476a185884adac85147..71d3445ba869c85654ae3dcaf3a5460e8fadb268 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -17,7 +17,7 @@ * Bi-directional Current/Power Monitor with I2C Interface * Datasheet: http://www.ti.com/product/ina230 * - * Copyright (C) 2012 Lothar Felten + * Copyright (C) 2012 Lothar Felten * Thanks to Jan Volkering * * This program is free software; you can redistribute it and/or modify @@ -329,6 +329,15 @@ static int ina2xx_set_shunt(struct ina2xx_data *data, long val) return 0; } +static ssize_t ina2xx_show_shunt(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct ina2xx_data *data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%li\n", data->rshunt); +} + static ssize_t ina2xx_store_shunt(struct device *dev, struct device_attribute *da, const char *buf, size_t count) @@ -403,7 +412,7 @@ static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL, /* shunt resistance */ static SENSOR_DEVICE_ATTR(shunt_resistor, S_IRUGO | S_IWUSR, - ina2xx_show_value, ina2xx_store_shunt, + ina2xx_show_shunt, ina2xx_store_shunt, INA2XX_CALIBRATION); /* update interval (ina226 only) */ diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index f5f3f8cf57ea66d1a95bd4511d767611fb0fb338..ca9941fa741b7e04e971f70e4e8055e442e92c43 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -63,6 +63,7 @@ #include #include #include +#include #include "lm75.h" #define USE_ALTERNATE @@ -2642,6 +2643,7 @@ store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, return err; if (val > NUM_TEMP) return -EINVAL; + val = array_index_nospec(val, NUM_TEMP + 1); if (val && (!(data->have_temp & BIT(val - 1)) || !data->temp_src[val - 1])) return -EINVAL; @@ -4107,7 +4109,7 @@ static int nct6775_probe(struct platform_device *pdev) * The temperature is already monitored if the respective bit in * is set. */ - for (i = 0; i < 32; i++) { + for (i = 0; i < 31; i++) { if (!(data->temp_mask & BIT(i + 1))) continue; if (!reg_temp_alternate[i]) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index ba736d11597428c9cede92412ed51a9d588c5b55..b004abe4f9a97815dd84b2a4ed50243a0c1fa6e9 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1039,7 +1039,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) pm_runtime_put(&adev->dev); etmdrvdata[drvdata->cpu] = drvdata; - dev_info(dev, "%s initialized\n", (char *)id->data); + dev_info(dev, "CPU%d: ETM v%d.%d initialized\n", + drvdata->cpu, drvdata->arch >> 4, drvdata->arch & 0xf); if (boot_enable) { coresight_enable(drvdata->csdev); @@ -1057,23 +1058,19 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return ret; } +#define ETM4x_AMBA_ID(pid) \ + { \ + .id = pid, \ + .mask = 0x000fffff, \ + } + static const struct amba_id etm4_ids[] = { - { /* ETM 4.0 - Cortex-A53 */ - .id = 0x000bb95d, - .mask = 0x000fffff, - .data = "ETM 4.0", - }, - { /* ETM 4.0 - Cortex-A57 */ - .id = 0x000bb95e, - .mask = 0x000fffff, - .data = "ETM 4.0", - }, - { /* ETM 4.0 - A72, Maia, HiSilicon */ - .id = 0x000bb95a, - .mask = 0x000fffff, - .data = "ETM 4.0", - }, - { 0, 0}, + ETM4x_AMBA_ID(0x000bb95d), /* Cortex-A53 */ + ETM4x_AMBA_ID(0x000bb95e), /* Cortex-A57 */ + ETM4x_AMBA_ID(0x000bb95a), /* Cortex-A72 */ + ETM4x_AMBA_ID(0x000bb959), /* Cortex-A73 */ + ETM4x_AMBA_ID(0x000bb9da), /* Cortex-A35 */ + {}, }; static struct amba_driver etm4x_driver = { diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 1820e094280e6aa554dbbf21375c72ba2f0f1f7f..c2fac28ae5ce29241a6b491a513fbf4cb9c6392c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -573,7 +573,7 @@ static int tmc_etr_alloc_mem(struct tmc_drvdata *drvdata) return ret; } -static void tmc_etr_free_mem(struct tmc_drvdata *drvdata) +void tmc_etr_free_mem(struct tmc_drvdata *drvdata) { if (drvdata->vaddr) { if (drvdata->memtype == TMC_ETR_MEM_TYPE_CONTIG) diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 8fef3c073b4fe0c817372319a7ff662c45380603..16c12c4ddd3f4ab1869d7a05acee9953015c745a 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -474,8 +474,12 @@ static ssize_t out_mode_store(struct device *dev, drvdata->out_mode = TMC_ETR_OUT_MODE_USB; spin_unlock_irqrestore(&drvdata->spinlock, flags); - coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0); - coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0); + if (drvdata->mode != CS_MODE_DISABLED) { + coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0); + coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0); + tmc_etr_byte_cntr_stop(drvdata->byte_cntr); + tmc_etr_free_mem(drvdata); + } drvdata->usbch = usb_qdss_open("qdss", drvdata, usb_notifier); diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 7fa37cb663bfaca034acdb772c50718ba3f422a6..ba3d376675b7278448f04c1cd4c819ce53d524fe 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -274,6 +274,7 @@ extern struct byte_cntr *byte_cntr_init(struct amba_device *adev, struct tmc_drvdata *drvdata); extern const struct coresight_ops tmc_etr_cs_ops; extern void tmc_etr_sg_rwp_pos(struct tmc_drvdata *drvdata, phys_addr_t rwp); +extern void tmc_etr_free_mem(struct tmc_drvdata *drvdata); extern const struct coresight_ops tmc_etr_cs_ops; diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 735dca089389ac7904bf533317d8ab8c8a4ed060..15dd01f8c197657bec42a61b909ba84a22df3deb 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -47,8 +47,9 @@ /** register definition **/ /* FFSR - 0x300 */ -#define FFSR_FT_STOPPED BIT(1) +#define FFSR_FT_STOPPED_BIT 1 /* FFCR - 0x304 */ +#define FFCR_FON_MAN_BIT 6 #define FFCR_FON_MAN BIT(6) #define FFCR_STOP_FI BIT(12) @@ -93,9 +94,9 @@ static void tpiu_disable_hw(struct tpiu_drvdata *drvdata) /* Generate manual flush */ writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR); /* Wait for flush to complete */ - coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN, 0); + coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0); /* Wait for formatter to stop */ - coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED, 1); + coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1); CS_LOCK(drvdata->base); } diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 7bb1ed6936423b7653f5d22ac508445da5c863bd..3a66a54d572e9ea3f6e5d36d4e396b41a939fbff 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -131,7 +131,7 @@ static int coresight_find_link_inport(struct coresight_device *csdev, dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n", dev_name(&parent->dev), dev_name(&csdev->dev)); - return 0; + return -ENODEV; } static int coresight_find_link_outport(struct coresight_device *csdev, @@ -149,7 +149,7 @@ static int coresight_find_link_outport(struct coresight_device *csdev, dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n", dev_name(&csdev->dev), dev_name(&child->dev)); - return 0; + return -ENODEV; } static int coresight_enable_sink(struct coresight_device *csdev, u32 mode) @@ -203,6 +203,9 @@ static int coresight_enable_link(struct coresight_device *csdev, else refport = 0; + if (refport < 0) + return refport; + if (atomic_inc_return(&csdev->refcnt[refport]) == 1) { if (link_ops(csdev)->enable) { ret = link_ops(csdev)->enable(csdev, inport, outport); diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index c1793313bb0873fea10e263062f6e580d34c7670..757801d2760439ac116acc52a0995af618331125 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -147,7 +147,8 @@ static int intel_th_remove(struct device *dev) th->thdev[i] = NULL; } - th->num_thdevs = lowest; + if (lowest >= 0) + th->num_thdevs = lowest; } if (thdrv->attr_group) diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 284f8670dbeb748bd8d0c6f240bbf41e62ce95f7..a074735456bc7571eab7e153168cd913ce9e4651 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -110,22 +110,22 @@ #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0) enum aspeed_i2c_master_state { + ASPEED_I2C_MASTER_INACTIVE, ASPEED_I2C_MASTER_START, ASPEED_I2C_MASTER_TX_FIRST, ASPEED_I2C_MASTER_TX, ASPEED_I2C_MASTER_RX_FIRST, ASPEED_I2C_MASTER_RX, ASPEED_I2C_MASTER_STOP, - ASPEED_I2C_MASTER_INACTIVE, }; enum aspeed_i2c_slave_state { + ASPEED_I2C_SLAVE_STOP, ASPEED_I2C_SLAVE_START, ASPEED_I2C_SLAVE_READ_REQUESTED, ASPEED_I2C_SLAVE_READ_PROCESSED, ASPEED_I2C_SLAVE_WRITE_REQUESTED, ASPEED_I2C_SLAVE_WRITE_RECEIVED, - ASPEED_I2C_SLAVE_STOP, }; struct aspeed_i2c_bus { @@ -859,7 +859,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) if (!match) bus->get_clk_reg_val = aspeed_i2c_24xx_get_clk_reg_val; else - bus->get_clk_reg_val = match->data; + bus->get_clk_reg_val = (u32 (*)(u32))match->data; /* Initialize the I2C adapter */ spin_lock_init(&bus->lock); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index b8c43535f16cf29b8f8b517fe2e7ecaba1c80156..5cf670f57be71c3f81b7ebc57f7a0aec325e5ce6 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -234,12 +234,16 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) /* * It's not always possible to have 1 to 2 ratio when d=7, so fall back * to minimal possible clkh in this case. + * + * Note: + * CLKH is not allowed to be 0, in this case I2C clock is not generated + * at all */ - if (clk >= clkl + d) { + if (clk > clkl + d) { clkh = clk - clkl - d; clkl -= d; } else { - clkh = 0; + clkh = 1; clkl = clk - (d << 1); } diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ba8df2fde1b2769fe65bdf49f338625577b6ced9..06debfa903b9c582f25fdc13fe7a0a359c055630 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -138,6 +138,7 @@ #define SBREG_BAR 0x10 #define SBREG_SMBCTRL 0xc6000c +#define SBREG_SMBCTRL_DNV 0xcf000c /* Host status bits for SMBPCISTS */ #define SMBPCISTS_INTS BIT(3) @@ -1395,7 +1396,11 @@ static void i801_add_tco(struct i801_priv *priv) spin_unlock(&p2sb_spinlock); res = &tco_res[ICH_RES_MEM_OFF]; - res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL; + if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS) + res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV; + else + res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL; + res->end = res->start + 3; res->flags = IORESOURCE_MEM; @@ -1411,6 +1416,13 @@ static void i801_add_tco(struct i801_priv *priv) } #ifdef CONFIG_ACPI +static bool i801_acpi_is_smbus_ioport(const struct i801_priv *priv, + acpi_physical_address address) +{ + return address >= priv->smba && + address <= pci_resource_end(priv->pci_dev, SMBBAR); +} + static acpi_status i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, u64 *value, void *handler_context, void *region_context) @@ -1426,7 +1438,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, */ mutex_lock(&priv->acpi_lock); - if (!priv->acpi_reserved) { + if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) { priv->acpi_reserved = true; dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n"); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 75c6b98585ba2e545ac0b3239e237796b68881b7..b73dd837fb533ae06491074b2a17a2a37d0db66f 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -665,9 +665,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, struct imx_i2c_dma *dma = i2c_imx->dma; struct device *dev = &i2c_imx->adapter.dev; - temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); - temp |= I2CR_DMAEN; - imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); dma->chan_using = dma->chan_rx; dma->dma_transfer_dir = DMA_DEV_TO_MEM; @@ -780,6 +777,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo int i, result; unsigned int temp; int block_data = msgs->flags & I2C_M_RECV_LEN; + int use_dma = i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data; dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n", @@ -806,12 +804,14 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo */ if ((msgs->len - 1) || block_data) temp &= ~I2CR_TXAK; + if (use_dma) + temp |= I2CR_DMAEN; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */ dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__); - if (i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data) + if (use_dma) return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg); /* read data */ diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index ae6ed254e01db5c10eb79e7bed4718da4d94536a..732d6c456a6f1cdb9e9687125930bd6722216ef0 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -538,6 +538,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c) { u8 rx_watermark; struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg; + unsigned long flags; /* Clear and enable Rx full interrupt. */ xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK); @@ -553,6 +554,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c) rx_watermark = IIC_RX_FIFO_DEPTH; xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); + local_irq_save(flags); if (!(msg->flags & I2C_M_NOSTART)) /* write the address */ xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, @@ -563,6 +565,8 @@ static void xiic_start_recv(struct xiic_i2c *i2c) xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0)); + local_irq_restore(flags); + if (i2c->nmsgs == 1) /* very last, enable bus not busy as well */ xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index a9126b3cda61bc95f6a9d1282821ab7552484534..847d9bf6744c21bde84d1c04aec88ad64a059a68 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -475,11 +475,16 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, msgs[0].buf = buffer; ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (ret < 0) - dev_err(&client->adapter->dev, "i2c write failed\n"); kfree(buffer); - return ret; + + if (ret < 0) { + dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret); + return ret; + } + + /* 1 transfer must have completed successfully */ + return (ret == 1) ? 0 : -EIO; } static acpi_status diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 6f2fe63e8f5aa80ade4daa76bdfe0b48516b2256..7b961c9c62eff5175bfdb193f215f1a78be8b83c 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -638,7 +638,7 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, unsigned int flags) { - rt_mutex_lock(&adapter->bus_lock); + rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter)); } /** diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 9669ca4937b891063d4cd63e552344d818f5eefa..7ba31f6bf1488e5a3ffef565d0d7c85091c91f0c 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -144,7 +144,7 @@ static void i2c_mux_lock_bus(struct i2c_adapter *adapter, unsigned int flags) struct i2c_mux_priv *priv = adapter->algo_data; struct i2c_adapter *parent = priv->muxc->parent; - rt_mutex_lock(&parent->mux_lock); + rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter)); if (!(flags & I2C_LOCK_ROOT_ADAPTER)) return; i2c_lock_bus(parent, flags); @@ -181,7 +181,7 @@ static void i2c_parent_lock_bus(struct i2c_adapter *adapter, struct i2c_mux_priv *priv = adapter->algo_data; struct i2c_adapter *parent = priv->muxc->parent; - rt_mutex_lock(&parent->mux_lock); + rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter)); i2c_lock_bus(parent, flags); } diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 9ccb5828db986def7c1531b5196457995b909190..3dda7afe8a11632bbdec2d12d17eb131198aaa0e 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -21,6 +21,8 @@ #define ADXL345_REG_DATAX0 0x32 #define ADXL345_REG_DATAY0 0x34 #define ADXL345_REG_DATAZ0 0x36 +#define ADXL345_REG_DATA_AXIS(index) \ + (ADXL345_REG_DATAX0 + (index) * sizeof(__le16)) #define ADXL345_POWER_CTL_MEASURE BIT(3) #define ADXL345_POWER_CTL_STANDBY 0x00 @@ -47,19 +49,19 @@ struct adxl345_data { u8 data_range; }; -#define ADXL345_CHANNEL(reg, axis) { \ +#define ADXL345_CHANNEL(index, axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ - .address = reg, \ + .address = index, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ } static const struct iio_chan_spec adxl345_channels[] = { - ADXL345_CHANNEL(ADXL345_REG_DATAX0, X), - ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y), - ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z), + ADXL345_CHANNEL(0, X), + ADXL345_CHANNEL(1, Y), + ADXL345_CHANNEL(2, Z), }; static int adxl345_read_raw(struct iio_dev *indio_dev, @@ -67,7 +69,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct adxl345_data *data = iio_priv(indio_dev); - __le16 regval; + __le16 accel; int ret; switch (mask) { @@ -77,12 +79,13 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, * ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte * and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte */ - ret = regmap_bulk_read(data->regmap, chan->address, ®val, - sizeof(regval)); + ret = regmap_bulk_read(data->regmap, + ADXL345_REG_DATA_AXIS(chan->address), + &accel, sizeof(accel)); if (ret < 0) return ret; - *val = sign_extend32(le16_to_cpu(regval), 12); + *val = sign_extend32(le16_to_cpu(accel), 12); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 0; diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 565f7d8d3304a3eba3b13d69ad568cc7f916b9bd..f2761b3855411d6db48ef93291c7d4ac256ac93f 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -797,6 +797,7 @@ static int sca3000_write_raw(struct iio_dev *indio_dev, mutex_lock(&st->lock); ret = sca3000_write_3db_freq(st, val); mutex_unlock(&st->lock); + return ret; default: return -EINVAL; } diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 59f99b3a180d7332c4bc41f45d14bdbc12ada06c..d5b9f831eba77e0ce32db8f812cee197df7b44a7 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -701,6 +702,7 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) { struct ina2xx_chip_info *chip = iio_priv(indio_dev); unsigned int sampling_us = SAMPLING_PERIOD(chip); + struct task_struct *task; dev_dbg(&indio_dev->dev, "Enabling buffer w/ scan_mask %02x, freq = %d, avg =%u\n", (unsigned int)(*indio_dev->active_scan_mask), @@ -710,11 +712,17 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) dev_dbg(&indio_dev->dev, "Async readout mode: %d\n", chip->allow_async_readout); - chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev, - "%s:%d-%uus", indio_dev->name, indio_dev->id, - sampling_us); + task = kthread_create(ina2xx_capture_thread, (void *)indio_dev, + "%s:%d-%uus", indio_dev->name, indio_dev->id, + sampling_us); + if (IS_ERR(task)) + return PTR_ERR(task); + + get_task_struct(task); + wake_up_process(task); + chip->task = task; - return PTR_ERR_OR_ZERO(chip->task); + return 0; } static int ina2xx_buffer_disable(struct iio_dev *indio_dev) @@ -723,6 +731,7 @@ static int ina2xx_buffer_disable(struct iio_dev *indio_dev) if (chip->task) { kthread_stop(chip->task); + put_task_struct(chip->task); chip->task = NULL; } diff --git a/drivers/iio/counter/104-quad-8.c b/drivers/iio/counter/104-quad-8.c index ba3d9030cd514f6ac433fb8ca7703eb97c71c0ac..181585ae6e171cc40bbe5dc3356335e990cd034c 100644 --- a/drivers/iio/counter/104-quad-8.c +++ b/drivers/iio/counter/104-quad-8.c @@ -138,7 +138,7 @@ static int quad8_write_raw(struct iio_dev *indio_dev, outb(val >> (8 * i), base_offset); /* Reset Borrow, Carry, Compare, and Sign flags */ - outb(0x02, base_offset + 1); + outb(0x04, base_offset + 1); /* Reset Error flag */ outb(0x06, base_offset + 1); diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 99eba524f6ddbe063d2cf2ac359491287177d10b..1642b55f70da3ab28fa604c3e373bbab429ac593 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -508,7 +508,7 @@ static ssize_t ad9523_store(struct device *dev, return ret; if (!state) - return 0; + return len; mutex_lock(&indio_dev->mlock); switch ((u32)this_attr->address) { @@ -642,7 +642,7 @@ static int ad9523_read_raw(struct iio_dev *indio_dev, code = (AD9523_CLK_DIST_DIV_PHASE_REV(ret) * 3141592) / AD9523_CLK_DIST_DIV_REV(ret); *val = code / 1000000; - *val2 = (code % 1000000) * 10; + *val2 = code % 1000000; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 8f26428804a236fa1a38e612c0cd6aa3245b7eff..5f625ffa2a88d8b12d10491d85e920e519c8a97c 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -362,10 +362,9 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2) } comp_humidity = bmp280_compensate_humidity(data, adc_humidity); - *val = comp_humidity; - *val2 = 1024; + *val = comp_humidity * 1000 / 1024; - return IIO_VAL_FRACTIONAL; + return IIO_VAL_INT; } static int bmp280_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 79843a3ca9dcd53d8cc4362bb72b9124ed33bd65..7c5eca312aa884d8a3a11a3651a361d6af12f3ea 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -730,6 +730,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) dgid = (union ib_gid *) &addr->sib_addr; pkey = ntohs(addr->sib_pkey); + mutex_lock(&lock); list_for_each_entry(cur_dev, &dev_list, list) { for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { if (!rdma_cap_af_ib(cur_dev->device, p)) @@ -756,18 +757,19 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) cma_dev = cur_dev; sgid = gid; id_priv->id.port_num = p; + goto found; } } } } - - if (!cma_dev) - return -ENODEV; + mutex_unlock(&lock); + return -ENODEV; found: cma_attach_to_dev(id_priv, cma_dev); - addr = (struct sockaddr_ib *) cma_src_addr(id_priv); - memcpy(&addr->sib_addr, &sgid, sizeof sgid); + mutex_unlock(&lock); + addr = (struct sockaddr_ib *)cma_src_addr(id_priv); + memcpy(&addr->sib_addr, &sgid, sizeof(sgid)); cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr); return 0; } @@ -1459,9 +1461,16 @@ static bool cma_match_net_dev(const struct rdma_cm_id *id, (addr->src_addr.ss_family == AF_IB || cma_protocol_roce_dev_port(id->device, port_num)); - return !addr->dev_addr.bound_dev_if || - (net_eq(dev_net(net_dev), addr->dev_addr.net) && - addr->dev_addr.bound_dev_if == net_dev->ifindex); + /* + * Net namespaces must match, and if the listner is listening + * on a specific netdevice than netdevice must match as well. + */ + if (net_eq(dev_net(net_dev), addr->dev_addr.net) && + (!!addr->dev_addr.bound_dev_if == + (addr->dev_addr.bound_dev_if == net_dev->ifindex))) + return true; + else + return false; } static struct rdma_id_private *cma_find_listener( diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c index 6ca607e8e293cab4405f6da09af5df8c0b7710ff..9939dcfb1b6a5b434879c3a168c5273aec142f22 100644 --- a/drivers/infiniband/core/rw.c +++ b/drivers/infiniband/core/rw.c @@ -87,7 +87,7 @@ static int rdma_rw_init_one_mr(struct ib_qp *qp, u8 port_num, } ret = ib_map_mr_sg(reg->mr, sg, nents, &offset, PAGE_SIZE); - if (ret < nents) { + if (ret < 0 || ret < nents) { ib_mr_pool_put(qp, &qp->rdma_mrs, reg->mr); return -EINVAL; } diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 0f70ff91276ef658db38d2cb856402c4336b4a6f..aff6ef3ad52c2f3648dbf5356ef9b7a5b94915fa 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -424,6 +424,7 @@ static int ib_uverbs_comp_event_close(struct inode *inode, struct file *filp) list_del(&entry->obj_list); kfree(entry); } + file->ev_queue.is_closed = 1; spin_unlock_irq(&file->ev_queue.lock); uverbs_close_fd(filp); diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c index 9536de8c5fb8b3d977b78a43af180b6d4b035b8d..124c8915b9eeee88f599b129e2760f2c767281e6 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c @@ -156,7 +156,7 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, struct bnxt_qplib_gid *gid) { - if (index > sgid_tbl->max) { + if (index >= sgid_tbl->max) { dev_err(&res->pdev->dev, "QPLIB: Index %d exceeded SGID table max (%d)", index, sgid_tbl->max); @@ -361,7 +361,7 @@ int bnxt_qplib_get_pkey(struct bnxt_qplib_res *res, *pkey = 0xFFFF; return 0; } - if (index > pkey_tbl->max) { + if (index >= pkey_tbl->max) { dev_err(&res->pdev->dev, "QPLIB: Index %d exceeded PKEY table max (%d)", index, pkey_tbl->max); diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index a8a8f65a1e51bd5e3868951fd801beca9e0e5d1a..24952af51a546bc325adb095d713d435a1d422f7 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1395,6 +1395,12 @@ static void flush_qp(struct c4iw_qp *qhp) schp = to_c4iw_cq(qhp->ibqp.send_cq); if (qhp->ibqp.uobject) { + + /* for user qps, qhp->wq.flushed is protected by qhp->mutex */ + if (qhp->wq.flushed) + return; + + qhp->wq.flushed = 1; t4_set_wq_in_error(&qhp->wq); t4_set_cq_in_error(&rchp->cq); spin_lock_irqsave(&rchp->comp_handler_lock, flag); diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c index b5fab55cc275068166369c184a759ab9a925849d..b197e925fe3639dfc33b4ce373876ee0a50f152a 100644 --- a/drivers/infiniband/hw/hfi1/affinity.c +++ b/drivers/infiniband/hw/hfi1/affinity.c @@ -146,7 +146,7 @@ int node_affinity_init(void) while ((dev = pci_get_device(ids->vendor, ids->device, dev))) { node = pcibus_to_node(dev->bus); if (node < 0) - node = numa_node_id(); + goto out; hfi1_per_node_cntr[node]++; } @@ -154,6 +154,18 @@ int node_affinity_init(void) } return 0; + +out: + /* + * Invalid PCI NUMA node information found, note it, and populate + * our database 1:1. + */ + pr_err("HFI: Invalid PCI NUMA node. Performance may be affected\n"); + pr_err("HFI: System BIOS may need to be upgraded\n"); + for (node = 0; node < node_affinity.num_possible_nodes; node++) + hfi1_per_node_cntr[node] = 1; + + return 0; } void node_affinity_destroy(void) @@ -227,8 +239,14 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd) const struct cpumask *local_mask; int curr_cpu, possible, i; - if (node < 0) - node = numa_node_id(); + /* + * If the BIOS does not have the NUMA node information set, select + * NUMA 0 so we get consistent performance. + */ + if (node < 0) { + dd_dev_err(dd, "Invalid PCI NUMA node. Performance may be affected\n"); + node = 0; + } dd->node = node; local_mask = cpumask_of_node(dd->node); diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c index a95ac62465592080ea60a2db31416e2b7b335288..19a8e6052820fec0344f3b81700017a49f21ab01 100644 --- a/drivers/infiniband/hw/hfi1/pio.c +++ b/drivers/infiniband/hw/hfi1/pio.c @@ -86,6 +86,7 @@ void pio_send_control(struct hfi1_devdata *dd, int op) unsigned long flags; int write = 1; /* write sendctrl back */ int flush = 0; /* re-read sendctrl to make sure it is flushed */ + int i; spin_lock_irqsave(&dd->sendctrl_lock, flags); @@ -95,9 +96,13 @@ void pio_send_control(struct hfi1_devdata *dd, int op) reg |= SEND_CTRL_SEND_ENABLE_SMASK; /* Fall through */ case PSC_DATA_VL_ENABLE: + mask = 0; + for (i = 0; i < ARRAY_SIZE(dd->vld); i++) + if (!dd->vld[i].mtu) + mask |= BIT_ULL(i); /* Disallow sending on VLs not enabled */ - mask = (((~0ull) << num_vls) & SEND_CTRL_UNSUPPORTED_VL_MASK) << - SEND_CTRL_UNSUPPORTED_VL_SHIFT; + mask = (mask & SEND_CTRL_UNSUPPORTED_VL_MASK) << + SEND_CTRL_UNSUPPORTED_VL_SHIFT; reg = (reg & ~SEND_CTRL_UNSUPPORTED_VL_SMASK) | mask; break; case PSC_GLOBAL_DISABLE: diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index c0c0e0445cbfbd72938fe07520f574515992298b..8c954a0ae3b69d9e0834f6906b2ba68f0acdeba0 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -828,7 +828,7 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts) if (ACCESS_ONCE(iovec->offset) == iovec->iov.iov_len) { if (++req->iov_idx == req->data_iovs) { ret = -EFAULT; - goto free_txreq; + goto free_tx; } iovec = &req->iovs[req->iov_idx]; WARN_ON(iovec->offset); diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index e232f3c608b41795a2da43b5439687756c9ec24d..63d404a6752a19db474303f31205e2b2e087d38e 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -1573,6 +1573,7 @@ static int hfi1_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr) struct hfi1_pportdata *ppd; struct hfi1_devdata *dd; u8 sc5; + u8 sl; if (hfi1_check_mcast(rdma_ah_get_dlid(ah_attr)) && !(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH)) @@ -1581,8 +1582,13 @@ static int hfi1_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr) /* test the mapping for validity */ ibp = to_iport(ibdev, rdma_ah_get_port_num(ah_attr)); ppd = ppd_from_ibp(ibp); - sc5 = ibp->sl_to_sc[rdma_ah_get_sl(ah_attr)]; dd = dd_from_ppd(ppd); + + sl = rdma_ah_get_sl(ah_attr); + if (sl >= ARRAY_SIZE(ibp->sl_to_sc)) + return -EINVAL; + + sc5 = ibp->sl_to_sc[sl]; if (sc_to_vlt(dd, sc5) > num_vls && sc_to_vlt(dd, sc5) != 0xf) return -EINVAL; return 0; diff --git a/drivers/infiniband/hw/hns/hns_roce_pd.c b/drivers/infiniband/hw/hns/hns_roce_pd.c index a64500fa114531e769b7816d1e5304559642d45b..3cef53c651331ffc2325b5868106c3b91b7b1358 100644 --- a/drivers/infiniband/hw/hns/hns_roce_pd.c +++ b/drivers/infiniband/hw/hns/hns_roce_pd.c @@ -35,7 +35,7 @@ static int hns_roce_pd_alloc(struct hns_roce_dev *hr_dev, unsigned long *pdn) { - return hns_roce_bitmap_alloc(&hr_dev->pd_bitmap, pdn); + return hns_roce_bitmap_alloc(&hr_dev->pd_bitmap, pdn) ? -ENOMEM : 0; } static void hns_roce_pd_free(struct hns_roce_dev *hr_dev, unsigned long pdn) diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index f5dd21c2d275eb6eb0db9cfe335f230cc9e33874..3a37d26889df169a61cd785cb455fb47d3863019 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c @@ -114,7 +114,10 @@ static int hns_roce_reserve_range_qp(struct hns_roce_dev *hr_dev, int cnt, { struct hns_roce_qp_table *qp_table = &hr_dev->qp_table; - return hns_roce_bitmap_alloc_range(&qp_table->bitmap, cnt, align, base); + return hns_roce_bitmap_alloc_range(&qp_table->bitmap, cnt, align, + base) ? + -ENOMEM : + 0; } enum hns_roce_qp_state to_hns_roce_state(enum ib_qp_state state) diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c index b7961f21b555b5a348c520aa184edfe00dacd116..39398dd074d662778066b4deb7d10aac22c174dd 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c +++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c @@ -1408,6 +1408,7 @@ static void i40iw_set_hugetlb_values(u64 addr, struct i40iw_mr *iwmr) struct vm_area_struct *vma; struct hstate *h; + down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm, addr); if (vma && is_vm_hugetlb_page(vma)) { h = hstate_vma(vma); @@ -1416,6 +1417,7 @@ static void i40iw_set_hugetlb_values(u64 addr, struct i40iw_mr *iwmr) iwmr->page_msk = huge_page_mask(h); } } + up_read(¤t->mm->mmap_sem); } /** diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 1587cedee13e2df7a1515700d6eaabdce862bccc..761d3ce6a63a0a2cc31e8ed5787dc35c13881d58 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c @@ -247,8 +247,11 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, } if (flags & IB_MR_REREG_ACCESS) { - if (ib_access_writable(mr_access_flags) && !mmr->umem->writable) - return -EPERM; + if (ib_access_writable(mr_access_flags) && + !mmr->umem->writable) { + err = -EPERM; + goto release_mpt_entry; + } err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry, convert_access(mr_access_flags)); diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 9354fec8efe78321c6d909d54d6d843933f003d3..e10c3d915e389156fb26debfbd33cbec7c6cd86b 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -4014,9 +4014,9 @@ static void to_rdma_ah_attr(struct mlx4_ib_dev *ibdev, u8 port_num = path->sched_queue & 0x40 ? 2 : 1; memset(ah_attr, 0, sizeof(*ah_attr)); - ah_attr->type = rdma_ah_find_type(&ibdev->ib_dev, port_num); if (port_num == 0 || port_num > dev->caps.num_ports) return; + ah_attr->type = rdma_ah_find_type(&ibdev->ib_dev, port_num); if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) rdma_ah_set_sl(ah_attr, ((path->sched_queue >> 3) & 0x7) | diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c index 3c7522d025f2b559f638fd2bde05200702488dde..93d67d97c279441f939705bb83298c3612563662 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c @@ -266,18 +266,24 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, desc_size = sizeof(struct mlx5_wqe_srq_next_seg) + srq->msrq.max_gs * sizeof(struct mlx5_wqe_data_seg); - if (desc_size == 0 || srq->msrq.max_gs > desc_size) - return ERR_PTR(-EINVAL); + if (desc_size == 0 || srq->msrq.max_gs > desc_size) { + err = -EINVAL; + goto err_srq; + } desc_size = roundup_pow_of_two(desc_size); desc_size = max_t(size_t, 32, desc_size); - if (desc_size < sizeof(struct mlx5_wqe_srq_next_seg)) - return ERR_PTR(-EINVAL); + if (desc_size < sizeof(struct mlx5_wqe_srq_next_seg)) { + err = -EINVAL; + goto err_srq; + } srq->msrq.max_avail_gather = (desc_size - sizeof(struct mlx5_wqe_srq_next_seg)) / sizeof(struct mlx5_wqe_data_seg); srq->msrq.wqe_shift = ilog2(desc_size); buf_size = srq->msrq.max * desc_size; - if (buf_size < desc_size) - return ERR_PTR(-EINVAL); + if (buf_size < desc_size) { + err = -EINVAL; + goto err_srq; + } in.type = init_attr->srq_type; if (pd->uobject) diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c index 9eb12c2e3c74cf69499124e21fcb1b4a8be4a40f..83cfe44f070ec47d85f43a02e7ce4a44158bab35 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -276,6 +276,7 @@ static inline enum comp_state check_ack(struct rxe_qp *qp, case IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE: if (wqe->wr.opcode != IB_WR_RDMA_READ && wqe->wr.opcode != IB_WR_RDMA_READ_WITH_INV) { + wqe->status = IB_WC_FATAL_ERR; return COMPST_ERROR; } reset_retry_counters(qp); diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c index fb8c83e055e14c653eb1f05f42a3265005d8d737..83412df726a5184cd049dea96d28724c13d3f6ae 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -225,9 +225,14 @@ static int hdr_check(struct rxe_pkt_info *pkt) goto err1; } + if (unlikely(qpn == 0)) { + pr_warn_once("QP 0 not supported"); + goto err1; + } + if (qpn != IB_MULTICAST_QPN) { - index = (qpn == 0) ? port->qp_smi_index : - ((qpn == 1) ? port->qp_gsi_index : qpn); + index = (qpn == 1) ? port->qp_gsi_index : qpn; + qp = rxe_pool_get_index(&rxe->qp_pool, index); if (unlikely(!qp)) { pr_warn_ratelimited("no qp matches qpn 0x%x\n", qpn); diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index 54cc9cb1e3b765b848782ad9779225a1dde7e1b6..de853bcc2384d92ede39f6f8d30c5c3749445d6d 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -645,6 +645,9 @@ int rxe_requester(void *arg) } else { goto exit; } + if ((wqe->wr.send_flags & IB_SEND_SIGNALED) || + qp->sq_sig_type == IB_SIGNAL_ALL_WR) + rxe_run_task(&qp->comp.task, 1); qp->req.wqe_index = next_index(qp->sq.queue, qp->req.wqe_index); goto next_wqe; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 7a5ed5a5391e12b1727a70faac5f0895e01b5b3a..9939f32d015487fc1ed8617d18e6f97f305751ba 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1018,12 +1018,14 @@ static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even skb_queue_head_init(&skqueue); + netif_tx_lock_bh(p->dev); spin_lock_irq(&priv->lock); set_bit(IPOIB_FLAG_OPER_UP, &p->flags); if (p->neigh) while ((skb = __skb_dequeue(&p->neigh->queue))) __skb_queue_tail(&skqueue, skb); spin_unlock_irq(&priv->lock); + netif_tx_unlock_bh(p->dev); while ((skb = __skb_dequeue(&skqueue))) { skb->dev = p->dev; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 6bc9a768f72193ef0a9b3ad00ed4e9f4da8f23d1..e6ff16b27acdb6c65a234c8536ffcdb87b690cd5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1752,7 +1752,8 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) goto out_free_pd; } - if (ipoib_neigh_hash_init(priv) < 0) { + ret = ipoib_neigh_hash_init(priv); + if (ret) { pr_warn("%s failed to init neigh hash\n", dev->name); goto out_dev_uninit; } diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 299a97b7e17fff2982e8762e4620afb904683870..ade98c234dcb39e1c860bb8b7a115964ac61d540 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -2669,7 +2669,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); struct srp_rdma_ch *ch; - int i; + int i, j; u8 status; shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n"); @@ -2683,8 +2683,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) for (i = 0; i < target->ch_count; i++) { ch = &target->ch[i]; - for (i = 0; i < target->req_ring_size; ++i) { - struct srp_request *req = &ch->req_ring[i]; + for (j = 0; j < target->req_ring_size; ++j) { + struct srp_request *req = &ch->req_ring[j]; srp_finish_req(ch, req, scmnd->device, DID_RESET << 16); } diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 2e7982042fe59e94efbb8870ed2bc414a3748374..7dbc0d9ad9a7656d9af03b016971d037bfce64c5 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1713,8 +1713,7 @@ static bool srpt_close_ch(struct srpt_rdma_ch *ch) int ret; if (!srpt_set_ch_state(ch, CH_DRAINING)) { - pr_debug("%s-%d: already closed\n", ch->sess_name, - ch->qp->qp_num); + pr_debug("%s: already closed\n", ch->sess_name); return false; } diff --git a/drivers/input/input.c b/drivers/input/input.c index 762bfb9487dc961cf1c7d12a18a0d10dd3386b4c..50d425fe6706faf84596851a730a0e62b860d1cb 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -480,11 +480,19 @@ EXPORT_SYMBOL(input_inject_event); */ void input_alloc_absinfo(struct input_dev *dev) { - if (!dev->absinfo) - dev->absinfo = kcalloc(ABS_CNT, sizeof(*dev->absinfo), - GFP_KERNEL); + if (dev->absinfo) + return; - WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__); + dev->absinfo = kcalloc(ABS_CNT, sizeof(*dev->absinfo), GFP_KERNEL); + if (!dev->absinfo) { + dev_err(dev->dev.parent ?: &dev->dev, + "%s: unable to allocate memory\n", __func__); + /* + * We will handle this allocation failure in + * input_register_device() when we refuse to register input + * device with ABS bits but without absinfo. + */ + } } EXPORT_SYMBOL(input_alloc_absinfo); diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c53755f44dc9e6a469359d0173dbbf264..92d7396490225732c2aa54fa7951fe771187c82d 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -229,7 +229,7 @@ static int xenkbd_probe(struct xenbus_device *dev, } } - touch = xenbus_read_unsigned(dev->nodename, + touch = xenbus_read_unsigned(dev->otherend, XENKBD_FIELD_FEAT_MTOUCH, 0); if (touch) { ret = xenbus_write(XBT_NIL, dev->nodename, @@ -304,13 +304,13 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!mtouch) goto error_nomem; - num_cont = xenbus_read_unsigned(info->xbdev->nodename, + num_cont = xenbus_read_unsigned(info->xbdev->otherend, XENKBD_FIELD_MT_NUM_CONTACTS, 1); - width = xenbus_read_unsigned(info->xbdev->nodename, + width = xenbus_read_unsigned(info->xbdev->otherend, XENKBD_FIELD_MT_WIDTH, XENFB_WIDTH); - height = xenbus_read_unsigned(info->xbdev->nodename, + height = xenbus_read_unsigned(info->xbdev->otherend, XENKBD_FIELD_MT_HEIGHT, XENFB_HEIGHT); diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index a250f433eb968b236ae2ddf99cf45f69d7f17fef..84c69e962230bc8f3fb739eb294d2e433147582f 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1180,6 +1180,8 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = { static const char * const middle_button_pnp_ids[] = { "LEN2131", /* ThinkPad P52 w/ NFC */ "LEN2132", /* ThinkPad P52 */ + "LEN2133", /* ThinkPad P72 w/ NFC */ + "LEN2134", /* ThinkPad P72 */ NULL }; diff --git a/drivers/input/rmi4/rmi_2d_sensor.c b/drivers/input/rmi4/rmi_2d_sensor.c index 8bb866c7b9855c5025d31b7be3f722d469f73da9..8eeffa066022dadb9f718f77aab1609700f05543 100644 --- a/drivers/input/rmi4/rmi_2d_sensor.c +++ b/drivers/input/rmi4/rmi_2d_sensor.c @@ -32,15 +32,15 @@ void rmi_2d_sensor_abs_process(struct rmi_2d_sensor *sensor, if (obj->type == RMI_2D_OBJECT_NONE) return; - if (axis_align->swap_axes) - swap(obj->x, obj->y); - if (axis_align->flip_x) obj->x = sensor->max_x - obj->x; if (axis_align->flip_y) obj->y = sensor->max_y - obj->y; + if (axis_align->swap_axes) + swap(obj->x, obj->y); + /* * Here checking if X offset or y offset are specified is * redundant. We just add the offsets or clip the values. @@ -120,15 +120,15 @@ void rmi_2d_sensor_rel_report(struct rmi_2d_sensor *sensor, int x, int y) x = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)x)); y = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)y)); - if (axis_align->swap_axes) - swap(x, y); - if (axis_align->flip_x) x = min(RMI_2D_REL_POS_MAX, -x); if (axis_align->flip_y) y = min(RMI_2D_REL_POS_MAX, -y); + if (axis_align->swap_axes) + swap(x, y); + if (x || y) { input_report_rel(sensor->input, REL_X, x); input_report_rel(sensor->input, REL_Y, y); @@ -141,17 +141,10 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor) struct input_dev *input = sensor->input; int res_x; int res_y; + int max_x, max_y; int input_flags = 0; if (sensor->report_abs) { - if (sensor->axis_align.swap_axes) { - swap(sensor->max_x, sensor->max_y); - swap(sensor->axis_align.clip_x_low, - sensor->axis_align.clip_y_low); - swap(sensor->axis_align.clip_x_high, - sensor->axis_align.clip_y_high); - } - sensor->min_x = sensor->axis_align.clip_x_low; if (sensor->axis_align.clip_x_high) sensor->max_x = min(sensor->max_x, @@ -163,14 +156,19 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor) sensor->axis_align.clip_y_high); set_bit(EV_ABS, input->evbit); - input_set_abs_params(input, ABS_MT_POSITION_X, 0, sensor->max_x, - 0, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, 0, sensor->max_y, - 0, 0); + + max_x = sensor->max_x; + max_y = sensor->max_y; + if (sensor->axis_align.swap_axes) + swap(max_x, max_y); + input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_x, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_y, 0, 0); if (sensor->x_mm && sensor->y_mm) { res_x = (sensor->max_x - sensor->min_x) / sensor->x_mm; res_y = (sensor->max_y - sensor->min_y) / sensor->y_mm; + if (sensor->axis_align.swap_axes) + swap(res_x, res_y); input_abs_set_res(input, ABS_X, res_x); input_abs_set_res(input, ABS_Y, res_y); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index fc149ea64be795f92616a920dd9ee492291bab74..59aaac43db91f9784edafe7e9a5b2770fed0d98c 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1647,10 +1647,11 @@ static int mxt_parse_object_table(struct mxt_data *data, break; case MXT_TOUCH_MULTI_T9: data->multitouch = MXT_TOUCH_MULTI_T9; + /* Only handle messages from first T9 instance */ data->T9_reportid_min = min_id; - data->T9_reportid_max = max_id; - data->num_touchids = object->num_report_ids - * mxt_obj_instances(object); + data->T9_reportid_max = min_id + + object->num_report_ids - 1; + data->num_touchids = object->num_report_ids; break; case MXT_SPT_MESSAGECOUNT_T44: data->T44_address = object->start_address; diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c index d350f1c19a11dff926abe3e4c090720a23a8b09f..d9c72f47841bd0ece1924d2e0d11b187c259da77 100644 --- a/drivers/input/touchscreen/hxchipset/himax_common.c +++ b/drivers/input/touchscreen/hxchipset/himax_common.c @@ -47,29 +47,23 @@ struct himax_target_report_data *g_target_report_data; static int HX_TOUCH_INFO_POINT_CNT; -unsigned long FW_VER_MAJ_FLASH_ADDR; -unsigned long FW_VER_MIN_FLASH_ADDR; -unsigned long CFG_VER_MAJ_FLASH_ADDR; -unsigned long CFG_VER_MIN_FLASH_ADDR; -unsigned long CID_VER_MAJ_FLASH_ADDR; -unsigned long CID_VER_MIN_FLASH_ADDR; - -unsigned long FW_VER_MAJ_FLASH_LENG; -unsigned long FW_VER_MIN_FLASH_LENG; -unsigned long CFG_VER_MAJ_FLASH_LENG; -unsigned long CFG_VER_MIN_FLASH_LENG; -unsigned long CID_VER_MAJ_FLASH_LENG; -unsigned long CID_VER_MIN_FLASH_LENG; +/* Himax: Set FW and CFG Flash Address */ +#define FW_VER_MAJ_FLASH_ADDR 0x00C005 +#define FW_VER_MIN_FLASH_ADDR 0x00C006 +#define CFG_VER_MAJ_FLASH_ADDR 0x00C100 +#define CFG_VER_MIN_FLASH_ADDR 0x00C101 +#define CID_VER_MAJ_FLASH_ADDR 0x00C002 +#define CID_VER_MIN_FLASH_ADDR 0x00C003 + +#define FW_VER_MAJ_FLASH_LENG 1 +#define FW_VER_MIN_FLASH_LENG 1 +#define CFG_VER_MAJ_FLASH_LENG 1 +#define CFG_VER_MIN_FLASH_LENG 1 +#define CID_VER_MAJ_FLASH_LENG 1 +#define CID_VER_MIN_FLASH_LENG 1 unsigned long FW_CFG_VER_FLASH_ADDR; -#ifdef HX_AUTO_UPDATE_FW - int g_i_FW_VER = 0; - int g_i_CFG_VER = 0; - int g_i_CID_MAJ = 0; /* GUEST ID */ - int g_i_CID_MIN = 0; /* VER for GUEST */ -#endif - unsigned char IC_CHECKSUM; #ifdef HX_ESD_RECOVERY @@ -513,25 +507,32 @@ static int i_update_FW(void) int upgrade_times = 0; unsigned char *ImageBuffer = NULL; int fullFileLength = 0; - uint8_t ret = 0, result = 0; + int ret = 0, result = 0; + uint32_t i_FW_VER = 0, i_CFG_VER = 0; - himax_int_enable(0); - - I("file name = %s\n", i_CTPM_firmware_name); - ret = request_firmware(&i_CTPM_FW, i_CTPM_firmware_name, private_ts->dev); - if (ret < 0) { - E("%s,fail in line%d error code=%d\n", __func__, __LINE__, ret); + D("file name = %s\n", i_CTPM_firmware_name); + if (request_firmware(&i_CTPM_FW, i_CTPM_firmware_name, + private_ts->dev)) { + I("%s: no firmware file\n", __func__); return OPEN_FILE_FAIL; } - if (i_CTPM_FW != NULL) { - fullFileLength = i_CTPM_FW->size; - ImageBuffer = (unsigned char *)i_CTPM_FW->data; - } else { - I("%s: i_CTPM_FW = NULL\n", __func__); - return OPEN_FILE_FAIL; + fullFileLength = i_CTPM_FW->size; + ImageBuffer = (unsigned char *)i_CTPM_FW->data; + + i_FW_VER = (ImageBuffer[FW_VER_MAJ_FLASH_ADDR] << 8) + | ImageBuffer[FW_VER_MIN_FLASH_ADDR]; + i_CFG_VER = (ImageBuffer[CFG_VER_MAJ_FLASH_ADDR] << 8) + | ImageBuffer[CFG_VER_MIN_FLASH_ADDR]; + + if ((ic_data->vendor_fw_ver >= i_FW_VER) + && (ic_data->vendor_config_ver >= i_CFG_VER)) { + D("FW_VER 0x%x, CFG_VER 0x%x\n", i_FW_VER, i_CFG_VER); + release_firmware(i_CTPM_FW); + return 0; } + himax_int_enable(0); update_retry: if (fullFileLength == FW_SIZE_32k) @@ -559,7 +560,7 @@ static int i_update_FW(void) g_core_fp.fp_read_FW_ver(); g_core_fp.fp_touch_information(); result = 1;/* upgrade success */ - I("%s: TP upgrade OK\n", __func__); + D("%s: TP upgrade OK\n", __func__); } #ifdef HX_RST_PIN_FUNC @@ -1618,20 +1619,19 @@ static void himax_finger_report(struct himax_ts_data *ts) g_target_report_data->x[i], g_target_report_data->y[i], g_target_report_data->w[i]); #ifndef HX_PROTOCOL_A input_mt_slot(ts->input_dev, i); + ts->last_slot = i; + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_FINGER, 1); #endif input_report_key(ts->input_dev, BTN_TOUCH, g_target_report_data->finger_on); input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, g_target_report_data->w[i]); - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i); #ifndef HX_PROTOCOL_A input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, g_target_report_data->w[i]); input_report_abs(ts->input_dev, ABS_MT_PRESSURE, g_target_report_data->w[i]); #endif input_report_abs(ts->input_dev, ABS_MT_POSITION_X, g_target_report_data->x[i]); input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, g_target_report_data->y[i]); -#ifndef HX_PROTOCOL_A - ts->last_slot = i; - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); -#else +#ifdef HX_PROTOCOL_A input_mt_sync(ts->input_dev); #endif @@ -1888,15 +1888,14 @@ static const struct t_cable_status_notifier himax_cable_status_handler = { #endif #ifdef HX_AUTO_UPDATE_FW -static void himax_update_register(struct work_struct *work) +void himax_update_register(struct work_struct *work) { - I(" %s in", __func__); + D(" %s in", __func__); if (i_update_FW() <= 0) - I("FW =NOT UPDATE=\n"); + D("FW =NOT UPDATE=\n"); else - I("Have new FW =UPDATE=\n"); - + D("Have new FW =UPDATE=\n"); } #endif @@ -2009,29 +2008,11 @@ int himax_chip_common_init(void) if (pdata->virtual_key) ts->button = pdata->virtual_key; -#ifdef HX_AUTO_UPDATE_FW - auto_update_flag = (!g_core_fp.fp_calculateChecksum(false)); - auto_update_flag |= g_core_fp.fp_flash_lastdata_check(); - if (auto_update_flag) - goto FW_force_upgrade; -#endif g_core_fp.fp_read_FW_ver(); #ifdef HX_AUTO_UPDATE_FW -FW_force_upgrade: - auto_update_flag |= ((ic_data->vendor_fw_ver < g_i_FW_VER) || (ic_data->vendor_config_ver < g_i_CFG_VER)); - /* Not sure to do */ - /* auto_update_flag |= ((ic_data->vendor_cid_maj_ver != g_i_CID_MAJ) || (ic_data->vendor_cid_min_ver < g_i_CID_MIN)); */ - if (auto_update_flag) { - ts->himax_update_wq = create_singlethread_workqueue("HMX_update_request"); - if (!ts->himax_update_wq) { - E(" allocate syn_update_wq failed\n"); - err = -ENOMEM; - goto err_update_wq_failed; - } - INIT_DELAYED_WORK(&ts->work_update, himax_update_register); - queue_delayed_work(ts->himax_update_wq, &ts->work_update, msecs_to_jiffies(2000)); - } + queue_delayed_work(ts->himax_update_wq, &ts->work_update, + msecs_to_jiffies(2000)); #endif #ifdef HX_ZERO_FLASH auto_update_flag = true; @@ -2136,12 +2117,7 @@ int himax_chip_common_init(void) E(" %s: debug initial failed!\n", __func__); #endif -#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) - - if (auto_update_flag) - himax_int_enable(0); -#endif return 0; err_register_interrupt_failed: remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); @@ -2162,7 +2138,7 @@ remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); cancel_delayed_work_sync(&ts->work_update); destroy_workqueue(ts->himax_update_wq); } -err_update_wq_failed: + #endif error_ic_detect_failed: @@ -2240,7 +2216,7 @@ void himax_chip_common_deinit(void) kfree(hx_touch_data); kfree(ic_data); kfree(ts->pdata); - kfree(ts->report_i2c_data); + kfree(ts->i2c_data); kfree(ts); probe_fail_flag = 0; } diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h index dc88efb0d57785e529be285b9650e321d4484060..8830e2c0fc1690331d2e4f14385b001ecc1e5102 100644 --- a/drivers/input/touchscreen/hxchipset/himax_common.h +++ b/drivers/input/touchscreen/hxchipset/himax_common.h @@ -66,7 +66,7 @@ #define HX_RST_PIN_FUNC #define HX_RESUME_SEND_CMD #define HX_ESD_RECOVERY -/*#define HX_AUTO_UPDATE_FW*/ +#define HX_AUTO_UPDATE_FW /*#define HX_SMART_WAKEUP*/ /*#define HX_GESTURE_TRACK*/ /*#define HX_HIGH_SENSE*/ @@ -365,7 +365,7 @@ struct himax_ts_data { struct work_struct ito_test_work; #endif - uint8_t *report_i2c_data; + uint8_t *i2c_data; /* for I2C DMA transfer */ }; struct himax_debug { @@ -439,14 +439,6 @@ extern struct himax_core_fp g_core_fp; extern struct himax_debug *debug_data; extern uint8_t HX_PROC_SEND_FLAG; -#ifdef HX_AUTO_UPDATE_FW -extern int g_i_FW_VER; -extern int g_i_CFG_VER; -extern int g_i_CID_MAJ; /* GUEST ID */ -extern int g_i_CID_MIN; /* VER for GUEST */ -extern unsigned char i_CTPM_FW[]; -#endif - extern unsigned long FW_VER_MAJ_FLASH_ADDR; extern unsigned long FW_VER_MIN_FLASH_ADDR; extern unsigned long CFG_VER_MAJ_FLASH_ADDR; @@ -496,5 +488,7 @@ extern struct himax_target_report_data *g_target_report_data; extern int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status); /* ts_work about end */ +void himax_update_register(struct work_struct *work); + #endif diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c index 14604dc1eb95cc15abb2295f7ce3cff5bd7256e9..bc927f87e3e1f345d2105308f4b9787f995c3750 100644 --- a/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c +++ b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c @@ -188,26 +188,6 @@ static void hx83112_chip_init(void) private_ts->chip_cell_type = CHIP_IS_IN_CELL; D("%s:IC cell type = %d\n", __func__, private_ts->chip_cell_type); IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; - /* Himax: Set FW and CFG Flash Address */ - FW_VER_MAJ_FLASH_ADDR = 49157; /* 0x00C005 */ - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 49158; /* 0x00C006 */ - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 49408; /* 0x00C100 */ - CFG_VER_MAJ_FLASH_LENG = 1; - CFG_VER_MIN_FLASH_ADDR = 49409; /* 0x00C101 */ - CFG_VER_MIN_FLASH_LENG = 1; - CID_VER_MAJ_FLASH_ADDR = 49154; /* 0x00C002 */ - CID_VER_MAJ_FLASH_LENG = 1; - CID_VER_MIN_FLASH_ADDR = 49155; /* 0x00C003 */ - CID_VER_MIN_FLASH_LENG = 1; - -#ifdef HX_AUTO_UPDATE_FW - g_i_FW_VER = (i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR] << 8) | i_CTPM_FW[FW_VER_MIN_FLASH_ADDR]; - g_i_CFG_VER = (i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR] << 8) | i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR]; - g_i_CID_MAJ = i_CTPM_FW[CID_VER_MAJ_FLASH_ADDR]; - g_i_CID_MIN = i_CTPM_FW[CID_VER_MIN_FLASH_ADDR]; -#endif } #ifdef CONFIG_CHIP_DTCFG diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c index 353f064f2731726ff9de96a51879603dcca46483..e1ea6a47f43915efa2a81698c8890fe4b727e4c9 100644 --- a/drivers/input/touchscreen/hxchipset/himax_platform.c +++ b/drivers/input/touchscreen/hxchipset/himax_platform.c @@ -16,6 +16,7 @@ #include "himax_platform.h" #include "himax_common.h" +#include "himax_ic_core.h" int i2c_error_count; int irq_enable_count; @@ -172,7 +173,7 @@ int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRe int retry; bool reallocate = false; struct himax_ts_data *ts = private_ts; - uint8_t *buf = ts->report_i2c_data; + uint8_t *buf = ts->i2c_data; struct i2c_client *client = ts->client; struct i2c_msg msg[] = { { @@ -189,7 +190,7 @@ int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRe } }; - if (length > HX_REPORT_SZ) { + if (length > FLASH_RW_MAX_LEN) { W("%s: data length too large %d!\n", __func__, length); buf = kmalloc(length + HX_CMD_BYTE, GFP_KERNEL); if (!buf) { @@ -233,7 +234,7 @@ int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toR int retry; bool reallocate = false; struct himax_ts_data *ts = private_ts; - uint8_t *buf = ts->report_i2c_data; + uint8_t *buf = ts->i2c_data; struct i2c_client *client = ts->client; struct i2c_msg msg[] = { { @@ -244,7 +245,7 @@ int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toR } }; - if (length > HX_REPORT_SZ) { + if (length > FLASH_RW_MAX_LEN) { W("%s: data length too large %d!\n", __func__, length); buf = kmalloc(length + HX_CMD_BYTE, GFP_KERNEL); if (!buf) { @@ -253,6 +254,7 @@ int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toR return -EIO; } reallocate = true; + msg[0].buf = buf; } mutex_lock(&ts->rw_lock); @@ -291,7 +293,7 @@ int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry) int retry; bool reallocate = false; struct himax_ts_data *ts = private_ts; - uint8_t *buf = ts->report_i2c_data; + uint8_t *buf = ts->i2c_data; struct i2c_client *client = private_ts->client; struct i2c_msg msg[] = { { @@ -302,7 +304,7 @@ int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry) } }; - if (length > HX_REPORT_SZ) { + if (length > FLASH_RW_MAX_LEN) { W("%s: data length too large %d!\n", __func__, length); buf = kmalloc(length, GFP_KERNEL); if (!buf) { @@ -310,6 +312,7 @@ int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry) return -EIO; } reallocate = true; + msg[0].buf = buf; } mutex_lock(&ts->rw_lock); @@ -723,13 +726,10 @@ int drm_notifier_callback(struct notifier_block *self, D("DRM %s\n", __func__); - if (evdata->data && event == MSM_DRM_EVENT_BLANK && ts && ts->client) { + if (evdata->data && event == MSM_DRM_EARLY_EVENT_BLANK && ts && + ts->client) { blank = evdata->data; - switch (*blank) { - case MSM_DRM_BLANK_UNBLANK: - himax_common_resume(&ts->client->dev); - break; case MSM_DRM_BLANK_POWERDOWN: if (!ts->initialized) return -ECANCELED; @@ -738,6 +738,15 @@ int drm_notifier_callback(struct notifier_block *self, } } + if (evdata->data && event == MSM_DRM_EVENT_BLANK && ts && ts->client) { + blank = evdata->data; + switch (*blank) { + case MSM_DRM_BLANK_UNBLANK: + himax_common_resume(&ts->client->dev); + break; + } + } + return 0; } @@ -801,11 +810,11 @@ int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_i mutex_init(&ts->rw_lock); private_ts = ts; - ts->report_i2c_data = kmalloc(HX_REPORT_SZ + HX_CMD_BYTE, GFP_KERNEL); - if (ts->report_i2c_data == NULL) { - E("%s: allocate report_i2c_data failed\n", __func__); + ts->i2c_data = kmalloc(FLASH_RW_MAX_LEN + HX_CMD_BYTE, GFP_KERNEL); + if (ts->i2c_data == NULL) { + E("%s: allocate i2c_data failed\n", __func__); ret = -ENOMEM; - goto err_report_i2c_data; + goto err_alloc_i2c_data; } /* @@ -819,11 +828,20 @@ int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_i goto err_fb_notify_reg_failed; #endif +#ifdef HX_AUTO_UPDATE_FW + ts->himax_update_wq = + create_singlethread_workqueue("HMX_update_request"); + if (!ts->himax_update_wq) { + E(" allocate syn_update_wq failed\n"); + goto err_fb_notify_reg_failed; + } + INIT_DELAYED_WORK(&ts->work_update, himax_update_register); +#endif return ret; err_fb_notify_reg_failed: - kfree(ts->report_i2c_data); -err_report_i2c_data: + kfree(ts->i2c_data); +err_alloc_i2c_data: kfree(ts); err_alloc_data_failed: err_check_functionality_failed: diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c index eeaf6ff035974c836668a0aaec55fb4bd0f05965..fc54e044fecef7be51d394a0ce92620cfe14a529 100644 --- a/drivers/input/touchscreen/rohm_bu21023.c +++ b/drivers/input/touchscreen/rohm_bu21023.c @@ -304,7 +304,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf, msg[1].len = len; msg[1].buf = buf; - i2c_lock_adapter(adap); + i2c_lock_bus(adap, I2C_LOCK_SEGMENT); for (i = 0; i < 2; i++) { if (__i2c_transfer(adap, &msg[i], 1) < 0) { @@ -313,7 +313,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf, } } - i2c_unlock_adapter(adap); + i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); return ret; } diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c index 740ccfe5d3071debdc9dc96829d13ea87ead17c1..5fa4cf353b140316a11267db6524920af0ec3bab 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c @@ -4643,14 +4643,21 @@ static int synaptics_rmi4_dsi_panel_notifier_cb(struct notifier_block *self, return 0; if (evdata && evdata->data && rmi4_data) { - if (event == MSM_DRM_EVENT_BLANK) { + if (event == MSM_DRM_EARLY_EVENT_BLANK) { transition = *(int *)evdata->data; if (transition == MSM_DRM_BLANK_POWERDOWN) { if (rmi4_data->initialized) synaptics_rmi4_suspend( &rmi4_data->pdev->dev); rmi4_data->fb_ready = false; - } else if (transition == MSM_DRM_BLANK_UNBLANK) { + } + } + } + + if (evdata && evdata->data && rmi4_data) { + if (event == MSM_DRM_EVENT_BLANK) { + transition = *(int *)evdata->data; + if (transition == MSM_DRM_BLANK_UNBLANK) { if (rmi4_data->initialized) synaptics_rmi4_resume( &rmi4_data->pdev->dev); diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 97a147ee94154e2ab502dc362d1f4521614c9db4..a0320bf64804a38bdb0b48b4dc89d8ca84920638 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -361,6 +361,16 @@ config ARM_SMMU_V3 Say Y here if your system includes an IOMMU device implementing the ARM SMMUv3 architecture. +config ARM_SMMU_SELFTEST + bool "ARM SMMU self test support" + depends on ARM_SMMU + help + Enables self tests for arm smmu. Tests basic hardware + configurations like interrupts. Note that enabling this + option can marginally increase the boot time. + + If unsure, say N here. + config QCOM_LAZY_MAPPING bool "Reference counted iommu-mapping support" depends on ION diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 10190e361a13db31135f3a7c44cc60a8ea1a6135..01746e7b90de27cf7150a004fae193234a94fa1e 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2400,9 +2400,9 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, } if (amd_iommu_unmap_flush) { - dma_ops_free_iova(dma_dom, dma_addr, pages); domain_flush_tlb(&dma_dom->domain); domain_flush_complete(&dma_dom->domain); + dma_ops_free_iova(dma_dom, dma_addr, pages); } else { pages = __roundup_pow_of_two(pages); queue_iova(&dma_dom->iovad, dma_addr >> PAGE_SHIFT, pages, 0); diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index fa58f40607518a702f00e5d147b79629a4e5e0e1..56135f4525cac65c722b402128479dc645f65e56 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1272,6 +1272,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) /* Sync our overflow flag, as we believe we're up to speed */ q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); + writel(q->cons, q->cons_reg); return IRQ_HANDLED; } diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index bdc5e032b7831ed2fa98241fdec5796c5e5871f3..508342cac5724720cf3779b6bb0bd2c5821b7524 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include @@ -525,6 +527,108 @@ static bool arm_smmu_opt_hibernation(struct arm_smmu_device *smmu) return IS_ENABLED(CONFIG_HIBERNATION); } +#ifdef CONFIG_ARM_SMMU_SELFTEST + +static int selftest; +module_param_named(selftest, selftest, int, 0644); +static int irq_count; + +static DECLARE_WAIT_QUEUE_HEAD(wait_int); +static irqreturn_t arm_smmu_cf_selftest(int irq, void *cb_base) +{ + u32 fsr; + struct irq_data *irq_data = irq_get_irq_data(irq); + unsigned long hwirq = ULONG_MAX; + + fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); + + irq_count++; + if (irq_data) + hwirq = irq_data->hwirq; + pr_info("Interrupt (irq:%d hwirq:%ld) received, fsr:0x%x\n", + irq, hwirq, fsr); + + writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR); + + wake_up(&wait_int); + return IRQ_HANDLED; +} + +static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) +{ + int cb; + int cb_count = 0; + + if (!selftest) + return; + + if (arm_smmu_is_static_cb(smmu)) + return; + + cb = smmu->num_s2_context_banks; + + if (smmu->version < ARM_SMMU_V2) + return; + + for_each_clear_bit_from(cb, smmu->context_map, + smmu->num_context_banks) { + int irq; + int ret; + void *cb_base; + u32 reg; + u32 reg_orig; + int irq_cnt; + + irq = smmu->irqs[smmu->num_global_irqs + cb]; + cb_base = ARM_SMMU_CB(smmu, cb); + + ret = devm_request_threaded_irq(smmu->dev, irq, NULL, + arm_smmu_cf_selftest, + IRQF_ONESHOT | IRQF_SHARED, + "arm-smmu-context-fault", cb_base); + if (ret < 0) { + dev_err(smmu->dev, + "Failed to request cntx IRQ %d (%u)\n", + cb, irq); + continue; + } + + cb_count++; + irq_cnt = irq_count; + + reg_orig = readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR); + reg = reg_orig | SCTLR_CFIE | SCTLR_CFRE; + + writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR); + dev_info(smmu->dev, "Testing cntx %d irq %d\n", cb, irq); + + /* Make sure ARM_SMMU_CB_SCTLR is configured */ + wmb(); + writel_relaxed(FSR_TF, cb_base + ARM_SMMU_CB_FSRRESTORE); + + wait_event_timeout(wait_int, (irq_count > irq_cnt), + msecs_to_jiffies(1000)); + + /* Make sure ARM_SMMU_CB_FSRRESTORE is written to */ + wmb(); + writel_relaxed(reg_orig, cb_base + ARM_SMMU_CB_SCTLR); + devm_free_irq(smmu->dev, irq, cb_base); + } + + dev_info(smmu->dev, + "Interrupt selftest completed...\n"); + dev_info(smmu->dev, + "Tested %d contexts, received %d interrupts\n", + cb_count, irq_count); + WARN_ON(cb_count != irq_count); + irq_count = 0; +} +#else +static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) +{ +} +#endif + /* * init() * Hook for additional device tree parsing at probe time. @@ -4711,12 +4815,15 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) if (err) goto out_power_off; - if (smmu->version == ARM_SMMU_V2 && - smmu->num_context_banks != smmu->num_context_irqs) { - dev_err(dev, - "found %d context interrupt(s) but have %d context banks. assuming %d context interrupts.\n", - smmu->num_context_irqs, smmu->num_context_banks, - smmu->num_context_banks); + if (smmu->version == ARM_SMMU_V2) { + if (smmu->num_context_banks > smmu->num_context_irqs) { + dev_err(dev, + "found %d context irq(s) but have %d context banks. assuming %d context interrupts.\n", + smmu->num_context_irqs, smmu->num_context_banks, + smmu->num_context_banks); + } + + /* Ignore superfluous interrupts */ smmu->num_context_irqs = smmu->num_context_banks; } @@ -4748,6 +4855,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, smmu); arm_smmu_device_reset(smmu); arm_smmu_test_smr_masks(smmu); + arm_smmu_interrupt_selftest(smmu); arm_smmu_power_off(smmu->pwr); /* diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index e3dbb6101b4a78fae47a093ddb2c365e4cb3d7af..c0d1c4db5794482c384b4bb6a5f5bd0dde1dab50 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1336,8 +1336,8 @@ void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, qi_submit_sync(&desc, iommu); } -void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep, - u64 addr, unsigned mask) +void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid, + u16 qdep, u64 addr, unsigned mask) { struct qi_desc desc; @@ -1352,7 +1352,7 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep, qdep = 0; desc.low = QI_DEV_IOTLB_SID(sid) | QI_DEV_IOTLB_QDEP(qdep) | - QI_DIOTLB_TYPE; + QI_DIOTLB_TYPE | QI_DEV_IOTLB_PFSID(pfsid); qi_submit_sync(&desc, iommu); } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index e8414bcf83904422be5aa819d41d9dd834d6d290..aaf3fed9747712500a3b7fe564beec81aaf422c5 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -422,6 +422,7 @@ struct device_domain_info { struct list_head global; /* link to global list */ u8 bus; /* PCI bus number */ u8 devfn; /* PCI devfn number */ + u16 pfsid; /* SRIOV physical function source ID */ u8 pasid_supported:3; u8 pasid_enabled:1; u8 pri_supported:1; @@ -1502,6 +1503,20 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info) return; pdev = to_pci_dev(info->dev); + /* For IOMMU that supports device IOTLB throttling (DIT), we assign + * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge + * queue depth at PF level. If DIT is not set, PFSID will be treated as + * reserved, which should be set to 0. + */ + if (!ecap_dit(info->iommu->ecap)) + info->pfsid = 0; + else { + struct pci_dev *pf_pdev; + + /* pdev will be returned if device is not a vf */ + pf_pdev = pci_physfn(pdev); + info->pfsid = PCI_DEVID(pf_pdev->bus->number, pf_pdev->devfn); + } #ifdef CONFIG_INTEL_IOMMU_SVM /* The PCIe spec, in its wisdom, declares that the behaviour of @@ -1567,7 +1582,8 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, sid = info->bus << 8 | info->devfn; qdep = info->ats_qdep; - qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask); + qi_flush_dev_iotlb(info->iommu, sid, info->pfsid, + qdep, addr, mask); } spin_unlock_irqrestore(&device_domain_lock, flags); } diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 6961fc393f0b25828f5981fad35ea744c7768b41..29b7a6755fcdaabfee66f9444b8193d4b6400cf6 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -192,6 +192,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, { struct io_pgtable_cfg *cfg = &data->iop.cfg; struct device *dev = cfg->iommu_dev; + phys_addr_t phys; dma_addr_t dma; size_t size = ARM_V7S_TABLE_SIZE(lvl); void *table = NULL; @@ -200,6 +201,10 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, table = (void *)__get_dma_pages(__GFP_ZERO, get_order(size)); else if (lvl == 2) table = kmem_cache_zalloc(data->l2_tables, gfp | GFP_DMA); + phys = virt_to_phys(table); + if (phys != (arm_v7s_iopte)phys) + /* Doesn't fit in PTE */ + goto out_free; if (table && !(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)) { dma = dma_map_single(dev, table, size, DMA_TO_DEVICE); if (dma_mapping_error(dev, dma)) @@ -209,7 +214,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, * address directly, so if the DMA layer suggests otherwise by * translating or truncating them, that bodes very badly... */ - if (dma != virt_to_phys(table)) + if (dma != phys) goto out_unmap; } kmemleak_ignore(table); diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 195d6e93ac7185aa53ee075521faf0de56ec53bf..5d0ba5f644c48ca89910102b01c8362fd0b796cf 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -54,7 +54,7 @@ struct ipmmu_vmsa_domain { struct io_pgtable_ops *iop; unsigned int context_id; - spinlock_t lock; /* Protects mappings */ + struct mutex mutex; /* Protects mappings */ }; struct ipmmu_vmsa_iommu_priv { @@ -523,7 +523,7 @@ static struct iommu_domain *__ipmmu_domain_alloc(unsigned type) if (!domain) return NULL; - spin_lock_init(&domain->lock); + mutex_init(&domain->mutex); return &domain->io_domain; } @@ -548,7 +548,6 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain, struct iommu_fwspec *fwspec = dev->iommu_fwspec; struct ipmmu_vmsa_device *mmu = priv->mmu; struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain); - unsigned long flags; unsigned int i; int ret = 0; @@ -557,7 +556,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain, return -ENXIO; } - spin_lock_irqsave(&domain->lock, flags); + mutex_lock(&domain->mutex); if (!domain->mmu) { /* The domain hasn't been used yet, initialize it. */ @@ -574,7 +573,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain, } else dev_info(dev, "Reusing IPMMU context %u\n", domain->context_id); - spin_unlock_irqrestore(&domain->lock, flags); + mutex_unlock(&domain->mutex); if (ret < 0) return ret; diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 04f4d51ffacb1e50ae3f87f04fd3b23306f7b55b..92c8c83ce38c3624359c1906d5a649641c02d81a 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -395,20 +395,15 @@ static int msm_iommu_add_device(struct device *dev) struct msm_iommu_dev *iommu; struct iommu_group *group; unsigned long flags; - int ret = 0; spin_lock_irqsave(&msm_iommu_lock, flags); - iommu = find_iommu_for_dev(dev); + spin_unlock_irqrestore(&msm_iommu_lock, flags); + if (iommu) iommu_device_link(&iommu->iommu, dev); else - ret = -ENODEV; - - spin_unlock_irqrestore(&msm_iommu_lock, flags); - - if (ret) - return ret; + return -ENODEV; group = iommu_group_get_for_dev(dev); if (IS_ERR(group)) @@ -425,13 +420,12 @@ static void msm_iommu_remove_device(struct device *dev) unsigned long flags; spin_lock_irqsave(&msm_iommu_lock, flags); - iommu = find_iommu_for_dev(dev); + spin_unlock_irqrestore(&msm_iommu_lock, flags); + if (iommu) iommu_device_unlink(&iommu->iommu, dev); - spin_unlock_irqrestore(&msm_iommu_lock, flags); - iommu_group_remove_device(dev); } diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index bd67e1b2c64eadf25f5b10d120cf1214b120b54f..57960cb5e04552f01b9d23cfe5e380c8e5004eb2 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -529,7 +529,7 @@ static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, pte_ready: iopte = iopte_offset(iopgd, da); - *pt_dma = virt_to_phys(iopte); + *pt_dma = iopgd_page_paddr(iopgd); dev_vdbg(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n", __func__, da, iopgd, *iopgd, iopte, *iopte); @@ -717,7 +717,7 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da) } bytes *= nent; memset(iopte, 0, nent * sizeof(*iopte)); - pt_dma = virt_to_phys(iopte); + pt_dma = iopgd_page_paddr(iopgd); flush_iopte_range(obj->dev, pt_dma, pt_offset, nent); /* diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index 55cfb986225be79386b3d6487b953ff63ca4ab59..0b9a8b709abf892a8af5f3cf82cbde5a344f0182 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -217,6 +217,7 @@ static int bcm7038_l1_set_affinity(struct irq_data *d, return 0; } +#ifdef CONFIG_SMP static void bcm7038_l1_cpu_offline(struct irq_data *d) { struct cpumask *mask = irq_data_get_affinity_mask(d); @@ -241,6 +242,7 @@ static void bcm7038_l1_cpu_offline(struct irq_data *d) } irq_set_affinity_locked(d, &new_affinity, false); } +#endif static int __init bcm7038_l1_init_one(struct device_node *dn, unsigned int idx, @@ -293,7 +295,9 @@ static struct irq_chip bcm7038_l1_irq_chip = { .irq_mask = bcm7038_l1_mask, .irq_unmask = bcm7038_l1_unmask, .irq_set_affinity = bcm7038_l1_set_affinity, +#ifdef CONFIG_SMP .irq_cpu_offline = bcm7038_l1_cpu_offline, +#endif }; static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq, diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig index 5d9a9b82544f0d6bf58c4efa7972db1e70c753cd..c9ae98ba2636620ab8ac44f65b2e67acca1a3d34 100644 --- a/drivers/irqchip/qcom/Kconfig +++ b/drivers/irqchip/qcom/Kconfig @@ -31,6 +31,16 @@ config QTI_PDC_SDMMAGPIE the wakeup interrupts. Enable it when ARCH_SDMMAGPIE is selected. +config QTI_PDC_SDXPRAIRIE + bool "QTI PDC SDXPRAIRIE" + select QTI_PDC + default y if ARCH_SDXPRAIRIE + help + QTI Power Domain Controller for SDXPRAIRIE + This is used for managing and configuring + the wakeup interrupts. Enable it when + ARCH_SDXPRAIRIE is selected. + config QTI_MPM bool "QTI MPM" depends on ARCH_QCOM diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile index 9ab6c8543f836bba2981519d43309730b0b4c86e..13455731eae69d9a59b590f5cf9b9a1282c7775a 100644 --- a/drivers/irqchip/qcom/Makefile +++ b/drivers/irqchip/qcom/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_QTI_PDC) += pdc.o obj-$(CONFIG_QTI_PDC_SM8150) += pdc-sm8150.o obj-$(CONFIG_QTI_PDC_SM6150) += pdc-sm6150.o obj-$(CONFIG_QTI_PDC_SDMMAGPIE) += pdc-sdmmagpie.o +obj-$(CONFIG_QTI_PDC_SDXPRAIRIE) += pdc-sdxprairie.o obj-$(CONFIG_QTI_MPM) += mpm.o obj-$(CONFIG_QTI_MPM) += mpm.o mpm-8937.o mpm-qcs405.o diff --git a/drivers/irqchip/qcom/pdc-sdxprairie.c b/drivers/irqchip/qcom/pdc-sdxprairie.c new file mode 100644 index 0000000000000000000000000000000000000000..b89237e83e89ae980a259c9f79de503af0fc7350 --- /dev/null +++ b/drivers/irqchip/qcom/pdc-sdxprairie.c @@ -0,0 +1,78 @@ +/* Copyright (c) 2018, 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 "pdc.h" + +static struct pdc_pin sdxprairie_data[] = { + {0, 179}, /* rpmh_wake */ + {1, 180}, /* ee0_apps_hlos_spmi_periph_irq */ + {2, 181}, /* ee1_apps_trustzone_spmi_periph_irq */ + {3, 182}, /* secure_wdog_expired */ + {4, 183}, /* secure_wdog_bark_irq */ + {5, 184}, /* aop_wdog_expired_irq */ + {6, 185}, /* spmi_vgis_irq_to_APPS */ + {7, 186}, /* not-connected */ + {8, 187}, /* aoss_pmic_arb_mpu_xpu_summary_irq */ + {9, 188}, /* rpmh_wake */ + {10, 189}, /* eud_p1_dpse_int_mx */ + {11, 190}, /* eud_p1_dmse_int_mx */ + {12, 191}, /* pdc_apps_epcb_timeout_summary_irq */ + {13, 192}, /* spmi_protocol_irq */ + {14, 193}, /* tsense0_tsense_max_min_int */ + {15, 194}, /* not-connected */ + {16, 195}, /* tsense0_tsense_upper_lower_int */ + {17, 196}, /* not-connected */ + {18, 197}, /* tsense0_tsense_critical_int */ + {19, 198}, /* eud_int_mx[4] */ + {20, 199}, /* apps_pdc.gp_irq_mux[0] */ + {21, 200}, /* apps_pdc.gp_irq_mux[1] */ + {22, 201}, /* apps_pdc.gp_irq_mux[2] */ + {23, 202}, /* apps_pdc.gp_irq_mux[3] */ + {24, 203}, /* apps_pdc.gp_irq_mux[4] */ + {25, 204}, /* apps_pdc.gp_irq_mux[5] */ + {26, 205}, /* apps_pdc.gp_irq_mux[6] */ + {27, 206}, /* apps_pdc.gp_irq_mux[7] */ + {28, 207}, /* apps_pdc.gp_irq_mux[8] */ + {29, 208}, /* apps_pdc.gp_irq_mux[9] */ + {30, 209}, /* apps_pdc.gp_irq_mux[10] */ + {31, 210}, /* apps_pdc.gp_irq_mux[11] */ + {32, 211}, /* apps_pdc.gp_irq_mux[12] */ + {33, 212}, /* apps_pdc.gp_irq_mux[13] */ + {34, 213}, /* apps_pdc.gp_irq_mux[14] */ + {35, 214}, /* apps_pdc.gp_irq_mux[15] */ + {36, 215}, /* apps_pdc.gp_irq_mux[16] */ + {37, 216}, /* apps_pdc.gp_irq_mux[17] */ + {38, 217}, /* apps_pdc.gp_irq_mux[18] */ + {39, 218}, /* apps_pdc.gp_irq_mux[19] */ + {40, 219}, /* apps_pdc.gp_irq_mux[20] */ + {41, 220}, /* apps_pdc.gp_irq_mux[21] */ + {42, 221}, /* apps_pdc.gp_irq_mux[22] */ + {43, 222}, /* apps_pdc.gp_irq_mux[23] */ + {44, 223}, /* apps_pdc.gp_irq_mux[24] */ + {45, 224}, /* apps_pdc.gp_irq_mux[25] */ + {46, 225}, /* apps_pdc.gp_irq_mux[26] */ + {47, 226}, /* apps_pdc.gp_irq_mux[27] */ + {48, 227}, /* apps_pdc.gp_irq_mux[28] */ + {49, 228}, /* apps_pdc.gp_irq_mux[29] */ + {50, 229}, /* apps_pdc.gp_irq_mux[30] */ + {51, 230}, /* apps_pdc.gp_irq_mux[31] */ + {-1}, +}; + +static int __init qcom_pdc_gic_init(struct device_node *node, + struct device_node *parent) +{ + return qcom_pdc_init(node, parent, sdxprairie_data); +} + +IRQCHIP_DECLARE(pdc_sdxprairie, "qcom,pdc-sdxprairie", qcom_pdc_gic_init); diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index 7b139f45f409709c49f38d1160954ff20dd9653b..2ed08a94f6d2ceb6fd5353c59b9f7b5241e6a2f2 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -188,6 +188,10 @@ enum strobe_type { LPG_STROBE, }; +enum wa_flags { + PM8150L_IRES_WA = BIT(0), +}; + /* * Configurations for each individual LED */ @@ -286,6 +290,7 @@ struct qpnp_flash_led { int num_snodes; int enable; int total_current_ma; + u32 wa_flags; u16 base; bool trigger_lmh; bool trigger_chgr; @@ -1028,7 +1033,12 @@ static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value) break; } } + } else if (prgm_current_ma <= 20 && + (led->wa_flags & PM8150L_IRES_WA)) { + fnode->ires_idx = FLASH_LED_IRES_BASE; + fnode->ires_ua = FLASH_LED_IRES_MIN_UA; } + fnode->current_ma = prgm_current_ma; fnode->cdev.brightness = prgm_current_ma; fnode->current_reg_val = get_current_reg_code(prgm_current_ma, @@ -1927,6 +1937,9 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, led->pdata->pmic_rev_id->pmic_subtype, led->pdata->pmic_rev_id->rev4); + if (led->pdata->pmic_rev_id->pmic_subtype == PM8150L_SUBTYPE) + led->wa_flags |= PM8150L_IRES_WA; + led->pdata->hdrm_auto_mode_en = of_property_read_bool(node, "qcom,hdrm-auto-mode"); diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c index 3f0ddc0d7393fdd477aa82578b43d37034e08e77..3fb65778e03d205df6ccd04a728d9241208ea1c0 100644 --- a/drivers/lightnvm/pblk-core.c +++ b/drivers/lightnvm/pblk-core.c @@ -190,7 +190,6 @@ void pblk_bio_free_pages(struct pblk *pblk, struct bio *bio, int off, WARN_ON(off + nr_pages != bio->bi_vcnt); - bio_advance(bio, off * PBLK_EXPOSED_PAGE_SIZE); for (i = off; i < nr_pages + off; i++) { bv = bio->bi_io_vec[i]; mempool_free(bv.bv_page, pblk->page_bio_pool); diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c index 3ad9e56d2473412ae3ead5b2946066643ebd541c..d89ac573f8d838eca3401f671f558c25df19260b 100644 --- a/drivers/lightnvm/pblk-write.c +++ b/drivers/lightnvm/pblk-write.c @@ -33,6 +33,10 @@ static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd, bio_endio(original_bio); } + if (c_ctx->nr_padded) + pblk_bio_free_pages(pblk, rqd->bio, c_ctx->nr_valid, + c_ctx->nr_padded); + #ifdef CONFIG_NVM_DEBUG atomic_long_add(c_ctx->nr_valid, &pblk->sync_writes); #endif @@ -521,7 +525,8 @@ static void pblk_free_write_rqd(struct pblk *pblk, struct nvm_rq *rqd) struct bio *bio = rqd->bio; if (c_ctx->nr_padded) - pblk_bio_free_pages(pblk, bio, rqd->nr_ppas, c_ctx->nr_padded); + pblk_bio_free_pages(pblk, bio, c_ctx->nr_valid, + c_ctx->nr_padded); } static int pblk_submit_write(struct pblk *pblk) diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index c4c2b3b85ebc05f4ceea9c484f674ed40d427b42..f6e040fcad9a4936447fcecd1a49525e6a117468 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -532,8 +532,9 @@ init_pmu(void) int timeout; struct adb_request req; - out_8(&via[B], via[B] | TREQ); /* negate TREQ */ - out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK); /* TACK in, TREQ out */ + /* Negate TREQ. Set TACK to input and TREQ to output. */ + out_8(&via[B], in_8(&via[B]) | TREQ); + out_8(&via[DIRB], (in_8(&via[DIRB]) | TREQ) & ~TACK); pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); timeout = 100000; @@ -1455,8 +1456,8 @@ pmu_sr_intr(void) struct adb_request *req; int bite = 0; - if (via[B] & TREQ) { - printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]); + if (in_8(&via[B]) & TREQ) { + printk(KERN_ERR "PMU: spurious SR intr (%x)\n", in_8(&via[B])); out_8(&via[IFR], SR_INT); return NULL; } diff --git a/drivers/mailbox/mailbox-xgene-slimpro.c b/drivers/mailbox/mailbox-xgene-slimpro.c index a7040163dd43983d26071faec7ac9f815db9b799..b8b2b3533f466badbf0645efda9ea975c460c998 100644 --- a/drivers/mailbox/mailbox-xgene-slimpro.c +++ b/drivers/mailbox/mailbox-xgene-slimpro.c @@ -195,9 +195,9 @@ static int slimpro_mbox_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctx); regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mb_base = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); - if (!mb_base) - return -ENOMEM; + mb_base = devm_ioremap_resource(&pdev->dev, regs); + if (IS_ERR(mb_base)) + return PTR_ERR(mb_base); /* Setup mailbox links */ for (i = 0; i < MBOX_CNT; i++) { diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c index a297ad4c61a22515e57668b4c1d5d9819b422220..da92b1a5ad5894e93bcd56fa1aca2cc912c38251 100644 --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c @@ -104,6 +104,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = { { .compatible = "qcom,msm8996-apcs-hmss-global", .data = (void *)16 }, { .compatible = "qcom,sm8150-apcs-hmss-global", .data = (void *)12 }, { .compatible = "qcom,sm8150-spcs-global", .data = (void *)0 }, + { .compatible = "qcom,sdxprairie-apcs-gcc", .data = (void *)8 }, {} }; MODULE_DEVICE_TABLE(of, qcom_apcs_ipc_of_match); diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 930b00f6a3a2a4b780d7c6ea166b7b36181caf22..5adb0c850b6c0800967c03f85810b74992d99c32 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -456,8 +456,10 @@ static int bch_writeback_thread(void *arg) * data on cache. BCACHE_DEV_DETACHING flag is set in * bch_cached_dev_detach(). */ - if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) + if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) { + up_write(&dc->writeback_lock); break; + } } up_write(&dc->writeback_lock); diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 4a4e9c75fc4cddca59c30df2f18ebaa6f0baaa61..0a5a45f3ec5fcd4dbd471e0a83a3a0694b25af85 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c @@ -362,7 +362,7 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd) disk_super->version = cpu_to_le32(cmd->version); memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name)); memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version)); - disk_super->policy_hint_size = 0; + disk_super->policy_hint_size = cpu_to_le32(0); __copy_sm_root(cmd, disk_super); @@ -700,6 +700,7 @@ static int __commit_transaction(struct dm_cache_metadata *cmd, disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]); disk_super->policy_version[1] = cpu_to_le32(cmd->policy_version[1]); disk_super->policy_version[2] = cpu_to_le32(cmd->policy_version[2]); + disk_super->policy_hint_size = cpu_to_le32(cmd->policy_hint_size); disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits); disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses); @@ -1321,6 +1322,7 @@ static int __load_mapping_v1(struct dm_cache_metadata *cmd, dm_oblock_t oblock; unsigned flags; + bool dirty = true; dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le); memcpy(&mapping, mapping_value_le, sizeof(mapping)); @@ -1331,8 +1333,10 @@ static int __load_mapping_v1(struct dm_cache_metadata *cmd, dm_array_cursor_get_value(hint_cursor, (void **) &hint_value_le); memcpy(&hint, hint_value_le, sizeof(hint)); } + if (cmd->clean_when_opened) + dirty = flags & M_DIRTY; - r = fn(context, oblock, to_cblock(cb), flags & M_DIRTY, + r = fn(context, oblock, to_cblock(cb), dirty, le32_to_cpu(hint), hints_valid); if (r) { DMERR("policy couldn't load cache block %llu", @@ -1360,7 +1364,7 @@ static int __load_mapping_v2(struct dm_cache_metadata *cmd, dm_oblock_t oblock; unsigned flags; - bool dirty; + bool dirty = true; dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le); memcpy(&mapping, mapping_value_le, sizeof(mapping)); @@ -1371,8 +1375,9 @@ static int __load_mapping_v2(struct dm_cache_metadata *cmd, dm_array_cursor_get_value(hint_cursor, (void **) &hint_value_le); memcpy(&hint, hint_value_le, sizeof(hint)); } + if (cmd->clean_when_opened) + dirty = dm_bitset_cursor_get_value(dirty_cursor); - dirty = dm_bitset_cursor_get_value(dirty_cursor); r = fn(context, oblock, to_cblock(cb), dirty, le32_to_cpu(hint), hints_valid); if (r) { diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 71c3507df9a0ee530c2927f1a8ac4a571d3e28fd..a4b7c26980966065836b6446f3825080b9036373 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2330,7 +2330,7 @@ static int parse_features(struct cache_args *ca, struct dm_arg_set *as, {0, 2, "Invalid number of cache feature arguments"}, }; - int r; + int r, mode_ctr = 0; unsigned argc; const char *arg; struct cache_features *cf = &ca->features; @@ -2344,14 +2344,20 @@ static int parse_features(struct cache_args *ca, struct dm_arg_set *as, while (argc--) { arg = dm_shift_arg(as); - if (!strcasecmp(arg, "writeback")) + if (!strcasecmp(arg, "writeback")) { cf->io_mode = CM_IO_WRITEBACK; + mode_ctr++; + } - else if (!strcasecmp(arg, "writethrough")) + else if (!strcasecmp(arg, "writethrough")) { cf->io_mode = CM_IO_WRITETHROUGH; + mode_ctr++; + } - else if (!strcasecmp(arg, "passthrough")) + else if (!strcasecmp(arg, "passthrough")) { cf->io_mode = CM_IO_PASSTHROUGH; + mode_ctr++; + } else if (!strcasecmp(arg, "metadata2")) cf->metadata_version = 2; @@ -2362,6 +2368,11 @@ static int parse_features(struct cache_args *ca, struct dm_arg_set *as, } } + if (mode_ctr > 1) { + *error = "Duplicate cache io_mode features requested"; + return -EINVAL; + } + return 0; } diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 98181028c7e9b4b1b3b6725d1f195c8c544bff10..eedbb31790653f3a55544533d1ce406b650fc3ea 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -3082,11 +3082,11 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits) */ limits->max_segment_size = PAGE_SIZE; - if (cc->sector_size != (1 << SECTOR_SHIFT)) { - limits->logical_block_size = cc->sector_size; - limits->physical_block_size = cc->sector_size; - blk_limits_io_min(limits, cc->sector_size); - } + limits->logical_block_size = + max_t(unsigned short, limits->logical_block_size, cc->sector_size); + limits->physical_block_size = + max_t(unsigned, limits->physical_block_size, cc->sector_size); + limits->io_min = max_t(unsigned, limits->io_min, cc->sector_size); } static struct target_type crypt_target = { diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index cbc56372ff97b7c82337d51bfb9ca8640b0c697d..898286ed47a1004f00e7ff23f9cb29133b0f9aa3 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -177,7 +177,7 @@ struct dm_integrity_c { __u8 sectors_per_block; unsigned char mode; - bool suspending; + int suspending; int failed; @@ -2209,7 +2209,7 @@ static void dm_integrity_postsuspend(struct dm_target *ti) del_timer_sync(&ic->autocommit_timer); - ic->suspending = true; + WRITE_ONCE(ic->suspending, 1); queue_work(ic->commit_wq, &ic->commit_work); drain_workqueue(ic->commit_wq); @@ -2219,7 +2219,7 @@ static void dm_integrity_postsuspend(struct dm_target *ti) dm_integrity_flush_buffers(ic); } - ic->suspending = false; + WRITE_ONCE(ic->suspending, 0); BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress)); diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index cf2c67e35eafe75353e016d48efefd9aadd36291..d4b326914f0687b49bdfc83f3c30ceb60411a493 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c @@ -484,6 +484,8 @@ static int run_complete_job(struct kcopyd_job *job) if (atomic_dec_and_test(&kc->nr_jobs)) wake_up(&kc->destroyq); + cond_resched(); + return 0; } diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 72ae5dc50532ec799b77458e7fba31d2480c23c0..6cf9ad4e4e16446815d86a94f1b946e835bbd317 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2514,6 +2514,8 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) case PM_WRITE: if (old_mode != new_mode) notify_of_pool_mode_change(pool, "write"); + if (old_mode == PM_OUT_OF_DATA_SPACE) + cancel_delayed_work_sync(&pool->no_space_timeout); pool->out_of_data_space = false; pool->pf.error_if_no_space = pt->requested_pf.error_if_no_space; dm_pool_metadata_read_write(pool->pmd); diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 72ce0bccc86553a5ecbf6ffb59d3883f01e3dc0e..717aaffc227dfa942821bebf4133670dbc684d95 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -304,15 +304,6 @@ static void recover_bitmaps(struct md_thread *thread) while (cinfo->recovery_map) { slot = fls64((u64)cinfo->recovery_map) - 1; - /* Clear suspend_area associated with the bitmap */ - spin_lock_irq(&cinfo->suspend_lock); - list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list) - if (slot == s->slot) { - list_del(&s->list); - kfree(s); - } - spin_unlock_irq(&cinfo->suspend_lock); - snprintf(str, 64, "bitmap%04d", slot); bm_lockres = lockres_init(mddev, str, NULL, 1); if (!bm_lockres) { @@ -331,6 +322,16 @@ static void recover_bitmaps(struct md_thread *thread) pr_err("md-cluster: Could not copy data from bitmap %d\n", slot); goto clear_bit; } + + /* Clear suspend_area associated with the bitmap */ + spin_lock_irq(&cinfo->suspend_lock); + list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list) + if (slot == s->slot) { + list_del(&s->list); + kfree(s); + } + spin_unlock_irq(&cinfo->suspend_lock); + if (hi > 0) { if (lo < mddev->recovery_cp) mddev->recovery_cp = lo; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index b20c23f970f494f18d6a4b5b29de8275aef77bc8..262a0f0f8fd5cd9aaa52c75bb4655c7f96b639bd 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3754,6 +3754,13 @@ static int raid10_run(struct mddev *mddev) disk->rdev->saved_raid_disk < 0) conf->fullsync = 1; } + + if (disk->replacement && + !test_bit(In_sync, &disk->replacement->flags) && + disk->replacement->saved_raid_disk < 0) { + conf->fullsync = 1; + } + disk->recovery_disabled = mddev->recovery_disabled - 1; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 07ca2fd10189f2e68cfbf840e95305e49b98c274..5018fb2352c279744913d29b0172946cc7599582 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4516,6 +4516,12 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) s->failed++; if (rdev && !test_bit(Faulty, &rdev->flags)) do_recovery = 1; + else if (!rdev) { + rdev = rcu_dereference( + conf->disks[i].replacement); + if (rdev && !test_bit(Faulty, &rdev->flags)) + do_recovery = 1; + } } if (test_bit(R5_InJournal, &dev->flags)) diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c index 2ab8d83e55768310ed826f3e4e36d07042070633..fcfe658a43288d418c5f56948f19ddd7088fe5da 100644 --- a/drivers/media/dvb-frontends/helene.c +++ b/drivers/media/dvb-frontends/helene.c @@ -897,7 +897,10 @@ static int helene_x_pon(struct helene_priv *priv) helene_write_regs(priv, 0x99, cdata, sizeof(cdata)); /* 0x81 - 0x94 */ - data[0] = 0x18; /* xtal 24 MHz */ + if (priv->xtal == SONY_HELENE_XTAL_16000) + data[0] = 0x10; /* xtal 16 MHz */ + else + data[0] = 0x18; /* xtal 24 MHz */ data[1] = (uint8_t)(0x80 | (0x04 & 0x1F)); /* 4 x 25 = 100uA */ data[2] = (uint8_t)(0x80 | (0x26 & 0x7F)); /* 38 x 0.25 = 9.5pF */ data[3] = 0x80; /* REFOUT signal output 500mVpp */ diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index a31fe18c71d6d7c7fd9278fdde6113c233e08856..2d96c184975936be0de8e2b3e9b7a0e8f9641104 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -510,8 +510,8 @@ static const struct reg_value ov5645_setting_full[] = { }; static const s64 link_freq[] = { - 222880000, - 334320000 + 224000000, + 336000000 }; static const struct ov5645_mode_info ov5645_mode_info_data[] = { @@ -520,7 +520,7 @@ static const struct ov5645_mode_info ov5645_mode_info_data[] = { .height = 960, .data = ov5645_setting_sxga, .data_size = ARRAY_SIZE(ov5645_setting_sxga), - .pixel_clock = 111440000, + .pixel_clock = 112000000, .link_freq = 0 /* an index in link_freq[] */ }, { @@ -528,7 +528,7 @@ static const struct ov5645_mode_info ov5645_mode_info_data[] = { .height = 1080, .data = ov5645_setting_1080p, .data_size = ARRAY_SIZE(ov5645_setting_1080p), - .pixel_clock = 167160000, + .pixel_clock = 168000000, .link_freq = 1 /* an index in link_freq[] */ }, { @@ -536,7 +536,7 @@ static const struct ov5645_mode_info ov5645_mode_info_data[] = { .height = 1944, .data = ov5645_setting_full, .data_size = ARRAY_SIZE(ov5645_setting_full), - .pixel_clock = 167160000, + .pixel_clock = 168000000, .link_freq = 1 /* an index in link_freq[] */ }, }; @@ -1157,7 +1157,8 @@ static int ov5645_probe(struct i2c_client *client, return ret; } - if (xclk_freq != 23880000) { + /* external clock must be 24MHz, allow 1% tolerance */ + if (xclk_freq < 23760000 || xclk_freq > 24240000) { dev_err(dev, "external clock frequency %u is not supported\n", xclk_freq); return -EINVAL; diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index 806383500313e029bcf9bbb14cdbac0f55fcefff..14377af7c888898b2c19e969c2475fe558ebdac3 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -834,7 +834,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, * set COM8 */ if (priv->band_filter) { - ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1); + ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, BNDF_ON_OFF); if (!ret) ret = ov772x_mask_set(client, BDBASE, 0xff, 256 - priv->band_filter); diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 698fa764999c7a0dab55e13ef1cf363c19f45a67..59b0c1fce9be70e7fdc00dd8dfee8d45ef2a2b05 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -871,7 +871,7 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd, f = &format->format; f->width = decoder->rect.width; - f->height = decoder->rect.height; + f->height = decoder->rect.height / 2; f->code = MEDIA_BUS_FMT_UYVY8_2X8; f->field = V4L2_FIELD_ALTERNATE; diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index 0ea8dd44026c34e6772b35c391aa03d15aefeffd..3a06c000f97bbf629c8539002cddb7d869baa850 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -1190,6 +1190,14 @@ int tw686x_video_init(struct tw686x_dev *dev) return err; } + /* Initialize vc->dev and vc->ch for the error path */ + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + + vc->dev = dev; + vc->ch = ch; + } + for (ch = 0; ch < max_channels(dev); ch++) { struct tw686x_video_channel *vc = &dev->video_channels[ch]; struct video_device *vdev; @@ -1198,9 +1206,6 @@ int tw686x_video_init(struct tw686x_dev *dev) spin_lock_init(&vc->qlock); INIT_LIST_HEAD(&vc->vidq_queued); - vc->dev = dev; - vc->ch = ch; - /* default settings */ err = tw686x_set_standard(vc, V4L2_STD_NTSC); if (err) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 56fe4e5b396e1a068ba601deeabe02af053e678c..4a65861433d6862cf0c7e8775e5d71658ecee3fb 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1114,6 +1114,14 @@ static int initialize_vpif(void) return err; } +static void free_vpif_objs(void) +{ + int i; + + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) + kfree(vpif_obj.dev[i]); +} + static int vpif_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd) @@ -1250,11 +1258,6 @@ static __init int vpif_probe(struct platform_device *pdev) return -EINVAL; } - if (!pdev->dev.platform_data) { - dev_warn(&pdev->dev, "Missing platform data. Giving up.\n"); - return -EINVAL; - } - vpif_dev = &pdev->dev; err = initialize_vpif(); @@ -1266,7 +1269,7 @@ static __init int vpif_probe(struct platform_device *pdev) err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); if (err) { v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); - return err; + goto vpif_free; } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { @@ -1309,7 +1312,10 @@ static __init int vpif_probe(struct platform_device *pdev) if (vpif_obj.sd[i]) vpif_obj.sd[i]->grp_id = 1 << i; } - vpif_probe_complete(); + err = vpif_probe_complete(); + if (err) { + goto probe_subdev_out; + } } else { vpif_obj.notifier.subdevs = vpif_obj.config->asd; vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; @@ -1330,6 +1336,8 @@ static __init int vpif_probe(struct platform_device *pdev) kfree(vpif_obj.sd); vpif_unregister: v4l2_device_unregister(&vpif_obj.v4l2_dev); +vpif_free: + free_vpif_objs(); return err; } @@ -1351,8 +1359,8 @@ static int vpif_remove(struct platform_device *device) ch = vpif_obj.dev[i]; /* Unregister video device */ video_unregister_device(&ch->video_dev); - kfree(vpif_obj.dev[i]); } + free_vpif_objs(); return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index 55ba696b8cf40e13339e42234bfd352e8df90520..a920164f53f1f0ab9de8a9947af72ac6cf653c95 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -384,12 +384,17 @@ static void __isp_video_try_fmt(struct fimc_isp *isp, struct v4l2_pix_format_mplane *pixm, const struct fimc_fmt **fmt) { - *fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, 2); + const struct fimc_fmt *__fmt; + + __fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, 2); + + if (fmt) + *fmt = __fmt; pixm->colorspace = V4L2_COLORSPACE_SRGB; pixm->field = V4L2_FIELD_NONE; - pixm->num_planes = (*fmt)->memplanes; - pixm->pixelformat = (*fmt)->fourcc; + pixm->num_planes = __fmt->memplanes; + pixm->pixelformat = __fmt->fourcc; /* * TODO: double check with the docmentation these width/height * constraints are correct. diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index fb43025df57379834a99e1be3d6124c827cd91a9..254d696dffd89058449083df4ed8652696dde24d 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -1417,7 +1417,7 @@ static int viu_of_probe(struct platform_device *op) sizeof(struct viu_reg), DRV_NAME)) { dev_err(&op->dev, "Error while requesting mem region\n"); ret = -EBUSY; - goto err; + goto err_irq; } /* remap registers */ @@ -1425,7 +1425,7 @@ static int viu_of_probe(struct platform_device *op) if (!viu_regs) { dev_err(&op->dev, "Can't map register set\n"); ret = -ENOMEM; - goto err; + goto err_irq; } /* Prepare our private structure */ @@ -1433,7 +1433,7 @@ static int viu_of_probe(struct platform_device *op) if (!viu_dev) { dev_err(&op->dev, "Can't allocate private structure\n"); ret = -ENOMEM; - goto err; + goto err_irq; } viu_dev->vr = viu_regs; @@ -1449,16 +1449,21 @@ static int viu_of_probe(struct platform_device *op) ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev); if (ret < 0) { dev_err(&op->dev, "v4l2_device_register() failed: %d\n", ret); - goto err; + goto err_irq; } ad = i2c_get_adapter(0); + if (!ad) { + ret = -EFAULT; + dev_err(&op->dev, "couldn't get i2c adapter\n"); + goto err_v4l2; + } v4l2_ctrl_handler_init(&viu_dev->hdl, 5); if (viu_dev->hdl.error) { ret = viu_dev->hdl.error; dev_err(&op->dev, "couldn't register control\n"); - goto err_vdev; + goto err_i2c; } /* This control handler will inherit the control(s) from the sub-device(s). */ @@ -1475,7 +1480,7 @@ static int viu_of_probe(struct platform_device *op) vdev = video_device_alloc(); if (vdev == NULL) { ret = -ENOMEM; - goto err_vdev; + goto err_hdl; } *vdev = viu_template; @@ -1496,7 +1501,7 @@ static int viu_of_probe(struct platform_device *op) ret = video_register_device(viu_dev->vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { video_device_release(viu_dev->vdev); - goto err_vdev; + goto err_unlock; } /* enable VIU clock */ @@ -1504,12 +1509,12 @@ static int viu_of_probe(struct platform_device *op) if (IS_ERR(clk)) { dev_err(&op->dev, "failed to lookup the clock!\n"); ret = PTR_ERR(clk); - goto err_clk; + goto err_vdev; } ret = clk_prepare_enable(clk); if (ret) { dev_err(&op->dev, "failed to enable the clock!\n"); - goto err_clk; + goto err_vdev; } viu_dev->clk = clk; @@ -1520,7 +1525,7 @@ static int viu_of_probe(struct platform_device *op) if (request_irq(viu_dev->irq, viu_intr, 0, "viu", (void *)viu_dev)) { dev_err(&op->dev, "Request VIU IRQ failed.\n"); ret = -ENODEV; - goto err_irq; + goto err_clk; } mutex_unlock(&viu_dev->lock); @@ -1528,16 +1533,19 @@ static int viu_of_probe(struct platform_device *op) dev_info(&op->dev, "Freescale VIU Video Capture Board\n"); return ret; -err_irq: - clk_disable_unprepare(viu_dev->clk); err_clk: - video_unregister_device(viu_dev->vdev); + clk_disable_unprepare(viu_dev->clk); err_vdev: - v4l2_ctrl_handler_free(&viu_dev->hdl); + video_unregister_device(viu_dev->vdev); +err_unlock: mutex_unlock(&viu_dev->lock); +err_hdl: + v4l2_ctrl_handler_free(&viu_dev->hdl); +err_i2c: i2c_put_adapter(ad); +err_v4l2: v4l2_device_unregister(&viu_dev->v4l2_dev); -err: +err_irq: irq_dispose_mapping(viu_irq); return ret; } diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c index 24e93f0ad4451795ebf4f6dcb7ca5b5208abb9cb..35bebf960961f55138747231156c145b0b0fee6d 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c @@ -42,25 +42,34 @@ static int cam_context_handle_hw_event(void *context, uint32_t evt_id, int cam_context_shutdown(struct cam_context *ctx) { int rc = 0; - int32_t ctx_hdl = ctx->dev_hdl; + struct cam_release_dev_cmd cmd; mutex_lock(&ctx->ctx_mutex); - if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev) { - rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev( - ctx, NULL); - if (rc < 0) - CAM_ERR(CAM_CORE, "Error while dev stop %d", rc); - } - if (ctx->state_machine[ctx->state].ioctl_ops.release_dev) { - rc = ctx->state_machine[ctx->state].ioctl_ops.release_dev( - ctx, NULL); - if (rc < 0) - CAM_ERR(CAM_CORE, "Error while dev release %d", rc); + if (ctx->state > CAM_CTX_AVAILABLE && ctx->state < CAM_CTX_STATE_MAX) { + cmd.session_handle = ctx->session_hdl; + cmd.dev_handle = ctx->dev_hdl; + rc = cam_context_handle_release_dev(ctx, &cmd); + if (rc) + CAM_ERR(CAM_CORE, + "context release failed for dev_name %s", + ctx->dev_name); + else + cam_context_putref(ctx); + } else { + CAM_WARN(CAM_CORE, + "dev %s context id %u state %d invalid to release hdl", + ctx->dev_name, ctx->ctx_id, ctx->state); + rc = -EINVAL; } mutex_unlock(&ctx->ctx_mutex); - if (!rc) - rc = cam_destroy_device_hdl(ctx_hdl); + rc = cam_destroy_device_hdl(ctx->dev_hdl); + if (rc) + CAM_ERR(CAM_CORE, "destroy device hdl failed for node %s", + ctx->dev_name); + else + ctx->dev_hdl = -1; + return rc; } @@ -448,6 +457,7 @@ int cam_context_handle_start_dev(struct cam_context *ctx, } mutex_lock(&ctx->ctx_mutex); + ctx->last_flush_req = 0; if (ctx->state_machine[ctx->state].ioctl_ops.start_dev) rc = ctx->state_machine[ctx->state].ioctl_ops.start_dev( ctx, cmd); diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h index 003fea6a0df1676425a03bb8e3d54c30247b4e77..cf07d95eb7f6f2a061cc6954d5d5b18769abbdf5 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context.h +++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h @@ -180,6 +180,7 @@ struct cam_ctx_ops { * @refcount: Context object refcount * @node: The main node to which this context belongs * @sync_mutex: mutex to sync with sync cb thread + * @last_flush_req: Last request to flush * */ struct cam_context { @@ -215,6 +216,7 @@ struct cam_context { struct kref refcount; void *node; struct mutex sync_mutex; + uint32_t last_flush_req; }; /** diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c index d78203a9609d23a387dfbc95be0e927ba2750f0b..0098756062bec60b0f10d0a2b5303ba109805aaa 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c @@ -326,6 +326,17 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx, packet = (struct cam_packet *) (packet_addr + cmd->offset); + if (packet->header.request_id <= ctx->last_flush_req) { + CAM_DBG(CAM_CORE, + "request %lld has been flushed, reject packet", + packet->header.request_id); + rc = -EINVAL; + goto free_req; + } + + if (packet->header.request_id > ctx->last_flush_req) + ctx->last_flush_req = 0; + /* preprocess the configuration */ memset(&cfg, 0, sizeof(cfg)); cfg.packet = packet; @@ -811,9 +822,10 @@ int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx, goto end; } - if (cmd->flush_type == CAM_FLUSH_TYPE_ALL) + if (cmd->flush_type == CAM_FLUSH_TYPE_ALL) { + ctx->last_flush_req = cmd->req_id; rc = cam_context_flush_ctx_to_hw(ctx); - else if (cmd->flush_type == CAM_FLUSH_TYPE_REQ) + } else if (cmd->flush_type == CAM_FLUSH_TYPE_REQ) rc = cam_context_flush_req_to_hw(ctx, cmd); else { rc = -EINVAL; diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c index 6584868e418ffdec16555b63018f33770d4c7883..2cc91bf8fb18cb9ff7114bbaa3f7b41e37bf09b9 100644 --- a/drivers/media/platform/msm/camera/cam_core/cam_node.c +++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c @@ -344,6 +344,8 @@ static int __cam_node_handle_release_dev(struct cam_node *node, if (rc) CAM_ERR(CAM_CORE, "destroy device hdl failed for node %s", node->name); + else + ctx->dev_hdl = -1; CAM_DBG(CAM_CORE, "[%s] Release ctx_id=%d, refcount=%d", node->name, ctx->ctx_id, @@ -510,9 +512,6 @@ int cam_node_shutdown(struct cam_node *node) "Node [%s] invoking shutdown on context [%d]", node->name, i); rc = cam_context_shutdown(&(node->ctx_list[i])); - if (rc) - continue; - cam_context_putref(&(node->ctx_list[i])); } } diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c index 7f531fdddd9e959e6ce29a12f663ba240f1f8550..75c0158722bea0461463c7938ae32ac6c48de74a 100644 --- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -405,7 +405,8 @@ static void cam_cpastop_work(struct work_struct *work) if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) && (camnoc_info->irq_err[i].enable)) { irq_type = camnoc_info->irq_err[i].irq_type; - CAM_ERR(CAM_CPAS, "Error occurred, type=%d", irq_type); + CAM_ERR_RATE_LIMIT(CAM_CPAS, + "Error occurred, type=%d", irq_type); memset(&irq_data, 0x0, sizeof(irq_data)); irq_data.irq_type = (enum cam_camnoc_irq_type)irq_type; diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c index 87dc6949de0ca6fe6ba9613bec4b608b24ac6f7b..fdf57bb41ff59825678e746522b91b73e2e68728 100644 --- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c @@ -544,6 +544,10 @@ irqreturn_t cam_fd_hw_irq(int irq_num, void *data) CAM_DBG(CAM_FD, "FD IRQ status 0x%x", reg_value); + cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, + hw_static_info->wrapper_regs.irq_clear, + reg_value); + if (reg_value & CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE)) { complete_all(&fd_core->halt_complete); irq_type = CAM_FD_IRQ_HALT_DONE; @@ -575,10 +579,6 @@ irqreturn_t cam_fd_hw_irq(int irq_num, void *data) trace_cam_irq_activated("FD", irq_type); - cam_fd_soc_register_write(soc_info, CAM_FD_REG_WRAPPER, - hw_static_info->wrapper_regs.irq_clear, - hw_static_info->irq_mask); - if (irq_type == CAM_FD_IRQ_HALT_DONE) { /* * Do not send HALT IRQ callback to Hw Mgr, diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c index cd44d834dd0654cb8bf1aa8895e46cd889915b2f..da1bf9e52ce879a4af8b44168dbd52f5f48144c3 100644 --- a/drivers/media/platform/msm/camera/cam_icp/hfi.c +++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c @@ -537,7 +537,7 @@ void cam_hfi_disable_cpu(void __iomem *icp_base) cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET, icp_base + HFI_REG_HOST_ICP_INIT_REQUEST); cam_io_w_mb((uint32_t)INTR_DISABLE, - g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN); + icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); } void cam_hfi_enable_cpu(void __iomem *icp_base) diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c index e73d538063832e3018968090a9c42f4d25908222..b969c92ccbc8ecc773726952dce6d136062fa38a 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c @@ -199,7 +199,7 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev) cam_cpas_reg_read(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); if (pwr_ctrl & BPS_COLLAPSE_MASK) { - CAM_WARN(CAM_ICP, "BPS: pwr_ctrl set(%x)", pwr_ctrl); + CAM_DBG(CAM_ICP, "BPS: pwr_ctrl set(%x)", pwr_ctrl); cam_cpas_reg_write(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, 0); diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index ce0389306c0a8737be9a9dae9e139b7a2e6b7ff5..6e18bde908c07b8652956fb4a74a5b20f1b58aa5 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -1186,7 +1186,8 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr, if (hw_mgr->bps_ctxt_cnt) goto end; - if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) { + if (icp_hw_mgr.ipe_bps_pc_flag && + !atomic_read(&hw_mgr->recovery)) { rc = bps_dev_intf->hw_ops.process_cmd( bps_dev_intf->hw_priv, CAM_ICP_BPS_CMD_POWER_COLLAPSE, @@ -1208,7 +1209,8 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr, if (hw_mgr->ipe_ctxt_cnt) goto end; - if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) { + if (icp_hw_mgr.ipe_bps_pc_flag && + !atomic_read(&hw_mgr->recovery)) { rc = ipe0_dev_intf->hw_ops.process_cmd( ipe0_dev_intf->hw_priv, CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0); @@ -1219,7 +1221,8 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr, ipe0_dev_intf->hw_priv, NULL, 0); if (ipe1_dev_intf) { - if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) { + if (icp_hw_mgr.ipe_bps_pc_flag && + !atomic_read(&hw_mgr->recovery)) { rc = ipe1_dev_intf->hw_ops.process_cmd( ipe1_dev_intf->hw_priv, CAM_ICP_IPE_CMD_POWER_COLLAPSE, @@ -1232,7 +1235,8 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr, } hw_mgr->ipe_clk_state = false; - if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) { + if (icp_hw_mgr.ipe_bps_pc_flag && + !atomic_read(&hw_mgr->recovery)) { hw_mgr->core_info = hw_mgr->core_info & (~(ICP_PWR_CLP_IPE0 | ICP_PWR_CLP_IPE1)); } @@ -1460,10 +1464,6 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) CAM_ERR(CAM_ICP, "Invalid Context"); return -EINVAL; } - CAM_DBG(CAM_REQ, - "ctx_id : %u, request_id :%lld dev_type: %d", - ctx_data->ctx_id, request_id, - ctx_data->icp_dev_acquire_info->dev_type); mutex_lock(&ctx_data->ctx_mutex); cam_icp_ctx_timer_reset(ctx_data); @@ -1474,6 +1474,11 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) return 0; } + CAM_DBG(CAM_REQ, + "ctx_id : %u, request_id :%lld dev_type: %d", + ctx_data->ctx_id, request_id, + ctx_data->icp_dev_acquire_info->dev_type); + clk_type = ICP_DEV_TYPE_TO_CLK_TYPE( ctx_data->icp_dev_acquire_info->dev_type); cam_icp_device_timer_reset(&icp_hw_mgr, clk_type); @@ -1764,15 +1769,12 @@ static int cam_icp_ipebps_reset(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr) { int rc = 0; - int i = 0; struct sfr_buf *sfr_buffer = NULL; CAM_DBG(CAM_ICP, "Enter"); - mutex_lock(&hw_mgr->hw_mgr_mutex); - if (hw_mgr->recovery) { + if (atomic_read(&hw_mgr->recovery)) { CAM_ERR(CAM_ICP, "Recovery is set"); - mutex_unlock(&hw_mgr->hw_mgr_mutex); return rc; } @@ -1781,28 +1783,7 @@ static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr) cam_icp_ipebps_reset(hw_mgr); - hw_mgr->recovery = true; - - if (hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog) { - hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog_reset_counter = 0; - crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog); - hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog = NULL; - } - if (hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog) { - hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog_reset_counter = 0; - crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog); - hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog = NULL; - } - - for (i = 0; i < CAM_ICP_CTX_MAX; i++) { - mutex_lock(&hw_mgr->ctx_data[i].ctx_mutex); - if (hw_mgr->ctx_data[i].state != CAM_ICP_CTX_STATE_RELEASE) - cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[i]); - mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex); - } - - mutex_unlock(&hw_mgr->hw_mgr_mutex); - + atomic_set(&hw_mgr->recovery, 1); CAM_DBG(CAM_ICP, "Done"); return rc; } @@ -2383,7 +2364,7 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) } a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; - if (!hw_mgr->icp_pc_flag || hw_mgr->recovery) { + if (!hw_mgr->icp_pc_flag || atomic_read(&hw_mgr->recovery)) { cam_hfi_disable_cpu( a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); rc = cam_icp_mgr_hw_close_k(hw_mgr, NULL); @@ -2587,7 +2568,7 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id) &hw_mgr->ctx_data[ctx_id], 0); hw_mgr->ctx_data[ctx_id].state = CAM_ICP_CTX_STATE_RELEASE; CAM_DBG(CAM_ICP, "E: ctx_id = %d recovery = %d", - ctx_id, hw_mgr->recovery); + ctx_id, atomic_read(&hw_mgr->recovery)); cam_icp_mgr_abort_handle(&hw_mgr->ctx_data[ctx_id]); cam_icp_mgr_destroy_handle(&hw_mgr->ctx_data[ctx_id]); cam_icp_mgr_cleanup_ctx(&hw_mgr->ctx_data[ctx_id]); @@ -2983,7 +2964,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) hw_mgr->ctxt_cnt = 0; hw_mgr->fw_download = true; - hw_mgr->recovery = false; + atomic_set(&hw_mgr->recovery, 0); CAM_INFO(CAM_ICP, "FW download done successfully"); @@ -3932,7 +3913,8 @@ static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args) switch (flush_args->flush_type) { case CAM_FLUSH_TYPE_ALL: mutex_lock(&hw_mgr->hw_mgr_mutex); - if (!hw_mgr->recovery && flush_args->num_req_active) { + if (!atomic_read(&hw_mgr->recovery) + && flush_args->num_req_active) { mutex_unlock(&hw_mgr->hw_mgr_mutex); cam_icp_mgr_abort_handle(ctx_data); } else { @@ -3975,7 +3957,8 @@ static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) return -EINVAL; } - CAM_DBG(CAM_ICP, "Enter recovery set %d", hw_mgr->recovery); + CAM_DBG(CAM_ICP, "Enter recovery set %d", + atomic_read(&hw_mgr->recovery)); ctx_data = release_hw->ctxt_to_hw_map; if (!ctx_data) { CAM_ERR(CAM_ICP, "NULL ctx data"); @@ -3997,12 +3980,10 @@ static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex); mutex_lock(&hw_mgr->hw_mgr_mutex); - if (!hw_mgr->recovery) { + if (!atomic_read(&hw_mgr->recovery) && release_hw->active_req) { mutex_unlock(&hw_mgr->hw_mgr_mutex); - if (release_hw->active_req) { - cam_icp_mgr_abort_handle(ctx_data); - cam_icp_mgr_send_abort_status(ctx_data); - } + cam_icp_mgr_abort_handle(ctx_data); + cam_icp_mgr_send_abort_status(ctx_data); } else { mutex_unlock(&hw_mgr->hw_mgr_mutex); } @@ -4575,7 +4556,7 @@ static int cam_icp_mgr_create_wq(void) goto debugfs_create_failed; icp_hw_mgr.icp_pc_flag = true; - icp_hw_mgr.ipe_bps_pc_flag = true; + icp_hw_mgr.ipe_bps_pc_flag = false; for (i = 0; i < ICP_WORKQ_NUM_TASK; i++) icp_hw_mgr.msg_work->task.pool[i].payload = diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index 93255c26f3e30f34299821170c2adb7ba51a5ea7..5c8456575dc8fad5b173ad5676e9b8a537410b14 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -361,7 +361,7 @@ struct cam_icp_hw_mgr { struct cam_hw_intf *bps_dev_intf; bool ipe_clk_state; bool bps_clk_state; - bool recovery; + atomic_t recovery; }; static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args); diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c index 21035c74acc7091cd85d32402d8e872e337ae84d..142fcdc6017d17096d3c672aa77614c958aabf47 100644 --- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -195,7 +195,7 @@ static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev) CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl); if (pwr_ctrl & IPE_COLLAPSE_MASK) { - CAM_WARN(CAM_ICP, "IPE pwr_ctrl set(%x)", pwr_ctrl); + CAM_DBG(CAM_ICP, "IPE pwr_ctrl set(%x)", pwr_ctrl); cam_cpas_reg_write(core_info->cpas_handle, CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, 0); diff --git a/drivers/media/platform/msm/camera/cam_isp/Makefile b/drivers/media/platform/msm/camera/cam_isp/Makefile index 4851535949bb7794fda0eae127272fd0c21496ab..6b5a21a5f7bd52bd722e3a1603a93397d1d93206 100644 --- a/drivers/media/platform/msm/camera/cam_isp/Makefile +++ b/drivers/media/platform/msm/camera/cam_isp/Makefile @@ -4,6 +4,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/ ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils +ccflags-y += -Idrivers/media/platform/msm/camera/cam_cdm/ obj-$(CONFIG_SPECTRA_CAMERA) += isp_hw_mgr/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp_dev.o cam_isp_context.o diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index 99ff87890b36e88c0b5670f19fd2428ee1536eb5..990dcb4b9ccffa5068544b9619afd8d374ffe0d0 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -16,7 +16,6 @@ #include #include -#include "cam_isp_context.h" #include "cam_mem_mgr.h" #include "cam_sync_api.h" #include "cam_req_mgr_dev.h" @@ -24,6 +23,8 @@ #include "cam_debug_util.h" #include "cam_packet_util.h" #include "cam_context_utils.h" +#include "cam_cdm_util.h" +#include "cam_isp_context.h" static const char isp_dev_name[] = "isp"; @@ -121,6 +122,36 @@ static void __cam_isp_ctx_dump_state_monitor_array( } } +static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) +{ + int i = 0, rc = 0; + size_t len = 0; + uint32_t *buf_addr; + uint32_t *buf_start, *buf_end; + + for (i = 0; i < req_isp->num_cfg; i++) { + rc = cam_packet_util_get_cmd_mem_addr( + req_isp->cfg[i].handle, &buf_addr, &len); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Failed to get_cmd_mem_addr, rc=%d", + rc); + } else { + buf_start = (uint32_t *)((uint8_t *) buf_addr + + req_isp->cfg[i].offset); + buf_end = (uint32_t *)((uint8_t *) buf_start + + req_isp->cfg[i].len - 1); + if (len < (buf_end - buf_start + 1)) { + CAM_ERR(CAM_ISP, + "Invalid len %lld buf_start-end=%d", + len, (buf_end - buf_start + 1)); + continue; + } + cam_cdm_util_dump_cmd_buf(buf_start, buf_end); + } + } +} + static int __cam_isp_ctx_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) { @@ -216,6 +247,8 @@ static int __cam_isp_ctx_enqueue_init_request( req_isp_new->num_cfg); req_isp_old->num_cfg += req_isp_new->num_cfg; + req_old->request_id = req->request_id; + list_add_tail(&req->list, &ctx->free_req_list); } } else { @@ -974,8 +1007,11 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, uint32_t i = 0; bool found = 0; struct cam_ctx_request *req = NULL; + struct cam_ctx_request *req_to_report = NULL; + struct cam_ctx_request *req_to_dump = NULL; struct cam_ctx_request *req_temp; struct cam_isp_ctx_req *req_isp = NULL; + struct cam_isp_ctx_req *req_isp_to_report = NULL; struct cam_req_mgr_error_notify notify; uint64_t error_request_id; struct cam_hw_fence_map_entry *fence_map_out = NULL; @@ -992,45 +1028,98 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, notify.error = CRM_KMD_ERR_OVERFLOW; /* - * Need to check the active req - * move all of them to the pending request list - * Note this funciton need revisit! + * The error is likely caused by first request on the active list. + * If active list is empty check wait list (maybe error hit as soon + * as RUP and we handle error before RUP. */ - if (list_empty(&ctx->active_req_list)) { - CAM_ERR_RATE_LIMIT(CAM_ISP, + CAM_DBG(CAM_ISP, "handling error with no active request"); + if (list_empty(&ctx->wait_req_list)) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Error with no active/wait request"); + goto end; + } else { + req_to_dump = list_first_entry(&ctx->wait_req_list, + struct cam_ctx_request, list); + } } else { - list_for_each_entry_safe(req, req_temp, - &ctx->active_req_list, list) { - req_isp = (struct cam_isp_ctx_req *) req->req_priv; - if (!req_isp->bubble_report) { - for (i = 0; i < req_isp->num_fence_map_out; - i++) { - fence_map_out = - &req_isp->fence_map_out[i]; - CAM_ERR(CAM_ISP, "req %llu, Sync fd %x", + req_to_dump = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + } + + req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv; + cam_isp_ctx_dump_req(req_isp); + + __cam_isp_ctx_update_state_monitor_array(ctx_isp, + CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req_to_dump->request_id); + + list_for_each_entry_safe(req, req_temp, + &ctx->active_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if (!req_isp->bubble_report) { + for (i = 0; i < req_isp->num_fence_map_out; i++) { + fence_map_out = + &req_isp->fence_map_out[i]; + CAM_ERR(CAM_ISP, "req %llu, Sync fd %x", req->request_id, req_isp->fence_map_out[i].sync_id); - if (req_isp->fence_map_out[i].sync_id - != -1) { - rc = cam_sync_signal( + if (req_isp->fence_map_out[i].sync_id != -1) { + rc = cam_sync_signal( fence_map_out->sync_id, CAM_SYNC_STATE_SIGNALED_ERROR); - fence_map_out->sync_id = - -1; - } + fence_map_out->sync_id = -1; + } + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + ctx_isp->active_req_cnt--; + } else { + found = 1; + break; + } + } + + if (found) + goto move_to_pending; + + list_for_each_entry_safe(req, req_temp, + &ctx->wait_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if (!req_isp->bubble_report) { + for (i = 0; i < req_isp->num_fence_map_out; i++) { + fence_map_out = + &req_isp->fence_map_out[i]; + CAM_ERR(CAM_ISP, "req %llu, Sync fd %x", + req->request_id, + req_isp->fence_map_out[i].sync_id); + if (req_isp->fence_map_out[i].sync_id != -1) { + rc = cam_sync_signal( + fence_map_out->sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + fence_map_out->sync_id = -1; } - list_del_init(&req->list); - list_add_tail(&req->list, &ctx->free_req_list); - ctx_isp->active_req_cnt--; - } else { - found = 1; - break; } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + ctx_isp->active_req_cnt--; + } else { + found = 1; + break; } } +move_to_pending: + /* + * If bubble recovery is enabled on any request we need to move that + * request and all the subsequent requests to the pending list. + * Note: + * We need to traverse the active list in reverse order and add + * to head of pending list. + * e.g. pending current state: 10, 11 | active current state: 8, 9 + * intermittent for loop iteration- pending: 9, 10, 11 | active: 8 + * final state - pending: 8, 9, 10, 11 | active: NULL + */ if (found) { list_for_each_entry_safe_reverse(req, req_temp, &ctx->active_req_list, list) { @@ -1039,6 +1128,13 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, list_add(&req->list, &ctx->pending_req_list); ctx_isp->active_req_cnt--; } + list_for_each_entry_safe_reverse(req, req_temp, + &ctx->wait_req_list, list) { + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + ctx_isp->active_req_cnt--; + } } do { @@ -1052,8 +1148,11 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, req_isp = (struct cam_isp_ctx_req *) req->req_priv; error_request_id = ctx_isp->last_applied_req_id; - if (req_isp->bubble_report) + if (req_isp->bubble_report) { + req_to_report = req; + req_isp_to_report = req_to_report->req_priv; break; + } for (i = 0; i < req_isp->num_fence_map_out; i++) { if (req_isp->fence_map_out[i].sync_id != -1) @@ -1067,14 +1166,18 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, } while (req->request_id < ctx_isp->last_applied_req_id); - +end: if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { notify.link_hdl = ctx->link_hdl; notify.dev_hdl = ctx->dev_hdl; notify.req_id = error_request_id; - if (req_isp && req_isp->bubble_report) - notify.error = CRM_KMD_ERR_BUBBLE; + if (req_isp_to_report && req_isp_to_report->bubble_report) { + if (error_event_data->recovery_enabled) + notify.error = CRM_KMD_ERR_BUBBLE; + } else { + notify.error = CRM_KMD_ERR_FATAL; + } CAM_WARN(CAM_ISP, "Notify CRM: req %lld, frame %lld\n", error_request_id, ctx_isp->frame_id); @@ -1086,15 +1189,8 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, rc = -EFAULT; } - - list_del_init(&req->list); - list_add(&req->list, &ctx->pending_req_list); - /* might need to check if active list is empty */ - if (req != NULL) { - __cam_isp_ctx_update_state_monitor_array(ctx_isp, - CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req->request_id); - } CAM_DBG(CAM_ISP, "Exit"); + return rc; } @@ -1197,13 +1293,14 @@ static int __cam_isp_ctx_apply_req_in_activated_state( * */ ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + spin_lock_bh(&ctx->lock); req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request, list); spin_unlock_bh(&ctx->lock); /* - * Check whehter the request id is matching the tip, if not, this means + * Check whether the request id is matching the tip, if not, this means * we are in the middle of the error handling. Need to reject this apply */ if (req->request_id != apply->request_id) { @@ -1398,6 +1495,12 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_isp_start_args start_isp; int rc = 0; + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + CAM_INFO(CAM_ISP, "Last request id to flush is %lld", + flush_req->req_id); + ctx->last_flush_req = flush_req->req_id; + } + CAM_DBG(CAM_ISP, "try to flush pending list"); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); @@ -1984,6 +2087,12 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, (struct cam_isp_context *) ctx->ctx_priv; struct cam_req_mgr_flush_request flush_req; + if (ctx->link_hdl != -1) { + CAM_ERR(CAM_ISP, "ctx expects release dev after unlink"); + rc = -EAGAIN; + return rc; + } + if (cmd && ctx_isp->hw_ctx && ctx_isp->split_acquire) { CAM_ERR(CAM_ISP, "ctx expects release HW before release dev"); return rc; @@ -2131,6 +2240,17 @@ static int __cam_isp_ctx_config_dev_in_top_state( CAM_DBG(CAM_ISP, "Packet size 0x%x", packet->header.size); CAM_DBG(CAM_ISP, "packet op %d", packet->header.op_code); + if (packet->header.request_id <= ctx->last_flush_req) { + CAM_INFO(CAM_ISP, + "request %lld has been flushed, reject packet", + packet->header.request_id); + rc = -EINVAL; + goto free_req; + } + + if (packet->header.request_id > ctx->last_flush_req) + ctx->last_flush_req = 0; + /* preprocess the configuration */ memset(&cfg, 0, sizeof(cfg)); cfg.packet = packet; @@ -2966,7 +3086,7 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, struct cam_isp_context *ctx_isp = (struct cam_isp_context *)ctx->ctx_priv; - spin_lock_bh(&ctx->lock); + spin_lock(&ctx->lock); trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id, __cam_isp_ctx_get_event_ts(evt_id, evt_data)); @@ -2981,9 +3101,10 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, ctx_isp->substate_activated); __cam_isp_ctx_dump_state_monitor_array(ctx_isp); } + CAM_DBG(CAM_ISP, "Exit: State %d Substate %d", ctx->state, ctx_isp->substate_activated); - spin_unlock_bh(&ctx->lock); + spin_unlock(&ctx->lock); return rc; } diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c index fc960bfba0f264ab9084a654990ea61c028061f5..d8b7a7b5e73e838f5f8e589a293cbe2d1eb28599 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c @@ -166,6 +166,8 @@ static int cam_isp_dev_probe(struct platform_device *pdev) cam_smmu_set_client_page_fault_handler(iommu_hdl, cam_isp_dev_iommu_fault_handler, node); + mutex_init(&g_isp_dev.isp_mutex); + CAM_INFO(CAM_ISP, "Camera ISP probe complete"); return 0; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 6e9627c7fc8ce3354959953ade4b53f8447c39b4..3773f771544789181c094c322d23e4481cfcd7ac 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -42,13 +42,14 @@ (CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1) #define CAM_ISP_GENERIC_BLOB_TYPE_MAX \ - (CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG + 1) + (CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG + 1) static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = { CAM_ISP_HW_CMD_GET_HFR_UPDATE, CAM_ISP_HW_CMD_CLOCK_UPDATE, CAM_ISP_HW_CMD_BW_UPDATE, CAM_ISP_HW_CMD_UBWC_UPDATE, + CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE, }; static struct cam_ife_hw_mgr g_ife_hw_mgr; @@ -2224,13 +2225,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle); - CAM_DBG(CAM_ISP, "Going to stop IFE Mux"); - - /* IFE mux in resources */ - list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { - cam_ife_hw_mgr_stop_hw_res(hw_mgr_res); - } - CAM_DBG(CAM_ISP, "Going to stop IFE Out"); /* IFE out resources */ @@ -2244,6 +2238,13 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) } } + CAM_DBG(CAM_ISP, "Going to stop IFE Mux"); + + /* IFE mux in resources */ + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + cam_ife_hw_mgr_stop_hw_res(hw_mgr_res); + } + cam_tasklet_stop(ctx->common.tasklet_info); /* @@ -2275,7 +2276,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, master_base_idx, csid_halt_type); - /* stop rest of the CIDs */ + /* stop rest of the CIDs */ for (i = 0; i < ctx->num_base; i++) { if (ctx->base[i].idx == master_base_idx) continue; @@ -2285,6 +2286,8 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) ctx->base[i].idx, csid_halt_type); } + cam_ife_mgr_pause_hw(ctx); + if (stop_isp->stop_only) goto end; @@ -2852,6 +2855,53 @@ static int cam_isp_blob_hfr_update( return rc; } +static int cam_isp_blob_csid_clock_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_csid_clock_config *clock_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_ife_csid_clock_update_args csid_clock_upd_args; + uint64_t clk_rate = 0; + int rc = -EINVAL; + uint32_t i; + + ctx = prepare->ctxt_to_hw_map; + + CAM_DBG(CAM_ISP, + "csid clk=%llu", clock_config->csid_clock); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + clk_rate = 0; + if (!hw_mgr_res->hw_res[i]) + continue; + clk_rate = clock_config->csid_clock; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + csid_clock_upd_args.clk_rate = clk_rate; + CAM_DBG(CAM_ISP, "i= %d clk=%llu\n", + i, csid_clock_upd_args.clk_rate); + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + blob_type_hw_cmd_map[blob_type], + &csid_clock_upd_args, + sizeof( + struct cam_ife_csid_clock_update_args)); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update failed"); + } else + CAM_ERR(CAM_ISP, "NULL hw_intf!"); + } + } + + return rc; +} + static int cam_isp_blob_clock_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, @@ -3038,6 +3088,16 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "UBWC Update Failed rc: %d", rc); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG: { + struct cam_isp_csid_clock_config *clock_config = + (struct cam_isp_csid_clock_config *)blob_data; + + rc = cam_isp_blob_csid_clock_update(blob_type, blob_info, + clock_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "Clock Update Failed"); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; @@ -3562,19 +3622,18 @@ static int cam_ife_hw_mgr_do_error_recovery( * is associated with this context. if YES * a. It fills the other cores associated with this context.in * affected_core[] - * b. Return 0 i.e.SUCCESS + * b. Return 1 if ctx is affected, 0 otherwise */ static int cam_ife_hw_mgr_is_ctx_affected( struct cam_ife_hw_mgr_ctx *ife_hwr_mgr_ctx, uint32_t *affected_core, uint32_t size) { - - int32_t rc = -EPERM; + int32_t rc = 0; uint32_t i = 0, j = 0; uint32_t max_idx = ife_hwr_mgr_ctx->num_base; uint32_t ctx_affected_core_idx[CAM_IFE_HW_NUM_MAX] = {0}; - CAM_DBG(CAM_ISP, "Enter:max_idx = %d", max_idx); + CAM_DBG(CAM_ISP, "max_idx = %d", max_idx); if ((max_idx >= CAM_IFE_HW_NUM_MAX) || (size > CAM_IFE_HW_NUM_MAX)) { @@ -3584,78 +3643,71 @@ static int cam_ife_hw_mgr_is_ctx_affected( for (i = 0; i < max_idx; i++) { if (affected_core[ife_hwr_mgr_ctx->base[i].idx]) - rc = 0; + rc = 1; else { ctx_affected_core_idx[j] = ife_hwr_mgr_ctx->base[i].idx; + CAM_DBG(CAM_ISP, "Add affected IFE %d for recovery", + ctx_affected_core_idx[j]); j = j + 1; } } - if (rc == 0) { + if (rc == 1) { while (j) { if (affected_core[ctx_affected_core_idx[j-1]] != 1) affected_core[ctx_affected_core_idx[j-1]] = 1; j = j - 1; } } - CAM_DBG(CAM_ISP, "Exit"); + return rc; } /* - * Loop through each context - * a. match core_idx - * b. For each context from ctx_list Stop the acquired resources - * c. Notify CRM with fatal error for the affected isp context - * d. For any dual VFE context, if copanion VFE is also serving - * other context it should also notify the CRM with fatal error + * For any dual VFE context, if non-affected VFE is also serving + * another context, then that context should also be notified with fatal error + * So Loop through each context and - + * a. match core_idx + * b. Notify CTX with fatal error */ -static int cam_ife_hw_mgr_process_overflow( - struct cam_ife_hw_mgr_ctx *curr_ife_hwr_mgr_ctx, - struct cam_isp_hw_error_event_data *error_event_data, - uint32_t curr_core_idx, - struct cam_hw_event_recovery_data *recovery_data) +static int cam_ife_hw_mgr_find_affected_ctx( + struct cam_ife_hw_mgr_ctx *curr_ife_hwr_mgr_ctx, + struct cam_isp_hw_error_event_data *error_event_data, + uint32_t curr_core_idx, + struct cam_hw_event_recovery_data *recovery_data) { uint32_t affected_core[CAM_IFE_HW_NUM_MAX] = {0}; struct cam_ife_hw_mgr_ctx *ife_hwr_mgr_ctx = NULL; - cam_hw_event_cb_func ife_hwr_irq_err_cb; - struct cam_ife_hw_mgr *ife_hwr_mgr = NULL; - struct cam_hw_stop_args stop_args; + cam_hw_event_cb_func notify_err_cb; + struct cam_ife_hw_mgr *ife_hwr_mgr = NULL; + enum cam_isp_hw_event_type event_type = CAM_ISP_HW_EVENT_ERROR; uint32_t i = 0; - CAM_DBG(CAM_ISP, "Enter"); - if (!recovery_data) { CAM_ERR(CAM_ISP, "recovery_data parameter is NULL"); return -EINVAL; } + recovery_data->no_of_context = 0; - /* affected_core is indexed by core_idx*/ affected_core[curr_core_idx] = 1; - ife_hwr_mgr = curr_ife_hwr_mgr_ctx->hw_mgr; list_for_each_entry(ife_hwr_mgr_ctx, &ife_hwr_mgr->used_ctx_list, list) { - /* * Check if current core_idx matches the HW associated * with this context */ - CAM_DBG(CAM_ISP, "Calling match Hw idx"); - if (cam_ife_hw_mgr_is_ctx_affected(ife_hwr_mgr_ctx, + if (!cam_ife_hw_mgr_is_ctx_affected(ife_hwr_mgr_ctx, affected_core, CAM_IFE_HW_NUM_MAX)) continue; atomic_set(&ife_hwr_mgr_ctx->overflow_pending, 1); + notify_err_cb = ife_hwr_mgr_ctx->common.event_cb[event_type]; - ife_hwr_irq_err_cb = - ife_hwr_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_ERROR]; - - stop_args.ctxt_to_hw_map = ife_hwr_mgr_ctx; - - /* Add affected_context in list of recovery data*/ - CAM_DBG(CAM_ISP, "Add new entry in affected_ctx_list"); + /* Add affected_context in list of recovery data */ + CAM_DBG(CAM_ISP, "Add affected ctx %d to list", + ife_hwr_mgr_ctx->ctx_index); if (recovery_data->no_of_context < CAM_CTX_MAX) recovery_data->affected_ctx[ recovery_data->no_of_context++] = @@ -3665,18 +3717,17 @@ static int cam_ife_hw_mgr_process_overflow( * In the call back function corresponding ISP context * will update CRM about fatal Error */ - - ife_hwr_irq_err_cb(ife_hwr_mgr_ctx->common.cb_priv, + notify_err_cb(ife_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_ERROR, error_event_data); - } + /* fill the affected_core in recovery data */ for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { recovery_data->affected_core[i] = affected_core[i]; CAM_DBG(CAM_ISP, "Vfe core %d is affected (%d)", i, recovery_data->affected_core[i]); } - CAM_DBG(CAM_ISP, "Exit"); + return 0; } @@ -3764,6 +3815,7 @@ static int cam_ife_hw_mgr_handle_camif_error( struct cam_vfe_top_irq_evt_payload *evt_payload; struct cam_isp_hw_error_event_data error_event_data = {0}; struct cam_hw_event_recovery_data recovery_data = {0}; + int rc = 0; ife_hwr_mgr_ctx = handler_priv; evt_payload = payload; @@ -3780,24 +3832,35 @@ static int cam_ife_hw_mgr_handle_camif_error( case CAM_ISP_HW_ERROR_P2I_ERROR: case CAM_ISP_HW_ERROR_VIOLATION: CAM_ERR(CAM_ISP, "Enter: error_type (%d)", error_status); + rc = -EFAULT; + + if (g_ife_hw_mgr.debug_cfg.enable_recovery) + error_event_data.recovery_enabled = true; error_event_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; - cam_ife_hw_mgr_process_overflow(ife_hwr_mgr_ctx, + cam_ife_hw_mgr_find_affected_ctx(ife_hwr_mgr_ctx, &error_event_data, core_idx, &recovery_data); + if (!g_ife_hw_mgr.debug_cfg.enable_recovery) { + CAM_DBG(CAM_ISP, "recovery is not enabled"); + break; + } + + CAM_DBG(CAM_ISP, "IFE Mgr recovery is enabled"); /* Trigger for recovery */ recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; cam_ife_hw_mgr_do_error_recovery(&recovery_data); break; default: - CAM_DBG(CAM_ISP, "None error (%d)", error_status); + CAM_DBG(CAM_ISP, "No error (%d)", error_status); + break; } - return 0; + return rc; } /* @@ -4542,7 +4605,7 @@ static int cam_ife_hw_mgr_handle_buf_done_for_hw_res( * the affected context and any successful buf_done event is not * reported. */ - rc = cam_ife_hw_mgr_process_overflow(ife_hwr_mgr_ctx, + rc = cam_ife_hw_mgr_find_affected_ctx(ife_hwr_mgr_ctx, &error_event_data, evt_payload->core_index, &recovery_data); @@ -4614,18 +4677,13 @@ int cam_ife_mgr_do_tasklet(void *handler_priv, void *evt_payload_priv) * for this context it needs to be handled remaining * interrupts are ignored. */ - if (g_ife_hw_mgr.debug_cfg.enable_recovery) { - CAM_DBG(CAM_ISP, "IFE Mgr recovery is enabled"); - rc = cam_ife_hw_mgr_handle_camif_error(ife_hwr_mgr_ctx, - evt_payload_priv); - } else { - CAM_DBG(CAM_ISP, "recovery is not enabled"); - rc = 0; - } + rc = cam_ife_hw_mgr_handle_camif_error(ife_hwr_mgr_ctx, + evt_payload_priv); if (rc) { - CAM_ERR(CAM_ISP, "Encountered Error (%d), ignoring other irqs", - rc); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Encountered Error (%d), ignoring other irqs", + rc); goto put_payload; } diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 1586216f2073bed7b23bb459f2b700f4ee7a796b..1a0f1ecab7b6fbbc733e448f88029bed81b9eea4 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -184,11 +184,13 @@ struct cam_isp_hw_eof_event_data { * * @error_type: Error type for the error event * @timestamp: Timestamp for the error event - * + * @recovery_enabled: Identifies if the context needs to recover & reapply + * this request */ struct cam_isp_hw_error_event_data { uint32_t error_type; uint64_t timestamp; + bool recovery_enabled; }; /* enum cam_isp_hw_mgr_command - Hardware manager command type */ diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index e820299852f1e581b0c1271827860e83c7152f9e..d4e40f9ec37d4f53fb0b5e8558e935e662c3640f 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -45,6 +45,9 @@ /* Max number of sof irq's triggered in case of SOF freeze */ #define CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX 12 +/* Max CSI Rx irq error count threshold value */ +#define CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT 100 + static int cam_ife_csid_is_ipp_ppp_format_supported( uint32_t in_format) { @@ -435,6 +438,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) if (val != 0) CAM_ERR(CAM_ISP, "CSID:%d IRQ value after reset rc = %d", csid_hw->hw_intf->hw_idx, val); + csid_hw->error_irq_count = 0; return rc; } @@ -1004,8 +1008,8 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) { int rc = 0; const struct cam_ife_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; - uint32_t i, val; + struct cam_hw_soc_info *soc_info; + uint32_t i, val, clk_lvl; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -1027,7 +1031,10 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw) CAM_DBG(CAM_ISP, "CSID:%d init CSID HW", csid_hw->hw_intf->hw_idx); - rc = cam_ife_csid_enable_soc_resources(soc_info); + clk_lvl = cam_ife_csid_get_vote_level(soc_info, csid_hw->clk_rate); + CAM_DBG(CAM_ISP, "CSID clock lvl %u", clk_lvl); + + rc = cam_ife_csid_enable_soc_resources(soc_info, clk_lvl); if (rc) { CAM_ERR(CAM_ISP, "CSID:%d Enable SOC failed", csid_hw->hw_intf->hw_idx); @@ -1122,6 +1129,8 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) csid_hw->hw_intf->hw_idx); csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; + csid_hw->error_irq_count = 0; + return rc; } @@ -2348,6 +2357,9 @@ static int cam_ife_csid_reserve(void *hw_priv, csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info; reserv = (struct cam_csid_hw_reserve_resource_args *)reserve_args; + CAM_DBG(CAM_ISP, "res_type %d, CSID: %u", + reserv->res_type, csid_hw->hw_intf->hw_idx); + mutex_lock(&csid_hw->hw_info->hw_mutex); switch (reserv->res_type) { case CAM_ISP_RESOURCE_CID: @@ -2792,18 +2804,28 @@ static int cam_ife_csid_sof_irq_debug( if (*((uint32_t *)cmd_args) == 1) sof_irq_enable = true; - val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + if (csid_hw->hw_info->hw_state == + CAM_HW_STATE_POWER_DOWN) { + CAM_WARN(CAM_ISP, + "CSID powered down unable to %s sof irq", + (sof_irq_enable == true) ? "enable" : "disable"); + return 0; + } + + if (csid_reg->ipp_reg) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); - if (val) { - if (sof_irq_enable) - val |= CSID_PATH_INFO_INPUT_SOF; - else - val &= ~CSID_PATH_INFO_INPUT_SOF; + if (val) { + if (sof_irq_enable) + val |= CSID_PATH_INFO_INPUT_SOF; + else + val &= ~CSID_PATH_INFO_INPUT_SOF; - cam_io_w_mb(val, soc_info->reg_map[0].mem_base + - csid_reg->ipp_reg->csid_pxl_irq_mask_addr); - val = 0; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_irq_mask_addr); + val = 0; + } } for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { @@ -2835,6 +2857,23 @@ static int cam_ife_csid_sof_irq_debug( return 0; } +static int cam_ife_csid_set_csid_clock( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_ife_csid_clock_update_args *clk_update = NULL; + + if (!csid_hw) + return -EINVAL; + + clk_update = + (struct cam_ife_csid_clock_update_args *)cmd_args; + + csid_hw->clk_rate = clk_update->clk_rate; + CAM_INFO(CAM_ISP, "CSID clock rate %llu", csid_hw->clk_rate); + + return 0; +} + static int cam_ife_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -2866,6 +2905,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_SOF_IRQ_DEBUG: rc = cam_ife_csid_sof_irq_debug(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE: + rc = cam_ife_csid_set_csid_clock(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); @@ -2981,10 +3023,12 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_EOT_RECEPTION", csid_hw->hw_intf->hw_idx); + csid_hw->error_irq_count++; } if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_SOT_RECEPTION", csid_hw->hw_intf->hw_idx); + csid_hw->error_irq_count++; } if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC", @@ -3011,6 +3055,12 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) csid_hw->hw_intf->hw_idx); } + if (csid_hw->error_irq_count > + CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT) { + fatal_err_detected = true; + csid_hw->error_irq_count = 0; + } + if (fatal_err_detected) cam_ife_csid_halt_csi2(csid_hw); @@ -3344,6 +3394,8 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, } ife_csid_hw->csid_debug = 0; + ife_csid_hw->error_irq_count = 0; + return 0; err: if (rc) { diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index d987f21965aeebb57896e4be145ccd7fbdc5ed50..43fd9b03132e965f7a04b4edf7fb250733248aee 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -449,6 +449,8 @@ struct cam_ife_csid_path_cfg { * @sof_irq_triggered: Flag is set on receiving event to enable sof irq * incase of SOF freeze. * @irq_debug_cnt: Counter to track sof irq's when above flag is set. + * @error_irq_count Error IRQ count, if continuous error irq comes + * need to stop the CSID and mask interrupts. * */ struct cam_ife_csid_hw { @@ -474,6 +476,7 @@ struct cam_ife_csid_hw { uint64_t clk_rate; bool sof_irq_triggered; uint32_t irq_debug_cnt; + uint32_t error_irq_count; }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c index d3261f84e2f408f1db66eaa0754c41c406d252fc..890dad3b66b25349276b05ccb9bec7df11f28da2 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c @@ -116,7 +116,8 @@ int cam_ife_csid_deinit_soc_resources( return rc; } -int cam_ife_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info) +int cam_ife_csid_enable_soc_resources( + struct cam_hw_soc_info *soc_info, uint32_t clk_lvl) { int rc = 0; struct cam_csid_soc_private *soc_private; @@ -141,7 +142,7 @@ int cam_ife_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info) } rc = cam_soc_util_enable_platform_resource(soc_info, true, - CAM_SVS_VOTE, true); + clk_lvl, true); if (rc) { CAM_ERR(CAM_ISP, "enable platform failed"); goto stop_cpas; @@ -235,3 +236,23 @@ int cam_ife_csid_disable_ife_force_clock_on(struct cam_hw_soc_info *soc_info, return rc; } +uint32_t cam_ife_csid_get_vote_level(struct cam_hw_soc_info *soc_info, + uint64_t clock_rate) +{ + int i = 0; + + if (!clock_rate) + return CAM_SVS_VOTE; + + for (i = 0; i < CAM_MAX_VOTE; i++) { + if (soc_info->clk_rate[i][soc_info->num_clk - 1] >= + clock_rate) { + CAM_DBG(CAM_ISP, + "Clock rate %lld, selected clock level %d", + clock_rate, i); + return i; + } + } + + return CAM_TURBO_VOTE; +} diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h index c83c191656a967e1ddd844edee4f3469ac5be1fa..474f0852dbec447354abfda8f31e3d8ae3981d42 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.h @@ -68,9 +68,11 @@ int cam_ife_csid_deinit_soc_resources(struct cam_hw_soc_info *soc_info); * @brief: csid soc resource enable function * * @soc_info: soc info structure pointer + * @clk_lvl: vote level to start with * */ -int cam_ife_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info); +int cam_ife_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info, + uint32_t clk_lvl); /** * cam_ife_csid_disable_soc_resources() @@ -109,6 +111,16 @@ int cam_ife_csid_enable_ife_force_clock_on(struct cam_hw_soc_info *soc_info, int cam_ife_csid_disable_ife_force_clock_on(struct cam_hw_soc_info *soc_info, uint32_t cpas_ife_base_offset); - +/** + * cam_ife_csid_get_vote_level() + * + * @brief: get the vote level from clock rate + * + * @soc_info: soc info structure pointer + * @clock_rate clock rate + * + */ +uint32_t cam_ife_csid_get_vote_level(struct cam_hw_soc_info *soc_info, + uint64_t clock_rate); #endif diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 5e35c47e85a75d17b6fc469c239f76cf730fa129..58818fbecf67e8ae2559548c169006b0ccecc9ba 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -171,4 +171,14 @@ enum cam_ife_csid_cmd_type { int cam_ife_csid_hw_init(struct cam_hw_intf **ife_csid_hw, uint32_t hw_idx); +/* + * struct cam_ife_csid_clock_update_args: + * + * @clk_rate: Clock rate requested + */ +struct cam_ife_csid_clock_update_args { + uint64_t clk_rate; +}; + + #endif /* _CAM_CSID_HW_INTF_H_ */ diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 6f5087d37825a61c4b111c0752af7ef3f39b1c37..b317f922cec55f888bce07abde96320d38df68b6 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -98,6 +98,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_UBWC_UPDATE, CAM_ISP_HW_CMD_SOF_IRQ_DEBUG, CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 620349faef6048f00c5b75959e2d8002bd0fe251..090f319e1e497465c4babb13a6db43d2dbe7bdd4 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -2644,10 +2644,10 @@ static int cam_vfe_bus_update_ubwc_3_regs( switch (wm_data->format) { case CAM_FORMAT_UBWC_TP10: - ubwc_bw_limit = 0x8 | BIT(0); + ubwc_bw_limit = (0x8 << 1) | BIT(0); break; case CAM_FORMAT_UBWC_NV12_4R: - ubwc_bw_limit = 0xB | BIT(0); + ubwc_bw_limit = (0xB << 1) | BIT(0); break; default: ubwc_bw_limit = 0; diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index fc257ecaa604d9f1240ea6282564ea6a02a91c95..007f97815b97aed6db9b651423e6172c5d3add37 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -378,6 +378,42 @@ static int cam_vfe_camif_reg_dump( return rc; } +static int cam_vfe_camif_reg_dump_bh(struct cam_vfe_mux_camif_data *camif_priv) +{ + uint32_t offset, val, wm_idx; + + for (offset = 0x0; offset < 0x1000; offset += 0x4) { + val = cam_soc_util_r(camif_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val); + } + + for (offset = 0x2000; offset <= 0x20B8; offset += 0x4) { + val = cam_soc_util_r(camif_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val); + } + + for (wm_idx = 0; wm_idx <= 23; wm_idx++) { + for (offset = 0x2200 + 0x100 * wm_idx; + offset < 0x2278 + 0x100 * wm_idx; offset += 0x4) { + val = cam_soc_util_r(camif_priv->soc_info, 0, offset); + CAM_INFO(CAM_ISP, + "offset 0x%x value 0x%x", offset, val); + } + } + + offset = 0x420; + val = cam_soc_util_r(camif_priv->soc_info, 1, offset); + CAM_INFO(CAM_ISP, "CAMNOC IFE02 MaxWR_LOW offset 0x%x value 0x%x", + offset, val); + + offset = 0x820; + val = cam_soc_util_r(camif_priv->soc_info, 1, offset); + CAM_INFO(CAM_ISP, "CAMNOC IFE13 MaxWR_LOW offset 0x%x value 0x%x", + offset, val); + + return 0; +} + static int cam_vfe_camif_resource_stop( struct cam_isp_resource_node *camif_res) { @@ -548,7 +584,7 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status1 & camif_priv->reg_data->error_irq_mask1) { CAM_DBG(CAM_ISP, "Received ERROR\n"); ret = CAM_ISP_HW_ERROR_OVERFLOW; - cam_vfe_camif_reg_dump(camif_node); + cam_vfe_camif_reg_dump_bh(camif_node->res_priv); } else { ret = CAM_ISP_HW_ERROR_NONE; } diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index 4cd2b98d81dc0d7fd31512711c754cf461683417..1989ac48a95772a706c0c47465233c7f16cd658c 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -598,27 +598,6 @@ int cam_vfe_top_stop(void *device_priv, break; } } - - if (hw_info->hw_state == CAM_HW_STATE_POWER_UP) { - rc = cam_vfe_top_set_hw_clk_rate(top_priv); - if (rc) { - CAM_ERR(CAM_ISP, - "set_hw_clk_rate failed, rc=%d", rc); - return rc; - } - - top_priv->hw_clk_rate = 0; - - rc = cam_vfe_top_set_axi_bw_vote(top_priv, true); - if (rc) { - CAM_ERR(CAM_ISP, - "set_axi_bw_vote failed, rc=%d", rc); - return rc; - } - } else { - CAM_ERR(CAM_ISP, "VFE HW not powered up"); - rc = -EPERM; - } } return rc; diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c index 022e1a7fcf1efbb258ab4611f31bc3712ab789e4..2133ffb48877d0cdd8bd2c44e82c20f36b6bff9e 100644 --- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c +++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c @@ -79,7 +79,9 @@ static void cam_lrme_hw_util_fill_fe_reg(struct cam_lrme_hw_io_buffer *io_buf, hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0, 0x0); else if (io_buf->io_cfg->format == CAM_FORMAT_Y_ONLY || - io_buf->io_cfg->format == CAM_FORMAT_PLAIN8) + io_buf->io_cfg->format == CAM_FORMAT_PLAIN8 || + io_buf->io_cfg->format == CAM_FORMAT_NV12 || + io_buf->io_cfg->format == CAM_FORMAT_NV21) cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0, 0x1); @@ -126,7 +128,7 @@ static void cam_lrme_hw_util_fill_we_reg(struct cam_lrme_hw_io_buffer *io_buf, /* client stride */ cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd, hw_info->bus_wr_reg.bus_client_reg[index].wr_stride, - io_buf->io_cfg->planes[0].meta_stride); + io_buf->io_cfg->planes[0].plane_stride); CAM_DBG(CAM_LRME, "plane_stride %d", io_buf->io_cfg->planes[0].plane_stride); } @@ -855,7 +857,8 @@ int cam_lrme_hw_stop(void *hw_priv, void *hw_stop_args, uint32_t arg_size) mutex_lock(&lrme_hw->hw_mutex); - if (lrme_hw->open_count == 0) { + if (lrme_hw->open_count == 0 || + lrme_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { mutex_unlock(&lrme_hw->hw_mutex); CAM_ERR(CAM_LRME, "Error Unbalanced stop"); return -EINVAL; @@ -884,10 +887,8 @@ int cam_lrme_hw_stop(void *hw_priv, void *hw_stop_args, uint32_t arg_size) } rc = cam_lrme_soc_disable_resources(lrme_hw); - if (rc) { + if (rc) CAM_ERR(CAM_LRME, "Failed in Disable SOC, rc=%d", rc); - goto unlock; - } lrme_hw->hw_state = CAM_HW_STATE_POWER_DOWN; if (lrme_core->state == CAM_LRME_CORE_STATE_IDLE) { @@ -1049,9 +1050,9 @@ int cam_lrme_hw_flush(void *hw_priv, void *hw_flush_args, uint32_t arg_size) if (lrme_core->state != CAM_LRME_CORE_STATE_PROCESSING && lrme_core->state != CAM_LRME_CORE_STATE_REQ_PENDING && - lrme_core->state == CAM_LRME_CORE_STATE_REQ_PROC_PEND) { + lrme_core->state != CAM_LRME_CORE_STATE_REQ_PROC_PEND) { mutex_unlock(&lrme_hw->hw_mutex); - CAM_DBG(CAM_LRME, "Stop not needed in %d state", + CAM_DBG(CAM_LRME, "Flush is not needed in %d state", lrme_core->state); return 0; } diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c index f47dea8d42f7d907d979b6407c65daf6004d580c..2d8e49d56682aca98ed117faa19c8b3d5d8eaf01 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c @@ -318,10 +318,10 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) if (dmabuf_flag & ION_FLAG_CACHED) { switch (cmd->mem_cache_ops) { case CAM_MEM_CLEAN_CACHE: - cache_dir = DMA_FROM_DEVICE; + cache_dir = DMA_TO_DEVICE; break; case CAM_MEM_INV_CACHE: - cache_dir = DMA_TO_DEVICE; + cache_dir = DMA_FROM_DEVICE; break; case CAM_MEM_CLEAN_INV_CACHE: cache_dir = DMA_BIDIRECTIONAL; @@ -338,7 +338,8 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd) } rc = dma_buf_begin_cpu_access(tbl.bufq[idx].dma_buf, - cache_dir); + (cmd->mem_cache_ops == CAM_MEM_CLEAN_INV_CACHE) ? + DMA_BIDIRECTIONAL : DMA_TO_DEVICE); if (rc) { CAM_ERR(CAM_MEM, "dma begin access failed rc=%d", rc); goto end; @@ -771,11 +772,11 @@ static int cam_mem_util_unmap_hw_va(int32_t idx, int32_t *mmu_hdls; int num_hdls; int fd; - int rc = -EINVAL; + int rc = 0; if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) { CAM_ERR(CAM_MEM, "Incorrect index"); - return rc; + return -EINVAL; } flags = tbl.bufq[idx].flags; @@ -920,13 +921,11 @@ static int cam_mem_util_unmap(int32_t idx, if (tbl.bufq[idx].dma_buf && tbl.bufq[idx].kmdvaddr) { rc = cam_mem_util_unmap_cpu_va(tbl.bufq[idx].dma_buf, tbl.bufq[idx].kmdvaddr); - if (rc) { + if (rc) CAM_ERR(CAM_MEM, "Failed, dmabuf=%pK, kmdvaddr=%pK", tbl.bufq[idx].dma_buf, tbl.bufq[idx].kmdvaddr); - return rc; - } } } @@ -940,9 +939,11 @@ static int cam_mem_util_unmap(int32_t idx, if ((tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_READ_WRITE) || (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) || - (tbl.bufq[idx].flags & CAM_MEM_FLAG_PROTECTED_MODE)) - rc = cam_mem_util_unmap_hw_va(idx, region, client); - + (tbl.bufq[idx].flags & CAM_MEM_FLAG_PROTECTED_MODE)) { + if (cam_mem_util_unmap_hw_va(idx, region, client)) + CAM_ERR(CAM_MEM, "Failed, dmabuf=%pK", + tbl.bufq[idx].dma_buf); + } mutex_lock(&tbl.bufq[idx].q_lock); tbl.bufq[idx].flags = 0; diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index a43865e64c3d47ab65e14f94a7d623d28ac8f600..7c061b92fd2458cc5111ad04c5d7b717e6c59872 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -403,10 +403,53 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_connected_device *dev = NULL; struct cam_req_mgr_apply_request apply_req; struct cam_req_mgr_link_evt_data evt_data; + struct cam_req_mgr_tbl_slot *slot = NULL; apply_req.link_hdl = link->link_hdl; apply_req.report_if_bubble = 0; + for (i = 0; i < link->num_devs; i++) { + dev = &link->l_dev[i]; + if (!dev) + continue; + pd = dev->dev_info.p_delay; + if (pd >= CAM_PIPELINE_DELAY_MAX) { + CAM_WARN(CAM_CRM, "pd %d greater than max", + pd); + continue; + } + + idx = link->req.apply_data[pd].idx; + slot = &dev->pd_tbl->slot[idx]; + /* + * Just let flash go for this request and other + * device get restricted + */ + + if ((slot->skip_next_frame != true) || + (slot->dev_hdl != dev->dev_hdl)) + continue; + + if (!(dev->dev_info.trigger & trigger)) + continue; + + apply_req.dev_hdl = dev->dev_hdl; + apply_req.request_id = + link->req.apply_data[pd].req_id; + apply_req.trigger_point = trigger; + if (dev->ops && dev->ops->apply_req) { + rc = dev->ops->apply_req(&apply_req); + if (rc) + return rc; + CAM_DBG(CAM_REQ, + "SEND: link_hdl: %x pd: %d req_id %lld", + link->link_hdl, pd, apply_req.request_id); + slot->skip_next_frame = false; + slot->is_applied = true; + return -EAGAIN; + } + } + for (i = 0; i < link->num_devs; i++) { dev = &link->l_dev[i]; if (dev) { @@ -430,9 +473,16 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.request_id = link->req.apply_data[pd].req_id; idx = link->req.apply_data[pd].idx; + slot = &dev->pd_tbl->slot[idx]; apply_req.report_if_bubble = in_q->slot[idx].recover; + if ((slot->dev_hdl == dev->dev_hdl) && + (slot->is_applied == true)) { + slot->is_applied = false; + continue; + } + trace_cam_req_mgr_apply_request(link, &apply_req, dev); apply_req.trigger_point = trigger; @@ -1289,9 +1339,9 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( return NULL; } - if (session->num_links >= MAX_LINKS_PER_SESSION) { + if (session->num_links >= MAXIMUM_LINKS_PER_SESSION) { CAM_ERR(CAM_CRM, "Reached max links %d per session limit %d", - session->num_links, MAX_LINKS_PER_SESSION); + session->num_links, MAXIMUM_LINKS_PER_SESSION); return NULL; } @@ -1326,7 +1376,7 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( mutex_lock(&session->lock); /* Loop through and find a free index */ - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (!session->links[i]) { CAM_DBG(CAM_CRM, "Free link index %d found, num_links=%d", @@ -1336,7 +1386,7 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link( } } - if (i == MAX_LINKS_PER_SESSION) { + if (i == MAXIMUM_LINKS_PER_SESSION) { CAM_ERR(CAM_CRM, "Free link index not found"); goto error; } @@ -1397,7 +1447,7 @@ static void __cam_req_mgr_unreserve_link( return; } - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i] == link) session->links[i] = NULL; } @@ -1409,7 +1459,7 @@ static void __cam_req_mgr_unreserve_link( * of only having 2 links in a given session */ session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i]) session->links[i]->sync_link = NULL; } @@ -1494,6 +1544,9 @@ int cam_req_mgr_process_flush_req(void *priv, void *data) mutex_lock(&link->req.lock); if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + link->last_flush_id = flush_info->req_id; + CAM_INFO(CAM_CRM, "Last request id to flush is %lld", + flush_info->req_id); for (i = 0; i < in_q->num_slots; i++) { slot = &in_q->slot[i]; slot->req_id = -1; @@ -1658,10 +1711,15 @@ int cam_req_mgr_process_add_req(void *priv, void *data) } slot = &tbl->slot[idx]; - if (add_req->skip_before_applying > slot->inject_delay) { - slot->inject_delay = add_req->skip_before_applying; - CAM_DBG(CAM_CRM, "Req_id %llu injecting delay %u", - add_req->req_id, add_req->skip_before_applying); + slot->is_applied = false; + if ((add_req->skip_before_applying & 0xFF) > slot->inject_delay) { + slot->inject_delay = (add_req->skip_before_applying & 0xFF); + slot->dev_hdl = add_req->dev_hdl; + if (add_req->skip_before_applying & SKIP_NEXT_FRAME) + slot->skip_next_frame = true; + CAM_DBG(CAM_CRM, "Req_id %llu injecting delay %llu", + add_req->req_id, + (add_req->skip_before_applying & 0xFF)); } if (slot->state != CRM_REQ_STATE_PENDING && @@ -2312,7 +2370,8 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link) if (rc < 0) { CAM_ERR(CAM_CRM, "error destroying link hdl %x rc %d", link->link_hdl, rc); - } + } else + link->link_hdl = -1; mutex_unlock(&link->lock); return rc; @@ -2345,7 +2404,7 @@ int cam_req_mgr_destroy_session( ses_info->session_hdl, cam_session->num_links); - for (i = 0; i < MAX_LINKS_PER_SESSION; i++) { + for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { link = cam_session->links[i]; if (!link) @@ -2422,6 +2481,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) goto link_hdl_fail; } link_info->link_hdl = link->link_hdl; + link->last_flush_id = 0; /* Allocate memory to hold data of all linked devs */ rc = __cam_req_mgr_create_subdevs(&link->l_dev, @@ -2468,7 +2528,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info) __cam_req_mgr_destroy_subdev(link->l_dev); create_subdev_failed: cam_destroy_device_hdl(link->link_hdl); - link_info->link_hdl = 0; + link_info->link_hdl = -1; link_hdl_fail: mutex_unlock(&link->lock); __cam_req_mgr_unreserve_link(cam_session, link); @@ -2547,6 +2607,17 @@ int cam_req_mgr_schedule_request( goto end; } + if (sched_req->req_id <= link->last_flush_id) { + CAM_INFO(CAM_CRM, + "request %d is flushed, last_flush_id to flush %lld", + sched_req->req_id, link->last_flush_id); + rc = -EINVAL; + goto end; + } + + if (sched_req->req_id > link->last_flush_id) + link->last_flush_id = 0; + CAM_DBG(CAM_CRM, "link 0x%x req %lld, sync_mode %d", sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode); @@ -2585,7 +2656,8 @@ int cam_req_mgr_sync_config( } if ((sync_info->num_links < 0) || - (sync_info->num_links > MAX_LINKS_PER_SESSION)) { + (sync_info->num_links > + MAX_LINKS_PER_SESSION)) { CAM_ERR(CAM_CRM, "Invalid num links %d", sync_info->num_links); return -EINVAL; } @@ -2734,6 +2806,13 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control) goto end; } + if (control->num_links > MAX_LINKS_PER_SESSION) { + CAM_ERR(CAM_CRM, "Invalid number of links %d", + control->num_links); + rc = -EINVAL; + goto end; + } + mutex_lock(&g_crm_core_dev->crm_lock); for (i = 0; i < control->num_links; i++) { link = (struct cam_req_mgr_core_link *) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h index 68ec09b1e89edba79d2cc94e44f0ac2a37d5b5cc..30341db68d327fbaa66a8766c16f98773bf784b1 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h @@ -34,6 +34,8 @@ #define SYNC_LINK_SOF_CNT_MAX_LMT 1 +#define MAXIMUM_LINKS_PER_SESSION 4 + /** * enum crm_workq_task_type * @codes: to identify which type of task is present @@ -166,16 +168,23 @@ struct cam_req_mgr_apply { /** * struct cam_req_mgr_tbl_slot - * @idx : slot index - * @req_ready_map : mask tracking which all devices have request ready - * @state : state machine for life cycle of a slot - * @inject_delay : insert extra bubbling for flash type of use cases + * @idx : slot index + * @req_ready_map : mask tracking which all devices have request ready + * @state : state machine for life cycle of a slot + * @inject_delay : insert extra bubbling for flash type of use cases + * @dev_hdl : stores the dev_hdl, who is having higher inject delay + * @skip_next_frame : flag to drop the frame after skip_before_apply frame + * @is_applied : flag to identify if request is already applied to + * device. */ struct cam_req_mgr_tbl_slot { int32_t idx; uint32_t req_ready_map; enum crm_req_state state; uint32_t inject_delay; + int32_t dev_hdl; + bool skip_next_frame; + bool is_applied; }; /** @@ -308,6 +317,7 @@ struct cam_req_mgr_connected_device { * frame in sync link as well. * @open_req_cnt : Counter to keep track of open requests that are yet * to be serviced in the kernel. + * @last_flush_id : Last request to flush * */ struct cam_req_mgr_core_link { @@ -332,6 +342,7 @@ struct cam_req_mgr_core_link { bool frame_skip_flag; bool sync_link_sof_skip; int32_t open_req_cnt; + uint32_t last_flush_id; }; /** @@ -353,7 +364,7 @@ struct cam_req_mgr_core_link { struct cam_req_mgr_core_session { int32_t session_hdl; uint32_t num_links; - struct cam_req_mgr_core_link *links[MAX_LINKS_PER_SESSION]; + struct cam_req_mgr_core_link *links[MAXIMUM_LINKS_PER_SESSION]; struct list_head entry; struct mutex lock; int32_t force_err_recovery; diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h index c9e4ab2e8886fb5dbc77d904849f912158536637..409e74961b45ba1e5b3fdfa97590219abff8ece6 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h @@ -27,6 +27,8 @@ struct cam_req_mgr_apply_request; struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; +#define SKIP_NEXT_FRAME 0x100 + /* Request Manager -- camera device driver interface */ /** * @brief: camera kernel drivers to cam req mgr communication diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c index 31d9d35062bdcd76964cd622b4c4c2ec2d0275bd..d35a8d1184f50d388cc4d2cfce505fdb272ddd56 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -457,6 +457,19 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, csl_packet = (struct cam_packet *)(generic_ptr + config.offset); CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code); + if ((csl_packet->header.op_code & 0xFFFFFF) != + CAM_ACTUATOR_PACKET_OPCODE_INIT && + csl_packet->header.request_id <= a_ctrl->last_flush_req + && a_ctrl->last_flush_req != 0) { + CAM_DBG(CAM_ACTUATOR, + "reject request %lld, last request to flush %lld", + csl_packet->header.request_id, a_ctrl->last_flush_req); + return -EINVAL; + } + + if (csl_packet->header.request_id > a_ctrl->last_flush_req) + a_ctrl->last_flush_req = 0; + switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_ACTUATOR_PACKET_OPCODE_INIT: offset = (uint32_t *)&csl_packet->payload; @@ -764,6 +777,16 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, rc = -EINVAL; goto release_mutex; } + + if (a_ctrl->bridge_intf.link_hdl != -1) { + CAM_ERR(CAM_ACTUATOR, + "Device [%d] still active on link 0x%x", + a_ctrl->cam_act_state, + a_ctrl->bridge_intf.link_hdl); + rc = -EAGAIN; + goto release_mutex; + } + rc = cam_destroy_device_hdl(a_ctrl->bridge_intf.device_hdl); if (rc < 0) CAM_ERR(CAM_ACTUATOR, "destroying the device hdl"); @@ -771,6 +794,7 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, a_ctrl->bridge_intf.link_hdl = -1; a_ctrl->bridge_intf.session_hdl = -1; a_ctrl->cam_act_state = CAM_ACTUATOR_INIT; + a_ctrl->last_flush_req = 0; kfree(power_info->power_setting); kfree(power_info->power_down_setting); power_info->power_setting = NULL; @@ -800,6 +824,7 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, goto release_mutex; } a_ctrl->cam_act_state = CAM_ACTUATOR_START; + a_ctrl->last_flush_req = 0; } break; case CAM_STOP_DEV: { @@ -825,6 +850,7 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, i2c_set->request_id, rc); } } + a_ctrl->last_flush_req = 0; a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG; } break; @@ -888,6 +914,13 @@ int32_t cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush_req) return -EINVAL; } + mutex_lock(&(a_ctrl->actuator_mutex)); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + a_ctrl->last_flush_req = flush_req->req_id; + CAM_DBG(CAM_ACTUATOR, "last reqest to flush is %lld", + flush_req->req_id); + } + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { i2c_set = &(a_ctrl->i2c_data.per_frame[i]); @@ -896,9 +929,7 @@ int32_t cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush_req) continue; if (i2c_set->is_settings_valid == 1) { - mutex_lock(&(a_ctrl->actuator_mutex)); rc = delete_request(i2c_set); - mutex_unlock(&(a_ctrl->actuator_mutex)); if (rc < 0) CAM_ERR(CAM_ACTUATOR, "delete request: %lld rc: %d", @@ -917,5 +948,6 @@ int32_t cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush_req) CAM_DBG(CAM_ACTUATOR, "Flush request id:%lld not found in the pending list", flush_req->req_id); + mutex_unlock(&(a_ctrl->actuator_mutex)); return rc; } diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c index 7d23f900199e0c7620be4e94244f0dab721b05dd..89e4df4234ce1204fe335090c00f94be37833c2f 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c @@ -209,12 +209,14 @@ static int32_t cam_actuator_driver_i2c_probe(struct i2c_client *client, INIT_LIST_HEAD(&(a_ctrl->i2c_data.per_frame[i].list_head)); a_ctrl->bridge_intf.device_hdl = -1; + a_ctrl->bridge_intf.link_hdl = -1; a_ctrl->bridge_intf.ops.get_dev_info = cam_actuator_publish_dev_info; a_ctrl->bridge_intf.ops.link_setup = cam_actuator_establish_link; a_ctrl->bridge_intf.ops.apply_req = cam_actuator_apply_request; + a_ctrl->last_flush_req = 0; v4l2_set_subdevdata(&(a_ctrl->v4l2_dev_str.sd), a_ctrl); @@ -363,6 +365,7 @@ static int32_t cam_actuator_driver_platform_probe( goto free_mem; a_ctrl->bridge_intf.device_hdl = -1; + a_ctrl->bridge_intf.link_hdl = -1; a_ctrl->bridge_intf.ops.get_dev_info = cam_actuator_publish_dev_info; a_ctrl->bridge_intf.ops.link_setup = @@ -371,6 +374,7 @@ static int32_t cam_actuator_driver_platform_probe( cam_actuator_apply_request; a_ctrl->bridge_intf.ops.flush_req = cam_actuator_flush_request; + a_ctrl->last_flush_req = 0; platform_set_drvdata(pdev, a_ctrl); v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, a_ctrl); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h index 8847f77e393b859b4844bd320665b658d55da03f..36b2994b9d7137a4acf5d2258ae4aa2a4c9aa932 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.h @@ -108,6 +108,7 @@ struct intf_params { * @act_info: Sensor query cap structure * @of_node: Node ptr * @device_name: Device name + * @last_flush_req: Last request to flush */ struct cam_actuator_ctrl_t { struct i2c_driver *i2c_driver; @@ -125,6 +126,7 @@ struct cam_actuator_ctrl_t { struct cam_actuator_query_cap act_info; struct intf_params bridge_intf; char device_name[20]; + uint32_t last_flush_req; }; #endif /* _CAM_ACTUATOR_DEV_H_ */ diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c index 80dc2711aa15243454b70446606866aebdc8602a..b0e810711c5d1502fa9b4f9370f2ff38cc4d7a3b 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c @@ -869,7 +869,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, struct cam_cci_ctrl *c_ctrl) { int32_t rc = 0; - uint32_t val = 0, i = 0, j = 0; + uint32_t val = 0, i = 0, j = 0, irq_mask_update = 0; unsigned long rem_jiffies, flags; int32_t read_words = 0, exp_words = 0; int32_t index = 0, first_byte = 0, total_read_words = 0; @@ -1048,13 +1048,20 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, j, total_read_words); spin_lock_irqsave(&cci_dev->lock_status, flags); - if (cci_dev->irq_status1) { - CAM_DBG(CAM_CCI, "clear irq_status1:%x", - cci_dev->irq_status1); - cam_io_w_mb(cci_dev->irq_status1, - base + CCI_IRQ_CLEAR_1_ADDR); - cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); - cci_dev->irq_status1 = 0; + if (cci_dev->irqs_disabled) { + irq_mask_update = + cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR) | + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + if (master == MASTER_0 && cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) + irq_mask_update |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + else if (master == MASTER_1 && cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) + irq_mask_update |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + cam_io_w_mb(irq_mask_update, + base + CCI_IRQ_MASK_1_ADDR); } spin_unlock_irqrestore(&cci_dev->lock_status, flags); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c index 3e1c5e19ec248b33767b6f61af8d93da70867c77..6ac042c83604bc5a9493b7cb318feb32318620ed 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -60,8 +60,8 @@ static long cam_cci_subdev_compat_ioctl(struct v4l2_subdev *sd, irqreturn_t cam_cci_irq(int irq_num, void *data) { - uint32_t irq_status0 = 0; - uint32_t irq_status1 = 0; + uint32_t irq_status0, irq_status1, reg_bmsk; + uint32_t irq_update_rd_done = 0; struct cci_device *cci_dev = data; struct cam_hw_soc_info *soc_info = &cci_dev->soc_info; @@ -143,6 +143,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) &cci_dev->cci_master_info[MASTER_0].lock_q[QUEUE_1], flags); } + rd_done_th_assert = false; if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) && (irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD)) { cci_dev->cci_master_info[MASTER_1].status = 0; @@ -225,19 +226,67 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); CAM_DBG(CAM_CCI, "MASTER_1 error 0x%x", irq_status0); + } - if ((rd_done_th_assert) || (!cci_dev->is_burst_read)) { - cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR); - CAM_DBG(CAM_CCI, "clear irq_status0:%x irq_status1:%x", - irq_status0, irq_status1); - } else { + cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); + + reg_bmsk = CCI_IRQ_MASK_1_RMSK; + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && + !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK)) { + reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; spin_lock_irqsave(&cci_dev->lock_status, flags); - cci_dev->irq_status1 |= irq_status1; + cci_dev->irqs_disabled |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; spin_unlock_irqrestore(&cci_dev->lock_status, flags); } - cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); + if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && + !(irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK)) { + reg_bmsk &= ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + spin_lock_irqsave(&cci_dev->lock_status, flags); + cci_dev->irqs_disabled |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + + if (reg_bmsk != CCI_IRQ_MASK_1_RMSK) { + cam_io_w_mb(reg_bmsk, base + CCI_IRQ_MASK_1_ADDR); + CAM_DBG(CAM_CCI, "Updating the reg mask for irq1: 0x%x", + reg_bmsk); + } else if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK || + irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) { + spin_lock_irqsave(&cci_dev->lock_status, flags); + if (cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) { + irq_update_rd_done |= + CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + cci_dev->irqs_disabled &= + ~CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD; + } + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) { + spin_lock_irqsave(&cci_dev->lock_status, flags); + if (cci_dev->irqs_disabled & + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) { + irq_update_rd_done |= + CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + cci_dev->irqs_disabled &= + ~CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD; + } + spin_unlock_irqrestore(&cci_dev->lock_status, flags); + } + } + + if (irq_update_rd_done != 0) { + irq_update_rd_done |= cam_io_r_mb(base + CCI_IRQ_MASK_1_ADDR); + cam_io_w_mb(irq_update_rd_done, base + CCI_IRQ_MASK_1_ADDR); + } + + + cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR); cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR); return IRQ_HANDLED; } diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h index eee2da11d2119db831e3321155a2bb2e7647617c..12abeabe0a380f9f954ae0548011193f3467df2a 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -200,6 +200,7 @@ enum cam_cci_state_t { * @lock_status: to protect changes to irq_status1 * @is_burst_read: Flag to determine if we are performing * a burst read operation or not + * @irqs_disabled: Mask for IRQs that are disabled */ struct cci_device { struct v4l2_subdev subdev; @@ -227,6 +228,7 @@ struct cci_device { uint32_t irq_status1; spinlock_t lock_status; bool is_burst_read; + uint32_t irqs_disabled; }; enum cam_cci_i2c_cmd_type { diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 2ffda23f6702e0d35efadda0185549c198e0fa17..99a1663ad244c5f6844fbecd501871d5f71da9b1 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -819,9 +819,11 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, rc = cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_SECURE, offset); - if (rc < 0) + if (rc < 0) { csiphy_dev->csiphy_info.secure_mode[offset] = CAM_SECURE_MODE_NON_SECURE; + goto release_mutex; + } } rc = cam_csiphy_enable_hw(csiphy_dev); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 0b9f52f9d3336dc8e39d1f05bb7a34158f7ed6c9..0902601cebd57dc8c1f030bf65a8c800a92c21cf 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -14,6 +14,7 @@ #include "cam_csiphy_core.h" #include "include/cam_csiphy_1_1_hwreg.h" #include "include/cam_csiphy_1_0_hwreg.h" +#include "include/cam_csiphy_1_2_hwreg.h" #include "include/cam_csiphy_2_0_hwreg.h" #define BYTES_PER_REGISTER 4 @@ -193,6 +194,22 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; csiphy_dev->hw_version = CSIPHY_VERSION_V11; csiphy_dev->clk_lane = 0; + } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW; + csiphy_dev->hw_version = CSIPHY_VERSION_V12; + csiphy_dev->clk_lane = 0; } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 972fff99b8e816b889d8ad7f1ca1808bac24bba3..68ca68ced31b6466a13cbe92858e699c0f6e567a 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -37,6 +37,7 @@ #define CSIPHY_VERSION_V35 0x35 #define CSIPHY_VERSION_V10 0x10 #define CSIPHY_VERSION_V11 0x11 +#define CSIPHY_VERSION_V12 0x12 #define CSIPHY_VERSION_V20 0x20 /** diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h new file mode 100644 index 0000000000000000000000000000000000000000..2bd3f89f27356b317ae8a0bdcc541ebb656d89d2 --- /dev/null +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -0,0 +1,399 @@ +/* Copyright (c) 2018, 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. + */ + +#ifndef _CAM_CSIPHY_1_2_HWREG_H_ +#define _CAM_CSIPHY_1_2_HWREG_H_ + +#include "../cam_csiphy_dev.h" + +struct csiphy_reg_parms_t csiphy_v1_2 = { + .mipi_csiphy_interrupt_status0_addr = 0x8B0, + .mipi_csiphy_interrupt_clear0_addr = 0x858, + .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_common_array_size = 4, + .csiphy_reset_array_size = 4, + .csiphy_2ph_config_array_size = 21, + .csiphy_3ph_config_array_size = 31, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, +}; + +struct csiphy_reg_t csiphy_common_reg_1_2[] = { + {0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE}, + {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_reset_reg_1_2[] = { + {0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE}, + {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_reg_t csiphy_irq_reg_1_2[] = { + {0x082c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0xFB, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083c, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0840, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0844, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0848, 0xEF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x084c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0850, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0854, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct +csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0x16, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct csiphy_reg_t + csiphy_2ph_v1_2_combo_mode_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0910, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0900, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0908, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C80, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C88, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x07C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0x16, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A00, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A08, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x02C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B00, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B08, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C10, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x14, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x06C4, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0xD4, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060c, 0x16, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +struct +csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { + { + {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0188, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x018C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0190, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0118, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x011C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0120, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0144, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0388, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x038C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0390, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0318, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x031C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0320, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0344, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AB0, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0588, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x058C, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0590, 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0518, 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x051C, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0520, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0544, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BB0, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + +#endif /* _CAM_CSIPHY_1_2_HWREG_H_ */ diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h index 04b827f9cb7995957bc96224b1f2769a01cca421..8d7a5b58215ae7cb323a97bba05dba892f822ca3 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h @@ -23,6 +23,8 @@ struct csiphy_reg_parms_t csiphy_v2_0 = { .csiphy_reset_array_size = 3, .csiphy_2ph_config_array_size = 15, .csiphy_3ph_config_array_size = 17, + .csiphy_2ph_clock_lane = 0x1, + .csiphy_2ph_combo_ck_ln = 0x10, }; struct csiphy_reg_t csiphy_common_reg_2_0[] = { diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c index a7c74dc07484c711466c44ebf445dd3747be4b2b..589dbea1c9200c6e03073bb5a3afa576cf040cfc 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c @@ -204,6 +204,7 @@ int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl, "Enable Regulator Failed rc = %d", rc); return rc; } + fctrl->last_flush_req = 0; } if (!regulator_enable) { @@ -394,6 +395,9 @@ int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush) mutex_lock(&fctrl->flash_mutex); if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + fctrl->last_flush_req = flush->req_id; + CAM_DBG(CAM_FLASH, "last reqest to flush is %lld", + flush->req_id); rc = fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); if (rc) { CAM_ERR(CAM_FLASH, "FLUSH_TYPE_ALL failed rc: %d", rc); @@ -729,12 +733,7 @@ int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, fctrl->flash_state); return -EINVAL; } - rc = cam_flash_prepare(fctrl, true); - if (rc) { - CAM_ERR(CAM_FLASH, - "Enable Regulator Failed rc = %d", rc); - return rc; - } + rc = cam_flash_high(fctrl, flash_data); if (rc) CAM_ERR(CAM_FLASH, @@ -749,12 +748,7 @@ int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, fctrl->flash_state); return -EINVAL; } - rc = cam_flash_prepare(fctrl, true); - if (rc) { - CAM_ERR(CAM_FLASH, - "Enable Regulator Failed rc = %d", rc); - return rc; - } + rc = cam_flash_low(fctrl, flash_data); if (rc) CAM_ERR(CAM_FLASH, @@ -769,15 +763,6 @@ int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, rc); return rc; } - if ((fctrl->flash_state == - CAM_FLASH_STATE_START) && - (fctrl->is_regulator_enabled == true)) { - rc = cam_flash_prepare(fctrl, false); - if (rc) - CAM_ERR(CAM_FLASH, - "Disable Regulator failed: %d", - rc); - } } } else if (fctrl->nrt_info.cmn_attr.cmd_type == CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) { @@ -956,6 +941,20 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) /* Add offset to the flash csl header */ csl_packet = (struct cam_packet *)(generic_ptr + config.offset); + + if ((csl_packet->header.op_code & 0xFFFFFF) != + CAM_FLASH_PACKET_OPCODE_INIT && + csl_packet->header.request_id <= fctrl->last_flush_req + && fctrl->last_flush_req != 0) { + CAM_DBG(CAM_FLASH, + "reject request %lld, last request to flush %lld", + csl_packet->header.request_id, fctrl->last_flush_req); + return -EINVAL; + } + + if (csl_packet->header.request_id > fctrl->last_flush_req) + fctrl->last_flush_req = 0; + switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_FLASH_PACKET_OPCODE_INIT: { /* INIT packet*/ @@ -1227,7 +1226,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) struct cam_cmd_buf_desc *cmd_desc = NULL; struct common_header *cmn_hdr; struct cam_config_dev_cmd config; - struct cam_req_mgr_add_request add_req; + struct cam_req_mgr_add_request add_req = {0}; struct cam_flash_init *cam_flash_info = NULL; struct cam_flash_set_rer *flash_rer_info = NULL; struct cam_flash_set_on_off *flash_operation_info = NULL; @@ -1270,6 +1269,19 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) /* Add offset to the flash csl header */ csl_packet = (struct cam_packet *)(generic_ptr + config.offset); + if ((csl_packet->header.op_code & 0xFFFFFF) != + CAM_FLASH_PACKET_OPCODE_INIT && + csl_packet->header.request_id <= fctrl->last_flush_req + && fctrl->last_flush_req != 0) { + CAM_DBG(CAM_FLASH, + "reject request %lld, last request to flush %lld", + csl_packet->header.request_id, fctrl->last_flush_req); + return -EINVAL; + } + + if (csl_packet->header.request_id > fctrl->last_flush_req) + fctrl->last_flush_req = 0; + switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_FLASH_PACKET_OPCODE_INIT: { /* INIT packet*/ @@ -1391,6 +1403,9 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) for (i = 0; i < flash_operation_info->count; i++) flash_data->led_current_ma[i] = flash_operation_info->led_current_ma[i]; + + if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) + add_req.skip_before_applying |= SKIP_NEXT_FRAME; } break; default: @@ -1529,7 +1544,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) if ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS) - add_req.skip_before_applying = 1; + add_req.skip_before_applying |= 1; else add_req.skip_before_applying = 0; @@ -1589,6 +1604,7 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl) fctrl->bridge_intf.device_hdl = -1; fctrl->bridge_intf.link_hdl = -1; fctrl->bridge_intf.session_hdl = -1; + fctrl->last_flush_req = 0; } return rc; @@ -1603,9 +1619,7 @@ void cam_flash_shutdown(struct cam_flash_ctrl *fctrl) if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || (fctrl->flash_state == CAM_FLASH_STATE_START)) { - mutex_lock(&(fctrl->flash_mutex)); fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); - mutex_unlock(&(fctrl->flash_mutex)); rc = fctrl->func_tbl.power_ops(fctrl, false); if (rc) CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d", diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c index 199b50502cad026c72765d4344beab48e4a0ee3c..55482ae3c1f00f7f776eb01603f106bdac10f3d7 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -107,6 +107,15 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, goto release_mutex; } + if (fctrl->bridge_intf.link_hdl != -1) { + CAM_ERR(CAM_SENSOR, + "Device [%d] still active on link 0x%x", + fctrl->flash_state, + fctrl->bridge_intf.link_hdl); + rc = -EAGAIN; + goto release_mutex; + } + if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) || (fctrl->flash_state == CAM_FLASH_STATE_START)) fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); @@ -170,6 +179,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, } fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0); + fctrl->last_flush_req = 0; fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE; break; } @@ -466,10 +476,12 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) } fctrl->bridge_intf.device_hdl = -1; + fctrl->bridge_intf.link_hdl = -1; fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info; fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link; fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request; fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request; + fctrl->last_flush_req = 0; mutex_init(&(fctrl->flash_mutex)); @@ -551,10 +563,12 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request; fctrl->bridge_intf.device_hdl = -1; + fctrl->bridge_intf.link_hdl = -1; fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info; fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link; fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request; fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request; + fctrl->last_flush_req = 0; mutex_init(&(fctrl->flash_mutex)); fctrl->flash_state = CAM_FLASH_STATE_INIT; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h index 3c8fd3e2d33ec85f42defc0fe002a568a69ea917..c7de59c9307931d89262b447dd9b3b69665e1eee 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -183,6 +183,7 @@ struct cam_flash_func_tbl { * @cci_i2c_master : I2C structure * @io_master_info : Information about the communication master * @i2c_data : I2C register settings + * @last_flush_req : last request to flush */ struct cam_flash_ctrl { struct cam_hw_soc_info soc_info; @@ -208,6 +209,7 @@ struct cam_flash_ctrl { enum cci_i2c_master_t cci_i2c_master; struct camera_io_master io_master_info; struct i2c_data_settings i2c_data; + uint32_t last_flush_req; }; int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c index 4aae41e70fe1f3cc0113c8fd0a19c58c7f8e42b8..242dbcbccd47a8ef6a1e43b1e848ad9603644c7c 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -126,6 +126,19 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, return -EINVAL; } + if ((csl_packet->header.op_code & 0xFFFFFF) != + CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG && + csl_packet->header.request_id <= s_ctrl->last_flush_req + && s_ctrl->last_flush_req != 0) { + CAM_DBG(CAM_SENSOR, + "reject request %lld, last request to flush %lld", + csl_packet->header.request_id, s_ctrl->last_flush_req); + return -EINVAL; + } + + if (csl_packet->header.request_id > s_ctrl->last_flush_req) + s_ctrl->last_flush_req = 0; + i2c_data = &(s_ctrl->i2c_data); CAM_DBG(CAM_SENSOR, "Header OpCode: %d", csl_packet->header.op_code); switch (csl_packet->header.op_code & 0xFFFFFF) { @@ -327,14 +340,18 @@ int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info, probe_info->expected_data; s_ctrl->sensordata->slave_info.sensor_id_mask = probe_info->data_mask; + /* Userspace passes the pipeline delay in reserved field */ + s_ctrl->pipeline_delay = + probe_info->reserved; s_ctrl->sensor_probe_addr_type = probe_info->addr_type; s_ctrl->sensor_probe_data_type = probe_info->data_type; CAM_DBG(CAM_SENSOR, - "Sensor Addr: 0x%x sensor_id: 0x%x sensor_mask: 0x%x", + "Sensor Addr: 0x%x sensor_id: 0x%x sensor_mask: 0x%x sensor_pipeline_delay:0x%x", s_ctrl->sensordata->slave_info.sensor_id_reg_addr, s_ctrl->sensordata->slave_info.sensor_id, - s_ctrl->sensordata->slave_info.sensor_id_mask); + s_ctrl->sensordata->slave_info.sensor_id_mask, + s_ctrl->pipeline_delay); return rc; } @@ -504,6 +521,7 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl) s_ctrl->streamon_count = 0; s_ctrl->streamoff_count = 0; s_ctrl->is_probe_succeed = 0; + s_ctrl->last_flush_req = 0; s_ctrl->sensor_state = CAM_SENSOR_INIT; } @@ -690,6 +708,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, } s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; + s_ctrl->last_flush_req = 0; CAM_INFO(CAM_SENSOR, "CAM_ACQUIRE_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", s_ctrl->sensordata->slave_info.sensor_id, @@ -706,6 +725,15 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, goto release_mutex; } + if (s_ctrl->bridge_intf.link_hdl != -1) { + CAM_ERR(CAM_SENSOR, + "Device [%d] still active on link 0x%x", + s_ctrl->sensor_state, + s_ctrl->bridge_intf.link_hdl); + rc = -EAGAIN; + goto release_mutex; + } + rc = cam_sensor_power_down(s_ctrl); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Sensor Power Down failed"); @@ -737,6 +765,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, s_ctrl->sensordata->slave_info.sensor_slave_addr); s_ctrl->streamon_count = 0; s_ctrl->streamoff_count = 0; + s_ctrl->last_flush_req = 0; } break; case CAM_QUERY_CAP: { @@ -798,6 +827,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, } cam_sensor_release_per_frame_resource(s_ctrl); + s_ctrl->last_flush_req = 0; s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; CAM_INFO(CAM_SENSOR, "CAM_STOP_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", @@ -874,13 +904,25 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info) { int rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; if (!info) return -EINVAL; + s_ctrl = (struct cam_sensor_ctrl_t *) + cam_get_device_priv(info->dev_hdl); + + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "Device data is NULL"); + return -EINVAL; + } + info->dev_id = CAM_REQ_MGR_DEVICE_SENSOR; strlcpy(info->name, CAM_SENSOR_NAME, sizeof(info->name)); - info->p_delay = 2; + if (s_ctrl->pipeline_delay >= 1 && s_ctrl->pipeline_delay <= 3) + info->p_delay = s_ctrl->pipeline_delay; + else + info->p_delay = 2; info->trigger = CAM_TRIGGER_POINT_SOF; return rc; @@ -1168,6 +1210,13 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) return -EINVAL; } + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + s_ctrl->last_flush_req = flush_req->req_id; + CAM_DBG(CAM_SENSOR, "last reqest to flush is %lld", + flush_req->req_id); + } + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { i2c_set = &(s_ctrl->i2c_data.per_frame[i]); @@ -1176,9 +1225,7 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) continue; if (i2c_set->is_settings_valid == 1) { - mutex_lock(&(s_ctrl->cam_sensor_mutex)); rc = delete_request(i2c_set); - mutex_unlock(&(s_ctrl->cam_sensor_mutex)); if (rc < 0) CAM_ERR(CAM_SENSOR, "delete request: %lld rc: %d", @@ -1197,5 +1244,6 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) CAM_DBG(CAM_SENSOR, "Flush request id:%lld not found in the pending list", flush_req->req_id); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); return rc; } diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 6cf40f8b0f1086b94de3b299965eb065cb239ae8..8dcb6c73312f8ba92d8b1bee75b8c3cc2c170ae3 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -162,6 +162,7 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, s_ctrl->of_node = client->dev.of_node; s_ctrl->io_master_info.master_type = I2C_MASTER; s_ctrl->is_probe_succeed = 0; + s_ctrl->last_flush_req = 0; rc = cam_sensor_parse_dt(s_ctrl); if (rc < 0) { @@ -191,6 +192,7 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); s_ctrl->bridge_intf.device_hdl = -1; + s_ctrl->bridge_intf.link_hdl = -1; s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; @@ -275,6 +277,7 @@ static int32_t cam_sensor_driver_platform_probe( /* Initialize sensor device type */ s_ctrl->of_node = pdev->dev.of_node; s_ctrl->is_probe_succeed = 0; + s_ctrl->last_flush_req = 0; /*fill in platform device*/ s_ctrl->pdev = pdev; @@ -312,6 +315,7 @@ static int32_t cam_sensor_driver_platform_probe( INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); s_ctrl->bridge_intf.device_hdl = -1; + s_ctrl->bridge_intf.link_hdl = -1; s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h index 8339d9b12de3a5991df5258d1f8f9da17c1070fe..e98a592dd5ea6a8cd9759b85fe934ede5a4d6e2a 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h @@ -94,6 +94,8 @@ struct intf_params { * @streamoff_count: Count to hold the number of times stream off called * @bob_reg_index: Hold to BoB regulator index * @bob_pwm_switch: Boolean flag to switch into PWM mode for BoB regulator + * @last_flush_req: Last request to flush + * @pipeline_delay: Sensor pipeline delay */ struct cam_sensor_ctrl_t { struct platform_device *pdev; @@ -118,6 +120,8 @@ struct cam_sensor_ctrl_t { uint32_t streamoff_count; int bob_reg_index; bool bob_pwm_switch; + uint32_t last_flush_req; + uint16_t pipeline_delay; }; #endif /* _CAM_SENSOR_DEV_H_ */ diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c index 242b1aafdc03987eed74536717ce6497acb2c66a..c70a87d0bba312572f76f90b161e1fdd5b53ea0c 100644 --- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c +++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c @@ -531,7 +531,7 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, } if (++iommu_cb_set.cb_info[idx].pf_count > g_num_pf_handled) { - CAM_INFO(CAM_SMMU, "PF already handled %d %d %d", + CAM_INFO_RATE_LIMIT(CAM_SMMU, "PF already handled %d %d %d", g_num_pf_handled, idx, iommu_cb_set.cb_info[idx].pf_count); return -EINVAL; @@ -1927,6 +1927,25 @@ static enum cam_smmu_buf_state cam_smmu_check_secure_fd_in_list(int idx, { struct cam_sec_buff_info *mapping; + list_for_each_entry(mapping, + &iommu_cb_set.cb_info[idx].smmu_buf_list, + list) { + if (mapping->ion_fd == ion_fd) { + *paddr_ptr = mapping->paddr; + *len_ptr = mapping->len; + mapping->ref_count++; + return CAM_SMMU_BUFF_EXIST; + } + } + + return CAM_SMMU_BUFF_NOT_EXIST; +} + +static enum cam_smmu_buf_state cam_smmu_validate_secure_fd_in_list(int idx, + int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr) +{ + struct cam_sec_buff_info *mapping; + list_for_each_entry(mapping, &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { @@ -2541,6 +2560,16 @@ int cam_smmu_unmap_stage2_iova(int handle, int ion_fd) goto put_addr_end; } + mapping_info->ref_count--; + if (mapping_info->ref_count > 0) { + CAM_DBG(CAM_SMMU, + "idx: %d fd = %d ref_count: %d", + idx, ion_fd, mapping_info->ref_count); + rc = 0; + goto put_addr_end; + } + mapping_info->ref_count = 0; + /* unmapping one buffer from device */ rc = cam_smmu_secure_unmap_buf_and_remove_from_list(mapping_info, idx); if (rc) { @@ -2816,7 +2845,7 @@ int cam_smmu_get_stage2_iova(int handle, int ion_fd, goto get_addr_end; } - buf_state = cam_smmu_check_secure_fd_in_list(idx, + buf_state = cam_smmu_validate_secure_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr); diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c index 4525bb5bce25448543ae5992f5f47fb3f850d21e..33bbadae2f95f355a7795ddde9f5c63a03017b0b 100644 --- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c +++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c @@ -65,7 +65,6 @@ int cam_sync_register_callback(sync_callback cb_func, void *userdata, int32_t sync_obj) { struct sync_callback_info *sync_cb; - struct sync_callback_info *cb_info; struct sync_table_row *row = NULL; int status = 0; @@ -83,17 +82,6 @@ int cam_sync_register_callback(sync_callback cb_func, return -EINVAL; } - /* Don't register if callback was registered earlier */ - list_for_each_entry(cb_info, &row->callback_list, list) { - if (cb_info->callback_func == cb_func && - cb_info->cb_data == userdata) { - CAM_ERR(CAM_SYNC, "Duplicate register for sync_obj %d", - sync_obj); - spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); - return -EALREADY; - } - } - sync_cb = kzalloc(sizeof(*sync_cb), GFP_ATOMIC); if (!sync_cb) { spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c index 0a059184311d21faf418f126193509d8eb05230a..5666218af76ebdde589e6c14ac560d0e1e7d214d 100644 --- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c +++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c @@ -178,7 +178,7 @@ int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) } if (row->state == CAM_SYNC_STATE_ACTIVE) - CAM_WARN(CAM_SYNC, + CAM_DBG(CAM_SYNC, "Destroying an active sync object name:%s id:%i", row->name, row->sync_id); @@ -225,7 +225,7 @@ int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) } if (child_row->state == CAM_SYNC_STATE_ACTIVE) - CAM_WARN(CAM_SYNC, + CAM_DBG(CAM_SYNC, "Warning: destroying active child sync obj = %d", child_info->sync_id); @@ -254,7 +254,7 @@ int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) } if (parent_row->state == CAM_SYNC_STATE_ACTIVE) - CAM_WARN(CAM_SYNC, + CAM_DBG(CAM_SYNC, "Warning: destroying active parent sync obj = %d", parent_info->sync_id); diff --git a/drivers/media/platform/msm/npu/npu_dev.c b/drivers/media/platform/msm/npu/npu_dev.c index 601a3213b99e233a8ecf754e138127b90256da0f..1a44fd251d8748618e720d94ade7b5e4672bd1ff 100644 --- a/drivers/media/platform/msm/npu/npu_dev.c +++ b/drivers/media/platform/msm/npu/npu_dev.c @@ -957,7 +957,7 @@ static int npu_load_network(struct npu_client *client, ret = npu_host_load_network(client, &req); if (ret) { - pr_err("network load failed: %d\n", ret); + pr_err("npu_host_load_network failed %d\n", ret); return ret; } @@ -1014,7 +1014,7 @@ static int npu_load_network_v2(struct npu_client *client, kfree(patch_info); if (ret) { - pr_err("network load failed: %d\n", ret); + pr_err("npu_host_load_network_v2 failed %d\n", ret); return ret; } @@ -1046,7 +1046,7 @@ static int npu_unload_network(struct npu_client *client, ret = npu_host_unload_network(client, &req); if (ret) { - pr_err("npu_host_unload_network failed\n"); + pr_err("npu_host_unload_network failed %d\n", ret); return ret; } @@ -1084,7 +1084,7 @@ static int npu_exec_network(struct npu_client *client, ret = npu_host_exec_network(client, &req); if (ret) { - pr_err("npu_host_exec_network failed\n"); + pr_err("npu_host_exec_network failed %d\n", ret); return ret; } @@ -1143,7 +1143,7 @@ static int npu_exec_network_v2(struct npu_client *client, kfree(patch_buf_info); if (ret) { - pr_err("npu_host_exec_network failed\n"); + pr_err("npu_host_exec_network_v2 failed %d\n", ret); return ret; } @@ -1529,7 +1529,6 @@ static int npu_mbox_init(struct npu_device *npu_dev) { struct platform_device *pdev = npu_dev->pdev; struct npu_mbox *mbox_aop = &npu_dev->mbox_aop; - int ret = 0; if (of_find_property(pdev->dev.of_node, "mboxes", NULL)) { mbox_aop->client.dev = &pdev->dev; @@ -1539,13 +1538,12 @@ static int npu_mbox_init(struct npu_device *npu_dev) mbox_aop->chan = mbox_request_channel(&mbox_aop->client, 0); if (IS_ERR(mbox_aop->chan)) { - ret = PTR_ERR(mbox_aop->chan); - pr_err("mailbox channel request failed, ret=%d\n", ret); + pr_warn("mailbox channel request failed\n"); mbox_aop->chan = NULL; } } - return ret; + return 0; } /* ------------------------------------------------------------------------- diff --git a/drivers/media/platform/msm/npu/npu_host_ipc.c b/drivers/media/platform/msm/npu/npu_host_ipc.c index 0730e2019edca11eeabbee2ccc86165d70a99e44..ac2c28981e7f16d0d2d672791554085b4915ca75 100644 --- a/drivers/media/platform/msm/npu/npu_host_ipc.c +++ b/drivers/media/platform/msm/npu/npu_host_ipc.c @@ -156,15 +156,17 @@ static int npu_host_ipc_send_cmd_hfi(struct npu_device *npu_dev, { int status = 0; uint8_t is_rx_req_set = 0; + uint32_t retry_cnt = 5; status = ipc_queue_write(npu_dev, q_idx, (uint8_t *)cmd_ptr, &is_rx_req_set); if (status == -ENOSPC) { - while (status == -ENOSPC) { + do { + msleep(20); status = ipc_queue_write(npu_dev, q_idx, (uint8_t *)cmd_ptr, &is_rx_req_set); - } + } while ((status == -ENOSPC) && (--retry_cnt > 0)); } if (status == 0) { diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index 1d3bc832d20a6d01be62d9a7779f2b83a03bfac5..d684ae47294ee4231cb75a027c4e6f29cc3148cd 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -46,15 +46,18 @@ static int wait_for_status_ready(struct npu_device *npu_dev, static struct npu_network *alloc_network(struct npu_host_ctx *ctx, struct npu_client *client); static struct npu_network *get_network_by_hdl(struct npu_host_ctx *ctx, - uint32_t hdl); + struct npu_client *client, uint32_t hdl); static struct npu_network *get_network_by_id(struct npu_host_ctx *ctx, + struct npu_client *client, int64_t id); +static void free_network(struct npu_host_ctx *ctx, struct npu_client *client, int64_t id); -static void free_network(struct npu_host_ctx *ctx, int64_t id); +static int network_get(struct npu_network *network); +static int network_put(struct npu_network *network); static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg); static void log_msg_proc(struct npu_device *npu_dev, uint32_t *msg); static void host_session_msg_hdlr(struct npu_device *npu_dev); static void host_session_log_hdlr(struct npu_device *npu_dev); -static int host_error_hdlr(struct npu_device *npu_dev); +static int host_error_hdlr(struct npu_device *npu_dev, bool force); static int npu_send_network_cmd(struct npu_device *npu_dev, struct npu_network *network, void *cmd_ptr, bool async); static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx, @@ -322,14 +325,15 @@ irqreturn_t npu_intr_hdler(int irq, void *ptr) * Function Definitions - Control * ------------------------------------------------------------------------- */ -static int host_error_hdlr(struct npu_device *npu_dev) +static int host_error_hdlr(struct npu_device *npu_dev, bool force) { struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; struct npu_network *network = NULL; struct npu_kevent kevt; int i; - if ((host_ctx->wdg_irq_sts == 0) && (host_ctx->err_irq_sts == 0)) + if ((host_ctx->wdg_irq_sts == 0) && (host_ctx->err_irq_sts == 0) + && !force) return 0; if (host_ctx->wdg_irq_sts) @@ -340,6 +344,7 @@ static int host_error_hdlr(struct npu_device *npu_dev) host_ctx->err_irq_sts = 0; /* flush all pending npu cmds */ + mutex_lock(&host_ctx->lock); for (i = 0; i < MAX_LOADED_NETWORK; i++) { network = &host_ctx->networks[i]; if (network->is_valid && network->cmd_pending && @@ -358,6 +363,7 @@ static int host_error_hdlr(struct npu_device *npu_dev) } } complete_all(&host_ctx->loopback_done); + mutex_unlock(&host_ctx->lock); return 1; } @@ -370,7 +376,7 @@ static void host_irq_wq(struct work_struct *work) host_ctx = container_of(work, struct npu_host_ctx, irq_work); npu_dev = container_of(host_ctx, struct npu_device, host_ctx); - if (host_error_hdlr(npu_dev)) + if (host_error_hdlr(npu_dev, false)) return; host_session_log_hdlr(npu_dev); @@ -488,86 +494,129 @@ static int npu_notify_aop(struct npu_device *npu_dev, bool on) * Function Definitions - Network Management * ------------------------------------------------------------------------- */ +static int network_put(struct npu_network *network) +{ + if (!network) + return 0; + + return atomic_dec_return(&network->ref_cnt); +} + +static int network_get(struct npu_network *network) +{ + if (!network) + return 0; + + return atomic_inc_return(&network->ref_cnt); +} + static struct npu_network *alloc_network(struct npu_host_ctx *ctx, struct npu_client *client) { int32_t i; struct npu_network *network = ctx->networks; - mutex_lock(&ctx->lock); + WARN_ON(!mutex_is_locked(&ctx->lock)); + for (i = 0; i < MAX_LOADED_NETWORK; i++) { - if (network->id == 0) { - network->id = i + 1; - network->network_hdl = 0; + if (network->id == 0) break; - } + network++; } - if (i >= MAX_LOADED_NETWORK) - network = NULL; - else - ctx->network_num++; - mutex_unlock(&ctx->lock); - if (network) { - init_completion(&network->cmd_done); - network->is_valid = true; - network->fw_error = false; - network->cmd_pending = false; - network->client = client; - network->stats_buf = kzalloc(NPU_MAX_STATS_BUF_SIZE, - GFP_KERNEL); - if (!network->stats_buf) { - free_network(ctx, network->id); - network = NULL; - } + if (i == MAX_LOADED_NETWORK) { + pr_err("No free network\n"); + return NULL; + } + + memset(network, 0, sizeof(struct npu_network)); + network->id = i + 1; + init_completion(&network->cmd_done); + network->is_valid = true; + network->client = client; + network->stats_buf = kzalloc(NPU_MAX_STATS_BUF_SIZE, + GFP_KERNEL); + if (!network->stats_buf) { + memset(network, 0, sizeof(struct npu_network)); + return NULL; } + ctx->network_num++; return network; } static struct npu_network *get_network_by_hdl(struct npu_host_ctx *ctx, - uint32_t hdl) + struct npu_client *client, uint32_t hdl) { int32_t i; struct npu_network *network = ctx->networks; + WARN_ON(!mutex_is_locked(&ctx->lock)); + for (i = 0; i < MAX_LOADED_NETWORK; i++) { if (network->network_hdl == hdl) break; network++; } + if ((i == MAX_LOADED_NETWORK) || !network->is_valid) { pr_err("network hdl invalid %d\n", hdl); - network = NULL; + return NULL; } + if (client && (client != network->client)) { + pr_err("network %d doesn't belong to this client\n", + network->id); + return NULL; + } + + network_get(network); return network; } static struct npu_network *get_network_by_id(struct npu_host_ctx *ctx, - int64_t id) + struct npu_client *client, int64_t id) { + struct npu_network *network = NULL; + + WARN_ON(!mutex_is_locked(&ctx->lock)); + if (id < 1 || id > MAX_LOADED_NETWORK || !ctx->networks[id - 1].is_valid) { - pr_err("network id invalid %d\n", (int32_t)id); + pr_err("Invalid network id %d\n", (int32_t)id); return NULL; } - return &ctx->networks[id - 1]; + network = &ctx->networks[id - 1]; + if (client && (client != network->client)) { + pr_err("network %d doesn't belong to this client\n", id); + return NULL; + } + + network_get(network); + return network; } -static void free_network(struct npu_host_ctx *ctx, int64_t id) +static void free_network(struct npu_host_ctx *ctx, struct npu_client *client, + int64_t id) { - struct npu_network *network = get_network_by_id(ctx, id); + struct npu_network *network = NULL; + + WARN_ON(!mutex_is_locked(&ctx->lock)); + network = get_network_by_id(ctx, client, id); if (network) { - kfree(network->stats_buf); - mutex_lock(&ctx->lock); - memset(network, 0, sizeof(struct npu_network)); - ctx->network_num--; - mutex_unlock(&ctx->lock); + network_put(network); + if (atomic_read(&network->ref_cnt) == 0) { + kfree(network->stats_buf); + memset(network, 0, sizeof(struct npu_network)); + ctx->network_num--; + } else { + pr_warn("network %d:%d is in use\n", network->id, + atomic_read(&network->ref_cnt)); + } } } @@ -617,7 +666,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) pr_debug("total_num_layers: %d\n", exe_rsp_pkt->stats.exe_stats.total_num_layers); - network = get_network_by_hdl(host_ctx, + network = get_network_by_hdl(host_ctx, NULL, exe_rsp_pkt->network_hdl); if (!network) { pr_err("can't find network %x\n", @@ -625,6 +674,14 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) break; } + if (network->trans_id != exe_rsp_pkt->header.trans_id) { + pr_err("execute_pkt trans_id is not match %d:%d\n", + network->trans_id, + exe_rsp_pkt->header.trans_id); + network_put(network); + break; + } + network->cmd_pending = false; network->cmd_ret_status = exe_rsp_pkt->header.status; @@ -640,6 +697,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) if (npu_queue_event(network->client, &kevt)) pr_err("queue npu event failed\n"); } + network_put(network); break; } @@ -653,7 +711,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) exe_rsp_pkt->header.status); pr_debug("trans_id : %d", exe_rsp_pkt->header.trans_id); - network = get_network_by_hdl(host_ctx, + network = get_network_by_hdl(host_ctx, NULL, exe_rsp_pkt->network_hdl); if (!network) { pr_err("can't find network %x\n", @@ -661,6 +719,14 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) break; } + if (network->trans_id != exe_rsp_pkt->header.trans_id) { + pr_err("execute_pkt_v2 trans_id is not match %d:%d\n", + network->trans_id, + exe_rsp_pkt->header.trans_id); + network_put(network); + break; + } + pr_debug("network id : %d", network->id); stats_size = exe_rsp_pkt->header.size - sizeof(*exe_rsp_pkt); pr_debug("stats_size %d:%d\n", exe_rsp_pkt->header.size, @@ -690,6 +756,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) } else { complete(&network->cmd_done); } + network_put(network); break; } case NPU_IPC_MSG_LOAD_DONE: @@ -708,16 +775,26 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) */ pr_debug("network_hdl: %x\n", load_rsp_pkt->network_hdl); network_id = load_rsp_pkt->network_hdl >> 16; - network = get_network_by_id(host_ctx, network_id); + network = get_network_by_id(host_ctx, NULL, network_id); if (!network) { pr_err("can't find network %d\n", network_id); break; } + + if (network->trans_id != load_rsp_pkt->header.trans_id) { + pr_err("load_rsp_pkt trans_id is not match %d:%d\n", + network->trans_id, + load_rsp_pkt->header.trans_id); + network_put(network); + break; + } + network->network_hdl = load_rsp_pkt->network_hdl; network->cmd_pending = false; network->cmd_ret_status = load_rsp_pkt->header.status; complete(&network->cmd_done); + network_put(network); break; } case NPU_IPC_MSG_UNLOAD_DONE: @@ -729,7 +806,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) unload_rsp_pkt->header.status, unload_rsp_pkt->header.trans_id); - network = get_network_by_hdl(host_ctx, + network = get_network_by_hdl(host_ctx, NULL, unload_rsp_pkt->network_hdl); if (!network) { pr_err("can't find network %x\n", @@ -737,10 +814,19 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) break; } + if (network->trans_id != unload_rsp_pkt->header.trans_id) { + pr_err("unload_rsp_pkt trans_id is not match %d:%d\n", + network->trans_id, + unload_rsp_pkt->header.trans_id); + network_put(network); + break; + } + network->cmd_pending = false; network->cmd_ret_status = unload_rsp_pkt->header.status; complete(&network->cmd_done); + network_put(network); break; } case NPU_IPC_MSG_LOOPBACK_DONE: @@ -768,10 +854,20 @@ static void host_session_msg_hdlr(struct npu_device *npu_dev) msg = kzalloc(sizeof(uint32_t) * NPU_IPC_BUF_LENGTH, GFP_KERNEL); if (!msg) return; + + mutex_lock(&host_ctx->lock); + if (host_ctx->fw_state == FW_DISABLED) { + pr_warn("handle npu session msg when FW is disabled\n"); + goto skip_read_msg; + } + while (npu_host_ipc_read_msg(npu_dev, IPC_QUEUE_APPS_RSP, msg) == 0) { pr_debug("received from msg queue\n"); app_msg_proc(host_ctx, msg); } + +skip_read_msg: + mutex_unlock(&host_ctx->lock); kfree(msg); } @@ -799,15 +895,26 @@ static void log_msg_proc(struct npu_device *npu_dev, uint32_t *msg) static void host_session_log_hdlr(struct npu_device *npu_dev) { uint32_t *msg; + struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; msg = kzalloc(sizeof(uint32_t) * NPU_IPC_BUF_LENGTH, GFP_KERNEL); if (!msg) return; + + mutex_lock(&host_ctx->lock); + if (host_ctx->fw_state == FW_DISABLED) { + pr_warn("handle npu session msg when FW is disabled\n"); + goto skip_read_msg; + } + while (npu_host_ipc_read_msg(npu_dev, IPC_QUEUE_LOG, msg) == 0) { pr_debug("received from log queue\n"); log_msg_proc(npu_dev, msg); } + +skip_read_msg: + mutex_unlock(&host_ctx->lock); kfree(msg); } @@ -855,7 +962,6 @@ static int npu_send_network_cmd(struct npu_device *npu_dev, struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; int ret = 0; - mutex_lock(&host_ctx->lock); if (network->fw_error || host_ctx->fw_error || (host_ctx->fw_state == FW_DISABLED)) { pr_err("fw is in error state or disabled, can't send network cmd\n"); @@ -870,12 +976,12 @@ static int npu_send_network_cmd(struct npu_device *npu_dev, network->cmd_async = async; network->cmd_ret_status = 0; network->cmd_pending = true; + network->trans_id = atomic_read(&host_ctx->ipc_trans_id); ret = npu_host_ipc_send_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, cmd_ptr); if (ret) network->cmd_pending = false; } - mutex_unlock(&host_ctx->lock); return ret; } @@ -975,12 +1081,14 @@ int32_t npu_host_load_network(struct npu_client *client, if (ret) return ret; + mutex_lock(&host_ctx->lock); network = alloc_network(host_ctx, client); if (!network) { ret = -ENOMEM; goto err_deinit_fw; } + network_get(network); network->buf_hdl = load_ioctl->buf_ion_hdl; network->size = load_ioctl->buf_size; network->phy_add = load_ioctl->buf_phys_addr; @@ -1021,16 +1129,26 @@ int32_t npu_host_load_network(struct npu_client *client, goto error_free_network; } - if (!wait_for_completion_interruptible_timeout( + mutex_unlock(&host_ctx->lock); + + ret = wait_for_completion_interruptible_timeout( &network->cmd_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? - NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) { - pr_err_ratelimited("npu: NPU_IPC_CMD_LOAD time out\n"); + NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); + + mutex_lock(&host_ctx->lock); + if (!ret) { + pr_err_ratelimited("NPU_IPC_CMD_LOAD time out\n"); ret = -ETIMEDOUT; goto error_free_network; - } else if (network->fw_error) { + } else if (ret < 0) { + pr_err("NPU_IPC_CMD_LOAD is interrupted by signal\n"); + goto error_free_network; + } + + if (network->fw_error) { ret = -EIO; - pr_err("load cmd returns with error\n"); + pr_err("fw is in error state during load network\n"); goto error_free_network; } @@ -1039,12 +1157,17 @@ int32_t npu_host_load_network(struct npu_client *client, goto error_free_network; load_ioctl->network_hdl = network->network_hdl; + network->is_active = true; + network_put(network); + mutex_unlock(&host_ctx->lock); return ret; error_free_network: - free_network(host_ctx, network->id); + network_put(network); + free_network(host_ctx, client, network->id); err_deinit_fw: + mutex_unlock(&host_ctx->lock); fw_deinit(npu_dev, false); return ret; } @@ -1065,12 +1188,14 @@ int32_t npu_host_load_network_v2(struct npu_client *client, if (ret) return ret; + mutex_lock(&host_ctx->lock); network = alloc_network(host_ctx, client); if (!network) { ret = -ENOMEM; goto err_deinit_fw; } + network_get(network); num_patch_params = load_ioctl->patch_info_num; pkt_size = sizeof(*load_packet) + num_patch_params * sizeof(struct npu_patch_tuple_v2); @@ -1128,16 +1253,27 @@ int32_t npu_host_load_network_v2(struct npu_client *client, goto error_free_network; } - if (!wait_for_completion_interruptible_timeout( + mutex_unlock(&host_ctx->lock); + + ret = wait_for_completion_interruptible_timeout( &network->cmd_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? - NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) { + NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); + + mutex_lock(&host_ctx->lock); + + if (!ret) { pr_err_ratelimited("npu: NPU_IPC_CMD_LOAD time out\n"); ret = -ETIMEDOUT; goto error_free_network; - } else if (network->fw_error) { + } else if (ret < 0) { + pr_err("NPU_IPC_CMD_LOAD_V2 is interrupted by signal\n"); + goto error_free_network; + } + + if (network->fw_error) { ret = -EIO; - pr_err("load cmd returns with error\n"); + pr_err("fw is in error state during load_v2 network\n"); goto error_free_network; } @@ -1146,13 +1282,18 @@ int32_t npu_host_load_network_v2(struct npu_client *client, goto error_free_network; load_ioctl->network_hdl = network->network_hdl; + network->is_active = true; + network_put(network); + mutex_unlock(&host_ctx->lock); return ret; error_free_network: kfree(load_packet); - free_network(host_ctx, network->id); + network_put(network); + free_network(host_ctx, client, network->id); err_deinit_fw: + mutex_unlock(&host_ctx->lock); fw_deinit(npu_dev, false); return ret; } @@ -1167,15 +1308,27 @@ int32_t npu_host_unload_network(struct npu_client *client, struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; /* get the corresponding network for ipc trans id purpose */ - network = get_network_by_hdl(host_ctx, unload->network_hdl); - if (!network) + mutex_lock(&host_ctx->lock); + network = get_network_by_hdl(host_ctx, client, + unload->network_hdl); + if (!network) { + mutex_unlock(&host_ctx->lock); return -EINVAL; + } + + if (!network->is_active) { + pr_err("network is not active\n"); + network_put(network); + mutex_unlock(&host_ctx->lock); + return -EINVAL; + } if (network->fw_error) { pr_err("fw in error state, skip unload network in fw\n"); - goto skip_fw; + goto free_network; } + pr_debug("Unload network %d\n", network->id); /* prepare IPC packet for UNLOAD */ unload_packet.header.cmd_type = NPU_IPC_CMD_UNLOAD; unload_packet.header.size = sizeof(struct ipc_cmd_unload_pkt); @@ -1190,23 +1343,55 @@ int32_t npu_host_unload_network(struct npu_client *client, if (ret) { pr_err("NPU_IPC_CMD_UNLOAD sent failed: %d\n", ret); - } else if (!wait_for_completion_interruptible_timeout( + /* + * If another command is running on this network, + * don't free_network now. + */ + if (ret == -EBUSY) { + pr_err("Network is running, retry later\n"); + network_put(network); + mutex_unlock(&host_ctx->lock); + return ret; + } + goto free_network; + } + + mutex_unlock(&host_ctx->lock); + + ret = wait_for_completion_interruptible_timeout( &network->cmd_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? - NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) { + NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); + + mutex_lock(&host_ctx->lock); + + if (!ret) { pr_err_ratelimited("npu: NPU_IPC_CMD_UNLOAD time out\n"); + network->cmd_pending = false; ret = -ETIMEDOUT; - } else if (network->fw_error) { + goto free_network; + } else if (ret < 0) { + pr_err("Wait for unload done interrupted by signal\n"); + network->cmd_pending = false; + goto free_network; + } + + if (network->fw_error) { ret = -EIO; - pr_err("unload cmd returns with error\n"); + pr_err("fw is in error state during unload network\n"); + } else { + ret = network->cmd_ret_status; + pr_debug("unload network status %d", ret); } -skip_fw: +free_network: /* * free the network on the kernel if the corresponding ACO * handle is unloaded on the firmware side */ - free_network(host_ctx, network->id); + network_put(network); + free_network(host_ctx, client, network->id); + mutex_unlock(&host_ctx->lock); fw_deinit(npu_dev, false); return ret; } @@ -1223,20 +1408,35 @@ int32_t npu_host_exec_network(struct npu_client *client, struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; bool async_ioctl = !!exec_ioctl->async; - network = get_network_by_hdl(host_ctx, exec_ioctl->network_hdl); + mutex_lock(&host_ctx->lock); + network = get_network_by_hdl(host_ctx, client, + exec_ioctl->network_hdl); - if (!network) + if (!network) { + mutex_unlock(&host_ctx->lock); return -EINVAL; + } - if (network->fw_error) - return -EIO; + if (!network->is_active) { + pr_err("network is not active\n"); + ret = -EINVAL; + goto exec_done; + } + + if (network->fw_error) { + pr_err("fw is in error state\n"); + ret = -EIO; + goto exec_done; + } + pr_debug("execute network %d\n", network->id); memset(&exec_packet, 0, sizeof(exec_packet)); if (exec_ioctl->patching_required) { if ((exec_ioctl->input_layer_num != 1) || (exec_ioctl->output_layer_num != 1)) { pr_err("Invalid input/output layer num\n"); - return -EINVAL; + ret = -EINVAL; + goto exec_done; } input_off = exec_ioctl->input_layers[0].buf_phys_addr; @@ -1245,7 +1445,8 @@ int32_t npu_host_exec_network(struct npu_client *client, if (!npu_mem_verify_addr(client, input_off) || !npu_mem_verify_addr(client, output_off)) { pr_err("Invalid patch buf address\n"); - return -EINVAL; + ret = -EINVAL; + goto exec_done; } exec_packet.patch_params.num_params = 2; @@ -1270,25 +1471,54 @@ int32_t npu_host_exec_network(struct npu_client *client, if (ret) { pr_err("NPU_IPC_CMD_EXECUTE sent failed: %d\n", ret); - } else if (async_ioctl) { + goto exec_done; + } + + if (async_ioctl) { pr_debug("Async ioctl, return now\n"); - } else if (!wait_for_completion_interruptible_timeout( + goto exec_done; + } + + mutex_unlock(&host_ctx->lock); + + ret = wait_for_completion_interruptible_timeout( &network->cmd_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? - NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) { + NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); + + mutex_lock(&host_ctx->lock); + if (!ret) { pr_err_ratelimited("npu: NPU_IPC_CMD_EXECUTE time out\n"); /* dump debug stats */ npu_dump_debug_timeout_stats(npu_dev); network->cmd_pending = false; - - /* treat execution timed out as ssr */ - fw_deinit(npu_dev, true); ret = -ETIMEDOUT; - } else if (network->fw_error) { + goto exec_done; + } else if (ret == -ERESTARTSYS) { + pr_err("Wait for execution done interrupted by signal\n"); + network->cmd_pending = false; + goto exec_done; + } + + if (network->fw_error) { ret = -EIO; - pr_err("execute cmd returns with error\n"); + pr_err("fw is in error state during execute network\n"); } else { ret = network->cmd_ret_status; + pr_debug("execution status %d", ret); + } + +exec_done: + network_put(network); + mutex_unlock(&host_ctx->lock); + + /* + * treat network execution timed our or interrupted by signal + * as error in order to force npu fw to stop execution + */ + if ((ret == -ETIMEDOUT) || (ret == -ERESTARTSYS)) { + pr_err("Error handling after execution failure\n"); + host_error_hdlr(npu_dev, true); } return ret; @@ -1307,21 +1537,37 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, bool async_ioctl = !!exec_ioctl->async; int i; - network = get_network_by_hdl(host_ctx, exec_ioctl->network_hdl); + mutex_lock(&host_ctx->lock); + network = get_network_by_hdl(host_ctx, client, + exec_ioctl->network_hdl); - if (!network) + if (!network) { + mutex_unlock(&host_ctx->lock); return -EINVAL; + } - if (network->fw_error) - return -EIO; + if (!network->is_active) { + pr_err("network is not active\n"); + ret = -EINVAL; + goto exec_v2_done; + } + + if (network->fw_error) { + pr_err("fw is in error state\n"); + ret = -EIO; + goto exec_v2_done; + } + pr_debug("execute_v2 network %d\n", network->id); num_patch_params = exec_ioctl->patch_buf_info_num; pkt_size = num_patch_params * sizeof(struct npu_patch_params_v2) + sizeof(*exec_packet); exec_packet = kzalloc(pkt_size, GFP_KERNEL); - if (!exec_packet) - return -ENOMEM; + if (!exec_packet) { + ret = -ENOMEM; + goto exec_v2_done; + } for (i = 0; i < num_patch_params; i++) { exec_packet->patch_params[i].id = patch_buf_info[i].buf_id; @@ -1336,8 +1582,8 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, if (!npu_mem_verify_addr(client, patch_buf_info[i].buf_phys_addr)) { pr_err("Invalid patch value\n"); - kfree(exec_packet); - return -EINVAL; + ret = -EINVAL; + goto free_exec_packet; } } @@ -1362,37 +1608,70 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, if (ret) { pr_err("NPU_IPC_CMD_EXECUTE_V2 sent failed: %d\n", ret); - } else if (async_ioctl) { + goto free_exec_packet; + } + + if (async_ioctl) { pr_debug("Async ioctl, return now\n"); - } else if (!wait_for_completion_interruptible_timeout( + goto free_exec_packet; + } + + mutex_unlock(&host_ctx->lock); + + ret = wait_for_completion_interruptible_timeout( &network->cmd_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? - NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) { + NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); + + mutex_lock(&host_ctx->lock); + if (!ret) { pr_err_ratelimited("npu: NPU_IPC_CMD_EXECUTE_V2 time out\n"); /* dump debug stats */ npu_dump_debug_timeout_stats(npu_dev); network->cmd_pending = false; - /* treat execution timed out as ssr */ - fw_deinit(npu_dev, true); ret = -ETIMEDOUT; - } else if (network->fw_error) { + goto free_exec_packet; + } else if (ret == -ERESTARTSYS) { + pr_err("Wait for execution_v2 done interrupted by signal\n"); + network->cmd_pending = false; + goto free_exec_packet; + } + + if (network->fw_error) { ret = -EIO; - pr_err("execute cmd returns with error\n"); - } else { - ret = network->cmd_ret_status; - if (!ret) { - exec_ioctl->stats_buf_size = network->stats_buf_size; - if (copy_to_user( - (void __user *)exec_ioctl->stats_buf_addr, - network->stats_buf, - exec_ioctl->stats_buf_size)) { - pr_err("copy stats to user failed\n"); - exec_ioctl->stats_buf_size = 0; - } + pr_err("fw is in error state during execute_v2 network\n"); + goto free_exec_packet; + } + + ret = network->cmd_ret_status; + if (!ret) { + exec_ioctl->stats_buf_size = network->stats_buf_size; + if (copy_to_user( + (void __user *)exec_ioctl->stats_buf_addr, + network->stats_buf, + exec_ioctl->stats_buf_size)) { + pr_err("copy stats to user failed\n"); + exec_ioctl->stats_buf_size = 0; } + } else { + pr_err("execution failed %d\n", ret); } +free_exec_packet: kfree(exec_packet); +exec_v2_done: + network_put(network); + mutex_unlock(&host_ctx->lock); + + /* + * treat network execution timed our or interrupted by signal + * as error in order to force npu fw to stop execution + */ + if ((ret == -ETIMEDOUT) || (ret == -ERESTARTSYS)) { + pr_err("Error handling after execution failure\n"); + host_error_hdlr(npu_dev, true); + } + return ret; } @@ -1418,14 +1697,22 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev) if (ret) { pr_err("NPU_IPC_CMD_LOOPBACK sent failed: %d\n", ret); - } else if (!wait_for_completion_interruptible_timeout( + goto loopback_exit; + } + + ret = wait_for_completion_interruptible_timeout( &host_ctx->loopback_done, (host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ? - NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) { + NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT); + + if (!ret) { pr_err_ratelimited("npu: NPU_IPC_CMD_LOOPBACK time out\n"); ret = -ETIMEDOUT; + } else if (ret < 0) { + pr_err("Wait for loopback done interrupted by signal\n"); } +loopback_exit: fw_deinit(npu_dev, false); return ret; diff --git a/drivers/media/platform/msm/npu/npu_mgr.h b/drivers/media/platform/msm/npu/npu_mgr.h index bf498cbe4f75711f7a9420762188bf7990886c71..a4e04b4f57d9b3f212bfd45c18d62c1bf83e46ee 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.h +++ b/drivers/media/platform/msm/npu/npu_mgr.h @@ -54,7 +54,10 @@ struct npu_network { void *stats_buf; void __user *stats_buf_u; uint32_t stats_buf_size; + uint32_t trans_id; + atomic_t ref_cnt; bool is_valid; + bool is_active; bool fw_error; bool cmd_pending; bool cmd_async; diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c index 7fd073a140bf002aff1497781a9e3cb5e648f294..b27761a2f10847d1fa8479b0f75dd6e41e60545d 100644 --- a/drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c +++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c @@ -407,15 +407,10 @@ static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d, motion_vector_complexity = FP(integer_part, frac_part, 100); - dpb_write_compression_factor = !dpb_compression_enabled ? FP_ONE : - __compression_ratio(__lut(width, height, fps), opb_bpp); - - dpb_write_compression_factor = d->use_dpb_read ? - dpb_read_compression_factor : - dpb_write_compression_factor; + dpb_write_compression_factor = dpb_read_compression_factor; opb_compression_factor = !opb_compression_enabled ? FP_ONE : - __compression_ratio(__lut(width, height, fps), opb_bpp); + dpb_write_compression_factor; llc_ref_read_l2_cache_enabled = llc_vpss_ds_line_buf_enabled = false; if (d->use_sys_cache) { @@ -427,7 +422,7 @@ static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d, lcu_per_frame = DIV_ROUND_UP(width, lcu_size) * DIV_ROUND_UP(height, lcu_size); - bitrate = __lut(width, height, fps)->bitrate; + bitrate = (d->bitrate + 1000000 - 1) / 1000000; bins_to_bit_factor = d->work_mode == VIDC_WORK_MODE_1 ? FP_INT(0) : FP_INT(4); @@ -481,7 +476,7 @@ static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d, if (llc_ref_read_l2_cache_enabled) { row_cache_penalty = FP(1, 30, 100); ddr.dpb_read = fp_div(ddr.dpb_read, row_cache_penalty); - llc.dpb_read = dpb_total - ddr.dpb_read; + llc.dpb_read = dpb_total - ddr.dpb_write - ddr.dpb_read; } opb_factor = dpb_bpp == 8 ? 8 : 4; @@ -507,7 +502,7 @@ static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d, qsmmu_bw_overhead_factor = FP(1, 3, 100); ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor); - llc.total = llc.dpb_read + llc.opb_read; + llc.total = llc.dpb_read + llc.opb_read + ddr.total; /* Dump all the variables for easier debugging */ if (debug) { @@ -644,7 +639,8 @@ static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d, b_frames_enabled = d->b_frames_enabled; width = max(d->input_width, BASELINE_DIMENSIONS.width); height = max(d->input_height, BASELINE_DIMENSIONS.height); - bitrate = __lut(width, height, fps)->bitrate; + bitrate = d->bitrate > 0 ? d->bitrate / 1000000 : + __lut(width, height, fps)->bitrate; lcu_per_frame = DIV_ROUND_UP(width, lcu_size) * DIV_ROUND_UP(height, lcu_size); @@ -688,10 +684,11 @@ static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d, input_compression_factor = FP(integer_part, frac_part, 100); + /* use input cr if it is valid (not 1), otherwise use lut */ original_compression_factor = - original_compression_enabled ? d->use_dpb_read ? - dpb_compression_factor : input_compression_factor : - FP_ONE; + !original_compression_enabled ? FP_ONE : + input_compression_factor != FP_ONE ? input_compression_factor : + __compression_ratio(__lut(width, height, fps), dpb_bpp); ddr.vsp_read = fp_mult(fp_div(FP_INT(bitrate), FP_INT(8)), bins_to_bit_factor); @@ -745,7 +742,7 @@ static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d, llc_ref_y_read -= ref_y_read; - ref_cb_cr_read = fp_mult(ref_cb_cr_bw_factor, dpb_bw_for_1x); + ref_cb_cr_read = fp_mult(ref_cb_cr_bw_factor, dpb_bw_for_1x) / 2; ref_cb_cr_read = fp_div(ref_cb_cr_read, dpb_compression_factor); @@ -767,7 +764,7 @@ static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d, ddr.dpb_write = fp_mult(ddr.dpb_write, FP(1, 50, 100)); - ddr.dpb_write = fp_div(ddr.dpb_write, input_compression_factor); + ddr.dpb_write = fp_div(ddr.dpb_write, dpb_compression_factor); ref_overlap_bw_factor = width <= vertical_tile_width ? FP_INT(0) : FP_INT(1); @@ -789,7 +786,7 @@ static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d, ddr.original_read + ddr.original_write + ddr.dpb_read + ddr.dpb_write; - llc.total = llc.dpb_read + llc.line_buffer; + llc.total = llc.dpb_read + llc.line_buffer + ddr.total; qsmmu_bw_overhead_factor = FP(1, 3, 100); ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor); diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index c384405fe0e44079fadb8695639c662dce7191ce..179c44fb5e9585727c6f8f3324faf6f3cad1daeb 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -1981,12 +1981,33 @@ static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst) { struct msm_vidc_buffer *temp, *dummy; struct getprop_buf *temp_prop, *dummy_prop; + struct list_head *ptr, *next; + enum vidc_ports ports[] = {OUTPUT_PORT, CAPTURE_PORT}; + int c = 0; if (!inst) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return; } + for (c = 0; c < ARRAY_SIZE(ports); ++c) { + enum vidc_ports port = ports[c]; + + mutex_lock(&inst->bufq[port].lock); + list_for_each_safe(ptr, next, + &inst->bufq[port].vb2_bufq.queued_list) { + struct vb2_buffer *vb = container_of(ptr, + struct vb2_buffer, queued_entry); + if (vb->state == VB2_BUF_STATE_ACTIVE) { + vb->planes[0].bytesused = 0; + print_vb2_buffer(VIDC_ERR, "undequeud vb2", + inst, vb); + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + } + } + mutex_unlock(&inst->bufq[port].lock); + } + mutex_lock(&inst->registeredbufs.lock); list_for_each_entry_safe(temp, dummy, &inst->registeredbufs.list, list) { diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c index 749ffea6660bfb2afb18b9e79001e668f9f53a6f..16545c892e166929f15ebffb00cd7464d9a748bd 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c @@ -1255,9 +1255,17 @@ static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst) pdata.video_work_mode = VIDC_WORK_MODE_1; break; } - } else if (inst->session_type == MSM_VIDC_ENCODER) + } else if (inst->session_type == MSM_VIDC_ENCODER) { + u32 rc_mode = 0; + pdata.video_work_mode = VIDC_WORK_MODE_1; - else { + rc_mode = msm_comm_g_ctrl_for_id(inst, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE); + if (rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR || + rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_MBR || + rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR) + pdata.video_work_mode = VIDC_WORK_MODE_2; + } else { return -EINVAL; } diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c index 03af199ebb7c02368b24b515e1c98fb4968cb878..49ac53c4a5d06b5b042f41b3614aec0908e9e928 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c @@ -16,12 +16,13 @@ #include "msm_vidc_debug.h" #include "vidc_hfi_api.h" -int msm_vidc_debug = VIDC_ERR | VIDC_WARN; +int msm_vidc_debug = VIDC_ERR | VIDC_WARN | VIDC_FW; EXPORT_SYMBOL(msm_vidc_debug); int msm_vidc_debug_out = VIDC_OUT_PRINTK; EXPORT_SYMBOL(msm_vidc_debug_out); +/* 0x18 = HFI_DEBUG_MSG_FATAL | HFI_DEBUG_MSG_ERROR */ int msm_vidc_fw_debug = 0x18; int msm_vidc_fw_debug_mode = 1; int msm_vidc_fw_low_power_mode = 1; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c index 5c5bbdfcb1ed9d9d1cc48f6505bf226aac9b9762..d3181ffc43c4443ddc279a835f289d784c9595a9 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c @@ -161,7 +161,7 @@ static struct msm_vidc_common_data sm6150_common_data[] = { }, { .key = "qcom,max-hw-load", - .value = 1216800, + .value = 1944000, }, { .key = "qcom,max-hq-mbs-per-frame", diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index c818474464eb2a2ce83a80058d4b3bdff2935b7b..58669671728b40a4873b96b1f858ccca2a29e8fd 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -122,6 +122,13 @@ static inline void msm_vidc_free_clock_table( res->clock_set.count = 0; } +static inline void msm_vidc_free_cx_ipeak_context( + struct msm_vidc_platform_resources *res) +{ + cx_ipeak_unregister(res->cx_ipeak_context); + res->cx_ipeak_context = NULL; +} + void msm_vidc_free_platform_resources( struct msm_vidc_platform_resources *res) { @@ -132,6 +139,7 @@ void msm_vidc_free_platform_resources( msm_vidc_free_qdss_addr_table(res); msm_vidc_free_bus_vectors(res); msm_vidc_free_buffer_usage_table(res); + msm_vidc_free_cx_ipeak_context(res); } static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res) @@ -804,6 +812,48 @@ int read_platform_resources_from_drv_data( } +static int msm_vidc_populate_cx_ipeak_context( + struct msm_vidc_platform_resources *res) +{ + struct platform_device *pdev = res->pdev; + int rc = 0; + + if (of_find_property(pdev->dev.of_node, + "qcom,cx-ipeak-data", NULL)) { + res->cx_ipeak_context = cx_ipeak_register( + pdev->dev.of_node, "qcom,cx-ipeak-data"); + } + + if (IS_ERR(res->cx_ipeak_context)) { + rc = PTR_ERR(res->cx_ipeak_context); + if (rc == -EPROBE_DEFER) + dprintk(VIDC_INFO, + "cx-ipeak register failed. Deferring probe!"); + else + dprintk(VIDC_ERR, + "cx-ipeak register failed. rc: %d", rc); + + res->cx_ipeak_context = NULL; + goto err_cx_ipeak; + } + + if (res->cx_ipeak_context) + dprintk(VIDC_INFO, "cx-ipeak register successful"); + else + dprintk(VIDC_INFO, "cx-ipeak register not implemented"); + + of_property_read_u32(pdev->dev.of_node, + "qcom,clock-freq-threshold", + &res->clk_freq_threshold); + dprintk(VIDC_DBG, "cx ipeak threshold frequency = %u\n", + res->clk_freq_threshold); + + return rc; + +err_cx_ipeak: + return rc; +} + int read_platform_resources_from_dt( struct msm_vidc_platform_resources *res) { @@ -892,8 +942,16 @@ int read_platform_resources_from_dt( "Using fw-bias : %pa", &res->firmware_base); } + rc = msm_vidc_populate_cx_ipeak_context(res); + if (rc) { + dprintk(VIDC_ERR, + "Failed to setup cx-ipeak %d\n", rc); + goto err_register_cx_ipeak; + } + return rc; +err_register_cx_ipeak: err_setup_legacy_cb: msm_vidc_free_allowed_clocks_table(res); err_load_allowed_clocks_table: diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h index fb2a75543b1dc9bae4403a0e99b3d4c5b0ebfd08..48cd7f2910ce403ed39d265dbcbbd91f644359d1 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h @@ -18,6 +18,7 @@ #include #include "msm_vidc.h" #include +#include "soc/qcom/cx_ipeak.h" #define MAX_BUFFER_TYPES 32 @@ -200,6 +201,8 @@ struct msm_vidc_platform_resources { struct msm_vidc_mem_cdsp mem_cdsp; uint32_t vpu_ver; uint32_t fw_cycles; + uint32_t clk_freq_threshold; + struct cx_ipeak_client *cx_ipeak_context; }; static inline bool is_iommu_present(struct msm_vidc_platform_resources *res) diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index cb4fd19e1aa4ebae704759e2fd017c0b5cff3f27..cc2a406ba380b957b184fc6b283b2440725208d5 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1383,6 +1384,49 @@ static enum hal_default_properties venus_hfi_get_default_properties(void *dev) return prop; } +static int __set_clk_rate(struct venus_hfi_device *device, + struct clock_info *cl, u64 rate) +{ + int rc = 0; + u64 threshold_freq = device->res->clk_freq_threshold; + struct cx_ipeak_client *ipeak = device->res->cx_ipeak_context; + struct clk *clk = cl->clk; + + if (device->clk_freq < threshold_freq && rate >= threshold_freq) { + rc = cx_ipeak_update(ipeak, true); + if (rc) { + dprintk(VIDC_ERR, + "cx_ipeak_update failed! ipeak %pK\n", ipeak); + return rc; + } + dprintk(VIDC_PROF, "cx_ipeak_update: up, clk freq = %lu\n", + device->clk_freq); + } + + rc = clk_set_rate(clk, rate); + if (rc) { + dprintk(VIDC_ERR, + "%s: Failed to set clock rate %llu %s: %d\n", + __func__, rate, cl->name, rc); + return rc; + } + + device->clk_freq = rate; + + if (device->clk_freq >= threshold_freq && rate < threshold_freq) { + rc = cx_ipeak_update(ipeak, false); + if (rc) { + dprintk(VIDC_ERR, + "cx_ipeak_update failed! ipeak %pK\n", ipeak); + return rc; + } + dprintk(VIDC_PROF, "cx_ipeak_update: down, clk freq = %lu\n", + device->clk_freq); + } + + return rc; +} + static int __set_clocks(struct venus_hfi_device *device, u32 freq) { struct clock_info *cl; @@ -1390,14 +1434,9 @@ static int __set_clocks(struct venus_hfi_device *device, u32 freq) venus_hfi_for_each_clock(device, cl) { if (cl->has_scaling) {/* has_scaling */ - device->clk_freq = freq; - rc = clk_set_rate(cl->clk, freq); - if (rc) { - dprintk(VIDC_ERR, - "Failed to set clock rate %u %s: %d %s\n", - freq, cl->name, rc, __func__); + rc = __set_clk_rate(device, cl, freq); + if (rc) return rc; - } trace_msm_vidc_perf_clock_scale(cl->name, freq); dprintk(VIDC_PROF, "Scaling clock %s to %u\n", @@ -3956,7 +3995,8 @@ static inline int __prepare_enable_clks(struct venus_hfi_device *device) * it to the lowest frequency possible */ if (cl->has_scaling) - clk_set_rate(cl->clk, clk_round_rate(cl->clk, 0)); + __set_clk_rate(device, cl, + clk_round_rate(cl->clk, 0)); rc = clk_set_flags(cl->clk, CLKFLAG_RETAIN_PERIPH); if (rc) { diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 9f023bc6e1b7e4dafd861a4a0344bb4868dec6b1..6e6e978263b0218f8f6b8b63f45d380cd9b81ad5 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -305,7 +305,7 @@ static struct clk *isp_xclk_src_get(struct of_phandle_args *clkspec, void *data) static int isp_xclk_init(struct isp_device *isp) { struct device_node *np = isp->dev->of_node; - struct clk_init_data init; + struct clk_init_data init = { 0 }; unsigned int i; for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) diff --git a/drivers/media/platform/qcom/camss-8x16/camss-csid.c b/drivers/media/platform/qcom/camss-8x16/camss-csid.c index 64df82817de3c4ce7a9314302273320fe5d1bb7b..4882ee25bd754d5a839fd0f8d41beffa2841412a 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-csid.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-csid.c @@ -392,9 +392,6 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) !media_entity_remote_pad(&csid->pads[MSM_CSID_PAD_SINK])) return -ENOLINK; - dt = csid_get_fmt_entry(csid->fmt[MSM_CSID_PAD_SRC].code)-> - data_type; - if (tg->enabled) { /* Config Test Generator */ struct v4l2_mbus_framefmt *f = @@ -416,6 +413,9 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_0(0)); + dt = csid_get_fmt_entry( + csid->fmt[MSM_CSID_PAD_SRC].code)->data_type; + /* 5:0 data type */ val = dt; writel_relaxed(val, csid->base + @@ -425,6 +425,9 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) val = tg->payload_mode; writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_2(0)); + + df = csid_get_fmt_entry( + csid->fmt[MSM_CSID_PAD_SRC].code)->decode_format; } else { struct csid_phy_config *phy = &csid->phy; @@ -439,13 +442,16 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_1); + + dt = csid_get_fmt_entry( + csid->fmt[MSM_CSID_PAD_SINK].code)->data_type; + df = csid_get_fmt_entry( + csid->fmt[MSM_CSID_PAD_SINK].code)->decode_format; } /* Config LUT */ dt_shift = (cid % 4) * 8; - df = csid_get_fmt_entry(csid->fmt[MSM_CSID_PAD_SINK].code)-> - decode_format; val = readl_relaxed(csid->base + CAMSS_CSID_CID_LUT_VC_n(vc)); val &= ~(0xff << dt_shift); diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index 0f0324a14d515552939cc697b03ab0f0575ec30a..85d26713cedb911b3fb6d14505f7f2234832137e 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -117,6 +117,8 @@ static int sensor_set_power(struct camif_dev *camif, int on) if (camif->sensor.power_count == !on) err = v4l2_subdev_call(sensor->sd, core, s_power, on); + if (err == -ENOIOCTLCMD) + err = 0; if (!err) sensor->power_count += on ? 1 : -1; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 8e9531f7f83f54fbb7b1df28f017f61058dcc680..9942932ecbf9c04a716fd1c7706d8496a707d7c8 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -254,24 +254,24 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx) static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - struct s5p_mfc_buf *dst_buf, *src_buf; - size_t dec_y_addr; + struct s5p_mfc_buf *dst_buf, *src_buf; + u32 dec_y_addr; unsigned int frame_type; /* Make sure we actually have a new frame before continuing. */ frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) return; - dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev); + dec_y_addr = (u32)s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev); /* Copy timestamp / timecode from decoded src to dst and set appropriate flags. */ src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); list_for_each_entry(dst_buf, &ctx->dst_queue, list) { - if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0) - == dec_y_addr) { - dst_buf->b->timecode = - src_buf->b->timecode; + u32 addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0); + + if (addr == dec_y_addr) { + dst_buf->b->timecode = src_buf->b->timecode; dst_buf->b->vb2_buf.timestamp = src_buf->b->vb2_buf.timestamp; dst_buf->b->flags &= @@ -307,10 +307,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) { struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *dst_buf; - size_t dspl_y_addr; + u32 dspl_y_addr; unsigned int frame_type; - dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); + dspl_y_addr = (u32)s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); if (IS_MFCV6_PLUS(dev)) frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_disp_frame_type, ctx); @@ -329,9 +329,10 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) /* The MFC returns address of the buffer, now we have to * check which videobuf does it correspond to */ list_for_each_entry(dst_buf, &ctx->dst_queue, list) { + u32 addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0); + /* Check if this is the buffer we're looking for */ - if (vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0) - == dspl_y_addr) { + if (addr == dspl_y_addr) { list_del(&dst_buf->list); ctx->dst_queue_cnt--; dst_buf->b->sequence = ctx->sequence; diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index b421329b21fae5a6b41af48b0e59377d70bc88d5..3d09e1c879217aba7a4853034b8f749be004daaf 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -2103,14 +2103,12 @@ static struct dvb_usb_device_properties s6x0_properties = { } }; -static struct dvb_usb_device_properties *p1100; static const struct dvb_usb_device_description d1100 = { "Prof 1100 USB ", {&dw2102_table[PROF_1100], NULL}, {NULL}, }; -static struct dvb_usb_device_properties *s660; static const struct dvb_usb_device_description d660 = { "TeVii S660 USB", {&dw2102_table[TEVII_S660], NULL}, @@ -2129,14 +2127,12 @@ static const struct dvb_usb_device_description d480_2 = { {NULL}, }; -static struct dvb_usb_device_properties *p7500; static const struct dvb_usb_device_description d7500 = { "Prof 7500 USB DVB-S2", {&dw2102_table[PROF_7500], NULL}, {NULL}, }; -static struct dvb_usb_device_properties *s421; static const struct dvb_usb_device_description d421 = { "TeVii S421 PCI", {&dw2102_table[TEVII_S421], NULL}, @@ -2336,6 +2332,11 @@ static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { int retval = -ENOMEM; + struct dvb_usb_device_properties *p1100; + struct dvb_usb_device_properties *s660; + struct dvb_usb_device_properties *p7500; + struct dvb_usb_device_properties *s421; + p1100 = kmemdup(&s6x0_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); if (!p1100) @@ -2404,8 +2405,16 @@ static int dw2102_probe(struct usb_interface *intf, 0 == dvb_usb_device_init(intf, &t220_properties, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties, - THIS_MODULE, NULL, adapter_nr)) + THIS_MODULE, NULL, adapter_nr)) { + + /* clean up copied properties */ + kfree(s421); + kfree(p7500); + kfree(s660); + kfree(p1100); + return 0; + } retval = -ENODEV; kfree(s421); diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c index 097ac321b7e1e35f1d89bd18456ab1d501a20773..349f578273b6ea480077d80d42eb893528afe3bc 100644 --- a/drivers/media/usb/tm6000/tm6000-dvb.c +++ b/drivers/media/usb/tm6000/tm6000-dvb.c @@ -267,6 +267,11 @@ static int register_dvb(struct tm6000_core *dev) ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T", THIS_MODULE, &dev->udev->dev, adapter_nr); + if (ret < 0) { + pr_err("tm6000: couldn't register the adapter!\n"); + goto err; + } + dvb->adapter.priv = dev; if (dvb->frontend) { diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index fb86d6af398d305a123be15e1b4c574888d1354c..a6d8002918831eebb0e60549e0c68c0fa52e84a6 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -163,14 +163,27 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, } } +static size_t uvc_video_ctrl_size(struct uvc_streaming *stream) +{ + /* + * Return the size of the video probe and commit controls, which depends + * on the protocol version. + */ + if (stream->dev->uvc_version < 0x0110) + return 26; + else if (stream->dev->uvc_version < 0x0150) + return 34; + else + return 48; +} + static int uvc_get_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe, __u8 query) { + __u16 size = uvc_video_ctrl_size(stream); __u8 *data; - __u16 size; int ret; - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) return -EIO; @@ -225,7 +238,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]); ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]); - if (size == 34) { + if (size >= 34) { ctrl->dwClockFrequency = get_unaligned_le32(&data[26]); ctrl->bmFramingInfo = data[30]; ctrl->bPreferedVersion = data[31]; @@ -254,11 +267,10 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, static int uvc_set_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe) { + __u16 size = uvc_video_ctrl_size(stream); __u8 *data; - __u16 size; int ret; - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; data = kzalloc(size, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -275,7 +287,7 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream, put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); - if (size == 34) { + if (size >= 34) { put_unaligned_le32(ctrl->dwClockFrequency, &data[26]); data[30] = ctrl->bmFramingInfo; data[31] = ctrl->bPreferedVersion; diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c index 968c2eb08b5aba52e18e66221a09b1f351b73337..568dd4affb337a7eb65cc4399db8f0084b4e25ee 100644 --- a/drivers/media/v4l2-core/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -115,14 +115,6 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e if (sev == NULL) return; - /* - * If the event has been added to the fh->subscribed list, but its - * add op has not completed yet elems will be 0, treat this as - * not being subscribed. - */ - if (!sev->elems) - return; - /* Increase event sequence number on fh. */ fh->sequence++; @@ -208,6 +200,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, struct v4l2_subscribed_event *sev, *found_ev; unsigned long flags; unsigned i; + int ret = 0; if (sub->type == V4L2_EVENT_ALL) return -EINVAL; @@ -226,31 +219,36 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, sev->flags = sub->flags; sev->fh = fh; sev->ops = ops; + sev->elems = elems; + + mutex_lock(&fh->subscribe_lock); spin_lock_irqsave(&fh->vdev->fh_lock, flags); found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); - if (!found_ev) - list_add(&sev->list, &fh->subscribed); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); if (found_ev) { + /* Already listening */ kvfree(sev); - return 0; /* Already listening */ + goto out_unlock; } if (sev->ops && sev->ops->add) { - int ret = sev->ops->add(sev, elems); + ret = sev->ops->add(sev, elems); if (ret) { - sev->ops = NULL; - v4l2_event_unsubscribe(fh, sub); - return ret; + kvfree(sev); + goto out_unlock; } } - /* Mark as ready for use */ - sev->elems = elems; + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + list_add(&sev->list, &fh->subscribed); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - return 0; +out_unlock: + mutex_unlock(&fh->subscribe_lock); + + return ret; } EXPORT_SYMBOL_GPL(v4l2_event_subscribe); @@ -289,6 +287,8 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, return 0; } + mutex_lock(&fh->subscribe_lock); + spin_lock_irqsave(&fh->vdev->fh_lock, flags); sev = v4l2_event_subscribed(fh, sub->type, sub->id); @@ -306,6 +306,8 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, if (sev && sev->ops && sev->ops->del) sev->ops->del(sev); + mutex_unlock(&fh->subscribe_lock); + kvfree(sev); return 0; diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c index 3895999bf8805c3c208a4f042cb59b786a6ec44c..c91a7bd3ecfc7d14853b56a8de273d35ac0ff870 100644 --- a/drivers/media/v4l2-core/v4l2-fh.c +++ b/drivers/media/v4l2-core/v4l2-fh.c @@ -45,6 +45,7 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) INIT_LIST_HEAD(&fh->available); INIT_LIST_HEAD(&fh->subscribed); fh->sequence = -1; + mutex_init(&fh->subscribe_lock); } EXPORT_SYMBOL_GPL(v4l2_fh_init); @@ -90,6 +91,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh) return; v4l_disable_media_source(fh->vdev); v4l2_event_unsubscribe_all(fh); + mutex_destroy(&fh->subscribe_lock); fh->vdev = NULL; } EXPORT_SYMBOL_GPL(v4l2_fh_exit); diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 2dbf632c10de350d72dc61f1a0b63343deee84ba..43522a09b11d50e10cad6eda3d39cd21edfbc1c5 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1373,6 +1373,11 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) struct vb2_buffer *vb; int ret; + if (q->error) { + dprintk(1, "fatal error occurred on queue\n"); + return -EIO; + } + vb = q->bufs[index]; switch (vb->state) { diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c index 84e313107233ee8b1e86f0610be093eaa5e1637d..7b9052ea74134a2694f8485f48cb589e9624b793 100644 --- a/drivers/mfd/88pm860x-i2c.c +++ b/drivers/mfd/88pm860x-i2c.c @@ -146,14 +146,14 @@ int pm860x_page_reg_write(struct i2c_client *i2c, int reg, unsigned char zero; int ret; - i2c_lock_adapter(i2c->adapter); + i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT); read_device(i2c, 0xFA, 0, &zero); read_device(i2c, 0xFB, 0, &zero); read_device(i2c, 0xFF, 0, &zero); ret = write_device(i2c, reg, 1, &data); read_device(i2c, 0xFE, 0, &zero); read_device(i2c, 0xFC, 0, &zero); - i2c_unlock_adapter(i2c->adapter); + i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT); return ret; } EXPORT_SYMBOL(pm860x_page_reg_write); @@ -164,14 +164,14 @@ int pm860x_page_bulk_read(struct i2c_client *i2c, int reg, unsigned char zero = 0; int ret; - i2c_lock_adapter(i2c->adapter); + i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT); read_device(i2c, 0xfa, 0, &zero); read_device(i2c, 0xfb, 0, &zero); read_device(i2c, 0xff, 0, &zero); ret = read_device(i2c, reg, count, buf); read_device(i2c, 0xFE, 0, &zero); read_device(i2c, 0xFC, 0, &zero); - i2c_unlock_adapter(i2c->adapter); + i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT); return ret; } EXPORT_SYMBOL(pm860x_page_bulk_read); diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index c37ccbfd52f2a14be65c0008b96697f55029698c..96c07fa1802adcce7d48f971410096b4b2a4f479 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -49,7 +49,7 @@ static struct regmap_config hi655x_regmap_config = { .reg_bits = 32, .reg_stride = HI655X_STRIDE, .val_bits = 8, - .max_register = HI655X_BUS_ADDR(0xFFF), + .max_register = HI655X_BUS_ADDR(0x400) - HI655X_STRIDE, }; static struct resource pwrkey_resources[] = { diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 40534352e57487191978492991dfe1154d608b02..3270b8dbc94982ebb447d9c3ace5d1000c28a670 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -714,6 +714,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name, smdev->pdev.name = name; smdev->pdev.id = sm->pdev_id; smdev->pdev.dev.parent = sm->dev; + smdev->pdev.dev.coherent_dma_mask = 0xffffffff; if (res_count) { smdev->pdev.resource = (struct resource *)(smdev+1); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 0f3fab47fe48052682fc686ee62381dd1e9c719b..7dc1cbcd2fb8951150c633290b02392c4f041543 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -210,14 +210,13 @@ static int ti_tscadc_probe(struct platform_device *pdev) * The TSC_ADC_SS controller design assumes the OCP clock is * at least 6x faster than the ADC clock. */ - clk = clk_get(&pdev->dev, "adc_tsc_fck"); + clk = devm_clk_get(&pdev->dev, "adc_tsc_fck"); if (IS_ERR(clk)) { dev_err(&pdev->dev, "failed to get TSC fck\n"); err = PTR_ERR(clk); goto err_disable_clk; } clock_rate = clk_get_rate(clk); - clk_put(clk); tscadc->clk_div = clock_rate / ADC_CLK; /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index c1ba0d42cbc865467334c25a0b62a3f1f8932a21..e0f29b8a872db807fc7e899d25ecfdc87be156d1 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c @@ -287,7 +287,7 @@ int cxl_adapter_context_get(struct cxl *adapter) int rc; rc = atomic_inc_unless_negative(&adapter->contexts_num); - return rc >= 0 ? 0 : -EBUSY; + return rc ? 0 : -EBUSY; } void cxl_adapter_context_put(struct cxl *adapter) diff --git a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c index 887c8eb2f9ee5401c628348fa3644a11f541bfbb..a6ed374e5b8e96d129b36e8dcf7d36577420b229 100644 --- a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c +++ b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c @@ -75,8 +75,8 @@ static const struct vreg_config vreg_conf[] = { struct fpc1020_data { struct device *dev; struct pinctrl *fingerprint_pinctrl; - struct pinctrl_state **pinctrl_state; - struct regulator **vreg; + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; + struct regulator *vreg[ARRAY_SIZE(vreg_conf)]; struct wakeup_source ttw_wl; struct mutex lock; /* To set/get exported values in sysfs */ int irq_gpio; diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c index eeb7eef62174c4dfb5c8854efbef2d798f161f1e..38f90e17992717d7cd0f12ad904490abbaa2d1a5 100644 --- a/drivers/misc/hmc6352.c +++ b/drivers/misc/hmc6352.c @@ -27,6 +27,7 @@ #include #include #include +#include static DEFINE_MUTEX(compass_mutex); @@ -50,6 +51,7 @@ static int compass_store(struct device *dev, const char *buf, size_t count, return ret; if (val >= strlen(map)) return -EINVAL; + val = array_index_nospec(val, strlen(map)); mutex_lock(&compass_mutex); ret = compass_command(c, map[val]); mutex_unlock(&compass_mutex); diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 0208c4b027c52b54dad37bddb13fe1288347b477..fa0236a5e59a39c751f6b3eee150d37e97836684 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -267,7 +267,7 @@ static int mei_nfc_if_version(struct mei_cl *cl, ret = 0; bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0); - if (bytes_recv < if_version_length) { + if (bytes_recv < 0 || bytes_recv < if_version_length) { dev_err(bus->dev, "Could not read IF version\n"); ret = -EIO; goto err; diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 1ac10cb64d6ed3e7d5ad20c1d5ebb1ec323fa05d..37b13bc5c16fe4b7d7ab87d6d4cc6d39b3b9ca33 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -465,17 +465,15 @@ int mei_cldev_enable(struct mei_cl_device *cldev) cl = cldev->cl; + mutex_lock(&bus->device_lock); if (cl->state == MEI_FILE_UNINITIALIZED) { - mutex_lock(&bus->device_lock); ret = mei_cl_link(cl); - mutex_unlock(&bus->device_lock); if (ret) - return ret; + goto out; /* update pointers */ cl->cldev = cldev; } - mutex_lock(&bus->device_lock); if (mei_cl_is_connected(cl)) { ret = 0; goto out; @@ -841,12 +839,13 @@ static void mei_cl_bus_dev_release(struct device *dev) mei_me_cl_put(cldev->me_cl); mei_dev_bus_put(cldev->bus); + mei_cl_unlink(cldev->cl); kfree(cldev->cl); kfree(cldev); } static const struct device_type mei_cl_device_type = { - .release = mei_cl_bus_dev_release, + .release = mei_cl_bus_dev_release, }; /** diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index fe6595fe94f1f4229bd1851cef7d5060952cb294..995ff1b7e7b5b7baf423716ab63d39af903e3e0b 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -1140,15 +1140,18 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) props_res = (struct hbm_props_response *)mei_msg; - if (props_res->status) { + if (props_res->status == MEI_HBMS_CLIENT_NOT_FOUND) { + dev_dbg(dev->dev, "hbm: properties response: %d CLIENT_NOT_FOUND\n", + props_res->me_addr); + } else if (props_res->status) { dev_err(dev->dev, "hbm: properties response: wrong status = %d %s\n", props_res->status, mei_hbm_status_str(props_res->status)); return -EPROTO; + } else { + mei_hbm_me_cl_add(dev, props_res); } - mei_hbm_me_cl_add(dev, props_res); - /* request property for the next client */ if (mei_hbm_prop_req(dev, props_res->me_addr + 1)) return -EIO; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 22efc039f3022237d1bc65b625cabb6ddb9fa3b1..8d1d40dbf7448fb51f2c8b70e5a88e8a404583f8 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -291,7 +291,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, goto out; } - *offset = 0; cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); if (!cb) { rets = -ENOMEM; diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c index ddc9e4b08b5cd809f4ce6e43fe1ec313dfb75e0d..56efa9d18a9afec2ddaea8bb76fc7ec34c14ce78 100644 --- a/drivers/misc/mic/scif/scif_api.c +++ b/drivers/misc/mic/scif/scif_api.c @@ -370,11 +370,10 @@ int scif_bind(scif_epd_t epd, u16 pn) goto scif_bind_exit; } } else { - pn = scif_get_new_port(); - if (!pn) { - ret = -ENOSPC; + ret = scif_get_new_port(); + if (ret < 0) goto scif_bind_exit; - } + pn = ret; } ep->state = SCIFEP_BOUND; @@ -648,13 +647,12 @@ int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block) err = -EISCONN; break; case SCIFEP_UNBOUND: - ep->port.port = scif_get_new_port(); - if (!ep->port.port) { - err = -ENOSPC; - } else { - ep->port.node = scif_info.nodeid; - ep->conn_async_state = ASYNC_CONN_IDLE; - } + err = scif_get_new_port(); + if (err < 0) + break; + ep->port.port = err; + ep->port.node = scif_info.nodeid; + ep->conn_async_state = ASYNC_CONN_IDLE; /* Fall through */ case SCIFEP_BOUND: /* diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 04b1f7088cc3dc582de0f457e81e0d98daaccfc3..b40719e88bcad1dd2367b2fde6898fd3d1f23c0a 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -191,6 +191,7 @@ struct qseecom_registered_listener_list { phys_addr_t sb_phys; size_t sb_length; wait_queue_head_t rcv_req_wq; + /* rcv_req_flag: -1: not ready; 0: ready and empty; 1: received req */ int rcv_req_flag; int send_resp_flag; bool listener_in_use; @@ -1346,7 +1347,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, if (!new_entry) return -ENOMEM; memcpy(&new_entry->svc, &rcvd_lstnr, sizeof(rcvd_lstnr)); - new_entry->rcv_req_flag = 0; + new_entry->rcv_req_flag = -1; new_entry->svc.listener_id = rcvd_lstnr.listener_id; new_entry->sb_length = rcvd_lstnr.sb_size; @@ -1770,21 +1771,20 @@ static void __qseecom_clean_listener_sglistinfo( } } -/* wake up listener receive request wq retry delay (ms) and max attemp count */ -#define QSEECOM_WAKE_LISTENER_RCVWQ_DELAY 10 -#define QSEECOM_WAKE_LISTENER_RCVWQ_MAX_ATTEMP 3 +/* wait listener retry delay (ms) and max attemp count */ +#define QSEECOM_WAIT_LISTENER_DELAY 10 +#define QSEECOM_WAIT_LISTENER_MAX_ATTEMP 3 -static int __qseecom_retry_wake_up_listener_rcv_wq( +static int __is_listener_rcv_wq_not_ready( struct qseecom_registered_listener_list *ptr_svc) { int retry = 0; - while (ptr_svc->rcv_req_flag == 1 && - retry++ < QSEECOM_WAKE_LISTENER_RCVWQ_MAX_ATTEMP) { - wake_up_interruptible(&ptr_svc->rcv_req_wq); - msleep(QSEECOM_WAKE_LISTENER_RCVWQ_DELAY); + while (ptr_svc->rcv_req_flag == -1 && + retry++ < QSEECOM_WAIT_LISTENER_MAX_ATTEMP) { + msleep(QSEECOM_WAIT_LISTENER_DELAY); } - return ptr_svc->rcv_req_flag == 1; + return ptr_svc->rcv_req_flag == -1; } static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, @@ -1815,6 +1815,8 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head, list) { if (ptr_svc->svc.listener_id == lstnr) { + if (__is_listener_rcv_wq_not_ready(ptr_svc)) + break; ptr_svc->listener_in_use = true; ptr_svc->rcv_req_flag = 1; wake_up_interruptible(&ptr_svc->rcv_req_wq); @@ -1855,14 +1857,15 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, goto err_resp; } - if (ptr_svc->rcv_req_flag == 1 && - __qseecom_retry_wake_up_listener_rcv_wq(ptr_svc)) { + if (ptr_svc->rcv_req_flag == -1) { pr_err("Service %d is not ready to receive request\n", lstnr); rc = -ENOENT; status = QSEOS_RESULT_FAILURE; goto err_resp; + } + pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n"); /* initialize the new signal mask with all signals*/ @@ -2144,6 +2147,8 @@ static int __qseecom_reentrancy_process_incomplete_cmd( list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head, list) { if (ptr_svc->svc.listener_id == lstnr) { + if (__is_listener_rcv_wq_not_ready(ptr_svc)) + break; ptr_svc->listener_in_use = true; ptr_svc->rcv_req_flag = 1; wake_up_interruptible(&ptr_svc->rcv_req_wq); @@ -2184,14 +2189,15 @@ static int __qseecom_reentrancy_process_incomplete_cmd( goto err_resp; } - if (ptr_svc->rcv_req_flag == 1 && - __qseecom_retry_wake_up_listener_rcv_wq(ptr_svc)) { + if (ptr_svc->rcv_req_flag == -1) { pr_err("Service %d is not ready to receive request\n", lstnr); rc = -ENOENT; status = QSEOS_RESULT_FAILURE; goto err_resp; + } + pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n"); /* initialize the new signal mask with all signals*/ @@ -3977,7 +3983,7 @@ static int __qseecom_listener_has_rcvd_req(struct qseecom_dev_handle *data, { int ret; - ret = (svc->rcv_req_flag != 0); + ret = (svc->rcv_req_flag == 1); return ret || data->abort || svc->abort; } @@ -3991,6 +3997,7 @@ static int qseecom_receive_req(struct qseecom_dev_handle *data) pr_err("Invalid listener ID\n"); return -ENODATA; } + this_lstnr->rcv_req_flag = 0; while (1) { if (wait_event_freezable(this_lstnr->rcv_req_wq, diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index 4dd0d868ff88818f7bcb8db51cac461cb6541684..8daefb81ba294ca4a5dd3455b5c9a82ec1ee5f2a 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -391,23 +391,23 @@ static int sram_probe(struct platform_device *pdev) if (IS_ERR(sram->pool)) return PTR_ERR(sram->pool); - ret = sram_reserve_regions(sram, res); - if (ret) - return ret; - sram->clk = devm_clk_get(sram->dev, NULL); if (IS_ERR(sram->clk)) sram->clk = NULL; else clk_prepare_enable(sram->clk); + ret = sram_reserve_regions(sram, res); + if (ret) + goto err_disable_clk; + platform_set_drvdata(pdev, sram); init_func = of_device_get_match_data(&pdev->dev); if (init_func) { ret = init_func(); if (ret) - goto err_disable_clk; + goto err_free_partitions; } dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n", @@ -415,10 +415,11 @@ static int sram_probe(struct platform_device *pdev) return 0; +err_free_partitions: + sram_free_partitions(sram); err_disable_clk: if (sram->clk) clk_disable_unprepare(sram->clk); - sram_free_partitions(sram); return ret; } diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index b77aacafc3fcd96bd52af1bb55a60123b22bdcf6..dda3ed72d05bc6e1284e8e860c6ac03657025bdb 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -756,14 +756,14 @@ static int kim_probe(struct platform_device *pdev) err = gpio_request(kim_gdata->nshutdown, "kim"); if (unlikely(err)) { pr_err(" gpio %d request failed ", kim_gdata->nshutdown); - return err; + goto err_sysfs_group; } /* Configure nShutdown GPIO as output=0 */ err = gpio_direction_output(kim_gdata->nshutdown, 0); if (unlikely(err)) { pr_err(" unable to configure gpio %d", kim_gdata->nshutdown); - return err; + goto err_sysfs_group; } /* get reference of pdev for request_firmware */ diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c index adf46072cb37d4a41a3ec95a9fd7d8a52890e677..3fce3b6a36246b28f9c81e339ba83bc67f0a08d2 100644 --- a/drivers/misc/tsl2550.c +++ b/drivers/misc/tsl2550.c @@ -177,7 +177,7 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1) } else lux = 0; else - return -EAGAIN; + return 0; /* LUX range check */ return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux; diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index 56c6f79a5c5af83a862cf76352f172f5e02ee0b8..f74166aa9a0dc09037fec9797838c8f78edf156d 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c @@ -45,6 +45,7 @@ #include #include #include +#include #include MODULE_AUTHOR("VMware, Inc."); @@ -341,7 +342,13 @@ static bool vmballoon_send_start(struct vmballoon *b, unsigned long req_caps) success = false; } - if (b->capabilities & VMW_BALLOON_BATCHED_2M_CMDS) + /* + * 2MB pages are only supported with batching. If batching is for some + * reason disabled, do not use 2MB pages, since otherwise the legacy + * mechanism is used with 2MB pages, causing a failure. + */ + if ((b->capabilities & VMW_BALLOON_BATCHED_2M_CMDS) && + (b->capabilities & VMW_BALLOON_BATCHED_CMDS)) b->supported_page_sizes = 2; else b->supported_page_sizes = 1; @@ -450,7 +457,7 @@ static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn, pfn32 = (u32)pfn; if (pfn32 != pfn) - return -1; + return -EINVAL; STATS_INC(b->stats.lock[false]); @@ -460,7 +467,7 @@ static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn, pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status); STATS_INC(b->stats.lock_fail[false]); - return 1; + return -EIO; } static int vmballoon_send_batched_lock(struct vmballoon *b, @@ -597,11 +604,12 @@ static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages, locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status, target); - if (locked > 0) { + if (locked) { STATS_INC(b->stats.refused_alloc[false]); - if (hv_status == VMW_BALLOON_ERROR_RESET || - hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) { + if (locked == -EIO && + (hv_status == VMW_BALLOON_ERROR_RESET || + hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED)) { vmballoon_free_page(page, false); return -EIO; } @@ -617,7 +625,7 @@ static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages, } else { vmballoon_free_page(page, false); } - return -EIO; + return locked; } /* track allocated page */ @@ -1029,29 +1037,30 @@ static void vmballoon_vmci_cleanup(struct vmballoon *b) */ static int vmballoon_vmci_init(struct vmballoon *b) { - int error = 0; + unsigned long error, dummy; - if ((b->capabilities & VMW_BALLOON_SIGNALLED_WAKEUP_CMD) != 0) { - error = vmci_doorbell_create(&b->vmci_doorbell, - VMCI_FLAG_DELAYED_CB, - VMCI_PRIVILEGE_FLAG_RESTRICTED, - vmballoon_doorbell, b); - - if (error == VMCI_SUCCESS) { - VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET, - b->vmci_doorbell.context, - b->vmci_doorbell.resource, error); - STATS_INC(b->stats.doorbell_set); - } - } + if ((b->capabilities & VMW_BALLOON_SIGNALLED_WAKEUP_CMD) == 0) + return 0; - if (error != 0) { - vmballoon_vmci_cleanup(b); + error = vmci_doorbell_create(&b->vmci_doorbell, VMCI_FLAG_DELAYED_CB, + VMCI_PRIVILEGE_FLAG_RESTRICTED, + vmballoon_doorbell, b); - return -EIO; - } + if (error != VMCI_SUCCESS) + goto fail; + + error = VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET, b->vmci_doorbell.context, + b->vmci_doorbell.resource, dummy); + + STATS_INC(b->stats.doorbell_set); + + if (error != VMW_BALLOON_SUCCESS) + goto fail; return 0; +fail: + vmballoon_vmci_cleanup(b); + return -EIO; } /* @@ -1289,7 +1298,14 @@ static int __init vmballoon_init(void) return 0; } -module_init(vmballoon_init); + +/* + * Using late_initcall() instead of module_init() allows the balloon to use the + * VMCI doorbell even when the balloon is built into the kernel. Otherwise the + * VMCI is probed only after the balloon is initialized. If the balloon is used + * as a module, late_initcall() is equivalent to module_init(). + */ +late_initcall(vmballoon_init); static void __exit vmballoon_exit(void) { diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index 8af5c2672f71cec186af5daf4dc50008fe771c7a..b4570d5c1fe7de4be6b0eeca109ea9797a3b1000 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -755,7 +755,7 @@ static int qp_host_get_user_memory(u64 produce_uva, retval = get_user_pages_fast((uintptr_t) produce_uva, produce_q->kernel_if->num_pages, 1, produce_q->kernel_if->u.h.header_page); - if (retval < produce_q->kernel_if->num_pages) { + if (retval < (int)produce_q->kernel_if->num_pages) { pr_debug("get_user_pages_fast(produce) failed (retval=%d)", retval); qp_release_pages(produce_q->kernel_if->u.h.header_page, @@ -767,7 +767,7 @@ static int qp_host_get_user_memory(u64 produce_uva, retval = get_user_pages_fast((uintptr_t) consume_uva, consume_q->kernel_if->num_pages, 1, consume_q->kernel_if->u.h.header_page); - if (retval < consume_q->kernel_if->num_pages) { + if (retval < (int)consume_q->kernel_if->num_pages) { pr_debug("get_user_pages_fast(consume) failed (retval=%d)", retval); qp_release_pages(consume_q->kernel_if->u.h.header_page, diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9d2751c81ad5565d69cc0b730b1df3f38e44a990..fa31c891eaf52cce2bc63828a7867fd50f782b94 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -4083,6 +4083,10 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) struct mmc_host *host = card->host; unsigned int max_discard, max_trim; + if (!host->max_busy_timeout || + (host->caps2 & MMC_CAP2_MAX_DISCARD_SIZE)) + return UINT_MAX; + /* * Without erase_group_def set, MMC erase timeout depends on clock * frequence which can change. In that case, the best choice is diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 3b5e6d11069bb58b80f3da5f257d617af9664571..9e03fada16dcbb7baa93ab445d2deeeaf6aff5c2 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2194,6 +2194,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) dma_release_channel(host->tx_chan); dma_release_channel(host->rx_chan); + dev_pm_clear_wake_irq(host->dev); pm_runtime_dont_use_autosuspend(host->dev); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 8bae88a150fd45b3284b594d2d090d4f78fe1fc7..713658be66614264640aa27db20b3fbf25a5e51c 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -44,7 +44,7 @@ /* DM_CM_RST */ #define RST_DTRANRST1 BIT(9) #define RST_DTRANRST0 BIT(8) -#define RST_RESERVED_BITS GENMASK_ULL(32, 0) +#define RST_RESERVED_BITS GENMASK_ULL(31, 0) /* DM_CM_INFO1 and DM_CM_INFO1_MASK */ #define INFO1_CLEAR 0 diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 4ffa6b173a21ef4a09a62108830869de16095ee2..8332f56e6c0da1bf2be953176b219b8ca73ea142 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" @@ -427,6 +428,11 @@ static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) static int esdhc_of_enable_dma(struct sdhci_host *host) { u32 value; + struct device *dev = mmc_dev(host->mmc); + + if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || + of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); value = sdhci_readl(host, ESDHC_DMA_SYSCTL); value |= ESDHC_DMA_SNOOP; diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 0cd6fa80db662a3ed2d8b10014047d50af4f2484..ce3f344d2b66ec70cf15c129c1cc89f592e5edfa 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -334,7 +334,8 @@ static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, - .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_BROKEN_HS200, .ops = &tegra_sdhci_ops, }; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 32febee5c9a4ba20d1698bafced804c9698d71ea..083a0d2deaa35c71070039e2642a9c7b9dcdda87 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -4604,14 +4604,21 @@ int sdhci_setup_host(struct sdhci_host *host) !(mmc->caps2 & MMC_CAP2_NONHOTPLUG) && !host->mmc->extcon) mmc->caps |= MMC_CAP_NEEDS_POLL; - /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ if (!IS_ERR(mmc->supply.vqmmc)) { ret = regulator_enable(mmc->supply.vqmmc); + + /* If vqmmc provides no 1.8V signalling, then there's no UHS */ if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 1950000)) host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); + + /* In eMMC case vqmmc might be a fixed 1.8V regulator */ + if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000, + 3600000)) + host->flags &= ~SDHCI_SIGNALING_330; + if (ret) { pr_warn("%s: Failed to enable vqmmc regulator: %d\n", mmc_hostname(mmc), ret); diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 5dc8bd042cc54b2d07407f123d0ee62bce738594..504e34f295180fd97bec354a01b47c5a484665f9 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -737,8 +737,8 @@ static struct flash_info dataflash_data[] = { { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, - { "AT45DB641E", 0x1f28000100, 32768, 264, 9, SUP_EXTID | SUP_POW2PS}, - { "at45db641e", 0x1f28000100, 32768, 256, 8, SUP_EXTID | SUP_POW2PS | IS_POW2PS}, + { "AT45DB641E", 0x1f28000100ULL, 32768, 264, 9, SUP_EXTID | SUP_POW2PS}, + { "at45db641e", 0x1f28000100ULL, 32768, 256, 8, SUP_EXTID | SUP_POW2PS | IS_POW2PS}, }; static struct flash_info *jedec_lookup(struct spi_device *spi, diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c index bb580bc164459a3dee5b27ef34125af8f31ba2d5..c07f21b20463252e63a0ac0f313f75a7c4c05eaa 100644 --- a/drivers/mtd/maps/solutionengine.c +++ b/drivers/mtd/maps/solutionengine.c @@ -59,9 +59,9 @@ static int __init init_soleng_maps(void) return -ENXIO; } } - printk(KERN_NOTICE "Solution Engine: Flash at 0x%08lx, EPROM at 0x%08lx\n", - soleng_flash_map.phys & 0x1fffffff, - soleng_eprom_map.phys & 0x1fffffff); + printk(KERN_NOTICE "Solution Engine: Flash at 0x%pap, EPROM at 0x%pap\n", + &soleng_flash_map.phys, + &soleng_eprom_map.phys); flash_mtd->owner = THIS_MODULE; eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map); diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index b25f444c5914b09980f54c50f88edd3743fe3097..fa4d12217652b542fdd5683a30b6c9cbbbfd9522 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -160,8 +160,12 @@ static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count, pr_debug("MTD_read\n"); - if (*ppos + count > mtd->size) - count = mtd->size - *ppos; + if (*ppos + count > mtd->size) { + if (*ppos < mtd->size) + count = mtd->size - *ppos; + else + count = 0; + } if (!count) return 0; @@ -246,7 +250,7 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c pr_debug("MTD_write\n"); - if (*ppos == mtd->size) + if (*ppos >= mtd->size) return -ENOSPC; if (*ppos + count > mtd->size) diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c index 68c9d98a3347c6ad4592979da0693de7cd27ab8e..148744418e82b768c558cf3c7395d77cd9ddba63 100644 --- a/drivers/mtd/nand/atmel/nand-controller.c +++ b/drivers/mtd/nand/atmel/nand-controller.c @@ -129,6 +129,11 @@ #define DEFAULT_TIMEOUT_MS 1000 #define MIN_DMA_LEN 128 +static bool atmel_nand_avoid_dma __read_mostly; + +MODULE_PARM_DESC(avoiddma, "Avoid using DMA"); +module_param_named(avoiddma, atmel_nand_avoid_dma, bool, 0400); + enum atmel_nand_rb_type { ATMEL_NAND_NO_RB, ATMEL_NAND_NATIVE_RB, @@ -1975,7 +1980,7 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc, return ret; } - if (nc->caps->has_dma) { + if (nc->caps->has_dma && !atmel_nand_avoid_dma) { dma_cap_mask_t mask; dma_cap_zero(mask); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 23a6986d512b4c75ffd22f5ca51b58a8609e5f75..a8f74d9bba4ff82c6d3430e3656f90dc7d5c4b47 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1615,8 +1615,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) cond_resched(); e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); - if (!e) + if (!e) { + err = -ENOMEM; goto out_free; + } e->pnum = aeb->pnum; e->ec = aeb->ec; @@ -1635,8 +1637,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) cond_resched(); e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); - if (!e) + if (!e) { + err = -ENOMEM; goto out_free; + } e->pnum = aeb->pnum; e->ec = aeb->ec; diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c index 9375cef2242053c1f1ade3323d04d7dd4bea77af..3d27616d9c85540304a8d78c4a2f050c0866b9a2 100644 --- a/drivers/net/appletalk/ipddp.c +++ b/drivers/net/appletalk/ipddp.c @@ -283,8 +283,12 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCFINDIPDDPRT: spin_lock_bh(&ipddp_route_lock); rp = __ipddp_find_route(&rcp); - if (rp) - memcpy(&rcp2, rp, sizeof(rcp2)); + if (rp) { + memset(&rcp2, 0, sizeof(rcp2)); + rcp2.ip = rp->ip; + rcp2.at = rp->at; + rcp2.flags = rp->flags; + } spin_unlock_bh(&ipddp_route_lock); if (rp) { diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index ca3fa82316c2a9940865c4b7b056f76fd268db55..d3ce904e929ec81756fdf27ca53921446bbfbe9f 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1637,8 +1637,6 @@ static int m_can_plat_probe(struct platform_device *pdev) priv->can.clock.freq = clk_get_rate(cclk); priv->mram_base = mram_addr; - m_can_of_parse_mram(priv, mram_config_vals); - platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); @@ -1649,6 +1647,8 @@ static int m_can_plat_probe(struct platform_device *pdev) goto failed_free_dev; } + m_can_of_parse_mram(priv, mram_config_vals); + devm_can_led_init(dev); dev_info(&pdev->dev, "%s device registered (irq=%d, version=%d)\n", @@ -1698,8 +1698,6 @@ static __maybe_unused int m_can_resume(struct device *dev) pinctrl_pm_select_default_state(dev); - m_can_init_ram(priv); - priv->can.state = CAN_STATE_ERROR_ACTIVE; if (netif_running(ndev)) { @@ -1709,6 +1707,7 @@ static __maybe_unused int m_can_resume(struct device *dev) if (ret) return ret; + m_can_init_ram(priv); m_can_start(ndev); netif_device_attach(ndev); netif_start_queue(ndev); diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index c7427bdd3a4bff957aaef3fdb1d2f8ed0ead41cb..2949a381a94dceb2674f150ad5feaf580a201d25 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -86,6 +86,11 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev, return 0; } cdm = of_iomap(np_cdm, 0); + if (!cdm) { + of_node_put(np_cdm); + dev_err(&ofdev->dev, "can't map clock node!\n"); + return 0; + } if (in_8(&cdm->ipb_clk_sel) & 0x1) freq *= 2; diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig index 5b7658bcf0209546a4577d708123231c55f97960..5c3ef9fc8207e3de01b86e4c538633ecc8a9f273 100644 --- a/drivers/net/ethernet/3com/Kconfig +++ b/drivers/net/ethernet/3com/Kconfig @@ -32,7 +32,7 @@ config EL3 config 3C515 tristate "3c515 ISA \"Fast EtherLink\"" - depends on ISA && ISA_DMA_API + depends on ISA && ISA_DMA_API && !PPC32 ---help--- If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet network card, say Y here. diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index d5c15e8bb3de706b12d343ee1a50477b23ab3d3f..a8e8f4e9c1bb6009e78150a4665814381c391158 100644 --- a/drivers/net/ethernet/amd/Kconfig +++ b/drivers/net/ethernet/amd/Kconfig @@ -44,7 +44,7 @@ config AMD8111_ETH config LANCE tristate "AMD LANCE and PCnet (AT1500 and NE2100) support" - depends on ISA && ISA_DMA_API && !ARM + depends on ISA && ISA_DMA_API && !ARM && !PPC32 ---help--- If you have a network (Ethernet) card of this type, say Y here. Some LinkSys cards are of this type. @@ -138,7 +138,7 @@ config PCMCIA_NMCLAN config NI65 tristate "NI6510 support" - depends on ISA && ISA_DMA_API && !ARM + depends on ISA && ISA_DMA_API && !ARM && !PPC32 ---help--- If you have a network (Ethernet) card of this type, say Y here. diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index 45d92304068eb5ddb4d48a7fa57996d340732429..a5eaf174d914c3d7057a51c577d1d9fc8ac8ec85 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -289,7 +289,7 @@ static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, struct page *pages = NULL; dma_addr_t pages_dma; gfp_t gfp; - int order, ret; + int order; again: order = alloc_order; @@ -316,10 +316,9 @@ static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, /* Map the pages */ pages_dma = dma_map_page(pdata->dev, pages, 0, PAGE_SIZE << order, DMA_FROM_DEVICE); - ret = dma_mapping_error(pdata->dev, pages_dma); - if (ret) { + if (dma_mapping_error(pdata->dev, pages_dma)) { put_page(pages); - return ret; + return -ENOMEM; } pa->pages = pages; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 8c9986f3fc0186701bd9ae81f27cbb1519e9f25f..3615c2a06fdadf425e45466b58159d3136c88b2d 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1685,6 +1685,7 @@ static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter) skb = build_skb(page_address(page) + adapter->rx_page_offset, adapter->rx_frag_size); if (likely(skb)) { + skb_reserve(skb, NET_SKB_PAD); adapter->rx_page_offset += adapter->rx_frag_size; if (adapter->rx_page_offset >= PAGE_SIZE) adapter->rx_page = NULL; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 352beff796ae5b090d8e3fa831078cc7182d3a2c..828e2e56b75e7617c03ba328b6a23d1d20299c84 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1529,6 +1529,7 @@ struct bnx2x { struct link_vars link_vars; u32 link_cnt; struct bnx2x_link_report_data last_reported_link; + bool force_link_down; struct mdio_if_info mdio; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 6465414dad7478ee9b0cda023512a10517cb9049..8498a357d3895f2fbcbaf374444ae84dbd63e906 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1260,6 +1260,11 @@ void __bnx2x_link_report(struct bnx2x *bp) { struct bnx2x_link_report_data cur_data; + if (bp->force_link_down) { + bp->link_vars.link_up = 0; + return; + } + /* reread mf_cfg */ if (IS_PF(bp) && !CHIP_IS_E1(bp)) bnx2x_read_mf_cfg(bp); @@ -2817,6 +2822,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->pending_max = 0; } + bp->force_link_down = false; if (bp->port.pmf) { rc = bnx2x_initial_phy_init(bp, load_mode); if (rc) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 1e33abde4a3e8c833386df176896ad9684c9dc10..3fd1085a093fa95a6a1bcac895d72a1e5d5063fb 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -3387,14 +3387,18 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); - return bnx2x_rss(bp, &bp->rss_conf_obj, false, true); + if (bp->state == BNX2X_STATE_OPEN) + return bnx2x_rss(bp, &bp->rss_conf_obj, false, + true); } else if ((info->flow_type == UDP_V6_FLOW) && (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); - return bnx2x_rss(bp, &bp->rss_conf_obj, false, true); + if (bp->state == BNX2X_STATE_OPEN) + return bnx2x_rss(bp, &bp->rss_conf_obj, false, + true); } return 0; @@ -3508,7 +3512,10 @@ static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir, bp->rss_conf_obj.ind_table[i] = indir[i] + bp->fp->cl_id; } - return bnx2x_config_rss_eth(bp, false); + if (bp->state == BNX2X_STATE_OPEN) + return bnx2x_config_rss_eth(bp, false); + + return 0; } /** diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index e855a271db48e8e6bc58191708c22c6fef0ff3ba..bd3e3f080ebf835d9df96ea07284b561e0c37180 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10279,6 +10279,12 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work) bp->sp_rtnl_state = 0; smp_mb(); + /* Immediately indicate link as down */ + bp->link_vars.link_up = 0; + bp->force_link_down = true; + netif_carrier_off(bp->dev); + BNX2X_ERR("Indicating link is down due to Tx-timeout\n"); + bnx2x_nic_unload(bp, UNLOAD_NORMAL, true); bnx2x_nic_load(bp, LOAD_NORMAL); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 94931318587c141c81658c6088c2ce76f9654896..937db801928922358cb8607f2f8ad97fb81b2506 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6348,7 +6348,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) rc = bnxt_request_irq(bp); if (rc) { netdev_err(bp->dev, "bnxt_request_irq err: %x\n", rc); - goto open_err; + goto open_err_irq; } } @@ -6386,6 +6386,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) open_err: bnxt_disable_napi(bp); + +open_err_irq: bnxt_del_napi(bp); open_err_free_mem: @@ -7866,11 +7868,11 @@ int bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx, bool shared) int rx, tx, cp; _bnxt_get_max_rings(bp, &rx, &tx, &cp); + *max_rx = rx; + *max_tx = tx; if (!rx || !tx || !cp) return -ENOMEM; - *max_rx = rx; - *max_tx = tx; return bnxt_trim_rings(bp, max_rx, max_tx, cp, shared); } @@ -7884,8 +7886,11 @@ static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx, /* Not enough rings, try disabling agg rings. */ bp->flags &= ~BNXT_FLAG_AGG_RINGS; rc = bnxt_get_max_rings(bp, max_rx, max_tx, shared); - if (rc) + if (rc) { + /* set BNXT_FLAG_AGG_RINGS back for consistency */ + bp->flags |= BNXT_FLAG_AGG_RINGS; return rc; + } bp->flags |= BNXT_FLAG_NO_AGG_RINGS; bp->dev->hw_features &= ~NETIF_F_LRO; bp->dev->features &= ~NETIF_F_LRO; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 4c49d0b9774839e073d35914f4932f110a1ec32b..9d499c5c8f8aaa2989190c6203170f6d456b17c6 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -185,6 +185,9 @@ struct bcmgenet_mib_counters { #define UMAC_MAC1 0x010 #define UMAC_MAX_FRAME_LEN 0x014 +#define UMAC_MODE 0x44 +#define MODE_LINK_STATUS (1 << 5) + #define UMAC_EEE_CTRL 0x064 #define EN_LPI_RX_PAUSE (1 << 0) #define EN_LPI_TX_PFC (1 << 1) diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 18f5723be2c91b1e533a21ef14e342fb9502961c..6ad0ca7ed3e919d0c75f3dd41508f18889523c49 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -115,8 +115,14 @@ void bcmgenet_mii_setup(struct net_device *dev) static int bcmgenet_fixed_phy_link_update(struct net_device *dev, struct fixed_phy_status *status) { - if (dev && dev->phydev && status) - status->link = dev->phydev->link; + struct bcmgenet_priv *priv; + u32 reg; + + if (dev && dev->phydev && status) { + priv = netdev_priv(dev); + reg = bcmgenet_umac_readl(priv, UMAC_MODE); + status->link = !!(reg & MODE_LINK_STATUS); + } return 0; } diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 6df2cad61647a6d7067df5c30371fbd6eda17923..dfef4ec167c186bd9a1f0b5d917b504240361e14 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -1884,14 +1884,17 @@ static void macb_reset_hw(struct macb *bp) { struct macb_queue *queue; unsigned int q; + u32 ctrl = macb_readl(bp, NCR); /* Disable RX and TX (XXX: Should we halt the transmission * more gracefully?) */ - macb_writel(bp, NCR, 0); + ctrl &= ~(MACB_BIT(RE) | MACB_BIT(TE)); /* Clear the stats registers (XXX: Update stats first?) */ - macb_writel(bp, NCR, MACB_BIT(CLRSTAT)); + ctrl |= MACB_BIT(CLRSTAT); + + macb_writel(bp, NCR, ctrl); /* Clear all status flags */ macb_writel(bp, TSR, -1); @@ -2070,7 +2073,7 @@ static void macb_init_hw(struct macb *bp) } /* Enable TX and RX */ - macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE)); + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE)); } /* The hash address register is 64 bits long and takes up two diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c index e8b290473ee25fe3c6f5b9683c86b87254d3767b..2e089b5ff8f327aeb2dbbac6f0076518d75d3de5 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c @@ -493,6 +493,9 @@ static void cn23xx_pf_setup_global_output_regs(struct octeon_device *oct) for (q_no = srn; q_no < ern; q_no++) { reg_val = octeon_read_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(q_no)); + /* clear IPTR */ + reg_val &= ~CN23XX_PKT_OUTPUT_CTL_IPTR; + /* set DPTR */ reg_val |= CN23XX_PKT_OUTPUT_CTL_DPTR; diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c index 9338a00083788059736edefd472710c00b30f9af..1f8b7f65125401ef250f9cf57c266fbb55da3f38 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c @@ -165,6 +165,9 @@ static void cn23xx_vf_setup_global_output_regs(struct octeon_device *oct) reg_val = octeon_read_csr(oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no)); + /* clear IPTR */ + reg_val &= ~CN23XX_PKT_OUTPUT_CTL_IPTR; + /* set DPTR */ reg_val |= CN23XX_PKT_OUTPUT_CTL_DPTR; diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c index 2887bcaf6af56890fbcf5e9f915151d5c08dc455..45c51277e0cf094b53136f466f99d74eca4542e5 100644 --- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c @@ -643,13 +643,21 @@ static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr) static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu) { struct octeon_mgmt *p = netdev_priv(netdev); - int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM; + int max_packet = new_mtu + ETH_HLEN + ETH_FCS_LEN; netdev->mtu = new_mtu; - cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs); + /* HW lifts the limit if the frame is VLAN tagged + * (+4 bytes per each tag, up to two tags) + */ + cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, max_packet); + /* Set the hardware to truncate packets larger than the MTU. The jabber + * register must be set to a multiple of 8 bytes, so round up. JABBER is + * an unconditional limit, so we need to account for two possible VLAN + * tags. + */ cvmx_write_csr(p->agl + AGL_GMX_RX_JABBER, - (size_without_fcs + 7) & 0xfff8); + (max_packet + 7 + VLAN_HLEN * 2) & 0xfff8); return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 44a0d04dd8a033e05507d40569a0e9b2642ee9a9..74a42f12064b6aced2f5813ef96ed92a10ce0c2a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -253,7 +253,7 @@ static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable) "Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n", enable ? "set" : "unset", pi->port_id, i, -err); else - txq->dcb_prio = value; + txq->dcb_prio = enable ? value : 0; } } diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig index 5ab912937aff2e8eb34887deb2aa36c8f45bebde..ec0b545197e2dfd7c0443917c0ec0f33861c77bd 100644 --- a/drivers/net/ethernet/cirrus/Kconfig +++ b/drivers/net/ethernet/cirrus/Kconfig @@ -19,6 +19,7 @@ if NET_VENDOR_CIRRUS config CS89x0 tristate "CS89x0 support" depends on ISA || EISA || ARM + depends on !PPC32 ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the file diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c index 8dc21c9f97168e1a0a12bcf2c0d6b9ea224fa42f..df613a87ccfffb1e4fe19e6107be316a8e67f82a 100644 --- a/drivers/net/ethernet/cisco/enic/enic_clsf.c +++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c @@ -79,7 +79,6 @@ void enic_rfs_flw_tbl_init(struct enic *enic) enic->rfs_h.max = enic->config.num_arfs; enic->rfs_h.free = enic->rfs_h.max; enic->rfs_h.toclean = 0; - enic_rfs_timer_start(enic); } void enic_rfs_flw_tbl_free(struct enic *enic) @@ -88,7 +87,6 @@ void enic_rfs_flw_tbl_free(struct enic *enic) enic_rfs_timer_stop(enic); spin_lock_bh(&enic->rfs_h.lock); - enic->rfs_h.free = 0; for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) { struct hlist_head *hhead; struct hlist_node *tmp; @@ -99,6 +97,7 @@ void enic_rfs_flw_tbl_free(struct enic *enic) enic_delfltr(enic, n->fltr_id); hlist_del(&n->node); kfree(n); + enic->rfs_h.free++; } } spin_unlock_bh(&enic->rfs_h.lock); diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index a03a32a4ffca4928bf4132aa31a33c28f9d48c98..2bfaf3e118b1ea7ef28bdab16084dcf470d651ba 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1930,7 +1930,7 @@ static int enic_open(struct net_device *netdev) vnic_intr_unmask(&enic->intr[i]); enic_notify_timer_start(enic); - enic_rfs_flw_tbl_init(enic); + enic_rfs_timer_start(enic); return 0; @@ -2007,28 +2007,42 @@ static int enic_stop(struct net_device *netdev) return 0; } +static int _enic_change_mtu(struct net_device *netdev, int new_mtu) +{ + bool running = netif_running(netdev); + int err = 0; + + ASSERT_RTNL(); + if (running) { + err = enic_stop(netdev); + if (err) + return err; + } + + netdev->mtu = new_mtu; + + if (running) { + err = enic_open(netdev); + if (err) + return err; + } + + return 0; +} + static int enic_change_mtu(struct net_device *netdev, int new_mtu) { struct enic *enic = netdev_priv(netdev); - int running = netif_running(netdev); if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) return -EOPNOTSUPP; - if (running) - enic_stop(netdev); - - netdev->mtu = new_mtu; - if (netdev->mtu > enic->port_mtu) netdev_warn(netdev, - "interface MTU (%d) set higher than port MTU (%d)\n", - netdev->mtu, enic->port_mtu); + "interface MTU (%d) set higher than port MTU (%d)\n", + netdev->mtu, enic->port_mtu); - if (running) - enic_open(netdev); - - return 0; + return _enic_change_mtu(netdev, new_mtu); } static void enic_change_mtu_work(struct work_struct *work) @@ -2036,47 +2050,9 @@ static void enic_change_mtu_work(struct work_struct *work) struct enic *enic = container_of(work, struct enic, change_mtu_work); struct net_device *netdev = enic->netdev; int new_mtu = vnic_dev_mtu(enic->vdev); - int err; - unsigned int i; - - new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu)); rtnl_lock(); - - /* Stop RQ */ - del_timer_sync(&enic->notify_timer); - - for (i = 0; i < enic->rq_count; i++) - napi_disable(&enic->napi[i]); - - vnic_intr_mask(&enic->intr[0]); - enic_synchronize_irqs(enic); - err = vnic_rq_disable(&enic->rq[0]); - if (err) { - rtnl_unlock(); - netdev_err(netdev, "Unable to disable RQ.\n"); - return; - } - vnic_rq_clean(&enic->rq[0], enic_free_rq_buf); - vnic_cq_clean(&enic->cq[0]); - vnic_intr_clean(&enic->intr[0]); - - /* Fill RQ with new_mtu-sized buffers */ - netdev->mtu = new_mtu; - vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); - /* Need at least one buffer on ring to get going */ - if (vnic_rq_desc_used(&enic->rq[0]) == 0) { - rtnl_unlock(); - netdev_err(netdev, "Unable to alloc receive buffers.\n"); - return; - } - - /* Start RQ */ - vnic_rq_enable(&enic->rq[0]); - napi_enable(&enic->napi[0]); - vnic_intr_unmask(&enic->intr[0]); - enic_notify_timer_start(enic); - + (void)_enic_change_mtu(netdev, new_mtu); rtnl_unlock(); netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu); @@ -2854,6 +2830,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) enic->notify_timer.function = enic_notify_timer; enic->notify_timer.data = (unsigned long)enic; + enic_rfs_flw_tbl_init(enic); enic_set_rx_coal_setting(enic); INIT_WORK(&enic->reset, enic_reset); INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset); @@ -2866,7 +2843,6 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ enic->port_mtu = enic->config.mtu; - (void)enic_change_mtu(netdev, enic->port_mtu); err = enic_set_mac_addr(netdev, enic->mac_addr); if (err) { @@ -2953,6 +2929,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* MTU range: 68 - 9000 */ netdev->min_mtu = ENIC_MIN_MTU; netdev->max_mtu = ENIC_MAX_MTU; + netdev->mtu = enic->port_mtu; err = register_netdev(netdev); if (err) { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 02dd5246dfae9a99b20f2bb4b2b13185d3239a3c..1589a568bfe0ab67c2745ea95c28b6749d6895f5 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -4500,7 +4500,7 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, port_res->max_vfs += le16_to_cpu(pcie->num_vfs); } } - return status; + goto err; } pcie = be_get_pcie_desc(resp->func_param, desc_count, diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 519a021c0a25b41a8102819c21785b1af9d77dab..a202c50d6fc7659d87e6d0763442caed78f96254 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -125,6 +125,9 @@ MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms"); /* Default alignment for start of data in an Rx FD */ #define DPAA_FD_DATA_ALIGNMENT 16 +/* The DPAA requires 256 bytes reserved and mapped for the SGT */ +#define DPAA_SGT_SIZE 256 + /* Values for the L3R field of the FM Parse Results */ /* L3 Type field: First IP Present IPv4 */ @@ -1622,8 +1625,8 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv, if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) { nr_frags = skb_shinfo(skb)->nr_frags; - dma_unmap_single(dev, addr, qm_fd_get_offset(fd) + - sizeof(struct qm_sg_entry) * (1 + nr_frags), + dma_unmap_single(dev, addr, + qm_fd_get_offset(fd) + DPAA_SGT_SIZE, dma_dir); /* The sgt buffer has been allocated with netdev_alloc_frag(), @@ -1907,8 +1910,7 @@ static int skb_to_sg_fd(struct dpaa_priv *priv, void *sgt_buf; /* get a page frag to store the SGTable */ - sz = SKB_DATA_ALIGN(priv->tx_headroom + - sizeof(struct qm_sg_entry) * (1 + nr_frags)); + sz = SKB_DATA_ALIGN(priv->tx_headroom + DPAA_SGT_SIZE); sgt_buf = netdev_alloc_frag(sz); if (unlikely(!sgt_buf)) { netdev_err(net_dev, "netdev_alloc_frag() failed for size %d\n", @@ -1976,9 +1978,8 @@ static int skb_to_sg_fd(struct dpaa_priv *priv, skbh = (struct sk_buff **)buffer_start; *skbh = skb; - addr = dma_map_single(dev, buffer_start, priv->tx_headroom + - sizeof(struct qm_sg_entry) * (1 + nr_frags), - dma_dir); + addr = dma_map_single(dev, buffer_start, + priv->tx_headroom + DPAA_SGT_SIZE, dma_dir); if (unlikely(dma_mapping_error(dev, addr))) { dev_err(dev, "DMA mapping failed"); err = -EINVAL; diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c index 1789b206be58396f3d1eca908d3f36289375ac9b..495190764155abdea8df91bacd686d3d902ca81a 100644 --- a/drivers/net/ethernet/freescale/fman/fman_port.c +++ b/drivers/net/ethernet/freescale/fman/fman_port.c @@ -324,6 +324,10 @@ struct fman_port_qmi_regs { #define HWP_HXS_PHE_REPORT 0x00000800 #define HWP_HXS_PCAC_PSTAT 0x00000100 #define HWP_HXS_PCAC_PSTOP 0x00000001 +#define HWP_HXS_TCP_OFFSET 0xA +#define HWP_HXS_UDP_OFFSET 0xB +#define HWP_HXS_SH_PAD_REM 0x80000000 + struct fman_port_hwp_regs { struct { u32 ssa; /* Soft Sequence Attachment */ @@ -728,6 +732,10 @@ static void init_hwp(struct fman_port *port) iowrite32be(0xffffffff, ®s->pmda[i].lcv); } + /* Short packet padding removal from checksum calculation */ + iowrite32be(HWP_HXS_SH_PAD_REM, ®s->pmda[HWP_HXS_TCP_OFFSET].ssa); + iowrite32be(HWP_HXS_SH_PAD_REM, ®s->pmda[HWP_HXS_UDP_OFFSET].ssa); + start_port_hwp(port); } diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index fa5b30f547f6620a6e761860be6afa341dc185c8..cad52bd331f7b295853b4d2765ad5b1ebd37b0d9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -220,10 +220,10 @@ struct hnae_desc_cb { /* priv data for the desc, e.g. skb when use with ip stack*/ void *priv; - u16 page_offset; - u16 reuse_flag; + u32 page_offset; + u32 length; /* length of the buffer */ - u16 length; /* length of the buffer */ + u16 reuse_flag; /* desc type, used by the ring user to mark the type of the priv data */ u16 type; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index e77192683dbad9a1fca22816e411abf4c3c25d8c..25a9732afc842935fae6770806248c279018ca8d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -530,7 +530,7 @@ static void hns_nic_reuse_page(struct sk_buff *skb, int i, } skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, - size - pull_len, truesize - pull_len); + size - pull_len, truesize); /* avoid re-using remote pages,flag default unreuse */ if (unlikely(page_to_nid(desc_cb->priv) != numa_node_id())) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c133491ad9fa0ab3e5bbd3a5356ff64e8e856627..654aad6e748bdb7d23b8ec3dae875c95d73548fd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3105,7 +3105,7 @@ static bool hclge_is_all_function_id_zero(struct hclge_desc *desc) #define HCLGE_FUNC_NUMBER_PER_DESC 6 int i, j; - for (i = 0; i < HCLGE_DESC_NUMBER; i++) + for (i = 1; i < HCLGE_DESC_NUMBER; i++) for (j = 0; j < HCLGE_FUNC_NUMBER_PER_DESC; j++) if (desc[i].data[j]) return false; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index f32d719c4f77a2bf4dfd00896250aa27cc29f78c..8f90dd1be6b593e808b466abbd948e8899773ba3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -187,6 +187,8 @@ int hclge_mac_start_phy(struct hclge_dev *hdev) if (!phydev) return 0; + phydev->supported &= ~SUPPORTED_FIBRE; + ret = phy_connect_direct(netdev, phydev, hclge_mac_adjust_link, PHY_INTERFACE_MODE_SGMII); diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index c8c7ad2eff77ecb5f2bd4ee5012a41b3ac1afcc8..9b5a68b6543287a93107ae2a923ee3bf99a38a82 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -2634,7 +2634,7 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin) /* Wait for link to drop */ time = jiffies + (HZ / 10); do { - if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST)) + if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST)) break; if (!in_interrupt()) schedule_timeout_interruptible(1); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index eb53bd93065e0da12ddd744feffdd34f853c952e..a696b5b2d40e6bb72bb4cd7663d8f84ea49588ff 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -981,6 +981,7 @@ static int nic_dev_init(struct pci_dev *pdev) hinic_hwdev_cb_register(nic_dev->hwdev, HINIC_MGMT_MSG_CMD_LINK_STATUS, nic_dev, link_status_event_handler); + SET_NETDEV_DEV(netdev, &pdev->dev); err = register_netdev(netdev); if (err) { dev_err(&pdev->dev, "Failed to register netdev\n"); diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 98493be7b4afedf1ad367ba6b21155ddcb25478b..046af22a37cbc13938ac4d1de2c33a63babc5368 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1463,8 +1463,8 @@ static int do_reset(struct ibmvnic_adapter *adapter, rc = ibmvnic_login(netdev); if (rc) { - adapter->state = VNIC_PROBED; - return 0; + adapter->state = reset_state; + return rc; } rc = reset_tx_pools(adapter); diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index 3b3983a1ffbba1d6795ead832c5aceb801023969..10df2d60c1814b91b1a282a2a44a7ddc39a8300c 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -644,14 +644,14 @@ static int e1000_set_ringparam(struct net_device *netdev, adapter->tx_ring = tx_old; e1000_free_all_rx_resources(adapter); e1000_free_all_tx_resources(adapter); - kfree(tx_old); - kfree(rx_old); adapter->rx_ring = rxdr; adapter->tx_ring = txdr; err = e1000_up(adapter); if (err) goto err_setup; } + kfree(tx_old); + kfree(rx_old); clear_bit(__E1000_RESETTING, &adapter->flags); return 0; @@ -664,7 +664,8 @@ static int e1000_set_ringparam(struct net_device *netdev, err_alloc_rx: kfree(txdr); err_alloc_tx: - e1000_up(adapter); + if (netif_running(adapter->netdev)) + e1000_up(adapter); err_setup: clear_bit(__E1000_RESETTING, &adapter->flags); return err; diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index afb7ebe20b2438e9500f5dff2b1126ccde9c4670..824fd44e25f0d694a20bed7733dfebfaff9d0195 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h @@ -400,6 +400,10 @@ #define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ #define E1000_ICR_RXO 0x00000040 /* Receiver Overrun */ #define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ +#define E1000_ICR_MDAC 0x00000200 /* MDIO Access Complete */ +#define E1000_ICR_SRPD 0x00010000 /* Small Receive Packet Detected */ +#define E1000_ICR_ACK 0x00020000 /* Receive ACK Frame Detected */ +#define E1000_ICR_MNG 0x00040000 /* Manageability Event Detected */ #define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 @@ -407,7 +411,7 @@ #define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ #define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ #define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ -#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ +#define E1000_ICR_OTHER 0x01000000 /* Other Interrupt */ /* PBA ECC Register */ #define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */ @@ -431,12 +435,27 @@ E1000_IMS_RXSEQ | \ E1000_IMS_LSC) +/* These are all of the events related to the OTHER interrupt. + */ +#define IMS_OTHER_MASK ( \ + E1000_IMS_LSC | \ + E1000_IMS_RXO | \ + E1000_IMS_MDAC | \ + E1000_IMS_SRPD | \ + E1000_IMS_ACK | \ + E1000_IMS_MNG) + /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ +#define E1000_IMS_RXO E1000_ICR_RXO /* Receiver Overrun */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ +#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO Access Complete */ +#define E1000_IMS_SRPD E1000_ICR_SRPD /* Small Receive Packet */ +#define E1000_IMS_ACK E1000_ICR_ACK /* Receive ACK Frame Detected */ +#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability Event */ #define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ #define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ #define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index ff308b05d68cc91efa7b195db9952d368553557f..00eedf202e62da10eec8ecf310fa1f689aaa0e57 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1367,9 +1367,6 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. - * - * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link - * up). **/ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) { @@ -1385,7 +1382,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) - return 1; + return 0; + mac->get_link_status = false; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex @@ -1393,12 +1391,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) */ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) - return ret_val; + goto out; if (hw->mac.type == e1000_pchlan) { ret_val = e1000_k1_gig_workaround_hv(hw, link); if (ret_val) - return ret_val; + goto out; } /* When connected at 10Mbps half-duplex, some parts are excessively @@ -1431,7 +1429,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire(hw); if (ret_val) - return ret_val; + goto out; if (hw->mac.type == e1000_pch2lan) emi_addr = I82579_RX_CONFIG; @@ -1453,7 +1451,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) hw->phy.ops.release(hw); if (ret_val) - return ret_val; + goto out; if (hw->mac.type >= e1000_pch_spt) { u16 data; @@ -1462,14 +1460,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (speed == SPEED_1000) { ret_val = hw->phy.ops.acquire(hw); if (ret_val) - return ret_val; + goto out; ret_val = e1e_rphy_locked(hw, PHY_REG(776, 20), &data); if (ret_val) { hw->phy.ops.release(hw); - return ret_val; + goto out; } ptr_gap = (data & (0x3FF << 2)) >> 2; @@ -1483,18 +1481,18 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) } hw->phy.ops.release(hw); if (ret_val) - return ret_val; + goto out; } else { ret_val = hw->phy.ops.acquire(hw); if (ret_val) - return ret_val; + goto out; ret_val = e1e_wphy_locked(hw, PHY_REG(776, 20), 0xC023); hw->phy.ops.release(hw); if (ret_val) - return ret_val; + goto out; } } @@ -1521,7 +1519,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) { ret_val = e1000_k1_workaround_lpt_lp(hw, link); if (ret_val) - return ret_val; + goto out; } if (hw->mac.type >= e1000_pch_lpt) { /* Set platform power management values for @@ -1529,7 +1527,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) */ ret_val = e1000_platform_pm_pch_lpt(hw, link); if (ret_val) - return ret_val; + goto out; } /* Clear link partner's EEE ability */ @@ -1552,9 +1550,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) } if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; + goto out; switch (hw->mac.type) { case e1000_pch2lan: @@ -1616,12 +1612,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * different link partner. */ ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { + if (ret_val) e_dbg("Error configuring flow control\n"); - return ret_val; - } - return 1; + return ret_val; + +out: + mac->get_link_status = true; + return ret_val; } static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index db735644b31214e8c35216d35642531c713abbb1..48cc945fc8b0f96e62d5066ba63b136718ce73d7 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -410,9 +410,6 @@ void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. - * - * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link - * up). **/ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) { @@ -426,20 +423,16 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) - return 1; + return 0; + mac->get_link_status = false; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; + if (ret_val || !link) + goto out; /* Check if there was DownShift, must be checked * immediately after link-up @@ -464,12 +457,14 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) * different link partner. */ ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { + if (ret_val) e_dbg("Error configuring flow control\n"); - return ret_val; - } - return 1; + return ret_val; + +out: + mac->get_link_status = true; + return ret_val; } /** diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 6265ce8915b66132f4e8aee12388491b517b8689..a25dc581a9030a8391bee1a630a36d6ba0057eba 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1910,30 +1910,20 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data) struct net_device *netdev = data; struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - u32 icr; - bool enable = true; - - icr = er32(ICR); - if (icr & E1000_ICR_RXO) { - ew32(ICR, E1000_ICR_RXO); - enable = false; - /* napi poll will re-enable Other, make sure it runs */ - if (napi_schedule_prep(&adapter->napi)) { - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } - } + u32 icr = er32(ICR); + + if (icr & adapter->eiac_mask) + ew32(ICS, (icr & adapter->eiac_mask)); + if (icr & E1000_ICR_LSC) { - ew32(ICR, E1000_ICR_LSC); hw->mac.get_link_status = true; /* guard against interrupt when we're going down */ if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); } - if (enable && !test_bit(__E1000_DOWN, &adapter->state)) - ew32(IMS, E1000_IMS_OTHER); + if (!test_bit(__E1000_DOWN, &adapter->state)) + ew32(IMS, E1000_IMS_OTHER | IMS_OTHER_MASK); return IRQ_HANDLED; } @@ -2036,7 +2026,6 @@ static void e1000_configure_msix(struct e1000_adapter *adapter) hw->hw_addr + E1000_EITR_82574(vector)); else writel(1, hw->hw_addr + E1000_EITR_82574(vector)); - adapter->eiac_mask |= E1000_IMS_OTHER; /* Cause Tx interrupts on every write back */ ivar |= BIT(31); @@ -2261,7 +2250,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter) if (adapter->msix_entries) { ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); - ew32(IMS, adapter->eiac_mask | E1000_IMS_LSC); + ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | + IMS_OTHER_MASK); } else if (hw->mac.type >= e1000_pch_lpt) { ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER); } else { @@ -2703,8 +2693,7 @@ static int e1000e_poll(struct napi_struct *napi, int weight) napi_complete_done(napi, work_done); if (!test_bit(__E1000_DOWN, &adapter->state)) { if (adapter->msix_entries) - ew32(IMS, adapter->rx_ring->ims_val | - E1000_IMS_OTHER); + ew32(IMS, adapter->rx_ring->ims_val); else e1000_irq_enable(adapter); } @@ -5100,7 +5089,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) case e1000_media_type_copper: if (hw->mac.get_link_status) { ret_val = hw->mac.ops.check_for_link(hw); - link_active = ret_val > 0; + link_active = !hw->mac.get_link_status; } else { link_active = true; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 64429a14c630f09a2aa4d370d10239046c373d08..815284fe93241ef29cb941465009f07323d9c8b4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1895,7 +1895,12 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, if (enable_addr != 0) rar_high |= IXGBE_RAH_AV; + /* Record lower 32 bits of MAC address and then make + * sure that write is flushed to hardware before writing + * the upper 16 bits and setting the valid bit. + */ IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); + IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); return 0; @@ -1927,8 +1932,13 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); - IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); + /* Clear the address valid bit and upper 16 bits of the address + * before clearing the lower bits. This way we aren't updating + * a live filter. + */ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + IXGBE_WRITE_FLUSH(hw); + IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); /* clear VMDq pool/queue selection for this RAR */ hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 3deaa341331370bf7e88e8e3583d7b4f0fd2b104..074a5b79d691318a3bd2bde35dcb3a5ee93df0ab 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3195,7 +3195,6 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) on_each_cpu(mvneta_percpu_enable, pp, true); mvneta_start_dev(pp); - mvneta_port_up(pp); netdev_update_features(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index cf94fdf25155f9882eb3d5d3395644a22259b982..c7654209668bdebbbb969af753ca54298fabdde0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -449,6 +449,7 @@ const char *mlx5_command_str(int command) MLX5_COMMAND_STR_CASE(SET_HCA_CAP); MLX5_COMMAND_STR_CASE(QUERY_ISSI); MLX5_COMMAND_STR_CASE(SET_ISSI); + MLX5_COMMAND_STR_CASE(SET_DRIVER_VERSION); MLX5_COMMAND_STR_CASE(CREATE_MKEY); MLX5_COMMAND_STR_CASE(QUERY_MKEY); MLX5_COMMAND_STR_CASE(DESTROY_MKEY); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index 17b723218b0c0d891a44379e0f69ad804d43c154..9f9c9ff107354eeb4651a40991c96f842d433c50 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -132,11 +132,11 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) delayed_event_start(priv); dev_ctx->context = intf->add(dev); - set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); - if (intf->attach) - set_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state); - if (dev_ctx->context) { + set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); + if (intf->attach) + set_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state); + spin_lock_irq(&priv->ctx_lock); list_add_tail(&dev_ctx->list, &priv->ctx_list); @@ -211,12 +211,17 @@ static void mlx5_attach_interface(struct mlx5_interface *intf, struct mlx5_priv if (intf->attach) { if (test_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state)) goto out; - intf->attach(dev, dev_ctx->context); + if (intf->attach(dev, dev_ctx->context)) + goto out; + set_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state); } else { if (test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state)) goto out; dev_ctx->context = intf->add(dev); + if (!dev_ctx->context) + goto out; + set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index f697084937c381113632317f263d0af6abef3eee..de72b66df3e587d88aec9353c344afd66a8d08ee 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1525,17 +1525,15 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num) } /* Public E-Switch API */ -#define ESW_ALLOWED(esw) ((esw) && MLX5_VPORT_MANAGER((esw)->dev)) +#define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev)) + int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) { int err; int i, enabled_events; - if (!ESW_ALLOWED(esw)) - return 0; - - if (!MLX5_ESWITCH_MANAGER(esw->dev) || + if (!ESW_ALLOWED(esw) || !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) { esw_warn(esw->dev, "E-Switch FDB is not supported, aborting ...\n"); return -EOPNOTSUPP; @@ -1728,7 +1726,7 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, u64 node_guid; int err = 0; - if (!ESW_ALLOWED(esw)) + if (!MLX5_CAP_GEN(esw->dev, vport_group_manager)) return -EPERM; if (!LEGAL_VPORT(esw, vport) || is_multicast_ether_addr(mac)) return -EINVAL; @@ -1805,7 +1803,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, { struct mlx5_vport *evport; - if (!ESW_ALLOWED(esw)) + if (!MLX5_CAP_GEN(esw->dev, vport_group_manager)) return -EPERM; if (!LEGAL_VPORT(esw, vport)) return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index c699055c0ffdecde6ddaac99a10b2f6dbe1af4ce..4b52b722135d98ac20e04ad76056e3382f9d9f65 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -557,6 +557,7 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw, int nvports) if (err) goto miss_rule_err; + kvfree(flow_group_in); return 0; miss_rule_err: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index db86e1506c8b67fa8849940c4adc958fb783ac92..61f284966a8c99e506f3c0d0f76acafa199a05ab 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -333,9 +333,17 @@ void mlx5_start_health_poll(struct mlx5_core_dev *dev) add_timer(&health->timer); } -void mlx5_stop_health_poll(struct mlx5_core_dev *dev) +void mlx5_stop_health_poll(struct mlx5_core_dev *dev, bool disable_health) { struct mlx5_core_health *health = &dev->priv.health; + unsigned long flags; + + if (disable_health) { + spin_lock_irqsave(&health->wq_lock, flags); + set_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags); + set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags); + spin_unlock_irqrestore(&health->wq_lock, flags); + } del_timer_sync(&health->timer); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 4ddd632d10f9958c34238329f14faed02a021243..e99f1382a4f0ca334421f74da18659010923d707 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -857,8 +857,10 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv) priv->numa_node = dev_to_node(&dev->pdev->dev); priv->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), mlx5_debugfs_root); - if (!priv->dbg_root) + if (!priv->dbg_root) { + dev_err(&pdev->dev, "Cannot create debugfs dir, aborting\n"); return -ENOMEM; + } err = mlx5_pci_enable_device(dev); if (err) { @@ -907,7 +909,7 @@ static void mlx5_pci_close(struct mlx5_core_dev *dev, struct mlx5_priv *priv) pci_clear_master(dev->pdev); release_bar(dev->pdev); mlx5_pci_disable_device(dev); - debugfs_remove(priv->dbg_root); + debugfs_remove_recursive(priv->dbg_root); } static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv) @@ -1227,7 +1229,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, mlx5_cleanup_once(dev); err_stop_poll: - mlx5_stop_health_poll(dev); + mlx5_stop_health_poll(dev, boot); if (mlx5_cmd_teardown_hca(dev)) { dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n"); goto out_err; @@ -1286,7 +1288,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, mlx5_free_irq_vectors(dev); if (cleanup) mlx5_cleanup_once(dev); - mlx5_stop_health_poll(dev); + mlx5_stop_health_poll(dev, cleanup); err = mlx5_cmd_teardown_hca(dev); if (err) { dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n"); @@ -1548,7 +1550,7 @@ static int mlx5_try_fast_unload(struct mlx5_core_dev *dev) * with the HCA, so the health polll is no longer needed. */ mlx5_drain_health_wq(dev); - mlx5_stop_health_poll(dev); + mlx5_stop_health_poll(dev, false); ret = mlx5_cmd_force_teardown_hca(dev); if (ret) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index 71153c0f16054a2e987972b067c0070a54863e88..aa9a88e84e3bf5c1056ee178b87a659020d5e041 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -549,8 +549,6 @@ int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, return -EINVAL; if (!MLX5_CAP_GEN(mdev, vport_group_manager)) return -EACCES; - if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify)) - return -EOPNOTSUPP; in = kvzalloc(inlen, GFP_KERNEL); if (!in) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 8c4ce0a0cc825e93999f5130ede9f136052da35c..06eeea6b2f93111be564f22adfe1e0403eab9249 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -395,6 +395,8 @@ int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, void mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan); void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif); +void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev); /* spectrum_kvdl.c */ int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, unsigned int entry_count, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 516e6324460676ce84cf09dc00b74309695e00c5..3ed4fb346f2357fce463bc812f5c22dc21015b39 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -5131,6 +5131,17 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) mlxsw_sp_vr_put(vr); } +void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev) +{ + struct mlxsw_sp_rif *rif; + + rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); + if (!rif) + return; + mlxsw_sp_rif_destroy(rif); +} + static void mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params, struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 7924f241e3ad068ed68ef295e967384ac559a08d..32c25772f75586dbb4884b6afc2c84d08931702d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -140,6 +140,24 @@ bool mlxsw_sp_bridge_device_is_offloaded(const struct mlxsw_sp *mlxsw_sp, return !!mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev); } +static int mlxsw_sp_bridge_device_upper_rif_destroy(struct net_device *dev, + void *data) +{ + struct mlxsw_sp *mlxsw_sp = data; + + mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev); + return 0; +} + +static void mlxsw_sp_bridge_device_rifs_destroy(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev) +{ + mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev); + netdev_walk_all_upper_dev_rcu(dev, + mlxsw_sp_bridge_device_upper_rif_destroy, + mlxsw_sp); +} + static struct mlxsw_sp_bridge_device * mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge, struct net_device *br_dev) @@ -176,6 +194,8 @@ static void mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge, struct mlxsw_sp_bridge_device *bridge_device) { + mlxsw_sp_bridge_device_rifs_destroy(bridge->mlxsw_sp, + bridge_device->dev); list_del(&bridge_device->list); if (bridge_device->vlan_enabled) bridge->vlan_enabled_exists = false; diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index 91fe0361710657ecbd6fba6dcc54b00894019480..72496060e3328e2be01b05be649f13e0f835b219 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -79,7 +79,7 @@ nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port) return NFP_REPR_TYPE_VF; } - return NFP_FLOWER_CMSG_PORT_TYPE_UNSPEC; + return __NFP_REPR_TYPE_MAX; } static struct net_device * @@ -90,6 +90,8 @@ nfp_flower_repr_get(struct nfp_app *app, u32 port_id) u8 port = 0; repr_type = nfp_flower_repr_get_type_and_port(app, port_id, &port); + if (repr_type > NFP_REPR_TYPE_MAX) + return NULL; reprs = rcu_dereference(app->reprs[repr_type]); if (!reprs) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 8d53a593fb27435052d5bcbbecac6a3b86aec873..56751990bceefc9e9fa27a1d6cd82980c443fd1c 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -227,29 +227,16 @@ static void nfp_net_reconfig_post(struct nfp_net *nn, u32 update) spin_unlock_bh(&nn->reconfig_lock); } -/** - * nfp_net_reconfig() - Reconfigure the firmware - * @nn: NFP Net device to reconfigure - * @update: The value for the update field in the BAR config - * - * Write the update word to the BAR and ping the reconfig queue. The - * poll until the firmware has acknowledged the update by zeroing the - * update word. - * - * Return: Negative errno on error, 0 on success - */ -int nfp_net_reconfig(struct nfp_net *nn, u32 update) +static void nfp_net_reconfig_sync_enter(struct nfp_net *nn) { bool cancelled_timer = false; u32 pre_posted_requests; - int ret; spin_lock_bh(&nn->reconfig_lock); nn->reconfig_sync_present = true; if (nn->reconfig_timer_active) { - del_timer(&nn->reconfig_timer); nn->reconfig_timer_active = false; cancelled_timer = true; } @@ -258,14 +245,43 @@ int nfp_net_reconfig(struct nfp_net *nn, u32 update) spin_unlock_bh(&nn->reconfig_lock); - if (cancelled_timer) + if (cancelled_timer) { + del_timer_sync(&nn->reconfig_timer); nfp_net_reconfig_wait(nn, nn->reconfig_timer.expires); + } /* Run the posted reconfigs which were issued before we started */ if (pre_posted_requests) { nfp_net_reconfig_start(nn, pre_posted_requests); nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT); } +} + +static void nfp_net_reconfig_wait_posted(struct nfp_net *nn) +{ + nfp_net_reconfig_sync_enter(nn); + + spin_lock_bh(&nn->reconfig_lock); + nn->reconfig_sync_present = false; + spin_unlock_bh(&nn->reconfig_lock); +} + +/** + * nfp_net_reconfig() - Reconfigure the firmware + * @nn: NFP Net device to reconfigure + * @update: The value for the update field in the BAR config + * + * Write the update word to the BAR and ping the reconfig queue. The + * poll until the firmware has acknowledged the update by zeroing the + * update word. + * + * Return: Negative errno on error, 0 on success + */ +int nfp_net_reconfig(struct nfp_net *nn, u32 update) +{ + int ret; + + nfp_net_reconfig_sync_enter(nn); nfp_net_reconfig_start(nn, update); ret = nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT); @@ -1071,7 +1087,7 @@ static bool nfp_net_xdp_complete(struct nfp_net_tx_ring *tx_ring) * @dp: NFP Net data path struct * @tx_ring: TX ring structure * - * Assumes that the device is stopped + * Assumes that the device is stopped, must be idempotent. */ static void nfp_net_tx_ring_reset(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring) @@ -1273,13 +1289,18 @@ static void nfp_net_rx_give_one(const struct nfp_net_dp *dp, * nfp_net_rx_ring_reset() - Reflect in SW state of freelist after disable * @rx_ring: RX ring structure * - * Warning: Do *not* call if ring buffers were never put on the FW freelist - * (i.e. device was not enabled)! + * Assumes that the device is stopped, must be idempotent. */ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) { unsigned int wr_idx, last_idx; + /* wr_p == rd_p means ring was never fed FL bufs. RX rings are always + * kept at cnt - 1 FL bufs. + */ + if (rx_ring->wr_p == 0 && rx_ring->rd_p == 0) + return; + /* Move the empty entry to the end of the list */ wr_idx = D_IDX(rx_ring, rx_ring->wr_p); last_idx = rx_ring->cnt - 1; @@ -2489,6 +2510,8 @@ static void nfp_net_vec_clear_ring_data(struct nfp_net *nn, unsigned int idx) /** * nfp_net_clear_config_and_disable() - Clear control BAR and disable NFP * @nn: NFP Net device to reconfigure + * + * Warning: must be fully idempotent. */ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) { @@ -3560,6 +3583,7 @@ struct nfp_net *nfp_net_alloc(struct pci_dev *pdev, bool needs_netdev, */ void nfp_net_free(struct nfp_net *nn) { + WARN_ON(timer_pending(&nn->reconfig_timer) || nn->reconfig_posted); if (nn->xdp_prog) bpf_prog_put(nn->xdp_prog); @@ -3829,4 +3853,5 @@ void nfp_net_clean(struct nfp_net *nn) return; unregister_netdev(nn->dp.netdev); + nfp_net_reconfig_wait_posted(nn); } diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.c index cd34097b79f1be9d313d8f28b9701bb5bd6a3100..37a6d7822a3860647c416efeff47c7a7837a3a85 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.c @@ -232,7 +232,7 @@ struct nfp_nffw_info *nfp_nffw_info_open(struct nfp_cpp *cpp) err = nfp_cpp_read(cpp, nfp_resource_cpp_id(state->res), nfp_resource_address(state->res), fwinf, sizeof(*fwinf)); - if (err < sizeof(*fwinf)) + if (err < (int)sizeof(*fwinf)) goto err_release; if (!nffw_res_flg_init_get(fwinf)) diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c index b306961b02fdf40aef89db7d5ed1e535a98a65a1..d62dccb85539404f8173e5713d805a096859b09a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c @@ -255,9 +255,8 @@ qed_dcbx_get_app_protocol_type(struct qed_hwfn *p_hwfn, *type = DCBX_PROTOCOL_ROCE_V2; } else { *type = DCBX_MAX_PROTOCOL_TYPE; - DP_ERR(p_hwfn, - "No action required, App TLV id = 0x%x app_prio_bitmap = 0x%x\n", - id, app_prio_bitmap); + DP_ERR(p_hwfn, "No action required, App TLV entry = 0x%x\n", + app_prio_bitmap); return false; } @@ -1472,8 +1471,8 @@ static u8 qed_dcbnl_getcap(struct qed_dev *cdev, int capid, u8 *cap) *cap = 0x80; break; case DCB_CAP_ATTR_DCBX: - *cap = (DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE | - DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_STATIC); + *cap = (DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_VER_IEEE | + DCB_CAP_DCBX_STATIC); break; default: *cap = false; @@ -1541,8 +1540,6 @@ static u8 qed_dcbnl_getdcbx(struct qed_dev *cdev) if (!dcbx_info) return 0; - if (dcbx_info->operational.enabled) - mode |= DCB_CAP_DCBX_LLD_MANAGED; if (dcbx_info->operational.ieee) mode |= DCB_CAP_DCBX_VER_IEEE; if (dcbx_info->operational.cee) diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index c5452b445c37c142de2eb3cc083ec1a2516a366d..83c1c4fa102b7bce5ce9822653f0f7688446a50f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -663,7 +663,7 @@ qed_sp_update_mcast_bin(struct qed_hwfn *p_hwfn, p_ramrod->common.update_approx_mcast_flg = 1; for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { - u32 *p_bins = (u32 *)p_params->bins; + u32 *p_bins = p_params->bins; p_ramrod->approx_mcast.bins[i] = cpu_to_le32(p_bins[i]); } @@ -1474,8 +1474,8 @@ qed_sp_eth_filter_mcast(struct qed_hwfn *p_hwfn, enum spq_mode comp_mode, struct qed_spq_comp_cb *p_comp_data) { - unsigned long bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; struct vport_update_ramrod_data *p_ramrod = NULL; + u32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; struct qed_spq_entry *p_ent = NULL; struct qed_sp_init_data init_data; u8 abs_vport_id = 0; @@ -1511,26 +1511,25 @@ qed_sp_eth_filter_mcast(struct qed_hwfn *p_hwfn, /* explicitly clear out the entire vector */ memset(&p_ramrod->approx_mcast.bins, 0, sizeof(p_ramrod->approx_mcast.bins)); - memset(bins, 0, sizeof(unsigned long) * - ETH_MULTICAST_MAC_BINS_IN_REGS); + memset(bins, 0, sizeof(bins)); /* filter ADD op is explicit set op and it removes * any existing filters for the vport */ if (p_filter_cmd->opcode == QED_FILTER_ADD) { for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) { - u32 bit; + u32 bit, nbits; bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]); - __set_bit(bit, bins); + nbits = sizeof(u32) * BITS_PER_BYTE; + bins[bit / nbits] |= 1 << (bit % nbits); } /* Convert to correct endianity */ for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { struct vport_update_ramrod_mcast *p_ramrod_bins; - u32 *p_bins = (u32 *)bins; p_ramrod_bins = &p_ramrod->approx_mcast; - p_ramrod_bins->bins[i] = cpu_to_le32(p_bins[i]); + p_ramrod_bins->bins[i] = cpu_to_le32(bins[i]); } } diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.h b/drivers/net/ethernet/qlogic/qed/qed_l2.h index cc1f248551c9d4a13c5235ba00d83ebcd24b61b1..91d383f3a661ff5898d9268166fb33e8ebf64e05 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.h +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.h @@ -214,7 +214,7 @@ struct qed_sp_vport_update_params { u8 anti_spoofing_en; u8 update_accept_any_vlan_flg; u8 accept_any_vlan; - unsigned long bins[8]; + u32 bins[8]; struct qed_rss_params *rss_params; struct qed_filter_accept_flags accept_flags; struct qed_sge_tpa_params *sge_tpa_params; diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c index c06ad4f0758eb755ad9d82ffccecc3def154fc6b..5f52f14761a30472c8a483474256fdb70d6c3861 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c @@ -201,8 +201,9 @@ void qed_ll2b_complete_rx_packet(void *cxt, struct qed_ll2_comp_rx_data *data) skb = build_skb(buffer->data, 0); if (!skb) { - rc = -ENOMEM; - goto out_post; + DP_INFO(cdev, "Failed to build SKB\n"); + kfree(buffer->data); + goto out_post1; } data->u.placement_offset += NET_SKB_PAD; @@ -224,8 +225,14 @@ void qed_ll2b_complete_rx_packet(void *cxt, struct qed_ll2_comp_rx_data *data) cdev->ll2->cbs->rx_cb(cdev->ll2->cb_cookie, skb, data->opaque_data_0, data->opaque_data_1); + } else { + DP_VERBOSE(p_hwfn, (NETIF_MSG_RX_STATUS | NETIF_MSG_PKTDATA | + QED_MSG_LL2 | QED_MSG_STORAGE), + "Dropping the packet\n"); + kfree(buffer->data); } +out_post1: /* Update Buffer information and update FW producer */ buffer->data = new_data; buffer->phys_addr = new_phys_addr; diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 2c958921dfb36f876594b6b0f7f22d67628731fb..954f7ce4cf2850a4130742bbd1e67e07ae1deea9 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -565,8 +565,16 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance) /* Fastpath interrupts */ for (j = 0; j < 64; j++) { if ((0x2ULL << j) & status) { - hwfn->simd_proto_handler[j].func( - hwfn->simd_proto_handler[j].token); + struct qed_simd_fp_handler *p_handler = + &hwfn->simd_proto_handler[j]; + + if (p_handler->func) + p_handler->func(p_handler->token); + else + DP_NOTICE(hwfn, + "Not calling fastpath handler as it is NULL [handler #%d, status 0x%llx]\n", + j, status); + status &= ~(0x2ULL << j); rc = IRQ_HANDLED; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 376485d99357dc0ca18dde626300da1327e35721..7938abe9a30106450245ff94f8a28a155dcac54f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -47,7 +47,7 @@ #include "qed_reg_addr.h" #include "qed_sriov.h" -#define CHIP_MCP_RESP_ITER_US 10 +#define QED_MCP_RESP_ITER_US 10 #define QED_DRV_MB_MAX_RETRIES (500 * 1000) /* Account for 5 sec */ #define QED_MCP_RESET_RETRIES (50 * 1000) /* Account for 500 msec */ @@ -182,18 +182,57 @@ int qed_mcp_free(struct qed_hwfn *p_hwfn) return 0; } +/* Maximum of 1 sec to wait for the SHMEM ready indication */ +#define QED_MCP_SHMEM_RDY_MAX_RETRIES 20 +#define QED_MCP_SHMEM_RDY_ITER_MS 50 + static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { struct qed_mcp_info *p_info = p_hwfn->mcp_info; + u8 cnt = QED_MCP_SHMEM_RDY_MAX_RETRIES; + u8 msec = QED_MCP_SHMEM_RDY_ITER_MS; u32 drv_mb_offsize, mfw_mb_offsize; u32 mcp_pf_id = MCP_PF_ID(p_hwfn); p_info->public_base = qed_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR); - if (!p_info->public_base) - return 0; + if (!p_info->public_base) { + DP_NOTICE(p_hwfn, + "The address of the MCP scratch-pad is not configured\n"); + return -EINVAL; + } p_info->public_base |= GRCBASE_MCP; + /* Get the MFW MB address and number of supported messages */ + mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, + SECTION_OFFSIZE_ADDR(p_info->public_base, + PUBLIC_MFW_MB)); + p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id); + p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, + p_info->mfw_mb_addr + + offsetof(struct public_mfw_mb, + sup_msgs)); + + /* The driver can notify that there was an MCP reset, and might read the + * SHMEM values before the MFW has completed initializing them. + * To avoid this, the "sup_msgs" field in the MFW mailbox is used as a + * data ready indication. + */ + while (!p_info->mfw_mb_length && --cnt) { + msleep(msec); + p_info->mfw_mb_length = + (u16)qed_rd(p_hwfn, p_ptt, + p_info->mfw_mb_addr + + offsetof(struct public_mfw_mb, sup_msgs)); + } + + if (!cnt) { + DP_NOTICE(p_hwfn, + "Failed to get the SHMEM ready notification after %d msec\n", + QED_MCP_SHMEM_RDY_MAX_RETRIES * msec); + return -EBUSY; + } + /* Calculate the driver and MFW mailbox address */ drv_mb_offsize = qed_rd(p_hwfn, p_ptt, SECTION_OFFSIZE_ADDR(p_info->public_base, @@ -203,13 +242,6 @@ static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n", drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id); - /* Set the MFW MB address */ - mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, - SECTION_OFFSIZE_ADDR(p_info->public_base, - PUBLIC_MFW_MB)); - p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id); - p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, p_info->mfw_mb_addr); - /* Get the current driver mailbox sequence before sending * the first command */ @@ -284,9 +316,15 @@ static void qed_mcp_reread_offsets(struct qed_hwfn *p_hwfn, int qed_mcp_reset(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 org_mcp_reset_seq, seq, delay = CHIP_MCP_RESP_ITER_US, cnt = 0; + u32 org_mcp_reset_seq, seq, delay = QED_MCP_RESP_ITER_US, cnt = 0; int rc = 0; + if (p_hwfn->mcp_info->b_block_cmd) { + DP_NOTICE(p_hwfn, + "The MFW is not responsive. Avoid sending MCP_RESET mailbox command.\n"); + return -EBUSY; + } + /* Ensure that only a single thread is accessing the mailbox */ spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); @@ -412,14 +450,41 @@ static void __qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, (p_mb_params->cmd | seq_num), p_mb_params->param); } +static void qed_mcp_cmd_set_blocking(struct qed_hwfn *p_hwfn, bool block_cmd) +{ + p_hwfn->mcp_info->b_block_cmd = block_cmd; + + DP_INFO(p_hwfn, "%s sending of mailbox commands to the MFW\n", + block_cmd ? "Block" : "Unblock"); +} + +static void qed_mcp_print_cpu_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2; + u32 delay = QED_MCP_RESP_ITER_US; + + cpu_mode = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); + cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); + cpu_pc_0 = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER); + udelay(delay); + cpu_pc_1 = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER); + udelay(delay); + cpu_pc_2 = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER); + + DP_NOTICE(p_hwfn, + "MCP CPU info: mode 0x%08x, state 0x%08x, pc {0x%08x, 0x%08x, 0x%08x}\n", + cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2); +} + static int _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, struct qed_mcp_mb_params *p_mb_params, - u32 max_retries, u32 delay) + u32 max_retries, u32 usecs) { + u32 cnt = 0, msecs = DIV_ROUND_UP(usecs, 1000); struct qed_mcp_cmd_elem *p_cmd_elem; - u32 cnt = 0; u16 seq_num; int rc = 0; @@ -442,7 +507,11 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, goto err; spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); - udelay(delay); + + if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) + msleep(msecs); + else + udelay(usecs); } while (++cnt < max_retries); if (cnt >= max_retries) { @@ -471,7 +540,11 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, * The spinlock stays locked until the list element is removed. */ - udelay(delay); + if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) + msleep(msecs); + else + udelay(usecs); + spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); if (p_cmd_elem->b_is_completed) @@ -490,11 +563,15 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, DP_NOTICE(p_hwfn, "The MFW failed to respond to command 0x%08x [param 0x%08x].\n", p_mb_params->cmd, p_mb_params->param); + qed_mcp_print_cpu_info(p_hwfn, p_ptt); spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); + if (!QED_MB_FLAGS_IS_SET(p_mb_params, AVOID_BLOCK)) + qed_mcp_cmd_set_blocking(p_hwfn, true); + return -EAGAIN; } @@ -506,7 +583,7 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, "MFW mailbox: response 0x%08x param 0x%08x [after %d.%03d ms]\n", p_mb_params->mcp_resp, p_mb_params->mcp_param, - (cnt * delay) / 1000, (cnt * delay) % 1000); + (cnt * usecs) / 1000, (cnt * usecs) % 1000); /* Clear the sequence number from the MFW response */ p_mb_params->mcp_resp &= FW_MSG_CODE_MASK; @@ -524,7 +601,7 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, { size_t union_data_size = sizeof(union drv_union_data); u32 max_retries = QED_DRV_MB_MAX_RETRIES; - u32 delay = CHIP_MCP_RESP_ITER_US; + u32 usecs = QED_MCP_RESP_ITER_US; /* MCP not initialized */ if (!qed_mcp_is_init(p_hwfn)) { @@ -532,6 +609,13 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, return -EBUSY; } + if (p_hwfn->mcp_info->b_block_cmd) { + DP_NOTICE(p_hwfn, + "The MFW is not responsive. Avoid sending mailbox command 0x%08x [param 0x%08x].\n", + p_mb_params->cmd, p_mb_params->param); + return -EBUSY; + } + if (p_mb_params->data_src_size > union_data_size || p_mb_params->data_dst_size > union_data_size) { DP_ERR(p_hwfn, @@ -541,8 +625,13 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, return -EINVAL; } + if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) { + max_retries = DIV_ROUND_UP(max_retries, 1000); + usecs *= 1000; + } + return _qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries, - delay); + usecs); } int qed_mcp_cmd(struct qed_hwfn *p_hwfn, @@ -731,6 +820,7 @@ __qed_mcp_load_req(struct qed_hwfn *p_hwfn, mb_params.data_src_size = sizeof(load_req); mb_params.p_data_dst = &load_rsp; mb_params.data_dst_size = sizeof(load_rsp); + mb_params.flags = QED_MB_FLAG_CAN_SLEEP | QED_MB_FLAG_AVOID_BLOCK; DP_VERBOSE(p_hwfn, QED_MSG_SP, "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n", @@ -952,7 +1042,8 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn, int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 wol_param, mcp_resp, mcp_param; + struct qed_mcp_mb_params mb_params; + u32 wol_param; switch (p_hwfn->cdev->wol_config) { case QED_OV_WOL_DISABLED: @@ -970,8 +1061,12 @@ int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP; } - return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_UNLOAD_REQ, wol_param, - &mcp_resp, &mcp_param); + memset(&mb_params, 0, sizeof(mb_params)); + mb_params.cmd = DRV_MSG_CODE_UNLOAD_REQ; + mb_params.param = wol_param; + mb_params.flags = QED_MB_FLAG_CAN_SLEEP | QED_MB_FLAG_AVOID_BLOCK; + + return qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); } int qed_mcp_unload_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) @@ -1182,6 +1277,7 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, break; default: p_link->speed = 0; + p_link->link_up = 0; } if (p_link->link_up && p_link->speed) @@ -1279,9 +1375,15 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up) phy_cfg.pause |= (params->pause.forced_tx) ? ETH_PAUSE_TX : 0; phy_cfg.adv_speed = params->speed.advertised_speeds; phy_cfg.loopback_mode = params->loopback_mode; - if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) { - if (params->eee.enable) - phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED; + + /* There are MFWs that share this capability regardless of whether + * this is feasible or not. And given that at the very least adv_caps + * would be set internally by qed, we want to make sure LFA would + * still work. + */ + if ((p_hwfn->mcp_info->capabilities & + FW_MB_PARAM_FEATURE_SUPPORT_EEE) && params->eee.enable) { + phy_cfg.eee_cfg |= EEE_CFG_EEE_ENABLED; if (params->eee.tx_lpi_enable) phy_cfg.eee_cfg |= EEE_CFG_TX_LPI; if (params->eee.adv_caps & QED_EEE_1G_ADV) @@ -1959,31 +2061,65 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, return rc; } +/* A maximal 100 msec waiting time for the MCP to halt */ +#define QED_MCP_HALT_SLEEP_MS 10 +#define QED_MCP_HALT_MAX_RETRIES 10 + int qed_mcp_halt(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 resp = 0, param = 0; + u32 resp = 0, param = 0, cpu_state, cnt = 0; int rc; rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp, ¶m); - if (rc) + if (rc) { DP_ERR(p_hwfn, "MCP response failure, aborting\n"); + return rc; + } - return rc; + do { + msleep(QED_MCP_HALT_SLEEP_MS); + cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); + if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) + break; + } while (++cnt < QED_MCP_HALT_MAX_RETRIES); + + if (cnt == QED_MCP_HALT_MAX_RETRIES) { + DP_NOTICE(p_hwfn, + "Failed to halt the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n", + qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE), cpu_state); + return -EBUSY; + } + + qed_mcp_cmd_set_blocking(p_hwfn, true); + + return 0; } +#define QED_MCP_RESUME_SLEEP_MS 10 + int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 value, cpu_mode; + u32 cpu_mode, cpu_state; qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff); - value = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); - value &= ~MCP_REG_CPU_MODE_SOFT_HALT; - qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, value); cpu_mode = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); + cpu_mode &= ~MCP_REG_CPU_MODE_SOFT_HALT; + qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, cpu_mode); + msleep(QED_MCP_RESUME_SLEEP_MS); + cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); - return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -EAGAIN : 0; + if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) { + DP_NOTICE(p_hwfn, + "Failed to resume the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n", + cpu_mode, cpu_state); + return -EBUSY; + } + + qed_mcp_cmd_set_blocking(p_hwfn, false); + + return 0; } int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index c7ec2395d1cebd795c9cd33de937da4de6099513..f1fe5e3427ea54f55831563e2a89e4aeea7ad2aa 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -540,11 +540,14 @@ struct qed_mcp_info { */ spinlock_t cmd_lock; + /* Flag to indicate whether sending a MFW mailbox command is blocked */ + bool b_block_cmd; + /* Spinlock used for syncing SW link-changes and link-changes * originating from attention context. */ spinlock_t link_lock; - bool block_mb_sending; + u32 public_base; u32 drv_mb_addr; u32 mfw_mb_addr; @@ -565,14 +568,20 @@ struct qed_mcp_info { }; struct qed_mcp_mb_params { - u32 cmd; - u32 param; - void *p_data_src; - u8 data_src_size; - void *p_data_dst; - u8 data_dst_size; - u32 mcp_resp; - u32 mcp_param; + u32 cmd; + u32 param; + void *p_data_src; + void *p_data_dst; + u8 data_src_size; + u8 data_dst_size; + u32 mcp_resp; + u32 mcp_param; + u32 flags; +#define QED_MB_FLAG_CAN_SLEEP (0x1 << 0) +#define QED_MB_FLAG_AVOID_BLOCK (0x1 << 1) +#define QED_MB_FLAGS_IS_SET(params, flag) \ + ({ typeof(params) __params = (params); \ + (__params && (__params->flags & QED_MB_FLAG_ ## flag)); }) }; /** diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index 0cdb4337b3a057befc98b3c69c0d65085d81b918..d1201bb2d4bb7d6ef28ca19d74f2b32fd2271a42 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -554,8 +554,10 @@ 0 #define MCP_REG_CPU_STATE \ 0xe05004UL +#define MCP_REG_CPU_STATE_SOFT_HALTED (0x1UL << 10) #define MCP_REG_CPU_EVENT_MASK \ 0xe05008UL +#define MCP_REG_CPU_PROGRAM_COUNTER 0xe0501cUL #define PGLUE_B_REG_PF_BAR0_SIZE \ 0x2aae60UL #define PGLUE_B_REG_PF_BAR1_SIZE \ diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index d08fe350ab6cd3f925ce2de8768c893b82796c93..c6411158afd7b4f837c49311515ff4d6c29325fc 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -2826,7 +2826,7 @@ qed_iov_vp_update_mcast_bin_param(struct qed_hwfn *p_hwfn, p_data->update_approx_mcast_flg = 1; memcpy(p_data->bins, p_mcast_tlv->bins, - sizeof(unsigned long) * ETH_MULTICAST_MAC_BINS_IN_REGS); + sizeof(u32) * ETH_MULTICAST_MAC_BINS_IN_REGS); *tlvs_mask |= 1 << QED_IOV_VP_UPDATE_MCAST; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c index 91b5e9f02a622cdfe4f1cff142d47c7a1b0b61ef..6eb85db69f9a9ada7c128706d60b434cd097d569 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.c +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c @@ -1126,7 +1126,7 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, resp_size += sizeof(struct pfvf_def_resp_tlv); memcpy(p_mcast_tlv->bins, p_params->bins, - sizeof(unsigned long) * ETH_MULTICAST_MAC_BINS_IN_REGS); + sizeof(u32) * ETH_MULTICAST_MAC_BINS_IN_REGS); } update_rx = p_params->accept_flags.update_rx_mode_config; @@ -1272,7 +1272,7 @@ void qed_vf_pf_filter_mcast(struct qed_hwfn *p_hwfn, u32 bit; bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]); - __set_bit(bit, sp_params.bins); + sp_params.bins[bit / 32] |= 1 << (bit % 32); } } diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h index 97d44dfb38ca2a3f9e9ca6e0585afcbe00378ca7..1e93c712fa346279cc2ec2d6038115ee91607c67 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.h +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h @@ -392,7 +392,12 @@ struct vfpf_vport_update_mcast_bin_tlv { struct channel_tlv tl; u8 padding[4]; - u64 bins[8]; + /* There are only 256 approx bins, and in HSI they're divided into + * 32-bit values. As old VFs used to set-bit to the values on its side, + * the upper half of the array is never expected to contain any data. + */ + u64 bins[4]; + u64 obsolete_bins[4]; }; struct vfpf_vport_update_accept_param_tlv { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 287d89dd086ff76981df302b847d882d887408c6..9c94240bb05ad7e88e97a0351ff6f57cb6b67882 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -1128,6 +1128,8 @@ static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp, struct qlcnic_adapter *adapter = dev_get_drvdata(dev); ret = kstrtoul(buf, 16, &data); + if (ret) + return ret; switch (data) { case QLC_83XX_FLASH_SECTOR_ERASE_CMD: diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 9feec70094435e19ee039f18ea430291d9f7d1a0..0e3b2890b92589771e11ff32660bde3c07ab6f20 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -2386,26 +2386,20 @@ static int qlge_update_hw_vlan_features(struct net_device *ndev, return status; } -static netdev_features_t qlge_fix_features(struct net_device *ndev, - netdev_features_t features) -{ - int err; - - /* Update the behavior of vlan accel in the adapter */ - err = qlge_update_hw_vlan_features(ndev, features); - if (err) - return err; - - return features; -} - static int qlge_set_features(struct net_device *ndev, netdev_features_t features) { netdev_features_t changed = ndev->features ^ features; + int err; + + if (changed & NETIF_F_HW_VLAN_CTAG_RX) { + /* Update the behavior of vlan accel in the adapter */ + err = qlge_update_hw_vlan_features(ndev, features); + if (err) + return err; - if (changed & NETIF_F_HW_VLAN_CTAG_RX) qlge_vlan_mode(ndev, features); + } return 0; } @@ -4719,7 +4713,6 @@ static const struct net_device_ops qlge_netdev_ops = { .ndo_set_mac_address = qlge_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = qlge_tx_timeout, - .ndo_fix_features = qlge_fix_features, .ndo_set_features = qlge_set_features, .ndo_vlan_rx_add_vid = qlge_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid, diff --git a/drivers/net/ethernet/qualcomm/qca_7k.c b/drivers/net/ethernet/qualcomm/qca_7k.c index ffe7a16bdfc840d859292f6939938b75fba15a41..6c8543fb90c0a3ac780edd36aa701b01e7c9d94a 100644 --- a/drivers/net/ethernet/qualcomm/qca_7k.c +++ b/drivers/net/ethernet/qualcomm/qca_7k.c @@ -45,34 +45,33 @@ qcaspi_read_register(struct qcaspi *qca, u16 reg, u16 *result) { __be16 rx_data; __be16 tx_data; - struct spi_transfer *transfer; - struct spi_message *msg; + struct spi_transfer transfer[2]; + struct spi_message msg; int ret; + memset(transfer, 0, sizeof(transfer)); + + spi_message_init(&msg); + tx_data = cpu_to_be16(QCA7K_SPI_READ | QCA7K_SPI_INTERNAL | reg); + *result = 0; + + transfer[0].tx_buf = &tx_data; + transfer[0].len = QCASPI_CMD_LEN; + transfer[1].rx_buf = &rx_data; + transfer[1].len = QCASPI_CMD_LEN; + + spi_message_add_tail(&transfer[0], &msg); if (qca->legacy_mode) { - msg = &qca->spi_msg1; - transfer = &qca->spi_xfer1; - transfer->tx_buf = &tx_data; - transfer->rx_buf = NULL; - transfer->len = QCASPI_CMD_LEN; - spi_sync(qca->spi_dev, msg); - } else { - msg = &qca->spi_msg2; - transfer = &qca->spi_xfer2[0]; - transfer->tx_buf = &tx_data; - transfer->rx_buf = NULL; - transfer->len = QCASPI_CMD_LEN; - transfer = &qca->spi_xfer2[1]; + spi_sync(qca->spi_dev, &msg); + spi_message_init(&msg); } - transfer->tx_buf = NULL; - transfer->rx_buf = &rx_data; - transfer->len = QCASPI_CMD_LEN; - ret = spi_sync(qca->spi_dev, msg); + spi_message_add_tail(&transfer[1], &msg); + ret = spi_sync(qca->spi_dev, &msg); if (!ret) - ret = msg->status; + ret = msg.status; if (ret) qcaspi_spi_error(qca); @@ -86,35 +85,32 @@ int qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value) { __be16 tx_data[2]; - struct spi_transfer *transfer; - struct spi_message *msg; + struct spi_transfer transfer[2]; + struct spi_message msg; int ret; + memset(&transfer, 0, sizeof(transfer)); + + spi_message_init(&msg); + tx_data[0] = cpu_to_be16(QCA7K_SPI_WRITE | QCA7K_SPI_INTERNAL | reg); tx_data[1] = cpu_to_be16(value); + transfer[0].tx_buf = &tx_data[0]; + transfer[0].len = QCASPI_CMD_LEN; + transfer[1].tx_buf = &tx_data[1]; + transfer[1].len = QCASPI_CMD_LEN; + + spi_message_add_tail(&transfer[0], &msg); if (qca->legacy_mode) { - msg = &qca->spi_msg1; - transfer = &qca->spi_xfer1; - transfer->tx_buf = &tx_data[0]; - transfer->rx_buf = NULL; - transfer->len = QCASPI_CMD_LEN; - spi_sync(qca->spi_dev, msg); - } else { - msg = &qca->spi_msg2; - transfer = &qca->spi_xfer2[0]; - transfer->tx_buf = &tx_data[0]; - transfer->rx_buf = NULL; - transfer->len = QCASPI_CMD_LEN; - transfer = &qca->spi_xfer2[1]; + spi_sync(qca->spi_dev, &msg); + spi_message_init(&msg); } - transfer->tx_buf = &tx_data[1]; - transfer->rx_buf = NULL; - transfer->len = QCASPI_CMD_LEN; - ret = spi_sync(qca->spi_dev, msg); + spi_message_add_tail(&transfer[1], &msg); + ret = spi_sync(qca->spi_dev, &msg); if (!ret) - ret = msg->status; + ret = msg.status; if (ret) qcaspi_spi_error(qca); diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 9c236298fe2125cf26afef756cfd5f3f7250098b..275fc6f154a71e52db57993d4e5e5c2d598abab9 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -99,22 +99,24 @@ static u32 qcaspi_write_burst(struct qcaspi *qca, u8 *src, u32 len) { __be16 cmd; - struct spi_message *msg = &qca->spi_msg2; - struct spi_transfer *transfer = &qca->spi_xfer2[0]; + struct spi_message msg; + struct spi_transfer transfer[2]; int ret; + memset(&transfer, 0, sizeof(transfer)); + spi_message_init(&msg); + cmd = cpu_to_be16(QCA7K_SPI_WRITE | QCA7K_SPI_EXTERNAL); - transfer->tx_buf = &cmd; - transfer->rx_buf = NULL; - transfer->len = QCASPI_CMD_LEN; - transfer = &qca->spi_xfer2[1]; - transfer->tx_buf = src; - transfer->rx_buf = NULL; - transfer->len = len; + transfer[0].tx_buf = &cmd; + transfer[0].len = QCASPI_CMD_LEN; + transfer[1].tx_buf = src; + transfer[1].len = len; - ret = spi_sync(qca->spi_dev, msg); + spi_message_add_tail(&transfer[0], &msg); + spi_message_add_tail(&transfer[1], &msg); + ret = spi_sync(qca->spi_dev, &msg); - if (ret || (msg->actual_length != QCASPI_CMD_LEN + len)) { + if (ret || (msg.actual_length != QCASPI_CMD_LEN + len)) { qcaspi_spi_error(qca); return 0; } @@ -125,17 +127,20 @@ qcaspi_write_burst(struct qcaspi *qca, u8 *src, u32 len) static u32 qcaspi_write_legacy(struct qcaspi *qca, u8 *src, u32 len) { - struct spi_message *msg = &qca->spi_msg1; - struct spi_transfer *transfer = &qca->spi_xfer1; + struct spi_message msg; + struct spi_transfer transfer; int ret; - transfer->tx_buf = src; - transfer->rx_buf = NULL; - transfer->len = len; + memset(&transfer, 0, sizeof(transfer)); + spi_message_init(&msg); + + transfer.tx_buf = src; + transfer.len = len; - ret = spi_sync(qca->spi_dev, msg); + spi_message_add_tail(&transfer, &msg); + ret = spi_sync(qca->spi_dev, &msg); - if (ret || (msg->actual_length != len)) { + if (ret || (msg.actual_length != len)) { qcaspi_spi_error(qca); return 0; } @@ -146,23 +151,25 @@ qcaspi_write_legacy(struct qcaspi *qca, u8 *src, u32 len) static u32 qcaspi_read_burst(struct qcaspi *qca, u8 *dst, u32 len) { - struct spi_message *msg = &qca->spi_msg2; + struct spi_message msg; __be16 cmd; - struct spi_transfer *transfer = &qca->spi_xfer2[0]; + struct spi_transfer transfer[2]; int ret; + memset(&transfer, 0, sizeof(transfer)); + spi_message_init(&msg); + cmd = cpu_to_be16(QCA7K_SPI_READ | QCA7K_SPI_EXTERNAL); - transfer->tx_buf = &cmd; - transfer->rx_buf = NULL; - transfer->len = QCASPI_CMD_LEN; - transfer = &qca->spi_xfer2[1]; - transfer->tx_buf = NULL; - transfer->rx_buf = dst; - transfer->len = len; + transfer[0].tx_buf = &cmd; + transfer[0].len = QCASPI_CMD_LEN; + transfer[1].rx_buf = dst; + transfer[1].len = len; - ret = spi_sync(qca->spi_dev, msg); + spi_message_add_tail(&transfer[0], &msg); + spi_message_add_tail(&transfer[1], &msg); + ret = spi_sync(qca->spi_dev, &msg); - if (ret || (msg->actual_length != QCASPI_CMD_LEN + len)) { + if (ret || (msg.actual_length != QCASPI_CMD_LEN + len)) { qcaspi_spi_error(qca); return 0; } @@ -173,17 +180,20 @@ qcaspi_read_burst(struct qcaspi *qca, u8 *dst, u32 len) static u32 qcaspi_read_legacy(struct qcaspi *qca, u8 *dst, u32 len) { - struct spi_message *msg = &qca->spi_msg1; - struct spi_transfer *transfer = &qca->spi_xfer1; + struct spi_message msg; + struct spi_transfer transfer; int ret; - transfer->tx_buf = NULL; - transfer->rx_buf = dst; - transfer->len = len; + memset(&transfer, 0, sizeof(transfer)); + spi_message_init(&msg); - ret = spi_sync(qca->spi_dev, msg); + transfer.rx_buf = dst; + transfer.len = len; - if (ret || (msg->actual_length != len)) { + spi_message_add_tail(&transfer, &msg); + ret = spi_sync(qca->spi_dev, &msg); + + if (ret || (msg.actual_length != len)) { qcaspi_spi_error(qca); return 0; } @@ -195,19 +205,23 @@ static int qcaspi_tx_cmd(struct qcaspi *qca, u16 cmd) { __be16 tx_data; - struct spi_message *msg = &qca->spi_msg1; - struct spi_transfer *transfer = &qca->spi_xfer1; + struct spi_message msg; + struct spi_transfer transfer; int ret; + memset(&transfer, 0, sizeof(transfer)); + + spi_message_init(&msg); + tx_data = cpu_to_be16(cmd); - transfer->len = sizeof(tx_data); - transfer->tx_buf = &tx_data; - transfer->rx_buf = NULL; + transfer.len = sizeof(cmd); + transfer.tx_buf = &tx_data; + spi_message_add_tail(&transfer, &msg); - ret = spi_sync(qca->spi_dev, msg); + ret = spi_sync(qca->spi_dev, &msg); if (!ret) - ret = msg->status; + ret = msg.status; if (ret) qcaspi_spi_error(qca); @@ -658,7 +672,7 @@ qcaspi_netdev_open(struct net_device *dev) return ret; } - netif_start_queue(qca->net_dev); + /* SPI thread takes care of TX queue */ return 0; } @@ -761,6 +775,9 @@ qcaspi_netdev_tx_timeout(struct net_device *dev) qca->net_dev->stats.tx_errors++; /* Trigger tx queue flush and QCA7000 reset */ qca->sync = QCASPI_SYNC_UNKNOWN; + + if (qca->spi_thread) + wake_up_process(qca->spi_thread); } static int @@ -833,16 +850,6 @@ qcaspi_netdev_setup(struct net_device *dev) qca = netdev_priv(dev); memset(qca, 0, sizeof(struct qcaspi)); - memset(&qca->spi_xfer1, 0, sizeof(struct spi_transfer)); - memset(&qca->spi_xfer2, 0, sizeof(struct spi_transfer) * 2); - - spi_message_init(&qca->spi_msg1); - spi_message_add_tail(&qca->spi_xfer1, &qca->spi_msg1); - - spi_message_init(&qca->spi_msg2); - spi_message_add_tail(&qca->spi_xfer2[0], &qca->spi_msg2); - spi_message_add_tail(&qca->spi_xfer2[1], &qca->spi_msg2); - memset(&qca->txr, 0, sizeof(qca->txr)); qca->txr.count = TX_RING_MAX_LEN; } @@ -879,22 +886,22 @@ qca_spi_probe(struct spi_device *spi) if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) || (qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) { - dev_info(&spi->dev, "Invalid clkspeed: %d\n", - qcaspi_clkspeed); + dev_err(&spi->dev, "Invalid clkspeed: %d\n", + qcaspi_clkspeed); return -EINVAL; } if ((qcaspi_burst_len < QCASPI_BURST_LEN_MIN) || (qcaspi_burst_len > QCASPI_BURST_LEN_MAX)) { - dev_info(&spi->dev, "Invalid burst len: %d\n", - qcaspi_burst_len); + dev_err(&spi->dev, "Invalid burst len: %d\n", + qcaspi_burst_len); return -EINVAL; } if ((qcaspi_pluggable < QCASPI_PLUGGABLE_MIN) || (qcaspi_pluggable > QCASPI_PLUGGABLE_MAX)) { - dev_info(&spi->dev, "Invalid pluggable: %d\n", - qcaspi_pluggable); + dev_err(&spi->dev, "Invalid pluggable: %d\n", + qcaspi_pluggable); return -EINVAL; } @@ -956,8 +963,8 @@ qca_spi_probe(struct spi_device *spi) } if (register_netdev(qcaspi_devs)) { - dev_info(&spi->dev, "Unable to register net device %s\n", - qcaspi_devs->name); + dev_err(&spi->dev, "Unable to register net device %s\n", + qcaspi_devs->name); free_netdev(qcaspi_devs); return -EFAULT; } diff --git a/drivers/net/ethernet/qualcomm/qca_spi.h b/drivers/net/ethernet/qualcomm/qca_spi.h index fc4beb1b32d1a070a101b3c48cc092bd14561150..fc0e98726b3613ddd3774169fa13aa6099a5c6e5 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.h +++ b/drivers/net/ethernet/qualcomm/qca_spi.h @@ -83,11 +83,6 @@ struct qcaspi { struct tx_ring txr; struct qcaspi_stats stats; - struct spi_message spi_msg1; - struct spi_message spi_msg2; - struct spi_transfer spi_xfer1; - struct spi_transfer spi_xfer2[2]; - u8 *rx_buffer; u32 buffer_size; u8 sync; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index b98fcc9e93e5ace2df1ea69f06136f074cd33b77..3669005b9294a15d177cd5ba0af9f3fae211e48a 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -329,6 +329,7 @@ static const struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, + { PCI_DEVICE(PCI_VENDOR_ID_NCUBE, 0x8168), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, { PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 }, diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index fdf30bfa403bf416572fa45ac3dde48f1e92cded..e87a779bfcfe5a38ba91ce13f4224e27ce19c022 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -959,6 +959,13 @@ static void ravb_adjust_link(struct net_device *ndev) struct ravb_private *priv = netdev_priv(ndev); struct phy_device *phydev = ndev->phydev; bool new_state = false; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + /* Disable TX and RX right over here, if E-MAC change is ignored */ + if (priv->no_avb_link) + ravb_rcv_snd_disable(ndev); if (phydev->link) { if (phydev->duplex != priv->duplex) { @@ -976,18 +983,21 @@ static void ravb_adjust_link(struct net_device *ndev) ravb_modify(ndev, ECMR, ECMR_TXF, 0); new_state = true; priv->link = phydev->link; - if (priv->no_avb_link) - ravb_rcv_snd_enable(ndev); } } else if (priv->link) { new_state = true; priv->link = 0; priv->speed = 0; priv->duplex = -1; - if (priv->no_avb_link) - ravb_rcv_snd_disable(ndev); } + /* Enable TX and RX right over here, if E-MAC change is ignored */ + if (priv->no_avb_link && phydev->link) + ravb_rcv_snd_enable(ndev); + + mmiowb(); + spin_unlock_irqrestore(&priv->lock, flags); + if (new_state && netif_msg_link(priv)) phy_print_status(phydev); } @@ -1094,52 +1104,18 @@ static int ravb_get_link_ksettings(struct net_device *ndev, static int ravb_set_link_ksettings(struct net_device *ndev, const struct ethtool_link_ksettings *cmd) { - struct ravb_private *priv = netdev_priv(ndev); - unsigned long flags; - int error; - if (!ndev->phydev) return -ENODEV; - spin_lock_irqsave(&priv->lock, flags); - - /* Disable TX and RX */ - ravb_rcv_snd_disable(ndev); - - error = phy_ethtool_ksettings_set(ndev->phydev, cmd); - if (error) - goto error_exit; - - if (cmd->base.duplex == DUPLEX_FULL) - priv->duplex = 1; - else - priv->duplex = 0; - - ravb_set_duplex(ndev); - -error_exit: - mdelay(1); - - /* Enable TX and RX */ - ravb_rcv_snd_enable(ndev); - - mmiowb(); - spin_unlock_irqrestore(&priv->lock, flags); - - return error; + return phy_ethtool_ksettings_set(ndev->phydev, cmd); } static int ravb_nway_reset(struct net_device *ndev) { - struct ravb_private *priv = netdev_priv(ndev); int error = -ENODEV; - unsigned long flags; - if (ndev->phydev) { - spin_lock_irqsave(&priv->lock, flags); + if (ndev->phydev) error = phy_start_aneg(ndev->phydev); - spin_unlock_irqrestore(&priv->lock, flags); - } return error; } diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 38080e95a82dccc6286a0cd40829be35ac9612ee..abfb9faadbc40b10a36dfba58d2801e603961bcb 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1821,8 +1821,15 @@ static void sh_eth_adjust_link(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); struct phy_device *phydev = ndev->phydev; + unsigned long flags; int new_state = 0; + spin_lock_irqsave(&mdp->lock, flags); + + /* Disable TX and RX right over here, if E-MAC change is ignored */ + if (mdp->cd->no_psr || mdp->no_ether_link) + sh_eth_rcv_snd_disable(ndev); + if (phydev->link) { if (phydev->duplex != mdp->duplex) { new_state = 1; @@ -1841,18 +1848,21 @@ static void sh_eth_adjust_link(struct net_device *ndev) sh_eth_modify(ndev, ECMR, ECMR_TXF, 0); new_state = 1; mdp->link = phydev->link; - if (mdp->cd->no_psr || mdp->no_ether_link) - sh_eth_rcv_snd_enable(ndev); } } else if (mdp->link) { new_state = 1; mdp->link = 0; mdp->speed = 0; mdp->duplex = -1; - if (mdp->cd->no_psr || mdp->no_ether_link) - sh_eth_rcv_snd_disable(ndev); } + /* Enable TX and RX right over here, if E-MAC change is ignored */ + if ((mdp->cd->no_psr || mdp->no_ether_link) && phydev->link) + sh_eth_rcv_snd_enable(ndev); + + mmiowb(); + spin_unlock_irqrestore(&mdp->lock, flags); + if (new_state && netif_msg_link(mdp)) phy_print_status(phydev); } @@ -1933,39 +1943,10 @@ static int sh_eth_get_link_ksettings(struct net_device *ndev, static int sh_eth_set_link_ksettings(struct net_device *ndev, const struct ethtool_link_ksettings *cmd) { - struct sh_eth_private *mdp = netdev_priv(ndev); - unsigned long flags; - int ret; - if (!ndev->phydev) return -ENODEV; - spin_lock_irqsave(&mdp->lock, flags); - - /* disable tx and rx */ - sh_eth_rcv_snd_disable(ndev); - - ret = phy_ethtool_ksettings_set(ndev->phydev, cmd); - if (ret) - goto error_exit; - - if (cmd->base.duplex == DUPLEX_FULL) - mdp->duplex = 1; - else - mdp->duplex = 0; - - if (mdp->cd->set_duplex) - mdp->cd->set_duplex(ndev); - -error_exit: - mdelay(1); - - /* enable tx and rx */ - sh_eth_rcv_snd_enable(ndev); - - spin_unlock_irqrestore(&mdp->lock, flags); - - return ret; + return phy_ethtool_ksettings_set(ndev->phydev, cmd); } /* If it is ever necessary to increase SH_ETH_REG_DUMP_MAX_REGS, the @@ -2156,18 +2137,10 @@ static void sh_eth_get_regs(struct net_device *ndev, struct ethtool_regs *regs, static int sh_eth_nway_reset(struct net_device *ndev) { - struct sh_eth_private *mdp = netdev_priv(ndev); - unsigned long flags; - int ret; - if (!ndev->phydev) return -ENODEV; - spin_lock_irqsave(&mdp->lock, flags); - ret = phy_start_aneg(ndev->phydev); - spin_unlock_irqrestore(&mdp->lock, flags); - - return ret; + return phy_start_aneg(ndev->phydev); } static u32 sh_eth_get_msglevel(struct net_device *ndev) diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 97035766c291b0a9df2734d1f97d88ac72d5f688..5790cd61436d0b2ca73eeb1d1eeab1b759083784 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -111,7 +111,7 @@ config DWMAC_ROCKCHIP config DWMAC_SOCFPGA tristate "SOCFPGA dwmac support" default ARCH_SOCFPGA - depends on OF && (ARCH_SOCFPGA || COMPILE_TEST) + depends on OF && (ARCH_SOCFPGA || ARCH_STRATIX10 || COMPILE_TEST) select MFD_SYSCON help Support for ethernet controller on Altera SOCFPGA diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 6e359572b9f0ea53ed46b553fb1cb51273415f57..5b3b06a0a3bf53e1eac9572ae8d14add0c3835e7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -55,6 +55,7 @@ struct socfpga_dwmac { struct device *dev; struct regmap *sys_mgr_base_addr; struct reset_control *stmmac_rst; + struct reset_control *stmmac_ocp_rst; void __iomem *splitter_base; bool f2h_ptp_ref_clk; struct tse_pcs pcs; @@ -262,8 +263,8 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac) val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; /* Assert reset to the enet controller before changing the phy mode */ - if (dwmac->stmmac_rst) - reset_control_assert(dwmac->stmmac_rst); + reset_control_assert(dwmac->stmmac_ocp_rst); + reset_control_assert(dwmac->stmmac_rst); regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); @@ -288,8 +289,8 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac) /* Deassert reset for the phy configuration to be sampled by * the enet controller, and operation to start in requested mode */ - if (dwmac->stmmac_rst) - reset_control_deassert(dwmac->stmmac_rst); + reset_control_deassert(dwmac->stmmac_ocp_rst); + reset_control_deassert(dwmac->stmmac_rst); if (phymode == PHY_INTERFACE_MODE_SGMII) { if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { dev_err(dwmac->dev, "Unable to initialize TSE PCS"); @@ -324,6 +325,15 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) goto err_remove_config_dt; } + dwmac->stmmac_ocp_rst = devm_reset_control_get_optional(dev, "stmmaceth-ocp"); + if (IS_ERR(dwmac->stmmac_ocp_rst)) { + ret = PTR_ERR(dwmac->stmmac_ocp_rst); + dev_err(dev, "error getting reset control of ocp %d\n", ret); + goto err_remove_config_dt; + } + + reset_control_deassert(dwmac->stmmac_ocp_rst); + ret = socfpga_dwmac_parse_data(dwmac, dev); if (ret) { dev_err(dev, "Unable to parse OF data\n"); diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 4bb561856af53c0165e1d052a7ebfa2bd279ce68..47a096134043c68037827789ced6f872eb1437d9 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1387,6 +1387,10 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) static int match_first_device(struct device *dev, void *data) { + if (dev->parent && dev->parent->of_node) + return of_device_is_compatible(dev->parent->of_node, + "ti,davinci_mdio"); + return !strncmp(dev_name(dev), "davinci_mdio", 12); } diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c index 16c3bfbe19928dfb56b2719490d0b401fae2ee5e..757a3b37ae8a8af8077001d548b65fe862d03c2d 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -218,6 +218,7 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) ret = of_mdiobus_register(bus, np1); if (ret) { mdiobus_free(bus); + lp->mii_bus = NULL; return ret; } return 0; diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 78a6414c5fd994445c7e530065bd6cfa7e5ad213..7d94a78425576c5337fe0445826f887430eb8ac3 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -89,10 +89,6 @@ static const char banner[] __initconst = KERN_INFO \ "AX.25: bpqether driver version 004\n"; -static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - -static char bpq_eth_addr[6]; - static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static int bpq_device_event(struct notifier_block *, unsigned long, void *); @@ -515,8 +511,8 @@ static int bpq_new_device(struct net_device *edev) bpq->ethdev = edev; bpq->axdev = ndev; - memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr)); - memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr)); + eth_broadcast_addr(bpq->dest_addr); + eth_broadcast_addr(bpq->acpt_addr); err = register_netdevice(ndev); if (err) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 6a77ef38c5495cc62b4c547c95f42a22051cdf2a..aba16d81e9bbac683b3b742be3c3edd88ffbffbe 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1895,11 +1896,15 @@ static int netvsc_register_vf(struct net_device *vf_netdev) { struct net_device *ndev; struct net_device_context *net_device_ctx; + struct device *pdev = vf_netdev->dev.parent; struct netvsc_device *netvsc_dev; if (vf_netdev->addr_len != ETH_ALEN) return NOTIFY_DONE; + if (!pdev || !dev_is_pci(pdev) || dev_is_pf(pdev)) + return NOTIFY_DONE; + /* * We will use the MAC address to locate the synthetic interface to * associate with the VF interface. If we don't find a matching @@ -2039,6 +2044,16 @@ static int netvsc_probe(struct hv_device *dev, memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); + /* We must get rtnl lock before scheduling nvdev->subchan_work, + * otherwise netvsc_subchan_work() can get rtnl lock first and wait + * all subchannels to show up, but that may not happen because + * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer() + * -> ... -> device_add() -> ... -> __device_attach() can't get + * the device lock, so all the subchannels can't be processed -- + * finally netvsc_subchan_work() hangs for ever. + */ + rtnl_lock(); + if (nvdev->num_chn > 1) schedule_work(&nvdev->subchan_work); @@ -2057,7 +2072,6 @@ static int netvsc_probe(struct hv_device *dev, else net->max_mtu = ETH_DATA_LEN; - rtnl_lock(); ret = register_netdevice(net); if (ret != 0) { pr_err("Unable to register netdev.\n"); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index cb03a6ea076a66c7ca856e912ed42a97741e05da..17025d46bdac8412e32b96fc86aaa28afc6d75f0 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -1299,6 +1299,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, /* setting up multiple channels failed */ net_device->max_chn = 1; net_device->num_chn = 1; + return net_device; err_dev_remv: rndis_filter_device_remove(dev, net_device); diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 548d9d026a85e2ff0e329f0f61454f555ab1a522..5c48bdb6f6787acbb74819ad7601ad302f644623 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -940,7 +940,7 @@ at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) static int at86rf230_ed(struct ieee802154_hw *hw, u8 *level) { - BUG_ON(!level); + WARN_ON(!level); *level = 0xbe; return 0; } @@ -1121,8 +1121,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw, if (changed & IEEE802154_AFILT_SADDR_CHANGED) { u16 addr = le16_to_cpu(filt->short_addr); - dev_vdbg(&lp->spi->dev, - "at86rf230_set_hw_addr_filt called for saddr\n"); + dev_vdbg(&lp->spi->dev, "%s called for saddr\n", __func__); __at86rf230_write(lp, RG_SHORT_ADDR_0, addr); __at86rf230_write(lp, RG_SHORT_ADDR_1, addr >> 8); } @@ -1130,8 +1129,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw, if (changed & IEEE802154_AFILT_PANID_CHANGED) { u16 pan = le16_to_cpu(filt->pan_id); - dev_vdbg(&lp->spi->dev, - "at86rf230_set_hw_addr_filt called for pan id\n"); + dev_vdbg(&lp->spi->dev, "%s called for pan id\n", __func__); __at86rf230_write(lp, RG_PAN_ID_0, pan); __at86rf230_write(lp, RG_PAN_ID_1, pan >> 8); } @@ -1140,15 +1138,13 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw, u8 i, addr[8]; memcpy(addr, &filt->ieee_addr, 8); - dev_vdbg(&lp->spi->dev, - "at86rf230_set_hw_addr_filt called for IEEE addr\n"); + dev_vdbg(&lp->spi->dev, "%s called for IEEE addr\n", __func__); for (i = 0; i < 8; i++) __at86rf230_write(lp, RG_IEEE_ADDR_0 + i, addr[i]); } if (changed & IEEE802154_AFILT_PANC_CHANGED) { - dev_vdbg(&lp->spi->dev, - "at86rf230_set_hw_addr_filt called for panc change\n"); + dev_vdbg(&lp->spi->dev, "%s called for panc change\n", __func__); if (filt->pan_coord) at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 1); else @@ -1252,7 +1248,6 @@ at86rf230_set_cca_mode(struct ieee802154_hw *hw, return at86rf230_write_subreg(lp, SR_CCA_MODE, val); } - static int at86rf230_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm) { diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c index 0d673f7682ee065223b64462bc2c4df0a03826a0..176395e4b7bb0ca628bdd22b4f13a23e425bfae2 100644 --- a/drivers/net/ieee802154/fakelb.c +++ b/drivers/net/ieee802154/fakelb.c @@ -49,7 +49,7 @@ struct fakelb_phy { static int fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level) { - BUG_ON(!level); + WARN_ON(!level); *level = 0xbe; return 0; diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index e7f7a1a002ee05bace0a05aab920eb3537a1d40b..58133c9f701b8cc65d0fcffa566511f691c5a5c3 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -73,10 +73,23 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval) { struct ipvl_dev *ipvlan; struct net_device *mdev = port->dev; - int err = 0; + unsigned int flags; + int err; ASSERT_RTNL(); if (port->mode != nval) { + list_for_each_entry(ipvlan, &port->ipvlans, pnode) { + flags = ipvlan->dev->flags; + if (nval == IPVLAN_MODE_L3 || nval == IPVLAN_MODE_L3S) { + err = dev_change_flags(ipvlan->dev, + flags | IFF_NOARP); + } else { + err = dev_change_flags(ipvlan->dev, + flags & ~IFF_NOARP); + } + if (unlikely(err)) + goto fail; + } if (nval == IPVLAN_MODE_L3S) { /* New mode is L3S */ err = ipvlan_register_nf_hook(read_pnet(&port->pnet)); @@ -84,21 +97,28 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval) mdev->l3mdev_ops = &ipvl_l3mdev_ops; mdev->priv_flags |= IFF_L3MDEV_MASTER; } else - return err; + goto fail; } else if (port->mode == IPVLAN_MODE_L3S) { /* Old mode was L3S */ mdev->priv_flags &= ~IFF_L3MDEV_MASTER; ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); mdev->l3mdev_ops = NULL; } - list_for_each_entry(ipvlan, &port->ipvlans, pnode) { - if (nval == IPVLAN_MODE_L3 || nval == IPVLAN_MODE_L3S) - ipvlan->dev->flags |= IFF_NOARP; - else - ipvlan->dev->flags &= ~IFF_NOARP; - } port->mode = nval; } + return 0; + +fail: + /* Undo the flags changes that have been done so far. */ + list_for_each_entry_continue_reverse(ipvlan, &port->ipvlans, pnode) { + flags = ipvlan->dev->flags; + if (port->mode == IPVLAN_MODE_L3 || + port->mode == IPVLAN_MODE_L3S) + dev_change_flags(ipvlan->dev, flags | IFF_NOARP); + else + dev_change_flags(ipvlan->dev, flags & ~IFF_NOARP); + } + return err; } diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index 0c5b68e7da51aa8d0c7c73e7c6b3cc632b1e3510..9b31670548433276a431458b69e515aa62debe7f 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -22,7 +22,7 @@ #include #include -#define MDIO_PARAM_OFFSET 0x00 +#define MDIO_PARAM_OFFSET 0x23c #define MDIO_PARAM_MIIM_CYCLE 29 #define MDIO_PARAM_INTERNAL_SEL 25 #define MDIO_PARAM_BUS_ID 22 @@ -30,20 +30,22 @@ #define MDIO_PARAM_PHY_ID 16 #define MDIO_PARAM_PHY_DATA 0 -#define MDIO_READ_OFFSET 0x04 +#define MDIO_READ_OFFSET 0x240 #define MDIO_READ_DATA_MASK 0xffff -#define MDIO_ADDR_OFFSET 0x08 +#define MDIO_ADDR_OFFSET 0x244 -#define MDIO_CTRL_OFFSET 0x0C +#define MDIO_CTRL_OFFSET 0x248 #define MDIO_CTRL_WRITE_OP 0x1 #define MDIO_CTRL_READ_OP 0x2 -#define MDIO_STAT_OFFSET 0x10 +#define MDIO_STAT_OFFSET 0x24c #define MDIO_STAT_DONE 1 #define BUS_MAX_ADDR 32 #define EXT_BUS_START_ADDR 16 +#define MDIO_REG_ADDR_SPACE_SIZE 0x250 + struct iproc_mdiomux_desc { void *mux_handle; void __iomem *base; @@ -169,6 +171,14 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) md->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res->start & 0xfff) { + /* For backward compatibility in case the + * base address is specified with an offset. + */ + dev_info(&pdev->dev, "fix base address in dt-blob\n"); + res->start &= ~0xfff; + res->end = res->start + MDIO_REG_ADDR_SPACE_SIZE - 1; + } md->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(md->base)) { dev_err(&pdev->dev, "failed to ioremap register\n"); diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c index 2e5150b0b8d52c5dd784a3df1818962d64972898..7a14e8170e8263fe84f362f4e04e313e2f3d312b 100644 --- a/drivers/net/phy/xilinx_gmii2rgmii.c +++ b/drivers/net/phy/xilinx_gmii2rgmii.c @@ -40,8 +40,11 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev) { struct gmii2rgmii *priv = phydev->priv; u16 val = 0; + int err; - priv->phy_drv->read_status(phydev); + err = priv->phy_drv->read_status(phydev); + if (err < 0) + return err; val = mdiobus_read(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG); val &= ~XILINX_GMII2RGMII_SPEED_MASK; @@ -81,6 +84,11 @@ static int xgmiitorgmii_probe(struct mdio_device *mdiodev) return -EPROBE_DEFER; } + if (!priv->phy_dev->drv) { + dev_info(dev, "Attached phy not ready\n"); + return -EPROBE_DEFER; + } + priv->addr = mdiodev->addr; priv->phy_drv = priv->phy_dev->drv; memcpy(&priv->conv_phy_drv, priv->phy_dev->drv, diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 71e2aef6b7a1b5cdb052fed4aeec2a843a1a9a4d..951892da3352e3b5f303d3f8c8659cc6031323cc 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -429,6 +429,9 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev, if (!skb) goto out; + if (skb_mac_header_len(skb) < ETH_HLEN) + goto drop; + if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) goto drop; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index e34ea5a2a69246a2566647ab0421334ff1a3b616..f34f26d2a97a56ecd5afe72d323433c0520a412c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -534,14 +534,6 @@ static void tun_queue_purge(struct tun_file *tfile) skb_queue_purge(&tfile->sk.sk_error_queue); } -static void tun_cleanup_tx_array(struct tun_file *tfile) -{ - if (tfile->tx_array.ring.queue) { - skb_array_cleanup(&tfile->tx_array); - memset(&tfile->tx_array, 0, sizeof(tfile->tx_array)); - } -} - static void __tun_detach(struct tun_file *tfile, bool clean) { struct tun_file *ntfile; @@ -583,7 +575,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean) tun->dev->reg_state == NETREG_REGISTERED) unregister_netdevice(tun->dev); } - tun_cleanup_tx_array(tfile); + skb_array_cleanup(&tfile->tx_array); sock_put(&tfile->sk); } } @@ -623,13 +615,11 @@ static void tun_detach_all(struct net_device *dev) /* Drop read queue */ tun_queue_purge(tfile); sock_put(&tfile->sk); - tun_cleanup_tx_array(tfile); } list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { tun_enable_queue(tfile); tun_queue_purge(tfile); sock_put(&tfile->sk); - tun_cleanup_tx_array(tfile); } BUG_ON(tun->numdisabled != 0); @@ -675,7 +665,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte } if (!tfile->detached && - skb_array_init(&tfile->tx_array, dev->tx_queue_len, GFP_KERNEL)) { + skb_array_resize(&tfile->tx_array, dev->tx_queue_len, GFP_KERNEL)) { err = -ENOMEM; goto out; } @@ -2634,6 +2624,11 @@ static int tun_chr_open(struct inode *inode, struct file * file) &tun_proto, 0); if (!tfile) return -ENOMEM; + if (skb_array_init(&tfile->tx_array, 0, GFP_KERNEL)) { + sk_free(&tfile->sk); + return -ENOMEM; + } + RCU_INIT_POINTER(tfile->tun, NULL); tfile->flags = 0; tfile->ifindex = 0; @@ -2654,8 +2649,6 @@ static int tun_chr_open(struct inode *inode, struct file * file) sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); - memset(&tfile->tx_array, 0, sizeof(tfile->tx_array)); - return 0; } diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6d3811c869fdddeadd3110f320b2ee5cb2c18f96..c5d4b35bb72aef97ef263843f8b6eb42cbc7acc4 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1205,13 +1205,13 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */ {QMI_FIXED_INTF(0x1199, 0x9063, 8)}, /* Sierra Wireless EM7305 */ {QMI_FIXED_INTF(0x1199, 0x9063, 10)}, /* Sierra Wireless EM7305 */ - {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx */ - {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */ - {QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x9079, 10)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x907b, 8)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x907b, 10)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x9091, 8)}, /* Sierra Wireless EM7565 */ + {QMI_QUIRK_SET_DTR(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx */ + {QMI_QUIRK_SET_DTR(0x1199, 0x9071, 10)},/* Sierra Wireless MC74xx */ + {QMI_QUIRK_SET_DTR(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ + {QMI_QUIRK_SET_DTR(0x1199, 0x9079, 10)},/* Sierra Wireless EM74xx */ + {QMI_QUIRK_SET_DTR(0x1199, 0x907b, 8)}, /* Sierra Wireless EM74xx */ + {QMI_QUIRK_SET_DTR(0x1199, 0x907b, 10)},/* Sierra Wireless EM74xx */ + {QMI_QUIRK_SET_DTR(0x1199, 0x9091, 8)}, /* Sierra Wireless EM7565 */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ @@ -1245,7 +1245,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x413c, 0x81b3, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ {QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */ {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ - {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e */ + {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ {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 */ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 5f565bd574da3bc7ce741e3b280a9ff5dece4352..48ba80a8ca5ce8e566931979edcff4bcfe47bc2e 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -681,7 +681,7 @@ static void rtl8150_set_multicast(struct net_device *netdev) (netdev->flags & IFF_ALLMULTI)) { rx_creg &= 0xfffe; rx_creg |= 0x0002; - dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name); + dev_dbg(&netdev->dev, "%s: allmulti set\n", netdev->name); } else { /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ rx_creg &= 0x00fc; diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 7a6a1fe793090b8e28f5ef075f5ebc2ad385b5eb..05553d2524469f97e4a02bb48f43f6820ad2b3e5 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -82,6 +82,9 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); +static int smsc75xx_link_ok_nopm(struct usbnet *dev); +static int smsc75xx_phy_gig_workaround(struct usbnet *dev); + static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { @@ -852,6 +855,9 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) return -EIO; } + /* phy workaround for gig link */ + smsc75xx_phy_gig_workaround(dev); + smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); @@ -987,6 +993,62 @@ static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm) return -EIO; } +static int smsc75xx_phy_gig_workaround(struct usbnet *dev) +{ + struct mii_if_info *mii = &dev->mii; + int ret = 0, timeout = 0; + u32 buf, link_up = 0; + + /* Set the phy in Gig loopback */ + smsc75xx_mdio_write(dev->net, mii->phy_id, MII_BMCR, 0x4040); + + /* Wait for the link up */ + do { + link_up = smsc75xx_link_ok_nopm(dev); + usleep_range(10000, 20000); + timeout++; + } while ((!link_up) && (timeout < 1000)); + + if (timeout >= 1000) { + netdev_warn(dev->net, "Timeout waiting for PHY link up\n"); + return -EIO; + } + + /* phy reset */ + ret = smsc75xx_read_reg(dev, PMT_CTL, &buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret); + return ret; + } + + buf |= PMT_CTL_PHY_RST; + + ret = smsc75xx_write_reg(dev, PMT_CTL, buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write PMT_CTL: %d\n", ret); + return ret; + } + + timeout = 0; + do { + usleep_range(10000, 20000); + ret = smsc75xx_read_reg(dev, PMT_CTL, &buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", + ret); + return ret; + } + timeout++; + } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100)); + + if (timeout >= 100) { + netdev_warn(dev->net, "timeout waiting for PHY Reset\n"); + return -EIO; + } + + return 0; +} + static int smsc75xx_reset(struct usbnet *dev) { struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 33df76405b869a8504415fc8529222616bac9586..18b648648adb2e5676fadf3fc66721e7f84ac972 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -192,7 +192,7 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) priv->ucc_pram_offset = qe_muram_alloc(sizeof(struct ucc_hdlc_param), ALIGNMENT_OF_UCC_HDLC_PRAM); - if (priv->ucc_pram_offset < 0) { + if (IS_ERR_VALUE(priv->ucc_pram_offset)) { dev_err(priv->dev, "Can not allocate MURAM for hdlc parameter.\n"); ret = -ENOMEM; goto free_tx_bd; @@ -228,14 +228,14 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) /* Alloc riptr, tiptr */ riptr = qe_muram_alloc(32, 32); - if (riptr < 0) { + if (IS_ERR_VALUE(riptr)) { dev_err(priv->dev, "Cannot allocate MURAM mem for Receive internal temp data pointer\n"); ret = -ENOMEM; goto free_tx_skbuff; } tiptr = qe_muram_alloc(32, 32); - if (tiptr < 0) { + if (IS_ERR_VALUE(tiptr)) { dev_err(priv->dev, "Cannot allocate MURAM mem for Transmit internal temp data pointer\n"); ret = -ENOMEM; goto free_riptr; diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 4698450c77d1ef8cac62c163e3e8f8c06b99dc13..bb43d176eb4e38ec875e37ac2f4985159bcdab04 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1371,7 +1371,7 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ case 0x001: printk(KERN_WARNING "%s: Master Abort (naughty)\n", dev->name); break; - case 0x010: + case 0x002: printk(KERN_WARNING "%s: Target Abort (not so naughty)\n", dev->name); break; default: diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 0aeeb233af780469fcc907ba5ee0bb53086d606a..21642bab485a12d0a6cda34161b9e2821d456b5d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -215,11 +215,12 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar) spin_lock_bh(&htt->rx_ring.lock); ret = ath10k_htt_rx_ring_fill_n(htt, (htt->rx_ring.fill_level - htt->rx_ring.fill_cnt)); - spin_unlock_bh(&htt->rx_ring.lock); if (ret) ath10k_htt_rx_ring_free(htt); + spin_unlock_bh(&htt->rx_ring.lock); + return ret; } @@ -231,7 +232,9 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) skb_queue_purge(&htt->rx_in_ord_compl_q); skb_queue_purge(&htt->tx_fetch_ind_q); + spin_lock_bh(&htt->rx_ring.lock); ath10k_htt_rx_ring_free(htt); + spin_unlock_bh(&htt->rx_ring.lock); dma_free_coherent(htt->ar->dev, (htt->rx_ring.size * diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index df11bb44998888c52632c72b856f06444be7a85b..cdcfb175ad9b8cf300af30a70bdaf3c234740b72 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3074,6 +3074,13 @@ static int ath10k_update_channel_list(struct ath10k *ar) passive = channel->flags & IEEE80211_CHAN_NO_IR; ch->passive = passive; + /* the firmware is ignoring the "radar" flag of the + * channel and is scanning actively using Probe Requests + * on "Radar detection"/DFS channels which are not + * marked as "available" + */ + ch->passive |= ch->chan_radar; + ch->freq = channel->center_freq; ch->band_center_freq1 = channel->center_freq; ch->min_power = 0; @@ -4008,6 +4015,7 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar) rcu_read_unlock(); spin_unlock_bh(&ar->txqs_lock); } +EXPORT_SYMBOL(ath10k_mac_tx_push_pending); /************/ /* Scanning */ @@ -5923,8 +5931,19 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) ath10k_mac_max_vht_nss(vht_mcs_mask))); if (changed & IEEE80211_RC_BW_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM peer bw %d\n", - sta->addr, bw); + enum wmi_phy_mode mode; + + mode = chan_to_phymode(&def); + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", + sta->addr, bw, mode); + + err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, + WMI_PEER_PHYMODE, mode); + if (err) { + ath10k_warn(ar, "failed to update STA %pM peer phymode %d: %d\n", + sta->addr, mode, err); + goto exit; + } err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, WMI_PEER_CHAN_WIDTH, bw); @@ -5965,6 +5984,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) sta->addr); } +exit: mutex_unlock(&ar->conf_mutex); } diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 03a69e5b11165753717517f098480306af881f26..da9dbf3ddaa5e5ec2c5c072641bc8d5cb963f7f4 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -30,6 +30,7 @@ #include "debug.h" #include "hif.h" #include "htc.h" +#include "mac.h" #include "targaddrs.h" #include "trace.h" #include "sdio.h" @@ -396,6 +397,7 @@ static int ath10k_sdio_mbox_rx_process_packet(struct ath10k *ar, int ret; payload_len = le16_to_cpu(htc_hdr->len); + skb->len = payload_len + sizeof(struct ath10k_htc_hdr); if (trailer_present) { trailer = skb->data + sizeof(*htc_hdr) + @@ -434,12 +436,14 @@ static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar, enum ath10k_htc_ep_id id; int ret, i, *n_lookahead_local; u32 *lookaheads_local; + int lookahead_idx = 0; for (i = 0; i < ar_sdio->n_rx_pkts; i++) { lookaheads_local = lookaheads; n_lookahead_local = n_lookahead; - id = ((struct ath10k_htc_hdr *)&lookaheads[i])->eid; + id = ((struct ath10k_htc_hdr *) + &lookaheads[lookahead_idx++])->eid; if (id >= ATH10K_HTC_EP_COUNT) { ath10k_warn(ar, "invalid endpoint in look-ahead: %d\n", @@ -462,6 +466,7 @@ static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar, /* Only read lookahead's from RX trailers * for the last packet in a bundle. */ + lookahead_idx--; lookaheads_local = NULL; n_lookahead_local = NULL; } @@ -1342,6 +1347,8 @@ static void ath10k_sdio_irq_handler(struct sdio_func *func) break; } while (time_before(jiffies, timeout) && !done); + ath10k_mac_tx_push_pending(ar); + sdio_claim_host(ar_sdio->func); if (ret && ret != -ECANCELED) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 7616c1c4bbd32a5f4cdf343fe8ece9a90bf2db22..baec856af90ffccd7bf9f21a6e3bae2aaffba552 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1451,6 +1451,11 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) cfg->keep_alive_pattern_size = __cpu_to_le32(0); cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1); cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1); + cfg->wmi_send_separate = __cpu_to_le32(0); + cfg->num_ocb_vdevs = __cpu_to_le32(0); + cfg->num_ocb_channels = __cpu_to_le32(0); + cfg->num_ocb_schedules = __cpu_to_le32(0); + cfg->host_capab = __cpu_to_le32(0); ath10k_wmi_put_host_mem_chunks(ar, chunks); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 22cf011e839afc190c55c65a387351787369e37d..e75bba0bbf6746ed50f76b4c4096275d402495cc 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1228,6 +1228,11 @@ struct wmi_tlv_resource_config { __le32 keep_alive_pattern_size; __le32 max_tdls_concurrent_sleep_sta; __le32 max_tdls_concurrent_buffer_sta; + __le32 wmi_send_separate; + __le32 num_ocb_vdevs; + __le32 num_ocb_channels; + __le32 num_ocb_schedules; + __le32 host_capab; } __packed; struct wmi_tlv_init_cmd { diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index bab876cf25fee02279a4a636b2d9aa430c2efab1..d0e05aa437e36549515016d72a35f2cf2dd14629 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -6002,6 +6002,7 @@ enum wmi_peer_param { WMI_PEER_NSS = 0x5, WMI_PEER_USE_4ADDR = 0x6, WMI_PEER_DEBUG = 0xa, + WMI_PEER_PHYMODE = 0xd, WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */ }; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8c5c2dd8fa7f13c4d12ebb98fa354deff212e124..a7f506eb7b366475eac78e0393504b29991063ad 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2915,16 +2915,19 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan, struct ath_regulatory *reg = ath9k_hw_regulatory(ah); struct ieee80211_channel *channel; int chan_pwr, new_pwr; + u16 ctl = NO_CTL; if (!chan) return; + if (!test) + ctl = ath9k_regd_get_ctl(reg, chan); + channel = chan->chan; chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER); new_pwr = min_t(int, chan_pwr, reg->power_limit); - ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(reg, chan), + ah->eep_ops->set_txpower(ah, chan, ctl, get_antenna_gain(ah, chan), new_pwr, test); } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index d8b041f48ca8e17ccb59fe4b099c9814d8e76a7c..fa64c1cc94aedb9ca80d1fbf1e9f78230e530ed7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -86,7 +86,8 @@ static void ath_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = info->status.status_driver_data[0]; - if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { + if (info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS | + IEEE80211_TX_STATUS_EOSP)) { ieee80211_tx_status(hw, skb); return; } diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 852ee04aab8e8e2021098febe5808782695ddf92..84455e9f76733b5042fdc206be3049f3b1893e2f 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -961,6 +961,8 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, int rc; void *frame; + memset(¶ms, 0, sizeof(params)); + if (!len) return -EINVAL; diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 5d287a8e1b458a8aca674275a55c007df944e4c3..a58fccb39bd09a631284e01a252b4b1ebe7e1187 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -575,10 +575,14 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) } if (isr & BIT_DMA_EP_MISC_ICR_HALP) { - wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); - wil6210_mask_halp(wil); isr &= ~BIT_DMA_EP_MISC_ICR_HALP; - complete(&wil->halp.comp); + if (atomic_read(&wil->halp.handle_icr)) { + /* no need to handle HALP ICRs until next vote */ + atomic_set(&wil->halp.handle_icr, 0); + wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); + wil6210_mask_halp(wil); + complete(&wil->halp.comp); + } } wil->isr_misc = isr; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index e77366fd8d78061dab8091d3e4f554fedc87b659..070619c5376117f004097e81036b0c263474692f 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1423,8 +1423,15 @@ static void wil_pre_fw_config(struct wil6210_priv *wil) wil6210_clear_irq(wil); /* CAF_ICR - clear and mask */ /* it is W1C, clear by writing back same value */ - wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0); - wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0); + if (wil->hw_version < HW_VER_TALYN_MB) { + wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0); + wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0); + } else { + wil_s(wil, + RGF_CAF_ICR_TALYN_MB + offsetof(struct RGF_ICR, ICR), 0); + wil_w(wil, RGF_CAF_ICR_TALYN_MB + + offsetof(struct RGF_ICR, IMV), ~0); + } /* clear PAL_UNIT_ICR (potential D0->D3 leftover) * In Talyn-MB host cannot access this register due to * access control, hence PAL_UNIT_ICR is cleared by the FW @@ -1851,6 +1858,8 @@ void wil_halp_vote(struct wil6210_priv *wil) if (++wil->halp.ref_cnt == 1) { reinit_completion(&wil->halp.comp); + /* mark to IRQ context to handle HALP ICR */ + atomic_set(&wil->halp.handle_icr, 1); wil6210_set_halp(wil); rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); if (!rc) { diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 59d0bc752fd07fc53ec6a0388de3318a90860432..16577b2188c5203e2addf6183021612527bad409 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -835,23 +835,24 @@ static int wil_rx_error_check_edma(struct wil6210_priv *wil, wil_dbg_txrx(wil, "L2 RX error, l2_rx_status=0x%x\n", l2_rx_status); /* Due to HW issue, KEY error will trigger a MIC error */ - if (l2_rx_status & WIL_RX_EDMA_ERROR_MIC) { - wil_dbg_txrx(wil, - "L2 MIC/KEY error, dropping packet\n"); + if (l2_rx_status == WIL_RX_EDMA_ERROR_MIC) { + wil_err_ratelimited(wil, + "L2 MIC/KEY error, dropping packet\n"); stats->rx_mic_error++; } - if (l2_rx_status & WIL_RX_EDMA_ERROR_KEY) { - wil_dbg_txrx(wil, "L2 KEY error, dropping packet\n"); + if (l2_rx_status == WIL_RX_EDMA_ERROR_KEY) { + wil_err_ratelimited(wil, + "L2 KEY error, dropping packet\n"); stats->rx_key_error++; } - if (l2_rx_status & WIL_RX_EDMA_ERROR_REPLAY) { - wil_dbg_txrx(wil, - "L2 REPLAY error, dropping packet\n"); + if (l2_rx_status == WIL_RX_EDMA_ERROR_REPLAY) { + wil_err_ratelimited(wil, + "L2 REPLAY error, dropping packet\n"); stats->rx_replay++; } - if (l2_rx_status & WIL_RX_EDMA_ERROR_AMSDU) { - wil_dbg_txrx(wil, - "L2 AMSDU error, dropping packet\n"); + if (l2_rx_status == WIL_RX_EDMA_ERROR_AMSDU) { + wil_err_ratelimited(wil, + "L2 AMSDU error, dropping packet\n"); stats->rx_amsdu_error++; } return -EFAULT; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index efa8a46a55602733b1b68346cd099ad004505c67..0a512fd60711c6e2f62b99e44d096c6c482b2722 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -324,6 +324,7 @@ struct RGF_ICR { /* MAC timer, usec, for packet lifetime */ #define RGF_MAC_MTRL_COUNTER_0 (0x886aa8) +#define RGF_CAF_ICR_TALYN_MB (0x8893d4) /* struct RGF_ICR */ #define RGF_CAF_ICR (0x88946c) /* struct RGF_ICR */ #define RGF_CAF_OSC_CONTROL (0x88afa4) #define BIT_CAF_OSC_XTAL_EN BIT(0) @@ -794,6 +795,7 @@ struct wil_halp { struct mutex lock; /* protect halp ref_cnt */ unsigned int ref_cnt; struct completion comp; + atomic_t handle_icr; }; struct wil_blob_wrapper { diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index f2c93c2a0645567daa2cd18d73271c7604a4cc8c..41b2e9fb3ad73d2e5727e1001a6d7b08d14537a9 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -3342,7 +3342,7 @@ static void wmi_event_handle(struct wil6210_priv *wil, if (mid == MID_BROADCAST) mid = 0; - if (mid >= wil->max_vifs) { + if (mid >= ARRAY_SIZE(wil->vifs) || mid >= wil->max_vifs) { wil_dbg_wmi(wil, "invalid mid %d, event skipped\n", mid); return; diff --git a/drivers/net/wireless/broadcom/b43/leds.c b/drivers/net/wireless/broadcom/b43/leds.c index cb987c2ecc6bf5295684c11da9604c03ef4d2e32..87131f6632929963506d0258d1bc20c97c09e5b8 100644 --- a/drivers/net/wireless/broadcom/b43/leds.c +++ b/drivers/net/wireless/broadcom/b43/leds.c @@ -131,7 +131,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, led->wl = dev->wl; led->index = led_index; led->activelow = activelow; - strncpy(led->name, name, sizeof(led->name)); + strlcpy(led->name, name, sizeof(led->name)); atomic_set(&led->state, 0); led->led_dev.name = led->name; diff --git a/drivers/net/wireless/broadcom/b43legacy/leds.c b/drivers/net/wireless/broadcom/b43legacy/leds.c index fd4565389c77df59056d239e2bc778164a622496..bc922118b6ac641aa1caa800489f77472542fe60 100644 --- a/drivers/net/wireless/broadcom/b43legacy/leds.c +++ b/drivers/net/wireless/broadcom/b43legacy/leds.c @@ -101,7 +101,7 @@ static int b43legacy_register_led(struct b43legacy_wldev *dev, led->dev = dev; led->index = led_index; led->activelow = activelow; - strncpy(led->name, name, sizeof(led->name)); + strlcpy(led->name, name, sizeof(led->name)); led->led_dev.name = led->name; led->led_dev.default_trigger = default_trigger; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index eccd25febfe6035a89df9e342476b43746afe287..4c28b04ea60536dce86508a9bac3168c51015ab2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -4245,6 +4245,13 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) brcmf_dbg(TRACE, "Enter\n"); if (bus) { + /* Stop watchdog task */ + if (bus->watchdog_tsk) { + send_sig(SIGTERM, bus->watchdog_tsk, 1); + kthread_stop(bus->watchdog_tsk); + bus->watchdog_tsk = NULL; + } + /* De-register interrupt handler */ brcmf_sdiod_intr_unregister(bus->sdiodev); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c index b9672da24a9d3d8f7b58cbe19cc282281cd271ef..b24bc57ca91b8a61bcbf0e26c12e3c3805e820d4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c @@ -213,7 +213,7 @@ static const s16 log_table[] = { 30498, 31267, 32024, - 32768 + 32767 }; #define LOG_TABLE_SIZE 32 /* log_table size */ diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c index 53a46202500fc16c7302130024c9333e4132c217..30e37a08d2911307d08cafb05920414f1e0db1f0 100644 --- a/drivers/net/wireless/cnss2/debug.c +++ b/drivers/net/wireless/cnss2/debug.c @@ -428,6 +428,82 @@ static const struct file_operations cnss_reg_write_debug_fops = { .llseek = seq_lseek, }; +static ssize_t cnss_runtime_pm_debug_write(struct file *fp, + const char __user *user_buf, + size_t count, loff_t *off) +{ + struct cnss_plat_data *plat_priv = + ((struct seq_file *)fp->private_data)->private; + struct cnss_pci_data *pci_priv; + char buf[64]; + char *cmd; + unsigned int len = 0; + int ret = 0; + + if (!plat_priv) + return -ENODEV; + + pci_priv = plat_priv->bus_priv; + if (!pci_priv) + return -ENODEV; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + cmd = buf; + + if (sysfs_streq(cmd, "usage_count")) { + cnss_pci_pm_runtime_show_usage_count(pci_priv); + } else if (sysfs_streq(cmd, "get")) { + ret = cnss_pci_pm_runtime_get(pci_priv); + } else if (sysfs_streq(cmd, "get_noresume")) { + cnss_pci_pm_runtime_get_noresume(pci_priv); + } else if (sysfs_streq(cmd, "put_autosuspend")) { + ret = cnss_pci_pm_runtime_put_autosuspend(pci_priv); + } else if (sysfs_streq(cmd, "put_noidle")) { + cnss_pci_pm_runtime_put_noidle(pci_priv); + } else if (sysfs_streq(cmd, "mark_last_busy")) { + cnss_pci_pm_runtime_mark_last_busy(pci_priv); + } else { + cnss_pr_err("Runtime PM debugfs command is invalid\n"); + ret = -EINVAL; + } + + if (ret) + return ret; + + return count; +} + +static int cnss_runtime_pm_debug_show(struct seq_file *s, void *data) +{ + seq_puts(s, "\nUsage: echo > /cnss/runtime_pm\n"); + seq_puts(s, " can be one of below:\n"); + seq_puts(s, "usage_count: get runtime PM usage count\n"); + seq_puts(s, "get: do runtime PM get\n"); + seq_puts(s, "get_noresume: do runtime PM get noresume\n"); + seq_puts(s, "put_noidle: do runtime PM put noidle\n"); + seq_puts(s, "put_autosuspend: do runtime PM put autosuspend\n"); + seq_puts(s, "mark_last_busy: do runtime PM mark last busy\n"); + + return 0; +} + +static int cnss_runtime_pm_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, cnss_runtime_pm_debug_show, inode->i_private); +} + +static const struct file_operations cnss_runtime_pm_debug_fops = { + .read = seq_read, + .write = cnss_runtime_pm_debug_write, + .open = cnss_runtime_pm_debug_open, + .owner = THIS_MODULE, + .llseek = seq_lseek, +}; + #ifdef CONFIG_CNSS2_DEBUG static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) { @@ -439,6 +515,8 @@ static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) &cnss_reg_read_debug_fops); debugfs_create_file("reg_write", 0600, root_dentry, plat_priv, &cnss_reg_write_debug_fops); + debugfs_create_file("runtime_pm", 0600, root_dentry, plat_priv, + &cnss_runtime_pm_debug_fops); return 0; } diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 44c48c503f06d5877565f77e1d120baf0498a3a2..8300d9752d58323bff9d46688a1abc73014159ea 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -426,6 +426,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) del_timer(&plat_priv->fw_boot_timer); set_bit(CNSS_FW_READY, &plat_priv->driver_state); + clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state); if (test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state)) { clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state); @@ -901,7 +902,6 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv, break; case CNSS_REASON_RDDM: cnss_bus_collect_dump_info(plat_priv, false); - clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state); break; case CNSS_REASON_DEFAULT: case CNSS_REASON_TIMEOUT: @@ -1039,19 +1039,34 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; + if (test_bit(CNSS_FW_READY, &plat_priv->driver_state) || + test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) || + test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) { + cnss_pr_dbg("Device is already active, ignore calibration\n"); + goto out; + } + set_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state); + reinit_completion(&plat_priv->cal_complete); ret = cnss_bus_dev_powerup(plat_priv); - if (ret) + if (ret) { + complete(&plat_priv->cal_complete); clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state); + } +out: return ret; } static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv) { + if (!test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) + return 0; + plat_priv->cal_done = true; cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF); cnss_bus_dev_shutdown(plat_priv); + complete(&plat_priv->cal_complete); clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state); return 0; @@ -1533,6 +1548,36 @@ static void cnss_event_work_deinit(struct cnss_plat_data *plat_priv) destroy_workqueue(plat_priv->event_wq); } +static int cnss_misc_init(struct cnss_plat_data *plat_priv) +{ + int ret; + + setup_timer(&plat_priv->fw_boot_timer, cnss_bus_fw_boot_timeout_hdlr, + (unsigned long)plat_priv); + + register_pm_notifier(&cnss_pm_notifier); + + ret = device_init_wakeup(&plat_priv->plat_dev->dev, true); + if (ret) + cnss_pr_err("Failed to init platform device wakeup source, err = %d\n", + ret); + + init_completion(&plat_priv->power_up_complete); + init_completion(&plat_priv->cal_complete); + mutex_init(&plat_priv->dev_lock); + + return 0; +} + +static void cnss_misc_deinit(struct cnss_plat_data *plat_priv) +{ + complete_all(&plat_priv->cal_complete); + complete_all(&plat_priv->power_up_complete); + device_init_wakeup(&plat_priv->plat_dev->dev, false); + unregister_pm_notifier(&cnss_pm_notifier); + del_timer(&plat_priv->fw_boot_timer); +} + static const struct platform_device_id cnss_platform_id_table[] = { { .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, }, { .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, }, @@ -1626,23 +1671,16 @@ static int cnss_probe(struct platform_device *plat_dev) if (ret) goto deinit_qmi; - setup_timer(&plat_priv->fw_boot_timer, cnss_bus_fw_boot_timeout_hdlr, - (unsigned long)plat_priv); - - register_pm_notifier(&cnss_pm_notifier); - - ret = device_init_wakeup(&plat_dev->dev, true); + ret = cnss_misc_init(plat_priv); if (ret) - cnss_pr_err("Failed to init platform device wakeup source, err = %d\n", - ret); - - init_completion(&plat_priv->power_up_complete); - mutex_init(&plat_priv->dev_lock); + goto destroy_debugfs; cnss_pr_info("Platform driver probed successfully.\n"); return 0; +destroy_debugfs: + cnss_debugfs_destroy(plat_priv); deinit_qmi: cnss_qmi_deinit(plat_priv); deinit_event_work: @@ -1672,10 +1710,7 @@ static int cnss_remove(struct platform_device *plat_dev) { struct cnss_plat_data *plat_priv = platform_get_drvdata(plat_dev); - complete_all(&plat_priv->power_up_complete); - device_init_wakeup(&plat_dev->dev, false); - unregister_pm_notifier(&cnss_pm_notifier); - del_timer(&plat_priv->fw_boot_timer); + cnss_misc_deinit(plat_priv); cnss_debugfs_destroy(plat_priv); cnss_qmi_deinit(plat_priv); cnss_event_work_deinit(plat_priv); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 00ab8a49a7b2854ec3c9fce5eb3f9336b69db0d8..0814cdfbfa96116c67af3a7c19a66da9381cf907 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -241,6 +241,7 @@ struct cnss_plat_data { atomic_t pm_count; struct timer_list fw_boot_timer; struct completion power_up_complete; + struct completion cal_complete; struct mutex dev_lock; /* mutex for register access through debugfs */ u32 diag_reg_read_addr; u32 diag_reg_read_mem_type; diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 7d80e5b90b79b86b841c467957dec419980d4a75..33965c5b2fae8623ffb99c1e2cd4732361bebc47 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -706,6 +706,7 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops) int ret = 0; struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL); struct cnss_pci_data *pci_priv; + unsigned int timeout; if (!plat_priv) { cnss_pr_err("plat_priv is NULL\n"); @@ -723,10 +724,27 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops) return -EEXIST; } + if (!test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) + goto register_driver; + + cnss_pr_dbg("Start to wait for calibration to complete\n"); + + timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev); + ret = wait_for_completion_timeout(&plat_priv->cal_complete, + msecs_to_jiffies(timeout) << 2); + if (!ret) { + cnss_pr_err("Timeout waiting for calibration to complete\n"); + ret = -EAGAIN; + goto out; + } + +register_driver: ret = cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_REGISTER_DRIVER, CNSS_EVENT_SYNC_UNINTERRUPTIBLE, driver_ops); + +out: return ret; } EXPORT_SYMBOL(cnss_wlan_register_driver); @@ -1154,6 +1172,59 @@ int cnss_wlan_pm_control(struct device *dev, bool vote) } EXPORT_SYMBOL(cnss_wlan_pm_control); +void cnss_pci_pm_runtime_show_usage_count(struct cnss_pci_data *pci_priv) +{ + struct device *dev; + + if (!pci_priv) + return; + + dev = &pci_priv->pci_dev->dev; + + cnss_pr_dbg("Runtime PM usage count: %d\n", + atomic_read(&dev->power.usage_count)); +} + +int cnss_pci_pm_runtime_get(struct cnss_pci_data *pci_priv) +{ + if (!pci_priv) + return -ENODEV; + + return pm_runtime_get(&pci_priv->pci_dev->dev); +} + +void cnss_pci_pm_runtime_get_noresume(struct cnss_pci_data *pci_priv) +{ + if (!pci_priv) + return; + + return pm_runtime_get_noresume(&pci_priv->pci_dev->dev); +} + +int cnss_pci_pm_runtime_put_autosuspend(struct cnss_pci_data *pci_priv) +{ + if (!pci_priv) + return -ENODEV; + + return pm_runtime_put_autosuspend(&pci_priv->pci_dev->dev); +} + +void cnss_pci_pm_runtime_put_noidle(struct cnss_pci_data *pci_priv) +{ + if (!pci_priv) + return; + + pm_runtime_put_noidle(&pci_priv->pci_dev->dev); +} + +void cnss_pci_pm_runtime_mark_last_busy(struct cnss_pci_data *pci_priv) +{ + if (!pci_priv) + return; + + pm_runtime_mark_last_busy(&pci_priv->pci_dev->dev); +} + int cnss_auto_suspend(struct device *dev) { int ret = 0; @@ -1954,10 +2025,6 @@ static void cnss_mhi_notify_status(struct mhi_controller *mhi_ctrl, void *priv, return; } - if (pci_priv->driver_ops && pci_priv->driver_ops->update_status) - pci_priv->driver_ops->update_status(pci_priv->pci_dev, - CNSS_FW_DOWN); - switch (reason) { case MHI_CB_EE_RDDM: cnss_reason = CNSS_REASON_RDDM; diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index c8de4d74a1875646d2a4a227a5283e7c4fcee79b..e326aed68cbe2bbc95187167d6f688039089f7aa 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -143,5 +143,11 @@ int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv, void *data); int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv); int cnss_pci_call_driver_modem_status(struct cnss_pci_data *pci_priv, int modem_current_status); +void cnss_pci_pm_runtime_show_usage_count(struct cnss_pci_data *pci_priv); +int cnss_pci_pm_runtime_get(struct cnss_pci_data *pci_priv); +void cnss_pci_pm_runtime_get_noresume(struct cnss_pci_data *pci_priv); +int cnss_pci_pm_runtime_put_autosuspend(struct cnss_pci_data *pci_priv); +void cnss_pci_pm_runtime_put_noidle(struct cnss_pci_data *pci_priv); +void cnss_pci_pm_runtime_mark_last_busy(struct cnss_pci_data *pci_priv); #endif /* _CNSS_PCI_H */ diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index 2551cb667d5d51d821a28e95c3baf01ecd1a9861..5f948a4c0abe3d6ea1f81b551ac839e6fe9cafd5 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -113,6 +113,8 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv) req->fw_init_done_enable = 1; req->pin_connect_result_enable_valid = 1; req->pin_connect_result_enable = 1; + req->cal_done_enable_valid = 1; + req->cal_done_enable = 1; ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, wlfw_ind_register_resp_msg_v01_ei, resp); @@ -1185,6 +1187,24 @@ static void cnss_wlfw_pin_result_ind_cb(struct qmi_handle *qmi_wlfw, ind_msg->rf_pin_result); } +static void cnss_wlfw_cal_done_ind_cb(struct qmi_handle *qmi_wlfw, + struct sockaddr_qrtr *sq, + struct qmi_txn *txn, const void *data) +{ + struct cnss_plat_data *plat_priv = + container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); + + cnss_pr_dbg("Received QMI WLFW calibration done indication\n"); + + if (!txn) { + cnss_pr_err("Spurious indication\n"); + return; + } + + cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE, + 0, NULL); +} + static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = { { .type = QMI_INDICATION, @@ -1222,6 +1242,13 @@ static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = { sizeof(struct wlfw_pin_connect_result_ind_msg_v01), .fn = cnss_wlfw_pin_result_ind_cb }, + { + .type = QMI_INDICATION, + .msg_id = QMI_WLFW_CAL_DONE_IND_V01, + .ei = wlfw_cal_done_ind_msg_v01_ei, + .decoded_size = sizeof(struct wlfw_cal_done_ind_msg_v01), + .fn = cnss_wlfw_cal_done_ind_cb + }, {} }; diff --git a/drivers/net/wireless/marvell/libertas/dev.h b/drivers/net/wireless/marvell/libertas/dev.h index dd1ee1f0af48968046c4ca605e90ae53754fba89..469134930026520bd6253ecee125af5cccee19b3 100644 --- a/drivers/net/wireless/marvell/libertas/dev.h +++ b/drivers/net/wireless/marvell/libertas/dev.h @@ -104,6 +104,7 @@ struct lbs_private { u8 fw_ready; u8 surpriseremoved; u8 setup_fw_on_resume; + u8 power_up_on_resume; int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); void (*reset_card) (struct lbs_private *priv); int (*power_save) (struct lbs_private *priv); diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index 2300e796c6ab9e8106e132b3988fa240dc4783a4..43743c26c071f538f1942696aa97d20b0cbf091d 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -1290,15 +1290,23 @@ static void if_sdio_remove(struct sdio_func *func) static int if_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); - int ret; struct if_sdio_card *card = sdio_get_drvdata(func); + struct lbs_private *priv = card->priv; + int ret; mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); + priv->power_up_on_resume = false; /* If we're powered off anyway, just let the mmc layer remove the * card. */ - if (!lbs_iface_active(card->priv)) - return -ENOSYS; + if (!lbs_iface_active(priv)) { + if (priv->fw_ready) { + priv->power_up_on_resume = true; + if_sdio_power_off(card); + } + + return 0; + } dev_info(dev, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), flags); @@ -1306,9 +1314,14 @@ static int if_sdio_suspend(struct device *dev) /* If we aren't being asked to wake on anything, we should bail out * and let the SD stack power down the card. */ - if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) { + if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { dev_info(dev, "Suspend without wake params -- powering down card\n"); - return -ENOSYS; + if (priv->fw_ready) { + priv->power_up_on_resume = true; + if_sdio_power_off(card); + } + + return 0; } if (!(flags & MMC_PM_KEEP_POWER)) { @@ -1321,7 +1334,7 @@ static int if_sdio_suspend(struct device *dev) if (ret) return ret; - ret = lbs_suspend(card->priv); + ret = lbs_suspend(priv); if (ret) return ret; @@ -1336,6 +1349,11 @@ static int if_sdio_resume(struct device *dev) dev_info(dev, "%s: resume: we're back\n", sdio_func_id(func)); + if (card->priv->power_up_on_resume) { + if_sdio_power_on(card); + wait_event(card->pwron_waitq, card->priv->fw_ready); + } + ret = lbs_resume(card->priv); return ret; diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 9935bd09db1fb309090222be94c85ec98917b5cc..d4947e3a909ec6758a7554647f18125d3c6cebbf 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2928,6 +2928,8 @@ static void rndis_wlan_auth_indication(struct usbnet *usbdev, while (buflen >= sizeof(*auth_req)) { auth_req = (void *)buf; + if (buflen < le32_to_cpu(auth_req->length)) + return; type = "unknown"; flags = le32_to_cpu(auth_req->flags); pairwise_error = false; diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 761cf8573a805e272121fa05bf129f1ee600a10a..f48c3f62966d43f0f74c83f311958f89da62f3dc 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -35,6 +35,7 @@ #include "wl12xx_80211.h" #include "cmd.h" #include "event.h" +#include "ps.h" #include "tx.h" #include "hw_ops.h" @@ -191,6 +192,10 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl, timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + return ret; + do { if (time_after(jiffies, timeout_time)) { wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", @@ -222,6 +227,7 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl, } while (!event); out: + wl1271_ps_elp_sleep(wl); kfree(events_vector); return ret; } diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 0f15696195f884f59c82e431757593362a0489ca..078a4940bc5c3bcd9a496b8afec6536c61fee5c8 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c @@ -59,7 +59,7 @@ static u32 wlcore_rx_get_align_buf_size(struct wl1271 *wl, u32 pkt_len) static void wl1271_rx_status(struct wl1271 *wl, struct wl1271_rx_descriptor *desc, struct ieee80211_rx_status *status, - u8 beacon) + u8 beacon, u8 probe_rsp) { memset(status, 0, sizeof(struct ieee80211_rx_status)); @@ -106,6 +106,9 @@ static void wl1271_rx_status(struct wl1271 *wl, } } + if (beacon || probe_rsp) + status->boottime_ns = ktime_get_boot_ns(); + if (beacon) wlcore_set_pending_regdomain_ch(wl, (u16)desc->channel, status->band); @@ -191,7 +194,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, if (ieee80211_is_data_present(hdr->frame_control)) is_data = 1; - wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); + wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon, + ieee80211_is_probe_resp(hdr->frame_control)); wlcore_hw_set_rx_csum(wl, desc, skb); seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index d5e790dd589a27bf1d4094d152c791cab6fb7248..1a40fc3517a8f0b6d443c5e16c94b18c700a4847 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -87,8 +87,7 @@ struct netfront_cb { /* IRQ name is queue name with "-tx" or "-rx" appended */ #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3) -static DECLARE_WAIT_QUEUE_HEAD(module_load_q); -static DECLARE_WAIT_QUEUE_HEAD(module_unload_q); +static DECLARE_WAIT_QUEUE_HEAD(module_wq); struct netfront_stats { u64 packets; @@ -908,7 +907,11 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue, BUG_ON(pull_to <= skb_headlen(skb)); __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); } - BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); + if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) { + queue->rx.rsp_cons = ++cons; + kfree_skb(nskb); + return ~0U; + } skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, skb_frag_page(nfrag), @@ -1045,6 +1048,8 @@ static int xennet_poll(struct napi_struct *napi, int budget) skb->len += rx->status; i = xennet_fill_frags(queue, skb, &tmpq); + if (unlikely(i == ~0U)) + goto err; if (rx->flags & XEN_NETRXF_csum_blank) skb->ip_summed = CHECKSUM_PARTIAL; @@ -1331,11 +1336,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netif_carrier_off(netdev); xenbus_switch_state(dev, XenbusStateInitialising); - wait_event(module_load_q, - xenbus_read_driver_state(dev->otherend) != - XenbusStateClosed && - xenbus_read_driver_state(dev->otherend) != - XenbusStateUnknown); + wait_event(module_wq, + xenbus_read_driver_state(dev->otherend) != + XenbusStateClosed && + xenbus_read_driver_state(dev->otherend) != + XenbusStateUnknown); return netdev; exit: @@ -1603,6 +1608,7 @@ static int xennet_init_queue(struct netfront_queue *queue) { unsigned short i; int err = 0; + char *devid; spin_lock_init(&queue->tx_lock); spin_lock_init(&queue->rx_lock); @@ -1610,8 +1616,9 @@ static int xennet_init_queue(struct netfront_queue *queue) setup_timer(&queue->rx_refill_timer, rx_refill_timeout, (unsigned long)queue); - snprintf(queue->name, sizeof(queue->name), "%s-q%u", - queue->info->netdev->name, queue->id); + devid = strrchr(queue->info->xbdev->nodename, '/') + 1; + snprintf(queue->name, sizeof(queue->name), "vif%s-q%u", + devid, queue->id); /* Initialise tx_skbs as a free chain containing every entry. */ queue->tx_skb_freelist = 0; @@ -2007,15 +2014,14 @@ static void netback_changed(struct xenbus_device *dev, dev_dbg(&dev->dev, "%s\n", xenbus_strstate(backend_state)); + wake_up_all(&module_wq); + switch (backend_state) { case XenbusStateInitialising: case XenbusStateInitialised: case XenbusStateReconfiguring: case XenbusStateReconfigured: - break; - case XenbusStateUnknown: - wake_up_all(&module_unload_q); break; case XenbusStateInitWait: @@ -2031,12 +2037,10 @@ static void netback_changed(struct xenbus_device *dev, break; case XenbusStateClosed: - wake_up_all(&module_unload_q); if (dev->state == XenbusStateClosed) break; /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: - wake_up_all(&module_unload_q); xenbus_frontend_closed(dev); break; } @@ -2144,14 +2148,14 @@ static int xennet_remove(struct xenbus_device *dev) if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) { xenbus_switch_state(dev, XenbusStateClosing); - wait_event(module_unload_q, + wait_event(module_wq, xenbus_read_driver_state(dev->otherend) == XenbusStateClosing || xenbus_read_driver_state(dev->otherend) == XenbusStateUnknown); xenbus_switch_state(dev, XenbusStateClosed); - wait_event(module_unload_q, + wait_event(module_wq, xenbus_read_driver_state(dev->otherend) == XenbusStateClosed || xenbus_read_driver_state(dev->otherend) == diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c index d5553c47014fade81a4f461903b3cb6c4372ccf5..5d823e965883b0f5f23db5ab39afc9f96a128267 100644 --- a/drivers/nfc/pn533/usb.c +++ b/drivers/nfc/pn533/usb.c @@ -74,7 +74,7 @@ static void pn533_recv_response(struct urb *urb) struct sk_buff *skb = NULL; if (!urb->status) { - skb = alloc_skb(urb->actual_length, GFP_KERNEL); + skb = alloc_skb(urb->actual_length, GFP_ATOMIC); if (!skb) { nfc_err(&phy->udev->dev, "failed to alloc memory\n"); } else { @@ -186,7 +186,7 @@ static int pn533_usb_send_frame(struct pn533 *dev, if (dev->protocol_type == PN533_PROTO_REQ_RESP) { /* request for response for sent packet directly */ - rc = pn533_submit_urb_for_response(phy, GFP_ATOMIC); + rc = pn533_submit_urb_for_response(phy, GFP_KERNEL); if (rc) goto error; } else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) { diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 2fffd42767c7b5ddb398b32c3d5a1ec7e8e1dcc8..fb5ab5812a22f255cfe8766ee3a82cea7dd375bb 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -808,9 +808,9 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd, * overshoots the remainder by 4 bytes, assume it was * including 'status'. */ - if (out_field[1] - 8 == remainder) + if (out_field[1] - 4 == remainder) return remainder; - return out_field[1] - 4; + return out_field[1] - 8; } else if (cmd == ND_CMD_CALL) { struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field; diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 38c128f230e7cdf1221e90c4f878f695347a077e..3a63d58d2ca9f86f6d6f39a6b0516ce1fa44116a 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1016,7 +1016,7 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c, (void __user *)(uintptr_t)cmd.addr, cmd.data_len, - (void __user *)(uintptr_t)cmd.metadata, cmd.metadata, + (void __user *)(uintptr_t)cmd.metadata, cmd.metadata_len, 0, &cmd.result, timeout); if (status >= 0) { if (put_user(cmd.result, &ucmd->result)) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index a67d037165104db83dea64ab0bf99f05ee64e8db..afb99876fa9e1ad5be351d602e1fc1358bc81340 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -306,6 +306,14 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db, old_value = *dbbuf_db; *dbbuf_db = value; + /* + * Ensure that the doorbell is updated before reading the event + * index from memory. The controller needs to provide similar + * ordering to ensure the envent index is updated before reading + * the doorbell. + */ + mb(); + if (!nvme_dbbuf_need_event(*dbbuf_ei, value, old_value)) return false; } diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 48a831d58e7aeab2f628bb43cc9c84339f6bb5a2..9fffe41ead5009c497d65ce16bcf67da31bd41ea 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -1728,6 +1728,8 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown) nvme_stop_queues(&ctrl->ctrl); blk_mq_tagset_busy_iter(&ctrl->tag_set, nvme_cancel_request, &ctrl->ctrl); + if (shutdown) + nvme_start_queues(&ctrl->ctrl); nvme_rdma_destroy_io_queues(ctrl, shutdown); } diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 240b0d628222026966db95be698c37031fb0c2c3..5fa7856f6b344c1d5dbef76b6d72a9ca1aa88513 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -598,6 +598,14 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl) } ctrl->csts = NVME_CSTS_RDY; + + /* + * Controllers that are not yet enabled should not really enforce the + * keep alive timeout, but we still want to track a timeout and cleanup + * in case a host died before it enabled the controller. Hence, simply + * reset the keep alive timer when the controller is enabled. + */ + mod_delayed_work(system_wq, &ctrl->ka_work, ctrl->kato * HZ); } static void nvmet_clear_ctrl(struct nvmet_ctrl *ctrl) diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index c0080f6ab2f5b209eb8aeae003df6659f9124f11..0b0a4825b3eb1274a776eafc502de4787ffa8b11 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -300,7 +300,7 @@ fcloop_tgt_lsrqst_done_work(struct work_struct *work) struct fcloop_tport *tport = tls_req->tport; struct nvmefc_ls_req *lsreq = tls_req->lsreq; - if (tport->remoteport) + if (!tport || tport->remoteport) lsreq->done(lsreq, tls_req->status); } @@ -318,6 +318,7 @@ fcloop_ls_req(struct nvme_fc_local_port *localport, if (!rport->targetport) { tls_req->status = -ECONNREFUSED; + tls_req->tport = NULL; schedule_work(&tls_req->work); return ret; } diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 2afafd5d8915088de1533881247fcb67b4a8aa4e..635886e4835cbb4b0a7836292c9bdd111ee0eb9c 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -865,6 +865,10 @@ struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id) return cell; } + /* NULL cell_id only allowed for device tree; invalid otherwise */ + if (!cell_id) + return ERR_PTR(-EINVAL); + return nvmem_cell_get_from_list(cell_id); } EXPORT_SYMBOL_GPL(nvmem_cell_get); diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 01cf1c1a841a4de23af9e84f7c40cea7c552ca16..8de329546b8220783664f291ffd55b62144cdec5 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -286,12 +286,16 @@ static int bpp_probe(struct platform_device *op) ops = kmemdup(&parport_sunbpp_ops, sizeof(struct parport_operations), GFP_KERNEL); - if (!ops) + if (!ops) { + err = -ENOMEM; goto out_unmap; + } dprintk(("register_port\n")); - if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) + if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) { + err = -ENOMEM; goto out_free_ops; + } p->size = size; p->dev = &op->dev; diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/host/pci-aardvark.c index 9bfc22b5da4b718ffe7ed5e1d9805e0e9317fee7..5f3048e75becb598b14013382ed102fa59a6f5b4 100644 --- a/drivers/pci/host/pci-aardvark.c +++ b/drivers/pci/host/pci-aardvark.c @@ -954,6 +954,7 @@ static int advk_pcie_probe(struct platform_device *pdev) bus = bridge->bus; + pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); list_for_each_entry(child, &bus->children, node) diff --git a/drivers/pci/host/pci-ftpci100.c b/drivers/pci/host/pci-ftpci100.c index 4ea7d2ebcc5cd4ed4e3702947152c72054a06efe..4e6b219315142b67e05200fd8f5f250f112b9586 100644 --- a/drivers/pci/host/pci-ftpci100.c +++ b/drivers/pci/host/pci-ftpci100.c @@ -353,11 +353,13 @@ static int faraday_pci_setup_cascaded_irq(struct faraday_pci *p) irq = of_irq_get(intc, 0); if (irq <= 0) { dev_err(p->dev, "failed to get parent IRQ\n"); + of_node_put(intc); return irq ?: -EINVAL; } p->irqdomain = irq_domain_add_linear(intc, PCI_NUM_INTX, &faraday_pci_irqdomain_ops, p); + of_node_put(intc); if (!p->irqdomain) { dev_err(p->dev, "failed to create Gemini PCI IRQ domain\n"); return -EINVAL; diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c index 44a47d4f0b8f294fef5c2b2482b0a16856849f01..148896f73c06f8eca9ab6cb99c9b3b98f569dab6 100644 --- a/drivers/pci/host/pci-host-common.c +++ b/drivers/pci/host/pci-host-common.c @@ -45,7 +45,7 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, switch (resource_type(res)) { case IORESOURCE_IO: - err = pci_remap_iospace(res, iobase); + err = devm_pci_remap_iospace(dev, res, iobase); if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 8d88f19dc171145a74e8a87345796406f1c0ec37..12c1c1851ee6308b043a1a4db37a18ec3304ec2d 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -1220,7 +1220,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) pcie->realio.start = PCIBIOS_MIN_IO; pcie->realio.end = min_t(resource_size_t, IO_SPACE_LIMIT, - resource_size(&pcie->io)); + resource_size(&pcie->io) - 1); } else pcie->realio = pcie->io; diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index d417acab0ecf7baa81fca755a97238cc1232131f..aff4cfb555fbbba74c122cc4efdb611546388ea3 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c @@ -89,7 +89,7 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, switch (resource_type(res)) { case IORESOURCE_IO: - err = pci_remap_iospace(res, iobase); + err = devm_pci_remap_iospace(dev, res, iobase); if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 8f44a7d14bffa046ce25700807b2bbf27cefc1d6..41edce16a07cdcebd9df7f6ef466d9f28babb545 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -1105,7 +1105,7 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) struct resource *res = win->res; if (resource_type(res) == IORESOURCE_IO) { - err = pci_remap_iospace(res, iobase); + err = devm_pci_remap_iospace(dev, res, iobase); if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index 65dea98b2643fb18469799a9e784ce8571416912..dd527ea558d71d51c1caff9593f43694f15a308c 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c @@ -561,7 +561,7 @@ static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie) PCI_NUM_INTX, &legacy_domain_ops, pcie); - + of_node_put(legacy_intc_node); if (!pcie->legacy_irq_domain) { dev_err(dev, "failed to create IRQ domain\n"); return -ENOMEM; diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index 94e13cb8608f179ba8e25d30dfd9436517bd55db..29f024f0ed7f2c2e8c0ab134a9f7949f09e8a9f8 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c @@ -511,6 +511,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port) port->leg_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, &intx_domain_ops, port); + of_node_put(pcie_intc_node); if (!port->leg_domain) { dev_err(dev, "Failed to get a INTx IRQ domain\n"); return -ENODEV; diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 7b0e97be9063d971dbd327836ab1c9cd2377287d..591f2e05ab1c3c1f7dc47b5d38c0aa390fdc72de 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -452,8 +452,17 @@ int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, list_add(&slot->slot_list, &pci_hotplug_slot_list); result = fs_add_slot(pci_slot); + if (result) + goto err_list_del; + kobject_uevent(&pci_slot->kobj, KOBJ_ADD); dbg("Added slot %s to the list\n", name); + goto out; + +err_list_del: + list_del(&slot->slot_list); + pci_slot->hotplug = NULL; + pci_destroy_slot(pci_slot); out: mutex_unlock(&pci_hp_mutex); return result; diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e7d6cfaf386581a7d89541c89298d235bde752d6..9fc4357c3db940312c7caf86e3e5cab8866316a7 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -132,6 +132,7 @@ int pciehp_unconfigure_device(struct slot *p_slot); void pciehp_queue_pushbutton_work(struct work_struct *work); struct controller *pcie_init(struct pcie_device *dev); int pcie_init_notification(struct controller *ctrl); +void pcie_shutdown_notification(struct controller *ctrl); int pciehp_enable_slot(struct slot *p_slot); int pciehp_disable_slot(struct slot *p_slot); void pcie_reenable_notification(struct controller *ctrl); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 1288289cc85d38fa09190586f7743ac1271e5a83..c38e392d63e4b2037b1c1cbb879b3d1239ec8a80 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -76,6 +76,12 @@ static int reset_slot(struct hotplug_slot *slot, int probe); */ static void release_slot(struct hotplug_slot *hotplug_slot) { + struct slot *slot = hotplug_slot->private; + + /* queued work needs hotplug_slot name */ + cancel_delayed_work(&slot->work); + drain_workqueue(slot->wq); + kfree(hotplug_slot->ops); kfree(hotplug_slot->info); kfree(hotplug_slot); @@ -278,6 +284,7 @@ static void pciehp_remove(struct pcie_device *dev) { struct controller *ctrl = get_service_data(dev); + pcie_shutdown_notification(ctrl); cleanup_slot(ctrl); pciehp_release_ctrl(ctrl); } diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 46c2ee2caf281680aa280f1a386f4d059d110888..2fa830727362939ef0446940d308ad5500244c35 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -562,8 +562,6 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; struct pci_dev *pdev = ctrl_dev(ctrl); - struct pci_bus *subordinate = pdev->subordinate; - struct pci_dev *dev; struct slot *slot = ctrl->slot; u16 status, events; u8 present; @@ -611,14 +609,9 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id) wake_up(&ctrl->queue); } - if (subordinate) { - list_for_each_entry(dev, &subordinate->devices, bus_list) { - if (dev->ignore_hotplug) { - ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n", - events, pci_name(dev)); - return IRQ_HANDLED; - } - } + if (pdev->ignore_hotplug) { + ctrl_dbg(ctrl, "ignoring hotplug event %#06x\n", events); + return IRQ_HANDLED; } /* Check Attention Button Pressed */ @@ -789,7 +782,7 @@ int pcie_init_notification(struct controller *ctrl) return 0; } -static void pcie_shutdown_notification(struct controller *ctrl) +void pcie_shutdown_notification(struct controller *ctrl) { if (ctrl->notification_enabled) { pcie_disable_notification(ctrl); @@ -824,7 +817,7 @@ static int pcie_init_slot(struct controller *ctrl) static void pcie_cleanup_slot(struct controller *ctrl) { struct slot *slot = ctrl->slot; - cancel_delayed_work(&slot->work); + destroy_workqueue(slot->wq); kfree(slot); } @@ -912,7 +905,6 @@ struct controller *pcie_init(struct pcie_device *dev) void pciehp_release_ctrl(struct controller *ctrl) { - pcie_shutdown_notification(ctrl); pcie_cleanup_slot(ctrl); kfree(ctrl); } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 62a0677b32f100989b40e96985534ae3063121ac..22924629e64a81357b2366b413a40d3966c86619 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3446,6 +3446,44 @@ void pci_unmap_iospace(struct resource *res) } EXPORT_SYMBOL(pci_unmap_iospace); +static void devm_pci_unmap_iospace(struct device *dev, void *ptr) +{ + struct resource **res = ptr; + + pci_unmap_iospace(*res); +} + +/** + * devm_pci_remap_iospace - Managed pci_remap_iospace() + * @dev: Generic device to remap IO address for + * @res: Resource describing the I/O space + * @phys_addr: physical address of range to be mapped + * + * Managed pci_remap_iospace(). Map is automatically unmapped on driver + * detach. + */ +int devm_pci_remap_iospace(struct device *dev, const struct resource *res, + phys_addr_t phys_addr) +{ + const struct resource **ptr; + int error; + + ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + error = pci_remap_iospace(res, phys_addr); + if (error) { + devres_free(ptr); + } else { + *ptr = res; + devres_add(dev, ptr); + } + + return error; +} +EXPORT_SYMBOL(devm_pci_remap_iospace); + /** * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace() * @dev: Generic device to remap IO address for diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4bccaf688aad7c7d5ed73b89b1b4f118c0a6690b..e23bfd9845b12f3808e88838bbb1bdec5c4dcc81 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1560,6 +1560,10 @@ static void pci_configure_mps(struct pci_dev *dev) if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge)) return; + /* MPS and MRRS fields are of type 'RsvdP' for VFs, short-circuit out */ + if (dev->is_virtfn) + return; + mps = pcie_get_mps(dev); p_mps = pcie_get_mps(bridge); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index ec2911c4ee425e7cde8ee990aa78848cfa96f8e1..35c9b2f4b293aae36cb0fee4cdd49982784c13f8 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4388,11 +4388,6 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags) * * 0x9d10-0x9d1b PCI Express Root port #{1-12} * - * The 300 series chipset suffers from the same bug so include those root - * ports here as well. - * - * 0xa32c-0xa343 PCI Express Root port #{0-24} - * * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html @@ -4410,7 +4405,6 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */ case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */ case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */ - case 0xa32c ... 0xa343: /* 300 series */ return true; } diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c index af81b2dec42e954692fe85ef2992ecf82fc44cb3..620f5b995a129d8a6409a3181dfe8951fd32d408 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -24,6 +24,8 @@ #include #include +#include + MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); @@ -1173,6 +1175,8 @@ static int ioctl_port_to_pff(struct switchtec_dev *stdev, default: if (p.port > ARRAY_SIZE(pcfg->dsp_pff_inst_id)) return -EINVAL; + p.port = array_index_nospec(p.port, + ARRAY_SIZE(pcfg->dsp_pff_inst_id) + 1); p.pff = ioread32(&pcfg->dsp_pff_inst_id[p.port - 1]); break; } diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c index eb23311bc70c042319909206fa4f015c7da4c905..8b79c2f7931f1711b4ed85b7f8a90123788c484a 100644 --- a/drivers/perf/xgene_pmu.c +++ b/drivers/perf/xgene_pmu.c @@ -1463,7 +1463,7 @@ static char *xgene_pmu_dev_name(struct device *dev, u32 type, int id) case PMU_TYPE_IOB: return devm_kasprintf(dev, GFP_KERNEL, "iob%d", id); case PMU_TYPE_IOB_SLOW: - return devm_kasprintf(dev, GFP_KERNEL, "iob-slow%d", id); + return devm_kasprintf(dev, GFP_KERNEL, "iob_slow%d", id); case PMU_TYPE_MCB: return devm_kasprintf(dev, GFP_KERNEL, "mcb%d", id); case PMU_TYPE_MC: diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-mux.c b/drivers/pinctrl/bcm/pinctrl-nsp-mux.c index 35c17653c694767c8e13d1a8d02d7d91718d23b3..87618a4e90e451f2834214a337ce81e12de560fc 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-mux.c @@ -460,8 +460,8 @@ static int nsp_pinmux_enable(struct pinctrl_dev *pctrl_dev, const struct nsp_pin_function *func; const struct nsp_pin_group *grp; - if (grp_select > pinctrl->num_groups || - func_select > pinctrl->num_functions) + if (grp_select >= pinctrl->num_groups || + func_select >= pinctrl->num_functions) return -EINVAL; func = &pinctrl->functions[func_select]; @@ -577,6 +577,8 @@ static int nsp_pinmux_probe(struct platform_device *pdev) return PTR_ERR(pinctrl->base0); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) + return -EINVAL; pinctrl->base1 = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); if (!pinctrl->base1) { diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index 6e472691d8eed6f0d3a71d20fe8e6e7e939d5b7d..17f2c5a505b25ee53a084c03d1d2c9afa5e82a44 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -389,7 +389,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, const char *name; int i, ret; - if (group > pctldev->num_groups) + if (group >= pctldev->num_groups) return; seq_printf(s, "\n"); diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index a4e9f430d45269c45367cacc1010087971c5596b..e2cca91fd2669c2953d13743279c21a852ddefd6 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -433,7 +433,7 @@ static void imx1_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, const char *name; int i, ret; - if (group > info->ngroups) + if (group >= info->ngroups) return; seq_puts(s, "\n"); diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 433af328d9817a028f4bccce07492fbc6ac27a68..b78f42abff2f8a029c954e58e5ca518f3168ddd0 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -530,7 +530,8 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) /* Each status bit covers four pins */ for (i = 0; i < 4; i++) { regval = readl(regs + i); - if (!(regval & PIN_IRQ_PENDING)) + if (!(regval & PIN_IRQ_PENDING) || + !(regval & BIT(INTERRUPT_MASK_OFF))) continue; irq = irq_find_mapping(gc->irqdomain, irqnr + i); generic_handle_irq(irq); diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index d84761822243ec4fb8716e0ecfed2859564ae291..103aaab41357033c1cc9a1e87bddda0cc376f4a7 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -536,7 +536,7 @@ static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input); } else { ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false); - ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, input); + ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, !input); ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, false); } diff --git a/drivers/pinctrl/pinctrl-rza1.c b/drivers/pinctrl/pinctrl-rza1.c index 04d058706b808fe8807192a6f3219c845cfa9b27..a865dc56a491b9b295f3d9cf6c409c4455b05e11 100644 --- a/drivers/pinctrl/pinctrl-rza1.c +++ b/drivers/pinctrl/pinctrl-rza1.c @@ -878,6 +878,7 @@ static int rza1_dt_node_to_map(struct pinctrl_dev *pctldev, const char *grpname; const char **fngrps; int ret, npins; + int gsel, fsel; npins = rza1_dt_node_pin_count(np); if (npins < 0) { @@ -927,18 +928,19 @@ static int rza1_dt_node_to_map(struct pinctrl_dev *pctldev, fngrps[0] = grpname; mutex_lock(&rza1_pctl->mutex); - ret = pinctrl_generic_add_group(pctldev, grpname, grpins, npins, - NULL); - if (ret) { + gsel = pinctrl_generic_add_group(pctldev, grpname, grpins, npins, + NULL); + if (gsel < 0) { mutex_unlock(&rza1_pctl->mutex); - return ret; + return gsel; } - ret = pinmux_generic_add_function(pctldev, grpname, fngrps, 1, - mux_confs); - if (ret) + fsel = pinmux_generic_add_function(pctldev, grpname, fngrps, 1, + mux_confs); + if (fsel < 0) { + ret = fsel; goto remove_group; - mutex_unlock(&rza1_pctl->mutex); + } dev_info(rza1_pctl->dev, "Parsed function and group %s with %d pins\n", grpname, npins); @@ -955,15 +957,15 @@ static int rza1_dt_node_to_map(struct pinctrl_dev *pctldev, (*map)->data.mux.group = np->name; (*map)->data.mux.function = np->name; *num_maps = 1; + mutex_unlock(&rza1_pctl->mutex); return 0; remove_function: - mutex_lock(&rza1_pctl->mutex); - pinmux_generic_remove_last_function(pctldev); + pinmux_generic_remove_function(pctldev, fsel); remove_group: - pinctrl_generic_remove_last_group(pctldev); + pinctrl_generic_remove_group(pctldev, gsel); mutex_unlock(&rza1_pctl->mutex); dev_info(rza1_pctl->dev, "Unable to parse function and group %s\n", diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 19b37b7cc11496a20b242827eb8179a2f74c8f43..31e29d2e77933e6b03a38e88557a51f18379ade8 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -287,22 +287,30 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev, /* Convert register value to pinconf value */ switch (param) { case PIN_CONFIG_BIAS_DISABLE: - arg = arg == MSM_NO_PULL; + if (arg != MSM_NO_PULL) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_BIAS_PULL_DOWN: - arg = arg == MSM_PULL_DOWN; + if (arg != MSM_PULL_DOWN) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_BIAS_BUS_HOLD: if (pctrl->soc->pull_no_keeper) return -ENOTSUPP; - arg = arg == MSM_KEEPER; + if (arg != MSM_KEEPER) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_BIAS_PULL_UP: if (pctrl->soc->pull_no_keeper) arg = arg == MSM_PULL_UP_NO_KEEPER; else arg = arg == MSM_PULL_UP; + if (!arg) + return -EINVAL; break; case PIN_CONFIG_DRIVE_STRENGTH: arg = msm_regval_to_drive(arg); diff --git a/drivers/pinctrl/qcom/pinctrl-sm6150.c b/drivers/pinctrl/qcom/pinctrl-sm6150.c index 601384ee2174a49e35667efd82d00e0eb391cdb1..da15d91793f0d683b2dcd86558d7733ba20659da 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6150.c @@ -474,7 +474,8 @@ enum sm6150_functions { msm_mux_qlink_request, msm_mux_qlink_enable, msm_mux_pa_indicator, - msm_mux_NAV_PPS, + msm_mux_NAV_PPS_IN, + msm_mux_NAV_PPS_OUT, msm_mux_GPS_TX, msm_mux_phase_flag23, msm_mux_GP_PDM0, @@ -587,20 +588,18 @@ static const char * const gpio_groups[] = { "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", "gpio45", "gpio46", "gpio47", "gpio48", - "gpio48", "gpio49", "gpio49", "gpio50", "gpio50", "gpio51", "gpio52", - "gpio53", "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59", - "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65", "gpio66", - "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", - "gpio74", "gpio75", "gpio76", "gpio77", "gpio78", "gpio79", "gpio80", - "gpio81", "gpio82", "gpio83", "gpio84", "gpio84", "gpio85", "gpio86", - "gpio87", "gpio88", "gpio88", "gpio89", "gpio90", "gpio91", "gpio92", - "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", "gpio98", - "gpio99", "gpio100", "gpio100", "gpio101", "gpio102", "gpio103", - "gpio104", "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", - "gpio110", "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", - "gpio116", "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", - "gpio122", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", + "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91", + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", + "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", + "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", + "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122", }; static const char * const qdss_gpio6_groups[] = { "gpio0", "gpio30", @@ -845,9 +844,13 @@ static const char * const qlink_enable_groups[] = { static const char * const pa_indicator_groups[] = { "gpio53", }; -static const char * const NAV_PPS_groups[] = { - "gpio53", "gpio53", "gpio56", "gpio56", "gpio57", "gpio57", "gpio59", - "gpio59", "gpio60", "gpio60", +static const char * const NAV_PPS_IN_groups[] = { + "gpio53", "gpio56", "gpio57", "gpio59", + "gpio60", +}; +static const char * const NAV_PPS_OUT_groups[] = { + "gpio53", "gpio56", "gpio57", "gpio59", + "gpio60", }; static const char * const GPS_TX_groups[] = { "gpio53", "gpio54", "gpio56", "gpio57", "gpio59", "gpio60", @@ -1232,7 +1235,8 @@ static const struct msm_function sm6150_functions[] = { FUNCTION(qlink_request), FUNCTION(qlink_enable), FUNCTION(pa_indicator), - FUNCTION(NAV_PPS), + FUNCTION(NAV_PPS_IN), + FUNCTION(NAV_PPS_OUT), FUNCTION(GPS_TX), FUNCTION(phase_flag23), FUNCTION(GP_PDM0), @@ -1433,21 +1437,21 @@ static const struct msm_pingroup sm6150_groups[] = { NA), [52] = PINGROUP(52, SOUTH, qlink_enable, NA, NA, NA, NA, NA, NA, NA, NA), - [53] = PINGROUP(53, SOUTH, pa_indicator, NAV_PPS, NAV_PPS, GPS_TX, NA, - phase_flag23, NA, NA, NA), + [53] = PINGROUP(53, SOUTH, pa_indicator, NAV_PPS_IN, NAV_PPS_OUT, + GPS_TX, NA, phase_flag23, NA, NA, NA), [54] = PINGROUP(54, SOUTH, NA, GPS_TX, GP_PDM0, NA, phase_flag22, atest_usb13, ddr_pxi1, NA, NA), [55] = PINGROUP(55, SOUTH, NA, NA, phase_flag4, atest_usb12, ddr_pxi1, NA, NA, NA, NA), - [56] = PINGROUP(56, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, - NA, NA), - [57] = PINGROUP(57, SOUTH, NA, NAV_PPS, GPS_TX, NAV_PPS, gcc_gp1, NA, - NA, NA, NA), + [56] = PINGROUP(56, SOUTH, NA, NAV_PPS_IN, NAV_PPS_OUT, GPS_TX, NA, + NA, NA, NA, NA), + [57] = PINGROUP(57, SOUTH, NA, NAV_PPS_IN, GPS_TX, NAV_PPS_OUT, + gcc_gp1, NA, NA, NA, NA), [58] = PINGROUP(58, SOUTH, NA, gcc_gp2, NA, NA, NA, NA, NA, NA, NA), - [59] = PINGROUP(59, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, gcc_gp3, NA, - NA, NA, NA), - [60] = PINGROUP(60, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, CRI_TRNG0, NA, - NA, NA, NA), + [59] = PINGROUP(59, SOUTH, NA, NAV_PPS_IN, NAV_PPS_OUT, GPS_TX, + gcc_gp3, NA, NA, NA, NA), + [60] = PINGROUP(60, SOUTH, NA, NAV_PPS_IN, NAV_PPS_OUT, GPS_TX, + CRI_TRNG0, NA, NA, NA, NA), [61] = PINGROUP(61, SOUTH, NA, CRI_TRNG, NA, NA, NA, NA, NA, NA, NA), [62] = PINGROUP(62, SOUTH, NA, CRI_TRNG1, NA, NA, NA, NA, NA, NA, NA), [63] = PINGROUP(63, SOUTH, NA, NA, GP_PDM2, NA, NA, NA, NA, NA, NA), diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 3bec5a41ca194845e658ee13c42b0269d50e7cd6..1b04e9adb957e42d0b921115cec2c6c5b263bf13 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -395,31 +395,47 @@ static int pmic_gpio_config_get(struct pinctrl_dev *pctldev, switch (param) { case PIN_CONFIG_DRIVE_PUSH_PULL: - arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_CMOS; + if (pad->buffer_type != PMIC_GPIO_OUT_BUF_CMOS) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_DRIVE_OPEN_DRAIN: - arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS; + if (pad->buffer_type != PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_DRIVE_OPEN_SOURCE: - arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS; + if (pad->buffer_type != PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_BIAS_PULL_DOWN: - arg = pad->pullup == PMIC_GPIO_PULL_DOWN; + if (pad->pullup != PMIC_GPIO_PULL_DOWN) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_BIAS_DISABLE: - arg = pad->pullup = PMIC_GPIO_PULL_DISABLE; + if (pad->pullup != PMIC_GPIO_PULL_DISABLE) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_BIAS_PULL_UP: - arg = pad->pullup == PMIC_GPIO_PULL_UP_30; + if (pad->pullup != PMIC_GPIO_PULL_UP_30) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: - arg = !pad->is_enabled; + if (pad->is_enabled) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_POWER_SOURCE: arg = pad->power_source; break; case PIN_CONFIG_INPUT_ENABLE: - arg = pad->input_enabled; + if (!pad->input_enabled) + return -EINVAL; + arg = 1; break; case PIN_CONFIG_OUTPUT_ENABLE: arg = pad->output_enabled; diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 7cc9274d7d5fa3e5741ccfef5a7a76b8fc3993d0..95a179df73d07389be8319c43cbe4eee0090b869 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -1202,6 +1202,8 @@ EXPORT_SYMBOL(gsi_register_device); int gsi_write_device_scratch(unsigned long dev_hdl, struct gsi_device_scratch *val) { + unsigned int max_usb_pkt_size = 0; + if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; @@ -1220,7 +1222,8 @@ int gsi_write_device_scratch(unsigned long dev_hdl, if (val->max_usb_pkt_size_valid && val->max_usb_pkt_size != 1024 && - val->max_usb_pkt_size != 512) { + val->max_usb_pkt_size != 512 && + val->max_usb_pkt_size != 64) { GSIERR("bad USB max pkt size dev_hdl=0x%lx sz=%u\n", dev_hdl, val->max_usb_pkt_size); return -GSI_STATUS_INVALID_PARAMS; @@ -1230,9 +1233,15 @@ int gsi_write_device_scratch(unsigned long dev_hdl, if (val->mhi_base_chan_idx_valid) gsi_ctx->scratch.word0.s.mhi_base_chan_idx = val->mhi_base_chan_idx; - if (val->max_usb_pkt_size_valid) - gsi_ctx->scratch.word0.s.max_usb_pkt_size = - (val->max_usb_pkt_size == 1024) ? 1 : 0; + + if (val->max_usb_pkt_size_valid) { + max_usb_pkt_size = 2; + if (val->max_usb_pkt_size > 64) + max_usb_pkt_size = + (val->max_usb_pkt_size == 1024) ? 1 : 0; + gsi_ctx->scratch.word0.s.max_usb_pkt_size = max_usb_pkt_size; + } + gsi_writel(gsi_ctx->scratch.word0.val, gsi_ctx->base + GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee)); @@ -2203,6 +2212,57 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, } EXPORT_SYMBOL(gsi_alloc_channel); +static int gsi_alloc_ap_channel(unsigned int chan_hdl) +{ + struct gsi_chan_ctx *ctx; + uint32_t val; + int res; + int ee; + enum gsi_ch_cmd_opcode op = GSI_CH_ALLOCATE; + + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return -GSI_STATUS_NODEV; + } + + ctx = &gsi_ctx->chan[chan_hdl]; + if (ctx->allocated) { + GSIERR("chan %d already allocated\n", chan_hdl); + return -GSI_STATUS_NODEV; + } + + memset(ctx, 0, sizeof(*ctx)); + + mutex_init(&ctx->mlock); + init_completion(&ctx->compl); + atomic_set(&ctx->poll_mode, GSI_CHAN_MODE_CALLBACK); + + mutex_lock(&gsi_ctx->mlock); + ee = gsi_ctx->per.ee; + gsi_ctx->ch_dbg[chan_hdl].ch_allocate++; + val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) & + GSI_EE_n_GSI_CH_CMD_CHID_BMSK) | + ((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) & + GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK)); + gsi_writel(val, gsi_ctx->base + + GSI_EE_n_GSI_CH_CMD_OFFS(ee)); + res = wait_for_completion_timeout(&ctx->compl, GSI_CMD_TIMEOUT); + if (res == 0) { + GSIERR("chan_hdl=%u timed out\n", chan_hdl); + mutex_unlock(&gsi_ctx->mlock); + return -GSI_STATUS_TIMED_OUT; + } + if (ctx->state != GSI_CHAN_STATE_ALLOCATED) { + GSIERR("chan_hdl=%u allocation failed state=%d\n", + chan_hdl, ctx->state); + mutex_unlock(&gsi_ctx->mlock); + return -GSI_STATUS_RES_ALLOC_FAILURE; + } + mutex_unlock(&gsi_ctx->mlock); + + return GSI_STATUS_SUCCESS; +} + static void __gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val) { @@ -2221,6 +2281,36 @@ static void __gsi_write_channel_scratch(unsigned long chan_hdl, gsi_ctx->per.ee)); } +int gsi_write_channel_scratch3_reg(unsigned long chan_hdl, + union __packed gsi_wdi_channel_scratch3_reg val) +{ + struct gsi_chan_ctx *ctx; + + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return -GSI_STATUS_NODEV; + } + + if (chan_hdl >= gsi_ctx->max_ch) { + GSIERR("bad params chan_hdl=%lu\n", chan_hdl); + return -GSI_STATUS_INVALID_PARAMS; + } + + ctx = &gsi_ctx->chan[chan_hdl]; + + mutex_lock(&ctx->mlock); + + ctx->scratch.wdi.endp_metadatareg_offset = + val.wdi.endp_metadatareg_offset; + ctx->scratch.wdi.qmap_id = val.wdi.qmap_id; + + gsi_writel(val.data.word1, gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, + gsi_ctx->per.ee)); + mutex_unlock(&ctx->mlock); + return GSI_STATUS_SUCCESS; +} + static void __gsi_read_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch * val) { @@ -3632,6 +3722,9 @@ int gsi_alloc_channel_ee(unsigned int chan_idx, unsigned int ee, int *code) return -GSI_STATUS_INVALID_PARAMS; } + if (ee == 0) + return gsi_alloc_ap_channel(chan_idx); + mutex_lock(&gsi_ctx->mlock); reinit_completion(&gsi_ctx->gen_ee_cmd_compl); diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c index 73369ed2fc639d902647381e51876227d0360d7b..44ed8ffb4fb06d0ce5c098db2e18fefca2f5f131 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c @@ -1493,7 +1493,7 @@ static bool ipa3_usb_check_connect_params( IPA_USB_DBG_LOW("max_supported_bandwidth_mbps = %d\n", params->max_supported_bandwidth_mbps); - if (params->max_pkt_size < IPA_USB_HIGH_SPEED_512B || + if (params->max_pkt_size < IPA_USB_FULL_SPEED_64B || params->max_pkt_size > IPA_USB_SUPER_SPEED_1024B || params->ipa_to_usb_xferrscidx > 127 || (params->teth_prot != IPA_USB_DIAG && diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index b42358d6127ef5a007d3c125748578038dbb4b4a..298c81b884392fda7eba1c64ec404a70afbf8c8a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -431,11 +431,16 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib, uint32_t mask[4]; int i; - if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) - pr_err("tos_value:%d ", attrib->tos_value); + if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) + pr_err("is_pure_ack "); - if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) - pr_err("tos_mask:%d ", attrib->tos_mask); + if (attrib->attrib_mask & IPA_FLT_TOS) + pr_cont("tos:%d ", attrib->u.v4.tos); + + if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) { + pr_cont("tos_value:%d ", attrib->tos_value); + pr_cont("tos_mask:%d ", attrib->tos_mask); + } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) pr_err("protocol:%d ", attrib->u.v4.protocol); @@ -557,8 +562,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) int i; int j; - if (attrib->tos_eq_present) - pr_err("tos_value:%d ", attrib->tos_eq); + if (attrib->tos_eq_present) { + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + pr_err("pure_ack "); + else + pr_err("tos:%d ", attrib->tos_eq); + } if (attrib->protocol_eq_present) pr_err("protocol:%d ", attrib->protocol_eq); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index ee97e9d2a4b12b5bf6ca29c225fe47d6e830c7bb..87ee538232b1c24d81c870c7330f2ed8cc67332c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -30,6 +30,8 @@ #define POLLING_INACTIVITY_TX 40 #define POLLING_MIN_SLEEP_TX 400 #define POLLING_MAX_SLEEP_TX 500 +#define SUSPEND_MIN_SLEEP_RX 1000 +#define SUSPEND_MAX_SLEEP_RX 1005 /* 8K less 1 nominal MTU (1500 bytes) rounded to units of KB */ #define IPA_MTU 1500 #define IPA_GENERIC_AGGR_BYTE_LIMIT 6 @@ -864,11 +866,24 @@ static void ipa_pm_sys_pipe_cb(void *p, enum ipa_pm_cb_event event) * pipe will be unsuspended as part of * enabling IPA clocks */ - ipa_pm_activate(sys->pm_hdl); - ipa_pm_deferred_deactivate(sys->pm_hdl); + IPADBG("calling wakeup for client %d\n", sys->ep->client); + if (sys->ep->client == IPA_CLIENT_APPS_WAN_CONS) { + IPA_ACTIVE_CLIENTS_INC_SPECIAL("PIPE_SUSPEND_WAN"); + usleep_range(SUSPEND_MIN_SLEEP_RX, + SUSPEND_MAX_SLEEP_RX); + IPA_ACTIVE_CLIENTS_DEC_SPECIAL("PIPE_SUSPEND_WAN"); + } else if (sys->ep->client == IPA_CLIENT_APPS_LAN_CONS) { + IPA_ACTIVE_CLIENTS_INC_SPECIAL("PIPE_SUSPEND_LAN"); + usleep_range(SUSPEND_MIN_SLEEP_RX, + SUSPEND_MAX_SLEEP_RX); + IPA_ACTIVE_CLIENTS_DEC_SPECIAL("PIPE_SUSPEND_LAN"); + } else + IPAERR("Unexpected event %d\n for client %d\n", + event, sys->ep->client); break; default: - IPAERR("Unexpected event %d\n", event); + IPAERR("Unexpected event %d\n for client %d\n", + event, sys->ep->client); WARN_ON(1); return; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c index f762a3c984f1899d2c984f79797be9f886be626e..93d328587451d0aefd165d9f13a3fc10db0959c4 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c @@ -50,6 +50,26 @@ static int ipa3_generate_flt_hw_rule(enum ipa_ip_type ip, memset(&gen_params, 0, sizeof(gen_params)); + if (entry->rule.hashable) { + if (entry->rule.attrib.attrib_mask & IPA_FLT_IS_PURE_ACK + && !entry->rule.eq_attrib_type) { + IPAERR_RL("PURE_ACK rule atrb used with hash rule\n"); + WARN_ON_RATELIMIT_IPA(1); + return -EPERM; + } + /* + * tos_eq_present field has two meanings: + * tos equation for IPA ver < 4.5 (as the field name reveals) + * pure_ack equation for IPA ver >= 4.5 + */ + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 && + entry->rule.eq_attrib_type && + entry->rule.eq_attrib.tos_eq_present) { + IPAERR_RL("PURE_ACK rule eq used with hash rule\n"); + return -EPERM; + } + } + gen_params.ipt = ip; if (entry->rt_tbl) gen_params.rt_tbl_idx = entry->rt_tbl->idx; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c index 48a0bb99b5159fcc66aaf548a0d73e6f19d858d9..97fc6af4e6fc9ff9d7804d852b1e84b4cd8d805a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c @@ -183,6 +183,7 @@ struct imp_context { struct imp_dev_info dev_info; struct imp_mhi_driver md; struct mutex mutex; + struct mutex lpm_mutex; enum imp_state state; bool in_lpm; bool lpm_disabled; @@ -709,6 +710,13 @@ static void imp_mhi_shutdown(void) iommu_unmap(cb->mapping->domain, iova_p, size_p); } } + if (!imp_ctx->in_lpm && + (imp_ctx->state == IMP_READY || + imp_ctx->state == IMP_STARTED)) { + IMP_DBG("devote IMP with state= %d\n", imp_ctx->state); + IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IMP"); + } + imp_ctx->in_lpm = false; imp_ctx->state = IMP_PROBED; IMP_FUNC_EXIT(); @@ -843,10 +851,10 @@ static void imp_mhi_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb) { IMP_DBG("%d\n", mhi_cb); - mutex_lock(&imp_ctx->mutex); + mutex_lock(&imp_ctx->lpm_mutex); if (mhi_dev != imp_ctx->md.mhi_dev) { IMP_DBG("ignoring secondary callbacks\n"); - mutex_unlock(&imp_ctx->mutex); + mutex_unlock(&imp_ctx->lpm_mutex); return; } @@ -879,7 +887,7 @@ static void imp_mhi_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb) IMP_ERR("unexpected event %d\n", mhi_cb); break; } - mutex_unlock(&imp_ctx->mutex); + mutex_unlock(&imp_ctx->lpm_mutex); } static int imp_probe(struct platform_device *pdev) @@ -943,12 +951,14 @@ static int imp_remove(struct platform_device *pdev) IMP_DBG("devote IMP with state= %d\n", imp_ctx->state); IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IMP"); } - imp_ctx->in_lpm = false; imp_ctx->lpm_disabled = false; - imp_ctx->state = IMP_INVALID; mutex_unlock(&imp_ctx->mutex); + mutex_lock(&imp_ctx->lpm_mutex); + imp_ctx->in_lpm = false; + mutex_unlock(&imp_ctx->lpm_mutex); + return 0; } @@ -986,6 +996,7 @@ void imp_handle_modem_ready(void) return; mutex_init(&imp_ctx->mutex); + mutex_init(&imp_ctx->lpm_mutex); } if (imp_ctx->state != IMP_INVALID) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h index 47a03f93824363fe72cf8a49331246d9de53c29a..1bef83cfc4d5bfcfaf80fdcec4c4192c48be61c6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h @@ -20,7 +20,7 @@ #define IPA_PM_MAX_EX_CL 64 #define IPA_PM_THRESHOLD_MAX 5 #define IPA_PM_EXCEPTION_MAX 2 -#define IPA_PM_DEFERRED_TIMEOUT 100 +#define IPA_PM_DEFERRED_TIMEOUT 10 #define IPA_PM_STATE_MAX 7 /* diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 6191811c4ff9b90d94369502bbd89e972440af96..dccf660a1e4f27894d65653d5aa6a3e857065303 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -58,6 +58,13 @@ static int ipa_generate_rt_hw_rule(enum ipa_ip_type ip, memset(&gen_params, 0, sizeof(gen_params)); + if (entry->rule.hashable && + entry->rule.attrib.attrib_mask & IPA_FLT_IS_PURE_ACK) { + IPAERR_RL("PURE_ACK rule atrb used with hash rule\n"); + WARN_ON_RATELIMIT_IPA(1); + return -EPERM; + } + gen_params.ipt = ip; gen_params.dst_pipe_idx = ipa3_get_ep_mapping(entry->rule.dst); if (gen_params.dst_pipe_idx == -1) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 5178354cf1e9f1bce03ee321bba4de4ee6b75cb2..fe4fc5cad0e3f48f9f31f506b82a123ef3d5e294 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -1857,12 +1857,8 @@ int ipa3_disconnect_gsi_wdi_pipe(u32 clnt_hdl) if (!ep->keep_ipa_awake) IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); - result = gsi_reset_evt_ring(ep->gsi_evt_ring_hdl); - if (result != GSI_STATUS_SUCCESS) { - IPAERR("Failed to reset evt ring: %d.\n", - result); - goto fail_dealloc_channel; - } + ipa3_reset_gsi_channel(clnt_hdl); + ipa3_reset_gsi_event_ring(clnt_hdl); if (!ep->keep_ipa_awake) IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); @@ -2223,6 +2219,8 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl) int result = 0; struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; + struct gsi_chan_info chan_info; + union __packed gsi_channel_scratch gsi_scratch; IPADBG("ep=%d\n", clnt_hdl); ep = &ipa3_ctx->ep[clnt_hdl]; @@ -2246,6 +2244,19 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl) IPAERR("gsi_start_channel failed %d\n", result); ipa_assert(); } + gsi_query_channel_info(ep->gsi_chan_hdl, &chan_info); + gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); + IPADBG("ch=%lu channel base = 0x%llx , event base 0x%llx\n", + ep->gsi_chan_hdl, + ep->gsi_mem_info.chan_ring_base_addr, + ep->gsi_mem_info.evt_ring_base_addr); + IPADBG("RP=0x%llx WP=0x%llx ev_valid=%d ERP=0x%llx EWP=0x%llx\n", + chan_info.rp, chan_info.wp, chan_info.evt_valid, + chan_info.evt_rp, chan_info.evt_wp); + IPADBG("Scratch 0 = %x Scratch 1 = %x Scratch 2 = %x Scratch 3 = %x\n", + gsi_scratch.data.word1, gsi_scratch.data.word2, + gsi_scratch.data.word3, gsi_scratch.data.word4); + ep->gsi_offload_state |= IPA_WDI_RESUMED; IPADBG("exit\n"); return result; @@ -2324,6 +2335,8 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl) bool disable_force_clear = false; struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 }; int retry_cnt = 0; + struct gsi_chan_info chan_info; + union __packed gsi_channel_scratch gsi_scratch; ipa_ep_idx = ipa3_get_ep_mapping(ipa3_get_client_mapping(clnt_hdl)); if (ipa_ep_idx < 0) { @@ -2373,14 +2386,22 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl) } else { IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl); } - - res = ipa3_reset_gsi_channel(clnt_hdl); - if (res != GSI_STATUS_SUCCESS) { - IPAERR("Failed to reset chan: %d.\n", res); - goto fail_stop_channel; - } - + gsi_query_channel_info(ep->gsi_chan_hdl, &chan_info); + gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); + IPADBG("ch=%lu channel base = 0x%llx , event base 0x%llx\n", + ep->gsi_chan_hdl, + ep->gsi_mem_info.chan_ring_base_addr, + ep->gsi_mem_info.evt_ring_base_addr); + IPADBG("RP=0x%llx WP=0x%llx ev_valid=%d ERP=0x%llx", + chan_info.rp, chan_info.wp, + chan_info.evt_valid, chan_info.evt_rp); + IPADBG("EWP=0x%llx\n", chan_info.evt_wp); + IPADBG("Scratch 0 = %x Scratch 1 = %x Scratch 2 = %x", + gsi_scratch.data.word1, gsi_scratch.data.word2, + gsi_scratch.data.word3); + IPADBG("Scratch 3 = %x\n", gsi_scratch.data.word4); } + if (disable_force_clear) ipa3_disable_force_clear(clnt_hdl); IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); @@ -2539,87 +2560,27 @@ int ipa3_write_qmapid_gsi_wdi_pipe(u32 clnt_hdl, u8 qmap_id) { int result = 0; struct ipa3_ep_context *ep; - union __packed gsi_channel_scratch gsi_scratch; - int retry_cnt = 0; - u32 source_pipe_bitmask = 0; - bool disable_force_clear = false; - struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 }; + union __packed gsi_wdi_channel_scratch3_reg gsi_scratch; memset(&gsi_scratch, 0, sizeof(gsi_scratch)); ep = &ipa3_ctx->ep[clnt_hdl]; IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); - result = gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); - if (result != GSI_STATUS_SUCCESS) { - IPAERR("gsi_read_write_channel_scratch failed %d\n", - result); - goto fail_read_channel_scratch; - } - if (ep->gsi_offload_state == (IPA_WDI_CONNECTED | IPA_WDI_ENABLED | - IPA_WDI_RESUMED)) { - source_pipe_bitmask = 1 << - ipa3_get_ep_mapping(ep->client); - result = ipa3_enable_force_clear(clnt_hdl, - false, source_pipe_bitmask); - if (result) { - /* - * assuming here modem SSR, AP can remove - * the delay in this case - */ - IPAERR("failed to force clear %d\n", result); - IPAERR("remove delay from SCND reg\n"); - ep_ctrl_scnd.endp_delay = false; - ipahal_write_reg_n_fields( - IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl, - &ep_ctrl_scnd); - } else { - disable_force_clear = true; - } - -retry_gsi_stop: - result = ipa3_stop_gsi_channel(clnt_hdl); - if (result != 0 && result != -GSI_STATUS_AGAIN && - result != -GSI_STATUS_TIMED_OUT) { - IPAERR("GSI stop channel failed %d\n", - result); - goto fail_stop_channel; - } else if (result == -GSI_STATUS_AGAIN) { - IPADBG("GSI stop channel failed retry cnt = %d\n", - retry_cnt); - retry_cnt++; - if (retry_cnt >= GSI_STOP_MAX_RETRY_CNT) - goto fail_stop_channel; - goto retry_gsi_stop; - } else { - IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl); - } - } gsi_scratch.wdi.qmap_id = qmap_id; - result = gsi_write_channel_scratch(ep->gsi_chan_hdl, - gsi_scratch); + gsi_scratch.wdi.endp_metadatareg_offset = ipahal_get_reg_mn_ofst( + IPA_ENDP_INIT_HDR_METADATA_n, 0, clnt_hdl)/4; + + result = gsi_write_channel_scratch3_reg(ep->gsi_chan_hdl, gsi_scratch); if (result != GSI_STATUS_SUCCESS) { IPAERR("gsi_write_channel_scratch failed %d\n", result); goto fail_write_channel_scratch; } - if (ep->gsi_offload_state == (IPA_WDI_CONNECTED | IPA_WDI_ENABLED | - IPA_WDI_RESUMED)) { - result = gsi_start_channel(ep->gsi_chan_hdl); - if (result != GSI_STATUS_SUCCESS) { - IPAERR("gsi_start_channel failed %d\n", result); - goto fail_start_channel; - } - } - - if (disable_force_clear) - ipa3_disable_force_clear(clnt_hdl); + IPADBG("client (ep: %d) qmap_id %d updated\n", clnt_hdl, qmap_id); IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); return 0; -fail_start_channel: -fail_read_channel_scratch: fail_write_channel_scratch: -fail_stop_channel: ipa_assert(); return result; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 62c8fd06d668ef09eaada5338f538dcc85d3b96e..3b303b2b69ad1802a355ec2ea123767bc0ccc139 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -174,7 +174,8 @@ #define IPA_v4_2_DST_GROUP_MAX (1) #define IPA_v4_5_MHI_GROUP_PCIE (0) -#define IPA_v4_5_GROUP_UL_DL (1) +#define IPA_v4_5_GROUP_UL_DL_DST (0) +#define IPA_v4_5_GROUP_UL_DL_SRC (1) #define IPA_v4_5_MHI_GROUP_DDR (1) #define IPA_v4_5_MHI_GROUP_DMA (2) #define IPA_v4_5_MHI_GROUP_QDSS (3) @@ -261,7 +262,7 @@ enum ipa_ver { static const struct rsrc_min_max ipa3_rsrc_src_grp_config [IPA_VER_MAX][IPA_RSRC_GRP_TYPE_SRC_MAX][IPA_GROUP_MAX] = { [IPA_3_0] = { - /*UL DL DIAG DMA Not Used uC Rx*/ + /* UL DL DIAG DMA Not Used uC Rx */ [IPA_v3_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {3, 255}, {3, 255}, {1, 255}, {1, 255}, {1, 255}, {2, 255} }, [IPA_v3_0_RSRC_GRP_TYPE_SRC_HDR_SECTORS] = { @@ -280,7 +281,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {14, 14}, {16, 16}, {5, 5}, {5, 5}, {0, 0}, {8, 8} }, }, [IPA_3_5] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q, other are invalid */ [IPA_v3_5_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {0, 0}, {1, 255}, {0, 0}, {1, 255}, {0, 0}, {0, 0} }, [IPA_v3_5_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -293,7 +294,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {0, 0}, {20, 20}, {0, 0}, {14, 14}, {0, 0}, {0, 0} }, }, [IPA_3_5_MHI] = { - /* PCIE DDR DMA not used, other are invalid */ + /* PCIE DDR DMA unused, other are invalid */ [IPA_v3_5_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {4, 4}, {5, 5}, {1, 1}, {0, 0}, {0, 0}, {0, 0} }, [IPA_v3_5_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -306,7 +307,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {14, 14}, {14, 14}, {14, 14}, {0, 0}, {0, 0}, {0, 0} }, }, [IPA_3_5_1] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q, other are invalid */ [IPA_v3_5_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {1, 255}, {1, 255}, {0, 0}, {1, 255}, {0, 0}, {0, 0} }, [IPA_v3_5_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -319,7 +320,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {14, 14}, {20, 20}, {0, 0}, {14, 14}, {0, 0}, {0, 0} }, }, [IPA_4_0] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q, other are invalid */ [IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {1, 255}, {1, 255}, {0, 0}, {1, 255}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -332,7 +333,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {14, 14}, {20, 20}, {0, 0}, {14, 14}, {0, 0}, {0, 0} }, }, [IPA_4_0_MHI] = { - /* PCIE DDR DMA not used, other are invalid */ + /* PCIE DDR DMA unused, other are invalid */ [IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {4, 4}, {5, 5}, {1, 1}, {0, 0}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -345,7 +346,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {14, 14}, {14, 14}, {14, 14}, {0, 0}, {0, 0}, {0, 0} }, }, [IPA_4_1] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q, other are invalid */ [IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {1, 63}, {1, 63}, {0, 0}, {1, 63}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -371,9 +372,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {5, 5}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, }, [IPA_4_5] = { - /* not used UL_DL not used not used UC_RX_Q - * other are invalid - */ + /* unused UL_DL_SRC unused unused UC_RX_Q N/A */ [IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {0, 0}, {1, 63}, {0, 0}, {0, 0}, {1, 63}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -386,7 +385,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config {0, 0}, {24, 24}, {0, 0}, {0, 0}, {8, 8}, {0, 0} }, }, [IPA_4_5_MHI] = { - /* PCIE DDR DMA QDSS not used other are invalid */ + /* PCIE DDR DMA QDSS unused N/A N/A */ [IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { {3, 8}, {4, 11}, {1, 1}, {1, 1}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { @@ -433,42 +432,42 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config {2, 255}, {1, 255}, {1, 2}, {0, 0}, {0, 0}, {0, 0} }, }, [IPA_4_0] = { - /*LWA_DL UL/DL/DPL uC, other are invalid */ + /* LWA_DL UL/DL/DPL uC, other are invalid */ [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { {4, 4}, {4, 4}, {3, 3}, {2, 2}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { {2, 255}, {1, 255}, {1, 2}, {0, 2}, {0, 0}, {0, 0} }, }, [IPA_4_0_MHI] = { - /*LWA_DL UL/DL/DPL uC, other are invalid */ + /* LWA_DL UL/DL/DPL uC, other are invalid */ [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { {4, 4}, {4, 4}, {3, 3}, {2, 2}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { {2, 255}, {1, 255}, {1, 2}, {0, 2}, {0, 0}, {0, 0} }, }, [IPA_4_1] = { - /*LWA_DL UL/DL/DPL uC, other are invalid */ + /* LWA_DL UL/DL/DPL uC, other are invalid */ [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { {4, 4}, {4, 4}, {3, 3}, {2, 2}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { {2, 63}, {1, 63}, {1, 2}, {0, 2}, {0, 0}, {0, 0} }, }, [IPA_4_2] = { - /*UL/DL/DPL, other are invalid */ + /* UL/DL/DPL, other are invalid */ [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { {3, 3}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { {1, 63}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, }, [IPA_4_5] = { - /* not-used UL/DL/DPL not-used not-used uC other are invalid */ + /* UL/DL/DPL_DST unused unused unused uC N/A */ [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { - {0, 0}, {5, 5}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, + {16, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { - {0, 0}, {1, 63}, {0, 0}, {0, 0}, {0, 2}, {0, 0} }, + {2, 63}, {0, 0}, {0, 0}, {0, 0}, {0, 2}, {0, 0} }, }, [IPA_4_5_MHI] = { - /* PCIE/DPL DDR DMA/CV2X QDSS uC other are invalid */ + /* PCIE/DPL DDR DMA/CV2X QDSS uC N/A */ [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { {16, 16}, {5, 5}, {2, 2}, {2, 2}, {0, 0}, {0, 0} }, [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { @@ -479,7 +478,7 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config static const struct rsrc_min_max ipa3_rsrc_rx_grp_config [IPA_VER_MAX][IPA_RSRC_GRP_TYPE_RX_MAX][IPA_GROUP_MAX] = { [IPA_3_0] = { - /* UL DL DIAG DMA Unused uC Rx */ + /* UL DL DIAG DMA unused uC Rx */ [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { {16, 16}, {24, 24}, {8, 8}, {8, 8}, {0, 0}, {8, 8} }, }, @@ -499,7 +498,7 @@ static const struct rsrc_min_max ipa3_rsrc_rx_grp_config {3, 3}, {7, 7}, {0, 0}, {2, 2}, {0, 0}, {0, 0} }, }, [IPA_4_0] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q, other are invalid */ [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { {3, 3}, {7, 7}, {0, 0}, {2, 2}, {0, 0}, {0, 0} }, }, @@ -509,7 +508,7 @@ static const struct rsrc_min_max ipa3_rsrc_rx_grp_config { 3, 3 }, { 7, 7 }, { 2, 2 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, }, [IPA_4_1] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q, other are invalid */ [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { {3, 3}, {7, 7}, {0, 0}, {2, 2}, {0, 0}, {0, 0} }, }, @@ -519,14 +518,12 @@ static const struct rsrc_min_max ipa3_rsrc_rx_grp_config {4, 4}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, }, [IPA_4_5] = { - /* not used UL_DL not used not used UC_RX_Q - * other are invalid - */ + /* unused UL_DL unused unused UC_RX_Q N/A */ [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { {0, 0}, {3, 3}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, }, [IPA_4_5_MHI] = { - /* PCIE DDR DMA QDSS not used other are invalid */ + /* PCIE DDR DMA QDSS unused N/A */ [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { { 3, 3 }, {3, 3}, {3, 3}, {3, 3}, {0, 0}, { 0, 0 } }, }, @@ -536,7 +533,7 @@ static const struct rsrc_min_max ipa3_rsrc_rx_grp_config static const u32 ipa3_rsrc_rx_grp_hps_weight_config [IPA_VER_MAX][IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_MAX][IPA_GROUP_MAX] = { [IPA_3_0] = { - /* UL DL DIAG DMA Unused uC Rx */ + /* UL DL DIAG DMA unused uC Rx */ [IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_CONFIG] = { 0, 0, 0, 0, 0, 0 }, }, [IPA_3_5] = { @@ -552,7 +549,7 @@ static const u32 ipa3_rsrc_rx_grp_hps_weight_config [IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_CONFIG] = { 1, 1, 1, 1, 0, 0 }, }, [IPA_4_0] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q N/A */ [IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_CONFIG] = { 1, 1, 1, 1, 0, 0 }, }, [IPA_4_0_MHI] = { @@ -560,7 +557,7 @@ static const u32 ipa3_rsrc_rx_grp_hps_weight_config [IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_CONFIG] = { 3, 5, 1, 1, 0, 0 }, }, [IPA_4_1] = { - /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ + /* LWA_DL UL_DL unused UC_RX_Q, other are invalid */ [IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_CONFIG] = { 1, 1, 1, 1, 0, 0 }, }, }; @@ -2043,165 +2040,165 @@ static const struct ipa_ep_configuration ipa3_ep_mapping /* IPA_4_5 */ [IPA_4_5][IPA_CLIENT_WLAN1_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, QMB_MASTER_SELECT_DDR, { 9, 12, 8, 16, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } }, [IPA_4_5][IPA_CLIENT_USB_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, QMB_MASTER_SELECT_DDR, { 0, 11, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_APPS_LAN_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, false, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 11, 14, 10, 16, IPA_EE_AP, GSI_SMART_PRE_FETCH, 2 } }, [IPA_4_5][IPA_CLIENT_APPS_WAN_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, QMB_MASTER_SELECT_DDR, { 2, 7, 16, 32, IPA_EE_AP, GSI_SMART_PRE_FETCH, 8 } }, [IPA_4_5][IPA_CLIENT_APPS_CMD_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, false, IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY, QMB_MASTER_SELECT_DDR, { 7, 9, 20, 24, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_ODU_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, QMB_MASTER_SELECT_DDR, { 1, 0, 16, 20, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } }, [IPA_4_5][IPA_CLIENT_ETHERNET_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, QMB_MASTER_SELECT_DDR, { 12, 0, 8, 16, IPA_EE_UC, GSI_SMART_PRE_FETCH, 4 } }, [IPA_4_5][IPA_CLIENT_Q6_WAN_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_DEC_UCP, QMB_MASTER_SELECT_DDR, { 5, 0, 16, 28, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 8 } }, [IPA_4_5][IPA_CLIENT_Q6_CMD_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, false, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 6, 1, 20, 24, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 8 } }, [IPA_4_5][IPA_CLIENT_Q6_DL_NLO_DATA_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_DEC_UCP, QMB_MASTER_SELECT_DDR, { 8, 2, 27, 32, IPA_EE_Q6, GSI_FREE_PRE_FETCH, 3 } }, /* Only for test purpose */ [IPA_4_5][IPA_CLIENT_TEST_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 0, 11, 8, 16, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST1_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 0, 11, 8, 16, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST2_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 1, 0, 8, 16, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST3_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 9, 12, 8, 16, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST4_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 11, 14, 8, 16, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_WLAN1_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 24, 3, 8, 14, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } }, [IPA_4_5][IPA_CLIENT_USB_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 25, 16, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_USB_DPL_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 15, 15, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_APPS_LAN_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 16, 10, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_APPS_WAN_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 14, 1, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_ODU_EMB_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 23, 8, 9, 9, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } }, [IPA_4_5][IPA_CLIENT_ETHERNET_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 28, 1, 9, 9, IPA_EE_UC } }, [IPA_4_5][IPA_CLIENT_Q6_LAN_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 17, 3, 9, 9, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_Q6_WAN_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 21, 7, 9, 9, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5][IPA_CLIENT_Q6_UL_NLO_DATA_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 19, 5, 5, 5, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 2 } }, [IPA_4_5][IPA_CLIENT_Q6_UL_NLO_ACK_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 20, 6, 5, 5, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 2 } }, [IPA_4_5][IPA_CLIENT_Q6_QBAP_STATUS_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, @@ -2209,38 +2206,38 @@ static const struct ipa_ep_configuration ipa3_ep_mapping /* Only for test purpose */ /* MBIM aggregation test pipes should have the same QMB as USB_CONS */ [IPA_4_5][IPA_CLIENT_TEST_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 14, 1, 9, 9, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST1_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 14, 1, 9, 9, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST2_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 24, 3, 8, 14, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST3_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 25, 16, 9, 9, IPA_EE_AP } }, [IPA_4_5][IPA_CLIENT_TEST4_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 27, 18, 9, 9, IPA_EE_AP } }, /* Dummy consumer (pipe 31) is used in L2TP rt rule */ [IPA_4_5][IPA_CLIENT_DUMMY_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, @@ -2297,7 +2294,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping { 10, 13, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, /* Only for test purpose */ [IPA_4_5_MHI][IPA_CLIENT_TEST_PROD] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_SRC, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, @@ -2372,7 +2369,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping /* Dummy consumer (pipe 31) is used in L2TP rt rule */ [IPA_4_5_MHI][IPA_CLIENT_DUMMY_CONS] = { - true, IPA_v4_5_GROUP_UL_DL, + true, IPA_v4_5_GROUP_UL_DL_DST, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, @@ -2517,7 +2514,7 @@ static struct ipa3_mem_partition ipa_4_2_mem_part = { .modem_comp_decomp_ofst = 0x0, .modem_comp_decomp_size = 0x0, .modem_ofst = 0xbf0, - .modem_size = 0x100c, + .modem_size = 0x140c, .apps_v4_flt_hash_ofst = 0x1bfc, .apps_v4_flt_hash_size = 0x0, .apps_v4_flt_nhash_ofst = 0x1bfc, @@ -2537,8 +2534,8 @@ static struct ipa3_mem_partition ipa_4_2_mem_part = { .apps_v6_rt_hash_size = 0x0, .apps_v6_rt_nhash_ofst = 0x1bfc, .apps_v6_rt_nhash_size = 0x0, - .uc_descriptor_ram_ofst = 0x1c00, - .uc_descriptor_ram_size = 0x400, + .uc_descriptor_ram_ofst = 0x2000, + .uc_descriptor_ram_size = 0x0, .pdn_config_ofst = 0x9F8, .pdn_config_size = 0x50, .stats_quota_ofst = 0xa50, @@ -6366,7 +6363,7 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index, if (src) { switch (group_index) { case IPA_v4_5_MHI_GROUP_PCIE: - case IPA_v4_5_GROUP_UL_DL: + case IPA_v4_5_GROUP_UL_DL_SRC: ipahal_write_reg_n_fields( IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n, n, val); @@ -6390,8 +6387,8 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index, } } else { switch (group_index) { - case IPA_v4_5_MHI_GROUP_PCIE: - case IPA_v4_5_GROUP_UL_DL: + case IPA_v4_5_GROUP_UL_DL_DST: + case IPA_v4_5_MHI_GROUP_DDR: ipahal_write_reg_n_fields( IPA_DST_RSRC_GRP_01_RSRC_TYPE_n, n, val); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c index 4237e1f7a726aacba80a1b0d43a668c9fe4a7676..db4eb65cada20149080d9d8b8e1b35ffce2a8bc2 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c @@ -44,7 +44,8 @@ * @flt_generate_eq: Generate flt equation attributes from rule attributes * @rt_parse_hw_rule: Parse rt rule read from H/W * @flt_parse_hw_rule: Parse flt rule read from H/W - * @eq_bitfield: Array of the bit fields of the support equations + * @eq_bitfield: Array of the bit fields of the support equations. + * 0xFF means the equation is not supported */ struct ipahal_fltrt_obj { bool support_hash; @@ -172,6 +173,9 @@ static int ipa_flt_parse_hw_rule_ipav4(u8 *addr, #define IPA_GET_RULE_EQ_BIT_PTRN(__eq) \ (BIT(ipahal_fltrt_objs[ipahal_ctx->hw_type].eq_bitfield[(__eq)])) +#define IPA_IS_RULE_EQ_VALID(__eq) \ + (ipahal_fltrt_objs[ipahal_ctx->hw_type].eq_bitfield[(__eq)] != 0xFF) + /* * ipa_fltrt_rule_generation_err_check() - check basic validity on the rule * attribs before starting building it @@ -489,6 +493,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, + [IPA_IS_PURE_ACK] = 0xFF, }, }, @@ -517,22 +522,23 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { ipa_rt_parse_hw_rule, ipa_flt_parse_hw_rule_ipav4, { - [IPA_TOS_EQ] = 0, - [IPA_PROTOCOL_EQ] = 1, - [IPA_TC_EQ] = 2, - [IPA_OFFSET_MEQ128_0] = 3, - [IPA_OFFSET_MEQ128_1] = 4, - [IPA_OFFSET_MEQ32_0] = 5, - [IPA_OFFSET_MEQ32_1] = 6, - [IPA_IHL_OFFSET_MEQ32_0] = 7, - [IPA_IHL_OFFSET_MEQ32_1] = 8, - [IPA_METADATA_COMPARE] = 9, - [IPA_IHL_OFFSET_RANGE16_0] = 10, - [IPA_IHL_OFFSET_RANGE16_1] = 11, - [IPA_IHL_OFFSET_EQ_32] = 12, - [IPA_IHL_OFFSET_EQ_16] = 13, - [IPA_FL_EQ] = 14, - [IPA_IS_FRAG] = 15, + [IPA_TOS_EQ] = 0, + [IPA_PROTOCOL_EQ] = 1, + [IPA_TC_EQ] = 2, + [IPA_OFFSET_MEQ128_0] = 3, + [IPA_OFFSET_MEQ128_1] = 4, + [IPA_OFFSET_MEQ32_0] = 5, + [IPA_OFFSET_MEQ32_1] = 6, + [IPA_IHL_OFFSET_MEQ32_0] = 7, + [IPA_IHL_OFFSET_MEQ32_1] = 8, + [IPA_METADATA_COMPARE] = 9, + [IPA_IHL_OFFSET_RANGE16_0] = 10, + [IPA_IHL_OFFSET_RANGE16_1] = 11, + [IPA_IHL_OFFSET_EQ_32] = 12, + [IPA_IHL_OFFSET_EQ_16] = 13, + [IPA_FL_EQ] = 14, + [IPA_IS_FRAG] = 15, + [IPA_IS_PURE_ACK] = 0xFF, }, }, @@ -561,22 +567,23 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { ipa_rt_parse_hw_rule, ipa_flt_parse_hw_rule_ipav4, { - [IPA_TOS_EQ] = 0, - [IPA_PROTOCOL_EQ] = 1, - [IPA_TC_EQ] = 2, - [IPA_OFFSET_MEQ128_0] = 3, - [IPA_OFFSET_MEQ128_1] = 4, - [IPA_OFFSET_MEQ32_0] = 5, - [IPA_OFFSET_MEQ32_1] = 6, - [IPA_IHL_OFFSET_MEQ32_0] = 7, - [IPA_IHL_OFFSET_MEQ32_1] = 8, - [IPA_METADATA_COMPARE] = 9, - [IPA_IHL_OFFSET_RANGE16_0] = 10, - [IPA_IHL_OFFSET_RANGE16_1] = 11, - [IPA_IHL_OFFSET_EQ_32] = 12, - [IPA_IHL_OFFSET_EQ_16] = 13, - [IPA_FL_EQ] = 14, - [IPA_IS_FRAG] = 15, + [IPA_TOS_EQ] = 0, + [IPA_PROTOCOL_EQ] = 1, + [IPA_TC_EQ] = 2, + [IPA_OFFSET_MEQ128_0] = 3, + [IPA_OFFSET_MEQ128_1] = 4, + [IPA_OFFSET_MEQ32_0] = 5, + [IPA_OFFSET_MEQ32_1] = 6, + [IPA_IHL_OFFSET_MEQ32_0] = 7, + [IPA_IHL_OFFSET_MEQ32_1] = 8, + [IPA_METADATA_COMPARE] = 9, + [IPA_IHL_OFFSET_RANGE16_0] = 10, + [IPA_IHL_OFFSET_RANGE16_1] = 11, + [IPA_IHL_OFFSET_EQ_32] = 12, + [IPA_IHL_OFFSET_EQ_16] = 13, + [IPA_FL_EQ] = 14, + [IPA_IS_FRAG] = 15, + [IPA_IS_PURE_ACK] = 0xFF, }, }, @@ -605,22 +612,23 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { ipa_rt_parse_hw_rule, ipa_flt_parse_hw_rule_ipav4, { - [IPA_TOS_EQ] = 0, - [IPA_PROTOCOL_EQ] = 1, - [IPA_TC_EQ] = 2, - [IPA_OFFSET_MEQ128_0] = 3, - [IPA_OFFSET_MEQ128_1] = 4, - [IPA_OFFSET_MEQ32_0] = 5, - [IPA_OFFSET_MEQ32_1] = 6, - [IPA_IHL_OFFSET_MEQ32_0] = 7, - [IPA_IHL_OFFSET_MEQ32_1] = 8, - [IPA_METADATA_COMPARE] = 9, - [IPA_IHL_OFFSET_RANGE16_0] = 10, - [IPA_IHL_OFFSET_RANGE16_1] = 11, - [IPA_IHL_OFFSET_EQ_32] = 12, - [IPA_IHL_OFFSET_EQ_16] = 13, - [IPA_FL_EQ] = 14, - [IPA_IS_FRAG] = 15, + [IPA_TOS_EQ] = 0xFF, + [IPA_PROTOCOL_EQ] = 1, + [IPA_TC_EQ] = 2, + [IPA_OFFSET_MEQ128_0] = 3, + [IPA_OFFSET_MEQ128_1] = 4, + [IPA_OFFSET_MEQ32_0] = 5, + [IPA_OFFSET_MEQ32_1] = 6, + [IPA_IHL_OFFSET_MEQ32_0] = 7, + [IPA_IHL_OFFSET_MEQ32_1] = 8, + [IPA_METADATA_COMPARE] = 9, + [IPA_IHL_OFFSET_RANGE16_0] = 10, + [IPA_IHL_OFFSET_RANGE16_1] = 11, + [IPA_IHL_OFFSET_EQ_32] = 12, + [IPA_IHL_OFFSET_EQ_16] = 13, + [IPA_FL_EQ] = 14, + [IPA_IS_FRAG] = 15, + [IPA_IS_PURE_ACK] = 0, }, }, }; @@ -696,10 +704,25 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, u8 ihl_ofst_meq32 = 0; u8 ofst_meq128 = 0; int rc = 0; + bool tos_done = false; + + if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { + if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { + IPAHAL_ERR("is_pure_ack eq not supported\n"); + goto err; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); + extra = ipa_write_8(0, extra); + } - if (attrib->attrib_mask & IPA_FLT_TOS) { - *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); - extra = ipa_write_8(attrib->u.v4.tos, extra); + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + if (!IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { + IPAHAL_DBG("tos eq not supported\n"); + } else { + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); + extra = ipa_write_8(attrib->u.v4.tos, extra); + tos_done = true; + } } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) { @@ -790,7 +813,7 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ofst_meq32[ofst_meq32]); - /* 0 => offset of TOS in v4 header */ + /* 0 => Take the first word. offset of TOS in v4 header is 1 */ extra = ipa_write_8(0, extra); rest = ipa_write_32((attrib->tos_mask << 16), rest); rest = ipa_write_32((attrib->tos_value << 16), rest); @@ -841,6 +864,24 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, ofst_meq32++; } + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { + IPAHAL_DBG("ran out of meq32 eq\n"); + } else { + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ofst_meq32[ofst_meq32]); + /* + * 0 => Take the first word. + * offset of TOS in v4 header is 1 + */ + extra = ipa_write_8(0, extra); + rest = ipa_write_32(0xFF << 16, rest); + rest = ipa_write_32((attrib->u.v4.tos << 16), rest); + ofst_meq32++; + tos_done = true; + } + } + if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { @@ -933,6 +974,26 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, ihl_ofst_meq32++; } + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32)) { + IPAHAL_DBG("ran out of ihl_meq32 eq\n"); + } else { + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + /* + * 0 => Take the first word. offset of TOS in + * v4 header is 1. MSB bit asserted at IHL means + * to ignore packet IHL and do offset inside IPA header + */ + extra = ipa_write_8(0x80, extra); + rest = ipa_write_32(0xFF << 16, rest); + rest = ipa_write_32((attrib->u.v4.tos << 16), rest); + ihl_ofst_meq32++; + tos_done = true; + } + } + if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_METADATA_COMPARE); rest = ipa_write_32(attrib->meta_data_mask, rest); @@ -1010,6 +1071,11 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, if (attrib->attrib_mask & IPA_FLT_FRAGMENT) *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_FRAG); + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + IPAHAL_ERR("could not find equation for tos\n"); + goto err; + } + goto done; err: @@ -1033,6 +1099,14 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip6(u16 *en_rule, int rc = 0; /* v6 code below assumes no extension headers TODO: fix this */ + if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { + if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { + IPAHAL_ERR("is_pure_ack eq not supported\n"); + goto err; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); + extra = ipa_write_8(0, extra); + } if (attrib->attrib_mask & IPA_FLT_NEXT_HDR) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ); @@ -1597,6 +1671,12 @@ static int ipa_fltrt_calc_extra_wrd_bytes( { int num = 0; + /* + * tos_eq_present field has two meanings: + * tos equation for IPA ver < 4.5 (as the field name reveals) + * pure_ack equation for IPA ver >= 4.5 + * In both cases it needs one extra word. + */ if (attrib->tos_eq_present) num++; if (attrib->protocol_eq_present) @@ -1650,8 +1730,22 @@ static int ipa_fltrt_generate_hw_rule_bdy_from_eq( rest = *buf; } - if (attrib->tos_eq_present) - extra = ipa_write_8(attrib->tos_eq, extra); + /* + * tos_eq_present field has two meanings: + * tos equation for IPA ver < 4.5 (as the field name reveals) + * pure_ack equation for IPA ver >= 4.5 + * In both cases it needs one extra word. + */ + if (attrib->tos_eq_present) { + if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { + extra = ipa_write_8(0, extra); + } else if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { + extra = ipa_write_8(attrib->tos_eq, extra); + } else { + IPAHAL_ERR("no support for pure_ack and tos eqs\n"); + return -EPERM; + } + } if (attrib->protocol_eq_present) extra = ipa_write_8(attrib->protocol_eq, extra); @@ -1807,11 +1901,31 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, u8 ofst_meq128 = 0; u16 eq_bitmap = 0; u16 *en_rule = &eq_bitmap; + bool tos_done = false; - if (attrib->attrib_mask & IPA_FLT_TOS) { - *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); + if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { + if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { + IPAHAL_ERR("is_pure_ack eq not supported\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); + /* + * Starting IPA 4.5, where PURE ACK equation supported + * and TOS equation support removed, field tos_eq_present + * represent pure_ack presence. + */ eq_atrb->tos_eq_present = 1; - eq_atrb->tos_eq = attrib->u.v4.tos; + eq_atrb->tos_eq = 0; + } + + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + if (!IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { + IPAHAL_DBG("tos eq not supported\n"); + } else { + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); + eq_atrb->tos_eq_present = 1; + eq_atrb->tos_eq = attrib->u.v4.tos; + } } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) { @@ -1993,6 +2107,26 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, ofst_meq32++; } + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { + IPAHAL_DBG("ran out of meq32 eq\n"); + } else { + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ofst_meq32[ofst_meq32]); + /* + * offset 0 => Take the first word. + * offset of TOS in v4 header is 1 + */ + eq_atrb->offset_meq_32[ofst_meq32].offset = 0; + eq_atrb->offset_meq_32[ofst_meq32].mask = + 0xFF << 16; + eq_atrb->offset_meq_32[ofst_meq32].value = + attrib->u.v4.tos << 16; + ofst_meq32++; + tos_done = true; + } + } + if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { @@ -2039,6 +2173,29 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, ihl_ofst_meq32++; } + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, + ihl_ofst_meq32)) { + IPAHAL_DBG("ran out of ihl_meq32 eq\n"); + } else { + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( + ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); + /* + * 0 => Take the first word. offset of TOS in + * v4 header is 1. MSB bit asserted at IHL means + * to ignore packet IHL and do offset inside IPA header + */ + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = + 0x80; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = + 0xFF << 16; + eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = + attrib->u.v4.tos << 16; + ihl_ofst_meq32++; + tos_done = true; + } + } + if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( IPA_METADATA_COMPARE); @@ -2125,6 +2282,11 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, eq_atrb->ipv4_frag_eq_present = 1; } + if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { + IPAHAL_ERR("could not find equation for tos\n"); + return -EPERM; + } + eq_atrb->rule_eq_bitmap = *en_rule; eq_atrb->num_offset_meq_32 = ofst_meq32; eq_atrb->num_ihl_offset_range_16 = ihl_ofst_rng16; @@ -2145,6 +2307,21 @@ static int ipa_flt_generate_eq_ip6(enum ipa_ip_type ip, u16 eq_bitmap = 0; u16 *en_rule = &eq_bitmap; + if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { + if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { + IPAHAL_ERR("is_pure_ack eq not supported\n"); + return -EPERM; + } + *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); + /* + * Starting IPA 4.5, where PURE ACK equation supported + * and TOS equation support removed, field tos_eq_present + * represent pure_ack presenence. + */ + eq_atrb->tos_eq_present = 1; + eq_atrb->tos_eq = 0; + } + if (attrib->attrib_mask & IPA_FLT_NEXT_HDR) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( IPA_PROTOCOL_EQ); @@ -2658,8 +2835,19 @@ static int ipa_fltrt_parse_hw_rule_eq(u8 *addr, u32 hdr_sz, IPAHAL_DBG_LOW("eq_bitmap=0x%x\n", eq_bitmap); - if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ)) + if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK) && + (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK))) { + /* + * tos_eq_present field represents pure_ack when pure + * ack equation valid (started IPA 4.5). In this case + * tos equation should not be supported. + */ + atrb->tos_eq_present = true; + } + if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ) && + (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ))) { atrb->tos_eq_present = true; + } if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ)) atrb->protocol_eq_present = true; if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TC_EQ)) @@ -2715,8 +2903,12 @@ static int ipa_fltrt_parse_hw_rule_eq(u8 *addr, u32 hdr_sz, IPAHAL_DBG_LOW("addr=0x%pK extra=0x%pK rest=0x%pK\n", addr, extra, rest); - if (atrb->tos_eq_present) + if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ) && atrb->tos_eq_present) atrb->tos_eq = *extra++; + if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK) && atrb->tos_eq_present) { + atrb->tos_eq = 0; + extra++; + } if (atrb->protocol_eq_present) atrb->protocol_eq = *extra++; if (atrb->tc_eq_present) @@ -2839,7 +3031,7 @@ static int ipa_rt_parse_hw_rule(u8 *addr, struct ipahal_rt_rule_entry *rule) IPAHAL_DBG_LOW("read hdr 0x%llx\n", rule_hdr->u.word); if (rule_hdr->u.word == 0) { - /* table termintator - empty table */ + /* table terminator - empty table */ rule->rule_size = 0; return 0; } @@ -2971,6 +3163,8 @@ int ipahal_fltrt_init(enum ipa_hw_type ipa_hw_type) int i; struct ipa_mem_buffer *mem; int rc = -EFAULT; + u32 eq_bits; + u8 *eq_bitfield; IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type); @@ -3102,6 +3296,20 @@ int ipahal_fltrt_init(enum ipa_hw_type ipa_hw_type) } } + eq_bits = 0; + eq_bitfield = ipahal_fltrt_objs[ipa_hw_type].eq_bitfield; + for (i = 0; i < IPA_EQ_MAX; i++) { + if (!IPA_IS_RULE_EQ_VALID(i)) + continue; + + if (eq_bits & IPA_GET_RULE_EQ_BIT_PTRN(eq_bitfield[i])) { + IPAHAL_ERR("more than eq with same bit. eq=%d\n", i); + WARN_ON(1); + return -EFAULT; + } + eq_bits |= IPA_GET_RULE_EQ_BIT_PTRN(eq_bitfield[i]); + } + mem = &ipahal_ctx->empty_fltrt_tbl; /* setup an empty table in system memory; This will @@ -3735,14 +3943,14 @@ int ipahal_rt_generate_hw_rule(struct ipahal_rt_rule_gen_params *params, if (!tmp) return -ENOMEM; buf = tmp; - } else + } else { if ((long)buf & obj->rule_start_alignment) { - IPAHAL_ERR("buff is not rule rule start aligned\n"); + IPAHAL_ERR("buff is not rule start aligned\n"); return -EPERM; } + } - rc = ipahal_fltrt_objs[ipahal_ctx->hw_type].rt_generate_hw_rule( - params, hw_len, buf); + rc = obj->rt_generate_hw_rule(params, hw_len, buf); if (!tmp && !rc) { /* write the rule-set terminator */ memset(buf + *hw_len, 0, obj->tbl_width); @@ -3800,8 +4008,7 @@ int ipahal_flt_generate_hw_rule(struct ipahal_flt_rule_gen_params *params, return -EPERM; } - rc = ipahal_fltrt_objs[ipahal_ctx->hw_type].flt_generate_hw_rule( - params, hw_len, buf); + rc = obj->flt_generate_hw_rule(params, hw_len, buf); if (!tmp && !rc) { /* write the rule-set terminator */ memset(buf + *hw_len, 0, obj->tbl_width); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt_i.h index 645383a8f1cf8948367d5d2e981ee1492b3ad892..681d08947555ca7c854e445b5a8c9b706949d58d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, 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 @@ -36,6 +36,7 @@ enum ipa_fltrt_equations { IPA_IHL_OFFSET_EQ_16, IPA_FL_EQ, IPA_IS_FRAG, + IPA_IS_PURE_ACK, IPA_EQ_MAX, }; diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 4eb8e1a472b23821280fae17f91df35a8ce8737e..e335b18da20fc8ccc3264f20b5cdb883d4149580 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -519,6 +519,7 @@ static acpi_status alienware_wmax_command(struct wmax_basic_args *in_args, if (obj && obj->type == ACPI_TYPE_INTEGER) *out_data = (u32) obj->integer.value; } + kfree(output.pointer); return status; } diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 5269a01d9bdd9fa069541dfec40200be3601f714..a6a33327f5e7f79f776b9fb61bfdcb70ac6a5f83 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -487,6 +487,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ + { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ { KE_END, 0}, }; diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index fe98d4ac0df37040c3da8ad470bf7a33c5477fbe..e1e7e587b45b57e65deaf32397f3b2af5defa760 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -1097,10 +1097,10 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { }, }, { - .ident = "Lenovo Legion Y520-15IKBN", + .ident = "Lenovo Legion Y520-15IKB", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBN"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKB"), }, }, { diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c index b5b890127479f8f586880762828bbd447a383ddf..b7dfe06261f1e6441644aebae16f8d2d6163b842 100644 --- a/drivers/platform/x86/intel_punit_ipc.c +++ b/drivers/platform/x86/intel_punit_ipc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index bb1dcd7fbdeb81902f8b9a395569d1101c342fae..8221e000c8c23616d5206694f87e1f8d2c4a8665 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -34,6 +34,7 @@ #define TOSHIBA_ACPI_VERSION "0.24" #define PROC_INTERFACE_VERSION 1 +#include #include #include #include @@ -1682,7 +1683,7 @@ static const struct file_operations keys_proc_fops = { .write = keys_proc_write, }; -static int version_proc_show(struct seq_file *m, void *v) +static int __maybe_unused version_proc_show(struct seq_file *m, void *v) { seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION); seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION); diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index 102f95a094603ff4c0b54245c6d79c50e764cab0..e9e749f87517d871cf2d4113568a44fb9c0b5d09 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -35,6 +35,7 @@ static void vexpress_reset_do(struct device *dev, const char *what) } static struct device *vexpress_power_off_device; +static atomic_t vexpress_restart_nb_refcnt = ATOMIC_INIT(0); static void vexpress_power_off(void) { @@ -99,10 +100,13 @@ static int _vexpress_register_restart_handler(struct device *dev) int err; vexpress_restart_device = dev; - err = register_restart_handler(&vexpress_restart_nb); - if (err) { - dev_err(dev, "cannot register restart handler (err=%d)\n", err); - return err; + if (atomic_inc_return(&vexpress_restart_nb_refcnt) == 1) { + err = register_restart_handler(&vexpress_restart_nb); + if (err) { + dev_err(dev, "cannot register restart handler (err=%d)\n", err); + atomic_dec(&vexpress_restart_nb_refcnt); + return err; + } } device_create_file(dev, &dev_attr_active); diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index 9dc7590e07cbe97795406b9810544f95faa2ae2a..4d016fbc3527ccfb447fdc91543d98757f540ea1 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -771,7 +771,7 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info) } /* Determine charge current limit */ - cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS; + cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS; cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET; info->cc = cc; diff --git a/drivers/power/supply/generic-adc-battery.c b/drivers/power/supply/generic-adc-battery.c index 37e523374fe00ebe44de3f20ae12a1b8674641b5..371b5ec700870f0b3bc23f62ed939fc717644185 100644 --- a/drivers/power/supply/generic-adc-battery.c +++ b/drivers/power/supply/generic-adc-battery.c @@ -243,10 +243,10 @@ static int gab_probe(struct platform_device *pdev) struct power_supply_desc *psy_desc; struct power_supply_config psy_cfg = {}; struct gab_platform_data *pdata = pdev->dev.platform_data; - enum power_supply_property *properties; int ret = 0; int chan; - int index = 0; + int index = ARRAY_SIZE(gab_props); + bool any = false; adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL); if (!adc_bat) { @@ -280,8 +280,6 @@ static int gab_probe(struct platform_device *pdev) } memcpy(psy_desc->properties, gab_props, sizeof(gab_props)); - properties = (enum power_supply_property *) - ((char *)psy_desc->properties + sizeof(gab_props)); /* * getting channel from iio and copying the battery properties @@ -295,15 +293,22 @@ static int gab_probe(struct platform_device *pdev) adc_bat->channel[chan] = NULL; } else { /* copying properties for supported channels only */ - memcpy(properties + sizeof(*(psy_desc->properties)) * index, - &gab_dyn_props[chan], - sizeof(gab_dyn_props[chan])); - index++; + int index2; + + for (index2 = 0; index2 < index; index2++) { + if (psy_desc->properties[index2] == + gab_dyn_props[chan]) + break; /* already known */ + } + if (index2 == index) /* really new */ + psy_desc->properties[index++] = + gab_dyn_props[chan]; + any = true; } } /* none of the channels are supported so let's bail out */ - if (index == 0) { + if (!any) { ret = -ENODEV; goto second_mem_fail; } @@ -314,7 +319,7 @@ static int gab_probe(struct platform_device *pdev) * as come channels may be not be supported by the device.So * we need to take care of that. */ - psy_desc->num_properties = ARRAY_SIZE(gab_props) + index; + psy_desc->num_properties = index; adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg); if (IS_ERR(adc_bat->psy)) { diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index b7b891a5da6c36ef6117421c58a6ee119290a38d..52a776b85d3e1210000d633c6bd2ae1ab9fe5afd 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -142,8 +143,13 @@ static void power_supply_deferred_register_work(struct work_struct *work) struct power_supply *psy = container_of(work, struct power_supply, deferred_register_work.work); - if (psy->dev.parent) - mutex_lock(&psy->dev.parent->mutex); + if (psy->dev.parent) { + while (!mutex_trylock(&psy->dev.parent->mutex)) { + if (psy->removing) + return; + msleep(10); + } + } psy_register_cooler(psy->dev.parent, psy); power_supply_changed(psy); @@ -1075,6 +1081,7 @@ EXPORT_SYMBOL_GPL(devm_power_supply_register_no_ws); void power_supply_unregister(struct power_supply *psy) { WARN_ON(atomic_dec_return(&psy->use_cnt)); + psy->removing = true; cancel_work_sync(&psy->changed_work); cancel_delayed_work_sync(&psy->deferred_register_work); sysfs_remove_link(&psy->dev.kobj, "powers"); diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index a32b1f60421ce018030a6b67b22afc6d65c96909..e5e80d55a779653fb0f9f927b2c1de2285b3eaa4 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -1263,6 +1263,8 @@ static bool is_parallel_available(struct pl_data *chip) if (!chip->pl_psy) return false; + vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, false, 0); + rc = power_supply_get_property(chip->pl_psy, POWER_SUPPLY_PROP_PARALLEL_MODE, &pval); if (rc < 0) { @@ -1311,8 +1313,6 @@ static bool is_parallel_available(struct pl_data *chip) if (!rc) chip->pl_fcc_max = pval.intval; - vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, false, 0); - return true; } diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 18f49fded5f8c17f8272d7495f9e0df3599903be..b6d7a56a9d8a08038bbe580c4b8c6b1acf084bfc 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -174,6 +174,8 @@ enum fg_sram_param_id { FG_SRAM_MONOTONIC_SOC, FG_SRAM_VOLTAGE_PRED, FG_SRAM_OCV, + FG_SRAM_VBAT_FINAL, + FG_SRAM_IBAT_FINAL, FG_SRAM_ESR, FG_SRAM_ESR_MDL, FG_SRAM_ESR_ACT, @@ -491,6 +493,8 @@ struct fg_dbgfs { extern int fg_decode_voltage_15b(struct fg_sram_param *sp, enum fg_sram_param_id id, int val); +extern int fg_decode_current_16b(struct fg_sram_param *sp, + enum fg_sram_param_id id, int val); extern int fg_decode_cc_soc(struct fg_sram_param *sp, enum fg_sram_param_id id, int value); extern int fg_decode_value_16b(struct fg_sram_param *sp, diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c index 4d7894c94267c715d716a38660ed74c2f2166a46..82c453fe63a7ebbcc94e96125999566efabbd2c5 100644 --- a/drivers/power/supply/qcom/fg-util.c +++ b/drivers/power/supply/qcom/fg-util.c @@ -38,6 +38,16 @@ int fg_decode_voltage_15b(struct fg_sram_param *sp, return sp[id].value; } +int fg_decode_current_16b(struct fg_sram_param *sp, + enum fg_sram_param_id id, int value) +{ + value = sign_extend32(value, 15); + sp[id].value = div_s64((s64)value * sp[id].denmtr, sp[id].numrtr); + pr_debug("id: %d raw value: %x decoded value: %d\n", id, value, + sp[id].value); + return sp[id].value; +} + int fg_decode_cc_soc(struct fg_sram_param *sp, enum fg_sram_param_id id, int value) { diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 996248b81109196d123a7ce6af441b8e340f6c32..1c622562b18644f9ee086f9a5b0b299925a5bae4 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -32,7 +32,7 @@ #define FG_MEM_IF_PM8150B 0x0D #define FG_ADC_RR_PM8150B 0x13 -#define FG_SRAM_LEN 960 +#define FG_SRAM_LEN 972 #define PROFILE_LEN 416 #define PROFILE_COMP_LEN 24 #define KI_COEFF_SOC_LEVELS 3 @@ -119,6 +119,10 @@ #define CYCLE_COUNT_OFFSET 0 #define PROFILE_INTEGRITY_WORD 299 #define PROFILE_INTEGRITY_OFFSET 0 +#define IBAT_FINAL_WORD 320 +#define IBAT_FINAL_OFFSET 0 +#define VBAT_FINAL_WORD 321 +#define VBAT_FINAL_OFFSET 0 #define ESR_WORD 331 #define ESR_OFFSET 0 #define ESR_MDL_WORD 335 @@ -180,6 +184,7 @@ struct fg_dt_props { bool hold_soc_while_full; bool linearize_soc; bool rapid_soc_dec_en; + bool five_pin_battery; int cutoff_volt_mv; int empty_volt_mv; int cutoff_curr_ma; @@ -247,6 +252,7 @@ struct fg_gen4_chip { bool esr_fcc_ctrl_en; bool rslow_low; bool rapid_soc_dec_en; + bool vbatt_low; }; struct bias_config { @@ -285,6 +291,10 @@ static struct fg_sram_param pm8150b_v1_sram_params[] = { 244141, 0, NULL, fg_decode_voltage_15b), PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 1000, 244141, 0, NULL, fg_decode_voltage_15b), + PARAM(VBAT_FINAL, VBAT_FINAL_WORD, VBAT_FINAL_OFFSET, 2, 1000, 244141, + 0, NULL, fg_decode_voltage_15b), + PARAM(IBAT_FINAL, IBAT_FINAL_WORD, IBAT_FINAL_OFFSET, 2, 1000, 488282, + 0, NULL, fg_decode_current_16b), PARAM(ESR, ESR_WORD, ESR_OFFSET, 2, 1000, 244141, 0, fg_encode_default, fg_decode_value_16b), PARAM(ESR_MDL, ESR_MDL_WORD, ESR_MDL_OFFSET, 2, 1000, 244141, 0, @@ -373,6 +383,10 @@ static struct fg_sram_param pm8150b_v2_sram_params[] = { 1000, 244141, 0, NULL, fg_decode_voltage_15b), PARAM(OCV, OCV_v2_WORD, OCV_v2_OFFSET, 2, 1000, 244141, 0, NULL, fg_decode_voltage_15b), + PARAM(VBAT_FINAL, VBAT_FINAL_WORD, VBAT_FINAL_OFFSET, 2, 1000, 244141, + 0, NULL, fg_decode_voltage_15b), + PARAM(IBAT_FINAL, IBAT_FINAL_WORD, IBAT_FINAL_OFFSET, 2, 1000, 488282, + 0, NULL, fg_decode_current_16b), PARAM(ESR, ESR_WORD, ESR_OFFSET, 2, 1000, 244141, 0, fg_encode_default, fg_decode_value_16b), PARAM(ESR_MDL, ESR_MDL_WORD, ESR_MDL_OFFSET, 2, 1000, 244141, 0, @@ -450,8 +464,6 @@ static struct fg_sram_param pm8150b_v2_sram_params[] = { 1, 1, 1, 0, fg_encode_default, NULL), }; -static bool is_batt_empty(struct fg_dev *fg); - /* All get functions below */ struct bias_config id_table[3] = { @@ -694,6 +706,51 @@ static bool is_debug_batt_id(struct fg_dev *fg) return false; } +static int fg_gen4_get_cell_impedance(struct fg_gen4_chip *chip, int *val) +{ + struct fg_dev *fg = &chip->fg; + int rc, esr_uohms, temp, vbat_term_mv, v_delta, rprot_uohms = 0; + + rc = fg_get_battery_resistance(fg, &esr_uohms); + if (rc < 0) + return rc; + + if (!chip->dt.five_pin_battery) + goto out; + + if (fg->charge_type != POWER_SUPPLY_CHARGE_TYPE_TAPER || + fg->bp.float_volt_uv <= 0) + goto out; + + rc = fg_get_battery_voltage(fg, &vbat_term_mv); + if (rc < 0) + goto out; + + rc = fg_get_sram_prop(fg, FG_SRAM_VBAT_FINAL, &temp); + if (rc < 0) { + pr_err("Error in getting VBAT_FINAL rc:%d\n", rc); + goto out; + } + + v_delta = abs(temp - fg->bp.float_volt_uv); + + rc = fg_get_sram_prop(fg, FG_SRAM_IBAT_FINAL, &temp); + if (rc < 0) { + pr_err("Error in getting IBAT_FINAL rc:%d\n", rc); + goto out; + } + + if (!temp) + goto out; + + rprot_uohms = div64_u64((u64)v_delta * 1000000, abs(temp)); + pr_debug("v_delta: %d ibat_final: %d rprot_uohms: %d\n", v_delta, temp, + rprot_uohms); +out: + *val = esr_uohms - rprot_uohms; + return rc; +} + static int fg_gen4_get_prop_capacity(struct fg_dev *fg, int *val) { struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); @@ -714,7 +771,7 @@ static int fg_gen4_get_prop_capacity(struct fg_dev *fg, int *val) return 0; } - if (is_batt_empty(fg)) { + if (chip->vbatt_low) { *val = EMPTY_SOC; return 0; } @@ -813,7 +870,7 @@ static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val) *val = chip->dt.sys_term_curr_ma; break; case TTF_RBATT: - rc = fg_get_battery_resistance(fg, val); + rc = fg_gen4_get_cell_impedance(chip, val); break; case TTF_VFLOAT: *val = fg->bp.float_volt_uv; @@ -2455,13 +2512,13 @@ static irqreturn_t fg_delta_esr_irq_handler(int irq, void *data) { struct fg_dev *fg = data; struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); - int esr_mohms, rc; + int esr_uohms, rc; - rc = fg_get_battery_resistance(fg, &esr_mohms); + rc = fg_get_battery_resistance(fg, &esr_uohms); if (rc < 0) return IRQ_HANDLED; - fg_dbg(fg, FG_IRQ, "irq %d triggered esr_mohms: %d\n", irq, esr_mohms); + fg_dbg(fg, FG_IRQ, "irq %d triggered esr_uohms: %d\n", irq, esr_uohms); if (chip->esr_fast_calib) { vote(fg->awake_votable, ESR_CALIB, true, 0); @@ -2489,17 +2546,22 @@ static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data) fg_dbg(fg, FG_IRQ, "irq %d triggered vbatt_mv: %d msoc_raw:%d\n", irq, vbatt_mv, msoc_raw); - if (chip->dt.rapid_soc_dec_en && vbatt_mv < chip->dt.cutoff_volt_mv) { - /* - * Set this flag so that slope limiter coefficient cannot be - * configured during rapid SOC decrease. - */ - chip->rapid_soc_dec_en = true; + if (vbatt_mv < chip->dt.cutoff_volt_mv) { + if (chip->dt.rapid_soc_dec_en) { + /* + * Set this flag so that slope limiter coefficient + * cannot be configured during rapid SOC decrease. + */ + chip->rapid_soc_dec_en = true; - rc = fg_gen4_rapid_soc_config(chip, true); - if (rc < 0) - pr_err("Error in configuring for rapid SOC reduction rc:%d\n", - rc); + rc = fg_gen4_rapid_soc_config(chip, true); + if (rc < 0) + pr_err("Error in configuring for rapid SOC reduction rc:%d\n", + rc); + } else { + /* Set the flag to show 0% */ + chip->vbatt_low = true; + } } if (batt_psy_initialized(fg)) @@ -2683,13 +2745,14 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc); /* - * If ESR fast calibration is done without a delta ESR interrupt, then - * it is possibly a failed attempt. In such cases, retry ESR fast - * calibration once again. This will get restored to normal config once - * a delta ESR interrupt fires or the timer expires. + * If ESR fast calibration is done even before 3 delta ESR interrupts + * had fired, then it is possibly a failed attempt. In such cases, + * retry ESR fast calibration once again. This will get restored to + * normal config once the timer expires or delta ESR interrupt count + * reaches the threshold. */ if (chip->esr_fast_calib && chip->esr_fast_calib_done && - !chip->delta_esr_count && !chip->esr_fast_calib_retry) { + (chip->delta_esr_count < 3) && !chip->esr_fast_calib_retry) { rc = fg_gen4_esr_fast_calib_config(chip, true); if (rc < 0) pr_err("Error in configuring esr_fast_calib, rc=%d\n", @@ -2836,36 +2899,6 @@ static struct fg_irq_info fg_irqs[FG_GEN4_IRQ_MAX] = { }, }; -static bool is_batt_empty(struct fg_dev *fg) -{ - struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); - u8 status; - int rc, vbatt_uv, msoc; - - rc = fg_read(fg, BATT_SOC_INT_RT_STS(fg), &status, 1); - if (rc < 0) { - pr_err("failed to read addr=0x%04x, rc=%d\n", - BATT_SOC_INT_RT_STS(fg), rc); - return false; - } - - if (!(status & MSOC_EMPTY_BIT)) - return false; - - rc = fg_get_battery_voltage(fg, &vbatt_uv); - if (rc < 0) { - pr_err("failed to get battery voltage, rc=%d\n", rc); - return false; - } - - rc = fg_get_msoc(fg, &msoc); - if (!rc) - pr_warn_ratelimited("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", - status, vbatt_uv, msoc); - - return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false); -} - static enum alarmtimer_restart fg_esr_fast_cal_timer(struct alarm *alarm, ktime_t time) { @@ -4570,6 +4603,9 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) chip->dt.rapid_soc_dec_en = of_property_read_bool(node, "qcom,rapid-soc-dec-en"); + + chip->dt.five_pin_battery = of_property_read_bool(node, + "qcom,five-pin-battery"); return 0; } diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 16d78a4ae1ec5b93bebd045a1a215da7ddbc74d9..386978d83eef26769235344aac53f6a01df09f51 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -2549,7 +2549,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip) } rc = qg_get_battery_temp(chip, &batt_temp); - if (rc) { + if (rc < 0) { pr_err("Failed to read BATT_TEMP at PON rc=%d\n", rc); goto done; } diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index d0591a479664d806fd4b625da2bfdd30d8d14ab9..0d7f3e2f4ae2d54f5f1fa1f94a8f00827876a4ec 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -443,11 +443,22 @@ static int smb5_parse_dt(struct smb5 *chip) "qcom,fcc-stepping-enable"); /* Extract ADC channels */ - rc = smblib_get_iio_channel(chg, "usb_in_voltage", - &chg->iio.usbin_v_chan); + rc = smblib_get_iio_channel(chg, "mid_voltage", &chg->iio.mid_chan); if (rc < 0) return rc; + if (!chg->iio.mid_chan) { + rc = smblib_get_iio_channel(chg, "usb_in_voltage", + &chg->iio.usbin_v_chan); + if (rc < 0) + return rc; + + if (!chg->iio.usbin_v_chan) { + dev_err(chg->dev, "No voltage channel defined"); + return -EINVAL; + } + } + rc = smblib_get_iio_channel(chg, "chg_temp", &chg->iio.temp_chan); if (rc < 0) return rc; diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c index 39a8ea5b8f3cc00faa00cacebd2a3a9086fecf70..bd2d19361beba49675f5ff43b9b988fa30a9f787 100644 --- a/drivers/power/supply/qcom/smb1355-charger.c +++ b/drivers/power/supply/qcom/smb1355-charger.c @@ -522,6 +522,7 @@ static int smb1355_parse_dt(struct smb1355 *chip) static enum power_supply_property smb1355_parallel_props[] = { POWER_SUPPLY_PROP_CHARGE_TYPE, + POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_CHARGING_ENABLED, POWER_SUPPLY_PROP_PIN_ENABLED, POWER_SUPPLY_PROP_INPUT_SUSPEND, @@ -605,6 +606,7 @@ static int smb1355_parallel_get_prop(struct power_supply *psy, rc = smb1355_get_prop_batt_charge_type(chip, val); break; case POWER_SUPPLY_PROP_CHARGING_ENABLED: + case POWER_SUPPLY_PROP_ONLINE: rc = smb1355_read(chip, BATTERY_STATUS_3_REG, &stat); if (rc >= 0) val->intval = (bool)(stat & ENABLE_CHARGING_BIT); diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index f086b5ea1225538e189b266a2d45be7bd5102aba..d6329cc966357ad30464d4d615d4a469f13d8144 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -492,6 +492,34 @@ static const struct apsd_result *smblib_get_apsd_result(struct smb_charger *chg) return result; } +#define INPUT_NOT_PRESENT 0 +#define INPUT_PRESENT_USB BIT(1) +#define INPUT_PRESENT_DC BIT(2) +static int smblib_is_input_present(struct smb_charger *chg, + int *present) +{ + int rc; + union power_supply_propval pval = {0, }; + + *present = INPUT_NOT_PRESENT; + + rc = smblib_get_prop_usb_present(chg, &pval); + if (rc < 0) { + pr_err("Couldn't get usb presence status rc=%d\n", rc); + return rc; + } + *present |= pval.intval ? INPUT_PRESENT_USB : INPUT_NOT_PRESENT; + + rc = smblib_get_prop_dc_present(chg, &pval); + if (rc < 0) { + pr_err("Couldn't get dc presence status rc=%d\n", rc); + return rc; + } + *present |= pval.intval ? INPUT_PRESENT_DC : INPUT_NOT_PRESENT; + + return 0; +} + /******************** * REGISTER SETTERS * ********************/ @@ -972,6 +1000,28 @@ static void smblib_uusb_removal(struct smb_charger *chg) if (rc < 0) smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n", rc); + + /* + * if non-compliant charger caused UV, restore original max pulses + * and turn SUSPEND_ON_COLLAPSE_USBIN_BIT back on. + */ + if (chg->qc2_unsupported_voltage) { + rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG, + HVDCP_PULSE_COUNT_MAX_QC2_MASK, + chg->qc2_max_pulses); + if (rc < 0) + smblib_err(chg, "Couldn't restore max pulses rc=%d\n", + rc); + + rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG, + SUSPEND_ON_COLLAPSE_USBIN_BIT, + SUSPEND_ON_COLLAPSE_USBIN_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n", + rc); + + chg->qc2_unsupported_voltage = QC2_COMPLIANT; + } } void smblib_suspend_on_debug_battery(struct smb_charger *chg) @@ -1056,7 +1106,6 @@ static int set_sdp_current(struct smb_charger *chg, int icl_ua) icl_options = CFG_USB3P0_SEL_BIT | USB51_MODE_BIT; break; default: - smblib_err(chg, "ICL %duA isn't supported for SDP\n", icl_ua); return -EINVAL; } @@ -1142,7 +1191,17 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) goto out; } } else { - set_sdp_current(chg, 100000); + /* + * Try USB 2.0/3,0 option first on USB path when maximum input + * current limit is 500mA or below for better accuracy; in case + * of error, proceed to use USB high-current mode. + */ + if (icl_ua <= USBIN_500MA) { + rc = set_sdp_current(chg, icl_ua); + if (rc >= 0) + goto out; + } + rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua); if (rc < 0) { smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc); @@ -2622,44 +2681,120 @@ int smblib_get_prop_usb_voltage_max(struct smb_charger *chg, return 0; } -int smblib_get_prop_usb_voltage_now(struct smb_charger *chg, - union power_supply_propval *val) +static int smblib_estimate_hvdcp_voltage(struct smb_charger *chg, + union power_supply_propval *val) { - int rc, ret = 0; + int rc; + u8 stat; - /* set 12V OV to 14.6V */ - if (chg->smb_version == PM8150B_SUBTYPE) { - rc = smblib_masked_write(chg, USB_ENG_SSUPPLY_USB2_REG, - ENG_SSUPPLY_12V_OV_OPT_BIT, - ENG_SSUPPLY_12V_OV_OPT_BIT); - if (rc < 0) { - smblib_err(chg, "Couldn't set USB_ENG_SSUPPLY_USB2_REG rc=%d\n", - rc); - return -ENODATA; - } + rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read QC_CHANGE_STATUS_REG rc=%d\n", + rc); + return rc; } - if (chg->iio.usbin_v_chan) { - rc = iio_read_channel_processed(chg->iio.usbin_v_chan, - &val->intval); - if (rc < 0) - ret = -ENODATA; - } else { - ret = -ENODATA; + if (stat & QC_5V_BIT) + val->intval = MICRO_5V; + else if (stat & QC_9V_BIT) + val->intval = MICRO_9V; + else if (stat & QC_12V_BIT) + val->intval = MICRO_12V; + + return 0; +} + +#define HVDCP3_STEP_UV 200000 +static int smblib_estimate_adaptor_voltage(struct smb_charger *chg, + union power_supply_propval *val) +{ + switch (chg->real_charger_type) { + case POWER_SUPPLY_TYPE_USB_HVDCP: + return smblib_estimate_hvdcp_voltage(chg, val); + case POWER_SUPPLY_TYPE_USB_HVDCP_3: + val->intval = MICRO_5V + (HVDCP3_STEP_UV * chg->pulse_cnt); + break; + case POWER_SUPPLY_TYPE_USB_PD: + /* Take the average of min and max values */ + val->intval = chg->voltage_min_uv + + ((chg->voltage_max_uv - chg->voltage_min_uv) / 2); + break; + default: + val->intval = MICRO_5V; + break; } - /* restore 12V OV to 13.2V */ - if (chg->smb_version == PM8150B_SUBTYPE) { - rc = smblib_masked_write(chg, USB_ENG_SSUPPLY_USB2_REG, - ENG_SSUPPLY_12V_OV_OPT_BIT, 0); - if (rc < 0) { - smblib_err(chg, "Couldn't restore USB_ENG_SSUPPLY_USB2_REG rc=%d\n", - rc); - ret = -ENODATA; - } + return 0; +} + +static int smblib_read_mid_voltage_chan(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc; + + if (!chg->iio.mid_chan) + return -ENODATA; + + rc = iio_read_channel_processed(chg->iio.mid_chan, &val->intval); + if (rc < 0) { + smblib_err(chg, "Couldn't read MID channel rc=%d\n", rc); + return rc; } - return ret; + /* + * If MID voltage < 1V, it is unreliable. + * Figure out voltage from registers and calculations. + */ + if (val->intval < 1000000) + return smblib_estimate_adaptor_voltage(chg, val); + + return 0; +} + +static int smblib_read_usbin_voltage_chan(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc; + + if (!chg->iio.usbin_v_chan) + return -ENODATA; + + rc = iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval); + if (rc < 0) { + smblib_err(chg, "Couldn't read USBIN channel rc=%d\n", rc); + return rc; + } + + return 0; +} + +int smblib_get_prop_usb_voltage_now(struct smb_charger *chg, + union power_supply_propval *val) +{ + union power_supply_propval pval = {0, }; + int rc; + + rc = smblib_get_prop_usb_present(chg, &pval); + if (rc < 0) { + smblib_err(chg, "Couldn't get usb presence status rc=%d\n", rc); + return -ENODATA; + } + + /* usb not present */ + if (!pval.intval) { + val->intval = 0; + return 0; + } + + /* + * For PM8150B, use MID_CHG ADC channel because overvoltage is observed + * to occur randomly in the USBIN channel, particularly at high + * voltages. + */ + if (chg->smb_version == PM8150B_SUBTYPE) + return smblib_read_mid_voltage_chan(chg, val); + else + return smblib_read_usbin_voltage_chan(chg, val); } bool smblib_rsbux_low(struct smb_charger *chg, int r_thr) @@ -2732,25 +2867,14 @@ bool smblib_rsbux_low(struct smb_charger *chg, int r_thr) int smblib_get_prop_charger_temp(struct smb_charger *chg, union power_supply_propval *val) { - union power_supply_propval pval = {0, }; - bool usb_present, dc_present; int temp, rc; + int input_present; - rc = smblib_get_prop_usb_present(chg, &pval); - if (rc < 0) { - pr_err("Couldn't get usb presence status rc=%d\n", rc); - return rc; - } - usb_present = pval.intval; - - rc = smblib_get_prop_dc_present(chg, &pval); - if (rc < 0) { - pr_err("Couldn't get dc presence status rc=%d\n", rc); + rc = smblib_is_input_present(chg, &input_present); + if (rc < 0) return rc; - } - dc_present = pval.intval; - if (!usb_present && !dc_present) + if (input_present == INPUT_NOT_PRESENT) return -ENODATA; if (chg->iio.temp_chan) { @@ -3017,7 +3141,6 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg, return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval); } -#define HVDCP3_STEP_UV 200000 int smblib_get_prop_input_voltage_settled(struct smb_charger *chg, union power_supply_propval *val) { @@ -3062,6 +3185,14 @@ int smblib_get_prop_die_health(struct smb_charger *chg) { int rc; u8 stat; + int input_present; + + rc = smblib_is_input_present(chg, &input_present); + if (rc < 0) + return rc; + + if (input_present == INPUT_NOT_PRESENT) + return POWER_SUPPLY_HEALTH_UNKNOWN; if (chg->wa_flags & SW_THERM_REGULATION_WA) { if (chg->die_temp == -ENODATA) @@ -4632,6 +4763,7 @@ irqreturn_t dc_plugin_irq_handler(int irq, void *data) struct smb_irq_data *irq_data = data; struct smb_charger *chg = irq_data->parent_data; union power_supply_propval pval; + int input_present; bool dcin_present, vbus_present; int rc, wireless_vout = 0; @@ -4644,20 +4776,12 @@ irqreturn_t dc_plugin_irq_handler(int irq, void *data) wireless_vout /= 100000; wireless_vout *= 100000; - rc = smblib_get_prop_dc_present(chg, &pval); + rc = smblib_is_input_present(chg, &input_present); if (rc < 0) return IRQ_HANDLED; - dcin_present = pval.intval; - - rc = smblib_get_prop_usb_present(chg, &pval); - if (rc < 0) { - smblib_err(chg, "Couldn't get usb present rc = %d\n", - rc); - return IRQ_HANDLED; - } - - vbus_present = pval.intval; + dcin_present = input_present & INPUT_PRESENT_DC; + vbus_present = input_present & INPUT_PRESENT_USB; if (dcin_present) { if (!vbus_present && chg->sec_cp_present) { diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 6962f9dbd8c36538cb185c35539f85083a7ed9b5..b9f5c44e6b89c88cdd1e4dc9e093aa9d70f934b5 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -290,6 +290,7 @@ struct smb_iio { struct iio_channel *temp_chan; struct iio_channel *usbin_i_chan; struct iio_channel *usbin_v_chan; + struct iio_channel *mid_chan; struct iio_channel *batt_i_chan; struct iio_channel *connector_temp_chan; struct iio_channel *sbux_chan; diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index d589331d1884b29f938c47f9fb3308ffcb212026..3540d00425d03be01fdcdb77c6f028c975a92617 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -432,7 +432,6 @@ static int meson_pwm_init_channels(struct meson_pwm *meson, struct meson_pwm_channel *channels) { struct device *dev = meson->chip.dev; - struct device_node *np = dev->of_node; struct clk_init_data init; unsigned int i; char name[255]; @@ -441,7 +440,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson, for (i = 0; i < meson->chip.npwm; i++) { struct meson_pwm_channel *channel = &channels[i]; - snprintf(name, sizeof(name), "%pOF#mux%u", np, i); + snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i); init.name = name; init.ops = &clk_mux_ops; diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 4c22cb39504094eb32db6ad94e7718eadb38917b..f7b8a86fa5c5e9570a616ccbcdb61e7d427b8ae3 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -33,10 +33,6 @@ #define TBCTL 0x00 #define TBPRD 0x0A -#define TBCTL_RUN_MASK (BIT(15) | BIT(14)) -#define TBCTL_STOP_NEXT 0 -#define TBCTL_STOP_ON_CYCLE BIT(14) -#define TBCTL_FREE_RUN (BIT(15) | BIT(14)) #define TBCTL_PRDLD_MASK BIT(3) #define TBCTL_PRDLD_SHDW 0 #define TBCTL_PRDLD_IMDT BIT(3) @@ -360,7 +356,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) /* Channels polarity can be configured from action qualifier module */ configure_polarity(pc, pwm->hwpwm); - /* Enable TBCLK before enabling PWM device */ + /* Enable TBCLK */ ret = clk_enable(pc->tbclk); if (ret) { dev_err(chip->dev, "Failed to enable TBCLK for %s: %d\n", @@ -368,9 +364,6 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) return ret; } - /* Enable time counter for free_run */ - ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); - return 0; } @@ -388,6 +381,8 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) aqcsfrc_mask = AQCSFRC_CSFA_MASK; } + /* Update shadow register first before modifying active register */ + ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); /* * Changes to immediate action on Action Qualifier. This puts * Action Qualifier control on PWM output from next TBCLK @@ -400,9 +395,6 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) /* Disabling TBCLK on PWM disable */ clk_disable(pc->tbclk); - /* Stop Time base counter */ - ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT); - /* Disable clock on PWM disable */ pm_runtime_put_sync(chip->dev); } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e1ed479d1a01d05385e68350a177146098c22b6e..25f493570262339198dfc65e8493a0ed6ade7c52 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -4499,13 +4499,13 @@ regulator_register(const struct regulator_desc *regulator_desc, !rdev->desc->fixed_uV) rdev->is_switch = true; + dev_set_drvdata(&rdev->dev, rdev); ret = device_register(&rdev->dev); if (ret != 0) { put_device(&rdev->dev); goto unset_supplies; } - dev_set_drvdata(&rdev->dev, rdev); rdev_init_debugfs(rdev); rdev->proxy_consumer = regulator_proxy_consumer_register(dev, config->of_node); diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c index 4db177bc89bc4b18bbeb55e8766a7045a7a221a9..fdeac194642946b713a2a3e00fa2ca371b746e4c 100644 --- a/drivers/reset/reset-imx7.c +++ b/drivers/reset/reset-imx7.c @@ -80,7 +80,7 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev, { struct imx7_src *imx7src = to_imx7_src(rcdev); const struct imx7_src_signal *signal = &imx7_src_signals[id]; - unsigned int value = 0; + unsigned int value = assert ? signal->bit : 0; switch (id) { case IMX7_RESET_PCIEPHY: diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 39cc5a69246aad53b82951fedca3a15fefcec213..c76febeae56d815b0a16101f900a68c3027bdd5a 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "rpmsg_internal.h" #include "qcom_glink_native.h" @@ -818,9 +819,11 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink, static void qcom_glink_handle_intent_req(struct qcom_glink *glink, u32 cid, size_t size) { - struct glink_core_rx_intent *intent; + struct glink_core_rx_intent *intent = NULL; + struct glink_core_rx_intent *tmp; struct glink_channel *channel; unsigned long flags; + int iid; spin_lock_irqsave(&glink->idr_lock, flags); channel = idr_find(&glink->rcids, cid); @@ -831,6 +834,19 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink, return; } + spin_lock_irqsave(&channel->intent_lock, flags); + idr_for_each_entry(&channel->liids, tmp, iid) { + if (tmp->size >= size && tmp->reuse) { + intent = tmp; + break; + } + } + spin_unlock_irqrestore(&channel->intent_lock, flags); + if (intent) { + qcom_glink_send_intent_req_ack(glink, channel, !!intent); + return; + } + intent = qcom_glink_alloc_intent(glink, channel, size, false); if (intent) qcom_glink_advertise_intent(glink, channel, intent); @@ -1813,6 +1829,23 @@ static void qcom_glink_set_affinity(struct qcom_glink *glink, u32 *arr, dev_err(glink->dev, "failed to set task affinity\n"); } +static void qcom_glink_notif_reset(void *data) +{ + struct qcom_glink *glink = data; + struct glink_channel *channel; + unsigned long flags; + int cid; + + if (!glink) + return; + atomic_inc(&glink->in_reset); + + spin_lock_irqsave(&glink->idr_lock, flags); + idr_for_each_entry(&glink->lcids, channel, cid) { + wake_up(&channel->intent_req_event); + } + spin_unlock_irqrestore(&glink->idr_lock, flags); +} struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, @@ -1871,6 +1904,13 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, return ERR_CAST(glink->task); } + ret = subsys_register_early_notifier(glink->name, XPORT_LAYER_NOTIF, + qcom_glink_notif_reset, glink); + if (ret) { + dev_err(dev, "failed to register early notif %d\n", ret); + return ERR_PTR(ret); + } + irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, @@ -1878,7 +1918,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, "glink-native", glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); - return ERR_PTR(ret); + goto unregister; } glink->irq = irq; @@ -1886,8 +1926,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); if (size > 0) { arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); - if (!arr) - return ERR_PTR(-ENOMEM); + if (!arr) { + ret = -ENOMEM; + goto unregister; + } ret = of_property_read_u32_array(dev->of_node, "cpu-affinity", arr, size); if (!ret) @@ -1898,7 +1940,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, ret = qcom_glink_send_version(glink); if (ret) { dev_err(dev, "failed to send version %d\n", ret); - return ERR_PTR(ret); + goto unregister; } ret = qcom_glink_create_chrdev(glink); @@ -1908,6 +1950,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, glink->ilc = ipc_log_context_create(GLINK_LOG_PAGE_CNT, glink->name, 0); return glink; + +unregister: + subsys_unregister_early_notifier(glink->name, XPORT_LAYER_NOTIF); + return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(qcom_glink_native_probe); @@ -1925,17 +1971,11 @@ void qcom_glink_native_remove(struct qcom_glink *glink) int ret; unsigned long flags; - atomic_inc(&glink->in_reset); + subsys_unregister_early_notifier(glink->name, XPORT_LAYER_NOTIF); + qcom_glink_notif_reset(glink); disable_irq(glink->irq); cancel_work_sync(&glink->rx_work); - /* Signal all threads to cancel tx */ - spin_lock_irqsave(&glink->idr_lock, flags); - idr_for_each_entry(&glink->lcids, channel, cid) { - wake_up(&channel->intent_req_event); - } - spin_unlock_irqrestore(&glink->idr_lock, flags); - ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); if (ret) dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index bd170cb3361ce15e511a3a81f2ff1c06a5ed3bfe..5747a54cbd423e34c13e5f920ee7f8bce1cc2c50 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c @@ -164,6 +164,10 @@ static int bq4802_probe(struct platform_device *pdev) } else if (p->r->flags & IORESOURCE_MEM) { p->regs = devm_ioremap(&pdev->dev, p->r->start, resource_size(p->r)); + if (!p->regs){ + err = -ENOMEM; + goto out; + } p->read = bq4802_read_mem; p->write = bq4802_write_mem; } else { diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 13f7cd11c07eb52948121225242b57f8ab2c8e2c..ac6e6a6a194c71de44bde323135e0cca8780921b 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -817,13 +817,6 @@ static int omap_rtc_probe(struct platform_device *pdev) goto err; } - if (rtc->is_pmic_controller) { - if (!pm_power_off) { - omap_rtc_power_off_rtc = rtc; - pm_power_off = omap_rtc_power_off; - } - } - /* Support ext_wakeup pinconf */ rtc_pinctrl_desc.name = dev_name(&pdev->dev); @@ -833,6 +826,13 @@ static int omap_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc->pctldev); } + if (rtc->is_pmic_controller) { + if (!pm_power_off) { + omap_rtc_power_off_rtc = rtc; + pm_power_off = omap_rtc_power_off; + } + } + return 0; err: diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d072f84a8535f160889eca5891370747e67b03c8..92c4f5180ad07914e8c2722988b8f8e2f32fff17 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3190,6 +3190,7 @@ static int dasd_alloc_queue(struct dasd_block *block) block->tag_set.nr_hw_queues = DASD_NR_HW_QUEUES; block->tag_set.queue_depth = DASD_MAX_LCU_DEV * DASD_REQ_PER_DEV; block->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + block->tag_set.numa_node = NUMA_NO_NODE; rc = blk_mq_alloc_tag_set(&block->tag_set); if (rc) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 5ede251c52ca980e51f6e22fdbfc3bef08c5c9c6..4c7c8455da961422c8a92f9c8862fb8a59c16132 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1778,6 +1778,9 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device) struct dasd_eckd_private *private = device->private; int i; + if (!private) + return; + dasd_alias_disconnect_device_from_lcu(device); private->ned = NULL; private->sneq = NULL; @@ -2032,8 +2035,11 @@ static int dasd_eckd_basic_to_ready(struct dasd_device *device) static int dasd_eckd_online_to_ready(struct dasd_device *device) { - cancel_work_sync(&device->reload_device); - cancel_work_sync(&device->kick_validate); + if (cancel_work_sync(&device->reload_device)) + dasd_put_device(device); + if (cancel_work_sync(&device->kick_validate)) + dasd_put_device(device); + return 0; }; diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c index eb51893c74a4ba4053fe8d15e064fbf42bed9845..5c944ee76ec1494c0515c5dee9aa80bc5da096df 100644 --- a/drivers/s390/block/scm_blk.c +++ b/drivers/s390/block/scm_blk.c @@ -454,6 +454,7 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev) bdev->tag_set.nr_hw_queues = nr_requests; bdev->tag_set.queue_depth = nr_requests_per_io * nr_requests; bdev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + bdev->tag_set.numa_node = NUMA_NO_NODE; ret = blk_mq_alloc_tag_set(&bdev->tag_set); if (ret) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 8941e7caaf4dc9c3ae180569329457f5342d1ae8..c7afdbded26b6bfefd82dd8db3c643c5c931f857 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -641,21 +641,20 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q, unsigned long phys_aob = 0; if (!q->use_cq) - goto out; + return 0; if (!q->aobs[bufnr]) { struct qaob *aob = qdio_allocate_aob(); q->aobs[bufnr] = aob; } if (q->aobs[bufnr]) { - q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE; q->sbal_state[bufnr].aob = q->aobs[bufnr]; q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user; phys_aob = virt_to_phys(q->aobs[bufnr]); WARN_ON_ONCE(phys_aob & 0xFF); } -out: + q->sbal_state[bufnr].flags = 0; return phys_aob; } diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 82f05c4b8c526f73a52aed819eacb33cdfd18e3a..ae7a49ade414bd8e33356f47e954cfc27a2488a3 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -176,6 +176,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process) { struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); unsigned long flags; + int rc = -EAGAIN; spin_lock_irqsave(sch->lock, flags); if (!device_is_registered(&sch->dev)) @@ -186,6 +187,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process) if (cio_update_schib(sch)) { vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER); + rc = 0; goto out_unlock; } @@ -194,11 +196,12 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process) private->state = private->mdev ? VFIO_CCW_STATE_IDLE : VFIO_CCW_STATE_STANDBY; } + rc = 0; out_unlock: spin_unlock_irqrestore(sch->lock, flags); - return 0; + return rc; } static struct css_device_id vfio_ccw_sch_ids[] = { diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 939b5b5e97efe81ad52a04ab04b678d0fc424ee5..0a6afd4b283d484daf8f4d3d96f2cca427970085 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3507,13 +3507,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, qdio_flags = QDIO_FLAG_SYNC_OUTPUT; if (atomic_read(&queue->set_pci_flags_count)) qdio_flags |= QDIO_FLAG_PCI_OUT; + atomic_add(count, &queue->used_buffers); + rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags, queue->queue_no, index, count); if (queue->card->options.performance_stats) queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() - queue->card->perf_stats.outbound_do_qdio_start_time; - atomic_add(count, &queue->used_buffers); if (rc) { queue->card->stats.tx_errors += count; /* ignore temporary SIGA errors without busy condition */ diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index d1ee9e30c68bec45fba048ae30c4ae325fc5f2d0..21e91fbb28605399116a1144cfced5ea27f57fd4 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -423,6 +423,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, if (card->discipline) { card->discipline->remove(card->gdev); qeth_core_free_discipline(card); + card->options.layer2 = -1; } rc = qeth_core_load_discipline(card, newdis); diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index a1388842e17e561e901726ccb61bc44163332c24..dd342207095af001581bce325583e0c991339d45 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2042,6 +2042,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) if (twa_initialize_device_extension(tw_dev)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x25, "Failed to initialize device extension"); + retval = -ENOMEM; goto out_free_device_extension; } @@ -2064,6 +2065,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) tw_dev->base_addr = ioremap(mem_addr, mem_len); if (!tw_dev->base_addr) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x35, "Failed to ioremap"); + retval = -ENOMEM; goto out_release_mem_region; } @@ -2071,8 +2073,10 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) TW_DISABLE_INTERRUPTS(tw_dev); /* Initialize the card */ - if (twa_reset_sequence(tw_dev, 0)) + if (twa_reset_sequence(tw_dev, 0)) { + retval = -ENOMEM; goto out_iounmap; + } /* Set host specific parameters */ if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) || diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index b150e131b2e76a172aa13bbf84949ec0cc269cd4..aa317d6909e8f0ea71196ad0cedd5337e10f87e4 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -1597,6 +1597,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) if (twl_initialize_device_extension(tw_dev)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Failed to initialize device extension"); + retval = -ENOMEM; goto out_free_device_extension; } @@ -1611,6 +1612,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) tw_dev->base_addr = pci_iomap(pdev, 1, 0); if (!tw_dev->base_addr) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to ioremap"); + retval = -ENOMEM; goto out_release_mem_region; } @@ -1620,6 +1622,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) /* Initialize the card */ if (twl_reset_sequence(tw_dev, 0)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Controller reset failed during probe"); + retval = -ENOMEM; goto out_iounmap; } diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index f6179e3d695397e368cdd57e913d8863e829fa31..961ea6f7def87263e314d389a6b33b3b34a883e1 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2280,6 +2280,7 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) if (tw_initialize_device_extension(tw_dev)) { printk(KERN_WARNING "3w-xxxx: Failed to initialize device extension."); + retval = -ENOMEM; goto out_free_device_extension; } @@ -2294,6 +2295,7 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) tw_dev->base_addr = pci_resource_start(pdev, 0); if (!tw_dev->base_addr) { printk(KERN_WARNING "3w-xxxx: Failed to get io address."); + retval = -ENOMEM; goto out_release_mem_region; } diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 6c838865ac5a7b32fd853aa36a07611e9809adc3..4a4746cc6745f2cc95b2ce0e570a7df05fc77484 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -1030,8 +1030,10 @@ static int __init aic94xx_init(void) aic94xx_transport_template = sas_domain_attach_transport(&aic94xx_transport_functions); - if (!aic94xx_transport_template) + if (!aic94xx_transport_template) { + err = -ENOMEM; goto out_destroy_caches; + } err = pci_register_driver(&aic94xx_pci_driver); if (err) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 42921dbba9272f793a2a4a483e727dfa78809e4b..4ca10501647b33573af8ef917810e7c199b97e4d 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -2742,6 +2742,8 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep) BNX2X_DOORBELL_PCI_BAR); reg_off = (1 << BNX2X_DB_SHIFT) * (cid_num & 0x1FFFF); ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, 4); + if (!ep->qp.ctx_base) + return -ENOMEM; goto arm_cq; } diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index fff6f1851dc1e56779acff511c5b6c3625a9f51c..03019e07abb96443fbdb21653c27eb4d7864091e 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -754,9 +754,9 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, case ELS_LOGO: if (fip->mode == FIP_MODE_VN2VN) { if (fip->state != FIP_ST_VNMP_UP) - return -EINVAL; + goto drop; if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI) - return -EINVAL; + goto drop; } else { if (fip->state != FIP_ST_ENABLED) return 0; @@ -799,9 +799,9 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, fip->send(fip, skb); return -EINPROGRESS; drop: - kfree_skb(skb); LIBFCOE_FIP_DBG(fip, "drop els_send op %u d_id %x\n", op, ntoh24(fh->fh_d_id)); + kfree_skb(skb); return -EINVAL; } EXPORT_SYMBOL(fcoe_ctlr_els_send); diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 7d156b161482988367ac323f8182d177421d1163..53eb277313739e982348ed2055342db7bca61c94 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -93,7 +93,7 @@ static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; static int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2; static int fast_fail = 1; static int client_reserve = 1; -static char partition_name[97] = "UNKNOWN"; +static char partition_name[96] = "UNKNOWN"; static unsigned int partition_number = -1; static LIST_HEAD(ibmvscsi_head); @@ -262,7 +262,7 @@ static void gather_partition_info(void) ppartition_name = of_get_property(of_root, "ibm,partition-name", NULL); if (ppartition_name) - strncpy(partition_name, ppartition_name, + strlcpy(partition_name, ppartition_name, sizeof(partition_name)); p_number_ptr = of_get_property(of_root, "ibm,partition-no", NULL); if (p_number_ptr) diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 8660f923ace02120eb63c2ac11724448d4cbd060..bb9c1c01664390a31ddb7fd225825467bf95f134 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -294,9 +294,11 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) * discovery, reverify or log them in. Otherwise, log them out. * Skip ports which were never discovered. These are the dNS port * and ports which were created by PLOGI. + * + * We don't need to use the _rcu variant here as the rport list + * is protected by the disc mutex which is already held on entry. */ - rcu_read_lock(); - list_for_each_entry_rcu(rdata, &disc->rports, peers) { + list_for_each_entry(rdata, &disc->rports, peers) { if (!kref_get_unless_zero(&rdata->kref)) continue; if (rdata->disc_id) { @@ -307,7 +309,6 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) } kref_put(&rdata->kref, fc_rport_destroy); } - rcu_read_unlock(); mutex_unlock(&disc->disc_mutex); disc->disc_callback(lport, event); mutex_lock(&disc->disc_mutex); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 31d31aad3de1d3fd0f2ff58d2141cabddec474bf..89b1f1af2fd456c38e45e0a905af9a76385c1d89 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -2164,6 +2164,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", fc_rport_state(rdata)); + rdata->flags &= ~FC_RP_STARTED; fc_rport_enter_delete(rdata, RPORT_EV_STOP); mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, fc_rport_destroy); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index bddbe2da528340b930e93c49134b9ab7b5c15067..cf8a15e54d83ff7de8e01e6791a61e65749495ec 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -284,11 +284,11 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) { iscsi_conn_printk(KERN_INFO, conn, - "task [op %x/%x itt " + "task [op %x itt " "0x%x/0x%x] " "rejected.\n", - task->hdr->opcode, opcode, - task->itt, task->hdr_itt); + opcode, task->itt, + task->hdr_itt); return -EACCES; } /* @@ -297,10 +297,10 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) */ if (conn->session->fast_abort) { iscsi_conn_printk(KERN_INFO, conn, - "task [op %x/%x itt " + "task [op %x itt " "0x%x/0x%x] fast abort.\n", - task->hdr->opcode, opcode, - task->itt, task->hdr_itt); + opcode, task->itt, + task->hdr_itt); return -EACCES; } break; diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 8eb3f96fe06896ca091e634cf55b8e76819d0dec..bc61cc8bc6f0227dfb37af5bb23a279c96e19e8f 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -676,7 +676,7 @@ struct lpfc_hba { #define LS_NPIV_FAB_SUPPORTED 0x2 /* Fabric supports NPIV */ #define LS_IGNORE_ERATT 0x4 /* intr handler should ignore ERATT */ #define LS_MDS_LINK_DOWN 0x8 /* MDS Diagnostics Link Down */ -#define LS_MDS_LOOPBACK 0x16 /* MDS Diagnostics Link Up (Loopback) */ +#define LS_MDS_LOOPBACK 0x10 /* MDS Diagnostics Link Up (Loopback) */ uint32_t hba_flag; /* hba generic flags */ #define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 985378e4bb6ff02ed3327bf719628508e1fee434..d55c365be2388dce37f72f30f5cc005a0153c909 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -6597,6 +6597,9 @@ megasas_resume(struct pci_dev *pdev) goto fail_init_mfi; } + if (megasas_get_ctrl_info(instance) != DCMD_SUCCESS) + goto fail_init_mfi; + tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, (unsigned long)instance); diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index d3940c5d079dc728ada053fc6ca6023fdd5cc02b..63dd9bc21ff2db8d01339a5196c1763b514191dc 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -1936,12 +1936,12 @@ _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", __func__, ioc->name); rc = -EFAULT; - goto out; + goto job_done; } rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex); if (rc) - goto out; + goto job_done; if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name, @@ -2066,6 +2066,7 @@ _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, out: ioc->transport_cmds.status = MPT3_CMD_NOT_USED; mutex_unlock(&ioc->transport_cmds.mutex); +job_done: bsg_job_done(job, rc, reslen); } diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 382edb79a0de99f4bda0551cf999ec3a20a3ad56..56bcdd412d268ad6c6ea6d11b960422eef08344d 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3240,6 +3240,11 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) init_completion(&qedf->flogi_compl); + status = qed_ops->common->update_drv_state(qedf->cdev, true); + if (status) + QEDF_ERR(&(qedf->dbg_ctx), + "Failed to send drv state to MFW.\n"); + memset(&link_params, 0, sizeof(struct qed_link_params)); link_params.link_up = true; status = qed_ops->common->set_link(qedf->cdev, &link_params); @@ -3288,6 +3293,7 @@ static int qedf_probe(struct pci_dev *pdev, const struct pci_device_id *id) static void __qedf_remove(struct pci_dev *pdev, int mode) { struct qedf_ctx *qedf; + int rc; if (!pdev) { QEDF_ERR(NULL, "pdev is NULL.\n"); @@ -3382,6 +3388,12 @@ static void __qedf_remove(struct pci_dev *pdev, int mode) qed_ops->common->set_power_state(qedf->cdev, PCI_D0); pci_set_drvdata(pdev, NULL); } + + rc = qed_ops->common->update_drv_state(qedf->cdev, false); + if (rc) + QEDF_ERR(&(qedf->dbg_ctx), + "Failed to send drv state to MFW.\n"); + qed_ops->common->slowpath_stop(qedf->cdev); qed_ops->common->remove(qedf->cdev); diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 1573749fe615cb5941db790e3668759c40fec2ae..e7daadc089fcbea1212507bad7313aac78fdadbe 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -2087,6 +2087,7 @@ static int qedi_setup_boot_info(struct qedi_ctx *qedi) static void __qedi_remove(struct pci_dev *pdev, int mode) { struct qedi_ctx *qedi = pci_get_drvdata(pdev); + int rval; if (qedi->tmf_thread) { flush_workqueue(qedi->tmf_thread); @@ -2116,6 +2117,10 @@ static void __qedi_remove(struct pci_dev *pdev, int mode) if (mode == QEDI_MODE_NORMAL) qedi_free_iscsi_pf_param(qedi); + rval = qedi_ops->common->update_drv_state(qedi->cdev, false); + if (rval) + QEDI_ERR(&qedi->dbg_ctx, "Failed to send drv state to MFW\n"); + if (!test_bit(QEDI_IN_OFFLINE, &qedi->flags)) { qedi_ops->common->slowpath_stop(qedi->cdev); qedi_ops->common->remove(qedi->cdev); @@ -2390,6 +2395,12 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) if (qedi_setup_boot_info(qedi)) QEDI_ERR(&qedi->dbg_ctx, "No iSCSI boot target configured\n"); + + rc = qedi_ops->common->update_drv_state(qedi->cdev, true); + if (rc) + QEDI_ERR(&qedi->dbg_ctx, + "Failed to send drv state to MFW\n"); + } return 0; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 0773c6ee2428573498beeb6a746803782f72ab49..761e8b5669b05d530ed0a7a6f2858c11ad8eca7e 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -721,8 +721,24 @@ static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (device_remove_file_self(dev, attr)) - scsi_remove_device(to_scsi_device(dev)); + struct kernfs_node *kn; + + kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); + WARN_ON_ONCE(!kn); + /* + * Concurrent writes into the "delete" sysfs attribute may trigger + * concurrent calls to device_remove_file() and scsi_remove_device(). + * device_remove_file() handles concurrent removal calls by + * serializing these and by ignoring the second and later removal + * attempts. Concurrent calls of scsi_remove_device() are + * serialized. The second and later calls of scsi_remove_device() are + * ignored because the first call of that function changes the device + * state into SDEV_DEL. + */ + device_remove_file(dev, attr); + scsi_remove_device(to_scsi_device(dev)); + if (kn) + sysfs_unbreak_active_protection(kn); return count; }; static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete); diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 15e0eb99bdacf85ae7ef6ca3e7410cafc4539614..f67ff8b4e108b257e85e2d61f31e185ee4220f93 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -940,6 +940,7 @@ static int ufs_qcom_crypto_req_setup(struct ufs_hba *hba, /* Use request LBA or given dun as the DUN value */ if (req->bio) { +#ifdef CONFIG_PFK if (bio_dun(req->bio)) { /* dun @bio can be split, so we have to adjust offset */ *dun = bio_dun(req->bio); @@ -947,8 +948,11 @@ static int ufs_qcom_crypto_req_setup(struct ufs_hba *hba, *dun = req->bio->bi_iter.bi_sector; *dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB; } +#else + *dun = req->bio->bi_iter.bi_sector; + *dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB; +#endif } - ret = ufs_qcom_ice_req_setup(host, lrbp->cmd, cc_index, enable); return ret; @@ -1343,11 +1347,11 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) /* * If we are here to disable this clock it might be immediately * after entering into hibern8 in which case we need to make - * sure that device ref_clk is active at least 1us after the - * hibern8 enter. + * sure that device ref_clk is active for a given time after the + * hibern8 enter for pre UFS3.0 devices */ if (!enable) - udelay(1); + udelay(host->hba->dev_ref_clk_gating_wait); writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio); diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 7ab94b585b85ff672f997d8bed5d5b03fa1e4b4c..02840d6e739b07791bcd8e31c5c4a9878dc9258e 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -504,6 +504,7 @@ struct ufs_dev_info { u8 b_device_sub_class; u16 w_manufacturer_id; u8 i_product_name; + u16 w_spec_version; /* query flags */ bool f_power_on_wp_en; @@ -527,6 +528,7 @@ struct ufs_dev_info { struct ufs_dev_desc { u16 wmanufacturerid; char model[MAX_MODEL_LEN + 1]; + u16 wspecversion; }; #endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6d529fe02aecc0118a70942a612de35029c3c80b..af90101de8946ce526710025d3eb296547ea8836 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -244,6 +244,9 @@ static void ufshcd_update_uic_error_cnt(struct ufs_hba *hba, u32 reg, int type) /* default value of auto suspend is 3 seconds */ #define UFSHCD_AUTO_SUSPEND_DELAY_MS 3000 /* millisecs */ +/* default value of ref clock gating wait time is 100 micro seconds */ +#define UFSHCD_REF_CLK_GATING_WAIT_US 100 /* microsecs */ + #define UFSHCD_CLK_GATING_DELAY_MS_PWR_SAVE 10 #define UFSHCD_CLK_GATING_DELAY_MS_PERF 50 @@ -8229,6 +8232,9 @@ static int ufs_get_device_desc(struct ufs_hba *hba, /* Null terminate the model string */ dev_desc->model[MAX_MODEL_LEN] = '\0'; + dev_desc->wspecversion = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | + desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1]; + out: return err; } @@ -8551,6 +8557,32 @@ static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba) return err; } +static int ufshcd_get_dev_ref_clk_gating_wait(struct ufs_hba *hba, + struct ufs_dev_desc *dev_desc) +{ + int err = 0; + u32 gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; + + if (dev_desc->wspecversion >= 0x300) { + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME, 0, 0, + &gating_wait); + + if (err) + dev_err(hba->dev, "failed reading bRefClkGatingWait. err = %d, use default %uus\n", + err, gating_wait); + + if (gating_wait == 0) { + gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; + dev_err(hba->dev, "undefined ref clk gating wait time, use default %uus\n", + gating_wait); + } + } + + hba->dev_ref_clk_gating_wait = gating_wait; + return err; +} + static int ufs_read_device_desc_data(struct ufs_hba *hba) { int err; @@ -8579,6 +8611,9 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba) hba->dev_info.b_device_sub_class = desc_buf[DEVICE_DESC_PARAM_DEVICE_SUB_CLASS]; hba->dev_info.i_product_name = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; + hba->dev_info.w_spec_version = + desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | + desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1]; return 0; } @@ -8652,6 +8687,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) "%s: Failed getting max supported power mode\n", __func__); } else { + ufshcd_get_dev_ref_clk_gating_wait(hba, &card); + /* * Set the right value to bRefClkFreq before attempting to * switch to HS gears. diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index af79660f8889888effd55869156643996efc9e7a..4fb4f57fdeb37bab44dc47a9ec19b499589dfe77 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -814,6 +814,7 @@ struct ufs_hba { unsigned int irq; bool is_irq_enabled; + u32 dev_ref_clk_gating_wait; u32 dev_ref_clk_freq; /* Interrupt aggregation support is broken */ diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index 777e5f1e52d10968d5f23e0e316db05b8209511d..0cd947f78b5bfdfa013ce4909afdc8f894b6146b 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -561,9 +561,14 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter, (btstat == BTSTAT_SUCCESS || btstat == BTSTAT_LINKED_COMMAND_COMPLETED || btstat == BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG)) { - cmd->result = (DID_OK << 16) | sdstat; - if (sdstat == SAM_STAT_CHECK_CONDITION && cmd->sense_buffer) - cmd->result |= (DRIVER_SENSE << 24); + if (sdstat == SAM_STAT_COMMAND_TERMINATED) { + cmd->result = (DID_RESET << 16); + } else { + cmd->result = (DID_OK << 16) | sdstat; + if (sdstat == SAM_STAT_CHECK_CONDITION && + cmd->sense_buffer) + cmd->result |= (DRIVER_SENSE << 24); + } } else switch (btstat) { case BTSTAT_SUCCESS: diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c index 36f59a1be7e9a60be61c2b1ba8f7468dfbd8c6c9..61389bdc7926690100fc0a38fc59e8b6a73853ab 100644 --- a/drivers/scsi/xen-scsifront.c +++ b/drivers/scsi/xen-scsifront.c @@ -654,10 +654,17 @@ static int scsifront_dev_reset_handler(struct scsi_cmnd *sc) static int scsifront_sdev_configure(struct scsi_device *sdev) { struct vscsifrnt_info *info = shost_priv(sdev->host); + int err; - if (info && current == info->curr) - xenbus_printf(XBT_NIL, info->dev->nodename, + if (info && current == info->curr) { + err = xenbus_printf(XBT_NIL, info->dev->nodename, info->dev_state_path, "%d", XenbusStateConnected); + if (err) { + xenbus_dev_error(info->dev, err, + "%s: writing dev_state_path", __func__); + return err; + } + } return 0; } @@ -665,10 +672,15 @@ static int scsifront_sdev_configure(struct scsi_device *sdev) static void scsifront_sdev_destroy(struct scsi_device *sdev) { struct vscsifrnt_info *info = shost_priv(sdev->host); + int err; - if (info && current == info->curr) - xenbus_printf(XBT_NIL, info->dev->nodename, + if (info && current == info->curr) { + err = xenbus_printf(XBT_NIL, info->dev->nodename, info->dev_state_path, "%d", XenbusStateClosed); + if (err) + xenbus_dev_error(info->dev, err, + "%s: writing dev_state_path", __func__); + } } static struct scsi_host_template scsifront_sht = { @@ -1003,9 +1015,12 @@ static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op) if (scsi_add_device(info->host, chn, tgt, lun)) { dev_err(&dev->dev, "scsi_add_device\n"); - xenbus_printf(XBT_NIL, dev->nodename, + err = xenbus_printf(XBT_NIL, dev->nodename, info->dev_state_path, "%d", XenbusStateClosed); + if (err) + xenbus_dev_error(dev, err, + "%s: writing dev_state_path", __func__); } break; case VSCSIFRONT_OP_DEL_LUN: @@ -1019,10 +1034,14 @@ static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op) } break; case VSCSIFRONT_OP_READD_LUN: - if (device_state == XenbusStateConnected) - xenbus_printf(XBT_NIL, dev->nodename, + if (device_state == XenbusStateConnected) { + err = xenbus_printf(XBT_NIL, dev->nodename, info->dev_state_path, "%d", XenbusStateConnected); + if (err) + xenbus_dev_error(dev, err, + "%s: writing dev_state_path", __func__); + } break; default: break; diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c index 1613ccf0c0591921bd044151fb9da9778f700023..c54d229f8da49c82f1fc9e104c2003bbe019104f 100644 --- a/drivers/soc/imx/gpc.c +++ b/drivers/soc/imx/gpc.c @@ -27,9 +27,16 @@ #define GPC_PGC_SW2ISO_SHIFT 0x8 #define GPC_PGC_SW_SHIFT 0x0 +#define GPC_PGC_PCI_PDN 0x200 +#define GPC_PGC_PCI_SR 0x20c + #define GPC_PGC_GPU_PDN 0x260 #define GPC_PGC_GPU_PUPSCR 0x264 #define GPC_PGC_GPU_PDNSCR 0x268 +#define GPC_PGC_GPU_SR 0x26c + +#define GPC_PGC_DISP_PDN 0x240 +#define GPC_PGC_DISP_SR 0x24c #define GPU_VPU_PUP_REQ BIT(1) #define GPU_VPU_PDN_REQ BIT(0) @@ -303,10 +310,24 @@ static const struct of_device_id imx_gpc_dt_ids[] = { { } }; +static const struct regmap_range yes_ranges[] = { + regmap_reg_range(GPC_CNTR, GPC_CNTR), + regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR), + regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR), + regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR), +}; + +static const struct regmap_access_table access_table = { + .yes_ranges = yes_ranges, + .n_yes_ranges = ARRAY_SIZE(yes_ranges), +}; + static const struct regmap_config imx_gpc_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .rd_table = &access_table, + .wr_table = &access_table, .max_register = 0x2ac, }; diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index f4e3bd40c72e60c0448c98456f7b53f6be7936bd..6ef18cf8f24387e324cf455ae98c30f2b27c95d3 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -39,10 +39,15 @@ #define GPC_M4_PU_PDN_FLG 0x1bc - -#define PGC_MIPI 4 -#define PGC_PCIE 5 -#define PGC_USB_HSIC 8 +/* + * The PGC offset values in Reference Manual + * (Rev. 1, 01/2018 and the older ones) GPC chapter's + * GPC_PGC memory map are incorrect, below offset + * values are from design RTL. + */ +#define PGC_MIPI 16 +#define PGC_PCIE 17 +#define PGC_USB_HSIC 20 #define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) #define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 3647c0e2af36f71bbc4ca14c5da62be9e7d5ce2d..eb3ed076ccbc819ab57b2a1b8b8defb7aaeeb31e 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -277,6 +277,7 @@ config QCOM_SMEM_STATE config QCOM_SMP2P tristate "Qualcomm Shared Memory Point to Point support" + depends on MAILBOX depends on QCOM_SMEM select QCOM_SMEM_STATE help diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index 22b44648a4029a16114d807b2f16a751de59e368..758717ca00549f8974101165585824291eb23fbb 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -352,6 +352,7 @@ static int cmd_db_dev_probe(struct platform_device *pdev) dict = of_iomap(pdev->dev.of_node, 0); if (!dict) { cmd_db_status = -ENOMEM; + pr_err("Command DB dictionary addr not found.\n"); goto failed; } @@ -372,6 +373,7 @@ static int cmd_db_dev_probe(struct platform_device *pdev) if (!cmd_db_header) { cmd_db_status = -ENOMEM; + pr_err("Command DB header not found.\n"); goto failed; } diff --git a/drivers/soc/qcom/dfc_qmi.c b/drivers/soc/qcom/dfc_qmi.c index 95d7443334a1b181d1d882b10f89922bfc6229f2..8c3047544c0b128ba24d3ad4c7996ba29345ba4c 100644 --- a/drivers/soc/qcom/dfc_qmi.c +++ b/drivers/soc/qcom/dfc_qmi.c @@ -58,12 +58,15 @@ struct dfc_qmi_data { struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; + struct svc_info svc; + struct work_struct qmi_ind_work; + struct list_head qmi_ind_q; + spinlock_t qmi_ind_lock; int index; int restart_state; }; static void dfc_svc_init(struct work_struct *work); -static void dfc_do_burst_flow_control(struct work_struct *work); /* **************************************************** */ #define DFC_SERVICE_ID_V01 0x4E @@ -307,8 +310,7 @@ struct dfc_flow_status_ind_msg_v01 { }; struct dfc_svc_ind { - struct work_struct work; - struct dfc_qmi_data *data; + struct list_head list; struct dfc_flow_status_ind_msg_v01 dfc_info; }; @@ -618,12 +620,11 @@ dfc_indication_register_req(struct qmi_handle *dfc_handle, return ret; } -static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) +static int dfc_init_service(struct dfc_qmi_data *data) { int rc; - rc = dfc_bind_client_req(&data->handle, &data->ssctl, - &qmi->fc_info[data->index].svc); + rc = dfc_bind_client_req(&data->handle, &data->ssctl, &data->svc); if (rc < 0) return rc; @@ -674,16 +675,13 @@ static int dfc_bearer_flow_ctl(struct net_device *dev, struct rmnet_bearer_map *bearer, struct qos_info *qos) { - struct list_head *p; struct rmnet_flow_map *itm; int rc = 0, qlen; int enable; enable = bearer->grant_size ? 1 : 0; - list_for_each(p, &qos->flow_head) { - itm = list_entry(p, struct rmnet_flow_map, list); - + list_for_each_entry(itm, &qos->flow_head, list) { if (itm->bearer_id == bearer->bearer_id) { /* * Do not flow disable ancillary q if ancillary is true @@ -713,14 +711,14 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, u8 ack_req, u32 ancillary, struct dfc_flow_status_info_type_v01 *fc_info) { - struct list_head *p; - struct rmnet_bearer_map *bearer_itm = NULL; - int enable; - int rc = 0; + struct rmnet_bearer_map *bearer_itm; + struct rmnet_flow_map *flow_itm; + int rc = 0, qlen; + bool enable; - list_for_each(p, &qos->bearer_head) { - bearer_itm = list_entry(p, struct rmnet_bearer_map, list); + enable = fc_info->num_bytes > 0 ? 1 : 0; + list_for_each_entry(bearer_itm, &qos->bearer_head, list) { bearer_itm->grant_size = fc_info->num_bytes; bearer_itm->grant_thresh = qmi_rmnet_grant_per(bearer_itm->grant_size); @@ -729,14 +727,14 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, bearer_itm->ancillary = ancillary; } - enable = fc_info->num_bytes > 0 ? 1 : 0; - - if (enable) - netif_tx_wake_all_queues(dev); - else - netif_tx_stop_all_queues(dev); - - trace_dfc_qmi_tc(dev->name, 0xFF, 0, fc_info->num_bytes, 0, 0, enable); + list_for_each_entry(flow_itm, &qos->flow_head, list) { + qlen = qmi_rmnet_flow_control(dev, flow_itm->tcm_handle, + enable); + trace_dfc_qmi_tc(dev->name, flow_itm->bearer_id, + flow_itm->flow_id, fc_info->num_bytes, + qlen, flow_itm->tcm_handle, enable); + rc++; + } if (enable == 0 && ack_req) dfc_send_ack(dev, fc_info->bearer_id, @@ -776,9 +774,9 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, return rc; } -static void dfc_do_burst_flow_control(struct work_struct *work) +static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, + struct dfc_svc_ind *svc_ind) { - struct dfc_svc_ind *svc_ind = (struct dfc_svc_ind *)work; struct dfc_flow_status_ind_msg_v01 *ind = &svc_ind->dfc_info; struct net_device *dev; struct qos_info *qos; @@ -788,11 +786,6 @@ static void dfc_do_burst_flow_control(struct work_struct *work) u32 ancillary; int i, j; - if (unlikely(svc_ind->data->restart_state)) { - kfree(svc_ind); - return; - } - rcu_read_lock(); for (i = 0; i < ind->flow_status_len; i++) { @@ -810,7 +803,7 @@ static void dfc_do_burst_flow_control(struct work_struct *work) } } - trace_dfc_flow_ind(svc_ind->data->index, + trace_dfc_flow_ind(dfc->index, i, flow_status->mux_id, flow_status->bearer_id, flow_status->num_bytes, @@ -818,7 +811,7 @@ static void dfc_do_burst_flow_control(struct work_struct *work) ack_req, ancillary); - dev = rmnet_get_rmnet_dev(svc_ind->data->rmnet_port, + dev = rmnet_get_rmnet_dev(dfc->rmnet_port, flow_status->mux_id); if (!dev) goto clean_out; @@ -841,7 +834,36 @@ static void dfc_do_burst_flow_control(struct work_struct *work) clean_out: rcu_read_unlock(); - kfree(svc_ind); +} + +static void dfc_qmi_ind_work(struct work_struct *work) +{ + struct dfc_qmi_data *dfc = container_of(work, struct dfc_qmi_data, + qmi_ind_work); + struct dfc_svc_ind *svc_ind; + unsigned long flags; + + if (!dfc) + return; + + local_bh_disable(); + + do { + spin_lock_irqsave(&dfc->qmi_ind_lock, flags); + svc_ind = list_first_entry_or_null(&dfc->qmi_ind_q, + struct dfc_svc_ind, list); + if (svc_ind) + list_del(&svc_ind->list); + spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags); + + if (svc_ind) { + if (!dfc->restart_state) + dfc_do_burst_flow_control(dfc, svc_ind); + kfree(svc_ind); + } + } while (svc_ind != NULL); + + local_bh_enable(); } static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, @@ -851,6 +873,7 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, handle); struct dfc_flow_status_ind_msg_v01 *ind_msg; struct dfc_svc_ind *svc_ind; + unsigned long flags; if (qmi != &dfc->handle) return; @@ -867,13 +890,13 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, if (!svc_ind) return; - INIT_WORK((struct work_struct *)svc_ind, - dfc_do_burst_flow_control); - memcpy(&svc_ind->dfc_info, ind_msg, sizeof(*ind_msg)); - svc_ind->data = dfc; - queue_work(dfc->dfc_wq, (struct work_struct *)svc_ind); + spin_lock_irqsave(&dfc->qmi_ind_lock, flags); + list_add_tail(&svc_ind->list, &dfc->qmi_ind_q); + spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags); + + queue_work(dfc->dfc_wq, &dfc->qmi_ind_work); } } @@ -884,19 +907,26 @@ static void dfc_svc_init(struct work_struct *work) svc_arrive); struct qmi_info *qmi; - qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); - if (!qmi) - goto clean_out; - - rc = dfc_init_service(data, qmi); + rc = dfc_init_service(data); if (rc < 0) goto clean_out; - qmi->fc_info[data->index].dfc_client = (void *)data; trace_dfc_client_state_up(data->index, - qmi->fc_info[data->index].svc.instance, - qmi->fc_info[data->index].svc.ep_type, - qmi->fc_info[data->index].svc.iface_id); + data->svc.instance, + data->svc.ep_type, + data->svc.iface_id); + + rtnl_lock(); + qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); + if (!qmi) { + rtnl_unlock(); + goto clean_out; + } + + qmi->dfc_clients[data->index] = (void *)data; + rtnl_unlock(); + + pr_info("Connection established with the DFC Service\n"); return; clean_out: @@ -944,7 +974,7 @@ static struct qmi_msg_handler qmi_indication_handler[] = { {}, }; -int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) +int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc) { struct dfc_qmi_data *data; int rc = -ENOMEM; @@ -956,6 +986,11 @@ int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) data->rmnet_port = port; data->index = index; data->restart_state = 0; + memcpy(&data->svc, psvc, sizeof(data->svc)); + + INIT_WORK(&data->qmi_ind_work, dfc_qmi_ind_work); + INIT_LIST_HEAD(&data->qmi_ind_q); + spin_lock_init(&data->qmi_ind_lock); data->dfc_wq = create_singlethread_workqueue("dfc_wq"); if (!data->dfc_wq) { @@ -974,7 +1009,7 @@ int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01, DFC_SERVICE_VERS_V01, - qmi->fc_info[index].svc.instance); + psvc->instance); if (rc < 0) { pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc); goto err2; @@ -1058,7 +1093,7 @@ void dfc_qmi_wq_flush(struct qmi_info *qmi) int i; for (i = 0; i < MAX_CLIENT_NUM; i++) { - dfc_data = (struct dfc_qmi_data *)(qmi->fc_info[i].dfc_client); + dfc_data = (struct dfc_qmi_data *)(qmi->dfc_clients[i]); if (dfc_data) flush_workqueue(dfc_data->dfc_wq); } diff --git a/drivers/soc/qcom/fsa4480-i2c.c b/drivers/soc/qcom/fsa4480-i2c.c index 8d4b37d5ec878f04a66389e52e4b2f81e86f988f..fea0b13feea7e18afe32491889b43d196cd41c58 100644 --- a/drivers/soc/qcom/fsa4480-i2c.c +++ b/drivers/soc/qcom/fsa4480-i2c.c @@ -123,6 +123,7 @@ static int fsa4480_usbc_event_changed(struct notifier_block *nb, dev_dbg(dev, "%s: queueing usbc_analog_work\n", __func__); + pm_stay_awake(fsa_priv->dev); schedule_work(&fsa_priv->usbc_analog_work); break; default: @@ -303,6 +304,7 @@ static void fsa4480_usbc_analog_work_fn(struct work_struct *work) } fsa4480_usbc_analog_setup_switches(fsa_priv, atomic_read(&(fsa_priv->usbc_mode)) != POWER_SUPPLY_TYPEC_NONE); + pm_relax(fsa_priv->dev); } static void fsa4480_update_reg_defaults(struct regmap *regmap) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index a4356a45a2af1384e069241de9bd15586f7bd7b2..4e59b04cc2d9fe1937de87b33c1cfcf58358b941 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -610,7 +610,8 @@ bool icnss_is_fw_down(void) return false; return test_bit(ICNSS_FW_DOWN, &penv->state) || - test_bit(ICNSS_PD_RESTART, &penv->state); + test_bit(ICNSS_PD_RESTART, &penv->state) || + test_bit(ICNSS_REJUVENATE, &penv->state); } EXPORT_SYMBOL(icnss_is_fw_down); @@ -775,12 +776,14 @@ int icnss_call_driver_uevent(struct icnss_priv *priv, static int icnss_driver_event_server_arrive(void *data) { int ret = 0; + bool ignore_assert = false; if (!penv) return -ENODEV; set_bit(ICNSS_WLFW_EXISTS, &penv->state); clear_bit(ICNSS_FW_DOWN, &penv->state); + icnss_ignore_fw_timeout(false); ret = icnss_connect_to_fw_server(penv, data); if (ret) @@ -793,8 +796,10 @@ static int icnss_driver_event_server_arrive(void *data) goto clear_server; ret = wlfw_ind_register_send_sync_msg(penv); - if (ret < 0) + if (ret < 0) { + ignore_assert = true; goto err_power_on; + } if (!penv->msa_va) { icnss_pr_err("Invalid MSA address\n"); @@ -803,8 +808,10 @@ static int icnss_driver_event_server_arrive(void *data) } ret = wlfw_msa_mem_info_send_sync_msg(penv); - if (ret < 0) + if (ret < 0) { + ignore_assert = true; goto err_power_on; + } if (!test_bit(ICNSS_MSA0_ASSIGNED, &penv->state)) { ret = icnss_assign_msa_perm_all(penv, @@ -815,12 +822,16 @@ static int icnss_driver_event_server_arrive(void *data) } ret = wlfw_msa_ready_send_sync_msg(penv); - if (ret < 0) + if (ret < 0) { + ignore_assert = true; goto err_setup_msa; + } ret = wlfw_cap_send_sync_msg(penv); - if (ret < 0) + if (ret < 0) { + ignore_assert = true; goto err_setup_msa; + } wlfw_dynamic_feature_mask_send_sync_msg(penv, dynamic_feature_mask); @@ -841,7 +852,7 @@ static int icnss_driver_event_server_arrive(void *data) clear_server: icnss_clear_server(penv); fail: - ICNSS_ASSERT(0); + ICNSS_ASSERT(ignore_assert); return ret; } @@ -972,6 +983,7 @@ static int icnss_driver_event_fw_ready_ind(void *data) return -ENODEV; set_bit(ICNSS_FW_READY, &penv->state); + clear_bit(ICNSS_MODE_ON, &penv->state); icnss_pr_info("WLAN FW is ready: 0x%lx\n", penv->state); @@ -1090,8 +1102,13 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv, int ret = 0; struct icnss_event_pd_service_down_data *event_data = data; - if (!test_bit(ICNSS_WLFW_EXISTS, &priv->state)) + if (!test_bit(ICNSS_WLFW_EXISTS, &priv->state)) { + icnss_ignore_fw_timeout(false); goto out; + } + + if (priv->force_err_fatal) + ICNSS_ASSERT(0); if (priv->early_crash_ind) { icnss_pr_dbg("PD Down ignored as early indication is processed: %d, state: 0x%lx\n", @@ -1107,16 +1124,11 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv, goto out; } - if (priv->force_err_fatal) - ICNSS_ASSERT(0); - icnss_fw_crashed(priv, event_data); out: kfree(data); - icnss_ignore_fw_timeout(false); - return ret; } @@ -1125,15 +1137,16 @@ static int icnss_driver_event_early_crash_ind(struct icnss_priv *priv, { int ret = 0; - if (!test_bit(ICNSS_WLFW_EXISTS, &priv->state)) + if (!test_bit(ICNSS_WLFW_EXISTS, &priv->state)) { + icnss_ignore_fw_timeout(false); goto out; + } priv->early_crash_ind = true; icnss_fw_crashed(priv, NULL); out: kfree(data); - icnss_ignore_fw_timeout(false); return ret; } @@ -1798,7 +1811,8 @@ int icnss_set_fw_log_mode(struct device *dev, uint8_t fw_log_mode) if (!dev) return -ENODEV; - if (test_bit(ICNSS_FW_DOWN, &penv->state)) { + if (test_bit(ICNSS_FW_DOWN, &penv->state) || + !test_bit(ICNSS_FW_READY, &penv->state)) { icnss_pr_err("FW down, ignoring fw_log_mode state: 0x%lx\n", penv->state); return -EINVAL; @@ -1890,12 +1904,19 @@ int icnss_wlan_enable(struct device *dev, struct icnss_wlan_enable_cfg *config, enum icnss_driver_mode mode, const char *host_version) { - if (test_bit(ICNSS_FW_DOWN, &penv->state)) { + if (test_bit(ICNSS_FW_DOWN, &penv->state) || + !test_bit(ICNSS_FW_READY, &penv->state)) { icnss_pr_err("FW down, ignoring wlan_enable state: 0x%lx\n", penv->state); return -EINVAL; } + if (test_bit(ICNSS_MODE_ON, &penv->state)) { + icnss_pr_err("Already Mode on, ignoring wlan_enable state: 0x%lx\n", + penv->state); + return -EINVAL; + } + return icnss_send_wlan_enable_to_fw(penv, config, mode, host_version); } EXPORT_SYMBOL(icnss_wlan_enable); @@ -2068,6 +2089,7 @@ static int icnss_smmu_init(struct icnss_priv *priv) int atomic_ctx = 1; int s1_bypass = 1; int fast = 1; + int stall_disable = 1; int ret = 0; icnss_pr_dbg("Initializing SMMU\n"); @@ -2111,6 +2133,16 @@ static int icnss_smmu_init(struct icnss_priv *priv) goto set_attr_fail; } icnss_pr_dbg("SMMU FAST map set\n"); + + ret = iommu_domain_set_attr(mapping->domain, + DOMAIN_ATTR_CB_STALL_DISABLE, + &stall_disable); + if (ret < 0) { + icnss_pr_err("Set stall disable map attribute failed, err = %d\n", + ret); + goto set_attr_fail; + } + icnss_pr_dbg("SMMU STALL DISABLE map set\n"); } ret = arm_iommu_attach_device(&priv->pdev->dev, mapping); @@ -2538,6 +2570,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) continue; case ICNSS_REJUVENATE: seq_puts(s, "FW REJUVENATE"); + continue; + case ICNSS_MODE_ON: + seq_puts(s, "MODE ON DONE"); } seq_printf(s, "UNKNOWN-%d", i); diff --git a/drivers/soc/qcom/icnss_private.h b/drivers/soc/qcom/icnss_private.h index 7fc3c9cbf9f076024d2f3efa5216cbf9248dc0f1..4d524e7f4197a2459e10ffcaa156d22554f80617 100644 --- a/drivers/soc/qcom/icnss_private.h +++ b/drivers/soc/qcom/icnss_private.h @@ -155,6 +155,7 @@ enum icnss_driver_state { ICNSS_FW_DOWN, ICNSS_DRIVER_UNLOADING, ICNSS_REJUVENATE, + ICNSS_MODE_ON, }; struct ce_irq_list { diff --git a/drivers/soc/qcom/icnss_qmi.c b/drivers/soc/qcom/icnss_qmi.c index 0aefbe99ddcff223707694fcc9cfe14340c86e79..8d391c47fa2b3722398674f344a5f55b8bb2cff3 100644 --- a/drivers/soc/qcom/icnss_qmi.c +++ b/drivers/soc/qcom/icnss_qmi.c @@ -471,6 +471,16 @@ int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv, priv->stats.mode_resp++; + if (mode == QMI_WLFW_OFF_V01) { + icnss_pr_dbg("Clear mode on 0x%lx, mode: %d\n", + priv->state, mode); + clear_bit(ICNSS_MODE_ON, &priv->state); + } else { + icnss_pr_dbg("Set mode on 0x%lx, mode: %d\n", + priv->state, mode); + set_bit(ICNSS_MODE_ON, &priv->state); + } + kfree(resp); kfree(req); return 0; diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index 44c035fbe06982557021291ae46d9510e45c8f7b..937399141bd4abbcd77f5b36c09ed58f8c49bceb 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -605,6 +605,7 @@ static struct socket *qmi_sock_create(struct qmi_handle *qmi, sock->sk->sk_user_data = qmi; sock->sk->sk_data_ready = qmi_data_ready; sock->sk->sk_error_report = qmi_data_ready; + sock->sk->sk_sndtimeo = HZ * 10; return sock; } diff --git a/drivers/soc/qcom/qmi_rmnet.c b/drivers/soc/qcom/qmi_rmnet.c index d1c4eb7992d50810b4ff662bce5399ed1a30dfcb..e3996137d6a7c26a3e6d60879c0b2d82ec730217 100644 --- a/drivers/soc/qcom/qmi_rmnet.c +++ b/drivers/soc/qcom/qmi_rmnet.c @@ -33,12 +33,13 @@ #define FLAG_POWERSAVE_MASK 0x0010 #define DFC_MODE_MULTIQ 2 -unsigned int rmnet_wq_frequency __read_mostly = 4; +unsigned int rmnet_wq_frequency __read_mostly = 1000; module_param(rmnet_wq_frequency, uint, 0644); -MODULE_PARM_DESC(rmnet_wq_frequency, "Frequency of PS check"); +MODULE_PARM_DESC(rmnet_wq_frequency, "Frequency of PS check in ms"); #define PS_WORK_ACTIVE_BIT 0 -#define PS_INTERVAL (((!rmnet_wq_frequency) ? 1 : rmnet_wq_frequency) * HZ) +#define PS_INTERVAL (((!rmnet_wq_frequency) ? \ + 1 : rmnet_wq_frequency/10) * (HZ/100)) #define NO_DELAY (0x0000 * HZ) #ifdef CONFIG_QCOM_QMI_DFC @@ -86,8 +87,8 @@ void *qmi_rmnet_has_dfc_client(struct qmi_info *qmi) return NULL; for (i = 0; i < MAX_CLIENT_NUM; i++) { - if (qmi->fc_info[i].dfc_client) - return qmi->fc_info[i].dfc_client; + if (qmi->dfc_clients[i]) + return qmi->dfc_clients[i]; } return NULL; @@ -364,6 +365,7 @@ static int qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) { int idx, rc, err = 0; + struct svc_info svc; ASSERT_RTNL(); @@ -374,7 +376,7 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) idx = (tcm->tcm_handle == 0) ? 0 : 1; if (!qmi) { - qmi = kzalloc(sizeof(struct qmi_info), GFP_KERNEL); + qmi = kzalloc(sizeof(struct qmi_info), GFP_ATOMIC); if (!qmi) return -ENOMEM; @@ -382,20 +384,20 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) } qmi->flag = tcm->tcm_ifindex; - qmi->fc_info[idx].svc.instance = tcm->tcm_handle; - qmi->fc_info[idx].svc.ep_type = tcm->tcm_info; - qmi->fc_info[idx].svc.iface_id = tcm->tcm_parent; + svc.instance = tcm->tcm_handle; + svc.ep_type = tcm->tcm_info; + svc.iface_id = tcm->tcm_parent; if (((tcm->tcm_ifindex & FLAG_DFC_MASK) == DFC_MODE_MULTIQ) && - (qmi->fc_info[idx].dfc_client == NULL)) { - rc = dfc_qmi_client_init(port, idx, qmi); + (qmi->dfc_clients[idx] == NULL)) { + rc = dfc_qmi_client_init(port, idx, &svc); if (rc < 0) err = rc; } if ((tcm->tcm_ifindex & FLAG_POWERSAVE_MASK) && (idx == 0) && (qmi->wda_client == NULL)) { - rc = wda_qmi_client_init(port, tcm->tcm_handle); + rc = wda_qmi_client_init(port, &svc); if (rc < 0) err = rc; } @@ -406,12 +408,11 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) static int __qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, int idx) { - ASSERT_RTNL(); - if (qmi->fc_info[idx].dfc_client) { - dfc_qmi_client_exit(qmi->fc_info[idx].dfc_client); - qmi->fc_info[idx].dfc_client = NULL; + if (qmi->dfc_clients[idx]) { + dfc_qmi_client_exit(qmi->dfc_clients[idx]); + qmi->dfc_clients[idx] = NULL; } if (!qmi_rmnet_has_client(qmi)) { diff --git a/drivers/soc/qcom/qmi_rmnet_i.h b/drivers/soc/qcom/qmi_rmnet_i.h index 2f7c262d26e6580331505c64bf2124ac605a3285..d076dcbcd40682b03df54c99808a154504e4ef6c 100644 --- a/drivers/soc/qcom/qmi_rmnet_i.h +++ b/drivers/soc/qcom/qmi_rmnet_i.h @@ -51,11 +51,6 @@ struct svc_info { u32 iface_id; }; -struct fc_info { - struct svc_info svc; - void *dfc_client; -}; - struct qos_info { u8 mux_id; struct net_device *real_dev; @@ -74,7 +69,7 @@ struct flow_info { struct qmi_info { int flag; void *wda_client; - struct fc_info fc_info[MAX_CLIENT_NUM]; + void *dfc_clients[MAX_CLIENT_NUM]; unsigned long ps_work_active; int ps_enabled; }; @@ -109,7 +104,7 @@ qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id); unsigned int qmi_rmnet_grant_per(unsigned int grant); -int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi); +int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc); void dfc_qmi_client_exit(void *dfc_data); @@ -129,13 +124,13 @@ qmi_rmnet_get_flow_map(struct qos_info *qos_info, } static inline struct rmnet_bearer_map * -qmi_rmnet_get_bearer_map(struct qos_info *qos_info, uint8_t bearer_id) +qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id) { return NULL; } static inline int -dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) +dfc_qmi_client_init(void *port, int index, struct svc_info *psvc) { return -EINVAL; } @@ -157,11 +152,11 @@ dfc_qmi_wq_flush(struct qmi_info *qmi) #endif #ifdef CONFIG_QCOM_QMI_POWER_COLLAPSE -int wda_qmi_client_init(void *port, uint32_t instance); +int wda_qmi_client_init(void *port, struct svc_info *psvc); void wda_qmi_client_exit(void *wda_data); -int wda_set_powersave_mode(void *wda_data, uint8_t enable); +int wda_set_powersave_mode(void *wda_data, u8 enable); #else -static inline int wda_qmi_client_init(void *port, uint32_t instance) +static inline int wda_qmi_client_init(void *port, struct svc_info *psvc) { return -EINVAL; } @@ -170,7 +165,7 @@ static inline void wda_qmi_client_exit(void *wda_data) { } -static inline int wda_set_powersave_mode(void *wda_data, uint8_t enable) +static inline int wda_set_powersave_mode(void *wda_data, u8 enable) { return -EINVAL; } diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index fba9c25e043b70f0cce5f65e2181ea0cec162092..f2f90ee18054aff178cf485c1f4a7278ae7e636c 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,8 @@ struct smp2p_entry { * @ipc_regmap: regmap for the outbound ipc * @ipc_offset: offset within the regmap * @ipc_bit: bit in regmap@offset to kick to signal remote processor + * @mbox_client: mailbox client handle + * @mbox_chan: apcs ipc mailbox channel handle * @inbound: list of inbound entries * @outbound: list of outbound entries */ @@ -158,6 +161,9 @@ struct qcom_smp2p { int ipc_offset; int ipc_bit; + struct mbox_client mbox_client; + struct mbox_chan *mbox_chan; + struct list_head inbound; struct list_head outbound; }; @@ -174,7 +180,13 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p) { /* Make sure any updated data is written before the kick */ wmb(); - regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit)); + + if (smp2p->mbox_chan) { + mbox_send_message(smp2p->mbox_chan, NULL); + mbox_client_txdone(smp2p->mbox_chan, 0); + } else { + regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit)); + } } static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p) @@ -555,10 +567,6 @@ static int qcom_smp2p_probe(struct platform_device *pdev) platform_set_drvdata(pdev, smp2p); - ret = smp2p_parse_ipc(smp2p); - if (ret) - return ret; - key = "qcom,smem"; ret = of_property_read_u32_array(pdev->dev.of_node, key, smp2p->smem_items, 2); @@ -585,9 +593,23 @@ static int qcom_smp2p_probe(struct platform_device *pdev) return smp2p->irq; } + smp2p->mbox_client.dev = &pdev->dev; + smp2p->mbox_client.knows_txdone = true; + smp2p->mbox_chan = mbox_request_channel(&smp2p->mbox_client, 0); + if (IS_ERR(smp2p->mbox_chan)) { + if (PTR_ERR(smp2p->mbox_chan) != -ENODEV) + return PTR_ERR(smp2p->mbox_chan); + + smp2p->mbox_chan = NULL; + + ret = smp2p_parse_ipc(smp2p); + if (ret) + return ret; + } + ret = qcom_smp2p_alloc_outbound_item(smp2p); if (ret < 0) - return ret; + goto release_mbox; for_each_available_child_of_node(pdev->dev.of_node, node) { entry = devm_kzalloc(&pdev->dev, sizeof(*entry), GFP_KERNEL); @@ -642,6 +664,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev) smp2p->out->valid_entries = 0; +release_mbox: + mbox_free_channel(smp2p->mbox_chan); + return ret; } @@ -656,6 +681,8 @@ static int qcom_smp2p_remove(struct platform_device *pdev) list_for_each_entry(entry, &smp2p->outbound, node) qcom_smem_state_unregister(entry->state); + mbox_free_channel(smp2p->mbox_chan); + smp2p->out->valid_entries = 0; return 0; diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index a19248f07c03dba9fd3db77474e907295831c463..4bac901a2f6c789672fd7df85825b5c17a6e7042 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -649,7 +649,10 @@ static int spcom_handle_send_command(struct spcom_channel *ch, mutex_unlock(&ch->lock); msleep(TX_RETRY_DELAY_MSEC); mutex_lock(&ch->lock); - } while (ret == -EAGAIN && time_msec < timeout_msec); + } while ((ret == -EBUSY || ret == -EAGAIN) && time_msec < timeout_msec); + if (ret) + pr_err("ch [%s] rpmsg_trysend() error (%d), timeout_msec=%d\n", + ch->name, ret, timeout_msec); mutex_unlock(&ch->lock); kfree(tx_buf); @@ -853,7 +856,11 @@ static int spcom_handle_send_modified_command(struct spcom_channel *ch, mutex_unlock(&ch->lock); msleep(TX_RETRY_DELAY_MSEC); mutex_lock(&ch->lock); - } while (ret == -EAGAIN && time_msec < timeout_msec); + } while ((ret == -EBUSY || ret == -EAGAIN) && time_msec < timeout_msec); + if (ret) + pr_err("ch [%s] rpmsg_trysend() error (%d), timeout_msec=%d\n", + ch->name, ret, timeout_msec); + mutex_unlock(&ch->lock); memset(tx_buf, 0, tx_buf_size); kfree(tx_buf); @@ -1425,7 +1432,7 @@ static ssize_t spcom_device_write(struct file *filp, if (ret) { pr_err("handle command error [%d].\n", ret); kfree(buf); - return -EFAULT; + return ret; } kfree(buf); diff --git a/drivers/soc/qcom/subsystem_notif.c b/drivers/soc/qcom/subsystem_notif.c index b79d988cc304e8efd3c654710adb21ce51013b4c..e6d0f12a20250d3d81c54d64cc544924cf89e67e 100644 --- a/drivers/soc/qcom/subsystem_notif.c +++ b/drivers/soc/qcom/subsystem_notif.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2013, 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011, 2013, 2016-2018, 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,10 +28,25 @@ #include #include +/** + * The callbacks that are registered in this data structure as early + * notification callbacks will be called as soon as the SSR framework is + * informed that the subsystem has crashed. This means that these functions will + * be invoked as part of an IRQ handler, and thus, will be called in an atomic + * context. Therefore, functions that are registered as early notification + * callback must obey to the same constraints as interrupt handlers + * (i.e. these functions must not sleep or block, etc). + */ +struct subsys_early_notif_info { + spinlock_t cb_lock; + void (*early_notif_cb[NUM_EARLY_NOTIFS])(void *); + void *data[NUM_EARLY_NOTIFS]; +}; struct subsys_notif_info { char name[50]; struct srcu_notifier_head subsys_notif_rcvr_list; + struct subsys_early_notif_info early_notif_info; struct list_head list; }; @@ -101,6 +116,105 @@ int subsys_notif_unregister_notifier(void *subsys_handle, } EXPORT_SYMBOL(subsys_notif_unregister_notifier); +void send_early_notifications(void *early_notif_handle) +{ + struct subsys_early_notif_info *early_info = early_notif_handle; + unsigned long flags; + unsigned int i; + void (*notif_cb)(void *); + + if (!early_notif_handle) + return; + + spin_lock_irqsave(&early_info->cb_lock, flags); + for (i = 0; i < NUM_EARLY_NOTIFS; i++) { + notif_cb = early_info->early_notif_cb[i]; + if (notif_cb) + notif_cb(early_info->data[i]); + } + spin_unlock_irqrestore(&early_info->cb_lock, flags); +} +EXPORT_SYMBOL(send_early_notifications); + +static bool valid_early_notif(enum early_subsys_notif_type notif_type) +{ + return notif_type >= 0 && notif_type < NUM_EARLY_NOTIFS; +} + +/** + * The early_notif_cb parameter must point to a function that conforms to the + * same constraints placed upon interrupt handlers, as the function will be + * called in an atomic context (i.e. these functions must not sleep or block). + */ +int subsys_register_early_notifier(const char *subsys_name, + enum early_subsys_notif_type notif_type, + void (*early_notif_cb)(void *), void *data) +{ + struct subsys_notif_info *subsys; + struct subsys_early_notif_info *early_notif_info; + unsigned long flags; + int rc = 0; + + if (!subsys_name || !early_notif_cb || !valid_early_notif(notif_type)) + return -EINVAL; + + subsys = _notif_find_subsys(subsys_name); + if (!subsys) + return -EINVAL; + + early_notif_info = &subsys->early_notif_info; + spin_lock_irqsave(&early_notif_info->cb_lock, flags); + if (early_notif_info->early_notif_cb[notif_type]) { + rc = -EEXIST; + goto out; + } + early_notif_info->early_notif_cb[notif_type] = early_notif_cb; + early_notif_info->data[notif_type] = data; +out: + spin_unlock_irqrestore(&early_notif_info->cb_lock, flags); + return rc; +} +EXPORT_SYMBOL(subsys_register_early_notifier); + +int subsys_unregister_early_notifier(const char *subsys_name, enum + early_subsys_notif_type notif_type) +{ + struct subsys_notif_info *subsys; + struct subsys_early_notif_info *early_notif_info; + unsigned long flags; + + if (!subsys_name || !valid_early_notif(notif_type)) + return -EINVAL; + + subsys = _notif_find_subsys(subsys_name); + if (!subsys) + return -EINVAL; + + early_notif_info = &subsys->early_notif_info; + spin_lock_irqsave(&early_notif_info->cb_lock, flags); + early_notif_info->early_notif_cb[notif_type] = NULL; + early_notif_info->data[notif_type] = NULL; + spin_unlock_irqrestore(&early_notif_info->cb_lock, flags); + return 0; +} +EXPORT_SYMBOL(subsys_unregister_early_notifier); + +void *subsys_get_early_notif_info(const char *subsys_name) +{ + struct subsys_notif_info *subsys; + + if (!subsys_name) + return ERR_PTR(-EINVAL); + + subsys = _notif_find_subsys(subsys_name); + + if (!subsys) + return ERR_PTR(-EINVAL); + + return &subsys->early_notif_info; +} +EXPORT_SYMBOL(subsys_get_early_notif_info); + void *subsys_notif_add_subsys(const char *subsys_name) { struct subsys_notif_info *subsys = NULL; @@ -128,6 +242,9 @@ void *subsys_notif_add_subsys(const char *subsys_name) srcu_init_notifier_head(&subsys->subsys_notif_rcvr_list); + memset(&subsys->early_notif_info, 0, sizeof(struct + subsys_early_notif_info)); + spin_lock_init(&subsys->early_notif_info.cb_lock); INIT_LIST_HEAD(&subsys->list); mutex_lock(¬if_lock); diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index 9c6a1bf950c7f2d19ec8a18a44f4769f9b4e4ba0..1b3e54c9b5a6d0ca991a0954611ec25d2f077521 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -62,7 +62,7 @@ module_param(enable_debug, int, 0644); #define setup_timeout(dest_ss, source_ss, comm_type) \ _setup_timeout(dest_ss, source_ss, comm_type) -#define cancel_timeout(subsys) del_timer(&subsys->timeout_data.timer) +#define cancel_timeout(subsys) del_timer_sync(&subsys->timeout_data.timer) #define init_subsys_timer(subsys) _init_subsys_timer(subsys) /* Timeout values */ @@ -194,6 +194,7 @@ struct subsys_device { struct subsys_tracking track; void *notify; + void *early_notify; struct device dev; struct module *owner; int count; @@ -1227,6 +1228,8 @@ int subsystem_restart_dev(struct subsys_device *dev) name = dev->desc->name; + send_early_notifications(dev->early_notify); + /* * If a system reboot/shutdown is underway, ignore subsystem errors. * However, print a message so that we know that a subsystem behaved @@ -1801,6 +1804,7 @@ struct subsys_device *subsys_register(struct subsys_desc *desc) sizeof(subsys->desc->fw_name)); subsys->notify = subsys_notif_add_subsys(desc->name); + subsys->early_notify = subsys_get_early_notif_info(desc->name); snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name); wakeup_source_init(&subsys->ssr_wlock, subsys->wlname); diff --git a/drivers/soc/qcom/wda_qmi.c b/drivers/soc/qcom/wda_qmi.c index 8e34aad2574ba1fa592121a79e13d31baee20938..6dcc7c58f948b7293dbc9c353b7137d6cb95d811 100644 --- a/drivers/soc/qcom/wda_qmi.c +++ b/drivers/soc/qcom/wda_qmi.c @@ -11,6 +11,7 @@ * */ +#include #include #include #define CREATE_TRACE_POINTS @@ -23,6 +24,7 @@ struct wda_qmi_data { struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; + struct svc_info svc; }; static void wda_svc_config(struct work_struct *work); @@ -255,8 +257,7 @@ static int wda_set_powersave_mode_req(void *wda_data, uint8_t enable) return ret; } -static int wda_set_powersave_config_req(struct qmi_handle *wda_handle, - struct qmi_info *qmi) +static int wda_set_powersave_config_req(struct qmi_handle *wda_handle) { struct wda_qmi_data *data = container_of(wda_handle, struct wda_qmi_data, handle); @@ -283,8 +284,8 @@ static int wda_set_powersave_config_req(struct qmi_handle *wda_handle, goto out; } - req->ep_id.ep_type = qmi->fc_info[0].svc.ep_type; - req->ep_id.iface_id = qmi->fc_info[0].svc.iface_id; + req->ep_id.ep_type = data->svc.ep_type; + req->ep_id.iface_id = data->svc.iface_id; req->req_data_cfg_valid = 1; req->req_data_cfg = WDA_DATA_POWERSAVE_CONFIG_ALL_MASK_V01; ret = qmi_send_request(wda_handle, &data->ssctl, &txn, @@ -319,20 +320,25 @@ static void wda_svc_config(struct work_struct *work) svc_arrive); struct qmi_info *qmi; - qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); - if (!qmi) - goto clean_out; - - if (wda_set_powersave_config_req(&data->handle, qmi) < 0) { + if (wda_set_powersave_config_req(&data->handle) < 0) { pr_err("%s() failed, qmi handle pt: %p\n", __func__, &data->handle); goto clean_out; } - trace_wda_client_state_up(qmi->fc_info[0].svc.instance, - qmi->fc_info[0].svc.ep_type, - qmi->fc_info[0].svc.iface_id); + trace_wda_client_state_up(data->svc.instance, + data->svc.ep_type, + data->svc.iface_id); + rtnl_lock(); + qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); + if (!qmi) { + rtnl_unlock(); + goto clean_out; + } + qmi->wda_client = (void *)data; + rtnl_unlock(); + pr_info("Connection established with the WDA Service\n"); return; @@ -370,7 +376,7 @@ static struct qmi_ops server_ops = { .del_server = wda_svc_exit, }; -int wda_qmi_client_init(void *port, uint32_t instance) +int wda_qmi_client_init(void *port, struct svc_info *psvc) { struct wda_qmi_data *data; int rc = 0; @@ -392,6 +398,7 @@ int wda_qmi_client_init(void *port, uint32_t instance) } data->rmnet_port = port; + memcpy(&data->svc, psvc, sizeof(data->svc)); INIT_WORK(&data->svc_arrive, wda_svc_config); rc = qmi_handle_init(&data->handle, @@ -404,7 +411,7 @@ int wda_qmi_client_init(void *port, uint32_t instance) } rc = qmi_add_lookup(&data->handle, WDA_SERVICE_ID_V01, - WDA_SERVICE_VERS_V01, instance); + WDA_SERVICE_VERS_V01, psvc->instance); if (rc < 0) { pr_err("%s(): Failed qmi_add_lookup, err: %d\n", __func__, rc); qmi_handle_release(&data->handle); diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 4a001634023e09b8e83b8e6b82b5af557e2c0853..02bd1eba045b8b6bc915ff44b076481971c7d1d6 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -319,7 +319,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) */ if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL) - usleep_range(10, 20); + udelay(10); if (xspi->txbuf) cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 6ddb6ef1fda4ff0900b97d7b87942bbe9935475d..c5bbe08771a4d06894e14b284a589f2149d58f02 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -217,7 +217,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) pdata = &dspi->pdata; /* program delay transfers if tx_delay is non zero */ - if (spicfg->wdelay) + if (spicfg && spicfg->wdelay) spidat1 |= SPIDAT1_WDEL; /* diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index d89127f4a46dfd567e2c7cfb290833d038c930ed..ca013dd4ff6bb19d410ae522fe1f91b27d5f7ace 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -1006,30 +1006,30 @@ static int dspi_probe(struct platform_device *pdev) goto out_master_put; } + dspi->clk = devm_clk_get(&pdev->dev, "dspi"); + if (IS_ERR(dspi->clk)) { + ret = PTR_ERR(dspi->clk); + dev_err(&pdev->dev, "unable to get clock\n"); + goto out_master_put; + } + ret = clk_prepare_enable(dspi->clk); + if (ret) + goto out_master_put; + dspi_init(dspi); dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq < 0) { dev_err(&pdev->dev, "can't get platform irq\n"); ret = dspi->irq; - goto out_master_put; + goto out_clk_put; } ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, 0, pdev->name, dspi); if (ret < 0) { dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n"); - goto out_master_put; - } - - dspi->clk = devm_clk_get(&pdev->dev, "dspi"); - if (IS_ERR(dspi->clk)) { - ret = PTR_ERR(dspi->clk); - dev_err(&pdev->dev, "unable to get clock\n"); - goto out_master_put; + goto out_clk_put; } - ret = clk_prepare_enable(dspi->clk); - if (ret) - goto out_master_put; if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { ret = dspi_request_dma(dspi, res->start); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 4cb515a3104c1759b451c1f2d313953c009fb3ce..3a2e46e49405b5ea2bd2e17f982d4298578b72ae 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1480,6 +1480,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x31c2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x31c4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x31c6), LPSS_BXT_SSP }, + /* ICL-LP */ + { PCI_VDEVICE(INTEL, 0x34aa), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x34ab), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x34fb), LPSS_CNL_SSP }, /* APL */ { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 2a10b3f94ff72a4ea3d6924a082ef6d2db174528..20981e08ee975d197c63845fcce11e0c76e53e8d 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -598,11 +598,13 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ret = wait_event_interruptible_timeout(rspi->wait, rspi->dma_callbacked, HZ); - if (ret > 0 && rspi->dma_callbacked) + if (ret > 0 && rspi->dma_callbacked) { ret = 0; - else if (!ret) { - dev_err(&rspi->master->dev, "DMA timeout\n"); - ret = -ETIMEDOUT; + } else { + if (!ret) { + dev_err(&rspi->master->dev, "DMA timeout\n"); + ret = -ETIMEDOUT; + } if (tx) dmaengine_terminate_all(rspi->master->dma_tx); if (rx) @@ -1352,12 +1354,36 @@ static const struct platform_device_id spi_driver_ids[] = { MODULE_DEVICE_TABLE(platform, spi_driver_ids); +#ifdef CONFIG_PM_SLEEP +static int rspi_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rspi_data *rspi = platform_get_drvdata(pdev); + + return spi_master_suspend(rspi->master); +} + +static int rspi_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rspi_data *rspi = platform_get_drvdata(pdev); + + return spi_master_resume(rspi->master); +} + +static SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume); +#define DEV_PM_OPS &rspi_pm_ops +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static struct platform_driver rspi_driver = { .probe = rspi_probe, .remove = rspi_remove, .id_table = spi_driver_ids, .driver = { .name = "renesas_spi", + .pm = DEV_PM_OPS, .of_match_table = of_match_ptr(rspi_of_match), }, }; diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 0fea18ab970e30424d0799f0b265d24f6d26dfc2..db2a529accae8471352ee54b70f19ef4a0fc2483 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -384,7 +384,8 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p) { - sh_msiof_write(p, STR, sh_msiof_read(p, STR)); + sh_msiof_write(p, STR, + sh_msiof_read(p, STR) & ~(STR_TDREQ | STR_RDREQ)); } static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, @@ -1361,12 +1362,37 @@ static const struct platform_device_id spi_driver_ids[] = { }; MODULE_DEVICE_TABLE(platform, spi_driver_ids); +#ifdef CONFIG_PM_SLEEP +static int sh_msiof_spi_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev); + + return spi_master_suspend(p->master); +} + +static int sh_msiof_spi_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev); + + return spi_master_resume(p->master); +} + +static SIMPLE_DEV_PM_OPS(sh_msiof_spi_pm_ops, sh_msiof_spi_suspend, + sh_msiof_spi_resume); +#define DEV_PM_OPS &sh_msiof_spi_pm_ops +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static struct platform_driver sh_msiof_spi_drv = { .probe = sh_msiof_spi_probe, .remove = sh_msiof_spi_remove, .id_table = spi_driver_ids, .driver = { .name = "spi_sh_msiof", + .pm = DEV_PM_OPS, .of_match_table = of_match_ptr(sh_msiof_match), }, }; diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 3e12d5f87ee4412b086649c8f2312fb3cc9e30a8..9831c1106945e835d6f8891569a8adc9bbcdc42a 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1063,6 +1063,24 @@ static int tegra_slink_probe(struct platform_device *pdev) goto exit_free_master; } + /* disabled clock may cause interrupt storm upon request */ + tspi->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(tspi->clk)) { + ret = PTR_ERR(tspi->clk); + dev_err(&pdev->dev, "Can not get clock %d\n", ret); + goto exit_free_master; + } + ret = clk_prepare(tspi->clk); + if (ret < 0) { + dev_err(&pdev->dev, "Clock prepare failed %d\n", ret); + goto exit_free_master; + } + ret = clk_enable(tspi->clk); + if (ret < 0) { + dev_err(&pdev->dev, "Clock enable failed %d\n", ret); + goto exit_free_master; + } + spi_irq = platform_get_irq(pdev, 0); tspi->irq = spi_irq; ret = request_threaded_irq(tspi->irq, tegra_slink_isr, @@ -1071,14 +1089,7 @@ static int tegra_slink_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", tspi->irq); - goto exit_free_master; - } - - tspi->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(tspi->clk)) { - dev_err(&pdev->dev, "can not get clock\n"); - ret = PTR_ERR(tspi->clk); - goto exit_free_irq; + goto exit_clk_disable; } tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); @@ -1138,6 +1149,8 @@ static int tegra_slink_probe(struct platform_device *pdev) tegra_slink_deinit_dma_param(tspi, true); exit_free_irq: free_irq(spi_irq, tspi); +exit_clk_disable: + clk_disable(tspi->clk); exit_free_master: spi_master_put(master); return ret; @@ -1150,6 +1163,8 @@ static int tegra_slink_remove(struct platform_device *pdev) free_irq(tspi->irq, tspi); + clk_disable(tspi->clk); + if (tspi->tx_dma_chan) tegra_slink_deinit_dma_param(tspi, false); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f85d30dc91878dbb8472b3bc8fec69ff2244fb6a..670dbb7a8500a228e4c7d13e1aad192b5a2e8d7d 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2108,8 +2108,17 @@ int spi_register_controller(struct spi_controller *ctlr) */ if (ctlr->num_chipselect == 0) return -EINVAL; - /* allocate dynamic bus number using Linux idr */ - if ((ctlr->bus_num < 0) && ctlr->dev.of_node) { + if (ctlr->bus_num >= 0) { + /* devices with a fixed bus num must check-in with the num */ + mutex_lock(&board_lock); + id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num, + ctlr->bus_num + 1, GFP_KERNEL); + mutex_unlock(&board_lock); + if (WARN(id < 0, "couldn't get idr")) + return id == -ENOSPC ? -EBUSY : id; + ctlr->bus_num = id; + } else if (ctlr->dev.of_node) { + /* allocate dynamic bus number using Linux idr */ id = of_alias_get_id(ctlr->dev.of_node, "spi"); if (id >= 0) { ctlr->bus_num = id; diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 9dc534f677d1b434c504948a1e652416e95ff28f..aebfe997af9151cfd9b350c60a7e511cb19fb70b 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -387,6 +387,12 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) goto out; } + /* requested mapping size larger than object size */ + if (vma->vm_end - vma->vm_start > PAGE_ALIGN(asma->size)) { + ret = -EINVAL; + goto out; + } + /* requested protection bits must match our allowed protection mask */ if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask, 0)) & calc_vm_prot_bits(PROT_MASK, 0))) { diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 2240c4ae61ce28f97177dfd2ddb4796853288a69..fe81a283ad142132fae067da59cc72a12c731856 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -505,6 +505,7 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf) struct ion_buffer *buffer = dmabuf->priv; _ion_buffer_destroy(buffer); + kfree(dmabuf->exp_name); } static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) @@ -1047,6 +1048,7 @@ struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask, struct ion_heap *heap; DEFINE_DMA_BUF_EXPORT_INFO(exp_info); struct dma_buf *dmabuf; + char task_comm[TASK_COMM_LEN]; pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, len, heap_id_mask, flags); @@ -1078,14 +1080,20 @@ struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask, if (IS_ERR(buffer)) return ERR_CAST(buffer); + get_task_comm(task_comm, current->group_leader); + exp_info.ops = &dma_buf_ops; exp_info.size = buffer->size; exp_info.flags = O_RDWR; exp_info.priv = buffer; + exp_info.exp_name = kasprintf(GFP_KERNEL, "%s-%s-%d-%s", KBUILD_MODNAME, + heap->name, current->tgid, task_comm); dmabuf = dma_buf_export(&exp_info); - if (IS_ERR(dmabuf)) + if (IS_ERR(dmabuf)) { _ion_buffer_destroy(buffer); + kfree(dmabuf->exp_name); + } return dmabuf; } diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 2cac160993bbd82f12246951e7db109b5fc043ac..158f3e83efb66d75daf0785f298da811900a9252 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -5453,11 +5453,11 @@ static int ni_E_init(struct comedi_device *dev, /* Digital I/O (PFI) subdevice */ s = &dev->subdevices[NI_PFI_DIO_SUBDEV]; s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->maxdata = 1; if (devpriv->is_m_series) { s->n_chan = 16; s->insn_bits = ni_pfi_insn_bits; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; ni_writew(dev, s->state, NI_M_PFI_DO_REG); for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) { @@ -5466,6 +5466,7 @@ static int ni_E_init(struct comedi_device *dev, } } else { s->n_chan = 10; + s->subdev_flags = SDF_INTERNAL; } s->insn_config = ni_pfi_insn_config; diff --git a/drivers/staging/irda/net/af_irda.c b/drivers/staging/irda/net/af_irda.c index 23fa7c8b09a5861e2acc042775830cc2dac4e0f4..cebe9878ca03629d054bb91e0fe309ca9a370615 100644 --- a/drivers/staging/irda/net/af_irda.c +++ b/drivers/staging/irda/net/af_irda.c @@ -775,6 +775,13 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; lock_sock(sk); + + /* Ensure that the socket is not already bound */ + if (self->ias_obj) { + err = -EINVAL; + goto out; + } + #ifdef CONFIG_IRDA_ULTRA /* Special care for Ultra sockets */ if ((sk->sk_type == SOCK_DGRAM) && @@ -2012,7 +2019,11 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, err = -EINVAL; goto out; } - irias_insert_object(ias_obj); + + /* Only insert newly allocated objects */ + if (free_ias) + irias_insert_object(ias_obj); + kfree(ias_opt); break; case IRLMP_IAS_DEL: diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c index 0790b3d9e25560366a48633ddce37beeea21e762..111afd34aa3c328e385d09fcdb0f4c19dbc1e6cb 100644 --- a/drivers/staging/media/imx/imx-ic-prpencvf.c +++ b/drivers/staging/media/imx/imx-ic-prpencvf.c @@ -210,6 +210,7 @@ static void prp_vb2_buf_done(struct prp_priv *priv, struct ipuv3_channel *ch) done = priv->active_vb2_buf[priv->ipu_buf_num]; if (done) { + done->vbuf.field = vdev->fmt.fmt.pix.field; vb = &done->vbuf.vb2_buf; vb->timestamp = ktime_get_ns(); vb2_buffer_done(vb, priv->nfb4eof ? diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 6d856118c223285702913468b29200e26c448a7c..83ecb5b2fb9e18c66426f56d18f8379f3cbdab9c 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -171,6 +171,7 @@ static void csi_vb2_buf_done(struct csi_priv *priv) done = priv->active_vb2_buf[priv->ipu_buf_num]; if (done) { + done->vbuf.field = vdev->fmt.fmt.pix.field; vb = &done->vbuf.vb2_buf; vb->timestamp = ktime_get_ns(); vb2_buffer_done(vb, priv->nfb4eof ? diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 9e2f0421a01eadd561e0fd1b247e95dc3f40ee65..0bf6643cca0722f1be7aa2d03d553faeaa6383db 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -11,7 +11,6 @@ * (at your option) any later version. */ -#include #include #include #include @@ -24,6 +23,8 @@ #include #include +#include + #include "iss_video.h" #include "iss.h" diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 4033a2cf7ac9b3b7028f84f7ea54f753a75536a4..d98d5fe25a17d755e6fe9ba19ba7474ff7233fcb 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -5002,7 +5002,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) goto sd_execute_write_cmd_failed; } - rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); + retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); if (retval != STATUS_SUCCESS) { rtsx_trace(chip); goto sd_execute_write_cmd_failed; diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c index 8af62e74d54c6319678f315a48e302a761dbb71c..f237e31926f4cfc13be67b2f0432cc429e750e7c 100644 --- a/drivers/staging/typec/tcpm.c +++ b/drivers/staging/typec/tcpm.c @@ -2479,7 +2479,8 @@ static void run_state_machine(struct tcpm_port *port) tcpm_port_is_sink(port) && time_is_after_jiffies(port->delayed_runtime)) { tcpm_set_state(port, SNK_DISCOVERY, - port->delayed_runtime - jiffies); + jiffies_to_msecs(port->delayed_runtime - + jiffies)); break; } tcpm_set_state(port, unattached_state(port), 0); diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 4be864dbd41c9f4eb63f03361a0dab1e13c54a67..9eb3b625a1b18b46fa940c96a9c5893ca44cade0 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -442,16 +442,16 @@ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) my_workqueue_init(alsa_stream); ret = bcm2835_audio_open_connection(alsa_stream); - if (ret) { - ret = -1; - goto exit; - } + if (ret) + goto free_wq; + instance = alsa_stream->instance; LOG_DBG(" instance (%p)\n", instance); if (mutex_lock_interruptible(&instance->vchi_mutex)) { LOG_DBG("Interrupted whilst waiting for lock on (%d)\n", instance->num_connections); - return -EINTR; + ret = -EINTR; + goto free_wq; } vchi_service_use(instance->vchi_handle[0]); @@ -474,7 +474,11 @@ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) unlock: vchi_service_release(instance->vchi_handle[0]); mutex_unlock(&instance->vchi_mutex); -exit: + +free_wq: + if (ret) + destroy_workqueue(alsa_stream->my_wq); + return ret; } diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index be936b8fe317599b132988f0a700ec7f7df15af6..377da037f31c3071499c43516395a0bd2745592f 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -580,6 +580,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) static void stop_streaming(struct vb2_queue *vq) { int ret; + unsigned long timeout; struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", @@ -605,10 +606,10 @@ static void stop_streaming(struct vb2_queue *vq) sizeof(dev->capture.frame_count)); /* wait for last frame to complete */ - ret = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ); - if (ret <= 0) + timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ); + if (timeout == 0) v4l2_err(&dev->v4l2_dev, - "error %d waiting for frame completion\n", ret); + "timed out waiting for frame completion\n"); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "disabling connection\n"); diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c index 4360db6d43927d071803255679ce789fd7dcd604..b3176f42c8207f6a54a6c3927a54b36f5571b3e0 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c @@ -834,6 +834,7 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, { struct mmal_msg_context *msg_context; int ret; + unsigned long timeout; /* payload size must not cause message to exceed max size */ if (payload_len > @@ -872,11 +873,11 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, return ret; } - ret = wait_for_completion_timeout(&msg_context->u.sync.cmplt, 3 * HZ); - if (ret <= 0) { - pr_err("error %d waiting for sync completion\n", ret); - if (ret == 0) - ret = -ETIME; + timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt, + 3 * HZ); + if (timeout == 0) { + pr_err("timed out waiting for sync completion\n"); + ret = -ETIME; /* todo: what happens if the message arrives after aborting */ release_msg_context(msg_context); return ret; diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index 514986b57c2d60ce19c1074f4d19d65dd550be2e..25eb3891e34b8435fe15b80c5b7eb5e2a7b7c6d6 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -652,6 +652,7 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk) struct iscsi_param *param; u32 mrdsl, mbl; u32 max_npdu, max_iso_npdu; + u32 max_iso_payload; if (conn->login->leading_connection) { param = iscsi_find_param_from_key(MAXBURSTLENGTH, @@ -670,8 +671,10 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk) mrdsl = conn_ops->MaxRecvDataSegmentLength; max_npdu = mbl / mrdsl; - max_iso_npdu = CXGBIT_MAX_ISO_PAYLOAD / - (ISCSI_HDR_LEN + mrdsl + + max_iso_payload = rounddown(CXGBIT_MAX_ISO_PAYLOAD, csk->emss); + + max_iso_npdu = max_iso_payload / + (ISCSI_HDR_LEN + mrdsl + cxgbit_digest_len[csk->submode]); csk->max_iso_npdu = min(max_npdu, max_iso_npdu); @@ -741,6 +744,9 @@ static int cxgbit_set_params(struct iscsi_conn *conn) if (conn_ops->MaxRecvDataSegmentLength > cdev->mdsl) conn_ops->MaxRecvDataSegmentLength = cdev->mdsl; + if (cxgbit_set_digest(csk)) + return -1; + if (conn->login->leading_connection) { param = iscsi_find_param_from_key(ERRORRECOVERYLEVEL, conn->param_list); @@ -764,7 +770,7 @@ static int cxgbit_set_params(struct iscsi_conn *conn) if (is_t5(cdev->lldi.adapter_type)) goto enable_ddp; else - goto enable_digest; + return 0; } if (test_bit(CDEV_ISO_ENABLE, &cdev->flags)) { @@ -781,10 +787,6 @@ static int cxgbit_set_params(struct iscsi_conn *conn) } } -enable_digest: - if (cxgbit_set_digest(csk)) - return -1; - return 0; } diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index 9518ffd8b8bac81cc1b725046857d5f229e58b15..4e680d753941f71ea299d87b6c0cd18fc307b50f 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -26,27 +26,6 @@ #include "iscsi_target_nego.h" #include "iscsi_target_auth.h" -static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len) -{ - int j = DIV_ROUND_UP(len, 2), rc; - - rc = hex2bin(dst, src, j); - if (rc < 0) - pr_debug("CHAP string contains non hex digit symbols\n"); - - dst[j] = '\0'; - return j; -} - -static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len) -{ - int i; - - for (i = 0; i < src_len; i++) { - sprintf(&dst[i*2], "%02x", (int) src[i] & 0xff); - } -} - static int chap_gen_challenge( struct iscsi_conn *conn, int caller, @@ -62,7 +41,7 @@ static int chap_gen_challenge( ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH); if (unlikely(ret)) return ret; - chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge, + bin2hex(challenge_asciihex, chap->challenge, CHAP_CHALLENGE_LENGTH); /* * Set CHAP_C, and copy the generated challenge into c_str. @@ -248,9 +227,16 @@ static int chap_server_compute_md5( pr_err("Could not find CHAP_R.\n"); goto out; } + if (strlen(chap_r) != MD5_SIGNATURE_SIZE * 2) { + pr_err("Malformed CHAP_R\n"); + goto out; + } + if (hex2bin(client_digest, chap_r, MD5_SIGNATURE_SIZE) < 0) { + pr_err("Malformed CHAP_R\n"); + goto out; + } pr_debug("[server] Got CHAP_R=%s\n", chap_r); - chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); tfm = crypto_alloc_shash("md5", 0, 0); if (IS_ERR(tfm)) { @@ -294,7 +280,7 @@ static int chap_server_compute_md5( goto out; } - chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE); + bin2hex(response, server_digest, MD5_SIGNATURE_SIZE); pr_debug("[server] MD5 Server Digest: %s\n", response); if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) { @@ -349,9 +335,7 @@ static int chap_server_compute_md5( pr_err("Could not find CHAP_C.\n"); goto out; } - pr_debug("[server] Got CHAP_C=%s\n", challenge); - challenge_len = chap_string_to_hex(challenge_binhex, challenge, - strlen(challenge)); + challenge_len = DIV_ROUND_UP(strlen(challenge), 2); if (!challenge_len) { pr_err("Unable to convert incoming challenge\n"); goto out; @@ -360,6 +344,11 @@ static int chap_server_compute_md5( pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); goto out; } + if (hex2bin(challenge_binhex, challenge, challenge_len) < 0) { + pr_err("Malformed CHAP_C\n"); + goto out; + } + pr_debug("[server] Got CHAP_C=%s\n", challenge); /* * During mutual authentication, the CHAP_C generated by the * initiator must not match the original CHAP_C generated by @@ -413,7 +402,7 @@ static int chap_server_compute_md5( /* * Convert response from binary hex to ascii hext. */ - chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE); + bin2hex(response, digest, MD5_SIGNATURE_SIZE); *nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s", response); *nr_out_len += 1; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index dc13afbd4c88dec2390ca8e65b3332d2f78acd73..98e27da34f3cb541e9575ec6b7ac5d021d258679 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -345,8 +345,7 @@ static int iscsi_login_zero_tsih_s1( pr_err("idr_alloc() for sess_idr failed\n"); iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); - kfree(sess); - return -ENOMEM; + goto free_sess; } sess->creation_time = get_jiffies_64(); @@ -362,20 +361,28 @@ static int iscsi_login_zero_tsih_s1( ISCSI_LOGIN_STATUS_NO_RESOURCES); pr_err("Unable to allocate memory for" " struct iscsi_sess_ops.\n"); - kfree(sess); - return -ENOMEM; + goto remove_idr; } sess->se_sess = transport_init_session(TARGET_PROT_NORMAL); if (IS_ERR(sess->se_sess)) { iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); - kfree(sess->sess_ops); - kfree(sess); - return -ENOMEM; + goto free_ops; } return 0; + +free_ops: + kfree(sess->sess_ops); +remove_idr: + spin_lock_bh(&sess_idr_lock); + idr_remove(&sess_idr, sess->session_index); + spin_unlock_bh(&sess_idr_lock); +free_sess: + kfree(sess); + conn->sess = NULL; + return -ENOMEM; } static int iscsi_login_zero_tsih_s2( @@ -1162,13 +1169,13 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn, ISCSI_LOGIN_STATUS_INIT_ERR); if (!zero_tsih || !conn->sess) goto old_sess_out; - if (conn->sess->se_sess) - transport_free_session(conn->sess->se_sess); - if (conn->sess->session_index != 0) { - spin_lock_bh(&sess_idr_lock); - idr_remove(&sess_idr, conn->sess->session_index); - spin_unlock_bh(&sess_idr_lock); - } + + transport_free_session(conn->sess->se_sess); + + spin_lock_bh(&sess_idr_lock); + idr_remove(&sess_idr, conn->sess->session_index); + spin_unlock_bh(&sess_idr_lock); + kfree(conn->sess->sess_ops); kfree(conn->sess); conn->sess = NULL; diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 594d07a1e995ec87d467f4286a1d8668f2e32e3d..16e7516052a4486601241026d0e411e9731a716c 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -633,8 +633,7 @@ int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication) none = strstr(buf1, NONE); if (none) goto out; - strncat(buf1, ",", strlen(",")); - strncat(buf1, NONE, strlen(NONE)); + strlcat(buf1, "," NONE, sizeof(buf1)); if (iscsi_update_param_value(param, buf1) < 0) return -EINVAL; } diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index e8dd6da164b28550f42d4909afed480291cc29ab..84742125f77303ce7bf6539d7659a88ff52bdf81 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -904,14 +904,20 @@ struct se_device *target_find_device(int id, bool do_depend) EXPORT_SYMBOL(target_find_device); struct devices_idr_iter { + struct config_item *prev_item; int (*fn)(struct se_device *dev, void *data); void *data; }; static int target_devices_idr_iter(int id, void *p, void *data) + __must_hold(&device_mutex) { struct devices_idr_iter *iter = data; struct se_device *dev = p; + int ret; + + config_item_put(iter->prev_item); + iter->prev_item = NULL; /* * We add the device early to the idr, so it can be used @@ -922,7 +928,15 @@ static int target_devices_idr_iter(int id, void *p, void *data) if (!(dev->dev_flags & DF_CONFIGURED)) return 0; - return iter->fn(dev, iter->data); + iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); + if (!iter->prev_item) + return 0; + mutex_unlock(&device_mutex); + + ret = iter->fn(dev, iter->data); + + mutex_lock(&device_mutex); + return ret; } /** @@ -936,15 +950,13 @@ static int target_devices_idr_iter(int id, void *p, void *data) int target_for_each_device(int (*fn)(struct se_device *dev, void *data), void *data) { - struct devices_idr_iter iter; + struct devices_idr_iter iter = { .fn = fn, .data = data }; int ret; - iter.fn = fn; - iter.data = data; - mutex_lock(&device_mutex); ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); mutex_unlock(&device_mutex); + config_item_put(iter.prev_item); return ret; } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e6d51135d1055cb4edabf08730fccc13c39a5b77..0d0be7d8b9d643ac8e2cebe952e867c4cd45a2cb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -317,6 +317,7 @@ void __transport_register_session( { const struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo; unsigned char buf[PR_REG_ISID_LEN]; + unsigned long flags; se_sess->se_tpg = se_tpg; se_sess->fabric_sess_ptr = fabric_sess_ptr; @@ -353,7 +354,7 @@ void __transport_register_session( se_sess->sess_bin_isid = get_unaligned_be64(&buf[0]); } - spin_lock_irq(&se_nacl->nacl_sess_lock); + spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags); /* * The se_nacl->nacl_sess pointer will be set to the * last active I_T Nexus for each struct se_node_acl. @@ -362,7 +363,7 @@ void __transport_register_session( list_add_tail(&se_sess->sess_acl_list, &se_nacl->acl_sess_list); - spin_unlock_irq(&se_nacl->nacl_sess_lock); + spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags); } list_add_tail(&se_sess->sess_list, &se_tpg->tpg_sess_list); diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 99b19c496e8b6713d2939ea39acc5b1d69316384..6bb4da382edfd8589513db7db3b9bf4bc745f64b 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -396,10 +396,13 @@ static int of_thermal_set_mode(struct thermal_zone_device *tz, mutex_lock(&tz->lock); - if (mode == THERMAL_DEVICE_ENABLED) + if (mode == THERMAL_DEVICE_ENABLED) { tz->polling_delay = data->polling_delay; - else + tz->passive_delay = data->passive_delay; + } else { tz->polling_delay = 0; + tz->passive_delay = 0; + } mutex_unlock(&tz->lock); diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 899e8fe5e00f512a75fe82c25b42f341eb9a338e..9e26c530d2ddb798385a2c731915e3ad336c0cd3 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -625,7 +625,7 @@ int ptm_open_peer(struct file *master, struct tty_struct *tty, int flags) if (tty->driver != ptm_driver) return -EIO; - fd = get_unused_fd_flags(0); + fd = get_unused_fd_flags(flags); if (fd < 0) { retval = fd; goto err; diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 20d79a6007d50bcb9457890df30c1d341899485d..070733ca94d5e7fd5eeac3b11462be64ecef95c9 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1894,7 +1894,7 @@ static __init int register_PCI(int i, struct pci_dev *dev) ByteIO_t UPCIRingInd = 0; if (!dev || !pci_match_id(rocket_pci_ids, dev) || - pci_enable_device(dev)) + pci_enable_device(dev) || i >= NUM_BOARDS) return 0; rcktpt_io_addr[i] = pci_resource_start(dev, 0); diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 933c2688dd7ea90c4a38d7f55938bfc454e9a67c..8106353ce7aa00853bcf4b051b80c1d02310fbbb 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -637,8 +637,10 @@ static int serial_config(struct pcmcia_device *link) (link->has_func_id) && (link->socket->pcmcia_pfc == 0) && ((link->func_id == CISTPL_FUNCID_MULTI) || - (link->func_id == CISTPL_FUNCID_SERIAL))) - pcmcia_loop_config(link, serial_check_for_multi, info); + (link->func_id == CISTPL_FUNCID_SERIAL))) { + if (pcmcia_loop_config(link, serial_check_for_multi, info)) + goto failed; + } /* * Apply any multi-port quirk. diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index 9ac142cfc1f1b99a89cf21582472e05993664ed2..8b2b694334ec0568b1e08b07427c57388d50c0d5 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -1068,8 +1068,8 @@ static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo) /* Get the address of the host memory buffer. */ bdp = pinfo->rx_cur; - while (bdp->cbd_sc & BD_SC_EMPTY) - ; + if (bdp->cbd_sc & BD_SC_EMPTY) + return NO_POLL_CHAR; /* If the buffer address is in the CPM DPRAM, don't * convert it. @@ -1104,7 +1104,11 @@ static int cpm_get_poll_char(struct uart_port *port) poll_chars = 0; } if (poll_chars <= 0) { - poll_chars = poll_wait_key(poll_buf, pinfo); + int ret = poll_wait_key(poll_buf, pinfo); + + if (ret == NO_POLL_CHAR) + return ret; + poll_chars = ret; pollp = poll_buf; } poll_chars--; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index ac667b47f19970c451712280c2a6d7fbbe7a5ff2..7b0a3a1688e8370d08257b735a0cd63c1d083926 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -254,7 +254,6 @@ int __init of_setup_earlycon(const struct earlycon_id *match, return -ENXIO; } port->mapbase = addr; - port->uartclk = BASE_BAUD * 16; val = of_get_flat_dt_prop(node, "reg-offset", NULL); if (val) @@ -289,6 +288,10 @@ int __init of_setup_earlycon(const struct earlycon_id *match, if (val) early_console_dev.baud = be32_to_cpu(*val); + val = of_get_flat_dt_prop(node, "clock-frequency", NULL); + if (val) + port->uartclk = be32_to_cpu(*val); + if (options) { early_console_dev.baud = simple_strtoul(options, NULL, 0); strlcpy(early_console_dev.options, options, diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 7a3db9378fa388818eddbdeb12082ac703686b9e..fd64ac2c1a748b80cef780d9076c2616787a85c2 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -983,7 +983,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) struct circ_buf *ring = &sport->rx_ring; int ret, nent; int bits, baud; - struct tty_struct *tty = tty_port_tty_get(&sport->port.state->port); + struct tty_port *port = &sport->port.state->port; + struct tty_struct *tty = port->tty; struct ktermios *termios = &tty->termios; baud = tty_get_baud_rate(tty); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 8deaf2ad8b34ac4bafeb795a5f5a8e4dc5faf345..4e827e5a52a364162055e4856305f6fec9b7fd19 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2213,6 +2213,14 @@ static int serial_imx_probe(struct platform_device *pdev) ret); return ret; } + + ret = devm_request_irq(&pdev->dev, rtsirq, imx_rtsint, 0, + dev_name(&pdev->dev), sport); + if (ret) { + dev_err(&pdev->dev, "failed to request rts irq: %d\n", + ret); + return ret; + } } else { ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0, dev_name(&pdev->dev), sport); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index de86a31d9ce776f1efd99e293abeccc4bee00bce..17fd89ae5642255361f3fe20a4faecc7cfd6e9c7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -198,6 +198,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, { struct uart_port *uport = uart_port_check(state); unsigned long page; + unsigned long flags = 0; int retval = 0; if (uport->type == PORT_UNKNOWN) @@ -212,15 +213,18 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, * Initialise and allocate the transmit and temporary * buffer. */ - if (!state->xmit.buf) { - /* This is protected by the per port mutex */ - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + uart_port_lock(state, flags); + if (!state->xmit.buf) { state->xmit.buf = (unsigned char *) page; uart_circ_clear(&state->xmit); + } else { + free_page(page); } + uart_port_unlock(uport, flags); retval = uport->ops->startup(uport); if (retval == 0) { @@ -279,6 +283,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) { struct uart_port *uport = uart_port_check(state); struct tty_port *port = &state->port; + unsigned long flags = 0; /* * Set the TTY IO error marker @@ -311,10 +316,12 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) /* * Free the transmit buffer page. */ + uart_port_lock(state, flags); if (state->xmit.buf) { free_page((unsigned long)state->xmit.buf); state->xmit.buf = NULL; } + uart_port_unlock(uport, flags); } /** diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 8bc8fe2b75f7a34cad43ac693a1faf7c4de8720d..37dba940d8980c36ada5e64ce70119f9a59e20af 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2060,6 +2060,8 @@ static void sci_shutdown(struct uart_port *port) } #endif + if (s->rx_trigger > 1 && s->rx_fifo_timeout > 0) + del_timer_sync(&s->rx_fifo_timer); sci_free_irq(s); sci_free_dma(port); } diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c index 5c33fd25676d59bc6453d7f4a5f4a46b2aadabf1..ebc797fc1afd30d5d96b2b4fd1f73db48f93aaaf 100644 --- a/drivers/tty/tty_baudrate.c +++ b/drivers/tty/tty_baudrate.c @@ -156,18 +156,25 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, termios->c_ospeed = obaud; #ifdef BOTHER + if ((termios->c_cflag >> IBSHIFT) & CBAUD) + ibinput = 1; /* An input speed was specified */ + /* If the user asked for a precise weird speed give a precise weird answer. If they asked for a Bfoo speed they may have problems digesting non-exact replies so fuzz a bit */ - if ((termios->c_cflag & CBAUD) == BOTHER) + if ((termios->c_cflag & CBAUD) == BOTHER) { oclose = 0; + if (!ibinput) + iclose = 0; + } if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER) iclose = 0; - if ((termios->c_cflag >> IBSHIFT) & CBAUD) - ibinput = 1; /* An input speed was specified */ #endif termios->c_cflag &= ~CBAUD; +#ifdef IBSHIFT + termios->c_cflag &= ~(CBAUD << IBSHIFT); +#endif /* * Our goal is to find a close match to the standard baud rate diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 2d2b420598b236a9aa8a135ea16e74cf5763350f..7b34b0ddbf0e0281ec8ca723fb6469b5ac43d30f 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -32,6 +32,8 @@ #include #include +#include + #include #include #include @@ -700,6 +702,8 @@ int vt_ioctl(struct tty_struct *tty, if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) ret = -ENXIO; else { + vsa.console = array_index_nospec(vsa.console, + MAX_NR_CONSOLES + 1); vsa.console--; console_lock(); ret = vc_allocate(vsa.console); diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index ff04b7f8549f06f5730afb1cf6334785afab9d05..41784798c789b9dd1c1bffbd80920e346ea283a3 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -841,8 +841,6 @@ int __uio_register_device(struct module *owner, if (ret) goto err_uio_dev_add_attributes; - info->uio_dev = idev; - if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) { /* * Note that we deliberately don't use devm_request_irq @@ -858,6 +856,7 @@ int __uio_register_device(struct module *owner, goto err_request_irq; } + info->uio_dev = idev; return 0; err_request_irq: diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index f2f31fc16f2909720bd1fdf2b53d77a405098a9e..feaa0d8f830acaf9fc16b7f6733673b6bd61c4d6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -792,20 +792,9 @@ static int acm_tty_write(struct tty_struct *tty, } if (acm->susp_count) { - if (acm->putbuffer) { - /* now to preserve order */ - usb_anchor_urb(acm->putbuffer->urb, &acm->delayed); - acm->putbuffer = NULL; - } usb_anchor_urb(wb->urb, &acm->delayed); spin_unlock_irqrestore(&acm->write_lock, flags); return count; - } else { - if (acm->putbuffer) { - /* at this point there is no good way to handle errors */ - acm_start_wb(acm, acm->putbuffer); - acm->putbuffer = NULL; - } } stat = acm_start_wb(acm, wb); @@ -816,66 +805,6 @@ static int acm_tty_write(struct tty_struct *tty, return count; } -static void acm_tty_flush_chars(struct tty_struct *tty) -{ - struct acm *acm = tty->driver_data; - struct acm_wb *cur; - int err; - unsigned long flags; - - spin_lock_irqsave(&acm->write_lock, flags); - - cur = acm->putbuffer; - if (!cur) /* nothing to do */ - goto out; - - acm->putbuffer = NULL; - err = usb_autopm_get_interface_async(acm->control); - if (err < 0) { - cur->use = 0; - acm->putbuffer = cur; - goto out; - } - - if (acm->susp_count) - usb_anchor_urb(cur->urb, &acm->delayed); - else - acm_start_wb(acm, cur); -out: - spin_unlock_irqrestore(&acm->write_lock, flags); - return; -} - -static int acm_tty_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct acm *acm = tty->driver_data; - struct acm_wb *cur; - int wbn; - unsigned long flags; - -overflow: - cur = acm->putbuffer; - if (!cur) { - spin_lock_irqsave(&acm->write_lock, flags); - wbn = acm_wb_alloc(acm); - if (wbn >= 0) { - cur = &acm->wb[wbn]; - acm->putbuffer = cur; - } - spin_unlock_irqrestore(&acm->write_lock, flags); - if (!cur) - return 0; - } - - if (cur->len == acm->writesize) { - acm_tty_flush_chars(tty); - goto overflow; - } - - cur->buf[cur->len++] = ch; - return 1; -} - static int acm_tty_write_room(struct tty_struct *tty) { struct acm *acm = tty->driver_data; @@ -2000,8 +1929,6 @@ static const struct tty_operations acm_ops = { .cleanup = acm_tty_cleanup, .hangup = acm_tty_hangup, .write = acm_tty_write, - .put_char = acm_tty_put_char, - .flush_chars = acm_tty_flush_chars, .write_room = acm_tty_write_room, .ioctl = acm_tty_ioctl, .throttle = acm_tty_throttle, diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index eacc116e83da2ccf38b2640aa5b5b02b5b3621c8..ca06b20d7af9cc9567da1f243ad99935f8bc99e7 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -96,7 +96,6 @@ struct acm { unsigned long read_urbs_free; struct urb *read_urbs[ACM_NR]; struct acm_rb read_buffers[ACM_NR]; - struct acm_wb *putbuffer; /* for acm_tty_put_char() */ int rx_buflimit; spinlock_t read_lock; u8 *notification_buffer; /* to reassemble fragmented notifications */ diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index ab245352f102a6bd6821a75be6840474f82e095e..76cb9b3649b4952d48b3c01a346134b7cd835e90 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1451,10 +1451,13 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb struct async *as = NULL; struct usb_ctrlrequest *dr = NULL; unsigned int u, totlen, isofrmlen; - int i, ret, is_in, num_sgs = 0, ifnum = -1; + int i, ret, num_sgs = 0, ifnum = -1; int number_of_packets = 0; unsigned int stream_id = 0; void *buf; + bool is_in; + bool allow_short = false; + bool allow_zero = false; unsigned long mask = USBDEVFS_URB_SHORT_NOT_OK | USBDEVFS_URB_BULK_CONTINUATION | USBDEVFS_URB_NO_FSBR | @@ -1488,6 +1491,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb u = 0; switch (uurb->type) { case USBDEVFS_URB_TYPE_CONTROL: + if (is_in) + allow_short = true; if (!usb_endpoint_xfer_control(&ep->desc)) return -EINVAL; /* min 8 byte setup packet */ @@ -1528,6 +1533,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb break; case USBDEVFS_URB_TYPE_BULK: + if (!is_in) + allow_zero = true; + else + allow_short = true; switch (usb_endpoint_type(&ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_ISOC: @@ -1548,6 +1557,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb if (!usb_endpoint_xfer_int(&ep->desc)) return -EINVAL; interrupt_urb: + if (!is_in) + allow_zero = true; + else + allow_short = true; break; case USBDEVFS_URB_TYPE_ISO: @@ -1692,16 +1705,21 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb u = (is_in ? URB_DIR_IN : URB_DIR_OUT); if (uurb->flags & USBDEVFS_URB_ISO_ASAP) u |= URB_ISO_ASAP; - if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in) + if (allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) u |= URB_SHORT_NOT_OK; if (uurb->flags & USBDEVFS_URB_NO_FSBR) u |= URB_NO_FSBR; - if (uurb->flags & USBDEVFS_URB_ZERO_PACKET) + if (allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET) u |= URB_ZERO_PACKET; if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT) u |= URB_NO_INTERRUPT; as->urb->transfer_flags = u; + if (!allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) + dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_SHORT_NOT_OK.\n"); + if (!allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET) + dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_ZERO_PACKET.\n"); + as->urb->transfer_buffer_length = uurb->buffer_length; as->urb->setup_packet = (unsigned char *)dr; dr = NULL; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index becbd6173f5ad9d9aebd1518a3f98ee0d4bb4069..6a0a20ef5043829283f26084f95b135b12deb6ce 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -512,7 +512,6 @@ int usb_driver_claim_interface(struct usb_driver *driver, struct device *dev; struct usb_device *udev; int retval = 0; - int lpm_disable_error = -ENODEV; if (!iface) return -ENODEV; @@ -533,16 +532,6 @@ int usb_driver_claim_interface(struct usb_driver *driver, iface->condition = USB_INTERFACE_BOUND; - /* See the comment about disabling LPM in usb_probe_interface(). */ - if (driver->disable_hub_initiated_lpm) { - lpm_disable_error = usb_unlocked_disable_lpm(udev); - if (lpm_disable_error) { - dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.", - __func__, driver->name); - return -ENOMEM; - } - } - /* Claimed interfaces are initially inactive (suspended) and * runtime-PM-enabled, but only if the driver has autosuspend * support. Otherwise they are marked active, to prevent the @@ -561,9 +550,20 @@ int usb_driver_claim_interface(struct usb_driver *driver, if (device_is_registered(dev)) retval = device_bind_driver(dev); - /* Attempt to re-enable USB3 LPM, if the disable was successful. */ - if (!lpm_disable_error) - usb_unlocked_enable_lpm(udev); + if (retval) { + dev->driver = NULL; + usb_set_intfdata(iface, NULL); + iface->needs_remote_wakeup = 0; + iface->condition = USB_INTERFACE_UNBOUND; + + /* + * Unbound interfaces are always runtime-PM-disabled + * and runtime-PM-suspended + */ + if (driver->supports_autosuspend) + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + } return retval; } diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index ea829ad798c0773c7ea93ec0dbeda5ff1772f6ba..5340d433cdf0ebc1bdc0d47fe312763a539bc06a 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -528,8 +528,6 @@ static int resume_common(struct device *dev, int event) event == PM_EVENT_RESTORE); if (retval) { dev_err(dev, "PCI post-resume error %d!\n", retval); - if (hcd->shared_hcd) - usb_hc_died(hcd->shared_hcd); usb_hc_died(hcd); } } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index dd29e6ec1c437d5c691fa6b9dc5cc64a2be0778c..833ddd228e3a80cc150a484cc683a567df48a62e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1280,6 +1280,11 @@ void usb_enable_interface(struct usb_device *dev, * is submitted that needs that bandwidth. Some other operating systems * allocate bandwidth early, when a configuration is chosen. * + * xHCI reserves bandwidth and configures the alternate setting in + * usb_hcd_alloc_bandwidth(). If it fails the original interface altsetting + * may be disabled. Drivers cannot rely on any particular alternate + * setting being in effect after a failure. + * * This call is synchronous, and may not be used in an interrupt context. * Also, drivers must not change altsettings while urbs are scheduled for * endpoints in that interface; all such urbs must first be completed @@ -1315,6 +1320,12 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) alternate); return -EINVAL; } + /* + * usb3 hosts configure the interface in usb_hcd_alloc_bandwidth, + * including freeing dropped endpoint ring buffers. + * Make sure the interface endpoints are flushed before that + */ + usb_disable_interface(dev, iface, false); /* Make sure we have enough bandwidth for this alternate interface. * Remove the current alt setting and add the new alt setting. diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 99f67764765fdc23bf78051c4c72d914eb64f3b6..37a5e07b3488de2173574dbd757ff1520a2e9332 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -37,6 +37,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* CBM - Flash disk */ { USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME }, + /* WORLDE Controller KS49 or Prodipe MIDI 49C USB controller */ + { USB_DEVICE(0x0218, 0x0201), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* WORLDE easy key (easykey.25) MIDI controller */ { USB_DEVICE(0x0218, 0x0401), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, @@ -259,6 +263,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x2040, 0x7200), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* DJI CineSSD */ + { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, + /* INTEL VALUE SSD */ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 70990b91ea3960f7211e2e4d30bf498308fc6927..c63bf226ed5bd8296519cf15b7090ab656768362 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -228,6 +228,8 @@ struct usb_host_interface *usb_find_alt_setting( struct usb_interface_cache *intf_cache = NULL; int i; + if (!config) + return NULL; for (i = 0; i < config->desc.bNumInterfaces; i++) { if (config->intf_cache[i]->altsetting[0].desc.bInterfaceNumber == iface_num) { diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index ec965ac5f1f5dfb4ae87f1f8ee830542e436c455..3c0d386dc62fcda61b77e70357aedd464bb640fa 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -872,6 +872,7 @@ struct dwc2_hregs_backup { * @frame_list_sz: Frame list size * @desc_gen_cache: Kmem cache for generic descriptors * @desc_hsisoc_cache: Kmem cache for hs isochronous descriptors + * @unaligned_cache: Kmem cache for DMA mode to handle non-aligned buf * * These are for peripheral mode: * @@ -1004,6 +1005,8 @@ struct dwc2_hsotg { u32 frame_list_sz; struct kmem_cache *desc_gen_cache; struct kmem_cache *desc_hsisoc_cache; + struct kmem_cache *unaligned_cache; +#define DWC2_KMEM_UNALIGNED_BUF_SIZE 1024 #ifdef DEBUG u32 frrem_samples; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 6ef001a83fe28bf0320d322dcc4867304c070055..e164439b215429492ce414bd8d088109397ea639 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -848,6 +848,7 @@ static int dwc2_gadget_fill_isoc_desc(struct dwc2_hsotg_ep *hs_ep, u32 index; u32 maxsize = 0; u32 mask = 0; + u8 pid = 0; maxsize = dwc2_gadget_get_desc_params(hs_ep, &mask); if (len > maxsize) { @@ -893,7 +894,11 @@ static int dwc2_gadget_fill_isoc_desc(struct dwc2_hsotg_ep *hs_ep, ((len << DEV_DMA_NBYTES_SHIFT) & mask)); if (hs_ep->dir_in) { - desc->status |= ((hs_ep->mc << DEV_DMA_ISOC_PID_SHIFT) & + if (len) + pid = DIV_ROUND_UP(len, hs_ep->ep.maxpacket); + else + pid = 1; + desc->status |= ((pid << DEV_DMA_ISOC_PID_SHIFT) & DEV_DMA_ISOC_PID_MASK) | ((len % hs_ep->ep.maxpacket) ? DEV_DMA_SHORT : 0) | @@ -932,6 +937,7 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) u32 ctrl; if (list_empty(&hs_ep->queue)) { + hs_ep->target_frame = TARGET_FRAME_INITIAL; dev_dbg(hsotg->dev, "%s: No requests in queue\n", __func__); return; } @@ -4716,9 +4722,11 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) } ret = usb_add_gadget_udc(dev, &hsotg->gadget); - if (ret) + if (ret) { + dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep, + hsotg->ctrl_req); return ret; - + } dwc2_hsotg_dump(hsotg); return 0; @@ -4731,6 +4739,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg) { usb_del_gadget_udc(&hsotg->gadget); + dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep, hsotg->ctrl_req); return 0; } diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 46d3b0fc00c5c6dadc91d61d3bcfeb3571697449..fa20ec43a187673e7461d408d55b725bcfc611eb 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -1544,11 +1544,20 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, } if (hsotg->params.host_dma) { - dwc2_writel((u32)chan->xfer_dma, - hsotg->regs + HCDMA(chan->hc_num)); + dma_addr_t dma_addr; + + if (chan->align_buf) { + if (dbg_hc(chan)) + dev_vdbg(hsotg->dev, "align_buf\n"); + dma_addr = chan->align_buf; + } else { + dma_addr = chan->xfer_dma; + } + dwc2_writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num)); + if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n", - (unsigned long)chan->xfer_dma, chan->hc_num); + (unsigned long)dma_addr, chan->hc_num); } /* Start the split */ @@ -2604,6 +2613,35 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, } } +static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg, + struct dwc2_qh *qh, + struct dwc2_host_chan *chan) +{ + if (!hsotg->unaligned_cache || + chan->max_packet > DWC2_KMEM_UNALIGNED_BUF_SIZE) + return -ENOMEM; + + if (!qh->dw_align_buf) { + qh->dw_align_buf = kmem_cache_alloc(hsotg->unaligned_cache, + GFP_ATOMIC | GFP_DMA); + if (!qh->dw_align_buf) + return -ENOMEM; + } + + qh->dw_align_buf_dma = dma_map_single(hsotg->dev, qh->dw_align_buf, + DWC2_KMEM_UNALIGNED_BUF_SIZE, + DMA_FROM_DEVICE); + + if (dma_mapping_error(hsotg->dev, qh->dw_align_buf_dma)) { + dev_err(hsotg->dev, "can't map align_buf\n"); + chan->align_buf = 0; + return -EINVAL; + } + + chan->align_buf = qh->dw_align_buf_dma; + return 0; +} + #define DWC2_USB_DMA_ALIGN 4 static void dwc2_free_dma_aligned_buffer(struct urb *urb) @@ -2783,6 +2821,32 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) /* Set the transfer attributes */ dwc2_hc_init_xfer(hsotg, chan, qtd); + /* For non-dword aligned buffers */ + if (hsotg->params.host_dma && qh->do_split && + chan->ep_is_in && (chan->xfer_dma & 0x3)) { + dev_vdbg(hsotg->dev, "Non-aligned buffer\n"); + if (dwc2_alloc_split_dma_aligned_buf(hsotg, qh, chan)) { + dev_err(hsotg->dev, + "Failed to allocate memory to handle non-aligned buffer\n"); + /* Add channel back to free list */ + chan->align_buf = 0; + chan->multi_count = 0; + list_add_tail(&chan->hc_list_entry, + &hsotg->free_hc_list); + qtd->in_process = 0; + qh->channel = NULL; + return -ENOMEM; + } + } else { + /* + * We assume that DMA is always aligned in non-split + * case or split out case. Warn if not. + */ + WARN_ON_ONCE(hsotg->params.host_dma && + (chan->xfer_dma & 0x3)); + chan->align_buf = 0; + } + if (chan->ep_type == USB_ENDPOINT_XFER_INT || chan->ep_type == USB_ENDPOINT_XFER_ISOC) /* @@ -5277,6 +5341,19 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) } } + if (hsotg->params.host_dma) { + /* + * Create kmem caches to handle non-aligned buffer + * in Buffer DMA mode. + */ + hsotg->unaligned_cache = kmem_cache_create("dwc2-unaligned-dma", + DWC2_KMEM_UNALIGNED_BUF_SIZE, 4, + SLAB_CACHE_DMA, NULL); + if (!hsotg->unaligned_cache) + dev_err(hsotg->dev, + "unable to create dwc2 unaligned cache\n"); + } + hsotg->otg_port = 1; hsotg->frame_list = NULL; hsotg->frame_list_dma = 0; @@ -5311,8 +5388,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) return 0; error4: - kmem_cache_destroy(hsotg->desc_gen_cache); + kmem_cache_destroy(hsotg->unaligned_cache); kmem_cache_destroy(hsotg->desc_hsisoc_cache); + kmem_cache_destroy(hsotg->desc_gen_cache); error3: dwc2_hcd_release(hsotg); error2: @@ -5353,8 +5431,9 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) usb_remove_hcd(hcd); hsotg->priv = NULL; - kmem_cache_destroy(hsotg->desc_gen_cache); + kmem_cache_destroy(hsotg->unaligned_cache); kmem_cache_destroy(hsotg->desc_hsisoc_cache); + kmem_cache_destroy(hsotg->desc_gen_cache); dwc2_hcd_release(hsotg); usb_put_hcd(hcd); diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 11c3c145b79363d673b4db83be09076ac38095ee..461bdc67df6fbb244e6c1cd492fa3be5db9aff96 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -75,6 +75,8 @@ struct dwc2_qh; * (micro)frame * @xfer_buf: Pointer to current transfer buffer position * @xfer_dma: DMA address of xfer_buf + * @align_buf: In Buffer DMA mode this will be used if xfer_buf is not + * DWORD aligned * @xfer_len: Total number of bytes to transfer * @xfer_count: Number of bytes transferred so far * @start_pkt_count: Packet count at start of transfer @@ -132,6 +134,7 @@ struct dwc2_host_chan { u8 *xfer_buf; dma_addr_t xfer_dma; + dma_addr_t align_buf; u32 xfer_len; u32 xfer_count; u16 start_pkt_count; @@ -302,6 +305,9 @@ struct dwc2_hs_transfer_time { * is tightly packed. * @ls_duration_us: Duration on the low speed bus schedule. * @ntd: Actual number of transfer descriptors in a list + * @dw_align_buf: Used instead of original buffer if its physical address + * is not dword-aligned + * @dw_align_buf_dma: DMA address for dw_align_buf * @qtd_list: List of QTDs for this QH * @channel: Host channel currently processing transfers for this QH * @qh_list_entry: Entry for QH in either the periodic or non-periodic @@ -345,6 +351,8 @@ struct dwc2_qh { struct dwc2_hs_transfer_time hs_transfers[DWC2_HS_SCHEDULE_UFRAMES]; u32 ls_start_schedule_slice; u16 ntd; + u8 *dw_align_buf; + dma_addr_t dw_align_buf_dma; struct list_head qtd_list; struct dwc2_host_chan *channel; struct list_head qh_list_entry; diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 28a8210710b121616353d881b2e27c73da7e03da..17905ba1139c5698a9a72b0ef4cf2c8a67f55291 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -923,14 +923,21 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; len = dwc2_get_actual_xfer_length(hsotg, chan, chnum, qtd, DWC2_HC_XFER_COMPLETE, NULL); - if (!len) { + if (!len && !qtd->isoc_split_offset) { qtd->complete_split = 0; - qtd->isoc_split_offset = 0; return 0; } frame_desc->actual_length += len; + if (chan->align_buf) { + dev_vdbg(hsotg->dev, "non-aligned buffer\n"); + dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, + DWC2_KMEM_UNALIGNED_BUF_SIZE, DMA_FROM_DEVICE); + memcpy(qtd->urb->buf + (chan->xfer_dma - qtd->urb->dma), + chan->qh->dw_align_buf, len); + } + qtd->isoc_split_offset += len; hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 7f51a77bc5ccd3335277a474f27c6e143b58df0f..56e61220efc66a5571159ca2f46932576ab451dd 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -1632,6 +1632,9 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) if (qh->desc_list) dwc2_hcd_qh_free_ddma(hsotg, qh); + else if (hsotg->unaligned_cache && qh->dw_align_buf) + kmem_cache_free(hsotg->unaligned_cache, qh->dw_align_buf); + kfree(qh); } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7f131e901d7d791859543e765aa9c58b465ce616..e9490e367148bb456ef437dd81a02bb04ccf14fc 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -519,6 +519,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); } +static int dwc3_core_ulpi_init(struct dwc3 *dwc) +{ + int intf; + int ret = 0; + + intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3); + + if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI || + (intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI && + dwc->hsphy_interface && + !strncmp(dwc->hsphy_interface, "ulpi", 4))) + ret = dwc3_ulpi_init(dwc); + + return ret; +} + /** * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core * @dwc: Pointer to our controller context structure @@ -530,7 +546,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) static int dwc3_phy_setup(struct dwc3 *dwc) { u32 reg; - int ret; reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); @@ -605,9 +620,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc) } /* FALLTHROUGH */ case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: - ret = dwc3_ulpi_init(dwc); - if (ret) - return ret; /* FALLTHROUGH */ default: break; @@ -768,6 +780,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) } static int dwc3_core_get_phy(struct dwc3 *dwc); +static int dwc3_core_ulpi_init(struct dwc3 *dwc); /** * dwc3_core_init - Low-level initialization of DWC3 Core @@ -807,17 +820,27 @@ int dwc3_core_init(struct dwc3 *dwc) dwc->maximum_speed = USB_SPEED_HIGH; } - ret = dwc3_core_get_phy(dwc); + ret = dwc3_phy_setup(dwc); if (ret) goto err0; - ret = dwc3_core_soft_reset(dwc); - if (ret) - goto err0; + if (!dwc->ulpi_ready) { + ret = dwc3_core_ulpi_init(dwc); + if (ret) + goto err0; + dwc->ulpi_ready = true; + } - ret = dwc3_phy_setup(dwc); + if (!dwc->phys_ready) { + ret = dwc3_core_get_phy(dwc); + if (ret) + goto err0a; + dwc->phys_ready = true; + } + + ret = dwc3_core_soft_reset(dwc); if (ret) - goto err0; + goto err0a; dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); @@ -926,6 +949,9 @@ int dwc3_core_init(struct dwc3 *dwc) phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); +err0a: + dwc3_ulpi_exit(dwc); + err0: return ret; } diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index fb6cd97214a32cb6a7deabf718dea4fe8e3e7c76..f608a270dc375dd617bb4bc0edfe2cb0f04ea3ef 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -902,7 +902,9 @@ struct dwc3_scratchpad_array { * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY * @usb3_generic_phy: pointer to USB3 PHY + * @phys_ready: flag to indicate that PHYs are ready * @ulpi: pointer to ulpi interface + * @ulpi_ready: flag to indicate that ULPI is initialized * @isoch_delay: wValue from Set Isochronous Delay request; * @u2sel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request. @@ -1021,7 +1023,10 @@ struct dwc3 { struct phy *usb2_generic_phy; struct phy *usb3_generic_phy; + bool phys_ready; + struct ulpi *ulpi; + bool ulpi_ready; void __iomem *regs; size_t regs_size; diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 75b96d398142f2725de0344548357ec57646b20d..84085b29e3658adc3fe8a3fcd2132dbff2178870 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -4164,7 +4164,7 @@ static int dwc3_usb_blocking_sync(struct notifier_block *nb, dbg_event(0xFF, "fw_blocksync", 0); flush_work(&mdwc->resume_work); - flush_delayed_work(&mdwc->sm_work); + drain_workqueue(mdwc->sm_usb_wq); if (!mdwc->in_host_mode && !mdwc->in_device_mode) { dbg_event(0xFF, "lpm_state", atomic_read(&dwc->in_lpm)); diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index d40ad0576a299693592a28e4144e239d71ca04f8..b0a78d57f1e0728cf18d9fe98b476d78bce49d3e 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -148,8 +148,9 @@ static int dwc3_of_simple_remove(struct platform_device *pdev) of_platform_depopulate(dev); - pm_runtime_put_sync(dev); pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + pm_runtime_set_suspended(dev); return 0; } diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index bc5e91d4fac87c80d184fccd24267467666d0dd3..09c0454833ad20cdde3e940b51eac9a1448d8815 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -41,6 +41,7 @@ #define PCI_DEVICE_ID_INTEL_GLK 0x31aa #define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee #define PCI_DEVICE_ID_INTEL_CNPH 0xa36e +#define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee #define PCI_INTEL_BXT_DSM_GUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511" #define PCI_INTEL_BXT_FUNC_PMU_PWR 4 @@ -273,6 +274,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICLLP), }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), }, { } /* Terminating Entry */ }; diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 6406fc4b99071925ea6787cef814e4e98520dbdc..2f22d74c5309d9e5c3cedffee753480bd4d60bfa 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -33,7 +33,7 @@ struct dwc3; #define DWC3_DEPCFG_XFER_IN_PROGRESS_EN BIT(9) #define DWC3_DEPCFG_XFER_NOT_READY_EN BIT(10) #define DWC3_DEPCFG_FIFO_ERROR_EN BIT(11) -#define DWC3_DEPCFG_STREAM_EVENT_EN BIT(12) +#define DWC3_DEPCFG_STREAM_EVENT_EN BIT(13) #define DWC3_DEPCFG_BINTERVAL_M1(n) (((n) & 0xff) << 16) #define DWC3_DEPCFG_STREAM_CAPABLE BIT(24) #define DWC3_DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 4df3b587a3777e701676a9b67b552decb323ba67..5e83dd319efdd1e1b44b03cb9e8c94f0dd0a3b72 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1856,6 +1856,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) */ if (w_value && !f->get_alt) break; + + spin_lock(&cdev->lock); value = f->set_alt(f, w_index, w_value); if (value == USB_GADGET_DELAYED_STATUS) { DBG(cdev, @@ -1865,6 +1867,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) DBG(cdev, "delayed_status count %d\n", cdev->delayed_status); } + spin_unlock(&cdev->lock); break; case USB_REQ_GET_INTERFACE: if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) @@ -2461,7 +2464,13 @@ void composite_resume(struct usb_gadget *gadget) f->func_wakeup_pending = 0; } - if (gadget->speed != USB_SPEED_SUPER && f->resume) + /* + * Call function resume irrespective of the speed. + * Individual function needs to retain the USB3 Function + * suspend state through out the Device suspend entry + * and exit process. + */ + if (f->resume) f->resume(f); } diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index d25bb0cebd44789defe8e40c9b2ab601cc7a2801..457da74660b646701b5f5a72a947af4b793e9f12 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -230,6 +230,7 @@ struct ffs_io_data { struct mm_struct *mm; struct work_struct work; + struct work_struct cancellation_work; struct usb_ep *ep; struct usb_request *req; @@ -1156,25 +1157,34 @@ ffs_epfile_open(struct inode *inode, struct file *file) return 0; } +static void ffs_aio_cancel_worker(struct work_struct *work) +{ + struct ffs_io_data *io_data = container_of(work, struct ffs_io_data, + cancellation_work); + + ENTER(); + + usb_ep_dequeue(io_data->ep, io_data->req); +} + 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; + struct ffs_data *ffs = io_data->ffs; int value; ENTER(); - 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); + ffs_log("enter:state %d setup_state %d flag %lu", ffs->state, + ffs->setup_state, ffs->flags); - if (likely(io_data && io_data->ep && io_data->req)) - value = usb_ep_dequeue(io_data->ep, io_data->req); - else + if (likely(io_data && io_data->ep && io_data->req)) { + INIT_WORK(&io_data->cancellation_work, ffs_aio_cancel_worker); + queue_work(ffs->io_completion_wq, &io_data->cancellation_work); + value = -EINPROGRESS; + } else { value = -EINVAL; - - spin_unlock_irq(&epfile->ffs->eps_lock); + } 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 fb2907027d2934694858e6e55041f557dd8ca7b9..95a10c52e1a0886ee870621358f41cf88c4ae067 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -586,8 +586,9 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) /* Populate connection params */ conn_params->max_pkt_size = - (cdev->gadget->speed >= USB_SPEED_SUPER) ? - IPA_USB_SUPER_SPEED_1024B : IPA_USB_HIGH_SPEED_512B; + le16_to_cpu(d_port->in_ep->desc->wMaxPacketSize); + log_event_dbg("%s(): max_pkt_size:%d\n", __func__, + conn_params->max_pkt_size); conn_params->ipa_to_usb_xferrscidx = d_port->in_xfer_rsc_index; conn_params->usb_to_ipa_xferrscidx = diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c index 4313fa8790b261d3978f605629881989704496e1..b230d94d8a23094e926b278864cfe8b624562c01 100644 --- a/drivers/usb/gadget/function/f_qdss.c +++ b/drivers/usb/gadget/function/f_qdss.c @@ -677,7 +677,6 @@ static int qdss_set_alt(struct usb_function *f, unsigned int intf, if (gadget->speed < USB_SPEED_HIGH) { pr_err("%s: qdss doesn't support USB full or low speed\n", __func__); - ret = -EINVAL; goto fail1; } diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 619d0f0bca2be39bb5263a2e726e2d59d76b882e..574a63a655d05b1f714e3251baa30f182cd1cf2d 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -491,14 +491,14 @@ static struct usb_descriptor_header *ss_audio_desc[] = { }; struct cntrl_cur_lay3 { - __u32 dCUR; + __le32 dCUR; }; struct cntrl_range_lay3 { - __u16 wNumSubRanges; - __u32 dMIN; - __u32 dMAX; - __u32 dRES; + __le16 wNumSubRanges; + __le32 dMIN; + __le32 dMAX; + __le32 dRES; } __packed; static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, @@ -613,13 +613,13 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); if (!agdev->out_ep) { dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return ret; + return -ENODEV; } agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); if (!agdev->in_ep) { dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return ret; + return -ENODEV; } agdev->in_ep_maxpsize = max_t(u16, @@ -757,9 +757,9 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) memset(&c, 0, sizeof(struct cntrl_cur_lay3)); if (entity_id == USB_IN_CLK_ID) - c.dCUR = p_srate; + c.dCUR = cpu_to_le32(p_srate); else if (entity_id == USB_OUT_CLK_ID) - c.dCUR = c_srate; + c.dCUR = cpu_to_le32(c_srate); value = min_t(unsigned, w_length, sizeof c); memcpy(req->buf, &c, value); @@ -796,15 +796,15 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { if (entity_id == USB_IN_CLK_ID) - r.dMIN = p_srate; + r.dMIN = cpu_to_le32(p_srate); else if (entity_id == USB_OUT_CLK_ID) - r.dMIN = c_srate; + r.dMIN = cpu_to_le32(c_srate); else return -EOPNOTSUPP; r.dMAX = r.dMIN; r.dRES = 0; - r.wNumSubRanges = 1; + r.wNumSubRanges = cpu_to_le16(1); value = min_t(unsigned, w_length, sizeof r); memcpy(req->buf, &r, value); diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index 147a958be7caa62c6bff5909adb90fd35669bec9..435f0614d57206e9cccf0e82b67e28918f2c5fc4 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -41,9 +41,6 @@ struct uac_req { struct uac_rtd_params { struct snd_uac_chip *uac; /* parent chip */ bool ep_enabled; /* if the ep is enabled */ - /* Size of the ring buffer */ - size_t dma_bytes; - unsigned char *dma_area; struct snd_pcm_substream *ss; @@ -52,8 +49,6 @@ struct uac_rtd_params { void *rbuf; - size_t period_size; - unsigned max_psize; /* MaxPacketSize of endpoint */ struct uac_req *ureq; @@ -93,12 +88,12 @@ static const struct snd_pcm_hardware uac_pcm_hardware = { static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) { unsigned pending; - unsigned long flags; + unsigned long flags, flags2; unsigned int hw_ptr; - bool update_alsa = false; int status = req->status; struct uac_req *ur = req->context; struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; struct uac_rtd_params *prm = ur->pp; struct snd_uac_chip *uac = prm->uac; @@ -120,6 +115,14 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) if (!substream) goto exit; + snd_pcm_stream_lock_irqsave(substream, flags2); + + runtime = substream->runtime; + if (!runtime || !snd_pcm_running(substream)) { + snd_pcm_stream_unlock_irqrestore(substream, flags2); + goto exit; + } + spin_lock_irqsave(&prm->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -146,43 +149,46 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) req->actual = req->length; } - pending = prm->hw_ptr % prm->period_size; - pending += req->actual; - if (pending >= prm->period_size) - update_alsa = true; - hw_ptr = prm->hw_ptr; - prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes; spin_unlock_irqrestore(&prm->lock, flags); /* Pack USB load in ALSA ring buffer */ - pending = prm->dma_bytes - hw_ptr; + pending = runtime->dma_bytes - hw_ptr; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (unlikely(pending < req->actual)) { - memcpy(req->buf, prm->dma_area + hw_ptr, pending); - memcpy(req->buf + pending, prm->dma_area, + memcpy(req->buf, runtime->dma_area + hw_ptr, pending); + memcpy(req->buf + pending, runtime->dma_area, req->actual - pending); } else { - memcpy(req->buf, prm->dma_area + hw_ptr, req->actual); + memcpy(req->buf, runtime->dma_area + hw_ptr, + req->actual); } } else { if (unlikely(pending < req->actual)) { - memcpy(prm->dma_area + hw_ptr, req->buf, pending); - memcpy(prm->dma_area, req->buf + pending, + memcpy(runtime->dma_area + hw_ptr, req->buf, pending); + memcpy(runtime->dma_area, req->buf + pending, req->actual - pending); } else { - memcpy(prm->dma_area + hw_ptr, req->buf, req->actual); + memcpy(runtime->dma_area + hw_ptr, req->buf, + req->actual); } } + spin_lock_irqsave(&prm->lock, flags); + /* update hw_ptr after data is copied to memory */ + prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes; + hw_ptr = prm->hw_ptr; + spin_unlock_irqrestore(&prm->lock, flags); + snd_pcm_stream_unlock_irqrestore(substream, flags2); + + if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual) + snd_pcm_period_elapsed(substream); + exit: if (usb_ep_queue(ep, req, GFP_ATOMIC)) dev_err(uac->card->dev, "%d Error!\n", __LINE__); - - if (update_alsa) - snd_pcm_period_elapsed(substream); } static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) @@ -245,40 +251,12 @@ static snd_pcm_uframes_t uac_pcm_pointer(struct snd_pcm_substream *substream) static int uac_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_uac_chip *uac = snd_pcm_substream_chip(substream); - struct uac_rtd_params *prm; - int err; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - prm = &uac->p_prm; - else - prm = &uac->c_prm; - - err = snd_pcm_lib_malloc_pages(substream, + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err >= 0) { - prm->dma_bytes = substream->runtime->dma_bytes; - prm->dma_area = substream->runtime->dma_area; - prm->period_size = params_period_bytes(hw_params); - } - - return err; } static int uac_pcm_hw_free(struct snd_pcm_substream *substream) { - struct snd_uac_chip *uac = snd_pcm_substream_chip(substream); - struct uac_rtd_params *prm; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - prm = &uac->p_prm; - else - prm = &uac->c_prm; - - prm->dma_area = NULL; - prm->dma_bytes = 0; - prm->period_size = 0; - return snd_pcm_lib_free_pages(substream); } @@ -609,15 +587,15 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, if (err < 0) goto snd_fail; - strcpy(pcm->name, pcm_name); + strlcpy(pcm->name, pcm_name, sizeof(pcm->name)); pcm->private_data = uac; uac->pcm = pcm; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops); - strcpy(card->driver, card_name); - strcpy(card->shortname, card_name); + strlcpy(card->driver, card_name, sizeof(card->driver)); + strlcpy(card->shortname, card_name, sizeof(card->shortname)); sprintf(card->longname, "%s %i", card_name, card->dev->id); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index f608c1f85e611f2a36fd6389006e3f00837a7035..9cbb061582a774676eb6cf4d42b8d84eb19b10f3 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -1549,11 +1549,14 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on) writel(tmp | BIT(USB_DETECT_ENABLE), &dev->usb->usbctl); } else { writel(tmp & ~BIT(USB_DETECT_ENABLE), &dev->usb->usbctl); - stop_activity(dev, dev->driver); + stop_activity(dev, NULL); } spin_unlock_irqrestore(&dev->lock, flags); + if (!is_on && dev->driver) + dev->driver->disconnect(&dev->gadget); + return 0; } @@ -2470,8 +2473,11 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver) nuke(&dev->ep[i]); /* report disconnect; the driver is already quiesced */ - if (driver) + if (driver) { + spin_unlock(&dev->lock); driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + } usb_reinit(dev); } @@ -3345,6 +3351,8 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) BIT(PCI_RETRY_ABORT_INTERRUPT)) static void handle_stat1_irqs(struct net2280 *dev, u32 stat) +__releases(dev->lock) +__acquires(dev->lock) { struct net2280_ep *ep; u32 tmp, num, mask, scratch; @@ -3385,12 +3393,14 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat) if (disconnect || reset) { stop_activity(dev, dev->driver); ep0_start(dev); + spin_unlock(&dev->lock); if (reset) usb_gadget_udc_reset (&dev->gadget, dev->driver); else (dev->driver->disconnect) (&dev->gadget); + spin_lock(&dev->lock); return; } } @@ -3409,6 +3419,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat) tmp = BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT); if (stat & tmp) { writel(tmp, &dev->regs->irqstat1); + spin_unlock(&dev->lock); if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) { if (dev->driver->suspend) dev->driver->suspend(&dev->gadget); @@ -3419,6 +3430,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat) dev->driver->resume(&dev->gadget); /* at high speed, note erratum 0133 */ } + spin_lock(&dev->lock); stat &= ~tmp; } diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index 118ad70f1af0f109714a83cfd4b48327382c3268..84b227ede08232eca9fd1b3602150c06a5fdff4c 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -835,11 +835,11 @@ static void init_controller(struct r8a66597 *r8a66597) r8a66597_bset(r8a66597, XCKE, SYSCFG0); - msleep(3); + mdelay(3); r8a66597_bset(r8a66597, PLLC, SYSCFG0); - msleep(1); + mdelay(1); r8a66597_bset(r8a66597, SCKE, SYSCFG0); @@ -1193,7 +1193,7 @@ __acquires(r8a66597->lock) r8a66597->ep0_req->length = 2; /* AV: what happens if we get called again before that gets through? */ spin_unlock(&r8a66597->lock); - r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_KERNEL); + r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_ATOMIC); spin_lock(&r8a66597->lock); } diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index c12a1a6554bad90bd36d805e3805453f433c5121..36a706f475d251d89bbbcac46258aec724393e10 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -788,12 +788,15 @@ static void usb3_irq_epc_int_1_speed(struct renesas_usb3 *usb3) switch (speed) { case USB_STA_SPEED_SS: usb3->gadget.speed = USB_SPEED_SUPER; + usb3->gadget.ep0->maxpacket = USB3_EP0_SS_MAX_PACKET_SIZE; break; case USB_STA_SPEED_HS: usb3->gadget.speed = USB_SPEED_HIGH; + usb3->gadget.ep0->maxpacket = USB3_EP0_HSFS_MAX_PACKET_SIZE; break; case USB_STA_SPEED_FS: usb3->gadget.speed = USB_SPEED_FULL; + usb3->gadget.ep0->maxpacket = USB3_EP0_HSFS_MAX_PACKET_SIZE; break; default: usb3->gadget.speed = USB_SPEED_UNKNOWN; @@ -2458,7 +2461,7 @@ static int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev, /* for control pipe */ usb3->gadget.ep0 = &usb3_ep->ep; usb_ep_set_maxpacket_limit(&usb3_ep->ep, - USB3_EP0_HSFS_MAX_PACKET_SIZE); + USB3_EP0_SS_MAX_PACKET_SIZE); usb3_ep->ep.caps.type_control = true; usb3_ep->ep.caps.dir_in = true; usb3_ep->ep.caps.dir_out = true; diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index c38855aed62c7df6ef3c7e134eae2c9b0e787da2..65c0086e25ae6d8ac1a302308e954ef15d88c41d 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2559,7 +2559,7 @@ static int u132_get_frame(struct usb_hcd *hcd) } else { int frame = 0; dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n"); - msleep(100); + mdelay(100); return frame; } } diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 74436f8ca5382f736dbf352c21b7c2f83a8438ba..32ddafe7af87d08276a03118e46b6e7b8f5494e6 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -482,7 +482,7 @@ static void tegra_xusb_mbox_handle(struct tegra_xusb *tegra, unsigned long mask; unsigned int port; bool idle, enable; - int err; + int err = 0; memset(&rsp, 0, sizeof(rsp)); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8cc779d9c99890ba23421002f7719cdbcf129b86..ad87c69869c9dc55059a1f3ad1796212f70c2512 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -47,6 +47,21 @@ static unsigned int quirks; module_param(quirks, uint, S_IRUGO); MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); +static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring) +{ + struct xhci_segment *seg = ring->first_seg; + + if (!td || !td->start_seg) + return false; + do { + if (seg == td->start_seg) + return true; + seg = seg->next; + } while (seg && seg != ring->first_seg); + + return false; +} + /* TODO: copied from ehci-hcd.c - can this be refactored? */ /* * xhci_handshake - spin reading hc until handshake completes or fails @@ -1030,8 +1045,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) command = readl(&xhci->op_regs->command); command |= CMD_CRS; writel(command, &xhci->op_regs->command); + /* + * Some controllers take up to 55+ ms to complete the controller + * restore so setting the timeout to 100ms. Xhci specification + * doesn't mention any timeout value. + */ if (xhci_handshake(&xhci->op_regs->status, - STS_RESTORE, 0, 10 * 1000)) { + STS_RESTORE, 0, 100 * 1000)) { xhci_warn(xhci, "WARN: xHC restore state timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; @@ -1512,6 +1532,21 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) goto done; } + /* + * check ring is not re-allocated since URB was enqueued. If it is, then + * make sure none of the ring related pointers in this URB private data + * are touched, such as td_list, otherwise we overwrite freed data + */ + if (!td_on_ring(&urb_priv->td[0], ep_ring)) { + xhci_err(xhci, "Canceled URB td not found on endpoint ring"); + for (i = urb_priv->num_tds_done; i < urb_priv->num_tds; i++) { + td = &urb_priv->td[i]; + if (!list_empty(&td->cancelled_td_list)) + list_del_init(&td->cancelled_td_list); + } + goto err_giveback; + } + if (xhci->xhc_state & XHCI_STATE_HALTED) { xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "HC halted, freeing TD manually."); diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 740db57464fc21814afc0102bd13d7aeda0b55c5..3118935961cc4f06e837e4ff24ce94ef83cc8218 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -281,3 +281,9 @@ config USB_REDRIVER_NB7VPQ904M depends on USB_PHY help Say Y here if you want to support USB super speed re-driver NB7VPQ904M. + +config USB_TYPEC_MUX_NXP5150A + tristate "Enable driver for NXP CC Logic chipset NXP5150A" + help + Say Y here if you want to use NXP CC Logic Type-C Chipset NXP5150A + for CC detection and Mux control. diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 4f7d20242470f7e9b7057f2d97512f7bb8225291..37baeaa384fc99631c14b0d84abe131cc56efb04 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_HUB_USB251XB) += usb251xb.o obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o obj-$(CONFIG_USB_HSIC_USB4604) += usb4604.o obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o +obj-$(CONFIG_USB_TYPEC_MUX_NXP5150A) += nxp_typec.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o diff --git a/drivers/usb/misc/nxp_typec.c b/drivers/usb/misc/nxp_typec.c new file mode 100644 index 0000000000000000000000000000000000000000..df6c6767a95e42875d292f858eee8eddd9fd4789 --- /dev/null +++ b/drivers/usb/misc/nxp_typec.c @@ -0,0 +1,262 @@ +/* Copyright (c) 2018, 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 + +#define CONTROL_REG 0x02 +#define STATUS_REG 0x04 +#define INTR_MASK_REG 0x18 +#define INTR_STATUS_REG 0x19 + +#define DISABLE_CABLE_INTR 0x05 +#define ENABLE_ROLE_CHANGE_INTR 0x08 + +#define ROLE_CHANGE_INTR_STATUS BIT(3) +#define GET_PORT_ROLE(n) (((n) >> 2) & 0x03) + +struct nxpusb5150a { + struct device *dev; + struct regmap *regmap; + struct extcon_dev *extcon; + + struct gpio_desc *vbus_out_gpio; +}; + +enum port_role { + PORT_ROLE_DISCONNECTED, + PORT_ROLE_UFP, + PORT_ROLE_DFP, +}; + +static const unsigned int nxpusb5150a_extcon_cable[] = { + EXTCON_USB_HOST, + EXTCON_NONE, +}; + +static const struct regmap_config nxpusb5150a_regmap = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int nxpusb5150a_read_reg(struct nxpusb5150a *nxp, u8 reg, u8 *val) +{ + int ret; + unsigned int reg_val; + + ret = regmap_read(nxp->regmap, (unsigned int)reg, ®_val); + if (ret < 0) { + dev_err(nxp->dev, "Failed to read reg:0x%02x\n", reg); + return ret; + } + + *val = (u8)reg_val; + dev_dbg(nxp->dev, "read reg:0x%02x val:0x%02x\n", reg, *val); + + return 0; +} + +static int nxpusb5150a_write_reg(struct nxpusb5150a *nxp, u8 reg, u8 mask, + u8 val) +{ + int ret; + u8 reg_val; + + ret = nxpusb5150a_read_reg(nxp, reg, ®_val); + if (ret) + return ret; + + val |= (reg_val & mask); + ret = regmap_write(nxp->regmap, (unsigned int)reg, (unsigned int)val); + if (ret < 0) { + dev_err(nxp->dev, "failed to write 0x%02x to reg: 0x%02x\n", + val, reg); + return ret; + } + + dev_dbg(nxp->dev, "write reg:0x%02x val:0x%02x\n", reg, val); + + return 0; +} +static irqreturn_t nxusb5150a_cable_thread_handler(int irq, void *dev_id) +{ + struct nxpusb5150a *nxp = dev_id; + union extcon_property_value val; + u8 status; + enum port_role role; + int ret; + + ret = nxpusb5150a_read_reg(nxp, INTR_STATUS_REG, &status); + if (ret) + goto error; + + if (!(status & ROLE_CHANGE_INTR_STATUS)) { + dev_dbg(nxp->dev, "No change in role of port\n"); + return IRQ_HANDLED; + } + + ret = nxpusb5150a_read_reg(nxp, STATUS_REG, &status); + if (ret) + goto error; + + role = GET_PORT_ROLE(status); + switch (role) { + case PORT_ROLE_DFP: + val.intval = 1; + if (nxp->vbus_out_gpio) + gpiod_set_value_cansleep(nxp->vbus_out_gpio, 1); + extcon_set_state_sync(nxp->extcon, EXTCON_USB_HOST, 1); + break; + + case PORT_ROLE_UFP: + dev_err(nxp->dev, "Port does not support device mode(UFP)\n"); + case PORT_ROLE_DISCONNECTED: + default: + if (nxp->vbus_out_gpio) + gpiod_set_value_cansleep(nxp->vbus_out_gpio, 0); + extcon_set_state_sync(nxp->extcon, EXTCON_USB_HOST, 0); + break; + } + + return IRQ_HANDLED; + + /* + * Register read failures are treated as errors. + * So notify the state as disconnected whenever the failures are seen. + */ +error: + if (nxp->vbus_out_gpio) + gpiod_set_value_cansleep(nxp->vbus_out_gpio, 0); + extcon_set_state_sync(nxp->extcon, EXTCON_USB_HOST, 0); + + return IRQ_HANDLED; +} + +/* + * Configure the NXP 5150a chipset to enable the role change + * interrupt and disable the remaining interrupts. + */ +static int nxpusb5150a_configure_interrupts(struct nxpusb5150a *nxp) +{ + int ret; + + /* + * Cable detach and attach interrupts are enabled after + * reset. So disable the same. + * Also set the mode to DRP so that the chipset can + * detect DFP connections. + */ + ret = nxpusb5150a_write_reg(nxp, CONTROL_REG, ~DISABLE_CABLE_INTR, + DISABLE_CABLE_INTR); + if (ret) + return ret; + + /* Enable the interrupt to detect role change.*/ + ret = nxpusb5150a_write_reg(nxp, INTR_MASK_REG, + ~ENABLE_ROLE_CHANGE_INTR, 0); + if (ret) + return ret; + + return 0; +} + +static int nxpusb5150a_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct nxpusb5150a *nxp; + int ret; + + nxp = devm_kzalloc(dev, sizeof(nxp), GFP_KERNEL); + if (!nxp) + return -ENOMEM; + + nxp->dev = dev; + + nxp->regmap = devm_regmap_init_i2c(client, &nxpusb5150a_regmap); + if (IS_ERR(nxp->regmap)) { + dev_err(nxp->dev, "Failed to allocate register map: %d\n", + PTR_ERR(nxp->regmap)); + return PTR_ERR(nxp->regmap); + } + + i2c_set_clientdata(client, nxp); + + nxp->extcon = devm_extcon_dev_allocate(dev, nxpusb5150a_extcon_cable); + if (IS_ERR(nxp->extcon)) { + dev_err(nxp->dev, "Failed to allocate extcon device: %d\n", + PTR_ERR(nxp->extcon)); + return PTR_ERR(nxp->extcon); + } + + ret = devm_extcon_dev_register(dev, nxp->extcon); + if (ret) { + dev_err(nxp->dev, "Failed to register extcon device: %d\n", + ret); + return ret; + } + + nxp->vbus_out_gpio = devm_gpiod_get_optional(nxp->dev, "vbus-out", + GPIOD_OUT_HIGH); + if (!nxp->vbus_out_gpio) + dev_err(dev, "No external VBUS GPIO supplied\n"); + + if (!client->irq) { + dev_err(dev, "no client irq\n"); + return -EINVAL; + } + + ret = devm_request_threaded_irq(dev, client->irq, NULL, + nxusb5150a_cable_thread_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->name, nxp); + if (ret < 0) { + dev_err(nxp->dev, "Failed to request interrupt handler\n"); + return ret; + } + + ret = nxpusb5150a_configure_interrupts(nxp); + if (ret) { + dev_err(dev, "failed to configure interrupts\n"); + return ret; + } + + nxusb5150a_cable_thread_handler(client->irq, nxp); + + return 0; +} + +static const struct of_device_id nxpusb5150a_match_table[] = { + { .compatible = "nxp,5150a",}, + { }, +}; + +static const struct i2c_device_id nxpusb5150a_table[] = { + { "nxpusb5150a" }, + {} +}; +MODULE_DEVICE_TABLE(i2c, nxpusb5150a_table); + +static struct i2c_driver nxpusb5150a_driver = { + .driver = { + .name = "nxpusb5150a", + .owner = THIS_MODULE, + .of_match_table = nxpusb5150a_match_table, + }, + .probe_new = nxpusb5150a_probe, + .id_table = nxpusb5150a_table, +}; +module_i2c_driver(nxpusb5150a_driver); diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 8a13b2fcf3e135d0403f1e6d40641906e45277f9..03152f98108c784ef6cb2d5951bb39b8f2921c88 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -382,7 +382,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch mask &= 0x0f; val &= 0x0f; d = (priv->reg[1] & (~mask)) ^ val; - if (set_1284_register(pp, 2, d, GFP_KERNEL)) + if (set_1284_register(pp, 2, d, GFP_ATOMIC)) return 0; priv->reg[1] = d; return d & 0xf; @@ -392,7 +392,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp) { unsigned char ret; - if (get_1284_register(pp, 1, &ret, GFP_KERNEL)) + if (get_1284_register(pp, 1, &ret, GFP_ATOMIC)) return 0; return ret & 0xf8; } diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 47763311a42e15a20eae8eee6b2b0427541ba773..0673f286afbd4abb3a360540c3c95dae6237a078 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -425,13 +425,13 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, { struct usb_yurex *dev; int i, set = 0, retval = 0; - char buffer[16]; + char buffer[16 + 1]; char *data = buffer; unsigned long long c, c2 = 0; signed long timeout = 0; DEFINE_WAIT(wait); - count = min(sizeof(buffer), count); + count = min(sizeof(buffer) - 1, count); dev = file->private_data; /* verify that we actually have some data to write */ @@ -450,6 +450,7 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, retval = -EFAULT; goto error; } + buffer[count] = 0; memset(dev->cntl_buffer, CMD_PADDING, YUREX_BUF_SIZE); switch (buffer[0]) { diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index f6b526606ad1092494f3d8eaac6946bd77069ad2..dbb482b7e0ba61181b6eb2be614e312b55240893 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -684,16 +684,6 @@ dsps_dma_controller_create(struct musb *musb, void __iomem *base) return controller; } -static void dsps_dma_controller_destroy(struct dma_controller *c) -{ - struct musb *musb = c->musb; - struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); - void __iomem *usbss_base = glue->usbss_base; - - musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP); - cppi41_dma_controller_destroy(c); -} - #ifdef CONFIG_PM_SLEEP static void dsps_dma_controller_suspend(struct dsps_glue *glue) { @@ -723,7 +713,7 @@ static struct musb_platform_ops dsps_ops = { #ifdef CONFIG_USB_TI_CPPI41_DMA .dma_init = dsps_dma_controller_create, - .dma_exit = dsps_dma_controller_destroy, + .dma_exit = cppi41_dma_controller_destroy, #endif .enable = dsps_musb_enable, .disable = dsps_musb_disable, diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index bd82fb9d17043327610c9193d28ef0d97b65fa13..70c5a7fef47867881711204568fd05c5467f3632 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -2001,6 +2001,9 @@ static void dr_swap(struct usbpd *pd) start_usb_host(pd, true); pd->current_dr = DR_DFP; + /* ensure host is started before allowing DP */ + extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 0); + usbpd_send_svdm(pd, USBPD_SID, USBPD_SVDM_DISCOVER_IDENTITY, SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0); } diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index cf8f40ae6e017943c9ae97e50fca17d50304d51e..9b4354a00ca71d7377bb846390c6f346e6593e48 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -874,6 +874,7 @@ int usb_otg_start(struct platform_device *pdev) if (pdata->init && pdata->init(pdev) != 0) return -EINVAL; +#ifdef CONFIG_PPC32 if (pdata->big_endian_mmio) { _fsl_readl = _fsl_readl_be; _fsl_writel = _fsl_writel_be; @@ -881,6 +882,7 @@ int usb_otg_start(struct platform_device *pdev) _fsl_readl = _fsl_readl_le; _fsl_writel = _fsl_writel_le; } +#endif /* request irq */ p_otg->irq = platform_get_irq(pdev, 0); @@ -971,7 +973,7 @@ int usb_otg_start(struct platform_device *pdev) /* * state file in sysfs */ -static int show_fsl_usb2_otg_state(struct device *dev, +static ssize_t show_fsl_usb2_otg_state(struct device *dev, struct device_attribute *attr, char *buf) { struct otg_fsm *fsm = &fsl_otg_dev->fsm; diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index d61ca0d89c97db38c7fdee9ee70f1c0afcead237..b95986c458c23d74fca4f9653a705505ee135605 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include enum core_ldo_levels { CORE_LEVEL_NONE = 0, @@ -83,6 +85,10 @@ enum core_ldo_levels { /* USB3 Gen2 link training indicator */ #define RX_EQUALIZATION_IN_PROGRESS BIT(3) +#define USB3_DP_PCS_CDR_RESET_TIME 0x1DB0 +#define USB3_UNI_PCS_CDR_RESET_TIME 0x09B0 +#define USB3_DP_PCS_EQ_CONFIG5 0x1DEC +#define USB3_UNI_PCS_EQ_CONFIG5 0x09EC enum qmp_phy_rev_reg { USB3_PHY_PCS_STATUS, @@ -137,6 +143,8 @@ struct msm_ssphy_qmp { struct reset_control *phy_reset; struct reset_control *phy_phy_reset; struct reset_control *global_phy_reset; + struct extcon_dev *extcon_dp; + struct notifier_block dp_nb; bool power_enabled; bool clk_enabled; bool cable_connected; @@ -146,6 +154,10 @@ struct msm_ssphy_qmp { u32 *qmp_phy_init_seq; int init_seq_len; struct hrtimer timer; + + bool link_training_reset; + u32 cdr_reset_time_offset; + u32 eq_config5_offset; }; static const struct of_device_id msm_usb_id_table[] = { @@ -170,6 +182,7 @@ MODULE_DEVICE_TABLE(of, msm_usb_id_table); static void usb_qmp_powerup_phy(struct msm_ssphy_qmp *phy); static void msm_ssphy_qmp_enable_clks(struct msm_ssphy_qmp *phy, bool on); +static int msm_ssphy_qmp_link_training(struct usb_phy *uphy, bool start); static inline char *get_cable_status_str(struct msm_ssphy_qmp *phy) { @@ -375,9 +388,11 @@ static void usb_qmp_update_portselect_phymode(struct msm_ssphy_qmp *phy) switch (phy->phy.type) { case USB_PHY_TYPE_USB3_AND_DP: /* override hardware control for reset of qmp phy */ - writel_relaxed(SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | - SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET, - phy->base + phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]); + if (!(phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE)) + writel_relaxed(SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | + SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET, + phy->base + + phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]); /* update port select */ if (val > 0) { @@ -387,11 +402,13 @@ static void usb_qmp_update_portselect_phymode(struct msm_ssphy_qmp *phy) phy->phy_reg[USB3_DP_COM_TYPEC_CTRL]); } - msm_ssphy_qmp_setmode(phy, USB3_DP_COMBO_MODE); + if (!(phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE)) { + msm_ssphy_qmp_setmode(phy, USB3_DP_COMBO_MODE); - /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ - writel_relaxed(0x00, - phy->base + phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]); + /* bring both USB and DP PHYs PCS block out of reset */ + writel_relaxed(0x00, phy->base + + phy->phy_reg[USB3_DP_COM_RESET_OVRD_CTRL]); + } break; case USB_PHY_TYPE_USB3_OR_DP: if (val > 0) { @@ -442,6 +459,30 @@ static void usb_qmp_powerup_phy(struct msm_ssphy_qmp *phy) mb(); } +static void usb_qmp_apply_link_training_workarounds(struct msm_ssphy_qmp *phy) +{ + uint32_t version, major, minor; + + if (!phy->link_training_reset) + return; + + version = socinfo_get_version(); + minor = SOCINFO_VERSION_MINOR(version); + major = SOCINFO_VERSION_MAJOR(version); + + /* sw workaround is needed only for hw reviosions below 2.1 */ + if ((major < 2) || (major == 2 && minor == 0)) { + writel_relaxed(0x52, phy->base + phy->eq_config5_offset); + phy->phy.link_training = msm_ssphy_qmp_link_training; + return; + } + + if (!phy->cdr_reset_time_offset) + return; + + writel_relaxed(0xA, phy->base + phy->cdr_reset_time_offset); +} + /* SSPHY Initialization */ static int msm_ssphy_qmp_init(struct usb_phy *uphy) { @@ -478,8 +519,11 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy) return ret; } + usb_qmp_apply_link_training_workarounds(phy); + /* perform software reset of PHY common logic */ - if (phy->phy.type == USB_PHY_TYPE_USB3_AND_DP) + if (phy->phy.type == USB_PHY_TYPE_USB3_AND_DP && + !(phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE)) writel_relaxed(0x00, phy->base + phy->phy_reg[USB3_DP_COM_SW_RESET]); @@ -517,6 +561,25 @@ static int msm_ssphy_qmp_dp_combo_reset(struct usb_phy *uphy) phy); int ret = 0; + if (phy->phy.flags & PHY_USB_DP_CONCURRENT_MODE) { + dev_dbg(uphy->dev, "Resetting USB part of QMP phy\n"); + + /* Assert USB3 PHY CSR reset */ + ret = reset_control_assert(phy->phy_reset); + if (ret) { + dev_err(uphy->dev, "phy_reset assert failed\n"); + goto exit; + } + + /* Deassert USB3 PHY CSR reset */ + ret = reset_control_deassert(phy->phy_reset); + if (ret) { + dev_err(uphy->dev, "phy_reset deassert failed\n"); + goto exit; + } + return 0; + } + dev_dbg(uphy->dev, "Global reset of QMP DP combo phy\n"); /* Assert global PHY reset */ ret = reset_control_assert(phy->global_phy_reset); @@ -800,6 +863,56 @@ static int msm_ssphy_qmp_powerup(struct usb_phy *uphy, bool powerup) return 0; } +static int msm_ssphy_qmp_vbus_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + return 0; +} + +static int msm_ssphy_qmp_dp_notifier(struct notifier_block *nb, + unsigned long dp_lane, void *ptr) +{ + struct msm_ssphy_qmp *phy = container_of(nb, + struct msm_ssphy_qmp, dp_nb); + + if (dp_lane == 2 || dp_lane == 4) + phy->phy.flags |= PHY_USB_DP_CONCURRENT_MODE; + else + phy->phy.flags &= ~PHY_USB_DP_CONCURRENT_MODE; + + return 0; + +} + +static int msm_ssphy_qmp_extcon_register(struct msm_ssphy_qmp *phy, + struct device *dev) +{ + struct device_node *node = dev->of_node; + struct extcon_dev *edev; + int ret = 0; + + if (!of_property_read_bool(node, "extcon")) + return 0; + + edev = extcon_get_edev_by_phandle(dev, 0); + if (IS_ERR(edev)) { + dev_err(dev, "failed to get phandle for msm_ssphy_qmp\n"); + return PTR_ERR(edev); + } + + phy->extcon_dp = edev; + phy->phy.vbus_nb.notifier_call = msm_ssphy_qmp_vbus_notifier; + phy->dp_nb.notifier_call = msm_ssphy_qmp_dp_notifier; + ret = extcon_register_blocking_notifier(edev, EXTCON_DISP_DP, + &phy->dp_nb); + if (ret < 0) { + dev_err(dev, "failed to register blocking notifier\n"); + return ret; + } + + return 0; +} + static int msm_ssphy_qmp_get_clks(struct msm_ssphy_qmp *phy, struct device *dev) { int ret = 0; @@ -1102,15 +1215,25 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev) phy->phy.notify_connect = msm_ssphy_qmp_notify_connect; phy->phy.notify_disconnect = msm_ssphy_qmp_notify_disconnect; phy->phy.powerup = msm_ssphy_qmp_powerup; + phy->phy.reset = msm_ssphy_qmp_reset; - if (of_property_read_bool(dev->of_node, "qcom,link-training-reset")) - phy->phy.link_training = msm_ssphy_qmp_link_training; + if (phy->phy.type == USB_PHY_TYPE_USB3_AND_DP) { + phy->eq_config5_offset = USB3_DP_PCS_EQ_CONFIG5; + phy->cdr_reset_time_offset = USB3_DP_PCS_CDR_RESET_TIME; + phy->phy.reset = msm_ssphy_qmp_dp_combo_reset; + } + if (phy->phy.type == USB_PHY_TYPE_USB3) { + phy->eq_config5_offset = USB3_UNI_PCS_EQ_CONFIG5; + phy->cdr_reset_time_offset = USB3_UNI_PCS_CDR_RESET_TIME; + } - if (phy->phy.type == USB_PHY_TYPE_USB3_AND_DP) - phy->phy.reset = msm_ssphy_qmp_dp_combo_reset; - else - phy->phy.reset = msm_ssphy_qmp_reset; + phy->link_training_reset = of_property_read_bool(dev->of_node, + "qcom,link-training-reset"); + + ret = msm_ssphy_qmp_extcon_register(phy, dev); + if (ret) + goto err; ret = usb_add_phy_dev(&phy->phy); diff --git a/drivers/usb/serial/io_ti.h b/drivers/usb/serial/io_ti.h index 1bd67b24f9160a2d9b674151708c3fb5e13b2821..bc9ff5ebd67c1b5a1ab1ea4c4e619558c47f8c32 100644 --- a/drivers/usb/serial/io_ti.h +++ b/drivers/usb/serial/io_ti.h @@ -178,7 +178,7 @@ struct ump_interrupt { } __attribute__((packed)); -#define TIUMP_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3) +#define TIUMP_GET_PORT_FROM_CODE(c) (((c) >> 6) & 0x01) #define TIUMP_GET_FUNC_FROM_CODE(c) ((c) & 0x0f) #define TIUMP_INTERRUPT_CODE_LSR 0x03 #define TIUMP_INTERRUPT_CODE_MSR 0x04 diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 3024b9b253605160a5f5e7038159bcc47ec4d1ea..75181d3afd958a81d2de0dfde24092481c089637 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -397,12 +397,20 @@ static int kobil_tiocmget(struct tty_struct *tty) transfer_buffer_length, KOBIL_TIMEOUT); - dev_dbg(&port->dev, "%s - Send get_status_line_state URB returns: %i. Statusline: %02x\n", - __func__, result, transfer_buffer[0]); + dev_dbg(&port->dev, "Send get_status_line_state URB returns: %i\n", + result); + if (result < 1) { + if (result >= 0) + result = -EIO; + goto out_free; + } + + dev_dbg(&port->dev, "Statusline: %02x\n", transfer_buffer[0]); result = 0; if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) result = TIOCM_DSR; +out_free: kfree(transfer_buffer); return result; } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 8fc3854e5e6967dc32f1a04e5ba95a304f10b683..57e9f6617084f4ae7aa62fafd9d8bcff6925549e 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1123,7 +1123,7 @@ static void ti_break(struct tty_struct *tty, int break_state) static int ti_get_port_from_code(unsigned char code) { - return (code >> 4) - 3; + return (code >> 6) & 0x01; } static int ti_get_func_from_code(unsigned char code) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 8cd2926fb1fe6f9a77fc8943beb5ac2eb3ddd40d..344ec8631481ee41dce9e7242f9063580bae696d 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -392,6 +392,15 @@ static int queuecommand_lck(struct scsi_cmnd *srb, return 0; } + if ((us->fflags & US_FL_NO_ATA_1X) && + (srb->cmnd[0] == ATA_12 || srb->cmnd[0] == ATA_16)) { + memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB, + sizeof(usb_stor_sense_invalidCDB)); + srb->result = SAM_STAT_CHECK_CONDITION; + done(srb); + return 0; + } + /* enqueue the command and wake up the control thread */ srb->scsi_done = done; us->srb = srb; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 33a6d624c8438b50e29c23bbf86af1cdf20d91d8..24de9c00d8e2498234fbc10887442950a1559977 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -842,6 +842,27 @@ static int uas_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; sdev->wce_default_on = 1; } + + /* + * Some disks return the total number of blocks in response + * to READ CAPACITY rather than the highest block number. + * If this device makes that mistake, tell the sd driver. + */ + if (devinfo->flags & US_FL_FIX_CAPACITY) + sdev->fix_capacity = 1; + + /* + * Some devices don't like MODE SENSE with page=0x3f, + * which is the command used for checking if a device + * is write-protected. Now that we tell the sd driver + * to do a 192-byte transfer with this command the + * majority of devices work fine, but a few still can't + * handle it. The sd driver will simply assume those + * devices are write-enabled. + */ + if (devinfo->flags & US_FL_NO_WP_DETECT) + sdev->skip_ms_page_3f = 1; + scsi_change_queue_depth(sdev, devinfo->qdepth - 2); return 0; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d100290628bd26beb11991ebbcd8e6c84d6d719a..5e9b35a91431987e1c14dd57ebb7a38a669daa64 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2307,6 +2307,13 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_GO_SLOW ), +/* Reported-by: Tim Anderson */ +UNUSUAL_DEV( 0x2ca3, 0x0031, 0x0000, 0x9999, + "DJI", + "CineSSD", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_ATA_1X), + /* * Reported by Frederic Marchal * Mio Moov 330 diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index 170f2c38de9b5695e37008c9dc975787f66021cb..5274aa7339b8fffc281e653134ccfdf57f99e790 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -230,7 +230,7 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, 0, secd, sizeof(*secd)); - if (result < sizeof(*secd)) { + if (result < (int)sizeof(*secd)) { dev_err(dev, "Can't read security descriptor or " "not enough data: %d\n", result); goto out; diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 9a53912bdfe9f73d4b7de6a1d3b74dd8a94dc8b6..5d3ba747ae17a8882a959ff7be59309eecf11c36 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c @@ -873,6 +873,7 @@ static int hwarc_probe(struct usb_interface *iface, error_rc_add: usb_put_intf(iface); usb_put_dev(hwarc->usb_dev); + kfree(hwarc); error_alloc: uwb_rc_put(uwb_rc); error_rc_alloc: diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 3cf74f54c7a1e2645f12c71c06e2c4da96a47044..7ee3167bc083e6ea1c36bd0795240d84d520eb19 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -960,7 +960,7 @@ static void vhost_iotlb_notify_vq(struct vhost_dev *d, list_for_each_entry_safe(node, n, &d->pending_list, node) { struct vhost_iotlb_msg *vq_msg = &node->msg.iotlb; if (msg->iova <= vq_msg->iova && - msg->iova + msg->size - 1 > vq_msg->iova && + msg->iova + msg->size - 1 >= vq_msg->iova && vq_msg->type == VHOST_IOTLB_MISS) { vhost_poll_queue(&node->vq->poll); list_del(&node->node); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 8634175da1fbf6e386ddea9741a4cd587e3e89af..f7f56121c746f09ca57cab536a3a855020e651cd 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1734,12 +1734,12 @@ static int do_register_framebuffer(struct fb_info *fb_info) return 0; } -static int do_unregister_framebuffer(struct fb_info *fb_info) +static int unbind_console(struct fb_info *fb_info) { struct fb_event event; - int i, ret = 0; + int ret; + int i = fb_info->node; - i = fb_info->node; if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) return -EINVAL; @@ -1754,17 +1754,29 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) unlock_fb_info(fb_info); console_unlock(); + return ret; +} + +static int __unlink_framebuffer(struct fb_info *fb_info); + +static int do_unregister_framebuffer(struct fb_info *fb_info) +{ + struct fb_event event; + int ret; + + ret = unbind_console(fb_info); + if (ret) return -EINVAL; pm_vt_switch_unregister(fb_info->dev); - unlink_framebuffer(fb_info); + __unlink_framebuffer(fb_info); if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) kfree(fb_info->pixmap.addr); fb_destroy_modelist(&fb_info->modelist); - registered_fb[i] = NULL; + registered_fb[fb_info->node] = NULL; num_registered_fb--; fb_cleanup_device(fb_info); event.info = fb_info; @@ -1777,7 +1789,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) return 0; } -int unlink_framebuffer(struct fb_info *fb_info) +static int __unlink_framebuffer(struct fb_info *fb_info) { int i; @@ -1789,6 +1801,20 @@ int unlink_framebuffer(struct fb_info *fb_info) device_destroy(fb_class, MKDEV(FB_MAJOR, i)); fb_info->dev = NULL; } + + return 0; +} + +int unlink_framebuffer(struct fb_info *fb_info) +{ + int ret; + + ret = __unlink_framebuffer(fb_info); + if (ret) + return ret; + + unbind_console(fb_info); + return 0; } EXPORT_SYMBOL(unlink_framebuffer); diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c index 2510fa728d77160326781219ec554ae50c99be4a..de119f11b78f964301ef9dafa4c3f1043b6e53e2 100644 --- a/drivers/video/fbdev/core/modedb.c +++ b/drivers/video/fbdev/core/modedb.c @@ -644,7 +644,7 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, * * Valid mode specifiers for @mode_option: * - * x[M][R][-][@][i][m] or + * x[M][R][-][@][i][p][m] or * [-][@] * * with , , and decimal numbers and @@ -653,10 +653,10 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, * If 'M' is present after yres (and before refresh/bpp if present), * the function will compute the timings using VESA(tm) Coordinated * Video Timings (CVT). If 'R' is present after 'M', will compute with - * reduced blanking (for flatpanels). If 'i' is present, compute - * interlaced mode. If 'm' is present, add margins equal to 1.8% - * of xres rounded down to 8 pixels, and 1.8% of yres. The char - * 'i' and 'm' must be after 'M' and 'R'. Example: + * reduced blanking (for flatpanels). If 'i' or 'p' are present, compute + * interlaced or progressive mode. If 'm' is present, add margins equal + * to 1.8% of xres rounded down to 8 pixels, and 1.8% of yres. The chars + * 'i', 'p' and 'm' must be after 'M' and 'R'. Example: * * 1024x768MR-8@60m - Reduced blank with margins at 60Hz. * @@ -697,7 +697,8 @@ int fb_find_mode(struct fb_var_screeninfo *var, unsigned int namelen = strlen(name); int res_specified = 0, bpp_specified = 0, refresh_specified = 0; unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; - int yres_specified = 0, cvt = 0, rb = 0, interlace = 0; + int yres_specified = 0, cvt = 0, rb = 0; + int interlace_specified = 0, interlace = 0; int margins = 0; u32 best, diff, tdiff; @@ -748,9 +749,17 @@ int fb_find_mode(struct fb_var_screeninfo *var, if (!cvt) margins = 1; break; + case 'p': + if (!cvt) { + interlace = 0; + interlace_specified = 1; + } + break; case 'i': - if (!cvt) + if (!cvt) { interlace = 1; + interlace_specified = 1; + } break; default: goto done; @@ -819,11 +828,21 @@ int fb_find_mode(struct fb_var_screeninfo *var, if ((name_matches(db[i], name, namelen) || (res_specified && res_matches(db[i], xres, yres))) && !fb_try_mode(var, info, &db[i], bpp)) { - if (refresh_specified && db[i].refresh == refresh) - return 1; + const int db_interlace = (db[i].vmode & + FB_VMODE_INTERLACED ? 1 : 0); + int score = abs(db[i].refresh - refresh); + + if (interlace_specified) + score += abs(db_interlace - interlace); + + if (!interlace_specified || + db_interlace == interlace) + if (refresh_specified && + db[i].refresh == refresh) + return 1; - if (abs(db[i].refresh - refresh) < diff) { - diff = abs(db[i].refresh - refresh); + if (score < diff) { + diff = score; best = i; } } diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c index 1e56b50e408234f826fd28fdaa1bee0807911dcf..8c93ad1dd9cc899a9ce492797f81a4c3ce4aa211 100644 --- a/drivers/video/fbdev/goldfishfb.c +++ b/drivers/video/fbdev/goldfishfb.c @@ -302,6 +302,7 @@ static int goldfish_fb_remove(struct platform_device *pdev) dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base, fb->fb.fix.smem_start); iounmap(fb->reg_base); + kfree(fb); return 0; } diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile index 09f874f1d956fcb2a4b49d2736fd883ac9123b7a..35b2a0fbb4087e770dede4fa7bdf6023655f020d 100644 --- a/drivers/video/fbdev/msm/Makefile +++ b/drivers/video/fbdev/msm/Makefile @@ -56,7 +56,8 @@ obj-$(CONFIG_FB_MSM_MDSS_EDP_PANEL) += mdss_edp_aux.o obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_tx.o obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_panel.o -obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_hdcp.o +obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdcp_1x.o +obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdcp_2x.o obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_hdcp2p2.o obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_cec.o obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_audio.o diff --git a/drivers/video/fbdev/msm/mdss_cec_core.c b/drivers/video/fbdev/msm/mdss_cec_core.c index 23a3ce55c2d62f68302b48d6678bb7c40095a825..b072ca4c22c662a556a4c605b43d81213fa0c7c7 100644 --- a/drivers/video/fbdev/msm/mdss_cec_core.c +++ b/drivers/video/fbdev/msm/mdss_cec_core.c @@ -50,7 +50,7 @@ static struct cec_ctl *cec_get_ctl(struct device *dev) struct mdss_panel_info *pinfo; if (!dev) { - pr_err("invalid input\n"); + pr_err("invalid device\n"); goto error; } @@ -83,8 +83,13 @@ static int cec_msg_send(struct cec_ctl *ctl, struct cec_msg *msg) int ret = -EINVAL; struct cec_ops *ops; - if (!ctl || !msg) { - pr_err("invalid input\n"); + if (!ctl) { + pr_err("invalid cec ctl\n"); + goto end; + } + + if (!msg) { + pr_err("invalid cec message\n"); goto end; } @@ -101,8 +106,13 @@ static void cec_dump_msg(struct cec_ctl *ctl, struct cec_msg *msg) int i; unsigned long flags; - if (!ctl || !msg) { - pr_err("invalid input\n"); + if (!ctl) { + pr_err("invalid cec ctl\n"); + return; + } + + if (!msg) { + pr_err("invalid cec message\n"); return; } @@ -136,7 +146,7 @@ static int cec_disable(struct cec_ctl *ctl) struct cec_ops *ops; if (!ctl) { - pr_err("Invalid input\n"); + pr_err("invalid cec ctl\n"); goto end; } @@ -165,7 +175,7 @@ static int cec_enable(struct cec_ctl *ctl) struct cec_ops *ops; if (!ctl) { - pr_err("Invalid input\n"); + pr_err("invalid cec ctl\n"); goto end; } @@ -189,8 +199,13 @@ static int cec_send_abort_opcode(struct cec_ctl *ctl, int i = 0; struct cec_msg out_msg; - if (!ctl || !in_msg) { - pr_err("Invalid input\n"); + if (!ctl) { + pr_err("invalid cec ctl\n"); + return -EINVAL; + } + + if (!in_msg) { + pr_err("invalid cec message\n"); return -EINVAL; } @@ -209,10 +224,14 @@ static int cec_msg_parser(struct cec_ctl *ctl, struct cec_msg *in_msg) int rc = 0, i = 0; struct cec_msg out_msg; - if (!ctl || !in_msg) { - pr_err("Invalid input\n"); - rc = -EINVAL; - goto end; + if (!ctl) { + pr_err("invalid cec ctl\n"); + return -EINVAL; + } + + if (!in_msg) { + pr_err("invalid cec message\n"); + return -EINVAL; } pr_debug("in_msg->opcode = 0x%x\n", in_msg->opcode); @@ -345,7 +364,7 @@ static int cec_msg_recv(void *data, struct cec_msg *msg) int ret = 0; if (!ctl) { - pr_err("invalid input\n"); + pr_err("invalid cec ctl\n"); ret = -EINVAL; goto end; } @@ -395,7 +414,7 @@ static ssize_t cec_rda_enable(struct device *dev, struct cec_ctl *ctl = cec_get_ctl(dev); if (!ctl) { - pr_err("Invalid input\n"); + pr_err("invalid cec ctl\n"); ret = -EINVAL; goto end; } @@ -423,7 +442,7 @@ static ssize_t cec_wta_enable(struct device *dev, struct cec_ops *ops; if (!ctl) { - pr_err("Invalid input\n"); + pr_err("invalid cec ctl\n"); ret = -EINVAL; goto end; } @@ -475,7 +494,7 @@ static ssize_t cec_rda_enable_compliance(struct device *dev, struct cec_ctl *ctl = cec_get_ctl(dev); if (!ctl) { - pr_err("Invalid ctl\n"); + pr_err("invalid cec ctl\n"); return -EINVAL; } @@ -497,7 +516,7 @@ static ssize_t cec_wta_enable_compliance(struct device *dev, struct cec_ops *ops; if (!ctl) { - pr_err("Invalid ctl\n"); + pr_err("invalid cec ctl\n"); ret = -EINVAL; goto end; } @@ -543,7 +562,7 @@ static ssize_t cec_rda_logical_addr(struct device *dev, struct cec_ctl *ctl = cec_get_ctl(dev); if (!ctl) { - pr_err("Invalid ctl\n"); + pr_err("invalid cec ctl\n"); return -EINVAL; } @@ -564,7 +583,7 @@ static ssize_t cec_wta_logical_addr(struct device *dev, struct cec_ops *ops; if (!ctl) { - pr_err("Invalid ctl\n"); + pr_err("invalid cec ctl\n"); ret = -EINVAL; goto end; } @@ -578,7 +597,7 @@ static ssize_t cec_wta_logical_addr(struct device *dev, } if (logical_addr < 0 || logical_addr > 15) { - pr_err("Invalid logical address\n"); + pr_err("invalid logical address\n"); ret = -EINVAL; goto end; } @@ -604,7 +623,7 @@ static ssize_t cec_rda_msg(struct device *dev, ssize_t ret; if (!ctl) { - pr_err("Invalid ctl\n"); + pr_err("invalid cec ctl\n"); ret = -EINVAL; goto end; } @@ -660,7 +679,7 @@ static ssize_t cec_wta_msg(struct device *dev, struct cec_ctl *ctl = cec_get_ctl(dev); if (!ctl) { - pr_err("Invalid ctl\n"); + pr_err("invalid cec ctl\n"); ret = -EINVAL; goto end; } @@ -763,7 +782,7 @@ void *cec_abstract_init(struct cec_abstract_init_data *init_data) int ret = 0; if (!init_data) { - pr_err("invalid input\n"); + pr_err("invalid cec abstract init data\n"); ret = -EINVAL; goto end; } diff --git a/drivers/video/fbdev/msm/mdss_dba_utils.c b/drivers/video/fbdev/msm/mdss_dba_utils.c index b920d2e1d7cf7c7e21c7d1a23ec1f05e2ea42d55..f56667f2f01d856a248d115c154d87e55d8108d8 100644 --- a/drivers/video/fbdev/msm/mdss_dba_utils.c +++ b/drivers/video/fbdev/msm/mdss_dba_utils.c @@ -298,7 +298,7 @@ static bool mdss_dba_check_audio_support(struct mdss_dba_utils_data *udata) { bool dvi_mode = false; int audio_blk_size = 0; - struct msm_hdmi_audio_edid_blk audio_blk; + struct msm_ext_disp_audio_edid_blk audio_blk; if (!udata) { pr_debug("%s: Invalid input\n", __func__); @@ -307,7 +307,7 @@ static bool mdss_dba_check_audio_support(struct mdss_dba_utils_data *udata) memset(&audio_blk, 0, sizeof(audio_blk)); /* check if sink is in DVI mode */ - dvi_mode = !hdmi_edid_get_sink_mode(udata->edid_data); + dvi_mode = hdmi_edid_is_dvi_mode(udata->edid_data); /* get the audio block size info from EDID */ hdmi_edid_get_audio_blk(udata->edid_data, &audio_blk); @@ -328,7 +328,7 @@ static void mdss_dba_utils_dba_cb(void *data, enum msm_dba_callback_event event) bool operands_present = false; u32 no_of_operands, size, i; u32 operands_offset = MAX_CEC_FRAME_SIZE - MAX_OPERAND_SIZE; - struct msm_hdmi_audio_edid_blk blk; + struct msm_ext_disp_audio_edid_blk blk; if (!udata) { pr_err("Invalid data\n"); @@ -578,7 +578,7 @@ int mdss_dba_utils_video_on(void *data, struct mdss_panel_info *pinfo) video_cfg.h_pulse_width = pinfo->lcdc.h_pulse_width; video_cfg.v_pulse_width = pinfo->lcdc.v_pulse_width; video_cfg.pclk_khz = (unsigned long)pinfo->clk_rate / 1000; - video_cfg.hdmi_mode = hdmi_edid_get_sink_mode(ud->edid_data); + video_cfg.hdmi_mode = !hdmi_edid_is_dvi_mode(ud->edid_data); /* Calculate number of DSI lanes configured */ video_cfg.num_of_input_lanes = 0; diff --git a/drivers/video/fbdev/msm/mdss_hdcp.h b/drivers/video/fbdev/msm/mdss_hdcp.h new file mode 100644 index 0000000000000000000000000000000000000000..5edb3b54000bc3c7725fa04903c67b82bf9f1483 --- /dev/null +++ b/drivers/video/fbdev/msm/mdss_hdcp.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2012, 2014-2018, 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. + */ + +#ifndef __MDSS_HDCP_H__ +#define __MDSS_HDCP_H__ + +#include