aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/emgd/emgd/include/memory.h
blob: 4f3c96f5631ca2c128e3aa600ec7bc65e91e8982 (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
/* -*- pse-c -*-
 *-----------------------------------------------------------------------------
 * Filename: memory.h
 * $Revision: 1.4 $
 *-----------------------------------------------------------------------------
 * Copyright © 2002-2010, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *-----------------------------------------------------------------------------
 * Description:
 *  This file contains OS abstracted interfaces to common memory operations.
 *-----------------------------------------------------------------------------
 */

#ifndef _OAL_MEMORY_H
#define _OAL_MEMORY_H

#include <linux/slab.h>

unsigned long os_gart_alloc_page( void );
unsigned long os_gart_virt_to_phys( unsigned char *a );
void os_gart_free_page( unsigned char *a );

/* #define INSTRUMENT_KERNEL_ALLOCS */
#ifdef INSTRUMENT_KERNEL_ALLOCS
#define MAX_FUNC_NAME 64

typedef struct _os_allocd_mem {
	void *ptr;
	unsigned int size;
	char function[MAX_FUNC_NAME];
	struct _os_allocd_mem *next;
} os_allocd_mem;

extern os_allocd_mem *list_head;
extern os_allocd_mem *list_tail;

static inline void *_os_alloc(unsigned int size, const char *function) {
	os_allocd_mem *mem;
	void *ptr = kmalloc(size, GFP_KERNEL);
	printk(KERN_DEBUG "%s OS_ALLOC(size=%u)=0x%p\n", function, size, ptr);
	mem = kmalloc(sizeof(os_allocd_mem), GFP_KERNEL);
	if (!ZERO_OR_NULL_PTR(mem)) {
		mem->ptr = ptr;
		mem->size = size;
		strncpy(mem->function, function, MAX_FUNC_NAME);
		mem->function[MAX_FUNC_NAME-1] = '\0';
		mem->next = NULL;
		if (NULL == list_tail) {
			list_head = mem;
		} else {
			list_tail->next = mem;
		}
		list_tail = mem;
	}
	return ptr;
}

static inline void _os_free(void *ptr, const char *function) {
	printk(KERN_DEBUG "%s OS_FREE(0x%p)\n", function, ptr);
	if (NULL != list_head) {
		os_allocd_mem *mem = list_head;
		os_allocd_mem *prev = NULL;
		while (NULL != mem) {
			if (mem->ptr == ptr) {
				if (mem == list_head) {
					list_head = mem->next;
					if (mem == list_tail) {
						list_tail = NULL;
					}
				} else {
					prev->next = mem->next;
					if (mem == list_tail) {
						list_tail = prev;
					}
				}
				kfree(mem);
				break;
			}
			prev = mem;
			mem = mem->next;
		}
	}
	kfree(ptr);
}

static inline void emgd_report_unfreed_memory(void) {
	os_allocd_mem *mem = list_head;
	os_allocd_mem *prev;

	printk(KERN_DEBUG "%s() REPORT ON NON-FREED MEMORY:\n", __FUNCTION__);
	while (NULL != mem) {
		printk(KERN_DEBUG "  addr=0x%p, size=%u, function=\"%s\"\n",
				mem->ptr, mem->size, mem->function);
		prev = mem;
		mem = mem->next;
		kfree(prev);
	}
}


/*!
 * void *OS_ALLOC(size_t size)
 *
 * OS_ALLOC is used by OS independent code to allocate system memory and
 * return a CPU writeable address to the allocated memory (Virtual address)
 * The returned address has no guarenteed alignment.
 * size should be <= 4k for larger sizes use OS_ALLOC_LARGE().
 *
 * Allocations returned from OS_ALLOC() should be freed with OS_FREE().
 *
 * All Full OAL implementations must implement the _OS_ALLOC entry point
 * to enable use of this function.
 *
 * @return NULL on Failure
 * @return Virtual or Flat address on Success
 */
#define OS_ALLOC(a) _os_alloc(a, __FUNCTION__)

/*!
 * void OS_FREE(void *p)
 * OS_FREE should be used to free allocations returned from OS_ALLOC()
 *
 * All Full OAL implementations must implement the _OS_FREE entry point
 * to enable use of this function.
 */
#define OS_FREE(a) _os_free(a, __FUNCTION__)

/*!
 * void *OS_ALLOC_LARGE(size_t size)
 *
 * OS_ALLOC_LARGE is used by OS independent code to allocate system memory
 * in the same manner as OS_ALLOC except that size must be > 4k.
 *
 * Allocations returned from OS_ALLOC_LARGE() should be freed with
 * OS_FREE_LARGE().
 *
 * All Full OAL implementations must implement the _OS_ALLOC_LARGE entry point
 * to enable use of this function. This entry point may be implemented
 * exactly the same as _OS_ALLOC is no diferentiation is required.
 *
 * @return NULL on Failure
 * @return Virtual or Flat address on Success
 */
#define OS_ALLOC_LARGE(a) _os_alloc(a, __FUNCTION__)

/*!
 * void OS_FREE_LARGE(void *p)
 * OS_FREE_LARGE should be used to free allocations returned from
 * OS_ALLOC_LARGE()
 *
 * All Full OAL implementations must implement the _OS_FREE_LARGE entry point
 * to enable use of this function. This entry point may be implemented
 * exactly the same as _OS_FREE is no diferentiation is required.
 *
 */
#define OS_FREE_LARGE(a) _os_free(a, __FUNCTION__)

#else /* INSTRUMENT_KERNEL_ALLOCS */

#define OS_ALLOC(a) kmalloc((a), GFP_KERNEL)
#define OS_FREE(a) kfree(a)
#define OS_ALLOC_LARGE(a) kmalloc((a), GFP_KERNEL)
#define OS_FREE_LARGE(a) kfree(a)

#endif /* INSTRUMENT_KERNEL_ALLOCS */

#define OS_ALLOC_PAGE() NULL
/*!
 * void *OS_VIRT_TO_PHYS( void *p )
 *
 * OS_VIRT_TO_PHYS is used by OS independent code to obtain the physical
 * address referenced by the virtual address p. The virtual address must be
 * one returned by OS_ALLOC_PAGE or OS_ALLOC_CONTIGUOUS.
 *
 * This entry point is OPTIONAL. Only OAL implementations that have
 * implemented the _OS_ALLOC_PAGE or _OS_ALLOC_CONTIGUOUS macros need
 * implement the _OS_VIRT_TO_PHYS macro. OS independent code that must
 * function on all implementation may not use this entry point.
 *
 * @returns Physical Address
 */
#define OS_VIRT_TO_PHYS(a) os_gart_virt_to_phys(a)

/*!
 * void OS_FREE_PAGE(void *p)
 * OS_FREE_PAGE should be used to free allocations returned from
 * OS_ALLOC_PAGE()
 *
 * This entry point is OPTIONAL. Only OAL implementations that have implemented
 * the _OS_ALLOC_PAGE macro need implement the _OS_FREE_PAGE macro.
 */
#define OS_FREE_PAGE(a) os_gart_free_page(a)

#define OS_MEMSET(a,b,c) memset(a,b,c)
#define OS_MEMCPY(a,b,c) memcpy(a,b,c)
#define OS_MEMCMP(a,b,c) memcmp(a,b,c)

#define OS_OFFSETOF(t,m) offsetof(t,m)


/*
 * void *OS_MEMSET(void *s, int c, size_t n)
 *
 * OS_MEMSET sets all bytes of the memory area referenced by address s and
 * size n to the char value c.
 *
 * ALL Full OAL implementations must implement the entry point _OS_MEMSET
 * to enable use of this function.
 *
 * @returns Address s
 */
#ifndef OS_MEMSET
#define OS_MEMSET(a,b,c) _oal_memset(a,b,c)
#endif

/*
 * void *OS_MEMCPY(void *dest, void *src, size_t n)
 *
 * OS_MEMCPY copies n bytes from the memory referenced by src to the
 * memory referenced by dest. The areas may not overlap.
 *
 * ALL Full OAL implementations must implement the entry point _OS_MEMCPY
 * to enable use of this function.
 *
 * @returns Address dest
 */
#ifndef OS_MEMCPY
#define OS_MEMCPY(a,b,c) _oal_memcpy(a,b,c)
#endif

/*
 * void *OS_MEMCMP(void *s1, void *s2, size_t n)
 *
 * OS_MEMCMP compares n bytes from the memory referenced by s1 to the
 * corresponding bytes referenced by s2.
 *
 * This entry point is available in all full OAL implementations. An OAL
 * may implement _OS_MEMCMP macro or the built-in version will be used.
 *
 * @returns < 0 if the s1 value is less than s2
 * @returns > 0 if the s1 value is greater than s2
 * @returns 0 if the values are equal
 */
#ifndef OS_MEMCMP
#define OS_MEMCMP(a,b,c) _oal_memcmp(a,b,c)
#endif


/*
 * void *OS_MEMZERO(void *s, size_t n)
 *
 * OS_MEMZERO sets all bytes of the memory area referenced by address s and
 * size n to 0.
 *
 * This entry point is available in all full OAL implementations. An OAL
 * may implement _OS_MEMZERO macro or the built-in version making use of
 * of _OS_MEMSET will be used.
 *
 * @returns Address s
 */
#ifndef OS_MEMZERO
#define OS_MEMZERO(a,b)  OS_MEMSET(a, 0, b)
#endif

/*
 * void *OS_MEMZERO(void *s, size_t n)
 *
 * OS_MEMZERO sets all bytes of the memory area referenced by address s and
 * size n to 0.
 *
 * This entry point is available in all full OAL implementations. An OAL
 * may implement _OS_MEMZERO macro or the built-in version making use of
 * of _OS_MEMSET will be used.
 *
 * @returns Address s
 */
#ifndef OS_STRNCPY
#define OS_STRNCPY(d, s, n)  _oal_strncpy(d, s, n)
#endif





/*!
 * void *OS_ALLOC_CONTIGUOUS( size_t n, size_t align )
 *
 * OS_ALLOC_CONTIGUOUS is used by OS independent code to allocate a number
 * of aligned system memory pages and return a CPU writeable address to the
 * allocated memory (Virtual address) The returned address must point to
 * physically contiguous memory aligned to the requested alignment.
 *
 * Allocations returned from OS_ALLOC_CONTIGUOUS() should be freed with
 * OS_FREE_CONTIGUOUS().
 *
 * This entry point is OPTIONAL. Only OAL implementations that have the
 * ability to allocate such pages need implement the _OS_ALLOC_CONTIGUOUS
 * macro. OS independent code that must function on all implementation may
 * not use this entry point.
 *
 * @return NULL on Failure
 * @return Virtual or Flat address on Success
 */
#define OS_ALLOC_CONTIGUOUS(a,b) _OS_ALLOC_CONTIGUOUS(a,b)
/*!
 * void OS_FREE_CONTIGUOUS(void *p)
 * OS_FREE_CONTIGUOUS should be used to free allocations returned from
 * OS_ALLOC_CONTIGUOUS()
 *
 * This entry point is OPTIONAL. Only OAL implementations that have implemented
 * the _OS_ALLOC_CONTIGUOUS macro need implement the _OS_FREE_CONTIGUOUS macro.
 */
#define OS_FREE_CONTIGUOUS(a) _OS_FREE_CONTIGUOUS(a)

/*!
 * size_t OS_OFFSETOF(type, member)
 *
 * OS_OFFSETOF is used by OS independent code to obtain the offset of a 
 * given member within a type.
 *
 * @returns size_t of the offset of member m within type t
 */
#ifndef OS_OFFSETOF
#define OS_OFFSETOF(t,m) ((size_t)&(((t *)0)->m))
#endif

/*
 * This is a OS independent helper is case the operating environment
 * does not supply a memcmp() function. The OAL may use this implementation.
 */
static __inline int _oal_memcmp(const void *s1, const void *s2, unsigned long n)
{
	const unsigned char *cs1 = (const unsigned char *) s1;
	const unsigned char *cs2 = (const unsigned char *)s2;

	for ( ; n-- > 0; cs1++, cs2++) {
		if (*cs1 != *cs2) {
			return *cs1 - *cs2;
		}
	}
	return 0;
}

static __inline void *_oal_memcpy(void *dest, const void *src, size_t n)
{
	size_t i;

	i=0;
	while( i < n ) {
		((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
		i++;
	}
	return dest;
}

static __inline char *_oal_strncpy(char *dest, const char *src, size_t n)
{
	size_t i;

	for(i=0; i<n; i++) {
		if(!(dest[i] = src[i])) {
			for(i=i; i<n; i++) {
				dest[i] = '\0';
			}
			return dest;
		}
	}
	return dest;
}

static __inline void *_oal_memset(void *s, int c, size_t n)
{
	unsigned int i;
	for(i=0; i<n; i++) {
		((unsigned char *)s)[i] = (unsigned char)c;
	}
	return s;
}

/*
 * These macros are optional for the OAL port. They are used to do memory
 * management for virtual apterture space process.
 */

#ifdef _OS_MAP_STOLEN_MEM
#define OS_MAP_STOLEN_MEM(a, b, c)        _OS_MAP_STOLEN_MEM(a, b, c)
#else
#define OS_MAP_STOLEN_MEM(a, b, c)        0
#endif

#ifdef _OS_VIRT_APERT_AVAILABLE
#define OS_VIRT_APERT_AVAILABLE()         _OS_VIRT_APERT_AVAILABLE()
#else
#define OS_VIRT_APERT_AVAILABLE()         0
#endif

#ifdef _OS_GET_VIRT_APERT_BASE
#define OS_GET_VIRT_APERT_BASE()          _OS_GET_VIRT_APERT_BASE()
#else
#define OS_GET_VIRT_APERT_BASE()          NULL
#endif

#endif