OSDN Git Service

msm: camera: Optimize memory allocation for small buffers
authorSultan Alsawaf <sultan@kerneltoast.com>
Wed, 31 Jul 2019 06:38:19 +0000 (23:38 -0700)
committer0ranko0P <ranko0p@outlook.com>
Sat, 7 Dec 2019 10:22:18 +0000 (18:22 +0800)
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>
drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c

index 54ca0dd..d62a88f 100644 (file)
@@ -1464,6 +1464,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;
@@ -1473,12 +1475,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,
@@ -1489,11 +1495,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,
@@ -1515,9 +1525,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;
 }
index fc6ceb1..f4b7c07 100644 (file)
@@ -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
@@ -78,16 +76,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,
@@ -96,12 +89,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;
 }
 
@@ -147,6 +134,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)
@@ -162,17 +151,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;
@@ -185,8 +182,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;
 }