diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2019-10-25 02:27:41 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2019-10-25 02:27:41 -0700 |
commit | af5699216695e8839c2b578266745447b6d503b1 (patch) | |
tree | 14db3236596812bee08a0d52bc14bd2fedbba677 | |
parent | c067df34e83888d7e6fe5a9d118f23c7179cf720 (diff) | |
parent | 34daca88bdeb0937e3a4a6fe4c7e8e5ab4dc4f75 (diff) |
Merge 34daca88bdeb0937e3a4a6fe4c7e8e5ab4dc4f75 on remote branchLA.UM.7.6.2.r1-10300-89xx.0
Change-Id: I4538dd3e7ed8dc1f451f6753416deac77ff27da6
25 files changed, 516 insertions, 66 deletions
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 57e24482f2d4..d26885aeb5c2 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -897,7 +897,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, goto end; if (mask_size + write_len > dest_len) mask_size = dest_len - write_len; - memcpy(dest_buf + write_len, src_buf + header_len, mask_size); + if (mask_size && src_len >= header_len + mask_size) + memcpy(dest_buf + write_len, src_buf + header_len, mask_size); write_len += mask_size; for (i = 0; i < NUM_MD_SESSIONS; i++) { if (i == APPS_DATA) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 64945cf752cd..e9b64af09937 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -176,6 +176,8 @@ static ssize_t dp_debug_write_dpcd(struct file *file, goto bail; size = min_t(size_t, count, SZ_2K); + if (size < 4) + goto bail; buf = kzalloc(size, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { @@ -204,6 +206,8 @@ static ssize_t dp_debug_write_dpcd(struct file *file, } size -= 4; + if (size == 0) + goto bail; dpcd_size = size / char_to_nib; buf_t = buf + 4; @@ -255,6 +259,7 @@ static ssize_t dp_debug_read_dpcd(struct file *file, len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; @@ -412,7 +417,7 @@ static ssize_t dp_debug_write_exe_mode(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; - char *buf; + char buf[SZ_32]; size_t len = 0; if (!debug) @@ -421,8 +426,11 @@ static ssize_t dp_debug_write_exe_mode(struct file *file, if (*ppos) return 0; + /* Leave room for termination char */ len = min_t(size_t, count, SZ_32 - 1); - buf = memdup_user(user_buff, len); + if (copy_from_user(buf, user_buff, len)) + goto end; + buf[len] = '\0'; if (sscanf(buf, "%3s", debug->exe_mode) != 1) @@ -453,6 +461,7 @@ static ssize_t dp_debug_read_connected(struct file *file, len += snprintf(buf, SZ_8, "%d\n", debug->usbpd->hpd_high); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; @@ -516,6 +525,7 @@ static ssize_t dp_debug_read_edid_modes(struct file *file, } mutex_unlock(&connector->dev->mode_config.mutex); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) { kfree(buf); rc = -EFAULT; @@ -605,6 +615,7 @@ static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) goto error; @@ -637,6 +648,7 @@ static ssize_t dp_debug_bw_code_read(struct file *file, len += snprintf(buf + len, (SZ_4K - len), "max_bw_code = %d\n", debug->panel->max_bw_code); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) { kfree(buf); return -EFAULT; @@ -662,6 +674,7 @@ static ssize_t dp_debug_tpg_read(struct file *file, len += snprintf(buf, SZ_8, "%d\n", debug->dp_debug.tpg_state); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; @@ -852,6 +865,7 @@ static ssize_t dp_debug_read_hdr(struct file *file, goto error; } + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) { kfree(buf); rc = -EFAULT; @@ -1011,6 +1025,7 @@ static ssize_t dp_debug_read_dump(struct file *file, print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE, 16, 4, buf, len, false); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 85b9f7e153a9..9d6ccb947825 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2019, 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 @@ -1537,6 +1537,9 @@ static ssize_t _sde_debugfs_conn_cmd_tx_sts_read(struct file *file, return 0; } + if (blen > count) + blen = count; + if (copy_to_user(buf, buffer, blen)) { SDE_ERROR("copy to user buffer failed\n"); return -EFAULT; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index d6e8fd34e051..9a0d9735bf07 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -1180,8 +1180,24 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start( else ret = 0; - if (sde_encoder_phys_cmd_is_master(phys_enc)) + if (sde_encoder_phys_cmd_is_master(phys_enc)) { + /* + * Signaling the retire fence at ctl start timeout + * to allow the next commit and avoid device freeze. + * As ctl start timeout can occurs due to no read ptr, + * updating pending_rd_ptr_cnt here may not cover all + * cases. Hence signaling the retire fence. + */ + if (atomic_add_unless( + &phys_enc->pending_retire_fence_cnt, -1, 0)) + phys_enc->parent_ops.handle_frame_done( + phys_enc->parent, + phys_enc, + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); + atomic_add_unless( + &phys_enc->pending_ctlstart_cnt, -1, 0); atomic_inc_return(&phys_enc->ctlstart_timeout); + } } return ret; diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c index 721e2789ddd5..7ded089b84d3 100644 --- a/drivers/gpu/drm/msm/sde_rsc.c +++ b/drivers/gpu/drm/msm/sde_rsc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2019, 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 @@ -1044,6 +1044,9 @@ end: if (blen <= 0) return 0; + if (blen > count) + blen = count; + if (copy_to_user(buf, buffer, blen)) return -EFAULT; @@ -1136,6 +1139,9 @@ end: if (blen <= 0) return 0; + if (blen > count) + blen = count; + if (copy_to_user(buf, buffer, blen)) return -EFAULT; diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 596d17381799..6ffc882ce75a 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -3337,12 +3337,16 @@ long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *process = dev_priv->process_priv; + struct kgsl_device *device = dev_priv->device; struct kgsl_sparse_phys_alloc *param = data; struct kgsl_mem_entry *entry; uint64_t flags; int ret; int id; + if (!(device->flags & KGSL_FLAG_SPARSE)) + return -ENOTSUPP; + ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize); if (ret) return ret; @@ -3422,9 +3426,13 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *process = dev_priv->process_priv; + struct kgsl_device *device = dev_priv->device; struct kgsl_sparse_phys_free *param = data; struct kgsl_mem_entry *entry; + if (!(device->flags & KGSL_FLAG_SPARSE)) + return -ENOTSUPP; + entry = kgsl_sharedmem_find_id_flags(process, param->id, KGSL_MEMFLAGS_SPARSE_PHYS); if (entry == NULL) @@ -3454,10 +3462,14 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *private = dev_priv->process_priv; + struct kgsl_device *device = dev_priv->device; struct kgsl_sparse_virt_alloc *param = data; struct kgsl_mem_entry *entry; int ret; + if (!(device->flags & KGSL_FLAG_SPARSE)) + return -ENOTSUPP; + ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize); if (ret) return ret; @@ -3498,9 +3510,13 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *process = dev_priv->process_priv; + struct kgsl_device *device = dev_priv->device; struct kgsl_sparse_virt_free *param = data; struct kgsl_mem_entry *entry = NULL; + if (!(device->flags & KGSL_FLAG_SPARSE)) + return -ENOTSUPP; + entry = kgsl_sharedmem_find_id_flags(process, param->id, KGSL_MEMFLAGS_SPARSE_VIRT); if (entry == NULL) @@ -3847,6 +3863,7 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *private = dev_priv->process_priv; + struct kgsl_device *device = dev_priv->device; struct kgsl_sparse_bind *param = data; struct kgsl_sparse_binding_object obj; struct kgsl_mem_entry *virt_entry; @@ -3855,6 +3872,9 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv, int ret = 0; int i = 0; + if (!(device->flags & KGSL_FLAG_SPARSE)) + return -ENOTSUPP; + ptr = (void __user *) (uintptr_t) param->list; if (param->size > sizeof(struct kgsl_sparse_binding_object) || @@ -3910,6 +3930,9 @@ long kgsl_ioctl_gpu_sparse_command(struct kgsl_device_private *dev_priv, long result; unsigned int i = 0; + if (!(device->flags & KGSL_FLAG_SPARSE)) + return -ENOTSUPP; + /* Make sure sparse and syncpoint count isn't too big */ if (param->numsparse > KGSL_MAX_SPARSE || param->numsyncs > KGSL_MAX_SYNCPOINTS) @@ -4665,6 +4688,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device) /* Initialize logging first, so that failures below actually print. */ kgsl_device_debugfs_init(device); + /* Disable the sparse ioctl invocation as they are not used */ + device->flags &= ~KGSL_FLAG_SPARSE; + status = kgsl_pwrctrl_init(device); if (status) goto error; diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 4a98a240810a..01c38d0b6b30 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2019, 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 @@ -66,6 +66,7 @@ enum kgsl_event_results { }; #define KGSL_FLAG_WAKE_ON_TOUCH BIT(0) +#define KGSL_FLAG_SPARSE BIT(1) /* * "list" of event types for ftrace symbolic magic diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c index b4f0dbf3d6d2..378a15af29b3 100644 --- a/drivers/hwmon/qpnp-adc-voltage.c +++ b/drivers/hwmon/qpnp-adc-voltage.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2019, 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 @@ -742,7 +742,7 @@ int32_t qpnp_vadc_hc_read(struct qpnp_vadc_chip *vadc, QPNP_VADC_CAL_DELAY_CTL_1, &val, 1); if (rc < 0) { pr_err("qpnp adc write cal_delay failed with %d\n", rc); - return rc; + goto fail_unlock; } } diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index e63c79abcdbb..d58dc78f6c06 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -1490,8 +1490,6 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { uint32_t i; int rc = -1; - int counter = 0; - u32 result = 0; struct cpp_device *cpp_dev = NULL; struct msm_device_queue *processing_q = NULL; struct msm_device_queue *eventData_q = NULL; @@ -1571,54 +1569,6 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) pr_debug("DEBUG_R1: 0x%x\n", msm_camera_io_r(cpp_dev->cpp_hw_base + 0x8C)); - /* mask IRQ status */ - msm_camera_io_w(0xB, cpp_dev->cpp_hw_base + 0xC); - - /* clear IRQ status */ - msm_camera_io_w(0xFFFFF, cpp_dev->cpp_hw_base + 0x14); - - /* MMSS_A_CPP_AXI_CMD = 0x16C, reset 0x1*/ - msm_camera_io_w(0x1, cpp_dev->cpp_hw_base + 0x16C); - - while (counter < MSM_CPP_POLL_RETRIES) { - result = msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10); - if (result & 0x2) - break; - /* - * Below usleep values are chosen based on experiments - * and this was the smallest number which works. This - * sleep is needed to leave enough time for hardware - * to update status register. - */ - usleep_range(200, 250); - counter++; - } - - pr_debug("CPP AXI done counter %d result 0x%x\n", - counter, result); - - /* clear IRQ status */ - msm_camera_io_w(0xFFFFF, cpp_dev->cpp_hw_base + 0x14); - counter = 0; - /* MMSS_A_CPP_RST_CMD_0 = 0x8, firmware reset = 0x3DF77 */ - msm_camera_io_w(0x3DF77, cpp_dev->cpp_hw_base + 0x8); - - while (counter < MSM_CPP_POLL_RETRIES) { - result = msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10); - if (result & 0x1) - break; - /* - * Below usleep values are chosen based on experiments - * and this was the smallest number which works. This - * sleep is needed to leave enough time for hardware - * to update status register. - */ - usleep_range(200, 250); - counter++; - } - pr_debug("CPP reset done counter %d result 0x%x\n", - counter, result); - msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL); msm_cpp_clear_timer(cpp_dev); cpp_release_hardware(cpp_dev); diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c index 42f5a840de46..1f19f58e33e4 100644 --- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c +++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c @@ -233,6 +233,28 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, return rc; } +int cam_context_handle_crm_dump_req(struct cam_context *ctx, + struct cam_req_mgr_dump_info *dump) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].crm_ops.dump_req) { + rc = ctx->state_machine[ctx->state].crm_ops.dump_req(ctx, + dump); + } else { + CAM_ERR(CAM_CORE, "No crm dump req in dev %d, state %d", + ctx->dev_hdl, ctx->state); + } + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, uint32_t buf_info) { @@ -501,6 +523,33 @@ int cam_context_handle_stop_dev(struct cam_context *ctx, return rc; } +int cam_context_handle_dump_dev(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc = 0; + + if (!ctx || !ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!cmd) { + CAM_ERR(CAM_CORE, "Invalid stop device command payload"); + return -EINVAL; + } + + mutex_lock(&ctx->ctx_mutex); + if (ctx->state_machine[ctx->state].ioctl_ops.dump_dev) + rc = ctx->state_machine[ctx->state].ioctl_ops.dump_dev( + ctx, cmd); + else + CAM_WARN(CAM_CORE, "No dump device in dev %d, name %s state %d", + ctx->dev_hdl, ctx->dev_name, ctx->state); + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + int cam_context_init(struct cam_context *ctx, const char *dev_name, uint64_t dev_id, diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h index 2d8c6e0ae819..84a190a4c5a6 100644 --- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h +++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h @@ -92,6 +92,7 @@ struct cam_ctx_request { * @flush_dev: Function pointer for flush device * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw + * @dump_dev: Function pointer for dump dev * */ struct cam_ctx_ioctl_ops { @@ -109,6 +110,9 @@ struct cam_ctx_ioctl_ops { struct cam_flush_dev_cmd *cmd); int (*acquire_hw)(struct cam_context *ctx, void *args); int (*release_hw)(struct cam_context *ctx, void *args); + int (*dump_dev)(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd); + }; /** @@ -120,6 +124,7 @@ struct cam_ctx_ioctl_ops { * @apply_req: Apply setting for the context * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) + * @dump_req: Dump information for the issue request * */ struct cam_ctx_crm_ops { @@ -135,6 +140,8 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_flush_request *flush); int (*process_evt)(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *evt_data); + int (*dump_req)(struct cam_context *ctx, + struct cam_req_mgr_dump_info *dump); }; @@ -305,6 +312,18 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *process_evt); /** + * cam_context_handle_crm_dump_req() + * + * @brief: Handle CRM dump request + * + * @ctx: Object pointer for cam_context + * @dump: Request to dump + * + */ +int cam_context_handle_crm_dump_req(struct cam_context *ctx, + struct cam_req_mgr_dump_info *dump); + +/** * cam_context_dump_pf_info() * * @brief: Handle dump active request request command @@ -413,6 +432,19 @@ int cam_context_handle_start_dev(struct cam_context *ctx, int cam_context_handle_stop_dev(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); + +/** + * cam_context_handle_dump_dev() + * + * @brief: Handle dump device command + * + * @ctx: Object pointer for cam_context + * @cmd: Dump device command payload + * + */ +int cam_context_handle_dump_dev(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd); + /** * cam_context_deinit() * diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c index 11bad5dd4647..d7500a138803 100644 --- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c +++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c @@ -1039,3 +1039,43 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, end: return rc; } + +int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd) +{ + int rc = 0; + struct cam_hw_dump_args dump_args; + + if (!ctx || !cmd) { + CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd); + return -EINVAL; + } + if (!ctx->hw_mgr_intf) { + CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready", + ctx->dev_name, ctx->ctx_id); + return -EFAULT; + } + memset(&dump_args, 0, sizeof(dump_args)); + if (ctx->hw_mgr_intf->hw_dump) { + dump_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + dump_args.buf_handle = cmd->buf_handle; + dump_args.offset = cmd->offset; + dump_args.request_id = cmd->issue_req_id; + rc = ctx->hw_mgr_intf->hw_dump( + ctx->hw_mgr_intf->hw_mgr_priv, + &dump_args); + if (rc) { + CAM_ERR(CAM_CTXT, "[%s][%d] handle[%u] failed", + ctx->dev_name, ctx->ctx_id, dump_args.buf_handle); + return rc; + } + CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %d", + ctx->dev_name, ctx->ctx_id, + dump_args.offset - cmd->offset); + /* Drivers update offest upto which the buffer is written*/ + cmd->offset = dump_args.offset; + } else { + CAM_INFO(CAM_CTXT, "%s hw dump not registered", ctx->dev_name); + } + return rc; +} diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h index e1809b2fa436..022641f064ea 100644 --- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h +++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, 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 @@ -36,5 +36,6 @@ int32_t cam_context_flush_req_to_hw(struct cam_context *ctx, int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx, struct cam_packet *packet, unsigned long iova, uint32_t buf_info, bool *mem_found); - +int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx, + struct cam_dump_req_cmd *cmd); #endif /* _CAM_CONTEXT_UTILS_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h index 2afdafb03184..19e3230d9011 100644 --- a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h @@ -272,6 +272,21 @@ struct cam_hw_reset_args { void *ctxt_to_hw_map; }; +/** + * struct cam_hw_dump_args - Dump arguments + * + * @request_id: request_id + * @buf_handle: Buffer handle + * @offset: Buffer offset. This is updated by the drivers. + * @ctxt_to_hw_map: HW context from the acquire + */ +struct cam_hw_dump_args { + uint64_t request_id; + uint32_t buf_handle; + int32_t offset; + void *ctxt_to_hw_map; +}; + /* enum cam_hw_mgr_command - Hardware manager command type */ enum cam_hw_mgr_command { CAM_HW_MGR_CMD_INTERNAL, @@ -324,6 +339,7 @@ struct cam_hw_cmd_args { * @hw_close: Function pointer for HW deinit * @hw_flush: Function pointer for HW flush * @hw_reset: Function pointer for HW reset + * @hw_dump: Function pointer for HW dump * */ struct cam_hw_mgr_intf { @@ -345,6 +361,7 @@ struct cam_hw_mgr_intf { int (*hw_close)(void *hw_priv, void *hw_close_args); int (*hw_flush)(void *hw_priv, void *hw_flush_args); int (*hw_reset)(void *hw_priv, void *hw_reset_args); + int (*hw_dump)(void *hw_priv, void *hw_dump_args); }; #endif /* _CAM_HW_MGR_INTF_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c index 2578fb93a615..322b7e68da69 100644 --- a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c +++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c @@ -330,6 +330,39 @@ static int __cam_node_handle_flush_dev(struct cam_node *node, return rc; } +static int __cam_node_handle_dump_dev(struct cam_node *node, + struct cam_dump_req_cmd *dump) +{ + struct cam_context *ctx = NULL; + int rc; + + if (!dump) + return -EINVAL; + + if (dump->dev_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid device handle for context"); + return -EINVAL; + } + + if (dump->session_handle <= 0) { + CAM_ERR(CAM_CORE, "Invalid session handle for context"); + return -EINVAL; + } + + ctx = (struct cam_context *)cam_get_device_priv(dump->dev_handle); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + dump->dev_handle); + return -EINVAL; + } + + rc = cam_context_handle_dump_dev(ctx, dump); + if (rc) + CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name); + + return rc; +} + static int __cam_node_handle_release_dev(struct cam_node *node, struct cam_release_dev_cmd *release) { @@ -531,6 +564,25 @@ static int __cam_node_crm_process_evt( return cam_context_handle_crm_process_evt(ctx, evt_data); } +static int __cam_node_crm_dump_req(struct cam_req_mgr_dump_info *dump) +{ + struct cam_context *ctx = NULL; + + if (!dump) { + CAM_ERR(CAM_CORE, "Invalid dump request payload"); + return -EINVAL; + } + + ctx = (struct cam_context *) cam_get_device_priv(dump->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + dump->dev_hdl); + return -EINVAL; + } + + return cam_context_handle_crm_dump_req(ctx, dump); +} + int cam_node_deinit(struct cam_node *node) { if (node) @@ -586,6 +638,7 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.link_setup = __cam_node_crm_link_setup; node->crm_node_intf.flush_req = __cam_node_crm_flush_req; node->crm_node_intf.process_evt = __cam_node_crm_process_evt; + node->crm_node_intf.dump_req = __cam_node_crm_dump_req; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); @@ -827,6 +880,28 @@ release_kfree: } break; } + case CAM_DUMP_REQ: { + struct cam_dump_req_cmd dump; + + if (copy_from_user(&dump, u64_to_user_ptr(cmd->handle), + sizeof(dump))) { + rc = -EFAULT; + } else { + rc = __cam_node_handle_dump_dev(node, &dump); + if (rc) { + CAM_ERR(CAM_CORE, + "Dump device %s failed(rc = %d) ", + node->name, rc); + } else if (copy_to_user(u64_to_user_ptr(cmd->handle), + &dump, sizeof(dump))) { + CAM_ERR(CAM_CORE, + "Dump device %s copy_to_user fail", + node->name); + rc = -EFAULT; + } + } + break; + } default: CAM_ERR(CAM_CORE, "Unknown op code %d", cmd->op_code); rc = -EINVAL; diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c index b2994d52d83c..4d10ea65818e 100644 --- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c @@ -3454,9 +3454,73 @@ end: } +int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req) +{ + int rc = 0; + struct cam_req_mgr_core_link *link = NULL; + struct cam_req_mgr_core_session *session = NULL; + struct cam_req_mgr_dump_info info; + struct cam_req_mgr_connected_device *device = NULL; + int i; + + if (!dump_req) { + CAM_ERR(CAM_CRM, "dump req is NULL"); + rc = -EFAULT; + goto end; + } + + mutex_lock(&g_crm_core_dev->crm_lock); + /* session hdl's priv data is cam session struct */ + session = (struct cam_req_mgr_core_session *) + cam_get_device_priv(dump_req->session_handle); + if (!session) { + CAM_ERR(CAM_CRM, "Invalid session %x", + dump_req->session_handle); + rc = -EINVAL; + goto end; + } + if (session->num_links <= 0) { + CAM_WARN(CAM_CRM, "No active links in session %x", + dump_req->session_handle); + goto end; + } + + link = (struct cam_req_mgr_core_link *) + cam_get_device_priv(dump_req->link_hdl); + if (!link) { + CAM_DBG(CAM_CRM, "link ptr NULL %x", dump_req->link_hdl); + rc = -EINVAL; + goto end; + } + info.offset = dump_req->offset; + for (i = 0; i < link->num_devs; i++) { + device = &link->l_dev[i]; + info.link_hdl = dump_req->link_hdl; + info.dev_hdl = device->dev_hdl; + info.req_id = dump_req->issue_req_id; + info.buf_handle = dump_req->buf_handle; + if (device->ops && device->ops->dump_req) { + rc = device->ops->dump_req(&info); + if (rc) { + CAM_ERR(CAM_REQ, "Fail dump req %lld dev %d", + info.req_id, + device->dev_hdl); + } + } + } + dump_req->offset = info.offset; + CAM_INFO(CAM_REQ, "req %lld, offset %u", + dump_req->issue_req_id, dump_req->offset); +end: + mutex_unlock(&g_crm_core_dev->crm_lock); + return 0; + +} + int cam_req_mgr_core_device_init(void) { int i; + CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev); if (g_crm_core_dev) { diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h index 94f26dee8917..679b2cf4a5a2 100644 --- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h @@ -56,6 +56,7 @@ enum crm_workq_task_type { CRM_WORKQ_TASK_NOTIFY_FREEZE, CRM_WORKQ_TASK_SCHED_REQ, CRM_WORKQ_TASK_FLUSH_REQ, + CRM_WORKQ_TASK_DUMP_REQ, CRM_WORKQ_TASK_INVALID, }; @@ -485,4 +486,11 @@ void cam_req_mgr_handle_core_shutdown(void); */ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control); +/** + * cam_req_mgr_dump_request() + * @brief: Dumps the request information + * @dump_req: Dump request + */ +int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req); + #endif diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c index 31607ac6391f..5d4d9fcc47ab 100644 --- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c @@ -473,6 +473,31 @@ static long cam_private_ioctl(struct file *file, void *fh, rc = -EINVAL; } break; + + case CAM_REQ_MGR_REQUEST_DUMP: { + struct cam_dump_req_cmd cmd; + + if (k_ioctl->size != sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, + u64_to_user_ptr(k_ioctl->handle), + sizeof(struct cam_dump_req_cmd))) { + rc = -EFAULT; + break; + } + + rc = cam_req_mgr_dump_request(&cmd); + if (!rc) + if (copy_to_user( + u64_to_user_ptr(k_ioctl->handle), + &cmd, sizeof(struct cam_dump_req_cmd))) { + rc = -EFAULT; + break; + } + } + break; + default: return -ENOIOCTLCMD; } diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h index 934bc76014a5..33274186fc15 100644 --- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h @@ -26,6 +26,7 @@ struct cam_req_mgr_core_dev_link_setup; struct cam_req_mgr_apply_request; struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; +struct cam_req_mgr_dump_info; #define SKIP_NEXT_FRAME 0x100 @@ -52,6 +53,7 @@ typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *); * @cam_req_mgr_apply_req : CRM asks device to apply certain request id. * @cam_req_mgr_flush_req : Flush or cancel request * cam_req_mgr_process_evt : generic events + * cam_req_mgr_dump_req : dump request */ typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)( @@ -59,6 +61,7 @@ typedef int (*cam_req_mgr_link_setup)( typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *); typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); +typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); /** * @brief : cam_req_mgr_crm_cb - func table @@ -81,6 +84,7 @@ struct cam_req_mgr_crm_cb { * @apply_req : payload to apply request id on a device linked * @flush_req : payload to flush request * @process_evt : payload to generic event + * @dump_req : payload to dump request */ struct cam_req_mgr_kmd_ops { cam_req_mgr_get_dev_info get_dev_info; @@ -88,6 +92,7 @@ struct cam_req_mgr_kmd_ops { cam_req_mgr_apply_req apply_req; cam_req_mgr_flush_req flush_req; cam_req_mgr_process_evt process_evt; + cam_req_mgr_dump_req dump_req; }; /** @@ -338,4 +343,25 @@ struct cam_req_mgr_send_request { int32_t link_hdl; struct cam_req_mgr_req_queue *in_q; }; + +/** + * struct cam_req_mgr_dump_info + * @req_id : request id to cancel + * @link_hdl : link identifier + * @dev_hdl : device handle for cross check + * @buf_handle : buf handle + * @offset : offset of buffere + * @error_type : error type + * + */ +struct cam_req_mgr_dump_info { + uint64_t req_id; + int32_t link_hdl; + int32_t dev_hdl; + uint32_t buf_handle; + int32_t offset; + int32_t error_type; +}; + + #endif diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.c index bba12cf106df..fd113aeb1dc5 100644 --- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.c +++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, 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 @@ -55,3 +55,22 @@ uint32_t cam_common_util_remove_duplicate_arr(int32_t *arr, uint32_t num) return wr_idx; } + +uint64_t cam_common_util_get_time_diff(struct timeval *t1, struct timeval *t2) +{ + uint64_t diff = 0; + + diff = (t1->tv_sec - t2->tv_sec) * 1000000 + + (t1->tv_usec - t2->tv_usec); + return diff; +} + +void cam_common_util_get_curr_timestamp(struct timeval *time_stamp) +{ + struct timespec ts; + + get_monotonic_boottime(&ts); + time_stamp->tv_sec = ts.tv_sec; + time_stamp->tv_usec = ts.tv_nsec/1000; +} + diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h index 47d441fe3aa1..136eaf013695 100644 --- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h +++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, 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 @@ -52,4 +52,26 @@ int cam_common_util_get_string_index(const char **strings, uint32_t cam_common_util_remove_duplicate_arr(int32_t *array, uint32_t num); +/** + * cam_common_util_get_time_diff() + * + * @brief Get the time difference between 2 timestamps in usecs + * + * @t1: Pointer to the later time + * @t2: Pointer to the prev time + * + * @return: differnce in usecs + */ +uint64_t cam_common_util_get_time_diff(struct timeval *t1, struct timeval *t2); + +/** + * cam_comomon_util_get_curr_timestamp() + * + * @brief Get the current timestamp + * + * @time_stamp: Pointer to the time + * + * @return: void + */ +void cam_common_util_get_curr_timestamp(struct timeval *time_stamp); #endif /* _CAM_COMMON_UTIL_H_ */ diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index f71621ea6966..2fff4345ec01 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -4725,7 +4725,6 @@ recheck: strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE); if (__qseecom_get_fw_size(app_name, &fw_size, &app_arch)) { ret = -EIO; - kfree(entry); goto exit_entry_free; } entry->app_arch = app_arch; @@ -7566,6 +7565,13 @@ static long qseecom_ioctl(struct file *file, break; } case QSEECOM_IOCTL_APP_LOADED_QUERY_REQ: { + if ((data->type != QSEECOM_GENERIC) && + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("app loaded query req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->type = QSEECOM_CLIENT_APP; mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index f18d7d306dd0..6385e1df55b6 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -2753,7 +2753,25 @@ out: mutex_unlock(&chip->cyc_ctr.lock); } -static const char *fg_get_cycle_count(struct fg_chip *chip) +static int fg_get_cycle_count(struct fg_chip *chip) +{ + int i, len = 0; + + if (!chip->cyc_ctr.en) + return 0; + + mutex_lock(&chip->cyc_ctr.lock); + for (i = 0; i < BUCKET_COUNT; i++) + len += chip->cyc_ctr.count[i]; + + mutex_unlock(&chip->cyc_ctr.lock); + + len = len / BUCKET_COUNT; + + return len; +} + +static const char *fg_get_cycle_counts(struct fg_chip *chip) { int i, len = 0; char *buf; @@ -4042,8 +4060,11 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: pval->intval = chip->bp.float_volt_uv; break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + pval->intval = fg_get_cycle_count(chip); + break; case POWER_SUPPLY_PROP_CYCLE_COUNTS: - pval->strval = fg_get_cycle_count(chip); + pval->strval = fg_get_cycle_counts(chip); break; case POWER_SUPPLY_PROP_CHARGE_NOW_RAW: rc = fg_get_charge_raw(chip, &pval->intval); @@ -4281,6 +4302,7 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_BATTERY_TYPE, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_CYCLE_COUNTS, POWER_SUPPLY_PROP_CHARGE_NOW_RAW, POWER_SUPPLY_PROP_CHARGE_NOW, diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h index e69fe7ab5f96..c0f2f2ed29ec 100644 --- a/include/uapi/media/cam_defs.h +++ b/include/uapi/media/cam_defs.h @@ -21,6 +21,7 @@ #define CAM_COMMON_OPCODE_BASE_v2 0x150 #define CAM_ACQUIRE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x1) #define CAM_RELEASE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x2) +#define CAM_DUMP_REQ (CAM_COMMON_OPCODE_BASE_v2 + 0x3) #define CAM_EXT_OPCODE_BASE 0x200 #define CAM_CONFIG_DEV_EXTERNAL (CAM_EXT_OPCODE_BASE + 0x1) @@ -207,6 +208,30 @@ struct cam_iommu_handle { #define CAM_PACKET_DEV_LRME 17 #define CAM_PACKET_DEV_MAX 18 +/** + * struct cam_dump_req_cmd - + * Dump the information of issue req id + * + * @issue_req_id : Issue Request Id + * @session_handle : Session Handle + * @link_hdl : link handle + * @dev_handle : Device Handle + * @error_type : Error Type + * @buf_handle : Buffer Handle + * @offset : offset for the buffer + * @reserved : Reserved + */ +struct cam_dump_req_cmd { + int64_t issue_req_id; + int32_t session_handle; + int32_t link_hdl; + int32_t dev_handle; + int32_t error_type; + uint32_t buf_handle; + int32_t offset; + uint32_t reserved; +}; + /* constants */ #define CAM_PACKET_MAX_PLANES 3 diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index 9b9f97bd50d5..08fe9b547855 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -246,6 +246,7 @@ struct cam_req_mgr_link_control { #define CAM_REQ_MGR_CACHE_OPS (CAM_COMMON_OPCODE_MAX + 12) #define CAM_REQ_MGR_LINK_CONTROL (CAM_COMMON_OPCODE_MAX + 13) #define CAM_REQ_MGR_LINK_V2 (CAM_COMMON_OPCODE_MAX + 14) +#define CAM_REQ_MGR_REQUEST_DUMP (CAM_COMMON_OPCODE_MAX + 15) /* end of cam_req_mgr opcodes */ #define CAM_MEM_FLAG_HW_READ_WRITE (1<<0) |