Merge "msm: ipa4: register only apps cons with PM"
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-cpu-sdm632.txt b/Documentation/devicetree/bindings/arm/msm/clock-cpu-sdm632.txt
new file mode 100644
index 0000000..2d89614
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/clock-cpu-sdm632.txt
@@ -0,0 +1,94 @@
+Qualcomm Technologies, Inc SDM632 CPU clock driver
+
+clock-cpu-sdm632 is a device that represents the SDM632 CPU subystem clock
+tree. It lists the various power supplies that need to be scaled when the
+clocks are scaled and also other HW specific parameters like fmax tables etc.
+
+The root clock generator could have the ramp controller in built.
+Ramp control will allow programming the sequence ID for pulse swallowing,
+enable sequence and for linking sequence IDs.
+
+Required properties:
+- compatible: Must be "qcom,clock-cpu-sdm632".
+
+- reg: Pairs of physical base addresses and region sizes of
+ memory mapped registers.
+- reg-names: Names of the bases for the above registers. Expected
+ bases are:
+ "apcs-c1-pll-base", "apcs-c0-pll-base",
+ "apcs-cci-pll-base", "apcs-c1-rcg-base",
+ "apcs-c0-rcg-base", "apcs-cci-rcg-base",
+ "efuse", "rcgwr-c0-base(optional)",
+ "rcgwr-c1-base(optional)".
+- clocks: The clocks sources used by the cluster/cci mux.
+- clock-names: Name of the clocks for the above clocks.
+- vdd-mx-supply: The regulator powering all the PLLs of clusters & cci.
+- vdd-c0-supply: The regulator powering the cluster 0.
+- vdd-c1-supply: The regulator powering the cluster 1.
+- vdd-cci-supply: The regulator powering the CCI cluster.
+
+- qcom,speedX-bin-vY-ZZZ:
+ A table of CPU frequency (Hz) to voltage (corner)
+ mapping that represents the max frequency possible
+ for each supported voltage level for a CPU. 'X' is
+ the speed bin into which the device falls into - a
+ bin will have unique frequency-voltage relationships.
+ 'Y' is the characterization version, implying that
+ characterization (deciding what speed bin a device
+ falls into) methods and/or encoding may change. The
+ values 'X' and 'Y' are read from efuse registers, and
+ the right table is picked from multiple possible tables.
+ 'ZZZ' can be cl for(c0 & c1) or cci depending on whether
+ the table for the clusters or cci.
+
+Example:
+ clock_cpu {
+ compatible = "qcom,cpu-clock-sdm632";
+ reg = <0xb114000 0x68>,
+ <0xb014000 0x68>,
+ <0xb016000 0x8>,
+ <0xb116000 0x8>,
+ <0xb1d0000 0x8>,
+ <0xb011050 0x8>,
+ <0xb111050 0x8>,
+ <0xb1d1050 0x8>,
+ <0x00a412c 0x8>;
+ reg-names = "rcgwr-c0-base", "rcgwr-c1-base",
+ "apcs-c1-pll-base", "apcs-c0-pll-base",
+ "apcs-cci-pll-base", "apcs-c1-rcg-base",
+ "apcs-c0-rcg-base", "apcs-cci-rcg-base",
+ "efuse";
+ qcom,num-clusters = <2>;
+ vdd-mx-supply = <&pm8953_s7_level_ao>;
+ vdd-c0-supply = <&apc_vreg_corner>;
+ vdd-c1-supply = <&apc_vreg_corner>;
+ vdd-cci-supply = <&apc_vreg_corner>;
+ clocks = <&clock_gcc clk_xo_a_clk_src>;
+ clock-names = "xo_a";
+ qcom,speed0-bin-v0-c0 =
+ < 0 0>,
+ < 614400000 1>,
+ < 883200000 2>,
+ < 1036200000 3>,
+ < 1363200000 4>,
+ < 1563000000 5>,
+ < 1670400000 6>,
+ < 1785600000 7>;
+ qcom,speed0-bin-v0-c1 =
+ < 0 0>,
+ < 633600000 1>,
+ < 902400000 2>,
+ < 1094400000 3>,
+ < 1401600000 4>,
+ < 1555200000 5>,
+ < 1785600000 6>;
+ qcom,speed0-bin-v0-cci =
+ < 0 0>,
+ < 307200000 1>,
+ < 403200000 2>,
+ < 499200000 3>,
+ < 691200000 4>,
+ < 768000000 5>,
+ < 787200000 6>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/qcom,debugcc.txt b/Documentation/devicetree/bindings/clock/qcom,debugcc.txt
new file mode 100644
index 0000000..a4452a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,debugcc.txt
@@ -0,0 +1,20 @@
+Qualcomm Technologies, Inc. Debug Clock Controller Binding
+----------------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+ "qcom,debugcc-sdm845"
+ "qcom,debugcc-sdxpoorwills"
+
+- clock-names: Shall contain "xo_clk_src"
+- clocks: phandle + clock reference to the CXO clock.
+- #clock-cells : Shall contain 1.
+
+Example:
+ clock_debug: qcom,cc-debug {
+ compatible = "qcom,sdxpoorwills";
+ qcom,gcc = <&clock_gcc>;
+ clock-names = "xo_clk_src";
+ clocks = <&clock_rpmh RPMH_CXO_CLK>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 7330db4..ba29471 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -20,7 +20,6 @@
"qcom,gcc-sdm845-v2"
"qcom,gcc-sdm845-v2.1"
"qcom,gcc-sdm670"
- "qcom,debugcc-sdm845"
"qcom,gcc-sdxpoorwills"
- reg : shall contain base register location and length
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8917-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8917-pinctrl.txt
new file mode 100644
index 0000000..d2327a257
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8917-pinctrl.txt
@@ -0,0 +1,204 @@
+Qualcomm Technologies, Inc. MSM8917 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8917 platform.
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be "qcom,msm8917-pinctrl"
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+ Usage: required
+ Value type: <string-array>
+ Definition: List of gpio pins affected by the properties specified in
+ this subnode.
+ Valid pins are:
+ gpio0-gpio133,
+ sdc1_clk,
+ sdc1_cmd,
+ sdc1_data,
+ sdc1_rclk,
+ sdc2_clk,
+ sdc2_cmd,
+ sdc2_data,
+ qdsd_clk,
+ qdsd_cmd,
+ qdsd_data0,
+ qdsd_data1,
+ qdsd_data2,
+ qdsd_data3,
+
+- function:
+ Usage: required
+ Value type: <string>
+ Definition: Specify the alternative function to be configured for the
+ specified pins. Functions are only valid for gpio pins.
+ Valid values are:
+ qdss_tracedata_b, blsp_uart1, gpio, blsp_spi1, adsp_ext, blsp_i2c1, prng_rosc,
+ qdss_cti_trig_out_b0, blsp_spi2, blsp_uart2, blsp_uart3, pbs0, pbs1,
+ pwr_modem_enabled_b, blsp_i2c3, gcc_gp2_clk_b, ldo_update,
+ atest_combodac_to_gpio_native, ldo_en, blsp_i2c2, gcc_gp1_clk_b, pbs2,
+ atest_gpsadc_dtest0_native, blsp_spi3, gcc_gp3_clk_b, blsp_spi4, blsp_uart4,
+ sec_mi2s, pwr_nav_enabled_b, codec_mad, pwr_crypto_enabled_b, blsp_i2c4,
+ blsp_spi5, blsp_uart5, qdss_traceclk_a, atest_bbrx1, m_voc,
+ qdss_cti_trig_in_a0, qdss_cti_trig_in_b0, blsp_i2c6, qdss_traceclk_b,
+ atest_wlan0, atest_wlan1, atest_bbrx0, blsp_i2c5, qdss_tracectl_a,
+ atest_gpsadc_dtest1_native, qdss_tracedata_a, blsp_spi6, blsp_uart6,
+ qdss_tracectl_b, mdp_vsync, pri_mi2s_mclk_a, sec_mi2s_mclk_a, cam_mclk,
+ cci_i2c, pwr_modem_enabled_a, cci_timer0, cci_timer1, cam1_standby,
+ pwr_nav_enabled_a, cam1_rst, pwr_crypto_enabled_a, forced_usb,
+ qdss_cti_trig_out_b1, cam2_rst, webcam_standby, cci_async, webcam_rst,
+ ov_ldo, sd_write, accel_int, gcc_gp1_clk_a, alsp_int, gcc_gp2_clk_a,
+ mag_int, gcc_gp3_clk_a, blsp6_spi, fp_int, qdss_cti_trig_in_b1, uim_batt,
+ cam2_standby, uim1_data, uim1_clk, uim1_reset, uim1_present, uim2_data,
+ uim2_clk, uim2_reset, uim2_present, sensor_rst, mipi_dsi0, smb_int,
+ cam0_ldo, us_euro, atest_char3, dbg_out, bimc_dte0, ts_resout, ts_sample,
+ sec_mi2s_mclk_b, pri_mi2s, sdcard_det, atest_char1, ebi_cdc, audio_reset,
+ atest_char0, audio_ref, cdc_pdm0, pri_mi2s_mclk_b, lpass_slimbus,
+ lpass_slimbus0, lpass_slimbus1, codec_int1, codec_int2, wcss_bt,
+ atest_char2, ebi_ch0, wcss_wlan2, wcss_wlan1, wcss_wlan0, wcss_wlan,
+ wcss_fm, ext_lpass, cri_trng, cri_trng1, cri_trng0, blsp_spi7, blsp_uart7,
+ pri_mi2s_ws, blsp_i2c7, gcc_tlmm, dmic0_clk, dmic0_data, key_volp,
+ qdss_cti_trig_in_a1, us_emitter, wsa_irq, wsa_io, wsa_reset, blsp_spi8,
+ blsp_uart8, blsp_i2c8, gcc_plltest, nav_pps_in_a, pa_indicator, modem_tsync,
+ nav_tsync, nav_pps_in_b, nav_pps, gsm0_tx, atest_char, atest_tsens,
+ bimc_dte1, ssbi_wtr1, fp_gpio, coex_uart, key_snapshot, key_focus, nfc_pwr,
+ blsp8_spi, qdss_cti_trig_out_a0, qdss_cti_trig_out_a1
+
+- bias-disable:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull up.
+
+- output-high:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ high.
+ Not valid for sdc pins.
+
+- output-low:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ low.
+ Not valid for sdc pins.
+
+- drive-strength:
+ Usage: optional
+ Value type: <u32>
+ Definition: Selects the drive strength for the specified pins, in mA.
+ Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,msm8917-pinctrl";
+ reg = <0x1000000 0x300000>;
+ interrupts = <0 208 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ pmx-uartconsole {
+ uart_console_active: uart_console_active {
+ mux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio4", "gpio5";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ uart_console_sleep: uart_console_sleep {
+ mux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio4", "gpio5";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ };
+ };
diff --git a/Makefile b/Makefile
index 1de0efc..42db02e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 9
-SUBLEVEL = 81
+SUBLEVEL = 82
EXTRAVERSION =
NAME = Roaring Lionus
diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
index 2b0ac42..412bb3c 100644
--- a/arch/alpha/kernel/pci_impl.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -143,7 +143,8 @@
};
#if defined(CONFIG_ALPHA_SRM) && \
- (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA))
+ (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA) || \
+ defined(CONFIG_ALPHA_AVANTI))
# define NEED_SRM_SAVE_RESTORE
#else
# undef NEED_SRM_SAVE_RESTORE
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index b483156..60c17b9 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -265,12 +265,13 @@
application calling fork. */
if (clone_flags & CLONE_SETTLS)
childti->pcb.unique = regs->r20;
+ else
+ regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */
childti->pcb.usp = usp ?: rdusp();
*childregs = *regs;
childregs->r0 = 0;
childregs->r19 = 0;
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
- regs->r20 = 0;
stack = ((struct switch_stack *) regs) - 1;
*childstack = *stack;
childstack->r26 = (unsigned long) ret_from_fork;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 74aceea..32ba92c 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -158,11 +158,16 @@
for(i=0; i < kstack_depth_to_print; i++) {
if (((long) stack & (THREAD_SIZE-1)) == 0)
break;
- if (i && ((i % 4) == 0))
- printk("\n ");
- printk("%016lx ", *stack++);
+ if ((i % 4) == 0) {
+ if (i)
+ pr_cont("\n");
+ printk(" ");
+ } else {
+ pr_cont(" ");
+ }
+ pr_cont("%016lx", *stack++);
}
- printk("\n");
+ pr_cont("\n");
dik_show_trace(sp);
}
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
index eab887c..4111071 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -92,4 +92,10 @@
};
};
};
+
+ qcom,rpm-stats@c300000 {
+ compatible = "qcom,rpm-stats";
+ reg = <0xC300000 0x1000>, <0xC3F0004 0x4>;
+ reg-names = "phys_addr_base", "offset_addr";
+ };
};
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 38232e3..7badee0 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -290,6 +290,8 @@
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_SMD_PKT=y
@@ -347,7 +349,13 @@
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_QCOM_KGSL=y
CONFIG_FB=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_LOGO=y
@@ -388,7 +396,6 @@
CONFIG_USB_STORAGE_KARMA=y
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
CONFIG_USB_DWC3_MSM=y
CONFIG_USB_SERIAL=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
@@ -464,6 +471,7 @@
CONFIG_QPNP_COINCELL=y
CONFIG_QPNP_REVID=y
CONFIG_USB_BAM=y
+CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
@@ -495,10 +503,13 @@
CONFIG_MSM_PM=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 06dddc8..a98e636 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -302,6 +302,8 @@
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_SMD_PKT=y
@@ -359,8 +361,14 @@
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_LOGO=y
@@ -401,7 +409,6 @@
CONFIG_USB_STORAGE_KARMA=y
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
CONFIG_USB_DWC3_MSM=y
CONFIG_USB_SERIAL=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
@@ -479,6 +486,7 @@
CONFIG_QPNP_REVID=y
CONFIG_USB_BAM=y
CONFIG_MSM_EXT_DISPLAY=y
+CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
@@ -516,10 +524,13 @@
CONFIG_MSM_PM=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 19b5f5c..c38bfbe 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1165,6 +1165,7 @@
cpu_hyp_reset();
return NOTIFY_OK;
+ case CPU_PM_ENTER_FAILED:
case CPU_PM_EXIT:
if (__this_cpu_read(kvm_arm_hardware_enabled))
/* The hardware was enabled before suspend. */
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 42f5daf..4e57ebc 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,7 +38,7 @@
ret = kvm_psci_call(vcpu);
if (ret < 0) {
- kvm_inject_undefined(vcpu);
+ vcpu_set_reg(vcpu, 0, ~0UL);
return 1;
}
@@ -47,7 +47,16 @@
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
- kvm_inject_undefined(vcpu);
+ /*
+ * "If an SMC instruction executed at Non-secure EL1 is
+ * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
+ * Trap exception, not a Secure Monitor Call exception [...]"
+ *
+ * We need to advance the PC after the trap, as it would
+ * otherwise return to the same address...
+ */
+ vcpu_set_reg(vcpu, 0, ~0UL);
+ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
return 1;
}
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index caed4e1..949f850 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -299,6 +299,8 @@
dtb-$(CONFIG_ARCH_MSM8937) += msm8937-pmi8950-mtp.dtb
+dtb-$(CONFIG_ARCH_MSM8917) += msm8917-pmi8950-mtp.dtb
+
dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
sdm450-cdp.dtb \
sdm450-mtp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cpu.dtsi b/arch/arm64/boot/dts/qcom/msm8917-cpu.dtsi
new file mode 100644
index 0000000..792d5d1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cpu.dtsi
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015-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.
+ */
+
+/ {
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu-map {
+
+ cluster0 {
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+ core1 {
+ cpu = <&CPU1>;
+ };
+ core2 {
+ cpu = <&CPU2>;
+ };
+ core3 {
+ cpu = <&CPU3>;
+ };
+ };
+ };
+
+ CPU0: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x100>;
+ enable-method = "psci";
+ cpu-release-addr = <0x0 0x90000000>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ compatible = "arm,arch-cache";
+ cache-level = <2>;
+ /* A53 L2 dump not supported */
+ qcom,dump-size = <0x0>;
+ };
+ L1_I_100: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x8800>;
+ };
+ L1_D_100: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9000>;
+ };
+ };
+
+ CPU1: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x101>;
+ enable-method = "psci";
+ cpu-release-addr = <0x0 0x90000000>;
+ next-level-cache = <&L2_1>;
+ L1_I_101: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x8800>;
+ };
+ L1_D_101: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9000>;
+ };
+ };
+
+ CPU2: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x102>;
+ enable-method = "psci";
+ cpu-release-addr = <0x0 0x90000000>;
+ next-level-cache = <&L2_1>;
+ L1_I_102: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x8800>;
+ };
+ L1_D_102: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9000>;
+ };
+ };
+
+ CPU3: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x103>;
+ enable-method = "psci";
+ cpu-release-addr = <0x0 0x90000000>;
+ next-level-cache = <&L2_1>;
+ L1_I_103: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x8800>;
+ };
+ L1_D_103: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9000>;
+ };
+ };
+
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-ion.dtsi b/arch/arm64/boot/dts/qcom/msm8917-ion.dtsi
new file mode 100644
index 0000000..823d99d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-ion.dtsi
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-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
+ * 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>;
+
+ qcom,ion-heap@25 {
+ reg = <25>;
+ qcom,ion-heap-type = "SYSTEM";
+ };
+
+ qcom,ion-heap@8 { /* CP_MM HEAP */
+ reg = <8>;
+ memory-region = <&secure_mem>;
+ qcom,ion-heap-type = "SECURE_DMA";
+ };
+
+ qcom,ion-heap@27 { /* QSEECOM HEAP */
+ reg = <27>;
+ memory-region = <&qseecom_mem>;
+ qcom,ion-heap-type = "DMA";
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
new file mode 100644
index 0000000..65bc046
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015-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.
+ */
+
+&blsp1_uart2 {
+ status = "ok";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
new file mode 100644
index 0000000..b8516d5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
@@ -0,0 +1,1669 @@
+/*
+ * Copyright (c) 2015-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 {
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,msm8917-pinctrl";
+ reg = <0x1000000 0x300000>;
+ interrupts = <0 208 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+
+ /* add pingrp for touchscreen */
+ pmx_ts_int_active {
+ ts_int_active: ts_int_active {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ pmx_ts_int_suspend {
+ ts_int_suspend: ts_int_suspend {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+
+ pmx_ts_reset_active {
+ ts_reset_active: ts_reset_active {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio64";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ pmx_ts_reset_suspend {
+ ts_reset_suspend: ts_reset_suspend {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio64";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+
+ pmx_ts_release {
+ ts_release: ts_release {
+ mux {
+ pins = "gpio65", "gpio64";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio65", "gpio64";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+
+ pmx-uartconsole {
+ uart_console_active: uart_console_active {
+ mux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio4", "gpio5";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ uart_console_sleep: uart_console_sleep {
+ mux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio4", "gpio5";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ };
+
+ blsp1_uart1 {
+ blsp1_uart1_active: blsp1_uart1_active {
+ mux {
+ pins = "gpio0", "gpio1",
+ "gpio2", "gpio3";
+ function = "blsp_uart1";
+ };
+
+ config {
+ pins = "gpio0", "gpio1",
+ "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp1_uart1_sleep: blsp1_uart1_sleep {
+ mux {
+ pins = "gpio0", "gpio1",
+ "gpio2", "gpio3";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio0", "gpio1",
+ "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ wcnss_pmux_5wire {
+ /* Active configuration of bus pins */
+ wcnss_default: wcnss_default {
+ wcss_wlan2 {
+ pins = "gpio76";
+ function = "wcss_wlan2";
+ };
+ wcss_wlan1 {
+ pins = "gpio77";
+ function = "wcss_wlan1";
+ };
+ wcss_wlan0 {
+ pins = "gpio78";
+ function = "wcss_wlan0";
+ };
+ wcss_wlan {
+ pins = "gpio79", "gpio80";
+ function = "wcss_wlan";
+ };
+
+ config {
+ pins = "gpio76", "gpio77",
+ "gpio78", "gpio79",
+ "gpio80";
+ drive-strength = <6>; /* 6 MA */
+ bias-pull-up; /* PULL UP */
+ };
+ };
+
+ wcnss_sleep: wcnss_sleep {
+ wcss_wlan2 {
+ pins = "gpio76";
+ function = "wcss_wlan2";
+ };
+ wcss_wlan1 {
+ pins = "gpio77";
+ function = "wcss_wlan1";
+ };
+ wcss_wlan0 {
+ pins = "gpio78";
+ function = "wcss_wlan0";
+ };
+ wcss_wlan {
+ pins = "gpio79", "gpio80";
+ function = "wcss_wlan";
+ };
+
+ config {
+ pins = "gpio76", "gpio77",
+ "gpio78", "gpio79",
+ "gpio80";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL Down */
+ };
+ };
+ };
+
+ wcnss_pmux_gpio: wcnss_pmux_gpio {
+ wcnss_gpio_default: wcnss_gpio_default {
+ /* Active configuration of bus pins */
+ mux {
+ /* Uses general purpose pins */
+ pins = "gpio76", "gpio77",
+ "gpio78", "gpio79",
+ "gpio80";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio76", "gpio77",
+ "gpio78", "gpio79",
+ "gpio80";
+ drive-strength = <6>; /* 6 MA */
+ bias-pull-up; /* PULL UP */
+ };
+ };
+ };
+
+ pmx_mdss: pmx_mdss {
+ mdss_dsi_active: mdss_dsi_active {
+ mux {
+ pins = "gpio60", "gpio98";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio60", "gpio98";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable = <0>; /* no pull */
+ output-high;
+ };
+ };
+ mdss_dsi_suspend: mdss_dsi_suspend {
+ mux {
+ pins = "gpio60", "gpio98";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio60", "gpio98";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
+ };
+
+ pmx_mdss_te {
+ mdss_te_active: mdss_te_active {
+ mux {
+ pins = "gpio24";
+ function = "mdp_vsync";
+ };
+
+ config {
+ pins = "gpio24";
+ drive-strength = <2>; /* 8 mA */
+ bias-pull-down; /* pull down*/
+ };
+ };
+ mdss_te_suspend: mdss_te_suspend {
+ mux {
+ pins = "gpio24";
+ function = "mdp_vsync";
+ };
+
+ config {
+ pins = "gpio24";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
+ };
+
+ pmx_qdsd_clk {
+ qdsd_clk_sdcard: clk_sdcard {
+ config {
+ pins = "qdsd_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <16>; /* 16 MA */
+ };
+ };
+ qdsd_clk_trace: clk_trace {
+ config {
+ pins = "qdsd_clk";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_clk_swdtrc: clk_swdtrc {
+ config {
+ pins = "qdsd_clk";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_clk_spmi: clk_spmi {
+ config {
+ pins = "qdsd_clk";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_cmd {
+ qdsd_cmd_sdcard: cmd_sdcard {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_cmd_trace: cmd_trace {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_cmd_swduart: cmd_uart {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_cmd_swdtrc: cmd_swdtrc {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_cmd_jtag: cmd_jtag {
+ config {
+ pins = "qdsd_cmd";
+ bias-disable; /* NO pull */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_cmd_spmi: cmd_spmi {
+ config {
+ pins = "qdsd_cmd";
+ bias-pull-down; /* pull down */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data0 {
+ qdsd_data0_sdcard: data0_sdcard {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data0_trace: data0_trace {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data0_swduart: data0_uart {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data0_swdtrc: data0_swdtrc {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data0_jtag: data0_jtag {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data0_spmi: data0_spmi {
+ config {
+ pins = "qdsd_data0";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data1 {
+ qdsd_data1_sdcard: data1_sdcard {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data1_trace: data1_trace {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data1_swduart: data1_uart {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data1_swdtrc: data1_swdtrc {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data1_jtag: data1_jtag {
+ config {
+ pins = "qdsd_data1";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data2 {
+ qdsd_data2_sdcard: data2_sdcard {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data2_trace: data2_trace {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data2_swduart: data2_uart {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data2_swdtrc: data2_swdtrc {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-down; /* pull down */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data2_jtag: data2_jtag {
+ config {
+ pins = "qdsd_data2";
+ bias-pull-up; /* pull up */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ };
+
+ pmx_qdsd_data3 {
+ qdsd_data3_sdcard: data3_sdcard {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data3_trace: data3_trace {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ qdsd_data3_swduart: data3_uart {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data3_swdtrc: data3_swdtrc {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data3_jtag: data3_jtag {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ qdsd_data3_spmi: data3_spmi {
+ config {
+ pins = "qdsd_data3";
+ bias-pull-down; /* pull down */
+ drive-strength = <8>; /* 8 MA */
+ };
+ };
+ };
+
+ pmx_sdc1_rclk {
+ sdc1_rclk_on: sdc1_rclk_on {
+ config {
+ pins = "sdc1_rclk";
+ bias-pull-down; /* pull down */
+ };
+ };
+
+ sdc1_rclk_off: sdc1_rclk_off {
+ config {
+ pins = "sdc1_rclk";
+ bias-pull-down; /* pull down */
+ };
+ };
+ };
+
+ pmx_sdc1_clk {
+ sdc1_clk_on: sdc1_clk_on {
+ config {
+ pins = "sdc1_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <16>; /* 16 MA */
+ };
+ };
+
+ sdc1_clk_off: sdc1_clk_off {
+ config {
+ pins = "sdc1_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_sdc1_cmd {
+ sdc1_cmd_on: sdc1_cmd_on {
+ config {
+ pins = "sdc1_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc1_cmd_off: sdc1_cmd_off {
+ config {
+ pins = "sdc1_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_sdc1_data {
+ sdc1_data_on: sdc1_data_on {
+ config {
+ pins = "sdc1_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc1_data_off: sdc1_data_off {
+ config {
+ pins = "sdc1_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ sdhc2_cd_pin {
+ sdc2_cd_on: cd_on {
+ mux {
+ pins = "gpio67";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ sdc2_cd_off: cd_off {
+ mux {
+ pins = "gpio67";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ pmx_sdc2_clk {
+ sdc2_clk_on: sdc2_clk_on {
+ config {
+ pins = "sdc2_clk";
+ drive-strength = <16>; /* 16 MA */
+ bias-disable; /* NO pull */
+ };
+ };
+
+ sdc2_clk_off: sdc2_clk_off {
+ config {
+ pins = "sdc2_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_sdc2_cmd {
+ sdc2_cmd_on: sdc2_cmd_on {
+ config {
+ pins = "sdc2_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc2_cmd_off: sdc2_cmd_off {
+ config {
+ pins = "sdc2_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ pmx_sdc2_data {
+ sdc2_data_on: sdc2_data_on {
+ config {
+ pins = "sdc2_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc2_data_off: sdc2_data_off {
+ config {
+ pins = "sdc2_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+ };
+
+ sdc2_wlan_gpio {
+ sdc2_wlan_gpio_active: sdc2_wlan_gpio_active {
+ config {
+ pins = "gpio99";
+ output-high;
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+ sdc2_wlan_gpio_sleep: sdc2_wlan_gpio_sleep {
+ config {
+ pins = "gpio99";
+ output-low;
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ wcd9xxx_intr {
+ wcd_intr_default: wcd_intr_default{
+ mux {
+ pins = "gpio73";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio73";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ input-enable;
+ };
+ };
+ };
+
+ pri_mi2s_mclk_b_lines {
+ pri_mi2s_mclk_b_default: pri_mi2s_mclk_default {
+ mux {
+ pins = "gpio69";
+ function = "pri_mi2s_mclk_b";
+ };
+ config {
+ pins = "gpio69";
+ drive-strength = <8>;
+ bias-disable;
+ input-enable;
+ };
+ };
+ };
+
+ sec_mi2s_mclk_a_lines {
+ sec_mi2s_mclk_a_active: sec_mi2s_mclk_a_active {
+ mux {
+ pins = "gpio25";
+ function = "sec_mi2s_mclk_a";
+ };
+
+ config {
+ pins = "gpio25";
+ drive-strength = <8>; /* 8 MA */
+ output-high;
+ bias-disable;
+ };
+ };
+
+ sec_mi2s_mclk_a_sleep: sec_mi2s_mclk_a_sleep {
+ mux {
+ pins = "gpio25";
+ function = "sec_mi2s_mclk_a";
+ };
+
+ config {
+ pins = "gpio25";
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ bias-pull-down;
+ };
+ };
+ };
+
+ cdc_reset_ctrl {
+ cdc_reset_sleep: cdc_reset_sleep {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio68";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+ };
+ cdc_reset_active:cdc_reset_active {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio68";
+ drive-strength = <16>;
+ bias-pull-down;
+ output-high;
+ };
+ };
+ };
+
+ cdc-pdm-2-lines {
+ cdc_pdm_lines_2_act: pdm_lines_2_on {
+ mux {
+ pins = "gpio70", "gpio71", "gpio72";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio70", "gpio71", "gpio72";
+ drive-strength = <8>;
+ };
+ };
+
+ cdc_pdm_lines_2_sus: pdm_lines_2_off {
+ mux {
+ pins = "gpio70", "gpio71", "gpio72";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio70", "gpio71", "gpio72";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ cdc-pdm-lines {
+ cdc_pdm_lines_act: pdm_lines_on {
+ mux {
+ pins = "gpio69", "gpio73", "gpio74";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio69", "gpio73", "gpio74";
+ drive-strength = <8>;
+ };
+ };
+ cdc_pdm_lines_sus: pdm_lines_off {
+ mux {
+ pins = "gpio69", "gpio73", "gpio74";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio69", "gpio73", "gpio74";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ cross-conn-det {
+ cross_conn_det_act: lines_on {
+ mux {
+ pins = "gpio63";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio63";
+ drive-strength = <8>;
+ output-low;
+ bias-pull-down;
+ };
+ };
+
+ cross_conn_det_sus: lines_off {
+ mux {
+ pins = "gpio63";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio63";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+
+ /* WSA VI sense */
+ wsa-vi {
+ wsa_vi_on: wsa_vi_on {
+ mux {
+ pins = "gpio94", "gpio95";
+ function = "wsa_io";
+ };
+
+ config {
+ pins = "gpio94", "gpio95";
+ drive-strength = <8>; /* 8 MA */
+ bias-disable; /* NO pull */
+ };
+ };
+
+ wsa_vi_off: wsa_vi_off {
+ mux {
+ pins = "gpio94", "gpio95";
+ function = "wsa_io";
+ };
+
+ config {
+ pins = "gpio94", "gpio95";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down;
+ };
+ };
+ };
+
+ /* WSA Reset */
+ wsa_reset {
+ wsa_reset_on: wsa_reset_on {
+ mux {
+ pins = "gpio96";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio96";
+ drive-strength = <2>; /* 2 MA */
+ output-high;
+ };
+ };
+
+ wsa_reset_off: wsa_reset_off {
+ mux {
+ pins = "gpio96";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio96";
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ };
+ };
+ };
+
+ /* WSA CLK */
+ wsa_clk {
+ wsa_clk_on: wsa_clk_on {
+ mux {
+ pins = "gpio25";
+ function = "pri_mi2s_mclk_a";
+ };
+
+ config {
+ pins = "gpio25";
+ drive-strength = <8>; /* 8 MA */
+ output-high;
+ };
+ };
+
+ wsa_clk_off: wsa_clk_off {
+ mux {
+ pins = "gpio25";
+ function = "pri_mi2s_mclk_a";
+ };
+
+ config {
+ pins = "gpio25";
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ bias-pull-down;
+ };
+ };
+ };
+
+ pri-tlmm-lines {
+ pri_tlmm_lines_act: pri_tlmm_lines_act {
+ mux {
+ pins = "gpio85", "gpio88";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio85", "gpio88";
+ drive-strength = <8>;
+ };
+ };
+
+ pri_tlmm_lines_sus: pri_tlmm_lines_sus {
+ mux {
+ pins = "gpio85", "gpio88";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio85", "gpio88";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+
+ pri-tlmm-ws-lines {
+ pri_tlmm_ws_act: pri_tlmm_ws_act {
+ mux {
+ pins = "gpio87";
+ function = "pri_mi2s_ws";
+ };
+
+ config {
+ pins = "gpio87";
+ drive-strength = <16>;
+ bias-disable;
+ output-high;
+ };
+ };
+
+ pri_tlmm_ws_sus: pri_tlmm_ws_sus {
+ mux {
+ pins = "gpio87";
+ function = "pri_mi2s_ws";
+ };
+
+ config {
+ pins = "gpio87";
+ drive-strength = <2>;
+ bias-pull-down;
+ input-enable;
+ };
+ };
+ };
+
+ spi3 {
+ spi3_default: spi3_default {
+ /* active state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio8", "gpio9", "gpio11";
+ function = "blsp_spi3";
+ };
+
+ config {
+ pins = "gpio8", "gpio9", "gpio11";
+ drive-strength = <12>; /* 12 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ spi3_sleep: spi3_sleep {
+ /* suspended state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio8", "gpio9", "gpio11";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio8", "gpio9", "gpio11";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL Down */
+ };
+ };
+
+ spi3_cs0_active: cs0_active {
+ /* CS */
+ mux {
+ pins = "gpio10";
+ function = "blsp_spi3";
+ };
+
+ config {
+ pins = "gpio10";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+
+ spi3_cs0_sleep: cs0_sleep {
+ /* CS */
+ mux {
+ pins = "gpio10";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio10";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+ };
+
+ spi6 {
+ spi6_default: spi6_default {
+ /* active state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio20", "gpio21", "gpio23";
+ function = "blsp_spi6";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio23";
+ drive-strength = <16>; /* 16 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ spi6_sleep: spi6_sleep {
+ /* suspended state */
+ mux {
+ /* MOSI, MISO, CLK */
+ pins = "gpio20", "gpio21", "gpio23";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio20", "gpio21", "gpio23";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL Down */
+ };
+ };
+
+ spi6_cs0_active: cs0_active {
+ /* CS */
+ mux {
+ pins = "gpio47";
+ function = "blsp6_spi";
+ };
+
+ config {
+ pins = "gpio47";
+ drive-strength = <16>;
+ bias-disable = <0>;
+ };
+ };
+
+ spi6_cs0_sleep: cs0_sleep {
+ /* CS */
+ mux {
+ pins = "gpio47";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio47";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+
+ spi6_cs1_active: cs1_active {
+ /* CS */
+ mux {
+ pins = "gpio22";
+ function = "blsp_spi6";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <16>;
+ bias-disable = <0>;
+ };
+ };
+
+ spi6_cs1_sleep: cs1_sleep {
+ /* CS */
+ mux {
+ pins = "gpio22";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio22";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+ };
+
+ i2c_2 {
+ i2c_2_active: i2c_2_active {
+ /* active state */
+ mux {
+ pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
+ };
+
+ config {
+ pins = "gpio6", "gpio7";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_2_sleep: i2c_2_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio6", "gpio7";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio6", "gpio7";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ i2c_3 {
+ i2c_3_active: i2c_3_active {
+ /* active state */
+ mux {
+ pins = "gpio10", "gpio11";
+ function = "blsp_i2c3";
+ };
+
+ config {
+ pins = "gpio10", "gpio11";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_3_sleep: i2c_3_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio10", "gpio11";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio10", "gpio11";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ /* IO Expander SX150xq */
+ i2c_4 {
+ i2c_4_active: i2c_4_active {
+ /* active state */
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_4_sleep: i2c_4_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ i2c_5 {
+ i2c_5_active: i2c_5_active {
+ /* active state */
+ mux {
+ pins = "gpio18", "gpio19";
+ function = "blsp_i2c5";
+ };
+
+ config {
+ pins = "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_5_sleep: i2c_5_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio18", "gpio19";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ i2c_6 {
+ i2c_6_active: i2c_6_active {
+ /* active state */
+ mux {
+ pins = "gpio22", "gpio23";
+ function = "blsp_i2c6";
+ };
+
+ config {
+ pins = "gpio22", "gpio23";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_6_sleep: i2c_6_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio22", "gpio23";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio22", "gpio23";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ pmx_rd_nfc_int {
+ /*qcom,pins = <&gp 17>;*/
+ pins = "gpio17";
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_nfc_int";
+
+ nfc_int_active: active {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ nfc_int_suspend: suspend {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ pmx_nfc_reset {
+ /*qcom,pins = <&gp 16>;*/
+ pins = "gpio16";
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_nfc_disable";
+
+ nfc_disable_active: active {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ nfc_disable_suspend: suspend {
+ drive-strength = <6>;
+ bias-disable;
+ };
+ };
+
+ tlmm_gpio_key {
+ gpio_key_active: gpio_key_active {
+ mux {
+ pins = "gpio91", "gpio127", "gpio128";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ gpio_key_suspend: gpio_key_suspend {
+ mux {
+ pins = "gpio91", "gpio127", "gpio128";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ tlmm_pmi_flash_led {
+ rear_flash_led_enable: rear_flash_led_enable {
+ mux {
+ pins = "gpio33";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio33";
+ drive-strength = <16>;
+ output-high;
+ };
+ };
+
+ rear_flash_led_disable: rear_flash_led_disable {
+ mux {
+ pins = "gpio33";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio33";
+ drive-strength = <2>;
+ output-low;
+ };
+ };
+
+ front_flash_led_enable: front_flash_led_enable {
+ mux {
+ pins = "gpio50";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio50";
+ drive-strength = <16>;
+ output-high;
+ };
+ };
+
+ front_flash_led_disable: front_flash_led_disable {
+ mux {
+ pins = "gpio50";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio50";
+ drive-strength = <2>;
+ output-low;
+ };
+ };
+ };
+
+ usbc_int_default: usbc_int_default {
+ mux {
+ pins = "gpio97", "gpio131";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio97", "gpio131";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pri_mi2s_sck {
+ pri_mi2s_sck_sleep: pri_mi2s_sck_sleep {
+ mux {
+ pins = "gpio85";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio85";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sck_active: pri_mi2s_sck_active {
+ mux {
+ pins = "gpio85";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio85";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_mi2s_sd0 {
+ pri_mi2s_sd0_sleep: pri_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio88";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio88";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sd0_active: pri_mi2s_sd0_active {
+ mux {
+ pins = "gpio88";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio88";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ pri_mi2s_sd1 {
+ pri_mi2s_sd1_sleep: pri_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio86";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio86";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+ pri_mi2s_sd1_active: pri_mi2s_sd1_active {
+ mux {
+ pins = "gpio86";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio86";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+ sec_mi2s_ws {
+ sec_mi2s_ws_sleep: sec_mi2s_ws_sleep {
+ mux {
+ pins = "gpio95";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio95";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ sec_mi2s_ws_active: sec_mi2s_ws_active {
+ mux {
+ pins = "gpio95";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio95";
+ drive-strength = <16>;
+ bias-disable;
+ output-high;
+ };
+ };
+ };
+ sec_mi2s_sck {
+ sec_mi2s_sck_sleep: sec_mi2s_sck_sleep {
+ mux {
+ pins = "gpio94";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio94";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ sec_mi2s_sck_active: sec_mi2s_sck_active {
+ mux {
+ pins = "gpio94";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio94";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ sec_mi2s_sd0 {
+ sec_mi2s_sd0_sleep: sec_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio12";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio12";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+ sec_mi2s_sd0_active: sec_mi2s_sd0_active {
+ mux {
+ pins = "gpio12";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio12";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ sec_mi2s_sd1 {
+ sec_mi2s_sd1_sleep: sec_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio13";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio13";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+ sec_mi2s_sd1_active: sec_mi2s_sd1_active {
+ mux {
+ pins = "gpio13";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio13";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ usb_mode_select: usb_mode_select {
+ mux {
+ pins = "gpio130";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio130";
+ drive-strength = <2>;
+ bias-disable;
+ input-enable;
+ };
+ };
+
+ usb2533_hub_reset: usb2533_hub_reset {
+ mux {
+ pins = "gpio100";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio100";
+ drive-strength = <2>;
+ output-low;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dts
new file mode 100644
index 0000000..3fe60a3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015-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
+ * 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 "msm8917.dtsi"
+#include "msm8917-pmi8950-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917-PMI8950 MTP";
+ compatible = "qcom,msm8917-mtp", "qcom,msm8917", "qcom,mtp";
+ qcom,board-id= <8 0>;
+ qcom,pmic-id = <0x10019 0x010011 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
new file mode 100644
index 0000000..a78f5fe
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015-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 "pmi8950.dtsi"
+#include "msm8917-mtp.dtsi"
+
+&soc {
+ led_flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>;
+ qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>;
+ qcom,switch-source = <&pmi8950_switch>;
+ };
+
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&tlmm 129 0>; /* BT_EN */
+ };
+};
+
+&vendor{
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&pm8937_gpios {
+ gpio@c400 {
+ qcom,mode = <0>;
+ qcom,output-type = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-sel = <0>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+};
+
+&pmi8950_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&pmi8950_charger {
+ qcom,battery-data = <&mtp_batterydata>;
+ qcom,chg-led-sw-controls;
+ qcom,chg-led-support;
+ /delete-property/ dpdm-supply;
+};
+
+&labibb {
+ status = "ok";
+ qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&ibb_regulator {
+ qcom,qpnp-ibb-discharge-resistor = <32>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
new file mode 100644
index 0000000..c1160ad
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2015-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 "skeleton64.dtsi"
+#include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/spmi/spmi.h>
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8917";
+ compatible = "qcom,msm8917";
+ qcom,msm-id = <303 0x0>, <308 0x0>, <309 0x0>;
+ interrupt-parent = <&intc>;
+
+ chosen {
+ bootargs = "sched_enable_hmp=1";
+ };
+
+ aliases {
+ /* smdtty devices */
+ smd1 = &smdtty_apps_fm;
+ smd2 = &smdtty_apps_riva_bt_acl;
+ smd3 = &smdtty_apps_riva_bt_cmd;
+ smd4 = &smdtty_mbalbridge;
+ smd5 = &smdtty_apps_riva_ant_cmd;
+ smd6 = &smdtty_apps_riva_ant_data;
+ smd7 = &smdtty_data1;
+ smd8 = &smdtty_data4;
+ smd11 = &smdtty_data11;
+ smd21 = &smdtty_data21;
+ smd36 = &smdtty_loopback;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ other_ext_mem: other_ext_region@0 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x0 0x85b00000 0x0 0xd00000>;
+ };
+
+ modem_mem: modem_region@0 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x0 0x86800000 0x0 0x5000000>;
+ };
+
+ adsp_fw_mem: adsp_fw_region@0 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x0 0x8b800000 0x0 0x1100000>;
+ };
+
+ wcnss_fw_mem: wcnss_fw_region@0 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x0 0x8c900000 0x0 0x700000>;
+ };
+
+ venus_mem: venus_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alloc-ranges = <0x0 0x80000000 0x0 0x10000000>;
+ alignment = <0 0x400000>;
+ size = <0 0x0800000>;
+ };
+
+ secure_mem: secure_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alignment = <0 0x400000>;
+ size = <0 0x7000000>;
+ };
+
+ qseecom_mem: qseecom_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alignment = <0 0x400000>;
+ size = <0 0x1000000>;
+ };
+
+ adsp_mem: adsp_region@0 {
+ compatible = "shared-dma-pool";
+ reusable;
+ alignment = <0 0x400000>;
+ size = <0 0x400000>;
+ };
+
+ cont_splash_mem: splash_region@83000000 {
+ reg = <0x0 0x90000000 0x0 0x1400000>;
+ };
+ };
+
+ soc: soc { };
+
+ vendor: vendor {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+ };
+};
+
+#include "msm8917-pinctrl.dtsi"
+#include "msm8917-cpu.dtsi"
+#include "msm8917-ion.dtsi"
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+
+ intc: interrupt-controller@b000000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x0b000000 0x1000>,
+ <0x0b002000 0x1000>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <1 2 0xff08>,
+ <1 3 0xff08>,
+ <1 4 0xff08>,
+ <1 1 0xff08>;
+ clock-frequency = <19200000>;
+ };
+
+ qcom,sps {
+ compatible = "qcom,msm_sps_4k";
+ qcom,pipe-attr-ee;
+ };
+
+ timer@b120000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0xb120000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@b121000 {
+ frame-number = <0>;
+ interrupts = <0 8 0x4>,
+ <0 7 0x4>;
+ reg = <0xb121000 0x1000>,
+ <0xb122000 0x1000>;
+ };
+
+ frame@b123000 {
+ frame-number = <1>;
+ interrupts = <0 9 0x4>;
+ reg = <0xb123000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b124000 {
+ frame-number = <2>;
+ interrupts = <0 10 0x4>;
+ reg = <0xb124000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b125000 {
+ frame-number = <3>;
+ interrupts = <0 11 0x4>;
+ reg = <0xb125000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b126000 {
+ frame-number = <4>;
+ interrupts = <0 12 0x4>;
+ reg = <0xb126000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b127000 {
+ frame-number = <5>;
+ interrupts = <0 13 0x4>;
+ reg = <0xb127000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b128000 {
+ frame-number = <6>;
+ interrupts = <0 14 0x4>;
+ reg = <0xb128000 0x1000>;
+ status = "disabled";
+ };
+ };
+
+ qcom,rmtfs_sharedmem@00000000 {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x00000000 0x00180000>;
+ reg-names = "rmtfs";
+ qcom,client-id = <0x00000001>;
+ };
+
+ restart@4ab000 {
+ compatible = "qcom,pshold";
+ reg = <0x4ab000 0x4>,
+ <0x193d100 0x4>;
+ reg-names = "pshold-base", "tcsr-boot-misc-detect";
+ };
+
+ qcom,mpm2-sleep-counter@4a3000 {
+ compatible = "qcom,mpm2-sleep-counter";
+ reg = <0x4a3000 0x1000>;
+ clock-frequency = <32768>;
+ };
+
+ cpu-pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <1 7 0xff00>;
+ };
+
+ slim_msm: slim@c140000{
+ cell-index = <1>;
+ compatible = "qcom,slim-ngd";
+ reg = <0xc140000 0x2c000>,
+ <0xc104000 0x2a000>;
+ reg-names = "slimbus_physical", "slimbus_bam_physical";
+ interrupts = <0 163 0>, <0 180 0>;
+ interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+ qcom,apps-ch-pipes = <0x600000>;
+ qcom,ea-pc = <0x230>;
+ status = "disabled";
+ };
+
+ blsp1_uart2: serial@78b0000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x78b0000 0x200>;
+ interrupts = <0 108 0>;
+ status = "disabled";
+ };
+
+ dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */
+ #dma-cells = <4>;
+ compatible = "qcom,sps-dma";
+ reg = <0x7884000 0x1f000>;
+ interrupts = <0 238 0>;
+ qcom,summing-threshold = <10>;
+ };
+
+ dma_blsp2: qcom,sps-dma@7ac4000 { /* BLSP2 */
+ #dma-cells = <4>;
+ compatible = "qcom,sps-dma";
+ reg = <0x7ac4000 0x1f000>;
+ interrupts = <0 239 0>;
+ qcom,summing-threshold = <10>;
+ };
+
+ rpm_bus: qcom,rpm-smd {
+ compatible = "qcom,rpm-smd";
+ rpm-channel-name = "rpm_requests";
+ rpm-channel-type = <15>; /* SMD_APPS_RPM */
+ };
+
+ cpubw: qcom,cpubw {
+ compatible = "qcom,devbw";
+ governor = "cpufreq";
+ qcom,src-dst-ports = <1 512>;
+ qcom,active-only;
+ qcom,bw-tbl =
+ < 769 /* 100.8 MHz */ >,
+ < 1611 /* 211.2 MHz */ >,
+ < 2270 /* 297.6 MHz */ >, /*SVS */
+ < 2929 /* 384 MHz */ >,
+ < 4248 /* 556.8 MHz */ >, /*SVS+*/
+ < 4541 /* 595.2 MHz */ >, /*NOM*/
+ < 5126 /* 672 MHz */ >, /*NOM+*/
+ < 5645 /* 740 MHz */ >; /*TURBO*/
+ };
+
+ mincpubw: qcom,mincpubw {
+ compatible = "qcom,devbw";
+ governor = "cpufreq";
+ qcom,src-dst-ports = <1 512>;
+ qcom,active-only;
+ qcom,bw-tbl =
+ < 769 /* 100.8 MHz */ >,
+ < 1611 /* 211.2 MHz */ >,
+ < 2270 /* 297.6 MHz */ >,
+ < 2929 /* 384 MHz */ >,
+ < 4248 /* 556.8 MHz */ >,
+ < 4541 /* 595.2 MHz */ >,
+ < 5126 /* 672 MHz */ >,
+ < 5645 /* 740 MHz */ >;
+ };
+
+ qcom,cpu-bwmon {
+ compatible = "qcom,bimc-bwmon2";
+ reg = <0x408000 0x300>, <0x401000 0x200>;
+ reg-names = "base", "global_base";
+ interrupts = <0 183 4>;
+ qcom,mport = <0>;
+ qcom,target-dev = <&cpubw>;
+ };
+
+ qcom,wdt@b017000 {
+ compatible = "qcom,msm-watchdog";
+ reg = <0xb017000 0x1000>;
+ reg-names = "wdt-base";
+ interrupts = <0 3 0>, <0 4 0>;
+ qcom,bark-time = <11000>;
+ qcom,pet-time = <10000>;
+ qcom,ipi-ping;
+ qcom,wakeup-enable;
+ };
+
+ spmi_bus: qcom,spmi@200f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x200f000 0x1000>,
+ <0x2400000 0x800000>,
+ <0x2c00000 0x800000>,
+ <0x3800000 0x200000>,
+ <0x200a000 0x2100>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 190 IRQ_TYPE_NONE>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+
+ qcom,msm-rtb {
+ compatible = "qcom,msm-rtb";
+ qcom,rtb-size = <0x100000>; /* 1M EBI1 buffer */
+ };
+
+ qcom,msm-imem@8600000 {
+ compatible = "qcom,msm-imem";
+ reg = <0x08600000 0x1000>; /* Address and size of IMEM */
+ ranges = <0x0 0x08600000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mem_dump_table@10 {
+ compatible = "qcom,msm-imem-mem_dump_table";
+ reg = <0x10 8>;
+ };
+
+ dload_type@18 {
+ compatible = "qcom,msm-imem-dload-type";
+ reg = <0x18 4>;
+ };
+
+ restart_reason@65c {
+ compatible = "qcom,msm-imem-restart_reason";
+ reg = <0x65c 4>;
+ };
+
+ boot_stats@6b0 {
+ compatible = "qcom,msm-imem-boot_stats";
+ reg = <0x6b0 32>;
+ };
+
+ pil@94c {
+ compatible = "qcom,msm-imem-pil";
+ reg = <0x94c 200>;
+ };
+
+ };
+
+
+ qcom,ipc-spinlock@1905000 {
+ compatible = "qcom,ipc-spinlock-sfpb";
+ reg = <0x1905000 0x8000>;
+ qcom,num-locks = <8>;
+ };
+
+ qcom,smem@86300000 {
+ compatible = "qcom,smem";
+ reg = <0x86300000 0x100000>,
+ <0xb011008 0x4>,
+ <0x60000 0x8000>,
+ <0x193d000 0x8>;
+ reg-names = "smem", "irq-reg-base", "aux-mem1",
+ "smem_targ_info_reg";
+ qcom,mpu-enabled;
+
+ qcom,smd-modem {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <0>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x1000>;
+ interrupts = <0 25 1>;
+ label = "modem";
+ qcom,not-loadable;
+ };
+
+ qcom,smsm-modem {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <0>;
+ qcom,smsm-irq-offset = <0x0>;
+ qcom,smsm-irq-bitmask = <0x2000>;
+ interrupts = <0 26 1>;
+ };
+
+ qcom,smd-wcnss {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <6>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x20000>;
+ interrupts = <0 142 1>;
+ label = "wcnss";
+ };
+
+ qcom,smsm-wcnss {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <6>;
+ qcom,smsm-irq-offset = <0x0>;
+ qcom,smsm-irq-bitmask = <0x80000>;
+ interrupts = <0 144 1>;
+ };
+
+ qcom,smd-adsp {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <1>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x100>;
+ interrupts = <0 289 1>;
+ label = "adsp";
+ };
+
+ qcom,smsm-adsp {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <1>;
+ qcom,smsm-irq-offset = <0x0>;
+ qcom,smsm-irq-bitmask = <0x200>;
+ interrupts = <0 290 1>;
+ };
+
+ qcom,smd-rpm {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <15>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x1>;
+ interrupts = <0 168 1>;
+ label = "rpm";
+ qcom,irq-no-suspend;
+ qcom,not-loadable;
+ };
+ };
+
+ qcom,smdtty {
+ compatible = "qcom,smdtty";
+
+ smdtty_apps_fm: qcom,smdtty-apps-fm {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_FM";
+ };
+
+ smdtty_apps_riva_bt_acl: smdtty-apps-riva-bt-acl {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_BT_ACL";
+ };
+
+ smdtty_apps_riva_bt_cmd: qcom,smdtty-apps-riva-bt-cmd {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_BT_CMD";
+ };
+
+ smdtty_mbalbridge: qcom,smdtty-mbalbridge {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "MBALBRIDGE";
+ };
+
+ smdtty_apps_riva_ant_cmd: smdtty-apps-riva-ant-cmd {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_ANT_CMD";
+ };
+
+ smdtty_apps_riva_ant_data: smdtty-apps-riva-ant-data {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_ANT_DATA";
+ };
+
+ smdtty_data1: qcom,smdtty-data1 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA1";
+ };
+
+ smdtty_data4: qcom,smdtty-data4 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA4";
+ };
+
+ smdtty_data11: qcom,smdtty-data11 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA11";
+ };
+
+ smdtty_data21: qcom,smdtty-data21 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA21";
+ };
+
+ smdtty_loopback: smdtty-loopback {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "LOOPBACK";
+ qcom,smdtty-dev-name = "LOOPBACK_TTY";
+ };
+ };
+
+ qcom,smdpkt {
+ compatible = "qcom,smdpkt";
+
+ qcom,smdpkt-data5-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA5_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl0";
+ };
+
+ qcom,smdpkt-data22 {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA22";
+ qcom,smdpkt-dev-name = "smd22";
+ };
+
+ qcom,smdpkt-data40-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA40_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl8";
+ };
+
+ qcom,smdpkt-apr-apps2 {
+ qcom,smdpkt-remote = "adsp";
+ qcom,smdpkt-port-name = "apr_apps2";
+ qcom,smdpkt-dev-name = "apr_apps2";
+ };
+
+ qcom,smdpkt-loopback {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "LOOPBACK";
+ qcom,smdpkt-dev-name = "smd_pkt_loopback";
+ };
+ };
+
+ qcom_tzlog: tz-log@8600720 {
+ compatible = "qcom,tz-log";
+ reg = <0x08600720 0x2000>;
+ };
+
+ qcom,ipc_router {
+ compatible = "qcom,ipc_router";
+ qcom,node-id = <1>;
+ };
+
+ qcom,ipc_router_modem_xprt {
+ compatible = "qcom,ipc_router_smd_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "modem";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ qcom,disable-pil-loading;
+ };
+
+ qcom,ipc_router_q6_xprt {
+ compatible = "qcom,ipc_router_smd_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "adsp";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ };
+
+ qcom,ipc_router_wcnss_xprt {
+ compatible = "qcom,ipc_router_smd_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "wcnss";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ };
+
+ qcom,adsprpc-mem {
+ compatible = "qcom,msm-adsprpc-mem-region";
+ memory-region = <&adsp_mem>;
+ };
+
+};
+
+#include "pm8937-rpm-regulator.dtsi"
+#include "pm8937.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8937-audio.dtsi b/arch/arm64/boot/dts/qcom/msm8937-audio.dtsi
new file mode 100644
index 0000000..2e4d38e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-audio.dtsi
@@ -0,0 +1,436 @@
+/*
+ * 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 "msm-audio-lpass.dtsi"
+#include "msm8953-wsa881x.dtsi"
+
+&msm_audio_ion {
+ iommus = <&apps_iommu 0x2001 0x0>;
+ qcom,smmu-sid-mask = /bits/ 64 <0xf>;
+};
+
+&soc {
+ qcom,msm-audio-apr {
+ compatible = "qcom,msm-audio-apr";
+ msm_audio_apr_dummy {
+ compatible = "qcom,msm-audio-apr-dummy";
+ };
+ };
+
+ qcom,avtimer@c0a300c {
+ compatible = "qcom,avtimer";
+ reg = <0x0c0a300c 0x4>,
+ <0x0c0a3010 0x4>;
+ reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+ qcom,clk-div = <27>;
+ };
+
+ int_codec: sound {
+ status = "okay";
+ compatible = "qcom,msm8952-audio-codec";
+ qcom,model = "msm8952-snd-card-mtp";
+ reg = <0xc051000 0x4>,
+ <0xc051004 0x4>,
+ <0xc055000 0x4>,
+ <0xc052000 0x4>;
+ reg-names = "csr_gp_io_mux_mic_ctl",
+ "csr_gp_io_mux_spkr_ctl",
+ "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+ "csr_gp_io_mux_quin_ctl";
+
+ qcom,msm-ext-pa = "primary";
+ qcom,msm-mclk-freq = <9600000>;
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,msm-hs-micbias-type = "external";
+ qcom,msm-micbias1-ext-cap;
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "SPK_RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "RX_I2S_CLK", "MCLK",
+ "TX_I2S_CLK", "MCLK",
+ "MIC BIAS External", "Handset Mic",
+ "MIC BIAS External2", "Headset Mic",
+ "MIC BIAS External", "Secondary Mic",
+ "AMIC1", "MIC BIAS External",
+ "AMIC2", "MIC BIAS External2",
+ "AMIC3", "MIC BIAS External",
+ "ADC1_IN", "ADC1_OUT",
+ "ADC2_IN", "ADC2_OUT",
+ "ADC3_IN", "ADC3_OUT",
+ "PDM_IN_RX1", "PDM_OUT_RX1",
+ "PDM_IN_RX2", "PDM_OUT_RX2",
+ "PDM_IN_RX3", "PDM_OUT_RX3",
+ "WSA_SPK OUT", "VDD_WSA_SWITCH",
+ "SpkrMono WSA_IN", "WSA_SPK OUT";
+
+ qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+ qcom,cdc-us-eu-gpios = <&cdc_us_euro_sw>;
+ qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+ qcom,quin-mi2s-gpios = <&cdc_quin_mi2s_gpios>;
+
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&pcm_noirq>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-pcm-dsp-noirq";
+ asoc-cpu = <&dai_pri_auxpcm>,
+ <&dai_mi2s0>, <&dai_mi2s1>,
+ <&dai_mi2s2>, <&dai_mi2s3>,
+ <&dai_mi2s4>, <&dai_mi2s5>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+ <&bt_sco_rx>, <&bt_sco_tx>,
+ <&int_fm_rx>, <&int_fm_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>,
+ <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>,
+ <&incall_music_rx>, <&incall_music_2_rx>;
+
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+ "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
+ "msm-dai-q6-dev.16384", "msmdai-q6-dev.16385",
+ "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+ "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+ "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+ "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+ "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+ "msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+ "msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+ "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+ "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+
+ asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+ <&pmic_analog_codec>;
+ asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+ "analog-codec";
+ asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f";
+ asoc-wsa-codec-prefixes = "SpkrMono";
+ msm-vdd-wsa-switch-supply = <&pm8937_l5>;
+ qcom,msm-vdd-wsa-switch-voltage = <1800000>;
+ qcom,msm-vdd-wsa-switch-current = <10000>;
+ };
+
+ cdc_us_euro_sw: msm_cdc_pinctrl_us_euro_sw {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cross_conn_det_act>;
+ pinctrl-1 = <&cross_conn_det_sus>;
+ };
+
+ cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act>;
+ pinctrl-1 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus>;
+ };
+
+ cdc_quin_mi2s_gpios: msm_cdc_pinctrl_quin {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-1 = <&pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ };
+
+
+ i2c@78b6000 {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wsa881x_i2c_f: wsa881x-i2c-codec@f {
+ status = "okay";
+ compatible = "qcom,wsa881x-i2c-codec";
+ reg = <0x0f>;
+ qcom,wsa-analog-vi-gpio = <&wsa881x_analog_vi_gpio>;
+ qcom,wsa-analog-clk-gpio = <&wsa881x_analog_clk_gpio>;
+ qcom,wsa-analog-reset-gpio =
+ <&wsa881x_analog_reset_gpio>;
+ };
+ wsa881x_i2c_45: wsa881x-i2c-codec@45 {
+ status = "okay";
+ compatible = "qcom,wsa881x-i2c-codec";
+ reg = <0x45>;
+ };
+ };
+
+ wsa881x_analog_vi_gpio: wsa881x_analog_vi_pctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&wsa_vi_on>;
+ pinctrl-1 = <&wsa_vi_off>;
+ };
+ wsa881x_analog_clk_gpio: wsa881x_analog_clk_pctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&wsa_clk_on>;
+ pinctrl-1 = <&wsa_clk_off>;
+ };
+ wsa881x_analog_reset_gpio: wsa881x_analog_reset_pctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&wsa_reset_on>;
+ pinctrl-1 = <&wsa_reset_off>;
+ };
+
+ ext_codec: sound-9335 {
+ status = "disabled";
+ compatible = "qcom,msm8952-audio-slim-codec";
+ qcom,model = "msm8952-tasha-snd-card";
+
+ reg = <0xc051000 0x4>,
+ <0xc051004 0x4>,
+ <0xc055000 0x4>,
+ <0xc052000 0x4>;
+ reg-names = "csr_gp_io_mux_mic_ctl",
+ "csr_gp_io_mux_spkr_ctl",
+ "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+ "csr_gp_io_mux_quin_ctl";
+
+ qcom,audio-routing =
+ "AIF4 VI", "MCLK",
+ "AIF4 VI", "MICBIAS_REGULATOR",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "AIF4 MAD", "MICBIAS_REGULATOR",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "AMIC3", "MIC BIAS2",
+ "MIC BIAS2", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2",
+ "MIC BIAS2", "ANCLeft Headset Mic",
+ "AMIC5", "MIC BIAS3",
+ "MIC BIAS3", "Handset Mic",
+ "AMIC6", "MIC BIAS4",
+ "MIC BIAS4", "Analog Mic6",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC2", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic2",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "DMIC4", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic4",
+ "DMIC5", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic5",
+ "MIC BIAS1", "MICBIAS_REGULATOR",
+ "MIC BIAS2", "MICBIAS_REGULATOR",
+ "MIC BIAS3", "MICBIAS_REGULATOR",
+ "MIC BIAS4", "MICBIAS_REGULATOR",
+ "SpkrLeft IN", "SPK1 OUT",
+ "SpkrRight IN", "SPK2 OUT";
+
+ qcom,tasha-mclk-clk-freq = <9600000>;
+
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing";
+
+ asoc-cpu = <&dai_pri_auxpcm>,
+ <&dai_mi2s2>, <&dai_mi2s3>, <&dai_mi2s5>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+ <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>,
+ <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>,
+ <&incall_music_rx>, <&incall_music_2_rx>,
+ <&sb_5_rx>, <&bt_sco_rx>, <&bt_sco_tx>,
+ <&int_fm_rx>, <&int_fm_tx>, <&sb_6_rx>;
+
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-mi2s.5", "msm-dai-q6-dev.16384",
+ "msm-dai-q6-dev.16385", "msm-dai-q6-dev.16386",
+ "msm-dai-q6-dev.16387", "msm-dai-q6-dev.16388",
+ "msm-dai-q6-dev.16389", "msm-dai-q6-dev.16390",
+ "msm-dai-q6-dev.16391", "msm-dai-q6-dev.16392",
+ "msm-dai-q6-dev.16393", "msm-dai-q6-dev.16395",
+ "msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+ "msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+ "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+ "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770",
+ "msm-dai-q6-dev.16394", "msm-dai-q6-dev.12288",
+ "msm-dai-q6-dev.12289", "msm-dai-q6-dev.12292",
+ "msm-dai-q6-dev.12293", "msm-dai-q6-dev.16396";
+
+ asoc-codec = <&stub_codec>, <&hdmi_dba>;
+ asoc-codec-names = "msm-stub-codec.1", "msm-hdmi-dba-codec-rx";
+ qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+
+ qcom,wsa-max-devs = <2>;
+ qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+ <&wsa881x_213>, <&wsa881x_214>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+ "SpkrLeft", "SpkrRight";
+ };
+
+ wcd9xxx_intc: wcd9xxx-irq {
+ status = "disabled";
+ interrupt-parent = <&tlmm>;
+ interrupts = <73 0>;
+ qcom,gpio-connect = <&tlmm 73 0>;
+ };
+
+ clock_audio: audio_ext_clk {
+ status = "disabled";
+ compatible = "qcom,audio-ref-clk";
+ clock-names = "osr_clk";
+ qcom,node_has_rpm_clock;
+ #clock-cells = <1>;
+ qcom,audio-ref-clk-gpio = <&pm8937_gpios 1 0>;
+ qcom,lpass-mclk-id = "pri_mclk";
+ clocks = <&clock_gcc clk_div_clk2>;
+ pinctrl-0 = <&cdc_mclk2_sleep>;
+ pinctrl-1 = <&cdc_mclk2_active>;
+ };
+
+ wcd_rst_gpio: wcd_gpio_ctrl {
+ status = "disabled";
+ qcom,cdc-rst-n-gpio = <&tlmm 68 0>;
+ };
+};
+
+&slim_msm {
+ status = "disabled";
+ wcd9335: tasha_codec {
+ status = "disabled";
+ compatible = "qcom,tasha-slim-pgd";
+ clock-names = "wcd_clk", "wcd_native_clk";
+ clocks = <&clock_audio clk_audio_pmi_clk>,
+ <&clock_audio clk_audio_ap_clk2>;
+
+ qcom,cdc-reset-gpio = <&tlmm 68 0>;
+
+ cdc-vdd-buck-supply = <&eldo2_pm8937>;
+ qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-buck-current = <650000>;
+
+ cdc-buck-sido-supply = <&eldo2_pm8937>;
+ qcom,cdc-buck-sido-voltage = <1800000 1800000>;
+ qcom,cdc-buck-sido-current = <250000>;
+
+ cdc-vdd-tx-h-supply = <&pm8937_l5>;
+ qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-tx-h-current = <25000>;
+
+ cdc-vdd-rx-h-supply = <&pm8937_l5>;
+ qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-rx-h-current = <25000>;
+
+ cdc-vdd-px-supply = <&pm8937_l5>;
+ qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-px-current = <10000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8937_l13>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <15000>;
+ };
+};
+
+&pm8937_gpios {
+ gpio@c000 {
+ status = "ok";
+ qcom,mode = <1>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <2>;
+ qcom,master-en = <1>;
+ qcom,out-strength = <2>;
+ };
+};
+
+&pm8937_1 {
+ pmic_analog_codec: analog-codec@f000 {
+ status = "okay";
+ compatible = "qcom,pmic-analog-codec";
+ reg = <0xf000 0x200>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+ interrupt-names = "spk_cnp_int",
+ "spk_clip_int",
+ "spk_ocp_int",
+ "ins_rem_det1",
+ "but_rel_det",
+ "but_press_det",
+ "ins_rem_det",
+ "mbhc_int",
+ "ear_ocp_int",
+ "hphr_ocp_int",
+ "hphl_ocp_det",
+ "ear_cnp_int",
+ "hphr_cnp_int",
+ "hphl_cnp_int";
+
+ cdc-vdda-cp-supply = <&pm8937_s4>;
+ qcom,cdc-vdda-cp-voltage = <2050000 2050000>;
+ qcom,cdc-vdda-cp-current = <210000>;
+
+ cdc-vdd-io-supply = <&pm8937_l5>;
+ qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-io-current = <5000>;
+
+ cdc-vdd-pa-supply = <&pm8937_s4>;
+ qcom,cdc-vdd-pa-voltage = <1900000 2050000>;
+ qcom,cdc-vdd-pa-current = <260000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8937_l13>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <5000>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-io",
+ "cdc-vdd-pa",
+ "cdc-vdda-cp";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+ msm_digital_codec: msm-dig-codec {
+ compatible = "qcom,msm-digital-codec";
+ reg = <0xc0f0000 0x0>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
index 84f73a4..7aaaf7e 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
@@ -57,6 +57,8 @@
compatible = "arm,cortex-a53";
reg = <0x100>;
enable-method = "psci";
+ efficiency = <1126>;
+ sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
next-level-cache = <&L2_1>;
L2_1: l2-cache {
compatible = "arm,arch-cache";
@@ -79,6 +81,8 @@
compatible = "arm,cortex-a53";
reg = <0x101>;
enable-method = "psci";
+ efficiency = <1126>;
+ sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
next-level-cache = <&L2_1>;
L1_I_101: l1-icache {
compatible = "arm,arch-cache";
@@ -95,6 +99,8 @@
compatible = "arm,cortex-a53";
reg = <0x102>;
enable-method = "psci";
+ efficiency = <1126>;
+ sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
next-level-cache = <&L2_1>;
L1_I_102: l1-icache {
compatible = "arm,arch-cache";
@@ -111,6 +117,8 @@
compatible = "arm,cortex-a53";
reg = <0x103>;
enable-method = "psci";
+ efficiency = <1126>;
+ sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
next-level-cache = <&L2_1>;
L1_I_103: l1-icache {
compatible = "arm,arch-cache";
@@ -127,6 +135,8 @@
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
+ efficiency = <1024>;
+ sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
next-level-cache = <&L2_0>;
L2_0: l2-cache {
compatible = "arm,arch-cache";
@@ -148,6 +158,8 @@
compatible = "arm,cortex-a53";
reg = <0x1>;
enable-method = "psci";
+ efficiency = <1024>;
+ sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
next-level-cache = <&L2_0>;
L1_I_1: l1-icache {
compatible = "arm,arch-cache";
@@ -164,6 +176,8 @@
compatible = "arm,cortex-a53";
reg = <0x2>;
enable-method = "psci";
+ efficiency = <1024>;
+ sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
next-level-cache = <&L2_0>;
L1_I_2: l1-icache {
compatible = "arm,arch-cache";
@@ -180,6 +194,8 @@
compatible = "arm,cortex-a53";
reg = <0x3>;
enable-method = "psci";
+ efficiency = <1024>;
+ sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
next-level-cache = <&L2_0>;
L1_I_3: l1-icache {
compatible = "arm,arch-cache";
@@ -191,4 +207,57 @@
};
};
};
+
+ energy_costs: energy-costs {
+ compatible = "sched-energy";
+
+ CPU_COST_0: core-cost0 {
+ busy-cost-data = <
+ 700000 623
+ 1000000 917
+ 1100000 1106
+ 1250000 1432
+ 1400000 1740
+ >;
+ idle-cost-data = <
+ 100 80 60 40
+ >;
+ };
+ CPU_COST_1: core-cost1 {
+ busy-cost-data = <
+ 500000 70
+ 800000 114
+ 900000 141
+ 1000000 178
+ 1100000 213
+ >;
+ idle-cost-data = <
+ 40 20 10 8
+ >;
+ };
+ CLUSTER_COST_0: cluster-cost0 {
+ busy-cost-data = <
+ 500000 19
+ 800000 29
+ 900000 36
+ 1000000 46
+ 1100000 55
+ >;
+ idle-cost-data = <
+ 4 3 2 1
+ >;
+ };
+ CLUSTER_COST_1: cluster-cost1 {
+ busy-cost-data = <
+ 700000 85
+ 1000000 126
+ 1100000 152
+ 1250000 197
+ 1400000 239
+ >;
+ idle-cost-data = <
+ 4 3 2 1
+ >;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
index 17ee465..1b273ef 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
@@ -19,6 +19,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
+ interrupt-parent = <&wakegpio>;
#interrupt-cells = <2>;
pmx-uartconsole {
@@ -369,6 +370,31 @@
};
};
+ cdc_mclk2_pin {
+ cdc_mclk2_sleep: cdc_mclk2_sleep {
+ mux {
+ pins = "gpio66";
+ function = "pri_mi2s";
+ };
+ config {
+ pins = "gpio66";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ cdc_mclk2_active: cdc_mclk2_active {
+ mux {
+ pins = "gpio66";
+ function = "pri_mi2s";
+ };
+ config {
+ pins = "gpio66";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
blsp2_uart1_active: blsp2_uart1_active {
mux {
pins = "gpio16", "gpio17", "gpio18", "gpio19";
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 59b7edb..2bc57c5 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -200,7 +200,7 @@
wakegpio: wake-gpio {
compatible = "qcom,mpm-gpio-msm8937", "qcom,mpm-gpio";
interrupt-controller;
- interrupt-parent = <&tlmm>;
+ interrupt-parent = <&intc>;
#interrupt-cells = <2>;
};
@@ -739,6 +739,50 @@
status = "disabled";
};
+ msm_cpufreq: qcom,msm-cpufreq {
+ compatible = "qcom,msm-cpufreq";
+ clock-names = "l2_clk", "cpu0_clk", "cpu1_clk", "cpu2_clk",
+ "cpu3_clk", "cpu4_clk", "cpu5_clk",
+ "cpu6_clk", "cpu7_clk";
+ clocks = <&clock_cpu clk_cci_clk>,
+ <&clock_cpu clk_a53_bc_clk>,
+ <&clock_cpu clk_a53_bc_clk>,
+ <&clock_cpu clk_a53_bc_clk>,
+ <&clock_cpu clk_a53_bc_clk>,
+ <&clock_cpu clk_a53_lc_clk>,
+ <&clock_cpu clk_a53_lc_clk>,
+ <&clock_cpu clk_a53_lc_clk>,
+ <&clock_cpu clk_a53_lc_clk>;
+
+ qcom,governor-per-policy;
+
+ qcom,cpufreq-table-0 =
+ < 960000 >,
+ < 1094400 >,
+ < 1209600 >,
+ < 1248000 >,
+ < 1344000 >,
+ < 1401000 >,
+ < 1497600 >;
+
+ qcom,cpufreq-table-4 =
+ < 768000 >,
+ < 902400 >,
+ < 998400 >,
+ < 1094400 >,
+ < 1209600 >;
+ };
+
+ cci_cache: qcom,cci {
+ compatible = "devfreq-simple-dev";
+ clock-names = "devfreq_clk";
+ clocks = <&clock_cpu clk_cci_clk>;
+ governor = "cpufreq";
+ freq-tbl-khz =
+ < 400000 >,
+ < 533333 >;
+ };
+
cpubw: qcom,cpubw {
compatible = "qcom,devbw";
governor = "cpufreq";
@@ -784,6 +828,48 @@
< 7031 /* 921.6 MHz */ >; /* TURBO */
};
+ devfreq-cpufreq {
+ cpubw-cpufreq {
+ target-dev = <&cpubw>;
+ cpu-to-dev-map-0 =
+ < 998400 2929 >, /* SVS */
+ < 1094400 5053 >, /* NOM */
+ < 1248000 5712 >, /* NOM+ */
+ < 1344000 7031 >,
+ < 1497600 7031 >; /* TURBO */
+ cpu-to-dev-map-4 =
+ < 806400 2929 >, /* SVS */
+ < 902400 5053 >, /* NOM */
+ < 998400 6152 >, /* NOM+ */
+ < 1209600 7031 >; /* TURBO */
+ };
+
+ cci-cpufreq {
+ target-dev = <&cci_cache>;
+ cpu-to-dev-map-0 =
+ < 998400 400000 >, /* SVS */
+ < 1094400 400000 >, /* NOM */
+ < 1248000 533333 >, /* NOM+ */
+ < 1344000 533333 >,
+ < 1497600 533333 >; /* TURBO */
+ cpu-to-dev-map-4 =
+ < 806400 400000 >, /* SVS */
+ < 902400 400000 >, /* NOM */
+ < 998400 533333 >, /* NOM+ */
+ < 1209600 533333 >; /* TURBO */
+ };
+
+ mincpubw-cpufreq {
+ target-dev = <&mincpubw>;
+ cpu-to-dev-map-0 =
+ < 1094400 2929 >,
+ < 1497600 4248 >;
+ cpu-to-dev-map-4 =
+ < 998400 2929 >,
+ < 1209600 4248 >;
+ };
+ };
+
blsp2_uart1: uart@7aef000 {
compatible = "qcom,msm-hsuart-v14";
reg = <0x7aef000 0x200>,
@@ -1232,6 +1318,15 @@
compatible = "qcom,msm-adsprpc-mem-region";
memory-region = <&adsp_mem>;
};
+ qcom,msm_fastrpc {
+ compatible = "qcom,msm-fastrpc-legacy-compute";
+ qcom,msm_fastrpc_compute_cb {
+ compatible = "qcom,msm-fastrpc-legacy-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&apps_iommu 0x2008 0x7>;
+ sids = <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>;
+ };
+ };
sdcc1_ice: sdcc1ice@7803000 {
compatible = "qcom,ice";
@@ -1612,6 +1707,91 @@
memory-region = <&venus_mem>;
};
+ qcom,wcnss-wlan@0a000000 {
+ compatible = "qcom,wcnss_wlan";
+ reg = <0x0a000000 0x280000>,
+ <0xb011008 0x04>,
+ <0x0a21b000 0x3000>,
+ <0x03204000 0x00000100>,
+ <0x03200800 0x00000200>,
+ <0x0a100400 0x00000200>,
+ <0x0a205050 0x00000200>,
+ <0x0a219000 0x00000020>,
+ <0x0a080488 0x00000008>,
+ <0x0a080fb0 0x00000008>,
+ <0x0a08040c 0x00000008>,
+ <0x0a0120a8 0x00000008>,
+ <0x0a012448 0x00000008>,
+ <0x0a080c00 0x00000001>;
+
+ reg-names = "wcnss_mmio", "wcnss_fiq",
+ "pronto_phy_base", "riva_phy_base",
+ "riva_ccu_base", "pronto_a2xb_base",
+ "pronto_ccpu_base", "pronto_saw2_base",
+ "wlan_tx_phy_aborts","wlan_brdg_err_source",
+ "wlan_tx_status", "alarms_txctl",
+ "alarms_tactl", "pronto_mcu_base";
+
+ interrupts = <0 145 0 0 146 0>;
+ interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+ qcom,pronto-vddmx-supply = <&pm8937_l3_level_ao>;
+ qcom,pronto-vddcx-supply = <&pm8937_s2_level>;
+ qcom,pronto-vddpx-supply = <&pm8937_l5>;
+ qcom,iris-vddxo-supply = <&pm8937_l7>;
+ qcom,iris-vddrfa-supply = <&pm8937_l19>;
+ qcom,iris-vddpa-supply = <&pm8937_l9>;
+ qcom,iris-vdddig-supply = <&pm8937_l5>;
+
+ qcom,iris-vddxo-voltage-level = <1800000 0 1800000>;
+ qcom,iris-vddrfa-voltage-level = <1300000 0 1300000>;
+ qcom,iris-vddpa-voltage-level = <3300000 0 3300000>;
+ qcom,iris-vdddig-voltage-level = <1800000 0 1800000>;
+
+ qcom,vddmx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_TURBO
+ RPM_SMD_REGULATOR_LEVEL_NONE
+ RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,vddcx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_NOM
+ RPM_SMD_REGULATOR_LEVEL_NONE
+ RPM_SMD_REGULATOR_LEVEL_BINNING>;
+ qcom,vddpx-voltage-level = <1800000 0 1800000>;
+
+ qcom,iris-vddxo-current = <10000>;
+ qcom,iris-vddrfa-current = <100000>;
+ qcom,iris-vddpa-current = <515000>;
+ qcom,iris-vdddig-current = <10000>;
+
+ qcom,pronto-vddmx-current = <0>;
+ qcom,pronto-vddcx-current = <0>;
+ qcom,pronto-vddpx-current = <0>;
+
+ pinctrl-names = "wcnss_default", "wcnss_sleep",
+ "wcnss_gpio_default";
+ pinctrl-0 = <&wcnss_default>;
+ pinctrl-1 = <&wcnss_sleep>;
+ pinctrl-2 = <&wcnss_gpio_default>;
+
+ gpios = <&tlmm 76 0>, <&tlmm 77 0>, <&tlmm 78 0>,
+ <&tlmm 79 0>, <&tlmm 80 0>;
+
+ clocks = <&clock_gcc clk_xo_wlan_clk>,
+ <&clock_gcc clk_rf_clk2>,
+ <&clock_debug clk_gcc_debug_mux_8937>,
+ <&clock_gcc clk_wcnss_m_clk>,
+ <&clock_gcc clk_snoc_wcnss_a_clk>;
+
+ clock-names = "xo", "rf_clk", "measure", "wcnss_debug",
+ "snoc_wcnss";
+
+ qcom,snoc-wcnss-clock-freq = <200000000>;
+
+ qcom,has-autodetect-xo;
+ qcom,is-pronto-v3;
+ qcom,has-pronto-hw;
+ qcom,has-vsys-adc-channel;
+ qcom,wcnss-adc_tm = <&pm8937_adc_tm>;
+ };
+
bam_dmux: qcom,bam_dmux@4044000 {
compatible = "qcom,bam_dmux";
reg = <0x4044000 0x19000>;
@@ -1626,6 +1806,7 @@
#include "pm8937-rpm-regulator.dtsi"
#include "msm8937-regulator.dtsi"
#include "pm8937.dtsi"
+#include "msm8937-audio.dtsi"
#include "msm-gdsc-8916.dtsi"
#include "msm8937-coresight.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index 171b7c4..6503b33 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -20,6 +20,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
+ interrupt-parent = <&wakegpio>;
#interrupt-cells = <2>;
pmx-uartconsole {
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index e66e1da..bb370cc 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -25,10 +25,6 @@
qcom,msm-name = "MSM8953";
interrupt-parent = <&wakegic>;
- chosen {
- bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1";
- };
-
firmware: firmware {
android {
compatible = "android,firmware";
@@ -220,20 +216,23 @@
<0x0b002000 0x1000>;
};
- mpm: mpm@601d4 {
- compatible = "qcom,mpm";
+ wakegic: wake-gic@601d4 {
+ compatible = "qcom,mpm-gic-msm8953", "qcom,mpm-gic";
interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
reg = <0x601d4 0x1000>,
<0xb011008 0x4>; /* MSM_APCS_GCC_BASE 4K */
reg-names = "vmpm", "ipc";
qcom,num-mpm-irqs = <96>;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ #interrupt-cells = <3>;
+ };
- wakegic: wake-gic {
- compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953";
- interrupt-controller;
- interrupt-parent = <&intc>;
- #interrupt-cells = <3>;
- };
+ wakegpio: wake-gpio {
+ compatible = "qcom,mpm-gpio-msm8953", "qcom,mpm-gpio";
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ #interrupt-cells = <2>;
};
qcom,msm-gladiator@b1c0000 {
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 7724714..fa10500 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -507,20 +507,6 @@
type = "passive";
};
};
- cooling-maps {
- vbat_map6 {
- trip = <&pm660_vbat_adc>;
- cooling-device =
- <&CPU6 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- vbat_map7 {
- trip = <&pm660_vbat_adc>;
- cooling-device =
- <&CPU7 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- };
};
vbat_low {
@@ -569,20 +555,6 @@
type = "passive";
};
};
- cooling-maps {
- soc_map6 {
- trip = <&pm660_low_soc>;
- cooling-device =
- <&CPU6 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- soc_map7 {
- trip = <&pm660_low_soc>;
- cooling-device =
- <&CPU7 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- };
};
pm660_temp_alarm: pm660_tz {
@@ -608,97 +580,5 @@
type = "critical";
};
};
- cooling-maps {
- trip0_cpu0 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU0 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip0_cpu1 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU1 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip0_cpu2 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU2 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip0_cpu3 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU3 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip0_cpu4 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU4 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip0_cpu5 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU5 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip0_cpu6 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU6 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip0_cpu7 {
- trip = <&pm660_trip0>;
- cooling-device =
- <&CPU7 (THERMAL_MAX_LIMIT-1)
- (THERMAL_MAX_LIMIT-1)>;
- };
- trip1_cpu1 {
- trip = <&pm660_trip1>;
- cooling-device =
- <&CPU1 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- trip1_cpu2 {
- trip = <&pm660_trip1>;
- cooling-device =
- <&CPU2 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- trip1_cpu3 {
- trip = <&pm660_trip1>;
- cooling-device =
- <&CPU3 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- trip1_cpu4 {
- trip = <&pm660_trip1>;
- cooling-device =
- <&CPU4 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- trip1_cpu5 {
- trip = <&pm660_trip1>;
- cooling-device =
- <&CPU5 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- trip1_cpu6 {
- trip = <&pm660_trip1>;
- cooling-device =
- <&CPU6 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- trip1_cpu7 {
- trip = <&pm660_trip1>;
- cooling-device =
- <&CPU7 THERMAL_MAX_LIMIT
- THERMAL_MAX_LIMIT>;
- };
- };
};
};
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index 38d2629..becc510 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -37,7 +37,7 @@
reg = <0x3100 0x100>;
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set";
qcom,adc-vdd-reference = <1875>;
qcom,adc-full-scale-code = <0x70e4>;
@@ -237,8 +237,8 @@
<0x2 0x10 0x3 IRQ_TYPE_EDGE_RISING>,
<0x2 0x10 0x4 IRQ_TYPE_EDGE_RISING>,
<0x2 0x10 0x5 IRQ_TYPE_EDGE_RISING>,
- <0x2 0x10 0x6 IRQ_TYPE_LEVEL_HIGH>,
- <0x2 0x10 0x7 IRQ_TYPE_LEVEL_HIGH>;
+ <0x2 0x10 0x6 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x10 0x7 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "chgr-error",
"chg-state-change",
@@ -256,7 +256,7 @@
<0x2 0x11 0x0 IRQ_TYPE_EDGE_RISING>,
<0x2 0x11 0x1 IRQ_TYPE_EDGE_RISING>,
<0x2 0x11 0x2 IRQ_TYPE_EDGE_RISING>,
- <0x2 0x11 0x3 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x11 0x3 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x11 0x4 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x11 0x5 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x11 0x6 IRQ_TYPE_EDGE_RISING>,
@@ -282,7 +282,7 @@
<0x2 0x12 0x4 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x12 0x5 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x12 0x6 IRQ_TYPE_EDGE_BOTH>,
- <0x2 0x12 0x7 IRQ_TYPE_LEVEL_HIGH>;
+ <0x2 0x12 0x7 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "bat-temp",
"all-chnl-conv-done",
@@ -301,8 +301,8 @@
<0x2 0x13 0x1 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x2 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x3 IRQ_TYPE_EDGE_BOTH>,
- <0x2 0x13 0x4 IRQ_TYPE_LEVEL_HIGH>,
- <0x2 0x13 0x5 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x13 0x5 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>,
<0x2 0x13 0x7 IRQ_TYPE_EDGE_RISING>;
@@ -320,12 +320,12 @@
reg = <0x1500 0x100>;
interrupts =
<0x2 0x15 0x0 IRQ_TYPE_EDGE_BOTH>,
- <0x2 0x15 0x1 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x15 0x1 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x15 0x2 IRQ_TYPE_EDGE_RISING>,
- <0x2 0x15 0x3 IRQ_TYPE_LEVEL_HIGH>,
- <0x2 0x15 0x4 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x3 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x4 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>,
- <0x2 0x15 0x6 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x15 0x6 IRQ_TYPE_EDGE_RISING>,
<0x2 0x15 0x7 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "typec-or-rid-detect-change",
@@ -343,11 +343,11 @@
interrupts =
<0x2 0x16 0x0 IRQ_TYPE_EDGE_RISING>,
<0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>,
- <0x2 0x16 0x2 IRQ_TYPE_LEVEL_HIGH>,
- <0x2 0x16 0x3 IRQ_TYPE_LEVEL_HIGH>,
- <0x2 0x16 0x4 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x16 0x2 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x16 0x3 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x16 0x4 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x16 0x5 IRQ_TYPE_EDGE_RISING>,
- <0x2 0x16 0x6 IRQ_TYPE_EDGE_FALLING>,
+ <0x2 0x16 0x6 IRQ_TYPE_EDGE_RISING>,
<0x2 0x16 0x7 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "wdog-snarl",
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index d33c42c..4a63f9e 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -36,9 +36,10 @@
status = "okay";
qcom,model = "msm8953-sku4-snd-card";
qcom,msm-micbias1-ext-cap;
+ qcom,msm-micbias2-ext-cap;
qcom,msm-mbhc-hphl-swh = <1>;
qcom,msm-mbhc-gnd-swh = <0>;
- qcom,msm-hs-micbias-type = "internal";
+ qcom,msm-hs-micbias-type = "external";
};
&wsa881x_i2c_f {
@@ -144,3 +145,7 @@
};
};
};
+
+&sdhc_2 {
+ cd-gpios = <&tlmm 133 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index 08a247f..12d4fc3 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -38,39 +38,32 @@
};
&thermal_zones {
- camera-usr {
- status = "disabled";
- };
+ /delete-node/ camera-usr;
+ /delete-node/ apc1-l2-usr;
+ /delete-node/ apc0-cpu0-usr;
+ /delete-node/ apc0-cpu1-usr;
+ /delete-node/ apc0-cpu2-usr;
+ /delete-node/ apc0-cpu3-usr;
+ /delete-node/ apc0-l2-usr;
+ /delete-node/ gpu0-usr;
+ /delete-node/ gpu1-usr;
+ /delete-node/ gpu1-step;
+ /delete-node/ deca-cpu-max-step;
+ /delete-node/ apc0-cpu0-step;
+ /delete-node/ apc0-cpu1-step;
+ /delete-node/ apc0-cpu2-step;
+ /delete-node/ apc0-cpu3-step;
+ /delete-node/ camera-lowf;
+ /delete-node/ apc1-l2-lowf;
+ /delete-node/ apc0-cpu0-lowf;
+ /delete-node/ apc0-cpu1-lowf;
+ /delete-node/ apc0-cpu2-lowf;
+ /delete-node/ apc0-cpu3-lowf;
+ /delete-node/ apc0-l2-lowf;
+ /delete-node/ gpu0-lowf;
+ /delete-node/ gpu1-lowf;
- apc1-l2-usr {
- status = "disabled";
- };
-
- apc0-cpu0-usr {
- status = "disabled";
- };
-
- apc0-cpu1-usr {
- status = "disabled";
- };
-
- apc0-cpu2-usr {
- status = "disabled";
- };
-
- apc0-cpu3-usr {
- status = "disabled";
- };
-
- apc0-l2-usr {
- status = "disabled";
- };
-
- gpu0-usr {
- status = "disabled";
- };
-
- gpu1-usr {
+ case-therm-step {
status = "disabled";
};
@@ -157,4 +150,343 @@
};
};
};
+
+ gpu0-step {
+ polling-delay-passive = <250>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 15>;
+ thermal-governor = "step_wise";
+
+ trips {
+ sdm632_gpu_trip0: gpu-trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ gpu_cdev0 {
+ trip = <&sdm632_gpu_trip0>;
+ cooling-device =
+ <&msm_gpu THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ hepta-cpu-max-step {
+ polling-delay-passive = <50>;
+ polling-delay = <100>;
+ thermal-governor = "step_wise";
+
+ trips {
+ sdm632_cpu_trip:cpu-trip {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ cpu0_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU0 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu1_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU1 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu2_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU2 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu3_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU3 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu4_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU4 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu5_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU5 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu6_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU6 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu7_cdev {
+ trip = <&sdm632_cpu_trip>;
+ cooling-device =
+ <&CPU7 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ };
+ };
+
+ cpuss3-step {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 13>;
+ thermal-governor = "step_wise";
+
+ trips {
+ cpuss3_trip: cpuss3-trip {
+ temperature = <105000>;
+ hysteresis = <15000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_cdev {
+ trip = <&cpuss3_trip>;
+ cooling-device =
+ <&CPU0 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ cpu1_cdev {
+ trip = <&cpuss3_trip>;
+ cooling-device =
+ <&CPU1 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ cpu2_cdev {
+ trip = <&cpuss3_trip>;
+ cooling-device =
+ <&CPU2 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ cpu3_cdev {
+ trip = <&cpuss3_trip>;
+ cooling-device =
+ <&CPU3 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
+
+ video-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 3>;
+ tracks-low;
+
+ trips {
+ video_trip: video-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&video_trip>;
+ cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+ (THERMAL_MAX_LIMIT - 4)>;
+ };
+ gpu_vdd_cdev {
+ trip = <&video_trip>;
+ cooling-device = <&msm_gpu 2 2>;
+ };
+ cx_vdd_cdev {
+ trip = <&video_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&video_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ };
+ };
+
+ cpuss0-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 8>;
+ tracks-low;
+
+ trips {
+ sdm632_cpuss0_trip: cpuss0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&sdm632_cpuss0_trip>;
+ cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+ (THERMAL_MAX_LIMIT - 4)>;
+ };
+ gpu_vdd_cdev {
+ trip = <&sdm632_cpuss0_trip>;
+ cooling-device = <&msm_gpu 2 2>;
+ };
+ cx_vdd_cdev {
+ trip = <&sdm632_cpuss0_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&sdm632_cpuss0_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ };
+ };
+
+ cpuss1-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 9>;
+ tracks-low;
+
+ trips {
+ sdm632_cpuss1_trip: cpuss1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&sdm632_cpuss1_trip>;
+ cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+ (THERMAL_MAX_LIMIT - 4)>;
+ };
+ gpu_vdd_cdev {
+ trip = <&sdm632_cpuss1_trip>;
+ cooling-device = <&msm_gpu 2 2>;
+ };
+ cx_vdd_cdev {
+ trip = <&sdm632_cpuss1_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&sdm632_cpuss1_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ };
+ };
+
+ cpuss3-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 13>;
+ tracks-low;
+
+ trips {
+ sdm632_cpuss3_trip: cpuss3-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&sdm632_cpuss3_trip>;
+ cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+ (THERMAL_MAX_LIMIT - 4)>;
+ };
+ gpu_vdd_cdev {
+ trip = <&sdm632_cpuss3_trip>;
+ cooling-device = <&msm_gpu 2 2>;
+ };
+ cx_vdd_cdev {
+ trip = <&sdm632_cpuss3_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&sdm632_cpuss3_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ };
+ };
+
+ camera-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 14>;
+ tracks-low;
+
+ trips {
+ sdm632_camera_trip: camera-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&sdm632_camera_trip>;
+ cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+ (THERMAL_MAX_LIMIT - 4)>;
+ };
+ gpu_vdd_cdev {
+ trip = <&sdm632_camera_trip>;
+ cooling-device = <&msm_gpu 2 2>;
+ };
+ cx_vdd_cdev {
+ trip = <&sdm632_camera_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&sdm632_camera_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ };
+ };
+
+ gpu0-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 15>;
+ tracks-low;
+
+ trips {
+ sdm632_gpu0_trip: gpu0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&sdm632_gpu0_trip>;
+ cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+ (THERMAL_MAX_LIMIT - 4)>;
+ };
+ gpu_vdd_cdev {
+ trip = <&sdm632_gpu0_trip>;
+ cooling-device = <&msm_gpu 2 2>;
+ };
+ cx_vdd_cdev {
+ trip = <&sdm632_gpu0_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&sdm632_gpu0_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
index f259838..39cbef0 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
@@ -689,4 +689,133 @@
};
};
};
+
+ vbat_adc {
+ cooling-maps {
+ vbat_map6 {
+ trip = <&pm660_vbat_adc>;
+ cooling-device =
+ <&CPU6 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ vbat_map7 {
+ trip = <&pm660_vbat_adc>;
+ cooling-device =
+ <&CPU7 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
+
+ soc {
+ cooling-maps {
+ soc_map6 {
+ trip = <&pm660_low_soc>;
+ cooling-device =
+ <&CPU6 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ soc_map7 {
+ trip = <&pm660_low_soc>;
+ cooling-device =
+ <&CPU7 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
+
+ pm660_temp_alarm: pm660_tz {
+ cooling-maps {
+ trip0_cpu0 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU0 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu1 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU1 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu2 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU2 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu3 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU3 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu4 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU4 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu5 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU5 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu6 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU6 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu7 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU7 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip1_cpu1 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU1 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu2 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU2 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu3 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU3 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu4 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU4 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu5 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU5 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu6 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU6 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu7 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU7 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
};
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index 3928513e..1db7cbe 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -545,6 +545,7 @@
CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
CONFIG_MSM_PM=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 4aca832..49812fb 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -565,6 +565,7 @@
CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
CONFIG_MSM_PM=y
CONFIG_QCOM_DCC=y
CONFIG_QTI_RPM_STATS_LOG=y
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
index b9920b1..70cef54 100644
--- a/arch/mn10300/mm/misalignment.c
+++ b/arch/mn10300/mm/misalignment.c
@@ -437,7 +437,7 @@
info.si_signo = SIGSEGV;
info.si_errno = 0;
- info.si_code = 0;
+ info.si_code = SEGV_MAPERR;
info.si_addr = (void *) regs->pc;
force_sig_info(SIGSEGV, &info, current);
return;
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
index 3d3f606..605a284 100644
--- a/arch/openrisc/kernel/traps.c
+++ b/arch/openrisc/kernel/traps.c
@@ -302,12 +302,12 @@
siginfo_t info;
if (user_mode(regs)) {
- /* Send a SIGSEGV */
- info.si_signo = SIGSEGV;
+ /* Send a SIGBUS */
+ info.si_signo = SIGBUS;
info.si_errno = 0;
- /* info.si_code has been set above */
- info.si_addr = (void *)address;
- force_sig_info(SIGSEGV, &info, current);
+ info.si_code = BUS_ADRALN;
+ info.si_addr = (void __user *)address;
+ force_sig_info(SIGBUS, &info, current);
} else {
printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
show_registers(regs);
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 0e12cb2..dc0996b 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -319,6 +319,7 @@
#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ull << 61) // IBM bit 2
#ifndef __ASSEMBLY__
+#include <linux/types.h>
/**
* plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index ff63934..c5b9977 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -607,7 +607,8 @@
break;
}
- force_sig_info(SIGFPE, &info, current);
+ info.si_signo = SIGFPE;
+ force_sig_info(info.si_signo, &info, current);
}
#endif
diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c
index e32142b..28c3720 100644
--- a/arch/x86/crypto/poly1305_glue.c
+++ b/arch/x86/crypto/poly1305_glue.c
@@ -164,7 +164,6 @@
.init = poly1305_simd_init,
.update = poly1305_simd_update,
.final = crypto_poly1305_final,
- .setkey = crypto_poly1305_setkey,
.descsize = sizeof(struct poly1305_simd_desc_ctx),
.base = {
.cra_name = "poly1305",
diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c
index 36870b2..d088050 100644
--- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c
+++ b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c
@@ -57,10 +57,12 @@
{
unsigned int j;
- state->lens[0] = 0;
- state->lens[1] = 1;
- state->lens[2] = 2;
- state->lens[3] = 3;
+ /* initially all lanes are unused */
+ state->lens[0] = 0xFFFFFFFF00000000;
+ state->lens[1] = 0xFFFFFFFF00000001;
+ state->lens[2] = 0xFFFFFFFF00000002;
+ state->lens[3] = 0xFFFFFFFF00000003;
+
state->unused_lanes = 0xFF03020100;
for (j = 0; j < 4; j++)
state->ldata[j].job_in_lane = NULL;
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index 9ee8506..62210da 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -13,7 +13,6 @@
*/
extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
extern bool vsyscall_enabled(void);
-extern unsigned long vsyscall_pgprot;
#else
static inline void map_vsyscall(void) {}
static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
@@ -22,5 +21,6 @@
}
static inline bool vsyscall_enabled(void) { return false; }
#endif
+extern unsigned long vsyscall_pgprot;
#endif /* _ASM_X86_VSYSCALL_H */
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d49da86..d66224e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4967,14 +4967,15 @@
if (is_guest_mode(vcpu) &&
vector == vmx->nested.posted_intr_nv) {
- /* the PIR and ON have been set by L1. */
- kvm_vcpu_trigger_posted_interrupt(vcpu);
/*
* If a posted intr is not recognized by hardware,
* we will accomplish it in the next vmentry.
*/
vmx->nested.pi_pending = true;
kvm_make_request(KVM_REQ_EVENT, vcpu);
+ /* the PIR and ON have been set by L1. */
+ if (!kvm_vcpu_trigger_posted_interrupt(vcpu))
+ kvm_vcpu_kick(vcpu);
return 0;
}
return -1;
diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h
index b39531b..72bfc1c 100644
--- a/arch/xtensa/include/asm/futex.h
+++ b/arch/xtensa/include/asm/futex.h
@@ -109,7 +109,6 @@
u32 oldval, u32 newval)
{
int ret = 0;
- u32 prev;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
@@ -120,26 +119,24 @@
__asm__ __volatile__ (
" # futex_atomic_cmpxchg_inatomic\n"
- "1: l32i %1, %3, 0\n"
- " mov %0, %5\n"
- " wsr %1, scompare1\n"
- "2: s32c1i %0, %3, 0\n"
- "3:\n"
+ " wsr %5, scompare1\n"
+ "1: s32c1i %1, %4, 0\n"
+ " s32i %1, %6, 0\n"
+ "2:\n"
" .section .fixup,\"ax\"\n"
" .align 4\n"
- "4: .long 3b\n"
- "5: l32r %1, 4b\n"
- " movi %0, %6\n"
+ "3: .long 2b\n"
+ "4: l32r %1, 3b\n"
+ " movi %0, %7\n"
" jx %1\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .long 1b,5b,2b,5b\n"
+ " .long 1b,4b\n"
" .previous\n"
- : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
- : "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT)
+ : "+r" (ret), "+r" (newval), "+m" (*uaddr), "+m" (*uval)
+ : "r" (uaddr), "r" (oldval), "r" (uval), "I" (-EFAULT)
: "memory");
- *uval = prev;
return ret;
}
diff --git a/crypto/ahash.c b/crypto/ahash.c
index cce0268..f3fa104 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -625,5 +625,16 @@
}
EXPORT_SYMBOL_GPL(ahash_attr_alg);
+bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg)
+{
+ struct crypto_alg *alg = &halg->base;
+
+ if (alg->cra_type != &crypto_ahash_type)
+ return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg));
+
+ return __crypto_ahash_alg(alg)->setkey != NULL;
+}
+EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Asynchronous cryptographic hash type");
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 0c654e5..af9ad45 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -691,7 +691,8 @@
inst->alg.finup = cryptd_hash_finup_enqueue;
inst->alg.export = cryptd_hash_export;
inst->alg.import = cryptd_hash_import;
- inst->alg.setkey = cryptd_hash_setkey;
+ if (crypto_shash_alg_has_setkey(salg))
+ inst->alg.setkey = cryptd_hash_setkey;
inst->alg.digest = cryptd_hash_digest_enqueue;
err = ahash_register_instance(tmpl, inst);
diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
index a14100e..6e9389c 100644
--- a/crypto/mcryptd.c
+++ b/crypto/mcryptd.c
@@ -534,7 +534,8 @@
inst->alg.finup = mcryptd_hash_finup_enqueue;
inst->alg.export = mcryptd_hash_export;
inst->alg.import = mcryptd_hash_import;
- inst->alg.setkey = mcryptd_hash_setkey;
+ if (crypto_hash_alg_has_setkey(halg))
+ inst->alg.setkey = mcryptd_hash_setkey;
inst->alg.digest = mcryptd_hash_digest_enqueue;
err = ahash_register_instance(tmpl, inst);
diff --git a/crypto/poly1305_generic.c b/crypto/poly1305_generic.c
index 2df9835d..bca9923 100644
--- a/crypto/poly1305_generic.c
+++ b/crypto/poly1305_generic.c
@@ -51,17 +51,6 @@
}
EXPORT_SYMBOL_GPL(crypto_poly1305_init);
-int crypto_poly1305_setkey(struct crypto_shash *tfm,
- const u8 *key, unsigned int keylen)
-{
- /* Poly1305 requires a unique key for each tag, which implies that
- * we can't set it on the tfm that gets accessed by multiple users
- * simultaneously. Instead we expect the key as the first 32 bytes in
- * the update() call. */
- return -ENOTSUPP;
-}
-EXPORT_SYMBOL_GPL(crypto_poly1305_setkey);
-
static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
{
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
@@ -80,6 +69,11 @@
dctx->s[3] = le32_to_cpuvp(key + 12);
}
+/*
+ * Poly1305 requires a unique key for each tag, which implies that we can't set
+ * it on the tfm that gets accessed by multiple users simultaneously. Instead we
+ * expect the key as the first 32 bytes in the update() call.
+ */
unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
const u8 *src, unsigned int srclen)
{
@@ -285,7 +279,6 @@
.init = crypto_poly1305_init,
.update = crypto_poly1305_update,
.final = crypto_poly1305_final,
- .setkey = crypto_poly1305_setkey,
.descsize = sizeof(struct poly1305_desc_ctx),
.base = {
.cra_name = "poly1305",
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index fe03d00..b1815b2 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1535,6 +1535,9 @@
struct kernfs_node *nfit_kernfs;
nvdimm = nfit_mem->nvdimm;
+ if (!nvdimm)
+ continue;
+
nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit");
if (nfit_kernfs)
nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs,
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index 2fa8304..7a34310 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -275,8 +275,8 @@
device->driver_data = hc;
acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
- printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
- hc->ec, hc->offset, hc->query_bit);
+ dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n",
+ hc->offset, hc->query_bit);
return 0;
}
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c940382..9b46ef4 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -265,9 +265,9 @@
{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
- { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
+ { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH M AHCI */
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
- { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH M RAID */
{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
@@ -290,9 +290,9 @@
{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
- { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT M AHCI */
{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
- { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
+ { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT M RAID */
{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
@@ -301,20 +301,20 @@
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
- { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
+ { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point M AHCI */
{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
- { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
+ { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point M RAID */
{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
- { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */
+ { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point M AHCI */
{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
- { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */
+ { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point M RAID */
{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
- { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
+ { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point M RAID */
{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
- { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
+ { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point M RAID */
{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
@@ -355,21 +355,21 @@
{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
- { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */
+ { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series M AHCI */
{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
- { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
+ { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series M RAID */
{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
- { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
+ { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series M RAID */
{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
- { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
+ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series M RAID */
{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
- { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
+ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H M AHCI */
{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
- { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
+ { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H M RAID */
{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
@@ -383,6 +383,11 @@
{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
+ { PCI_VDEVICE(INTEL, 0x0f22), board_ahci }, /* Bay Trail AHCI */
+ { PCI_VDEVICE(INTEL, 0x0f23), board_ahci }, /* Bay Trail AHCI */
+ { PCI_VDEVICE(INTEL, 0x22a3), board_ahci }, /* Cherry Trail AHCI */
+ { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci }, /* Apollo Lake AHCI */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index b0d2cb7..4a5bccd 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2779,7 +2779,7 @@
pd->pkt_dev = MKDEV(pktdev_major, idx);
ret = pkt_new_dev(pd, dev);
if (ret)
- goto out_new_dev;
+ goto out_mem2;
/* inherit events of the host device */
disk->events = pd->bdev->bd_disk->events;
@@ -2797,8 +2797,6 @@
mutex_unlock(&ctl_mutex);
return 0;
-out_new_dev:
- blk_cleanup_queue(disk->queue);
out_mem2:
put_disk(disk);
out_mem:
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 1cb958e..94e914a 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -31,6 +31,7 @@
#include <linux/errno.h>
#include <linux/skbuff.h>
+#include <linux/mmc/host.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
@@ -291,6 +292,14 @@
tuple = tuple->next;
}
+ /* BCM43341 devices soldered onto the PCB (non-removable) use an
+ * uart connection for bluetooth, ignore the BT SDIO interface.
+ */
+ if (func->vendor == SDIO_VENDOR_ID_BROADCOM &&
+ func->device == SDIO_DEVICE_ID_BROADCOM_43341 &&
+ !mmc_card_is_removable(func->card->host))
+ return -ENODEV;
+
data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 6930286..3257647 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/usb/quirks.h>
#include <linux/firmware.h>
#include <asm/unaligned.h>
@@ -369,8 +370,8 @@
#define BTUSB_FIRMWARE_LOADED 7
#define BTUSB_FIRMWARE_FAILED 8
#define BTUSB_BOOTING 9
-#define BTUSB_RESET_RESUME 10
-#define BTUSB_DIAG_RUNNING 11
+#define BTUSB_DIAG_RUNNING 10
+#define BTUSB_OOB_WAKE_ENABLED 11
struct btusb_data {
struct hci_dev *hdev;
@@ -2928,9 +2929,9 @@
/* QCA Rome devices lose their updated firmware over suspend,
* but the USB hub doesn't notice any status change.
- * Explicitly request a device reset on resume.
+ * explicitly request a device reset on resume.
*/
- set_bit(BTUSB_RESET_RESUME, &data->flags);
+ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
}
#ifdef CONFIG_BT_HCIBTUSB_RTL
@@ -2941,7 +2942,7 @@
* but the USB hub doesn't notice any status change.
* Explicitly request a device reset on resume.
*/
- set_bit(BTUSB_RESET_RESUME, &data->flags);
+ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
}
#endif
@@ -3098,14 +3099,6 @@
btusb_stop_traffic(data);
usb_kill_anchored_urbs(&data->tx_anchor);
- /* Optionally request a device reset on resume, but only when
- * wakeups are disabled. If wakeups are enabled we assume the
- * device will stay powered up throughout suspend.
- */
- if (test_bit(BTUSB_RESET_RESUME, &data->flags) &&
- !device_may_wakeup(&data->udev->dev))
- data->udev->reset_resume = 1;
-
return 0;
}
diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile
index 74c8055..57a330d 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -19,6 +19,7 @@
obj-$(CONFIG_ARCH_MSM8937) += clock-gcc-8952.o
obj-$(CONFIG_ARCH_MSM8937) += clock-cpu-8939.o
obj-$(CONFIG_ARCH_MSM8937) += clock-rcgwr.o
+obj-$(CONFIG_ARCH_MSM8953) += clock-cpu-sdm632.o
endif
obj-y += mdss/
diff --git a/drivers/clk/msm/clock-cpu-sdm632.c b/drivers/clk/msm/clock-cpu-sdm632.c
new file mode 100644
index 0000000..b59739a
--- /dev/null
+++ b/drivers/clk/msm/clock-cpu-sdm632.c
@@ -0,0 +1,1169 @@
+/*
+ * 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) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/clk/msm-clock-generic.h>
+#include <linux/suspend.h>
+#include <linux/of_platform.h>
+#include <linux/pm_opp.h>
+#include <soc/qcom/clock-local2.h>
+#include <soc/qcom/pm.h>
+#include <soc/qcom/clock-pll.h>
+#include <soc/qcom/clock-alpha-pll.h>
+#include <linux/regulator/rpm-smd-regulator.h>
+
+#include <dt-bindings/clock/msm-clocks-8953.h>
+
+#include "clock.h"
+
+#define APCS_PLL_MODE 0x0
+#define APCS_PLL_L_VAL 0x8
+#define APCS_PLL_ALPHA_VAL 0x10
+#define APCS_PLL_USER_CTL 0x18
+#define APCS_PLL_CONFIG_CTL_LO 0x20
+#define APCS_PLL_CONFIG_CTL_HI 0x24
+#define APCS_PLL_STATUS 0x28
+#define APCS_PLL_TEST_CTL_LO 0x30
+#define APCS_PLL_TEST_CTL_HI 0x34
+
+#define PLL_MODE(x) (*(x)->base + (unsigned long) (x)->mode_reg)
+
+#define GLB_DIAG 0x0b11101c
+
+static struct clk_ops clk_ops_variable_rate;
+
+DEFINE_EXT_CLK(xo_a_clk, NULL);
+DEFINE_VDD_REGS_INIT(vdd_cpu, 1);
+
+enum {
+ APCS_C0_PLL_BASE,
+ APCS_C1_PLL_BASE,
+ APCS_CCI_PLL_BASE,
+ N_PLL_BASES,
+};
+
+enum vdd_mx_pll_levels {
+ VDD_MX_OFF,
+ VDD_MX_MIN,
+ VDD_MX_LOWER,
+ VDD_MX_SVS,
+ VDD_MX_NUM,
+};
+
+static int vdd_pll_levels[] = {
+ RPM_REGULATOR_LEVEL_NONE, /* VDD_PLL_OFF */
+ RPM_REGULATOR_LEVEL_MIN_SVS, /* VDD_PLL_MIN */
+ RPM_REGULATOR_LEVEL_LOW_SVS, /* VDD_PLL_LOW_SVS */
+ RPM_REGULATOR_LEVEL_SVS, /* VDD_PLL_SVS */
+};
+
+static DEFINE_VDD_REGULATORS(vdd_mx, VDD_MX_NUM, 1,
+ vdd_pll_levels, NULL);
+
+#define VDD_MX_FMAX_MAP2(l1, f1, l2, f2) \
+ .vdd_class = &vdd_mx, \
+ .fmax = (unsigned long[VDD_MX_NUM]) { \
+ [VDD_MX_##l1] = (f1), \
+ [VDD_MX_##l2] = (f2), \
+ }, \
+ .num_fmax = VDD_MX_NUM
+
+#define VDD_MX_FMAX_MAP1(l1, f1) \
+ .vdd_class = &vdd_mx, \
+ .fmax = (unsigned long[VDD_MX_NUM]) { \
+ [VDD_MX_##l1] = (f1), \
+ }, \
+ .num_fmax = VDD_MX_NUM
+
+static void __iomem *virt_bases[N_PLL_BASES];
+
+/* Power PLL */
+static struct pll_clk apcs_c0_pll = {
+ .mode_reg = (void __iomem *)APCS_PLL_MODE,
+ .l_reg = (void __iomem *)APCS_PLL_L_VAL,
+ .alpha_reg = (void __iomem *)APCS_PLL_ALPHA_VAL,
+ .config_reg = (void __iomem *)APCS_PLL_USER_CTL,
+ .config_ctl_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_LO,
+ .config_ctl_hi_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_HI,
+ .test_ctl_lo_reg = (void __iomem *)APCS_PLL_TEST_CTL_LO,
+ .test_ctl_hi_reg = (void __iomem *)APCS_PLL_TEST_CTL_HI,
+ .status_reg = (void __iomem *)APCS_PLL_MODE,
+ .init_test_ctl = true,
+ .test_ctl_dbg = true,
+ .masks = {
+ .main_output_mask = BIT(0),
+ .early_output_mask = BIT(3),
+ .lock_mask = BIT(31),
+ },
+ .vals = {
+ .config_ctl_val = 0x200D4828,
+ .config_ctl_hi_val = 0x006,
+ .test_ctl_hi_val = 0x00004000,
+ .test_ctl_lo_val = 0x1C000000,
+ },
+ .max_rate = 1785600000UL,
+ .min_rate = 614400000UL,
+ .src_rate = 19200000UL,
+ .base = &virt_bases[APCS_C0_PLL_BASE],
+ .c = {
+ .parent = &xo_a_clk.c,
+ .dbg_name = "apcs_c0_pll",
+ .ops = &clk_ops_variable_rate,
+ VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+ CLK_INIT(apcs_c0_pll.c),
+ },
+};
+
+/* Perf PLL */
+static struct pll_clk apcs_c1_pll = {
+ .mode_reg = (void __iomem *)APCS_PLL_MODE,
+ .l_reg = (void __iomem *)APCS_PLL_L_VAL,
+ .alpha_reg = (void __iomem *)APCS_PLL_ALPHA_VAL,
+ .config_reg = (void __iomem *)APCS_PLL_USER_CTL,
+ .config_ctl_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_LO,
+ .config_ctl_hi_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_HI,
+ .test_ctl_lo_reg = (void __iomem *)APCS_PLL_TEST_CTL_LO,
+ .test_ctl_hi_reg = (void __iomem *)APCS_PLL_TEST_CTL_HI,
+ .status_reg = (void __iomem *)APCS_PLL_MODE,
+ .init_test_ctl = true,
+ .test_ctl_dbg = true,
+ .masks = {
+ .main_output_mask = BIT(0),
+ .early_output_mask = BIT(3),
+ .lock_mask = BIT(31),
+ },
+ .vals = {
+ .config_ctl_val = 0x200D4828,
+ .config_ctl_hi_val = 0x006,
+ .test_ctl_hi_val = 0x00004000,
+ .test_ctl_lo_val = 0x1C000000,
+ },
+ .max_rate = 2054400000UL,
+ .min_rate = 633600000UL,
+ .src_rate = 19200000UL,
+ .base = &virt_bases[APCS_C1_PLL_BASE],
+ .c = {
+ .parent = &xo_a_clk.c,
+ .dbg_name = "apcs_c1_pll",
+ .ops = &clk_ops_variable_rate,
+ VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+ CLK_INIT(apcs_c1_pll.c),
+ },
+};
+
+static struct alpha_pll_masks pll_masks_p = {
+ .lock_mask = BIT(31),
+ .update_mask = BIT(22),
+ .output_mask = 0xf,
+ .vco_mask = BM(21, 20) >> 20,
+ .vco_shift = 20,
+ .alpha_en_mask = BIT(24),
+ .cal_l_val_mask = BM(31, 16),
+};
+
+static struct alpha_pll_vco_tbl apcs_cci_pll_vco[] = {
+ VCO(2, 500000000, 1000000000),
+};
+
+static struct alpha_pll_clk apcs_cci_pll = {
+ .masks = &pll_masks_p,
+ .offset = 0x1D0000,
+ .vco_tbl = apcs_cci_pll_vco,
+ .num_vco = ARRAY_SIZE(apcs_cci_pll_vco),
+ .enable_config = 0x8, /* Early output */
+ .slew = true,
+ .config_ctl_val = 0x4001055b,
+ .cal_l_val = 0x27 << 16, /* Mid of VCO mode - 748.8MHz */
+ .base = &virt_bases[APCS_CCI_PLL_BASE],
+ .c = {
+ .parent = &xo_a_clk.c,
+ .rate = 787200000,
+ .dbg_name = "apcs_cci_pll",
+ .ops = &clk_ops_dyna_alpha_pll,
+ /* TODO: FMAX */
+ VDD_MX_FMAX_MAP1(SVS, 1000000000UL),
+ CLK_INIT(apcs_cci_pll.c),
+ },
+};
+
+enum {
+ A53SS_MUX_PERF,
+ A53SS_MUX_PWR,
+ A53SS_MUX_CCI,
+ A53SS_MUX_NUM,
+};
+
+static const char * const pll_names[] = { "c1", "c0", "cci" };
+static const char * const mux_names[] = { "c1", "c0", "cci" };
+
+struct a53_cpu_clk {
+ u32 cpu_reg_mask;
+ cpumask_t cpumask;
+ bool hw_low_power_ctrl;
+ struct pm_qos_request req;
+ struct clk c;
+ struct latency_level latency_lvl;
+ s32 cpu_latency_no_l2_pc_us;
+};
+
+static struct mux_div_clk a53ssmux_perf = {
+ .ops = &rcg_mux_div_ops,
+ .data = {
+ .max_div = 32,
+ .min_div = 2,
+ .is_half_divider = true,
+ },
+ .c = {
+ .dbg_name = "a53ssmux_perf",
+ .ops = &clk_ops_mux_div_clk,
+ CLK_INIT(a53ssmux_perf.c),
+ },
+ .div_mask = BM(4, 0),
+ .src_mask = BM(10, 8) >> 8,
+ .src_shift = 8,
+ MUX_SRC_LIST(
+ { &apcs_c1_pll.c, 5},
+ ),
+};
+
+static struct mux_div_clk a53ssmux_pwr = {
+ .ops = &rcg_mux_div_ops,
+ .data = {
+ .max_div = 32,
+ .min_div = 2,
+ .is_half_divider = true,
+ },
+ .c = {
+ .dbg_name = "a53ssmux_pwr",
+ .ops = &clk_ops_mux_div_clk,
+ CLK_INIT(a53ssmux_pwr.c),
+ },
+ .div_mask = BM(4, 0),
+ .src_mask = BM(10, 8) >> 8,
+ .src_shift = 8,
+ MUX_SRC_LIST(
+ { &apcs_c0_pll.c, 5},
+ ),
+};
+
+static struct mux_div_clk a53ssmux_cci = {
+ .ops = &rcg_mux_div_ops,
+ .data = {
+ .max_div = 32,
+ .min_div = 2,
+ .is_half_divider = true,
+ },
+ .c = {
+ .dbg_name = "a53ssmux_cci",
+ .ops = &clk_ops_mux_div_clk,
+ CLK_INIT(a53ssmux_cci.c),
+ },
+ .div_mask = BM(4, 0),
+ .src_mask = BM(10, 8) >> 8,
+ .src_shift = 8,
+ MUX_SRC_LIST(
+ { &apcs_cci_pll.c, 5},
+ ),
+};
+
+static struct a53_cpu_clk a53_pwr_clk;
+static struct a53_cpu_clk a53_perf_clk;
+static struct a53_cpu_clk a53_cci_clk;
+
+static void do_nothing(void *unused) { }
+
+static inline struct a53_cpu_clk *to_a53_cpu_clk(struct clk *c)
+{
+ return container_of(c, struct a53_cpu_clk, c);
+}
+
+static enum handoff a53_cpu_clk_handoff(struct clk *c)
+{
+ c->rate = clk_get_rate(c->parent);
+ return HANDOFF_DISABLED_CLK;
+}
+
+static long a53_cpu_clk_round_rate(struct clk *c, unsigned long rate)
+{
+ return clk_round_rate(c->parent, rate);
+}
+
+static int a53_cpu_clk_set_rate(struct clk *c, unsigned long rate)
+{
+ int ret = 0;
+ struct a53_cpu_clk *cpuclk = to_a53_cpu_clk(c);
+ bool hw_low_power_ctrl = cpuclk->hw_low_power_ctrl;
+
+ /*
+ * If hardware control of the clock tree is enabled during power
+ * collapse, setup a PM QOS request to prevent power collapse and
+ * wake up one of the CPUs in this clock domain, to ensure software
+ * control while the clock rate is being switched.
+ */
+ if (hw_low_power_ctrl) {
+ memset(&cpuclk->req, 0, sizeof(cpuclk->req));
+ cpumask_copy(&cpuclk->req.cpus_affine,
+ (const struct cpumask *)&cpuclk->cpumask);
+ cpuclk->req.type = PM_QOS_REQ_AFFINE_CORES;
+ pm_qos_add_request(&cpuclk->req, PM_QOS_CPU_DMA_LATENCY,
+ cpuclk->cpu_latency_no_l2_pc_us - 1);
+ smp_call_function_any(&cpuclk->cpumask, do_nothing,
+ NULL, 1);
+ }
+
+ ret = clk_set_rate(c->parent, rate);
+
+ /* Remove PM QOS request */
+ if (hw_low_power_ctrl)
+ pm_qos_remove_request(&cpuclk->req);
+
+ return ret;
+}
+
+static void __iomem *variable_pll_list_registers(struct clk *c, int n,
+ struct clk_register_data **regs, u32 *size)
+{
+ struct pll_clk *pll = to_pll_clk(c);
+ static struct clk_register_data data[] = {
+ {"MODE", 0x0},
+ {"L", 0x8},
+ {"ALPHA", 0x10},
+ {"USER_CTL", 0x18},
+ {"CONFIG_CTL_LO", 0x20},
+ {"CONFIG_CTL_HI", 0x24},
+ {"STATUS", 0x28},
+ };
+ if (n)
+ return ERR_PTR(-EINVAL);
+
+ *regs = data;
+ *size = ARRAY_SIZE(data);
+ return PLL_MODE(pll);
+}
+
+static const struct clk_ops clk_ops_cpu = {
+ .set_rate = a53_cpu_clk_set_rate,
+ .round_rate = a53_cpu_clk_round_rate,
+ .handoff = a53_cpu_clk_handoff,
+};
+
+static struct a53_cpu_clk a53_perf_clk = {
+ .cpu_reg_mask = 0x103,
+ .latency_lvl = {
+ .affinity_level = LPM_AFF_LVL_L2,
+ .reset_level = LPM_RESET_LVL_GDHS,
+ .level_name = "perf",
+ },
+ .cpu_latency_no_l2_pc_us = 280,
+ .c = {
+ .parent = &a53ssmux_perf.c,
+ .ops = &clk_ops_cpu,
+ .vdd_class = &vdd_cpu,
+ .dbg_name = "a53_perf_clk",
+ CLK_INIT(a53_perf_clk.c),
+ },
+};
+
+static struct a53_cpu_clk a53_pwr_clk = {
+ .cpu_reg_mask = 0x3,
+ .latency_lvl = {
+ .affinity_level = LPM_AFF_LVL_L2,
+ .reset_level = LPM_RESET_LVL_GDHS,
+ .level_name = "pwr",
+ },
+ .cpu_latency_no_l2_pc_us = 280,
+ .c = {
+ .parent = &a53ssmux_pwr.c,
+ .ops = &clk_ops_cpu,
+ .vdd_class = &vdd_cpu,
+ .dbg_name = "a53_pwr_clk",
+ CLK_INIT(a53_pwr_clk.c),
+ },
+};
+
+static struct a53_cpu_clk a53_cci_clk = {
+ .c = {
+ .parent = &a53ssmux_cci.c,
+ .ops = &clk_ops_cpu,
+ .vdd_class = &vdd_cpu,
+ .dbg_name = "a53_cci_clk",
+ CLK_INIT(a53_cci_clk.c),
+ },
+};
+
+static void __iomem *meas_base;
+
+static struct measure_clk apc0_m_clk = {
+ .c = {
+ .ops = &clk_ops_empty,
+ .dbg_name = "apc0_m_clk",
+ CLK_INIT(apc0_m_clk.c),
+ },
+};
+
+static struct measure_clk apc1_m_clk = {
+ .c = {
+ .ops = &clk_ops_empty,
+ .dbg_name = "apc1_m_clk",
+ CLK_INIT(apc1_m_clk.c),
+ },
+};
+
+static struct measure_clk cci_m_clk = {
+ .c = {
+ .ops = &clk_ops_empty,
+ .dbg_name = "cci_m_clk",
+ CLK_INIT(cci_m_clk.c),
+ },
+};
+
+static struct mux_clk cpu_debug_ter_mux = {
+ .ops = &mux_reg_ops,
+ .mask = 0x3,
+ .shift = 8,
+ MUX_SRC_LIST(
+ { &apc0_m_clk.c, 0},
+ { &apc1_m_clk.c, 1},
+ { &cci_m_clk.c, 2},
+ ),
+ .base = &meas_base,
+ .c = {
+ .dbg_name = "cpu_debug_ter_mux",
+ .ops = &clk_ops_gen_mux,
+ CLK_INIT(cpu_debug_ter_mux.c),
+ },
+};
+
+static struct mux_clk cpu_debug_sec_mux = {
+ .ops = &mux_reg_ops,
+ .mask = 0x7,
+ .shift = 12,
+ MUX_SRC_LIST(
+ { &cpu_debug_ter_mux.c, 0},
+ ),
+ MUX_REC_SRC_LIST(
+ &cpu_debug_ter_mux.c,
+ ),
+ .base = &meas_base,
+ .c = {
+ .dbg_name = "cpu_debug_sec_mux",
+ .ops = &clk_ops_gen_mux,
+ CLK_INIT(cpu_debug_sec_mux.c),
+ },
+};
+
+static struct mux_clk cpu_debug_pri_mux = {
+ .ops = &mux_reg_ops,
+ .mask = 0x3,
+ .shift = 16,
+ MUX_SRC_LIST(
+ { &cpu_debug_sec_mux.c, 0},
+ ),
+ MUX_REC_SRC_LIST(
+ &cpu_debug_sec_mux.c,
+ ),
+ .base = &meas_base,
+ .c = {
+ .dbg_name = "cpu_debug_pri_mux",
+ .ops = &clk_ops_gen_mux,
+ CLK_INIT(cpu_debug_pri_mux.c),
+ },
+};
+
+static struct clk_lookup a53_cpu_clocks[] = {
+ /* PLLs */
+ CLK_LIST(apcs_c0_pll),
+ CLK_LIST(apcs_c1_pll),
+ CLK_LIST(apcs_cci_pll),
+
+ /* Muxes */
+ CLK_LIST(a53ssmux_pwr),
+ CLK_LIST(a53ssmux_perf),
+ CLK_LIST(a53ssmux_cci),
+
+ /* CPU clocks */
+ CLK_LIST(a53_pwr_clk),
+ CLK_LIST(a53_perf_clk),
+ CLK_LIST(a53_cci_clk),
+
+ /* debug clocks */
+ CLK_LIST(apc0_m_clk),
+ CLK_LIST(apc1_m_clk),
+ CLK_LIST(cci_m_clk),
+ CLK_LIST(cpu_debug_pri_mux),
+};
+
+static struct pll_clk *a53sspll[] = { &apcs_c1_pll, &apcs_c0_pll };
+
+static struct mux_div_clk *a53ssmux[] = { &a53ssmux_perf, &a53ssmux_pwr,
+ &a53ssmux_cci };
+
+static struct a53_cpu_clk *cpuclk[] = { &a53_perf_clk, &a53_pwr_clk,
+ &a53_cci_clk };
+
+static struct clk *logical_cpu_to_clk(int cpu)
+{
+ struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
+ u32 reg;
+
+ if (cpu_node && !of_property_read_u32(cpu_node, "reg", ®)) {
+ if ((reg | a53_pwr_clk.cpu_reg_mask) ==
+ a53_pwr_clk.cpu_reg_mask)
+ return &a53_pwr_clk.c;
+ if ((reg | a53_perf_clk.cpu_reg_mask) ==
+ a53_perf_clk.cpu_reg_mask)
+ return &a53_perf_clk.c;
+ }
+
+ return NULL;
+}
+
+static int of_get_fmax_vdd_class(struct platform_device *pdev, struct clk *c,
+ char *prop_name)
+{
+ struct device_node *of = pdev->dev.of_node;
+ int prop_len, i;
+ struct clk_vdd_class *vdd = c->vdd_class;
+ u32 *array;
+
+ if (!of_find_property(of, prop_name, &prop_len)) {
+ dev_err(&pdev->dev, "missing %s\n", prop_name);
+ return -EINVAL;
+ }
+
+ prop_len /= sizeof(u32);
+ if (prop_len % 2) {
+ dev_err(&pdev->dev, "bad length %d\n", prop_len);
+ return -EINVAL;
+ }
+
+ prop_len /= 2;
+ vdd->level_votes = devm_kzalloc(&pdev->dev,
+ prop_len * sizeof(*vdd->level_votes),
+ GFP_KERNEL);
+ if (!vdd->level_votes)
+ return -ENOMEM;
+
+ vdd->vdd_uv = devm_kzalloc(&pdev->dev, prop_len * sizeof(int),
+ GFP_KERNEL);
+ if (!vdd->vdd_uv)
+ return -ENOMEM;
+
+ c->fmax = devm_kzalloc(&pdev->dev, prop_len * sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!c->fmax)
+ return -ENOMEM;
+
+ array = devm_kzalloc(&pdev->dev,
+ prop_len * sizeof(u32) * 2, GFP_KERNEL);
+ if (!array)
+ return -ENOMEM;
+
+ of_property_read_u32_array(of, prop_name, array, prop_len * 2);
+ for (i = 0; i < prop_len; i++) {
+ c->fmax[i] = array[2 * i];
+ vdd->vdd_uv[i] = array[2 * i + 1];
+ }
+
+ devm_kfree(&pdev->dev, array);
+ vdd->num_levels = prop_len;
+ vdd->cur_level = prop_len;
+ vdd->use_max_uV = true;
+ c->num_fmax = prop_len;
+ return 0;
+}
+
+static void get_speed_bin(struct platform_device *pdev, int *bin,
+ int *version)
+{
+ struct resource *res;
+ void __iomem *base;
+ u32 pte_efuse;
+
+ *bin = 0;
+ *version = 0;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse");
+ if (!res) {
+ dev_info(&pdev->dev,
+ "No speed/PVS binning available. Defaulting to 0!\n");
+ return;
+ }
+
+ base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!base) {
+ dev_warn(&pdev->dev,
+ "Unable to read efuse data. Defaulting to 0!\n");
+ return;
+ }
+
+ pte_efuse = readl_relaxed(base);
+ devm_iounmap(&pdev->dev, base);
+
+ *bin = (pte_efuse >> 8) & 0x7;
+
+ dev_info(&pdev->dev, "Speed bin: %d PVS Version: %d\n", *bin,
+ *version);
+}
+
+static int cpu_parse_pll_data(struct platform_device *pdev, int pll_count)
+{
+ int pll_num;
+ struct resource *res;
+ struct clk *c;
+ char pll_name[] = "apcs-xxx-pll-base";
+
+ for (pll_num = 0; pll_num < pll_count; pll_num++) {
+ snprintf(pll_name, ARRAY_SIZE(pll_name), "apcs-%s-pll-base",
+ pll_names[pll_num]);
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, pll_name);
+ if (!res) {
+ dev_err(&pdev->dev, "missing %s\n", pll_name);
+ return -EINVAL;
+ }
+
+ if (pll_num < APCS_CCI_PLL_BASE) {
+ a53sspll[pll_num]->base = devm_ioremap(&pdev->dev,
+ res->start, resource_size(res));
+ if (!a53sspll[pll_num]->base) {
+ dev_err(&pdev->dev, "ioremap failed for %s\n",
+ pll_name);
+ return -ENOMEM;
+ }
+ } else {
+ apcs_cci_pll.base = devm_ioremap(&pdev->dev,
+ res->start, resource_size(res));
+ if (!apcs_cci_pll.base) {
+ dev_err(&pdev->dev, "ioremap failed for %s\n",
+ pll_name);
+ return -ENOMEM;
+ }
+ }
+ }
+
+ c = devm_clk_get(&pdev->dev, "xo_a");
+ if (IS_ERR(c)) {
+ if (PTR_ERR(c) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Unable to get xo clock\n");
+ return PTR_ERR(c);
+ }
+ xo_a_clk.c.parent = c;
+
+ return 0;
+}
+
+static int cpu_parse_devicetree(struct platform_device *pdev, int mux_id)
+{
+ struct resource *res;
+ char rcg_name[] = "apcs-xxx-rcg-base";
+ char vdd_name[] = "vdd-xxx";
+ struct regulator *regulator;
+
+ snprintf(rcg_name, ARRAY_SIZE(rcg_name), "apcs-%s-rcg-base",
+ mux_names[mux_id]);
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, rcg_name);
+ if (!res) {
+ dev_err(&pdev->dev, "missing %s\n", rcg_name);
+ return -EINVAL;
+ }
+
+ a53ssmux[mux_id]->base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!a53ssmux[mux_id]->base) {
+ dev_err(&pdev->dev, "ioremap failed for %s\n", rcg_name);
+ return -ENOMEM;
+ }
+
+ snprintf(vdd_name, ARRAY_SIZE(vdd_name), "vdd-%s", mux_names[mux_id]);
+ regulator = devm_regulator_get(&pdev->dev, vdd_name);
+ if (IS_ERR(regulator)) {
+ if (PTR_ERR(regulator) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "unable to get regulator\n");
+ return PTR_ERR(regulator);
+ }
+
+ cpuclk[mux_id]->c.vdd_class->regulator[0] = regulator;
+
+ return 0;
+}
+
+static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev,
+ unsigned long max_rate)
+{
+ unsigned long rate = 0;
+ int level;
+ long ret, uv, corner;
+ int j = 1;
+
+ while (1) {
+ rate = c->fmax[j++];
+
+ level = find_vdd_level(c, rate);
+ if (level <= 0) {
+ pr_warn("clock-cpu: no vdd level for %lu.\n", rate);
+ return -EINVAL;
+ }
+
+ corner = c->vdd_class->vdd_uv[level];
+ if (corner < 0)
+ return -EINVAL;
+
+ /* Get actual voltage corresponding to each corner */
+ uv = regulator_list_corner_voltage(c->vdd_class->regulator[0],
+ corner);
+ if (uv < 0) {
+ pr_warn("%s: no uv for corner %ld - err: %ld\n",
+ c->dbg_name, corner, uv);
+ return uv;
+ }
+
+ /*
+ * Populate both CPU and regulator devices with the
+ * freq-to-corner OPP table to maintain backward
+ * compatibility.
+ */
+ ret = dev_pm_opp_add(cpudev, rate, uv);
+ if (ret) {
+ pr_warn("clock-cpu: couldn't add OPP for %lu\n",
+ rate);
+ return ret;
+ }
+
+ ret = dev_pm_opp_add(vregdev, rate, uv);
+ if (ret) {
+ pr_warn("clock-cpu: couldn't add OPP for %lu\n",
+ rate);
+ return ret;
+ }
+
+ if (rate >= max_rate)
+ break;
+ }
+
+ return 0;
+}
+
+static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu)
+{
+ struct dev_pm_opp *oppfmax, *oppfmin;
+ unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin;
+
+ apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
+ apc0_fmin = a53_pwr_clk.c.fmax[1];
+ apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
+ apc1_fmin = a53_perf_clk.c.fmax[1];
+
+ rcu_read_lock();
+ oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu),
+ apc0_fmax, true);
+ oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu),
+ apc0_fmin, true);
+ /*
+ * One time information during boot. Important to know that this
+ * looks sane since it can eventually make its way to the
+ * scheduler.
+ */
+ pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n",
+ apc0_fmin, dev_pm_opp_get_voltage(oppfmin));
+ pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n",
+ apc0_fmax, dev_pm_opp_get_voltage(oppfmax));
+
+ oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu),
+ apc1_fmax, true);
+ oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu),
+ apc1_fmin, true);
+ pr_info("clock_cpu: a53_c1: OPP voltage for %lu: %lu\n", apc1_fmin,
+ dev_pm_opp_get_voltage(oppfmin));
+ pr_info("clock_cpu: a53_c1: OPP voltage for %lu: %lu\n", apc1_fmax,
+ dev_pm_opp_get_voltage(oppfmax));
+ rcu_read_unlock();
+}
+
+static void populate_opp_table(struct platform_device *pdev)
+{
+ struct platform_device *apc0_dev, *apc1_dev;
+ struct device_node *apc0_node = NULL, *apc1_node;
+ unsigned long apc0_fmax, apc1_fmax;
+ int cpu, a53_c0_cpu = 0, a53_c1_cpu = 0;
+
+ apc0_node = of_parse_phandle(pdev->dev.of_node,
+ "vdd-c0-supply", 0);
+ if (!apc0_node) {
+ pr_err("can't find the apc0 dt node.\n");
+ return;
+ }
+
+ apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0);
+ if (!apc1_node) {
+ pr_err("can't find the apc1 dt node.\n");
+ return;
+ }
+
+ apc0_dev = of_find_device_by_node(apc0_node);
+ if (!apc0_dev) {
+ pr_err("can't find the apc0 device node.\n");
+ return;
+ }
+
+ apc1_dev = of_find_device_by_node(apc1_node);
+ if (!apc1_dev) {
+ pr_err("can't find the apc1 device node.\n");
+ return;
+ }
+
+ apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
+
+ apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
+
+ for_each_possible_cpu(cpu) {
+ if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c) {
+ a53_c0_cpu = cpu;
+ WARN(add_opp(&a53_pwr_clk.c, get_cpu_device(cpu),
+ &apc0_dev->dev, apc0_fmax),
+ "Failed to add OPP levels for %d\n", cpu);
+ }
+ if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c) {
+ a53_c1_cpu = cpu;
+ WARN(add_opp(&a53_perf_clk.c, get_cpu_device(cpu),
+ &apc1_dev->dev, apc1_fmax),
+ "Failed to add OPP levels for %d\n", cpu);
+ }
+ }
+ /* One time print during bootup */
+ pr_info("clock-cpu: OPP tables populated (cpu %d and %d)",
+ a53_c0_cpu, a53_c1_cpu);
+
+ print_opp_table(a53_c0_cpu, a53_c1_cpu);
+
+}
+
+static int clock_sdm632_pm_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ switch (event) {
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ clk_unprepare(&a53_pwr_clk.c);
+ clk_unprepare(&a53_perf_clk.c);
+ clk_unprepare(&a53_cci_clk.c);
+ break;
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ clk_prepare(&a53_pwr_clk.c);
+ clk_prepare(&a53_perf_clk.c);
+ clk_prepare(&a53_cci_clk.c);
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block clock_sdm632_pm_notifier = {
+ .notifier_call = clock_sdm632_pm_event,
+};
+
+/**
+ * clock_panic_callback() - panic notification callback function.
+ * This function is invoked when a kernel panic occurs.
+ * @nfb: Notifier block pointer
+ * @event: Value passed unmodified to notifier function
+ * @data: Pointer passed unmodified to notifier function
+ *
+ * Return: NOTIFY_OK
+ */
+static int clock_panic_callback(struct notifier_block *nfb,
+ unsigned long event, void *data)
+{
+ unsigned long rate;
+
+ rate = (a53_perf_clk.c.count) ? a53_perf_clk.c.rate : 0;
+ pr_err("%s frequency: %10lu Hz\n", a53_perf_clk.c.dbg_name, rate);
+
+ rate = (a53_pwr_clk.c.count) ? a53_pwr_clk.c.rate : 0;
+ pr_err("%s frequency: %10lu Hz\n", a53_pwr_clk.c.dbg_name, rate);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block clock_panic_notifier = {
+ .notifier_call = clock_panic_callback,
+ .priority = 1,
+};
+
+/* Configure PLL at Nominal frequency */
+static unsigned long pwrcl_early_boot_rate = 1363200000;
+static unsigned long perfcl_early_boot_rate = 1401600000;
+static unsigned long cci_early_boot_rate = 691200000;
+
+static int clock_a53_probe(struct platform_device *pdev)
+{
+ int speed_bin, version, rc, cpu, mux_id;
+ char prop_name[] = "qcom,speedX-bin-vX-XXX";
+ int mux_num = A53SS_MUX_NUM;
+
+ get_speed_bin(pdev, &speed_bin, &version);
+
+ rc = cpu_parse_pll_data(pdev, N_PLL_BASES);
+ if (rc)
+ return rc;
+
+ /* PLL core logic */
+ vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd-mx");
+ if (IS_ERR(vdd_mx.regulator[0])) {
+ dev_err(&pdev->dev, "Get vdd-mx regulator!!!\n");
+ if (PTR_ERR(vdd_mx.regulator[0]) != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "Unable to get vdd-mx regulator!!!\n");
+ return PTR_ERR(vdd_mx.regulator[0]);
+ }
+
+ for (mux_id = 0; mux_id < mux_num; mux_id++) {
+ rc = cpu_parse_devicetree(pdev, mux_id);
+ if (rc)
+ return rc;
+
+ snprintf(prop_name, ARRAY_SIZE(prop_name),
+ "qcom,speed%d-bin-v%d-%s",
+ speed_bin, version, mux_names[mux_id]);
+
+ rc = of_get_fmax_vdd_class(pdev, &cpuclk[mux_id]->c,
+ prop_name);
+ if (rc) {
+ /* Fall back to most conservative PVS table */
+ dev_err(&pdev->dev, "Unable to load voltage plan %s!\n",
+ prop_name);
+
+ snprintf(prop_name, ARRAY_SIZE(prop_name),
+ "qcom,speed0-bin-v0-%s", mux_names[mux_id]);
+ rc = of_get_fmax_vdd_class(pdev, &cpuclk[mux_id]->c,
+ prop_name);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to load safe voltage plan\n");
+ return rc;
+ }
+ dev_info(&pdev->dev, "Safe voltage plan loaded.\n");
+ }
+ }
+
+ /* Debug MUX */
+ meas_base = devm_ioremap(&pdev->dev, GLB_DIAG, SZ_8);
+ if (!meas_base) {
+ dev_err(&pdev->dev, "Failed to ioremap GLB_DIAG registers\n");
+ return -ENOMEM;
+ }
+
+ rc = of_msm_clock_register(pdev->dev.of_node, a53_cpu_clocks,
+ ARRAY_SIZE(a53_cpu_clocks));
+
+ if (rc) {
+ dev_err(&pdev->dev, "msm_clock_register failed\n");
+ return rc;
+ }
+
+ /* Force to move to PLL configuartion */
+ rc = clk_set_rate(&a53_cci_clk.c, cci_early_boot_rate);
+ if (rc)
+ dev_err(&pdev->dev, "Can't set CCI PLL rate for CCI\n");
+
+ rc = clk_set_rate(&a53_pwr_clk.c, pwrcl_early_boot_rate);
+ if (rc)
+ dev_err(&pdev->dev, "Can't set pwr PLL rate for Cluster-0 %ld\n",
+ pwrcl_early_boot_rate);
+
+ rc = clk_set_rate(&a53_perf_clk.c, perfcl_early_boot_rate);
+ if (rc)
+ dev_err(&pdev->dev, "Can't set perf PLL rate for Cluster-1 %ld\n",
+ perfcl_early_boot_rate);
+
+ rc = clock_rcgwr_init(pdev);
+ if (rc)
+ dev_err(&pdev->dev, "Failed to init RCGwR\n");
+
+ /*
+ * We don't want the CPU clocks to be turned off at late init
+ * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
+ * refcount of these clocks. Any cpufreq/hotplug manager can assume
+ * that the clocks have already been prepared and enabled by the time
+ * they take over.
+ */
+ get_online_cpus();
+ for_each_online_cpu(cpu) {
+ WARN(clk_prepare_enable(&cpuclk[cpu/4]->c),
+ "Unable to turn on CPU clock");
+ WARN(clk_prepare_enable(&a53_cci_clk.c),
+ "Unable to turn on CCI clock");
+ }
+ put_online_cpus();
+
+ for_each_possible_cpu(cpu) {
+ if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c)
+ cpumask_set_cpu(cpu, &a53_perf_clk.cpumask);
+ if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c)
+ cpumask_set_cpu(cpu, &a53_pwr_clk.cpumask);
+ }
+
+ a53_pwr_clk.hw_low_power_ctrl = true;
+ a53_perf_clk.hw_low_power_ctrl = true;
+
+ register_pm_notifier(&clock_sdm632_pm_notifier);
+
+ populate_opp_table(pdev);
+
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &clock_panic_notifier);
+
+ return 0;
+}
+
+static const struct of_device_id clock_a53_match_table[] = {
+ {.compatible = "qcom,cpu-clock-sdm632"},
+ {}
+};
+
+static struct platform_driver clock_a53_driver = {
+ .probe = clock_a53_probe,
+ .driver = {
+ .name = "cpu-clock-sdm632",
+ .of_match_table = clock_a53_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init clock_a53_init(void)
+{
+ return platform_driver_register(&clock_a53_driver);
+}
+arch_initcall(clock_a53_init);
+
+static int __init clock_cpu_lpm_get_latency(void)
+{
+ int rc = 0;
+ struct device_node *ofnode = of_find_compatible_node(NULL, NULL,
+ "qcom,cpu-clock-sdm632");
+
+ if (!ofnode)
+ return 0;
+
+ rc = lpm_get_latency(&a53_perf_clk.latency_lvl,
+ &a53_perf_clk.cpu_latency_no_l2_pc_us);
+ if (rc < 0)
+ pr_err("Failed to get the L2 PC value for perf\n");
+
+ rc = lpm_get_latency(&a53_pwr_clk.latency_lvl,
+ &a53_pwr_clk.cpu_latency_no_l2_pc_us);
+ if (rc < 0)
+ pr_err("Failed to get the L2 PC value for pwr\n");
+
+ pr_debug("Latency for pwr/perf cluster %d : %d\n",
+ a53_pwr_clk.cpu_latency_no_l2_pc_us,
+ a53_perf_clk.cpu_latency_no_l2_pc_us);
+
+ return rc;
+}
+late_initcall(clock_cpu_lpm_get_latency);
+
+#define PWR_PLL_BASE 0xb116000
+#define PERF_PLL_BASE 0xb016000
+#define CCI_PLL_BASE 0xb1d0000
+#define APCS_ALIAS1_CMD_RCGR 0xb011050
+#define APCS_ALIAS1_CFG_OFF 0x4
+#define APCS_ALIAS1_CORE_CBCR_OFF 0x8
+#define SRC_SEL 0x4
+#define SRC_DIV 0x1
+
+static int __init cpu_clock_init(void)
+{
+ void __iomem *base;
+ int regval = 0, count;
+ struct device_node *ofnode = of_find_compatible_node(NULL, NULL,
+ "qcom,cpu-clock-sdm632");
+ if (!ofnode)
+ return 0;
+
+ virt_bases[APCS_C0_PLL_BASE] = ioremap_nocache(PWR_PLL_BASE, SZ_1K);
+ virt_bases[APCS_C1_PLL_BASE] = ioremap_nocache(PERF_PLL_BASE, SZ_1K);
+ virt_bases[APCS_CCI_PLL_BASE] = ioremap_nocache(CCI_PLL_BASE, SZ_1K);
+ clk_ops_variable_rate = clk_ops_variable_rate_pll_hwfsm;
+ clk_ops_variable_rate.list_registers = variable_pll_list_registers;
+
+ /* Initialize the PLLs */
+ __variable_rate_pll_init(&apcs_c0_pll.c);
+ __variable_rate_pll_init(&apcs_c1_pll.c);
+ __init_alpha_pll(&apcs_cci_pll.c);
+
+ /* Enable the PLLs */
+ apcs_c0_pll.c.ops->set_rate(&apcs_c0_pll.c, pwrcl_early_boot_rate);
+ clk_ops_variable_rate_pll.enable(&apcs_c0_pll.c);
+
+ apcs_c1_pll.c.ops->set_rate(&apcs_c1_pll.c, perfcl_early_boot_rate);
+ clk_ops_variable_rate_pll.enable(&apcs_c1_pll.c);
+
+ apcs_cci_pll.c.ops->set_rate(&apcs_cci_pll.c, cci_early_boot_rate);
+ clk_ops_dyna_alpha_pll.enable(&apcs_cci_pll.c);
+
+ base = ioremap_nocache(APCS_ALIAS1_CMD_RCGR, SZ_8);
+ regval = readl_relaxed(base);
+
+ /* Source from GPLL0 */
+ regval = (SRC_SEL << 8) | SRC_DIV; /* 0x401 */
+ writel_relaxed(regval, base + APCS_ALIAS1_CFG_OFF);
+ /* Make sure src sel and src div is set before update bit */
+ mb();
+
+ /* update bit */
+ regval = readl_relaxed(base);
+ regval |= BIT(0);
+ writel_relaxed(regval, base);
+ /* Make sure src sel and src div is set before update bit */
+ mb();
+
+ /* Wait for update to take effect */
+ for (count = 500; count > 0; count--) {
+ if (!(readl_relaxed(base)) & BIT(0))
+ break;
+ udelay(1);
+ }
+
+ /* Enable the branch */
+ regval = readl_relaxed(base + APCS_ALIAS1_CORE_CBCR_OFF);
+ regval |= BIT(0);
+ writel_relaxed(regval, base + APCS_ALIAS1_CORE_CBCR_OFF);
+
+ /* Branch enable should be complete */
+ mb();
+ iounmap(base);
+
+ pr_info("CPU clocks configured\n");
+
+ return 0;
+}
+early_initcall(cpu_clock_init);
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
index c5d12e5..20b8e34 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
@@ -485,7 +485,8 @@
struct dsi_pll_input *pin = &pdb->in;
struct dsi_pll_output *pout = &pdb->out;
s64 multiplier = BIT(20);
- s64 dec_start_multiple, dec_start, pll_comp_val;
+ s64 dec_start_multiple, dec_start;
+ u64 pll_comp_val;
s32 duration, div_frac_start;
s64 vco_clk_rate = pll->vco_current_rate;
s64 fref = pll->vco_ref_clk_rate;
@@ -560,8 +561,8 @@
{
struct dsi_pll_input *pin = &pdb->in;
struct dsi_pll_output *pout = &pdb->out;
- s64 data;
- u32 cnt;
+ u64 data;
+ u64 cnt;
data = fref * pin->vco_measure_time;
do_div(data, 1000000);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 87d067a..79739bc 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -252,4 +252,13 @@
Say Y if you want to support CPU clock scaling using
CPUfreq drivers for dyanmic power management.
+config MDM_DEBUGCC_SDXPOORWILLS
+ tristate "SDXPOORWILLS Debug Clock Controller"
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the debug clock controller on sdxpoorwills
+ based devices.
+ Say Y if you want to support the clock measurement
+ functionality.
+
source "drivers/clk/qcom/mdss/Kconfig"
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 8cb46a7..0cd2e94 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -23,6 +23,7 @@
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
obj-$(CONFIG_MDM_CLOCK_CPU_SDXPOORWILLS) += clk-cpu-a7.o
+obj-$(CONFIG_MDM_DEBUGCC_SDXPOORWILLS) += debugcc-sdxpoorwills.o
obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
obj-$(CONFIG_MDM_GCC_SDXPOORWILLS) += gcc-sdxpoorwills.o
obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
diff --git a/drivers/clk/qcom/clk-debug.h b/drivers/clk/qcom/clk-debug.h
index aa8d97b..a9f71b4 100644
--- a/drivers/clk/qcom/clk-debug.h
+++ b/drivers/clk/qcom/clk-debug.h
@@ -44,6 +44,7 @@
GPU_CC,
VIDEO_CC,
CPU,
+ MAX_NUM_CC,
};
/**
diff --git a/drivers/clk/qcom/debugcc-sdxpoorwills.c b/drivers/clk/qcom/debugcc-sdxpoorwills.c
new file mode 100644
index 0000000..d66a623
--- /dev/null
+++ b/drivers/clk/qcom/debugcc-sdxpoorwills.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2017-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 <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-debug.h"
+
+static struct measure_clk_data debug_mux_priv = {
+ .ctl_reg = 0x79004,
+ .status_reg = 0x79008,
+ .xo_div4_cbcr = 0x22008,
+};
+
+static const char *const debug_mux_parent_names[] = {
+ "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_phy_refgen_clk",
+ "gcc_pcie_pipe_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_prng_ahb_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_sys_noc_usb3_clk",
+ "gcc_usb30_master_clk",
+ "gcc_usb30_mock_utmi_clk",
+ "gcc_usb30_sleep_clk",
+ "gcc_usb3_phy_aux_clk",
+ "gcc_usb3_phy_pipe_clk",
+ "gcc_usb_phy_cfg_ahb2phy_clk",
+ "gcc_xo_div4_clk",
+ "measure_only_ipa_2x_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_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_phy_refgen_clk", 0x104, 4, GCC,
+ 0x104, 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_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_prng_ahb_clk", 0x49, 4, GCC,
+ 0x49, 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_sys_noc_usb3_clk", 0xB, 4, GCC,
+ 0xB, 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_sleep_clk", 0x29, 4, GCC,
+ 0x29, 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 },
+ { "measure_only_ipa_2x_clk", 0xAC, 4, GCC,
+ 0xAC, 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-sdxpoorwills" },
+ { }
+};
+
+static int clk_debug_sdxpoorwills_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;
+
+ if (!of_get_property(pdev->dev.of_node, "qcom,gcc", NULL))
+ return -ENODEV;
+
+ gcc_debug_mux.regmap[GCC] =
+ syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "qcom,gcc");
+ if (IS_ERR(gcc_debug_mux.regmap[GCC])) {
+ pr_err("Failed to map qcom,gcc\n");
+ return PTR_ERR(gcc_debug_mux.regmap[GCC]);
+ }
+
+ 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_sdxpoorwills_probe,
+ .driver = {
+ .name = "debugcc-sdxpoorwills",
+ .of_match_table = clk_debug_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init clk_debug_sdxpoorwills_init(void)
+{
+ return platform_driver_register(&clk_debug_driver);
+}
+fs_initcall(clk_debug_sdxpoorwills_init);
+
+MODULE_DESCRIPTION("QTI DEBUG CC SDXPOORWILLS Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:debugcc-sdxpoorwills");
diff --git a/drivers/clk/qcom/gcc-sdxpoorwills.c b/drivers/clk/qcom/gcc-sdxpoorwills.c
index c6e8faa..2fb2e34 100644
--- a/drivers/clk/qcom/gcc-sdxpoorwills.c
+++ b/drivers/clk/qcom/gcc-sdxpoorwills.c
@@ -1711,6 +1711,19 @@
},
};
+/* Measure-only clock for gcc_ipa_2x_clk. */
+static struct clk_dummy measure_only_ipa_2x_clk = {
+ .rrate = 1000,
+ .hw.init = &(struct clk_init_data){
+ .name = "measure_only_ipa_2x_clk",
+ .ops = &clk_dummy_ops,
+ },
+};
+
+static struct clk_hw *gcc_sdxpoorwills_hws[] = {
+ [MEASURE_ONLY_IPA_2X_CLK] = &measure_only_ipa_2x_clk.hw,
+};
+
static struct clk_regmap *gcc_sdxpoorwills_clocks[] = {
[GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
[GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
@@ -1854,7 +1867,8 @@
static int gcc_sdxpoorwills_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int i, ret = 0;
+ struct clk *clk;
struct regmap *regmap;
regmap = qcom_cc_map(pdev, &gcc_sdxpoorwills_desc);
@@ -1869,6 +1883,13 @@
return PTR_ERR(vdd_cx.regulator[0]);
}
+ /* Register the dummy measurement clocks */
+ for (i = 0; i < ARRAY_SIZE(gcc_sdxpoorwills_hws); i++) {
+ clk = devm_clk_register(&pdev->dev, gcc_sdxpoorwills_hws[i]);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ }
+
ret = qcom_cc_really_probe(pdev, &gcc_sdxpoorwills_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register GCC clocks\n");
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index 7290205..874c229 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -925,6 +925,11 @@
if (!vco->priv)
pr_err("vco priv is null\n");
+ if (!pll) {
+ pr_err("pll is null\n");
+ return 0;
+ }
+
/*
* Calculate the vco rate from HW registers only for handoff cases.
* For other cases where a vco_10nm_set_rate() has already been
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 1b2574c..b167cc6 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,7 @@
#include <linux/of_irq.h>
#include <linux/clk.h>
#include <linux/reset.h>
+#include <linux/slab.h>
#define TIM_CR1 0x00
#define TIM_DIER 0x0c
@@ -106,6 +107,10 @@
unsigned long rate, max_delta;
int irq, ret, bits, prescaler = 1;
+ data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
clk = of_clk_get(np, 0);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
@@ -156,8 +161,8 @@
writel_relaxed(prescaler - 1, data->base + TIM_PSC);
writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
- writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
writel_relaxed(0, data->base + TIM_SR);
+ writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
@@ -184,6 +189,7 @@
err_clk_enable:
clk_put(clk);
err_clk_get:
+ kfree(data);
return ret;
}
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 98468b9..2ca101a 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -228,12 +228,16 @@
* without any error (HW optimizations for later
* CAAM eras), then try again.
*/
- rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
- if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
- !(rdsta_val & (1 << sh_idx)))
- ret = -EAGAIN;
if (ret)
break;
+
+ rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
+ if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
+ !(rdsta_val & (1 << sh_idx))) {
+ ret = -EAGAIN;
+ break;
+ }
+
dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
/* Clear the contents before recreating the descriptor */
memset(desc, 0x00, CAAM_CMD_SZ * 7);
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index e0bd578..ebe72a4 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -339,7 +339,7 @@
{
struct dmatest_done *done = arg;
struct dmatest_thread *thread =
- container_of(arg, struct dmatest_thread, done_wait);
+ container_of(done, struct dmatest_thread, test_done);
if (!thread->done) {
done->done = true;
wake_up_all(done->wait);
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c
index cda6dab..6b65a10 100644
--- a/drivers/edac/octeon_edac-lmc.c
+++ b/drivers/edac/octeon_edac-lmc.c
@@ -79,6 +79,7 @@
if (!pvt->inject)
int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx));
else {
+ int_reg.u64 = 0;
if (pvt->error_type == 1)
int_reg.s.sec_err = 1;
if (pvt->error_type == 2)
diff --git a/drivers/gpu/drm/bridge/lt9611.c b/drivers/gpu/drm/bridge/lt9611.c
index 4327e93..887dd6f 100644
--- a/drivers/gpu/drm/bridge/lt9611.c
+++ b/drivers/gpu/drm/bridge/lt9611.c
@@ -708,15 +708,24 @@
u32 h_act = 0;
struct lt9611_reg_cfg reg_cfg[] = {
{0xff, 0x83, 0},
+ {0x0b, 0x01, 0},
+ {0x0c, 0x10, 0},
+ {0x48, 0x00, 0},
+ {0x49, 0x81, 0},
- {0x2d, 0x38, 0}, /* up_lmt */
- {0x2e, 0x00, 0},
- {0x31, 0x10, 0}, /* low lmt */
- {0x32, 0x00, 0},
+ /* stage 1 */
+ {0x21, 0x4a, 0},
+ {0x24, 0x71, 0},
+ {0x25, 0x30, 0},
+ {0x2a, 0x01, 0},
- {0xff, 0x80, 0},
- {0x11, 0x5a, 0}, /* pcr reset */
- {0x11, 0xfa, 0},
+ /* stage 2 */
+ {0x4a, 0x40, 0},
+ {0x1d, 0x10, 0},
+
+ /* MK limit */
+ {0x2d, 0x38, 0},
+ {0x31, 0x08, 0},
};
if (!pdata || !cfg) {
@@ -724,54 +733,31 @@
return -EINVAL;
}
+ lt9611_write_array(pdata, reg_cfg, sizeof(reg_cfg));
+
h_act = cfg->h_active;
if (h_act == 1920) {
- lt9611_write(pdata, 0xff, 0x83);
- lt9611_write(pdata, 0x48, 0x00);
- lt9611_write(pdata, 0x49, 0x81);
-
- lt9611_write(pdata, 0x4a, 0x10);
- lt9611_write(pdata, 0x1d, 0x10);
- lt9611_write(pdata, 0x21, 0x41);
- lt9611_write(pdata, 0x22, 0x40);
- lt9611_write(pdata, 0x24, 0x11);
- lt9611_write(pdata, 0x25, 0x30);
lt9611_write(pdata, 0x26, 0x37);
- lt9611_write(pdata, 0x2a, 0x02);
} else if (h_act == 3840) {
- lt9611_write(pdata, 0xff, 0x83);
lt9611_write(pdata, 0x0b, 0x03);
lt9611_write(pdata, 0x0c, 0xd0);
lt9611_write(pdata, 0x48, 0x03);
- lt9611_write(pdata, 0x49, 0xd0);
-
- lt9611_write(pdata, 0x4a, 0x01);
- lt9611_write(pdata, 0x1d, 0x10);
- lt9611_write(pdata, 0x21, 0x41);
- lt9611_write(pdata, 0x22, 0x40);
- lt9611_write(pdata, 0x24, 0x70);
- lt9611_write(pdata, 0x25, 0x50);
- lt9611_write(pdata, 0x26, 0x37);
- lt9611_write(pdata, 0x2a, 0x03);
- } else if (h_act == 640) {
- lt9611_write(pdata, 0xff, 0x83);
- lt9611_write(pdata, 0x0b, 0x01);
- lt9611_write(pdata, 0x0c, 0x20);
- lt9611_write(pdata, 0x48, 0x00);
- lt9611_write(pdata, 0x49, 0x81);
-
+ lt9611_write(pdata, 0x49, 0xe0);
+ lt9611_write(pdata, 0x24, 0x72);
+ lt9611_write(pdata, 0x25, 0x00);
+ lt9611_write(pdata, 0x2a, 0x01);
lt9611_write(pdata, 0x4a, 0x10);
lt9611_write(pdata, 0x1d, 0x10);
- lt9611_write(pdata, 0x21, 0x41);
- lt9611_write(pdata, 0x22, 0x40);
- lt9611_write(pdata, 0x24, 0x11);
- lt9611_write(pdata, 0x25, 0x30);
- lt9611_write(pdata, 0x26, 0x13);
- lt9611_write(pdata, 0x2a, 0x03);
+ lt9611_write(pdata, 0x26, 0x37);
+ } else if (h_act == 640) {
+ lt9611_write(pdata, 0x26, 0x14);
}
- lt9611_write_array(pdata, reg_cfg, sizeof(reg_cfg));
+ /* pcr rst */
+ lt9611_write(pdata, 0xff, 0x80);
+ lt9611_write(pdata, 0x11, 0x5a);
+ lt9611_write(pdata, 0x11, 0xfa);
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 7fdc42e..74163a9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5063,6 +5063,12 @@
*/
final->t8 = 1;
final->t9 = 1;
+
+ /*
+ * HW has only a 100msec granularity for t11_t12 so round it up
+ * accordingly.
+ */
+ final->t11_t12 = roundup(final->t11_t12, 100 * 10);
}
static void
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index b834230..7c817d3 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -184,7 +184,12 @@
bridge = to_dp_bridge(drm_bridge);
dp = bridge->display;
- if (dp && dp->connector)
+ if (!dp) {
+ pr_err("dp is null\n");
+ return;
+ }
+
+ if (dp->connector)
sde_connector_helper_bridge_disable(dp->connector);
rc = dp->pre_disable(dp);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index ff2c9ce..1682e61 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -323,8 +323,7 @@
if (!display)
return IRQ_HANDLED;
- atomic_set(&display->te_irq_triggered, 1);
-
+ complete_all(&display->esd_te_gate);
return IRQ_HANDLED;
}
@@ -338,12 +337,10 @@
/* Handle unbalanced irq enable/disbale calls */
if (enable && !display->is_te_irq_enabled) {
- atomic_set(&display->te_irq_triggered, 1);
enable_irq(gpio_to_irq(display->disp_te_gpio));
display->is_te_irq_enabled = true;
} else if (!enable && display->is_te_irq_enabled) {
disable_irq(gpio_to_irq(display->disp_te_gpio));
- atomic_set(&display->te_irq_triggered, 0);
display->is_te_irq_enabled = false;
}
}
@@ -374,6 +371,8 @@
return;
}
+ init_completion(&display->esd_te_gate);
+
disable_irq(gpio_to_irq(display->disp_te_gpio));
display->is_te_irq_enabled = false;
}
@@ -673,16 +672,21 @@
static int dsi_display_status_check_te(struct dsi_display *display)
{
- int const esd_check_success = 1;
+ int rc = 1;
+ int const esd_te_timeout = msecs_to_jiffies(3*20);
- if (atomic_read(&display->te_irq_triggered)) {
- atomic_set(&display->te_irq_triggered, 0);
- } else {
+ dsi_display_change_te_irq_status(display, true);
+
+ reinit_completion(&display->esd_te_gate);
+ if (!wait_for_completion_timeout(&display->esd_te_gate,
+ esd_te_timeout)) {
pr_err("ESD check failed\n");
- return -EINVAL;
+ rc = -EINVAL;
}
- return esd_check_success;
+ dsi_display_change_te_irq_status(display, false);
+
+ return rc;
}
int dsi_display_check_status(void *display)
@@ -5454,9 +5458,6 @@
mode = display->panel->cur_mode;
- if (dsi_display_is_te_based_esd(display))
- dsi_display_change_te_irq_status(display, true);
-
if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
if (display->is_cont_splash_enabled) {
pr_err("DMS is not supposed to be set on first frame\n");
@@ -5984,10 +5985,6 @@
pr_err("[%s] display wake up failed, rc=%d\n",
display->name, rc);
- /* Disable panel TE irq */
- if (dsi_display_is_te_based_esd(display))
- dsi_display_change_te_irq_status(display, false);
-
rc = dsi_panel_unprepare(display->panel);
if (rc)
pr_err("[%s] panel unprepare failed, rc=%d\n",
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index e243a92..bb6c8c6 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -134,7 +134,7 @@
* @display_lock: Mutex for dsi_display interface.
* @disp_te_gpio: GPIO for panel TE interrupt.
* @is_te_irq_enabled:bool to specify whether TE interrupt is enabled.
- * @te_irq_triggered: atomic state notifying panel TE interrupt.
+ * @esd_te_gate: completion gate to signal TE interrupt.
* @ctrl_count: Number of DSI interfaces required by panel.
* @ctrl: Controller information for DSI display.
* @panel: Handle to DSI panel.
@@ -178,7 +178,7 @@
struct mutex display_lock;
int disp_te_gpio;
bool is_te_irq_enabled;
- atomic_t te_irq_triggered;
+ struct completion esd_te_gate;
u32 ctrl_count;
struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY];
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index 211acce..85867b2 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -321,7 +321,7 @@
DRM_DEBUG("%pad/0x%x/0x%x/0x%lx\n", &sgt->sgl->dma_address,
sgt->sgl->dma_length, dir, attrs);
SDE_EVT32(sgt->sgl->dma_address, sgt->sgl->dma_length,
- dir, attrs);
+ dir, attrs, client->secure);
}
return 0;
@@ -342,7 +342,8 @@
if (sgt && sgt->sgl) {
DRM_DEBUG("%pad/0x%x/0x%x\n", &sgt->sgl->dma_address,
sgt->sgl->dma_length, dir);
- SDE_EVT32(sgt->sgl->dma_address, sgt->sgl->dma_length, dir);
+ SDE_EVT32(sgt->sgl->dma_address, sgt->sgl->dma_length, dir,
+ client->secure);
}
msm_dma_unmap_sg(client->dev, sgt->sgl, sgt->nents, dir, dma_buf);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 9355080..356f9ef 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -375,19 +375,24 @@
c = &ctx->hw;
- if (enable) {
- if ((rect_mode == SDE_SSPP_RECT_SOLO)
- || (rect_mode == SDE_SSPP_RECT_0))
- secure_bit_mask =
- (rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
- else
- secure_bit_mask = 0xA;
+ if ((rect_mode == SDE_SSPP_RECT_SOLO)
+ || (rect_mode == SDE_SSPP_RECT_0))
+ secure_bit_mask =
+ (rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
+ else
+ secure_bit_mask = 0xA;
- secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
+ secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
+
+ if (enable)
secure |= secure_bit_mask;
- }
+ else
+ secure &= ~secure_bit_mask;
SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
+
+ /* multiple planes share same sw_status register */
+ wmb();
}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 691fbd4..3bede65 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -2315,7 +2315,7 @@
* configuration.
*/
if (conn_iter &&
- conn_iter->encoder_ids[0] == encoder->base.id) {
+ (conn_iter->encoder_ids[0] == encoder->base.id)) {
connector = conn_iter;
break;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 83cf812..52a5bc9 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -398,7 +398,7 @@
void __iomem *mmio,
struct drm_device *dev)
{
- int rc, i;
+ int rc = 0, i;
enum sde_hw_blk_type type;
if (!rm || !cat || !mmio || !dev) {
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index ab9f203..20b1bb85 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -3508,6 +3508,8 @@
.clk_set_options = adreno_clk_set_options,
.gpu_model = adreno_gpu_model,
.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
+ .dispatcher_halt = adreno_dispatcher_halt,
+ .dispatcher_unhalt = adreno_dispatcher_unhalt,
};
static struct platform_driver adreno_platform_driver = {
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 86b3986..b8c282d 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -2857,6 +2857,16 @@
return ret;
}
+void adreno_dispatcher_halt(struct kgsl_device *device)
+{
+ adreno_get_gpu_halt(ADRENO_DEVICE(device));
+}
+
+void adreno_dispatcher_unhalt(struct kgsl_device *device)
+{
+ adreno_put_gpu_halt(ADRENO_DEVICE(device));
+}
+
/*
* adreno_dispatcher_idle() - Wait for dispatcher to idle
* @adreno_dev: Adreno device whose dispatcher needs to idle
@@ -2887,6 +2897,13 @@
mutex_unlock(&device->mutex);
+ /*
+ * Flush the worker to make sure all executing
+ * or pending dispatcher works on worker are
+ * finished
+ */
+ kthread_flush_worker(&kgsl_driver.worker);
+
ret = wait_for_completion_timeout(&dispatcher->idle_gate,
msecs_to_jiffies(ADRENO_IDLE_TIMEOUT));
if (ret == 0) {
diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h
index 48f0cdc..61bd06f 100644
--- a/drivers/gpu/msm/adreno_dispatch.h
+++ b/drivers/gpu/msm/adreno_dispatch.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -103,6 +103,8 @@
};
void adreno_dispatcher_start(struct kgsl_device *device);
+void adreno_dispatcher_halt(struct kgsl_device *device);
+void adreno_dispatcher_unhalt(struct kgsl_device *device);
int adreno_dispatcher_init(struct adreno_device *adreno_dev);
void adreno_dispatcher_close(struct adreno_device *adreno_dev);
int adreno_dispatcher_idle(struct adreno_device *adreno_dev);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index ebf96b53..913f9bf 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -531,14 +531,21 @@
int ret = 0, id;
struct kgsl_process_private *proc_priv = dev_priv->process_priv;
+ /*
+ * Read and increment the context count under lock to make sure
+ * no process goes beyond the specified context limit.
+ */
+ spin_lock(&proc_priv->ctxt_count_lock);
if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) {
KGSL_DRV_ERR(device,
"Per process context limit reached for pid %u",
dev_priv->process_priv->pid);
+ spin_unlock(&proc_priv->ctxt_count_lock);
return -ENOSPC;
}
atomic_inc(&proc_priv->ctxt_count);
+ spin_unlock(&proc_priv->ctxt_count_lock);
id = _kgsl_get_context_id(device);
if (id == -ENOSPC) {
@@ -753,6 +760,8 @@
mutex_lock(&device->mutex);
status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
+ if (status == 0)
+ device->ftbl->dispatcher_halt(device);
mutex_unlock(&device->mutex);
KGSL_PWR_WARN(device, "suspend end\n");
@@ -767,6 +776,7 @@
KGSL_PWR_WARN(device, "resume start\n");
mutex_lock(&device->mutex);
if (device->state == KGSL_STATE_SUSPEND) {
+ device->ftbl->dispatcher_unhalt(device);
kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
} else if (device->state != KGSL_STATE_INIT) {
/*
@@ -918,6 +928,7 @@
spin_lock_init(&private->mem_lock);
spin_lock_init(&private->syncsource_lock);
+ spin_lock_init(&private->ctxt_count_lock);
idr_init(&private->mem_idr);
idr_init(&private->syncsource_idr);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index b6a2edb..41d1a38 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -190,6 +190,8 @@
void (*gpu_model)(struct kgsl_device *device, char *str,
size_t bufsz);
void (*stop_fault_timer)(struct kgsl_device *device);
+ void (*dispatcher_halt)(struct kgsl_device *device);
+ void (*dispatcher_unhalt)(struct kgsl_device *device);
};
struct kgsl_ioctl {
@@ -443,6 +445,7 @@
* @syncsource_lock: Spinlock to protect the syncsource idr
* @fd_count: Counter for the number of FDs for this process
* @ctxt_count: Count for the number of contexts for this process
+ * @ctxt_count_lock: Spinlock to protect ctxt_count
*/
struct kgsl_process_private {
unsigned long priv;
@@ -463,6 +466,7 @@
spinlock_t syncsource_lock;
int fd_count;
atomic_t ctxt_count;
+ spinlock_t ctxt_count_lock;
};
/**
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f2a7483..b5888db 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2366,7 +2366,6 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) },
- { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
@@ -2636,6 +2635,17 @@
strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
return true;
break;
+ case USB_VENDOR_ID_ELAN:
+ /*
+ * Many Elan devices have a product id of 0x0401 and are handled
+ * by the elan_i2c input driver. But the ACPI HID ELAN0800 dev
+ * is not (and cannot be) handled by that driver ->
+ * Ignore all 0x0401 devs except for the ELAN0800 dev.
+ */
+ if (hdev->product == 0x0401 &&
+ strncmp(hdev->name, "ELAN0800", 8) != 0)
+ return true;
+ break;
}
if (hdev->type == HID_TYPE_USBMOUSE &&
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index b35605d..62ad4f4 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -2033,6 +2033,34 @@
}
EXPORT_SYMBOL(qpnp_adc_scale_pmi_chg_temp);
+int32_t qpnp_adc_scale_die_temp_1390(struct qpnp_vadc_chip *chip,
+ int32_t adc_code,
+ const struct qpnp_adc_properties *adc_properties,
+ const struct qpnp_vadc_chan_properties *chan_properties,
+ struct qpnp_vadc_result *adc_chan_result)
+{
+ int rc = 0;
+
+ if (!chan_properties || !chan_properties->offset_gain_numerator ||
+ !chan_properties->offset_gain_denominator || !adc_properties
+ || !adc_chan_result)
+ return -EINVAL;
+
+ rc = qpnp_adc_scale_default(chip, adc_code, adc_properties,
+ chan_properties, adc_chan_result);
+ if (rc < 0)
+ return rc;
+
+ pr_debug("raw_code:%x, v_adc:%lld\n", adc_code,
+ adc_chan_result->physical);
+ /* T = (1.49322 – V) / 0.00356 */
+ adc_chan_result->physical = 1493220 - adc_chan_result->physical;
+ adc_chan_result->physical = div64_s64(adc_chan_result->physical, 356);
+
+ return 0;
+}
+EXPORT_SYMBOL(qpnp_adc_scale_die_temp_1390);
+
int32_t qpnp_adc_enable_voltage(struct qpnp_adc_drv *adc)
{
int rc = 0;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index f5f914fc6..88b879c 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -225,6 +225,7 @@
[SCALE_I_DEFAULT] = {qpnp_iadc_scale_default},
[SCALE_USBIN_I] = {qpnp_adc_scale_usbin_curr},
[SCALE_BATT_THERM_TEMP_QRD] = {qpnp_adc_batt_therm_qrd},
+ [SCALE_SMB1390_DIE_TEMP] = {qpnp_adc_scale_die_temp_1390},
};
static struct qpnp_vadc_rscale_fn adc_vadc_rscale_fn[] = {
diff --git a/drivers/hwtracing/coresight/coresight-byte-cntr.c b/drivers/hwtracing/coresight/coresight-byte-cntr.c
index 7204cdfd..5173770 100644
--- a/drivers/hwtracing/coresight/coresight-byte-cntr.c
+++ b/drivers/hwtracing/coresight/coresight-byte-cntr.c
@@ -149,6 +149,8 @@
if (!byte_cntr_data->read_active)
goto err0;
+ bufp = (char *)(tmcdrvdata->buf + *ppos);
+
if (byte_cntr_data->enable) {
if (!atomic_read(&byte_cntr_data->irq_cnt)) {
mutex_unlock(&byte_cntr_data->byte_cntr_lock);
@@ -159,7 +161,6 @@
if (!byte_cntr_data->read_active)
goto err0;
}
- bufp = (char *)(tmcdrvdata->buf + *ppos);
if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
tmc_etr_read_bytes(byte_cntr_data, ppos,
diff --git a/drivers/irqchip/qcom/mpm.c b/drivers/irqchip/qcom/mpm.c
index c6970fe..7c91b9e 100644
--- a/drivers/irqchip/qcom/mpm.c
+++ b/drivers/irqchip/qcom/mpm.c
@@ -202,19 +202,35 @@
}
}
-static void msm_mpm_chip_mask(struct irq_data *d)
+static void msm_mpm_gpio_chip_mask(struct irq_data *d)
+{
+ msm_mpm_enable_irq(d, false);
+}
+
+static void msm_mpm_gpio_chip_unmask(struct irq_data *d)
+{
+ msm_mpm_enable_irq(d, true);
+}
+
+static int msm_mpm_gpio_chip_set_type(struct irq_data *d, unsigned int type)
+{
+ msm_mpm_set_type(d, type);
+ return 0;
+}
+
+static void msm_mpm_gic_chip_mask(struct irq_data *d)
{
msm_mpm_enable_irq(d, false);
irq_chip_mask_parent(d);
}
-static void msm_mpm_chip_unmask(struct irq_data *d)
+static void msm_mpm_gic_chip_unmask(struct irq_data *d)
{
msm_mpm_enable_irq(d, true);
irq_chip_unmask_parent(d);
}
-static int msm_mpm_chip_set_type(struct irq_data *d, unsigned int type)
+static int msm_mpm_gic_chip_set_type(struct irq_data *d, unsigned int type)
{
msm_mpm_set_type(d, type);
return irq_chip_set_type_parent(d, type);
@@ -223,21 +239,21 @@
static struct irq_chip msm_mpm_gic_chip = {
.name = "mpm-gic",
.irq_eoi = irq_chip_eoi_parent,
- .irq_mask = msm_mpm_chip_mask,
- .irq_disable = msm_mpm_chip_mask,
- .irq_unmask = msm_mpm_chip_unmask,
+ .irq_mask = msm_mpm_gic_chip_mask,
+ .irq_disable = msm_mpm_gic_chip_mask,
+ .irq_unmask = msm_mpm_gic_chip_unmask,
.irq_retrigger = irq_chip_retrigger_hierarchy,
- .irq_set_type = msm_mpm_chip_set_type,
+ .irq_set_type = msm_mpm_gic_chip_set_type,
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
.irq_set_affinity = irq_chip_set_affinity_parent,
};
static struct irq_chip msm_mpm_gpio_chip = {
.name = "mpm-gpio",
- .irq_mask = msm_mpm_chip_mask,
- .irq_disable = msm_mpm_chip_mask,
- .irq_unmask = msm_mpm_chip_unmask,
- .irq_set_type = msm_mpm_chip_set_type,
+ .irq_mask = msm_mpm_gpio_chip_mask,
+ .irq_disable = msm_mpm_gpio_chip_mask,
+ .irq_unmask = msm_mpm_gpio_chip_unmask,
+ .irq_set_type = msm_mpm_gpio_chip_set_type,
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
.irq_retrigger = irq_chip_retrigger_hierarchy,
.irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
@@ -267,7 +283,6 @@
{
int ret = 0;
struct irq_fwspec *fwspec = data;
- struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
@@ -277,10 +292,8 @@
irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
&msm_mpm_gpio_chip, NULL);
- parent_fwspec = *fwspec;
- parent_fwspec.fwnode = domain->parent->fwnode;
- return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
- &parent_fwspec);
+
+ return 0;
}
static const struct irq_domain_ops msm_mpm_gpio_chip_domain_ops = {
@@ -643,22 +656,21 @@
IRQCHIP_DECLARE(mpm_gic_chip, "qcom,mpm-gic", mpm_gic_chip_init);
-static int mpm_gpio_chip_probe(struct platform_device *pdev)
+static int __init mpm_gpio_chip_init(struct device_node *node,
+ struct device_node *parent)
{
- struct device_node *node, *parent;
struct irq_domain *parent_domain;
const struct of_device_id *id;
- node = pdev->dev.of_node;
- parent = of_irq_find_parent(node);
if (!parent) {
- pr_err("%s(): no parent for mpm-gpio\n", node->full_name);
+ pr_err("%s(): no parent for mpm-gic\n", node->full_name);
return -ENXIO;
}
+
parent_domain = irq_find_host(parent);
if (!parent_domain) {
pr_err("unable to obtain gpio parent domain defer probe\n");
- return -EPROBE_DEFER;
+ return -ENXIO;
}
id = of_match_node(mpm_gpio_chip_data_table, node);
if (!id) {
@@ -678,22 +690,4 @@
return 0;
}
-static const struct of_device_id msm_mpm_dt_match[] = {
- { .compatible = "qcom,mpm-gpio"},
- { },
-};
-
-static struct platform_driver msm_mpm_driver = {
- .probe = mpm_gpio_chip_probe,
- .driver = {
- .name = "qcom,mpm-gpio",
- .of_match_table = msm_mpm_dt_match,
- },
-};
-
-static int __init msm_mpm_gpio_init(void)
-{
- return platform_driver_register(&msm_mpm_driver);
-}
-
-arch_initcall(msm_mpm_gpio_init)
+IRQCHIP_DECLARE(mpm_gpio_chip, "qcom,mpm-gpio", mpm_gpio_chip_init);
diff --git a/drivers/media/dvb-frontends/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c
index ad304ee..c61227c 100644
--- a/drivers/media/dvb-frontends/ascot2e.c
+++ b/drivers/media/dvb-frontends/ascot2e.c
@@ -155,7 +155,9 @@
static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val)
{
- return ascot2e_write_regs(priv, reg, &val, 1);
+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return ascot2e_write_regs(priv, reg, &tmp, 1);
}
static int ascot2e_read_regs(struct ascot2e_priv *priv,
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c
index fd0f25e..b97647c 100644
--- a/drivers/media/dvb-frontends/cxd2841er.c
+++ b/drivers/media/dvb-frontends/cxd2841er.c
@@ -261,7 +261,9 @@
static int cxd2841er_write_reg(struct cxd2841er_priv *priv,
u8 addr, u8 reg, u8 val)
{
- return cxd2841er_write_regs(priv, addr, reg, &val, 1);
+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return cxd2841er_write_regs(priv, addr, reg, &tmp, 1);
}
static int cxd2841er_read_regs(struct cxd2841er_priv *priv,
diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c
index dc43c5f..e06bcd4 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -331,7 +331,9 @@
static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val)
{
- return helene_write_regs(priv, reg, &val, 1);
+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return helene_write_regs(priv, reg, &tmp, 1);
}
static int helene_read_regs(struct helene_priv *priv,
diff --git a/drivers/media/dvb-frontends/horus3a.c b/drivers/media/dvb-frontends/horus3a.c
index 0c089b5..4ebddc8 100644
--- a/drivers/media/dvb-frontends/horus3a.c
+++ b/drivers/media/dvb-frontends/horus3a.c
@@ -89,7 +89,9 @@
static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val)
{
- return horus3a_write_regs(priv, reg, &val, 1);
+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return horus3a_write_regs(priv, reg, &tmp, 1);
}
static int horus3a_enter_power_save(struct horus3a_priv *priv)
diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c
index cadcae4..ac9d259 100644
--- a/drivers/media/dvb-frontends/itd1000.c
+++ b/drivers/media/dvb-frontends/itd1000.c
@@ -99,8 +99,9 @@
static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
{
- int ret = itd1000_write_regs(state, r, &v, 1);
- state->shadow[r] = v;
+ u8 tmp = v; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+ int ret = itd1000_write_regs(state, r, &tmp, 1);
+ state->shadow[r] = tmp;
return ret;
}
diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
index fc08429..7824926 100644
--- a/drivers/media/dvb-frontends/mt312.c
+++ b/drivers/media/dvb-frontends/mt312.c
@@ -142,7 +142,10 @@
static inline int mt312_writereg(struct mt312_state *state,
const enum mt312_reg_addr reg, const u8 val)
{
- return mt312_write(state, reg, &val, 1);
+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+
+ return mt312_write(state, reg, &tmp, 1);
}
static inline u32 mt312_div(u32 a, u32 b)
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index 3d171b0..3deddbc 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -552,7 +552,8 @@
int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
{
- return stb0899_write_regs(state, reg, &data, 1);
+ u8 tmp = data;
+ return stb0899_write_regs(state, reg, &tmp, 1);
}
/*
diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c
index 5add118..4746b1e 100644
--- a/drivers/media/dvb-frontends/stb6100.c
+++ b/drivers/media/dvb-frontends/stb6100.c
@@ -226,12 +226,14 @@
static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
{
+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
if (unlikely(reg >= STB6100_NUMREGS)) {
dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
return -EREMOTEIO;
}
- data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
- return stb6100_write_reg_range(state, &data, reg, 1);
+ tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set;
+ return stb6100_write_reg_range(state, &tmp, reg, 1);
}
diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index abc379a..94cec81 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -804,7 +804,9 @@
static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
{
- return stv0367_writeregs(state, reg, &data, 1);
+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return stv0367_writeregs(state, reg, &tmp, 1);
}
static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index 25bdf6e..f0377e2 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -761,7 +761,9 @@
static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
{
- return stv090x_write_regs(state, reg, &data, 1);
+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return stv090x_write_regs(state, reg, &tmp, 1);
}
static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c
index c611ad2..924f16f 100644
--- a/drivers/media/dvb-frontends/stv6110x.c
+++ b/drivers/media/dvb-frontends/stv6110x.c
@@ -97,7 +97,9 @@
static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
{
- return stv6110x_write_regs(stv6110x, reg, &data, 1);
+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return stv6110x_write_regs(stv6110x, reg, &tmp, 1);
}
static int stv6110x_init(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
index a9f6bbe..103b9c8 100644
--- a/drivers/media/dvb-frontends/ts2020.c
+++ b/drivers/media/dvb-frontends/ts2020.c
@@ -369,7 +369,7 @@
gain2 = clamp_t(long, gain2, 0, 13);
v_agc = clamp_t(long, v_agc, 400, 1100);
- *_gain = -(gain1 * 2330 +
+ *_gain = -((__s64)gain1 * 2330 +
gain2 * 3500 +
v_agc * 24 / 10 * 10 +
10000);
@@ -387,7 +387,7 @@
gain3 = clamp_t(long, gain3, 0, 6);
v_agc = clamp_t(long, v_agc, 600, 1600);
- *_gain = -(gain1 * 2650 +
+ *_gain = -((__s64)gain1 * 2650 +
gain2 * 3380 +
gain3 * 2850 +
v_agc * 176 / 100 * 10 -
diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c
index f8c271b..0d2bef6 100644
--- a/drivers/media/dvb-frontends/zl10039.c
+++ b/drivers/media/dvb-frontends/zl10039.c
@@ -138,7 +138,9 @@
const enum zl10039_reg_addr reg,
const u8 val)
{
- return zl10039_write(state, reg, &val, 1);
+ const u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+ return zl10039_write(state, reg, &tmp, 1);
}
static int zl10039_init(struct dvb_frontend *fe)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index de7d9ed..5fff66e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -1106,8 +1106,10 @@
fe_cfg->stream_id);
vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
index bc0a31f..a9ff454 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
@@ -891,8 +891,11 @@
vfe_dev->buf_mgr, fe_cfg->session_id,
fe_cfg->stream_id);
vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
+
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0) {
pr_err("%s: No fetch buffer\n", __func__);
return -EINVAL;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
index b319738..0239fe7 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
@@ -830,8 +830,10 @@
fe_cfg->stream_id);
vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index e03f76f..d1a95cd 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1151,8 +1151,10 @@
fe_cfg->stream_id);
vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 769a9a5..625a0db 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -57,6 +57,11 @@
CDBG("Enter\n");
+ if (a_ctrl->i2c_reg_tbl == NULL) {
+ pr_err("failed. i2c reg table is NULL");
+ return -EFAULT;
+ }
+
if (a_ctrl->curr_step_pos != 0) {
a_ctrl->i2c_tbl_index = 0;
a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
@@ -99,7 +104,7 @@
}
if (a_ctrl->i2c_reg_tbl == NULL) {
- pr_err("failed. i2c reg tabl is NULL");
+ pr_err("failed. i2c reg table is NULL");
return;
}
@@ -526,6 +531,11 @@
CDBG("Enter\n");
+ if (a_ctrl->i2c_reg_tbl == NULL) {
+ pr_err("failed. i2c reg table is NULL");
+ return -EFAULT;
+ }
+
if (copy_from_user(&ringing_params_kernel,
&(move_params->ringing_params[0]),
sizeof(struct damping_params_t))) {
@@ -599,6 +609,10 @@
pr_err("Invalid direction = %d\n", dir);
return -EFAULT;
}
+ if (a_ctrl->i2c_reg_tbl == NULL) {
+ pr_err("failed. i2c reg table is NULL");
+ return -EFAULT;
+ }
if (dest_step_pos > a_ctrl->total_steps) {
pr_err("Step pos greater than total steps = %d\n",
dest_step_pos);
@@ -719,6 +733,10 @@
pr_err("Invalid direction = %d\n", dir);
return -EFAULT;
}
+ if (a_ctrl->i2c_reg_tbl == NULL) {
+ pr_err("failed. i2c reg table is NULL");
+ return -EFAULT;
+ }
if (dest_step_pos > a_ctrl->total_steps) {
pr_err("Step pos greater than total steps = %d\n",
dest_step_pos);
@@ -1182,7 +1200,8 @@
}
if (!a_ctrl || !a_ctrl->func_tbl ||
- !a_ctrl->func_tbl->actuator_parse_i2c_params) {
+ !a_ctrl->func_tbl->actuator_parse_i2c_params ||
+ !a_ctrl->i2c_reg_tbl) {
pr_err("failed. NULL actuator pointers.");
return -EFAULT;
}
@@ -1294,12 +1313,10 @@
a_ctrl->region_size = set_info->af_tuning_params.region_size;
a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step;
- a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
if (copy_from_user(&a_ctrl->region_params,
(void __user *)set_info->af_tuning_params.region_params,
a_ctrl->region_size * sizeof(struct region_params_t))) {
- a_ctrl->total_steps = 0;
pr_err("Error copying region_params\n");
return -EFAULT;
}
@@ -1341,6 +1358,7 @@
return -ENOMEM;
}
+ a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
if (copy_from_user(&a_ctrl->reg_tbl,
(void __user *)set_info->actuator_params.reg_tbl_params,
a_ctrl->reg_tbl_size *
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
index 9d92acf..6dac1ed 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
@@ -217,12 +217,18 @@
SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%llu rd:%d\n",
width, height, fps, pixfmt, is_yuv, res, is_rd);
+ if (!is_yuv)
+ goto exit;
+
+ /*
+ * If (total_source_pixels <= 62208000 && YUV) -> RD/WROT=2 //1080p30
+ * If (total_source_pixels <= 124416000 && YUV) -> RD/WROT=4 //1080p60
+ * If (total_source_pixels <= 2160p && YUV && FPS <= 30) -> RD/WROT = 32
+ */
if (res <= (RES_1080p * 30))
ot_lim = 2;
else if (res <= (RES_1080p * 60))
ot_lim = 4;
- else if (res <= (RES_UHD * 30))
- ot_lim = 8;
exit:
SDEROT_DBG("ot_lim=%d\n", ot_lim);
@@ -252,6 +258,8 @@
val &= (0xFF << bit_off);
val = val >> bit_off;
+ SDEROT_EVTLOG(val, ot_lim);
+
if (val == ot_lim)
ot_lim = 0;
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index 0e8fb89..5c4aa24 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -504,18 +504,23 @@
static int lme2510_return_status(struct dvb_usb_device *d)
{
- int ret = 0;
+ int ret;
u8 *data;
- data = kzalloc(10, GFP_KERNEL);
+ data = kzalloc(6, GFP_KERNEL);
if (!data)
return -ENOMEM;
- ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
- 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
- info("Firmware Status: %x (%x)", ret , data[2]);
+ ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+ 0x06, 0x80, 0x0302, 0x00,
+ data, 0x6, 200);
+ if (ret != 6)
+ ret = -EINVAL;
+ else
+ ret = data[2];
- ret = (ret < 0) ? -ENODEV : data[2];
+ info("Firmware Status: %6ph", data);
+
kfree(data);
return ret;
}
@@ -1079,8 +1084,6 @@
if (adap->fe[0]) {
info("FE Found M88RS2000");
- dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config,
- &d->i2c_adap);
st->i2c_tuner_gate_w = 5;
st->i2c_tuner_gate_r = 5;
st->i2c_tuner_addr = 0x60;
@@ -1146,17 +1149,18 @@
ret = st->tuner_config;
break;
case TUNER_RS2000:
- ret = st->tuner_config;
+ if (dvb_attach(ts2020_attach, adap->fe[0],
+ &ts2020_config, &d->i2c_adap))
+ ret = st->tuner_config;
break;
default:
break;
}
- if (ret)
+ if (ret) {
info("TUN Found %s tuner", tun_msg[ret]);
- else {
- info("TUN No tuner found --- resetting device");
- lme_coldreset(d);
+ } else {
+ info("TUN No tuner found");
return -ENODEV;
}
@@ -1200,6 +1204,7 @@
static int lme2510_identify_state(struct dvb_usb_device *d, const char **name)
{
struct lme2510_state *st = d->priv;
+ int status;
usb_reset_configuration(d->udev);
@@ -1208,12 +1213,16 @@
st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware;
- if (lme2510_return_status(d) == 0x44) {
+ status = lme2510_return_status(d);
+ if (status == 0x44) {
*name = lme_firmware_switch(d, 0);
return COLD;
}
- return 0;
+ if (status != 0x47)
+ return -EINVAL;
+
+ return WARM;
}
static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index 9fd43a3..b20f03d 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -820,6 +820,8 @@
case XC2028_RESET_CLK:
deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
break;
+ case XC2028_I2C_FLUSH:
+ break;
default:
deb_info("%s: unknown command %d, arg %d\n", __func__,
command, arg);
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index caa5540..2868766 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -431,6 +431,7 @@
state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
break;
case XC2028_RESET_CLK:
+ case XC2028_I2C_FLUSH:
break;
default:
err("%s: unknown command %d, arg %d\n", __func__,
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c
index a61d8fd..a20b60a 100644
--- a/drivers/media/usb/hdpvr/hdpvr-core.c
+++ b/drivers/media/usb/hdpvr/hdpvr-core.c
@@ -295,7 +295,7 @@
/* register v4l2_device early so it can be used for printks */
if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
dev_err(&interface->dev, "v4l2_device_register failed\n");
- goto error;
+ goto error_free_dev;
}
mutex_init(&dev->io_mutex);
@@ -304,7 +304,7 @@
dev->usbc_buf = kmalloc(64, GFP_KERNEL);
if (!dev->usbc_buf) {
v4l2_err(&dev->v4l2_dev, "Out of memory\n");
- goto error;
+ goto error_v4l2_unregister;
}
init_waitqueue_head(&dev->wait_buffer);
@@ -342,13 +342,13 @@
}
if (!dev->bulk_in_endpointAddr) {
v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
- goto error;
+ goto error_put_usb;
}
/* init the device */
if (hdpvr_device_init(dev)) {
v4l2_err(&dev->v4l2_dev, "device init failed\n");
- goto error;
+ goto error_put_usb;
}
mutex_lock(&dev->io_mutex);
@@ -356,7 +356,7 @@
mutex_unlock(&dev->io_mutex);
v4l2_err(&dev->v4l2_dev,
"allocating transfer buffers failed\n");
- goto error;
+ goto error_put_usb;
}
mutex_unlock(&dev->io_mutex);
@@ -364,7 +364,7 @@
retval = hdpvr_register_i2c_adapter(dev);
if (retval < 0) {
v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
- goto error;
+ goto error_free_buffers;
}
client = hdpvr_register_ir_rx_i2c(dev);
@@ -397,13 +397,17 @@
reg_fail:
#if IS_ENABLED(CONFIG_I2C)
i2c_del_adapter(&dev->i2c_adapter);
+error_free_buffers:
#endif
+ hdpvr_free_buffers(dev);
+error_put_usb:
+ usb_put_dev(dev->udev);
+ kfree(dev->usbc_buf);
+error_v4l2_unregister:
+ v4l2_device_unregister(&dev->v4l2_dev);
+error_free_dev:
+ kfree(dev);
error:
- if (dev) {
- flush_work(&dev->worker);
- /* this frees allocated memory */
- hdpvr_delete(dev);
- }
return retval;
}
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index f37d64c..9eaab98 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -18,8 +18,18 @@
#include <linux/videodev2.h>
#include <linux/v4l2-subdev.h>
#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-ioctl.h>
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from) \
+({ \
+ typeof(*from) __assign_tmp; \
+ \
+ get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
+})
+
static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = -ENOIOCTLCMD;
@@ -33,157 +43,88 @@
struct v4l2_clip32 {
struct v4l2_rect c;
- compat_caddr_t next;
+ compat_caddr_t next;
};
struct v4l2_window32 {
struct v4l2_rect w;
- __u32 field; /* enum v4l2_field */
+ __u32 field; /* enum v4l2_field */
__u32 chromakey;
compat_caddr_t clips; /* actually struct v4l2_clip32 * */
__u32 clipcount;
compat_caddr_t bitmap;
+ __u8 global_alpha;
};
static int get_v4l2_window32(struct v4l2_window __user *kp,
- struct v4l2_window32 __user *up)
+ struct v4l2_window32 __user *up,
+ void __user *aux_buf, u32 aux_space)
{
- u32 clipcount = 0;
+ struct v4l2_clip32 __user *uclips;
+ struct v4l2_clip __user *kclips;
+ compat_caddr_t p;
+ u32 clipcount;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
- !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_window)) ||
- copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
- copy_in_user(&kp->field, &up->field, sizeof(up->field)) ||
- copy_in_user(&kp->chromakey, &up->chromakey,
- sizeof(up->chromakey)) ||
- copy_in_user(&kp->clipcount, &up->clipcount,
- sizeof(up->clipcount)))
- return -EFAULT;
- if (get_user(clipcount, &kp->clipcount))
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
+ assign_in_user(&kp->field, &up->field) ||
+ assign_in_user(&kp->chromakey, &up->chromakey) ||
+ assign_in_user(&kp->global_alpha, &up->global_alpha) ||
+ get_user(clipcount, &up->clipcount) ||
+ put_user(clipcount, &kp->clipcount))
return -EFAULT;
if (clipcount > 2048)
return -EINVAL;
- if (clipcount) {
- struct v4l2_clip32 __user *uclips;
- struct v4l2_clip __user *kclips;
- int n = clipcount;
- compat_caddr_t p;
+ if (!clipcount)
+ return put_user(NULL, &kp->clips);
- if (get_user(p, &up->clips))
+ if (get_user(p, &up->clips))
+ return -EFAULT;
+ uclips = compat_ptr(p);
+ if (aux_space < clipcount * sizeof(*kclips))
+ return -EFAULT;
+ kclips = aux_buf;
+ if (put_user(kclips, &kp->clips))
+ return -EFAULT;
+
+ while (clipcount--) {
+ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
return -EFAULT;
- uclips = compat_ptr(p);
- kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
- if (put_user(kclips, &kp->clips))
+ if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next))
return -EFAULT;
- while (--n >= 0) {
- if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
- return -EFAULT;
- if (put_user(n ? kclips + 1 : NULL, &kclips->next))
- return -EFAULT;
- uclips += 1;
- kclips += 1;
- }
- } else {
- if (put_user(NULL, &kp->clips))
- return -EFAULT;
+ uclips++;
+ kclips++;
}
return 0;
}
static int put_v4l2_window32(struct v4l2_window __user *kp,
- struct v4l2_window32 __user *up)
+ struct v4l2_window32 __user *up)
{
- if (copy_in_user(&up->w, &kp->w, sizeof(up->w)) ||
- copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
- copy_in_user(&up->chromakey, &kp->chromakey,
- sizeof(up->chromakey)) ||
- copy_in_user(&up->clipcount, &kp->clipcount,
- sizeof(up->clipcount)))
- return -EFAULT;
- return 0;
-}
+ struct v4l2_clip __user *kclips = kp->clips;
+ struct v4l2_clip32 __user *uclips;
+ compat_caddr_t p;
+ u32 clipcount;
-static inline int get_v4l2_pix_format(struct v4l2_pix_format __user *kp,
- struct v4l2_pix_format __user *up)
-{
- if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format)))
+ if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) ||
+ assign_in_user(&up->field, &kp->field) ||
+ assign_in_user(&up->chromakey, &kp->chromakey) ||
+ assign_in_user(&up->global_alpha, &kp->global_alpha) ||
+ get_user(clipcount, &kp->clipcount) ||
+ put_user(clipcount, &up->clipcount))
return -EFAULT;
- return 0;
-}
+ if (!clipcount)
+ return 0;
-static inline int get_v4l2_pix_format_mplane(
- struct v4l2_pix_format_mplane __user *kp,
- struct v4l2_pix_format_mplane __user *up)
-{
- if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+ if (get_user(p, &up->clips))
return -EFAULT;
- return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format __user *kp,
- struct v4l2_pix_format __user *up)
-{
- if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format)))
- return -EFAULT;
- return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(
- struct v4l2_pix_format_mplane __user *kp,
- struct v4l2_pix_format_mplane __user *up)
-{
- if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
- return -EFAULT;
- return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
- struct v4l2_vbi_format __user *up)
-{
- if (copy_in_user(kp, up, sizeof(struct v4l2_vbi_format)))
- return -EFAULT;
- return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
- struct v4l2_vbi_format __user *up)
-{
- if (copy_in_user(up, kp, sizeof(struct v4l2_vbi_format)))
- return -EFAULT;
- return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(
- struct v4l2_sliced_vbi_format __user *kp,
- struct v4l2_sliced_vbi_format __user *up)
-{
- if (copy_in_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
- return -EFAULT;
- return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(
- struct v4l2_sliced_vbi_format __user *kp,
- struct v4l2_sliced_vbi_format __user *up)
-{
- if (copy_in_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
- return -EFAULT;
- return 0;
-}
-
-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
- struct v4l2_sdr_format __user *up)
-{
- if (copy_in_user(kp, up, sizeof(struct v4l2_sdr_format)))
- return -EFAULT;
- return 0;
-}
-
-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
- struct v4l2_sdr_format __user *up)
-{
- if (copy_in_user(up, kp, sizeof(struct v4l2_sdr_format)))
- return -EFAULT;
+ uclips = compat_ptr(p);
+ while (clipcount--) {
+ if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+ uclips++;
+ kclips++;
+ }
return 0;
}
@@ -217,120 +158,158 @@
__u32 reserved[8];
};
-static int __get_v4l2_format32(struct v4l2_format __user *kp,
- struct v4l2_format32 __user *up)
+static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
{
u32 type;
- if (copy_in_user(&kp->type, &up->type, sizeof(up->type)))
+ if (get_user(type, &up->type))
return -EFAULT;
- if (get_user(type, &kp->type))
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+ u32 clipcount;
+
+ if (get_user(clipcount, &up->fmt.win.clipcount))
+ return -EFAULT;
+ if (clipcount > 2048)
+ return -EINVAL;
+ *size = clipcount * sizeof(struct v4l2_clip);
+ return 0;
+ }
+ default:
+ *size = 0;
+ return 0;
+ }
+}
+
+static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
+ return __bufsize_v4l2_format(up, size);
+}
+
+static int __get_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up,
+ void __user *aux_buf, u32 aux_space)
+{
+ u32 type;
+
+ if (get_user(type, &up->type) || put_user(type, &kp->type))
+ return -EFAULT;
+
switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+ return copy_in_user(&kp->fmt.pix, &up->fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
- &up->fmt.pix_mp);
+ return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ return get_v4l2_window32(&kp->fmt.win, &up->fmt.win,
+ aux_buf, aux_space);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
- return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+ return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
+ return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SDR_CAPTURE:
case V4L2_BUF_TYPE_SDR_OUTPUT:
- return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+ return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr,
+ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
default:
- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
- kp->type);
return -EINVAL;
}
}
static int get_v4l2_format32(struct v4l2_format __user *kp,
- struct v4l2_format32 __user *up)
+ struct v4l2_format32 __user *up,
+ void __user *aux_buf, u32 aux_space)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
- !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_format)))
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
- return __get_v4l2_format32(kp, up);
+ return __get_v4l2_format32(kp, up, aux_buf, aux_space);
+}
+
+static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up,
+ u32 *size)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+ return -EFAULT;
+ return __bufsize_v4l2_format(&up->format, size);
}
static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
- struct v4l2_create_buffers32 __user *up)
+ struct v4l2_create_buffers32 __user *up,
+ void __user *aux_buf, u32 aux_space)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
- !access_ok(VERIFY_WRITE, kp,
- sizeof(struct v4l2_create_buffers)) ||
- copy_in_user(kp, up,
- offsetof(struct v4l2_create_buffers32, format)))
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ copy_in_user(kp, up,
+ offsetof(struct v4l2_create_buffers32, format)))
return -EFAULT;
- return __get_v4l2_format32(&kp->format, &up->format);
+ return __get_v4l2_format32(&kp->format, &up->format,
+ aux_buf, aux_space);
}
static int __put_v4l2_format32(struct v4l2_format __user *kp,
- struct v4l2_format32 __user *up)
+ struct v4l2_format32 __user *up)
{
u32 type;
- if (copy_in_user(&up->type, &kp->type, sizeof(up->type)))
- return -EFAULT;
-
if (get_user(type, &kp->type))
return -EFAULT;
switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+ return copy_in_user(&up->fmt.pix, &kp->fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
- &up->fmt.pix_mp);
+ return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
- return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+ return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
+ return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SDR_CAPTURE:
case V4L2_BUF_TYPE_SDR_OUTPUT:
- return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+ return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr,
+ sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
default:
- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
- kp->type);
return -EINVAL;
}
}
static int put_v4l2_format32(struct v4l2_format __user *kp,
- struct v4l2_format32 __user *up)
+ struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
- !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_format)))
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
return -EFAULT;
return __put_v4l2_format32(kp, up);
}
static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
- struct v4l2_create_buffers32 __user *up)
+ struct v4l2_create_buffers32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
- !access_ok(VERIFY_READ, kp,
- sizeof(struct v4l2_create_buffers)) ||
- copy_in_user(up, kp,
- offsetof(struct v4l2_create_buffers32, format)) ||
- copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ copy_in_user(up, kp,
+ offsetof(struct v4l2_create_buffers32, format)) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return __put_v4l2_format32(&kp->format, &up->format);
}
@@ -345,30 +324,27 @@
};
static int get_v4l2_standard32(struct v4l2_standard __user *kp,
- struct v4l2_standard32 __user *up)
+ struct v4l2_standard32 __user *up)
{
/* other fields are not set by the user, nor used by the driver */
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
- !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_standard)) ||
- copy_in_user(&kp->index, &up->index, sizeof(up->index)))
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ assign_in_user(&kp->index, &up->index))
return -EFAULT;
return 0;
}
static int put_v4l2_standard32(struct v4l2_standard __user *kp,
- struct v4l2_standard32 __user *up)
+ struct v4l2_standard32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
- !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_standard)) ||
- copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
- copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
- copy_in_user(up->name, kp->name, 24) ||
- copy_in_user(&up->frameperiod, &kp->frameperiod,
- sizeof(up->frameperiod)) ||
- copy_in_user(&up->framelines, &kp->framelines,
- sizeof(up->framelines)) ||
- copy_in_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
- return -EFAULT;
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ assign_in_user(&up->index, &kp->index) ||
+ assign_in_user(&up->id, &kp->id) ||
+ copy_in_user(up->name, kp->name, sizeof(up->name)) ||
+ copy_in_user(&up->frameperiod, &kp->frameperiod,
+ sizeof(up->frameperiod)) ||
+ assign_in_user(&up->framelines, &kp->framelines) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ return -EFAULT;
return 0;
}
@@ -407,160 +383,192 @@
__u32 reserved;
};
-static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
- enum v4l2_memory memory)
+static int get_v4l2_plane32(struct v4l2_plane __user *up,
+ struct v4l2_plane32 __user *up32,
+ enum v4l2_memory memory)
{
- void __user *up_pln;
- compat_long_t p;
+ compat_ulong_t p;
if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
- copy_in_user(&up->data_offset, &up32->data_offset,
- sizeof(__u32)) ||
- copy_in_user(up->reserved, up32->reserved,
- sizeof(up->reserved)) ||
- copy_in_user(&up->length, &up32->length,
- sizeof(__u32)))
+ copy_in_user(&up->data_offset, &up32->data_offset,
+ sizeof(up->data_offset)) ||
+ copy_in_user(up->reserved, up32->reserved,
+ sizeof(up->reserved)) ||
+ copy_in_user(&up->length, &up32->length,
+ sizeof(up->length)))
return -EFAULT;
- if (memory == V4L2_MEMORY_USERPTR) {
- if (get_user(p, &up32->m.userptr))
- return -EFAULT;
- up_pln = compat_ptr(p);
- if (put_user((unsigned long)up_pln, &up->m.userptr))
- return -EFAULT;
- } else if (memory == V4L2_MEMORY_DMABUF) {
- if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
- return -EFAULT;
- } else {
+ switch (memory) {
+ case V4L2_MEMORY_MMAP:
+ case V4L2_MEMORY_OVERLAY:
if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
- sizeof(__u32)))
+ sizeof(up32->m.mem_offset)))
return -EFAULT;
+ break;
+ case V4L2_MEMORY_USERPTR:
+ if (get_user(p, &up32->m.userptr) ||
+ put_user((unsigned long)compat_ptr(p), &up->m.userptr))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_DMABUF:
+ if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
+ return -EFAULT;
+ break;
}
return 0;
}
-static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
- enum v4l2_memory memory)
+static int put_v4l2_plane32(struct v4l2_plane __user *up,
+ struct v4l2_plane32 __user *up32,
+ enum v4l2_memory memory)
{
+ unsigned long p;
+
if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
- copy_in_user(&up32->data_offset, &up->data_offset,
- sizeof(__u32)) ||
- copy_in_user(up32->reserved, up->reserved,
- sizeof(up32->reserved)))
+ copy_in_user(&up32->data_offset, &up->data_offset,
+ sizeof(up->data_offset)) ||
+ copy_in_user(up32->reserved, up->reserved,
+ sizeof(up32->reserved)))
return -EFAULT;
- /* For MMAP, driver might've set up the offset, so copy it back.
- * USERPTR stays the same (was userspace-provided), so no copying. */
- if (memory == V4L2_MEMORY_MMAP)
+ switch (memory) {
+ case V4L2_MEMORY_MMAP:
+ case V4L2_MEMORY_OVERLAY:
if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
- sizeof(__u32)))
+ sizeof(up->m.mem_offset)))
return -EFAULT;
- /* For DMABUF, driver might've set up the fd, so copy it back. */
- if (memory == V4L2_MEMORY_DMABUF)
- if (copy_in_user(&up32->m.fd, &up->m.fd,
- sizeof(int)))
+ break;
+ case V4L2_MEMORY_USERPTR:
+ if (get_user(p, &up->m.userptr) ||
+ put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+ &up32->m.userptr))
return -EFAULT;
+ break;
+ case V4L2_MEMORY_DMABUF:
+ if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd)))
+ return -EFAULT;
+ break;
+ }
return 0;
}
-static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
- struct v4l2_buffer32 __user *up)
+static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size)
{
+ u32 type;
+ u32 length;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(type, &up->type) ||
+ get_user(length, &up->length))
+ return -EFAULT;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+ if (length > VIDEO_MAX_PLANES)
+ return -EINVAL;
+
+ /*
+ * We don't really care if userspace decides to kill itself
+ * by passing a very big length value
+ */
+ *size = length * sizeof(struct v4l2_plane);
+ } else {
+ *size = 0;
+ }
+ return 0;
+}
+
+static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
+ struct v4l2_buffer32 __user *up,
+ void __user *aux_buf, u32 aux_space)
+{
+ u32 type;
+ u32 length;
+ enum v4l2_memory memory;
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
compat_caddr_t p;
- int num_planes;
- struct timeval time;
- u32 plane_count, memory, type;
int ret;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
- !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_buffer)) ||
- copy_in_user(&kp->index, &up->index, sizeof(up->index)) ||
- copy_in_user(&kp->type, &up->type, sizeof(up->type)) ||
- copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
- copy_in_user(&kp->memory, &up->memory, sizeof(up->memory)) ||
- copy_in_user(&kp->length, &up->length, sizeof(up->length)))
- return -EFAULT;
-
- if (get_user(type, &kp->type))
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ assign_in_user(&kp->index, &up->index) ||
+ get_user(type, &up->type) ||
+ put_user(type, &kp->type) ||
+ assign_in_user(&kp->flags, &up->flags) ||
+ get_user(memory, &up->memory) ||
+ put_user(memory, &kp->memory) ||
+ get_user(length, &up->length) ||
+ put_user(length, &kp->length))
return -EFAULT;
+
if (V4L2_TYPE_IS_OUTPUT(type))
- if (copy_in_user(&kp->bytesused, &up->bytesused,
- sizeof(up->bytesused)) ||
- copy_in_user(&kp->field, &up->field,
- sizeof(up->field)) ||
- get_user(time.tv_sec, &up->timestamp.tv_sec) ||
- get_user(time.tv_usec, &up->timestamp.tv_usec) ||
- put_user(time.tv_sec, &kp->timestamp.tv_sec) ||
- put_user(time.tv_usec, &kp->timestamp.tv_usec))
+ if (assign_in_user(&kp->bytesused, &up->bytesused) ||
+ assign_in_user(&kp->field, &up->field) ||
+ assign_in_user(&kp->timestamp.tv_sec,
+ &up->timestamp.tv_sec) ||
+ assign_in_user(&kp->timestamp.tv_usec,
+ &up->timestamp.tv_usec))
return -EFAULT;
- if (get_user(memory, &kp->memory))
- return -EFAULT;
if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
- if (get_user(plane_count, &kp->length))
- return -EFAULT;
- num_planes = plane_count;
+ u32 num_planes = length;
+
if (num_planes == 0) {
- if (put_user(NULL, &kp->m.planes))
- return -EFAULT;
- /* num_planes == 0 is legal, e.g. when userspace doesn't
- * need planes array on DQBUF*/
- return 0;
+ /*
+ * num_planes == 0 is legal, e.g. when userspace doesn't
+ * need planes array on DQBUF
+ */
+ return put_user(NULL, &kp->m.planes);
}
+ if (num_planes > VIDEO_MAX_PLANES)
+ return -EINVAL;
if (get_user(p, &up->m.planes))
return -EFAULT;
uplane32 = compat_ptr(p);
if (!access_ok(VERIFY_READ, uplane32,
- num_planes * sizeof(struct v4l2_plane32)))
+ num_planes * sizeof(*uplane32)))
return -EFAULT;
- /* We don't really care if userspace decides to kill itself
- * by passing a very big num_planes value */
- uplane = compat_alloc_user_space(num_planes *
- sizeof(struct v4l2_plane));
- if (put_user(uplane, &kp->m.planes))
+ /*
+ * We don't really care if userspace decides to kill itself
+ * by passing a very big num_planes value
+ */
+ if (aux_space < num_planes * sizeof(*uplane))
return -EFAULT;
- while (--num_planes >= 0) {
+ uplane = aux_buf;
+ if (put_user((__force struct v4l2_plane *)uplane,
+ &kp->m.planes))
+ return -EFAULT;
+
+ while (num_planes--) {
ret = get_v4l2_plane32(uplane, uplane32, memory);
if (ret)
return ret;
- ++uplane;
- ++uplane32;
+ uplane++;
+ uplane32++;
}
} else {
switch (memory) {
case V4L2_MEMORY_MMAP:
- if (copy_in_user(&kp->m.offset, &up->m.offset,
- sizeof(up->m.offset)))
- return -EFAULT;
- break;
- case V4L2_MEMORY_USERPTR:
- {
- compat_long_t tmp;
- unsigned long userptr;
-
- if (get_user(tmp, &up->m.userptr))
- return -EFAULT;
-
- userptr = (unsigned long)compat_ptr(tmp);
- put_user(userptr, &kp->m.userptr);
- }
- break;
case V4L2_MEMORY_OVERLAY:
- if (copy_in_user(&kp->m.offset, &up->m.offset,
- sizeof(up->m.offset)))
+ if (assign_in_user(&kp->m.offset, &up->m.offset))
return -EFAULT;
break;
+ case V4L2_MEMORY_USERPTR: {
+ compat_ulong_t userptr;
+
+ if (get_user(userptr, &up->m.userptr) ||
+ put_user((unsigned long)compat_ptr(userptr),
+ &kp->m.userptr))
+ return -EFAULT;
+ break;
+ }
case V4L2_MEMORY_DMABUF:
- if (copy_in_user(&kp->m.fd, &up->m.fd,
- sizeof(up->m.fd)))
+ if (assign_in_user(&kp->m.fd, &up->m.fd))
return -EFAULT;
break;
}
@@ -570,59 +578,50 @@
}
static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
- struct v4l2_buffer32 __user *up)
+ struct v4l2_buffer32 __user *up)
{
+ u32 type;
+ u32 length;
+ enum v4l2_memory memory;
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
compat_caddr_t p;
- int num_planes;
int ret;
- struct timeval time;
- u32 memory, type, length;
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
- !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_buffer)) ||
- copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
- copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
- copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
- copy_in_user(&up->memory, &kp->memory, sizeof(up->memory)))
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ assign_in_user(&up->index, &kp->index) ||
+ get_user(type, &kp->type) ||
+ put_user(type, &up->type) ||
+ assign_in_user(&up->flags, &kp->flags) ||
+ get_user(memory, &kp->memory) ||
+ put_user(memory, &up->memory))
return -EFAULT;
- if (copy_in_user(&up->bytesused, &kp->bytesused,
- sizeof(up->bytesused)) ||
- copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
- get_user(time.tv_sec, &kp->timestamp.tv_sec) ||
- get_user(time.tv_usec, &kp->timestamp.tv_usec) ||
- put_user(time.tv_sec, &up->timestamp.tv_sec) ||
- put_user(time.tv_usec, &up->timestamp.tv_usec) ||
- copy_in_user(&up->timecode, &kp->timecode,
- sizeof(struct v4l2_timecode)) ||
- copy_in_user(&up->sequence, &kp->sequence,
- sizeof(up->sequence)) ||
- copy_in_user(&up->reserved2, &kp->reserved2,
- sizeof(up->reserved2)) ||
- copy_in_user(&up->reserved, &kp->reserved,
- sizeof(up->reserved)) ||
- copy_in_user(&up->length, &kp->length, sizeof(up->length)))
+ if (assign_in_user(&up->bytesused, &kp->bytesused) ||
+ assign_in_user(&up->field, &kp->field) ||
+ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
+ assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) ||
+ copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
+ assign_in_user(&up->sequence, &kp->sequence) ||
+ assign_in_user(&up->reserved2, &kp->reserved2) ||
+ assign_in_user(&up->reserved, &kp->reserved) ||
+ get_user(length, &kp->length) ||
+ put_user(length, &up->length))
return -EFAULT;
- if (get_user(type, &kp->type) ||
- get_user(memory, &kp->memory) ||
- get_user(length, &kp->length))
- return -EINVAL;
-
if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
- num_planes = length;
+ u32 num_planes = length;
+
if (num_planes == 0)
return 0;
- if (get_user(uplane, &kp->m.planes))
+ if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes)))
return -EFAULT;
if (get_user(p, &up->m.planes))
return -EFAULT;
uplane32 = compat_ptr(p);
- while (--num_planes >= 0) {
+ while (num_planes--) {
ret = put_v4l2_plane32(uplane, uplane32, memory);
if (ret)
return ret;
@@ -632,23 +631,16 @@
} else {
switch (memory) {
case V4L2_MEMORY_MMAP:
- if (copy_in_user(&up->m.offset, &kp->m.offset,
- sizeof(up->m.offset)))
+ case V4L2_MEMORY_OVERLAY:
+ if (assign_in_user(&up->m.offset, &kp->m.offset))
return -EFAULT;
break;
case V4L2_MEMORY_USERPTR:
- if (copy_in_user(&up->m.userptr, &kp->m.userptr,
- sizeof(up->m.userptr)))
- return -EFAULT;
- break;
- case V4L2_MEMORY_OVERLAY:
- if (copy_in_user(&up->m.offset, &kp->m.offset,
- sizeof(up->m.offset)))
+ if (assign_in_user(&up->m.userptr, &kp->m.userptr))
return -EFAULT;
break;
case V4L2_MEMORY_DMABUF:
- if (copy_in_user(&up->m.fd, &kp->m.fd,
- sizeof(up->m.fd)))
+ if (assign_in_user(&up->m.fd, &kp->m.fd))
return -EFAULT;
break;
}
@@ -660,7 +652,7 @@
struct v4l2_framebuffer32 {
__u32 capability;
__u32 flags;
- compat_caddr_t base;
+ compat_caddr_t base;
struct {
__u32 width;
__u32 height;
@@ -674,39 +666,32 @@
};
static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
- struct v4l2_framebuffer32 __user *up)
+ struct v4l2_framebuffer32 __user *up)
{
- u32 tmp;
+ compat_caddr_t tmp;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
- !access_ok(VERIFY_WRITE, kp,
- sizeof(struct v4l2_framebuffer)) ||
- get_user(tmp, &up->base) ||
- put_user(compat_ptr(tmp), &kp->base) ||
- copy_in_user(&kp->capability, &up->capability,
- sizeof(up->capability)) ||
- copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
- copy_in_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
- return -EFAULT;
-
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(tmp, &up->base) ||
+ put_user((__force void *)compat_ptr(tmp), &kp->base) ||
+ assign_in_user(&kp->capability, &up->capability) ||
+ assign_in_user(&kp->flags, &up->flags) ||
+ copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
+ return -EFAULT;
return 0;
}
static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
- struct v4l2_framebuffer32 __user *up)
+ struct v4l2_framebuffer32 __user *up)
{
- unsigned long base;
+ void *base;
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
- !access_ok(VERIFY_READ, kp,
- sizeof(struct v4l2_framebuffer)) ||
- copy_from_user(&base, &kp->base, sizeof(base)) ||
- put_user((u32)base, &up->base) ||
- copy_in_user(&up->capability, &kp->capability,
- sizeof(up->capability)) ||
- copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
- copy_in_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
- return -EFAULT;
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ get_user(base, &kp->base) ||
+ put_user(ptr_to_compat(base), &up->base) ||
+ assign_in_user(&up->capability, &kp->capability) ||
+ assign_in_user(&up->flags, &kp->flags) ||
+ copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt)))
+ return -EFAULT;
return 0;
}
@@ -718,23 +703,26 @@
__u32 tuner; /* Associated tuner */
compat_u64 std;
__u32 status;
- __u32 reserved[4];
+ __u32 capabilities;
+ __u32 reserved[3];
};
-/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
- Otherwise it is identical to the 32-bit version. */
+/*
+ * The 64-bit v4l2_input struct has extra padding at the end of the struct.
+ * Otherwise it is identical to the 32-bit version.
+ */
static inline int get_v4l2_input32(struct v4l2_input __user *kp,
- struct v4l2_input32 __user *up)
+ struct v4l2_input32 __user *up)
{
- if (copy_in_user(kp, up, sizeof(struct v4l2_input32)))
+ if (copy_in_user(kp, up, sizeof(*up)))
return -EFAULT;
return 0;
}
static inline int put_v4l2_input32(struct v4l2_input __user *kp,
- struct v4l2_input32 __user *up)
+ struct v4l2_input32 __user *up)
{
- if (copy_in_user(up, kp, sizeof(struct v4l2_input32)))
+ if (copy_in_user(up, kp, sizeof(*up)))
return -EFAULT;
return 0;
}
@@ -758,70 +746,95 @@
};
} __attribute__ ((packed));
-/* The following function really belong in v4l2-common, but that causes
- a circular dependency between modules. We need to think about this, but
- for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
- type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
{
- switch (id) {
- case V4L2_CID_RDS_TX_PS_NAME:
- case V4L2_CID_RDS_TX_RADIO_TEXT:
- return 1;
- default:
- return 0;
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_fh *fh = NULL;
+ struct v4l2_ctrl_handler *hdl = NULL;
+ struct v4l2_query_ext_ctrl qec = { id };
+ const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
+
+ if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
+ fh = file->private_data;
+
+ if (fh && fh->ctrl_handler)
+ hdl = fh->ctrl_handler;
+ else if (vdev->ctrl_handler)
+ hdl = vdev->ctrl_handler;
+
+ if (hdl) {
+ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
+
+ return ctrl && ctrl->is_ptr;
}
+
+ if (!ops || !ops->vidioc_query_ext_ctrl)
+ return false;
+
+ return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
+ (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
}
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
- struct v4l2_ext_controls32 __user *up)
+static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up,
+ u32 *size)
+{
+ u32 count;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ get_user(count, &up->count))
+ return -EFAULT;
+ if (count > V4L2_CID_MAX_CTRLS)
+ return -EINVAL;
+ *size = count * sizeof(struct v4l2_ext_control);
+ return 0;
+}
+
+static int get_v4l2_ext_controls32(struct file *file,
+ struct v4l2_ext_controls __user *kp,
+ struct v4l2_ext_controls32 __user *up,
+ void __user *aux_buf, u32 aux_space)
{
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
- int n;
- compat_caddr_t p;
u32 count;
+ u32 n;
+ compat_caddr_t p;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
- !access_ok(VERIFY_WRITE, kp,
- sizeof(struct v4l2_ext_controls)) ||
- copy_in_user(&kp->which, &up->which,
- sizeof(up->which)) ||
- copy_in_user(&kp->count, &up->count, sizeof(up->count)) ||
- copy_in_user(&kp->error_idx, &up->error_idx,
- sizeof(up->error_idx)) ||
- copy_in_user(kp->reserved, up->reserved,
- sizeof(up->reserved)))
- return -EFAULT;
-
- if (get_user(count, &kp->count))
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ assign_in_user(&kp->which, &up->which) ||
+ get_user(count, &up->count) ||
+ put_user(count, &kp->count) ||
+ assign_in_user(&kp->error_idx, &up->error_idx) ||
+ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
return -EFAULT;
- n = count;
- if (n == 0) {
- if (put_user(NULL, &kp->controls))
- return -EINVAL;
- return 0;
- }
+
+ if (count == 0)
+ return put_user(NULL, &kp->controls);
+ if (count > V4L2_CID_MAX_CTRLS)
+ return -EINVAL;
if (get_user(p, &up->controls))
return -EFAULT;
ucontrols = compat_ptr(p);
- if (!access_ok(VERIFY_READ, ucontrols,
- n * sizeof(struct v4l2_ext_control32)))
+ if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols)))
return -EFAULT;
- kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
- if (put_user(kcontrols, &kp->controls))
+ if (aux_space < count * sizeof(*kcontrols))
+ return -EFAULT;
+ kcontrols = aux_buf;
+ if (put_user((__force struct v4l2_ext_control *)kcontrols,
+ &kp->controls))
return -EFAULT;
- while (--n >= 0) {
+ for (n = 0; n < count; n++) {
u32 id;
if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
return -EFAULT;
+
if (get_user(id, &kcontrols->id))
return -EFAULT;
- if (ctrl_is_pointer(id)) {
+
+ if (ctrl_is_pointer(file, id)) {
void __user *s;
if (get_user(p, &ucontrols->string))
@@ -836,53 +849,55 @@
return 0;
}
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
- struct v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+ struct v4l2_ext_controls __user *kp,
+ struct v4l2_ext_controls32 __user *up)
{
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
- int n;
u32 count;
+ u32 n;
compat_caddr_t p;
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
- !access_ok(VERIFY_READ, kp,
- sizeof(struct v4l2_ext_controls)) ||
- copy_in_user(&up->which, &kp->which,
- sizeof(up->which)) ||
- copy_in_user(&up->count, &kp->count,
- sizeof(up->count)) ||
- copy_in_user(&up->error_idx, &kp->error_idx,
- sizeof(up->error_idx)) ||
- copy_in_user(up->reserved, kp->reserved,
- sizeof(up->reserved)) ||
- get_user(count, &kp->count) ||
- get_user(kcontrols, &kp->controls))
- return -EFAULT;
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ assign_in_user(&up->which, &kp->which) ||
+ get_user(count, &kp->count) ||
+ put_user(count, &up->count) ||
+ assign_in_user(&up->error_idx, &kp->error_idx) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
+ get_user(kcontrols, &kp->controls))
+ return -EFAULT;
+
if (!count)
return 0;
-
- n = count;
if (get_user(p, &up->controls))
return -EFAULT;
ucontrols = compat_ptr(p);
- if (!access_ok(VERIFY_WRITE, ucontrols,
- n * sizeof(struct v4l2_ext_control32)))
+ if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols)))
return -EFAULT;
- while (--n >= 0) {
- unsigned size = sizeof(*ucontrols);
+ for (n = 0; n < count; n++) {
+ unsigned int size = sizeof(*ucontrols);
u32 id;
- if (get_user(id, &kcontrols->id))
+ if (get_user(id, &kcontrols->id) ||
+ put_user(id, &ucontrols->id) ||
+ assign_in_user(&ucontrols->size, &kcontrols->size) ||
+ copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
+ sizeof(ucontrols->reserved2)))
return -EFAULT;
- /* Do not modify the pointer when copying a pointer control.
- The contents of the pointer was changed, not the pointer
- itself. */
- if (ctrl_is_pointer(id))
+
+ /*
+ * Do not modify the pointer when copying a pointer control.
+ * The contents of the pointer was changed, not the pointer
+ * itself.
+ */
+ if (ctrl_is_pointer(file, id))
size -= sizeof(ucontrols->value64);
+
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
+
ucontrols++;
kcontrols++;
}
@@ -903,22 +918,18 @@
};
static int put_v4l2_event32(struct v4l2_event __user *kp,
- struct v4l2_event32 __user *up)
+ struct v4l2_event32 __user *up)
{
- struct timespec ts;
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
- !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_event)) ||
- copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
- copy_in_user(&up->u, &kp->u, sizeof(up->u)) ||
- copy_in_user(&up->pending, &kp->pending,
- sizeof(up->pending)) ||
- copy_in_user(&up->sequence, &kp->sequence,
- sizeof(up->sequence)) ||
- copy_from_user(&ts, &kp->timestamp, sizeof(ts)) ||
- compat_put_timespec(&ts, &up->timestamp) ||
- copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
- copy_in_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
- return -EFAULT;
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ assign_in_user(&up->type, &kp->type) ||
+ copy_in_user(&up->u, &kp->u, sizeof(kp->u)) ||
+ assign_in_user(&up->pending, &kp->pending) ||
+ assign_in_user(&up->sequence, &kp->sequence) ||
+ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
+ assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) ||
+ assign_in_user(&up->id, &kp->id) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ return -EFAULT;
return 0;
}
@@ -931,39 +942,34 @@
};
static int get_v4l2_edid32(struct v4l2_edid __user *kp,
- struct v4l2_edid32 __user *up)
+ struct v4l2_edid32 __user *up)
{
- u32 tmp;
+ compat_uptr_t tmp;
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
- !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_edid)) ||
- copy_in_user(&kp->pad, &up->pad, sizeof(up->pad)) ||
- copy_in_user(&kp->start_block, &up->start_block,
- sizeof(up->start_block)) ||
- copy_in_user(&kp->blocks, &up->blocks, sizeof(up->blocks)) ||
- get_user(tmp, &up->edid) ||
- put_user(compat_ptr(tmp), &kp->edid) ||
- copy_in_user(kp->reserved, up->reserved,
- sizeof(kp->reserved)))
- return -EFAULT;
+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+ assign_in_user(&kp->pad, &up->pad) ||
+ assign_in_user(&kp->start_block, &up->start_block) ||
+ assign_in_user(&kp->blocks, &up->blocks) ||
+ get_user(tmp, &up->edid) ||
+ put_user(compat_ptr(tmp), &kp->edid) ||
+ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+ return -EFAULT;
return 0;
}
static int put_v4l2_edid32(struct v4l2_edid __user *kp,
- struct v4l2_edid32 __user *up)
+ struct v4l2_edid32 __user *up)
{
- unsigned long ptr;
+ void *edid;
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
- !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_edid)) ||
- copy_in_user(&up->pad, &kp->pad, sizeof(up->pad)) ||
- copy_in_user(&up->start_block, &kp->start_block,
- sizeof(up->start_block)) ||
- copy_in_user(&up->blocks, &kp->blocks, sizeof(up->blocks)) ||
- copy_from_user(&ptr, &kp->edid, sizeof(ptr)) ||
- put_user((u32)ptr, &up->edid) ||
- copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
- return -EFAULT;
+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+ assign_in_user(&up->pad, &kp->pad) ||
+ assign_in_user(&up->start_block, &kp->start_block) ||
+ assign_in_user(&up->blocks, &kp->blocks) ||
+ get_user(edid, &kp->edid) ||
+ put_user(ptr_to_compat(edid), &up->edid) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ return -EFAULT;
return 0;
}
@@ -979,7 +985,7 @@
#define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
#define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
#define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
-#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
+#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
@@ -995,30 +1001,26 @@
#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
+static int alloc_userspace(unsigned int size, u32 aux_space,
+ void __user **up_native)
+{
+ *up_native = compat_alloc_user_space(size + aux_space);
+ if (!*up_native)
+ return -ENOMEM;
+ if (clear_user(*up_native, size))
+ return -EFAULT;
+ return 0;
+}
+
static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- union {
- struct v4l2_format v2f;
- struct v4l2_buffer v2b;
- struct v4l2_framebuffer v2fb;
- struct v4l2_input v2i;
- struct v4l2_standard v2s;
- struct v4l2_ext_controls v2ecs;
- struct v4l2_event v2ev;
- struct v4l2_create_buffers v2crt;
- struct v4l2_edid v2edid;
- unsigned long vx;
- int vi;
- } *karg;
void __user *up = compat_ptr(arg);
+ void __user *up_native = NULL;
+ void __user *aux_buf;
+ u32 aux_space;
int compatible_arg = 1;
long err = 0;
- karg = compat_alloc_user_space(sizeof(*karg));
- if (karg == NULL) {
- return -EFAULT;
- }
-
/* First, convert the command. */
switch (cmd) {
case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
@@ -1054,31 +1056,52 @@
case VIDIOC_STREAMOFF:
case VIDIOC_S_INPUT:
case VIDIOC_S_OUTPUT:
- err = copy_in_user(&karg->vi, (s32 __user *)up,
- sizeof(karg->vi));
+ err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
+ if (!err && assign_in_user((unsigned int __user *)up_native,
+ (compat_uint_t __user *)up))
+ err = -EFAULT;
compatible_arg = 0;
break;
case VIDIOC_G_INPUT:
case VIDIOC_G_OUTPUT:
+ err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
compatible_arg = 0;
break;
case VIDIOC_G_EDID:
case VIDIOC_S_EDID:
- err = get_v4l2_edid32(&karg->v2edid, up);
+ err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native);
+ if (!err)
+ err = get_v4l2_edid32(up_native, up);
compatible_arg = 0;
break;
case VIDIOC_G_FMT:
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
- err = get_v4l2_format32(&karg->v2f, up);
+ err = bufsize_v4l2_format(up, &aux_space);
+ if (!err)
+ err = alloc_userspace(sizeof(struct v4l2_format),
+ aux_space, &up_native);
+ if (!err) {
+ aux_buf = up_native + sizeof(struct v4l2_format);
+ err = get_v4l2_format32(up_native, up,
+ aux_buf, aux_space);
+ }
compatible_arg = 0;
break;
case VIDIOC_CREATE_BUFS:
- err = get_v4l2_create32(&karg->v2crt, up);
+ err = bufsize_v4l2_create(up, &aux_space);
+ if (!err)
+ err = alloc_userspace(sizeof(struct v4l2_create_buffers),
+ aux_space, &up_native);
+ if (!err) {
+ aux_buf = up_native + sizeof(struct v4l2_create_buffers);
+ err = get_v4l2_create32(up_native, up,
+ aux_buf, aux_space);
+ }
compatible_arg = 0;
break;
@@ -1086,36 +1109,63 @@
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
- err = get_v4l2_buffer32(&karg->v2b, up);
+ err = bufsize_v4l2_buffer(up, &aux_space);
+ if (!err)
+ err = alloc_userspace(sizeof(struct v4l2_buffer),
+ aux_space, &up_native);
+ if (!err) {
+ aux_buf = up_native + sizeof(struct v4l2_buffer);
+ err = get_v4l2_buffer32(up_native, up,
+ aux_buf, aux_space);
+ }
compatible_arg = 0;
break;
case VIDIOC_S_FBUF:
- err = get_v4l2_framebuffer32(&karg->v2fb, up);
+ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
+ &up_native);
+ if (!err)
+ err = get_v4l2_framebuffer32(up_native, up);
compatible_arg = 0;
break;
case VIDIOC_G_FBUF:
+ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
+ &up_native);
compatible_arg = 0;
break;
case VIDIOC_ENUMSTD:
- err = get_v4l2_standard32(&karg->v2s, up);
+ err = alloc_userspace(sizeof(struct v4l2_standard), 0,
+ &up_native);
+ if (!err)
+ err = get_v4l2_standard32(up_native, up);
compatible_arg = 0;
break;
case VIDIOC_ENUMINPUT:
- err = get_v4l2_input32(&karg->v2i, up);
+ err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
+ if (!err)
+ err = get_v4l2_input32(up_native, up);
compatible_arg = 0;
break;
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
- err = get_v4l2_ext_controls32(&karg->v2ecs, up);
+ err = bufsize_v4l2_ext_controls(up, &aux_space);
+ if (!err)
+ err = alloc_userspace(sizeof(struct v4l2_ext_controls),
+ aux_space, &up_native);
+ if (!err) {
+ aux_buf = up_native + sizeof(struct v4l2_ext_controls);
+ err = get_v4l2_ext_controls32(file, up_native, up,
+ aux_buf, aux_space);
+ }
compatible_arg = 0;
break;
case VIDIOC_DQEVENT:
+ err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
compatible_arg = 0;
break;
}
@@ -1124,18 +1174,26 @@
if (compatible_arg)
err = native_ioctl(file, cmd, (unsigned long)up);
- else {
- err = native_ioctl(file, cmd, (unsigned long)karg);
- }
+ else
+ err = native_ioctl(file, cmd, (unsigned long)up_native);
- /* Special case: even after an error we need to put the
- results back for these ioctls since the error_idx will
- contain information on which control failed. */
+ if (err == -ENOTTY)
+ return err;
+
+ /*
+ * Special case: even after an error we need to put the
+ * results back for these ioctls since the error_idx will
+ * contain information on which control failed.
+ */
switch (cmd) {
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
- if (put_v4l2_ext_controls32(&karg->v2ecs, up))
+ if (put_v4l2_ext_controls32(file, up_native, up))
+ err = -EFAULT;
+ break;
+ case VIDIOC_S_EDID:
+ if (put_v4l2_edid32(up_native, up))
err = -EFAULT;
break;
}
@@ -1147,44 +1205,46 @@
case VIDIOC_S_OUTPUT:
case VIDIOC_G_INPUT:
case VIDIOC_G_OUTPUT:
- err = copy_in_user(up, &karg->vi, sizeof(s32));
+ if (assign_in_user((compat_uint_t __user *)up,
+ ((unsigned int __user *)up_native)))
+ err = -EFAULT;
break;
case VIDIOC_G_FBUF:
- err = put_v4l2_framebuffer32(&karg->v2fb, up);
+ err = put_v4l2_framebuffer32(up_native, up);
break;
case VIDIOC_DQEVENT:
- err = put_v4l2_event32(&karg->v2ev, up);
+ err = put_v4l2_event32(up_native, up);
break;
case VIDIOC_G_EDID:
- case VIDIOC_S_EDID:
- err = put_v4l2_edid32(&karg->v2edid, up);
+ err = put_v4l2_edid32(up_native, up);
break;
case VIDIOC_G_FMT:
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
- err = put_v4l2_format32(&karg->v2f, up);
+ err = put_v4l2_format32(up_native, up);
break;
case VIDIOC_CREATE_BUFS:
- err = put_v4l2_create32(&karg->v2crt, up);
+ err = put_v4l2_create32(up_native, up);
break;
+ case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
- err = put_v4l2_buffer32(&karg->v2b, up);
+ err = put_v4l2_buffer32(up_native, up);
break;
case VIDIOC_ENUMSTD:
- err = put_v4l2_standard32(&karg->v2s, up);
+ err = put_v4l2_standard32(up_native, up);
break;
case VIDIOC_ENUMINPUT:
- err = put_v4l2_input32(&karg->v2i, up);
+ err = put_v4l2_input32(up_native, up);
break;
}
return err;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 5a12b41..e2e23ff 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2952,8 +2952,11 @@
/* Handles IOCTL */
err = func(file, cmd, parg);
- if (err == -ENOIOCTLCMD)
+ if (err == -ENOTTY || err == -ENOIOCTLCMD) {
err = -ENOTTY;
+ goto out;
+ }
+
if (err == 0) {
if (cmd == VIDIOC_DQBUF)
trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index d9fab22..1a4a790 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -2193,16 +2193,9 @@
if (ctrl->nand_version >= 0x0702)
tmp |= ACC_CONTROL_RD_ERASED;
tmp &= ~ACC_CONTROL_FAST_PGM_RDIN;
- if (ctrl->features & BRCMNAND_HAS_PREFETCH) {
- /*
- * FIXME: Flash DMA + prefetch may see spurious erased-page ECC
- * errors
- */
- if (has_flash_dma(ctrl))
- tmp &= ~ACC_CONTROL_PREFETCH;
- else
- tmp |= ACC_CONTROL_PREFETCH;
- }
+ if (ctrl->features & BRCMNAND_HAS_PREFETCH)
+ tmp &= ~ACC_CONTROL_PREFETCH;
+
nand_writereg(ctrl, offs, tmp);
return 0;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a77cfd7..21c0308 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2320,6 +2320,7 @@
static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
+ unsigned int max_bitflips = 0;
int page, realpage, chipnr;
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_ecc_stats stats;
@@ -2377,6 +2378,8 @@
nand_wait_ready(mtd);
}
+ max_bitflips = max_t(unsigned int, max_bitflips, ret);
+
readlen -= len;
if (!readlen)
break;
@@ -2402,7 +2405,7 @@
if (mtd->ecc_stats.failed - stats.failed)
return -EBADMSG;
- return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+ return max_bitflips;
}
/**
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index f9b2a77..e26c4f8 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1835,8 +1835,14 @@
/* Add ECC info retrieval from DT */
for (i = 0; i < ARRAY_SIZE(strengths); i++) {
- if (ecc->strength <= strengths[i])
+ if (ecc->strength <= strengths[i]) {
+ /*
+ * Update ecc->strength value with the actual strength
+ * that will be used by the ECC engine.
+ */
+ ecc->strength = strengths[i];
break;
+ }
}
if (i >= ARRAY_SIZE(strengths)) {
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index d1e6931..46913ef2 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -99,6 +99,8 @@
/* Linked list of all ubiblock instances */
static LIST_HEAD(ubiblock_devices);
+static DEFINE_IDR(ubiblock_minor_idr);
+/* Protects ubiblock_devices and ubiblock_minor_idr */
static DEFINE_MUTEX(devices_mutex);
static int ubiblock_major;
@@ -353,8 +355,6 @@
.init_request = ubiblock_init_request,
};
-static DEFINE_IDR(ubiblock_minor_idr);
-
int ubiblock_create(struct ubi_volume_info *vi)
{
struct ubiblock *dev;
@@ -367,14 +367,15 @@
/* Check that the volume isn't already handled */
mutex_lock(&devices_mutex);
if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
- mutex_unlock(&devices_mutex);
- return -EEXIST;
+ ret = -EEXIST;
+ goto out_unlock;
}
- mutex_unlock(&devices_mutex);
dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
+ if (!dev) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
mutex_init(&dev->dev_mutex);
@@ -439,14 +440,13 @@
goto out_free_queue;
}
- mutex_lock(&devices_mutex);
list_add_tail(&dev->list, &ubiblock_devices);
- mutex_unlock(&devices_mutex);
/* Must be the last step: anyone can call file ops from now on */
add_disk(dev->gd);
dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
dev->ubi_num, dev->vol_id, vi->name);
+ mutex_unlock(&devices_mutex);
return 0;
out_free_queue:
@@ -459,6 +459,8 @@
put_disk(dev->gd);
out_free_dev:
kfree(dev);
+out_unlock:
+ mutex_unlock(&devices_mutex);
return ret;
}
@@ -480,30 +482,36 @@
int ubiblock_remove(struct ubi_volume_info *vi)
{
struct ubiblock *dev;
+ int ret;
mutex_lock(&devices_mutex);
dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
if (!dev) {
- mutex_unlock(&devices_mutex);
- return -ENODEV;
+ ret = -ENODEV;
+ goto out_unlock;
}
/* Found a device, let's lock it so we can check if it's busy */
mutex_lock(&dev->dev_mutex);
if (dev->refcnt > 0) {
- mutex_unlock(&dev->dev_mutex);
- mutex_unlock(&devices_mutex);
- return -EBUSY;
+ ret = -EBUSY;
+ goto out_unlock_dev;
}
/* Remove from device list */
list_del(&dev->list);
- mutex_unlock(&devices_mutex);
-
ubiblock_cleanup(dev);
mutex_unlock(&dev->dev_mutex);
+ mutex_unlock(&devices_mutex);
+
kfree(dev);
return 0;
+
+out_unlock_dev:
+ mutex_unlock(&dev->dev_mutex);
+out_unlock:
+ mutex_unlock(&devices_mutex);
+ return ret;
}
static int ubiblock_resize(struct ubi_volume_info *vi)
@@ -632,6 +640,7 @@
struct ubiblock *next;
struct ubiblock *dev;
+ mutex_lock(&devices_mutex);
list_for_each_entry_safe(dev, next, &ubiblock_devices, list) {
/* The module is being forcefully removed */
WARN_ON(dev->desc);
@@ -640,6 +649,7 @@
ubiblock_cleanup(dev);
kfree(dev);
}
+ mutex_unlock(&devices_mutex);
}
int __init ubiblock_init(void)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index b5b8cd6..668b462 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1529,6 +1529,46 @@
}
/**
+ * erase_aeb - erase a PEB given in UBI attach info PEB
+ * @ubi: UBI device description object
+ * @aeb: UBI attach info PEB
+ * @sync: If true, erase synchronously. Otherwise schedule for erasure
+ */
+static int erase_aeb(struct ubi_device *ubi, struct ubi_ainf_peb *aeb, bool sync)
+{
+ struct ubi_wl_entry *e;
+ int err;
+
+ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
+ ubi->lookuptbl[e->pnum] = e;
+
+ if (sync) {
+ err = sync_erase(ubi, e, false);
+ if (err)
+ goto out_free;
+
+ wl_tree_add(e, &ubi->free);
+ ubi->free_count++;
+ } else {
+ err = schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false);
+ if (err)
+ goto out_free;
+ }
+
+ return 0;
+
+out_free:
+ wl_entry_destroy(ubi, e);
+
+ return err;
+}
+
+/**
* ubi_wl_init - initialize the WL sub-system using attaching information.
* @ubi: UBI device description object
* @ai: attaching information
@@ -1566,18 +1606,10 @@
list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) {
cond_resched();
- e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
- if (!e)
+ err = erase_aeb(ubi, aeb, false);
+ if (err)
goto out_free;
- e->pnum = aeb->pnum;
- e->ec = aeb->ec;
- ubi->lookuptbl[e->pnum] = e;
- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) {
- wl_entry_destroy(ubi, e);
- goto out_free;
- }
-
found_pebs++;
}
@@ -1635,6 +1667,8 @@
ubi_assert(!ubi->lookuptbl[e->pnum]);
ubi->lookuptbl[e->pnum] = e;
} else {
+ bool sync = false;
+
/*
* Usually old Fastmap PEBs are scheduled for erasure
* and we don't have to care about them but if we face
@@ -1644,18 +1678,21 @@
if (ubi->lookuptbl[aeb->pnum])
continue;
- e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
- if (!e)
- goto out_free;
+ /*
+ * The fastmap update code might not find a free PEB for
+ * writing the fastmap anchor to and then reuses the
+ * current fastmap anchor PEB. When this PEB gets erased
+ * and a power cut happens before it is written again we
+ * must make sure that the fastmap attach code doesn't
+ * find any outdated fastmap anchors, hence we erase the
+ * outdated fastmap anchor PEBs synchronously here.
+ */
+ if (aeb->vol_id == UBI_FM_SB_VOLUME_ID)
+ sync = true;
- e->pnum = aeb->pnum;
- e->ec = aeb->ec;
- ubi_assert(!ubi->lookuptbl[e->pnum]);
- ubi->lookuptbl[e->pnum] = e;
- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) {
- wl_entry_destroy(ubi, e);
+ err = erase_aeb(ubi, aeb, sync);
+ if (err)
goto out_free;
- }
}
found_pebs++;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 62d1d07..dcec343 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -636,8 +636,8 @@
v->swtail = next_tail) {
rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom);
if (unlikely(rc)) {
- wil_err(wil, "Error %d in wil_rx_refill[%d]\n",
- rc, v->swtail);
+ wil_err_ratelimited(wil, "Error %d in rx refill[%d]\n",
+ rc, v->swtail);
break;
}
}
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index b40a074..df63b7d 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -368,6 +368,18 @@
writel(value, padcfg0);
}
+static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
+{
+ u32 value;
+
+ /* Put the pad into GPIO mode */
+ value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
+ /* Disable SCI/SMI/NMI generation */
+ value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
+ value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
+ writel(value, padcfg0);
+}
+
static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin)
@@ -375,7 +387,6 @@
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg0;
unsigned long flags;
- u32 value;
raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -385,13 +396,7 @@
}
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
- /* Put the pad into GPIO mode */
- value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
- /* Disable SCI/SMI/NMI generation */
- value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
- value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
- writel(value, padcfg0);
-
+ intel_gpio_set_gpio_mode(padcfg0);
/* Disable TX buffer and enable RX (this will be input) */
__intel_gpio_set_direction(padcfg0, true);
@@ -770,6 +775,8 @@
raw_spin_lock_irqsave(&pctrl->lock, flags);
+ intel_gpio_set_gpio_mode(reg);
+
value = readl(reg);
value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index d57879b..9e1c8d2 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -584,6 +584,9 @@
clear_bit(d->hwirq, pctrl->enabled_irqs);
spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ if (d->parent_data)
+ irq_chip_mask_parent(d);
}
static void msm_gpio_irq_enable(struct irq_data *d)
@@ -612,6 +615,9 @@
set_bit(d->hwirq, pctrl->enabled_irqs);
spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ if (d->parent_data)
+ irq_chip_enable_parent(d);
}
static void msm_gpio_irq_unmask(struct irq_data *d)
@@ -633,6 +639,9 @@
set_bit(d->hwirq, pctrl->enabled_irqs);
spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ if (d->parent_data)
+ irq_chip_unmask_parent(d);
}
static void msm_gpio_irq_ack(struct irq_data *d)
@@ -746,6 +755,9 @@
spin_unlock_irqrestore(&pctrl->lock, flags);
+ if (d->parent_data)
+ irq_chip_set_type_parent(d, type);
+
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
irq_set_handler_locked(d, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
@@ -766,6 +778,9 @@
spin_unlock_irqrestore(&pctrl->lock, flags);
+ if (d->parent_data)
+ irq_chip_set_wake_parent(d, on);
+
return 0;
}
@@ -839,16 +854,20 @@
static int msm_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *arg)
{
- int ret;
+ int ret = 0;
irq_hw_number_t hwirq;
- struct irq_fwspec *fwspec = arg;
+ struct irq_fwspec *fwspec = arg, parent_fwspec;
ret = msm_gpio_domain_translate(domain, fwspec, &hwirq, NULL);
if (ret)
return ret;
msm_gpio_domain_set_info(domain, virq, hwirq);
- return ret;
+
+ parent_fwspec = *fwspec;
+ parent_fwspec.fwnode = domain->parent->fwnode;
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+ &parent_fwspec);
}
static const struct irq_domain_ops msm_gpio_domain_ops = {
@@ -873,16 +892,9 @@
unsigned int parent_irq, unsigned int gpio)
{
int irq;
- struct irq_fwspec fwspec;
-
- fwspec.fwnode = domain->fwnode;
- fwspec.param[0] = gpio;
- fwspec.param[1] = IRQ_TYPE_NONE;
- fwspec.param_count = 2;
-
if (gpio != 0) {
- irq = irq_create_fwspec_mapping(&fwspec);
+ irq = irq_find_mapping(domain, gpio);
irq_set_parent(irq, parent_irq);
irq_set_chip(irq, &msm_dirconn_irq_chip);
irq_set_handler_data(parent_irq, irq_get_irq_data(irq));
@@ -1387,7 +1399,14 @@
static int msm_gpiochip_to_irq(struct gpio_chip *chip, unsigned int offset)
{
- return irq_find_mapping(chip->irqdomain, offset);
+ struct irq_fwspec fwspec;
+
+ fwspec.fwnode = of_node_to_fwnode(chip->of_node);
+ fwspec.param[0] = offset;
+ fwspec.param[1] = IRQ_TYPE_NONE;
+ fwspec.param_count = 2;
+
+ return irq_create_fwspec_mapping(&fwspec);
}
static int msm_gpio_init(struct msm_pinctrl *pctrl)
@@ -1395,6 +1414,7 @@
struct gpio_chip *chip;
int ret;
unsigned ngpio = pctrl->soc->ngpios;
+ struct device_node *irq_parent = NULL;
struct irq_domain *domain_parent;
if (WARN_ON(ngpio > MAX_NR_GPIO))
@@ -1407,11 +1427,6 @@
chip->parent = pctrl->dev;
chip->owner = THIS_MODULE;
chip->of_node = pctrl->dev->of_node;
- chip->irqchip = &msm_gpio_irq_chip;
- chip->irq_handler = handle_fasteoi_irq;
- chip->irq_default_type = IRQ_TYPE_NONE;
- chip->to_irq = msm_gpiochip_to_irq;
- chip->lock_key = NULL;
ret = gpiochip_add_data(&pctrl->chip, pctrl);
if (ret) {
@@ -1426,25 +1441,43 @@
return ret;
}
- domain_parent = irq_find_host(of_irq_find_parent(chip->of_node));
- if (!domain_parent) {
- pr_err("unable to find parent domain\n");
- gpiochip_remove(&pctrl->chip);
- return -ENXIO;
- }
+ irq_parent = of_irq_find_parent(chip->of_node);
+ if (of_device_is_compatible(irq_parent, "qcom,mpm-gpio")) {
+ chip->irqchip = &msm_gpio_irq_chip;
+ chip->irq_handler = handle_fasteoi_irq;
+ chip->irq_default_type = IRQ_TYPE_NONE;
+ chip->to_irq = msm_gpiochip_to_irq;
+ chip->lock_key = NULL;
+ domain_parent = irq_find_host(irq_parent);
+ if (!domain_parent) {
+ pr_err("unable to find parent domain\n");
+ gpiochip_remove(&pctrl->chip);
+ return -ENXIO;
+ }
- chip->irqdomain = irq_domain_add_hierarchy(domain_parent, 0,
+ chip->irqdomain = irq_domain_add_hierarchy(domain_parent, 0,
chip->ngpio,
chip->of_node,
&msm_gpio_domain_ops,
chip);
- if (!chip->irqdomain) {
- dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
- chip->irqchip = NULL;
- gpiochip_remove(&pctrl->chip);
- return -ENOSYS;
+ if (!chip->irqdomain) {
+ dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
+ chip->irqchip = NULL;
+ gpiochip_remove(&pctrl->chip);
+ return -ENXIO;
+ }
+ } else {
+ ret = gpiochip_irqchip_add(chip,
+ &msm_gpio_irq_chip,
+ 0,
+ handle_fasteoi_irq,
+ IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
+ gpiochip_remove(&pctrl->chip);
+ return ret;
+ }
}
-
gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip,
pctrl->irq, msm_gpio_irq_handler);
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index bf498f9..b99435d 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -3167,52 +3167,53 @@
EXPORT_SYMBOL(ipa_get_smmu_params);
/**
- * ipa_conn_wdi3_pipes() - connect wdi3 pipes
+ * ipa_conn_wdi_pipes() - connect wdi pipes
*/
-int ipa_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out)
+int ipa_conn_wdi_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out,
+ ipa_wdi_meter_notifier_cb wdi_notify)
{
int ret;
- IPA_API_DISPATCH_RETURN(ipa_conn_wdi3_pipes, in, out);
+ IPA_API_DISPATCH_RETURN(ipa_conn_wdi_pipes, in, out, wdi_notify);
return ret;
}
/**
- * ipa_disconn_wdi3_pipes() - disconnect wdi3 pipes
+ * ipa_disconn_wdi_pipes() - disconnect wdi pipes
*/
-int ipa_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa_disconn_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
{
int ret;
- IPA_API_DISPATCH_RETURN(ipa_disconn_wdi3_pipes, ipa_ep_idx_tx,
+ IPA_API_DISPATCH_RETURN(ipa_disconn_wdi_pipes, ipa_ep_idx_tx,
ipa_ep_idx_rx);
return ret;
}
/**
- * ipa_enable_wdi3_pipes() - enable wdi3 pipes
+ * ipa_enable_wdi_pipes() - enable wdi pipes
*/
-int ipa_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa_enable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
{
int ret;
- IPA_API_DISPATCH_RETURN(ipa_enable_wdi3_pipes, ipa_ep_idx_tx,
+ IPA_API_DISPATCH_RETURN(ipa_enable_wdi_pipes, ipa_ep_idx_tx,
ipa_ep_idx_rx);
return ret;
}
/**
- * ipa_disable_wdi3_pipes() - disable wdi3 pipes
+ * ipa_disable_wdi_pipes() - disable wdi pipes
*/
-int ipa_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa_disable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
{
int ret;
- IPA_API_DISPATCH_RETURN(ipa_disable_wdi3_pipes, ipa_ep_idx_tx,
+ IPA_API_DISPATCH_RETURN(ipa_disable_wdi_pipes, ipa_ep_idx_tx,
ipa_ep_idx_rx);
return ret;
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index 79d0c70..fc4362f 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -403,16 +403,17 @@
void (*ipa_ntn_uc_dereg_rdyCB)(void);
- int (*ipa_conn_wdi3_pipes)(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out);
+ int (*ipa_conn_wdi_pipes)(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out,
+ ipa_wdi_meter_notifier_cb wdi_notify);
- int (*ipa_disconn_wdi3_pipes)(int ipa_ep_idx_tx,
+ int (*ipa_disconn_wdi_pipes)(int ipa_ep_idx_tx,
int ipa_ep_idx_rx);
- int (*ipa_enable_wdi3_pipes)(int ipa_ep_idx_tx,
+ int (*ipa_enable_wdi_pipes)(int ipa_ep_idx_tx,
int ipa_ep_idx_rx);
- int (*ipa_disable_wdi3_pipes)(int ipa_ep_idx_tx,
+ int (*ipa_disable_wdi_pipes)(int ipa_ep_idx_tx,
int ipa_ep_idx_rx);
int (*ipa_tz_unlock_reg)(struct ipa_tz_unlock_reg_info *reg_info,
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
index f4c8763..b2e454a 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-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
@@ -14,9 +14,10 @@
#include <linux/msm_ipa.h>
#include <linux/string.h>
#include "../ipa_common_i.h"
+#include "../ipa_v3/ipa_pm.h"
-#define OFFLOAD_DRV_NAME "ipa_wdi3"
-#define IPA_WDI3_DBG(fmt, args...) \
+#define OFFLOAD_DRV_NAME "ipa_wdi"
+#define IPA_WDI_DBG(fmt, args...) \
do { \
pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
__func__, __LINE__, ## args); \
@@ -26,7 +27,7 @@
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
-#define IPA_WDI3_DBG_LOW(fmt, args...) \
+#define IPA_WDI_DBG_LOW(fmt, args...) \
do { \
pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
__func__, __LINE__, ## args); \
@@ -34,7 +35,7 @@
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
-#define IPA_WDI3_ERR(fmt, args...) \
+#define IPA_WDI_ERR(fmt, args...) \
do { \
pr_err(OFFLOAD_DRV_NAME " %s:%d " fmt, \
__func__, __LINE__, ## args); \
@@ -44,32 +45,107 @@
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
-struct ipa_wdi3_intf_info {
+struct ipa_wdi_intf_info {
char netdev_name[IPA_RESOURCE_NAME_MAX];
u8 hdr_len;
u32 partial_hdr_hdl[IPA_IP_MAX];
struct list_head link;
};
-struct ipa_wdi3_context {
+struct ipa_wdi_context {
struct list_head head_intf_list;
- ipa_notify_cb notify;
- void *priv;
- struct completion wdi3_completion;
+ struct completion wdi_completion;
struct mutex lock;
+ enum ipa_wdi_version wdi_version;
+ u8 is_smmu_enabled;
+ u32 tx_pipe_hdl;
+ u32 rx_pipe_hdl;
+ u8 num_sys_pipe_needed;
+ u32 sys_pipe_hdl[IPA_WDI_MAX_SUPPORTED_SYS_PIPE];
+ u32 ipa_pm_hdl;
+ ipa_wdi_meter_notifier_cb wdi_notify;
};
-static struct ipa_wdi3_context *ipa_wdi3_ctx;
+static struct ipa_wdi_context *ipa_wdi_ctx;
-static int ipa_wdi3_commit_partial_hdr(
+int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
+ struct ipa_wdi_init_out_params *out)
+{
+ struct ipa_wdi_uc_ready_params uc_ready_params;
+ struct ipa_smmu_in_params smmu_in;
+ struct ipa_smmu_out_params smmu_out;
+
+ if (ipa_wdi_ctx) {
+ IPA_WDI_ERR("ipa_wdi_ctx was initialized before\n");
+ return -EFAULT;
+ }
+
+ if (in->wdi_version > IPA_WDI_3 || in->wdi_version < IPA_WDI_1) {
+ IPA_WDI_ERR("wrong wdi version: %d\n", in->wdi_version);
+ return -EFAULT;
+ }
+
+ ipa_wdi_ctx = kzalloc(sizeof(*ipa_wdi_ctx), GFP_KERNEL);
+ if (ipa_wdi_ctx == NULL)
+ return -ENOMEM;
+
+ mutex_init(&ipa_wdi_ctx->lock);
+ init_completion(&ipa_wdi_ctx->wdi_completion);
+ INIT_LIST_HEAD(&ipa_wdi_ctx->head_intf_list);
+
+ ipa_wdi_ctx->wdi_version = in->wdi_version;
+ uc_ready_params.notify = in->notify;
+ uc_ready_params.priv = in->priv;
+ ipa_wdi_ctx->wdi_notify = in->wdi_notify;
+
+ if (ipa_uc_reg_rdyCB(&uc_ready_params) != 0) {
+ mutex_destroy(&ipa_wdi_ctx->lock);
+ kfree(ipa_wdi_ctx);
+ ipa_wdi_ctx = NULL;
+ return -EFAULT;
+ }
+
+ out->is_uC_ready = uc_ready_params.is_uC_ready;
+
+ smmu_in.smmu_client = IPA_SMMU_WLAN_CLIENT;
+ if (ipa_get_smmu_params(&smmu_in, &smmu_out))
+ out->is_smmu_enabled = false;
+ else
+ out->is_smmu_enabled = smmu_out.smmu_enable;
+
+ ipa_wdi_ctx->is_smmu_enabled = out->is_smmu_enabled;
+
+ return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_init);
+
+int ipa_wdi_cleanup(void)
+{
+ struct ipa_wdi_intf_info *entry;
+ struct ipa_wdi_intf_info *next;
+
+ /* clear interface list */
+ list_for_each_entry_safe(entry, next,
+ &ipa_wdi_ctx->head_intf_list, link) {
+ list_del(&entry->link);
+ kfree(entry);
+ }
+ mutex_destroy(&ipa_wdi_ctx->lock);
+ kfree(ipa_wdi_ctx);
+ ipa_wdi_ctx = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_cleanup);
+
+static int ipa_wdi_commit_partial_hdr(
struct ipa_ioc_add_hdr *hdr,
const char *netdev_name,
- struct ipa_wdi3_hdr_info *hdr_info)
+ struct ipa_wdi_hdr_info *hdr_info)
{
int i;
if (!hdr || !hdr_info || !netdev_name) {
- IPA_WDI3_ERR("Invalid input\n");
+ IPA_WDI_ERR("Invalid input\n");
return -EINVAL;
}
@@ -90,18 +166,18 @@
}
if (ipa_add_hdr(hdr)) {
- IPA_WDI3_ERR("fail to add partial headers\n");
+ IPA_WDI_ERR("fail to add partial headers\n");
return -EFAULT;
}
return 0;
}
-int ipa_wdi3_reg_intf(struct ipa_wdi3_reg_intf_in_params *in)
+int ipa_wdi_reg_intf(struct ipa_wdi_reg_intf_in_params *in)
{
struct ipa_ioc_add_hdr *hdr;
- struct ipa_wdi3_intf_info *new_intf;
- struct ipa_wdi3_intf_info *entry;
+ struct ipa_wdi_intf_info *new_intf;
+ struct ipa_wdi_intf_info *entry;
struct ipa_tx_intf tx;
struct ipa_rx_intf rx;
struct ipa_ioc_tx_intf_prop tx_prop[2];
@@ -110,36 +186,30 @@
int ret = 0;
if (in == NULL) {
- IPA_WDI3_ERR("invalid params in=%pK\n", in);
+ IPA_WDI_ERR("invalid params in=NULL\n");
return -EINVAL;
}
- if (!ipa_wdi3_ctx) {
- ipa_wdi3_ctx = kzalloc(sizeof(*ipa_wdi3_ctx), GFP_KERNEL);
- if (ipa_wdi3_ctx == NULL) {
- IPA_WDI3_ERR("fail to alloc wdi3 ctx\n");
- return -ENOMEM;
- }
- mutex_init(&ipa_wdi3_ctx->lock);
- INIT_LIST_HEAD(&ipa_wdi3_ctx->head_intf_list);
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
+ return -EPERM;
}
- IPA_WDI3_DBG("register interface for netdev %s\n",
+ IPA_WDI_DBG("register interface for netdev %s\n",
in->netdev_name);
- mutex_lock(&ipa_wdi3_ctx->lock);
- list_for_each_entry(entry, &ipa_wdi3_ctx->head_intf_list, link)
+ mutex_lock(&ipa_wdi_ctx->lock);
+ list_for_each_entry(entry, &ipa_wdi_ctx->head_intf_list, link)
if (strcmp(entry->netdev_name, in->netdev_name) == 0) {
- IPA_WDI3_DBG("intf was added before.\n");
- mutex_unlock(&ipa_wdi3_ctx->lock);
+ IPA_WDI_DBG("intf was added before\n");
+ mutex_unlock(&ipa_wdi_ctx->lock);
return 0;
}
- IPA_WDI3_DBG("intf was not added before, proceed.\n");
+ IPA_WDI_DBG("intf was not added before, proceed\n");
new_intf = kzalloc(sizeof(*new_intf), GFP_KERNEL);
if (new_intf == NULL) {
- IPA_WDI3_ERR("fail to alloc new intf\n");
- mutex_unlock(&ipa_wdi3_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return -ENOMEM;
}
@@ -152,20 +222,19 @@
len = sizeof(struct ipa_ioc_add_hdr) + 2 * sizeof(struct ipa_hdr_add);
hdr = kzalloc(len, GFP_KERNEL);
if (hdr == NULL) {
- IPA_WDI3_ERR("fail to alloc %d bytes\n", len);
ret = -EFAULT;
goto fail_alloc_hdr;
}
- if (ipa_wdi3_commit_partial_hdr(hdr, in->netdev_name, in->hdr_info)) {
- IPA_WDI3_ERR("fail to commit partial headers\n");
+ if (ipa_wdi_commit_partial_hdr(hdr, in->netdev_name, in->hdr_info)) {
+ IPA_WDI_ERR("fail to commit partial headers\n");
ret = -EFAULT;
goto fail_commit_hdr;
}
new_intf->partial_hdr_hdl[IPA_IP_v4] = hdr->hdr[IPA_IP_v4].hdr_hdl;
new_intf->partial_hdr_hdl[IPA_IP_v6] = hdr->hdr[IPA_IP_v6].hdr_hdl;
- IPA_WDI3_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
+ IPA_WDI_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
hdr->hdr[IPA_IP_v4].hdr_hdl, hdr->hdr[IPA_IP_v6].hdr_hdl);
/* populate tx prop */
@@ -175,12 +244,14 @@
memset(tx_prop, 0, sizeof(tx_prop));
tx_prop[0].ip = IPA_IP_v4;
tx_prop[0].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+ tx_prop[0].alt_dst_pipe = in->alt_dst_pipe;
tx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
strlcpy(tx_prop[0].hdr_name, hdr->hdr[IPA_IP_v4].name,
sizeof(tx_prop[0].hdr_name));
tx_prop[1].ip = IPA_IP_v6;
tx_prop[1].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+ tx_prop[1].alt_dst_pipe = in->alt_dst_pipe;
tx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
strlcpy(tx_prop[1].hdr_name, hdr->hdr[IPA_IP_v6].name,
sizeof(tx_prop[1].hdr_name));
@@ -209,54 +280,53 @@
}
if (ipa_register_intf(in->netdev_name, &tx, &rx)) {
- IPA_WDI3_ERR("fail to add interface prop\n");
+ IPA_WDI_ERR("fail to add interface prop\n");
ret = -EFAULT;
goto fail_commit_hdr;
}
- list_add(&new_intf->link, &ipa_wdi3_ctx->head_intf_list);
- init_completion(&ipa_wdi3_ctx->wdi3_completion);
+ list_add(&new_intf->link, &ipa_wdi_ctx->head_intf_list);
+ init_completion(&ipa_wdi_ctx->wdi_completion);
kfree(hdr);
- mutex_unlock(&ipa_wdi3_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return 0;
fail_commit_hdr:
kfree(hdr);
fail_alloc_hdr:
kfree(new_intf);
- mutex_unlock(&ipa_wdi3_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return ret;
}
-EXPORT_SYMBOL(ipa_wdi3_reg_intf);
+EXPORT_SYMBOL(ipa_wdi_reg_intf);
-int ipa_wdi3_dereg_intf(const char *netdev_name)
+int ipa_wdi_dereg_intf(const char *netdev_name)
{
int len, ret = 0;
struct ipa_ioc_del_hdr *hdr = NULL;
- struct ipa_wdi3_intf_info *entry;
- struct ipa_wdi3_intf_info *next;
+ struct ipa_wdi_intf_info *entry;
+ struct ipa_wdi_intf_info *next;
if (!netdev_name) {
- IPA_WDI3_ERR("no netdev name.\n");
+ IPA_WDI_ERR("no netdev name\n");
return -EINVAL;
}
- if (!ipa_wdi3_ctx) {
- IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
return -EPERM;
}
- mutex_lock(&ipa_wdi3_ctx->lock);
- list_for_each_entry_safe(entry, next, &ipa_wdi3_ctx->head_intf_list,
+ mutex_lock(&ipa_wdi_ctx->lock);
+ list_for_each_entry_safe(entry, next, &ipa_wdi_ctx->head_intf_list,
link)
if (strcmp(entry->netdev_name, netdev_name) == 0) {
len = sizeof(struct ipa_ioc_del_hdr) +
2 * sizeof(struct ipa_hdr_del);
hdr = kzalloc(len, GFP_KERNEL);
if (hdr == NULL) {
- IPA_WDI3_ERR("fail to alloc %d bytes\n", len);
- mutex_unlock(&ipa_wdi3_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return -ENOMEM;
}
@@ -264,20 +334,21 @@
hdr->num_hdls = 2;
hdr->hdl[0].hdl = entry->partial_hdr_hdl[0];
hdr->hdl[1].hdl = entry->partial_hdr_hdl[1];
- IPA_WDI3_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
+ IPA_WDI_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
hdr->hdl[0].hdl, hdr->hdl[1].hdl);
if (ipa_del_hdr(hdr)) {
- IPA_WDI3_ERR("fail to delete partial header\n");
+ IPA_WDI_ERR("fail to delete partial header\n");
ret = -EFAULT;
goto fail;
}
if (ipa_deregister_intf(entry->netdev_name)) {
- IPA_WDI3_ERR("fail to del interface props\n");
+ IPA_WDI_ERR("fail to del interface props\n");
ret = -EFAULT;
goto fail;
}
+
list_del(&entry->link);
kfree(entry);
@@ -286,241 +357,512 @@
fail:
kfree(hdr);
- mutex_unlock(&ipa_wdi3_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return ret;
}
-EXPORT_SYMBOL(ipa_wdi3_dereg_intf);
+EXPORT_SYMBOL(ipa_wdi_dereg_intf);
-static void ipa_wdi3_rm_notify(void *user_data, enum ipa_rm_event event,
+static void ipa_wdi_rm_notify(void *user_data, enum ipa_rm_event event,
unsigned long data)
{
- if (!ipa_wdi3_ctx) {
- IPA_WDI3_ERR("Invalid context\n");
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("Invalid context\n");
return;
}
switch (event) {
case IPA_RM_RESOURCE_GRANTED:
- complete_all(&ipa_wdi3_ctx->wdi3_completion);
+ complete_all(&ipa_wdi_ctx->wdi_completion);
break;
case IPA_RM_RESOURCE_RELEASED:
break;
default:
- IPA_WDI3_ERR("Invalid RM Evt: %d", event);
+ IPA_WDI_ERR("Invalid RM Evt: %d", event);
break;
}
}
-static int ipa_wdi3_cons_release(void)
+static int ipa_wdi_cons_release(void)
{
return 0;
}
-static int ipa_wdi3_cons_request(void)
+static int ipa_wdi_cons_request(void)
{
int ret = 0;
- if (!ipa_wdi3_ctx) {
- IPA_WDI3_ERR("wdi3 ctx is not initialized\n");
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
ret = -EFAULT;
}
return ret;
}
-int ipa_wdi3_conn_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out)
+static void ipa_wdi_pm_cb(void *p, enum ipa_pm_cb_event event)
{
- int ret = 0;
+ IPA_WDI_DBG("received pm event %d\n", event);
+}
+
+int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out)
+{
+ int i, j, ret = 0;
struct ipa_rm_create_params param;
+ struct ipa_pm_register_params pm_params;
+ struct ipa_wdi_in_params in_tx;
+ struct ipa_wdi_in_params in_rx;
+ struct ipa_wdi_out_params out_tx;
+ struct ipa_wdi_out_params out_rx;
if (!(in && out)) {
- IPA_WDI3_ERR("empty parameters. in=%pK out=%pK\n", in, out);
+ IPA_WDI_ERR("empty parameters. in=%pK out=%pK\n", in, out);
return -EINVAL;
}
- if (!ipa_wdi3_ctx) {
- ipa_wdi3_ctx = kzalloc(sizeof(*ipa_wdi3_ctx), GFP_KERNEL);
- if (ipa_wdi3_ctx == NULL) {
- IPA_WDI3_ERR("fail to alloc wdi3 ctx\n");
- return -EFAULT;
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
+ return -EPERM;
+ }
+
+ if (in->num_sys_pipe_needed > IPA_WDI_MAX_SUPPORTED_SYS_PIPE) {
+ IPA_WDI_ERR("ipa can only support up to %d sys pipe\n",
+ IPA_WDI_MAX_SUPPORTED_SYS_PIPE);
+ return -EINVAL;
+ }
+ ipa_wdi_ctx->num_sys_pipe_needed = in->num_sys_pipe_needed;
+ IPA_WDI_DBG("number of sys pipe %d\n", in->num_sys_pipe_needed);
+
+ /* setup sys pipe when needed */
+ for (i = 0; i < ipa_wdi_ctx->num_sys_pipe_needed; i++) {
+ ret = ipa_setup_sys_pipe(&in->sys_in[i],
+ &ipa_wdi_ctx->sys_pipe_hdl[i]);
+ if (ret) {
+ IPA_WDI_ERR("fail to setup sys pipe %d\n", i);
+ ret = -EFAULT;
+ goto fail_setup_sys_pipe;
}
- mutex_init(&ipa_wdi3_ctx->lock);
- INIT_LIST_HEAD(&ipa_wdi3_ctx->head_intf_list);
- }
- ipa_wdi3_ctx->notify = in->notify;
- ipa_wdi3_ctx->priv = in->priv;
-
- memset(¶m, 0, sizeof(param));
- param.name = IPA_RM_RESOURCE_WLAN_PROD;
- param.reg_params.user_data = ipa_wdi3_ctx;
- param.reg_params.notify_cb = ipa_wdi3_rm_notify;
- param.floor_voltage = IPA_VOLTAGE_SVS;
- ret = ipa_rm_create_resource(¶m);
- if (ret) {
- IPA_WDI3_ERR("fail to create WLAN_PROD resource\n");
- return -EFAULT;
}
- memset(¶m, 0, sizeof(param));
- param.name = IPA_RM_RESOURCE_WLAN_CONS;
- param.request_resource = ipa_wdi3_cons_request;
- param.release_resource = ipa_wdi3_cons_release;
- ret = ipa_rm_create_resource(¶m);
- if (ret) {
- IPA_WDI3_ERR("fail to create WLAN_CONS resource\n");
- goto fail_create_rm_cons;
+ if (!ipa_pm_is_used()) {
+ memset(¶m, 0, sizeof(param));
+ param.name = IPA_RM_RESOURCE_WLAN_PROD;
+ param.reg_params.user_data = ipa_wdi_ctx;
+ param.reg_params.notify_cb = ipa_wdi_rm_notify;
+ param.floor_voltage = IPA_VOLTAGE_SVS;
+ ret = ipa_rm_create_resource(¶m);
+ if (ret) {
+ IPA_WDI_ERR("fail to create WLAN_PROD resource\n");
+ ret = -EFAULT;
+ goto fail_setup_sys_pipe;
+ }
+
+ memset(¶m, 0, sizeof(param));
+ param.name = IPA_RM_RESOURCE_WLAN_CONS;
+ param.request_resource = ipa_wdi_cons_request;
+ param.release_resource = ipa_wdi_cons_release;
+ ret = ipa_rm_create_resource(¶m);
+ if (ret) {
+ IPA_WDI_ERR("fail to create WLAN_CONS resource\n");
+ goto fail_create_rm_cons;
+ }
+
+ if (ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+ IPA_RM_RESOURCE_APPS_CONS)) {
+ IPA_WDI_ERR("fail to add rm dependency\n");
+ ret = -EFAULT;
+ goto fail_add_dependency;
+ }
+ } else {
+ pm_params.name = "wdi";
+ pm_params.callback = ipa_wdi_pm_cb;
+ pm_params.user_data = NULL;
+ pm_params.group = IPA_PM_GROUP_DEFAULT;
+ if (ipa_pm_register(&pm_params, &ipa_wdi_ctx->ipa_pm_hdl)) {
+ IPA_WDI_ERR("fail to register ipa pm\n");
+ ret = -EFAULT;
+ goto fail_setup_sys_pipe;
+ }
}
- if (ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
- IPA_RM_RESOURCE_APPS_CONS)) {
- IPA_WDI3_ERR("fail to add rm dependency\n");
- ret = -EFAULT;
- goto fail;
- }
+ if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+ if (ipa_conn_wdi_pipes(in, out, ipa_wdi_ctx->wdi_notify)) {
+ IPA_WDI_ERR("fail to setup wdi pipes\n");
+ ret = -EFAULT;
+ goto fail_connect_pipe;
+ }
+ } else {
+ memset(&in_tx, 0, sizeof(in_tx));
+ memset(&in_rx, 0, sizeof(in_rx));
+ memset(&out_tx, 0, sizeof(out_tx));
+ memset(&out_rx, 0, sizeof(out_rx));
+ in_rx.wdi_notify = ipa_wdi_ctx->wdi_notify;
+ if (in->is_smmu_enabled == false) {
+ /* firsr setup rx pipe */
+ in_rx.sys.ipa_ep_cfg = in->u_rx.rx.ipa_ep_cfg;
+ in_rx.sys.client = in->u_rx.rx.client;
+ in_rx.sys.notify = in->notify;
+ in_rx.sys.priv = in->priv;
+ in_rx.smmu_enabled = in->is_smmu_enabled;
+ in_rx.u.ul.rdy_ring_base_pa =
+ in->u_rx.rx.transfer_ring_base_pa;
+ in_rx.u.ul.rdy_ring_size =
+ in->u_rx.rx.transfer_ring_size;
+ in_rx.u.ul.rdy_ring_rp_pa =
+ in->u_rx.rx.transfer_ring_doorbell_pa;
+ in_rx.u.ul.rdy_comp_ring_base_pa =
+ in->u_rx.rx.event_ring_base_pa;
+ in_rx.u.ul.rdy_comp_ring_wp_pa =
+ in->u_rx.rx.event_ring_doorbell_pa;
+ in_rx.u.ul.rdy_comp_ring_size =
+ in->u_rx.rx.event_ring_size;
+ if (ipa_connect_wdi_pipe(&in_rx, &out_rx)) {
+ IPA_WDI_ERR("fail to setup rx pipe\n");
+ ret = -EFAULT;
+ goto fail_connect_pipe;
+ }
+ ipa_wdi_ctx->rx_pipe_hdl = out_rx.clnt_hdl;
+ out->rx_uc_db_pa = out_rx.uc_door_bell_pa;
+ IPA_WDI_DBG("rx uc db pa: 0x%pad\n", &out->rx_uc_db_pa);
- if (ipa_conn_wdi3_pipes(in, out)) {
- IPA_WDI3_ERR("fail to setup wdi3 pipes\n");
- ret = -EFAULT;
- goto fail;
+ /* then setup tx pipe */
+ in_tx.sys.ipa_ep_cfg = in->u_tx.tx.ipa_ep_cfg;
+ in_tx.sys.client = in->u_tx.tx.client;
+ in_tx.smmu_enabled = in->is_smmu_enabled;
+ in_tx.u.dl.comp_ring_base_pa =
+ in->u_tx.tx.transfer_ring_base_pa;
+ in_tx.u.dl.comp_ring_size =
+ in->u_tx.tx.transfer_ring_size;
+ in_tx.u.dl.ce_ring_base_pa =
+ in->u_tx.tx.event_ring_base_pa;
+ in_tx.u.dl.ce_door_bell_pa =
+ in->u_tx.tx.event_ring_doorbell_pa;
+ in_tx.u.dl.ce_ring_size =
+ in->u_tx.tx.event_ring_size;
+ in_tx.u.dl.num_tx_buffers =
+ in->u_tx.tx.num_pkt_buffers;
+ if (ipa_connect_wdi_pipe(&in_tx, &out_tx)) {
+ IPA_WDI_ERR("fail to setup tx pipe\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ ipa_wdi_ctx->tx_pipe_hdl = out_tx.clnt_hdl;
+ out->tx_uc_db_pa = out_tx.uc_door_bell_pa;
+ IPA_WDI_DBG("tx uc db pa: 0x%pad\n", &out->tx_uc_db_pa);
+ } else { /* smmu is enabled */
+ /* firsr setup rx pipe */
+ in_rx.sys.ipa_ep_cfg = in->u_rx.rx_smmu.ipa_ep_cfg;
+ in_rx.sys.client = in->u_rx.rx_smmu.client;
+ in_rx.sys.notify = in->notify;
+ in_rx.sys.priv = in->priv;
+ in_rx.smmu_enabled = in->is_smmu_enabled;
+ in_rx.u.ul_smmu.rdy_ring =
+ in->u_rx.rx_smmu.transfer_ring_base;
+ in_rx.u.ul_smmu.rdy_ring_size =
+ in->u_rx.rx_smmu.transfer_ring_size;
+ in_rx.u.ul_smmu.rdy_ring_rp_pa =
+ in->u_rx.rx_smmu.transfer_ring_doorbell_pa;
+ in_rx.u.ul_smmu.rdy_comp_ring =
+ in->u_rx.rx_smmu.event_ring_base;
+ in_rx.u.ul_smmu.rdy_comp_ring_wp_pa =
+ in->u_rx.rx_smmu.event_ring_doorbell_pa;
+ in_rx.u.ul_smmu.rdy_comp_ring_size =
+ in->u_rx.rx_smmu.event_ring_size;
+ if (ipa_connect_wdi_pipe(&in_rx, &out_rx)) {
+ IPA_WDI_ERR("fail to setup rx pipe\n");
+ ret = -EFAULT;
+ goto fail_connect_pipe;
+ }
+ ipa_wdi_ctx->rx_pipe_hdl = out_rx.clnt_hdl;
+ out->rx_uc_db_pa = out_rx.uc_door_bell_pa;
+ IPA_WDI_DBG("rx uc db pa: 0x%pad\n", &out->rx_uc_db_pa);
+
+ /* then setup tx pipe */
+ in_tx.sys.ipa_ep_cfg = in->u_tx.tx_smmu.ipa_ep_cfg;
+ in_tx.sys.client = in->u_tx.tx_smmu.client;
+ in_tx.smmu_enabled = in->is_smmu_enabled;
+ in_tx.u.dl_smmu.comp_ring =
+ in->u_tx.tx_smmu.transfer_ring_base;
+ in_tx.u.dl_smmu.comp_ring_size =
+ in->u_tx.tx_smmu.transfer_ring_size;
+ in_tx.u.dl_smmu.ce_ring =
+ in->u_tx.tx_smmu.event_ring_base;
+ in_tx.u.dl_smmu.ce_door_bell_pa =
+ in->u_tx.tx_smmu.event_ring_doorbell_pa;
+ in_tx.u.dl_smmu.ce_ring_size =
+ in->u_tx.tx_smmu.event_ring_size;
+ in_tx.u.dl_smmu.num_tx_buffers =
+ in->u_tx.tx_smmu.num_pkt_buffers;
+ if (ipa_connect_wdi_pipe(&in_tx, &out_tx)) {
+ IPA_WDI_ERR("fail to setup tx pipe\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ ipa_wdi_ctx->tx_pipe_hdl = out_tx.clnt_hdl;
+ out->tx_uc_db_pa = out_tx.uc_door_bell_pa;
+ IPA_WDI_DBG("tx uc db pa: 0x%pad\n", &out->tx_uc_db_pa);
+ }
}
return 0;
fail:
- ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
+ ipa_disconnect_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl);
+fail_connect_pipe:
+ if (!ipa_pm_is_used())
+ ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+ IPA_RM_RESOURCE_APPS_CONS);
+ else
+ ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl);
+fail_add_dependency:
+ if (!ipa_pm_is_used())
+ ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
fail_create_rm_cons:
- ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
-
+ if (!ipa_pm_is_used())
+ ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
+fail_setup_sys_pipe:
+ for (j = 0; j < i; j++)
+ ipa_teardown_sys_pipe(ipa_wdi_ctx->sys_pipe_hdl[j]);
return ret;
}
-EXPORT_SYMBOL(ipa_wdi3_conn_pipes);
+EXPORT_SYMBOL(ipa_wdi_conn_pipes);
-int ipa_wdi3_disconn_pipes(void)
+int ipa_wdi_disconn_pipes(void)
{
- int ipa_ep_idx_rx, ipa_ep_idx_tx;
+ int i, ipa_ep_idx_rx, ipa_ep_idx_tx;
- if (!ipa_wdi3_ctx) {
- IPA_WDI3_ERR("wdi3 ctx is not initialized\n");
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
return -EPERM;
}
- ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
- ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
- if (ipa_disconn_wdi3_pipes(ipa_ep_idx_rx, ipa_ep_idx_tx)) {
- IPA_WDI3_ERR("fail to tear down wdi3 pipes\n");
- return -EFAULT;
- }
-
- if (ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD,
- IPA_RM_RESOURCE_APPS_CONS)) {
- IPA_WDI3_ERR("fail to delete rm dependency\n");
- return -EFAULT;
- }
-
- if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
- IPA_WDI3_ERR("fail to delete WLAN_PROD resource\n");
- return -EFAULT;
- }
-
- if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS)) {
- IPA_WDI3_ERR("fail to delete WLAN_CONS resource\n");
- return -EFAULT;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(ipa_wdi3_disconn_pipes);
-
-int ipa_wdi3_enable_pipes(void)
-{
- int ret;
- int ipa_ep_idx_tx, ipa_ep_idx_rx;
-
- if (!ipa_wdi3_ctx) {
- IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
- return -EPERM;
- }
-
- ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
- ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
- if (ipa_enable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
- IPA_WDI3_ERR("fail to enable wdi3 pipes\n");
- return -EFAULT;
- }
-
- ret = ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD);
- if (ret == -EINPROGRESS) {
- if (wait_for_completion_timeout(&ipa_wdi3_ctx->wdi3_completion,
- 10*HZ) == 0) {
- IPA_WDI3_ERR("WLAN_PROD resource req time out\n");
+ /* tear down sys pipe if needed */
+ for (i = 0; i < ipa_wdi_ctx->num_sys_pipe_needed; i++) {
+ if (ipa_teardown_sys_pipe(ipa_wdi_ctx->sys_pipe_hdl[i])) {
+ IPA_WDI_ERR("fail to tear down sys pipe %d\n", i);
return -EFAULT;
}
- } else if (ret != 0) {
- IPA_WDI3_ERR("fail to request resource\n");
- return -EFAULT;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(ipa_wdi3_enable_pipes);
-
-int ipa_wdi3_disable_pipes(void)
-{
- int ret;
- int ipa_ep_idx_tx, ipa_ep_idx_rx;
-
- if (!ipa_wdi3_ctx) {
- IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
- return -EPERM;
- }
-
- ret = ipa_rm_release_resource(IPA_RM_RESOURCE_WLAN_PROD);
- if (ret != 0) {
- IPA_WDI3_ERR("fail to release resource\n");
- return -EFAULT;
}
ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
- if (ipa_disable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
- IPA_WDI3_ERR("fail to disable wdi3 pipes\n");
- return -EFAULT;
+
+ if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+ if (ipa_disconn_wdi_pipes(ipa_ep_idx_rx, ipa_ep_idx_tx)) {
+ IPA_WDI_ERR("fail to tear down wdi pipes\n");
+ return -EFAULT;
+ }
+ } else {
+ if (ipa_disconnect_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to tear down wdi tx pipes\n");
+ return -EFAULT;
+ }
+ if (ipa_disconnect_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to tear down wdi rx pipes\n");
+ return -EFAULT;
+ }
+ }
+
+ if (!ipa_pm_is_used()) {
+ if (ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+ IPA_RM_RESOURCE_APPS_CONS)) {
+ IPA_WDI_ERR("fail to delete rm dependency\n");
+ return -EFAULT;
+ }
+
+ if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
+ IPA_WDI_ERR("fail to delete WLAN_PROD resource\n");
+ return -EFAULT;
+ }
+
+ if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS)) {
+ IPA_WDI_ERR("fail to delete WLAN_CONS resource\n");
+ return -EFAULT;
+ }
+ } else {
+ if (ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl)) {
+ IPA_WDI_ERR("fail to deregister ipa pm\n");
+ return -EFAULT;
+ }
}
return 0;
}
-EXPORT_SYMBOL(ipa_wdi3_disable_pipes);
+EXPORT_SYMBOL(ipa_wdi_disconn_pipes);
-int ipa_wdi3_set_perf_profile(struct ipa_wdi3_perf_profile *profile)
+int ipa_wdi_enable_pipes(void)
+{
+ int ret;
+ int ipa_ep_idx_tx, ipa_ep_idx_rx;
+
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
+ return -EPERM;
+ }
+
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
+
+ if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+ if (ipa_enable_wdi_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
+ IPA_WDI_ERR("fail to enable wdi pipes\n");
+ return -EFAULT;
+ }
+ } else {
+ if (ipa_enable_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to enable wdi tx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa_resume_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to resume wdi tx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa_enable_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to enable wdi rx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa_resume_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to resume wdi rx pipe\n");
+ return -EFAULT;
+ }
+ }
+
+ if (!ipa_pm_is_used()) {
+ ret = ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD);
+ if (ret == -EINPROGRESS) {
+ if (wait_for_completion_timeout(
+ &ipa_wdi_ctx->wdi_completion, 10*HZ) == 0) {
+ IPA_WDI_ERR("WLAN_PROD res req time out\n");
+ return -EFAULT;
+ }
+ } else if (ret != 0) {
+ IPA_WDI_ERR("fail to request resource\n");
+ return -EFAULT;
+ }
+ } else {
+ ret = ipa_pm_activate_sync(ipa_wdi_ctx->ipa_pm_hdl);
+ if (ret) {
+ IPA_WDI_ERR("fail to activate ipa pm\n");
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_enable_pipes);
+
+int ipa_wdi_disable_pipes(void)
+{
+ int ret;
+ int ipa_ep_idx_tx, ipa_ep_idx_rx;
+
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized.\n");
+ return -EPERM;
+ }
+
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
+
+ if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+ if (ipa_disable_wdi_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
+ IPA_WDI_ERR("fail to disable wdi pipes\n");
+ return -EFAULT;
+ }
+ } else {
+ if (ipa_suspend_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to suspend wdi tx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa_disable_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to disable wdi tx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa_suspend_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to suspend wdi rx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa_disable_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to disable wdi rx pipe\n");
+ return -EFAULT;
+ }
+ }
+
+ if (!ipa_pm_is_used()) {
+ ret = ipa_rm_release_resource(IPA_RM_RESOURCE_WLAN_PROD);
+ if (ret != 0) {
+ IPA_WDI_ERR("fail to release resource\n");
+ return -EFAULT;
+ }
+ } else {
+ ret = ipa_pm_deactivate_sync(ipa_wdi_ctx->ipa_pm_hdl);
+ if (ret) {
+ IPA_WDI_ERR("fail to deactivate ipa pm\n");
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_disable_pipes);
+
+int ipa_wdi_set_perf_profile(struct ipa_wdi_perf_profile *profile)
{
struct ipa_rm_perf_profile rm_profile;
enum ipa_rm_resource_name resource_name;
if (profile == NULL) {
- IPA_WDI3_ERR("Invalid input\n");
+ IPA_WDI_ERR("Invalid input\n");
return -EINVAL;
}
- rm_profile.max_supported_bandwidth_mbps =
- profile->max_supported_bw_mbps;
+ if (!ipa_pm_is_used()) {
+ rm_profile.max_supported_bandwidth_mbps =
+ profile->max_supported_bw_mbps;
- if (profile->client == IPA_CLIENT_WLAN1_PROD) {
- resource_name = IPA_RM_RESOURCE_WLAN_PROD;
- } else if (profile->client == IPA_CLIENT_WLAN1_CONS) {
- resource_name = IPA_RM_RESOURCE_WLAN_CONS;
+ if (profile->client == IPA_CLIENT_WLAN1_PROD) {
+ resource_name = IPA_RM_RESOURCE_WLAN_PROD;
+ } else if (profile->client == IPA_CLIENT_WLAN1_CONS) {
+ resource_name = IPA_RM_RESOURCE_WLAN_CONS;
+ } else {
+ IPA_WDI_ERR("not supported\n");
+ return -EINVAL;
+ }
+
+ if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
+ IPA_WDI_ERR("fail to setup rm perf profile\n");
+ return -EFAULT;
+ }
} else {
- IPA_WDI3_ERR("not supported\n");
- return -EINVAL;
- }
-
- if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
- IPA_WDI3_ERR("fail to setup rm perf profile\n");
- return -EFAULT;
+ if (ipa_pm_set_perf_profile(ipa_wdi_ctx->ipa_pm_hdl,
+ profile->max_supported_bw_mbps)) {
+ IPA_WDI_ERR("fail to setup pm perf profile\n");
+ return -EFAULT;
+ }
}
return 0;
}
-EXPORT_SYMBOL(ipa_wdi3_set_perf_profile);
+EXPORT_SYMBOL(ipa_wdi_set_perf_profile);
+
+int ipa_wdi_create_smmu_mapping(u32 num_buffers,
+ struct ipa_wdi_buffer_info *info)
+{
+ return ipa_create_wdi_mapping(num_buffers, info);
+}
+EXPORT_SYMBOL(ipa_wdi_create_smmu_mapping);
+
+int ipa_wdi_release_smmu_mapping(u32 num_buffers,
+ struct ipa_wdi_buffer_info *info)
+{
+ return ipa_release_wdi_mapping(num_buffers, info);
+}
+EXPORT_SYMBOL(ipa_wdi_release_smmu_mapping);
+
+int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats)
+{
+ return ipa_get_wdi_stats(stats);
+}
+EXPORT_SYMBOL(ipa_wdi_get_stats);
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 98a1cf9..b37a127 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_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
@@ -419,14 +419,15 @@
void *user_data);
void ipa_ntn_uc_dereg_rdyCB(void);
-int ipa_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out);
+int ipa_conn_wdi_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out,
+ ipa_wdi_meter_notifier_cb wdi_notify);
-int ipa_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa_disconn_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
-int ipa_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa_enable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
-int ipa_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa_disable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
const char *ipa_get_version_string(enum ipa_hw_type ver);
int ipa_start_gsi_channel(u32 clnt_hdl);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 78d1c96..e43a201 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -4358,7 +4358,7 @@
else
IPADBG(":ipa Uc interface init ok\n");
- result = ipa_wdi_init();
+ result = ipa2_wdi_init();
if (result)
IPAERR(":wdi init failed (%d)\n", -result);
else
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 91017a5..bd7f600 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -67,6 +67,16 @@
#define IPA_MAX_NUM_REQ_CACHE 10
#define IPA_IPC_LOG_PAGES 50
+#define IPA_WDI_RX_RING_RES 0
+#define IPA_WDI_RX_RING_RP_RES 1
+#define IPA_WDI_RX_COMP_RING_RES 2
+#define IPA_WDI_RX_COMP_RING_WP_RES 3
+#define IPA_WDI_TX_RING_RES 4
+#define IPA_WDI_CE_RING_RES 5
+#define IPA_WDI_CE_DB_RES 6
+#define IPA_WDI_TX_DB_RES 7
+#define IPA_WDI_MAX_RES 8
+
#define IPADBG(fmt, args...) \
do { \
pr_debug(DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args);\
@@ -1578,8 +1588,9 @@
int ipa2_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
void ipa2_ntn_uc_dereg_rdyCB(void);
-int ipa2_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out);
+int ipa2_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out,
+ ipa_wdi_meter_notifier_cb wdi_notify);
int ipa2_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
int ipa2_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
int ipa2_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
@@ -1601,6 +1612,9 @@
*/
int ipa2_uc_dereg_rdyCB(void);
+int ipa2_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+ phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
+ unsigned long *iova);
/*
* Tethering bridge (Rmnet / MBIM)
*/
@@ -1864,7 +1878,7 @@
int ipa_active_clients_trylock(unsigned long *flags);
void ipa_active_clients_unlock(void);
void ipa_active_clients_trylock_unlock(unsigned long *flags);
-int ipa_wdi_init(void);
+int ipa2_wdi_init(void);
int ipa_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id);
int ipa_tag_process(struct ipa_desc *desc, int num_descs,
unsigned long timeout);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index a3db092..66a8d0b 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -51,6 +51,7 @@
u32 tmp[IPA_RT_FLT_HW_RULE_BUF_SIZE/4];
u8 *start;
int pipe_idx;
+ struct ipa_hdr_entry *hdr_entry;
if (buf == NULL) {
memset(tmp, 0, (IPA_RT_FLT_HW_RULE_BUF_SIZE/4));
@@ -74,6 +75,18 @@
}
rule_hdr->u.hdr.pipe_dest_idx = pipe_idx;
rule_hdr->u.hdr.system = !ipa_ctx->hdr_tbl_lcl;
+
+ /* Adding check to confirm still
+ * header entry present in header table or not
+ */
+
+ if (entry->hdr) {
+ hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+ if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL("Header entry already deleted\n");
+ return -EPERM;
+ }
+ }
if (entry->hdr) {
if (entry->hdr->cookie == IPA_HDR_COOKIE) {
rule_hdr->u.hdr.hdr_offset =
@@ -140,6 +153,8 @@
u32 tmp[IPA_RT_FLT_HW_RULE_BUF_SIZE/4];
u8 *start;
int pipe_idx;
+ struct ipa_hdr_entry *hdr_entry;
+ struct ipa_hdr_proc_ctx_entry *hdr_proc_entry;
if (buf == NULL) {
memset(tmp, 0, IPA_RT_FLT_HW_RULE_BUF_SIZE);
@@ -162,6 +177,24 @@
return -EPERM;
}
rule_hdr->u.hdr_v2_5.pipe_dest_idx = pipe_idx;
+ /* Adding check to confirm still
+ * header entry present in header table or not
+ */
+
+ if (entry->hdr) {
+ hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+ if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL("Header entry already deleted\n");
+ return -EPERM;
+ }
+ } else if (entry->proc_ctx) {
+ hdr_proc_entry = ipa_id_find(entry->rule.hdr_proc_ctx_hdl);
+ if (!hdr_proc_entry ||
+ hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+ IPAERR_RL("Proc header entry already deleted\n");
+ return -EPERM;
+ }
+ }
if (entry->proc_ctx || (entry->hdr && entry->hdr->is_hdr_proc_ctx)) {
struct ipa_hdr_proc_ctx_entry *proc_ctx;
@@ -1132,6 +1165,8 @@
{
struct ipa_rt_entry *entry;
int id;
+ struct ipa_hdr_entry *hdr_entry;
+ struct ipa_hdr_proc_ctx_entry *hdr_proc_entry;
entry = ipa_id_find(rule_hdl);
@@ -1153,6 +1188,24 @@
return -EINVAL;
}
}
+ /* Adding check to confirm still
+ * header entry present in header table or not
+ */
+
+ if (entry->hdr) {
+ hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+ if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL("Header entry already deleted\n");
+ return -EINVAL;
+ }
+ } else if (entry->proc_ctx) {
+ hdr_proc_entry = ipa_id_find(entry->rule.hdr_proc_ctx_hdl);
+ if (!hdr_proc_entry ||
+ hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+ IPAERR_RL("Proc header entry already deleted\n");
+ return -EINVAL;
+ }
+ }
if (entry->hdr)
__ipa_release_hdr(entry->hdr->id);
@@ -1466,6 +1519,7 @@
{
struct ipa_rt_entry *entry;
struct ipa_hdr_entry *hdr = NULL;
+ struct ipa_hdr_entry *hdr_entry;
if (rtrule->rule.hdr_hdl) {
hdr = ipa_id_find(rtrule->rule.hdr_hdl);
@@ -1486,6 +1540,17 @@
goto error;
}
+ /* Adding check to confirm still
+ * header entry present in header table or not
+ */
+
+ if (entry->hdr) {
+ hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+ if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL("Header entry already deleted\n");
+ return -EPERM;
+ }
+ }
if (entry->hdr)
entry->hdr->ref_cnt--;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
index cf8f0b8..459c207 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
@@ -26,15 +26,6 @@
#define IPA_WDI_RESUMED BIT(2)
#define IPA_UC_POLL_SLEEP_USEC 100
-#define IPA_WDI_RX_RING_RES 0
-#define IPA_WDI_RX_RING_RP_RES 1
-#define IPA_WDI_RX_COMP_RING_RES 2
-#define IPA_WDI_RX_COMP_RING_WP_RES 3
-#define IPA_WDI_TX_RING_RES 4
-#define IPA_WDI_CE_RING_RES 5
-#define IPA_WDI_CE_DB_RES 6
-#define IPA_WDI_MAX_RES 7
-
struct ipa_wdi_res {
struct ipa_wdi_buffer_info *res;
unsigned int nents;
@@ -448,7 +439,7 @@
return 0;
}
-int ipa_wdi_init(void)
+int ipa2_wdi_init(void)
{
struct ipa_uc_hdlrs uc_wdi_cbs = { 0 };
@@ -629,7 +620,7 @@
}
}
-static int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+int ipa2_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
unsigned long *iova)
{
@@ -845,7 +836,7 @@
in->smmu_enabled,
in->u.dl_smmu.comp_ring_size,
in->u.dl.comp_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
in->smmu_enabled,
in->u.dl.comp_ring_base_pa,
&in->u.dl_smmu.comp_ring,
@@ -870,7 +861,7 @@
in->smmu_enabled,
in->u.dl_smmu.ce_ring_size,
in->u.dl.ce_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
in->smmu_enabled,
in->u.dl.ce_ring_base_pa,
&in->u.dl_smmu.ce_ring,
@@ -891,7 +882,7 @@
pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa :
in->u.dl.ce_door_bell_pa;
- if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
in->smmu_enabled,
pa,
NULL,
@@ -919,7 +910,7 @@
in->smmu_enabled,
in->u.dl_smmu.comp_ring_size,
in->u.dl.comp_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
in->smmu_enabled,
in->u.dl.comp_ring_base_pa,
&in->u.dl_smmu.comp_ring,
@@ -939,7 +930,7 @@
in->smmu_enabled,
in->u.dl_smmu.ce_ring_size,
in->u.dl.ce_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
in->smmu_enabled,
in->u.dl.ce_ring_base_pa,
&in->u.dl_smmu.ce_ring,
@@ -954,7 +945,7 @@
tx->ce_ring_size = len;
pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa :
in->u.dl.ce_door_bell_pa;
- if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
in->smmu_enabled,
pa,
NULL,
@@ -995,7 +986,7 @@
in->smmu_enabled,
in->u.ul_smmu.rdy_ring_size,
in->u.ul.rdy_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
in->smmu_enabled,
in->u.ul.rdy_ring_base_pa,
&in->u.ul_smmu.rdy_ring,
@@ -1016,7 +1007,7 @@
pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa :
in->u.ul.rdy_ring_rp_pa;
- if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
in->smmu_enabled,
pa,
NULL,
@@ -1040,7 +1031,8 @@
in->smmu_enabled,
in->u.ul_smmu.rdy_comp_ring_size,
in->u.ul.rdy_comp_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_COMP_RING_RES,
+ if (ipa2_create_uc_smmu_mapping(
+ IPA_WDI_RX_COMP_RING_RES,
in->smmu_enabled,
in->u.ul.rdy_comp_ring_base_pa,
&in->u.ul_smmu.rdy_comp_ring,
@@ -1062,7 +1054,7 @@
pa = in->smmu_enabled ?
in->u.ul_smmu.rdy_comp_ring_wp_pa :
in->u.ul.rdy_comp_ring_wp_pa;
- if (ipa_create_uc_smmu_mapping(
+ if (ipa2_create_uc_smmu_mapping(
IPA_WDI_RX_COMP_RING_WP_RES,
in->smmu_enabled,
pa,
@@ -1090,7 +1082,7 @@
in->smmu_enabled,
in->u.ul_smmu.rdy_ring_size,
in->u.ul.rdy_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
in->smmu_enabled,
in->u.ul.rdy_ring_base_pa,
&in->u.ul_smmu.rdy_ring,
@@ -1106,7 +1098,7 @@
pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa :
in->u.ul.rdy_ring_rp_pa;
- if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
in->smmu_enabled,
pa,
NULL,
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index 27120c8..c9273ec 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -5160,10 +5160,10 @@
api_ctrl->ipa_get_pdev = ipa2_get_pdev;
api_ctrl->ipa_ntn_uc_reg_rdyCB = ipa2_ntn_uc_reg_rdyCB;
api_ctrl->ipa_ntn_uc_dereg_rdyCB = ipa2_ntn_uc_dereg_rdyCB;
- api_ctrl->ipa_conn_wdi3_pipes = ipa2_conn_wdi3_pipes;
- api_ctrl->ipa_disconn_wdi3_pipes = ipa2_disconn_wdi3_pipes;
- api_ctrl->ipa_enable_wdi3_pipes = ipa2_enable_wdi3_pipes;
- api_ctrl->ipa_disable_wdi3_pipes = ipa2_disable_wdi3_pipes;
+ api_ctrl->ipa_conn_wdi_pipes = ipa2_conn_wdi3_pipes;
+ api_ctrl->ipa_disconn_wdi_pipes = ipa2_disconn_wdi3_pipes;
+ api_ctrl->ipa_enable_wdi_pipes = ipa2_enable_wdi3_pipes;
+ api_ctrl->ipa_disable_wdi_pipes = ipa2_disable_wdi3_pipes;
api_ctrl->ipa_pm_is_used = ipa2_pm_is_used;
return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c b/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c
index a2c33a1..62748b2 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-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
@@ -10,43 +10,27 @@
* GNU General Public License for more details.
*/
#include "ipa_i.h"
-#include "ipa_uc_offload_i.h"
#include <linux/ipa_wdi3.h>
#define IPA_HW_WDI3_RX_MBOX_START_INDEX 48
#define IPA_HW_WDI3_TX_MBOX_START_INDEX 50
static int ipa_send_wdi3_setup_pipe_cmd(
- struct ipa_wdi3_setup_info *info, u8 dir)
+ u8 is_smmu_enabled, struct ipa_wdi_pipe_setup_info *info,
+ struct ipa_wdi_pipe_setup_info_smmu *info_smmu, u8 dir)
{
int ipa_ep_idx;
- int result = 0;
+ int result = 0, len;
+ unsigned long va;
struct ipa_mem_buffer cmd;
struct IpaHwWdi3SetUpCmdData_t *wdi3_params;
struct IpaHwOffloadSetUpCmdData_t *cmd_data;
- if (info == NULL) {
+ if (info == NULL || info_smmu == NULL) {
IPAERR("invalid input\n");
return -EINVAL;
}
- ipa_ep_idx = ipa_get_ep_mapping(info->client);
- IPAERR("ep number: %d\n", ipa_ep_idx);
- if (ipa_ep_idx == -1) {
- IPAERR("fail to get ep idx.\n");
- return -EFAULT;
- }
-
- IPAERR("client=%d ep=%d\n", info->client, ipa_ep_idx);
- IPAERR("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
- IPAERR("ring_size = %hu\n", info->transfer_ring_size);
- IPAERR("ring_db_pa = 0x%pad\n", &info->transfer_ring_doorbell_pa);
- IPAERR("evt_ring_base_pa = 0x%pad\n", &info->event_ring_base_pa);
- IPAERR("evt_ring_size = %hu\n", info->event_ring_size);
- IPAERR("evt_ring_db_pa = 0x%pad\n", &info->event_ring_doorbell_pa);
- IPAERR("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
- IPAERR("pkt_offset = %d.\n", info->pkt_offset);
-
cmd.size = sizeof(*cmd_data);
cmd.base = dma_alloc_coherent(ipa_ctx->uc_pdev, cmd.size,
&cmd.phys_base, GFP_KERNEL);
@@ -54,35 +38,181 @@
IPAERR("fail to get DMA memory.\n");
return -ENOMEM;
}
- IPAERR("suceeded in allocating memory.\n");
cmd_data = (struct IpaHwOffloadSetUpCmdData_t *)cmd.base;
cmd_data->protocol = IPA_HW_FEATURE_WDI3;
- wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
- wdi3_params->transfer_ring_base_pa = (u32)info->transfer_ring_base_pa;
- wdi3_params->transfer_ring_base_pa_hi =
- (u32)((u64)info->transfer_ring_base_pa >> 32);
- wdi3_params->transfer_ring_size = info->transfer_ring_size;
- wdi3_params->transfer_ring_doorbell_pa =
- (u32)info->transfer_ring_doorbell_pa;
- wdi3_params->transfer_ring_doorbell_pa_hi =
- (u32)((u64)info->transfer_ring_doorbell_pa >> 32);
- wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
- wdi3_params->event_ring_base_pa_hi =
- (u32)((u64)info->event_ring_base_pa >> 32);
- wdi3_params->event_ring_size = info->event_ring_size;
- wdi3_params->event_ring_doorbell_pa =
- (u32)info->event_ring_doorbell_pa;
- wdi3_params->event_ring_doorbell_pa_hi =
- (u32)((u64)info->event_ring_doorbell_pa >> 32);
- wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
- wdi3_params->ipa_pipe_number = ipa_ep_idx;
- wdi3_params->dir = dir;
- wdi3_params->pkt_offset = info->pkt_offset;
- memcpy(wdi3_params->desc_format_template, info->desc_format_template,
- sizeof(wdi3_params->desc_format_template));
- IPAERR("suceeded in populating the command memory.\n");
+ if (!is_smmu_enabled) {
+ ipa_ep_idx = ipa_get_ep_mapping(info->client);
+ if (ipa_ep_idx == -1) {
+ IPAERR("fail to get ep idx.\n");
+ return -EFAULT;
+ }
+
+ IPADBG("client=%d ep=%d\n", info->client, ipa_ep_idx);
+ IPADBG("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
+ IPADBG("ring_size = %hu\n", info->transfer_ring_size);
+ IPADBG("ring_db_pa = 0x%pad\n",
+ &info->transfer_ring_doorbell_pa);
+ IPADBG("evt_ring_base_pa = 0x%pad\n",
+ &info->event_ring_base_pa);
+ IPADBG("evt_ring_size = %hu\n", info->event_ring_size);
+ IPADBG("evt_ring_db_pa = 0x%pad\n",
+ &info->event_ring_doorbell_pa);
+ IPADBG("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
+ IPADBG("pkt_offset = %d\n", info->pkt_offset);
+
+ wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+ wdi3_params->transfer_ring_base_pa =
+ (u32)info->transfer_ring_base_pa;
+ wdi3_params->transfer_ring_base_pa_hi =
+ (u32)((u64)info->transfer_ring_base_pa >> 32);
+ wdi3_params->transfer_ring_size = info->transfer_ring_size;
+ wdi3_params->transfer_ring_doorbell_pa =
+ (u32)info->transfer_ring_doorbell_pa;
+ wdi3_params->transfer_ring_doorbell_pa_hi =
+ (u32)((u64)info->transfer_ring_doorbell_pa >> 32);
+ wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
+ wdi3_params->event_ring_base_pa_hi =
+ (u32)((u64)info->event_ring_base_pa >> 32);
+ wdi3_params->event_ring_size = info->event_ring_size;
+ wdi3_params->event_ring_doorbell_pa =
+ (u32)info->event_ring_doorbell_pa;
+ wdi3_params->event_ring_doorbell_pa_hi =
+ (u32)((u64)info->event_ring_doorbell_pa >> 32);
+ wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
+ wdi3_params->ipa_pipe_number = ipa_ep_idx;
+ wdi3_params->dir = dir;
+ wdi3_params->pkt_offset = info->pkt_offset;
+ memcpy(wdi3_params->desc_format_template,
+ info->desc_format_template,
+ sizeof(wdi3_params->desc_format_template));
+ } else {
+ ipa_ep_idx = ipa_get_ep_mapping(info_smmu->client);
+ if (ipa_ep_idx == -1) {
+ IPAERR("fail to get ep idx\n");
+ return -EFAULT;
+ }
+
+ IPADBG("client=%d ep=%d\n", info_smmu->client, ipa_ep_idx);
+ IPADBG("ring_size = %hu\n", info_smmu->transfer_ring_size);
+ IPADBG("ring_db_pa = 0x%pad\n",
+ &info_smmu->transfer_ring_doorbell_pa);
+ IPADBG("evt_ring_size = %hu\n", info_smmu->event_ring_size);
+ IPADBG("evt_ring_db_pa = 0x%pad\n",
+ &info_smmu->event_ring_doorbell_pa);
+ IPADBG("num_pkt_buffers = %hu\n", info_smmu->num_pkt_buffers);
+ IPADBG("pkt_offset = %d\n", info_smmu->pkt_offset);
+
+ wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+
+ if (dir == IPA_WDI3_TX_DIR) {
+ len = info_smmu->transfer_ring_size;
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+ true, info->transfer_ring_base_pa,
+ &info_smmu->transfer_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_base_pa = (u32)va;
+ wdi3_params->transfer_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->transfer_ring_size = len;
+
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_DB_RES,
+ true, info_smmu->transfer_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->transfer_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+
+ len = info_smmu->event_ring_size;
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+ true, info->event_ring_base_pa,
+ &info_smmu->event_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_base_pa = (u32)va;
+ wdi3_params->event_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->event_ring_size = len;
+
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+ true, info_smmu->event_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->event_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+ } else {
+ len = info_smmu->transfer_ring_size;
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+ true, info->transfer_ring_base_pa,
+ &info_smmu->transfer_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_base_pa = (u32)va;
+ wdi3_params->transfer_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->transfer_ring_size = len;
+
+ if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+ true, info_smmu->transfer_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->transfer_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+
+ len = info_smmu->event_ring_size;
+ if (ipa2_create_uc_smmu_mapping(
+ IPA_WDI_RX_COMP_RING_RES, true,
+ info->event_ring_base_pa,
+ &info_smmu->event_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_base_pa = (u32)va;
+ wdi3_params->event_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->event_ring_size = len;
+
+ if (ipa2_create_uc_smmu_mapping(
+ IPA_WDI_RX_COMP_RING_WP_RES, true,
+ info_smmu->event_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->event_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+ }
+ wdi3_params->num_pkt_buffers = info_smmu->num_pkt_buffers;
+ wdi3_params->ipa_pipe_number = ipa_ep_idx;
+ wdi3_params->dir = dir;
+ wdi3_params->pkt_offset = info_smmu->pkt_offset;
+ memcpy(wdi3_params->desc_format_template,
+ info_smmu->desc_format_template,
+ sizeof(wdi3_params->desc_format_template));
+ }
result = ipa_uc_send_cmd((u32)(cmd.phys_base),
IPA_CPU_2_HW_CMD_OFFLOAD_CHANNEL_SET_UP,
@@ -94,13 +224,15 @@
}
dma_free_coherent(ipa_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);
- IPAERR("suceeded in freeing memory.\n");
return result;
}
-int ipa2_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out)
+int ipa2_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out,
+ ipa_wdi_meter_notifier_cb wdi_notify)
{
+ enum ipa_client_type rx_client;
+ enum ipa_client_type tx_client;
struct ipa_ep_context *ep_rx;
struct ipa_ep_context *ep_tx;
int ipa_ep_idx_rx;
@@ -112,12 +244,26 @@
return -EINVAL;
}
- ipa_ep_idx_rx = ipa_get_ep_mapping(in->rx.client);
- ipa_ep_idx_tx = ipa_get_ep_mapping(in->tx.client);
+ if (in->is_smmu_enabled == false) {
+ rx_client = in->u_rx.rx.client;
+ tx_client = in->u_tx.tx.client;
+ } else {
+ rx_client = in->u_rx.rx_smmu.client;
+ tx_client = in->u_tx.tx_smmu.client;
+ }
+
+ ipa_ep_idx_rx = ipa_get_ep_mapping(rx_client);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(tx_client);
+
if (ipa_ep_idx_rx == -1 || ipa_ep_idx_tx == -1) {
IPAERR("fail to alloc EP.\n");
return -EFAULT;
}
+ if (ipa_ep_idx_rx >= IPA_MAX_NUM_PIPES ||
+ ipa_ep_idx_tx >= IPA_MAX_NUM_PIPES) {
+ IPAERR("ep out of range.\n");
+ return -EFAULT;
+ }
ep_rx = &ipa_ctx->ep[ipa_ep_idx_rx];
ep_tx = &ipa_ctx->ep[ipa_ep_idx_tx];
@@ -132,9 +278,14 @@
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+ if (wdi_notify)
+ ipa_ctx->uc_wdi_ctx.stats_notify = wdi_notify;
+ else
+ IPADBG("wdi_notify is null\n");
+
/* setup rx ep cfg */
ep_rx->valid = 1;
- ep_rx->client = in->rx.client;
+ ep_rx->client = rx_client;
result = ipa_disable_data_path(ipa_ep_idx_rx);
if (result) {
IPAERR("disable data path failed res=%d clnt=%d.\n", result,
@@ -145,65 +296,71 @@
ep_rx->client_notify = in->notify;
ep_rx->priv = in->priv;
- memcpy(&ep_rx->cfg, &in->rx.ipa_ep_cfg, sizeof(ep_rx->cfg));
+ if (in->is_smmu_enabled == false)
+ memcpy(&ep_rx->cfg, &in->u_rx.rx.ipa_ep_cfg,
+ sizeof(ep_rx->cfg));
+ else
+ memcpy(&ep_rx->cfg, &in->u_rx.rx_smmu.ipa_ep_cfg,
+ sizeof(ep_rx->cfg));
if (ipa_cfg_ep(ipa_ep_idx_rx, &ep_rx->cfg)) {
IPAERR("fail to setup rx pipe cfg\n");
result = -EFAULT;
goto fail;
}
- IPAERR("configured RX EP.\n");
- if (ipa_send_wdi3_setup_pipe_cmd(&in->rx, IPA_WDI3_RX_DIR)) {
+ if (ipa_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+ &in->u_rx.rx, &in->u_rx.rx_smmu, IPA_WDI3_RX_DIR)) {
IPAERR("fail to send cmd to uc for rx pipe\n");
result = -EFAULT;
goto fail;
}
- IPAERR("rx pipe was setup.\n");
-
ipa_install_dflt_flt_rules(ipa_ep_idx_rx);
out->rx_uc_db_pa = ipa_ctx->ipa_wrapper_base +
IPA_REG_BASE_OFST_v2_5 +
IPA_UC_MAILBOX_m_n_OFFS_v2_5(
IPA_HW_WDI3_RX_MBOX_START_INDEX/32,
IPA_HW_WDI3_RX_MBOX_START_INDEX % 32);
- IPADBG("client %d (ep: %d) connected\n", in->rx.client,
+
+ IPADBG("client %d (ep: %d) connected\n", rx_client,
ipa_ep_idx_rx);
- /* setup dl ep cfg */
+ /* setup tx ep cfg */
ep_tx->valid = 1;
- ep_tx->client = in->tx.client;
+ ep_tx->client = tx_client;
result = ipa_disable_data_path(ipa_ep_idx_tx);
if (result) {
- IPAERR("disable data path failed res=%d clnt=%d.\n", result,
+ IPAERR("disable data path failed res=%d ep=%d.\n", result,
ipa_ep_idx_tx);
result = -EFAULT;
goto fail;
}
- memcpy(&ep_tx->cfg, &in->tx.ipa_ep_cfg, sizeof(ep_tx->cfg));
+ if (in->is_smmu_enabled == false)
+ memcpy(&ep_tx->cfg, &in->u_tx.tx.ipa_ep_cfg,
+ sizeof(ep_tx->cfg));
+ else
+ memcpy(&ep_tx->cfg, &in->u_tx.tx_smmu.ipa_ep_cfg,
+ sizeof(ep_tx->cfg));
if (ipa_cfg_ep(ipa_ep_idx_tx, &ep_tx->cfg)) {
IPAERR("fail to setup tx pipe cfg\n");
result = -EFAULT;
goto fail;
}
- IPAERR("configured TX EP in DMA mode.\n");
- if (ipa_send_wdi3_setup_pipe_cmd(&in->tx, IPA_WDI3_TX_DIR)) {
+ if (ipa_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+ &in->u_tx.tx, &in->u_tx.tx_smmu, IPA_WDI3_TX_DIR)) {
IPAERR("fail to send cmd to uc for tx pipe\n");
result = -EFAULT;
goto fail;
}
- IPAERR("tx pipe was setup.\n");
-
out->tx_uc_db_pa = ipa_ctx->ipa_wrapper_base +
IPA_REG_BASE_OFST_v2_5 +
IPA_UC_MAILBOX_m_n_OFFS_v2_5(
IPA_HW_WDI3_TX_MBOX_START_INDEX/32,
IPA_HW_WDI3_TX_MBOX_START_INDEX % 32);
- out->tx_uc_db_va = ioremap(out->tx_uc_db_pa, 4);
- IPADBG("client %d (ep: %d) connected\n", in->tx.client,
+ IPADBG("client %d (ep: %d) connected\n", tx_client,
ipa_ep_idx_tx);
fail:
@@ -233,7 +390,6 @@
wdi3 = &cmd_data->CommonCh_params.Wdi3CommonCh_params;
wdi3->params.ipa_pipe_number = ipa_ep_idx;
- IPAERR("cmd: %d ep_idx: %d\n", command, ipa_ep_idx);
result = ipa_uc_send_cmd((u32)(cmd.phys_base), command,
IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
false, 10*HZ);
@@ -256,6 +412,12 @@
IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
+ if (ipa_ep_idx_tx < 0 || ipa_ep_idx_tx >= IPA_MAX_NUM_PIPES ||
+ ipa_ep_idx_rx < 0 || ipa_ep_idx_rx >= IPA_MAX_NUM_PIPES) {
+ IPAERR("invalid ipa ep index\n");
+ return -EINVAL;
+ }
+
ep_tx = &ipa_ctx->ep[ipa_ep_idx_tx];
ep_rx = &ipa_ctx->ep[ipa_ep_idx_rx];
@@ -291,8 +453,8 @@
struct ipa_ep_context *ep_tx, *ep_rx;
int result = 0;
- IPAERR("ep_tx = %d\n", ipa_ep_idx_tx);
- IPAERR("ep_rx = %d\n", ipa_ep_idx_rx);
+ IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
+ IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
ep_tx = &ipa_ctx->ep[ipa_ep_idx_tx];
ep_rx = &ipa_ctx->ep[ipa_ep_idx_rx];
@@ -301,7 +463,6 @@
if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_tx,
IPA_CPU_2_HW_CMD_OFFLOAD_ENABLE)) {
IPAERR("fail to enable tx pipe\n");
- WARN_ON(1);
result = -EFAULT;
goto fail;
}
@@ -310,7 +471,6 @@
if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_tx,
IPA_CPU_2_HW_CMD_OFFLOAD_RESUME)) {
IPAERR("fail to resume tx pipe\n");
- WARN_ON(1);
result = -EFAULT;
goto fail;
}
@@ -319,7 +479,6 @@
if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_rx,
IPA_CPU_2_HW_CMD_OFFLOAD_ENABLE)) {
IPAERR("fail to enable rx pipe\n");
- WARN_ON(1);
result = -EFAULT;
goto fail;
}
@@ -328,7 +487,6 @@
if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_rx,
IPA_CPU_2_HW_CMD_OFFLOAD_RESUME)) {
IPAERR("fail to resume rx pipe\n");
- WARN_ON(1);
result = -EFAULT;
goto fail;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 7bd1731..4a8e7c7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -185,6 +185,16 @@
#define IPA3_ACTIVE_CLIENTS_LOG_HASHTABLE_SIZE 50
#define IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN 40
+#define IPA_WDI_RX_RING_RES 0
+#define IPA_WDI_RX_RING_RP_RES 1
+#define IPA_WDI_RX_COMP_RING_RES 2
+#define IPA_WDI_RX_COMP_RING_WP_RES 3
+#define IPA_WDI_TX_RING_RES 4
+#define IPA_WDI_CE_RING_RES 5
+#define IPA_WDI_CE_DB_RES 6
+#define IPA_WDI_TX_DB_RES 7
+#define IPA_WDI_MAX_RES 8
+
struct ipa3_active_client_htable_entry {
struct hlist_node list;
char id_string[IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN];
@@ -1898,8 +1908,9 @@
int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
int ipa3_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
void ipa3_ntn_uc_dereg_rdyCB(void);
-int ipa3_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out);
+int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out,
+ ipa_wdi_meter_notifier_cb wdi_notify);
int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
@@ -1921,6 +1932,10 @@
*/
int ipa3_uc_dereg_rdyCB(void);
+int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+ phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
+ unsigned long *iova);
+
/*
* Tethering bridge (Rmnet / MBIM)
*/
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index 1bdc0fb..a0f1f54 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -52,6 +52,8 @@
struct ipa3_rt_entry *entry, u8 *buf)
{
struct ipahal_rt_rule_gen_params gen_params;
+ struct ipa3_hdr_entry *hdr_entry;
+ struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
int res = 0;
memset(&gen_params, 0, sizeof(gen_params));
@@ -71,6 +73,25 @@
return -EPERM;
}
+ /* Adding check to confirm still
+ * header entry present in header table or not
+ */
+
+ if (entry->hdr) {
+ hdr_entry = ipa3_id_find(entry->rule.hdr_hdl);
+ if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL("Header entry already deleted\n");
+ return -EPERM;
+ }
+ } else if (entry->proc_ctx) {
+ hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl);
+ if (!hdr_proc_entry ||
+ hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+ IPAERR_RL("Proc header entry already deleted\n");
+ return -EPERM;
+ }
+ }
+
if (entry->proc_ctx || (entry->hdr && entry->hdr->is_hdr_proc_ctx)) {
struct ipa3_hdr_proc_ctx_entry *proc_ctx;
@@ -1269,6 +1290,8 @@
{
struct ipa3_rt_entry *entry;
int id;
+ struct ipa3_hdr_entry *hdr_entry;
+ struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
entry = ipa3_id_find(rule_hdl);
@@ -1291,6 +1314,25 @@
}
}
+ /* Adding check to confirm still
+ * header entry present in header table or not
+ */
+
+ if (entry->hdr) {
+ hdr_entry = ipa3_id_find(entry->rule.hdr_hdl);
+ if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL("Header entry already deleted\n");
+ return -EINVAL;
+ }
+ } else if (entry->proc_ctx) {
+ hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl);
+ if (!hdr_proc_entry ||
+ hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+ IPAERR_RL("Proc header entry already deleted\n");
+ return -EINVAL;
+ }
+ }
+
if (entry->hdr)
__ipa3_release_hdr(entry->hdr->id);
else if (entry->proc_ctx)
@@ -1611,7 +1653,8 @@
struct ipa3_rt_entry *entry;
struct ipa3_hdr_entry *hdr = NULL;
struct ipa3_hdr_proc_ctx_entry *proc_ctx = NULL;
-
+ struct ipa3_hdr_entry *hdr_entry;
+ struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
if (rtrule->rule.hdr_hdl) {
hdr = ipa3_id_find(rtrule->rule.hdr_hdl);
if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) {
@@ -1638,6 +1681,25 @@
goto error;
}
+ /* Adding check to confirm still
+ * header entry present in header table or not
+ */
+
+ if (entry->hdr) {
+ hdr_entry = ipa3_id_find(entry->rule.hdr_hdl);
+ if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL("Header entry already deleted\n");
+ return -EPERM;
+ }
+ } else if (entry->proc_ctx) {
+ hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl);
+ if (!hdr_proc_entry ||
+ hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+ IPAERR_RL("Proc header entry already deleted\n");
+ return -EPERM;
+ }
+ }
+
if (entry->hdr)
entry->hdr->ref_cnt--;
if (entry->proc_ctx)
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 d5fe3fb..ec777bc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -28,15 +28,6 @@
#define IPA_WDI_RESUMED BIT(2)
#define IPA_UC_POLL_SLEEP_USEC 100
-#define IPA_WDI_RX_RING_RES 0
-#define IPA_WDI_RX_RING_RP_RES 1
-#define IPA_WDI_RX_COMP_RING_RES 2
-#define IPA_WDI_RX_COMP_RING_WP_RES 3
-#define IPA_WDI_TX_RING_RES 4
-#define IPA_WDI_CE_RING_RES 5
-#define IPA_WDI_CE_DB_RES 6
-#define IPA_WDI_MAX_RES 7
-
struct ipa_wdi_res {
struct ipa_wdi_buffer_info *res;
unsigned int nents;
@@ -670,7 +661,7 @@
}
}
-static int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
unsigned long *iova)
{
@@ -703,6 +694,7 @@
case IPA_WDI_RX_RING_RP_RES:
case IPA_WDI_RX_COMP_RING_WP_RES:
case IPA_WDI_CE_DB_RES:
+ case IPA_WDI_TX_DB_RES:
if (ipa_create_uc_smmu_mapping_pa(pa, len,
(res_idx == IPA_WDI_CE_DB_RES) ? true : false,
iova)) {
@@ -840,35 +832,6 @@
in->u.ul.rdy_comp_ring_wp_pa;
ipa3_ctx->uc_ctx.rdy_comp_ring_size =
in->u.ul.rdy_comp_ring_size;
-
- /* check if the VA is empty */
- if (ipa3_ctx->ipa_wdi2) {
- if (in->smmu_enabled) {
- if (!in->u.ul_smmu.rdy_ring_rp_va ||
- !in->u.ul_smmu.rdy_comp_ring_wp_va)
- goto dma_alloc_fail;
- } else {
- if (!in->u.ul.rdy_ring_rp_va ||
- !in->u.ul.rdy_comp_ring_wp_va)
- goto dma_alloc_fail;
- }
- IPADBG("rdy_ring_rp value =%d\n",
- in->smmu_enabled ?
- *in->u.ul_smmu.rdy_ring_rp_va :
- *in->u.ul.rdy_ring_rp_va);
- IPADBG("rx_comp_ring_wp value=%d\n",
- in->smmu_enabled ?
- *in->u.ul_smmu.rdy_comp_ring_wp_va :
- *in->u.ul.rdy_comp_ring_wp_va);
- ipa3_ctx->uc_ctx.rdy_ring_rp_va =
- in->smmu_enabled ?
- in->u.ul_smmu.rdy_ring_rp_va :
- in->u.ul.rdy_ring_rp_va;
- ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va =
- in->smmu_enabled ?
- in->u.ul_smmu.rdy_comp_ring_wp_va :
- in->u.ul.rdy_comp_ring_wp_va;
- }
}
cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index b3726e1..d2b3b4e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4519,10 +4519,10 @@
api_ctrl->ipa_get_pdev = ipa3_get_pdev;
api_ctrl->ipa_ntn_uc_reg_rdyCB = ipa3_ntn_uc_reg_rdyCB;
api_ctrl->ipa_ntn_uc_dereg_rdyCB = ipa3_ntn_uc_dereg_rdyCB;
- api_ctrl->ipa_conn_wdi3_pipes = ipa3_conn_wdi3_pipes;
- api_ctrl->ipa_disconn_wdi3_pipes = ipa3_disconn_wdi3_pipes;
- api_ctrl->ipa_enable_wdi3_pipes = ipa3_enable_wdi3_pipes;
- api_ctrl->ipa_disable_wdi3_pipes = ipa3_disable_wdi3_pipes;
+ api_ctrl->ipa_conn_wdi_pipes = ipa3_conn_wdi3_pipes;
+ api_ctrl->ipa_disconn_wdi_pipes = ipa3_disconn_wdi3_pipes;
+ api_ctrl->ipa_enable_wdi_pipes = ipa3_enable_wdi3_pipes;
+ api_ctrl->ipa_disable_wdi_pipes = ipa3_disable_wdi3_pipes;
api_ctrl->ipa_tz_unlock_reg = ipa3_tz_unlock_reg;
api_ctrl->ipa_get_smmu_params = ipa3_get_smmu_params;
api_ctrl->ipa_is_vlan_mode = ipa3_is_vlan_mode;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
index 7801745..6c019b9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-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
@@ -16,35 +16,21 @@
#define IPA_HW_WDI3_TX_MBOX_START_INDEX 50
static int ipa3_send_wdi3_setup_pipe_cmd(
- struct ipa_wdi3_setup_info *info, u8 dir)
+ u8 is_smmu_enabled, struct ipa_wdi_pipe_setup_info *info,
+ struct ipa_wdi_pipe_setup_info_smmu *info_smmu, u8 dir)
{
int ipa_ep_idx;
- int result = 0;
+ int result = 0, len;
+ unsigned long va;
struct ipa_mem_buffer cmd;
struct IpaHwWdi3SetUpCmdData_t *wdi3_params;
struct IpaHwOffloadSetUpCmdData_t *cmd_data;
- if (info == NULL) {
+ if (info == NULL || info_smmu == NULL) {
IPAERR("invalid input\n");
return -EINVAL;
}
- ipa_ep_idx = ipa_get_ep_mapping(info->client);
- if (ipa_ep_idx == -1) {
- IPAERR("fail to get ep idx.\n");
- return -EFAULT;
- }
-
- IPADBG("client=%d ep=%d\n", info->client, ipa_ep_idx);
- IPADBG("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
- IPADBG("ring_size = %hu\n", info->transfer_ring_size);
- IPADBG("ring_db_pa = 0x%pad\n", &info->transfer_ring_doorbell_pa);
- IPADBG("evt_ring_base_pa = 0x%pad\n", &info->event_ring_base_pa);
- IPADBG("evt_ring_size = %hu\n", info->event_ring_size);
- IPADBG("evt_ring_db_pa = 0x%pad\n", &info->event_ring_doorbell_pa);
- IPADBG("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
- IPADBG("pkt_offset = %d\n", info->pkt_offset);
-
cmd.size = sizeof(*cmd_data);
cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
&cmd.phys_base, GFP_KERNEL);
@@ -56,29 +42,177 @@
cmd_data = (struct IpaHwOffloadSetUpCmdData_t *)cmd.base;
cmd_data->protocol = IPA_HW_FEATURE_WDI3;
- wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
- wdi3_params->transfer_ring_base_pa = (u32)info->transfer_ring_base_pa;
- wdi3_params->transfer_ring_base_pa_hi =
- (u32)((u64)info->transfer_ring_base_pa >> 32);
- wdi3_params->transfer_ring_size = info->transfer_ring_size;
- wdi3_params->transfer_ring_doorbell_pa =
- (u32)info->transfer_ring_doorbell_pa;
- wdi3_params->transfer_ring_doorbell_pa_hi =
- (u32)((u64)info->transfer_ring_doorbell_pa >> 32);
- wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
- wdi3_params->event_ring_base_pa_hi =
- (u32)((u64)info->event_ring_base_pa >> 32);
- wdi3_params->event_ring_size = info->event_ring_size;
- wdi3_params->event_ring_doorbell_pa =
- (u32)info->event_ring_doorbell_pa;
- wdi3_params->event_ring_doorbell_pa_hi =
- (u32)((u64)info->event_ring_doorbell_pa >> 32);
- wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
- wdi3_params->ipa_pipe_number = ipa_ep_idx;
- wdi3_params->dir = dir;
- wdi3_params->pkt_offset = info->pkt_offset;
- memcpy(wdi3_params->desc_format_template, info->desc_format_template,
- sizeof(wdi3_params->desc_format_template));
+ if (!is_smmu_enabled) {
+ ipa_ep_idx = ipa_get_ep_mapping(info->client);
+ if (ipa_ep_idx == -1) {
+ IPAERR("fail to get ep idx.\n");
+ return -EFAULT;
+ }
+
+ IPADBG("client=%d ep=%d\n", info->client, ipa_ep_idx);
+ IPADBG("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
+ IPADBG("ring_size = %hu\n", info->transfer_ring_size);
+ IPADBG("ring_db_pa = 0x%pad\n",
+ &info->transfer_ring_doorbell_pa);
+ IPADBG("evt_ring_base_pa = 0x%pad\n",
+ &info->event_ring_base_pa);
+ IPADBG("evt_ring_size = %hu\n", info->event_ring_size);
+ IPADBG("evt_ring_db_pa = 0x%pad\n",
+ &info->event_ring_doorbell_pa);
+ IPADBG("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
+ IPADBG("pkt_offset = %d\n", info->pkt_offset);
+
+ wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+ wdi3_params->transfer_ring_base_pa =
+ (u32)info->transfer_ring_base_pa;
+ wdi3_params->transfer_ring_base_pa_hi =
+ (u32)((u64)info->transfer_ring_base_pa >> 32);
+ wdi3_params->transfer_ring_size = info->transfer_ring_size;
+ wdi3_params->transfer_ring_doorbell_pa =
+ (u32)info->transfer_ring_doorbell_pa;
+ wdi3_params->transfer_ring_doorbell_pa_hi =
+ (u32)((u64)info->transfer_ring_doorbell_pa >> 32);
+ wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
+ wdi3_params->event_ring_base_pa_hi =
+ (u32)((u64)info->event_ring_base_pa >> 32);
+ wdi3_params->event_ring_size = info->event_ring_size;
+ wdi3_params->event_ring_doorbell_pa =
+ (u32)info->event_ring_doorbell_pa;
+ wdi3_params->event_ring_doorbell_pa_hi =
+ (u32)((u64)info->event_ring_doorbell_pa >> 32);
+ wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
+ wdi3_params->ipa_pipe_number = ipa_ep_idx;
+ wdi3_params->dir = dir;
+ wdi3_params->pkt_offset = info->pkt_offset;
+ memcpy(wdi3_params->desc_format_template,
+ info->desc_format_template,
+ sizeof(wdi3_params->desc_format_template));
+ } else {
+ ipa_ep_idx = ipa_get_ep_mapping(info_smmu->client);
+ if (ipa_ep_idx == -1) {
+ IPAERR("fail to get ep idx\n");
+ return -EFAULT;
+ }
+
+ IPADBG("client=%d ep=%d\n", info_smmu->client, ipa_ep_idx);
+ IPADBG("ring_size = %hu\n", info_smmu->transfer_ring_size);
+ IPADBG("ring_db_pa = 0x%pad\n",
+ &info_smmu->transfer_ring_doorbell_pa);
+ IPADBG("evt_ring_size = %hu\n", info_smmu->event_ring_size);
+ IPADBG("evt_ring_db_pa = 0x%pad\n",
+ &info_smmu->event_ring_doorbell_pa);
+ IPADBG("num_pkt_buffers = %hu\n", info_smmu->num_pkt_buffers);
+ IPADBG("pkt_offset = %d\n", info_smmu->pkt_offset);
+
+ wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+
+ if (dir == IPA_WDI3_TX_DIR) {
+ len = info_smmu->transfer_ring_size;
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+ true, info->transfer_ring_base_pa,
+ &info_smmu->transfer_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_base_pa = (u32)va;
+ wdi3_params->transfer_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->transfer_ring_size = len;
+
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_DB_RES,
+ true, info_smmu->transfer_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->transfer_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+
+ len = info_smmu->event_ring_size;
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+ true, info->event_ring_base_pa,
+ &info_smmu->event_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_base_pa = (u32)va;
+ wdi3_params->event_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->event_ring_size = len;
+
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+ true, info_smmu->event_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->event_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+ } else {
+ len = info_smmu->transfer_ring_size;
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+ true, info->transfer_ring_base_pa,
+ &info_smmu->transfer_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_base_pa = (u32)va;
+ wdi3_params->transfer_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->transfer_ring_size = len;
+
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+ true, info_smmu->transfer_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->transfer_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->transfer_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+
+ len = info_smmu->event_ring_size;
+ if (ipa_create_uc_smmu_mapping(
+ IPA_WDI_RX_COMP_RING_RES, true,
+ info->event_ring_base_pa,
+ &info_smmu->event_ring_base, len,
+ false, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_base_pa = (u32)va;
+ wdi3_params->event_ring_base_pa_hi =
+ (u32)((u64)va >> 32);
+ wdi3_params->event_ring_size = len;
+
+ if (ipa_create_uc_smmu_mapping(
+ IPA_WDI_RX_COMP_RING_WP_RES, true,
+ info_smmu->event_ring_doorbell_pa,
+ NULL, 4, true, &va)) {
+ IPAERR("failed to get smmu mapping\n");
+ return -EFAULT;
+ }
+ wdi3_params->event_ring_doorbell_pa =
+ (u32)va;
+ wdi3_params->event_ring_doorbell_pa_hi =
+ (u32)((u64)va >> 32);
+ }
+ wdi3_params->num_pkt_buffers = info_smmu->num_pkt_buffers;
+ wdi3_params->ipa_pipe_number = ipa_ep_idx;
+ wdi3_params->dir = dir;
+ wdi3_params->pkt_offset = info_smmu->pkt_offset;
+ memcpy(wdi3_params->desc_format_template,
+ info_smmu->desc_format_template,
+ sizeof(wdi3_params->desc_format_template));
+ }
result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
IPA_CPU_2_HW_CMD_OFFLOAD_CHANNEL_SET_UP,
@@ -93,9 +227,12 @@
return result;
}
-int ipa3_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out)
+int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out,
+ ipa_wdi_meter_notifier_cb wdi_notify)
{
+ enum ipa_client_type rx_client;
+ enum ipa_client_type tx_client;
struct ipa3_ep_context *ep_rx;
struct ipa3_ep_context *ep_tx;
int ipa_ep_idx_rx;
@@ -107,8 +244,17 @@
return -EINVAL;
}
- ipa_ep_idx_rx = ipa_get_ep_mapping(in->rx.client);
- ipa_ep_idx_tx = ipa_get_ep_mapping(in->tx.client);
+ if (in->is_smmu_enabled == false) {
+ rx_client = in->u_rx.rx.client;
+ tx_client = in->u_tx.tx.client;
+ } else {
+ rx_client = in->u_rx.rx_smmu.client;
+ tx_client = in->u_tx.tx_smmu.client;
+ }
+
+ ipa_ep_idx_rx = ipa_get_ep_mapping(rx_client);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(tx_client);
+
if (ipa_ep_idx_rx == -1 || ipa_ep_idx_tx == -1) {
IPAERR("fail to alloc EP.\n");
return -EFAULT;
@@ -132,9 +278,14 @@
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+ if (wdi_notify)
+ ipa3_ctx->uc_wdi_ctx.stats_notify = wdi_notify;
+ else
+ IPADBG("wdi_notify is null\n");
+
/* setup rx ep cfg */
ep_rx->valid = 1;
- ep_rx->client = in->rx.client;
+ ep_rx->client = rx_client;
result = ipa3_disable_data_path(ipa_ep_idx_rx);
if (result) {
IPAERR("disable data path failed res=%d clnt=%d.\n", result,
@@ -145,7 +296,12 @@
ep_rx->client_notify = in->notify;
ep_rx->priv = in->priv;
- memcpy(&ep_rx->cfg, &in->rx.ipa_ep_cfg, sizeof(ep_rx->cfg));
+ if (in->is_smmu_enabled == false)
+ memcpy(&ep_rx->cfg, &in->u_rx.rx.ipa_ep_cfg,
+ sizeof(ep_rx->cfg));
+ else
+ memcpy(&ep_rx->cfg, &in->u_rx.rx_smmu.ipa_ep_cfg,
+ sizeof(ep_rx->cfg));
if (ipa3_cfg_ep(ipa_ep_idx_rx, &ep_rx->cfg)) {
IPAERR("fail to setup rx pipe cfg\n");
@@ -153,7 +309,8 @@
goto fail;
}
- if (ipa3_send_wdi3_setup_pipe_cmd(&in->rx, IPA_WDI3_RX_DIR)) {
+ if (ipa3_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+ &in->u_rx.rx, &in->u_rx.rx_smmu, IPA_WDI3_RX_DIR)) {
IPAERR("fail to send cmd to uc for rx pipe\n");
result = -EFAULT;
goto fail;
@@ -165,12 +322,12 @@
IPA_HW_WDI3_RX_MBOX_START_INDEX/32,
IPA_HW_WDI3_RX_MBOX_START_INDEX % 32);
- IPADBG("client %d (ep: %d) connected\n", in->rx.client,
+ IPADBG("client %d (ep: %d) connected\n", rx_client,
ipa_ep_idx_rx);
- /* setup dl ep cfg */
+ /* setup tx ep cfg */
ep_tx->valid = 1;
- ep_tx->client = in->tx.client;
+ ep_tx->client = tx_client;
result = ipa3_disable_data_path(ipa_ep_idx_tx);
if (result) {
IPAERR("disable data path failed res=%d ep=%d.\n", result,
@@ -179,7 +336,12 @@
goto fail;
}
- memcpy(&ep_tx->cfg, &in->tx.ipa_ep_cfg, sizeof(ep_tx->cfg));
+ if (in->is_smmu_enabled == false)
+ memcpy(&ep_tx->cfg, &in->u_tx.tx.ipa_ep_cfg,
+ sizeof(ep_tx->cfg));
+ else
+ memcpy(&ep_tx->cfg, &in->u_tx.tx_smmu.ipa_ep_cfg,
+ sizeof(ep_tx->cfg));
if (ipa3_cfg_ep(ipa_ep_idx_tx, &ep_tx->cfg)) {
IPAERR("fail to setup tx pipe cfg\n");
@@ -187,7 +349,8 @@
goto fail;
}
- if (ipa3_send_wdi3_setup_pipe_cmd(&in->tx, IPA_WDI3_TX_DIR)) {
+ if (ipa3_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+ &in->u_tx.tx, &in->u_tx.tx_smmu, IPA_WDI3_TX_DIR)) {
IPAERR("fail to send cmd to uc for tx pipe\n");
result = -EFAULT;
goto fail;
@@ -197,13 +360,7 @@
ipahal_get_reg_mn_ofst(IPA_UC_MAILBOX_m_n,
IPA_HW_WDI3_TX_MBOX_START_INDEX/32,
IPA_HW_WDI3_TX_MBOX_START_INDEX % 32);
- out->tx_uc_db_va = ioremap(out->tx_uc_db_pa, 4);
- if (!out->tx_uc_db_va) {
- IPAERR("fail to ioremap tx uc db\n");
- result = -EFAULT;
- goto fail;
- }
- IPADBG("client %d (ep: %d) connected\n", in->tx.client,
+ IPADBG("client %d (ep: %d) connected\n", tx_client,
ipa_ep_idx_tx);
fail:
diff --git a/drivers/power/supply/qcom/qg-battery-profile.c b/drivers/power/supply/qcom/qg-battery-profile.c
index b86c7f5..e90e269 100644
--- a/drivers/power/supply/qcom/qg-battery-profile.c
+++ b/drivers/power/supply/qcom/qg-battery-profile.c
@@ -393,19 +393,33 @@
return rc;
}
-int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging)
+int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup)
{
- u8 table_index = charging ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2;
+ u8 table_index = 0;
+ int soc_avg = 0, soc_charge = 0, soc_discharge = 0;
if (!the_battery || !the_battery->profile) {
pr_err("Battery profile not loaded\n");
return -ENODEV;
}
- *soc = interpolate_soc(&the_battery->profile[table_index],
+ if (lookup == SOC_AVERAGE) {
+ soc_charge = interpolate_soc(
+ &the_battery->profile[TABLE_SOC_OCV1],
batt_temp, UV_TO_DECIUV(ocv_uv));
+ soc_discharge = interpolate_soc(
+ &the_battery->profile[TABLE_SOC_OCV2],
+ batt_temp, UV_TO_DECIUV(ocv_uv));
+ soc_avg = (soc_charge + soc_discharge) / 2;
+ } else {
+ table_index = (lookup == SOC_CHARGE) ?
+ TABLE_SOC_OCV1 : TABLE_SOC_OCV2;
+ soc_avg = interpolate_soc(
+ &the_battery->profile[table_index],
+ batt_temp, UV_TO_DECIUV(ocv_uv));
+ }
- *soc = CAP(0, 100, DIV_ROUND_CLOSEST(*soc, 100));
+ *soc = CAP(0, 100, DIV_ROUND_CLOSEST(soc_avg, 100));
return 0;
}
diff --git a/drivers/power/supply/qcom/qg-battery-profile.h b/drivers/power/supply/qcom/qg-battery-profile.h
index 143a4f2..4314d73 100644
--- a/drivers/power/supply/qcom/qg-battery-profile.h
+++ b/drivers/power/supply/qcom/qg-battery-profile.h
@@ -14,6 +14,6 @@
int qg_batterydata_init(struct device_node *node);
void qg_batterydata_exit(void);
-int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging);
+int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, u8 lookup);
#endif /* __QG_BATTERY_PROFILE_H__ */
diff --git a/drivers/power/supply/qcom/qg-defs.h b/drivers/power/supply/qcom/qg-defs.h
index bbbc7ee..a16e652 100644
--- a/drivers/power/supply/qcom/qg-defs.h
+++ b/drivers/power/supply/qcom/qg-defs.h
@@ -45,4 +45,10 @@
#define CAP(min, max, value) \
((min > value) ? min : ((value > max) ? max : value))
+enum soc_lookup {
+ SOC_CHARGE,
+ SOC_DISCHARGE,
+ SOC_AVERAGE,
+};
+
#endif /* __QG_DEFS_H__ */
diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c
index 44e5048..03d6fd6 100644
--- a/drivers/power/supply/qcom/qg-util.c
+++ b/drivers/power/supply/qcom/qg-util.c
@@ -122,7 +122,7 @@
}
if (rt) {
- *fifo_length &= COUNT_FIFO_RT_MASK;
+ *fifo_length = reg & COUNT_FIFO_RT_MASK;
} else {
*fifo_length = (reg & FIFO_LENGTH_MASK) >> FIFO_LENGTH_SHIFT;
*fifo_length += 1;
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index fbac25c..f2ac481 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -247,6 +247,20 @@
return rc;
}
+ /*
+ * If there is pending data from suspend, append the new FIFO
+ * data to it.
+ */
+ if (chip->suspend_data) {
+ j = chip->kdata.fifo_length; /* append the data */
+ chip->suspend_data = false;
+ qg_dbg(chip, QG_DEBUG_FIFO,
+ "Pending suspend-data FIFO length=%d\n", j);
+ } else {
+ /* clear any old pending data */
+ chip->kdata.fifo_length = 0;
+ }
+
for (i = 0; i < fifo_length * 2; i = i + 2, j++) {
rc = qg_read(chip, chip->qg_base + QG_V_FIFO0_DATA0_REG + i,
&v_fifo[i], 2);
@@ -280,7 +294,7 @@
chip->kdata.fifo[j].count);
}
- chip->kdata.fifo_length = fifo_length;
+ chip->kdata.fifo_length += fifo_length;
chip->kdata.seq_no = chip->seq_no++ % U32_MAX;
return rc;
@@ -1481,7 +1495,8 @@
pr_err("Failed to read good_ocv rc=%d\n", rc);
use_pon_ocv = true;
} else {
- rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
+ rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp,
+ SOC_AVERAGE);
if (rc < 0) {
pr_err("Failed to lookup SOC (GOOD_OCV) @ PON rc=%d\n",
rc);
@@ -1534,7 +1549,7 @@
pr_err("Failed to read HW PON ocv rc=%d\n", rc);
return rc;
}
- rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
+ rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, SOC_AVERAGE);
if (rc < 0) {
pr_err("Failed to lookup SOC @ PON rc=%d\n", rc);
soc = 50;
@@ -2046,6 +2061,8 @@
int rc;
u32 fifo_rt_length = 0, sleep_fifo_length = 0;
+ chip->suspend_data = false;
+
/* ignore any suspend processing if we are charging */
if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
qg_dbg(chip, QG_DEBUG_PM, "Charging @ suspend - ignore processing\n");
@@ -2104,9 +2121,9 @@
static int process_resume(struct qpnp_qg *chip)
{
- int rc, batt_temp = 0;
u8 status2 = 0, rt_status = 0;
- u32 ocv_uv = 0, soc = 0;
+ u32 ocv_uv = 0;
+ int rc, batt_temp = 0;
rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1);
if (rc < 0) {
@@ -2128,23 +2145,12 @@
chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
+ /* Clear suspend data as there has been a GOOD OCV */
chip->suspend_data = false;
- rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
- if (rc < 0) {
- pr_err("Failed to lookup OCV, rc=%d\n", rc);
- return rc;
- }
- chip->catch_up_soc = soc;
- /* update the SOC immediately */
- qg_scale_soc(chip, true);
-
- qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV soc=%d\n",
- ocv_uv, soc);
+ qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n",
+ ocv_uv);
}
- /*
- * If the wakeup was not because of FIFO_DONE
- * send the pending data collected during suspend.
- */
+
rc = qg_read(chip, chip->qg_base + QG_INT_LATCHED_STS_REG,
&rt_status, 1);
if (rc < 0) {
@@ -2153,18 +2159,23 @@
}
rt_status &= FIFO_UPDATE_DONE_INT_LAT_STS_BIT;
- if (!rt_status && chip->suspend_data) {
+ qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d\n",
+ !!rt_status, chip->suspend_data,
+ chip->kdata.param[QG_GOOD_OCV_UV].valid);
+ /*
+ * If this is not a wakeup from FIFO-done,
+ * process the data immediately if - we have data from
+ * suspend or there is a good OCV.
+ */
+ if (!rt_status && (chip->suspend_data ||
+ chip->kdata.param[QG_GOOD_OCV_UV].valid)) {
vote(chip->awake_votable, SUSPEND_DATA_VOTER, true, 0);
/* signal the read thread */
chip->data_ready = true;
wake_up_interruptible(&chip->qg_wait_q);
+ chip->suspend_data = false;
}
- qg_dbg(chip, QG_DEBUG_PM, "fifo_done rt_status=%d suspend_data=%d data_ready=%d\n",
- !!rt_status, chip->suspend_data, chip->data_ready);
-
- chip->suspend_data = false;
-
return rc;
}
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 0e6adff..b91850d 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1710,30 +1710,25 @@
[CHG_STATE_CHANGE_IRQ] = {
.name = "chg-state-change",
.handler = chg_state_change_irq_handler,
+ .wake = true,
},
[STEP_CHG_STATE_CHANGE_IRQ] = {
.name = "step-chg-state-change",
- .handler = default_irq_handler,
},
[STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
.name = "step-chg-soc-update-fail",
- .handler = default_irq_handler,
},
[STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
.name = "step-chg-soc-update-req",
- .handler = default_irq_handler,
},
[FG_FVCAL_QUALIFIED_IRQ] = {
.name = "fg-fvcal-qualified",
- .handler = default_irq_handler,
},
[VPH_ALARM_IRQ] = {
.name = "vph-alarm",
- .handler = default_irq_handler,
},
[VPH_DROP_PRECHG_IRQ] = {
.name = "vph-drop-prechg",
- .handler = default_irq_handler,
},
/* DCDC IRQs */
[OTG_FAIL_IRQ] = {
@@ -1742,19 +1737,17 @@
},
[OTG_OC_DISABLE_SW_IRQ] = {
.name = "otg-oc-disable-sw",
- .handler = default_irq_handler,
},
[OTG_OC_HICCUP_IRQ] = {
.name = "otg-oc-hiccup",
- .handler = default_irq_handler,
},
[BSM_ACTIVE_IRQ] = {
.name = "bsm-active",
- .handler = default_irq_handler,
},
[HIGH_DUTY_CYCLE_IRQ] = {
.name = "high-duty-cycle",
.handler = high_duty_cycle_irq_handler,
+ .wake = true,
},
[INPUT_CURRENT_LIMITING_IRQ] = {
.name = "input-current-limiting",
@@ -1762,7 +1755,6 @@
},
[CONCURRENT_MODE_DISABLE_IRQ] = {
.name = "concurrent-mode-disable",
- .handler = default_irq_handler,
},
[SWITCHER_POWER_OK_IRQ] = {
.name = "switcher-power-ok",
@@ -1772,10 +1764,10 @@
[BAT_TEMP_IRQ] = {
.name = "bat-temp",
.handler = batt_temp_changed_irq_handler,
+ .wake = true,
},
[ALL_CHNL_CONV_DONE_IRQ] = {
.name = "all-chnl-conv-done",
- .handler = default_irq_handler,
},
[BAT_OV_IRQ] = {
.name = "bat-ov",
@@ -1795,11 +1787,9 @@
},
[BUCK_OC_IRQ] = {
.name = "buck-oc",
- .handler = default_irq_handler,
},
[VPH_OV_IRQ] = {
.name = "vph-ov",
- .handler = default_irq_handler,
},
/* USB INPUT IRQs */
[USBIN_COLLAPSE_IRQ] = {
@@ -1821,23 +1811,24 @@
[USBIN_PLUGIN_IRQ] = {
.name = "usbin-plugin",
.handler = usb_plugin_irq_handler,
+ .wake = true,
},
[USBIN_REVI_CHANGE_IRQ] = {
.name = "usbin-revi-change",
- .handler = default_irq_handler,
},
[USBIN_SRC_CHANGE_IRQ] = {
.name = "usbin-src-change",
.handler = usb_source_change_irq_handler,
+ .wake = true,
},
[USBIN_ICL_CHANGE_IRQ] = {
.name = "usbin-icl-change",
.handler = icl_change_irq_handler,
+ .wake = true,
},
/* DC INPUT IRQs */
[DCIN_VASHDN_IRQ] = {
.name = "dcin-vashdn",
- .handler = default_irq_handler,
},
[DCIN_UV_IRQ] = {
.name = "dcin-uv",
@@ -1854,7 +1845,6 @@
},
[DCIN_REVI_IRQ] = {
.name = "dcin-revi",
- .handler = default_irq_handler,
},
[DCIN_PON_IRQ] = {
.name = "dcin-pon",
@@ -1868,14 +1858,15 @@
[TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
.name = "typec-or-rid-detect-change",
.handler = typec_or_rid_detection_change_irq_handler,
+ .wake = true,
},
[TYPEC_VPD_DETECT_IRQ] = {
.name = "typec-vpd-detect",
- .handler = default_irq_handler,
},
[TYPEC_CC_STATE_CHANGE_IRQ] = {
.name = "typec-cc-state-change",
.handler = typec_state_change_irq_handler,
+ .wake = true,
},
[TYPEC_VCONN_OC_IRQ] = {
.name = "typec-vconn-oc",
@@ -1883,11 +1874,9 @@
},
[TYPEC_VBUS_CHANGE_IRQ] = {
.name = "typec-vbus-change",
- .handler = default_irq_handler,
},
[TYPEC_ATTACH_DETACH_IRQ] = {
.name = "typec-attach-detach",
- .handler = default_irq_handler,
},
[TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
.name = "typec-legacy-cable-detect",
@@ -1895,12 +1884,10 @@
},
[TYPEC_TRY_SNK_SRC_DETECT_IRQ] = {
.name = "typec-try-snk-src-detect",
- .handler = default_irq_handler,
},
/* MISCELLANEOUS IRQs */
[WDOG_SNARL_IRQ] = {
.name = "wdog-snarl",
- .handler = NULL,
},
[WDOG_BARK_IRQ] = {
.name = "wdog-bark",
@@ -1908,7 +1895,6 @@
},
[AICL_FAIL_IRQ] = {
.name = "aicl-fail",
- .handler = default_irq_handler,
},
[AICL_DONE_IRQ] = {
.name = "aicl-done",
@@ -1916,24 +1902,19 @@
},
[SMB_EN_IRQ] = {
.name = "smb-en",
- .handler = default_irq_handler,
},
[IMP_TRIGGER_IRQ] = {
.name = "imp-trigger",
- .handler = default_irq_handler,
},
[TEMP_CHANGE_IRQ] = {
.name = "temp-change",
- .handler = default_irq_handler,
},
[TEMP_CHANGE_SMB_IRQ] = {
.name = "temp-change-smb",
- .handler = default_irq_handler,
},
/* FLASH */
[VREG_OK_IRQ] = {
.name = "vreg-ok",
- .handler = schgm_flash_default_irq_handler,
},
[ILIM_S2_IRQ] = {
.name = "ilim2-s2",
@@ -1941,15 +1922,12 @@
},
[ILIM_S1_IRQ] = {
.name = "ilim1-s1",
- .handler = schgm_flash_default_irq_handler,
},
[VOUT_DOWN_IRQ] = {
.name = "vout-down",
- .handler = schgm_flash_default_irq_handler,
},
[VOUT_UP_IRQ] = {
.name = "vout-up",
- .handler = schgm_flash_default_irq_handler,
},
[FLASH_STATE_CHANGE_IRQ] = {
.name = "flash-state-change",
@@ -1957,11 +1935,9 @@
},
[TORCH_REQ_IRQ] = {
.name = "torch-req",
- .handler = schgm_flash_default_irq_handler,
},
[FLASH_EN_IRQ] = {
.name = "flash-en",
- .handler = schgm_flash_default_irq_handler,
},
};
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index ba44523..bca52ca 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2615,6 +2615,27 @@
kfree(testbus);
}
+static void ufs_qcom_print_utp_hci_testbus(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ u32 *testbus = NULL;
+ int i, nminor = 32, testbus_len = nminor * sizeof(u32);
+
+ testbus = kmalloc(testbus_len, GFP_KERNEL);
+ if (!testbus)
+ return;
+
+ host->testbus.select_major = TSTBUS_UTP_HCI;
+ for (i = 0; i <= nminor; i++) {
+ host->testbus.select_minor = i;
+ ufs_qcom_testbus_config(host);
+ testbus[i] = ufshcd_readl(hba, UFS_TEST_BUS);
+ }
+ print_hex_dump(KERN_ERR, "UTP_HCI_TEST_BUS ", DUMP_PREFIX_OFFSET,
+ 16, 4, testbus, testbus_len, false);
+ kfree(testbus);
+}
+
static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba, bool no_sleep)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -2633,6 +2654,8 @@
usleep_range(1000, 1100);
ufs_qcom_print_unipro_testbus(hba);
usleep_range(1000, 1100);
+ ufs_qcom_print_utp_hci_testbus(hba);
+ usleep_range(1000, 1100);
ufs_qcom_phy_dbg_register_dump(phy);
usleep_range(1000, 1100);
ufs_qcom_ice_print_regs(host);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 02dfbcc..d250418 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
*
* This code is based on drivers/scsi/ufs/ufshcd.c
* Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -6498,6 +6498,7 @@
hba = container_of(work, struct ufs_hba, rls_work);
ufshcd_scsi_block_requests(hba);
pm_runtime_get_sync(hba->dev);
+ down_write(&hba->lock);
ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
if (ret) {
dev_err(hba->dev,
@@ -6531,6 +6532,7 @@
hba->restore_needed = false;
out:
+ up_write(&hba->lock);
ufshcd_scsi_unblock_requests(hba);
pm_runtime_put_sync(hba->dev);
}
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e5e3147..c5a15b2 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -646,6 +646,15 @@
monitor events that require the core to be awake and ready to
handle the event.
+config MSM_AVTIMER
+ tristate "Avtimer Driver"
+ default n
+ help
+ This driver gets the Q6 out of power collapsed state
+ and exposes ioctl control to read avtimer tick.
+ Enables camera to use for VT call to get avtimer
+ timestamp.
+
config MSM_PM
depends on PM
select MSM_IDLE_STATS if DEBUG_FS
diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c
index b5ce753..fb3af15 100644
--- a/drivers/soc/qcom/msm_performance.c
+++ b/drivers/soc/qcom/msm_performance.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -26,59 +26,6 @@
#include <linux/input.h>
#include <linux/kthread.h>
-static struct mutex managed_cpus_lock;
-
-/* Maximum number to clusters that this module will manage */
-static unsigned int num_clusters;
-struct cluster {
- cpumask_var_t cpus;
- /* stats for load detection */
- /* IO */
- u64 last_io_check_ts;
- unsigned int iowait_enter_cycle_cnt;
- unsigned int iowait_exit_cycle_cnt;
- spinlock_t iowait_lock;
- unsigned int cur_io_busy;
- bool io_change;
- /* CPU */
- unsigned int mode;
- bool mode_change;
- u64 last_mode_check_ts;
- unsigned int single_enter_cycle_cnt;
- unsigned int single_exit_cycle_cnt;
- unsigned int multi_enter_cycle_cnt;
- unsigned int multi_exit_cycle_cnt;
- spinlock_t mode_lock;
- /* Perf Cluster Peak Loads */
- unsigned int perf_cl_peak;
- u64 last_perf_cl_check_ts;
- bool perf_cl_detect_state_change;
- unsigned int perf_cl_peak_enter_cycle_cnt;
- unsigned int perf_cl_peak_exit_cycle_cnt;
- spinlock_t perf_cl_peak_lock;
- /* Tunables */
- unsigned int single_enter_load;
- unsigned int pcpu_multi_enter_load;
- unsigned int perf_cl_peak_enter_load;
- unsigned int single_exit_load;
- unsigned int pcpu_multi_exit_load;
- unsigned int perf_cl_peak_exit_load;
- unsigned int single_enter_cycles;
- unsigned int single_exit_cycles;
- unsigned int multi_enter_cycles;
- unsigned int multi_exit_cycles;
- unsigned int perf_cl_peak_enter_cycles;
- unsigned int perf_cl_peak_exit_cycles;
- unsigned int current_freq;
- spinlock_t timer_lock;
- unsigned int timer_rate;
- struct timer_list mode_exit_timer;
- struct timer_list perf_cl_peak_mode_exit_timer;
-};
-
-static struct cluster **managed_clusters;
-static bool clusters_inited;
-
/* To handle cpufreq min/max request */
struct cpu_status {
@@ -87,8 +34,6 @@
};
static DEFINE_PER_CPU(struct cpu_status, cpu_stats);
-static int init_cluster_control(void);
-static int init_events_group(void);
struct events {
spinlock_t cpu_hotplug_lock;
bool cpu_hotplug;
@@ -97,176 +42,7 @@
static struct events events_group;
static struct task_struct *events_notify_thread;
-#define LAST_UPDATE_TOL USEC_PER_MSEC
-
-struct input_events {
- unsigned int evt_x_cnt;
- unsigned int evt_y_cnt;
- unsigned int evt_pres_cnt;
- unsigned int evt_dist_cnt;
-};
-struct trig_thr {
- unsigned int pwr_cl_trigger_threshold;
- unsigned int perf_cl_trigger_threshold;
- unsigned int ip_evt_threshold;
-};
-struct load_stats {
- u64 last_wallclock;
- /* IO wait related */
- u64 last_iowait;
- unsigned int last_iopercent;
- /* CPU load related */
- unsigned int cpu_load;
- /* CPU Freq */
- unsigned int freq;
-};
-static bool input_events_handler_registered;
-static struct input_events *ip_evts;
-static struct trig_thr thr;
-static unsigned int use_input_evts_with_hi_slvt_detect;
-static int register_input_handler(void);
-static void unregister_input_handler(void);
-static DEFINE_PER_CPU(struct load_stats, cpu_load_stats);
-
-/* Bitmask to keep track of the workloads being detected */
-static unsigned int workload_detect;
-#define IO_DETECT 1
-#define MODE_DETECT 2
-#define PERF_CL_PEAK_DETECT 4
-
-/* IOwait related tunables */
-static unsigned int io_enter_cycles = 4;
-static unsigned int io_exit_cycles = 4;
-static u64 iowait_ceiling_pct = 25;
-static u64 iowait_floor_pct = 8;
-#define LAST_IO_CHECK_TOL (3 * USEC_PER_MSEC)
-
-static unsigned int aggr_iobusy;
-static unsigned int aggr_mode;
-
-static struct task_struct *notify_thread;
-
-static struct input_handler *handler;
-
-/* CPU workload detection related */
-#define NO_MODE (0)
-#define SINGLE (1)
-#define MULTI (2)
-#define MIXED (3)
-#define PERF_CL_PEAK (4)
-#define DEF_SINGLE_ENT 90
-#define DEF_PCPU_MULTI_ENT 85
-#define DEF_PERF_CL_PEAK_ENT 80
-#define DEF_SINGLE_EX 60
-#define DEF_PCPU_MULTI_EX 50
-#define DEF_PERF_CL_PEAK_EX 70
-#define DEF_SINGLE_ENTER_CYCLE 4
-#define DEF_SINGLE_EXIT_CYCLE 4
-#define DEF_MULTI_ENTER_CYCLE 4
-#define DEF_MULTI_EXIT_CYCLE 4
-#define DEF_PERF_CL_PEAK_ENTER_CYCLE 100
-#define DEF_PERF_CL_PEAK_EXIT_CYCLE 20
-#define LAST_LD_CHECK_TOL (2 * USEC_PER_MSEC)
-#define CLUSTER_0_THRESHOLD_FREQ 147000
-#define CLUSTER_1_THRESHOLD_FREQ 190000
-#define INPUT_EVENT_CNT_THRESHOLD 15
-#define MAX_LENGTH_CPU_STRING 256
-
/**************************sysfs start********************************/
-
-static int set_num_clusters(const char *buf, const struct kernel_param *kp)
-{
- unsigned int val;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
- if (num_clusters)
- return -EINVAL;
-
- num_clusters = val;
-
- if (init_cluster_control()) {
- num_clusters = 0;
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int get_num_clusters(char *buf, const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u", num_clusters);
-}
-
-static const struct kernel_param_ops param_ops_num_clusters = {
- .set = set_num_clusters,
- .get = get_num_clusters,
-};
-device_param_cb(num_clusters, ¶m_ops_num_clusters, NULL, 0644);
-
-
-static int set_managed_cpus(const char *buf, const struct kernel_param *kp)
-{
- int i, ret;
- struct cpumask tmp_mask;
-
- if (!clusters_inited)
- return -EINVAL;
-
- ret = cpulist_parse(buf, &tmp_mask);
-
- if (ret)
- return ret;
-
- for (i = 0; i < num_clusters; i++) {
- if (cpumask_empty(managed_clusters[i]->cpus)) {
- mutex_lock(&managed_cpus_lock);
- cpumask_copy(managed_clusters[i]->cpus, &tmp_mask);
- mutex_unlock(&managed_cpus_lock);
- break;
- }
- }
-
- return ret;
-}
-
-static int get_managed_cpus(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0, total_cnt = 0;
- char tmp[MAX_LENGTH_CPU_STRING] = "";
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++) {
- cnt = cpumap_print_to_pagebuf(true, buf,
- managed_clusters[i]->cpus);
- if ((i + 1) < num_clusters &&
- (total_cnt + cnt + 1) <= MAX_LENGTH_CPU_STRING) {
- snprintf(tmp + total_cnt, cnt, "%s", buf);
- tmp[cnt-1] = ':';
- tmp[cnt] = '\0';
- total_cnt += cnt;
- } else if ((i + 1) == num_clusters &&
- (total_cnt + cnt) <= MAX_LENGTH_CPU_STRING) {
- snprintf(tmp + total_cnt, cnt, "%s", buf);
- total_cnt += cnt;
- } else {
- pr_err("invalid string for managed_cpu:%s%s\n", tmp,
- buf);
- break;
- }
- }
- snprintf(buf, PAGE_SIZE, "%s", tmp);
- return total_cnt;
-}
-
-static const struct kernel_param_ops param_ops_managed_cpus = {
- .set = set_managed_cpus,
- .get = get_managed_cpus,
-};
-device_param_cb(managed_cpus, ¶m_ops_managed_cpus, NULL, 0644);
-
/*
* Userspace sends cpu#:min_freq_value to vote for min_freq_value as the new
* scaling_min. To withdraw its vote it needs to enter cpu#:0
@@ -425,1716 +201,8 @@
};
module_param_cb(cpu_max_freq, ¶m_ops_cpu_max_freq, NULL, 0644);
-static int set_ip_evt_trigger_threshold(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
-
- thr.ip_evt_threshold = val;
- return 0;
-}
-
-static int get_ip_evt_trigger_threshold(char *buf,
- const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u", thr.ip_evt_threshold);
-}
-
-static const struct kernel_param_ops param_ops_ip_evt_trig_thr = {
- .set = set_ip_evt_trigger_threshold,
- .get = get_ip_evt_trigger_threshold,
-};
-device_param_cb(ip_evt_trig_thr, ¶m_ops_ip_evt_trig_thr, NULL, 0644);
-
-
-static int set_perf_cl_trigger_threshold(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
-
- thr.perf_cl_trigger_threshold = val;
- return 0;
-}
-
-static int get_perf_cl_trigger_threshold(char *buf,
- const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u", thr.perf_cl_trigger_threshold);
-}
-
-static const struct kernel_param_ops param_ops_perf_trig_thr = {
- .set = set_perf_cl_trigger_threshold,
- .get = get_perf_cl_trigger_threshold,
-};
-device_param_cb(perf_cl_trig_thr, ¶m_ops_perf_trig_thr, NULL, 0644);
-
-
-static int set_pwr_cl_trigger_threshold(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
-
- thr.pwr_cl_trigger_threshold = val;
- return 0;
-}
-
-static int get_pwr_cl_trigger_threshold(char *buf,
- const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u", thr.pwr_cl_trigger_threshold);
-}
-
-static const struct kernel_param_ops param_ops_pwr_trig_thr = {
- .set = set_pwr_cl_trigger_threshold,
- .get = get_pwr_cl_trigger_threshold,
-};
-device_param_cb(pwr_cl_trig_thr, ¶m_ops_pwr_trig_thr, NULL, 0644);
-
-static int freq_greater_than_threshold(struct cluster *cl, int idx)
-{
- int rc = 0;
- /* Check for Cluster 0 */
- if (!idx && cl->current_freq >= thr.pwr_cl_trigger_threshold)
- rc = 1;
- /* Check for Cluster 1 */
- if (idx && cl->current_freq >= thr.perf_cl_trigger_threshold)
- rc = 1;
- return rc;
-}
-
-static bool input_events_greater_than_threshold(void)
-{
-
- bool rc = false;
-
- if ((ip_evts->evt_x_cnt >= thr.ip_evt_threshold) ||
- (ip_evts->evt_y_cnt >= thr.ip_evt_threshold) ||
- !use_input_evts_with_hi_slvt_detect)
- rc = true;
-
- return rc;
-}
-
-static int set_single_enter_load(const char *buf, const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val < managed_clusters[i]->single_exit_load)
- return -EINVAL;
-
- managed_clusters[i]->single_enter_load = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_single_enter_load(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->single_enter_load);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_enter_load = {
- .set = set_single_enter_load,
- .get = get_single_enter_load,
-};
-device_param_cb(single_enter_load, ¶m_ops_single_enter_load, NULL, 0644);
-
-static int set_single_exit_load(const char *buf, const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val > managed_clusters[i]->single_enter_load)
- return -EINVAL;
-
- managed_clusters[i]->single_exit_load = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_single_exit_load(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->single_exit_load);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_exit_load = {
- .set = set_single_exit_load,
- .get = get_single_exit_load,
-};
-device_param_cb(single_exit_load, ¶m_ops_single_exit_load, NULL, 0644);
-
-static int set_pcpu_multi_enter_load(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val < managed_clusters[i]->pcpu_multi_exit_load)
- return -EINVAL;
-
- managed_clusters[i]->pcpu_multi_enter_load = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_pcpu_multi_enter_load(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->pcpu_multi_enter_load);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_pcpu_multi_enter_load = {
- .set = set_pcpu_multi_enter_load,
- .get = get_pcpu_multi_enter_load,
-};
-device_param_cb(pcpu_multi_enter_load, ¶m_ops_pcpu_multi_enter_load,
- NULL, 0644);
-
-static int set_pcpu_multi_exit_load(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val > managed_clusters[i]->pcpu_multi_enter_load)
- return -EINVAL;
-
- managed_clusters[i]->pcpu_multi_exit_load = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_pcpu_multi_exit_load(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->pcpu_multi_exit_load);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_pcpu_multi_exit_load = {
- .set = set_pcpu_multi_exit_load,
- .get = get_pcpu_multi_exit_load,
-};
-device_param_cb(pcpu_multi_exit_load, ¶m_ops_pcpu_multi_exit_load,
- NULL, 0644);
-static int set_perf_cl_peak_enter_load(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val < managed_clusters[i]->perf_cl_peak_exit_load)
- return -EINVAL;
-
- managed_clusters[i]->perf_cl_peak_enter_load = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_perf_cl_peak_enter_load(char *buf,
- const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->perf_cl_peak_enter_load);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_enter_load = {
- .set = set_perf_cl_peak_enter_load,
- .get = get_perf_cl_peak_enter_load,
-};
-device_param_cb(perf_cl_peak_enter_load, ¶m_ops_perf_cl_peak_enter_load,
- NULL, 0644);
-
-static int set_perf_cl_peak_exit_load(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val > managed_clusters[i]->perf_cl_peak_enter_load)
- return -EINVAL;
-
- managed_clusters[i]->perf_cl_peak_exit_load = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_perf_cl_peak_exit_load(char *buf,
- const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->perf_cl_peak_exit_load);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_exit_load = {
- .set = set_perf_cl_peak_exit_load,
- .get = get_perf_cl_peak_exit_load,
-};
-device_param_cb(perf_cl_peak_exit_load, ¶m_ops_perf_cl_peak_exit_load,
- NULL, 0644);
-
-static int set_perf_cl_peak_enter_cycles(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- managed_clusters[i]->perf_cl_peak_enter_cycles = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_perf_cl_peak_enter_cycles(char *buf,
- const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "%u:",
- managed_clusters[i]->perf_cl_peak_enter_cycles);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_enter_cycles = {
- .set = set_perf_cl_peak_enter_cycles,
- .get = get_perf_cl_peak_enter_cycles,
-};
-device_param_cb(perf_cl_peak_enter_cycles, ¶m_ops_perf_cl_peak_enter_cycles,
- NULL, 0644);
-
-
-static int set_perf_cl_peak_exit_cycles(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- managed_clusters[i]->perf_cl_peak_exit_cycles = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_perf_cl_peak_exit_cycles(char *buf,
- const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->perf_cl_peak_exit_cycles);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_exit_cycles = {
- .set = set_perf_cl_peak_exit_cycles,
- .get = get_perf_cl_peak_exit_cycles,
-};
-device_param_cb(perf_cl_peak_exit_cycles, ¶m_ops_perf_cl_peak_exit_cycles,
- NULL, 0644);
-
-
-static int set_single_enter_cycles(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- managed_clusters[i]->single_enter_cycles = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_single_enter_cycles(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "%u:",
- managed_clusters[i]->single_enter_cycles);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_enter_cycles = {
- .set = set_single_enter_cycles,
- .get = get_single_enter_cycles,
-};
-device_param_cb(single_enter_cycles, ¶m_ops_single_enter_cycles,
- NULL, 0644);
-
-
-static int set_single_exit_cycles(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- managed_clusters[i]->single_exit_cycles = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_single_exit_cycles(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->single_exit_cycles);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_exit_cycles = {
- .set = set_single_exit_cycles,
- .get = get_single_exit_cycles,
-};
-device_param_cb(single_exit_cycles, ¶m_ops_single_exit_cycles, NULL, 0644);
-
-static int set_multi_enter_cycles(const char *buf,
- const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- managed_clusters[i]->multi_enter_cycles = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_multi_enter_cycles(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->multi_enter_cycles);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_multi_enter_cycles = {
- .set = set_multi_enter_cycles,
- .get = get_multi_enter_cycles,
-};
-device_param_cb(multi_enter_cycles, ¶m_ops_multi_enter_cycles, NULL, 0644);
-
-static int set_multi_exit_cycles(const char *buf, const struct kernel_param *kp)
-{
- unsigned int val, i, ntokens = 0;
- const char *cp = buf;
- unsigned int bytes_left;
-
- if (!clusters_inited)
- return -EINVAL;
-
- while ((cp = strpbrk(cp + 1, ":")))
- ntokens++;
-
- if (ntokens != (num_clusters - 1))
- return -EINVAL;
-
- cp = buf;
- for (i = 0; i < num_clusters; i++) {
-
- if (sscanf(cp, "%u\n", &val) != 1)
- return -EINVAL;
-
- managed_clusters[i]->multi_exit_cycles = val;
-
- bytes_left = PAGE_SIZE - (cp - buf);
- cp = strnchr(cp, bytes_left, ':');
- cp++;
- }
-
- return 0;
-}
-
-static int get_multi_exit_cycles(char *buf, const struct kernel_param *kp)
-{
- int i, cnt = 0;
-
- if (!clusters_inited)
- return cnt;
-
- for (i = 0; i < num_clusters; i++)
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
- "%u:", managed_clusters[i]->multi_exit_cycles);
- cnt--;
- cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
- return cnt;
-}
-
-static const struct kernel_param_ops param_ops_multi_exit_cycles = {
- .set = set_multi_exit_cycles,
- .get = get_multi_exit_cycles,
-};
-device_param_cb(multi_exit_cycles, ¶m_ops_multi_exit_cycles, NULL, 0644);
-
-static int set_io_enter_cycles(const char *buf, const struct kernel_param *kp)
-{
- unsigned int val;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
-
- io_enter_cycles = val;
-
- return 0;
-}
-
-static int get_io_enter_cycles(char *buf, const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u", io_enter_cycles);
-}
-
-static const struct kernel_param_ops param_ops_io_enter_cycles = {
- .set = set_io_enter_cycles,
- .get = get_io_enter_cycles,
-};
-device_param_cb(io_enter_cycles, ¶m_ops_io_enter_cycles, NULL, 0644);
-
-static int set_io_exit_cycles(const char *buf, const struct kernel_param *kp)
-{
- unsigned int val;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
-
- io_exit_cycles = val;
-
- return 0;
-}
-
-static int get_io_exit_cycles(char *buf, const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u", io_exit_cycles);
-}
-
-static const struct kernel_param_ops param_ops_io_exit_cycles = {
- .set = set_io_exit_cycles,
- .get = get_io_exit_cycles,
-};
-device_param_cb(io_exit_cycles, ¶m_ops_io_exit_cycles, NULL, 0644);
-
-static int set_iowait_floor_pct(const char *buf, const struct kernel_param *kp)
-{
- u64 val;
-
- if (sscanf(buf, "%llu\n", &val) != 1)
- return -EINVAL;
- if (val > iowait_ceiling_pct)
- return -EINVAL;
-
- iowait_floor_pct = val;
-
- return 0;
-}
-
-static int get_iowait_floor_pct(char *buf, const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%llu", iowait_floor_pct);
-}
-
-static const struct kernel_param_ops param_ops_iowait_floor_pct = {
- .set = set_iowait_floor_pct,
- .get = get_iowait_floor_pct,
-};
-device_param_cb(iowait_floor_pct, ¶m_ops_iowait_floor_pct, NULL, 0644);
-
-static int set_iowait_ceiling_pct(const char *buf,
- const struct kernel_param *kp)
-{
- u64 val;
-
- if (sscanf(buf, "%llu\n", &val) != 1)
- return -EINVAL;
- if (val < iowait_floor_pct)
- return -EINVAL;
-
- iowait_ceiling_pct = val;
-
- return 0;
-}
-
-static int get_iowait_ceiling_pct(char *buf, const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%llu", iowait_ceiling_pct);
-}
-
-static const struct kernel_param_ops param_ops_iowait_ceiling_pct = {
- .set = set_iowait_ceiling_pct,
- .get = get_iowait_ceiling_pct,
-};
-device_param_cb(iowait_ceiling_pct, ¶m_ops_iowait_ceiling_pct, NULL, 0644);
-
-static int set_workload_detect(const char *buf, const struct kernel_param *kp)
-{
- unsigned int val, i;
- struct cluster *i_cl;
- unsigned long flags;
-
- if (!clusters_inited)
- return -EINVAL;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val == workload_detect)
- return 0;
-
- workload_detect = val;
- if (!(workload_detect & IO_DETECT)) {
- for (i = 0; i < num_clusters; i++) {
- i_cl = managed_clusters[i];
- spin_lock_irqsave(&i_cl->iowait_lock, flags);
- i_cl->iowait_enter_cycle_cnt = 0;
- i_cl->iowait_exit_cycle_cnt = 0;
- i_cl->cur_io_busy = 0;
- i_cl->io_change = true;
- spin_unlock_irqrestore(&i_cl->iowait_lock, flags);
- }
- }
- if (!(workload_detect & MODE_DETECT)) {
- for (i = 0; i < num_clusters; i++) {
- i_cl = managed_clusters[i];
- spin_lock_irqsave(&i_cl->mode_lock, flags);
- i_cl->single_enter_cycle_cnt = 0;
- i_cl->single_exit_cycle_cnt = 0;
- i_cl->multi_enter_cycle_cnt = 0;
- i_cl->multi_exit_cycle_cnt = 0;
- i_cl->mode = 0;
- i_cl->mode_change = true;
- spin_unlock_irqrestore(&i_cl->mode_lock, flags);
- }
- }
-
- if (!(workload_detect & PERF_CL_PEAK_DETECT)) {
- for (i = 0; i < num_clusters; i++) {
- i_cl = managed_clusters[i];
- spin_lock_irqsave(&i_cl->perf_cl_peak_lock, flags);
- i_cl->perf_cl_peak_enter_cycle_cnt = 0;
- i_cl->perf_cl_peak_exit_cycle_cnt = 0;
- i_cl->perf_cl_peak = 0;
- spin_unlock_irqrestore(&i_cl->perf_cl_peak_lock, flags);
- }
- }
-
- wake_up_process(notify_thread);
- return 0;
-}
-
-static int get_workload_detect(char *buf, const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u", workload_detect);
-}
-
-static const struct kernel_param_ops param_ops_workload_detect = {
- .set = set_workload_detect,
- .get = get_workload_detect,
-};
-device_param_cb(workload_detect, ¶m_ops_workload_detect, NULL, 0644);
-
-
-static int set_input_evts_with_hi_slvt_detect(const char *buf,
- const struct kernel_param *kp)
-{
-
- unsigned int val;
-
- if (sscanf(buf, "%u\n", &val) != 1)
- return -EINVAL;
-
- if (val == use_input_evts_with_hi_slvt_detect)
- return 0;
-
- use_input_evts_with_hi_slvt_detect = val;
-
- if ((workload_detect & PERF_CL_PEAK_DETECT) &&
- !input_events_handler_registered &&
- use_input_evts_with_hi_slvt_detect) {
- if (register_input_handler() == -ENOMEM) {
- use_input_evts_with_hi_slvt_detect = 0;
- return -ENOMEM;
- }
- } else if ((workload_detect & PERF_CL_PEAK_DETECT) &&
- input_events_handler_registered &&
- !use_input_evts_with_hi_slvt_detect) {
- unregister_input_handler();
- }
- return 0;
-}
-
-static int get_input_evts_with_hi_slvt_detect(char *buf,
- const struct kernel_param *kp)
-{
- return snprintf(buf, PAGE_SIZE, "%u",
- use_input_evts_with_hi_slvt_detect);
-}
-
-static const struct kernel_param_ops param_ops_ip_evts_with_hi_slvt_detect = {
- .set = set_input_evts_with_hi_slvt_detect,
- .get = get_input_evts_with_hi_slvt_detect,
-};
-device_param_cb(input_evts_with_hi_slvt_detect,
- ¶m_ops_ip_evts_with_hi_slvt_detect, NULL, 0644);
-
-static struct kobject *mode_kobj;
-
-static ssize_t show_aggr_mode(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", aggr_mode);
-}
-static struct kobj_attribute aggr_mode_attr =
-__ATTR(aggr_mode, 0444, show_aggr_mode, NULL);
-
-static ssize_t show_aggr_iobusy(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", aggr_iobusy);
-}
-static struct kobj_attribute aggr_iobusy_attr =
-__ATTR(aggr_iobusy, 0444, show_aggr_iobusy, NULL);
-
-static struct attribute *attrs[] = {
- &aggr_mode_attr.attr,
- &aggr_iobusy_attr.attr,
- NULL,
-};
-
-static struct attribute_group attr_group = {
- .attrs = attrs,
-};
-
-static bool check_notify_status(void)
-{
- int i;
- struct cluster *cl;
- bool any_change = false;
- unsigned long flags;
-
-
- for (i = 0; i < num_clusters; i++) {
- cl = managed_clusters[i];
- spin_lock_irqsave(&cl->iowait_lock, flags);
- if (!any_change)
- any_change = cl->io_change;
- cl->io_change = false;
- spin_unlock_irqrestore(&cl->iowait_lock, flags);
-
- spin_lock_irqsave(&cl->mode_lock, flags);
- if (!any_change)
- any_change = cl->mode_change;
- cl->mode_change = false;
- spin_unlock_irqrestore(&cl->mode_lock, flags);
-
- spin_lock_irqsave(&cl->perf_cl_peak_lock, flags);
- if (!any_change)
- any_change = cl->perf_cl_detect_state_change;
- cl->perf_cl_detect_state_change = false;
- spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
- }
-
- return any_change;
-}
-
-static int notify_userspace(void *data)
-{
- unsigned int i, io, cpu_mode, perf_cl_peak_mode;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (!check_notify_status()) {
- schedule();
-
- if (kthread_should_stop())
- break;
- }
- set_current_state(TASK_RUNNING);
-
- io = 0;
- cpu_mode = 0;
- perf_cl_peak_mode = 0;
- for (i = 0; i < num_clusters; i++) {
- io |= managed_clusters[i]->cur_io_busy;
- cpu_mode |= managed_clusters[i]->mode;
- perf_cl_peak_mode |= managed_clusters[i]->perf_cl_peak;
- }
- if (io != aggr_iobusy) {
- aggr_iobusy = io;
- sysfs_notify(mode_kobj, NULL, "aggr_iobusy");
- pr_debug("msm_perf: Notifying IO: %u\n", aggr_iobusy);
- }
- if ((aggr_mode & (SINGLE | MULTI)) != cpu_mode) {
- aggr_mode &= ~(SINGLE | MULTI);
- aggr_mode |= cpu_mode;
- sysfs_notify(mode_kobj, NULL, "aggr_mode");
- pr_debug("msm_perf: Notifying CPU mode:%u\n",
- aggr_mode);
- }
- if ((aggr_mode & PERF_CL_PEAK) != perf_cl_peak_mode) {
- aggr_mode &= ~(PERF_CL_PEAK);
- aggr_mode |= perf_cl_peak_mode;
- sysfs_notify(mode_kobj, NULL, "aggr_mode");
- pr_debug("msm_perf: Notifying Gaming mode:%u\n",
- aggr_mode);
- }
- }
-
- return 0;
-}
-
-static void check_cluster_iowait(struct cluster *cl, u64 now)
-{
- struct load_stats *pcpu_st;
- unsigned int i;
- unsigned long flags;
- unsigned int temp_iobusy;
- u64 max_iowait = 0;
-
- spin_lock_irqsave(&cl->iowait_lock, flags);
-
- if (((now - cl->last_io_check_ts)
- < (cl->timer_rate - LAST_IO_CHECK_TOL)) ||
- !(workload_detect & IO_DETECT)) {
- spin_unlock_irqrestore(&cl->iowait_lock, flags);
- return;
- }
-
- temp_iobusy = cl->cur_io_busy;
- for_each_cpu(i, cl->cpus) {
- pcpu_st = &per_cpu(cpu_load_stats, i);
- if ((now - pcpu_st->last_wallclock)
- > (cl->timer_rate + LAST_UPDATE_TOL))
- continue;
- if (max_iowait < pcpu_st->last_iopercent)
- max_iowait = pcpu_st->last_iopercent;
- }
-
- if (!cl->cur_io_busy) {
- if (max_iowait > iowait_ceiling_pct) {
- cl->iowait_enter_cycle_cnt++;
- if (cl->iowait_enter_cycle_cnt >= io_enter_cycles) {
- cl->cur_io_busy = 1;
- cl->iowait_enter_cycle_cnt = 0;
- }
- } else {
- cl->iowait_enter_cycle_cnt = 0;
- }
- } else {
- if (max_iowait < iowait_floor_pct) {
- cl->iowait_exit_cycle_cnt++;
- if (cl->iowait_exit_cycle_cnt >= io_exit_cycles) {
- cl->cur_io_busy = 0;
- cl->iowait_exit_cycle_cnt = 0;
- }
- } else {
- cl->iowait_exit_cycle_cnt = 0;
- }
- }
-
- cl->last_io_check_ts = now;
- trace_track_iowait(cpumask_first(cl->cpus), cl->iowait_enter_cycle_cnt,
- cl->iowait_exit_cycle_cnt, cl->cur_io_busy, max_iowait);
-
- if (temp_iobusy != cl->cur_io_busy) {
- cl->io_change = true;
- pr_debug("msm_perf: IO changed to %u\n", cl->cur_io_busy);
- }
-
- spin_unlock_irqrestore(&cl->iowait_lock, flags);
- if (cl->io_change)
- wake_up_process(notify_thread);
-}
-
-static void disable_timer(struct cluster *cl)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cl->timer_lock, flags);
-
- if (del_timer(&cl->mode_exit_timer)) {
- trace_single_cycle_exit_timer_stop(cpumask_first(cl->cpus),
- cl->single_enter_cycles, cl->single_enter_cycle_cnt,
- cl->single_exit_cycles, cl->single_exit_cycle_cnt,
- cl->multi_enter_cycles, cl->multi_enter_cycle_cnt,
- cl->multi_exit_cycles, cl->multi_exit_cycle_cnt,
- cl->timer_rate, cl->mode);
- }
-
- spin_unlock_irqrestore(&cl->timer_lock, flags);
-}
-
-static void start_timer(struct cluster *cl)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cl->timer_lock, flags);
- if ((cl->mode & SINGLE) && !timer_pending(&cl->mode_exit_timer)) {
- /* Set timer for the Cluster since there is none pending */
- cl->mode_exit_timer.expires = get_jiffies_64() +
- usecs_to_jiffies(cl->single_exit_cycles * cl->timer_rate);
- cl->mode_exit_timer.data = cpumask_first(cl->cpus);
- add_timer(&cl->mode_exit_timer);
- trace_single_cycle_exit_timer_start(cpumask_first(cl->cpus),
- cl->single_enter_cycles, cl->single_enter_cycle_cnt,
- cl->single_exit_cycles, cl->single_exit_cycle_cnt,
- cl->multi_enter_cycles, cl->multi_enter_cycle_cnt,
- cl->multi_exit_cycles, cl->multi_exit_cycle_cnt,
- cl->timer_rate, cl->mode);
- }
- spin_unlock_irqrestore(&cl->timer_lock, flags);
-}
-
-static void disable_perf_cl_peak_timer(struct cluster *cl)
-{
-
- if (del_timer(&cl->perf_cl_peak_mode_exit_timer)) {
- trace_perf_cl_peak_exit_timer_stop(cpumask_first(cl->cpus),
- cl->perf_cl_peak_enter_cycles,
- cl->perf_cl_peak_enter_cycle_cnt,
- cl->perf_cl_peak_exit_cycles,
- cl->perf_cl_peak_exit_cycle_cnt,
- cl->timer_rate, cl->mode);
- }
-
-}
-
-static void start_perf_cl_peak_timer(struct cluster *cl)
-{
- if ((cl->mode & PERF_CL_PEAK) &&
- !timer_pending(&cl->perf_cl_peak_mode_exit_timer)) {
- /* Set timer for the Cluster since there is none pending */
- cl->perf_cl_peak_mode_exit_timer.expires = get_jiffies_64() +
- usecs_to_jiffies(cl->perf_cl_peak_exit_cycles * cl->timer_rate);
- cl->perf_cl_peak_mode_exit_timer.data = cpumask_first(cl->cpus);
- add_timer(&cl->perf_cl_peak_mode_exit_timer);
- trace_perf_cl_peak_exit_timer_start(cpumask_first(cl->cpus),
- cl->perf_cl_peak_enter_cycles,
- cl->perf_cl_peak_enter_cycle_cnt,
- cl->perf_cl_peak_exit_cycles,
- cl->perf_cl_peak_exit_cycle_cnt,
- cl->timer_rate, cl->mode);
- }
-}
-
-static const struct input_device_id msm_perf_input_ids[] = {
-
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
- .evbit = {BIT_MASK(EV_ABS)},
- .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
- BIT_MASK(ABS_MT_POSITION_X) |
- BIT_MASK(ABS_MT_POSITION_Y)},
- },
-
- {},
-};
-
-static void msm_perf_input_event_handler(struct input_handle *handle,
- unsigned int type,
- unsigned int code,
- int value)
-{
- if (type != EV_ABS)
- return;
-
- switch (code) {
-
- case ABS_MT_POSITION_X:
- ip_evts->evt_x_cnt++;
- break;
- case ABS_MT_POSITION_Y:
- ip_evts->evt_y_cnt++;
- break;
-
- case ABS_MT_DISTANCE:
- break;
-
- case ABS_MT_PRESSURE:
- break;
-
- default:
- break;
-
- }
-}
-static int msm_perf_input_connect(struct input_handler *handler,
- struct input_dev *dev,
- const struct input_device_id *id)
-{
- int rc;
- struct input_handle *handle;
-
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle)
- return -ENOMEM;
-
- handle->dev = dev;
- handle->handler = handler;
- handle->name = handler->name;
-
- rc = input_register_handle(handle);
- if (rc) {
- pr_err("Failed to register handle\n");
- goto error;
- }
-
- rc = input_open_device(handle);
- if (rc) {
- pr_err("Failed to open device\n");
- goto error_unregister;
- }
- return 0;
-
-error_unregister:
- input_unregister_handle(handle);
-error:
- kfree(handle);
- return rc;
-}
-
-static void msm_perf_input_disconnect(struct input_handle *handle)
-{
- input_close_device(handle);
- input_unregister_handle(handle);
- kfree(handle);
-}
-
-static void unregister_input_handler(void)
-{
- if (handler != NULL) {
- input_unregister_handler(handler);
- input_events_handler_registered = false;
- }
-}
-
-static int register_input_handler(void)
-{
- int rc;
-
- if (handler == NULL) {
- handler = kzalloc(sizeof(*handler), GFP_KERNEL);
- if (!handler)
- return -ENOMEM;
- handler->event = msm_perf_input_event_handler;
- handler->connect = msm_perf_input_connect;
- handler->disconnect = msm_perf_input_disconnect;
- handler->name = "msm_perf";
- handler->id_table = msm_perf_input_ids;
- handler->private = NULL;
- }
- rc = input_register_handler(handler);
- if (rc) {
- pr_err("Unable to register the input handler for msm_perf\n");
- kfree(handler);
- } else {
- input_events_handler_registered = true;
- }
- return rc;
-}
-
-static void check_perf_cl_peak_load(struct cluster *cl, u64 now)
-{
- struct load_stats *pcpu_st;
- unsigned int i, ret_mode, max_load = 0;
- unsigned int total_load = 0, cpu_cnt = 0;
- unsigned long flags;
- bool cpu_of_cluster_zero = true;
-
- spin_lock_irqsave(&cl->perf_cl_peak_lock, flags);
-
- cpu_of_cluster_zero = cpumask_first(cl->cpus) ? false:true;
- /*
- * If delta of last load to now < than timer_rate - ld check tolerance
- * which is 18ms OR if perf_cl_peak detection not set
- * OR the first CPU of Cluster is CPU 0 (LVT)
- * then return do nothing. We are interested only in SLVT
- */
- if (((now - cl->last_perf_cl_check_ts)
- < (cl->timer_rate - LAST_LD_CHECK_TOL)) ||
- !(workload_detect & PERF_CL_PEAK_DETECT) ||
- cpu_of_cluster_zero) {
- spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
- return;
- }
- for_each_cpu(i, cl->cpus) {
- pcpu_st = &per_cpu(cpu_load_stats, i);
- if ((now - pcpu_st->last_wallclock)
- > (cl->timer_rate + LAST_UPDATE_TOL))
- continue;
- if (pcpu_st->cpu_load > max_load)
- max_load = pcpu_st->cpu_load;
- /*
- * Save the frequency for the cpu of the cluster
- * This frequency is the most recent/current
- * as obtained due to a transition
- * notifier callback.
- */
- cl->current_freq = pcpu_st->freq;
- }
- ret_mode = cl->perf_cl_peak;
-
- if (!(cl->perf_cl_peak & PERF_CL_PEAK)) {
- if (max_load >= cl->perf_cl_peak_enter_load &&
- freq_greater_than_threshold(cl,
- cpumask_first(cl->cpus))) {
- /*
- * Reset the event count for the first cycle
- * of perf_cl_peak we detect
- */
- if (!cl->perf_cl_peak_enter_cycle_cnt)
- ip_evts->evt_x_cnt = ip_evts->evt_y_cnt = 0;
- cl->perf_cl_peak_enter_cycle_cnt++;
- if (cl->perf_cl_peak_enter_cycle_cnt >=
- cl->perf_cl_peak_enter_cycles) {
- if (input_events_greater_than_threshold())
- ret_mode |= PERF_CL_PEAK;
- cl->perf_cl_peak_enter_cycle_cnt = 0;
- }
- } else {
- cl->perf_cl_peak_enter_cycle_cnt = 0;
- /* Reset the event count */
- ip_evts->evt_x_cnt = ip_evts->evt_y_cnt = 0;
- }
- } else {
- if (max_load >= cl->perf_cl_peak_exit_load &&
- freq_greater_than_threshold(cl,
- cpumask_first(cl->cpus))) {
- cl->perf_cl_peak_exit_cycle_cnt = 0;
- disable_perf_cl_peak_timer(cl);
- } else {
- start_perf_cl_peak_timer(cl);
- cl->perf_cl_peak_exit_cycle_cnt++;
- if (cl->perf_cl_peak_exit_cycle_cnt
- >= cl->perf_cl_peak_exit_cycles) {
- ret_mode &= ~PERF_CL_PEAK;
- cl->perf_cl_peak_exit_cycle_cnt = 0;
- disable_perf_cl_peak_timer(cl);
- }
- }
- }
-
- cl->last_perf_cl_check_ts = now;
- if (ret_mode != cl->perf_cl_peak) {
- pr_debug("msm_perf: Mode changed to %u\n", ret_mode);
- cl->perf_cl_peak = ret_mode;
- cl->perf_cl_detect_state_change = true;
- }
-
- trace_cpu_mode_detect(cpumask_first(cl->cpus), max_load,
- cl->single_enter_cycle_cnt, cl->single_exit_cycle_cnt,
- total_load, cl->multi_enter_cycle_cnt,
- cl->multi_exit_cycle_cnt, cl->perf_cl_peak_enter_cycle_cnt,
- cl->perf_cl_peak_exit_cycle_cnt, cl->mode, cpu_cnt);
-
- spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
-
- if (cl->perf_cl_detect_state_change)
- wake_up_process(notify_thread);
-
-}
-
-static void check_cpu_load(struct cluster *cl, u64 now)
-{
- struct load_stats *pcpu_st;
- unsigned int i, max_load = 0, total_load = 0, ret_mode, cpu_cnt = 0;
- unsigned int total_load_ceil, total_load_floor;
- unsigned long flags;
-
- spin_lock_irqsave(&cl->mode_lock, flags);
-
- if (((now - cl->last_mode_check_ts)
- < (cl->timer_rate - LAST_LD_CHECK_TOL)) ||
- !(workload_detect & MODE_DETECT)) {
- spin_unlock_irqrestore(&cl->mode_lock, flags);
- return;
- }
-
- for_each_cpu(i, cl->cpus) {
- pcpu_st = &per_cpu(cpu_load_stats, i);
- if ((now - pcpu_st->last_wallclock)
- > (cl->timer_rate + LAST_UPDATE_TOL))
- continue;
- if (pcpu_st->cpu_load > max_load)
- max_load = pcpu_st->cpu_load;
- total_load += pcpu_st->cpu_load;
- cpu_cnt++;
- }
-
- if (cpu_cnt > 1) {
- total_load_ceil = cl->pcpu_multi_enter_load * cpu_cnt;
- total_load_floor = cl->pcpu_multi_exit_load * cpu_cnt;
- } else {
- total_load_ceil = UINT_MAX;
- total_load_floor = UINT_MAX;
- }
-
- ret_mode = cl->mode;
- if (!(cl->mode & SINGLE)) {
- if (max_load >= cl->single_enter_load) {
- cl->single_enter_cycle_cnt++;
- if (cl->single_enter_cycle_cnt
- >= cl->single_enter_cycles) {
- ret_mode |= SINGLE;
- cl->single_enter_cycle_cnt = 0;
- }
- } else {
- cl->single_enter_cycle_cnt = 0;
- }
- } else {
- if (max_load < cl->single_exit_load) {
- start_timer(cl);
- cl->single_exit_cycle_cnt++;
- if (cl->single_exit_cycle_cnt
- >= cl->single_exit_cycles) {
- ret_mode &= ~SINGLE;
- cl->single_exit_cycle_cnt = 0;
- disable_timer(cl);
- }
- } else {
- cl->single_exit_cycle_cnt = 0;
- disable_timer(cl);
- }
- }
-
- if (!(cl->mode & MULTI)) {
- if (total_load >= total_load_ceil) {
- cl->multi_enter_cycle_cnt++;
- if (cl->multi_enter_cycle_cnt
- >= cl->multi_enter_cycles) {
- ret_mode |= MULTI;
- cl->multi_enter_cycle_cnt = 0;
- }
- } else {
- cl->multi_enter_cycle_cnt = 0;
- }
- } else {
- if (total_load < total_load_floor) {
- cl->multi_exit_cycle_cnt++;
- if (cl->multi_exit_cycle_cnt
- >= cl->multi_exit_cycles) {
- ret_mode &= ~MULTI;
- cl->multi_exit_cycle_cnt = 0;
- }
- } else {
- cl->multi_exit_cycle_cnt = 0;
- }
- }
-
- cl->last_mode_check_ts = now;
-
- if (ret_mode != cl->mode) {
- cl->mode = ret_mode;
- cl->mode_change = true;
- pr_debug("msm_perf: Mode changed to %u\n", ret_mode);
- }
-
- trace_cpu_mode_detect(cpumask_first(cl->cpus), max_load,
- cl->single_enter_cycle_cnt, cl->single_exit_cycle_cnt,
- total_load, cl->multi_enter_cycle_cnt,
- cl->multi_exit_cycle_cnt, cl->perf_cl_peak_enter_cycle_cnt,
- cl->perf_cl_peak_exit_cycle_cnt, cl->mode, cpu_cnt);
-
- spin_unlock_irqrestore(&cl->mode_lock, flags);
-
- if (cl->mode_change)
- wake_up_process(notify_thread);
-}
-
-static void check_workload_stats(unsigned int cpu, unsigned int rate, u64 now)
-{
- struct cluster *cl = NULL;
- unsigned int i;
-
- for (i = 0; i < num_clusters; i++) {
- if (cpumask_test_cpu(cpu, managed_clusters[i]->cpus)) {
- cl = managed_clusters[i];
- break;
- }
- }
- if (cl == NULL)
- return;
-
- cl->timer_rate = rate;
- check_cluster_iowait(cl, now);
- check_cpu_load(cl, now);
- check_perf_cl_peak_load(cl, now);
-}
-
-static int perf_govinfo_notify(struct notifier_block *nb, unsigned long val,
- void *data)
-{
- struct cpufreq_govinfo *gov_info = data;
- unsigned int cpu = gov_info->cpu;
- struct load_stats *cpu_st = &per_cpu(cpu_load_stats, cpu);
- u64 now, cur_iowait, time_diff, iowait_diff;
-
- if (!clusters_inited || !workload_detect)
- return NOTIFY_OK;
-
- cur_iowait = get_cpu_iowait_time_us(cpu, &now);
- if (cur_iowait >= cpu_st->last_iowait)
- iowait_diff = cur_iowait - cpu_st->last_iowait;
- else
- iowait_diff = 0;
-
- if (now > cpu_st->last_wallclock)
- time_diff = now - cpu_st->last_wallclock;
- else
- return NOTIFY_OK;
-
- if (iowait_diff <= time_diff) {
- iowait_diff *= 100;
- cpu_st->last_iopercent = div64_u64(iowait_diff, time_diff);
- } else {
- cpu_st->last_iopercent = 100;
- }
-
- cpu_st->last_wallclock = now;
- cpu_st->last_iowait = cur_iowait;
- cpu_st->cpu_load = gov_info->load;
-
- /*
- * Avoid deadlock in case governor notifier ran in the context
- * of notify_work thread
- */
- if (current == notify_thread)
- return NOTIFY_OK;
-
- check_workload_stats(cpu, gov_info->sampling_rate_us, now);
-
- return NOTIFY_OK;
-}
-
-static int perf_cputrans_notify(struct notifier_block *nb, unsigned long val,
- void *data)
-{
- struct cpufreq_freqs *freq = data;
- unsigned int cpu = freq->cpu;
- unsigned long flags;
- unsigned int i;
- struct cluster *cl = NULL;
- struct load_stats *cpu_st = &per_cpu(cpu_load_stats, cpu);
-
- if (!clusters_inited || !workload_detect)
- return NOTIFY_OK;
- for (i = 0; i < num_clusters; i++) {
- if (cpumask_test_cpu(cpu, managed_clusters[i]->cpus)) {
- cl = managed_clusters[i];
- break;
- }
- }
- if (cl == NULL)
- return NOTIFY_OK;
- if (val == CPUFREQ_POSTCHANGE) {
- spin_lock_irqsave(&cl->perf_cl_peak_lock, flags);
- cpu_st->freq = freq->new;
- spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
- }
-
- /*
- * Avoid deadlock in case governor notifier ran in the context
- * of notify_work thread
- */
- if (current == notify_thread)
- return NOTIFY_OK;
- return NOTIFY_OK;
-}
-
-static struct notifier_block perf_govinfo_nb = {
- .notifier_call = perf_govinfo_notify,
-};
-
-static struct notifier_block perf_cputransitions_nb = {
- .notifier_call = perf_cputrans_notify,
-};
-
-static void single_mod_exit_timer(unsigned long data)
-{
- int i;
- struct cluster *i_cl = NULL;
- unsigned long flags;
-
- if (!clusters_inited)
- return;
-
- for (i = 0; i < num_clusters; i++) {
- if (cpumask_test_cpu(data,
- managed_clusters[i]->cpus)) {
- i_cl = managed_clusters[i];
- break;
- }
- }
-
- if (i_cl == NULL)
- return;
-
- spin_lock_irqsave(&i_cl->mode_lock, flags);
- if (i_cl->mode & SINGLE) {
- /* Disable SINGLE mode and exit since the timer expired */
- i_cl->mode = i_cl->mode & ~SINGLE;
- i_cl->single_enter_cycle_cnt = 0;
- i_cl->single_exit_cycle_cnt = 0;
- trace_single_mode_timeout(cpumask_first(i_cl->cpus),
- i_cl->single_enter_cycles, i_cl->single_enter_cycle_cnt,
- i_cl->single_exit_cycles, i_cl->single_exit_cycle_cnt,
- i_cl->multi_enter_cycles, i_cl->multi_enter_cycle_cnt,
- i_cl->multi_exit_cycles, i_cl->multi_exit_cycle_cnt,
- i_cl->timer_rate, i_cl->mode);
- }
- spin_unlock_irqrestore(&i_cl->mode_lock, flags);
- wake_up_process(notify_thread);
-}
-
-static void perf_cl_peak_mod_exit_timer(unsigned long data)
-{
- int i;
- struct cluster *i_cl = NULL;
- unsigned long flags;
-
- if (!clusters_inited)
- return;
-
- for (i = 0; i < num_clusters; i++) {
- if (cpumask_test_cpu(data,
- managed_clusters[i]->cpus)) {
- i_cl = managed_clusters[i];
- break;
- }
- }
- if (i_cl == NULL)
- return;
- spin_lock_irqsave(&i_cl->perf_cl_peak_lock, flags);
- if (i_cl->perf_cl_peak & PERF_CL_PEAK) {
- /* Disable PERF_CL_PEAK mode and exit since the timer expired */
- i_cl->perf_cl_peak = i_cl->perf_cl_peak & ~PERF_CL_PEAK;
- i_cl->perf_cl_peak_enter_cycle_cnt = 0;
- i_cl->perf_cl_peak_exit_cycle_cnt = 0;
- }
- spin_unlock_irqrestore(&i_cl->perf_cl_peak_lock, flags);
- wake_up_process(notify_thread);
-}
/* CPU Hotplug */
static struct kobject *events_kobj;
@@ -2186,19 +254,18 @@
.notifier_call = perf_adjust_notify,
};
-static void hotplug_notify(int action)
+static int hotplug_notify(unsigned int cpu)
{
unsigned long flags;
- if (!events_group.init_success)
- return;
-
- if ((action == CPU_ONLINE) || (action == CPU_DEAD)) {
+ if (events_group.init_success) {
spin_lock_irqsave(&(events_group.cpu_hotplug_lock), flags);
events_group.cpu_hotplug = true;
spin_unlock_irqrestore(&(events_group.cpu_hotplug_lock), flags);
wake_up_process(events_notify_thread);
}
+
+ return 0;
}
static int events_notify_userspace(void *data)
@@ -2233,138 +300,7 @@
return 0;
}
-static int __ref msm_performance_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- uint32_t cpu = (uintptr_t)hcpu;
- unsigned int i;
- struct cluster *i_cl = NULL;
- hotplug_notify(action);
-
- if (!clusters_inited)
- return NOTIFY_OK;
-
- for (i = 0; i < num_clusters; i++) {
- if (managed_clusters[i]->cpus == NULL)
- return NOTIFY_OK;
- if (cpumask_test_cpu(cpu, managed_clusters[i]->cpus)) {
- i_cl = managed_clusters[i];
- break;
- }
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata msm_performance_cpu_notifier = {
- .notifier_call = msm_performance_cpu_callback,
-};
-
-static int init_cluster_control(void)
-{
- unsigned int i;
- int ret = 0;
-
- struct kobject *module_kobj;
-
- managed_clusters = kcalloc(num_clusters, sizeof(struct cluster *),
- GFP_KERNEL);
- if (!managed_clusters)
- return -ENOMEM;
- for (i = 0; i < num_clusters; i++) {
- managed_clusters[i] = kcalloc(1, sizeof(struct cluster),
- GFP_KERNEL);
- if (!managed_clusters[i]) {
- ret = -ENOMEM;
- goto error;
- }
- if (!alloc_cpumask_var(&managed_clusters[i]->cpus,
- GFP_KERNEL)) {
- ret = -ENOMEM;
- goto error;
- }
-
- managed_clusters[i]->single_enter_load = DEF_SINGLE_ENT;
- managed_clusters[i]->single_exit_load = DEF_SINGLE_EX;
- managed_clusters[i]->single_enter_cycles
- = DEF_SINGLE_ENTER_CYCLE;
- managed_clusters[i]->single_exit_cycles
- = DEF_SINGLE_EXIT_CYCLE;
- managed_clusters[i]->pcpu_multi_enter_load
- = DEF_PCPU_MULTI_ENT;
- managed_clusters[i]->pcpu_multi_exit_load = DEF_PCPU_MULTI_EX;
- managed_clusters[i]->multi_enter_cycles = DEF_MULTI_ENTER_CYCLE;
- managed_clusters[i]->multi_exit_cycles = DEF_MULTI_EXIT_CYCLE;
- managed_clusters[i]->perf_cl_peak_enter_load =
- DEF_PERF_CL_PEAK_ENT;
- managed_clusters[i]->perf_cl_peak_exit_load =
- DEF_PERF_CL_PEAK_EX;
- managed_clusters[i]->perf_cl_peak_enter_cycles =
- DEF_PERF_CL_PEAK_ENTER_CYCLE;
- managed_clusters[i]->perf_cl_peak_exit_cycles =
- DEF_PERF_CL_PEAK_EXIT_CYCLE;
-
- /* Initialize trigger threshold */
- thr.perf_cl_trigger_threshold = CLUSTER_1_THRESHOLD_FREQ;
- thr.pwr_cl_trigger_threshold = CLUSTER_0_THRESHOLD_FREQ;
- thr.ip_evt_threshold = INPUT_EVENT_CNT_THRESHOLD;
- spin_lock_init(&(managed_clusters[i]->iowait_lock));
- spin_lock_init(&(managed_clusters[i]->mode_lock));
- spin_lock_init(&(managed_clusters[i]->timer_lock));
- spin_lock_init(&(managed_clusters[i]->perf_cl_peak_lock));
- init_timer(&managed_clusters[i]->mode_exit_timer);
- managed_clusters[i]->mode_exit_timer.function =
- single_mod_exit_timer;
- init_timer(&managed_clusters[i]->perf_cl_peak_mode_exit_timer);
- managed_clusters[i]->perf_cl_peak_mode_exit_timer.function =
- perf_cl_peak_mod_exit_timer;
- }
-
- mutex_init(&managed_cpus_lock);
-
- ip_evts = kcalloc(1, sizeof(struct input_events), GFP_KERNEL);
- if (!ip_evts) {
- ret = -ENOMEM;
- goto error;
- }
- module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
- if (!module_kobj) {
- pr_err("msm_perf: Couldn't find module kobject\n");
- ret = -ENOENT;
- goto error;
- }
- mode_kobj = kobject_create_and_add("workload_modes", module_kobj);
- if (!mode_kobj) {
- pr_err("msm_perf: Failed to add mode_kobj\n");
- ret = -ENOMEM;
- kobject_put(module_kobj);
- goto error;
- }
- ret = sysfs_create_group(mode_kobj, &attr_group);
- if (ret) {
- pr_err("msm_perf: Failed to create sysfs\n");
- kobject_put(module_kobj);
- kobject_put(mode_kobj);
- goto error;
- }
- notify_thread = kthread_run(notify_userspace, NULL, "wrkld_notify");
-
- clusters_inited = true;
-
- return 0;
-
-error:
- for (i = 0; i < num_clusters; i++) {
- if (!managed_clusters[i])
- break;
- if (managed_clusters[i]->cpus)
- free_cpumask_var(managed_clusters[i]->cpus);
- kfree(managed_clusters[i]);
- }
- kfree(managed_clusters);
- return ret;
-}
static int init_events_group(void)
{
@@ -2403,16 +339,17 @@
static int __init msm_performance_init(void)
{
unsigned int cpu;
+ int rc;
cpufreq_register_notifier(&perf_cpufreq_nb, CPUFREQ_POLICY_NOTIFIER);
- cpufreq_register_notifier(&perf_govinfo_nb, CPUFREQ_GOVINFO_NOTIFIER);
- cpufreq_register_notifier(&perf_cputransitions_nb,
- CPUFREQ_TRANSITION_NOTIFIER);
for_each_present_cpu(cpu)
per_cpu(cpu_stats, cpu).max = UINT_MAX;
- register_cpu_notifier(&msm_performance_cpu_notifier);
+ rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE,
+ "msm_performance_cpu_hotplug",
+ hotplug_notify,
+ NULL);
init_events_group();
diff --git a/drivers/thermal/qcom/qti_virtual_sensor.c b/drivers/thermal/qcom/qti_virtual_sensor.c
index 9b4fae8..cc66f37 100644
--- a/drivers/thermal/qcom/qti_virtual_sensor.c
+++ b/drivers/thermal/qcom/qti_virtual_sensor.c
@@ -79,6 +79,18 @@
"apc1-l2-usr"},
.logic = VIRT_MAXIMUM,
},
+ {
+ .virt_zone_name = "hepta-cpu-max-step",
+ .num_sensors = 7,
+ .sensor_names = {"apc1-cpu0-usr",
+ "apc1-cpu1-usr",
+ "apc1-cpu2-usr",
+ "apc1-cpu3-usr",
+ "cpuss0-usr",
+ "cpuss1-usr",
+ "cpuss3-usr"},
+ .logic = VIRT_MAXIMUM,
+ },
};
int qti_virtual_sensor_register(struct device *dev)
diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
index 56a8e1b..fcfdb26 100644
--- a/drivers/usb/gadget/function/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -793,7 +793,8 @@
rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
if (!rndis->notify_req)
goto fail;
- rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+ rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT +
+ cdev->gadget->extra_buf_alloc, GFP_KERNEL);
if (!rndis->notify_req->buf)
goto fail;
rndis->notify_req->length = STATUS_BYTECOUNT;
diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c
index 710930a..038993d 100644
--- a/drivers/usb/gadget/function/rndis.c
+++ b/drivers/usb/gadget/function/rndis.c
@@ -932,6 +932,7 @@
}
#endif
+ spin_lock_init(¶ms->lock);
params->confignr = i;
params->used = 1;
params->state = RNDIS_UNINITIALIZED;
@@ -1096,29 +1097,36 @@
void rndis_free_response(struct rndis_params *params, u8 *buf)
{
rndis_resp_t *r, *n;
+ unsigned long flags;
+ spin_lock_irqsave(¶ms->lock, flags);
list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) {
if (r->buf == buf) {
list_del(&r->list);
kfree(r);
}
}
+ spin_unlock_irqrestore(¶ms->lock, flags);
}
EXPORT_SYMBOL_GPL(rndis_free_response);
u8 *rndis_get_next_response(struct rndis_params *params, u32 *length)
{
rndis_resp_t *r, *n;
+ unsigned long flags;
if (!length) return NULL;
+ spin_lock_irqsave(¶ms->lock, flags);
list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) {
if (!r->send) {
r->send = 1;
*length = r->length;
+ spin_unlock_irqrestore(¶ms->lock, flags);
return r->buf;
}
}
+ spin_unlock_irqrestore(¶ms->lock, flags);
return NULL;
}
@@ -1127,6 +1135,7 @@
static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length)
{
rndis_resp_t *r;
+ unsigned long flags;
/* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC);
@@ -1136,7 +1145,9 @@
r->length = length;
r->send = 0;
+ spin_lock_irqsave(¶ms->lock, flags);
list_add_tail(&r->list, ¶ms->resp_queue);
+ spin_unlock_irqrestore(¶ms->lock, flags);
return r;
}
diff --git a/drivers/usb/gadget/function/rndis.h b/drivers/usb/gadget/function/rndis.h
index a3051c4..2211146 100644
--- a/drivers/usb/gadget/function/rndis.h
+++ b/drivers/usb/gadget/function/rndis.h
@@ -203,6 +203,7 @@
void *v;
struct list_head resp_queue;
+ spinlock_t lock;
} rndis_params;
/* RNDIS Message parser and other useless functions */
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 4dbeba1..4eeb49c 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -23,6 +23,8 @@
#include <linux/if_vlan.h>
#include <linux/if_arp.h>
#include <linux/msm_rmnet.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include "u_ether.h"
@@ -70,7 +72,7 @@
struct list_head tx_reqs, rx_reqs;
unsigned tx_qlen;
/* Minimum number of TX USB request queued to UDC */
-#define TX_REQ_THRESHOLD 5
+#define MAX_TX_REQ_WITH_NO_INT 5
int no_tx_req_used;
int tx_skb_hold_count;
u32 tx_req_bufsize;
@@ -99,14 +101,34 @@
bool no_skb_reserve;
u8 host_mac[ETH_ALEN];
u8 dev_mac[ETH_ALEN];
+ unsigned long tx_throttle;
+ unsigned long rx_throttle;
+ unsigned int tx_pkts_rcvd;
+ struct dentry *uether_dent;
+ struct dentry *uether_dfile;
};
+static void uether_debugfs_init(struct eth_dev *dev);
+static void uether_debugfs_exit(struct eth_dev *dev);
+
/*-------------------------------------------------------------------------*/
#define RX_EXTRA 20 /* bytes guarding against rx overflows */
#define DEFAULT_QLEN 2 /* double buffering by default */
+/*
+ * Usually downlink rates are higher than uplink rates and it
+ * deserve higher number of requests. For CAT-6 data rates of
+ * 300Mbps (~30 packets per milli-sec) 40 usb request may not
+ * be sufficient. At this rate and with interrupt moderation
+ * of interconnect, data can be very bursty. tx_qmult is the
+ * additional multipler on qmult.
+ */
+static unsigned int tx_qmult = 1;
+module_param(tx_qmult, uint, 0644);
+MODULE_PARM_DESC(tx_qmult, "Additional queue length multiplier for tx");
+
/* for dual-speed hardware, use deeper queues at high/super speed */
static inline int qlen(struct usb_gadget *gadget, unsigned qmult)
{
@@ -118,6 +140,10 @@
}
/*-------------------------------------------------------------------------*/
+#define U_ETHER_RX_PENDING_TSHOLD 500
+
+static unsigned int u_ether_rx_pending_thld = U_ETHER_RX_PENDING_TSHOLD;
+module_param(u_ether_rx_pending_thld, uint, 0644);
/* REVISIT there must be a better way than having two sets
* of debug calls ...
@@ -231,11 +257,11 @@
out = dev->port_usb->out_ep;
else
out = NULL;
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!out)
+ if (!out) {
+ spin_unlock_irqrestore(&dev->lock, flags);
return -ENOTCONN;
-
+ }
/* Padding up to RX_EXTRA handles minor disagreements with host.
* Normally we use the USB "terminate on short read" convention;
@@ -259,9 +285,10 @@
if (dev->port_usb->is_fixed)
size = max_t(size_t, size, dev->port_usb->fixed_out_len);
+ spin_unlock_irqrestore(&dev->lock, flags);
DBG(dev, "%s: size: %zd\n", __func__, size);
- skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
+ skb = alloc_skb(size, gfp_flags);
if (skb == NULL) {
DBG(dev, "no rx skb\n");
goto enomem;
@@ -272,7 +299,7 @@
* RNDIS headers involve variable numbers of LE32 values.
*/
if (likely(!dev->no_skb_reserve))
- skb_reserve(skb, NET_IP_ALIGN);
+ skb_reserve(skb, 0);
req->buf = skb->data;
req->length = size;
@@ -356,9 +383,20 @@
}
clean:
- spin_lock(&dev->req_lock);
- list_add(&req->list, &dev->rx_reqs);
- spin_unlock(&dev->req_lock);
+ if (queue && dev->rx_frames.qlen <= u_ether_rx_pending_thld) {
+ if (rx_submit(dev, req, GFP_ATOMIC) < 0) {
+ spin_lock(&dev->req_lock);
+ list_add(&req->list, &dev->rx_reqs);
+ spin_unlock(&dev->req_lock);
+ }
+ } else {
+ /* rx buffers draining is delayed,defer further queuing to wq */
+ if (queue)
+ dev->rx_throttle++;
+ spin_lock(&dev->req_lock);
+ list_add(&req->list, &dev->rx_reqs);
+ spin_unlock(&dev->req_lock);
+ }
if (queue)
queue_work(uether_wq, &dev->rx_work);
@@ -409,7 +447,7 @@
spin_lock(&dev->req_lock);
if (link->in_ep) {
- status = prealloc(&dev->tx_reqs, link->in_ep, n);
+ status = prealloc(&dev->tx_reqs, link->in_ep, n * tx_qmult);
if (status < 0)
goto fail;
}
@@ -526,21 +564,21 @@
break;
case 0:
if (!req->zero)
- dev->net->stats.tx_bytes += req->length-1;
+ dev->net->stats.tx_bytes += req->actual-1;
else
- dev->net->stats.tx_bytes += req->length;
+ dev->net->stats.tx_bytes += req->actual;
}
dev->net->stats.tx_packets++;
spin_lock(&dev->req_lock);
- list_add_tail(&req->list, &dev->tx_reqs);
- if (dev->port_usb->multi_pkt_xfer) {
+ if (dev->port_usb->multi_pkt_xfer && !req->context) {
dev->no_tx_req_used--;
req->length = 0;
in = dev->port_usb->in_ep;
- if (!list_empty(&dev->tx_reqs)) {
+ /* Do not process further if no_interrupt is set */
+ if (!req->no_interrupt && !list_empty(&dev->tx_reqs)) {
new_req = container_of(dev->tx_reqs.next,
struct usb_request, list);
list_del(&new_req->list);
@@ -568,7 +606,18 @@
length++;
}
+ /* set when tx completion interrupt needed */
+ spin_lock(&dev->req_lock);
+ dev->tx_qlen++;
+ if (dev->tx_qlen == MAX_TX_REQ_WITH_NO_INT) {
+ new_req->no_interrupt = 0;
+ dev->tx_qlen = 0;
+ } else {
+ new_req->no_interrupt = 1;
+ }
+ spin_unlock(&dev->req_lock);
new_req->length = length;
+ new_req->complete = tx_complete;
retval = usb_ep_queue(in, new_req, GFP_ATOMIC);
switch (retval) {
default:
@@ -600,10 +649,24 @@
spin_unlock(&dev->req_lock);
}
} else {
+ /* Is aggregation already enabled and buffers allocated ? */
+ if (dev->port_usb->multi_pkt_xfer && dev->tx_req_bufsize) {
+ req->buf = kzalloc(dev->tx_req_bufsize
+ + dev->gadget->extra_buf_alloc, GFP_ATOMIC);
+ req->context = NULL;
+ } else {
+ req->buf = NULL;
+ }
+
spin_unlock(&dev->req_lock);
dev_kfree_skb_any(skb);
}
+ /* put the completed req back to tx_reqs tail pool */
+ spin_lock(&dev->req_lock);
+ list_add_tail(&req->list, &dev->tx_reqs);
+ spin_unlock(&dev->req_lock);
+
if (netif_carrier_ok(dev->net))
netif_wake_queue(dev->net);
}
@@ -628,11 +691,14 @@
list_for_each(act, &dev->tx_reqs) {
req = container_of(act, struct usb_request, list);
if (!req->buf)
- req->buf = kmalloc(dev->tx_req_bufsize,
- GFP_ATOMIC);
+ req->buf = kmalloc(dev->tx_req_bufsize
+ + dev->gadget->extra_buf_alloc, GFP_ATOMIC);
if (!req->buf)
goto free_buf;
+
+ /* req->context is not used for multi_pkt_xfers */
+ req->context = NULL;
}
return 0;
@@ -655,8 +721,8 @@
int retval;
struct usb_request *req = NULL;
unsigned long flags;
- struct usb_ep *in;
- u16 cdc_filter;
+ struct usb_ep *in = NULL;
+ u16 cdc_filter = 0;
bool multi_pkt_xfer = false;
spin_lock_irqsave(&dev->lock, flags);
@@ -664,9 +730,6 @@
in = dev->port_usb->in_ep;
cdc_filter = dev->port_usb->cdc_filter;
multi_pkt_xfer = dev->port_usb->multi_pkt_xfer;
- } else {
- in = NULL;
- cdc_filter = 0;
}
spin_unlock_irqrestore(&dev->lock, flags);
@@ -675,13 +738,6 @@
return NETDEV_TX_OK;
}
- /* Allocate memory for tx_reqs to support multi packet transfer */
- if (multi_pkt_xfer && !dev->tx_req_bufsize) {
- retval = alloc_tx_buffer(dev);
- if (retval < 0)
- return -ENOMEM;
- }
-
/* apply outgoing CDC or RNDIS filters */
if (skb && !is_promisc(cdc_filter)) {
u8 *dest = skb->data;
@@ -704,7 +760,41 @@
/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
}
+ dev->tx_pkts_rcvd++;
+ /*
+ * no buffer copies needed, unless the network stack did it
+ * or the hardware can't use skb buffers.
+ * or there's not enough space for extra headers we need
+ */
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->wrap && dev->port_usb)
+ skb = dev->wrap(dev->port_usb, skb);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ if (!skb) {
+ if (dev->port_usb && dev->port_usb->supports_multi_frame) {
+ /*
+ * Multi frame CDC protocols may store the frame for
+ * later which is not a dropped frame.
+ */
+ } else {
+ dev->net->stats.tx_dropped++;
+ }
+
+ /* no error code for dropped packets */
+ return NETDEV_TX_OK;
+ }
+
+ /* Allocate memory for tx_reqs to support multi packet transfer */
spin_lock_irqsave(&dev->req_lock, flags);
+ if (multi_pkt_xfer && !dev->tx_req_bufsize) {
+ retval = alloc_tx_buffer(dev);
+ if (retval < 0) {
+ spin_unlock_irqrestore(&dev->req_lock, flags);
+ return -ENOMEM;
+ }
+ }
+
/*
* this freelist can be empty if an interrupt triggered disconnect()
* and reconfigured the gadget (shutting down this queue) after the
@@ -719,33 +809,16 @@
list_del(&req->list);
/* temporarily stop TX queue when the freelist empties */
- if (list_empty(&dev->tx_reqs))
+ if (list_empty(&dev->tx_reqs)) {
+ /*
+ * tx_throttle gives info about number of times u_ether
+ * asked network layer to stop queueing packets to it
+ * when transmit resources are unavailable
+ */
+ dev->tx_throttle++;
netif_stop_queue(net);
- spin_unlock_irqrestore(&dev->req_lock, flags);
-
- /* no buffer copies needed, unless the network stack did it
- * or the hardware can't use skb buffers.
- * or there's not enough space for extra headers we need
- */
- if (dev->wrap) {
- unsigned long flags;
-
- spin_lock_irqsave(&dev->lock, flags);
- if (dev->port_usb)
- skb = dev->wrap(dev->port_usb, skb);
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!skb) {
- /* Multi frame CDC protocols may store the frame for
- * later which is not a dropped frame.
- */
- if (dev->port_usb &&
- dev->port_usb->supports_multi_frame)
- goto multiframe;
- goto drop;
- }
}
- spin_lock_irqsave(&dev->req_lock, flags);
dev->tx_skb_hold_count++;
spin_unlock_irqrestore(&dev->req_lock, flags);
@@ -757,7 +830,13 @@
spin_lock_irqsave(&dev->req_lock, flags);
if (dev->tx_skb_hold_count < dev->dl_max_pkts_per_xfer) {
- if (dev->no_tx_req_used > TX_REQ_THRESHOLD) {
+ /*
+ * should allow aggregation only, if the number of
+ * requests queued more than the tx requests that can
+ * be queued with no interrupt flag set sequentially.
+ * Otherwise, packets may be blocked forever.
+ */
+ if (dev->no_tx_req_used > MAX_TX_REQ_WITH_NO_INT) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->req_lock, flags);
goto success;
@@ -801,13 +880,15 @@
/* throttle highspeed IRQ rate back slightly */
if (gadget_is_dualspeed(dev->gadget) &&
(dev->gadget->speed == USB_SPEED_HIGH)) {
+ spin_lock_irqsave(&dev->req_lock, flags);
dev->tx_qlen++;
- if (dev->tx_qlen == (dev->qmult/2)) {
+ if (dev->tx_qlen == MAX_TX_REQ_WITH_NO_INT) {
req->no_interrupt = 0;
dev->tx_qlen = 0;
} else {
req->no_interrupt = 1;
}
+ spin_unlock_irqrestore(&dev->req_lock, flags);
} else {
req->no_interrupt = 0;
}
@@ -826,9 +907,7 @@
dev_kfree_skb_any(skb);
else
req->length = 0;
-drop:
dev->net->stats.tx_dropped++;
-multiframe:
spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty(&dev->tx_reqs))
netif_start_queue(net);
@@ -1211,6 +1290,7 @@
* - tx queueing enabled if open *and* carrier is "on"
*/
netif_carrier_off(net);
+ uether_debugfs_init(dev);
}
return dev;
@@ -1412,6 +1492,7 @@
if (!dev)
return;
+ uether_debugfs_exit(dev);
unregister_netdev(dev->net);
flush_work(&dev->work);
free_netdev(dev->net);
@@ -1584,6 +1665,12 @@
link->out_ep->desc = NULL;
}
+ pr_debug("%s(): tx_throttle count= %lu", __func__,
+ dev->tx_throttle);
+ /* reset tx_throttle count */
+ dev->tx_throttle = 0;
+ dev->rx_throttle = 0;
+
/* finish forgetting about this USB link episode */
dev->header_len = 0;
dev->unwrap = NULL;
@@ -1595,6 +1682,70 @@
}
EXPORT_SYMBOL_GPL(gether_disconnect);
+static int uether_stat_show(struct seq_file *s, void *unused)
+{
+ struct eth_dev *dev = s->private;
+ int ret = 0;
+
+ if (dev) {
+ seq_printf(s, "tx_throttle = %lu\n", dev->tx_throttle);
+ seq_printf(s, "tx_pkts_rcvd=%u\n", dev->tx_pkts_rcvd);
+ seq_printf(s, "rx_throttle = %lu\n", dev->rx_throttle);
+ }
+ return ret;
+}
+
+static int uether_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, uether_stat_show, inode->i_private);
+}
+
+static ssize_t uether_stat_reset(struct file *file,
+ const char __user *ubuf, size_t count, loff_t *ppos)
+{
+ struct seq_file *s = file->private_data;
+ struct eth_dev *dev = s->private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ /* Reset tx_throttle */
+ dev->tx_throttle = 0;
+ dev->rx_throttle = 0;
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return count;
+}
+
+static const struct file_operations uether_stats_ops = {
+ .open = uether_open,
+ .read = seq_read,
+ .write = uether_stat_reset,
+};
+
+static void uether_debugfs_init(struct eth_dev *dev)
+{
+ struct dentry *uether_dent;
+ struct dentry *uether_dfile;
+
+ uether_dent = debugfs_create_dir("uether_rndis", NULL);
+ if (IS_ERR(uether_dent))
+ return;
+ dev->uether_dent = uether_dent;
+
+ uether_dfile = debugfs_create_file("status", 0644,
+ uether_dent, dev, &uether_stats_ops);
+ if (!uether_dfile || IS_ERR(uether_dfile))
+ debugfs_remove(uether_dent);
+ dev->uether_dfile = uether_dfile;
+}
+
+static void uether_debugfs_exit(struct eth_dev *dev)
+{
+ debugfs_remove(dev->uether_dfile);
+ debugfs_remove(dev->uether_dent);
+ dev->uether_dent = NULL;
+ dev->uether_dfile = NULL;
+}
+
static int __init gether_init(void)
{
uether_wq = create_singlethread_workqueue("uether");
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 984b1d7..4debbcbf 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -2518,7 +2518,7 @@
.release = uvc_attr_release,
};
-#define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \
+#define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
static ssize_t f_uvc_opts_##cname##_show( \
struct config_item *item, char *page) \
{ \
@@ -2565,12 +2565,12 @@
#define identity_conv(x) (x)
-UVCG_OPTS_ATTR(streaming_interval, identity_conv, kstrtou8, u8, identity_conv,
- 16);
-UVCG_OPTS_ATTR(streaming_maxpacket, le16_to_cpu, kstrtou16, u16, le16_to_cpu,
- 3072);
-UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv,
- 15);
+UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv,
+ kstrtou8, u8, identity_conv, 16);
+UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu,
+ kstrtou16, u16, le16_to_cpu, 3072);
+UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv,
+ kstrtou8, u8, identity_conv, 15);
#undef identity_conv
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index 02bf1eb..e28173b 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -476,7 +476,6 @@
dev_dbg(phy->dev, "%s\n", __func__);
- qusb_phy_reset(qphy);
qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq,
qphy->host_init_seq_len, 0);
@@ -524,6 +523,12 @@
qusb_phy_enable_clocks(qphy, true);
qusb_phy_reset(qphy);
+
+ if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE) {
+ qusb_phy_host_init(phy);
+ return 0;
+ }
+
if (qphy->emulation) {
if (qphy->emu_init_seq)
qusb_phy_write_seq(qphy->emu_phy_base + 0x8000,
@@ -769,9 +774,6 @@
qphy->cable_connected = true;
- if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE)
- qusb_phy_host_init(phy);
-
dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
qphy->cable_connected);
return 0;
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index eb44e99..1809e66 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2334,8 +2334,7 @@
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select SYNC
- select SW_SYNC
+ select SYNC_FILE
---help---
The MSM driver implements a frame buffer interface to
provide access to the display hardware and provide
diff --git a/drivers/video/fbdev/msm/Kconfig b/drivers/video/fbdev/msm/Kconfig
index 60b86e7..e8f902b 100644
--- a/drivers/video/fbdev/msm/Kconfig
+++ b/drivers/video/fbdev/msm/Kconfig
@@ -21,8 +21,7 @@
config FB_MSM_MDSS
bool "MDSS HW"
- select SYNC
- select SW_SYNC
+ select SYNC_FILE
select FB_MSM_MDSS_COMMON
---help---
The Mobile Display Sub System (MDSS) driver supports devices which
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 1ce9be0..ae9b7cf 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -279,7 +279,7 @@
enum led_brightness value)
{
struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
- int bl_lvl;
+ u64 bl_lvl;
if (mfd->boot_notification_led) {
led_trigger_event(mfd->boot_notification_led, 0);
@@ -518,13 +518,13 @@
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct msm_fb_data_type *mfd = fbi->par;
- unsigned int fps_int, fps_float;
+ u64 fps_int, fps_float;
if (mfd->panel_power_state != MDSS_PANEL_POWER_ON)
mfd->fps_info.measured_fps = 0;
- fps_int = (unsigned int) mfd->fps_info.measured_fps;
+ fps_int = (u64) mfd->fps_info.measured_fps;
fps_float = do_div(fps_int, 10);
- return scnprintf(buf, PAGE_SIZE, "%d.%d\n", fps_int, fps_float);
+ return scnprintf(buf, PAGE_SIZE, "%llu.%llu\n", fps_int, fps_float);
}
@@ -2292,9 +2292,10 @@
pr_debug("vma=%pK, addr=%x len=%ld\n",
vma, (unsigned int)addr, len);
pr_debug("vm_start=%x vm_end=%x vm_page_prot=%ld\n",
- (unsigned int)vma->vm_start,
- (unsigned int)vma->vm_end,
- (unsigned long int)vma->vm_page_prot.pgprot);
+ (unsigned int)vma->vm_start,
+ (unsigned int)vma->vm_end,
+ (unsigned long int)pgprot_val(
+ vma->vm_page_prot));
io_remap_pfn_range(vma, addr, page_to_pfn(page), len,
vma->vm_page_prot);
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index 19e6299..c85f033 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -307,7 +307,7 @@
u32 calib_mode;
u32 calib_mode_bl;
u32 ad_bl_level;
- u32 bl_level;
+ u64 bl_level;
u32 bl_scale;
u32 bl_min_lvl;
u32 unset_bl_level;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c
index d24ff53..6024ea1 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_debug.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c
@@ -1414,7 +1414,7 @@
seq_printf(s, "vsync: %08u \tunderrun: %08u\n",
ctl->vsync_cnt, ctl->underrun_cnt);
if (ctl->mfd) {
- seq_printf(s, "user_bl: %08u \tmod_bl: %08u\n",
+ seq_printf(s, "user_bl: %08llu \tmod_bl: %08u\n",
ctl->mfd->bl_level, ctl->mfd->bl_level_scaled);
}
} else {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 3da2a07..3ae59a2 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2015,7 +2015,7 @@
{
int vsync_diff;
int round_up = 0;
- s64 ts_diff = (cur_ts - base_ts) * display_fp1000s;
+ u64 ts_diff = (cur_ts - base_ts) * display_fp1000s;
do_div(ts_diff, 1000000);
vsync_diff = (int)ts_diff;
@@ -2065,7 +2065,7 @@
struct mdss_mdp_frc_cadence_calc *calc = &frc_info->calc;
struct mdss_mdp_frc_data *first = &calc->samples[0];
struct mdss_mdp_frc_data *last = &calc->samples[cnt-1];
- s64 ts_diff =
+ u64 ts_diff =
(last->timestamp - first->timestamp)
* frc_info->display_fp1000s;
u32 fcnt_diff =
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index 6b03f1d..13afa46 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -5778,7 +5778,7 @@
struct mdss_ad_input *input, int wait) {
int ret = 0;
struct mdss_ad_info *ad;
- u32 bl;
+ u64 bl;
struct mdss_overlay_private *mdp5_data;
ret = mdss_mdp_get_ad(mfd, &ad);
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index 7a44824..fbbdaf2 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -316,7 +316,7 @@
}
ATRACE_END("map_buffer");
*iova = table->sgl->dma_address;
- *size = table->sgl->dma_length;
+ *size = sg_dma_len(table->sgl);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_sync.c b/drivers/video/fbdev/msm/mdss_sync.c
index 7b1028ab..22fdcf5 100644
--- a/drivers/video/fbdev/msm/mdss_sync.c
+++ b/drivers/video/fbdev/msm/mdss_sync.c
@@ -51,6 +51,7 @@
struct mdss_timeline {
struct kref kref;
spinlock_t lock;
+ spinlock_t list_lock;
char name[MDSS_SYNC_NAME_SIZE];
u32 next_value;
u32 value;
@@ -58,6 +59,7 @@
struct list_head fence_list_head;
};
+#if defined(CONFIG_SYNC_FILE)
/*
* to_mdss_fence - get mdss fence from fence base object
* @fence: Pointer to fence base object
@@ -148,12 +150,13 @@
static void mdss_fence_release(struct fence *fence)
{
struct mdss_fence *f = to_mdss_fence(fence);
- unsigned long flags;
+ struct mdss_timeline *tl = to_mdss_timeline(fence);
- spin_lock_irqsave(fence->lock, flags);
+ pr_debug("%s for fence %s\n", __func__, f->name);
+ spin_lock(&tl->list_lock);
if (!list_empty(&f->fence_list))
list_del(&f->fence_list);
- spin_unlock_irqrestore(fence->lock, flags);
+ spin_unlock(&tl->list_lock);
mdss_put_timeline(to_mdss_timeline(fence));
kfree_rcu(f, base.rcu);
}
@@ -202,6 +205,7 @@
kref_init(&tl->kref);
snprintf(tl->name, sizeof(tl->name), "%s", name);
spin_lock_init(&tl->lock);
+ spin_lock_init(&tl->list_lock);
tl->context = fence_context_alloc(1);
INIT_LIST_HEAD(&tl->fence_list_head);
@@ -227,15 +231,41 @@
{
struct mdss_fence *f, *next;
s32 val;
+ bool is_signaled = false;
+ struct list_head local_list_head;
+ unsigned long flags;
+ INIT_LIST_HEAD(&local_list_head);
+
+ spin_lock(&tl->list_lock);
+ if (list_empty(&tl->fence_list_head)) {
+ pr_debug("fence list is empty\n");
+ spin_unlock(&tl->list_lock);
+ return 0;
+ }
+
+ list_for_each_entry_safe(f, next, &tl->fence_list_head, fence_list)
+ list_move(&f->fence_list, &local_list_head);
+ spin_unlock(&tl->list_lock);
+
+ spin_lock_irqsave(&tl->lock, flags);
val = tl->next_value - tl->value;
if (val >= increment)
tl->value += increment;
+ spin_unlock_irqrestore(&tl->lock, flags);
- list_for_each_entry_safe(f, next, &tl->fence_list_head, fence_list) {
- if (fence_is_signaled_locked(&f->base)) {
+ list_for_each_entry_safe(f, next, &local_list_head, fence_list) {
+ spin_lock_irqsave(&tl->lock, flags);
+ is_signaled = fence_is_signaled_locked(&f->base);
+ spin_unlock_irqrestore(&tl->lock, flags);
+ if (is_signaled) {
pr_debug("%s signaled\n", f->name);
list_del_init(&f->fence_list);
+ fence_put(&f->base);
+ } else {
+ spin_lock(&tl->list_lock);
+ list_move(&f->fence_list, &tl->fence_list_head);
+ spin_unlock(&tl->list_lock);
}
}
@@ -248,7 +278,6 @@
*/
void mdss_resync_timeline(struct mdss_timeline *tl)
{
- unsigned long flags;
s32 val;
if (!tl) {
@@ -256,14 +285,12 @@
return;
}
- spin_lock_irqsave(&tl->lock, flags);
val = tl->next_value - tl->value;
if (val > 0) {
pr_warn("flush %s:%d TL(Nxt %d , Crnt %d)\n", tl->name, val,
tl->next_value, tl->value);
mdss_inc_timeline_locked(tl, val);
}
- spin_unlock_irqrestore(&tl->lock, flags);
}
/*
@@ -277,8 +304,8 @@
u32 *timestamp, int offset)
{
struct mdss_fence *f;
- unsigned long flags;
u32 val;
+ unsigned long flags;
if (!tl) {
pr_err("invalid parameters\n");
@@ -294,9 +321,12 @@
val = tl->next_value + offset;
tl->next_value += 1;
fence_init(&f->base, &mdss_fence_ops, &tl->lock, tl->context, val);
- list_add_tail(&f->fence_list, &tl->fence_list_head);
mdss_get_timeline(tl);
spin_unlock_irqrestore(&tl->lock, flags);
+
+ spin_lock(&tl->list_lock);
+ list_add_tail(&f->fence_list, &tl->fence_list_head);
+ spin_unlock(&tl->list_lock);
snprintf(f->name, sizeof(f->name), "%s_%u", fence_name, val);
if (timestamp)
@@ -315,7 +345,6 @@
*/
int mdss_inc_timeline(struct mdss_timeline *tl, int increment)
{
- unsigned long flags;
int rc;
if (!tl) {
@@ -323,10 +352,7 @@
return -EINVAL;
}
- spin_lock_irqsave(&tl->lock, flags);
rc = mdss_inc_timeline_locked(tl, increment);
- spin_unlock_irqrestore(&tl->lock, flags);
-
return rc;
}
@@ -468,3 +494,4 @@
return fence->name;
}
+#endif
diff --git a/drivers/video/fbdev/msm/mdss_sync.h b/drivers/video/fbdev/msm/mdss_sync.h
index 39a1aa7b..a2e84d4 100644
--- a/drivers/video/fbdev/msm/mdss_sync.h
+++ b/drivers/video/fbdev/msm/mdss_sync.h
@@ -112,11 +112,12 @@
{
return -EBADF;
}
+
+static inline
const char *mdss_get_sync_fence_name(struct mdss_fence *fence)
{
return NULL;
}
-}
#endif
#endif /* MDSS_SYNC_H */
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index 39d26a4..ec1ee60 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -2033,7 +2033,7 @@
{
int rc = 0;
struct mdss_dsi_ctrl_pdata *mctrl = NULL;
- int i, *vote_cnt;
+ int i, *vote_cnt = NULL;
void *m_clk_handle;
bool is_ecg = false;
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 4874b0f..518dfa1 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -169,15 +169,21 @@
return 0;
}
-static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
- unsigned int new_timeout)
+static void __imx2_wdt_set_timeout(struct watchdog_device *wdog,
+ unsigned int new_timeout)
{
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
- wdog->timeout = new_timeout;
-
regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT,
WDOG_SEC_TO_COUNT(new_timeout));
+}
+
+static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
+ unsigned int new_timeout)
+{
+ __imx2_wdt_set_timeout(wdog, new_timeout);
+
+ wdog->timeout = new_timeout;
return 0;
}
@@ -371,7 +377,11 @@
/* The watchdog IP block is running */
if (imx2_wdt_is_running(wdev)) {
- imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
+ /*
+ * Don't update wdog->timeout, we'll restore the current value
+ * during resume.
+ */
+ __imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
imx2_wdt_ping(wdog);
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 894d563..a8a1fb4 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2063,8 +2063,15 @@
goto out;
}
- btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state,
- 0);
+ ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
+ &cached_state, 0);
+ if (ret) {
+ mapping_set_error(page->mapping, ret);
+ end_extent_writepage(page, ret, page_start, page_end);
+ ClearPageChecked(page);
+ goto out;
+ }
+
ClearPageChecked(page);
set_page_dirty(page);
out:
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 5eb0412..73360df 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -318,9 +318,8 @@
{
int i;
int rc;
- char password_with_pad[CIFS_ENCPWD_SIZE];
+ char password_with_pad[CIFS_ENCPWD_SIZE] = {0};
- memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
if (password)
strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 580b3a4..441d434 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1667,7 +1667,7 @@
tmp_end++;
if (!(tmp_end < end && tmp_end[1] == delim)) {
/* No it is not. Set the password to NULL */
- kfree(vol->password);
+ kzfree(vol->password);
vol->password = NULL;
break;
}
@@ -1705,7 +1705,7 @@
options = end;
}
- kfree(vol->password);
+ kzfree(vol->password);
/* Now build new password string */
temp_len = strlen(value);
vol->password = kzalloc(temp_len+1, GFP_KERNEL);
@@ -4159,7 +4159,7 @@
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
out:
kfree(vol_info->username);
- kfree(vol_info->password);
+ kzfree(vol_info->password);
kfree(vol_info);
return tcon;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index cf192f9..02e403a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3285,20 +3285,18 @@
int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
{
- int rc, xid;
+ int xid, rc = 0;
struct inode *inode = file_inode(file);
xid = get_xid();
- if (!CIFS_CACHE_READ(CIFS_I(inode))) {
+ if (!CIFS_CACHE_READ(CIFS_I(inode)))
rc = cifs_zap_mapping(inode);
- if (rc)
- return rc;
- }
-
- rc = generic_file_mmap(file, vma);
- if (rc == 0)
+ if (!rc)
+ rc = generic_file_mmap(file, vma);
+ if (!rc)
vma->vm_ops = &cifs_file_vm_ops;
+
free_xid(xid);
return rc;
}
@@ -3308,16 +3306,16 @@
int rc, xid;
xid = get_xid();
+
rc = cifs_revalidate_file(file);
- if (rc) {
+ if (rc)
cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
rc);
- free_xid(xid);
- return rc;
- }
- rc = generic_file_mmap(file, vma);
- if (rc == 0)
+ if (!rc)
+ rc = generic_file_mmap(file, vma);
+ if (!rc)
vma->vm_ops = &cifs_file_vm_ops;
+
free_xid(xid);
return rc;
}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 5419afe..323d8e3 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -99,14 +99,11 @@
kfree(buf_to_free->serverOS);
kfree(buf_to_free->serverDomain);
kfree(buf_to_free->serverNOS);
- if (buf_to_free->password) {
- memset(buf_to_free->password, 0, strlen(buf_to_free->password));
- kfree(buf_to_free->password);
- }
+ kzfree(buf_to_free->password);
kfree(buf_to_free->user_name);
kfree(buf_to_free->domainName);
- kfree(buf_to_free->auth_key.response);
- kfree(buf_to_free);
+ kzfree(buf_to_free->auth_key.response);
+ kzfree(buf_to_free);
}
struct cifs_tcon *
@@ -137,10 +134,7 @@
}
atomic_dec(&tconInfoAllocCount);
kfree(buf_to_free->nativeFileSystem);
- if (buf_to_free->password) {
- memset(buf_to_free->password, 0, strlen(buf_to_free->password));
- kfree(buf_to_free->password);
- }
+ kzfree(buf_to_free->password);
kfree(buf_to_free);
}
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 69b610ad..94c4c19 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -585,8 +585,7 @@
}
/* check validate negotiate info response matches what we got earlier */
- if (pneg_rsp->Dialect !=
- cpu_to_le16(tcon->ses->server->vals->protocol_id))
+ if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect))
goto vneg_out;
if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode))
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 78219d5..d6512cd 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -275,7 +275,7 @@
{
struct kernfs_open_file *of = kernfs_of(file);
const struct kernfs_ops *ops;
- size_t len;
+ ssize_t len;
char *buf;
if (of->atomic_write_len) {
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index bd81bcf..1ac1593 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -787,10 +787,8 @@
spin_lock(&dreq->lock);
- if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
- dreq->flags = 0;
+ if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
dreq->error = hdr->error;
- }
if (dreq->error == 0) {
nfs_direct_good_bytes(dreq, hdr);
if (nfs_write_need_commit(hdr)) {
diff --git a/fs/nfs/io.c b/fs/nfs/io.c
index 1fc5d1c..d18ccc1 100644
--- a/fs/nfs/io.c
+++ b/fs/nfs/io.c
@@ -98,7 +98,7 @@
{
if (!test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
set_bit(NFS_INO_ODIRECT, &nfsi->flags);
- nfs_wb_all(inode);
+ nfs_sync_mapping(inode->i_mapping);
}
}
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
index c444285..f1160cd 100644
--- a/fs/nfs/nfs4idmap.c
+++ b/fs/nfs/nfs4idmap.c
@@ -567,9 +567,13 @@
struct idmap_msg *im;
struct idmap *idmap = (struct idmap *)aux;
struct key *key = cons->key;
- int ret = -ENOMEM;
+ int ret = -ENOKEY;
+
+ if (!aux)
+ goto out1;
/* msg and im are freed in idmap_pipe_destroy_msg */
+ ret = -ENOMEM;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
goto out1;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index b7a07ba..b8e4474 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2145,7 +2145,7 @@
nfs_pageio_reset_write_mds(desc);
mirror->pg_recoalesce = 1;
}
- hdr->release(hdr);
+ hdr->completion_ops->completion(hdr);
}
static enum pnfs_try_status
@@ -2256,7 +2256,7 @@
nfs_pageio_reset_read_mds(desc);
mirror->pg_recoalesce = 1;
}
- hdr->release(hdr);
+ hdr->completion_ops->completion(hdr);
}
/*
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9905735..9a3b382 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1806,6 +1806,8 @@
set_bit(NFS_CONTEXT_RESEND_WRITES, &req->wb_context->flags);
next:
nfs_unlock_and_release_request(req);
+ /* Latency breaker */
+ cond_resched();
}
nfss = NFS_SERVER(data->inode);
if (atomic_long_read(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH)
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index f241b4e..a1be6ba 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -434,10 +434,14 @@
struct dentry *dentry = file->f_path.dentry;
struct file *realfile = od->realfile;
+ /* Nothing to sync for lower */
+ if (!OVL_TYPE_UPPER(ovl_path_type(dentry)))
+ return 0;
+
/*
* Need to check if we started out being a lower dir, but got copied up
*/
- if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) {
+ if (!od->is_upper) {
struct inode *inode = file_inode(file);
realfile = lockless_dereference(od->upperfile);
diff --git a/fs/pipe.c b/fs/pipe.c
index 9faecf1..3434553 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -609,12 +609,17 @@
static bool too_many_pipe_buffers_soft(unsigned long user_bufs)
{
- return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft;
+ return pipe_user_pages_soft && user_bufs > pipe_user_pages_soft;
}
static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
{
- return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard;
+ return pipe_user_pages_hard && user_bufs > pipe_user_pages_hard;
+}
+
+static bool is_unprivileged_user(void)
+{
+ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
}
struct pipe_inode_info *alloc_pipe_info(void)
@@ -633,12 +638,12 @@
user_bufs = account_pipe_buffers(user, 0, pipe_bufs);
- if (too_many_pipe_buffers_soft(user_bufs)) {
+ if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) {
user_bufs = account_pipe_buffers(user, pipe_bufs, 1);
pipe_bufs = 1;
}
- if (too_many_pipe_buffers_hard(user_bufs))
+ if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user())
goto out_revert_acct;
pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer),
@@ -1069,7 +1074,7 @@
if (nr_pages > pipe->buffers &&
(too_many_pipe_buffers_hard(user_bufs) ||
too_many_pipe_buffers_soft(user_bufs)) &&
- !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+ is_unprivileged_user()) {
ret = -EPERM;
goto out_revert_acct;
}
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 5c89a07..df7e079 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -507,23 +507,15 @@
return -EFAULT;
} else {
if (kern_addr_valid(start)) {
- unsigned long n;
-
/*
* Using bounce buffer to bypass the
* hardened user copy kernel text checks.
*/
- memcpy(buf, (char *) start, tsz);
- n = copy_to_user(buffer, buf, tsz);
- /*
- * We cannot distinguish between fault on source
- * and fault on destination. When this happens
- * we clear too and hope it will trigger the
- * EFAULT again.
- */
- if (n) {
- if (clear_user(buffer + tsz - n,
- n))
+ if (probe_kernel_read(buf, (void *) start, tsz)) {
+ if (clear_user(buffer, tsz))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(buffer, buf, tsz))
return -EFAULT;
}
} else {
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index d9f9615..3979d76 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -270,7 +270,8 @@
}
static int __ubifs_setxattr(struct inode *host, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags,
+ bool check_lock)
{
struct inode *inode;
struct ubifs_info *c = host->i_sb->s_fs_info;
@@ -279,7 +280,8 @@
union ubifs_key key;
int err;
- ubifs_assert(inode_is_locked(host));
+ if (check_lock)
+ ubifs_assert(inode_is_locked(host));
if (size > UBIFS_MAX_INO_DATA)
return -ERANGE;
@@ -548,7 +550,8 @@
}
strcpy(name, XATTR_SECURITY_PREFIX);
strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
- err = __ubifs_setxattr(inode, name, xattr->value, xattr->value_len, 0);
+ err = __ubifs_setxattr(inode, name, xattr->value,
+ xattr->value_len, 0, false);
kfree(name);
if (err < 0)
break;
@@ -594,7 +597,8 @@
name = xattr_full_name(handler, name);
if (value)
- return __ubifs_setxattr(inode, name, value, size, flags);
+ return __ubifs_setxattr(inode, name, value, size, flags,
+ true);
else
return __ubifs_removexattr(inode, name);
}
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index cac5735..5203560 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -88,6 +88,8 @@
return alg->setkey != shash_no_setkey;
}
+bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg);
+
int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn,
struct hash_alg_common *alg,
struct crypto_instance *inst);
diff --git a/include/crypto/poly1305.h b/include/crypto/poly1305.h
index 894df59..d586f74 100644
--- a/include/crypto/poly1305.h
+++ b/include/crypto/poly1305.h
@@ -30,8 +30,6 @@
};
int crypto_poly1305_init(struct shash_desc *desc);
-int crypto_poly1305_setkey(struct crypto_shash *tfm,
- const u8 *key, unsigned int keylen);
unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
const u8 *src, unsigned int srclen);
int crypto_poly1305_update(struct shash_desc *desc,
diff --git a/include/dt-bindings/clock/msm-clocks-8952.h b/include/dt-bindings/clock/msm-clocks-8952.h
index e8afdba..4547751 100644
--- a/include/dt-bindings/clock/msm-clocks-8952.h
+++ b/include/dt-bindings/clock/msm-clocks-8952.h
@@ -339,6 +339,7 @@
#define clk_audio_ap_clk 0x312ac429
#define clk_audio_pmi_clk 0xb7ba2274
+#define clk_audio_ap_clk2 0xf0fbaf5b
#define clk_audio_lpass_mclk 0x575ec22b
/* GCC block resets */
diff --git a/include/dt-bindings/clock/msm-clocks-8953.h b/include/dt-bindings/clock/msm-clocks-8953.h
index 6bfca0b..9550a41 100644
--- a/include/dt-bindings/clock/msm-clocks-8953.h
+++ b/include/dt-bindings/clock/msm-clocks-8953.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -313,6 +313,12 @@
#define clk_cpu_debug_pri_mux 0x61a2945f
#define clk_debug_cpu_clk 0x0e696b2b
+#define clk_apcs_c0_pll 0xfbc57bbd
+#define clk_apcs_c1_pll 0x17d32f1e
+#define clk_apcs_cci_pll 0x09affb3c
+#define clk_a53ssmux_cci 0x15560bd5
+#define clk_a53_cci_clk 0x4cdbbe58
+
#define clk_audio_ap_clk 0x312ac429
#define clk_audio_pmi_clk 0xb7ba2274
#define clk_audio_ap_clk2 0xf0fbaf5b
diff --git a/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
index 36d34b1..1018b0e 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
@@ -126,4 +126,7 @@
#define GCC_USB_PHY_CFG_AHB2PHY_BCR 18
#define GCC_EMAC_BCR 19
+/* Dummy clocks for rate measurement */
+#define MEASURE_ONLY_IPA_2X_CLK 0
+
#endif
diff --git a/include/linux/ipa_wdi3.h b/include/linux/ipa_wdi3.h
index aed8c59..6f00711 100644
--- a/include/linux/ipa_wdi3.h
+++ b/include/linux/ipa_wdi3.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-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,15 +24,49 @@
(IPA_HW_WDI3_TCL_DATA_CMD_ER_DESC_SIZE) : \
(IPA_HW_WDI3_IPA2FW_ER_DESC_SIZE))
+#define IPA_WDI_MAX_SUPPORTED_SYS_PIPE 3
+
+enum ipa_wdi_version {
+ IPA_WDI_1,
+ IPA_WDI_2,
+ IPA_WDI_3
+};
+
/**
- * struct ipa_wdi3_hdr_info - Header to install on IPA HW
+ * struct ipa_wdi_init_in_params - wdi init input parameters
+ *
+ * @wdi_version: wdi version
+ * @notify: uc ready callback
+ * @priv: uc ready callback cookie
+ */
+struct ipa_wdi_init_in_params {
+ enum ipa_wdi_version wdi_version;
+ ipa_uc_ready_cb notify;
+ void *priv;
+ ipa_wdi_meter_notifier_cb wdi_notify;
+};
+
+/**
+ * struct ipa_wdi_init_out_params - wdi init output parameters
+ *
+ * @is_uC_ready: is uC ready. No API should be called until uC
+ is ready.
+ * @is_smmu_enable: is smmu enabled
+ */
+struct ipa_wdi_init_out_params {
+ bool is_uC_ready;
+ bool is_smmu_enabled;
+};
+
+/**
+ * struct ipa_wdi_hdr_info - Header to install on IPA HW
*
* @hdr: header to install on IPA HW
* @hdr_len: length of header
* @dst_mac_addr_offset: destination mac address offset
* @hdr_type: layer two header type
*/
-struct ipa_wdi3_hdr_info {
+struct ipa_wdi_hdr_info {
u8 *hdr;
u8 hdr_len;
u8 dst_mac_addr_offset;
@@ -40,7 +74,7 @@
};
/**
- * struct ipa_wdi3_reg_intf_in_params - parameters for uC offload
+ * struct ipa_wdi_reg_intf_in_params - parameters for uC offload
* interface registration
*
* @netdev_name: network interface name
@@ -49,16 +83,17 @@
* @meta_data: meta data if any
* @meta_data_mask: meta data mask
*/
-struct ipa_wdi3_reg_intf_in_params {
+struct ipa_wdi_reg_intf_in_params {
const char *netdev_name;
- struct ipa_wdi3_hdr_info hdr_info[IPA_IP_MAX];
+ struct ipa_wdi_hdr_info hdr_info[IPA_IP_MAX];
+ enum ipa_client_type alt_dst_pipe;
u8 is_meta_data_valid;
u32 meta_data;
u32 meta_data_mask;
};
/**
- * struct ipa_wdi3_setup_info - WDI3 TX/Rx configuration
+ * struct ipa_wdi_pipe_setup_info - WDI TX/Rx configuration
* @ipa_ep_cfg: ipa endpoint configuration
* @client: type of "client"
* @transfer_ring_base_pa: physical address of the base of the transfer ring
@@ -71,20 +106,20 @@
will update the headpointer of the event ring
* @num_pkt_buffers: Number of pkt buffers allocated. The size of the event
ring and the transfer ring has to be atleast ( num_pkt_buffers + 1)
- * @pkt_offset: packet offset (wdi3 header length)
+ * @pkt_offset: packet offset (wdi header length)
* @desc_format_template[IPA_HW_WDI3_MAX_ER_DESC_SIZE]: Holds a cached
template of the desc format
*/
-struct ipa_wdi3_setup_info {
+struct ipa_wdi_pipe_setup_info {
struct ipa_ep_cfg ipa_ep_cfg;
enum ipa_client_type client;
- dma_addr_t transfer_ring_base_pa;
+ phys_addr_t transfer_ring_base_pa;
u32 transfer_ring_size;
- dma_addr_t transfer_ring_doorbell_pa;
+ phys_addr_t transfer_ring_doorbell_pa;
- dma_addr_t event_ring_base_pa;
+ phys_addr_t event_ring_base_pa;
u32 event_ring_size;
- dma_addr_t event_ring_doorbell_pa;
+ phys_addr_t event_ring_doorbell_pa;
u16 num_pkt_buffers;
u16 pkt_offset;
@@ -93,40 +128,87 @@
};
/**
- * struct ipa_wdi3_conn_in_params - information provided by
+ * struct ipa_wdi_pipe_setup_info_smmu - WDI TX/Rx configuration
+ * @ipa_ep_cfg: ipa endpoint configuration
+ * @client: type of "client"
+ * @transfer_ring_base_pa: physical address of the base of the transfer ring
+ * @transfer_ring_size: size of the transfer ring
+ * @transfer_ring_doorbell_pa: physical address of the doorbell that
+ IPA uC will update the tailpointer of the transfer ring
+ * @event_ring_base_pa: physical address of the base of the event ring
+ * @event_ring_size: event ring size
+ * @event_ring_doorbell_pa: physical address of the doorbell that IPA uC
+ will update the headpointer of the event ring
+ * @num_pkt_buffers: Number of pkt buffers allocated. The size of the event
+ ring and the transfer ring has to be atleast ( num_pkt_buffers + 1)
+ * @pkt_offset: packet offset (wdi header length)
+ * @desc_format_template[IPA_HW_WDI3_MAX_ER_DESC_SIZE]: Holds a cached
+ template of the desc format
+ */
+struct ipa_wdi_pipe_setup_info_smmu {
+ struct ipa_ep_cfg ipa_ep_cfg;
+ enum ipa_client_type client;
+ struct sg_table transfer_ring_base;
+ u32 transfer_ring_size;
+ phys_addr_t transfer_ring_doorbell_pa;
+
+ struct sg_table event_ring_base;
+ u32 event_ring_size;
+ phys_addr_t event_ring_doorbell_pa;
+ u16 num_pkt_buffers;
+
+ u16 pkt_offset;
+
+ u32 desc_format_template[IPA_HW_WDI3_MAX_ER_DESC_SIZE];
+};
+
+/**
+ * struct ipa_wdi_conn_in_params - information provided by
* uC offload client
* @notify: client callback function
* @priv: client cookie
+ * @is_smmu_enabled: if smmu is enabled
+ * @num_sys_pipe_needed: number of sys pipe needed
+ * @sys_in: parameters to setup sys pipe in mcc mode
* @tx: parameters to connect TX pipe(from IPA to WLAN)
+ * @tx_smmu: smmu parameters to connect TX pipe(from IPA to WLAN)
* @rx: parameters to connect RX pipe(from WLAN to IPA)
+ * @rx_smmu: smmu parameters to connect RX pipe(from WLAN to IPA)
*/
-struct ipa_wdi3_conn_in_params {
+struct ipa_wdi_conn_in_params {
ipa_notify_cb notify;
void *priv;
- struct ipa_wdi3_setup_info tx;
- struct ipa_wdi3_setup_info rx;
+ bool is_smmu_enabled;
+ u8 num_sys_pipe_needed;
+ struct ipa_sys_connect_params sys_in[IPA_WDI_MAX_SUPPORTED_SYS_PIPE];
+ union {
+ struct ipa_wdi_pipe_setup_info tx;
+ struct ipa_wdi_pipe_setup_info_smmu tx_smmu;
+ } u_tx;
+ union {
+ struct ipa_wdi_pipe_setup_info rx;
+ struct ipa_wdi_pipe_setup_info_smmu rx_smmu;
+ } u_rx;
};
/**
- * struct ipa_wdi3_conn_out_params - information provided
+ * struct ipa_wdi_conn_out_params - information provided
* to WLAN driver
* @tx_uc_db_pa: physical address of IPA uC doorbell for TX
- * @tx_uc_db_va: virtual address of IPA uC doorbell for TX
* @rx_uc_db_pa: physical address of IPA uC doorbell for RX
*/
-struct ipa_wdi3_conn_out_params {
- dma_addr_t tx_uc_db_pa;
- void __iomem *tx_uc_db_va;
- dma_addr_t rx_uc_db_pa;
+struct ipa_wdi_conn_out_params {
+ phys_addr_t tx_uc_db_pa;
+ phys_addr_t rx_uc_db_pa;
};
/**
- * struct ipa_wdi3_perf_profile - To set BandWidth profile
+ * struct ipa_wdi_perf_profile - To set BandWidth profile
*
* @client: type of client
* @max_supported_bw_mbps: maximum bandwidth needed (in Mbps)
*/
-struct ipa_wdi3_perf_profile {
+struct ipa_wdi_perf_profile {
enum ipa_client_type client;
u32 max_supported_bw_mbps;
};
@@ -134,117 +216,193 @@
#if defined CONFIG_IPA || defined CONFIG_IPA3
/**
- * ipa_wdi3_reg_intf - Client should call this function to
- * init WDI3 IPA offload data path
+ * ipa_wdi_init - Client should call this function to
+ * init WDI IPA offload data path
*
* Note: Should not be called from atomic context and only
* after checking IPA readiness using ipa_register_ipa_ready_cb()
*
* @Return 0 on success, negative on failure
*/
-int ipa_wdi3_reg_intf(
- struct ipa_wdi3_reg_intf_in_params *in);
+int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
+ struct ipa_wdi_init_out_params *out);
/**
- * ipa_wdi3_dereg_intf - Client Driver should call this
+ * ipa_wdi_cleanup - Client should call this function to
+ * clean up WDI IPA offload data path
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_wdi_cleanup(void);
+
+/**
+ * ipa_wdi_reg_intf - Client should call this function to
+ * register interface
+ *
+ * Note: Should not be called from atomic context
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_wdi_reg_intf(
+ struct ipa_wdi_reg_intf_in_params *in);
+
+/**
+ * ipa_wdi_dereg_intf - Client Driver should call this
* function to deregister before unload and after disconnect
*
* @Return 0 on success, negative on failure
*/
-int ipa_wdi3_dereg_intf(const char *netdev_name);
+int ipa_wdi_dereg_intf(const char *netdev_name);
/**
- * ipa_wdi3_conn_pipes - Client should call this
+ * ipa_wdi_conn_pipes - Client should call this
* function to connect pipes
*
* @in: [in] input parameters from client
* @out: [out] output params to client
*
- * Note: Should not be called from atomic context and only
- * after checking IPA readiness using ipa_register_ipa_ready_cb()
+ * Note: Should not be called from atomic context
*
* @Return 0 on success, negative on failure
*/
-int ipa_wdi3_conn_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out);
+int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out);
/**
- * ipa_wdi3_disconn_pipes() - Client should call this
+ * ipa_wdi_disconn_pipes() - Client should call this
* function to disconnect pipes
*
* Note: Should not be called from atomic context
*
* Returns: 0 on success, negative on failure
*/
-int ipa_wdi3_disconn_pipes(void);
+int ipa_wdi_disconn_pipes(void);
/**
- * ipa_wdi3_enable_pipes() - Client should call this
+ * ipa_wdi_enable_pipes() - Client should call this
* function to enable IPA offload data path
*
* Note: Should not be called from atomic context
*
* Returns: 0 on success, negative on failure
*/
-int ipa_wdi3_enable_pipes(void);
+int ipa_wdi_enable_pipes(void);
/**
- * ipa_wdi3_disable_pipes() - Client should call this
+ * ipa_wdi_disable_pipes() - Client should call this
* function to disable IPA offload data path
*
* Note: Should not be called from atomic context
*
* Returns: 0 on success, negative on failure
*/
-int ipa_wdi3_disable_pipes(void);
+int ipa_wdi_disable_pipes(void);
/**
- * ipa_wdi3_set_perf_profile() - Client should call this function to
+ * ipa_wdi_set_perf_profile() - Client should call this function to
* set IPA clock bandwidth based on data rates
*
* @profile: [in] BandWidth profile to use
*
* Returns: 0 on success, negative on failure
*/
-int ipa_wdi3_set_perf_profile(struct ipa_wdi3_perf_profile *profile);
+int ipa_wdi_set_perf_profile(struct ipa_wdi_perf_profile *profile);
+/**
+ * ipa_wdi_create_smmu_mapping() - Create smmu mapping
+ *
+ * @num_buffers: number of buffers
+ *
+ * @info: wdi buffer info
+ */
+int ipa_wdi_create_smmu_mapping(u32 num_buffers,
+ struct ipa_wdi_buffer_info *info);
+
+/**
+ * ipa_wdi_release_smmu_mapping() - Release smmu mapping
+ *
+ * @num_buffers: number of buffers
+ *
+ * @info: wdi buffer info
+ */
+int ipa_wdi_release_smmu_mapping(u32 num_buffers,
+ struct ipa_wdi_buffer_info *info);
+
+/**
+ * ipa_wdi_get_stats() - Query WDI statistics
+ * @stats: [inout] stats blob from client populated by driver
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * @note Cannot be called from atomic context
+ *
+ */
+int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats);
#else /* (CONFIG_IPA || CONFIG_IPA3) */
-static inline int ipa_wdi3_reg_intf(
- struct ipa_wdi3_reg_intf_in_params *in)
+static inline int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
+ struct ipa_wdi_init_out_params *out)
{
return -EPERM;
}
-static inline int ipa_wdi3_dereg_intf(const char *netdev_name)
+static inline int ipa_wdi_cleanup(void)
{
return -EPERM;
}
-static inline int ipa_wdi3_conn_pipes(struct ipa_wdi3_conn_in_params *in,
- struct ipa_wdi3_conn_out_params *out)
+static inline int ipa_wdi_reg_intf(
+ struct ipa_wdi_reg_intf_in_params *in)
{
return -EPERM;
}
-static inline int ipa_wdi3_disconn_pipes(void)
+static inline int ipa_wdi_dereg_intf(const char *netdev_name)
{
return -EPERM;
}
-static inline int ipa_wdi3_enable_pipes(void)
+static inline int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out)
{
return -EPERM;
}
-static inline int ipa_wdi3_disable_pipes(void)
+static inline int ipa_wdi_disconn_pipes(void)
{
return -EPERM;
}
-static inline int ipa_wdi3_set_perf_profile(
- struct ipa_wdi3_perf_profile *profile)
+static inline int ipa_wdi_enable_pipes(void)
+{
+ return -EPERM;
+}
+
+static inline int ipa_wdi_disable_pipes(void)
+{
+ return -EPERM;
+}
+
+static inline int ipa_wdi_set_perf_profile(
+ struct ipa_wdi_perf_profile *profile)
+{
+ return -EPERM;
+}
+
+static inline int ipa_wdi_create_smmu_mapping(u32 num_buffers,
+ struct ipa_wdi_buffer_info *info)
+{
+ return -EPERM;
+}
+
+static inline int ipa_wdi_release_smmu_mapping(u32 num_buffers,
+ struct ipa_wdi_buffer_info *info)
+{
+ return -EPERM;
+}
+
+static inline int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats)
{
return -EPERM;
}
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 3aa56e3..b5b43f9 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -270,75 +270,67 @@
#define INVALIDATE_CACHED_RANGE(map, from, size) \
do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0)
+#define map_word_equal(map, val1, val2) \
+({ \
+ int i, ret = 1; \
+ for (i = 0; i < map_words(map); i++) \
+ if ((val1).x[i] != (val2).x[i]) { \
+ ret = 0; \
+ break; \
+ } \
+ ret; \
+})
-static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
-{
- int i;
+#define map_word_and(map, val1, val2) \
+({ \
+ map_word r; \
+ int i; \
+ for (i = 0; i < map_words(map); i++) \
+ r.x[i] = (val1).x[i] & (val2).x[i]; \
+ r; \
+})
- for (i = 0; i < map_words(map); i++) {
- if (val1.x[i] != val2.x[i])
- return 0;
- }
+#define map_word_clr(map, val1, val2) \
+({ \
+ map_word r; \
+ int i; \
+ for (i = 0; i < map_words(map); i++) \
+ r.x[i] = (val1).x[i] & ~(val2).x[i]; \
+ r; \
+})
- return 1;
-}
+#define map_word_or(map, val1, val2) \
+({ \
+ map_word r; \
+ int i; \
+ for (i = 0; i < map_words(map); i++) \
+ r.x[i] = (val1).x[i] | (val2).x[i]; \
+ r; \
+})
-static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
-{
- map_word r;
- int i;
+#define map_word_andequal(map, val1, val2, val3) \
+({ \
+ int i, ret = 1; \
+ for (i = 0; i < map_words(map); i++) { \
+ if (((val1).x[i] & (val2).x[i]) != (val2).x[i]) { \
+ ret = 0; \
+ break; \
+ } \
+ } \
+ ret; \
+})
- for (i = 0; i < map_words(map); i++)
- r.x[i] = val1.x[i] & val2.x[i];
-
- return r;
-}
-
-static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2)
-{
- map_word r;
- int i;
-
- for (i = 0; i < map_words(map); i++)
- r.x[i] = val1.x[i] & ~val2.x[i];
-
- return r;
-}
-
-static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
-{
- map_word r;
- int i;
-
- for (i = 0; i < map_words(map); i++)
- r.x[i] = val1.x[i] | val2.x[i];
-
- return r;
-}
-
-static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)
-{
- int i;
-
- for (i = 0; i < map_words(map); i++) {
- if ((val1.x[i] & val2.x[i]) != val3.x[i])
- return 0;
- }
-
- return 1;
-}
-
-static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
-{
- int i;
-
- for (i = 0; i < map_words(map); i++) {
- if (val1.x[i] & val2.x[i])
- return 1;
- }
-
- return 0;
-}
+#define map_word_bitsset(map, val1, val2) \
+({ \
+ int i, ret = 0; \
+ for (i = 0; i < map_words(map); i++) { \
+ if ((val1).x[i] & (val2).x[i]) { \
+ ret = 1; \
+ break; \
+ } \
+ } \
+ ret; \
+})
static inline map_word map_word_load(struct map_info *map, const void *ptr)
{
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index a2a0152..71764767 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -390,6 +390,7 @@
* %SCALE_USBIN_I: Conversion for USB input current.
* %SCALE_BATT_THERM_TEMP_QRD: Conversion to temperature(decidegC) based on btm
* parameters for QRD.
+ * %SCALE_SMB1390_DIE_TEMP: Conversion for SMB1390 die temp
* %SCALE_NONE: Do not use this scaling type.
*/
enum qpnp_adc_scale_fn_type {
@@ -413,6 +414,7 @@
SCALE_I_DEFAULT,
SCALE_USBIN_I,
SCALE_BATT_THERM_TEMP_QRD,
+ SCALE_SMB1390_DIE_TEMP,
SCALE_NONE,
};
@@ -1712,6 +1714,25 @@
const struct qpnp_vadc_chan_properties *chan_prop,
struct qpnp_vadc_result *chan_rslt);
/**
+ * qpnp_adc_scale_die_temp_1390() - Scales the pre-calibrated digital output
+ * of an ADC to the ADC reference and compensates for the
+ * gain and offset. The voltage measured by HKADC is related to
+ * the junction temperature according to
+ * V_adc = 1.496 – 0.00381*Tj
+ * @dev: Structure device for qpnp vadc
+ * @adc_code: pre-calibrated digital output of the ADC.
+ * @adc_prop: adc properties of the pm8xxx adc such as bit resolution,
+ * reference voltage.
+ * @chan_prop: individual channel properties to compensate the i/p scaling,
+ * slope and offset.
+ * @chan_rslt: physical result to be stored.
+ */
+int32_t qpnp_adc_scale_die_temp_1390(struct qpnp_vadc_chip *dev,
+ int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt);
+/**
* qpnp_get_vadc() - Clients need to register with the vadc using the
* corresponding device instance it wants to read the channels
* from. Read the bindings document on how to pass the phandle
@@ -2149,6 +2170,12 @@
const struct qpnp_vadc_chan_properties *chan_prop,
struct qpnp_vadc_result *chan_rslt)
{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_die_temp_1390(struct qpnp_vadc_chip *vadc,
+ int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
static inline struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev,
const char *name)
{ return ERR_PTR(-ENXIO); }
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d5e79f1..040f928 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3937,6 +3937,9 @@
* @conn: (private) cfg80211 software SME connection state machine data
* @connect_keys: (private) keys to set after connection is established
* @conn_bss_type: connecting/connected BSS type
+ * @conn_owner_nlportid: (private) connection owner socket port ID
+ * @disconnect_wk: (private) auto-disconnect work
+ * @disconnect_bssid: (private) the BSSID to use for auto-disconnect
* @ibss_fixed: (private) IBSS is using fixed BSSID
* @ibss_dfs_possible: (private) IBSS may change to a DFS channel
* @event_list: (private) list for internal event processing
@@ -3968,6 +3971,10 @@
struct cfg80211_conn *conn;
struct cfg80211_cached_keys *connect_keys;
enum ieee80211_bss_type conn_bss_type;
+ u32 conn_owner_nlportid;
+
+ struct work_struct disconnect_wk;
+ u8 disconnect_bssid[ETH_ALEN];
struct list_head event_list;
spinlock_t event_lock;
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 8cfb1d7..a29c76f 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -858,322 +858,6 @@
__entry->freq)
);
-DECLARE_EVENT_CLASS(kpm_module,
-
- TP_PROTO(unsigned int managed_cpus, unsigned int max_cpus),
-
- TP_ARGS(managed_cpus, max_cpus),
-
- TP_STRUCT__entry(
- __field(u32, managed_cpus)
- __field(u32, max_cpus)
- ),
-
- TP_fast_assign(
- __entry->managed_cpus = managed_cpus;
- __entry->max_cpus = max_cpus;
- ),
-
- TP_printk("managed:%x max_cpus=%u", (unsigned int)__entry->managed_cpus,
- (unsigned int)__entry->max_cpus)
-);
-
-DEFINE_EVENT(kpm_module, set_max_cpus,
- TP_PROTO(unsigned int managed_cpus, unsigned int max_cpus),
- TP_ARGS(managed_cpus, max_cpus)
-);
-
-DEFINE_EVENT(kpm_module, reevaluate_hotplug,
- TP_PROTO(unsigned int managed_cpus, unsigned int max_cpus),
- TP_ARGS(managed_cpus, max_cpus)
-);
-
-DECLARE_EVENT_CLASS(kpm_module2,
-
- TP_PROTO(unsigned int cpu, unsigned int enter_cycle_cnt,
- unsigned int exit_cycle_cnt,
- unsigned int io_busy, u64 iowait),
-
- TP_ARGS(cpu, enter_cycle_cnt, exit_cycle_cnt, io_busy, iowait),
-
- TP_STRUCT__entry(
- __field(u32, cpu)
- __field(u32, enter_cycle_cnt)
- __field(u32, exit_cycle_cnt)
- __field(u32, io_busy)
- __field(u64, iowait)
- ),
-
- TP_fast_assign(
- __entry->cpu = cpu;
- __entry->enter_cycle_cnt = enter_cycle_cnt;
- __entry->exit_cycle_cnt = exit_cycle_cnt;
- __entry->io_busy = io_busy;
- __entry->iowait = iowait;
- ),
-
- TP_printk("CPU:%u enter_cycles=%u exit_cycles=%u io_busy=%u iowait=%lu",
- (unsigned int)__entry->cpu,
- (unsigned int)__entry->enter_cycle_cnt,
- (unsigned int)__entry->exit_cycle_cnt,
- (unsigned int)__entry->io_busy,
- (unsigned long)__entry->iowait)
-);
-
-DEFINE_EVENT(kpm_module2, track_iowait,
- TP_PROTO(unsigned int cpu, unsigned int enter_cycle_cnt,
- unsigned int exit_cycle_cnt, unsigned int io_busy, u64 iowait),
- TP_ARGS(cpu, enter_cycle_cnt, exit_cycle_cnt, io_busy, iowait)
-);
-
-DECLARE_EVENT_CLASS(cpu_modes,
-
- TP_PROTO(unsigned int cpu, unsigned int max_load,
- unsigned int single_enter_cycle_cnt,
- unsigned int single_exit_cycle_cnt,
- unsigned int total_load, unsigned int multi_enter_cycle_cnt,
- unsigned int multi_exit_cycle_cnt,
- unsigned int perf_cl_peak_enter_cycle_cnt,
- unsigned int perf_cl_peak_exit_cycle_cnt,
- unsigned int mode,
- unsigned int cpu_cnt),
-
- TP_ARGS(cpu, max_load, single_enter_cycle_cnt, single_exit_cycle_cnt,
- total_load, multi_enter_cycle_cnt, multi_exit_cycle_cnt,
- perf_cl_peak_enter_cycle_cnt, perf_cl_peak_exit_cycle_cnt, mode,
- cpu_cnt),
-
- TP_STRUCT__entry(
- __field(u32, cpu)
- __field(u32, max_load)
- __field(u32, single_enter_cycle_cnt)
- __field(u32, single_exit_cycle_cnt)
- __field(u32, total_load)
- __field(u32, multi_enter_cycle_cnt)
- __field(u32, multi_exit_cycle_cnt)
- __field(u32, perf_cl_peak_enter_cycle_cnt)
- __field(u32, perf_cl_peak_exit_cycle_cnt)
- __field(u32, mode)
- __field(u32, cpu_cnt)
- ),
-
- TP_fast_assign(
- __entry->cpu = cpu;
- __entry->max_load = max_load;
- __entry->single_enter_cycle_cnt = single_enter_cycle_cnt;
- __entry->single_exit_cycle_cnt = single_exit_cycle_cnt;
- __entry->total_load = total_load;
- __entry->multi_enter_cycle_cnt = multi_enter_cycle_cnt;
- __entry->multi_exit_cycle_cnt = multi_exit_cycle_cnt;
- __entry->perf_cl_peak_enter_cycle_cnt =
- perf_cl_peak_enter_cycle_cnt;
- __entry->perf_cl_peak_exit_cycle_cnt =
- perf_cl_peak_exit_cycle_cnt;
- __entry->mode = mode;
- __entry->cpu_cnt = cpu_cnt;
- ),
-
- TP_printk("%u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%u",
- (unsigned int)__entry->cpu, (unsigned int)__entry->max_load,
- (unsigned int)__entry->single_enter_cycle_cnt,
- (unsigned int)__entry->single_exit_cycle_cnt,
- (unsigned int)__entry->total_load,
- (unsigned int)__entry->multi_enter_cycle_cnt,
- (unsigned int)__entry->multi_exit_cycle_cnt,
- (unsigned int)__entry->perf_cl_peak_enter_cycle_cnt,
- (unsigned int)__entry->perf_cl_peak_exit_cycle_cnt,
- (unsigned int)__entry->mode,
- (unsigned int)__entry->cpu_cnt)
-);
-
-DEFINE_EVENT(cpu_modes, cpu_mode_detect,
- TP_PROTO(unsigned int cpu, unsigned int max_load,
- unsigned int single_enter_cycle_cnt,
- unsigned int single_exit_cycle_cnt,
- unsigned int total_load, unsigned int multi_enter_cycle_cnt,
- unsigned int multi_exit_cycle_cnt,
- unsigned int perf_cl_peak_enter_cycle_cnt,
- unsigned int perf_cl_peak_exit_cycle_cnt,
- unsigned int mode,
- unsigned int cpu_cnt),
- TP_ARGS(cpu, max_load, single_enter_cycle_cnt, single_exit_cycle_cnt,
- total_load, multi_enter_cycle_cnt, multi_exit_cycle_cnt,
- perf_cl_peak_enter_cycle_cnt, perf_cl_peak_exit_cycle_cnt,
- mode, cpu_cnt)
-);
-
-DECLARE_EVENT_CLASS(timer_status,
- TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
- unsigned int single_enter_cycle_cnt,
- unsigned int single_exit_cycles,
- unsigned int single_exit_cycle_cnt,
- unsigned int multi_enter_cycles,
- unsigned int multi_enter_cycle_cnt,
- unsigned int multi_exit_cycles,
- unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
- unsigned int mode),
- TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
- single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
- multi_enter_cycle_cnt, multi_exit_cycles,
- multi_exit_cycle_cnt, timer_rate, mode),
-
- TP_STRUCT__entry(
- __field(unsigned int, cpu)
- __field(unsigned int, single_enter_cycles)
- __field(unsigned int, single_enter_cycle_cnt)
- __field(unsigned int, single_exit_cycles)
- __field(unsigned int, single_exit_cycle_cnt)
- __field(unsigned int, multi_enter_cycles)
- __field(unsigned int, multi_enter_cycle_cnt)
- __field(unsigned int, multi_exit_cycles)
- __field(unsigned int, multi_exit_cycle_cnt)
- __field(unsigned int, timer_rate)
- __field(unsigned int, mode)
- ),
-
- TP_fast_assign(
- __entry->cpu = cpu;
- __entry->single_enter_cycles = single_enter_cycles;
- __entry->single_enter_cycle_cnt = single_enter_cycle_cnt;
- __entry->single_exit_cycles = single_exit_cycles;
- __entry->single_exit_cycle_cnt = single_exit_cycle_cnt;
- __entry->multi_enter_cycles = multi_enter_cycles;
- __entry->multi_enter_cycle_cnt = multi_enter_cycle_cnt;
- __entry->multi_exit_cycles = multi_exit_cycles;
- __entry->multi_exit_cycle_cnt = multi_exit_cycle_cnt;
- __entry->timer_rate = timer_rate;
- __entry->mode = mode;
- ),
-
- TP_printk("%u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u",
- (unsigned int) __entry->cpu,
- (unsigned int) __entry->single_enter_cycles,
- (unsigned int) __entry->single_enter_cycle_cnt,
- (unsigned int) __entry->single_exit_cycles,
- (unsigned int) __entry->single_exit_cycle_cnt,
- (unsigned int) __entry->multi_enter_cycles,
- (unsigned int) __entry->multi_enter_cycle_cnt,
- (unsigned int) __entry->multi_exit_cycles,
- (unsigned int) __entry->multi_exit_cycle_cnt,
- (unsigned int) __entry->timer_rate,
- (unsigned int) __entry->mode)
-);
-
-DEFINE_EVENT(timer_status, single_mode_timeout,
- TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
- unsigned int single_enter_cycle_cnt,
- unsigned int single_exit_cycles,
- unsigned int single_exit_cycle_cnt,
- unsigned int multi_enter_cycles,
- unsigned int multi_enter_cycle_cnt,
- unsigned int multi_exit_cycles,
- unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
- unsigned int mode),
- TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
- single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
- multi_enter_cycle_cnt, multi_exit_cycles, multi_exit_cycle_cnt,
- timer_rate, mode)
-);
-
-DEFINE_EVENT(timer_status, single_cycle_exit_timer_start,
- TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
- unsigned int single_enter_cycle_cnt,
- unsigned int single_exit_cycles,
- unsigned int single_exit_cycle_cnt,
- unsigned int multi_enter_cycles,
- unsigned int multi_enter_cycle_cnt,
- unsigned int multi_exit_cycles,
- unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
- unsigned int mode),
- TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
- single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
- multi_enter_cycle_cnt, multi_exit_cycles, multi_exit_cycle_cnt,
- timer_rate, mode)
-);
-
-DEFINE_EVENT(timer_status, single_cycle_exit_timer_stop,
- TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
- unsigned int single_enter_cycle_cnt,
- unsigned int single_exit_cycles,
- unsigned int single_exit_cycle_cnt,
- unsigned int multi_enter_cycles,
- unsigned int multi_enter_cycle_cnt,
- unsigned int multi_exit_cycles,
- unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
- unsigned int mode),
- TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
- single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
- multi_enter_cycle_cnt, multi_exit_cycles, multi_exit_cycle_cnt,
- timer_rate, mode)
-);
-
-DECLARE_EVENT_CLASS(perf_cl_peak_timer_status,
- TP_PROTO(unsigned int cpu, unsigned int perf_cl_peak_enter_cycles,
- unsigned int perf_cl_peak_enter_cycle_cnt,
- unsigned int perf_cl_peak_exit_cycles,
- unsigned int perf_cl_peak_exit_cycle_cnt,
- unsigned int timer_rate,
- unsigned int mode),
- TP_ARGS(cpu, perf_cl_peak_enter_cycles, perf_cl_peak_enter_cycle_cnt,
- perf_cl_peak_exit_cycles, perf_cl_peak_exit_cycle_cnt,
- timer_rate, mode),
-
- TP_STRUCT__entry(
- __field(unsigned int, cpu)
- __field(unsigned int, perf_cl_peak_enter_cycles)
- __field(unsigned int, perf_cl_peak_enter_cycle_cnt)
- __field(unsigned int, perf_cl_peak_exit_cycles)
- __field(unsigned int, perf_cl_peak_exit_cycle_cnt)
- __field(unsigned int, timer_rate)
- __field(unsigned int, mode)
- ),
-
- TP_fast_assign(
- __entry->cpu = cpu;
- __entry->perf_cl_peak_enter_cycles = perf_cl_peak_enter_cycles;
- __entry->perf_cl_peak_enter_cycle_cnt =
- perf_cl_peak_enter_cycle_cnt;
- __entry->perf_cl_peak_exit_cycles = perf_cl_peak_exit_cycles;
- __entry->perf_cl_peak_exit_cycle_cnt =
- perf_cl_peak_exit_cycle_cnt;
- __entry->timer_rate = timer_rate;
- __entry->mode = mode;
- ),
-
- TP_printk("%u:%4u:%4u:%4u:%4u:%4u:%4u",
- (unsigned int) __entry->cpu,
- (unsigned int) __entry->perf_cl_peak_enter_cycles,
- (unsigned int) __entry->perf_cl_peak_enter_cycle_cnt,
- (unsigned int) __entry->perf_cl_peak_exit_cycles,
- (unsigned int) __entry->perf_cl_peak_exit_cycle_cnt,
- (unsigned int) __entry->timer_rate,
- (unsigned int) __entry->mode)
-);
-
-DEFINE_EVENT(perf_cl_peak_timer_status, perf_cl_peak_exit_timer_start,
- TP_PROTO(unsigned int cpu, unsigned int perf_cl_peak_enter_cycles,
- unsigned int perf_cl_peak_enter_cycle_cnt,
- unsigned int perf_cl_peak_exit_cycles,
- unsigned int perf_cl_peak_exit_cycle_cnt,
- unsigned int timer_rate,
- unsigned int mode),
- TP_ARGS(cpu, perf_cl_peak_enter_cycles, perf_cl_peak_enter_cycle_cnt,
- perf_cl_peak_exit_cycles, perf_cl_peak_exit_cycle_cnt,
- timer_rate, mode)
-);
-
-
-DEFINE_EVENT(perf_cl_peak_timer_status, perf_cl_peak_exit_timer_stop,
- TP_PROTO(unsigned int cpu, unsigned int perf_cl_peak_enter_cycles,
- unsigned int perf_cl_peak_enter_cycle_cnt,
- unsigned int perf_cl_peak_exit_cycles,
- unsigned int perf_cl_peak_exit_cycle_cnt,
- unsigned int timer_rate,
- unsigned int mode),
- TP_ARGS(cpu, perf_cl_peak_enter_cycles, perf_cl_peak_enter_cycle_cnt,
- perf_cl_peak_exit_cycles, perf_cl_peak_exit_cycle_cnt,
- timer_rate, mode)
-);
#endif /* _TRACE_POWER_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 3092188..5222d49 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1870,6 +1870,8 @@
* and remove functions. NAN notifications will be sent in unicast to that
* socket. Without this attribute, any socket can add functions and the
* notifications will be sent to the %NL80211_MCGRP_NAN multicast group.
+ * If set during %NL80211_CMD_ASSOCIATE or %NL80211_CMD_CONNECT the
+ * station will deauthenticate when the socket is closed.
*
* @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
* the TDLS link initiator.
diff --git a/kernel/async.c b/kernel/async.c
index d2edd6e..d84d486 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -84,20 +84,24 @@
static async_cookie_t lowest_in_progress(struct async_domain *domain)
{
- struct list_head *pending;
+ struct async_entry *first = NULL;
async_cookie_t ret = ASYNC_COOKIE_MAX;
unsigned long flags;
spin_lock_irqsave(&async_lock, flags);
- if (domain)
- pending = &domain->pending;
- else
- pending = &async_global_pending;
+ if (domain) {
+ if (!list_empty(&domain->pending))
+ first = list_first_entry(&domain->pending,
+ struct async_entry, domain_list);
+ } else {
+ if (!list_empty(&async_global_pending))
+ first = list_first_entry(&async_global_pending,
+ struct async_entry, global_list);
+ }
- if (!list_empty(pending))
- ret = list_first_entry(pending, struct async_entry,
- domain_list)->cookie;
+ if (first)
+ ret = first->cookie;
spin_unlock_irqrestore(&async_lock, flags);
return ret;
diff --git a/kernel/relay.c b/kernel/relay.c
index 8f18d31..2603e04 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -611,7 +611,6 @@
kref_put(&chan->kref, relay_destroy_channel);
mutex_unlock(&relay_channels_mutex);
- kfree(chan);
return NULL;
}
EXPORT_SYMBOL_GPL(relay_open);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 31b45b7..ad2b980 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6447,6 +6447,19 @@
call_rcu_sched(&old_rd->rcu, free_rootdomain);
}
+void sched_get_rd(struct root_domain *rd)
+{
+ atomic_inc(&rd->refcount);
+}
+
+void sched_put_rd(struct root_domain *rd)
+{
+ if (!atomic_dec_and_test(&rd->refcount))
+ return;
+
+ call_rcu_sched(&rd->rcu, free_rootdomain);
+}
+
static int init_rootdomain(struct root_domain *rd)
{
memset(rd, 0, sizeof(*rd));
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 73f11c4..e6abbb4 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -2261,8 +2261,11 @@
rto_start_unlock(&rq->rd->rto_loop_start);
- if (cpu >= 0)
+ if (cpu >= 0) {
+ /* Make sure the rd does not get freed while pushing */
+ sched_get_rd(rq->rd);
irq_work_queue_on(&rq->rd->rto_push_work, cpu);
+ }
}
/* Called from hardirq context */
@@ -2292,8 +2295,10 @@
raw_spin_unlock(&rd->rto_lock);
- if (cpu < 0)
+ if (cpu < 0) {
+ sched_put_rd(rd);
return;
+ }
/* Try the next RT overloaded CPU */
irq_work_queue_on(&rd->rto_push_work, cpu);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index e0aa30d..2d04a9d 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -679,6 +679,8 @@
};
extern struct root_domain def_root_domain;
+extern void sched_get_rd(struct root_domain *rd);
+extern void sched_put_rd(struct root_domain *rd);
#ifdef HAVE_RT_PUSH_IPI
extern void rto_push_irq_work_func(struct irq_work *work);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 5df97e7..b593317 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -234,8 +234,16 @@
static inline void lockdep_softirq_end(bool in_hardirq) { }
#endif
-#define long_softirq_pending() (local_softirq_pending() & LONG_SOFTIRQ_MASK)
-#define defer_for_rt() (long_softirq_pending() && cpupri_check_rt())
+#define softirq_deferred_for_rt(pending) \
+({ \
+ __u32 deferred = 0; \
+ if (cpupri_check_rt()) { \
+ deferred = pending & LONG_SOFTIRQ_MASK; \
+ pending &= ~LONG_SOFTIRQ_MASK; \
+ } \
+ deferred; \
+})
+
asmlinkage __visible void __softirq_entry __do_softirq(void)
{
unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
@@ -243,6 +251,7 @@
int max_restart = MAX_SOFTIRQ_RESTART;
struct softirq_action *h;
bool in_hardirq;
+ __u32 deferred;
__u32 pending;
int softirq_bit;
@@ -254,14 +263,14 @@
current->flags &= ~PF_MEMALLOC;
pending = local_softirq_pending();
+ deferred = softirq_deferred_for_rt(pending);
account_irq_enter_time(current);
-
__local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
in_hardirq = lockdep_softirq_start();
restart:
/* Reset the pending bitmask before enabling irqs */
- set_softirq_pending(0);
+ set_softirq_pending(deferred);
__this_cpu_write(active_softirqs, pending);
local_irq_enable();
@@ -297,15 +306,16 @@
local_irq_disable();
pending = local_softirq_pending();
+ deferred = softirq_deferred_for_rt(pending);
+
if (pending) {
if (time_before(jiffies, end) && !need_resched() &&
- !defer_for_rt() &&
--max_restart)
goto restart;
-
- wakeup_softirqd();
}
+ if (pending | deferred)
+ wakeup_softirqd();
lockdep_softirq_end(in_hardirq);
account_irq_exit_time(current);
__local_bh_enable(SOFTIRQ_OFFSET);
@@ -352,7 +362,7 @@
static inline void invoke_softirq(void)
{
- if (!force_irqthreads && !defer_for_rt()) {
+ if (!force_irqthreads) {
#ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
/*
* We can safely execute softirq on the current stack if
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index f2826c3..fc7c37a 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -507,17 +507,22 @@
{
struct task_struct *rtn = current->group_leader;
- if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
- (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) ||
- !same_thread_group(rtn, current) ||
- (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
+ switch (event->sigev_notify) {
+ case SIGEV_SIGNAL | SIGEV_THREAD_ID:
+ rtn = find_task_by_vpid(event->sigev_notify_thread_id);
+ if (!rtn || !same_thread_group(rtn, current))
+ return NULL;
+ /* FALLTHRU */
+ case SIGEV_SIGNAL:
+ case SIGEV_THREAD:
+ if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX)
+ return NULL;
+ /* FALLTHRU */
+ case SIGEV_NONE:
+ return task_pid(rtn);
+ default:
return NULL;
-
- if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) &&
- ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX)))
- return NULL;
-
- return task_pid(rtn);
+ }
}
void posix_timers_register_clock(const clockid_t clock_id,
@@ -745,8 +750,7 @@
/* interval timer ? */
if (iv.tv64)
cur_setting->it_interval = ktime_to_timespec(iv);
- else if (!hrtimer_active(timer) &&
- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
+ else if (!hrtimer_active(timer) && timr->it_sigev_notify != SIGEV_NONE)
return;
now = timer->base->get_time();
@@ -757,7 +761,7 @@
* expiry is > now.
*/
if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+ timr->it_sigev_notify == SIGEV_NONE))
timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
remaining = __hrtimer_expires_remaining_adjusted(timer, now);
@@ -767,7 +771,7 @@
* A single shot SIGEV_NONE timer must return 0, when
* it is expired !
*/
- if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
+ if (timr->it_sigev_notify != SIGEV_NONE)
cur_setting->it_value.tv_nsec = 1;
} else
cur_setting->it_value = ktime_to_timespec(remaining);
@@ -865,7 +869,7 @@
timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
/* SIGEV_NONE timers are not queued ! See common_timer_get */
- if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
+ if (timr->it_sigev_notify == SIGEV_NONE) {
/* Setup correct expiry time for relative timers */
if (mode == HRTIMER_MODE_REL) {
hrtimer_add_expires(timer, timer->base->get_time());
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 5b8d718..2884fe0 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3911,7 +3911,6 @@
func_g.type = filter_parse_regex(glob, strlen(glob),
&func_g.search, ¬);
func_g.len = strlen(func_g.search);
- func_g.search = glob;
/* we do not support '!' for function probes */
if (WARN_ON(not))
diff --git a/lib/ubsan.c b/lib/ubsan.c
index fb0409d..50d1d5c 100644
--- a/lib/ubsan.c
+++ b/lib/ubsan.c
@@ -265,14 +265,14 @@
}
EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
-static void handle_null_ptr_deref(struct type_mismatch_data *data)
+static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
{
unsigned long flags;
- if (suppress_report(&data->location))
+ if (suppress_report(data->location))
return;
- ubsan_prologue(&data->location, &flags);
+ ubsan_prologue(data->location, &flags);
pr_err("%s null pointer of type %s\n",
type_check_kinds[data->type_check_kind],
@@ -281,15 +281,15 @@
ubsan_epilogue(&flags);
}
-static void handle_missaligned_access(struct type_mismatch_data *data,
+static void handle_misaligned_access(struct type_mismatch_data_common *data,
unsigned long ptr)
{
unsigned long flags;
- if (suppress_report(&data->location))
+ if (suppress_report(data->location))
return;
- ubsan_prologue(&data->location, &flags);
+ ubsan_prologue(data->location, &flags);
pr_err("%s misaligned address %p for type %s\n",
type_check_kinds[data->type_check_kind],
@@ -299,15 +299,15 @@
ubsan_epilogue(&flags);
}
-static void handle_object_size_mismatch(struct type_mismatch_data *data,
+static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
unsigned long ptr)
{
unsigned long flags;
- if (suppress_report(&data->location))
+ if (suppress_report(data->location))
return;
- ubsan_prologue(&data->location, &flags);
+ ubsan_prologue(data->location, &flags);
pr_err("%s address %p with insufficient space\n",
type_check_kinds[data->type_check_kind],
(void *) ptr);
@@ -315,19 +315,47 @@
ubsan_epilogue(&flags);
}
-void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
+static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
unsigned long ptr)
{
if (!ptr)
handle_null_ptr_deref(data);
else if (data->alignment && !IS_ALIGNED(ptr, data->alignment))
- handle_missaligned_access(data, ptr);
+ handle_misaligned_access(data, ptr);
else
handle_object_size_mismatch(data, ptr);
}
+
+void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
+ unsigned long ptr)
+{
+ struct type_mismatch_data_common common_data = {
+ .location = &data->location,
+ .type = data->type,
+ .alignment = data->alignment,
+ .type_check_kind = data->type_check_kind
+ };
+
+ ubsan_type_mismatch_common(&common_data, ptr);
+}
EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
+void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
+ unsigned long ptr)
+{
+
+ struct type_mismatch_data_common common_data = {
+ .location = &data->location,
+ .type = data->type,
+ .alignment = 1UL << data->log_alignment,
+ .type_check_kind = data->type_check_kind
+ };
+
+ ubsan_type_mismatch_common(&common_data, ptr);
+}
+EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
+
void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
{
unsigned long flags;
diff --git a/lib/ubsan.h b/lib/ubsan.h
index b2d18d4..d8b8085 100644
--- a/lib/ubsan.h
+++ b/lib/ubsan.h
@@ -36,6 +36,20 @@
unsigned char type_check_kind;
};
+struct type_mismatch_data_v1 {
+ struct source_location location;
+ struct type_descriptor *type;
+ unsigned char log_alignment;
+ unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_common {
+ struct source_location *location;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
struct nonnull_arg_data {
struct source_location location;
struct source_location attr_location;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index b68168f..9d43c1f 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -259,6 +259,7 @@
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct inet_sock *inet = inet_sk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
int err = 0;
const int old_state = sk->sk_state;
@@ -278,6 +279,10 @@
sk->sk_err = ECONNRESET;
dccp_clear_xmit_timers(sk);
+ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
+ dp->dccps_hc_rx_ccid = NULL;
+ dp->dccps_hc_tx_ccid = NULL;
__skb_queue_purge(&sk->sk_receive_queue);
__skb_queue_purge(&sk->sk_write_queue);
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d..95d5088 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1117,6 +1117,8 @@
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
dev->priv_flags |= IFF_DONT_BRIDGE;
+ INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
+
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
break;
case NETDEV_GOING_DOWN:
@@ -1205,6 +1207,7 @@
#ifdef CONFIG_CFG80211_WEXT
kzfree(wdev->wext.keys);
#endif
+ flush_work(&wdev->disconnect_wk);
}
/*
* synchronise (so that we won't find this netdev
diff --git a/net/wireless/core.h b/net/wireless/core.h
index c40f3de..478e37a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -382,6 +382,7 @@
struct cfg80211_roam_info *info);
int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);
+void cfg80211_autodisconnect_wk(struct work_struct *work);
/* SME implementation */
void cfg80211_conn_work(struct work_struct *work);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 5499e9f..5f85a4e 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -350,6 +350,11 @@
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
return 0;
+ if (ether_addr_equal(wdev->disconnect_bssid, bssid) ||
+ (wdev->current_bss &&
+ ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
+ wdev->conn_owner_nlportid = 0;
+
return rdev_deauth(rdev, dev, &req);
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 466aa7e..e6b916b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8129,8 +8129,17 @@
err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
if (!err) {
wdev_lock(dev->ieee80211_ptr);
+
err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
ssid, ssid_len, &req);
+
+ if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+ dev->ieee80211_ptr->conn_owner_nlportid =
+ info->snd_portid;
+ memcpy(dev->ieee80211_ptr->disconnect_bssid,
+ bssid, ETH_ALEN);
+ }
+
wdev_unlock(dev->ieee80211_ptr);
}
@@ -8879,11 +8888,24 @@
}
wdev_lock(dev->ieee80211_ptr);
+
err = cfg80211_connect(rdev, dev, &connect, connkeys,
connect.prev_bssid);
- wdev_unlock(dev->ieee80211_ptr);
if (err)
kzfree(connkeys);
+
+ if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+ dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
+ if (connect.bssid)
+ memcpy(dev->ieee80211_ptr->disconnect_bssid,
+ connect.bssid, ETH_ALEN);
+ else
+ memset(dev->ieee80211_ptr->disconnect_bssid,
+ 0, ETH_ALEN);
+ }
+
+ wdev_unlock(dev->ieee80211_ptr);
+
return err;
}
@@ -14737,6 +14759,8 @@
if (wdev->owner_nlportid == notify->portid)
schedule_destroy_work = true;
+ else if (wdev->conn_owner_nlportid == notify->portid)
+ schedule_work(&wdev->disconnect_wk);
}
spin_lock_bh(&rdev->beacon_registrations_lock);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index d414049..2d64e0f 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -763,6 +763,7 @@
kzfree(wdev->connect_keys);
wdev->connect_keys = NULL;
wdev->ssid_len = 0;
+ wdev->conn_owner_nlportid = 0;
if (cr->bss) {
cfg80211_unhold_bss(bss_from_pub(cr->bss));
cfg80211_put_bss(wdev->wiphy, cr->bss);
@@ -1010,6 +1011,7 @@
wdev->current_bss = NULL;
wdev->ssid_len = 0;
+ wdev->conn_owner_nlportid = 0;
nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
@@ -1182,6 +1184,8 @@
kzfree(wdev->connect_keys);
wdev->connect_keys = NULL;
+ wdev->conn_owner_nlportid = 0;
+
if (wdev->conn)
err = cfg80211_sme_disconnect(wdev, reason);
else if (!rdev->ops->disconnect)
@@ -1199,3 +1203,32 @@
return err;
}
+
+/*
+ * Used to clean up after the connection / connection attempt owner socket
+ * disconnects
+ */
+void cfg80211_autodisconnect_wk(struct work_struct *work)
+{
+ struct wireless_dev *wdev =
+ container_of(work, struct wireless_dev, disconnect_wk);
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+
+ wdev_lock(wdev);
+
+ if (wdev->conn_owner_nlportid) {
+ /*
+ * Use disconnect_bssid if still connecting and ops->disconnect
+ * not implemented. Otherwise we can use cfg80211_disconnect.
+ */
+ if (rdev->ops->disconnect || wdev->current_bss)
+ cfg80211_disconnect(rdev, wdev->netdev,
+ WLAN_REASON_DEAUTH_LEAVING, true);
+ else
+ cfg80211_mlme_deauth(rdev, wdev->netdev,
+ wdev->disconnect_bssid, NULL, 0,
+ WLAN_REASON_DEAUTH_LEAVING, false);
+ }
+
+ wdev_unlock(wdev);
+}
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c
index 3f8e6f0..dcf0369 100644
--- a/sound/soc/intel/skylake/skl-nhlt.c
+++ b/sound/soc/intel/skylake/skl-nhlt.c
@@ -41,7 +41,8 @@
obj = acpi_evaluate_dsm(handle, OSC_UUID, 1, 1, NULL);
if (obj && obj->type == ACPI_TYPE_BUFFER) {
nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer;
- nhlt_table = (struct nhlt_acpi_table *)
+ if (nhlt_ptr->length)
+ nhlt_table = (struct nhlt_acpi_table *)
memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
MEMREMAP_WB);
ACPI_FREE(obj);
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 974915c..08bfee4 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -476,6 +476,7 @@
case I2S_INTCR:
case I2S_XFER:
case I2S_CLR:
+ case I2S_TXDR:
case I2S_RXDR:
case I2S_FIFOLR:
case I2S_INTSR:
@@ -490,6 +491,9 @@
switch (reg) {
case I2S_INTSR:
case I2S_CLR:
+ case I2S_FIFOLR:
+ case I2S_TXDR:
+ case I2S_RXDR:
return true;
default:
return false;
@@ -499,6 +503,8 @@
static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case I2S_RXDR:
+ return true;
default:
return false;
}