summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi35
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi35
-rw-r--r--arch/arm64/configs/msm-auto-perf_defconfig2
-rw-r--r--arch/arm64/configs/msm-auto_defconfig2
-rw-r--r--drivers/char/diag/diag_mux.c4
-rw-r--r--drivers/char/diag/diagchar_core.c7
-rw-r--r--drivers/char/diag/diagfwd.c5
-rw-r--r--drivers/clk/qcom/clk-cpu-osm.c4
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c7
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c38
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h3
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h4
-rw-r--r--drivers/gpu/drm/msm/msm_smmu.c70
-rw-r--r--drivers/gpu/drm/msm/sde/sde_core_irq.c18
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c62
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c8
-rw-r--r--drivers/gpu/drm/msm/sde/sde_irq.c26
-rw-r--r--drivers/gpu/drm/msm/sde/sde_splash.c11
-rw-r--r--drivers/gpu/drm/msm/sde/sde_trace.h18
-rw-r--r--drivers/gpu/drm/msm/sde_dbg.c195
-rw-r--r--drivers/gpu/drm/msm/sde_dbg.h35
-rw-r--r--drivers/gpu/drm/msm/sde_dbg_evtlog.c37
-rw-r--r--drivers/gpu/msm/adreno-gpulist.h18
-rw-r--r--drivers/gpu/msm/adreno.h4
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c20
-rw-r--r--drivers/media/i2c/adv7481.c2
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp.h1
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp47.c30
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c4
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp_util.c27
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode_i.h1
-rw-r--r--drivers/power/qcom/lpm-stats.c3
-rw-r--r--drivers/regulator/kryo-regulator.c5
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c2
-rw-r--r--drivers/scsi/ufs/ufshcd.c1
-rw-r--r--drivers/soc/qcom/hab/hab.c21
-rw-r--r--drivers/soc/qcom/hab/hab.h2
-rw-r--r--drivers/soc/qcom/hab/hab_qvm.c3
-rw-r--r--drivers/video/fbdev/msm/mdp3_ctrl.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c11
-rw-r--r--include/uapi/linux/habmm.h10
-rw-r--r--include/uapi/media/ais/msm_ais_isp.h5
-rw-r--r--sound/soc/msm/sdm660-common.c6
48 files changed, 693 insertions, 151 deletions
diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
index 9c6d12f38563..9e14211bdac8 100644
--- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
@@ -828,15 +828,14 @@
<&clock_mmss clk_camss_vfe0_ahb_clk>,
<&clock_mmss clk_camss_vfe1_ahb_clk>,
<&clock_mmss clk_camss_vfe_axi_clk>,
- <&clock_mmss clk_camss_vfe0_stream_clk>,
- <&clock_mmss clk_camss_vfe1_stream_clk>,
<&clock_mmss clk_smmu_vfe_axi_clk>,
<&clock_mmss clk_smmu_vfe_ahb_clk>,
- <&clock_mmss clk_camss_csi_vfe0_clk>,
- <&clock_mmss clk_camss_csi_vfe1_clk>,
<&clock_mmss clk_vfe0_clk_src>,
<&clock_mmss clk_vfe1_clk_src>,
+ <&clock_mmss clk_camss_vfe0_stream_clk>,
+ <&clock_mmss clk_camss_vfe1_stream_clk>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_camss_csi_vfe1_clk>,
<&clock_mmss clk_camss_csi2_ahb_clk>,
<&clock_mmss clk_camss_csi2_clk>,
<&clock_mmss clk_camss_csi2phy_clk>,
@@ -858,15 +857,14 @@
"camss_vfe0_ahb_clk",
"camss_vfe1_ahb_clk",
"camss_vfe_axi_clk",
- "camss_vfe0_stream_clk",
- "camss_vfe1_stream_clk",
"smmu_vfe_axi_clk",
"smmu_vfe_ahb_clk",
- "camss_csi_vfe0_clk",
- "camss_csi_vfe1_clk",
"vfe0_clk_src",
"vfe1_clk_src",
+ "camss_vfe0_stream_clk",
+ "camss_vfe1_stream_clk",
"camss_csi_vfe0_clk",
+ "camss_csi_vfe1_clk",
"camss_csi2_ahb_clk",
"camss_csi2_clk",
"camss_csi2phy_clk",
@@ -876,7 +874,6 @@
"camss_ispif_ahb_clk",
"clk_camss_vfe0_clk",
"clk_camss_vfe1_clk";
-
qcom,clock-rates = <19200000
19200000
19200000
@@ -890,13 +887,12 @@
320000000
0
0
+ 320000000
+ 320000000
0
0
0
0
- 320000000
- 320000000
- 0
0
200000000
200000000
@@ -906,6 +902,21 @@
0
100000000
100000000>;
+ qcom,clock-cntl-support;
+ qcom,clock-control = "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "INIT_RATE",
+ "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE","NO_SET_RATE",
+ "INIT_RATE","NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE","NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE";
};
qcom,ntn_avb {
diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
index 0c648a93aaab..5c08acbbcd19 100644
--- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
@@ -593,15 +593,14 @@
<&clock_mmss clk_camss_vfe0_ahb_clk>,
<&clock_mmss clk_camss_vfe1_ahb_clk>,
<&clock_mmss clk_camss_vfe_axi_clk>,
- <&clock_mmss clk_camss_vfe0_stream_clk>,
- <&clock_mmss clk_camss_vfe1_stream_clk>,
<&clock_mmss clk_smmu_vfe_axi_clk>,
<&clock_mmss clk_smmu_vfe_ahb_clk>,
- <&clock_mmss clk_camss_csi_vfe0_clk>,
- <&clock_mmss clk_camss_csi_vfe1_clk>,
<&clock_mmss clk_vfe0_clk_src>,
<&clock_mmss clk_vfe1_clk_src>,
+ <&clock_mmss clk_camss_vfe0_stream_clk>,
+ <&clock_mmss clk_camss_vfe1_stream_clk>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_camss_csi_vfe1_clk>,
<&clock_mmss clk_camss_csi2_ahb_clk>,
<&clock_mmss clk_camss_csi2_clk>,
<&clock_mmss clk_camss_csi2phy_clk>,
@@ -623,15 +622,14 @@
"camss_vfe0_ahb_clk",
"camss_vfe1_ahb_clk",
"camss_vfe_axi_clk",
- "camss_vfe0_stream_clk",
- "camss_vfe1_stream_clk",
"smmu_vfe_axi_clk",
"smmu_vfe_ahb_clk",
- "camss_csi_vfe0_clk",
- "camss_csi_vfe1_clk",
"vfe0_clk_src",
"vfe1_clk_src",
+ "camss_vfe0_stream_clk",
+ "camss_vfe1_stream_clk",
"camss_csi_vfe0_clk",
+ "camss_csi_vfe1_clk",
"camss_csi2_ahb_clk",
"camss_csi2_clk",
"camss_csi2phy_clk",
@@ -641,7 +639,6 @@
"camss_ispif_ahb_clk",
"clk_camss_vfe0_clk",
"clk_camss_vfe1_clk";
-
qcom,clock-rates = <19200000
19200000
19200000
@@ -655,13 +652,12 @@
320000000
0
0
+ 320000000
+ 320000000
0
0
0
0
- 320000000
- 320000000
- 0
0
200000000
200000000
@@ -671,6 +667,21 @@
0
100000000
100000000>;
+ qcom,clock-cntl-support;
+ qcom,clock-control = "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "INIT_RATE",
+ "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE","NO_SET_RATE",
+ "INIT_RATE","NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE","NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE";
};
ntn1: ntn_avb@1 { /* Neutrno device on RC1*/
diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig
index 44d4c072dd29..a8d66b122429 100644
--- a/arch/arm64/configs/msm-auto-perf_defconfig
+++ b/arch/arm64/configs/msm-auto-perf_defconfig
@@ -387,7 +387,7 @@ CONFIG_MSM_AIS_DEBUG=y
CONFIG_MSM_AIS_CAMERA_SENSOR=y
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
CONFIG_VIDEO_ADV7481=m
-CONFIG_VIDEO_TVTUNER=y
+CONFIG_VIDEO_TVTUNER=m
CONFIG_QCOM_KGSL=y
CONFIG_DRM=y
CONFIG_MSM_BA_V4L2=y
diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig
index b691690187c2..3a7e60990a81 100644
--- a/arch/arm64/configs/msm-auto_defconfig
+++ b/arch/arm64/configs/msm-auto_defconfig
@@ -391,7 +391,7 @@ CONFIG_MSM_AIS_DEBUG=y
CONFIG_MSM_AIS_CAMERA_SENSOR=y
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
CONFIG_VIDEO_ADV7481=m
-CONFIG_VIDEO_TVTUNER=y
+CONFIG_VIDEO_TVTUNER=m
CONFIG_QCOM_KGSL=y
CONFIG_DRM=y
CONFIG_MSM_BA_V4L2=y
diff --git a/drivers/char/diag/diag_mux.c b/drivers/char/diag/diag_mux.c
index 8cc803eef552..8d766e1ae583 100644
--- a/drivers/char/diag/diag_mux.c
+++ b/drivers/char/diag/diag_mux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -239,6 +239,8 @@ int diag_mux_switch_logging(int *req_mode, int *peripheral_mask)
new_mask = ~(*peripheral_mask) & diag_mux->mux_mask;
if (new_mask != DIAG_CON_NONE)
*req_mode = DIAG_MULTI_MODE;
+ if (new_mask == DIAG_CON_ALL)
+ *req_mode = DIAG_MEMORY_DEVICE_MODE;
break;
case DIAG_MEMORY_DEVICE_MODE:
new_mask = (*peripheral_mask) | diag_mux->mux_mask;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 678e3a2b051c..4885412dd014 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1710,19 +1710,20 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param)
return -EINVAL;
}
+ i = upd - UPD_WLAN;
+
if (driver->md_session_map[peripheral] &&
(MD_PERIPHERAL_MASK(peripheral) &
- diag_mux->mux_mask)) {
+ diag_mux->mux_mask) &&
+ !driver->pd_session_clear[i]) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"diag_fr: User PD is already logging onto active peripheral logging\n");
- i = upd - UPD_WLAN;
driver->pd_session_clear[i] = 0;
return -EINVAL;
}
peripheral_mask =
diag_translate_mask(param->pd_mask);
param->peripheral_mask = peripheral_mask;
- i = upd - UPD_WLAN;
if (!driver->pd_session_clear[i]) {
driver->pd_logging_mode[i] = 1;
driver->num_pd_session += 1;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index f876489e202d..f6027ae96833 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1003,8 +1003,11 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
} else {
mutex_unlock(&driver->md_session_lock);
if (MD_PERIPHERAL_MASK(reg_item->proc) &
- driver->logging_mask)
+ driver->logging_mask) {
+ mutex_unlock(&driver->cmd_reg_mutex);
diag_send_error_rsp(buf, len, pid);
+ return write_len;
+ }
else
write_len = diag_send_data(reg_item, buf, len);
}
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index 510a9803bd82..68f4afde0d0c 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2691,7 +2691,7 @@ static ssize_t debugfs_trace_method_get(struct file *file, char __user *buf,
else if (c->trace_method == XOR_PACKET)
len = snprintf(debug_buf, sizeof(debug_buf), "xor\n");
- rc = simple_read_from_buffer((void __user *) buf, len, ppos,
+ rc = simple_read_from_buffer((void __user *) buf, count, ppos,
(void *) debug_buf, len);
mutex_unlock(&debug_buf_mutex);
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 0c119ec5d97c..7d40f38092d4 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2014 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -562,6 +562,11 @@ int msm_atomic_commit(struct drm_device *dev,
struct msm_commit *commit;
int i, ret;
+ if (!priv || priv->shutdown_in_progress) {
+ DRM_ERROR("priv is null or shutdwon is in-progress\n");
+ return -EINVAL;
+ }
+
SDE_ATRACE_BEGIN("atomic_commit");
ret = drm_atomic_helper_prepare_planes(dev, state);
if (ret) {
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 6f968e93d959..b57663013dcb 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -439,6 +439,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
struct msm_kms *kms;
struct sde_dbg_power_ctrl dbg_power_ctrl = { NULL };
int ret, i;
+ struct sched_param param;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
@@ -532,7 +533,12 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
goto fail;
}
}
-
+ /**
+ * this priority was found during empiric testing to have appropriate
+ * realtime scheduling to process display updates and interact with
+ * other real time and normal priority task
+ */
+ param.sched_priority = 16;
/* initialize commit thread structure */
for (i = 0; i < priv->num_crtcs; i++) {
priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id;
@@ -543,6 +549,11 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
&priv->disp_thread[i].worker,
"crtc_commit:%d",
priv->disp_thread[i].crtc_id);
+ ret = sched_setscheduler(priv->disp_thread[i].thread,
+ SCHED_FIFO, &param);
+ if (ret)
+ pr_warn("display thread priority update failed: %d\n",
+ ret);
if (IS_ERR(priv->disp_thread[i].thread)) {
dev_err(dev->dev, "failed to create kthread\n");
@@ -2199,6 +2210,28 @@ static const struct platform_device_id msm_id[] = {
{ }
};
+static void msm_pdev_shutdown(struct platform_device *pdev)
+{
+ struct drm_device *ddev = platform_get_drvdata(pdev);
+ struct msm_drm_private *priv = NULL;
+
+ if (!ddev) {
+ DRM_ERROR("invalid drm device node\n");
+ return;
+ }
+
+ priv = ddev->dev_private;
+ if (!priv) {
+ DRM_ERROR("invalid msm drm private node\n");
+ return;
+ }
+
+ msm_lastclose(ddev);
+
+ /* set this after lastclose to allow kickoff from lastclose */
+ priv->shutdown_in_progress = true;
+}
+
static const struct of_device_id dt_match[] = {
{ .compatible = "qcom,mdp" }, /* mdp4 */
{ .compatible = "qcom,sde-kms" }, /* sde */
@@ -2209,6 +2242,7 @@ MODULE_DEVICE_TABLE(of, dt_match);
static struct platform_driver msm_platform_driver = {
.probe = msm_pdev_probe,
.remove = msm_pdev_remove,
+ .shutdown = msm_pdev_shutdown,
.driver = {
.name = "msm_drm",
.of_match_table = dt_match,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index fb24b833082c..e0ac0582e791 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -375,6 +375,9 @@ struct msm_drm_private {
/* list of clients waiting for events */
struct list_head client_event_list;
+
+ /* update the flag when msm driver receives shutdown notification */
+ bool shutdown_in_progress;
};
struct msm_format {
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index cd3a710f8f27..74dea95d90de 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -46,6 +46,10 @@ struct msm_mmu_funcs {
void (*destroy)(struct msm_mmu *mmu);
void (*enable)(struct msm_mmu *mmu);
void (*disable)(struct msm_mmu *mmu);
+ int (*early_splash_map)(struct msm_mmu *mmu, uint64_t iova,
+ struct sg_table *sgt, u32 flags);
+ void (*early_splash_unmap)(struct msm_mmu *mmu, uint64_t iova,
+ struct sg_table *sgt);
int (*set_property)(struct msm_mmu *mmu,
enum iommu_attr attr, void *data);
};
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index 4247243055b6..aefbe0988fe5 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -120,30 +120,19 @@ static int msm_smmu_map(struct msm_mmu *mmu, uint64_t iova,
{
struct msm_smmu *smmu = to_msm_smmu(mmu);
struct msm_smmu_client *client = msm_smmu_to_client(smmu);
- struct iommu_domain *domain;
int ret;
if (!client || !sgt)
return -EINVAL;
- if (iova != 0) {
- if (!client->mmu_mapping || !client->mmu_mapping->domain)
- return -EINVAL;
-
- domain = client->mmu_mapping->domain;
-
- return iommu_map_sg(domain, iova, sgt->sgl,
- sgt->nents, flags);
- } else {
- if (priv)
- ret = msm_dma_map_sg_lazy(client->dev, sgt->sgl,
- sgt->nents, DMA_BIDIRECTIONAL, priv);
- else
- ret = dma_map_sg(client->dev, sgt->sgl, sgt->nents,
- DMA_BIDIRECTIONAL);
+ if (priv)
+ ret = msm_dma_map_sg_lazy(client->dev, sgt->sgl,
+ sgt->nents, DMA_BIDIRECTIONAL, priv);
+ else
+ ret = dma_map_sg(client->dev, sgt->sgl, sgt->nents,
+ DMA_BIDIRECTIONAL);
- return (ret != sgt->nents) ? -ENOMEM : 0;
- }
+ return (ret != sgt->nents) ? -ENOMEM : 0;
}
static void msm_smmu_unmap(struct msm_mmu *mmu, uint64_t iova,
@@ -160,6 +149,47 @@ static void msm_smmu_unmap(struct msm_mmu *mmu, uint64_t iova,
DMA_BIDIRECTIONAL);
}
+static int msm_smmu_early_splash_map(struct msm_mmu *mmu, uint64_t iova,
+ struct sg_table *sgt, u32 flags)
+{
+ struct msm_smmu *smmu = to_msm_smmu(mmu);
+ struct msm_smmu_client *client = msm_smmu_to_client(smmu);
+ struct iommu_domain *domain;
+
+ if (!client || !sgt)
+ return -EINVAL;
+
+ if (!client->mmu_mapping || !client->mmu_mapping->domain)
+ return -EINVAL;
+
+ domain = client->mmu_mapping->domain;
+
+ return iommu_map_sg(domain, iova, sgt->sgl, sgt->nents, flags);
+}
+
+static void msm_smmu_early_splash_unmap(struct msm_mmu *mmu, uint64_t iova,
+ struct sg_table *sgt)
+{
+ struct msm_smmu *smmu = to_msm_smmu(mmu);
+ struct msm_smmu_client *client = msm_smmu_to_client(smmu);
+ struct iommu_domain *domain;
+ struct scatterlist *sg;
+ size_t len = 0;
+ int unmapped, i = 0;
+
+ if (!client || !client->mmu_mapping || !client->mmu_mapping->domain)
+ return;
+
+ domain = client->mmu_mapping->domain;
+
+ for_each_sg(sgt->sgl, sg, sgt->nents, i)
+ len += sg->length;
+
+ unmapped = iommu_unmap(domain, iova, len);
+ if (unmapped < len)
+ DRM_ERROR("could not unmap iova@%llx\n", iova);
+}
+
static void msm_smmu_destroy(struct msm_mmu *mmu)
{
struct msm_smmu *smmu = to_msm_smmu(mmu);
@@ -199,6 +229,8 @@ static const struct msm_mmu_funcs funcs = {
.map = msm_smmu_map,
.unmap = msm_smmu_unmap,
.destroy = msm_smmu_destroy,
+ .early_splash_map = msm_smmu_early_splash_map,
+ .early_splash_unmap = msm_smmu_early_splash_unmap,
.set_property = msm_smmu_set_property,
};
diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.c b/drivers/gpu/drm/msm/sde/sde_core_irq.c
index 83c8982b2e00..4f7e688650de 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_irq.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_irq.c
@@ -31,23 +31,35 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx)
struct sde_irq *irq_obj = &sde_kms->irq_obj;
struct sde_irq_callback *cb;
unsigned long irq_flags;
+ bool cb_tbl_error = false;
+ int enable_counts = 0;
pr_debug("irq_idx=%d\n", irq_idx);
- if (list_empty(&irq_obj->irq_cb_tbl[irq_idx]))
- SDE_ERROR("irq_idx=%d has no registered callback\n", irq_idx);
+ spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
+ if (list_empty(&irq_obj->irq_cb_tbl[irq_idx])) {
+ /* print error outside lock */
+ cb_tbl_error = true;
+ enable_counts = atomic_read(
+ &sde_kms->irq_obj.enable_counts[irq_idx]);
+ }
atomic_inc(&irq_obj->irq_counts[irq_idx]);
/*
* Perform registered function callback
*/
- spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
list_for_each_entry(cb, &irq_obj->irq_cb_tbl[irq_idx], list)
if (cb->func)
cb->func(cb->arg, irq_idx);
spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags);
+ if (cb_tbl_error) {
+ SDE_ERROR("irq has no registered callback, idx %d enables %d\n",
+ irq_idx, enable_counts);
+ SDE_EVT32_IRQ(irq_idx, enable_counts, SDE_EVTLOG_ERROR);
+ }
+
/*
* Clear pending interrupt status in HW.
* NOTE: sde_core_irq_callback_handler is protected by top-level
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 96ef909e14f4..ea3f138ee461 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -1441,43 +1441,67 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
goto end;
}
- /*
- * enforce pipe priority restrictions
+ /* validate source split:
* use pstates sorted by stage to check planes on same stage
* we assume that all pipes are in source split so its valid to compare
* without taking into account left/right mixer placement
*/
for (i = 1; i < cnt; i++) {
struct plane_state *prv_pstate, *cur_pstate;
- int32_t prv_x, cur_x, prv_id, cur_id;
+ struct sde_rect left_rect, right_rect;
+ int32_t left_pid, right_pid;
+ int32_t stage;
prv_pstate = &pstates[i - 1];
cur_pstate = &pstates[i];
if (prv_pstate->stage != cur_pstate->stage)
continue;
- prv_x = prv_pstate->drm_pstate->crtc_x;
- cur_x = cur_pstate->drm_pstate->crtc_x;
- prv_id = prv_pstate->sde_pstate->base.plane->base.id;
- cur_id = cur_pstate->sde_pstate->base.plane->base.id;
+ stage = cur_pstate->stage;
- /*
- * Planes are enumerated in pipe-priority order such that planes
- * with lower drm_id must be left-most in a shared blend-stage
- * when using source split.
+ left_pid = prv_pstate->sde_pstate->base.plane->base.id;
+ POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x,
+ prv_pstate->drm_pstate->crtc_y,
+ prv_pstate->drm_pstate->crtc_w,
+ prv_pstate->drm_pstate->crtc_h, false);
+
+ right_pid = cur_pstate->sde_pstate->base.plane->base.id;
+ POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x,
+ cur_pstate->drm_pstate->crtc_y,
+ cur_pstate->drm_pstate->crtc_w,
+ cur_pstate->drm_pstate->crtc_h, false);
+
+ if (right_rect.x < left_rect.x) {
+ swap(left_pid, right_pid);
+ swap(left_rect, right_rect);
+ }
+
+ /**
+ * - planes are enumerated in pipe-priority order such that
+ * planes with lower drm_id must be left-most in a shared
+ * blend-stage when using source split.
+ * - planes in source split must be contiguous in width
+ * - planes in source split must have same dest yoff and height
*/
- if (cur_x > prv_x && cur_id < prv_id) {
+ if (right_pid < left_pid) {
+ SDE_ERROR(
+ "invalid src split cfg. priority mismatch. stage: %d left: %d right: %d\n",
+ stage, left_pid, right_pid);
+ rc = -EINVAL;
+ goto end;
+ } else if (right_rect.x != (left_rect.x + left_rect.w)) {
SDE_ERROR(
- "shared z_pos %d lower id plane%d @ x%d should be left of plane%d @ x %d\n",
- cur_pstate->stage, cur_id, cur_x,
- prv_id, prv_x);
+ "non-contiguous coordinates for src split. stage: %d left: %d - %d right: %d - %d\n",
+ stage, left_rect.x, left_rect.w,
+ right_rect.x, right_rect.w);
rc = -EINVAL;
goto end;
- } else if (cur_x < prv_x && cur_id > prv_id) {
+ } else if ((left_rect.y != right_rect.y) ||
+ (left_rect.h != right_rect.h)) {
SDE_ERROR(
- "shared z_pos %d lower id plane%d @ x%d should be left of plane%d @ x %d\n",
- cur_pstate->stage, prv_id, prv_x,
- cur_id, cur_x);
+ "source split at stage: %d. invalid yoff/height: l_y: %d r_y: %d l_h: %d r_h: %d\n",
+ stage, left_rect.y, right_rect.y,
+ left_rect.h, right_rect.h);
rc = -EINVAL;
goto end;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 6e4de62c6957..fa17768d9939 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -602,6 +602,12 @@ static void sde_encoder_underrun_callback(struct drm_encoder *drm_enc,
SDE_ATRACE_BEGIN("encoder_underrun_callback");
atomic_inc(&phy_enc->underrun_cnt);
SDE_EVT32(DRMID(drm_enc), atomic_read(&phy_enc->underrun_cnt));
+
+ trace_sde_encoder_underrun(DRMID(drm_enc),
+ atomic_read(&phy_enc->underrun_cnt));
+ SDE_DBG_CTRL("stop_ftrace");
+ SDE_DBG_CTRL("panic_underrun");
+
SDE_ATRACE_END("encoder_underrun_callback");
}
diff --git a/drivers/gpu/drm/msm/sde/sde_irq.c b/drivers/gpu/drm/msm/sde/sde_irq.c
index eeb7a0002eab..7864b9fef87b 100644
--- a/drivers/gpu/drm/msm/sde/sde_irq.c
+++ b/drivers/gpu/drm/msm/sde/sde_irq.c
@@ -19,6 +19,8 @@
#include "sde_irq.h"
#include "sde_core_irq.h"
+static uint32_t g_sde_irq_status;
+
irqreturn_t sde_irq(struct msm_kms *kms)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
@@ -27,6 +29,9 @@ irqreturn_t sde_irq(struct msm_kms *kms)
sde_kms->hw_intr->ops.get_interrupt_sources(sde_kms->hw_intr,
&interrupts);
+ /* store irq status in case of irq-storm debugging */
+ g_sde_irq_status = interrupts;
+
/*
* Taking care of MDP interrupt
*/
@@ -40,13 +45,30 @@ irqreturn_t sde_irq(struct msm_kms *kms)
*/
while (interrupts) {
irq_hw_number_t hwirq = fls(interrupts) - 1;
+ unsigned int mapping;
+ int rc;
+
+ mapping = irq_find_mapping(sde_kms->irq_controller.domain,
+ hwirq);
+ if (mapping == 0) {
+ SDE_EVT32(hwirq, SDE_EVTLOG_ERROR);
+ goto error;
+ }
+
+ rc = generic_handle_irq(mapping);
+ if (rc < 0) {
+ SDE_EVT32(hwirq, mapping, rc, SDE_EVTLOG_ERROR);
+ goto error;
+ }
- generic_handle_irq(irq_find_mapping(
- sde_kms->irq_controller.domain, hwirq));
interrupts &= ~(1 << hwirq);
}
return IRQ_HANDLED;
+
+error:
+ /* bad situation, inform irq system, it may disable overall MDSS irq */
+ return IRQ_NONE;
}
void sde_irq_preinstall(struct msm_kms *kms)
diff --git a/drivers/gpu/drm/msm/sde/sde_splash.c b/drivers/gpu/drm/msm/sde/sde_splash.c
index 19e6406600cd..2789ae053663 100644
--- a/drivers/gpu/drm/msm/sde/sde_splash.c
+++ b/drivers/gpu/drm/msm/sde/sde_splash.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -301,8 +301,8 @@ static int _sde_splash_free_resource(struct msm_mmu *mmu,
return -EINVAL;
if (mmu->funcs && mmu->funcs->unmap)
- mmu->funcs->unmap(mmu, sinfo->splash_mem_paddr[conn],
- msm_obj->sgt, NULL);
+ mmu->funcs->early_splash_unmap(mmu,
+ sinfo->splash_mem_paddr[conn], msm_obj->sgt);
_sde_splash_free_bootup_memory_to_system(sinfo->splash_mem_paddr[conn],
sinfo->splash_mem_size[conn]);
@@ -489,8 +489,9 @@ int sde_splash_smmu_map(struct drm_device *dev, struct msm_mmu *mmu,
msm_obj = to_msm_bo(sinfo->obj[i]);
if (mmu->funcs && mmu->funcs->map) {
- ret = mmu->funcs->map(mmu, sinfo->splash_mem_paddr[i],
- msm_obj->sgt, IOMMU_READ | IOMMU_NOEXEC, NULL);
+ ret = mmu->funcs->early_splash_map(mmu,
+ sinfo->splash_mem_paddr[i], msm_obj->sgt,
+ IOMMU_READ | IOMMU_NOEXEC);
if (!ret) {
SDE_ERROR("Map blk %d @%pK failed.\n",
diff --git a/drivers/gpu/drm/msm/sde/sde_trace.h b/drivers/gpu/drm/msm/sde/sde_trace.h
index 2a4e6b59a08c..d28562eabccb 100644
--- a/drivers/gpu/drm/msm/sde/sde_trace.h
+++ b/drivers/gpu/drm/msm/sde/sde_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -125,6 +125,22 @@ TRACE_EVENT(sde_cmd_release_bw,
TP_printk("crtc:%d", __entry->crtc_id)
);
+TRACE_EVENT(sde_encoder_underrun,
+ TP_PROTO(u32 enc_id, u32 underrun_cnt),
+ TP_ARGS(enc_id, underrun_cnt),
+ TP_STRUCT__entry(
+ __field(u32, enc_id)
+ __field(u32, underrun_cnt)
+ ),
+ TP_fast_assign(
+ __entry->enc_id = enc_id;
+ __entry->underrun_cnt = underrun_cnt;
+
+ ),
+ TP_printk("enc:%d underrun_cnt:%d", __entry->enc_id,
+ __entry->underrun_cnt)
+);
+
TRACE_EVENT(sde_mark_write,
TP_PROTO(int pid, const char *name, bool trace_begin),
TP_ARGS(pid, name, trace_begin),
diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c
index ea133619cf62..c886950e5212 100644
--- a/drivers/gpu/drm/msm/sde_dbg.c
+++ b/drivers/gpu/drm/msm/sde_dbg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -57,6 +57,9 @@
/* print debug ranges in groups of 4 u32s */
#define REG_DUMP_ALIGN 16
+#define DBG_CTRL_STOP_FTRACE BIT(0)
+#define DBG_CTRL_PANIC_UNDERRUN BIT(1)
+#define DBG_CTRL_MAX BIT(2)
/**
* struct sde_dbg_reg_offset - tracking for start and end of region
@@ -162,6 +165,7 @@ struct sde_dbg_vbif_debug_bus {
* @enable_reg_dump: whether to dump registers into memory, kernel log, or both
* @dbgbus_sde: debug bus structure for the sde
* @dbgbus_vbif_rt: debug bus structure for the realtime vbif
+ * @dump_all: dump all entries in register dump
*/
static struct sde_dbg_base {
struct sde_dbg_evtlog *evtlog;
@@ -180,6 +184,8 @@ static struct sde_dbg_base {
struct sde_dbg_sde_debug_bus dbgbus_sde;
struct sde_dbg_vbif_debug_bus dbgbus_vbif_rt;
+ bool dump_all;
+ u32 debugfs_ctrl;
} sde_dbg_base;
/* sde_dbg_base_evtlog - global pointer to main sde event log for macro use */
@@ -1448,7 +1454,7 @@ static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus)
*/
static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[],
u32 len, bool do_panic, const char *name, bool dump_dbgbus_sde,
- bool dump_dbgbus_vbif_rt)
+ bool dump_dbgbus_vbif_rt, bool dump_all)
{
int i;
@@ -1460,7 +1466,8 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[],
sde_dbg_base.enable_reg_dump);
}
- sde_evtlog_dump_all(sde_dbg_base.evtlog);
+ if (dump_all)
+ sde_evtlog_dump_all(sde_dbg_base.evtlog);
if (dump_dbgbus_sde)
_sde_dbg_dump_sde_dbg_bus(&sde_dbg_base.dbgbus_sde);
@@ -1484,7 +1491,8 @@ static void _sde_dump_work(struct work_struct *work)
ARRAY_SIZE(sde_dbg_base.req_dump_blks),
sde_dbg_base.work_panic, "evtlog_workitem",
sde_dbg_base.dbgbus_sde.cmn.include_in_deferred_work,
- sde_dbg_base.dbgbus_vbif_rt.cmn.include_in_deferred_work);
+ sde_dbg_base.dbgbus_vbif_rt.cmn.include_in_deferred_work,
+ sde_dbg_base.dump_all);
}
void sde_dbg_dump(bool queue_work, const char *name, ...)
@@ -1493,6 +1501,7 @@ void sde_dbg_dump(bool queue_work, const char *name, ...)
bool do_panic = false;
bool dump_dbgbus_sde = false;
bool dump_dbgbus_vbif_rt = false;
+ bool dump_all = false;
va_list args;
char *blk_name = NULL;
struct sde_dbg_reg_base *blk_base = NULL;
@@ -1510,6 +1519,7 @@ void sde_dbg_dump(bool queue_work, const char *name, ...)
memset(sde_dbg_base.req_dump_blks, 0,
sizeof(sde_dbg_base.req_dump_blks));
+ sde_dbg_base.dump_all = false;
va_start(args, name);
i = 0;
@@ -1531,6 +1541,8 @@ void sde_dbg_dump(bool queue_work, const char *name, ...)
blk_name);
}
}
+ if (!strcmp(blk_name, "all"))
+ dump_all = true;
if (!strcmp(blk_name, "dbg_bus"))
dump_dbgbus_sde = true;
@@ -1550,11 +1562,51 @@ void sde_dbg_dump(bool queue_work, const char *name, ...)
dump_dbgbus_sde;
sde_dbg_base.dbgbus_vbif_rt.cmn.include_in_deferred_work =
dump_dbgbus_vbif_rt;
+ sde_dbg_base.dump_all = dump_all;
schedule_work(&sde_dbg_base.dump_work);
} else {
_sde_dump_array(blk_arr, blk_len, do_panic, name,
- dump_dbgbus_sde, dump_dbgbus_vbif_rt);
+ dump_dbgbus_sde, dump_dbgbus_vbif_rt, dump_all);
+ }
+}
+
+void sde_dbg_ctrl(const char *name, ...)
+{
+ int i = 0;
+ va_list args;
+ char *blk_name = NULL;
+
+
+ /* no debugfs controlled events are enabled, just return */
+ if (!sde_dbg_base.debugfs_ctrl)
+ return;
+
+ va_start(args, name);
+
+ while ((blk_name = va_arg(args, char*))) {
+ if (i++ >= SDE_EVTLOG_MAX_DATA) {
+ pr_err("could not parse all dbg arguments\n");
+ break;
+ }
+
+ if (IS_ERR_OR_NULL(blk_name))
+ break;
+
+ if (!strcmp(blk_name, "stop_ftrace") &&
+ sde_dbg_base.debugfs_ctrl &
+ DBG_CTRL_STOP_FTRACE) {
+ pr_debug("tracing off\n");
+ tracing_off();
+ }
+
+ if (!strcmp(blk_name, "panic_underrun") &&
+ sde_dbg_base.debugfs_ctrl &
+ DBG_CTRL_PANIC_UNDERRUN) {
+ pr_debug("panic underrun\n");
+ panic("underrun");
+ }
}
+
}
/*
@@ -1564,6 +1616,9 @@ void sde_dbg_dump(bool queue_work, const char *name, ...)
*/
static int sde_dbg_debugfs_open(struct inode *inode, struct file *file)
{
+ if (!inode || !file)
+ return -EINVAL;
+
/* non-seekable */
file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
file->private_data = inode->i_private;
@@ -1583,8 +1638,11 @@ static ssize_t sde_evtlog_dump_read(struct file *file, char __user *buff,
ssize_t len = 0;
char evtlog_buf[SDE_EVTLOG_BUF_MAX];
+ if (!buff || !ppos)
+ return -EINVAL;
+
len = sde_evtlog_dump_to_buffer(sde_dbg_base.evtlog, evtlog_buf,
- SDE_EVTLOG_BUF_MAX);
+ SDE_EVTLOG_BUF_MAX, true);
if (copy_to_user(buff, evtlog_buf, len))
return -EFAULT;
*ppos += len;
@@ -1621,6 +1679,82 @@ static const struct file_operations sde_evtlog_fops = {
.write = sde_evtlog_dump_write,
};
+/**
+ * sde_dbg_ctrl_read - debugfs read handler for debug ctrl read
+ * @file: file handler
+ * @buff: user buffer content for debugfs
+ * @count: size of user buffer
+ * @ppos: position offset of user buffer
+ */
+static ssize_t sde_dbg_ctrl_read(struct file *file, char __user *buff,
+ size_t count, loff_t *ppos)
+{
+ ssize_t len = 0;
+ char buf[24] = {'\0'};
+
+ if (!buff || !ppos)
+ return -EINVAL;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(buf, sizeof(buf), "0x%x\n", sde_dbg_base.debugfs_ctrl);
+ pr_debug("%s: ctrl:0x%x len:0x%zx\n",
+ __func__, sde_dbg_base.debugfs_ctrl, len);
+
+ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) {
+ pr_err("error copying the buffer! count:0x%zx\n", count);
+ return -EFAULT;
+ }
+
+ *ppos += len; /* increase offset */
+ return len;
+}
+
+/**
+ * sde_dbg_ctrl_write - debugfs read handler for debug ctrl write
+ * @file: file handler
+ * @user_buf: user buffer content from debugfs
+ * @count: size of user buffer
+ * @ppos: position offset of user buffer
+ */
+static ssize_t sde_dbg_ctrl_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ u32 dbg_ctrl = 0;
+ char buf[24];
+
+ if (!file) {
+ pr_err("DbgDbg: %s: error no file --\n", __func__);
+ return -EINVAL;
+ }
+
+ if (count >= sizeof(buf))
+ return -EFAULT;
+
+
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+
+ buf[count] = 0; /* end of string */
+
+ if (kstrtouint(buf, 0, &dbg_ctrl)) {
+ pr_err("%s: error in the number of bytes\n", __func__);
+ return -EFAULT;
+ }
+
+ pr_debug("dbg_ctrl_read:0x%x\n", dbg_ctrl);
+ sde_dbg_base.debugfs_ctrl = dbg_ctrl;
+
+ return count;
+}
+
+static const struct file_operations sde_dbg_ctrl_fops = {
+ .open = sde_dbg_debugfs_open,
+ .read = sde_dbg_ctrl_read,
+ .write = sde_dbg_ctrl_write,
+};
+
void sde_dbg_init_dbg_buses(u32 hwversion)
{
static struct sde_dbg_base *dbg = &sde_dbg_base;
@@ -1695,6 +1829,8 @@ int sde_dbg_init(struct dentry *debugfs_root, struct device *dev,
for (i = 0; i < SDE_EVTLOG_ENTRY; i++)
sde_dbg_base.evtlog->logs[i].counter = i;
+ debugfs_create_file("dbg_ctrl", 0600, sde_dbg_base.root, NULL,
+ &sde_dbg_ctrl_fops);
debugfs_create_file("dump", 0600, sde_dbg_base.root, NULL,
&sde_evtlog_fops);
debugfs_create_u32("enable", 0600, sde_dbg_base.root,
@@ -1736,7 +1872,14 @@ void sde_dbg_destroy(void)
*/
static int sde_dbg_reg_base_release(struct inode *inode, struct file *file)
{
- struct sde_dbg_reg_base *dbg = file->private_data;
+ struct sde_dbg_reg_base *dbg;
+
+ if (!file)
+ return -EINVAL;
+
+ dbg = file->private_data;
+ if (!dbg)
+ return -ENODEV;
mutex_lock(&sde_dbg_base.mutex);
if (dbg && dbg->buf) {
@@ -1760,12 +1903,16 @@ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file)
static ssize_t sde_dbg_reg_base_offset_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
- struct sde_dbg_reg_base *dbg = file->private_data;
+ struct sde_dbg_reg_base *dbg;
u32 off = 0;
u32 cnt = DEFAULT_BASE_REG_CNT;
char buf[24];
ssize_t rc = count;
+ if (!file)
+ return -EINVAL;
+
+ dbg = file->private_data;
if (!dbg)
return -ENODEV;
@@ -1799,6 +1946,9 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file,
goto exit;
}
+ if (cnt == 0)
+ return -EINVAL;
+
dbg->off = off;
dbg->cnt = cnt;
@@ -1819,17 +1969,29 @@ exit:
static ssize_t sde_dbg_reg_base_offset_read(struct file *file,
char __user *buff, size_t count, loff_t *ppos)
{
- struct sde_dbg_reg_base *dbg = file->private_data;
+ struct sde_dbg_reg_base *dbg;
int len = 0;
char buf[24] = {'\0'};
+ if (!file)
+ return -EINVAL;
+
+ dbg = file->private_data;
if (!dbg)
return -ENODEV;
+ if (!ppos)
+ return -EINVAL;
+
if (*ppos)
return 0; /* the end */
mutex_lock(&sde_dbg_base.mutex);
+ if (dbg->off % sizeof(u32)) {
+ mutex_unlock(&sde_dbg_base.mutex);
+ return -EFAULT;
+ }
+
len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt);
if (len < 0 || len >= sizeof(buf)) {
mutex_unlock(&sde_dbg_base.mutex);
@@ -1857,11 +2019,15 @@ static ssize_t sde_dbg_reg_base_offset_read(struct file *file,
static ssize_t sde_dbg_reg_base_reg_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
- struct sde_dbg_reg_base *dbg = file->private_data;
+ struct sde_dbg_reg_base *dbg;
size_t off;
u32 data, cnt;
char buf[24];
+ if (!file)
+ return -EINVAL;
+
+ dbg = file->private_data;
if (!dbg)
return -ENODEV;
@@ -1907,14 +2073,21 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file,
static ssize_t sde_dbg_reg_base_reg_read(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
{
- struct sde_dbg_reg_base *dbg = file->private_data;
+ struct sde_dbg_reg_base *dbg;
size_t len;
+ if (!file)
+ return -EINVAL;
+
+ dbg = file->private_data;
if (!dbg) {
pr_err("invalid handle\n");
return -ENODEV;
}
+ if (!ppos)
+ return -EINVAL;
+
mutex_lock(&sde_dbg_base.mutex);
if (!dbg->buf) {
char *hwbuf;
diff --git a/drivers/gpu/drm/msm/sde_dbg.h b/drivers/gpu/drm/msm/sde_dbg.h
index 74fd4c94b490..ce36cba08039 100644
--- a/drivers/gpu/drm/msm/sde_dbg.h
+++ b/drivers/gpu/drm/msm/sde_dbg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,9 +17,10 @@
#include <linux/debugfs.h>
#include <linux/list.h>
-#define SDE_EVTLOG_DATA_LIMITER (-1)
+#define SDE_EVTLOG_DATA_LIMITER (0xC0DEBEEF)
#define SDE_EVTLOG_FUNC_ENTRY 0x1111
#define SDE_EVTLOG_FUNC_EXIT 0x2222
+#define SDE_EVTLOG_ERROR 0xebad
#define SDE_DBG_DUMP_DATA_LIMITER (NULL)
@@ -52,7 +53,7 @@ enum sde_dbg_dump_flag {
* number must be greater than print entry to prevent out of bound evtlog
* entry array access.
*/
-#define SDE_EVTLOG_ENTRY (SDE_EVTLOG_PRINT_ENTRY * 4)
+#define SDE_EVTLOG_ENTRY (SDE_EVTLOG_PRINT_ENTRY * 8)
#define SDE_EVTLOG_MAX_DATA 15
#define SDE_EVTLOG_BUF_MAX 512
#define SDE_EVTLOG_BUF_ALIGN 32
@@ -77,6 +78,7 @@ struct sde_dbg_evtlog {
struct sde_dbg_evtlog_log logs[SDE_EVTLOG_ENTRY];
u32 first;
u32 last;
+ u32 last_dump;
u32 curr;
u32 next;
u32 enable;
@@ -123,6 +125,13 @@ extern struct sde_dbg_evtlog *sde_dbg_base_evtlog;
#define SDE_DBG_DUMP_WQ(...) sde_dbg_dump(true, __func__, ##__VA_ARGS__, \
SDE_DBG_DUMP_DATA_LIMITER)
+/**
+ * SDE_DBG_EVT_CTRL - trigger a different driver events
+ * event: event that trigger different behavior in the driver
+ */
+#define SDE_DBG_CTRL(...) sde_dbg_ctrl(__func__, ##__VA_ARGS__, \
+ SDE_DBG_DUMP_DATA_LIMITER)
+
#if defined(CONFIG_DEBUG_FS)
/**
@@ -172,10 +181,12 @@ bool sde_evtlog_is_enabled(struct sde_dbg_evtlog *evtlog, u32 flag);
* @evtlog: pointer to evtlog
* @evtlog_buf: target buffer to print into
* @evtlog_buf_size: size of target buffer
+ * @update_last_entry:ยป whether or not to stop at most recent entry
* Returns: number of bytes written to buffer
*/
ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog,
- char *evtlog_buf, ssize_t evtlog_buf_size);
+ char *evtlog_buf, ssize_t evtlog_buf_size,
+ bool update_last_entry);
/**
* sde_dbg_init_dbg_buses - initialize debug bus dumping support for the chipset
@@ -214,6 +225,15 @@ void sde_dbg_destroy(void);
void sde_dbg_dump(bool queue_work, const char *name, ...);
/**
+ * sde_dbg_ctrl - trigger specific actions for the driver with debugging
+ * purposes. Those actions need to be enabled by the debugfs entry
+ * so the driver executes those actions in the corresponding calls.
+ * @va_args: list of actions to trigger
+ * Returns: none
+ */
+void sde_dbg_ctrl(const char *name, ...);
+
+/**
* sde_dbg_reg_register_base - register a hw register address section for later
* dumping. call this before calling sde_dbg_reg_register_dump_range
* to be able to specify sub-ranges within the base hw range.
@@ -272,7 +292,8 @@ static inline bool sde_evtlog_is_enabled(struct sde_dbg_evtlog *evtlog,
}
static inline ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog,
- char *evtlog_buf, ssize_t evtlog_buf_size)
+ char *evtlog_buf, ssize_t evtlog_buf_size,
+ bool update_last_entry)
{
return 0;
}
@@ -295,6 +316,10 @@ static inline void sde_dbg_dump(bool queue_work, const char *name, ...)
{
}
+static inline void sde_dbg_ctrl(const char *name, ...)
+{
+}
+
static inline int sde_dbg_reg_register_base(const char *name,
void __iomem *base, size_t max_offset)
{
diff --git a/drivers/gpu/drm/msm/sde_dbg_evtlog.c b/drivers/gpu/drm/msm/sde_dbg_evtlog.c
index 759bdab48840..70ba127ceb08 100644
--- a/drivers/gpu/drm/msm/sde_dbg_evtlog.c
+++ b/drivers/gpu/drm/msm/sde_dbg_evtlog.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -75,7 +75,8 @@ void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line,
}
/* always dump the last entries which are not dumped yet */
-static bool _sde_evtlog_dump_calc_range(struct sde_dbg_evtlog *evtlog)
+static bool _sde_evtlog_dump_calc_range(struct sde_dbg_evtlog *evtlog,
+ bool update_last_entry)
{
bool need_dump = true;
unsigned long flags;
@@ -87,21 +88,26 @@ static bool _sde_evtlog_dump_calc_range(struct sde_dbg_evtlog *evtlog)
evtlog->first = evtlog->next;
- if (evtlog->last == evtlog->first) {
+ if (update_last_entry)
+ evtlog->last_dump = evtlog->last;
+
+ if (evtlog->last_dump == evtlog->first) {
need_dump = false;
goto dump_exit;
}
- if (evtlog->last < evtlog->first) {
+ if (evtlog->last_dump < evtlog->first) {
evtlog->first %= SDE_EVTLOG_ENTRY;
- if (evtlog->last < evtlog->first)
- evtlog->last += SDE_EVTLOG_ENTRY;
+ if (evtlog->last_dump < evtlog->first)
+ evtlog->last_dump += SDE_EVTLOG_ENTRY;
}
- if ((evtlog->last - evtlog->first) > SDE_EVTLOG_PRINT_ENTRY) {
- pr_warn("evtlog buffer overflow before dump: %d\n",
- evtlog->last - evtlog->first);
- evtlog->first = evtlog->last - SDE_EVTLOG_PRINT_ENTRY;
+ if ((evtlog->last_dump - evtlog->first) > SDE_EVTLOG_PRINT_ENTRY) {
+ pr_info("evtlog skipping %d entries, last=%d\n",
+ evtlog->last_dump - evtlog->first -
+ SDE_EVTLOG_PRINT_ENTRY,
+ evtlog->last_dump - 1);
+ evtlog->first = evtlog->last_dump - SDE_EVTLOG_PRINT_ENTRY;
}
evtlog->next = evtlog->first + 1;
@@ -112,7 +118,8 @@ dump_exit:
}
ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog,
- char *evtlog_buf, ssize_t evtlog_buf_size)
+ char *evtlog_buf, ssize_t evtlog_buf_size,
+ bool update_last_entry)
{
int i;
ssize_t off = 0;
@@ -123,7 +130,7 @@ ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog,
return 0;
/* update markers, exit if nothing to print */
- if (!_sde_evtlog_dump_calc_range(evtlog))
+ if (!_sde_evtlog_dump_calc_range(evtlog, update_last_entry))
return 0;
spin_lock_irqsave(&evtlog->spin_lock, flags);
@@ -159,12 +166,16 @@ ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog,
void sde_evtlog_dump_all(struct sde_dbg_evtlog *evtlog)
{
char buf[SDE_EVTLOG_BUF_MAX];
+ bool update_last_entry = true;
if (!evtlog)
return;
- while (sde_evtlog_dump_to_buffer(evtlog, buf, sizeof(buf)))
+ while (sde_evtlog_dump_to_buffer(evtlog, buf, sizeof(buf),
+ update_last_entry)) {
pr_info("%s", buf);
+ update_last_entry = false;
+ }
}
struct sde_dbg_evtlog *sde_evtlog_init(void)
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index 4ec04001ae7e..bc3f794555a5 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -300,6 +300,22 @@ static const struct adreno_gpu_core adreno_gpulist[] = {
.busy_mask = 0xFFFFFFFE,
},
{
+ .gpurev = ADRENO_REV_A509,
+ .core = 5,
+ .major = 0,
+ .minor = 9,
+ .patchid = ANY_ID,
+ .features = ADRENO_PREEMPTION | ADRENO_64BIT |
+ ADRENO_CONTENT_PROTECTION | ADRENO_CPZ_RETENTION,
+ .pm4fw_name = "a530_pm4.fw",
+ .pfpfw_name = "a530_pfp.fw",
+ .zap_name = "a512_zap",
+ .gpudev = &adreno_a5xx_gpudev,
+ .gmem_size = (SZ_256K + SZ_16K),
+ .num_protected_regs = 0x20,
+ .busy_mask = 0xFFFFFFFE,
+ },
+ {
.gpurev = ADRENO_REV_A508,
.core = 5,
.major = 0,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 305163147c1a..9ea50007ec38 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -170,6 +170,7 @@ enum adreno_gpurev {
ADRENO_REV_A505 = 505,
ADRENO_REV_A506 = 506,
ADRENO_REV_A508 = 508,
+ ADRENO_REV_A509 = 509,
ADRENO_REV_A510 = 510,
ADRENO_REV_A512 = 512,
ADRENO_REV_A530 = 530,
@@ -1007,6 +1008,7 @@ static inline int adreno_is_a5xx(struct adreno_device *adreno_dev)
ADRENO_TARGET(a505, ADRENO_REV_A505)
ADRENO_TARGET(a506, ADRENO_REV_A506)
ADRENO_TARGET(a508, ADRENO_REV_A508)
+ADRENO_TARGET(a509, ADRENO_REV_A509)
ADRENO_TARGET(a510, ADRENO_REV_A510)
ADRENO_TARGET(a512, ADRENO_REV_A512)
ADRENO_TARGET(a530, ADRENO_REV_A530)
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index cd8cb7837911..119741f7ce47 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -59,6 +59,7 @@ static const struct adreno_vbif_platform a5xx_vbif_platforms[] = {
{ adreno_is_a530, a530_vbif },
{ adreno_is_a512, a540_vbif },
{ adreno_is_a510, a530_vbif },
+ { adreno_is_a509, a540_vbif },
{ adreno_is_a508, a530_vbif },
{ adreno_is_a505, a530_vbif },
{ adreno_is_a506, a530_vbif },
@@ -161,6 +162,7 @@ static const struct {
{ adreno_is_a530, a530_efuse_speed_bin },
{ adreno_is_a505, a530_efuse_speed_bin },
{ adreno_is_a512, a530_efuse_speed_bin },
+ { adreno_is_a509, a530_efuse_speed_bin },
{ adreno_is_a508, a530_efuse_speed_bin },
};
@@ -201,7 +203,8 @@ static void a5xx_platform_setup(struct adreno_device *adreno_dev)
gpudev->vbif_xin_halt_ctrl0_mask =
A510_VBIF_XIN_HALT_CTRL0_MASK;
} else if (adreno_is_a540(adreno_dev) ||
- adreno_is_a512(adreno_dev)) {
+ adreno_is_a512(adreno_dev) ||
+ adreno_is_a509(adreno_dev)) {
gpudev->snapshot_data->sect_sizes->cp_merciu = 1024;
}
@@ -539,7 +542,8 @@ static void a5xx_regulator_disable(struct adreno_device *adreno_dev)
unsigned int reg;
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
- if (adreno_is_a512(adreno_dev) || adreno_is_a508(adreno_dev))
+ if (adreno_is_a512(adreno_dev) || adreno_is_a509(adreno_dev) ||
+ adreno_is_a508(adreno_dev))
return;
/* If feature is not supported or not enabled */
@@ -1199,6 +1203,7 @@ static const struct {
{ adreno_is_a540, a540_hwcg_regs, ARRAY_SIZE(a540_hwcg_regs) },
{ adreno_is_a530, a530_hwcg_regs, ARRAY_SIZE(a530_hwcg_regs) },
{ adreno_is_a512, a512_hwcg_regs, ARRAY_SIZE(a512_hwcg_regs) },
+ { adreno_is_a509, a512_hwcg_regs, ARRAY_SIZE(a512_hwcg_regs) },
{ adreno_is_a510, a510_hwcg_regs, ARRAY_SIZE(a510_hwcg_regs) },
{ adreno_is_a505, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) },
{ adreno_is_a506, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) },
@@ -1651,7 +1656,7 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev,
{
if (!adreno_is_a540(adreno_dev) && !adreno_is_a512(adreno_dev) &&
- !adreno_is_a508(adreno_dev))
+ !adreno_is_a508(adreno_dev) && !adreno_is_a509(adreno_dev))
return;
/* Handle clock settings for GFX PSCBCs */
@@ -1957,7 +1962,8 @@ static void a5xx_start(struct adreno_device *adreno_dev)
kgsl_regwrite(device, A5XX_CP_MERCIU_SIZE, 0x20);
kgsl_regwrite(device, A5XX_CP_ROQ_THRESHOLDS_2, 0x40000030);
kgsl_regwrite(device, A5XX_CP_ROQ_THRESHOLDS_1, 0x20100D0A);
- } else if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev)) {
+ } else if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev) ||
+ adreno_is_a509(adreno_dev)) {
kgsl_regwrite(device, A5XX_CP_MEQ_THRESHOLDS, 0x40);
kgsl_regwrite(device, A5XX_CP_MERCIU_SIZE, 0x400);
kgsl_regwrite(device, A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
@@ -1976,7 +1982,8 @@ static void a5xx_start(struct adreno_device *adreno_dev)
if (adreno_is_a505_or_a506(adreno_dev) || adreno_is_a508(adreno_dev))
kgsl_regwrite(device, A5XX_PC_DBG_ECO_CNTL,
(0x100 << 11 | 0x100 << 22));
- else if (adreno_is_a510(adreno_dev) || adreno_is_a512(adreno_dev))
+ else if (adreno_is_a510(adreno_dev) || adreno_is_a512(adreno_dev) ||
+ adreno_is_a509(adreno_dev))
kgsl_regwrite(device, A5XX_PC_DBG_ECO_CNTL,
(0x200 << 11 | 0x200 << 22));
else
@@ -2069,7 +2076,8 @@ static void a5xx_start(struct adreno_device *adreno_dev)
kgsl_regwrite(device, A5XX_TPL1_MODE_CNTL, bit << 7);
kgsl_regwrite(device, A5XX_RB_MODE_CNTL, bit << 1);
if (adreno_is_a540(adreno_dev) ||
- adreno_is_a512(adreno_dev))
+ adreno_is_a512(adreno_dev) ||
+ adreno_is_a509(adreno_dev))
kgsl_regwrite(device, A5XX_UCHE_DBG_ECO_CNTL_2,
bit);
}
diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c
index 7cac0a8abd81..aa9dcc67c66c 100644
--- a/drivers/media/i2c/adv7481.c
+++ b/drivers/media/i2c/adv7481.c
@@ -1998,7 +1998,7 @@ static int adv7481_get_fmt(struct v4l2_subdev *sd,
fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
fmt->width = 720;
- fmt->height = 576;
+ fmt->height = 507;
break;
default:
return -EINVAL;
diff --git a/drivers/media/platform/msm/ais/isp/msm_isp.h b/drivers/media/platform/msm/ais/isp/msm_isp.h
index 419615cc9b4a..856bf55f8c29 100644
--- a/drivers/media/platform/msm/ais/isp/msm_isp.h
+++ b/drivers/media/platform/msm/ais/isp/msm_isp.h
@@ -782,6 +782,7 @@ struct vfe_device {
uint32_t is_split;
uint32_t dual_vfe_enable;
unsigned long page_fault_addr;
+ bool clk_enabled;
/* Debug variables */
int dump_reg;
diff --git a/drivers/media/platform/msm/ais/isp/msm_isp47.c b/drivers/media/platform/msm/ais/isp/msm_isp47.c
index 6ca91b4fcf83..52bf8121f32b 100644
--- a/drivers/media/platform/msm/ais/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/ais/isp/msm_isp47.c
@@ -1038,16 +1038,18 @@ int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev,
vfe_dev->buf_mgr, fe_cfg->session_id,
fe_cfg->stream_id);
vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
-
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
@@ -1100,14 +1102,15 @@ int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev,
mutex_lock(&vfe_dev->buf_mgr->lock);
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
- mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0 || !buf) {
pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
return -EINVAL;
}
mapped_info = buf->mapped_info[0];
buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
} else {
rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
&mapped_info, fe_cfg->fd);
@@ -2423,9 +2426,30 @@ void msm_vfe47_put_clks(struct vfe_device *vfe_dev)
int msm_vfe47_enable_clks(struct vfe_device *vfe_dev, int enable)
{
- return msm_camera_clk_enable(&vfe_dev->pdev->dev,
+ unsigned long flags;
+ int rc;
+
+ if (!enable) {
+ spin_lock_irqsave(&vfe_dev->tasklet_lock, flags);
+ vfe_dev->clk_enabled = false;
+ spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+ }
+
+ rc = msm_camera_clk_enable(&vfe_dev->pdev->dev,
vfe_dev->vfe_clk_info,
vfe_dev->vfe_clk, vfe_dev->num_clk, enable);
+ if (rc < 0) {
+ pr_err("%s: clk set %d failed %d\n", __func__, enable, rc);
+ return rc;
+ }
+
+ if (enable) {
+ spin_lock_irqsave(&vfe_dev->tasklet_lock, flags);
+ vfe_dev->clk_enabled = true;
+ spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+ }
+
+ return rc;
}
int msm_vfe47_set_clk_rate(struct vfe_device *vfe_dev, long *rate)
diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c
index c0a36843d7ff..22820a0b8e79 100644
--- a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c
@@ -3822,10 +3822,12 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
&update_cmd->update_info[i];
stream_info = &axi_data->stream_info[HANDLE_TO_IDX(
update_info->stream_handle)];
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_request_frame(vfe_dev, stream_info,
update_info->user_stream_id,
update_info->frame_id,
MSM_ISP_INVALID_BUF_INDEX);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc)
pr_err("%s failed to request frame!\n",
__func__);
@@ -3898,10 +3900,12 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
stream_info = &axi_data->stream_info[HANDLE_TO_IDX(
req_frm->stream_handle)];
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_request_frame(vfe_dev, stream_info,
req_frm->user_stream_id,
req_frm->frame_id,
req_frm->buf_index);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc)
pr_err("%s failed to request frame!\n",
__func__);
diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_util.c
index 5ca3b8d531a2..3cacb5b0db10 100644
--- a/drivers/media/platform/msm/ais/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/ais/isp/msm_isp_util.c
@@ -392,9 +392,10 @@ static int msm_isp_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev,
vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev,
0, 1);
msm_isp_reset_framedrop(vfe_dev, stream_info);
-
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_offline_ping_pong_address(vfe_dev, stream_info,
VFE_PING_FLAG, fe_cfg->output_buf_idx);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
if (rc < 0) {
pr_err("%s: Fetch engine config failed\n", __func__);
return -EINVAL;
@@ -851,6 +852,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
{
long rc = 0;
long rc2 = 0;
+ unsigned long flags;
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
if (!vfe_dev || !vfe_dev->vfe_base) {
@@ -917,7 +919,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
break;
case VIDIOC_MSM_ISP_CFG_STREAM:
mutex_lock(&vfe_dev->core_mutex);
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_CFG_HW_STATE:
@@ -947,6 +951,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
break;
case VIDIOC_MSM_ISP_AXI_RESTART:
mutex_lock(&vfe_dev->core_mutex);
+ mutex_lock(&vfe_dev->buf_mgr->lock);
if (atomic_read(&vfe_dev->error_info.overflow_state)
!= HALT_ENFORCED) {
rc = msm_isp_stats_restart(vfe_dev);
@@ -957,6 +962,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
pr_err_ratelimited("%s: no AXI restart, halt enforced.\n",
__func__);
}
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_INPUT_CFG:
@@ -1016,7 +1022,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
break;
case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
mutex_lock(&vfe_dev->core_mutex);
+ mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->buf_mgr->lock);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_UPDATE_STATS_STREAM:
@@ -1061,6 +1069,11 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
while (vfe_dev->vfe_open_cnt != 0)
msm_isp_close_node(sd, NULL);
break;
+ case VIDIOC_MSM_ISP_SET_CLK_STATUS:
+ spin_lock_irqsave(&vfe_dev->tasklet_lock, flags);
+ vfe_dev->clk_enabled = *((unsigned int *)arg);
+ spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+ break;
default:
pr_err_ratelimited("%s: Invalid ISP command %d\n", __func__,
@@ -2113,11 +2126,21 @@ void msm_isp_do_tasklet(unsigned long data)
}
atomic_sub(1, &vfe_dev->irq_cnt);
list_del(&queue_cmd->list);
+
+ if (!vfe_dev->clk_enabled) {
+ /* client closed, delayed task should exit directly */
+ spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+ return;
+ }
+
queue_cmd->cmd_used = 0;
irq_status0 = queue_cmd->vfeInterruptStatus0;
irq_status1 = queue_cmd->vfeInterruptStatus1;
pingpong_status = queue_cmd->vfePingPongStatus;
ts = queue_cmd->ts;
+ /* related to rw reg, need to be protected */
+ irq_ops->process_halt_irq(vfe_dev,
+ irq_status0, irq_status1);
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n",
__func__, vfe_dev->pdev->id, irq_status0, irq_status1);
@@ -2141,8 +2164,6 @@ void msm_isp_do_tasklet(unsigned long data)
}
irq_ops->process_reset_irq(vfe_dev,
irq_status0, irq_status1);
- irq_ops->process_halt_irq(vfe_dev,
- irq_status0, irq_status1);
if (atomic_read(&vfe_dev->error_info.overflow_state)
!= NO_OVERFLOW) {
ISP_DBG("%s: Recovery in processing, Ignore IRQs!!!\n",
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 7079044526b2..fa116b180682 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
@@ -3722,13 +3722,6 @@ static int msm_isp_stream_axi_cfg_update(struct vfe_device *vfe_dev,
unsigned long flags;
int vfe_idx;
- if (atomic_read(&vfe_dev->axi_data.axi_cfg_update[
- SRC_TO_INTF(stream_info->stream_src)])) {
- pr_err("%s: Update in progress for vfe %d intf %d\n",
- __func__, vfe_dev->pdev->id,
- SRC_TO_INTF(stream_info->stream_src));
- return -EINVAL;
- }
spin_lock_irqsave(&stream_info->lock, flags);
if (stream_info->state != ACTIVE) {
spin_unlock_irqrestore(&stream_info->lock, flags);
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
index f760481026db..1a067a4ece4d 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.c
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -137,6 +137,13 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
return ret;
}
+ ret = nla_put_u32(skb, ATH10K_TM_ATTR_WMI_OP_VERSION,
+ ar->normal_mode_fw.fw_file.wmi_op_version);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
return cfg80211_testmode_reply(skb);
}
diff --git a/drivers/net/wireless/ath/ath10k/testmode_i.h b/drivers/net/wireless/ath/ath10k/testmode_i.h
index ba81bf66ce85..191a8f34c8ea 100644
--- a/drivers/net/wireless/ath/ath10k/testmode_i.h
+++ b/drivers/net/wireless/ath/ath10k/testmode_i.h
@@ -33,6 +33,7 @@ enum ath10k_tm_attr {
ATH10K_TM_ATTR_WMI_CMDID = 3,
ATH10K_TM_ATTR_VERSION_MAJOR = 4,
ATH10K_TM_ATTR_VERSION_MINOR = 5,
+ ATH10K_TM_ATTR_WMI_OP_VERSION = 6,
/* keep last */
__ATH10K_TM_ATTR_AFTER_LAST,
diff --git a/drivers/power/qcom/lpm-stats.c b/drivers/power/qcom/lpm-stats.c
index 90458d6a7212..46056255e5c0 100644
--- a/drivers/power/qcom/lpm-stats.c
+++ b/drivers/power/qcom/lpm-stats.c
@@ -682,9 +682,10 @@ static void cleanup_stats(struct lpm_stats *stats)
{
struct list_head *centry = NULL;
struct lpm_stats *pos = NULL;
+ struct lpm_stats *n = NULL;
centry = &stats->child;
- list_for_each_entry_reverse(pos, centry, sibling) {
+ list_for_each_entry_safe_reverse(pos, n, centry, sibling) {
if (!list_empty(&pos->child)) {
cleanup_stats(pos);
continue;
diff --git a/drivers/regulator/kryo-regulator.c b/drivers/regulator/kryo-regulator.c
index fd853e7323bb..d403ee43d924 100644
--- a/drivers/regulator/kryo-regulator.c
+++ b/drivers/regulator/kryo-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* 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
@@ -311,7 +311,6 @@ done:
static int kryo_regulator_disable(struct regulator_dev *rdev)
{
struct kryo_regulator *kvreg = rdev_get_drvdata(rdev);
- int rc;
unsigned long flags;
if (kvreg->vreg_en == false)
@@ -322,7 +321,7 @@ static int kryo_regulator_disable(struct regulator_dev *rdev)
kvreg_debug(kvreg, "disabled\n");
spin_unlock_irqrestore(&kvreg->slock, flags);
- return rc;
+ return 0;
}
static int kryo_regulator_is_enabled(struct regulator_dev *rdev)
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 105d861a2325..aaddf2fff99c 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2596,7 +2596,7 @@ bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host,
int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
{
int reg = 0;
- int offset, ret = 0, testbus_sel_offset = 19;
+ int offset = 0, ret = 0, testbus_sel_offset = 19;
u32 mask = TEST_BUS_SUB_SEL_MASK;
unsigned long flags;
struct ufs_hba *hba;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 10021f25afdd..6d43254d84b9 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -635,6 +635,7 @@ static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
entry.str = str;
entry.lba = lba;
+ entry.cmd_id = cmd_id;
entry.transfer_len = transfer_len;
entry.doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
entry.tag = tag;
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c
index 5ca94579b6f1..4136f2995046 100644
--- a/drivers/soc/qcom/hab/hab.c
+++ b/drivers/soc/qcom/hab/hab.c
@@ -47,6 +47,8 @@ static struct hab_device hab_devices[] = {
HAB_DEVICE_CNSTR(DEVICE_QCPE4_NAME, MM_QCPE_VM4, 17),
HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 18),
HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 19),
+ HAB_DEVICE_CNSTR(DEVICE_FDE1_NAME, MM_FDE_1, 20),
+ HAB_DEVICE_CNSTR(DEVICE_BUFFERQ1_NAME, MM_BUFFERQ_1, 21),
};
struct hab_driver hab_driver = {
@@ -624,7 +626,24 @@ static void hab_generate_pchan(struct local_vmid *settings, int i, int j)
HABCFG_GET_BE(settings, i, j));
}
break;
-
+ case MM_FDE_START/100:
+ for (k = MM_FDE_START + 1; k < MM_FDE_END; k++) {
+ ret += hab_initialize_pchan_entry(
+ find_hab_device(k),
+ settings->self,
+ HABCFG_GET_VMID(settings, i),
+ HABCFG_GET_BE(settings, i, j));
+ }
+ break;
+ case MM_BUFFERQ_START/100:
+ for (k = MM_BUFFERQ_START + 1; k < MM_BUFFERQ_END; k++) {
+ ret += hab_initialize_pchan_entry(
+ find_hab_device(k),
+ settings->self,
+ HABCFG_GET_VMID(settings, i),
+ HABCFG_GET_BE(settings, i, j));
+ }
+ break;
default:
pr_err("failed to find mmid %d, i %d, j %d\n",
HABCFG_GET_MMID(settings, i, j), i, j);
diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h
index d94467e6bc76..f13d6f44b929 100644
--- a/drivers/soc/qcom/hab/hab.h
+++ b/drivers/soc/qcom/hab/hab.h
@@ -81,6 +81,8 @@ enum hab_payload_type {
#define DEVICE_QCPE4_NAME "hab_qcpe_vm4"
#define DEVICE_CLK1_NAME "hab_clock_vm1"
#define DEVICE_CLK2_NAME "hab_clock_vm2"
+#define DEVICE_FDE1_NAME "hab_fde1"
+#define DEVICE_BUFFERQ1_NAME "hab_bufferq1"
/* make sure concascaded name is less than this value */
#define MAX_VMID_NAME_SIZE 30
diff --git a/drivers/soc/qcom/hab/hab_qvm.c b/drivers/soc/qcom/hab/hab_qvm.c
index 280eb3148337..9aa41320a33f 100644
--- a/drivers/soc/qcom/hab/hab_qvm.c
+++ b/drivers/soc/qcom/hab/hab_qvm.c
@@ -52,7 +52,8 @@ static struct shmem_irq_config pchan_factory_settings[] = {
{0x1b011000, 24},
{0x1b012000, 25},
{0x1b013000, 26},
-
+ {0x1b014000, 27},
+ {0x1b015000, 28},
};
static struct qvm_plugin_info {
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index fc89a2ea772e..d357a616b05e 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -2643,6 +2643,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
mdp3_interface->kickoff_fnc = mdp3_ctrl_display_commit_kickoff;
mdp3_interface->lut_update = NULL;
mdp3_interface->configure_panel = mdp3_update_panel_info;
+ mdp3_interface->signal_retire_fence = NULL;
mdp3_session = kzalloc(sizeof(struct mdp3_session_data), GFP_KERNEL);
if (!mdp3_session) {
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index d35858137191..6c4db0f1f5bd 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -3743,8 +3743,11 @@ skip_commit:
if (IS_ERR_VALUE(ret) || !sync_pt_data->flushed) {
mdss_fb_release_kickoff(mfd);
mdss_fb_signal_timeline(sync_pt_data);
- }
+ if ((mfd->panel.type == MIPI_CMD_PANEL) &&
+ (mfd->mdp.signal_retire_fence))
+ mfd->mdp.signal_retire_fence(mfd, 1);
+ }
if (dynamic_dsi_switch) {
MDSS_XLOG(mfd->index, mfd->split_mode, new_dsi_mode,
XLOG_FUNC_EXIT);
@@ -4658,6 +4661,7 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
struct mdp_destination_scaler_data *ds_data = NULL;
struct mdp_destination_scaler_data __user *ds_data_user;
struct msm_fb_data_type *mfd;
+ struct mdss_overlay_private *mdp5_data = NULL;
ret = copy_from_user(&commit, argp, sizeof(struct mdp_layer_commit));
if (ret) {
@@ -4669,9 +4673,20 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
if (!mfd)
return -EINVAL;
+ mdp5_data = mfd_to_mdp5_data(mfd);
+
if (mfd->panel_info->panel_dead) {
pr_debug("early commit return\n");
MDSS_XLOG(mfd->panel_info->panel_dead);
+ /*
+ * In case of an ESD attack, since we early return from the
+ * commits, we need to signal the outstanding fences.
+ */
+ mdss_fb_release_fences(mfd);
+ if ((mfd->panel.type == MIPI_CMD_PANEL) &&
+ mfd->mdp.signal_retire_fence && mdp5_data)
+ mfd->mdp.signal_retire_fence(mfd,
+ mdp5_data->retire_cnt);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index 6e52390c2886..301c1386a639 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -234,6 +234,8 @@ struct msm_mdp_interface {
int (*input_event_handler)(struct msm_fb_data_type *mfd);
void (*footswitch_ctrl)(bool on);
int (*pp_release_fnc)(struct msm_fb_data_type *mfd);
+ void (*signal_retire_fence)(struct msm_fb_data_type *mfd,
+ int retire_cnt);
void *private1;
};
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index 747b4e3e2f81..2c92a480af6b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -406,7 +406,7 @@ static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
return;
}
- if (line_out < ctl->mixer_left->roi.h) {
+ if ((line_out < ctl->mixer_left->roi.h) && (line_out)) {
reinit_completion(&ctx->autorefresh_ppdone);
/* enable ping pong done */
@@ -2510,6 +2510,7 @@ int mdss_mdp_cmd_set_autorefresh_mode(struct mdss_mdp_ctl *mctl, int frame_cnt)
*/
ctx->autorefresh_state = MDP_AUTOREFRESH_ON_REQUESTED;
ctx->autorefresh_frame_cnt = frame_cnt;
+ mctl->mdata->serialize_wait4pp = true;
/* Cancel GATE Work Item */
if (cancel_work_sync(&ctx->gate_clk_work))
@@ -2523,8 +2524,10 @@ int mdss_mdp_cmd_set_autorefresh_mode(struct mdss_mdp_ctl *mctl, int frame_cnt)
if (frame_cnt == 0) {
ctx->autorefresh_state = MDP_AUTOREFRESH_OFF;
ctx->autorefresh_frame_cnt = 0;
+ mctl->mdata->serialize_wait4pp = false;
} else {
ctx->autorefresh_frame_cnt = frame_cnt;
+ mctl->mdata->serialize_wait4pp = true;
}
break;
case MDP_AUTOREFRESH_ON:
@@ -2536,6 +2539,7 @@ int mdss_mdp_cmd_set_autorefresh_mode(struct mdss_mdp_ctl *mctl, int frame_cnt)
ctx->autorefresh_state = MDP_AUTOREFRESH_OFF_REQUESTED;
} else {
ctx->autorefresh_frame_cnt = frame_cnt;
+ mctl->mdata->serialize_wait4pp = true;
}
break;
case MDP_AUTOREFRESH_OFF_REQUESTED:
@@ -2545,6 +2549,7 @@ int mdss_mdp_cmd_set_autorefresh_mode(struct mdss_mdp_ctl *mctl, int frame_cnt)
pr_debug("cancelling autorefresh off request\n");
ctx->autorefresh_state = MDP_AUTOREFRESH_ON;
ctx->autorefresh_frame_cnt = frame_cnt;
+ mctl->mdata->serialize_wait4pp = true;
}
break;
default:
@@ -2873,6 +2878,7 @@ static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl,
cfg |= BIT(20);
mdss_mdp_pingpong_write(pp_base,
MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+ ctl->mdata->serialize_wait4pp = false;
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 791c73baa9e7..f3984201fbc5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -6140,6 +6140,9 @@ static void __vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
sw_sync_timeline_inc(mdp5_data->vsync_timeline, val);
mdp5_data->retire_cnt -= min(val, mdp5_data->retire_cnt);
+ pr_debug("Retire signaled! timeline val=%d remaining=%d\n",
+ mdp5_data->vsync_timeline->value,
+ mdp5_data->retire_cnt);
if (mdp5_data->retire_cnt == 0) {
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
mdp5_data->ctl->ops.remove_vsync_handler(mdp5_data->ctl,
@@ -6361,6 +6364,13 @@ void mdss_mdp_footswitch_ctrl_handler(bool on)
mdss_mdp_footswitch_ctrl(mdata, on);
}
+static void mdss_mdp_signal_retire_fence(struct msm_fb_data_type *mfd,
+ int retire_cnt)
+{
+ __vsync_retire_signal(mfd, retire_cnt);
+ pr_debug("Signaled (%d) pending retire fence\n", retire_cnt);
+}
+
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
{
struct device *dev = mfd->fbi->dev;
@@ -6402,6 +6412,7 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
mdp5_interface->splash_init_fnc = mdss_mdp_splash_init;
mdp5_interface->configure_panel = mdss_mdp_update_panel_info;
mdp5_interface->input_event_handler = mdss_mdp_input_event_handler;
+ mdp5_interface->signal_retire_fence = mdss_mdp_signal_retire_fence;
/*
* Register footswitch control only for primary fb pm
diff --git a/include/uapi/linux/habmm.h b/include/uapi/linux/habmm.h
index 59b603a0fcf7..8586048e20c0 100644
--- a/include/uapi/linux/habmm.h
+++ b/include/uapi/linux/habmm.h
@@ -109,7 +109,15 @@ struct hab_unimport {
#define MM_CLK_VM2 802
#define MM_CLK_END 803
-#define MM_ID_MAX 804
+#define MM_FDE_START 900
+#define MM_FDE_1 901
+#define MM_FDE_END 902
+
+#define MM_BUFFERQ_START 1000
+#define MM_BUFFERQ_1 1001
+#define MM_BUFFERQ_END 1002
+
+#define MM_ID_MAX 1003
#define HABMM_SOCKET_OPEN_FLAGS_SINGLE_BE_SINGLE_FE 0x00000000
#define HABMM_SOCKET_OPEN_FLAGS_SINGLE_BE_SINGLE_DOMU 0x00000001
diff --git a/include/uapi/media/ais/msm_ais_isp.h b/include/uapi/media/ais/msm_ais_isp.h
index f323d3bf7baf..55bc5290ce28 100644
--- a/include/uapi/media/ais/msm_ais_isp.h
+++ b/include/uapi/media/ais/msm_ais_isp.h
@@ -973,6 +973,8 @@ enum msm_isp_ioctl_cmd_code {
MSM_ISP_AXI_OUTPUT_CFG,
MSM_ISP_START,
MSM_ISP_STOP,
+
+ MSM_ISP_SET_CLK_STATUS,
};
@@ -1104,5 +1106,8 @@ enum msm_isp_ioctl_cmd_code {
_IOWR('V', MSM_ISP_CAMIF_CFG, \
struct msm_vfe_camif_cfg)
+#define VIDIOC_MSM_ISP_SET_CLK_STATUS \
+ _IOWR('V', MSM_ISP_SET_CLK_STATUS, \
+ unsigned int)
#endif /* __UAPI_MSM_AIS_ISP__ */
diff --git a/sound/soc/msm/sdm660-common.c b/sound/soc/msm/sdm660-common.c
index 90b661dff7ec..271697747dd2 100644
--- a/sound/soc/msm/sdm660-common.c
+++ b/sound/soc/msm/sdm660-common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2552,11 +2552,9 @@ void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
mutex_lock(&mi2s_intf_conf[index].lock);
if (--mi2s_intf_conf[index].ref_cnt == 0) {
ret = msm_mi2s_set_sclk(substream, false);
- if (ret < 0) {
+ if (ret < 0)
pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
__func__, index, ret);
- mi2s_intf_conf[index].ref_cnt++;
- }
if (mi2s_intf_conf[index].msm_is_ext_mclk) {
mi2s_mclk[index].enable = 0;
pr_debug("%s: Disabling mclk, clk_freq_in_hz = %u\n",