diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_compat_utils.c | 91 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_compat_utils.h | 11 |
2 files changed, 92 insertions, 10 deletions
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c index 48d0f11e8671..b7ce8480b486 100644 --- a/drivers/video/fbdev/msm/mdss_compat_utils.c +++ b/drivers/video/fbdev/msm/mdss_compat_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (C) 1994 Martin Schaller * * 2001 - Documented with DocBook @@ -582,11 +582,38 @@ static int __to_user_csc_cfg_data( return 0; } +static int __from_user_igc_lut_data_v17( + struct mdp_igc_lut_data32 __user *igc_lut32, + struct mdp_igc_lut_data __user *igc_lut) +{ + struct mdp_igc_lut_data_v1_7_32 igc_cfg_payload_32; + struct mdp_igc_lut_data_v1_7 igc_cfg_payload; + + if (copy_from_user(&igc_cfg_payload_32, + compat_ptr(igc_lut32->cfg_payload), + sizeof(igc_cfg_payload_32))) { + pr_err("failed to copy payload from user for igc\n"); + return -EFAULT; + } + igc_cfg_payload.c0_c1_data = compat_ptr(igc_cfg_payload_32.c0_c1_data); + igc_cfg_payload.c2_data = compat_ptr(igc_cfg_payload_32.c2_data); + igc_cfg_payload.len = igc_cfg_payload_32.len; + igc_cfg_payload.table_fmt = igc_cfg_payload_32.table_fmt; + if (copy_to_user(igc_lut->cfg_payload, &igc_cfg_payload, + sizeof(igc_cfg_payload))) { + pr_err("failed to copy payload to user for igc\n"); + return -EFAULT; + } + return 0; +} + static int __from_user_igc_lut_data( struct mdp_igc_lut_data32 __user *igc_lut32, struct mdp_igc_lut_data __user *igc_lut) { uint32_t data; + uint32_t version = mdp_igc_vmax; + int ret = 0; if (copy_in_user(&igc_lut->block, &igc_lut32->block, @@ -596,16 +623,35 @@ static int __from_user_igc_lut_data( sizeof(uint32_t)) || copy_in_user(&igc_lut->ops, &igc_lut32->ops, + sizeof(uint32_t)) || + copy_in_user(&igc_lut->version, + &igc_lut32->version, sizeof(uint32_t))) return -EFAULT; - if (get_user(data, &igc_lut32->c0_c1_data) || - put_user(compat_ptr(data), &igc_lut->c0_c1_data) || - get_user(data, &igc_lut32->c2_data) || - put_user(compat_ptr(data), &igc_lut->c2_data)) + if (get_user(version, &igc_lut32->version)) { + pr_err("failed to copy the version for IGC\n"); return -EFAULT; + } - return 0; + switch (version) { + case mdp_igc_v1_7: + ret = __from_user_igc_lut_data_v17(igc_lut32, igc_lut); + if (ret) + pr_err("failed to copy payload for igc version %d ret %d\n", + version, ret); + break; + default: + pr_debug("version not supported fallback to legacy %d\n", + version); + if (get_user(data, &igc_lut32->c0_c1_data) || + put_user(compat_ptr(data), &igc_lut->c0_c1_data) || + get_user(data, &igc_lut32->c2_data) || + put_user(compat_ptr(data), &igc_lut->c2_data)) + return -EFAULT; + break; + } + return ret; } static int __to_user_igc_lut_data( @@ -1804,6 +1850,14 @@ static int __from_user_pp_init_data( return 0; } +static u32 __pp_compat_size_igc(void) +{ + u32 alloc_size = 0; + /* When we have mutiple versions pick largest struct size */ + alloc_size = sizeof(struct mdp_igc_lut_data_v1_7); + return alloc_size; +} + static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, struct msmfb_mdp_pp __user **pp, uint32_t op) @@ -1820,7 +1874,8 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, sizeof(uint32_t))) return -EFAULT; - if (lut_type == mdp_lut_pgc) { + switch (lut_type) { + case mdp_lut_pgc: pgc_data32 = compat_ptr((uintptr_t) &pp32->data.lut_cfg_data.data.pgc_lut_data); if (copy_from_user(&num_r_stages, @@ -1869,11 +1924,29 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, ((unsigned long) *pp + sizeof(struct msmfb_mdp_pp) + r_size + g_size); - } else { + break; + case mdp_lut_igc: + alloc_size += __pp_compat_size_igc(); *pp = compat_alloc_user_space(alloc_size); - if (NULL == *pp) + if (NULL == *pp) { + pr_err("failed to alloc from user size %d for igc\n", + alloc_size); + return -ENOMEM; + } + memset(*pp, 0, alloc_size); + (*pp)->data.lut_cfg_data.data.igc_lut_data.cfg_payload + = (void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)); + break; + default: + *pp = compat_alloc_user_space(alloc_size); + if (NULL == *pp) { + pr_err("failed to alloc from user size %d for lut_type %d\n", + alloc_size, lut_type); return -ENOMEM; + } memset(*pp, 0, alloc_size); + break; } } else { *pp = compat_alloc_user_space(alloc_size); diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.h b/drivers/video/fbdev/msm/mdss_compat_utils.h index 364746866db8..77452b7194c6 100644 --- a/drivers/video/fbdev/msm/mdss_compat_utils.h +++ b/drivers/video/fbdev/msm/mdss_compat_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * 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 @@ -168,11 +168,20 @@ struct mdp_pa_cfg_data32 { struct mdp_pa_cfg32 pa_data; }; +struct mdp_igc_lut_data_v1_7_32 { + uint32_t table_fmt; + uint32_t len; + compat_caddr_t c0_c1_data; + compat_caddr_t c2_data; +}; + struct mdp_igc_lut_data32 { uint32_t block; + uint32_t version; uint32_t len, ops; compat_caddr_t c0_c1_data; compat_caddr_t c2_data; + compat_caddr_t cfg_payload; }; struct mdp_hist_lut_data32 { |
