summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/scheduler/sched_hmp.txt35
-rw-r--r--Documentation/scheduler/sched-hmp.txt8
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi302
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi22
-rw-r--r--arch/arm/configs/msmfalcon_defconfig3
-rw-r--r--arch/arm/kernel/topology.c34
-rw-r--r--drivers/clk/msm/clock-osm.c8
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c24
-rw-r--r--drivers/hwtracing/coresight/coresight-csr.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-stm.c4
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c21
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c14
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c28
-rw-r--r--drivers/net/wireless/ath/wil6210/fw.h3
-rw-r--r--drivers/net/wireless/ath/wil6210/fw_inc.c7
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h3
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c8
-rw-r--r--drivers/power/qcom-charger/battery_current_limit.c77
-rw-r--r--drivers/soc/qcom/jtag-fuse.c4
-rw-r--r--include/linux/percpu-rwsem.h84
-rw-r--r--include/linux/rcu_sync.h1
-rw-r--r--kernel/cgroup.c6
-rw-r--r--kernel/fork.c4
-rw-r--r--kernel/locking/percpu-rwsem.c229
-rw-r--r--kernel/rcu/sync.c12
-rw-r--r--kernel/sched/core.c2
-rw-r--r--kernel/sched/hmp.c56
-rw-r--r--kernel/sched/sched.h4
-rw-r--r--kernel/sched/sched_avg.c19
-rw-r--r--net/rmnet_data/rmnet_data_vnd.c2
34 files changed, 838 insertions, 213 deletions
diff --git a/Documentation/devicetree/bindings/scheduler/sched_hmp.txt b/Documentation/devicetree/bindings/scheduler/sched_hmp.txt
new file mode 100644
index 000000000000..ba1d4db9e407
--- /dev/null
+++ b/Documentation/devicetree/bindings/scheduler/sched_hmp.txt
@@ -0,0 +1,35 @@
+* HMP scheduler
+
+This file describes the bindings for an optional HMP scheduler
+node (/sched-hmp).
+
+Required properties:
+
+Optional properties:
+
+- boost-policy: The HMP scheduler has two types of task placement boost
+policies.
+
+(1) boost-on-big policy make use of all big CPUs up to their full capacity
+before using the little CPUs. This improves performance on true b.L systems
+where the big CPUs have higher efficiency compared to the little CPUs.
+
+(2) boost-on-all policy place the tasks on the CPU having the highest
+spare capacity. This policy is optimal for SMP like systems.
+
+The scheduler sets the boost policy to boost-on-big on systems which has
+CPUs of different efficiencies. However it is possible that CPUs of the
+same micro architecture to have slight difference in efficiency due to
+other factors like cache size. Selecting the boost-on-big policy based
+on relative difference in efficiency is not optimal on such systems.
+The boost-policy device tree property is introduced to specify the
+required boost type and it overrides the default selection of boost
+type in the scheduler.
+
+The possible values for this property are "boost-on-big" and "boost-on-all".
+
+Example:
+
+sched-hmp {
+ boost-policy = "boost-on-all"
+}
diff --git a/Documentation/scheduler/sched-hmp.txt b/Documentation/scheduler/sched-hmp.txt
index b400e053e55d..298064bc44d7 100644
--- a/Documentation/scheduler/sched-hmp.txt
+++ b/Documentation/scheduler/sched-hmp.txt
@@ -43,6 +43,7 @@ CONTENTS
8.8 sched_get_busy
8.9 sched_freq_alert
8.10 sched_set_boost
+9. Device Tree bindings
===============
1. INTRODUCTION
@@ -1447,3 +1448,10 @@ Logged when boost settings are being changed
<task>-0 [004] d.h4 12700.711489: sched_set_boost: ref_count=1
- ref_count: A non-zero value indicates boost is in effect
+
+========================
+9. Device Tree bindings
+========================
+
+The device tree bindings for the HMP scheduler are defined in
+Documentation/devicetree/bindings/sched/sched_hmp.txt
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index e19fb5f7c233..25fd35c1bd10 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -664,11 +664,11 @@
/* SVS2 */
qcom,imem-ab-tbl =
- <200000000 1752000>,
- <269330000 1752000>,
- <355200000 2500000>,
- <444000000 6000000>,
- <533000000 6000000>;
+ <200000000 1560000>,/* imem @ svs2 freq 75 Mhz */
+ <269330000 3570000>,/* imem @ svs freq 171 Mhz */
+ <355200000 3570000>,/* imem @ svs freq 171 Mhz */
+ <444000000 6750000>,/* imem @ nom freq 323 Mhz */
+ <533000000 8490000>;/* imem @ turbo freq 406 Mhz */
};
/* GPU overrides */
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi
index c44e8f976710..f17be7570742 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi
@@ -66,10 +66,10 @@
* corresponding video core frequency.
*/
qcom,imem-ab-tbl =
- <100000000 1752000>, /* imem @ svs2 freq 75 Mhz */
- <186000000 1752000>, /* imem @ svs2 freq 75 Mhz */
- <360000000 2500000>, /* imem @ svs freq 171 Mhz */
- <465000000 6000000>; /* imem @ noimal freq 320 Mhz */
+ <100000000 1560000>, /* imem @ svs2 freq 75 Mhz */
+ <186000000 3570000>, /* imem @ svs freq 171 Mhz */
+ <360000000 6750000>, /* imem @ nom freq 323 Mhz */
+ <465000000 8490000>; /* imem @ turbo freq 406 Mhz */
/* Regulators */
smmu-vdd-supply = <&gdsc_bimc_smmu>;
@@ -124,7 +124,7 @@
qcom,bus-master = <MSM_BUS_MASTER_VIDEO_P0_OCMEM>;
qcom,bus-slave = <MSM_BUS_SLAVE_VMEM>;
qcom,bus-governor = "msm-vidc-vmem+";
- qcom,bus-range-kbps = <1000 6776000>;
+ qcom,bus-range-kbps = <1000 8490000>;
};
arm9_bus_ddr {
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi
index 352856965373..b60d4013dad8 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi
@@ -26,6 +26,8 @@
arm,buffer-size = <0x400000>;
arm,sg-enable;
+ coresight-ctis = <&cti0 &cti8>;
+
coresight-name = "coresight-tmc-etr";
clocks = <&clock_gcc RPM_QDSS_CLK>,
@@ -76,6 +78,8 @@
coresight-name = "coresight-tmc-etf";
+ coresight-ctis = <&cti0 &cti8>;
+
clocks = <&clock_gcc RPM_QDSS_CLK>,
<&clock_gcc RPM_QDSS_A_CLK>;
clock-names = "apb_pclk", "core_a_clk";
@@ -161,6 +165,14 @@
<&funnel_merg_in_funnel_in0>;
};
};
+ port@3 {
+ reg = <6>;
+ funnel_in0_in_funnel_qatb: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_qatb_out_funnel_in0>;
+ };
+ };
port@4 {
reg = <7>;
funnel_in0_in_stm: endpoint {
@@ -191,4 +203,294 @@
};
};
};
+
+ cti0: cti@6010000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6010000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti0";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti1: cti@6011000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6011000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti1";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti2: cti@6012000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6012000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti2";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti3: cti@6013000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6013000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti3";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti4: cti@6014000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6014000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti4";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti5: cti@6015000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6015000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti5";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti6: cti@6016000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6016000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti6";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti7: cti@6017000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6017000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti7";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti8: cti@6018000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6018000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti8";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti9: cti@6019000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x6019000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti9";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti10: cti@601a000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x601a000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti10";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti11: cti@601b000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x601b000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti11";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti12: cti@601c000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x601c000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti12";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti13: cti@601d000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x601d000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti13";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti14: cti@601e000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x601e000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti14";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ cti15: cti@601f000 {
+ compatible = "arm,coresight-cti";
+ reg = <0x601f000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti15";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+ };
+
+ funnel_qatb: funnel@6005000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6005000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-qatb";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "core_a_clk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_qatb_out_funnel_in0: endpoint {
+ remote-endpoint =
+ <&funnel_in0_in_funnel_qatb>;
+ };
+ };
+ port@1 {
+ reg = <0>;
+ funnel_qatb_in_tpda: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpda_out_funnel_qatb>;
+ };
+ };
+ };
+ };
+
+ tpda: tpda@6004000 {
+ compatible = "qcom,coresight-tpda";
+ reg = <0x6004000 0x1000>;
+ reg-names = "tpda-base";
+
+ coresight-name = "coresight-tpda";
+
+ qcom,tpda-atid = <65>;
+ qcom,bc-elem-size = <7 32>,
+ <9 32>;
+ qcom,tc-elem-size = <3 32>,
+ <6 32>,
+ <9 32>;
+ qcom,dsb-elem-size = <7 32>,
+ <9 32>;
+ qcom,cmb-elem-size = <3 32>,
+ <4 32>,
+ <5 32>,
+ <9 64>;
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ tpda_out_funnel_qatb: endpoint {
+ remote-endpoint =
+ <&funnel_qatb_in_tpda>;
+ };
+ };
+ port@2 {
+ reg = <5>;
+ tpda_in_tpdm_dcc: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_dcc_out_tpda>;
+ };
+ };
+ };
+ };
+
+ tpdm_dcc: tpdm@7054000 {
+ compatible = "qcom,coresight-tpdm";
+ reg = <0x7054000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-dcc";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>,
+ <&clock_gcc RPM_QDSS_A_CLK>;
+ clock-names = "core_clk", "core_a_clk";
+
+ port{
+ tpdm_dcc_out_tpda: endpoint {
+ remote-endpoint = <&tpda_in_tpdm_dcc>;
+ };
+ };
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 4765a8cb7c79..67748d6683c0 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -252,6 +252,18 @@
status = "ok";
};
+ wdog: qcom,wdt@17817000 {
+ status = "disabled";
+ compatible = "qcom,msm-watchdog";
+ reg = <0x17817000 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;
+ };
+
qcom,sps {
compatible = "qcom,msm_sps_4k";
qcom,pipe-attr-ee;
@@ -380,6 +392,16 @@
qcom,mpu-enabled;
};
+ dcc: dcc@10b3000 {
+ compatible = "qcom,dcc";
+ reg = <0x10b3000 0x1000>,
+ <0x10b4000 0x800>;
+ reg-names = "dcc-base", "dcc-ram-base";
+
+ clocks = <&clock_gcc RPM_QDSS_CLK>;
+ clock-names = "dcc_clk";
+ };
+
qcom,glink-smem-native-xprt-modem@86000000 {
compatible = "qcom,glink-smem-native-xprt";
reg = <0x86000000 0x200000>,
diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig
index 2b35b0f12787..103b90c7d6fc 100644
--- a/arch/arm/configs/msmfalcon_defconfig
+++ b/arch/arm/configs/msmfalcon_defconfig
@@ -416,6 +416,9 @@ CONFIG_GPIO_USB_DETECT=y
CONFIG_USB_BAM=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_ARM_SMMU=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
CONFIG_QCOM_COMMON_LOG=y
CONFIG_MSM_SMEM=y
CONFIG_QPNP_HAPTIC=y
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 598323a1842e..e683d147816c 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -190,6 +190,13 @@ static int __init parse_cluster(struct device_node *cluster, int depth)
return 0;
}
+static DEFINE_PER_CPU(unsigned long, cpu_efficiency) = SCHED_CAPACITY_SCALE;
+
+unsigned long arch_get_cpu_efficiency(int cpu)
+{
+ return per_cpu(cpu_efficiency, cpu);
+}
+
#ifdef CONFIG_OF
struct cpu_efficiency {
const char *compatible;
@@ -266,6 +273,7 @@ static int __init parse_dt_topology(void)
for_each_possible_cpu(cpu) {
const u32 *rate;
int len;
+ u32 efficiency;
/* too early to use cpu->of_node */
cn = of_get_cpu_node(cpu, NULL);
@@ -274,12 +282,26 @@ static int __init parse_dt_topology(void)
continue;
}
- for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
- if (of_device_is_compatible(cn, cpu_eff->compatible))
- break;
+ /*
+ * The CPU efficiency value passed from the device tree
+ * overrides the value defined in the table_efficiency[]
+ */
+ if (of_property_read_u32(cn, "efficiency", &efficiency) < 0) {
+
+ for (cpu_eff = table_efficiency;
+ cpu_eff->compatible; cpu_eff++)
- if (cpu_eff->compatible == NULL)
- continue;
+ if (of_device_is_compatible(cn,
+ cpu_eff->compatible))
+ break;
+
+ if (cpu_eff->compatible == NULL)
+ continue;
+
+ efficiency = cpu_eff->efficiency;
+ }
+
+ per_cpu(cpu_efficiency, cpu) = efficiency;
rate = of_get_property(cn, "clock-frequency", &len);
if (!rate || len != 4) {
@@ -288,7 +310,7 @@ static int __init parse_dt_topology(void)
continue;
}
- capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency;
+ capacity = ((be32_to_cpup(rate)) >> 20) * efficiency;
/* Save min capacity of the system */
if (capacity < min_capacity)
diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c
index 68274765a6c1..0d733f49f184 100644
--- a/drivers/clk/msm/clock-osm.c
+++ b/drivers/clk/msm/clock-osm.c
@@ -460,7 +460,7 @@ static int clk_osm_set_rate(struct clk *c, unsigned long rate)
}
pr_debug("rate: %lu --> index %d\n", rate, index);
- if (cpuclk->llm_sw_overr) {
+ if (cpuclk->llm_sw_overr[0]) {
clk_osm_write_reg(cpuclk, cpuclk->llm_sw_overr[0],
LLM_SW_OVERRIDE_REG);
clk_osm_write_reg(cpuclk, cpuclk->llm_sw_overr[1],
@@ -471,7 +471,7 @@ static int clk_osm_set_rate(struct clk *c, unsigned long rate)
/* Choose index and send request to OSM hardware */
clk_osm_write_reg(cpuclk, index, DCVS_PERF_STATE_DESIRED_REG);
- if (cpuclk->llm_sw_overr) {
+ if (cpuclk->llm_sw_overr[0]) {
udelay(1);
clk_osm_write_reg(cpuclk, cpuclk->llm_sw_overr[2],
LLM_SW_OVERRIDE_REG);
@@ -1882,8 +1882,8 @@ static void clk_osm_apm_vc_setup(struct clk_osm *c)
}
scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(72),
c->apm_crossover_vc);
- clk_osm_write_reg(c, c->apm_threshold_vc,
- SEQ_REG(15));
+ scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(15),
+ c->apm_threshold_vc);
scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(31),
c->apm_threshold_vc != 0 ?
c->apm_threshold_vc - 1 : 0xff);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 1f2178848664..0fcc0c3b0d49 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1913,20 +1913,38 @@ void kgsl_idle_check(struct work_struct *work)
{
struct kgsl_device *device = container_of(work, struct kgsl_device,
idle_check_ws);
+ int ret = 0;
+ unsigned int requested_state;
+
WARN_ON(device == NULL);
if (device == NULL)
return;
mutex_lock(&device->mutex);
+ requested_state = device->requested_state;
+
if (device->state == KGSL_STATE_ACTIVE
|| device->state == KGSL_STATE_NAP) {
- if (!atomic_read(&device->active_cnt))
- kgsl_pwrctrl_change_state(device,
+ if (!atomic_read(&device->active_cnt)) {
+ ret = kgsl_pwrctrl_change_state(device,
device->requested_state);
+ if (ret == -EBUSY) {
+ /*
+ * If the GPU is currently busy, restore
+ * the requested state and reschedule
+ * idle work.
+ */
+ kgsl_pwrctrl_request_state(device,
+ requested_state);
+ kgsl_schedule_work(&device->idle_check_ws);
+ }
+ }
+
+ if (!ret)
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
- kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
if (device->state == KGSL_STATE_ACTIVE)
mod_timer(&device->idle_timer,
jiffies +
diff --git a/drivers/hwtracing/coresight/coresight-csr.c b/drivers/hwtracing/coresight/coresight-csr.c
index dfb2922b6f33..3c18d686091a 100644
--- a/drivers/hwtracing/coresight/coresight-csr.c
+++ b/drivers/hwtracing/coresight/coresight-csr.c
@@ -191,8 +191,6 @@ static int csr_probe(struct platform_device *pdev)
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
- /* Store the driver data pointer for use in exported functions */
- csrdrvdata = drvdata;
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
@@ -220,6 +218,8 @@ static int csr_probe(struct platform_device *pdev)
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
+ /* Store the driver data pointer for use in exported functions */
+ csrdrvdata = drvdata;
dev_info(dev, "CSR initialized\n");
return 0;
}
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index a234d61802ce..fb2f27299417 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -774,8 +774,6 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
- /* Store the driver data pointer for use in exported functions */
- stmdrvdata = drvdata;
drvdata->dev = &adev->dev;
dev_set_drvdata(dev, drvdata);
@@ -846,6 +844,8 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
if (boot_enable)
coresight_enable(drvdata->csdev);
+ /* Store the driver data pointer for use in exported functions */
+ stmdrvdata = drvdata;
return 0;
err:
coresight_unregister(drvdata->csdev);
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
index 4c341ffb6094..9d61eb110e2f 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
@@ -347,7 +347,7 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
ssize_t retval;
- unsigned char tmpbuf[count + 1];
+ unsigned char *tmpbuf;
struct rmidev_data *dev_data = filp->private_data;
if (IS_ERR(dev_data)) {
@@ -361,6 +361,10 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
if (count > (REG_ADDR_LIMIT - *f_pos))
count = REG_ADDR_LIMIT - *f_pos;
+ tmpbuf = kzalloc(count + 1, GFP_KERNEL);
+ if (!tmpbuf)
+ return -ENOMEM;
+
mutex_lock(&(dev_data->file_mutex));
retval = synaptics_rmi4_reg_read(rmidev->rmi4_data,
@@ -377,7 +381,7 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
clean_up:
mutex_unlock(&(dev_data->file_mutex));
-
+ kfree(tmpbuf);
return retval;
}
@@ -393,7 +397,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
ssize_t retval;
- unsigned char tmpbuf[count + 1];
+ unsigned char *tmpbuf;
struct rmidev_data *dev_data = filp->private_data;
if (IS_ERR(dev_data)) {
@@ -407,9 +411,14 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf,
if (count > (REG_ADDR_LIMIT - *f_pos))
count = REG_ADDR_LIMIT - *f_pos;
- if (copy_from_user(tmpbuf, buf, count))
- return -EFAULT;
+ tmpbuf = kzalloc(count + 1, GFP_KERNEL);
+ if (!tmpbuf)
+ return -ENOMEM;
+ if (copy_from_user(tmpbuf, buf, count)) {
+ kfree(tmpbuf);
+ return -EFAULT;
+ }
mutex_lock(&(dev_data->file_mutex));
retval = synaptics_rmi4_reg_write(rmidev->rmi4_data,
@@ -420,7 +429,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf,
*f_pos += retval;
mutex_unlock(&(dev_data->file_mutex));
-
+ kfree(tmpbuf);
return retval;
}
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 0b3e4e1fcf04..bf3973888573 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
@@ -101,11 +101,6 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl,
i2c_tbl = a_ctrl->i2c_reg_tbl;
for (i = 0; i < size; i++) {
- /* check that the index into i2c_tbl cannot grow larger that
- the allocated size of i2c_tbl */
- if ((a_ctrl->total_steps + 1) < (a_ctrl->i2c_tbl_index))
- break;
-
if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) {
value = (next_lens_position <<
write_arr[i].data_shift) |
@@ -119,6 +114,11 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl,
i2c_byte2 = value & 0xFF;
CDBG("byte1:0x%x, byte2:0x%x\n",
i2c_byte1, i2c_byte2);
+ if (a_ctrl->i2c_tbl_index >
+ a_ctrl->total_steps) {
+ pr_err("failed:i2c table index out of bound\n");
+ break;
+ }
i2c_tbl[a_ctrl->i2c_tbl_index].
reg_addr = i2c_byte1;
i2c_tbl[a_ctrl->i2c_tbl_index].
@@ -139,6 +139,10 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl,
i2c_byte2 = (hw_dword & write_arr[i].hw_mask) >>
write_arr[i].hw_shift;
}
+ if (a_ctrl->i2c_tbl_index > a_ctrl->total_steps) {
+ pr_err("failed: i2c table index out of bound\n");
+ break;
+ }
CDBG("i2c_byte1:0x%x, i2c_byte2:0x%x\n", i2c_byte1, i2c_byte2);
i2c_tbl[a_ctrl->i2c_tbl_index].reg_addr = i2c_byte1;
i2c_tbl[a_ctrl->i2c_tbl_index].reg_data = i2c_byte2;
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index ce115c98a72f..d3e420f1b26b 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1583,6 +1583,32 @@ static const struct file_operations fops_fw_capabilities = {
.llseek = seq_lseek,
};
+/*---------FW version------------*/
+static int wil_fw_version_debugfs_show(struct seq_file *s, void *data)
+{
+ struct wil6210_priv *wil = s->private;
+
+ if (wil->fw_version[0])
+ seq_printf(s, "%s\n", wil->fw_version);
+ else
+ seq_puts(s, "N/A\n");
+
+ return 0;
+}
+
+static int wil_fw_version_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wil_fw_version_debugfs_show,
+ inode->i_private);
+}
+
+static const struct file_operations fops_fw_version = {
+ .open = wil_fw_version_seq_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
/*----------------*/
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
struct dentry *dbg)
@@ -1634,6 +1660,7 @@ static const struct {
{"led_cfg", S_IRUGO | S_IWUSR, &fops_led_cfg},
{"led_blink_time", S_IRUGO | S_IWUSR, &fops_led_blink_time},
{"fw_capabilities", S_IRUGO, &fops_fw_capabilities},
+ {"fw_version", S_IRUGO, &fops_fw_version},
};
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1674,7 +1701,6 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil,
static const struct dbg_off dbg_wil_off[] = {
WIL_FIELD(privacy, S_IRUGO, doff_u32),
WIL_FIELD(status[0], S_IRUGO | S_IWUSR, doff_ulong),
- WIL_FIELD(fw_version, S_IRUGO, doff_u32),
WIL_FIELD(hw_version, S_IRUGO, doff_x32),
WIL_FIELD(recovery_count, S_IRUGO, doff_u32),
WIL_FIELD(ap_isolate, S_IRUGO, doff_u32),
diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h
index c3191c61832c..2f2b910501ba 100644
--- a/drivers/net/wireless/ath/wil6210/fw.h
+++ b/drivers/net/wireless/ath/wil6210/fw.h
@@ -102,6 +102,9 @@ struct wil_fw_record_verify { /* type == wil_fw_verify */
/* file header
* First record of every file
*/
+/* the FW version prefix in the comment */
+#define WIL_FW_VERSION_PREFIX "FW version: "
+#define WIL_FW_VERSION_PREFIX_LEN (sizeof(WIL_FW_VERSION_PREFIX) - 1)
struct wil_fw_record_file_header {
__le32 signature ; /* Wilocity signature */
__le32 reserved;
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index 3860238840ba..8f40eb301924 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -223,6 +223,13 @@ static int fw_handle_file_header(struct wil6210_priv *wil, const void *data,
wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, d->comment,
sizeof(d->comment), true);
+ if (!memcmp(d->comment, WIL_FW_VERSION_PREFIX,
+ WIL_FW_VERSION_PREFIX_LEN))
+ memcpy(wil->fw_version,
+ d->comment + WIL_FW_VERSION_PREFIX_LEN,
+ min(sizeof(d->comment) - WIL_FW_VERSION_PREFIX_LEN,
+ sizeof(wil->fw_version) - 1));
+
return 0;
}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 88dfb93d0f3d..a509841c3187 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -892,6 +892,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
WIL_FW2_NAME);
wil_halt_cpu(wil);
+ memset(wil->fw_version, 0, sizeof(wil->fw_version));
/* Loading f/w from the file */
rc = wil_request_firmware(wil, WIL_FW_NAME, true);
if (rc)
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 81a4c6a684f5..f4fca9d4eedf 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -222,6 +222,8 @@ int wil_if_add(struct wil6210_priv *wil)
wil_dbg_misc(wil, "entered");
+ strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
+
rc = wiphy_register(wiphy);
if (rc < 0) {
wil_err(wil, "failed to register wiphy, err %d\n", rc);
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 1e0536adb6e7..ce33e919d321 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -17,6 +17,7 @@
#ifndef __WIL6210_H__
#define __WIL6210_H__
+#include <linux/etherdevice.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/cfg80211.h>
@@ -579,7 +580,7 @@ struct wil6210_priv {
struct wireless_dev *wdev;
void __iomem *csr;
DECLARE_BITMAP(status, wil_status_last);
- u32 fw_version;
+ u8 fw_version[ETHTOOL_FWVERS_LEN];
u32 hw_version;
const char *hw_name;
DECLARE_BITMAP(hw_capabilities, hw_capability_last);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 0c5db9584159..6ec3ddc5b6f1 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -312,14 +312,14 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
struct wireless_dev *wdev = wil->wdev;
struct wmi_ready_event *evt = d;
- wil->fw_version = le32_to_cpu(evt->sw_version);
wil->n_mids = evt->numof_additional_mids;
- wil_info(wil, "FW ver. %d; MAC %pM; %d MID's\n", wil->fw_version,
+ wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
+ wil->fw_version, le32_to_cpu(evt->sw_version),
evt->mac, wil->n_mids);
/* ignore MAC address, we already have it from the boot loader */
- snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
- "%d", wil->fw_version);
+ strlcpy(wdev->wiphy->fw_version, wil->fw_version,
+ sizeof(wdev->wiphy->fw_version));
wil_set_recovery_state(wil, fw_recovery_idle);
set_bit(wil_status_fwready, wil->status);
diff --git a/drivers/power/qcom-charger/battery_current_limit.c b/drivers/power/qcom-charger/battery_current_limit.c
index 2bda5ce1a8c4..951d0544efa0 100644
--- a/drivers/power/qcom-charger/battery_current_limit.c
+++ b/drivers/power/qcom-charger/battery_current_limit.c
@@ -174,6 +174,9 @@ struct bcl_context {
struct qpnp_adc_tm_btm_param btm_vph_adc_param;
/* Low temp min freq limit requested by thermal */
uint32_t thermal_freq_limit;
+ /* state of charge notifier */
+ struct notifier_block psy_nb;
+ struct work_struct soc_mitig_work;
/* BCL Peripheral monitor parameters */
struct bcl_threshold ibat_high_thresh;
@@ -204,8 +207,6 @@ static DEFINE_MUTEX(bcl_hotplug_mutex);
static bool bcl_hotplug_enabled;
static uint32_t battery_soc_val = 100;
static uint32_t soc_low_threshold;
-static struct power_supply *bcl_psy;
-static struct power_supply_desc bcl_psy_des;
static const char bcl_psy_name[] = "bcl";
static void bcl_handle_hotplug(struct work_struct *work)
@@ -277,22 +278,34 @@ static void update_cpu_freq(void)
trace_bcl_sw_mitigation_event("End Frequency Mitigation");
}
-static void power_supply_callback(struct power_supply *psy)
+static void soc_mitigate(struct work_struct *work)
{
- static struct power_supply *bms_psy;
+ if (bcl_hotplug_enabled)
+ queue_work(gbcl->bcl_hotplug_wq, &bcl_hotplug_work);
+ update_cpu_freq();
+}
+
+static int power_supply_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct power_supply *psy = data;
+ static struct power_supply *batt_psy;
union power_supply_propval ret = {0,};
int battery_percentage;
enum bcl_threshold_state prev_soc_state;
if (gbcl->bcl_mode != BCL_DEVICE_ENABLED) {
pr_debug("BCL is not enabled\n");
- return;
+ return NOTIFY_OK;
}
- if (!bms_psy)
- bms_psy = power_supply_get_by_name("bms");
- if (bms_psy) {
- battery_percentage = power_supply_get_property(bms_psy,
+ if (strcmp(psy->desc->name, "battery"))
+ return NOTIFY_OK;
+
+ if (!batt_psy)
+ batt_psy = power_supply_get_by_name("battery");
+ if (batt_psy) {
+ battery_percentage = power_supply_get_property(batt_psy,
POWER_SUPPLY_PROP_CAPACITY, &ret);
battery_percentage = ret.intval;
battery_soc_val = battery_percentage;
@@ -302,15 +315,14 @@ static void power_supply_callback(struct power_supply *psy)
bcl_soc_state = (battery_soc_val <= soc_low_threshold) ?
BCL_LOW_THRESHOLD : BCL_HIGH_THRESHOLD;
if (bcl_soc_state == prev_soc_state)
- return;
+ return NOTIFY_OK;
trace_bcl_sw_mitigation_event(
(bcl_soc_state == BCL_LOW_THRESHOLD)
? "trigger SoC mitigation"
: "clear SoC mitigation");
- if (bcl_hotplug_enabled)
- queue_work(gbcl->bcl_hotplug_wq, &bcl_hotplug_work);
- update_cpu_freq();
+ schedule_work(&gbcl->soc_mitig_work);
}
+ return NOTIFY_OK;
}
static int bcl_get_battery_voltage(int *vbatt_mv)
@@ -624,7 +636,6 @@ static void bcl_periph_vbat_notify(enum bcl_trip_type type, int trip_temp,
static void bcl_periph_mode_set(enum bcl_device_mode mode)
{
int ret = 0;
- struct power_supply_config bcl_psy_cfg = {};
if (mode == BCL_DEVICE_ENABLED) {
/*
@@ -632,15 +643,11 @@ static void bcl_periph_mode_set(enum bcl_device_mode mode)
* power state changes. Make sure we read the current SoC
* and mitigate.
*/
- power_supply_callback(bcl_psy);
- bcl_psy_cfg.num_supplicants = 0;
- bcl_psy_cfg.drv_data = gbcl;
-
- bcl_psy = power_supply_register(gbcl->dev, &bcl_psy_des,
- &bcl_psy_cfg);
- if (IS_ERR(bcl_psy)) {
- pr_err("Unable to register bcl_psy rc = %ld\n",
- PTR_ERR(bcl_psy));
+ power_supply_callback(&gbcl->psy_nb, 1, gbcl);
+ ret = power_supply_reg_notifier(&gbcl->psy_nb);
+ if (ret < 0) {
+ pr_err("Unable to register soc notifier rc = %d\n",
+ ret);
return;
}
ret = msm_bcl_set_threshold(BCL_PARAM_CURRENT, BCL_HIGH_TRIP,
@@ -678,7 +685,7 @@ static void bcl_periph_mode_set(enum bcl_device_mode mode)
}
gbcl->btm_mode = BCL_VPH_MONITOR_MODE;
} else {
- power_supply_unregister(bcl_psy);
+ power_supply_unreg_notifier(&gbcl->psy_nb);
ret = msm_bcl_disable();
if (ret) {
pr_err("Error disabling BCL\n");
@@ -1627,19 +1634,6 @@ btm_probe_exit:
return ret;
}
-static int bcl_battery_get_property(struct power_supply *psy,
- enum power_supply_property prop,
- union power_supply_propval *val)
-{
- return 0;
-}
-static int bcl_battery_set_property(struct power_supply *psy,
- enum power_supply_property prop,
- const union power_supply_propval *val)
-{
- return 0;
-}
-
static uint32_t get_mask_from_core_handle(struct platform_device *pdev,
const char *key)
{
@@ -1725,12 +1719,8 @@ static int bcl_probe(struct platform_device *pdev)
pr_err("Cannot create bcl sysfs\n");
return ret;
}
- bcl_psy_des.name = bcl_psy_name;
- bcl_psy_des.type = POWER_SUPPLY_TYPE_BMS;
- bcl_psy_des.get_property = bcl_battery_get_property;
- bcl_psy_des.set_property = bcl_battery_set_property;
- bcl_psy_des.num_properties = 0;
- bcl_psy_des.external_power_changed = power_supply_callback;
+ INIT_WORK(&bcl->soc_mitig_work, soc_mitigate);
+ bcl->psy_nb.notifier_call = power_supply_callback;
bcl->bcl_hotplug_wq = alloc_workqueue("bcl_hotplug_wq", WQ_HIGHPRI, 0);
if (!bcl->bcl_hotplug_wq) {
pr_err("Workqueue alloc failed\n");
@@ -1773,6 +1763,7 @@ static int bcl_remove(struct platform_device *pdev)
int cpu;
/* De-register KTM handle */
+ power_supply_unreg_notifier(&gbcl->psy_nb);
if (gbcl->hotplug_handle)
devmgr_unregister_mitigation_client(&pdev->dev,
gbcl->hotplug_handle);
diff --git a/drivers/soc/qcom/jtag-fuse.c b/drivers/soc/qcom/jtag-fuse.c
index 0b05ce9a22bb..0f347723e378 100644
--- a/drivers/soc/qcom/jtag-fuse.c
+++ b/drivers/soc/qcom/jtag-fuse.c
@@ -152,8 +152,6 @@ static int jtag_fuse_probe(struct platform_device *pdev)
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
- /* Store the driver data pointer for use in exported functions */
- fusedrvdata = drvdata;
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
@@ -174,6 +172,8 @@ static int jtag_fuse_probe(struct platform_device *pdev)
if (!drvdata->base)
return -ENOMEM;
+ /* Store the driver data pointer for use in exported functions */
+ fusedrvdata = drvdata;
dev_info(dev, "JTag Fuse initialized\n");
return 0;
}
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h
index c2fa3ecb0dce..146efefde2a1 100644
--- a/include/linux/percpu-rwsem.h
+++ b/include/linux/percpu-rwsem.h
@@ -10,30 +10,96 @@
struct percpu_rw_semaphore {
struct rcu_sync rss;
- unsigned int __percpu *fast_read_ctr;
+ unsigned int __percpu *read_count;
struct rw_semaphore rw_sem;
- atomic_t slow_read_ctr;
- wait_queue_head_t write_waitq;
+ wait_queue_head_t writer;
+ int readers_block;
};
-extern void percpu_down_read(struct percpu_rw_semaphore *);
-extern int percpu_down_read_trylock(struct percpu_rw_semaphore *);
-extern void percpu_up_read(struct percpu_rw_semaphore *);
+extern int __percpu_down_read(struct percpu_rw_semaphore *, int);
+extern void __percpu_up_read(struct percpu_rw_semaphore *);
+
+static inline void percpu_down_read(struct percpu_rw_semaphore *sem)
+{
+ might_sleep();
+
+ rwsem_acquire_read(&sem->rw_sem.dep_map, 0, 0, _RET_IP_);
+
+ preempt_disable();
+ /*
+ * We are in an RCU-sched read-side critical section, so the writer
+ * cannot both change sem->state from readers_fast and start checking
+ * counters while we are here. So if we see !sem->state, we know that
+ * the writer won't be checking until we're past the preempt_enable()
+ * and that one the synchronize_sched() is done, the writer will see
+ * anything we did within this RCU-sched read-size critical section.
+ */
+ __this_cpu_inc(*sem->read_count);
+ if (unlikely(!rcu_sync_is_idle(&sem->rss)))
+ __percpu_down_read(sem, false); /* Unconditional memory barrier */
+ preempt_enable();
+ /*
+ * The barrier() from preempt_enable() prevents the compiler from
+ * bleeding the critical section out.
+ */
+}
+
+static inline int percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
+{
+ int ret = 1;
+
+ preempt_disable();
+ /*
+ * Same as in percpu_down_read().
+ */
+ __this_cpu_inc(*sem->read_count);
+ if (unlikely(!rcu_sync_is_idle(&sem->rss)))
+ ret = __percpu_down_read(sem, true); /* Unconditional memory barrier */
+ preempt_enable();
+ /*
+ * The barrier() from preempt_enable() prevents the compiler from
+ * bleeding the critical section out.
+ */
+
+ if (ret)
+ rwsem_acquire_read(&sem->rw_sem.dep_map, 0, 1, _RET_IP_);
+
+ return ret;
+}
+
+static inline void percpu_up_read(struct percpu_rw_semaphore *sem)
+{
+ /*
+ * The barrier() in preempt_disable() prevents the compiler from
+ * bleeding the critical section out.
+ */
+ preempt_disable();
+ /*
+ * Same as in percpu_down_read().
+ */
+ if (likely(rcu_sync_is_idle(&sem->rss)))
+ __this_cpu_dec(*sem->read_count);
+ else
+ __percpu_up_read(sem); /* Unconditional memory barrier */
+ preempt_enable();
+
+ rwsem_release(&sem->rw_sem.dep_map, 1, _RET_IP_);
+}
extern void percpu_down_write(struct percpu_rw_semaphore *);
extern void percpu_up_write(struct percpu_rw_semaphore *);
extern int __percpu_init_rwsem(struct percpu_rw_semaphore *,
const char *, struct lock_class_key *);
+
extern void percpu_free_rwsem(struct percpu_rw_semaphore *);
-#define percpu_init_rwsem(brw) \
+#define percpu_init_rwsem(sem) \
({ \
static struct lock_class_key rwsem_key; \
- __percpu_init_rwsem(brw, #brw, &rwsem_key); \
+ __percpu_init_rwsem(sem, #sem, &rwsem_key); \
})
-
#define percpu_rwsem_is_held(sem) lockdep_is_held(&(sem)->rw_sem)
static inline void percpu_rwsem_release(struct percpu_rw_semaphore *sem,
diff --git a/include/linux/rcu_sync.h b/include/linux/rcu_sync.h
index a63a33e6196e..ece7ed9a4a70 100644
--- a/include/linux/rcu_sync.h
+++ b/include/linux/rcu_sync.h
@@ -59,6 +59,7 @@ static inline bool rcu_sync_is_idle(struct rcu_sync *rsp)
}
extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type);
+extern void rcu_sync_enter_start(struct rcu_sync *);
extern void rcu_sync_enter(struct rcu_sync *);
extern void rcu_sync_exit(struct rcu_sync *);
extern void rcu_sync_dtor(struct rcu_sync *);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index ad4a12371069..cc6c7d0a6758 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -5376,6 +5376,12 @@ int __init cgroup_init(void)
BUG_ON(cgroup_init_cftypes(NULL, cgroup_dfl_base_files));
BUG_ON(cgroup_init_cftypes(NULL, cgroup_legacy_base_files));
+ /*
+ * The latency of the synchronize_sched() is too high for cgroups,
+ * avoid it at the cost of forcing all readers into the slow path.
+ */
+ rcu_sync_enter_start(&cgroup_threadgroup_rwsem.rss);
+
mutex_lock(&cgroup_mutex);
/* Add init_css_set to the hash table */
diff --git a/kernel/fork.c b/kernel/fork.c
index c9eb86b646ab..e89d0bae6f20 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1375,7 +1375,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->real_start_time = ktime_get_boot_ns();
p->io_context = NULL;
p->audit_context = NULL;
- threadgroup_change_begin(current);
cgroup_fork(p);
#ifdef CONFIG_NUMA
p->mempolicy = mpol_dup(p->mempolicy);
@@ -1527,6 +1526,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
INIT_LIST_HEAD(&p->thread_group);
p->task_works = NULL;
+ threadgroup_change_begin(current);
/*
* Ensure that the cgroup subsystem policies allow the new process to be
* forked. It should be noted the the new process's css_set can be changed
@@ -1627,6 +1627,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
bad_fork_cancel_cgroup:
cgroup_cancel_fork(p, cgrp_ss_priv);
bad_fork_free_pid:
+ threadgroup_change_end(current);
if (pid != &init_struct_pid)
free_pid(pid);
bad_fork_cleanup_io:
@@ -1657,7 +1658,6 @@ bad_fork_cleanup_policy:
mpol_put(p->mempolicy);
bad_fork_cleanup_threadgroup_lock:
#endif
- threadgroup_change_end(current);
delayacct_tsk_free(p);
bad_fork_cleanup_count:
atomic_dec(&p->cred->user->processes);
diff --git a/kernel/locking/percpu-rwsem.c b/kernel/locking/percpu-rwsem.c
index f231e0bb311c..ce182599cf2e 100644
--- a/kernel/locking/percpu-rwsem.c
+++ b/kernel/locking/percpu-rwsem.c
@@ -8,151 +8,186 @@
#include <linux/sched.h>
#include <linux/errno.h>
-int __percpu_init_rwsem(struct percpu_rw_semaphore *brw,
+int __percpu_init_rwsem(struct percpu_rw_semaphore *sem,
const char *name, struct lock_class_key *rwsem_key)
{
- brw->fast_read_ctr = alloc_percpu(int);
- if (unlikely(!brw->fast_read_ctr))
+ sem->read_count = alloc_percpu(int);
+ if (unlikely(!sem->read_count))
return -ENOMEM;
/* ->rw_sem represents the whole percpu_rw_semaphore for lockdep */
- __init_rwsem(&brw->rw_sem, name, rwsem_key);
- rcu_sync_init(&brw->rss, RCU_SCHED_SYNC);
- atomic_set(&brw->slow_read_ctr, 0);
- init_waitqueue_head(&brw->write_waitq);
+ rcu_sync_init(&sem->rss, RCU_SCHED_SYNC);
+ __init_rwsem(&sem->rw_sem, name, rwsem_key);
+ init_waitqueue_head(&sem->writer);
+ sem->readers_block = 0;
return 0;
}
EXPORT_SYMBOL_GPL(__percpu_init_rwsem);
-void percpu_free_rwsem(struct percpu_rw_semaphore *brw)
+void percpu_free_rwsem(struct percpu_rw_semaphore *sem)
{
/*
* XXX: temporary kludge. The error path in alloc_super()
* assumes that percpu_free_rwsem() is safe after kzalloc().
*/
- if (!brw->fast_read_ctr)
+ if (!sem->read_count)
return;
- rcu_sync_dtor(&brw->rss);
- free_percpu(brw->fast_read_ctr);
- brw->fast_read_ctr = NULL; /* catch use after free bugs */
+ rcu_sync_dtor(&sem->rss);
+ free_percpu(sem->read_count);
+ sem->read_count = NULL; /* catch use after free bugs */
}
+EXPORT_SYMBOL_GPL(percpu_free_rwsem);
-/*
- * This is the fast-path for down_read/up_read. If it succeeds we rely
- * on the barriers provided by rcu_sync_enter/exit; see the comments in
- * percpu_down_write() and percpu_up_write().
- *
- * If this helper fails the callers rely on the normal rw_semaphore and
- * atomic_dec_and_test(), so in this case we have the necessary barriers.
- */
-static bool update_fast_ctr(struct percpu_rw_semaphore *brw, unsigned int val)
+int __percpu_down_read(struct percpu_rw_semaphore *sem, int try)
{
- bool success;
+ /*
+ * Due to having preemption disabled the decrement happens on
+ * the same CPU as the increment, avoiding the
+ * increment-on-one-CPU-and-decrement-on-another problem.
+ *
+ * If the reader misses the writer's assignment of readers_block, then
+ * the writer is guaranteed to see the reader's increment.
+ *
+ * Conversely, any readers that increment their sem->read_count after
+ * the writer looks are guaranteed to see the readers_block value,
+ * which in turn means that they are guaranteed to immediately
+ * decrement their sem->read_count, so that it doesn't matter that the
+ * writer missed them.
+ */
- preempt_disable();
- success = rcu_sync_is_idle(&brw->rss);
- if (likely(success))
- __this_cpu_add(*brw->fast_read_ctr, val);
- preempt_enable();
+ smp_mb(); /* A matches D */
- return success;
-}
+ /*
+ * If !readers_block the critical section starts here, matched by the
+ * release in percpu_up_write().
+ */
+ if (likely(!smp_load_acquire(&sem->readers_block)))
+ return 1;
-/*
- * Like the normal down_read() this is not recursive, the writer can
- * come after the first percpu_down_read() and create the deadlock.
- *
- * Note: returns with lock_is_held(brw->rw_sem) == T for lockdep,
- * percpu_up_read() does rwsem_release(). This pairs with the usage
- * of ->rw_sem in percpu_down/up_write().
- */
-void percpu_down_read(struct percpu_rw_semaphore *brw)
-{
- might_sleep();
- rwsem_acquire_read(&brw->rw_sem.dep_map, 0, 0, _RET_IP_);
+ /*
+ * Per the above comment; we still have preemption disabled and
+ * will thus decrement on the same CPU as we incremented.
+ */
+ __percpu_up_read(sem);
- if (likely(update_fast_ctr(brw, +1)))
- return;
+ if (try)
+ return 0;
- /* Avoid rwsem_acquire_read() and rwsem_release() */
- __down_read(&brw->rw_sem);
- atomic_inc(&brw->slow_read_ctr);
- __up_read(&brw->rw_sem);
-}
-EXPORT_SYMBOL_GPL(percpu_down_read);
+ /*
+ * We either call schedule() in the wait, or we'll fall through
+ * and reschedule on the preempt_enable() in percpu_down_read().
+ */
+ preempt_enable_no_resched();
-int percpu_down_read_trylock(struct percpu_rw_semaphore *brw)
-{
- if (unlikely(!update_fast_ctr(brw, +1))) {
- if (!__down_read_trylock(&brw->rw_sem))
- return 0;
- atomic_inc(&brw->slow_read_ctr);
- __up_read(&brw->rw_sem);
- }
-
- rwsem_acquire_read(&brw->rw_sem.dep_map, 0, 1, _RET_IP_);
+ /*
+ * Avoid lockdep for the down/up_read() we already have them.
+ */
+ __down_read(&sem->rw_sem);
+ this_cpu_inc(*sem->read_count);
+ __up_read(&sem->rw_sem);
+
+ preempt_disable();
return 1;
}
+EXPORT_SYMBOL_GPL(__percpu_down_read);
-void percpu_up_read(struct percpu_rw_semaphore *brw)
+void __percpu_up_read(struct percpu_rw_semaphore *sem)
{
- rwsem_release(&brw->rw_sem.dep_map, 1, _RET_IP_);
-
- if (likely(update_fast_ctr(brw, -1)))
- return;
+ smp_mb(); /* B matches C */
+ /*
+ * In other words, if they see our decrement (presumably to aggregate
+ * zero, as that is the only time it matters) they will also see our
+ * critical section.
+ */
+ __this_cpu_dec(*sem->read_count);
- /* false-positive is possible but harmless */
- if (atomic_dec_and_test(&brw->slow_read_ctr))
- wake_up_all(&brw->write_waitq);
+ /* Prod writer to recheck readers_active */
+ wake_up(&sem->writer);
}
-EXPORT_SYMBOL_GPL(percpu_up_read);
+EXPORT_SYMBOL_GPL(__percpu_up_read);
+
+#define per_cpu_sum(var) \
+({ \
+ typeof(var) __sum = 0; \
+ int cpu; \
+ compiletime_assert_atomic_type(__sum); \
+ for_each_possible_cpu(cpu) \
+ __sum += per_cpu(var, cpu); \
+ __sum; \
+})
-static int clear_fast_ctr(struct percpu_rw_semaphore *brw)
+/*
+ * Return true if the modular sum of the sem->read_count per-CPU variable is
+ * zero. If this sum is zero, then it is stable due to the fact that if any
+ * newly arriving readers increment a given counter, they will immediately
+ * decrement that same counter.
+ */
+static bool readers_active_check(struct percpu_rw_semaphore *sem)
{
- unsigned int sum = 0;
- int cpu;
+ if (per_cpu_sum(*sem->read_count) != 0)
+ return false;
+
+ /*
+ * If we observed the decrement; ensure we see the entire critical
+ * section.
+ */
- for_each_possible_cpu(cpu) {
- sum += per_cpu(*brw->fast_read_ctr, cpu);
- per_cpu(*brw->fast_read_ctr, cpu) = 0;
- }
+ smp_mb(); /* C matches B */
- return sum;
+ return true;
}
-void percpu_down_write(struct percpu_rw_semaphore *brw)
+void percpu_down_write(struct percpu_rw_semaphore *sem)
{
+ /* Notify readers to take the slow path. */
+ rcu_sync_enter(&sem->rss);
+
+ down_write(&sem->rw_sem);
+
/*
- * Make rcu_sync_is_idle() == F and thus disable the fast-path in
- * percpu_down_read() and percpu_up_read(), and wait for gp pass.
- *
- * The latter synchronises us with the preceding readers which used
- * the fast-past, so we can not miss the result of __this_cpu_add()
- * or anything else inside their criticial sections.
+ * Notify new readers to block; up until now, and thus throughout the
+ * longish rcu_sync_enter() above, new readers could still come in.
*/
- rcu_sync_enter(&brw->rss);
+ WRITE_ONCE(sem->readers_block, 1);
- /* exclude other writers, and block the new readers completely */
- down_write(&brw->rw_sem);
+ smp_mb(); /* D matches A */
- /* nobody can use fast_read_ctr, move its sum into slow_read_ctr */
- atomic_add(clear_fast_ctr(brw), &brw->slow_read_ctr);
+ /*
+ * If they don't see our writer of readers_block, then we are
+ * guaranteed to see their sem->read_count increment, and therefore
+ * will wait for them.
+ */
- /* wait for all readers to complete their percpu_up_read() */
- wait_event(brw->write_waitq, !atomic_read(&brw->slow_read_ctr));
+ /* Wait for all now active readers to complete. */
+ wait_event(sem->writer, readers_active_check(sem));
}
EXPORT_SYMBOL_GPL(percpu_down_write);
-void percpu_up_write(struct percpu_rw_semaphore *brw)
+void percpu_up_write(struct percpu_rw_semaphore *sem)
{
- /* release the lock, but the readers can't use the fast-path */
- up_write(&brw->rw_sem);
/*
- * Enable the fast-path in percpu_down_read() and percpu_up_read()
- * but only after another gp pass; this adds the necessary barrier
- * to ensure the reader can't miss the changes done by us.
+ * Signal the writer is done, no fast path yet.
+ *
+ * One reason that we cannot just immediately flip to readers_fast is
+ * that new readers might fail to see the results of this writer's
+ * critical section.
+ *
+ * Therefore we force it through the slow path which guarantees an
+ * acquire and thereby guarantees the critical section's consistency.
+ */
+ smp_store_release(&sem->readers_block, 0);
+
+ /*
+ * Release the write lock, this will allow readers back in the game.
+ */
+ up_write(&sem->rw_sem);
+
+ /*
+ * Once this completes (at least one RCU-sched grace period hence) the
+ * reader fast path will be available again. Safe to use outside the
+ * exclusive write lock because its counting.
*/
- rcu_sync_exit(&brw->rss);
+ rcu_sync_exit(&sem->rss);
}
EXPORT_SYMBOL_GPL(percpu_up_write);
diff --git a/kernel/rcu/sync.c b/kernel/rcu/sync.c
index be922c9f3d37..e358313a0d6c 100644
--- a/kernel/rcu/sync.c
+++ b/kernel/rcu/sync.c
@@ -83,6 +83,18 @@ void rcu_sync_init(struct rcu_sync *rsp, enum rcu_sync_type type)
}
/**
+ * Must be called after rcu_sync_init() and before first use.
+ *
+ * Ensures rcu_sync_is_idle() returns false and rcu_sync_{enter,exit}()
+ * pairs turn into NO-OPs.
+ */
+void rcu_sync_enter_start(struct rcu_sync *rsp)
+{
+ rsp->gp_count++;
+ rsp->gp_state = GP_PASSED;
+}
+
+/**
* rcu_sync_enter() - Force readers onto slowpath
* @rsp: Pointer to rcu_sync structure to use for synchronization
*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 4b5b0c3cef7a..4cdf967b67c1 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7812,6 +7812,7 @@ void __init sched_init_smp(void)
hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE);
update_cluster_topology();
+ init_sched_hmp_boost_policy();
init_hrtick();
@@ -7860,6 +7861,7 @@ void __init sched_init(void)
BUG_ON(num_possible_cpus() > BITS_PER_LONG);
+ sched_hmp_parse_dt();
init_clusters();
#ifdef CONFIG_FAIR_GROUP_SCHED
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index 61e352aeec00..1e7b4cd4e64c 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -17,6 +17,7 @@
#include <linux/cpufreq.h>
#include <linux/list_sort.h>
#include <linux/syscore_ops.h>
+#include <linux/of.h>
#include "sched.h"
#include "core_ctl.h"
@@ -225,6 +226,52 @@ fail:
return ret;
}
+/*
+ * It is possible that CPUs of the same micro architecture can have slight
+ * difference in the efficiency due to other factors like cache size. The
+ * BOOST_ON_BIG policy may not be optimial for such systems. The required
+ * boost policy can be specified via device tree to handle this.
+ */
+static int __read_mostly sched_boost_policy = SCHED_BOOST_NONE;
+
+/*
+ * This should be called after clusters are populated and
+ * the respective efficiency values are initialized.
+ */
+void init_sched_hmp_boost_policy(void)
+{
+ /*
+ * Initialize the boost type here if it is not passed from
+ * device tree.
+ */
+ if (sched_boost_policy == SCHED_BOOST_NONE) {
+ if (max_possible_efficiency != min_possible_efficiency)
+ sched_boost_policy = SCHED_BOOST_ON_BIG;
+ else
+ sched_boost_policy = SCHED_BOOST_ON_ALL;
+ }
+}
+
+void sched_hmp_parse_dt(void)
+{
+ struct device_node *sn;
+ const char *boost_policy;
+
+ if (!sched_enable_hmp)
+ return;
+
+ sn = of_find_node_by_path("/sched-hmp");
+ if (!sn)
+ return;
+
+ if (!of_property_read_string(sn, "boost-policy", &boost_policy)) {
+ if (!strcmp(boost_policy, "boost-on-big"))
+ sched_boost_policy = SCHED_BOOST_ON_BIG;
+ else if (!strcmp(boost_policy, "boost-on-all"))
+ sched_boost_policy = SCHED_BOOST_ON_ALL;
+ }
+}
+
unsigned int max_possible_efficiency = 1;
unsigned int min_possible_efficiency = UINT_MAX;
@@ -1169,12 +1216,9 @@ int task_load_will_fit(struct task_struct *p, u64 task_load, int cpu,
enum sched_boost_type sched_boost_type(void)
{
- if (sched_boost()) {
- if (min_possible_efficiency != max_possible_efficiency)
- return SCHED_BOOST_ON_BIG;
- else
- return SCHED_BOOST_ON_ALL;
- }
+ if (sched_boost())
+ return sched_boost_policy;
+
return SCHED_BOOST_NONE;
}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 1b641e60233e..ada5e580e968 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1399,6 +1399,8 @@ extern u64 cpu_upmigrate_discourage_read_u64(struct cgroup_subsys_state *css,
struct cftype *cft);
extern int cpu_upmigrate_discourage_write_u64(struct cgroup_subsys_state *css,
struct cftype *cft, u64 upmigrate_discourage);
+extern void sched_hmp_parse_dt(void);
+extern void init_sched_hmp_boost_policy(void);
#else /* CONFIG_SCHED_HMP */
@@ -1589,6 +1591,8 @@ static inline void post_big_task_count_change(void) { }
static inline void set_hmp_defaults(void) { }
static inline void clear_reserved(int cpu) { }
+static inline void sched_hmp_parse_dt(void) {}
+static inline void init_sched_hmp_boost_policy(void) {}
#define trace_sched_cpu_load(...)
#define trace_sched_cpu_load_lb(...)
diff --git a/kernel/sched/sched_avg.c b/kernel/sched/sched_avg.c
index c70e0466c36c..29d8a26a78ed 100644
--- a/kernel/sched/sched_avg.c
+++ b/kernel/sched/sched_avg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -60,17 +60,17 @@ void sched_get_nr_running_avg(int *avg, int *iowait_avg, int *big_avg)
spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
curr_time = sched_clock();
+ diff = curr_time - per_cpu(last_time, cpu);
+ BUG_ON((s64)diff < 0);
+
tmp_avg += per_cpu(nr_prod_sum, cpu);
- tmp_avg += per_cpu(nr, cpu) *
- (curr_time - per_cpu(last_time, cpu));
+ tmp_avg += per_cpu(nr, cpu) * diff;
tmp_big_avg += per_cpu(nr_big_prod_sum, cpu);
- tmp_big_avg += nr_eligible_big_tasks(cpu) *
- (curr_time - per_cpu(last_time, cpu));
+ tmp_big_avg += nr_eligible_big_tasks(cpu) * diff;
tmp_iowait += per_cpu(iowait_prod_sum, cpu);
- tmp_iowait += nr_iowait_cpu(cpu) *
- (curr_time - per_cpu(last_time, cpu));
+ tmp_iowait += nr_iowait_cpu(cpu) * diff;
per_cpu(last_time, cpu) = curr_time;
@@ -107,14 +107,15 @@ EXPORT_SYMBOL(sched_get_nr_running_avg);
*/
void sched_update_nr_prod(int cpu, long delta, bool inc)
{
- int diff;
- s64 curr_time;
+ u64 diff;
+ u64 curr_time;
unsigned long flags, nr_running;
spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
nr_running = per_cpu(nr, cpu);
curr_time = sched_clock();
diff = curr_time - per_cpu(last_time, cpu);
+ BUG_ON((s64)diff < 0);
per_cpu(last_time, cpu) = curr_time;
per_cpu(nr, cpu) = nr_running + (inc ? delta : -delta);
diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c
index 6d6893c7d99d..4e3a205551e0 100644
--- a/net/rmnet_data/rmnet_data_vnd.c
+++ b/net/rmnet_data/rmnet_data_vnd.c
@@ -928,7 +928,7 @@ int rmnet_vnd_add_tc_flow(uint32_t id, uint32_t map_flow, uint32_t tc_flow)
list_add(&(itm->list), &(dev_conf->flow_head));
write_unlock_irqrestore(&dev_conf->flow_map_lock, flags);
- LOGD("Created flow mapping [%s][0x%08X][0x%08X]@%p",
+ LOGD("Created flow mapping [%s][0x%08X][0x%08X]@%pK",
dev->name, itm->map_flow_id, itm->tc_flow_id[0], itm);
return RMNET_CONFIG_OK;