Merge "msm: camera: Fix CCI sequential write"
diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h
index 1f4e718..799b575 100644
--- a/arch/arm/boot/compressed/libfdt_env.h
+++ b/arch/arm/boot/compressed/libfdt_env.h
@@ -1,6 +1,7 @@
#ifndef _ARM_LIBFDT_ENV_H
#define _ARM_LIBFDT_ENV_H
+#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
#include <asm/byteorder.h>
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 0eee530..032cca4 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -215,6 +215,7 @@
cmd_done.device_id = device_id;
cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
session_id;
+ cmd_done.status = hfi_map_err_status(pkt->event_data1);
dprintk(VIDC_INFO, "Received : SESSION_ERROR with event id : %d\n",
pkt->event_data1);
switch (pkt->event_data1) {
@@ -222,6 +223,7 @@
case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
+ cmd_done.status = VIDC_ERR_NONE;
dprintk(VIDC_INFO, "Non Fatal : HFI_EVENT_SESSION_ERROR\n");
break;
default:
@@ -834,12 +836,9 @@
} else {
sess_close = (struct hal_session *)pkt->session_id;
if (sess_close) {
- dprintk(VIDC_INFO,
- "Sess init failed: Deleting session: 0x%x 0x%p",
+ dprintk(VIDC_WARN,
+ "Sess init failed: 0x%x, 0x%p",
sess_close->session_id, sess_close);
- list_del(&sess_close->list);
- kfree(sess_close);
- sess_close = NULL;
}
}
cmd_done.size = sizeof(struct vidc_hal_session_init_done);
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 30ca194..7830db7 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -1400,7 +1400,7 @@
case V4L2_DEC_QCOM_CMD_FLUSH:
if (core->state != VIDC_CORE_INVALID &&
inst->state == MSM_VIDC_CORE_INVALID) {
- rc = msm_comm_recover_from_session_error(inst);
+ rc = msm_comm_kill_session(inst);
if (rc)
dprintk(VIDC_ERR,
"Failed to recover from session_error: %d\n",
@@ -1415,7 +1415,7 @@
case V4L2_DEC_CMD_STOP:
if (core->state != VIDC_CORE_INVALID &&
inst->state == MSM_VIDC_CORE_INVALID) {
- rc = msm_comm_recover_from_session_error(inst);
+ rc = msm_comm_kill_session(inst);
if (rc)
dprintk(VIDC_ERR,
"Failed to recover from session_error: %d\n",
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index ba17820..794d116 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -46,6 +46,10 @@
u32 __mbs = (__h >> 4) * (__w >> 4);\
__mbs;\
})
+static void msm_comm_generate_session_error(struct msm_vidc_inst *inst);
+static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst);
+static void handle_session_error(enum command_response cmd, void *data);
+
static bool is_turbo_requested(struct msm_vidc_core *core,
enum session_type type)
{
@@ -398,7 +402,7 @@
dprintk(VIDC_ERR,
"%s: Wait interrupted or timeout[%u]: %d\n",
__func__, (u32)inst->session, SESSION_MSG_INDEX(cmd));
- msm_comm_recover_from_session_error(inst);
+ msm_comm_kill_session(inst);
rc = -EIO;
} else {
rc = 0;
@@ -432,32 +436,19 @@
wake_up(&inst->kernel_event_queue);
}
-static void msm_comm_generate_session_error(struct msm_vidc_inst *inst)
-{
- if (!inst) {
- dprintk(VIDC_ERR, "%s: invalid input parameters", __func__);
- return;
- }
- mutex_lock(&inst->lock);
- inst->session = NULL;
- inst->state = MSM_VIDC_CORE_INVALID;
- msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
- mutex_unlock(&inst->lock);
-}
-
static void msm_comm_generate_max_clients_error(struct msm_vidc_inst *inst)
{
+ enum command_response cmd = SESSION_ERROR;
+ struct msm_vidc_cb_cmd_done response = {0};
+
if (!inst) {
dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
return;
}
- mutex_lock(&inst->sync_lock);
- inst->session = NULL;
- inst->state = MSM_VIDC_CORE_INVALID;
- msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_MAX_CLIENTS);
- dprintk(VIDC_WARN,
- "%s: Too many clients\n", __func__);
- mutex_unlock(&inst->sync_lock);
+ dprintk(VIDC_ERR, "%s: Too many clients\n", __func__);
+ response.session_id = (u32) inst;
+ response.status = VIDC_ERR_MAX_CLIENTS;
+ handle_session_error(cmd, (void *)&response);
}
static void handle_session_init_done(enum command_response cmd, void *data)
@@ -834,21 +825,50 @@
static void handle_session_error(enum command_response cmd, void *data)
{
struct msm_vidc_cb_cmd_done *response = data;
+ int rc;
+ struct hfi_device *hdev = NULL;
struct msm_vidc_inst *inst = NULL;
- if (response) {
- inst = (struct msm_vidc_inst *)response->session_id;
- if (inst) {
- dprintk(VIDC_WARN,
- "Session error receivd for session %p\n", inst);
- mutex_lock(&inst->sync_lock);
- inst->state = MSM_VIDC_CORE_INVALID;
- mutex_unlock(&inst->sync_lock);
- msm_vidc_queue_v4l2_event(inst,
- V4L2_EVENT_MSM_VIDC_SYS_ERROR);
- }
- } else {
+
+ if (!response) {
dprintk(VIDC_ERR,
"Failed to get valid response for session error\n");
+ return;
+ }
+
+ inst = (struct msm_vidc_inst *)response->session_id;
+
+ if (!inst || !inst->session || !inst->core->device) {
+ dprintk(VIDC_ERR,
+ "Session (%p) not in a stable enough state to handle session error\n",
+ inst);
+ return;
+ }
+
+ hdev = inst->core->device;
+ dprintk(VIDC_WARN, "Session error received for session %p\n", inst);
+ change_inst_state(inst, MSM_VIDC_CORE_INVALID);
+
+ mutex_lock(&inst->lock);
+ dprintk(VIDC_DBG, "cleaning up inst: %p\n", inst);
+ rc = call_hfi_op(hdev, session_clean, inst->session);
+ if (rc)
+ dprintk(VIDC_ERR, "Session (%p) clean failed: %d\n", inst, rc);
+
+ inst->session = NULL;
+ mutex_unlock(&inst->lock);
+
+ if (response->status == VIDC_ERR_MAX_CLIENTS) {
+ dprintk(VIDC_WARN,
+ "send max clients reached error to client: %p\n",
+ inst);
+ msm_vidc_queue_v4l2_event(inst,
+ V4L2_EVENT_MSM_VIDC_MAX_CLIENTS);
+ } else {
+ dprintk(VIDC_ERR,
+ "send session error to client: %p\n",
+ inst);
+ msm_vidc_queue_v4l2_event(inst,
+ V4L2_EVENT_MSM_VIDC_SYS_ERROR);
}
}
@@ -1249,10 +1269,10 @@
inst = (struct msm_vidc_inst *)response->session_id;
fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
buffer_type = msm_comm_get_hal_output_buffer(inst);
- if (fill_buf_done->buffer_type == buffer_type)
+ if (fill_buf_done->buffer_type == buffer_type) {
vb = get_vb_from_device_addr(&inst->bufq[CAPTURE_PORT],
(u32)fill_buf_done->packet_buffer1);
- else {
+ } else {
if (handle_multi_stream_buffers(inst,
(u32)fill_buf_done->packet_buffer1))
dprintk(VIDC_ERR,
@@ -1881,7 +1901,7 @@
num_mbs_per_sec, inst->core->resources.max_load);
msm_vidc_print_running_insts(inst->core);
inst->state = MSM_VIDC_CORE_INVALID;
- msm_comm_recover_from_session_error(inst);
+ msm_comm_kill_session(inst);
return -EBUSY;
}
@@ -2672,7 +2692,7 @@
__func__, (u32)inst->session,
SESSION_MSG_INDEX(SESSION_PROPERTY_INFO));
inst->state = MSM_VIDC_CORE_INVALID;
- msm_comm_recover_from_session_error(inst);
+ msm_comm_kill_session(inst);
rc = -EIO;
goto exit;
}
@@ -2790,11 +2810,9 @@
rc = wait_for_sess_signal_receipt(inst,
SESSION_RELEASE_BUFFER_DONE);
if (rc) {
- mutex_lock(&inst->sync_lock);
- inst->state = MSM_VIDC_CORE_INVALID;
- mutex_unlock(&inst->sync_lock);
- msm_comm_recover_from_session_error(
- inst);
+ change_inst_state(inst,
+ MSM_VIDC_CORE_INVALID);
+ msm_comm_kill_session(inst);
}
mutex_lock(&inst->lock);
}
@@ -2861,11 +2879,9 @@
rc = wait_for_sess_signal_receipt(inst,
SESSION_RELEASE_BUFFER_DONE);
if (rc) {
- mutex_lock(&inst->sync_lock);
- inst->state = MSM_VIDC_CORE_INVALID;
- mutex_unlock(&inst->sync_lock);
- msm_comm_recover_from_session_error(
- inst);
+ change_inst_state(inst,
+ MSM_VIDC_CORE_INVALID);
+ msm_comm_kill_session(inst);
}
mutex_lock(&inst->lock);
}
@@ -3472,9 +3488,7 @@
}
}
if (rc) {
- mutex_lock(&inst->sync_lock);
- inst->state = MSM_VIDC_CORE_INVALID;
- mutex_unlock(&inst->sync_lock);
+ change_inst_state(inst, MSM_VIDC_CORE_INVALID);
msm_vidc_queue_v4l2_event(inst,
V4L2_EVENT_MSM_VIDC_HW_OVERLOAD);
dprintk(VIDC_WARN,
@@ -3484,6 +3498,22 @@
return rc;
}
+static void msm_comm_generate_session_error(struct msm_vidc_inst *inst)
+{
+ enum command_response cmd = SESSION_ERROR;
+ struct msm_vidc_cb_cmd_done response = {0};
+
+ dprintk(VIDC_WARN, "msm_comm_generate_session_error\n");
+ if (!inst || !inst->core) {
+ dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
+ return;
+ }
+
+ response.session_id = (u32)inst;
+ response.status = VIDC_ERR_FAIL;
+ handle_session_error(cmd, (void *)&response);
+}
+
static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst)
{
struct msm_vidc_core *core;
@@ -3498,43 +3528,55 @@
handle_sys_error(cmd, (void *) &response);
}
-int msm_comm_recover_from_session_error(struct msm_vidc_inst *inst)
+
+int msm_comm_kill_session(struct msm_vidc_inst *inst)
{
- struct hfi_device *hdev;
int rc = 0;
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s: invalid input parameters", __func__);
return -EINVAL;
+ } else if (!inst->session) {
+ /* There's no hfi session to kill */
+ return 0;
}
- if (!inst->session || inst->state < MSM_VIDC_OPEN_DONE) {
- dprintk(VIDC_WARN,
- "No corresponding FW session. No need to send Abort");
- return rc;
- }
- hdev = inst->core->device;
- init_completion(&inst->completions[SESSION_MSG_INDEX
- (SESSION_ABORT_DONE)]);
-
- /* We have received session_error. Send session_abort to firmware
- * to clean up and release the session
+ /*
+ * We're internally forcibly killing the session, if fw is aware of
+ * the session send session_abort to firmware to clean up and release
+ * the session, else just kill the session inside the driver.
*/
- rc = call_hfi_op(hdev, session_abort, (void *) inst->session);
- if (rc) {
- dprintk(VIDC_ERR, "session_abort failed rc: %d\n", rc);
- return rc;
+ if (inst->state >= MSM_VIDC_OPEN_DONE &&
+ inst->state < MSM_VIDC_CLOSE_DONE) {
+ struct hfi_device *hdev = inst->core->device;
+ int abort_completion = SESSION_MSG_INDEX(SESSION_ABORT_DONE);
+
+ rc = call_hfi_op(hdev, session_abort, (void *) inst->session);
+ if (rc) {
+ dprintk(VIDC_ERR, "session_abort failed rc: %d\n", rc);
+ return rc;
+ }
+
+ init_completion(&inst->completions[abort_completion]);
+ rc = wait_for_completion_timeout(
+ &inst->completions[abort_completion],
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
+ if (!rc) {
+ dprintk(VIDC_ERR,
+ "%s: Wait interrupted or timed out [%p]: %d\n",
+ __func__, inst, abort_completion);
+ msm_comm_generate_sys_error(inst);
+ } else {
+ change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
+ }
+ } else {
+ dprintk(VIDC_WARN,
+ "Inactive session %p, triggering an internal session error\n",
+ inst);
+ msm_comm_generate_session_error(inst);
+
}
- rc = wait_for_completion_timeout(
- &inst->completions[SESSION_MSG_INDEX(SESSION_ABORT_DONE)],
- msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
- if (!rc) {
- dprintk(VIDC_ERR, "%s: Wait interrupted or timeout[%u]: %d\n",
- __func__, (u32)inst->session,
- SESSION_MSG_INDEX(SESSION_ABORT_DONE));
- msm_comm_generate_sys_error(inst);
- } else
- change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
+
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index f4e2cd5..1e86278 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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,7 +52,7 @@
V4L2_CTRL_DRIVER_PRIV(idx))
int msm_comm_check_scaling_supported(struct msm_vidc_inst *inst);
-int msm_comm_recover_from_session_error(struct msm_vidc_inst *inst);
+int msm_comm_kill_session(struct msm_vidc_inst *inst);
enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst);
enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst);
struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst,
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index e56833a..e591c54 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -71,6 +71,20 @@
return -FDT_ERR_BADMAGIC;
}
+ if (fdt_off_dt_struct(fdt) > (UINT_MAX - fdt_size_dt_struct(fdt)))
+ return FDT_ERR_BADOFFSET;
+
+ if (fdt_off_dt_strings(fdt) > (UINT_MAX - fdt_size_dt_strings(fdt)))
+ return FDT_ERR_BADOFFSET;
+
+ if ((fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt))
+ > fdt_totalsize(fdt))
+ return FDT_ERR_BADOFFSET;
+
+ if ((fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))
+ > fdt_totalsize(fdt))
+ return FDT_ERR_BADOFFSET;
+
return 0;
}
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 24437df..d7d09fe 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -394,7 +394,7 @@
static void _fdt_packblocks(const char *old, char *new,
int mem_rsv_size, int struct_size)
{
- int mem_rsv_off, struct_off, strings_off;
+ uint32_t mem_rsv_off, struct_off, strings_off;
mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
struct_off = mem_rsv_off + mem_rsv_size;