msm: vidc: Handles secure/non-secure concurrency.
Handles concurrency scenarios by preventing
nonsecure sessions when secure sessions are
ongoing. This is required since secure and
non-secure sessions cannot run concurrently.
Change-Id: I197a4c437312d916c0f75e7eb026c0570fee12ff
Signed-off-by: Deepak Kotur <dkotur@codeaurora.org>
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 483eab0..77ad02e 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -33,6 +33,7 @@
struct mem_region *mregion);
u32 width;
u32 height;
+ int secure;
};
struct venc {
@@ -266,6 +267,7 @@
struct venc_inst *inst;
struct video_client_ctx *client_ctx;
struct venc_msg_ops *vmops = arg;
+ int flags = 0;
mutex_lock(&venc_p.lock);
client_index = venc_get_empty_client_index();
if (client_index < 0) {
@@ -284,7 +286,11 @@
inst->op_buffer_done = vmops->op_buffer_done;
inst->ip_buffer_done = vmops->ip_buffer_done;
inst->cbdata = vmops->cbdata;
-
+ inst->secure = vmops->secure;
+ if (vmops->secure) {
+ WFD_MSG_ERR("OPENING SECURE SESSION\n");
+ flags |= VCD_CP_SESSION;
+ }
if (vcd_get_ion_status()) {
client_ctx->user_ion_client = vcd_get_ion_client();
if (!client_ctx->user_ion_client) {
@@ -294,9 +300,10 @@
}
rc = vcd_open(venc_p.device_handle, false, venc_cb,
- inst);
+ inst, flags);
if (rc) {
WFD_MSG_ERR("vcd_open failed, rc = %d\n", rc);
+ rc = -ENODEV;
goto no_free_client;
}
wait_for_completion(&client_ctx->event);
@@ -1684,6 +1691,7 @@
struct vcd_property_enc_recon_buffer *ctrl = NULL;
unsigned long phy_addr;
int i = 0;
+ int flags = 0;
u32 len;
control.width = inst->width;
control.height = inst->height;
@@ -1696,6 +1704,8 @@
WFD_MSG_ERR("Failed to get recon buf size\n");
goto err;
}
+ flags = ION_HEAP(ION_CP_MM_HEAP_ID);
+ flags |= inst->secure ? ION_SECURE : ION_HEAP(ION_IOMMU_HEAP_ID);
if (vcd_get_ion_status()) {
for (i = 0; i < 4; ++i) {
@@ -1706,8 +1716,7 @@
ctrl->user_virtual_addr = (void *)i;
client_ctx->recon_buffer_ion_handle[i]
= ion_alloc(client_ctx->user_ion_client,
- control.size, SZ_8K, ION_HEAP(ION_IOMMU_HEAP_ID) |
- ION_HEAP(ION_CP_MM_HEAP_ID));
+ control.size, SZ_8K, flags);
ctrl->kernel_virtual_addr = ion_map_kernel(
client_ctx->user_ion_client,
diff --git a/drivers/media/video/msm/wfd/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index 69e7521..cafc9d5 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -44,6 +44,7 @@
struct venc_msg_ops {
void *cookie;
void *cbdata;
+ int secure;
void (*op_buffer_done)(void *cookie, u32 status,
struct vb2_buffer *buf);
void (*ip_buffer_done)(void *cookie, u32 status,
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 2c2c551..fb586be 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -152,7 +152,7 @@
int rc;
alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
- alloc_regions |= secure ? 0 :
+ alloc_regions |= secure ? ION_SECURE :
ION_HEAP(ION_IOMMU_HEAP_ID);
handle = ion_alloc(client,
mregion->size, SZ_4K, alloc_regions);
@@ -1279,6 +1279,7 @@
enc_mops.op_buffer_done = venc_op_buffer_done;
enc_mops.ip_buffer_done = venc_ip_buffer_done;
enc_mops.cbdata = filp;
+ enc_mops.secure = wfd_dev->secure_device;
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, OPEN,
(void *)&enc_mops);
if (rc || !enc_mops.cookie) {
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index b4161dd..a8ccebf 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -60,7 +60,7 @@
#define DDL_ENC_MIN_DPB_BUFFERS 2
#define DDL_ENC_MAX_DPB_BUFFERS 4
-#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE (DDL_KILO_BYTE(8))
+#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE (DDL_KILO_BYTE(4))
#define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
#define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
#define DDL_FW_H264ENC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(20))
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 61deb8d..9b6d4b4 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -2034,29 +2034,38 @@
return true;
}
-struct video_client_ctx *vid_dec_open_client(void)
+int vid_dec_open_client(struct video_client_ctx **vid_clnt_ctx, int flags)
{
+ int rc = 0;
s32 client_index;
- struct video_client_ctx *client_ctx;
- u32 vcd_status = VCD_ERR_FAIL;
+ struct video_client_ctx *client_ctx = NULL;
u8 client_count;
+ if (!vid_clnt_ctx) {
+ ERR("Invalid input\n");
+ return -EINVAL;
+ }
+ *vid_clnt_ctx = NULL;
client_count = vcd_get_num_of_clients();
if (client_count == VIDC_MAX_NUM_CLIENTS) {
ERR("ERROR : vid_dec_open() max number of clients"
"limit reached\n");
+ rc = -ENOMEM;
goto client_failure;
}
DBG(" Virtual Address of ioremap is %p\n", vid_dec_device_p->virt_base);
if (!vid_dec_device_p->num_clients) {
- if (!vidc_load_firmware())
+ if (!vidc_load_firmware()) {
+ rc = -ENOMEM;
goto client_failure;
+ }
}
client_index = vid_dec_get_empty_client_index();
- if (client_index < 0) {
- ERR("%s() : No free clients client_index < 0\n", __func__);
+ if (client_index == -1) {
+ ERR("%s() : No free clients client_index == -1\n", __func__);
+ rc = -ENOMEM;
goto client_failure;
}
client_ctx = &vid_dec_device_p->vdec_clients[client_index];
@@ -2074,72 +2083,82 @@
client_ctx->user_ion_client = vcd_get_ion_client();
if (!client_ctx->user_ion_client) {
ERR("vcd_open ion client get failed");
+ rc = -ENOMEM;
goto client_failure;
}
}
- vcd_status = vcd_open(vid_dec_device_p->device_handle, true,
- vid_dec_vcd_cb, client_ctx);
- if (!vcd_status) {
+ rc = vcd_open(vid_dec_device_p->device_handle, true,
+ vid_dec_vcd_cb, client_ctx, flags);
+ if (!rc) {
wait_for_completion(&client_ctx->event);
if (client_ctx->event_status) {
ERR("callback for vcd_open returned error: %u",
client_ctx->event_status);
+ rc = -ENODEV;
goto client_failure;
}
} else {
- ERR("vcd_open returned error: %u", vcd_status);
+ ERR("vcd_open returned error: %u", rc);
goto client_failure;
}
client_ctx->seq_header_set = false;
- return client_ctx;
+ *vid_clnt_ctx = client_ctx;
client_failure:
- return NULL;
+ return rc;
}
static int vid_dec_open_secure(struct inode *inode, struct file *file)
{
+ int rc = 0;
+ struct video_client_ctx *client_ctx;
mutex_lock(&vid_dec_device_p->lock);
- if (res_trk_check_for_sec_session() || vcd_get_num_of_clients()) {
- ERR("Secure session present return failure\n");
- mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
- }
res_trk_secure_set();
- file->private_data = vid_dec_open_client();
- if (!file->private_data) {
+ rc = vid_dec_open_client(&client_ctx, VCD_CP_SESSION);
+ if (rc)
+ goto error;
+ if (!client_ctx) {
+ rc = -ENOMEM;
goto error;
}
+ file->private_data = client_ctx;
if (res_trk_open_secure_session()) {
ERR("Secure session operation failure\n");
+ rc = -EACCES;
goto error;
}
mutex_unlock(&vid_dec_device_p->lock);
return 0;
-
error:
res_trk_secure_unset();
mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
-
+ return rc;
}
static int vid_dec_open(struct inode *inode, struct file *file)
{
+ int rc = 0;
+ struct video_client_ctx *client_ctx;
INFO("msm_vidc_dec: Inside %s()", __func__);
mutex_lock(&vid_dec_device_p->lock);
if (res_trk_check_for_sec_session()) {
ERR("Secure session present return failure\n");
mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
+ return -EACCES;
}
- file->private_data = vid_dec_open_client();
- if (!file->private_data) {
+ rc = vid_dec_open_client(&client_ctx, 0);
+ if (rc) {
mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
+ return rc;
}
+ if (!client_ctx) {
+ mutex_unlock(&vid_dec_device_p->lock);
+ return -ENOMEM;
+ }
+
+ file->private_data = client_ctx;
mutex_unlock(&vid_dec_device_p->lock);
- return 0;
+ return rc;
}
static int vid_dec_release_secure(struct inode *inode, struct file *file)
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 93b1848..d93d07e 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -521,7 +521,7 @@
{
s32 client_index;
struct video_client_ctx *client_ctx;
- u32 vcd_status = VCD_ERR_FAIL;
+ int rc = 0;
u8 client_count = 0;
INFO("\n msm_vidc_enc: Inside %s()", __func__);
@@ -530,10 +530,9 @@
stop_cmd = 0;
client_count = vcd_get_num_of_clients();
- if (client_count == VIDC_MAX_NUM_CLIENTS ||
- res_trk_check_for_sec_session()) {
+ if (client_count == VIDC_MAX_NUM_CLIENTS) {
ERR("ERROR : vid_enc_open() max number of clients"
- "limit reached or secure session is open\n");
+ "limit reached\n");
mutex_unlock(&vid_enc_device_p->lock);
return -ENODEV;
}
@@ -568,11 +567,11 @@
return -EFAULT;
}
}
- vcd_status = vcd_open(vid_enc_device_p->device_handle, false,
- vid_enc_vcd_cb, client_ctx);
+ rc = vcd_open(vid_enc_device_p->device_handle, false,
+ vid_enc_vcd_cb, client_ctx, 0);
client_ctx->stop_msg = 0;
- if (!vcd_status) {
+ if (!rc) {
wait_for_completion(&client_ctx->event);
if (client_ctx->event_status) {
ERR("callback for vcd_open returned error: %u",
@@ -581,13 +580,13 @@
return -EFAULT;
}
} else {
- ERR("vcd_open returned error: %u", vcd_status);
+ ERR("vcd_open returned error: %u", rc);
mutex_unlock(&vid_enc_device_p->lock);
- return -EFAULT;
+ return rc;
}
file->private_data = client_ctx;
mutex_unlock(&vid_enc_device_p->lock);
- return 0;
+ return rc;
}
static int vid_enc_release(struct inode *inode, struct file *file)
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index e0ef3af..401aa43 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -74,24 +74,103 @@
}
EXPORT_SYMBOL(vcd_term);
+struct client_security_info {
+ int secure_enc;
+ int secure_dec;
+ int non_secure_enc;
+ int non_secure_dec;
+};
+
+static int vcd_get_clients_security_info(struct client_security_info *sec_info)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_clnt_ctxt *cctxt;
+ int count = 0;
+ if (!sec_info) {
+ VCD_MSG_ERROR("Invalid argument\n");
+ return -EINVAL;
+ }
+ memset(sec_info, 0 , sizeof(*sec_info));
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+ cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+ while (cctxt) {
+ if (cctxt->secure && cctxt->decoding)
+ sec_info->secure_dec++;
+ else if (cctxt->secure && !cctxt->decoding)
+ sec_info->secure_enc++;
+ else if (!cctxt->secure && cctxt->decoding)
+ sec_info->non_secure_dec++;
+ else
+ sec_info->non_secure_enc++;
+ count++;
+ cctxt = cctxt->next;
+ }
+ mutex_unlock(&drv_ctxt->dev_mutex);
+ return count;
+}
+
+static int is_session_invalid(u32 decoding, u32 flags)
+{
+ int is_secure;
+ struct client_security_info sec_info;
+ int client_count = 0;
+ int secure_session_running = 0;
+ is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
+ client_count = vcd_get_clients_security_info(&sec_info);
+ secure_session_running = (sec_info.secure_enc > 0) ||
+ (sec_info.secure_dec > 0);
+ if (!decoding && is_secure) {
+ if ((sec_info.secure_dec > 1) ||
+ (sec_info.secure_enc)
+ ) {
+ VCD_MSG_HIGH("SE-SE: FAILURE\n");
+ VCD_MSG_HIGH("S-S-SE: FAILURE\n");
+ return -EACCES;
+ }
+ } else if (!decoding && !is_secure) {
+ if (secure_session_running) {
+ VCD_MSG_HIGH("SD-NSE: FAILURE\n");
+ VCD_MSG_HIGH("SE-NSE: FAILURE\n");
+ return -EACCES;
+ }
+ } else if (decoding && is_secure) {
+ if (client_count > 0) {
+ VCD_MSG_HIGH("S/NS-SD: FAILURE\n");
+ if (sec_info.secure_enc > 0 ||
+ sec_info.non_secure_enc > 0) {
+ return -EAGAIN;
+ }
+ return -EACCES;
+ }
+ } else {
+ if (sec_info.secure_dec > 0) {
+ VCD_MSG_HIGH("SD-NSD: FAILURE\n");
+ return -EACCES;
+ }
+ }
+ return 0;
+}
+
u32 vcd_open(s32 driver_handle, u32 decoding,
void (*callback) (u32 event, u32 status, void *info, size_t sz,
void *handle, void *const client_data),
- void *client_data)
+ void *client_data, int flags)
{
- u32 rc = VCD_S_SUCCESS;
+ u32 rc = 0;
struct vcd_drv_ctxt *drv_ctxt;
-
+ struct vcd_clnt_ctxt *cctxt;
+ int is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
VCD_MSG_MED("vcd_open:");
if (!callback) {
VCD_MSG_ERROR("Bad parameters");
-
- return VCD_ERR_ILLEGAL_PARM;
+ return -EINVAL;
}
- if (res_trk_check_for_sec_session() && vcd_get_num_of_clients()) {
- VCD_MSG_ERROR("Secure session in progress");
- return VCD_ERR_BAD_STATE;
+ rc = is_session_invalid(decoding, flags);
+ if (rc) {
+ VCD_MSG_ERROR("Secure session in progress");
+ return rc;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
@@ -100,17 +179,19 @@
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
open(drv_ctxt, driver_handle, decoding, callback,
client_data);
+ if (rc)
+ rc = -ENODEV;
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
-
- rc = VCD_ERR_BAD_STATE;
+ rc = -EPERM;
}
-
+ if (!rc) {
+ cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+ cctxt->secure = is_secure;
+ }
mutex_unlock(&drv_ctxt->dev_mutex);
-
return rc;
-
}
EXPORT_SYMBOL(vcd_open);
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index b8438e1..e33c8cd 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -210,6 +210,7 @@
struct vcd_clnt_ctxt *next;
u32 meta_mode;
int perf_set_by_client;
+ int secure;
};
#define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 20d3ef9..32a1759 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -116,11 +116,14 @@
void (*timer_stop) (void *timer_handle);
};
+/*Flags passed to vcd_open*/
+#define VCD_CP_SESSION 0x00000001
+
u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle);
u32 vcd_term(s32 driver_handle);
u32 vcd_open(s32 driver_handle, u32 decoding,
void (*callback) (u32 event, u32 status, void *info, size_t sz,
- void *handle, void *const client_data), void *client_data);
+ void *handle, void *const client_data), void *client_data, int flags);
u32 vcd_close(void *handle);
u32 vcd_encode_start(void *handle);
u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame);