diff --git a/patch/kernel/sun4i-default/0001-arm-sunxi-disp-Fix-division-by-zero.patch b/patch/kernel/sun4i-default/0001-arm-sunxi-disp-Fix-division-by-zero.patch new file mode 100644 index 000000000..0aaac3451 --- /dev/null +++ b/patch/kernel/sun4i-default/0001-arm-sunxi-disp-Fix-division-by-zero.patch @@ -0,0 +1,35 @@ +From ef19ae19f876d9cb04fac10141d23c8ae500f9e7 Mon Sep 17 00:00:00 2001 +From: Andreas Baierl +Date: Tue, 26 May 2015 09:18:46 -0400 +Subject: [PATCH 1/9] arm:sunxi:disp: Fix division by zero + +--- + drivers/video/sunxi/disp/disp_video.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/sunxi/disp/disp_video.c b/drivers/video/sunxi/disp/disp_video.c +index aa07364..765f6ec 100644 +--- a/drivers/video/sunxi/disp/disp_video.c ++++ b/drivers/video/sunxi/disp/disp_video.c +@@ -71,10 +71,14 @@ static __s32 video_enhancement_start(__u32 sel, __u32 id) + /* !!! assume open HDMI before video start */ + if (gdisp.screen[sel].output_type == DISP_OUTPUT_TYPE_HDMI) { + scaler_index = gdisp.screen[sel].layer_manage[id].scaler_index; +- scaleuprate = +- gdisp.screen[sel].layer_manage[id].para.scn_win.width * +- 2 / +- gdisp.screen[sel].layer_manage[id].para.src_win.width; ++ ++ if ((gdisp.screen[sel].layer_manage[id].para.scn_win.width == ++ gdisp.screen[sel].layer_manage[id].para.src_win.width) || ++ (gdisp.screen[sel].layer_manage[id].para.src_win.width < 1280)) ++ scaleuprate = 0; ++ else ++ scaleuprate = gdisp.screen[sel].layer_manage[id].para.scn_win.width * 2 / ++ gdisp.screen[sel].layer_manage[id].para.src_win.width; + + switch (scaleuprate) { + case 0: /* scale down, do noting */ +-- +2.7.0 + diff --git a/patch/kernel/sun4i-default/0002-arm-sunxi-g2d-Fix-handle-noop-blits.patch b/patch/kernel/sun4i-default/0002-arm-sunxi-g2d-Fix-handle-noop-blits.patch new file mode 100644 index 000000000..1fe7c1351 --- /dev/null +++ b/patch/kernel/sun4i-default/0002-arm-sunxi-g2d-Fix-handle-noop-blits.patch @@ -0,0 +1,87 @@ +From 3526df71cb2d2f9416a1a007da66ce88d3c70af9 Mon Sep 17 00:00:00 2001 +From: Andreas Baierl +Date: Tue, 26 May 2015 09:20:10 -0400 +Subject: [PATCH 2/9] arm:sunxi:g2d: Fix: handle noop blits + +Zero area blits are technically valid noops and are requested by +libvdpau. Return 0 when blit area is zero without performing bogus +calculations. +--- + drivers/char/sunxi_g2d/g2d.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/char/sunxi_g2d/g2d.c b/drivers/char/sunxi_g2d/g2d.c +index 539c726..02bc83c 100644 +--- a/drivers/char/sunxi_g2d/g2d.c ++++ b/drivers/char/sunxi_g2d/g2d.c +@@ -142,8 +142,7 @@ int g2d_blit(g2d_blt * para) + __s32 err = 0; + + /* check the parameter valid */ +- if(para->src_rect.w == 0 || para->src_rect.h == 0 || +- ((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) || ++ if(((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) || + ((para->src_rect.y < 0)&&((-para->src_rect.y) > para->src_rect.h)) || + ((para->dst_x < 0)&&((-para->dst_x) > para->src_rect.w)) || + ((para->dst_y < 0)&&((-para->dst_y) > para->src_rect.h)) || +@@ -157,6 +156,11 @@ int g2d_blit(g2d_blt * para) + } + else + { ++ if((para->src_rect.w == 0) || (para->src_rect.h == 0)) ++ { ++ printk(KERN_DEBUG "User requested g2d blit on zero region\n"); ++ return err; ++ } + if(((para->src_rect.x < 0)&&((-para->src_rect.x) < para->src_rect.w))) + { + para->src_rect.w = para->src_rect.w + para->src_rect.x; +@@ -209,8 +213,7 @@ int g2d_fill(g2d_fillrect * para) + __s32 err = 0; + + /* check the parameter valid */ +- if(para->dst_rect.w == 0 || para->dst_rect.h == 0 || +- ((para->dst_rect.x < 0)&&((-para->dst_rect.x)>para->dst_rect.w)) || ++ if(((para->dst_rect.x < 0)&&((-para->dst_rect.x)>para->dst_rect.w)) || + ((para->dst_rect.y < 0)&&((-para->dst_rect.y)>para->dst_rect.h)) || + ((para->dst_rect.x > 0)&&(para->dst_rect.x > para->dst_image.w - 1)) || + ((para->dst_rect.y > 0)&&(para->dst_rect.y > para->dst_image.h - 1))) +@@ -220,6 +223,11 @@ int g2d_fill(g2d_fillrect * para) + } + else + { ++ if((para->dst_rect.w == 0) || (para->dst_rect.h == 0)) ++ { ++ printk(KERN_DEBUG "User requested g2d fill on zero region\n"); ++ return err; ++ } + if(((para->dst_rect.x < 0)&&((-para->dst_rect.x) < para->dst_rect.w))) + { + para->dst_rect.w = para->dst_rect.w + para->dst_rect.x; +@@ -251,9 +259,7 @@ int g2d_stretchblit(g2d_stretchblt * para) + __s32 err = 0; + + /* check the parameter valid */ +- if(para->src_rect.w == 0 || para->src_rect.h == 0 || +- para->dst_rect.w == 0 || para->dst_rect.h == 0 || +- ((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) || ++ if(((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) || + ((para->src_rect.y < 0)&&((-para->src_rect.y) > para->src_rect.h)) || + ((para->dst_rect.x < 0)&&((-para->dst_rect.x) > para->dst_rect.w)) || + ((para->dst_rect.y < 0)&&((-para->dst_rect.y) > para->dst_rect.h)) || +@@ -267,6 +273,12 @@ int g2d_stretchblit(g2d_stretchblt * para) + } + else + { ++ if((para->dst_rect.w == 0) || (para->dst_rect.h == 0) || ++ (para->src_rect.w == 0) || (para->src_rect.h == 0)) ++ { ++ printk(KERN_DEBUG "User requested g2d stretchblit on zero region\n"); ++ return err; ++ } + if(((para->src_rect.x < 0)&&((-para->src_rect.x) < para->src_rect.w))) + { + para->src_rect.w = para->src_rect.w + para->src_rect.x; +-- +2.7.0 + diff --git a/patch/kernel/sun4i-default/0003-arm-sunxi-disp-Fix-csc-calculations.patch b/patch/kernel/sun4i-default/0003-arm-sunxi-disp-Fix-csc-calculations.patch new file mode 100644 index 000000000..8f10da029 --- /dev/null +++ b/patch/kernel/sun4i-default/0003-arm-sunxi-disp-Fix-csc-calculations.patch @@ -0,0 +1,31 @@ +From c92d32e1adc7ee2fcf014a9abf35039b59478bf3 Mon Sep 17 00:00:00 2001 +From: Andreas Baierl +Date: Tue, 26 May 2015 09:23:00 -0400 +Subject: [PATCH 3/9] arm:sunxi:disp: Fix csc calculations. + +--- + drivers/video/sunxi/disp/de_fe.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/sunxi/disp/de_fe.c b/drivers/video/sunxi/disp/de_fe.c +index 92799a0..54dfe7f 100644 +--- a/drivers/video/sunxi/disp/de_fe.c ++++ b/drivers/video/sunxi/disp/de_fe.c +@@ -1382,10 +1382,10 @@ __s32 DE_SCAL_Set_CSC_Coef_Enhance(__u8 sel, __u8 in_csc_mode, + __u32 i; + __s32 sinv, cosv; /* sin_tab: 7 bit fractional */ + +- bright = bright * 64 / 100; +- bright = saturation * 64 / 100; +- bright = contrast * 64 / 100; +- bright = hue * 64 / 100; ++ bright = DIV_ROUND_CLOSEST((clamp(bright, 0, 100) * 63), 100); ++ saturation = DIV_ROUND_CLOSEST((clamp(saturation, 0, 100) * 63), 100); ++ contrast = DIV_ROUND_CLOSEST((clamp(contrast, 0, 100) * 63), 100); ++ hue = DIV_ROUND_CLOSEST((clamp(hue, 0, 100) * 63), 100); + + sinv = image_enhance_tab[8 * 12 + (hue & 0x3f)]; + cosv = image_enhance_tab[8 * 12 + 8 * 8 + (hue & 0x3f)]; +-- +2.7.0 + diff --git a/patch/kernel/sun4i-default/0009-Added-new-backend-based-on-CMA-for-the-Mali-UMP-memo.patch b/patch/kernel/sun4i-default/0009-Added-new-backend-based-on-CMA-for-the-Mali-UMP-memo.patch new file mode 100644 index 000000000..c0fd35e86 --- /dev/null +++ b/patch/kernel/sun4i-default/0009-Added-new-backend-based-on-CMA-for-the-Mali-UMP-memo.patch @@ -0,0 +1,632 @@ +From 16ad799b917a761b1b3c269a1063e5f0e991d35c Mon Sep 17 00:00:00 2001 +From: Martin Ostertag +Date: Tue, 29 Dec 2015 23:37:47 +0100 +Subject: [PATCH 9/9] Added new backend based on CMA for the Mali UMP memory + block allocator. + +This one is necesary for a zero-copy interworking between Cedarx and Mali hardware +--- + drivers/gpu/mali/ump/Kbuild | 1 + + .../mali/ump/arch-ca7-virtex820-m400-2/config.h | 4 +- + .../mali/ump/arch-ca8-virtex820-m400-1/config.h | 4 +- + drivers/gpu/mali/ump/common/ump_kernel_api.c | 27 ++- + drivers/gpu/mali/ump/common/ump_kernel_types.h | 13 +- + drivers/gpu/mali/ump/common/ump_uk_types.h | 11 ++ + drivers/gpu/mali/ump/common/ump_ukk.h | 2 + + drivers/gpu/mali/ump/linux/ump_ioctl.h | 1 + + drivers/gpu/mali/ump/linux/ump_kernel_linux.c | 29 +-- + .../mali/ump/linux/ump_kernel_memory_backend_cma.c | 209 +++++++++++++++++++++ + .../mali/ump/linux/ump_kernel_memory_backend_cma.h | 27 +++ + drivers/gpu/mali/ump/linux/ump_memory_backend.c | 8 +- + drivers/gpu/mali/ump/linux/ump_ukk_wrappers.c | 40 ++++ + drivers/gpu/mali/ump/linux/ump_ukk_wrappers.h | 1 + + 14 files changed, 358 insertions(+), 19 deletions(-) + create mode 100644 drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.c + create mode 100644 drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.h + +diff --git a/drivers/gpu/mali/ump/Kbuild b/drivers/gpu/mali/ump/Kbuild +index 62380fa..a581a27 100644 +--- a/drivers/gpu/mali/ump/Kbuild ++++ b/drivers/gpu/mali/ump/Kbuild +@@ -43,6 +43,7 @@ ump-y = common/ump_kernel_common.o \ + linux/ump_kernel_linux.o \ + linux/ump_kernel_memory_backend_os.o \ + linux/ump_kernel_memory_backend_dedicated.o \ ++ linux/ump_kernel_memory_backend_cma.o \ + linux/ump_memory_backend.o \ + linux/ump_ukk_wrappers.o \ + linux/ump_ukk_ref_wrappers.o \ +diff --git a/drivers/gpu/mali/ump/arch-ca7-virtex820-m400-2/config.h b/drivers/gpu/mali/ump/arch-ca7-virtex820-m400-2/config.h +index 9560e96..9199061 100644 +--- a/drivers/gpu/mali/ump/arch-ca7-virtex820-m400-2/config.h ++++ b/drivers/gpu/mali/ump/arch-ca7-virtex820-m400-2/config.h +@@ -1,8 +1,8 @@ + #ifndef __ARCH_CONFIG_H__ + #define __ARCH_CONFIG_H__ + +-#define ARCH_UMP_BACKEND_DEFAULT 1 ++#define ARCH_UMP_BACKEND_DEFAULT 2 + #define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x5E000000 + #define ARCH_UMP_MEMORY_SIZE_DEFAULT 128UL * 1024UL * 1024UL + +-#endif /* __ARCH_CONFIG_H__ */ +\ No newline at end of file ++#endif /* __ARCH_CONFIG_H__ */ +diff --git a/drivers/gpu/mali/ump/arch-ca8-virtex820-m400-1/config.h b/drivers/gpu/mali/ump/arch-ca8-virtex820-m400-1/config.h +index 9560e96..9199061 100644 +--- a/drivers/gpu/mali/ump/arch-ca8-virtex820-m400-1/config.h ++++ b/drivers/gpu/mali/ump/arch-ca8-virtex820-m400-1/config.h +@@ -1,8 +1,8 @@ + #ifndef __ARCH_CONFIG_H__ + #define __ARCH_CONFIG_H__ + +-#define ARCH_UMP_BACKEND_DEFAULT 1 ++#define ARCH_UMP_BACKEND_DEFAULT 2 + #define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x5E000000 + #define ARCH_UMP_MEMORY_SIZE_DEFAULT 128UL * 1024UL * 1024UL + +-#endif /* __ARCH_CONFIG_H__ */ +\ No newline at end of file ++#endif /* __ARCH_CONFIG_H__ */ +diff --git a/drivers/gpu/mali/ump/common/ump_kernel_api.c b/drivers/gpu/mali/ump/common/ump_kernel_api.c +index e86bc33..e5ce026 100644 +--- a/drivers/gpu/mali/ump/common/ump_kernel_api.c ++++ b/drivers/gpu/mali/ump/common/ump_kernel_api.c +@@ -7,6 +7,8 @@ + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ ++#include ++#include + + #include "mali_osk.h" + #include "mali_osk_list.h" +@@ -16,7 +18,6 @@ + #include "ump_kernel_common.h" + + +- + /* ---------------- UMP kernel space API functions follows ---------------- */ + + +@@ -291,6 +292,30 @@ _mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ) + return ret; + } + ++_mali_osk_errcode_t _ump_ukk_phys_addr_get( _ump_uk_phys_addr_get_s *user_interaction ) ++{ ++ ump_dd_mem * mem; ++ _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; ++ ++ DEBUG_ASSERT_POINTER( user_interaction ); ++ ++ /* We lock the mappings so things don't get removed while we are looking for the memory */ ++ _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); ++ if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)user_interaction->secure_id, (void**)&mem)) ++ { ++ user_interaction->phys_addr = __phys_to_bus(mem->block_array[0].addr); ++ DBG_MSG(4, ("Returning physical address. ID: %u, phys_addr: 0x%x ", (ump_secure_id)user_interaction->secure_id, (unsigned long)user_interaction->phys_addr)); ++ ret = _MALI_OSK_ERR_OK; ++ } ++ else ++ { ++ user_interaction->phys_addr = 0; ++ DBG_MSG(1, ("Failed to look up mapping in ump_ioctl_phys_addr_get(). ID: %u\n", (ump_secure_id)user_interaction->secure_id)); ++ } ++ ++ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); ++ return ret; ++} + + + void _ump_ukk_msync( _ump_uk_msync_s *args ) +diff --git a/drivers/gpu/mali/ump/common/ump_kernel_types.h b/drivers/gpu/mali/ump/common/ump_kernel_types.h +index fdacd86..45d4939 100644 +--- a/drivers/gpu/mali/ump/common/ump_kernel_types.h ++++ b/drivers/gpu/mali/ump/common/ump_kernel_types.h +@@ -13,7 +13,10 @@ + + #include "ump_kernel_interface.h" + #include "mali_osk.h" ++#include ++#include + ++#define UMP_LICENSE_IS_GPL 1 + + typedef enum + { +@@ -40,6 +43,7 @@ typedef struct ump_dd_mem + unsigned long size_bytes; + unsigned long nr_blocks; + ump_dd_physical_block * block_array; ++ void * cpu_addr; + void (*release_func)(void * ctx, struct ump_dd_mem * descriptor); + void * ctx; + void * backend_info; +@@ -48,6 +52,13 @@ typedef struct ump_dd_mem + ump_lock_usage lock_usage; + } ump_dd_mem; + +- ++struct ump_device ++{ ++ struct cdev cdev; ++#if UMP_LICENSE_IS_GPL ++ struct class * ump_class; ++ struct device *mdev; ++#endif ++}; + + #endif /* __UMP_KERNEL_TYPES_H__ */ +diff --git a/drivers/gpu/mali/ump/common/ump_uk_types.h b/drivers/gpu/mali/ump/common/ump_uk_types.h +index 24f4596..bd0cc8d 100644 +--- a/drivers/gpu/mali/ump/common/ump_uk_types.h ++++ b/drivers/gpu/mali/ump/common/ump_uk_types.h +@@ -49,6 +49,7 @@ typedef enum + _UMP_IOC_SWITCH_HW_USAGE, + _UMP_IOC_LOCK, + _UMP_IOC_UNLOCK, ++ _UMP_IOC_PHYS_ADDR_GET, + }_ump_uk_functions; + + typedef enum +@@ -118,6 +119,16 @@ typedef struct _ump_uk_size_get_s + } _ump_uk_size_get_s; + + /** ++ * PHYS_ADDR_GET ([in] u32 secure_id, [out]phys_addr ) ++ */ ++typedef struct _ump_uk_phys_addr_get_s ++{ ++ void *ctx; /**< [in,out] user-kernel context (trashed on output) */ ++ u32 secure_id; /**< Input to DD */ ++ void *phys_addr; /**< Returned physical address; output */ ++} _ump_uk_phys_addr_get_s; ++ ++/** + * Release ([in] u32 secure_id) + */ + typedef struct _ump_uk_release_s +diff --git a/drivers/gpu/mali/ump/common/ump_ukk.h b/drivers/gpu/mali/ump/common/ump_ukk.h +index 4e6bb86..926a286 100644 +--- a/drivers/gpu/mali/ump/common/ump_ukk.h ++++ b/drivers/gpu/mali/ump/common/ump_ukk.h +@@ -36,6 +36,8 @@ _mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ); + + _mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ); + ++_mali_osk_errcode_t _ump_ukk_phys_addr_get( _ump_uk_phys_addr_get_s *user_interaction ); ++ + _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ); + + _mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args ); +diff --git a/drivers/gpu/mali/ump/linux/ump_ioctl.h b/drivers/gpu/mali/ump/linux/ump_ioctl.h +index 675e36e..6778b67 100644 +--- a/drivers/gpu/mali/ump/linux/ump_ioctl.h ++++ b/drivers/gpu/mali/ump/linux/ump_ioctl.h +@@ -46,6 +46,7 @@ extern "C" + #define UMP_IOC_LOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_LOCK, _ump_uk_lock_s) + #define UMP_IOC_UNLOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_UNLOCK, _ump_uk_unlock_s) + ++#define UMP_IOC_PHYS_ADDR_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_PHYS_ADDR_GET, _ump_uk_phys_addr_get_s) + + #ifdef __cplusplus + } +diff --git a/drivers/gpu/mali/ump/linux/ump_kernel_linux.c b/drivers/gpu/mali/ump/linux/ump_kernel_linux.c +index 40514fe..02b12b4 100644 +--- a/drivers/gpu/mali/ump/linux/ump_kernel_linux.c ++++ b/drivers/gpu/mali/ump/linux/ump_kernel_linux.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include "config.h" /* Configuration for current platform. The symlinc for arch is set by Makefile */ + #include "ump_ioctl.h" +@@ -65,16 +66,10 @@ typedef struct ump_vma_usage_tracker + ump_dd_handle handle; + } ump_vma_usage_tracker; + +-struct ump_device +-{ +- struct cdev cdev; +-#if UMP_LICENSE_IS_GPL +- struct class * ump_class; +-#endif +-}; ++ + + /* The global variable containing the global device data */ +-static struct ump_device ump_device; ++struct ump_device ump_device; + + + /* Forward declare static functions */ +@@ -207,14 +202,19 @@ int ump_kernel_device_initialize(void) + } + else + { +- struct device * mdev; +- mdev = device_create(ump_device.ump_class, NULL, dev, NULL, ump_dev_name); +- if (!IS_ERR(mdev)) ++ ump_device.mdev = device_create(ump_device.ump_class, NULL, dev, NULL, ump_dev_name); ++ if (!IS_ERR(ump_device.mdev)) + { ++ DBG_MSG(2, ("dma_set_mask_and_coherent calling\n")); ++ err = dma_set_coherent_mask(ump_device.mdev, DMA_BIT_MASK(28)); ++ DBG_MSG(2, ("dma_set_mask_and_coherent result=%d\n", err)); ++ if(err < 0) ++ DBG_MSG(2, ("dma_set_mask_and_coherent failed\n")); ++ + return 0; + } + +- err = PTR_ERR(mdev); ++ err = PTR_ERR(ump_device.mdev); + } + cdev_del(&ump_device.cdev); + #else +@@ -367,6 +367,10 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c + case UMP_IOC_UNLOCK: + err = ump_unlock_wrapper((u32 __user *)argument, session_data); + break; ++ ++ case UMP_IOC_PHYS_ADDR_GET: ++ err = ump_phys_addr_get_wrapper((u32 __user *)argument, session_data); ++ break; + + default: + DBG_MSG(1, ("No handler for IOCTL. cmd: 0x%08x, arg: 0x%08lx\n", cmd, arg)); +@@ -449,6 +453,7 @@ EXPORT_SYMBOL(ump_dd_phys_blocks_get); + EXPORT_SYMBOL(ump_dd_size_get); + EXPORT_SYMBOL(ump_dd_reference_add); + EXPORT_SYMBOL(ump_dd_reference_release); ++EXPORT_SYMBOL(ump_device); + + /* Export our own extended kernel space allocator */ + EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); +diff --git a/drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.c b/drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.c +new file mode 100644 +index 0000000..84021cd +--- /dev/null ++++ b/drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.c +@@ -0,0 +1,209 @@ ++/* ++ * Based on code originally written by ARM Limited. ++ * Copyright (C) 2010-2011 ARM Limited. All rights reserved. ++ * Copyright 2015 Martin Ostertag Martin.Ostertag@gmx.de ++ * ++ * ++ * This program is free software and is provided to you under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. ++ * ++ * A copy of the licence is included with the program, and can also be obtained from Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++/* needed to detect kernel version specific code */ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++#include ++#else /* pre 2.6.26 the file was in the arch specific location */ ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ump_kernel_common.h" ++#include "ump_kernel_memory_backend.h" ++ ++ ++extern struct ump_device ump_device; ++ ++typedef struct os_allocator ++{ ++ struct semaphore mutex; ++ u32 mem_maximum; /**< Maximum number of pages to allocate from the CMA */ ++ u32 mem_allocated; /**< Number of pages allocated from the CMA */ ++} cma_allocator; ++ ++ ++ ++static void cma_free(void* ctx, ump_dd_mem * descriptor); ++static int cma_allocate(void* ctx, ump_dd_mem * descriptor); ++static void cma_memory_backend_destroy(ump_memory_backend * backend); ++static u32 cma_stat(struct ump_memory_backend *backend); ++ ++ ++ ++/* ++ * Create CMA memory backend ++ */ ++ump_memory_backend * ump_cma_memory_backend_create(const int max_allocation) ++{ ++ ump_memory_backend * backend; ++ cma_allocator * info; ++ ++ info = kmalloc(sizeof(cma_allocator), GFP_KERNEL); ++ if (NULL == info) ++ { ++ return NULL; ++ } ++ ++ info->mem_maximum = max_allocation; ++ info->mem_allocated = 0; ++ ++ sema_init(&info->mutex, 1); ++ ++ backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); ++ if (NULL == backend) ++ { ++ kfree(info); ++ return NULL; ++ } ++ ++ backend->ctx = info; ++ backend->allocate = cma_allocate; ++ backend->release = cma_free; ++ backend->shutdown = cma_memory_backend_destroy; ++ backend->stat = cma_stat; ++ backend->pre_allocate_physical_check = NULL; ++ backend->adjust_to_mali_phys = NULL; ++ ++ return backend; ++} ++ ++ ++ ++/* ++ * Destroy specified OS memory backend ++ */ ++static void cma_memory_backend_destroy(ump_memory_backend * backend) ++{ ++ cma_allocator * info = (cma_allocator*)backend->ctx; ++ ++ DBG_MSG_IF(1, 0 != info->mem_allocated, ("%d bytes still in use during shutdown\n", info->mem_allocated)); ++ ++ kfree(info); ++ kfree(backend); ++} ++ ++ ++ ++/* ++ * Allocate UMP memory ++ */ ++static int cma_allocate(void* ctx, ump_dd_mem * descriptor) ++{ ++ u32 left; ++ cma_allocator * info; ++ int pages_allocated = 0; ++ int is_cached; ++ dma_addr_t paddr; ++ ++ BUG_ON(!descriptor); ++ BUG_ON(!ctx); ++ ++ info = (cma_allocator*)ctx; ++ left = descriptor->size_bytes; ++ is_cached = descriptor->is_cached; ++ ++ if (down_interruptible(&info->mutex)) ++ { ++ DBG_MSG(1, ("Failed to get mutex in os_free\n")); ++ return 0; /* failure */ ++ } ++ ++ descriptor->backend_info = NULL; ++ descriptor->nr_blocks = ((left + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) >> PAGE_SHIFT; ++ ++ DBG_MSG(5, ("Allocating page array. Size: %lu\n", descriptor->nr_blocks * sizeof(ump_dd_physical_block))); ++ ++ descriptor->block_array = (ump_dd_physical_block *)vmalloc(sizeof(ump_dd_physical_block) * descriptor->nr_blocks); ++ if (NULL == descriptor->block_array) ++ { ++ up(&info->mutex); ++ DBG_MSG(1, ("Block array could not be allocated\n")); ++ return 0; /* failure */ ++ } ++ ++ descriptor->cpu_addr = dma_alloc_coherent(/* ump_device.mdev */ NULL, descriptor->size_bytes, &paddr, GFP_KERNEL | GFP_DMA); ++ if(! descriptor->cpu_addr) ++ { ++ up(&info->mutex); ++ DBG_MSG(1, ("Failed to allocate needed CMA memory %d bytes\n", descriptor->size_bytes)); ++ return 0; /* failure */ ++ } ++ ++ if(is_cached) ++ DBG_MSG(1, ("caching not supported\n")); ++ ++ for (; pages_allocated < descriptor->nr_blocks; pages_allocated++) ++ { ++ descriptor->block_array[pages_allocated].addr = ((char*)paddr) + (PAGE_SIZE * pages_allocated); ++ descriptor->block_array[pages_allocated].size = PAGE_SIZE; ++ } ++ ++ DBG_MSG(5, ("Alloce for ID:%2d got %d pages\n", descriptor->secure_id, pages_allocated)); ++ ++ info->mem_allocated += descriptor->size_bytes; ++ ++ DBG_MSG(6, ("%d out of %d bytes now allocated\n", info->mem_allocated, info->mem_maximum)); ++ ++ up(&info->mutex); ++ ++ return 1; /* success*/ ++} ++ ++ ++/* ++ * Free specified UMP memory ++ */ ++static void cma_free(void* ctx, ump_dd_mem * descriptor) ++{ ++ cma_allocator * info; ++ int i; ++ ++ BUG_ON(!ctx); ++ BUG_ON(!descriptor); ++ ++ info = (cma_allocator*)ctx; ++ ++ BUG_ON(descriptor->nr_blocks * PAGE_SIZE > info->mem_allocated); ++ ++ if (down_interruptible(&info->mutex)) ++ { ++ DBG_MSG(1, ("Failed to get mutex in cma_free\n")); ++ return; ++ } ++ ++ DBG_MSG(5, ("Releasing %lu OS pages\n", descriptor->nr_blocks)); ++ ++ info->mem_allocated -= descriptor->nr_blocks * PAGE_SIZE; ++ ++ up(&info->mutex); ++ ++ dma_free_coherent(ump_device.mdev, descriptor->nr_blocks * PAGE_SIZE, ++ descriptor->cpu_addr, descriptor->block_array[0].addr); ++ vfree(descriptor->block_array); ++} ++ ++ ++static u32 cma_stat(struct ump_memory_backend *backend) ++{ ++ cma_allocator *info; ++ info = (cma_allocator*)backend->ctx; ++ return info->mem_allocated; ++} +diff --git a/drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.h b/drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.h +new file mode 100644 +index 0000000..7687b58 +--- /dev/null ++++ b/drivers/gpu/mali/ump/linux/ump_kernel_memory_backend_cma.h +@@ -0,0 +1,27 @@ ++/* ++ * Based on code originally written by ARM Limited. ++ * Copyright (C) 2010-2011 ARM Limited. All rights reserved. ++ * Copyright 2015 Martin Ostertag Martin.Ostertag@gmx.de ++ * ++ * This program is free software and is provided to you under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. ++ * ++ * A copy of the licence is included with the program, and can also be obtained from Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * Modified 2015: Martin Ostertag ++ */ ++ ++/** ++ * @file ump_kernel_memory_backend_CMA.h ++ */ ++ ++#ifndef __UMP_KERNEL_MEMORY_BACKEND_CMA_H__ ++#define __UMP_KERNEL_MEMORY_BACKEND_CMA_H__ ++ ++#include "ump_kernel_memory_backend.h" ++ ++ump_memory_backend * ump_cma_memory_backend_create(const int max_allocation); ++ ++#endif /* __UMP_KERNEL_MEMORY_BACKEND_CMA_H__ */ ++ +diff --git a/drivers/gpu/mali/ump/linux/ump_memory_backend.c b/drivers/gpu/mali/ump/linux/ump_memory_backend.c +index 9242819..76c5c96 100644 +--- a/drivers/gpu/mali/ump/linux/ump_memory_backend.c ++++ b/drivers/gpu/mali/ump/linux/ump_memory_backend.c +@@ -17,11 +17,12 @@ + #include "ump_kernel_common.h" + #include "ump_kernel_memory_backend_os.h" + #include "ump_kernel_memory_backend_dedicated.h" ++#include "ump_kernel_memory_backend_cma.h" + + /* Configure which dynamic memory allocator to use */ + int ump_backend = ARCH_UMP_BACKEND_DEFAULT; + module_param(ump_backend, int, S_IRUGO); /* r--r--r-- */ +-MODULE_PARM_DESC(ump_backend, "0 = dedicated memory backend (default), 1 = OS memory backend"); ++MODULE_PARM_DESC(ump_backend, "0 = dedicated memory backend (default), 1 = OS memory backend, 2 = CMA based backend"); + + /* The base address of the memory block for the dedicated memory backend */ + unsigned int ump_memory_address = ARCH_UMP_MEMORY_ADDRESS_DEFAULT; +@@ -56,6 +57,11 @@ ump_memory_backend* ump_memory_backend_create ( void ) + DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size)); + backend = ump_os_memory_backend_create(ump_memory_size); + } ++ else if (2 == ump_backend) ++ { ++ DBG_MSG(2, ("Using CMA memory backend, allocation limit: %d\n", ump_memory_size)); ++ backend = ump_cma_memory_backend_create(ump_memory_size); ++ } + + return backend; + } +diff --git a/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.c b/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.c +index e5c5903..1f06242 100644 +--- a/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.c ++++ b/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.c +@@ -138,6 +138,46 @@ int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * sessi + } + + /* ++ * IOCTL operation; Return physical address for specified UMP memory. ++ */ ++int ump_phys_addr_get_wrapper(u32 __user * argument, struct ump_session_data * session_data) ++{ ++ _ump_uk_phys_addr_get_s user_interaction; ++ _mali_osk_errcode_t err; ++ ++ /* Sanity check input parameters */ ++ if (NULL == argument || NULL == session_data) ++ { ++ MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n")); ++ return -ENOTTY; ++ } ++ ++ if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) ++ { ++ MSG_ERR(("copy_from_user() in ump_ioctl_size_get()\n")); ++ return -EFAULT; ++ } ++ ++ user_interaction.ctx = (void *) session_data; ++ err = _ump_ukk_phys_addr_get( &user_interaction ); ++ if( _MALI_OSK_ERR_OK != err ) ++ { ++ MSG_ERR(("_ump_ukk_size_get() failed in ump_ioctl_size_get()\n")); ++ return map_errcode(err); ++ } ++ ++ user_interaction.ctx = NULL; ++ ++ if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) ++ { ++ MSG_ERR(("copy_to_user() failed in ump_ioctl_size_get()\n")); ++ return -EFAULT; ++ } ++ ++ return 0; /* success */ ++} ++ ++/* + * IOCTL operation; Do cache maintenance on specified UMP memory. + */ + int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data) +diff --git a/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.h b/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.h +index 1cbacf7..acb3505 100644 +--- a/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.h ++++ b/drivers/gpu/mali/ump/linux/ump_ukk_wrappers.h +@@ -34,6 +34,7 @@ int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_sessi + int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data); + int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data); + int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data); ++int ump_phys_addr_get_wrapper(u32 __user * argument, struct ump_session_data * session_data); + + + +-- +2.7.0 +