Merge "msm: camera: reqmgr: reader writer locks to avoid memory faults"

This commit is contained in:
Linux Build Service Account 2022-03-07 05:17:17 -08:00 • committed by Gerrit - the friendly Code Review server
commit 975d708f86
15 changed files with 132 additions and 10 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -60,8 +60,10 @@ static long cam_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd,
switch (cmd) { switch (cmd) {
case VIDIOC_CAM_CONTROL: case VIDIOC_CAM_CONTROL:
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK);
rc = cam_node_handle_ioctl(node, rc = cam_node_handle_ioctl(node,
(struct cam_control *) arg); (struct cam_control *) arg);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
break; break;
default: default:
CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd, CAM_ERR(CAM_CORE, "Invalid command %d for %s", cmd,

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -50,8 +50,11 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd,
{ {
struct cam_fd_dev *fd_dev = &g_fd_dev; struct cam_fd_dev *fd_dev = &g_fd_dev;
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK);
if (!fd_dev->probe_done) { if (!fd_dev->probe_done) {
CAM_ERR(CAM_FD, "FD Dev not initialized, fd_dev=%pK", fd_dev); CAM_ERR(CAM_FD, "FD Dev not initialized, fd_dev=%pK", fd_dev);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
return -ENODEV; return -ENODEV;
} }
@ -60,6 +63,8 @@ static int cam_fd_dev_open(struct v4l2_subdev *sd,
CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt); CAM_DBG(CAM_FD, "FD Subdev open count %d", fd_dev->open_cnt);
mutex_unlock(&fd_dev->lock); mutex_unlock(&fd_dev->lock);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
return 0; return 0;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 2021The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -82,6 +82,8 @@ static int cam_icp_subdev_open(struct v4l2_subdev *sd,
struct cam_node *node = v4l2_get_subdevdata(sd); struct cam_node *node = v4l2_get_subdevdata(sd);
int rc = 0; int rc = 0;
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK);
mutex_lock(&g_icp_dev.icp_lock); mutex_lock(&g_icp_dev.icp_lock);
if (g_icp_dev.open_cnt >= 1) { if (g_icp_dev.open_cnt >= 1) {
CAM_ERR(CAM_ICP, "ICP subdev is already opened"); CAM_ERR(CAM_ICP, "ICP subdev is already opened");
@ -104,6 +106,7 @@ static int cam_icp_subdev_open(struct v4l2_subdev *sd,
g_icp_dev.open_cnt++; g_icp_dev.open_cnt++;
end: end:
mutex_unlock(&g_icp_dev.icp_lock); mutex_unlock(&g_icp_dev.icp_lock);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
return rc; return rc;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -58,10 +58,14 @@ static const struct of_device_id cam_isp_dt_match[] = {
static int cam_isp_subdev_open(struct v4l2_subdev *sd, static int cam_isp_subdev_open(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh) struct v4l2_subdev_fh *fh)
{ {
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK);
mutex_lock(&g_isp_dev.isp_mutex); mutex_lock(&g_isp_dev.isp_mutex);
g_isp_dev.open_cnt++; g_isp_dev.open_cnt++;
mutex_unlock(&g_isp_dev.isp_mutex); mutex_unlock(&g_isp_dev.isp_mutex);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
return 0; return 0;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -57,11 +57,14 @@ static const struct of_device_id cam_jpeg_dt_match[] = {
static int cam_jpeg_subdev_open(struct v4l2_subdev *sd, static int cam_jpeg_subdev_open(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh) struct v4l2_subdev_fh *fh)
{ {
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK);
mutex_lock(&g_jpeg_dev.jpeg_mutex); mutex_lock(&g_jpeg_dev.jpeg_mutex);
g_jpeg_dev.open_cnt++; g_jpeg_dev.open_cnt++;
mutex_unlock(&g_jpeg_dev.jpeg_mutex); mutex_unlock(&g_jpeg_dev.jpeg_mutex);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
return 0; return 0;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -65,9 +65,12 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd,
{ {
struct cam_lrme_dev *lrme_dev = g_lrme_dev; struct cam_lrme_dev *lrme_dev = g_lrme_dev;
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_LOCK);
if (!lrme_dev) { if (!lrme_dev) {
CAM_ERR(CAM_LRME, CAM_ERR(CAM_LRME,
"LRME Dev not initialized, dev=%pK", lrme_dev); "LRME Dev not initialized, dev=%pK", lrme_dev);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
return -ENODEV; return -ENODEV;
} }
@ -75,6 +78,8 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd,
lrme_dev->open_cnt++; lrme_dev->open_cnt++;
mutex_unlock(&lrme_dev->lock); mutex_unlock(&lrme_dev->lock);
cam_req_mgr_rwsem_read_op(CAM_SUBDEV_UNLOCK);
return 0; return 0;
} }

View file

@ -11,6 +11,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <media/v4l2-fh.h> #include <media/v4l2-fh.h>
@ -33,6 +34,8 @@
static struct cam_req_mgr_device g_dev; static struct cam_req_mgr_device g_dev;
struct kmem_cache *g_cam_req_mgr_timer_cachep; struct kmem_cache *g_cam_req_mgr_timer_cachep;
DECLARE_RWSEM(rwsem_lock);
static int cam_media_device_setup(struct device *dev) static int cam_media_device_setup(struct device *dev)
{ {
int rc; int rc;
@ -98,10 +101,28 @@ static void cam_v4l2_device_cleanup(void)
g_dev.v4l2_dev = NULL; g_dev.v4l2_dev = NULL;
} }
void cam_req_mgr_rwsem_read_op(enum cam_subdev_rwsem lock)
{
if (lock == CAM_SUBDEV_LOCK)
down_read(&rwsem_lock);
else if (lock == CAM_SUBDEV_UNLOCK)
up_read(&rwsem_lock);
}
static void cam_req_mgr_rwsem_write_op(enum cam_subdev_rwsem lock)
{
if (lock == CAM_SUBDEV_LOCK)
down_write(&rwsem_lock);
else if (lock == CAM_SUBDEV_UNLOCK)
up_write(&rwsem_lock);
}
static int cam_req_mgr_open(struct file *filep) static int cam_req_mgr_open(struct file *filep)
{ {
int rc; int rc;
cam_req_mgr_rwsem_write_op(CAM_SUBDEV_LOCK);
mutex_lock(&g_dev.cam_lock); mutex_lock(&g_dev.cam_lock);
if (g_dev.open_cnt >= 1) { if (g_dev.open_cnt >= 1) {
rc = -EALREADY; rc = -EALREADY;
@ -127,12 +148,14 @@ static int cam_req_mgr_open(struct file *filep)
} }
mutex_unlock(&g_dev.cam_lock); mutex_unlock(&g_dev.cam_lock);
cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK);
return rc; return rc;
mem_mgr_init_fail: mem_mgr_init_fail:
v4l2_fh_release(filep); v4l2_fh_release(filep);
end: end:
mutex_unlock(&g_dev.cam_lock); mutex_unlock(&g_dev.cam_lock);
cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK);
return rc; return rc;
} }
@ -158,10 +181,13 @@ static int cam_req_mgr_close(struct file *filep)
struct v4l2_fh *vfh = filep->private_data; struct v4l2_fh *vfh = filep->private_data;
struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
cam_req_mgr_rwsem_write_op(CAM_SUBDEV_LOCK);
mutex_lock(&g_dev.cam_lock); mutex_lock(&g_dev.cam_lock);
if (g_dev.open_cnt <= 0) { if (g_dev.open_cnt <= 0) {
mutex_unlock(&g_dev.cam_lock); mutex_unlock(&g_dev.cam_lock);
cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK);
return -EINVAL; return -EINVAL;
} }
@ -188,6 +214,8 @@ static int cam_req_mgr_close(struct file *filep)
cam_mem_mgr_deinit(); cam_mem_mgr_deinit();
mutex_unlock(&g_dev.cam_lock); mutex_unlock(&g_dev.cam_lock);
cam_req_mgr_rwsem_write_op(CAM_SUBDEV_UNLOCK);
return 0; return 0;
} }
@ -586,6 +614,18 @@ void cam_register_subdev_fops(struct v4l2_file_operations *fops)
} }
EXPORT_SYMBOL(cam_register_subdev_fops); EXPORT_SYMBOL(cam_register_subdev_fops);
bool cam_req_mgr_is_open(void)
{
bool crm_status;
mutex_lock(&g_dev.cam_lock);
crm_status = g_dev.open_cnt ? true : false;
mutex_unlock(&g_dev.cam_lock);
return crm_status;
}
EXPORT_SYMBOL(cam_req_mgr_is_open);
int cam_register_subdev(struct cam_subdev *csd) int cam_register_subdev(struct cam_subdev *csd)
{ {
struct v4l2_subdev *sd; struct v4l2_subdev *sd;

View file

@ -21,6 +21,7 @@
#include <media/cam_req_mgr.h> #include <media/cam_req_mgr.h>
#include "cam_req_mgr_util.h" #include "cam_req_mgr_util.h"
#include "cam_debug_util.h" #include "cam_debug_util.h"
#include "cam_subdev.h"
static struct cam_req_mgr_util_hdl_tbl *hdl_tbl; static struct cam_req_mgr_util_hdl_tbl *hdl_tbl;
static DEFINE_SPINLOCK(hdl_tbl_lock); static DEFINE_SPINLOCK(hdl_tbl_lock);
@ -166,6 +167,14 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
int idx; int idx;
int rand = 0; int rand = 0;
int32_t handle; int32_t handle;
bool crm_active;
crm_active = cam_req_mgr_is_open();
if (!crm_active) {
CAM_ERR(CAM_ICP, "CRM is not ACTIVE");
spin_unlock_bh(&hdl_tbl_lock);
return -EINVAL;
}
spin_lock_bh(&hdl_tbl_lock); spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) { if (!hdl_tbl) {

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -23,6 +23,11 @@
#define CAM_SUBDEVICE_EVENT_MAX 30 #define CAM_SUBDEVICE_EVENT_MAX 30
enum cam_subdev_rwsem {
CAM_SUBDEV_LOCK = 1,
CAM_SUBDEV_UNLOCK,
};
/** /**
* struct cam_subdev - describes a camera sub-device * struct cam_subdev - describes a camera sub-device
* *
@ -112,4 +117,21 @@ int cam_register_subdev(struct cam_subdev *sd);
*/ */
int cam_unregister_subdev(struct cam_subdev *sd); int cam_unregister_subdev(struct cam_subdev *sd);
/**
* cam_req_mgr_rwsem_read_op()
*
* @brief : API to acquire read semaphore lock to platform framework.
*
* @lock : value indicates to lock or unlock the read lock
*/
void cam_req_mgr_rwsem_read_op(enum cam_subdev_rwsem lock);
/**
* cam_req_mgr_is_open()
*
* @brief: This common utility function returns the crm active status
*
*/
bool cam_req_mgr_is_open(void);
#endif /* _CAM_SUBDEV_H_ */ #endif /* _CAM_SUBDEV_H_ */

View file

@ -790,6 +790,11 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl,
bridge_params.dev_id = CAM_ACTUATOR; bridge_params.dev_id = CAM_ACTUATOR;
actuator_acq_dev.device_handle = actuator_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params); cam_create_device_hdl(&bridge_params);
if (actuator_acq_dev.device_handle <= 0) {
rc = -EFAULT;
CAM_ERR(CAM_ACTUATOR, "Can not create device handle");
goto release_mutex;
}
a_ctrl->bridge_intf.device_hdl = actuator_acq_dev.device_handle; a_ctrl->bridge_intf.device_hdl = actuator_acq_dev.device_handle;
a_ctrl->bridge_intf.session_hdl = a_ctrl->bridge_intf.session_hdl =
actuator_acq_dev.session_handle; actuator_acq_dev.session_handle;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2020, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -738,6 +738,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
csiphy_acq_dev.device_handle = csiphy_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params); cam_create_device_hdl(&bridge_params);
if (csiphy_acq_dev.device_handle <= 0) {
rc = -EFAULT;
CAM_ERR(CAM_CSIPHY, "Can not create device handle");
goto release_mutex;
}
bridge_intf = &csiphy_dev->bridge_intf; bridge_intf = &csiphy_dev->bridge_intf;
bridge_intf->device_hdl[csiphy_acq_params.combo_mode] bridge_intf->device_hdl[csiphy_acq_params.combo_mode]
= csiphy_acq_dev.device_handle; = csiphy_acq_dev.device_handle;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2020, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -360,6 +360,10 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl,
bridge_params.dev_id = CAM_EEPROM; bridge_params.dev_id = CAM_EEPROM;
eeprom_acq_dev.device_handle = eeprom_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params); cam_create_device_hdl(&bridge_params);
if (eeprom_acq_dev.device_handle <= 0) {
CAM_ERR(CAM_EEPROM, "Can not create device handle");
return -EFAULT;
}
e_ctrl->bridge_intf.device_hdl = eeprom_acq_dev.device_handle; e_ctrl->bridge_intf.device_hdl = eeprom_acq_dev.device_handle;
e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle; e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -74,6 +74,11 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
bridge_params.dev_id = CAM_FLASH; bridge_params.dev_id = CAM_FLASH;
flash_acq_dev.device_handle = flash_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params); cam_create_device_hdl(&bridge_params);
if (flash_acq_dev.device_handle <= 0) {
rc = -EFAULT;
CAM_ERR(CAM_FLASH, "Can not create device handle");
goto release_mutex;
}
fctrl->bridge_intf.device_hdl = fctrl->bridge_intf.device_hdl =
flash_acq_dev.device_handle; flash_acq_dev.device_handle;
fctrl->bridge_intf.session_hdl = fctrl->bridge_intf.session_hdl =

View file

@ -94,6 +94,10 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl,
bridge_params.dev_id = CAM_OIS; bridge_params.dev_id = CAM_OIS;
ois_acq_dev.device_handle = ois_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params); cam_create_device_hdl(&bridge_params);
if (ois_acq_dev.device_handle <= 0) {
CAM_ERR(CAM_OIS, "Can not create device handle");
return -EFAULT;
}
o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle; o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle;
o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle; o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle;

View file

@ -800,6 +800,11 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
bridge_params.dev_id = CAM_SENSOR; bridge_params.dev_id = CAM_SENSOR;
sensor_acq_dev.device_handle = sensor_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params); cam_create_device_hdl(&bridge_params);
if (sensor_acq_dev.device_handle <= 0) {
rc = -EFAULT;
CAM_ERR(CAM_SENSOR, "Can not create device handle");
goto release_mutex;
}
s_ctrl->bridge_intf.device_hdl = sensor_acq_dev.device_handle; s_ctrl->bridge_intf.device_hdl = sensor_acq_dev.device_handle;
s_ctrl->bridge_intf.session_hdl = sensor_acq_dev.session_handle; s_ctrl->bridge_intf.session_hdl = sensor_acq_dev.session_handle;