Skip to content

Commit

Permalink
msm: camera: Optimize memory allocation for small buffers
Browse files Browse the repository at this point in the history
Try to use an on-stack buffer for memory allocations that are small
enough to not warrant a dynamic allocation, and eliminate dynamic memory
allocation entirely in msm_camera_cci_i2c_read_seq. This improves
performance by skipping latency-prone dynamic memory allocation when it
isn't needed.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
  • Loading branch information
kerneltoast committed Aug 21, 2019
1 parent 64bc351 commit 9b963ad
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 38 deletions.
38 changes: 25 additions & 13 deletions drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
Expand Up @@ -1450,6 +1450,8 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg)
{
int rc = 0, i;
uint32_t cfg_data_onstack[SZ_4K / sizeof(uint32_t)];
struct msm_vfe_reg_cfg_cmd cfg_cmd_onstack[20];
struct msm_vfe_cfg_cmd2 *proc_cmd = arg;
struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd;
uint32_t *cfg_data = NULL;
Expand All @@ -1459,12 +1461,16 @@ int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg)
return -EINVAL;
}

reg_cfg_cmd = kzalloc(sizeof(struct msm_vfe_reg_cfg_cmd)*
proc_cmd->num_cfg, GFP_KERNEL);
if (!reg_cfg_cmd) {
pr_err("%s: reg_cfg alloc failed\n", __func__);
rc = -ENOMEM;
goto reg_cfg_failed;
if (proc_cmd->num_cfg <= ARRAY_SIZE(cfg_cmd_onstack)) {
reg_cfg_cmd = cfg_cmd_onstack;
} else {
reg_cfg_cmd = kmalloc(sizeof(struct msm_vfe_reg_cfg_cmd)*
proc_cmd->num_cfg, GFP_KERNEL);
if (!reg_cfg_cmd) {
pr_err("%s: reg_cfg alloc failed\n", __func__);
rc = -ENOMEM;
goto reg_cfg_failed;
}
}

if (copy_from_user(reg_cfg_cmd,
Expand All @@ -1475,11 +1481,15 @@ int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg)
}

if (proc_cmd->cmd_len > 0) {
cfg_data = kzalloc(proc_cmd->cmd_len, GFP_KERNEL);
if (!cfg_data) {
pr_err("%s: cfg_data alloc failed\n", __func__);
rc = -ENOMEM;
goto cfg_data_failed;
if (proc_cmd->cmd_len <= sizeof(cfg_data_onstack)) {
cfg_data = cfg_data_onstack;
} else {
cfg_data = kmalloc(proc_cmd->cmd_len, GFP_KERNEL);
if (!cfg_data) {
pr_err("%s: cfg_data alloc failed\n", __func__);
rc = -ENOMEM;
goto cfg_data_failed;
}
}

if (copy_from_user(cfg_data,
Expand All @@ -1501,9 +1511,11 @@ int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg)
}

copy_cmd_failed:
kfree(cfg_data);
if (cfg_data != cfg_data_onstack)
kfree(cfg_data);
cfg_data_failed:
kfree(reg_cfg_cmd);
if (reg_cfg_cmd != cfg_cmd_onstack)
kfree(reg_cfg_cmd);
reg_cfg_failed:
return rc;
}
Expand Down
47 changes: 22 additions & 25 deletions drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
Expand Up @@ -61,8 +61,6 @@ int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
uint32_t addr, uint8_t *data, uint32_t num_byte)
{
int32_t rc = -EFAULT;
unsigned char *buf = NULL;
int i;
struct msm_camera_cci_ctrl cci_ctrl;

if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
Expand All @@ -77,16 +75,11 @@ int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
return rc;
}

buf = kzalloc(num_byte, GFP_KERNEL);
if (!buf) {
pr_err("%s:%d no memory\n", __func__, __LINE__);
return -ENOMEM;
}
cci_ctrl.cmd = MSM_CCI_I2C_READ;
cci_ctrl.cci_info = client->cci_client;
cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr;
cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = client->addr_type;
cci_ctrl.cfg.cci_i2c_read_cfg.data = buf;
cci_ctrl.cfg.cci_i2c_read_cfg.data = data;
cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = num_byte;
cci_ctrl.status = -EFAULT;
rc = v4l2_subdev_call(client->cci_client->cci_subdev,
Expand All @@ -95,12 +88,6 @@ int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
rc = cci_ctrl.status;

S_I2C_DBG("%s addr = 0x%x", __func__, addr);
for (i = 0; i < num_byte; i++) {
data[i] = buf[i];
S_I2C_DBG("Byte %d: 0x%x\n", i, buf[i]);
S_I2C_DBG("Data: 0x%x\n", data[i]);
}
kfree(buf);
return rc;
}

Expand Down Expand Up @@ -146,6 +133,8 @@ int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
uint32_t i = 0;
struct msm_camera_cci_ctrl cci_ctrl;
struct msm_camera_i2c_reg_array *reg_conf_tbl = NULL;
struct msm_camera_i2c_reg_array reg_tbl_onstack[
SZ_4K / sizeof(struct msm_camera_i2c_reg_array)];

if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
Expand All @@ -161,17 +150,25 @@ int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
S_I2C_DBG("%s reg addr = 0x%x num bytes: %d\n",
__func__, addr, num_byte);

reg_conf_tbl = kzalloc(num_byte *
(sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);
if (!reg_conf_tbl) {
pr_err("%s:%d no memory\n", __func__, __LINE__);
return -ENOMEM;
if (num_byte <= ARRAY_SIZE(reg_tbl_onstack)) {
reg_conf_tbl = reg_tbl_onstack;
} else {
reg_conf_tbl = kmalloc(num_byte *
(sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);
if (!reg_conf_tbl) {
pr_err("%s:%d no memory\n", __func__, __LINE__);
return -ENOMEM;
}
}

reg_conf_tbl[0].reg_addr = addr;
for (i = 0; i < num_byte; i++) {
reg_conf_tbl[i].reg_data = data[i];
reg_conf_tbl[i].delay = 0;
reg_conf_tbl[0] = (typeof(*reg_conf_tbl)){
.reg_addr = addr,
.reg_data = data[0]
};
for (i = 1; i < num_byte; i++) {
reg_conf_tbl[i] = (typeof(*reg_conf_tbl)){
.reg_data = data[i]
};
}
cci_ctrl.cmd = MSM_CCI_I2C_WRITE_SEQ;
cci_ctrl.cci_info = client->cci_client;
Expand All @@ -184,8 +181,8 @@ int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
CDBG("%s line %d rc = %d\n", __func__, __LINE__, rc);
rc = cci_ctrl.status;
kfree(reg_conf_tbl);
reg_conf_tbl = NULL;
if (reg_conf_tbl != reg_tbl_onstack)
kfree(reg_conf_tbl);
return rc;
}

Expand Down

0 comments on commit 9b963ad

Please sign in to comment.