From aaa4dd32bafa88f5285af027e2f17cbee07b8262 Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Thu, 15 Apr 2021 16:23:09 +0530 Subject: [PATCH 01/18] diag: Prevent out of bound write while sending dci pkt to remote Sanitize user input length for the maximum buffer size before writing the dci packet to remote. Change-Id: I1f813a969fcce589f9e5024864ef4a650f2cf64e Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_dci.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index ba07d791c5b9..cb9f4e46607e 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -1739,7 +1739,16 @@ static int diag_send_dci_pkt_remote(unsigned char *data, int len, int tag, write_len += dci_header_size; *(int *)(buf + write_len) = tag; write_len += sizeof(int); - memcpy(buf + write_len, data, len); + if ((write_len + len) < DIAG_MDM_BUF_SIZE) { + memcpy(buf + write_len, data, len); + } else { + pr_err("diag: skip writing invalid length packet, token: %d, pkt_len: %d\n", + token, (write_len + len)); + spin_lock_irqsave(&driver->dci_mempool_lock, flags); + diagmem_free(driver, buf, dci_ops_tbl[token].mempool); + spin_unlock_irqrestore(&driver->dci_mempool_lock, flags); + return -EAGAIN; + } write_len += len; *(buf + write_len) = CONTROL_CHAR; /* End Terminator */ write_len += sizeof(uint8_t); From 232eae5f68dd1dde688778d579dd1a7bbc55bbb9 Mon Sep 17 00:00:00 2001 From: Muralidharan M Date: Thu, 7 Oct 2021 18:05:15 +0530 Subject: [PATCH 02/18] msm-ipa: fix use-after-free of rt_tbl Fix use-after-free of rt_tbl in __ipa_del_flt_rule by checking if the rt_tbl is already freed. Change-Id: I09541f65f474dc42f262c603d99f6bbcbb0ce8ec Signed-off-by: Muralidharan M --- drivers/platform/msm/ipa/ipa_v3/ipa_flt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c index 1ab4934774e3..3df8f49e5f0b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c @@ -982,7 +982,7 @@ static int __ipa_del_flt_rule(u32 rule_hdl) list_del(&entry->link); entry->tbl->rule_cnt--; - if (entry->rt_tbl) + if (entry->rt_tbl && !ipa3_check_idr_if_freed(entry->rt_tbl)) entry->rt_tbl->ref_cnt--; IPADBG("del flt rule rule_cnt=%d rule_id=%d\n", entry->tbl->rule_cnt, entry->rule_id); From 5ecc44355ee22ebbeb526465cb82bedef44f2124 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Fri, 29 Oct 2021 12:33:06 +0530 Subject: [PATCH 03/18] msm: camera: jpeg: Ensure in/out map entries are within allowed range Added checks to make sure in_map /out_map entries of packet io configs are within expected maximum value. CRs-Fixed: 3007258 Change-Id: Ia8f10f464691427d83ae7aed5cc7c90124eaa2be Signed-off-by: Shravya Samala --- .../msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index b00486412ebd..1ad563399308 100644 --- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -721,10 +721,11 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, } if ((packet->num_cmd_buf > 5) || !packet->num_patches || - !packet->num_io_configs) { - CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u", - packet->num_cmd_buf, - packet->num_patches); + !packet->num_io_configs || + (packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) { + CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u %u", + packet->num_cmd_buf, packet->num_patches, + packet->num_io_configs); return -EINVAL; } From a972102ba63dfe5d2be0fe9ee72165e15c87075a Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 21 Jul 2020 10:31:23 -0700 Subject: [PATCH 04/18] Makefile: Fix GCC_TOOLCHAIN_DIR prefix for Clang cross compilation commit ca9b31f6bb9c6aa9b4e5f0792f39a97bbffb8c51 upstream. When CROSS_COMPILE is set (e.g. aarch64-linux-gnu-), if $(CROSS_COMPILE)elfedit is found at /usr/bin/aarch64-linux-gnu-elfedit, GCC_TOOLCHAIN_DIR will be set to /usr/bin/. --prefix= will be set to /usr/bin/ and Clang as of 11 will search for both $(prefix)aarch64-linux-gnu-$needle and $(prefix)$needle. GCC searchs for $(prefix)aarch64-linux-gnu/$version/$needle, $(prefix)aarch64-linux-gnu/$needle and $(prefix)$needle. In practice, $(prefix)aarch64-linux-gnu/$needle rarely contains executables. To better model how GCC's -B/--prefix takes in effect in practice, newer Clang (since https://github.com/llvm/llvm-project/commit/3452a0d8c17f7166f479706b293caf6ac76ffd90) only searches for $(prefix)$needle. Currently it will find /usr/bin/as instead of /usr/bin/aarch64-linux-gnu-as. Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE)) (/usr/bin/aarch64-linux-gnu-) so that newer Clang can find the appropriate cross compiling GNU as (when -no-integrated-as is in effect). Change-Id: I1375d087204fb8605282c7a6b4bda3582438022e Cc: stable@vger.kernel.org Reported-by: Nathan Chancellor Signed-off-by: Fangrui Song Reviewed-by: Nathan Chancellor Tested-by: Nathan Chancellor Tested-by: Nick Desaulniers Link: https://github.com/ClangBuiltLinux/linux/issues/1099 Reviewed-by: Nick Desaulniers Signed-off-by: Masahiro Yamada Signed-off-by: Greg Kroah-Hartman Git-commit: d98d958276c73db039a4c47499cd9f085bcec6bb Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Srinivasarao Pathipati --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 25f9ad4232c9..bf0aff17b08c 100644 --- a/Makefile +++ b/Makefile @@ -523,7 +523,7 @@ ifeq ($(shell $(srctree)/scripts/clang-android.sh $(CC) $(CLANG_FLAGS)), y) $(error "Clang with Android --target detected. Did you specify CLANG_TRIPLE?") endif GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) -CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) +CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE)) GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..) endif ifneq ($(GCC_TOOLCHAIN),) From 227b6ebb59071f7f7b99daf64e6cc7b16c89f281 Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Tue, 27 Jul 2021 19:45:20 +0530 Subject: [PATCH 05/18] drm/msm/dp: read extended dpcd if present In case sink supports DPCD 1.4 version, check if corresponding DPCP is available at extended receiver capability field. Read the extended receiver capability field for DPCD if present. Change-Id: I60b93482b403ad0a3413b46214f4c288fa27c2da Signed-off-by: Ajay Singh Parmar Signed-off-by: Narender Ankam --- drivers/gpu/drm/msm/dp/dp_panel.c | 77 ++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 4b006c59fee3..43f011de5113 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, 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 @@ -22,6 +22,7 @@ #define DP_MAX_DS_PORT_COUNT 1 #define DPRX_FEATURE_ENUMERATION_LIST 0x2210 +#define DPRX_EXTENDED_DPCD_FIELD 0x2200 #define VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED BIT(3) #define VSC_EXT_VESA_SDP_SUPPORTED BIT(4) #define VSC_EXT_VESA_SDP_CHAINING_SUPPORTED BIT(5) @@ -122,8 +123,9 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel, bool multi_func) int rlen, rc = 0; struct dp_panel_private *panel; struct drm_dp_link *link_info; - u8 *dpcd, rx_feature; - u32 dfp_count = 0; + struct drm_dp_aux *drm_aux; + u8 *dpcd, rx_feature, temp; + u32 dfp_count = 0, offset = DP_DPCD_REV; unsigned long caps = DP_LINK_CAP_ENHANCED_FRAMING; if (!dp_panel) { @@ -135,44 +137,64 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel, bool multi_func) dpcd = dp_panel->dpcd; panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + drm_aux = panel->aux->drm_aux; link_info = &dp_panel->link_info; - if (!panel->custom_dpcd) { - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DPCD_REV, - dp_panel->dpcd, (DP_RECEIVER_CAP_SIZE + 1)); - if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) { - pr_err("dpcd read failed, rlen=%d\n", rlen); - if (rlen == -ETIMEDOUT) - rc = rlen; - else - rc = -EINVAL; + /* reset vsc data */ + panel->vsc_supported = false; + panel->vscext_supported = false; + panel->vscext_chaining_supported = false; - goto end; - } + if (panel->custom_dpcd) { + pr_debug("skip dpcd read in debug mode\n"); + goto skip_dpcd_read; } + rlen = drm_dp_dpcd_read(drm_aux, DP_TRAINING_AUX_RD_INTERVAL, &temp, 1); + if (rlen != 1) { + pr_err("error reading DP_TRAINING_AUX_RD_INTERVAL\n"); + rc = -EINVAL; + goto end; + } + + /* check for EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT */ + if (temp & BIT(7)) { + pr_debug("using EXTENDED_RECEIVER_CAPABILITY_FIELD\n"); + offset = DPRX_EXTENDED_DPCD_FIELD; + } + + rlen = drm_dp_dpcd_read(drm_aux, offset, + dp_panel->dpcd, (DP_RECEIVER_CAP_SIZE + 1)); + if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) { + pr_err("dpcd read failed, rlen=%d\n", rlen); + if (rlen == -ETIMEDOUT) + rc = rlen; + else + rc = -EINVAL; + + goto end; + } + + print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DPCD: ", + DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false); + rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1); if (rlen != 1) { pr_debug("failed to read DPRX_FEATURE_ENUMERATION_LIST\n"); - panel->vsc_supported = false; - panel->vscext_supported = false; - panel->vscext_chaining_supported = false; - } else { - panel->vsc_supported = !!(rx_feature & - VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED); - - panel->vscext_supported = !!(rx_feature & - VSC_EXT_VESA_SDP_SUPPORTED); - - panel->vscext_chaining_supported = !!(rx_feature & - VSC_EXT_VESA_SDP_CHAINING_SUPPORTED); + goto skip_dpcd_read; } + panel->vsc_supported = !!(rx_feature & + VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED); + panel->vscext_supported = !!(rx_feature & VSC_EXT_VESA_SDP_SUPPORTED); + panel->vscext_chaining_supported = !!(rx_feature & + VSC_EXT_VESA_SDP_CHAINING_SUPPORTED); pr_debug("vsc=%d, vscext=%d, vscext_chaining=%d\n", panel->vsc_supported, panel->vscext_supported, panel->vscext_chaining_supported); +skip_dpcd_read: link_info->revision = dp_panel->dpcd[DP_DPCD_REV]; panel->major = (link_info->revision >> 4) & 0x0f; @@ -271,6 +293,7 @@ static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid, panel->custom_edid = false; } + pr_debug("%d\n", panel->custom_edid); return 0; } @@ -295,6 +318,8 @@ static int dp_panel_set_dpcd(struct dp_panel *dp_panel, u8 *dpcd) panel->custom_dpcd = false; } + pr_debug("%d\n", panel->custom_dpcd); + return 0; } From 1b81041299dcf926274165dbbc3abb62a729421c Mon Sep 17 00:00:00 2001 From: Ilia Lin Date: Thu, 26 Aug 2021 11:14:33 +0300 Subject: [PATCH 06/18] ipa: Null persistent pointers after free Assign NULL to pointers that may be used later after calling kfree on them. Change-Id: I3298eb484c92ee2373f0bc41aae8ae45fb373cf0 Signed-off-by: Ilia Lin --- drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c | 3 +++ drivers/platform/msm/ipa/ipa_v3/ipa.c | 4 ++++ drivers/platform/msm/ipa/ipa_v3/ipa_pm.c | 1 + drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c | 1 + 4 files changed, 9 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c index 793d13c003cf..30a2d28b4bb3 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c @@ -428,6 +428,7 @@ static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest, source->buff_pool_base_sgt); if (result) { kfree(dest->data_buff_list); + dest->data_buff_list = NULL; return result; } @@ -435,6 +436,7 @@ static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest, source->ring_base_sgt); if (result) { kfree(dest->data_buff_list); + dest->data_buff_list = NULL; ipa_smmu_free_sgt(&dest->buff_pool_base_sgt); return result; } @@ -445,6 +447,7 @@ static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest, static void ipa_uc_ntn_free_conn_smmu_info(struct ipa_ntn_setup_info *params) { kfree(params->data_buff_list); + params->data_buff_list = NULL; ipa_smmu_free_sgt(¶ms->buff_pool_base_sgt); ipa_smmu_free_sgt(¶ms->ring_base_sgt); } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index ec298bbcb97e..1e03e6d9f464 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -344,6 +344,7 @@ static void ipa3_active_clients_log_destroy(void) kfree(active_clients_table_buf); active_clients_table_buf = NULL; kfree(ipa3_ctx->ipa3_active_clients_logging.log_buffer[0]); + ipa3_ctx->ipa3_active_clients_logging.log_buffer[0] = NULL; ipa3_ctx->ipa3_active_clients_logging.log_head = 0; ipa3_ctx->ipa3_active_clients_logging.log_tail = IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES - 1; @@ -5861,8 +5862,10 @@ fail_bus_reg: fail_init_mem_partition: fail_bind: kfree(ipa3_ctx->ctrl); + ipa3_ctx->ctrl = NULL; fail_mem_ctrl: kfree(ipa3_ctx->ipa_tz_unlock_reg); + ipa3_ctx->ipa_tz_unlock_reg = NULL; fail_tz_unlock_reg: if (ipa3_ctx->logbuf) ipc_log_context_destroy(ipa3_ctx->logbuf); @@ -6240,6 +6243,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, IPAERR("failed to read register addresses\n"); kfree(ipa_tz_unlock_reg); kfree(ipa_drv_res->ipa_tz_unlock_reg); + ipa_drv_res->ipa_tz_unlock_reg = NULL; return -EFAULT; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c index e244a19fcd4e..1e7a06509cdc 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c @@ -617,6 +617,7 @@ int ipa_pm_init(struct ipa_pm_init_params *params) if (!ipa_pm_ctx->wq) { IPA_PM_ERR("create workqueue failed\n"); kfree(ipa_pm_ctx); + ipa_pm_ctx = NULL; return -ENOMEM; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 8811805cf14e..b94164b7528e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -599,6 +599,7 @@ static void ipa_release_uc_smmu_mappings(enum ipa_client_type client) ipa3_ctx->wdi_map_cnt--; } kfree(wdi_res[i].res); + wdi_res[i].res = NULL; wdi_res[i].valid = false; } } From d9e397cf6301f28158172809a33542334e4f6160 Mon Sep 17 00:00:00 2001 From: Swetha Chikkaboraiah Date: Wed, 17 Nov 2021 09:59:42 +0530 Subject: [PATCH 07/18] ion: Fix integer overflow in msm_ion_custom_ioctl While handling some of custom commands vaddr and offset are controlled from userspace. Handle the case where start address can become 0 and leading to unintentional operations. Fixes: ff8868e4cf88 ("ion: ensure valid start address") Change-Id: I995c7f0ae76910fa136ed95aaf4ac254d09885bd Signed-off-by: Swetha Chikkaboraiah --- drivers/staging/android/ion/msm/msm_ion.c | 31 +++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 12186066c999..8740b3339862 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -637,6 +637,9 @@ static int check_vaddr_bounds(unsigned long start, unsigned long end) struct vm_area_struct *vma; int ret = 1; + if (!start) + goto out; + if (end < start) goto out; @@ -834,20 +837,28 @@ long msm_ion_custom_ioctl(struct ion_client *client, down_read(&mm->mmap_sem); - start = (unsigned long)data.flush_data.vaddr + - data.flush_data.offset; - end = start + data.flush_data.length; - - if (start && check_vaddr_bounds(start, end)) { - pr_err("%s: virtual address %pK is out of bounds\n", + if ((unsigned long)data.flush_data.vaddr > + (ULONG_MAX - data.flush_data.offset)) { + pr_err("%s: Integer overflow detected for %pK\n", __func__, data.flush_data.vaddr); ret = -EINVAL; } else { - ret = ion_do_cache_op( - client, handle, data.flush_data.vaddr, - data.flush_data.offset, - data.flush_data.length, cmd); + start = (unsigned long)data.flush_data.vaddr + + data.flush_data.offset; + end = start + data.flush_data.length; + + if (check_vaddr_bounds(start, end)) { + pr_err("%s: virtual address %pK is out of bounds\n", + __func__, data.flush_data.vaddr); + ret = -EINVAL; + } else { + ret = ion_do_cache_op( + client, handle, data.flush_data.vaddr, + data.flush_data.offset, + data.flush_data.length, cmd); + } } + up_read(&mm->mmap_sem); ion_free_nolock(client, handle); From e51b895c55f795fee6ec68701cfdce424608b0ce Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 10 Apr 2020 17:10:17 +0530 Subject: [PATCH 08/18] msm: camera: isp: Fix race condition b/w add and apply req There is a chance that CRM shows request as ready while request is not passed in isp pending list. Change-Id: I0056b09b31d78629957ba196d148f1b308205753 Signed-off-by: Trishansh Bhardwaj --- .../msm/camera/cam_isp/cam_isp_context.c | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index a506ff4676c4..f462a3179020 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -124,6 +124,24 @@ static void __cam_isp_ctx_dump_state_monitor_array( } } +static int __cam_isp_ctx_dequeue_request(struct cam_context *ctx, + struct cam_ctx_request *req) +{ + struct cam_ctx_request *req_current; + struct cam_ctx_request *req_prev; + + spin_lock_bh(&ctx->lock); + list_for_each_entry_safe_reverse(req_current, req_prev, + &ctx->pending_req_list, list) { + if (req->request_id == req_current->request_id) { + list_del_init(&req_current->list); + break; + } + } + spin_unlock_bh(&ctx->lock); + return 0; +} + static int __cam_isp_ctx_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) { @@ -2193,13 +2211,12 @@ static int __cam_isp_ctx_config_dev_in_top_state( add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; add_req.skip_before_applying = 0; + __cam_isp_ctx_enqueue_request_in_order(ctx, req); rc = ctx->ctx_crm_intf->add_req(&add_req); if (rc) { CAM_ERR(CAM_ISP, "Add req failed: req id=%llu", req->request_id); - } else { - __cam_isp_ctx_enqueue_request_in_order( - ctx, req); + __cam_isp_ctx_dequeue_request(ctx, req); } } else { rc = -EINVAL; From 165856d3e128598bee6939adc1946bc7f5961608 Mon Sep 17 00:00:00 2001 From: Petar Sivenov Date: Tue, 7 Dec 2021 09:38:36 +0200 Subject: [PATCH 09/18] arm: dts: msm: regulator change to power up imx334 lc sensor on hp device Change power source for power up imx334 camera sensor Change-Id: Ie615ebbb22d4f294575c19be89dc92e9155913c5 Signed-off-by: Petar Sivenov --- arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi index f71fbd38f70d..195fa2ac1a19 100644 --- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi @@ -294,7 +294,7 @@ eeprom-src = <&eeprom_rear>; cam_vio-supply = <&camera_vio_ldo>; cam_vana-supply = <&camera_vana_ldo>; - cam_vdig-supply = <&camera_rear_ldo>; + cam_vdig-supply = <&camera_ldo>; cam_clk-supply = <&titan_top_gdsc>; regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_clk"; From e4a2eae99c4f65d7b4a3dc573e0a7354b8b409e5 Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Thu, 28 Oct 2021 12:26:41 +0530 Subject: [PATCH 10/18] scripts: checkpatch: Allow quicinc.com identity Since @quicinc.com identity is now allowed, remove the check for it from author and Signed-off-by fields. Change-Id: I83dfae8511f11fcc849db98c42b998ba3c5c0345 Signed-off-by: Vijayanand Jitta Signed-off-by: Komal Bajaj --- scripts/checkpatch.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index c141b05c391a..eca87a51ba78 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2607,7 +2607,7 @@ sub process { $qca_sign_off = 1; } elsif ($line =~ /^\s*signed-off-by:.*codeaurora\.org/i) { $codeaurora_sign_off = 1; - } elsif ($line =~ /^\s*signed-off-by:.*(quicinc|qualcomm)\.com/i) { + } elsif ($line =~ /^\s*signed-off-by:.*qualcomm\.com/i) { WARN("BAD_SIGN_OFF", "invalid Signed-off-by identity\n" . $line ); } @@ -2746,7 +2746,7 @@ sub process { #check the patch for invalid author credentials if ($chk_author && !($line =~ /^From:.*qca\.qualcomm\.com/) && - $line =~ /^From:.*(quicinc|qualcomm)\.com/) { + $line =~ /^From:.*qualcomm\.com/) { WARN("BAD_AUTHOR", "invalid author identity\n" . $line ); } From ffa57525bc9632537a9863300277760c915f8b71 Mon Sep 17 00:00:00 2001 From: Shubham Talekar Date: Thu, 16 Dec 2021 22:24:25 +0530 Subject: [PATCH 11/18] drm/dp: handle power state transitions Program SET_POWER & SET_DP_PWR_VOLTAGE DPCD register as per current power mode. Possible modes are: D0: normal mode D3: power down mode D5: power down mode with AUX block fully powered. Change-Id: I49b16be330bf1e78c80927dfe2415ac4fdf89457 Signed-off-by: Shubham Talekar --- drivers/gpu/drm/drm_dp_helper.c | 24 +++++++++++++ drivers/gpu/drm/msm/dp/dp_display.c | 54 +++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 2 ++ drivers/gpu/drm/msm/dp/dp_link.c | 14 ++++++-- drivers/gpu/drm/msm/dp/dp_link.h | 1 + drivers/gpu/drm/msm/sde/sde_kms.c | 1 + include/drm/drm_dp_helper.h | 5 ++- 7 files changed, 97 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 8164c6f6b9de..a1c7d7fa6f23 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -411,6 +411,30 @@ int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link) } EXPORT_SYMBOL(drm_dp_link_power_down); +int drm_dp_link_power_down_aux_up(struct drm_dp_aux *aux, + struct drm_dp_link *link) +{ + u8 value; + int err; + + if (link->revision < 0x11) + return 0; + + err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D5; + + err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(drm_dp_link_power_down_aux_up); + /** * drm_dp_link_configure() - configure a DisplayPort link * @aux: DisplayPort AUX channel diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 331d6ade2454..4409c46547a1 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1414,6 +1414,60 @@ static int dp_display_get_modes(struct dp_display *dp, return ret; } +int dp_display_set_power(struct drm_connector *connector, + int power_mode, void *disp) +{ + struct dp_display *dp = disp; + struct dp_display_private *dp_priv = + container_of(dp, struct dp_display_private, dp_display); + int rc = 0; + + if (!dp) { + pr_err("invalid display\n"); + return -EINVAL; + } + + if (!dp_priv) { + pr_err("invalid display private\n"); + return -EINVAL; + } + + if (!dp_priv->panel) { + pr_err("invalid link_info\n"); + return -EINVAL; + } + + if (!dp_priv->aux->drm_aux) { + pr_err("Invalid drm_aux"); + return -EINVAL; + } + + if (!dp_priv->link) { + pr_err("invalid dp_link\n"); + return -EINVAL; + } + + switch (power_mode) { + case SDE_MODE_DPMS_STANDBY: + dp_priv->link->power_mode = DRM_MODE_DPMS_STANDBY; + rc = dp_priv->link->psm_config(dp_priv->link, + &dp_priv->panel->link_info, true); + dp_priv->ctrl->push_idle(dp_priv->ctrl); + break; + case SDE_MODE_DPMS_SUSPEND: + dp_priv->link->power_mode = DRM_MODE_DPMS_SUSPEND; + rc = dp_priv->link->psm_config(dp_priv->link, + &dp_priv->panel->link_info, true); + dp_priv->ctrl->push_idle(dp_priv->ctrl); + break; + default: + pr_err("conn %d dpms set to unrecognized mode %d\n", + connector->base.id, power_mode); + break; + } + return rc; +} + static int dp_display_config_hdr(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr) { diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index c980d9dbf5f2..e31a1645080d 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -63,4 +63,6 @@ bool dp_connector_mode_needs_full_range(void *display); bool dp_connector_mode_is_cea_mode(void *display); enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn, void *data); +int dp_display_set_power(struct drm_connector *connector, + int power_mode, void *display); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 410e0754ebf5..3ebac9001c0f 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -17,6 +17,8 @@ #include "dp_link.h" #include "dp_panel.h" +#include + enum dynamic_range { DP_DYNAMIC_RANGE_RGB_VESA = 0x00, DP_DYNAMIC_RANGE_RGB_CEA = 0x01, @@ -961,9 +963,15 @@ static int dp_link_psm_config(struct dp_link *dp_link, link = container_of(dp_link, struct dp_link_private, dp_link); - if (enable) - ret = drm_dp_link_power_down(link->aux->drm_aux, link_info); - else + if (enable) { + if (dp_link->power_mode != DRM_MODE_DPMS_STANDBY + && dp_link->power_mode != DRM_MODE_DPMS_SUSPEND) + ret = drm_dp_link_power_down(link->aux->drm_aux, + link_info); + else + ret = drm_dp_link_power_down_aux_up(link->aux->drm_aux, + link_info); + } else ret = drm_dp_link_power_up(link->aux->drm_aux, link_info); if (ret) diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index d14b88155444..53edda03eaa5 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -109,6 +109,7 @@ static inline char *dp_link_get_test_name(u32 test_requested) struct dp_link { u32 sink_request; u32 test_response; + int power_mode; struct dp_link_sink_count sink_count; struct dp_link_test_video test_video; diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 381e43206037..6212fd62eb61 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1314,6 +1314,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_info = dp_connector_get_info, .get_mode_info = dp_connector_get_mode_info, .post_open = dp_connector_post_open, + .set_power = dp_display_set_power, .check_status = NULL, .config_hdr = dp_connector_config_hdr, .cmd_transfer = NULL, diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 4d8f7a104137..67175f22cec4 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -536,7 +536,8 @@ #define DP_SET_POWER 0x600 # define DP_SET_POWER_D0 0x1 # define DP_SET_POWER_D3 0x2 -# define DP_SET_POWER_MASK 0x3 +#define DP_SET_POWER_D5 0x5 +# define DP_SET_POWER_MASK 0x7 #define DP_EDP_DPCD_REV 0x700 /* eDP 1.2 */ # define DP_EDP_11 0x00 @@ -983,6 +984,8 @@ struct drm_dp_link { int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_link_power_down_aux_up(struct drm_dp_aux *aux, + struct drm_dp_link *link); int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); From b7e0f9fdf7011509de2ed0ff9e20f5fbbe6b1c5c Mon Sep 17 00:00:00 2001 From: Rohith M Date: Mon, 10 Jan 2022 17:22:32 +0530 Subject: [PATCH 12/18] msm: camera: sensor: Add support for sensor read Added support for Sensor read from userspace CRs-Fixed: 3109314 Change-Id: I9e7e09177cf4079b92d08c1613ca38acfcf11c60 Signed-off-by: Rohith M --- .../cam_actuator/cam_actuator_core.c | 8 +- .../cam_flash/cam_flash_core.c | 8 +- .../cam_sensor_module/cam_ois/cam_ois_core.c | 8 +- .../cam_sensor/cam_sensor_core.c | 45 ++- .../cam_sensor/cam_sensor_dev.c | 4 +- .../cam_sensor_utils/cam_sensor_cmn_header.h | 9 +- .../cam_sensor_utils/cam_sensor_util.c | 317 +++++++++++++++++- .../cam_sensor_utils/cam_sensor_util.h | 10 +- 8 files changed, 386 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c index 3837aac6a2e5..2a735c705322 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, 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 @@ -563,7 +563,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = cam_sensor_i2c_command_parser( &a_ctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Failed:parse init settings: %d", @@ -625,7 +625,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = cam_sensor_i2c_command_parser( &a_ctrl->io_master_info, i2c_reg_settings, - cmd_desc, 1); + cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Auto move lens parsing failed: %d", rc); @@ -656,7 +656,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = cam_sensor_i2c_command_parser( &a_ctrl->io_master_info, i2c_reg_settings, - cmd_desc, 1); + cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, "Manual move lens parsing failed: %d", rc); diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c index 4302d4897ea9..feda13141aa5 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, 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 @@ -1079,7 +1079,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) rc = cam_sensor_i2c_command_parser( &fctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_FLASH, "pkt parsing failed: %d", rc); @@ -1159,7 +1159,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_sensor_i2c_command_parser( &fctrl->io_master_info, - i2c_reg_settings, cmd_desc, 1); + i2c_reg_settings, cmd_desc, 1, NULL); if (rc) { CAM_ERR(CAM_FLASH, "Failed in parsing i2c packets"); @@ -1190,7 +1190,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_sensor_i2c_command_parser( &fctrl->io_master_info, - i2c_reg_settings, cmd_desc, 1); + i2c_reg_settings, cmd_desc, 1, NULL); if (rc) { CAM_ERR(CAM_FLASH, "Failed in parsing i2c NRT packets"); diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c index 711077cdfdf8..e08d1f659d3f 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, 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 @@ -552,7 +552,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) rc = cam_sensor_i2c_command_parser( &o_ctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "init parsing failed: %d", rc); @@ -569,7 +569,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) rc = cam_sensor_i2c_command_parser( &o_ctrl->io_master_info, i2c_reg_settings, - &cmd_desc[i], 1); + &cmd_desc[i], 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "Calib parsing failed: %d", rc); @@ -644,7 +644,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, i2c_reg_settings, - cmd_desc, 1); + cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); goto rel_pkt; diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c index 94bc611a9120..17fa95ff64d5 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, 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 @@ -94,6 +94,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, struct cam_control *ioctl_ctrl = NULL; struct cam_packet *csl_packet = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL; + struct cam_buf_io_cfg *io_cfg = NULL; struct i2c_settings_array *i2c_reg_settings = NULL; size_t len_of_buff = 0; size_t remain_len = 0; @@ -194,7 +195,27 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, i2c_reg_settings->is_settings_valid = 1; break; } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_READ: { + i2c_reg_settings = &(i2c_data->read_settings); + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + CAM_DBG(CAM_SENSOR, "number of IO configs: %d:", + csl_packet->num_io_configs); + if (csl_packet->num_io_configs == 0) { + CAM_ERR(CAM_SENSOR, "No I/O configs to process"); + goto rel_pkt_buf; + } + io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) + &csl_packet->payload + + csl_packet->io_configs_offset); + + if (io_cfg == NULL) { + CAM_ERR(CAM_SENSOR, "I/O config is invalid(NULL)"); + goto rel_pkt_buf; + } + break; + } case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE: { if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { @@ -246,7 +267,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, cmd_desc = (struct cam_cmd_buf_desc *)(offset); rc = cam_sensor_i2c_command_parser(&s_ctrl->io_master_info, - i2c_reg_settings, cmd_desc, 1); + i2c_reg_settings, cmd_desc, 1, io_cfg); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Fail parsing I2C Pkt: %d", rc); goto rel_pkt_buf; @@ -323,7 +344,6 @@ static int32_t cam_sensor_i2c_modes_util( } } } - return rc; } @@ -986,6 +1006,25 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, } s_ctrl->sensor_state = CAM_SENSOR_CONFIG; } + + if (s_ctrl->i2c_data.read_settings.is_settings_valid) { + rc = cam_sensor_i2c_read_data( + &s_ctrl->i2c_data.read_settings, + &s_ctrl->io_master_info); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "cannot read data: %d", rc); + delete_request(&s_ctrl->i2c_data.read_settings); + goto release_mutex; + } + rc = delete_request( + &s_ctrl->i2c_data.read_settings); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Fail in deleting the read settings"); + goto release_mutex; + } + } + } break; default: diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 5c5c97099d43..8b94ad51d81e 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, 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 @@ -187,6 +187,7 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); @@ -323,6 +324,7 @@ static int32_t cam_sensor_driver_platform_probe( INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 7a2c56e3b686..857cc138006c 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, 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 @@ -159,6 +159,7 @@ enum cam_sensor_packet_opcodes { CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE, CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF, + CAM_SENSOR_PACKET_OPCODE_SENSOR_READ, CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127 }; @@ -224,7 +225,8 @@ enum cam_sensor_i2c_cmd_type { CAM_SENSOR_I2C_WRITE_RANDOM, CAM_SENSOR_I2C_WRITE_BURST, CAM_SENSOR_I2C_WRITE_SEQ, - CAM_SENSOR_I2C_READ, + CAM_SENSOR_I2C_READ_RANDOM, + CAM_SENSOR_I2C_READ_SEQ, CAM_SENSOR_I2C_POLL }; @@ -275,6 +277,8 @@ struct cam_sensor_i2c_reg_setting { enum camera_sensor_i2c_type addr_type; enum camera_sensor_i2c_type data_type; unsigned short delay; + uint8_t *read_buff; + uint32_t read_buff_len; }; struct i2c_settings_list { @@ -294,6 +298,7 @@ struct i2c_data_settings { struct i2c_settings_array config_settings; struct i2c_settings_array streamon_settings; struct i2c_settings_array streamoff_settings; + struct i2c_settings_array read_settings; struct i2c_settings_array *per_frame; }; diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 4d314964effd..2e7c2b7e2da8 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, 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 @@ -241,6 +241,143 @@ static int32_t cam_sensor_handle_continuous_write( return rc; } +static int32_t cam_sensor_get_io_buffer( + struct cam_buf_io_cfg *io_cfg, + struct cam_sensor_i2c_reg_setting *i2c_settings) +{ + uintptr_t buf_addr = 0x0; + size_t buf_size = 0; + int32_t rc = 0; + + if (io_cfg == NULL || i2c_settings == NULL) { + CAM_ERR(CAM_SENSOR, + "Invalid args, io buf or i2c settings is NULL"); + return -EINVAL; + } + + if (io_cfg->direction == CAM_BUF_OUTPUT) { + rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0], + &buf_addr, &buf_size); + if ((rc < 0) || (!buf_addr)) { + CAM_ERR(CAM_SENSOR, + "invalid buffer, rc: %d, buf_addr: %pK", + rc, (void *)buf_addr); + return -EINVAL; + } + CAM_DBG(CAM_SENSOR, + "buf_addr: %pK, buf_size: %zu, offsetsize: %d", + (void *)buf_addr, buf_size, io_cfg->offsets[0]); + if (io_cfg->offsets[0] >= buf_size) { + CAM_ERR(CAM_SENSOR, + "invalid size:io_cfg->offsets[0]: %d, buf_size: %d", + io_cfg->offsets[0], (unsigned int)buf_size); + return -EINVAL; + } + i2c_settings->read_buff = + (uint8_t *)buf_addr + io_cfg->offsets[0]; + i2c_settings->read_buff_len = + buf_size - io_cfg->offsets[0]; + } else { + CAM_ERR(CAM_SENSOR, "Invalid direction: %d", + io_cfg->direction); + rc = -EINVAL; + } + return rc; +} + +static int32_t cam_sensor_handle_random_read( + struct cam_cmd_i2c_random_rd *cmd_i2c_random_rd, + struct i2c_settings_array *i2c_reg_settings, + uint16_t *cmd_length_in_bytes, + int32_t *offset, + struct list_head **list, + struct cam_buf_io_cfg *io_cfg) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0, cnt = 0; + + i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings, + cmd_i2c_random_rd->header.count); + if ((i2c_list == NULL) || + (i2c_list->i2c_settings.reg_setting == NULL)) { + CAM_ERR(CAM_SENSOR, + "Failed in allocating i2c_list: %pK", + i2c_list); + return -ENOMEM; + } + + rc = cam_sensor_get_io_buffer(io_cfg, &(i2c_list->i2c_settings)); + if (rc) { + CAM_ERR(CAM_SENSOR, "Failed to get read buffer: %d", rc); + } else { + *cmd_length_in_bytes = sizeof(struct i2c_rdwr_header) + + (sizeof(struct cam_cmd_read) * + (cmd_i2c_random_rd->header.count)); + i2c_list->op_code = CAM_SENSOR_I2C_READ_RANDOM; + i2c_list->i2c_settings.addr_type = + cmd_i2c_random_rd->header.addr_type; + i2c_list->i2c_settings.data_type = + cmd_i2c_random_rd->header.data_type; + i2c_list->i2c_settings.size = + cmd_i2c_random_rd->header.count; + + for (cnt = 0; cnt < (cmd_i2c_random_rd->header.count); + cnt++) { + i2c_list->i2c_settings.reg_setting[cnt].reg_addr = + cmd_i2c_random_rd->data_read[cnt].reg_data; + } + *offset = cnt; + *list = &(i2c_list->list); + } + + return rc; +} + +static int32_t cam_sensor_handle_continuous_read( + struct cam_cmd_i2c_continuous_rd *cmd_i2c_continuous_rd, + struct i2c_settings_array *i2c_reg_settings, + uint16_t *cmd_length_in_bytes, int32_t *offset, + struct list_head **list, + struct cam_buf_io_cfg *io_cfg) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0, cnt = 0; + + i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings, 1); + if ((i2c_list == NULL) || + (i2c_list->i2c_settings.reg_setting == NULL)) { + CAM_ERR(CAM_SENSOR, + "Failed in allocating i2c_list: %pK", + i2c_list); + return -ENOMEM; + } + + rc = cam_sensor_get_io_buffer(io_cfg, &(i2c_list->i2c_settings)); + if (rc) { + CAM_ERR(CAM_SENSOR, + "Failed to get read buffer: %d %d", rc, cnt); + } else { + + *cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd); + i2c_list->op_code = CAM_SENSOR_I2C_READ_SEQ; + + i2c_list->i2c_settings.addr_type = + cmd_i2c_continuous_rd->header.addr_type; + i2c_list->i2c_settings.data_type = + cmd_i2c_continuous_rd->header.data_type; + i2c_list->i2c_settings.size = + cmd_i2c_continuous_rd->header.count; + i2c_list->i2c_settings.reg_setting[0].reg_addr = + cmd_i2c_continuous_rd->reg_addr; + + *offset = cnt; + *list = &(i2c_list->list); + } + + return rc; +} + + static int cam_sensor_handle_slave_info( struct camera_io_master *io_master, uint32_t *cmd_buf) @@ -291,7 +428,8 @@ int cam_sensor_i2c_command_parser( struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, struct cam_cmd_buf_desc *cmd_desc, - int32_t num_cmd_buffers) + int32_t num_cmd_buffers, + struct cam_buf_io_cfg *io_cfg) { int16_t rc = 0, i = 0; size_t len_of_buff = 0; @@ -496,6 +634,92 @@ int cam_sensor_i2c_command_parser( byte_cnt += cmd_length_in_bytes; break; } + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD: { + uint16_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_random_rd *i2c_random_rd = + (struct cam_cmd_i2c_random_rd *)cmd_buf; + + if (remain_len - byte_cnt < + sizeof(struct cam_cmd_i2c_random_rd)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer space"); + rc = -EINVAL; + goto rel_buf; + } + + tot_size = sizeof(struct i2c_rdwr_header) + + (sizeof(struct cam_cmd_read) * + i2c_random_rd->header.count); + + if (tot_size > (remain_len - byte_cnt)) { + CAM_ERR(CAM_SENSOR, + "Not enough buff provided %x, %x, %d", + (unsigned int)tot_size, + (unsigned int)remain_len, + byte_cnt); + rc = -EINVAL; + goto rel_buf; + } + + rc = cam_sensor_handle_random_read( + i2c_random_rd, + i2c_reg_settings, + &cmd_length_in_bytes, &j, &list, + io_cfg); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in random read %d", rc); + goto end; + } + + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + byte_cnt += cmd_length_in_bytes; + break; + } + case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD: { + uint16_t cmd_length_in_bytes = 0; + struct cam_cmd_i2c_continuous_rd + *i2c_continuous_rd = + (struct cam_cmd_i2c_continuous_rd *)cmd_buf; + + if (remain_len - byte_cnt < + sizeof(struct cam_cmd_i2c_continuous_rd)) { + CAM_ERR(CAM_SENSOR, + "Not enough buffer space"); + rc = -EINVAL; + goto end; + } + + tot_size = + sizeof(struct cam_cmd_i2c_continuous_rd); + + if (tot_size > (remain_len - byte_cnt)) { + CAM_ERR(CAM_SENSOR, + "Not enough buff provided %d, %d, %d", + (int)tot_size, (int)remain_len, + byte_cnt); + rc = -EINVAL; + goto end; + } + + rc = cam_sensor_handle_continuous_read( + i2c_continuous_rd, + i2c_reg_settings, + &cmd_length_in_bytes, &j, &list, + io_cfg); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed in continuous read %d", rc); + goto end; + } + + cmd_buf += cmd_length_in_bytes / + sizeof(uint32_t); + byte_cnt += cmd_length_in_bytes; + break; + } + default: CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d", cmm_hdr->cmd_type); @@ -508,7 +732,7 @@ int cam_sensor_i2c_command_parser( CAM_WARN(CAM_SENSOR, "put failed for buffer :%d", cmd_desc[i].mem_handle); } - +end: return rc; rel_buf: @@ -587,6 +811,93 @@ int cam_sensor_util_i2c_apply_setting( return rc; } +int32_t cam_sensor_i2c_read_data( + struct i2c_settings_array *i2c_settings, + struct camera_io_master *io_master_info) +{ + int32_t rc = 0; + struct i2c_settings_list *i2c_list; + uint32_t cnt = 0; + uint8_t *read_buff = NULL; + uint32_t buff_length = 0; + uint32_t read_length = 0; + + list_for_each_entry(i2c_list, + &(i2c_settings->list_head), list) { + read_buff = i2c_list->i2c_settings.read_buff; + buff_length = i2c_list->i2c_settings.read_buff_len; + if ((read_buff == NULL) || (buff_length == 0)) { + CAM_ERR(CAM_SENSOR, + "Invalid input buffer, buffer: %pK, length: %d", + read_buff, buff_length); + return -EINVAL; + } + + if (i2c_list->op_code == CAM_SENSOR_I2C_READ_RANDOM) { + read_length = i2c_list->i2c_settings.data_type * + i2c_list->i2c_settings.size; + if ((read_length > buff_length) || + (read_length < + i2c_list->i2c_settings.size)) { + CAM_ERR(CAM_SENSOR, + "Invalid size, readLen:%d, bufLen:%d, size:%d", + read_length, buff_length, + i2c_list->i2c_settings.size); + return -EINVAL; + } + for (cnt = 0; cnt < (i2c_list->i2c_settings.size); + cnt++) { + struct cam_sensor_i2c_reg_array *reg_setting = + &(i2c_list->i2c_settings.reg_setting[cnt]); + rc = camera_io_dev_read(io_master_info, + reg_setting->reg_addr, + ®_setting->reg_data, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "Failed: random read I2C settings: %d", + rc); + return rc; + } + if (i2c_list->i2c_settings.data_type < + CAMERA_SENSOR_I2C_TYPE_MAX) { + memcpy(read_buff, + ®_setting->reg_data, + i2c_list->i2c_settings.data_type); + read_buff += + i2c_list->i2c_settings.data_type; + } + } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_READ_SEQ) { + read_length = i2c_list->i2c_settings.size; + if (read_length > buff_length) { + CAM_ERR(CAM_SENSOR, + "Invalid buffer size,readLen: %d, bufLen:%d", + read_length, buff_length); + return -EINVAL; + } + rc = camera_io_dev_read_seq( + io_master_info, + i2c_list->i2c_settings.reg_setting[0].reg_addr, + read_buff, + i2c_list->i2c_settings.addr_type, + i2c_list->i2c_settings.data_type, + i2c_list->i2c_settings.size); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "failed: seq read I2C settings: %d", + rc); + return rc; + } + } + } + + return rc; +} + + + int32_t msm_camera_fill_vreg_params( struct cam_hw_soc_info *soc_info, struct cam_sensor_power_setting *power_setting, diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 85497fda011c..ea3c2bc3b828 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,6 +28,10 @@ #define INVALID_VREG 100 +int32_t cam_sensor_i2c_read_data( + struct i2c_settings_array *i2c_settings, + struct camera_io_master *io_master_info); + int cam_get_dt_power_setting_data(struct device_node *of_node, struct cam_hw_soc_info *soc_info, struct cam_sensor_power_ctrl_t *power_info); @@ -37,7 +41,9 @@ int msm_camera_pinctrl_init int cam_sensor_i2c_command_parser(struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, - struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers); + struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers, + struct cam_buf_io_cfg *io_cfg); + int cam_sensor_util_i2c_apply_setting(struct camera_io_master *io_master_info, struct i2c_settings_list *i2c_list); From 4a9b62c9d3b0506c4f3090968920fe846010ac6a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 30 Jan 2018 11:27:04 +0100 Subject: [PATCH 13/18] drm/atomic: Remove WARN_ON for invalid plane configuration. Userspace can set a FB_ID on a plane without setting CRTC_ID, which will fail with -EINVAL, but the kernel shouldn't warn about that. Same for !FB_ID and CRTC_ID being set. Change-Id: Iee21baf7efbe44a1ede9f4d3bfa84fa12f784891 Signed-off-by: Maarten Lankhorst Acked-by: Daniel Vetter Cc: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20180130102704.28016-1-maarten.lankhorst@linux.intel.com Reviewed-by: Harry Wentland Signed-off-by: Raghavendra Ambadas --- drivers/gpu/drm/drm_atomic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 4e4043fca223..20a8a571a5ac 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -862,10 +862,10 @@ static int drm_atomic_plane_check(struct drm_plane *plane, int ret; /* either *both* CRTC and FB must be set, or neither */ - if (WARN_ON(state->crtc && !state->fb)) { + if (state->crtc && !state->fb) { DRM_DEBUG_ATOMIC("CRTC set but no FB\n"); return -EINVAL; - } else if (WARN_ON(state->fb && !state->crtc)) { + } else if (state->fb && !state->crtc) { DRM_DEBUG_ATOMIC("FB set but no CRTC\n"); return -EINVAL; } From d399eb5fb27ff98f7c3bc865c064374c0b9d238b Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Fri, 7 Jan 2022 02:20:41 +0530 Subject: [PATCH 14/18] msm: kgsl: Perform cache flush on the pages obtained using get_user_pages() Consider a scenario where user allocates anonymous memory but does not write to it. Here the physical pages are not yet allocated. Now when this memory is requested to be imported, a list of newly allocated zero pages is obtained using get_user_pages(). Currently cache flush is not done for these pages and hence GPU sees stale data. Fix this by performing cache flush on these pages. Change-Id: Id1e8aa20e8a9de112761732ed92f30c01088840b Signed-off-by: Puranam V G Tejaswi Signed-off-by: Sebanti Das --- drivers/gpu/msm/kgsl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 4c6078edb66e..5d76314cd809 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1,4 +1,5 @@ /* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -2179,6 +2180,15 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, unsigned long useraddr) ret = sg_alloc_table_from_pages(memdesc->sgt, pages, npages, 0, memdesc->size, GFP_KERNEL); + + if (ret) + goto out; + + ret = kgsl_cache_range_op(memdesc, 0, memdesc->size, + KGSL_CACHE_OP_FLUSH); + + if (ret) + sg_free_table(memdesc->sgt); out: if (ret) { for (i = 0; i < npages; i++) From 458da91848006e0e18b300b2456a2950b2738c92 Mon Sep 17 00:00:00 2001 From: Shubham Talekar Date: Tue, 11 Jan 2022 18:42:21 +0530 Subject: [PATCH 15/18] drm/dp: via debugfs entry node perform power transition The change will make a debugfs entry into /sys/kernel/debug/drm_dp/dpms_mode. echo 1: normal mode echo 2: power down mode echo 5: power down mode with AUX block fully powered. Change-Id: I7b04e4884ad0fdb531f94b5d5cabf6578c0c39e2 Signed-off-by: Shubham Talekar --- drivers/gpu/drm/msm/dp/dp_debug.c | 101 +++++++++++++++++++++++++++- drivers/gpu/drm/msm/dp/dp_debug.h | 3 +- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 97de1b803f55..a3d2ebb550c6 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -25,6 +25,8 @@ #include "sde_connector.h" #include "dp_display.h" +#include + #define DEBUG_NAME "drm_dp" struct dp_debug_private { @@ -50,6 +52,13 @@ struct dp_debug_private { struct work_struct sim_work; struct dp_debug dp_debug; struct mutex lock; + struct dp_ctrl *ctrl; +}; + +enum dpms_mode_status { + DRM_DPMS_ON = 1, + DRM_DPMS_OFF = 2, + DRM_DPMS_SUSPEND = 5, }; static int dp_debug_get_edid_buf(struct dp_debug_private *debug) @@ -985,6 +994,77 @@ end: return len; } +static ssize_t dp_debug_write_dpms(struct file *file, + const char __user *user_buff, size_t count, loff_t *ppos) +{ + int dpms_mode; + struct dp_debug_private *debug = file->private_data; + char buf[SZ_8]; + size_t len = 0; + enum dpms_mode_status mode_status; + + len = min_t(size_t, count, SZ_8-1); + if (copy_from_user(buf, user_buff, len)) + goto end; + + buf[len] = '\0'; + + if (kstrtoint(buf, 8, &dpms_mode)) { + pr_err("offset kstrtoint error\n"); + return 0; + } + + if (!debug->aux || !debug->aux->drm_aux || !debug->panel) + return 0; + + pr_info("dpms_mode = %d", dpms_mode); + mode_status = dpms_mode; + switch (mode_status) { + case DRM_DPMS_ON: + drm_dp_link_power_up(debug->aux->drm_aux, + &debug->panel->link_info); + debug->ctrl->link_maintenance(debug->ctrl); + break; + case DRM_DPMS_OFF: + drm_dp_link_power_down(debug->aux->drm_aux, + &debug->panel->link_info); + break; + case DRM_DPMS_SUSPEND: + drm_dp_link_power_down_aux_up(debug->aux->drm_aux, + &debug->panel->link_info); + break; + default: + pr_err("Invalid values\n"); + } +end: + return count; +} + +static ssize_t dp_debug_read_dpms(struct file *file, + char __user *user_buff, size_t count, loff_t *ppos) +{ + u8 value; + int err, len; + char buf[SZ_8]; + struct dp_debug_private *debug = file->private_data; + + err = drm_dp_dpcd_readb(debug->aux->drm_aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + if (*ppos) + return 0; + + len += snprintf(buf, SZ_8, "%d\n", value); + + len = min_t(size_t, count, len); + if (copy_to_user(user_buff, buf, len)) + return -EFAULT; + + *ppos += len; + return len; +} + static ssize_t dp_debug_write_dump(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { @@ -1121,6 +1201,12 @@ static const struct file_operations dump_fops = { .read = dp_debug_read_dump, }; +static const struct file_operations dpms_mode_fops = { + .open = simple_open, + .write = dp_debug_write_dpms, + .read = dp_debug_read_dpms, +}; + static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; @@ -1260,6 +1346,16 @@ static int dp_debug_init(struct dp_debug *dp_debug) goto error_remove_dir; } + file = debugfs_create_file("dpms_mode", 0644, dir, + debug, &dpms_mode_fops); + + if (IS_ERR_OR_NULL(file)) { + rc = PTR_ERR(file); + pr_err("[%s] debugfs dpms failed, rc=%d\n", + DEBUG_NAME, rc); + goto error_remove_dir; + } + return 0; error_remove_dir: @@ -1281,13 +1377,13 @@ static void dp_debug_sim_work(struct work_struct *work) struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, struct dp_usbpd *usbpd, struct dp_link *link, struct dp_aux *aux, struct drm_connector **connector, - struct dp_catalog *catalog) + struct dp_catalog *catalog, struct dp_ctrl *ctrl) { int rc = 0; struct dp_debug_private *debug; struct dp_debug *dp_debug; - if (!dev || !panel || !usbpd || !link || !catalog) { + if (!dev || !panel || !usbpd || !link || !catalog || !ctrl) { pr_err("invalid input\n"); rc = -EINVAL; goto error; @@ -1309,6 +1405,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, debug->dev = dev; debug->connector = connector; debug->catalog = catalog; + debug->ctrl = ctrl; dp_debug = &debug->dp_debug; dp_debug->vdisplay = 0; diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h index 2643f70f219d..2f08a188822f 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.h +++ b/drivers/gpu/drm/msm/dp/dp_debug.h @@ -19,6 +19,7 @@ #include "dp_link.h" #include "dp_usbpd.h" #include "dp_aux.h" +#include "dp_ctrl.h" /** * struct dp_debug @@ -56,7 +57,7 @@ struct dp_debug { struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, struct dp_usbpd *usbpd, struct dp_link *link, struct dp_aux *aux, struct drm_connector **connector, - struct dp_catalog *catalog); + struct dp_catalog *catalog, struct dp_ctrl *ctrl); /** * dp_debug_put() * diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 4409c46547a1..e967eb6c9bc9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -977,7 +977,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, dp->link, dp->aux, &dp->dp_display.connector, - dp->catalog); + dp->catalog, dp->ctrl); if (IS_ERR(dp->debug)) { rc = PTR_ERR(dp->debug); pr_err("failed to initialize debug, rc = %d\n", rc); From 1f6edb7d3801b7416df5563f68f91d44ea0a1336 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 1 Sep 2017 17:13:43 -0700 Subject: [PATCH 16/18] Input: uinput - avoid FF flush when destroying device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e8b95728f724797f958912fd9b765a695595d3a6 upstream. Normally, when input device supporting force feedback effects is being destroyed, we try to "flush" currently playing effects, so that the physical device does not continue vibrating (or executing other effects). Unfortunately this does not work well for uinput as flushing of the effects deadlocks with the destroy action: - if device is being destroyed because the file descriptor is being closed, then there is noone to even service FF requests; - if device is being destroyed because userspace sent UI_DEV_DESTROY, while theoretically it could be possible to service FF requests, userspace is unlikely to do so (they'd need to make sure FF handling happens on a separate thread) even if kernel solves the issue with FF ioctls deadlocking with UI_DEV_DESTROY ioctl on udev->mutex. To avoid lockups like the one below, let's install a custom input device flush handler, and avoid trying to flush force feedback effects when we destroying the device, and instead rely on uinput to shut off the device properly. NMI watchdog: Watchdog detected hard LOCKUP on cpu 3 ... <> [] _raw_spin_lock_irqsave+0x37/0x40 [] complete+0x1d/0x50 [] uinput_request_done+0x3c/0x40 [uinput] [] uinput_request_submit.part.7+0x47/0xb0 [uinput] [] uinput_dev_erase_effect+0x5b/0x76 [uinput] [] erase_effect+0xad/0xf0 [] flush_effects+0x4d/0x90 [] input_flush_device+0x40/0x60 [] evdev_cleanup+0xac/0xc0 [] evdev_disconnect+0x2b/0x60 [] __input_unregister_device+0xac/0x150 [] input_unregister_device+0x47/0x70 [] uinput_destroy_device+0xb5/0xc0 [uinput] [] uinput_ioctl_handler.isra.9+0x65e/0x740 [uinput] [] ? do_futex+0x12b/0xad0 [] uinput_ioctl+0x18/0x20 [uinput] [] do_vfs_ioctl+0x298/0x480 [] ? security_file_ioctl+0x43/0x60 [] SyS_ioctl+0x79/0x90 [] entry_SYSCALL_64_fastpath+0x12/0x71. Change-Id: I4354852aa34bd4001bf006fecceb859312e62f20 Reported-by: Rodrigo Rivas Costa Reported-by: ClĂ©ment VUCHENER Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=193741 Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman Git-commit: e8b95728f724797f958912fd9b765a695595d3a6 Git-repo: https://source.codeaurora.org/quic/la/kernel/common/ Signed-off-by: Swetha Chikkaboraiah --- drivers/input/ff-core.c | 13 ++++++++++--- drivers/input/misc/uinput.c | 18 ++++++++++++++++++ include/linux/input.h | 1 + 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 8f2042432c85..66a46c84e28f 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -237,9 +237,15 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file) EXPORT_SYMBOL_GPL(input_ff_erase); /* - * flush_effects - erase all effects owned by a file handle + * input_ff_flush - erase all effects owned by a file handle + * @dev: input device to erase effect from + * @file: purported owner of the effects + * + * This function erases all force-feedback effects associated with + * the given owner from specified device. Note that @file may be %NULL, + * in which case all effects will be erased. */ -static int flush_effects(struct input_dev *dev, struct file *file) +int input_ff_flush(struct input_dev *dev, struct file *file) { struct ff_device *ff = dev->ff; int i; @@ -255,6 +261,7 @@ static int flush_effects(struct input_dev *dev, struct file *file) return 0; } +EXPORT_SYMBOL_GPL(input_ff_flush); /** * input_ff_event() - generic handler for force-feedback events @@ -343,7 +350,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects) mutex_init(&ff->mutex); dev->ff = ff; - dev->flush = flush_effects; + dev->flush = input_ff_flush; dev->event = input_ff_event; __set_bit(EV_FF, dev->evbit); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 89d37d0d45ed..fcd10a4708c3 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -231,6 +231,18 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) return uinput_request_submit(udev, &request); } +static int uinput_dev_flush(struct input_dev *dev, struct file *file) +{ + /* + * If we are called with file == NULL that means we are tearing + * down the device, and therefore we can not handle FF erase + * requests: either we are handling UI_DEV_DESTROY (and holding + * the udev->mutex), or the file descriptor is closed and there is + * nobody on the other side anymore. + */ + return file ? input_ff_flush(dev, file) : 0; +} + static void uinput_destroy_device(struct uinput_device *udev) { const char *name, *phys; @@ -298,6 +310,12 @@ static int uinput_create_device(struct uinput_device *udev) dev->ff->playback = uinput_dev_playback; dev->ff->set_gain = uinput_dev_set_gain; dev->ff->set_autocenter = uinput_dev_set_autocenter; + /* + * The standard input_ff_flush() implementation does + * not quite work for uinput as we can't reasonably + * handle FF requests during device teardown. + */ + dev->flush = uinput_dev_flush; } error = input_register_device(udev->dev); diff --git a/include/linux/input.h b/include/linux/input.h index a65e3b24fb18..fb5e23c7ed98 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -529,6 +529,7 @@ int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code, int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file); int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file); +int input_ff_flush(struct input_dev *dev, struct file *file); int input_ff_create_memless(struct input_dev *dev, void *data, int (*play_effect)(struct input_dev *, void *, struct ff_effect *)); From 0ad56197f8ffec2b662f077cc838cb4df78123cd Mon Sep 17 00:00:00 2001 From: Swathi K Date: Wed, 2 Feb 2022 01:50:14 +0530 Subject: [PATCH 17/18] msm: adsprpc: Handle UAF in fastrpc debugfs read Use lock to protect maps among multiple threads to avoid race condition. Change-Id: Ib0c83dd38ea8e5acb54a1478d10b02385c27ba31 Signed-off-by: Swathi K --- drivers/char/adsprpc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index cd481f49be3e..4bcfdc7d773c 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -3476,6 +3477,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + spin_lock(&me->hlock); hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20d|0x%-18llX|0x%-18X|0x%-20lX\n\n", @@ -3483,18 +3485,21 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, (uint32_t)gmaps->size, gmaps->va); } + spin_unlock(&me->hlock); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20s|%-20s|%-20s|%-20s\n", "len", "refs", "raddr", "flags"); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + spin_lock(&me->hlock); hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "0x%-18X|%-20d|%-20lu|%-20u\n", (uint32_t)gmaps->len, gmaps->refs, gmaps->raddr, gmaps->flags); } + spin_unlock(&me->hlock); } else { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "\n%s %13s %d\n", "cid", ":", fl->cid); @@ -3544,12 +3549,14 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + mutex_lock(&fl->map_mutex); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "0x%-20lX|0x%-20llX|0x%-20zu\n\n", map->va, map->phys, map->size); } + mutex_unlock(&fl->map_mutex); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20s|%-20s|%-20s|%-20s\n", "len", "refs", @@ -3558,23 +3565,27 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + mutex_lock(&fl->map_mutex); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20zu|%-20d|0x%-20lX|%-20d\n\n", map->len, map->refs, map->raddr, map->uncached); } + mutex_unlock(&fl->map_mutex); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20s|%-20s\n", "secure", "attr"); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + mutex_lock(&fl->map_mutex); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20d|0x%-20lX\n\n", map->secure, map->attr); } + mutex_unlock(&fl->map_mutex); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s %d\n\n", "KERNEL MEMORY ALLOCATION:", 1); From 028bfb9c8453af9d536b71a4e38e2e6574290f84 Mon Sep 17 00:00:00 2001 From: Rohith M Date: Wed, 9 Feb 2022 23:29:24 +0530 Subject: [PATCH 18/18] msm: camera: sensor: Add copyright details Add copyright details Change-Id: Iff9d7e930b2fd892c5d00e6dac7036339d266cc0 Signed-off-by: Rohith M --- .../cam_sensor_module/cam_actuator/cam_actuator_core.c | 3 ++- .../msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c | 3 ++- .../msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c | 3 ++- .../camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c | 3 ++- .../camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c | 3 ++- .../cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h | 3 ++- .../cam_sensor_module/cam_sensor_utils/cam_sensor_util.c | 3 ++- .../cam_sensor_module/cam_sensor_utils/cam_sensor_util.h | 3 ++- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c index 2a735c705322..51375809b6e2 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c index feda13141aa5..47eb2022ea66 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c index e08d1f659d3f..c8d3a1a0a49b 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c index 17fa95ff64d5..0ed36d143265 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 8b94ad51d81e..3e5e6b9982b6 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 857cc138006c..87cf5734e60e 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 2e7c2b7e2da8..a9bf591bbd6a 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index ea3c2bc3b828..b8cc41c0d215 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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