summaryrefslogtreecommitdiff
path: root/drivers/gpu/arm/utgard/linux/mali_osk_low_level_mem.c
blob: c14e872a7d639107489bd747130cdd77d96344c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * Copyright (C) 2010-2015 ARM Limited. All rights reserved.
 * 
 * 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.
 */

/**
 * @file mali_osk_low_level_mem.c
 * Implementation of the OS abstraction layer for the kernel device driver
 */

#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/slab.h>

#include "mali_kernel_common.h"
#include "mali_osk.h"
#include "mali_ukk.h"

void _mali_osk_mem_barrier(void)
{
	mb();
}

void _mali_osk_write_mem_barrier(void)
{
	wmb();
}

mali_io_address _mali_osk_mem_mapioregion(uintptr_t phys, u32 size, const char *description)
{
	return (mali_io_address)ioremap_nocache(phys, size);
}

void _mali_osk_mem_unmapioregion(uintptr_t phys, u32 size, mali_io_address virt)
{
	iounmap((void *)virt);
}

_mali_osk_errcode_t inline _mali_osk_mem_reqregion(uintptr_t phys, u32 size, const char *description)
{
#if MALI_LICENSE_IS_GPL
	return _MALI_OSK_ERR_OK; /* GPL driver gets the mem region for the resources registered automatically */
#else
	return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK);
#endif
}

void inline _mali_osk_mem_unreqregion(uintptr_t phys, u32 size)
{
#if !MALI_LICENSE_IS_GPL
	release_mem_region(phys, size);
#endif
}

void inline _mali_osk_mem_iowrite32_relaxed(volatile mali_io_address addr, u32 offset, u32 val)
{
	__raw_writel(cpu_to_le32(val), ((u8 *)addr) + offset);
}

u32 inline _mali_osk_mem_ioread32(volatile mali_io_address addr, u32 offset)
{
	return ioread32(((u8 *)addr) + offset);
}

void inline _mali_osk_mem_iowrite32(volatile mali_io_address addr, u32 offset, u32 val)
{
	iowrite32(val, ((u8 *)addr) + offset);
}

void _mali_osk_cache_flushall(void)
{
	/** @note Cached memory is not currently supported in this implementation */
}

void _mali_osk_cache_ensure_uncached_range_flushed(void *uncached_mapping, u32 offset, u32 size)
{
	_mali_osk_write_mem_barrier();
}

u32 _mali_osk_mem_write_safe(void __user *dest, const void __user *src, u32 size)
{
#define MALI_MEM_SAFE_COPY_BLOCK_SIZE 4096
	u32 retval = 0;
	void *temp_buf;

	temp_buf = kmalloc(MALI_MEM_SAFE_COPY_BLOCK_SIZE, GFP_KERNEL);
	if (NULL != temp_buf) {
		u32 bytes_left_to_copy = size;
		u32 i;
		for (i = 0; i < size; i += MALI_MEM_SAFE_COPY_BLOCK_SIZE) {
			u32 size_to_copy;
			u32 size_copied;
			u32 bytes_left;

			if (bytes_left_to_copy > MALI_MEM_SAFE_COPY_BLOCK_SIZE) {
				size_to_copy = MALI_MEM_SAFE_COPY_BLOCK_SIZE;
			} else {
				size_to_copy = bytes_left_to_copy;
			}

			bytes_left = copy_from_user(temp_buf, ((char *)src) + i, size_to_copy);
			size_copied = size_to_copy - bytes_left;

			bytes_left = copy_to_user(((char *)dest) + i, temp_buf, size_copied);
			size_copied -= bytes_left;

			bytes_left_to_copy -= size_copied;
			retval += size_copied;

			if (size_copied != size_to_copy) {
				break; /* Early out, we was not able to copy this entire block */
			}
		}

		kfree(temp_buf);
	}

	return retval;
}

_mali_osk_errcode_t _mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s *args)
{
	void __user *src;
	void __user *dst;
	struct mali_session_data *session;

	MALI_DEBUG_ASSERT_POINTER(args);

	session = (struct mali_session_data *)(uintptr_t)args->ctx;

	if (NULL == session) {
		return _MALI_OSK_ERR_INVALID_ARGS;
	}

	src = (void __user *)(uintptr_t)args->src;
	dst = (void __user *)(uintptr_t)args->dest;

	/* Return number of bytes actually copied */
	args->size = _mali_osk_mem_write_safe(dst, src, args->size);
	return _MALI_OSK_ERR_OK;
}