|
@@ -2438,7 +2438,7 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
|
|
|
*
|
|
|
*/
|
|
|
static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
- struct cam_req_mgr_link_info *link_info)
|
|
|
+ struct cam_req_mgr_ver_info *link_info)
|
|
|
{
|
|
|
int rc = 0, i = 0;
|
|
|
struct cam_req_mgr_core_dev_link_setup link_data;
|
|
@@ -2446,10 +2446,16 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
struct cam_req_mgr_req_tbl *pd_tbl;
|
|
|
enum cam_pipeline_delay max_delay;
|
|
|
uint32_t subscribe_event = 0;
|
|
|
-
|
|
|
- if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES)
|
|
|
- return -EPERM;
|
|
|
-
|
|
|
+ if (link_info->version == VERSION_1) {
|
|
|
+ if (link_info->u.link_info_v1.num_devices >
|
|
|
+ CAM_REQ_MGR_MAX_HANDLES)
|
|
|
+ return -EPERM;
|
|
|
+ }
|
|
|
+ else if (link_info->version == VERSION_2) {
|
|
|
+ if (link_info->u.link_info_v2.num_devices >
|
|
|
+ CAM_REQ_MGR_MAX_HANDLES_V2)
|
|
|
+ return -EPERM;
|
|
|
+ }
|
|
|
mutex_init(&link->req.lock);
|
|
|
CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
|
|
|
link->req.num_tbl = 0;
|
|
@@ -2459,11 +2465,12 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
return rc;
|
|
|
|
|
|
max_delay = CAM_PIPELINE_DELAY_0;
|
|
|
- for (i = 0; i < link_info->num_devices; i++) {
|
|
|
+ for (i = 0; i < link_info->u.link_info_v1.num_devices; i++) {
|
|
|
dev = &link->l_dev[i];
|
|
|
/* Using dev hdl, get ops ptr to communicate with device */
|
|
|
dev->ops = (struct cam_req_mgr_kmd_ops *)
|
|
|
- cam_get_device_ops(link_info->dev_hdls[i]);
|
|
|
+ cam_get_device_ops(
|
|
|
+ link_info->u.link_info_v1.dev_hdls[i]);
|
|
|
if (!dev->ops ||
|
|
|
!dev->ops->get_dev_info ||
|
|
|
!dev->ops->link_setup) {
|
|
@@ -2471,7 +2478,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
rc = -ENXIO;
|
|
|
goto error;
|
|
|
}
|
|
|
- dev->dev_hdl = link_info->dev_hdls[i];
|
|
|
+ dev->dev_hdl = link_info->u.link_info_v1.dev_hdls[i];
|
|
|
dev->parent = (void *)link;
|
|
|
dev->dev_info.dev_hdl = dev->dev_hdl;
|
|
|
rc = dev->ops->get_dev_info(&dev->dev_info);
|
|
@@ -2480,7 +2487,8 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
|
|
|
CAM_DBG(CAM_CRM,
|
|
|
"%x: connected: %s, id %d, delay %d, trigger %x",
|
|
|
- link_info->session_hdl, dev->dev_info.name,
|
|
|
+ link_info->u.link_info_v1.session_hdl,
|
|
|
+ dev->dev_info.name,
|
|
|
dev->dev_info.dev_id, dev->dev_info.p_delay,
|
|
|
dev->dev_info.trigger);
|
|
|
if (rc < 0 ||
|
|
@@ -2492,7 +2500,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
goto error;
|
|
|
} else {
|
|
|
CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d",
|
|
|
- link_info->session_hdl,
|
|
|
+ link_info->u.link_info_v1.session_hdl,
|
|
|
dev->dev_info.name,
|
|
|
dev->dev_info.p_delay);
|
|
|
if (dev->dev_info.p_delay > max_delay)
|
|
@@ -2509,7 +2517,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
link_data.max_delay = max_delay;
|
|
|
link_data.subscribe_event = subscribe_event;
|
|
|
|
|
|
- for (i = 0; i < link_info->num_devices; i++) {
|
|
|
+ for (i = 0; i < link_info->u.link_info_v1.num_devices; i++) {
|
|
|
dev = &link->l_dev[i];
|
|
|
|
|
|
link_data.dev_hdl = dev->dev_hdl;
|
|
@@ -2552,7 +2560,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
if (link->max_delay < dev->dev_info.p_delay)
|
|
|
link->max_delay = dev->dev_info.p_delay;
|
|
|
}
|
|
|
- link->num_devs = link_info->num_devices;
|
|
|
+ link->num_devs = link_info->u.link_info_v1.num_devices;
|
|
|
|
|
|
/* Assign id for pd tables */
|
|
|
__cam_req_mgr_tbl_set_id(link->req.l_tbl, &link->req);
|
|
@@ -2710,7 +2718,115 @@ end:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
|
|
|
+int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info)
|
|
|
+{
|
|
|
+ int rc = 0;
|
|
|
+ int wq_flag = 0;
|
|
|
+ char buf[128];
|
|
|
+ struct cam_create_dev_hdl root_dev;
|
|
|
+ struct cam_req_mgr_core_session *cam_session;
|
|
|
+ struct cam_req_mgr_core_link *link;
|
|
|
+
|
|
|
+ if (!link_info) {
|
|
|
+ CAM_DBG(CAM_CRM, "NULL pointer");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (link_info->u.link_info_v1.num_devices > CAM_REQ_MGR_MAX_HANDLES) {
|
|
|
+ CAM_ERR(CAM_CRM, "Invalid num devices %d",
|
|
|
+ link_info->u.link_info_v1.num_devices);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_lock(&g_crm_core_dev->crm_lock);
|
|
|
+
|
|
|
+ /* session hdl's priv data is cam session struct */
|
|
|
+ cam_session = (struct cam_req_mgr_core_session *)
|
|
|
+ cam_get_device_priv(link_info->u.link_info_v1.session_hdl);
|
|
|
+ if (!cam_session) {
|
|
|
+ CAM_DBG(CAM_CRM, "NULL pointer");
|
|
|
+ mutex_unlock(&g_crm_core_dev->crm_lock);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Allocate link struct and map it with session's request queue */
|
|
|
+ link = __cam_req_mgr_reserve_link(cam_session);
|
|
|
+ if (!link) {
|
|
|
+ CAM_ERR(CAM_CRM, "failed to reserve new link");
|
|
|
+ mutex_unlock(&g_crm_core_dev->crm_lock);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl);
|
|
|
+
|
|
|
+ memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl));
|
|
|
+ root_dev.session_hdl = link_info->u.link_info_v1.session_hdl;
|
|
|
+ root_dev.priv = (void *)link;
|
|
|
+
|
|
|
+ mutex_lock(&link->lock);
|
|
|
+ /* Create unique dev handle for link */
|
|
|
+ link->link_hdl = cam_create_device_hdl(&root_dev);
|
|
|
+ if (link->link_hdl < 0) {
|
|
|
+ CAM_ERR(CAM_CRM,
|
|
|
+ "Insufficient memory to create new device handle");
|
|
|
+ rc = link->link_hdl;
|
|
|
+ goto link_hdl_fail;
|
|
|
+ }
|
|
|
+ link_info->u.link_info_v1.link_hdl = link->link_hdl;
|
|
|
+ link->last_flush_id = 0;
|
|
|
+
|
|
|
+ /* Allocate memory to hold data of all linked devs */
|
|
|
+ rc = __cam_req_mgr_create_subdevs(&link->l_dev,
|
|
|
+ link_info->u.link_info_v1.num_devices);
|
|
|
+ if (rc < 0) {
|
|
|
+ CAM_ERR(CAM_CRM,
|
|
|
+ "Insufficient memory to create new crm subdevs");
|
|
|
+ goto create_subdev_failed;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Using device ops query connected devs, prepare request tables */
|
|
|
+ rc = __cam_req_mgr_setup_link_info(link, link_info);
|
|
|
+ if (rc < 0)
|
|
|
+ goto setup_failed;
|
|
|
+
|
|
|
+ spin_lock_bh(&link->link_state_spin_lock);
|
|
|
+ link->state = CAM_CRM_LINK_STATE_READY;
|
|
|
+ spin_unlock_bh(&link->link_state_spin_lock);
|
|
|
+
|
|
|
+ /* Create worker for current link */
|
|
|
+ snprintf(buf, sizeof(buf), "%x-%x",
|
|
|
+ link_info->u.link_info_v1.session_hdl, link->link_hdl);
|
|
|
+ wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL;
|
|
|
+ rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
|
|
|
+ &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag);
|
|
|
+ if (rc < 0) {
|
|
|
+ CAM_ERR(CAM_CRM, "FATAL: unable to create worker");
|
|
|
+ __cam_req_mgr_destroy_link_info(link);
|
|
|
+ goto setup_failed;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Assign payload to workqueue tasks */
|
|
|
+ rc = __cam_req_mgr_setup_payload(link->workq);
|
|
|
+ if (rc < 0) {
|
|
|
+ __cam_req_mgr_destroy_link_info(link);
|
|
|
+ cam_req_mgr_workq_destroy(&link->workq);
|
|
|
+ goto setup_failed;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_unlock(&link->lock);
|
|
|
+ mutex_unlock(&g_crm_core_dev->crm_lock);
|
|
|
+ return rc;
|
|
|
+setup_failed:
|
|
|
+ __cam_req_mgr_destroy_subdev(link->l_dev);
|
|
|
+create_subdev_failed:
|
|
|
+ cam_destroy_device_hdl(link->link_hdl);
|
|
|
+ link_info->u.link_info_v1.link_hdl = -1;
|
|
|
+link_hdl_fail:
|
|
|
+ mutex_unlock(&link->lock);
|
|
|
+ __cam_req_mgr_unreserve_link(cam_session, link);
|
|
|
+ mutex_unlock(&g_crm_core_dev->crm_lock);
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
+int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info)
|
|
|
{
|
|
|
int rc = 0;
|
|
|
int wq_flag = 0;
|
|
@@ -2723,9 +2839,10 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
|
|
|
CAM_DBG(CAM_CRM, "NULL pointer");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) {
|
|
|
+ if (link_info->u.link_info_v2.num_devices >
|
|
|
+ CAM_REQ_MGR_MAX_HANDLES_V2) {
|
|
|
CAM_ERR(CAM_CRM, "Invalid num devices %d",
|
|
|
- link_info->num_devices);
|
|
|
+ link_info->u.link_info_v2.num_devices);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
@@ -2733,7 +2850,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
|
|
|
|
|
|
/* session hdl's priv data is cam session struct */
|
|
|
cam_session = (struct cam_req_mgr_core_session *)
|
|
|
- cam_get_device_priv(link_info->session_hdl);
|
|
|
+ cam_get_device_priv(link_info->u.link_info_v2.session_hdl);
|
|
|
if (!cam_session) {
|
|
|
CAM_DBG(CAM_CRM, "NULL pointer");
|
|
|
mutex_unlock(&g_crm_core_dev->crm_lock);
|
|
@@ -2750,7 +2867,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
|
|
|
CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl);
|
|
|
|
|
|
memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl));
|
|
|
- root_dev.session_hdl = link_info->session_hdl;
|
|
|
+ root_dev.session_hdl = link_info->u.link_info_v2.session_hdl;
|
|
|
root_dev.priv = (void *)link;
|
|
|
|
|
|
mutex_lock(&link->lock);
|
|
@@ -2762,12 +2879,12 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
|
|
|
rc = link->link_hdl;
|
|
|
goto link_hdl_fail;
|
|
|
}
|
|
|
- link_info->link_hdl = link->link_hdl;
|
|
|
+ link_info->u.link_info_v2.link_hdl = link->link_hdl;
|
|
|
link->last_flush_id = 0;
|
|
|
|
|
|
/* Allocate memory to hold data of all linked devs */
|
|
|
rc = __cam_req_mgr_create_subdevs(&link->l_dev,
|
|
|
- link_info->num_devices);
|
|
|
+ link_info->u.link_info_v2.num_devices);
|
|
|
if (rc < 0) {
|
|
|
CAM_ERR(CAM_CRM,
|
|
|
"Insufficient memory to create new crm subdevs");
|
|
@@ -2785,7 +2902,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
|
|
|
|
|
|
/* Create worker for current link */
|
|
|
snprintf(buf, sizeof(buf), "%x-%x",
|
|
|
- link_info->session_hdl, link->link_hdl);
|
|
|
+ link_info->u.link_info_v2.session_hdl, link->link_hdl);
|
|
|
wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL;
|
|
|
rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
|
|
|
&link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag);
|
|
@@ -2810,7 +2927,7 @@ setup_failed:
|
|
|
__cam_req_mgr_destroy_subdev(link->l_dev);
|
|
|
create_subdev_failed:
|
|
|
cam_destroy_device_hdl(link->link_hdl);
|
|
|
- link_info->link_hdl = -1;
|
|
|
+ link_info->u.link_info_v2.link_hdl = -1;
|
|
|
link_hdl_fail:
|
|
|
mutex_unlock(&link->lock);
|
|
|
__cam_req_mgr_unreserve_link(cam_session, link);
|
|
@@ -2818,6 +2935,7 @@ link_hdl_fail:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info)
|
|
|
{
|
|
|
int rc = 0;
|