summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-oledb-regulator.txt6
-rw-r--r--Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt4
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660l.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8998.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi1
-rw-r--r--arch/arm64/configs/msmcortex_mediabox_defconfig1
-rw-r--r--drivers/clk/qcom/clk-cpu-osm.c2
-rw-r--r--drivers/clk/qcom/gcc-sdm660.c4
-rw-r--r--drivers/crypto/msm/qcedev.c51
-rw-r--r--drivers/leds/leds-qpnp-flash-v2.c20
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c53
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c16
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h9
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c11
-rw-r--r--drivers/power/supply/qcom/battery.c51
-rw-r--r--drivers/power/supply/qcom/qpnp-qnovo.c37
-rw-r--r--drivers/regulator/qpnp-oledb-regulator.c16
-rw-r--r--drivers/soc/qcom/qpnp-haptic.c92
-rw-r--r--drivers/soc/qcom/spcom.c2
-rw-r--r--drivers/spmi/spmi-pmic-arb.c13
-rw-r--r--drivers/staging/android/lowmemorykiller.c34
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_cdm.c13
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c12
-rw-r--r--fs/ext4/inline.c14
-rw-r--r--fs/ext4/inode.c54
-rw-r--r--fs/ext4/readpage.c47
-rw-r--r--fs/f2fs/data.c41
-rw-r--r--fs/f2fs/inline.c18
-rw-r--r--fs/mpage.c36
-rw-r--r--include/linux/shrinker.h1
-rw-r--r--include/trace/events/android_fs.h65
-rw-r--r--include/trace/events/android_fs_template.h57
-rw-r--r--mm/vmscan.c54
-rw-r--r--sound/soc/msm/msm8998.c22
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c2
41 files changed, 770 insertions, 117 deletions
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-oledb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-oledb-regulator.txt
index 38f599ba5321..efff6c79a9c0 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-oledb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-oledb-regulator.txt
@@ -14,6 +14,11 @@ Required Node Structure
Value type: <string>
Definition: should be "qcom,qpnp-oledb-regulator".
+- qcom,pmic-revid
+ Usage: required
+ Value type: <phandle>
+ Definition: Used to identify the PMIC subtype.
+
- reg
Usage: required
Value type: <prop-encoded-array>
@@ -224,6 +229,7 @@ pm660a_oledb: qpnp-oledb@e000 {
compatible = "qcom,qpnp-oledb-regulator";
#address-cells = <1>;
#size-cells = <1>;
+ qcom,pmic-revid = <&pm660l_revid>;
reg = <0xe000 0x100>;
label = "oledb";
diff --git a/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
index bef919334574..633abd2b8d08 100644
--- a/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
+++ b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
@@ -42,6 +42,9 @@ Required properties:
cell 4: interrupt flags indicating level-sense information, as defined in
dt-bindings/interrupt-controller/irq.h
+Optional properties:
+- qcom,reserved-chan : Reserved channel for debug purpose
+
Example V1 PMIC-Arbiter:
spmi {
@@ -56,6 +59,7 @@ Example V1 PMIC-Arbiter:
qcom,ee = <0>;
qcom,channel = <0>;
+ qcom,reserved-chan = <511>;
#address-cells = <2>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
index fdc04b9726b4..236565af6af2 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
@@ -415,6 +415,7 @@
compatible = "qcom,qpnp-oledb-regulator";
#address-cells = <1>;
#size-cells = <1>;
+ qcom,pmic-revid = <&pm660l_revid>;
reg = <0xe000 0x100>;
label = "oledb";
diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
index 85142c6c755e..9b5092cf7f14 100644
--- a/arch/arm/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
@@ -441,6 +441,7 @@
interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>;
qcom,ee = <0>;
qcom,channel = <0>;
+ qcom,reserved-chan = <511>;
#address-cells = <2>;
#size-cells = <0>;
interrupt-controller;
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index 0011e1d75321..24a935ffebec 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -1988,6 +1988,7 @@
interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>;
qcom,ee = <0>;
qcom,channel = <0>;
+ qcom,reserved-chan = <511>;
#address-cells = <2>;
#size-cells = <0>;
interrupt-controller;
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index be200f8dd531..2e576a51677f 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -466,6 +466,7 @@
interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>;
qcom,ee = <0>;
qcom,channel = <0>;
+ qcom,reserved-chan = <511>;
#address-cells = <2>;
#size-cells = <0>;
interrupt-controller;
diff --git a/arch/arm64/configs/msmcortex_mediabox_defconfig b/arch/arm64/configs/msmcortex_mediabox_defconfig
index 29a511d3eec5..3322f8fa11fc 100644
--- a/arch/arm64/configs/msmcortex_mediabox_defconfig
+++ b/arch/arm64/configs/msmcortex_mediabox_defconfig
@@ -194,6 +194,7 @@ CONFIG_L2TP_V3=y
CONFIG_L2TP_IP=y
CONFIG_L2TP_ETH=y
CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index f82ddc3b008b..d3914ab5f47c 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -772,7 +772,7 @@ static const char * const gcc_parent_names_1[] = {
};
static struct freq_tbl ftbl_osm_clk_src[] = {
- F(200000000, LMH_LITE_CLK_SRC, 3, 0, 0),
+ F(200000000, LMH_LITE_CLK_SRC, 1.5, 0, 0),
{ }
};
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
index b55310e091af..b10f9ca9fe1a 100644
--- a/drivers/clk/qcom/gcc-sdm660.c
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -732,6 +732,7 @@ static struct clk_rcg2 gp3_clk_src = {
};
static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
+ F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
F(600000000, P_GPLL0_OUT_MAIN, 1, 0, 0),
{ }
};
@@ -2755,6 +2756,9 @@ static int gcc_660_probe(struct platform_device *pdev)
/* Keep bimc gfx clock port on all the time */
clk_prepare_enable(gcc_bimc_gfx_clk.clkr.hw.clk);
+ /* Set the HMSS_GPLL0_SRC for 300MHz to CPU subsystem */
+ clk_set_rate(hmss_gpll0_clk_src.clkr.hw.clk, 300000000);
+
dev_info(&pdev->dev, "Registered GCC clocks\n");
return ret;
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 7459401979fe..d04ca6f28f90 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -56,6 +56,7 @@ static uint8_t _std_init_vector_sha256_uint8[] = {
static DEFINE_MUTEX(send_cmd_lock);
static DEFINE_MUTEX(qcedev_sent_bw_req);
+static DEFINE_MUTEX(hash_access_lock);
static void qcedev_ce_high_bw_req(struct qcedev_control *podev,
bool high_bw_req)
@@ -1648,12 +1649,18 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
err = qcedev_hash_init(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1671,32 +1678,42 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
if (qcedev_areq.sha_op_req.alg == QCEDEV_ALG_AES_CMAC) {
err = qcedev_hash_cmac(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
} else {
if (handle->sha_ctxt.init_done == false) {
pr_err("%s Init was not called\n", __func__);
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
}
err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
}
if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
pr_err("Invalid sha_ctxt.diglen %d\n",
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
}
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1713,16 +1730,22 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
err = qcedev_hash_final(&qcedev_areq, handle);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1737,20 +1760,28 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
qcedev_hash_init(&qcedev_areq, handle, &sg_src);
err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
err = qcedev_hash_final(&qcedev_areq, handle);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index 4c28e0922c84..de5c61418d07 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -152,7 +152,6 @@
#define FLASH_LED_MOD_ENABLE BIT(7)
#define FLASH_LED_DISABLE 0x00
#define FLASH_LED_SAFETY_TMR_DISABLED 0x13
-#define FLASH_LED_MIN_CURRENT_MA 25
#define FLASH_LED_MAX_TOTAL_CURRENT_MA 3750
/* notifier call chain for flash-led irqs */
@@ -879,11 +878,12 @@ static int qpnp_flash_led_get_max_avail_current(struct qpnp_flash_led *led)
static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
{
int prgm_current_ma = value;
+ int min_ma = fnode->ires_ua / 1000;
if (value <= 0)
prgm_current_ma = 0;
- else if (value < FLASH_LED_MIN_CURRENT_MA)
- prgm_current_ma = FLASH_LED_MIN_CURRENT_MA;
+ else if (value < min_ma)
+ prgm_current_ma = min_ma;
prgm_current_ma = min(prgm_current_ma, fnode->max_current);
fnode->current_ma = prgm_current_ma;
@@ -1335,7 +1335,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
struct flash_node_data *fnode, struct device_node *node)
{
const char *temp_string;
- int rc;
+ int rc, min_ma;
u32 val;
bool strobe_sel = 0, edge_trigger = 0, active_high = 0;
@@ -1391,10 +1391,11 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
return rc;
}
+ min_ma = fnode->ires_ua / 1000;
rc = of_property_read_u32(node, "qcom,max-current", &val);
if (!rc) {
- if (val < FLASH_LED_MIN_CURRENT_MA)
- val = FLASH_LED_MIN_CURRENT_MA;
+ if (val < min_ma)
+ val = min_ma;
fnode->max_current = val;
fnode->cdev.max_brightness = val;
} else {
@@ -1404,11 +1405,10 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
rc = of_property_read_u32(node, "qcom,current-ma", &val);
if (!rc) {
- if (val < FLASH_LED_MIN_CURRENT_MA ||
- val > fnode->max_current)
+ if (val < min_ma || val > fnode->max_current)
pr_warn("Invalid operational current specified, capping it\n");
- if (val < FLASH_LED_MIN_CURRENT_MA)
- val = FLASH_LED_MIN_CURRENT_MA;
+ if (val < min_ma)
+ val = min_ma;
if (val > fnode->max_current)
val = fnode->max_current;
fnode->current_ma = val;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index dce474e40470..5f1c9c2f9436 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -773,6 +773,40 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev,
}
}
+static int msm_isp_check_sync_time(struct msm_vfe_src_info *src_info,
+ struct msm_isp_timestamp *ts,
+ struct master_slave_resource_info *ms_res)
+{
+ int i;
+ struct msm_vfe_src_info *master_src_info = NULL;
+ uint32_t master_time = 0, current_time;
+
+ if (!ms_res->src_sof_mask)
+ return 0;
+
+ for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) {
+ if (ms_res->src_info[i] == NULL)
+ continue;
+ if (src_info == ms_res->src_info[i] ||
+ ms_res->src_info[i]->active == 0)
+ continue;
+ if (ms_res->src_sof_mask &
+ (1 << ms_res->src_info[i]->dual_hw_ms_info.index)) {
+ master_src_info = ms_res->src_info[i];
+ break;
+ }
+ }
+ if (!master_src_info)
+ return 0;
+ master_time = master_src_info->
+ dual_hw_ms_info.sof_info.mono_timestamp_ms;
+ current_time = ts->buf_time.tv_sec * 1000 +
+ ts->buf_time.tv_usec / 1000;
+ if ((current_time - master_time) > ms_res->sof_delta_threshold)
+ return 1;
+ return 0;
+}
+
static void msm_isp_sync_dual_cam_frame_id(
struct vfe_device *vfe_dev,
struct master_slave_resource_info *ms_res,
@@ -787,11 +821,24 @@ static void msm_isp_sync_dual_cam_frame_id(
if (src_info->dual_hw_ms_info.sync_state ==
ms_res->dual_sync_mode) {
- (frame_src == VFE_PIX_0) ? src_info->frame_id +=
+ if (msm_isp_check_sync_time(src_info, ts, ms_res) == 0) {
+ (frame_src == VFE_PIX_0) ? src_info->frame_id +=
vfe_dev->axi_data.src_info[frame_src].
sof_counter_step :
src_info->frame_id++;
- return;
+ return;
+ }
+ ms_res->src_sof_mask = 0;
+ ms_res->active_src_mask = 0;
+ for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) {
+ if (ms_res->src_info[i] == NULL)
+ continue;
+ if (ms_res->src_info[i]->active == 0)
+ continue;
+ ms_res->src_info[i]->dual_hw_ms_info.
+ sync_state =
+ MSM_ISP_DUAL_CAM_ASYNC;
+ }
}
WARN_ON(ms_res->dual_sync_mode == MSM_ISP_DUAL_CAM_ASYNC);
@@ -948,8 +995,6 @@ static void msm_isp_update_pd_stats_idx(struct vfe_device *vfe_dev,
uint32_t pingpong_status = 0, pingpong_bit = 0;
struct msm_isp_buffer *done_buf = NULL;
int vfe_idx = -1;
- /* initialize pd_buf_idx with an invalid index 0xF */
- vfe_dev->pd_buf_idx = 0xF;
if (frame_src < VFE_RAW_0 || frame_src > VFE_RAW_2)
return;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index f2cf4d477b3f..f92c67150215 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -228,9 +228,10 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
done_buf->buf_idx;
stats_event->pd_stats_idx = 0xF;
- if (stream_info->stats_type == MSM_ISP_STATS_BF)
+ if (stream_info->stats_type == MSM_ISP_STATS_BF) {
stats_event->pd_stats_idx = vfe_dev->pd_buf_idx;
-
+ vfe_dev->pd_buf_idx = 0xF;
+ }
if (comp_stats_type_mask == NULL) {
stats_event->stats_mask =
1 << stream_info->stats_type;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index e7be914ca267..2a9bb6e8e505 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -2315,6 +2315,9 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
vfe_dev->reg_update_requested = 0;
/* Register page fault handler */
vfe_dev->buf_mgr->pagefault_debug_disable = 0;
+ /* initialize pd_buf_idx with an invalid index 0xF */
+ vfe_dev->pd_buf_idx = 0xF;
+
cam_smmu_reg_client_page_fault_handler(
vfe_dev->buf_mgr->iommu_hdl,
msm_vfe_iommu_fault_handler, vfe_dev);
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 476521b77008..37898146f01d 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1414,6 +1414,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
wil_set_recovery_state(wil, fw_recovery_idle);
+ set_bit(wil_status_resetting, wil->status);
+
mutex_lock(&wil->mutex);
wmi_pcp_stop(wil);
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index d472e13fb9d9..2a515e848820 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -26,6 +26,10 @@ static bool use_msi = true;
module_param(use_msi, bool, 0444);
MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true");
+static bool ftm_mode;
+module_param(ftm_mode, bool, 0444);
+MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false");
+
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int wil6210_pm_notify(struct notifier_block *notify_block,
@@ -36,13 +40,15 @@ static int wil6210_pm_notify(struct notifier_block *notify_block,
static
void wil_set_capabilities(struct wil6210_priv *wil)
{
+ const char *wil_fw_name;
u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID);
u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) &
RGF_USER_REVISION_ID_MASK);
bitmap_zero(wil->hw_capabilities, hw_capability_last);
bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX);
- wil->wil_fw_name = WIL_FW_NAME_DEFAULT;
+ wil->wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_DEFAULT :
+ WIL_FW_NAME_DEFAULT;
wil->chip_revision = chip_revision;
switch (jtag_id) {
@@ -51,9 +57,11 @@ void wil_set_capabilities(struct wil6210_priv *wil)
case REVISION_ID_SPARROW_D0:
wil->hw_name = "Sparrow D0";
wil->hw_version = HW_VER_SPARROW_D0;
- if (wil_fw_verify_file_exists(wil,
- WIL_FW_NAME_SPARROW_PLUS))
- wil->wil_fw_name = WIL_FW_NAME_SPARROW_PLUS;
+ wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_SPARROW_PLUS :
+ WIL_FW_NAME_SPARROW_PLUS;
+
+ if (wil_fw_verify_file_exists(wil, wil_fw_name))
+ wil->wil_fw_name = wil_fw_name;
break;
case REVISION_ID_SPARROW_B0:
wil->hw_name = "Sparrow B0";
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 9d3e7a4f911e..0529d10a8268 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -37,8 +37,13 @@ extern bool debug_fw;
extern bool disable_ap_sme;
#define WIL_NAME "wil6210"
-#define WIL_FW_NAME_DEFAULT "wil6210.fw" /* code Sparrow B0 */
-#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */
+
+#define WIL_FW_NAME_DEFAULT "wil6210.fw"
+#define WIL_FW_NAME_FTM_DEFAULT "wil6210_ftm.fw"
+
+#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw"
+#define WIL_FW_NAME_FTM_SPARROW_PLUS "wil6210_sparrow_plus_ftm.fw"
+
#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */
#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 83ef6eb57e53..41afbdc34c18 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -518,16 +518,16 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
assoc_resp_ielen = 0;
}
- mutex_lock(&wil->mutex);
if (test_bit(wil_status_resetting, wil->status) ||
!test_bit(wil_status_fwready, wil->status)) {
wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
evt->cid);
- mutex_unlock(&wil->mutex);
/* no need for cleanup, wil_reset will do that */
return;
}
+ mutex_lock(&wil->mutex);
+
if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
(wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
if (!test_bit(wil_status_fwconnecting, wil->status)) {
@@ -631,6 +631,13 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
wil->sinfo_gen++;
+ if (test_bit(wil_status_resetting, wil->status) ||
+ !test_bit(wil_status_fwready, wil->status)) {
+ wil_err(wil, "status_resetting, cancel disconnect event\n");
+ /* no need for cleanup, wil_reset will do that */
+ return;
+ }
+
mutex_lock(&wil->mutex);
wil6210_disconnect(wil, evt->bssid, reason_code, true);
mutex_unlock(&wil->mutex);
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index 67f9d4fafeb8..539e757d3e99 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -434,23 +434,28 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
return rc;
}
- split_fcc(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua);
- pval.intval = slave_fcc_ua;
- rc = power_supply_set_property(chip->pl_psy,
- POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
- if (rc < 0) {
- pr_err("Couldn't set parallel fcc, rc=%d\n", rc);
- return rc;
- }
+ if (chip->pl_mode != POWER_SUPPLY_PL_NONE) {
+ split_fcc(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua);
+
+ pval.intval = slave_fcc_ua;
+ rc = power_supply_set_property(chip->pl_psy,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ &pval);
+ if (rc < 0) {
+ pr_err("Couldn't set parallel fcc, rc=%d\n", rc);
+ return rc;
+ }
- chip->slave_fcc_ua = slave_fcc_ua;
+ chip->slave_fcc_ua = slave_fcc_ua;
- pval.intval = master_fcc_ua;
- rc = power_supply_set_property(chip->main_psy,
- POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
- if (rc < 0) {
- pr_err("Could not set main fcc, rc=%d\n", rc);
- return rc;
+ pval.intval = master_fcc_ua;
+ rc = power_supply_set_property(chip->main_psy,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ &pval);
+ if (rc < 0) {
+ pr_err("Could not set main fcc, rc=%d\n", rc);
+ return rc;
+ }
}
pl_dbg(chip, PR_PARALLEL, "master_fcc=%d slave_fcc=%d distribution=(%d/%d)\n",
@@ -685,9 +690,6 @@ static bool is_main_available(struct pl_data *chip)
chip->main_psy = power_supply_get_by_name("main");
- if (chip->main_psy)
- rerun_election(chip->usb_icl_votable);
-
return !!chip->main_psy;
}
@@ -866,7 +868,18 @@ static void status_change_work(struct work_struct *work)
struct pl_data *chip = container_of(work,
struct pl_data, status_change_work);
- if (!is_main_available(chip))
+ if (!chip->main_psy && is_main_available(chip)) {
+ /*
+ * re-run election for FCC/FV/ICL once main_psy
+ * is available to ensure all votes are reflected
+ * on hardware
+ */
+ rerun_election(chip->usb_icl_votable);
+ rerun_election(chip->fcc_votable);
+ rerun_election(chip->fv_votable);
+ }
+
+ if (!chip->main_psy)
return;
if (!is_batt_available(chip))
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index c74dc8989821..eb97eb0ff2ac 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -89,7 +89,16 @@
#define QNOVO_STRM_CTRL 0xA8
#define QNOVO_IADC_OFFSET_OVR_VAL 0xA9
#define QNOVO_IADC_OFFSET_OVR 0xAA
+
#define QNOVO_DISABLE_CHARGING 0xAB
+#define ERR_SWITCHER_DISABLED BIT(7)
+#define ERR_JEITA_SOFT_CONDITION BIT(6)
+#define ERR_BAT_OV BIT(5)
+#define ERR_CV_MODE BIT(4)
+#define ERR_BATTERY_MISSING BIT(3)
+#define ERR_SAFETY_TIMER_EXPIRED BIT(2)
+#define ERR_CHARGING_DISABLED BIT(1)
+#define ERR_JEITA_HARD_CONDITION BIT(0)
#define QNOVO_TR_IADC_OFFSET_0 0xF1
#define QNOVO_TR_IADC_OFFSET_1 0xF2
@@ -1107,24 +1116,28 @@ static int qnovo_update_status(struct qnovo *chip)
{
u8 val = 0;
int rc;
- bool charging;
+ bool ok_to_qnovo;
bool changed = false;
rc = qnovo_read(chip, QNOVO_ERROR_STS2, &val, 1);
if (rc < 0) {
pr_err("Couldn't read error sts rc = %d\n", rc);
- charging = false;
+ ok_to_qnovo = false;
} else {
- charging = !(val & QNOVO_ERROR_CHARGING_DISABLED);
+ /*
+ * For CV mode keep qnovo enabled, userspace is expected to
+ * disable it after few runs
+ */
+ ok_to_qnovo = (val == ERR_CV_MODE || val == 0) ? true : false;
}
- if (chip->ok_to_qnovo ^ charging) {
+ if (chip->ok_to_qnovo ^ ok_to_qnovo) {
- vote(chip->disable_votable, OK_TO_QNOVO_VOTER, !charging, 0);
- if (!charging)
+ vote(chip->disable_votable, OK_TO_QNOVO_VOTER, !ok_to_qnovo, 0);
+ if (!ok_to_qnovo)
vote(chip->disable_votable, USER_VOTER, true, 0);
- chip->ok_to_qnovo = charging;
+ chip->ok_to_qnovo = ok_to_qnovo;
changed = true;
}
@@ -1247,6 +1260,16 @@ static int qnovo_hw_init(struct qnovo *chip)
chip->v_gain_mega = 1000000000 + (s64)(s8)vadc_gain * GAIN_LSB_FACTOR;
chip->v_gain_mega = div_s64(chip->v_gain_mega, 1000);
+ /* allow charger error conditions to disable qnovo, CV mode excluded */
+ val = ERR_SWITCHER_DISABLED | ERR_JEITA_SOFT_CONDITION | ERR_BAT_OV |
+ ERR_BATTERY_MISSING | ERR_SAFETY_TIMER_EXPIRED |
+ ERR_CHARGING_DISABLED | ERR_JEITA_HARD_CONDITION;
+ rc = qnovo_write(chip, QNOVO_DISABLE_CHARGING, &val, 1);
+ if (rc < 0) {
+ pr_err("Couldn't write QNOVO_DISABLE_CHARGING rc = %d\n", rc);
+ return rc;
+ }
+
return 0;
}
diff --git a/drivers/regulator/qpnp-oledb-regulator.c b/drivers/regulator/qpnp-oledb-regulator.c
index c012f373e80e..fa14445f9d26 100644
--- a/drivers/regulator/qpnp-oledb-regulator.c
+++ b/drivers/regulator/qpnp-oledb-regulator.c
@@ -27,6 +27,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/qpnp-labibb-regulator.h>
#include <linux/qpnp/qpnp-pbs.h>
+#include <linux/qpnp/qpnp-revid.h>
#define QPNP_OLEDB_REGULATOR_DRIVER_NAME "qcom,qpnp-oledb-regulator"
#define OLEDB_VOUT_STEP_MV 100
@@ -162,6 +163,7 @@ struct qpnp_oledb {
struct notifier_block oledb_nb;
struct mutex bus_lock;
struct device_node *pbs_dev_node;
+ struct pmic_revid_data *pmic_rev_id;
u32 base;
u8 mod_enable;
@@ -1085,8 +1087,22 @@ static int qpnp_oledb_parse_fast_precharge(struct qpnp_oledb *oledb)
static int qpnp_oledb_parse_dt(struct qpnp_oledb *oledb)
{
int rc = 0;
+ struct device_node *revid_dev_node;
struct device_node *of_node = oledb->dev->of_node;
+ revid_dev_node = of_parse_phandle(oledb->dev->of_node,
+ "qcom,pmic-revid", 0);
+ if (!revid_dev_node) {
+ pr_err("Missing qcom,pmic-revid property - driver failed\n");
+ return -EINVAL;
+ }
+
+ oledb->pmic_rev_id = get_revid_data(revid_dev_node);
+ if (IS_ERR(oledb->pmic_rev_id)) {
+ pr_debug("Unable to get revid data\n");
+ return -EPROBE_DEFER;
+ }
+
oledb->swire_control =
of_property_read_bool(of_node, "qcom,swire-control");
diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c
index c86eebcd390f..70cf11359e97 100644
--- a/drivers/soc/qcom/qpnp-haptic.c
+++ b/drivers/soc/qcom/qpnp-haptic.c
@@ -138,7 +138,7 @@
#define QPNP_HAP_WAV_SAMP_MAX 0x7E
#define QPNP_HAP_BRAKE_PAT_LEN 4
#define QPNP_HAP_PLAY_EN 0x80
-#define QPNP_HAP_EN 0x80
+#define QPNP_HAP_EN_BIT BIT(7)
#define QPNP_HAP_BRAKE_MASK BIT(0)
#define QPNP_HAP_AUTO_RES_MASK BIT(7)
#define AUTO_RES_ENABLE BIT(7)
@@ -305,7 +305,6 @@ struct qpnp_pwm_info {
* @ wave_samp - array of wave samples
* @ shadow_wave_samp - shadow array of wave samples
* @ brake_pat - pattern for active breaking
- * @ reg_en_ctl - enable control register
* @ reg_play - play register
* @ lra_res_cal_period - period for resonance calibration
* @ sc_duration - counter to determine the duration of short circuit condition
@@ -358,6 +357,7 @@ struct qpnp_hap {
u32 sc_irq;
u32 status_flags;
u16 base;
+ u16 last_rate_cfg;
u16 drive_period_code_max_limit;
u16 drive_period_code_min_limit;
u16 lra_res_cal_period;
@@ -368,7 +368,6 @@ struct qpnp_hap {
u8 wave_samp[QPNP_HAP_WAV_SAMP_LEN];
u8 shadow_wave_samp[QPNP_HAP_WAV_SAMP_LEN];
u8 brake_pat[QPNP_HAP_BRAKE_PAT_LEN];
- u8 reg_en_ctl;
u8 reg_play;
u8 sc_duration;
u8 ext_pwm_dtest_line;
@@ -391,6 +390,18 @@ struct qpnp_hap {
static struct qpnp_hap *ghap;
/* helper to read a pmic register */
+static int qpnp_hap_read_mult_reg(struct qpnp_hap *hap, u16 addr, u8 *val,
+ int len)
+{
+ int rc;
+
+ rc = regmap_bulk_read(hap->regmap, addr, val, len);
+ if (rc < 0)
+ pr_err("Error reading address: %X - ret %X\n", addr, rc);
+
+ return rc;
+}
+
static int qpnp_hap_read_reg(struct qpnp_hap *hap, u16 addr, u8 *val)
{
int rc;
@@ -399,11 +410,28 @@ static int qpnp_hap_read_reg(struct qpnp_hap *hap, u16 addr, u8 *val)
rc = regmap_read(hap->regmap, addr, &tmp);
if (rc < 0)
pr_err("Error reading address: %X - ret %X\n", addr, rc);
- *val = (u8)tmp;
+ else
+ *val = (u8)tmp;
+
return rc;
}
/* helper to write a pmic register */
+static int qpnp_hap_write_mult_reg(struct qpnp_hap *hap, u16 addr, u8 *val,
+ int len)
+{
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&hap->bus_lock, flags);
+ rc = regmap_bulk_write(hap->regmap, addr, val, len);
+ if (rc < 0)
+ pr_err("Error writing address: %X - ret %X\n", addr, rc);
+
+ spin_unlock_irqrestore(&hap->bus_lock, flags);
+ return rc;
+}
+
static int qpnp_hap_write_reg(struct qpnp_hap *hap, u16 addr, u8 val)
{
unsigned long flags;
@@ -480,15 +508,12 @@ static void qpnp_handle_sc_irq(struct work_struct *work)
}
}
-static int qpnp_hap_mod_enable(struct qpnp_hap *hap, int on)
+static int qpnp_hap_mod_enable(struct qpnp_hap *hap, bool on)
{
u8 val;
int rc, i;
- val = hap->reg_en_ctl;
- if (on) {
- val |= QPNP_HAP_EN;
- } else {
+ if (!on) {
for (i = 0; i < QPNP_HAP_MAX_RETRIES; i++) {
/* wait for 4 cycles of play rate */
unsigned long sleep_time =
@@ -511,16 +536,13 @@ static int qpnp_hap_mod_enable(struct qpnp_hap *hap, int on)
if (i >= QPNP_HAP_MAX_RETRIES)
pr_debug("Haptics Busy. Force disable\n");
-
- val &= ~QPNP_HAP_EN;
}
+ val = on ? QPNP_HAP_EN_BIT : 0;
rc = qpnp_hap_write_reg(hap, QPNP_HAP_EN_CTL_REG(hap->base), val);
if (rc < 0)
return rc;
- hap->reg_en_ctl = val;
-
return 0;
}
@@ -1517,20 +1539,23 @@ static int qpnp_hap_auto_res_enable(struct qpnp_hap *hap, int enable)
static void update_lra_frequency(struct qpnp_hap *hap)
{
- u8 lra_auto_res_lo = 0, lra_auto_res_hi = 0, val;
+ u8 lra_auto_res[2], val;
u32 play_rate_code;
+ u16 rate_cfg;
int rc;
- qpnp_hap_read_reg(hap, QPNP_HAP_LRA_AUTO_RES_LO(hap->base),
- &lra_auto_res_lo);
- qpnp_hap_read_reg(hap, QPNP_HAP_LRA_AUTO_RES_HI(hap->base),
- &lra_auto_res_hi);
+ rc = qpnp_hap_read_mult_reg(hap, QPNP_HAP_LRA_AUTO_RES_LO(hap->base),
+ lra_auto_res, 2);
+ if (rc < 0) {
+ pr_err("Error in reading LRA_AUTO_RES_LO/HI, rc=%d\n", rc);
+ return;
+ }
play_rate_code =
- (lra_auto_res_hi & 0xF0) << 4 | (lra_auto_res_lo & 0xFF);
+ (lra_auto_res[1] & 0xF0) << 4 | (lra_auto_res[0] & 0xFF);
pr_debug("lra_auto_res_lo = 0x%x lra_auto_res_hi = 0x%x play_rate_code = 0x%x\n",
- lra_auto_res_lo, lra_auto_res_hi, play_rate_code);
+ lra_auto_res[0], lra_auto_res[1], play_rate_code);
rc = qpnp_hap_read_reg(hap, QPNP_HAP_STATUS(hap->base), &val);
if (rc < 0)
@@ -1559,12 +1584,21 @@ static void update_lra_frequency(struct qpnp_hap *hap)
return;
}
- qpnp_hap_write_reg(hap, QPNP_HAP_RATE_CFG1_REG(hap->base),
- lra_auto_res_lo);
+ lra_auto_res[1] >>= 4;
+ rate_cfg = lra_auto_res[1] << 8 | lra_auto_res[0];
+ if (hap->last_rate_cfg == rate_cfg) {
+ pr_debug("Same rate_cfg, skip updating\n");
+ return;
+ }
- lra_auto_res_hi = lra_auto_res_hi >> 4;
- qpnp_hap_write_reg(hap, QPNP_HAP_RATE_CFG2_REG(hap->base),
- lra_auto_res_hi);
+ rc = qpnp_hap_write_mult_reg(hap, QPNP_HAP_RATE_CFG1_REG(hap->base),
+ lra_auto_res, 2);
+ if (rc < 0) {
+ pr_err("Error in writing to RATE_CFG1/2, rc=%d\n", rc);
+ } else {
+ pr_debug("Update RATE_CFG with [0x%x]\n", rate_cfg);
+ hap->last_rate_cfg = rate_cfg;
+ }
}
static enum hrtimer_restart detect_auto_res_error(struct hrtimer *timer)
@@ -1983,6 +2017,8 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
if (rc)
return rc;
+ hap->last_rate_cfg = hap->init_drive_period_code;
+
if (hap->act_type == QPNP_HAP_LRA &&
hap->perform_lra_auto_resonance_search)
calculate_lra_code(hap);
@@ -2019,12 +2055,6 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
return rc;
}
- /* Cache enable control register */
- rc = qpnp_hap_read_reg(hap, QPNP_HAP_EN_CTL_REG(hap->base), &val);
- if (rc < 0)
- return rc;
- hap->reg_en_ctl = val;
-
/* Cache play register */
rc = qpnp_hap_read_reg(hap, QPNP_HAP_PLAY_REG(hap->base), &val);
if (rc < 0)
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index 0c44d76bc7c7..f7b9c3f85a30 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -898,12 +898,12 @@ static int spcom_rx(struct spcom_channel *ch,
goto exit_err;
}
+copy_buf:
if (!ch->glink_rx_buf) {
pr_err("invalid glink_rx_buf.\n");
goto exit_err;
}
-copy_buf:
/* Copy from glink buffer to spcom buffer */
size = min_t(int, ch->actual_rx_size, size);
memcpy(buf, ch->glink_rx_buf, size);
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index a5bfeab596ac..d1802bcba0fb 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -166,6 +166,7 @@ struct spmi_pmic_arb {
u16 max_apid;
u16 max_periph;
u32 *mapping_table;
+ int reserved_chan;
DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
struct irq_domain *domain;
struct spmi_controller *spmic;
@@ -861,6 +862,10 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
* ppid_to_apid is an in-memory invert of that table.
*/
for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
+ /* Do not keep the reserved channel in the mapping table */
+ if (pa->reserved_chan >= 0 && apid == pa->reserved_chan)
+ continue;
+
regval = readl_relaxed(pa->cnfg +
SPMI_OWNERSHIP_TABLE_REG(apid));
pa->apid_data[apid].irq_owner
@@ -920,6 +925,10 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pa)
* receive interrupts from the PPID.
*/
for (apid = 0; apid < pa->max_periph; apid++) {
+ /* Do not keep the reserved channel in the mapping table */
+ if (pa->reserved_chan >= 0 && apid == pa->reserved_chan)
+ continue;
+
offset = pa->ver_ops->channel_map_offset(apid);
if (offset >= pa->core_size)
break;
@@ -1340,6 +1349,10 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
pa->ee = ee;
+ pa->reserved_chan = -EINVAL;
+ of_property_read_u32(pdev->dev.of_node, "qcom,reserved-chan",
+ &pa->reserved_chan);
+
pa->mapping_table = devm_kcalloc(&ctrl->dev, PMIC_ARB_MAX_PERIPHS - 1,
sizeof(*pa->mapping_table), GFP_KERNEL);
if (!pa->mapping_table) {
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index bec687853c5d..205af6627b80 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -217,6 +217,22 @@ static int test_task_flag(struct task_struct *p, int flag)
return 0;
}
+static int test_task_state(struct task_struct *p, int state)
+{
+ struct task_struct *t;
+
+ for_each_thread(p, t) {
+ task_lock(t);
+ if (t->state & state) {
+ task_unlock(t);
+ return 1;
+ }
+ task_unlock(t);
+ }
+
+ return 0;
+}
+
static DEFINE_MUTEX(scan_mutex);
int can_use_cma_pages(gfp_t gfp_mask)
@@ -404,7 +420,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
int other_free;
int other_file;
- if (mutex_lock_interruptible(&scan_mutex) < 0)
+ if (!mutex_trylock(&scan_mutex))
return 0;
other_free = global_page_state(NR_FREE_PAGES);
@@ -462,8 +478,6 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
if (test_task_flag(tsk, TIF_MEMDIE)) {
rcu_read_unlock();
- /* give the system time to free up the memory */
- msleep_interruptible(20);
mutex_unlock(&scan_mutex);
return 0;
}
@@ -497,6 +511,17 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
}
if (selected) {
long cache_size, cache_limit, free;
+
+ if (test_task_flag(selected, TIF_MEMDIE) &&
+ (test_task_state(selected, TASK_UNINTERRUPTIBLE))) {
+ lowmem_print(2, "'%s' (%d) is already killed\n",
+ selected->comm,
+ selected->pid);
+ rcu_read_unlock();
+ mutex_unlock(&scan_mutex);
+ return 0;
+ }
+
task_lock(selected);
send_sig(SIGKILL, selected, 0);
/*
@@ -565,7 +590,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
static struct shrinker lowmem_shrinker = {
.scan_objects = lowmem_scan,
.count_objects = lowmem_count,
- .seeks = DEFAULT_SEEKS * 16
+ .seeks = DEFAULT_SEEKS * 16,
+ .flags = SHRINKER_LMK
};
static int __init lowmem_init(void)
diff --git a/drivers/video/fbdev/msm/mdss_mdp_cdm.c b/drivers/video/fbdev/msm/mdss_mdp_cdm.c
index f1d1bdd301e3..10928e6bceaa 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_cdm.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_cdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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
@@ -377,6 +377,17 @@ int mdss_mdp_cdm_destroy(struct mdss_mdp_cdm *cdm)
return -EINVAL;
}
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
+ mutex_lock(&cdm->lock);
+ /* Disable HDMI packer */
+ writel_relaxed(0x0, cdm->base + MDSS_MDP_REG_CDM_HDMI_PACK_OP_MODE);
+
+ /* Put CDM in bypass */
+ writel_relaxed(0x0, cdm->mdata->mdp_base + MDSS_MDP_MDP_OUT_CTL_0);
+
+ mutex_unlock(&cdm->lock);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
+
kref_put(&cdm->kref, mdss_mdp_cdm_free);
return rc;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index ea55203afc51..39233b8ad3a4 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -1071,6 +1071,13 @@ static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
{
int intfs_num, ret = 0;
+ if (ctl->cdm) {
+ if (!mdss_mdp_cdm_destroy(ctl->cdm))
+ mdss_mdp_ctl_write(ctl,
+ MDSS_MDP_REG_CTL_FLUSH, BIT(26));
+ ctl->cdm = NULL;
+ }
+
intfs_num = ctl->intf_num - MDSS_MDP_INTF0;
ret = mdss_mdp_video_intfs_stop(ctl, ctl->panel_data, intfs_num);
if (IS_ERR_VALUE(ret)) {
@@ -1083,10 +1090,6 @@ static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
mdss_mdp_ctl_reset(ctl, false);
ctl->intf_ctx[MASTER_CTX] = NULL;
- if (ctl->cdm) {
- mdss_mdp_cdm_destroy(ctl->cdm);
- ctl->cdm = NULL;
- }
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
index 87ed56028edd..9b63499e64b0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
@@ -792,7 +792,9 @@ static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl,
}
if (ctl->cdm) {
- mdss_mdp_cdm_destroy(ctl->cdm);
+ if (!mdss_mdp_cdm_destroy(ctl->cdm))
+ mdss_mdp_ctl_write(ctl,
+ MDSS_MDP_REG_CTL_FLUSH, BIT(26));
ctl->cdm = NULL;
}
return 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 8eb12d764be3..c800bbe4963c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2601,6 +2601,18 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
mdss_mdp_splash_cleanup(mfd, true);
/*
+ * Wait for pingpong done only during resume for
+ * command mode panels. Ensure that one commit is
+ * sent before kickoff completes so that backlight
+ * update happens after it.
+ */
+ if (mdss_fb_is_power_off(mfd) &&
+ mfd->panel_info->type == MIPI_CMD_PANEL) {
+ pr_debug("wait for pp done after resume for cmd mode\n");
+ mdss_mdp_display_wait4pingpong(ctl, true);
+ }
+
+ /*
* Configure Timing Engine, if new fps was set.
* We need to do this after the wait for vsync
* to guarantee that mdp flush bit and dsi flush
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index cb3d6f6419cd..db81acb686c0 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -18,6 +18,7 @@
#include "ext4.h"
#include "xattr.h"
#include "truncate.h"
+#include <trace/events/android_fs.h>
#define EXT4_XATTR_SYSTEM_DATA "data"
#define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS))
@@ -502,6 +503,17 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
return -EAGAIN;
}
+ if (trace_android_fs_dataread_start_enabled()) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_dataread_start(inode, page_offset(page),
+ PAGE_SIZE, current->pid,
+ path, current->comm);
+ }
+
/*
* Current inline data can only exist in the 1st page,
* So for all the other pages, just set them uptodate.
@@ -513,6 +525,8 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
SetPageUptodate(page);
}
+ trace_android_fs_dataread_end(inode, page_offset(page), PAGE_SIZE);
+
up_read(&EXT4_I(inode)->xattr_sem);
unlock_page(page);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 99fa2fca52b1..72b384931f66 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -45,6 +45,7 @@
#include "ext4_ice.h"
#include <trace/events/ext4.h>
+#include <trace/events/android_fs.h>
#define MPAGE_DA_EXTENT_TAIL 0x01
@@ -1018,6 +1019,16 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
pgoff_t index;
unsigned from, to;
+ if (trace_android_fs_datawrite_start_enabled()) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_datawrite_start(inode, pos, len,
+ current->pid, path,
+ current->comm);
+ }
trace_ext4_write_begin(inode, pos, len, flags);
/*
* Reserve one block more for addition to orphan list in case
@@ -1154,6 +1165,7 @@ static int ext4_write_end(struct file *file,
int ret = 0, ret2;
int i_size_changed = 0;
+ trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_write_end(inode, pos, len, copied);
if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
ret = ext4_jbd2_file_inode(handle, inode);
@@ -1267,6 +1279,7 @@ static int ext4_journalled_write_end(struct file *file,
unsigned from, to;
int size_changed = 0;
+ trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_journalled_write_end(inode, pos, len, copied);
from = pos & (PAGE_CACHE_SIZE - 1);
to = from + len;
@@ -2742,6 +2755,16 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
len, flags, pagep, fsdata);
}
*fsdata = (void *)0;
+ if (trace_android_fs_datawrite_start_enabled()) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_datawrite_start(inode, pos, len,
+ current->pid,
+ path, current->comm);
+ }
trace_ext4_da_write_begin(inode, pos, len, flags);
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@@ -2860,6 +2883,7 @@ static int ext4_da_write_end(struct file *file,
return ext4_write_end(file, mapping, pos,
len, copied, page, fsdata);
+ trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_da_write_end(inode, pos, len, copied);
start = pos & (PAGE_CACHE_SIZE - 1);
end = start + copied - 1;
@@ -3352,12 +3376,42 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
if (ext4_has_inline_data(inode))
return 0;
+ if (trace_android_fs_dataread_start_enabled() &&
+ (iov_iter_rw(iter) == READ)) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_dataread_start(inode, offset, count,
+ current->pid, path,
+ current->comm);
+ }
+ if (trace_android_fs_datawrite_start_enabled() &&
+ (iov_iter_rw(iter) == WRITE)) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_datawrite_start(inode, offset, count,
+ current->pid, path,
+ current->comm);
+ }
trace_ext4_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
ret = ext4_ext_direct_IO(iocb, iter, offset);
else
ret = ext4_ind_direct_IO(iocb, iter, offset);
trace_ext4_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret);
+
+ if (trace_android_fs_dataread_start_enabled() &&
+ (iov_iter_rw(iter) == READ))
+ trace_android_fs_dataread_end(inode, offset, count);
+ if (trace_android_fs_datawrite_start_enabled() &&
+ (iov_iter_rw(iter) == WRITE))
+ trace_android_fs_datawrite_end(inode, offset, count);
+
return ret;
}
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 71a08a294529..99f1bd8c7f05 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -46,6 +46,7 @@
#include "ext4.h"
#include "ext4_ice.h"
+#include <trace/events/android_fs.h>
/*
* Call ext4_decrypt on every single page, reusing the encryption
@@ -92,6 +93,17 @@ static inline bool ext4_bio_encrypted(struct bio *bio)
#endif
}
+static void
+ext4_trace_read_completion(struct bio *bio)
+{
+ struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+ if (first_page != NULL)
+ trace_android_fs_dataread_end(first_page->mapping->host,
+ page_offset(first_page),
+ bio->bi_iter.bi_size);
+}
+
/*
* I/O completion handler for multipage BIOs.
*
@@ -109,6 +121,9 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
int i;
+ if (trace_android_fs_dataread_start_enabled())
+ ext4_trace_read_completion(bio);
+
if (ext4_bio_encrypted(bio)) {
struct ext4_crypto_ctx *ctx = bio->bi_private;
@@ -136,6 +151,30 @@ static void mpage_end_io(struct bio *bio)
bio_put(bio);
}
+static void
+ext4_submit_bio_read(struct bio *bio)
+{
+ if (trace_android_fs_dataread_start_enabled()) {
+ struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+ if (first_page != NULL) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ first_page->mapping->host);
+ trace_android_fs_dataread_start(
+ first_page->mapping->host,
+ page_offset(first_page),
+ bio->bi_iter.bi_size,
+ current->pid,
+ path,
+ current->comm);
+ }
+ }
+ submit_bio(READ, bio);
+}
+
int ext4_mpage_readpages(struct address_space *mapping,
struct list_head *pages, struct page *page,
unsigned nr_pages)
@@ -277,7 +316,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
*/
if (bio && (last_block_in_bio != blocks[0] - 1)) {
submit_and_realloc:
- submit_bio(READ, bio);
+ ext4_submit_bio_read(bio);
bio = NULL;
}
if (bio == NULL) {
@@ -309,14 +348,14 @@ int ext4_mpage_readpages(struct address_space *mapping,
if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
(relative_block == map.m_len)) ||
(first_hole != blocks_per_page)) {
- submit_bio(READ, bio);
+ ext4_submit_bio_read(bio);
bio = NULL;
} else
last_block_in_bio = blocks[blocks_per_page - 1];
goto next_page;
confused:
if (bio) {
- submit_bio(READ, bio);
+ ext4_submit_bio_read(bio);
bio = NULL;
}
if (!PageUptodate(page))
@@ -329,6 +368,6 @@ int ext4_mpage_readpages(struct address_space *mapping,
}
BUG_ON(pages && !list_empty(pages));
if (bio)
- submit_bio(READ, bio);
+ ext4_submit_bio_read(bio);
return 0;
}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index f53826ec30f3..4fb5709256fd 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -26,6 +26,7 @@
#include "segment.h"
#include "trace.h"
#include <trace/events/f2fs.h>
+#include <trace/events/android_fs.h>
static void f2fs_read_end_io(struct bio *bio)
{
@@ -1405,6 +1406,16 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
struct dnode_of_data dn;
int err = 0;
+ if (trace_android_fs_datawrite_start_enabled()) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_datawrite_start(inode, pos, len,
+ current->pid, path,
+ current->comm);
+ }
trace_f2fs_write_begin(inode, pos, len, flags);
f2fs_balance_fs(sbi);
@@ -1533,6 +1544,7 @@ static int f2fs_write_end(struct file *file,
{
struct inode *inode = page->mapping->host;
+ trace_android_fs_datawrite_end(inode, pos, len);
trace_f2fs_write_end(inode, pos, len, copied);
set_page_dirty(page);
@@ -1586,6 +1598,28 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
+ if (trace_android_fs_dataread_start_enabled() &&
+ (iov_iter_rw(iter) == READ)) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_dataread_start(inode, offset,
+ count, current->pid, path,
+ current->comm);
+ }
+ if (trace_android_fs_datawrite_start_enabled() &&
+ (iov_iter_rw(iter) == WRITE)) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_datawrite_start(inode, offset, count,
+ current->pid, path,
+ current->comm);
+ }
if (iov_iter_rw(iter) == WRITE) {
__allocate_data_blocks(inode, offset, count);
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
@@ -1599,6 +1633,13 @@ out:
if (err < 0 && iov_iter_rw(iter) == WRITE)
f2fs_write_failed(mapping, offset + count);
+ if (trace_android_fs_dataread_start_enabled() &&
+ (iov_iter_rw(iter) == READ))
+ trace_android_fs_dataread_end(inode, offset, count);
+ if (trace_android_fs_datawrite_start_enabled() &&
+ (iov_iter_rw(iter) == WRITE))
+ trace_android_fs_datawrite_end(inode, offset, count);
+
trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
return err;
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index bda7126466c0..dbb2cc4df603 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -13,6 +13,7 @@
#include "f2fs.h"
#include "node.h"
+#include <trace/events/android_fs.h>
bool f2fs_may_inline_data(struct inode *inode)
{
@@ -84,14 +85,29 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
{
struct page *ipage;
+ if (trace_android_fs_dataread_start_enabled()) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ inode);
+ trace_android_fs_dataread_start(inode, page_offset(page),
+ PAGE_SIZE, current->pid,
+ path, current->comm);
+ }
+
ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
if (IS_ERR(ipage)) {
+ trace_android_fs_dataread_end(inode, page_offset(page),
+ PAGE_SIZE);
unlock_page(page);
return PTR_ERR(ipage);
}
if (!f2fs_has_inline_data(inode)) {
f2fs_put_page(ipage, 1);
+ trace_android_fs_dataread_end(inode, page_offset(page),
+ PAGE_SIZE);
return -EAGAIN;
}
@@ -102,6 +118,8 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
SetPageUptodate(page);
f2fs_put_page(ipage, 1);
+ trace_android_fs_dataread_end(inode, page_offset(page),
+ PAGE_SIZE);
unlock_page(page);
return 0;
}
diff --git a/fs/mpage.c b/fs/mpage.c
index 1480d3a18037..0fd48fdcc1b1 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -30,6 +30,14 @@
#include <linux/cleancache.h>
#include "internal.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/android_fs.h>
+
+EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_start);
+EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_end);
+EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_start);
+EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_end);
+
/*
* I/O completion handler for multipage BIOs.
*
@@ -47,6 +55,16 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
int i;
+ if (trace_android_fs_dataread_end_enabled() &&
+ (bio_data_dir(bio) == READ)) {
+ struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+ if (first_page != NULL)
+ trace_android_fs_dataread_end(first_page->mapping->host,
+ page_offset(first_page),
+ bio->bi_iter.bi_size);
+ }
+
bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page;
page_endio(page, bio_data_dir(bio), bio->bi_error);
@@ -57,6 +75,24 @@ static void mpage_end_io(struct bio *bio)
static struct bio *mpage_bio_submit(int rw, struct bio *bio)
{
+ if (trace_android_fs_dataread_start_enabled() && (rw == READ)) {
+ struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+ if (first_page != NULL) {
+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+ path = android_fstrace_get_pathname(pathbuf,
+ MAX_TRACE_PATHBUF_LEN,
+ first_page->mapping->host);
+ trace_android_fs_dataread_start(
+ first_page->mapping->host,
+ page_offset(first_page),
+ bio->bi_iter.bi_size,
+ current->pid,
+ path,
+ current->comm);
+ }
+ }
bio->bi_end_io = mpage_end_io;
guard_bio_eod(rw, bio);
submit_bio(rw, bio);
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h
index 4fcacd915d45..e77f648f9662 100644
--- a/include/linux/shrinker.h
+++ b/include/linux/shrinker.h
@@ -66,6 +66,7 @@ struct shrinker {
/* Flags */
#define SHRINKER_NUMA_AWARE (1 << 0)
#define SHRINKER_MEMCG_AWARE (1 << 1)
+#define SHRINKER_LMK (1 << 2)
extern int register_shrinker(struct shrinker *);
extern void unregister_shrinker(struct shrinker *);
diff --git a/include/trace/events/android_fs.h b/include/trace/events/android_fs.h
new file mode 100644
index 000000000000..49509533d3fa
--- /dev/null
+++ b/include/trace/events/android_fs.h
@@ -0,0 +1,65 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM android_fs
+
+#if !defined(_TRACE_ANDROID_FS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ANDROID_FS_H
+
+#include <linux/tracepoint.h>
+#include <trace/events/android_fs_template.h>
+
+DEFINE_EVENT(android_fs_data_start_template, android_fs_dataread_start,
+ TP_PROTO(struct inode *inode, loff_t offset, int bytes,
+ pid_t pid, char *pathname, char *command),
+ TP_ARGS(inode, offset, bytes, pid, pathname, command));
+
+DEFINE_EVENT(android_fs_data_end_template, android_fs_dataread_end,
+ TP_PROTO(struct inode *inode, loff_t offset, int bytes),
+ TP_ARGS(inode, offset, bytes));
+
+DEFINE_EVENT(android_fs_data_start_template, android_fs_datawrite_start,
+ TP_PROTO(struct inode *inode, loff_t offset, int bytes,
+ pid_t pid, char *pathname, char *command),
+ TP_ARGS(inode, offset, bytes, pid, pathname, command));
+
+DEFINE_EVENT(android_fs_data_end_template, android_fs_datawrite_end,
+ TP_PROTO(struct inode *inode, loff_t offset, int bytes),
+ TP_ARGS(inode, offset, bytes));
+
+#endif /* _TRACE_ANDROID_FS_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
+
+#ifndef ANDROID_FSTRACE_GET_PATHNAME
+#define ANDROID_FSTRACE_GET_PATHNAME
+
+/* Sizes an on-stack array, so careful if sizing this up ! */
+#define MAX_TRACE_PATHBUF_LEN 256
+
+static inline char *
+android_fstrace_get_pathname(char *buf, int buflen, struct inode *inode)
+{
+ char *path;
+ struct dentry *d;
+
+ /*
+ * d_obtain_alias() will either iput() if it locates an existing
+ * dentry or transfer the reference to the new dentry created.
+ * So get an extra reference here.
+ */
+ ihold(inode);
+ d = d_obtain_alias(inode);
+ if (likely(!IS_ERR(d))) {
+ path = dentry_path_raw(d, buf, buflen);
+ if (unlikely(IS_ERR(path))) {
+ strcpy(buf, "ERROR");
+ path = buf;
+ }
+ dput(d);
+ } else {
+ strcpy(buf, "ERROR");
+ path = buf;
+ }
+ return path;
+}
+#endif
diff --git a/include/trace/events/android_fs_template.h b/include/trace/events/android_fs_template.h
new file mode 100644
index 000000000000..4e61ffe7a814
--- /dev/null
+++ b/include/trace/events/android_fs_template.h
@@ -0,0 +1,57 @@
+#if !defined(_TRACE_ANDROID_FS_TEMPLATE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ANDROID_FS_TEMPLATE_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(android_fs_data_start_template,
+ TP_PROTO(struct inode *inode, loff_t offset, int bytes,
+ pid_t pid, char *pathname, char *command),
+ TP_ARGS(inode, offset, bytes, pid, pathname, command),
+ TP_STRUCT__entry(
+ __string(pathbuf, pathname);
+ __field(loff_t, offset);
+ __field(int, bytes);
+ __field(loff_t, i_size);
+ __string(cmdline, command);
+ __field(pid_t, pid);
+ __field(ino_t, ino);
+ ),
+ TP_fast_assign(
+ {
+ __assign_str(pathbuf, pathname);
+ __entry->offset = offset;
+ __entry->bytes = bytes;
+ __entry->i_size = i_size_read(inode);
+ __assign_str(cmdline, command);
+ __entry->pid = pid;
+ __entry->ino = inode->i_ino;
+ }
+ ),
+ TP_printk("entry_name %s, offset %llu, bytes %d, cmdline %s,"
+ " pid %d, i_size %llu, ino %lu",
+ __get_str(pathbuf), __entry->offset, __entry->bytes,
+ __get_str(cmdline), __entry->pid, __entry->i_size,
+ (unsigned long) __entry->ino)
+);
+
+DECLARE_EVENT_CLASS(android_fs_data_end_template,
+ TP_PROTO(struct inode *inode, loff_t offset, int bytes),
+ TP_ARGS(inode, offset, bytes),
+ TP_STRUCT__entry(
+ __field(ino_t, ino);
+ __field(loff_t, offset);
+ __field(int, bytes);
+ ),
+ TP_fast_assign(
+ {
+ __entry->ino = inode->i_ino;
+ __entry->offset = offset;
+ __entry->bytes = bytes;
+ }
+ ),
+ TP_printk("ino %lu, offset %llu, bytes %d",
+ (unsigned long) __entry->ino,
+ __entry->offset, __entry->bytes)
+);
+
+#endif /* _TRACE_ANDROID_FS_TEMPLATE_H */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 5e9e74955bd1..94fecacf0ddc 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -399,6 +399,35 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
return freed;
}
+static void shrink_slab_lmk(gfp_t gfp_mask, int nid,
+ struct mem_cgroup *memcg,
+ unsigned long nr_scanned,
+ unsigned long nr_eligible)
+{
+ struct shrinker *shrinker;
+
+ if (nr_scanned == 0)
+ nr_scanned = SWAP_CLUSTER_MAX;
+
+ if (!down_read_trylock(&shrinker_rwsem))
+ goto out;
+
+ list_for_each_entry(shrinker, &shrinker_list, list) {
+ struct shrink_control sc = {
+ .gfp_mask = gfp_mask,
+ };
+
+ if (!(shrinker->flags & SHRINKER_LMK))
+ continue;
+
+ do_shrink_slab(&sc, shrinker, nr_scanned, nr_eligible);
+ }
+
+ up_read(&shrinker_rwsem);
+out:
+ cond_resched();
+}
+
/**
* shrink_slab - shrink slab caches
* @gfp_mask: allocation context
@@ -460,6 +489,9 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
.memcg = memcg,
};
+ if (shrinker->flags & SHRINKER_LMK)
+ continue;
+
if (memcg && !(shrinker->flags & SHRINKER_MEMCG_AWARE))
continue;
@@ -2626,6 +2658,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
gfp_t orig_mask;
enum zone_type requested_highidx = gfp_zone(sc->gfp_mask);
bool reclaimable = false;
+ unsigned long lru_pages = 0;
/*
* If the number of buffer_heads in the machine exceeds the maximum
@@ -2653,6 +2686,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
* to global LRU.
*/
if (global_reclaim(sc)) {
+ lru_pages += zone_reclaimable_pages(zone);
if (!cpuset_zone_allowed(zone,
GFP_KERNEL | __GFP_HARDWALL))
continue;
@@ -2703,6 +2737,9 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
reclaimable = true;
}
+ if (global_reclaim(sc))
+ shrink_slab_lmk(sc->gfp_mask, 0, NULL,
+ sc->nr_scanned, lru_pages);
/*
* Restore to original mask to avoid the impact on the caller if we
* promoted it to __GFP_HIGHMEM.
@@ -3181,7 +3218,8 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining,
*/
static bool kswapd_shrink_zone(struct zone *zone,
int classzone_idx,
- struct scan_control *sc)
+ struct scan_control *sc,
+ unsigned long lru_pages)
{
unsigned long balance_gap;
bool lowmem_pressure;
@@ -3208,6 +3246,8 @@ static bool kswapd_shrink_zone(struct zone *zone,
return true;
shrink_zone(zone, sc, zone_idx(zone) == classzone_idx);
+ shrink_slab_lmk(sc->gfp_mask, zone_to_nid(zone), NULL,
+ sc->nr_scanned, lru_pages);
clear_bit(ZONE_WRITEBACK, &zone->flags);
@@ -3265,6 +3305,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
do {
bool raise_priority = true;
+ unsigned long lru_pages = 0;
sc.nr_reclaimed = 0;
@@ -3322,6 +3363,15 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
if (sc.priority < DEF_PRIORITY - 2)
sc.may_writepage = 1;
+ for (i = 0; i <= end_zone; i++) {
+ struct zone *zone = pgdat->node_zones + i;
+
+ if (!populated_zone(zone))
+ continue;
+
+ lru_pages += zone_reclaimable_pages(zone);
+ }
+
/*
* Now scan the zone in the dma->highmem direction, stopping
* at the last zone which needs scanning.
@@ -3358,7 +3408,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
* that that high watermark would be met at 100%
* efficiency.
*/
- if (kswapd_shrink_zone(zone, end_zone, &sc))
+ if (kswapd_shrink_zone(zone, end_zone, &sc, lru_pages))
raise_priority = false;
}
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 0f09c68ab344..f6a5d1344568 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -4203,6 +4203,13 @@ static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
ret = -EINVAL;
goto err;
}
+
+ if (pinctrl_info->pinctrl == NULL) {
+ pr_err("%s: pinctrl_info->pinctrl is NULL\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
curr_state = pinctrl_info->curr_state;
pinctrl_info->curr_state = new_state;
pr_debug("%s: curr_state = %s new_state = %s\n", __func__,
@@ -4471,6 +4478,7 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
+ int ret_pinctrl = 0;
dev_dbg(rtd->card->dev,
"%s: substream = %s stream = %d, dai name %s, dai ID %d\n",
@@ -4485,11 +4493,10 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
goto done;
}
if (index == QUAT_MI2S) {
- ret = msm_set_pinctrl(pinctrl_info, STATE_MI2S_ACTIVE);
- if (ret) {
+ ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_MI2S_ACTIVE);
+ if (ret_pinctrl) {
pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
- __func__, ret);
- goto done;
+ __func__, ret_pinctrl);
}
}
@@ -4548,6 +4555,7 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
+ int ret_pinctrl = 0;
pr_debug("%s(): substream = %s stream = %d\n", __func__,
substream->name, substream->stream);
@@ -4568,10 +4576,10 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
mutex_unlock(&mi2s_intf_conf[index].lock);
if (index == QUAT_MI2S) {
- ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE);
- if (ret)
+ ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_DISABLE);
+ if (ret_pinctrl)
pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
- __func__, ret);
+ __func__, ret_pinctrl);
}
}
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 6616edcd3347..f0a78dc8aee8 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -5193,7 +5193,7 @@ static int afe_sidetone(u16 tx_port_id, u16 rx_port_id, bool enable)
AFE_API_VERSION_LOOPBACK_CONFIG;
cmd_sidetone.cfg_data.dst_port_id = rx_port_id;
cmd_sidetone.cfg_data.routing_mode = LB_MODE_SIDETONE;
- cmd_sidetone.cfg_data.enable = ((enable == 1) ? sidetone_enable : 0);
+ cmd_sidetone.cfg_data.enable = enable;
pr_debug("%s rx(0x%x) tx(0x%x) enable(%d) mid(0x%x) gain(%d) sidetone_enable(%d)\n",
__func__, rx_port_id, tx_port_id,