OSDN Git Service

msm: mdss: Don't allocate memory dynamically for destination scaler
authorSultan Alsawaf <sultan@kerneltoast.com>
Wed, 31 Jul 2019 04:22:00 +0000 (21:22 -0700)
committer0ranko0P <ranko0p@outlook.com>
Sat, 7 Dec 2019 10:22:17 +0000 (18:22 +0800)
Every atomic frame commit allocates memory dynamically for the
destination scaler, when those allocations can just be stored on the
stack instead. Eliminate these dynamic memory allocations in the frame
commit path to improve performance.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
drivers/video/fbdev/msm/mdss_fb.c
drivers/video/fbdev/msm/mdss_mdp.c

index 50cc659..5f51102 100644 (file)
@@ -4857,99 +4857,66 @@ err:
 }
 
 static int __mdss_fb_copy_destscaler_data(struct fb_info *info,
-               struct mdp_layer_commit *commit)
+               struct mdp_layer_commit *commit,
+               struct mdp_destination_scaler_data *ds_data,
+               struct mdp_scale_data_v2 *scale_data)
 {
        int    i = 0;
        int    ret = 0;
-       u32    data_size;
        struct mdp_destination_scaler_data __user *ds_data_user;
-       struct mdp_destination_scaler_data *ds_data = NULL;
        void __user *scale_data_user;
-       struct mdp_scale_data_v2 *scale_data = NULL;
        struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
        struct mdss_data_type *mdata;
 
        if (!mfd || !mfd->mdp.private1) {
                pr_err("mfd is NULL or operation not permitted\n");
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        mdata = mfd_to_mdata(mfd);
        if (!mdata) {
                pr_err("mdata is NULL or not initialized\n");
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        if (commit->commit_v1.dest_scaler_cnt >
                        mdata->scaler_off->ndest_scalers) {
                pr_err("Commit destination scaler cnt larger than HW setting, commit cnt=%d\n",
                                commit->commit_v1.dest_scaler_cnt);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        ds_data_user = (struct mdp_destination_scaler_data *)
                commit->commit_v1.dest_scaler;
-       data_size = commit->commit_v1.dest_scaler_cnt *
-               sizeof(struct mdp_destination_scaler_data);
-       ds_data = kzalloc(data_size, GFP_KERNEL);
-       if (!ds_data) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       ret = copy_from_user(ds_data, ds_data_user, data_size);
+       ret = copy_from_user(ds_data, ds_data_user,
+               commit->commit_v1.dest_scaler_cnt * sizeof(*ds_data));
        if (ret) {
                pr_err("dest scaler data copy from user failed\n");
-               goto err;
+               return ret;
        }
 
        commit->commit_v1.dest_scaler = ds_data;
 
        for (i = 0; i < commit->commit_v1.dest_scaler_cnt; i++) {
-               scale_data = NULL;
-
-               if (ds_data[i].scale) {
-                       scale_data_user = to_user_ptr(ds_data[i].scale);
-                       data_size = sizeof(struct mdp_scale_data_v2);
-
-                       scale_data = kzalloc(data_size, GFP_KERNEL);
-                       if (!scale_data) {
-                               ds_data[i].scale = 0;
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-
-                       ds_data[i].scale = to_user_u64(scale_data);
-               }
+               if (!ds_data[i].scale)
+                       continue;
 
-               if (scale_data && (ds_data[i].flags &
-                                       (MDP_DESTSCALER_SCALE_UPDATE |
-                                       MDP_DESTSCALER_ENHANCER_UPDATE))) {
-                       ret = copy_from_user(scale_data, scale_data_user,
-                                       data_size);
+               scale_data_user = to_user_ptr(ds_data[i].scale);
+               ds_data[i].scale = to_user_u64(&scale_data[i]);
+               if (ds_data[i].flags & (MDP_DESTSCALER_SCALE_UPDATE |
+                                       MDP_DESTSCALER_ENHANCER_UPDATE)) {
+                       ret = copy_from_user(scale_data + i, scale_data_user,
+                                            sizeof(*scale_data));
                        if (ret) {
                                pr_err("scale data copy from user failed\n");
-                               kfree(scale_data);
-                               goto err;
+                               return ret;
                        }
+               } else {
+                       memset(scale_data + i, 0, sizeof(*scale_data));
                }
        }
 
        return ret;
-
-err:
-       if (ds_data) {
-               for (i--; i >= 0; i--) {
-                       scale_data = to_user_ptr(ds_data[i].scale);
-                       kfree(scale_data);
-               }
-               kfree(ds_data);
-       }
-
-       return ret;
 }
 
 static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
@@ -4962,11 +4929,12 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
        struct mdp_input_layer __user *input_layer_list;
        struct mdp_output_layer *output_layer = NULL;
        struct mdp_output_layer __user *output_layer_user;
-       struct mdp_destination_scaler_data *ds_data = NULL;
        struct mdp_destination_scaler_data __user *ds_data_user;
        struct msm_fb_data_type *mfd;
        struct mdss_overlay_private *mdp5_data = NULL;
        struct mdss_data_type *mdata;
+       struct mdp_destination_scaler_data ds_data[2];
+       struct mdp_scale_data_v2 scale_data[2];
 
        ret = copy_from_user(&commit, argp, sizeof(struct mdp_layer_commit));
        if (ret) {
@@ -5076,12 +5044,12 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
                        ret = -EPERM;
                        goto err;
                }
-               ret = __mdss_fb_copy_destscaler_data(info, &commit);
+               ret = __mdss_fb_copy_destscaler_data(info, &commit, ds_data,
+                                                    scale_data);
                if (ret) {
                        pr_err("copy dest scaler failed\n");
                        goto err;
                }
-               ds_data = commit.commit_v1.dest_scaler;
        }
 
        ATRACE_BEGIN("ATOMIC_COMMIT");
@@ -5126,11 +5094,6 @@ err:
        }
        kfree(layer_list);
        kfree(output_layer);
-       if (ds_data) {
-               for (i = 0; i < commit.commit_v1.dest_scaler_cnt; i++)
-                       kfree(to_user_ptr(ds_data[i].scale));
-               kfree(ds_data);
-       }
 
        return ret;
 }
index 93aac0c..1cf3b05 100644 (file)
@@ -2411,6 +2411,7 @@ static u32 mdss_mdp_scaler_init(struct mdss_data_type *mdata,
                        return -EINVAL;
                }
                mdata->scaler_off->ndest_scalers = len/sizeof(u32);
+               BUG_ON(mdata->scaler_off->ndest_scalers > 2);
 
                mdata->scaler_off->dest_scaler_off =
                        devm_kzalloc(dev, sizeof(u32) *