~gma500/+junk/emgd152-natty

« back to all changes in this revision

Viewing changes to emgd-dkms-1.5.15.3082/pvr/services4/srvkm/env/linux/mmap.c

  • Committer: Luca Forina
  • Date: 2011-02-06 15:11:54 UTC
  • Revision ID: luca.forina@gmail.com-20110206151154-9dzn5ugxjub9qenb
Upload Emgd 1.5.2 for Natty (override Maverick)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************
 
2
 *
 
3
 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
 
4
 * 
 
5
 * This program is free software; you can redistribute it and/or modify it
 
6
 * under the terms and conditions of the GNU General Public License,
 
7
 * version 2, as published by the Free Software Foundation.
 
8
 * 
 
9
 * This program is distributed in the hope it will be useful but, except 
 
10
 * as otherwise stated in writing, without any warranty; without even the 
 
11
 * implied warranty of merchantability or fitness for a particular purpose. 
 
12
 * See the GNU General Public License for more details.
 
13
 * 
 
14
 * You should have received a copy of the GNU General Public License along with
 
15
 * this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 
17
 * 
 
18
 * The full GNU General Public License is included in this distribution in
 
19
 * the file called "COPYING".
 
20
 *
 
21
 * Contact Information:
 
22
 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
 
23
 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
 
24
 *
 
25
 ******************************************************************************/
 
26
 
 
27
#ifndef AUTOCONF_INCLUDED
 
28
 /*#include <linux/config.h>*/
 
29
 #include <generated/autoconf.h>
 
30
#endif
 
31
 
 
32
#include <linux/version.h>
 
33
#include <linux/mm.h>
 
34
#include <linux/module.h>
 
35
#include <linux/vmalloc.h>
 
36
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
 
37
#include <linux/wrapper.h>
 
38
#endif
 
39
#include <linux/slab.h>
 
40
#include <asm/io.h>
 
41
#include <asm/page.h>
 
42
#include <asm/shmparam.h>
 
43
#include <asm/pgtable.h>
 
44
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 
45
#include <linux/sched.h>
 
46
#include <asm/current.h>
 
47
#endif
 
48
#if defined(SUPPORT_DRI_DRM)
 
49
#include <drm/drmP.h>
 
50
#endif
 
51
 
 
52
#include "img_defs.h"
 
53
#include "services.h"
 
54
#include "servicesint.h"
 
55
#include "pvrmmap.h"
 
56
#include "mutils.h"
 
57
#include "mmap.h"
 
58
#include "mm.h"
 
59
#include "pvr_debug.h"
 
60
#include "osfunc.h"
 
61
#include "proc.h"
 
62
#include "mutex.h"
 
63
#include "handle.h"
 
64
#include "perproc.h"
 
65
#include "env_perproc.h"
 
66
#include "bridged_support.h"
 
67
#if defined(SUPPORT_DRI_DRM)
 
68
#include "pvr_drm.h"
 
69
#endif
 
70
 
 
71
#if !defined(PVR_SECURE_HANDLES)
 
72
#error "The mmap code requires PVR_SECURE_HANDLES"
 
73
#endif
 
74
 
 
75
static PVRSRV_LINUX_MUTEX g_sMMapMutex;
 
76
 
 
77
static LinuxKMemCache *g_psMemmapCache = NULL;
 
78
static LIST_HEAD(g_sMMapAreaList);
 
79
static LIST_HEAD(g_sMMapOffsetStructList);
 
80
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
81
static IMG_UINT32 g_ui32RegisteredAreas = 0;
 
82
static IMG_UINT32 g_ui32TotalByteSize = 0;
 
83
#endif
 
84
 
 
85
 
 
86
#if defined(PVR_PROC_USE_SEQ_FILE) && defined(DEBUG_LINUX_MMAP_AREAS)
 
87
static struct proc_dir_entry *g_ProcMMap;
 
88
#endif 
 
89
 
 
90
#define FIRST_PHYSICAL_PFN      0
 
91
#define LAST_PHYSICAL_PFN       0x7fffffffUL
 
92
#define FIRST_SPECIAL_PFN       (LAST_PHYSICAL_PFN + 1)
 
93
#define LAST_SPECIAL_PFN        0xffffffffUL
 
94
 
 
95
#define MAX_MMAP_HANDLE         0x7fffffffUL
 
96
 
 
97
static inline IMG_BOOL
 
98
PFNIsPhysical(IMG_UINT32 pfn)
 
99
{
 
100
         
 
101
        return ((pfn >= FIRST_PHYSICAL_PFN) && (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
 
102
}
 
103
 
 
104
static inline IMG_BOOL
 
105
PFNIsSpecial(IMG_UINT32 pfn)
 
106
{
 
107
         
 
108
        return ((pfn >= FIRST_SPECIAL_PFN) && (pfn <= LAST_SPECIAL_PFN)) ? IMG_TRUE : IMG_FALSE;
 
109
}
 
110
 
 
111
static inline IMG_HANDLE
 
112
MMapOffsetToHandle(IMG_UINT32 pfn)
 
113
{
 
114
        if (PFNIsPhysical(pfn))
 
115
        {
 
116
                PVR_ASSERT(PFNIsPhysical(pfn));
 
117
                return IMG_NULL;
 
118
        }
 
119
 
 
120
        return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
 
121
}
 
122
 
 
123
static inline IMG_UINT32
 
124
HandleToMMapOffset(IMG_HANDLE hHandle)
 
125
{
 
126
        IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
 
127
 
 
128
        if (PFNIsSpecial(ulHandle))
 
129
        {
 
130
                PVR_ASSERT(PFNIsSpecial(ulHandle));
 
131
                return 0;
 
132
        }
 
133
 
 
134
        return ulHandle + FIRST_SPECIAL_PFN;
 
135
}
 
136
 
 
137
static inline IMG_BOOL
 
138
LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
 
139
{
 
140
    return LinuxMemAreaPhysIsContig(psLinuxMemArea);
 
141
}
 
142
 
 
143
static inline IMG_UINT32
 
144
GetCurrentThreadID(IMG_VOID)
 
145
{
 
146
        
 
147
        return (IMG_UINT32)current->pid;
 
148
}
 
149
 
 
150
static PKV_OFFSET_STRUCT
 
151
CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
 
152
{
 
153
    PKV_OFFSET_STRUCT psOffsetStruct;
 
154
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
 
155
    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
 
156
#endif
 
157
 
 
158
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
 
159
    PVR_DPF((PVR_DBG_MESSAGE,
 
160
             "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)",
 
161
             __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
 
162
#endif
 
163
 
 
164
    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
 
165
 
 
166
    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
 
167
 
 
168
    psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
 
169
    if(psOffsetStruct == IMG_NULL)
 
170
    {
 
171
        PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
 
172
        return IMG_NULL;
 
173
    }
 
174
    
 
175
    psOffsetStruct->ui32MMapOffset = ui32Offset;
 
176
 
 
177
    psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
 
178
 
 
179
    psOffsetStruct->ui32Mapped = 0;
 
180
 
 
181
    psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
 
182
 
 
183
    
 
184
    psOffsetStruct->ui32TID = GetCurrentThreadID();
 
185
 
 
186
    psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
 
187
 
 
188
    psOffsetStruct->bOnMMapList = IMG_FALSE;
 
189
 
 
190
    psOffsetStruct->ui32RefCount = 0;
 
191
 
 
192
    psOffsetStruct->ui32UserVAddr = 0;
 
193
 
 
194
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
195
    
 
196
    psOffsetStruct->pszName = pszName;
 
197
#endif
 
198
 
 
199
    list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
 
200
 
 
201
    return psOffsetStruct;
 
202
}
 
203
 
 
204
 
 
205
static IMG_VOID
 
206
DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
 
207
{
 
208
    list_del(&psOffsetStruct->sAreaItem);
 
209
 
 
210
    if (psOffsetStruct->bOnMMapList)
 
211
    {
 
212
        list_del(&psOffsetStruct->sMMapItem);
 
213
    }
 
214
 
 
215
    PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
 
216
             "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__,
 
217
             psOffsetStruct->psLinuxMemArea,
 
218
             LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0)));
 
219
    
 
220
    KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
 
221
}
 
222
 
 
223
 
 
224
static inline IMG_VOID
 
225
DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
 
226
                               IMG_UINT32 *pui32RealByteSize,
 
227
                               IMG_UINT32 *pui32ByteOffset)
 
228
{
 
229
    IMG_UINT32 ui32PageAlignmentOffset;
 
230
    IMG_CPU_PHYADDR CpuPAddr;
 
231
    
 
232
    CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
 
233
    ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
 
234
    
 
235
    *pui32ByteOffset = ui32PageAlignmentOffset;
 
236
 
 
237
    *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
 
238
}
 
239
 
 
240
 
 
241
PVRSRV_ERROR
 
242
PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
 
243
                                IMG_HANDLE hMHandle,
 
244
                                IMG_UINT32 *pui32MMapOffset,
 
245
                                IMG_UINT32 *pui32ByteOffset,
 
246
                                IMG_UINT32 *pui32RealByteSize,
 
247
                                IMG_UINT32 *pui32UserVAddr)
 
248
{
 
249
    LinuxMemArea *psLinuxMemArea;
 
250
    PKV_OFFSET_STRUCT psOffsetStruct;
 
251
    IMG_HANDLE hOSMemHandle;
 
252
    PVRSRV_ERROR eError;
 
253
 
 
254
    LinuxLockMutex(&g_sMMapMutex);
 
255
 
 
256
    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
 
257
 
 
258
    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
 
259
    if (eError != PVRSRV_OK)
 
260
    {
 
261
        PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
 
262
 
 
263
        goto exit_unlock;
 
264
    }
 
265
 
 
266
    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
 
267
 
 
268
    DetermineUsersSizeAndByteOffset(psLinuxMemArea,
 
269
                                   pui32RealByteSize,
 
270
                                   pui32ByteOffset);
 
271
 
 
272
    
 
273
    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
 
274
    {
 
275
        if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
 
276
        {
 
277
 
 
278
           PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
 
279
           
 
280
           *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
 
281
           *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
 
282
           psOffsetStruct->ui32RefCount++;
 
283
 
 
284
           eError = PVRSRV_OK;
 
285
           goto exit_unlock;
 
286
        }
 
287
    }
 
288
 
 
289
    
 
290
    *pui32UserVAddr = 0;
 
291
 
 
292
    if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
 
293
    {
 
294
        *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
 
295
        PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
 
296
    }
 
297
    else
 
298
    {
 
299
        *pui32MMapOffset = HandleToMMapOffset(hMHandle);
 
300
        PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
 
301
    }
 
302
 
 
303
    psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
 
304
    if (psOffsetStruct == IMG_NULL)
 
305
    {
 
306
        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
 
307
        goto exit_unlock;
 
308
    }
 
309
 
 
310
    
 
311
    list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
 
312
 
 
313
    psOffsetStruct->bOnMMapList = IMG_TRUE;
 
314
 
 
315
    psOffsetStruct->ui32RefCount++;
 
316
 
 
317
    eError = PVRSRV_OK;
 
318
 
 
319
exit_unlock:
 
320
    LinuxUnLockMutex(&g_sMMapMutex);
 
321
 
 
322
    return eError;
 
323
}
 
324
 
 
325
 
 
326
PVRSRV_ERROR
 
327
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
 
328
                                IMG_HANDLE hMHandle,
 
329
                                IMG_BOOL *pbMUnmap,
 
330
                                IMG_UINT32 *pui32RealByteSize,
 
331
                                IMG_UINT32 *pui32UserVAddr)
 
332
{
 
333
    LinuxMemArea *psLinuxMemArea;
 
334
    PKV_OFFSET_STRUCT psOffsetStruct;
 
335
    IMG_HANDLE hOSMemHandle;
 
336
    PVRSRV_ERROR eError;
 
337
    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
 
338
 
 
339
    LinuxLockMutex(&g_sMMapMutex);
 
340
 
 
341
    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
 
342
 
 
343
    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
 
344
    if (eError != PVRSRV_OK)
 
345
    {
 
346
        PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
 
347
 
 
348
        goto exit_unlock;
 
349
    }
 
350
 
 
351
    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
 
352
 
 
353
    
 
354
    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
 
355
    {
 
356
        if (psOffsetStruct->ui32PID == ui32PID)
 
357
        {
 
358
            if (psOffsetStruct->ui32RefCount == 0)
 
359
            {
 
360
                PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area 0x%p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
 
361
                eError = PVRSRV_ERROR_GENERIC;
 
362
                goto exit_unlock;
 
363
            }
 
364
 
 
365
            psOffsetStruct->ui32RefCount--;
 
366
 
 
367
            *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
 
368
 
 
369
            *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
 
370
            *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
 
371
 
 
372
            eError = PVRSRV_OK;
 
373
            goto exit_unlock;
 
374
        }
 
375
    }
 
376
 
 
377
    
 
378
    PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle 0x%lx (memory area 0x%p)", __FUNCTION__, hMHandle, psLinuxMemArea));
 
379
 
 
380
    eError =  PVRSRV_ERROR_GENERIC;
 
381
 
 
382
exit_unlock:
 
383
    LinuxUnLockMutex(&g_sMMapMutex);
 
384
 
 
385
    return eError;
 
386
}
 
387
 
 
388
static inline PKV_OFFSET_STRUCT
 
389
FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
 
390
{
 
391
    PKV_OFFSET_STRUCT psOffsetStruct;
 
392
    IMG_UINT32 ui32TID = GetCurrentThreadID();
 
393
    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
 
394
 
 
395
    list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
 
396
    {
 
397
        if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
 
398
        {
 
399
            
 
400
            if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
 
401
            {
 
402
                return psOffsetStruct;
 
403
            }
 
404
        }
 
405
    }
 
406
 
 
407
    return IMG_NULL;
 
408
}
 
409
 
 
410
 
 
411
static IMG_BOOL
 
412
DoMapToUser(LinuxMemArea *psLinuxMemArea,
 
413
            struct vm_area_struct* ps_vma,
 
414
            IMG_UINT32 ui32ByteOffset)
 
415
{
 
416
    IMG_UINT32 ui32ByteSize;
 
417
 
 
418
    if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
 
419
    {
 
420
        return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),             
 
421
                    ps_vma,
 
422
                    psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
 
423
    }
 
424
 
 
425
    
 
426
    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
 
427
    PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
 
428
 
 
429
#if defined (__sparc__)
 
430
    
 
431
#error "SPARC not supported"
 
432
#endif
 
433
 
 
434
    if (PFNIsPhysical(ps_vma->vm_pgoff))
 
435
    {
 
436
        IMG_INT result;
 
437
 
 
438
        PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
 
439
        PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
 
440
 
 
441
        
 
442
        result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
 
443
 
 
444
        if(result == 0)
 
445
        {
 
446
            return IMG_TRUE;
 
447
        }
 
448
 
 
449
        PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
 
450
    }
 
451
 
 
452
    {
 
453
        
 
454
        IMG_UINT32 ulVMAPos;
 
455
        IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
 
456
        IMG_UINT32 ui32PA;
 
457
 
 
458
        
 
459
        for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
 
460
        {
 
461
            IMG_UINT32 pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
 
462
 
 
463
            if (!pfn_valid(pfn))
 
464
            {
 
465
                PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%lx", __FUNCTION__, pfn));
 
466
                return IMG_FALSE;
 
467
            }
 
468
        }
 
469
 
 
470
        
 
471
        ulVMAPos = ps_vma->vm_start;
 
472
        for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
 
473
        {
 
474
            IMG_UINT32 pfn;
 
475
            struct page *psPage;
 
476
            IMG_INT result;
 
477
 
 
478
            pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
 
479
            PVR_ASSERT(pfn_valid(pfn));
 
480
 
 
481
            psPage = pfn_to_page(pfn);
 
482
 
 
483
            result = VM_INSERT_PAGE(ps_vma,  ulVMAPos, psPage);
 
484
            if(result != 0)
 
485
            {
 
486
                PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
 
487
                return IMG_FALSE;
 
488
            }
 
489
            ulVMAPos += PAGE_SIZE;
 
490
        }
 
491
    }
 
492
 
 
493
    return IMG_TRUE;
 
494
}
 
495
 
 
496
 
 
497
static IMG_VOID
 
498
MMapVOpenNoLock(struct vm_area_struct* ps_vma)
 
499
{
 
500
    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
 
501
    PVR_ASSERT(psOffsetStruct != IMG_NULL)
 
502
    psOffsetStruct->ui32Mapped++;
 
503
    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
 
504
 
 
505
    if (psOffsetStruct->ui32Mapped > 1)
 
506
    {
 
507
        PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %lu)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
 
508
        PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
 
509
    }
 
510
 
 
511
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
512
 
 
513
    PVR_DPF((PVR_DBG_MESSAGE,
 
514
             "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %ld, ui32Mapped %d",
 
515
             __FUNCTION__,
 
516
             psOffsetStruct->psLinuxMemArea,
 
517
             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
 
518
             psOffsetStruct->ui32MMapOffset,
 
519
             psOffsetStruct->ui32Mapped));
 
520
#endif
 
521
 
 
522
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
 
523
    MOD_INC_USE_COUNT;
 
524
#endif
 
525
}
 
526
 
 
527
 
 
528
static void
 
529
MMapVOpen(struct vm_area_struct* ps_vma)
 
530
{
 
531
    LinuxLockMutex(&g_sMMapMutex);
 
532
 
 
533
    MMapVOpenNoLock(ps_vma);
 
534
 
 
535
    LinuxUnLockMutex(&g_sMMapMutex);
 
536
}
 
537
 
 
538
 
 
539
static IMG_VOID
 
540
MMapVCloseNoLock(struct vm_area_struct* ps_vma)
 
541
{
 
542
    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
 
543
    PVR_ASSERT(psOffsetStruct != IMG_NULL)
 
544
 
 
545
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
546
    PVR_DPF((PVR_DBG_MESSAGE,
 
547
             "%s: psLinuxMemArea 0x%p, CpuVAddr 0x%p ui32MMapOffset %ld, ui32Mapped %d",
 
548
             __FUNCTION__,
 
549
             psOffsetStruct->psLinuxMemArea,
 
550
             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
 
551
             psOffsetStruct->ui32MMapOffset,
 
552
             psOffsetStruct->ui32Mapped));
 
553
#endif
 
554
 
 
555
    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
 
556
    psOffsetStruct->ui32Mapped--;
 
557
    if (psOffsetStruct->ui32Mapped == 0)
 
558
    {
 
559
        if (psOffsetStruct->ui32RefCount != 0)
 
560
        {
 
561
                PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct 0x%p has non-zero reference count (ui32RefCount = %lu). User mode address of start of mapping: 0x%lx", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
 
562
        }
 
563
 
 
564
        DestroyOffsetStruct(psOffsetStruct);
 
565
    }
 
566
 
 
567
    ps_vma->vm_private_data = NULL;
 
568
 
 
569
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
 
570
    MOD_DEC_USE_COUNT;
 
571
#endif
 
572
}
 
573
 
 
574
static void
 
575
MMapVClose(struct vm_area_struct* ps_vma)
 
576
{
 
577
    LinuxLockMutex(&g_sMMapMutex);
 
578
 
 
579
    MMapVCloseNoLock(ps_vma);
 
580
 
 
581
    LinuxUnLockMutex(&g_sMMapMutex);
 
582
}
 
583
 
 
584
 
 
585
static struct vm_operations_struct MMapIOOps =
 
586
{
 
587
        .open=MMapVOpen,
 
588
        .close=MMapVClose
 
589
};
 
590
 
 
591
 
 
592
int
 
593
PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
 
594
{
 
595
    IMG_UINT32 ui32ByteSize;
 
596
    PKV_OFFSET_STRUCT psOffsetStruct;
 
597
    int iRetVal = 0;
 
598
 
 
599
    PVR_UNREFERENCED_PARAMETER(pFile);
 
600
 
 
601
    LinuxLockMutex(&g_sMMapMutex);
 
602
    
 
603
    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
 
604
    
 
605
 
 
606
    PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
 
607
                              " and ui32ByteSize %ld(0x%08lx)",
 
608
            __FUNCTION__,
 
609
            ps_vma->vm_pgoff,
 
610
            ui32ByteSize, ui32ByteSize));
 
611
 
 
612
    psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
 
613
    if (psOffsetStruct == IMG_NULL)
 
614
    {
 
615
#if defined(SUPPORT_DRI_DRM)
 
616
        LinuxUnLockMutex(&g_sMMapMutex);
 
617
 
 
618
        
 
619
        return drm_mmap(pFile, ps_vma);
 
620
#else
 
621
        PVR_UNREFERENCED_PARAMETER(pFile);
 
622
 
 
623
#if 0 /* FIXME: crash when call to print debug messages */
 
624
        PVR_DPF((PVR_DBG_ERROR,
 
625
             "%s: Attempted to mmap unregistered area at vm_pgoff %ld",
 
626
             __FUNCTION__, ps_vma->vm_pgoff));
 
627
#endif
 
628
        iRetVal = -EINVAL;
 
629
#endif
 
630
        goto unlock_and_return;
 
631
    }
 
632
    list_del(&psOffsetStruct->sMMapItem);
 
633
    psOffsetStruct->bOnMMapList = IMG_FALSE;
 
634
 
 
635
    
 
636
    if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
 
637
        ((ps_vma->vm_flags & VM_SHARED) == 0))
 
638
    {
 
639
#if 0 /* FIXME: crash when call to print debug messages */
 
640
        PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
 
641
#endif
 
642
        iRetVal = -EINVAL;
 
643
        goto unlock_and_return;
 
644
    }
 
645
   
 
646
 
 
647
#if 0 /* FIXME: crash when call to print debug messages */
 
648
    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
 
649
         __FUNCTION__, psOffsetStruct->psLinuxMemArea));
 
650
#endif
 
651
    ps_vma->vm_flags |= VM_RESERVED;
 
652
    ps_vma->vm_flags |= VM_IO;
 
653
 
 
654
    
 
655
    ps_vma->vm_flags |= VM_DONTEXPAND;
 
656
    
 
657
    
 
658
    ps_vma->vm_flags |= VM_DONTCOPY;
 
659
 
 
660
    ps_vma->vm_private_data = (void *)psOffsetStruct;
 
661
    
 
662
    switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
 
663
    {
 
664
        case PVRSRV_HAP_CACHED:
 
665
            
 
666
            break;
 
667
        case PVRSRV_HAP_WRITECOMBINE:
 
668
            ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
 
669
            break;
 
670
        case PVRSRV_HAP_UNCACHED:
 
671
            ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
 
672
            break;
 
673
        default:
 
674
            PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
 
675
            iRetVal = -EINVAL;
 
676
            goto unlock_and_return;
 
677
    }
 
678
    
 
679
    
 
680
    ps_vma->vm_ops = &MMapIOOps;
 
681
    
 
682
    if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
 
683
    {
 
684
        iRetVal = -EAGAIN;
 
685
        goto unlock_and_return;
 
686
    }
 
687
    
 
688
    PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
 
689
 
 
690
    psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
 
691
 
 
692
    
 
693
    MMapVOpenNoLock(ps_vma);
 
694
 
 
695
#if 0 /* FIXME: crash when call to print debug messages */
 
696
    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
 
697
             __FUNCTION__, ps_vma->vm_pgoff));
 
698
#endif
 
699
   
 
700
unlock_and_return:
 
701
    if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
 
702
    {
 
703
        DestroyOffsetStruct(psOffsetStruct);
 
704
    }
 
705
 
 
706
    LinuxUnLockMutex(&g_sMMapMutex);
 
707
    
 
708
    return iRetVal;
 
709
}
 
710
 
 
711
 
 
712
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
713
 
 
714
#ifdef PVR_PROC_USE_SEQ_FILE
 
715
 
 
716
static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start) 
 
717
{
 
718
        if(start) 
 
719
        {
 
720
            LinuxLockMutex(&g_sMMapMutex);              
 
721
        }
 
722
        else
 
723
        {
 
724
            LinuxUnLockMutex(&g_sMMapMutex);
 
725
        }
 
726
}
 
727
 
 
728
 
 
729
static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
 
730
{
 
731
    LinuxMemArea *psLinuxMemArea;
 
732
        if(!off) 
 
733
        {
 
734
                return PVR_PROC_SEQ_START_TOKEN;
 
735
        }
 
736
 
 
737
    list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
 
738
    {
 
739
        PKV_OFFSET_STRUCT psOffsetStruct;
 
740
 
 
741
                list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
 
742
        {
 
743
                off--;
 
744
                if (off == 0)
 
745
                {                               
 
746
                                PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
 
747
                                return (void*)psOffsetStruct;
 
748
                    }
 
749
        }
 
750
    }
 
751
        return (void*)0;
 
752
}
 
753
 
 
754
static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
 
755
{
 
756
        return ProcSeqOff2ElementMMapRegistrations(sfile,off);
 
757
}
 
758
 
 
759
 
 
760
static void ProcSeqShowMMapRegistrations(struct seq_file *sfile,void* el)
 
761
{
 
762
        KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
 
763
    LinuxMemArea *psLinuxMemArea;
 
764
        IMG_UINT32 ui32RealByteSize;
 
765
        IMG_UINT32 ui32ByteOffset;
 
766
 
 
767
        if(el == PVR_PROC_SEQ_START_TOKEN) 
 
768
        {
 
769
        seq_printf( sfile,
 
770
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
 
771
                                                  "Allocations registered for mmap: %lu\n"
 
772
                          "In total these areas correspond to %lu bytes\n"
 
773
                          "psLinuxMemArea "
 
774
                                                  "UserVAddr "
 
775
                                                  "KernelVAddr "
 
776
                                                  "CpuPAddr "
 
777
                          "MMapOffset "
 
778
                          "ByteLength "
 
779
                          "LinuxMemType             "
 
780
                                                  "Pid   Name     Flags\n",
 
781
#else
 
782
                          "<mmap_header>\n"
 
783
                          "\t<count>%lu</count>\n"
 
784
                          "\t<bytes>%lu</bytes>\n"
 
785
                          "</mmap_header>\n",
 
786
#endif
 
787
                                                  g_ui32RegisteredAreas,
 
788
                          g_ui32TotalByteSize
 
789
                          );
 
790
                return;
 
791
        }
 
792
 
 
793
        psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
 
794
 
 
795
        DetermineUsersSizeAndByteOffset(psLinuxMemArea,
 
796
                                                                        &ui32RealByteSize,
 
797
                                                                        &ui32ByteOffset);
 
798
 
 
799
        seq_printf( sfile,
 
800
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
 
801
                                                "%-8p       %08lx %-8p %08lx %08lx   %-8ld   %-24s %-5lu %-8s %08lx(%s)\n",
 
802
#else
 
803
                        "<mmap_record>\n"
 
804
                                                "\t<pointer>%-8p</pointer>\n"
 
805
                        "\t<user_virtual>%-8lx</user_virtual>\n"
 
806
                        "\t<kernel_virtual>%-8p</kernel_virtual>\n"
 
807
                        "\t<cpu_physical>%08lx</cpu_physical>\n"
 
808
                        "\t<mmap_offset>%08lx</mmap_offset>\n"
 
809
                        "\t<bytes>%-8ld</bytes>\n"
 
810
                        "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
 
811
                        "\t<pid>%-5lu</pid>\n"
 
812
                        "\t<name>%-8s</name>\n"
 
813
                        "\t<flags>%08lx</flags>\n"
 
814
                        "\t<flags_string>%s</flags_string>\n"
 
815
                        "</mmap_record>\n",
 
816
#endif
 
817
                        psLinuxMemArea,
 
818
                                                psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
 
819
                                                LinuxMemAreaToCpuVAddr(psLinuxMemArea),
 
820
                        LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
 
821
                                                psOffsetStruct->ui32MMapOffset,
 
822
                                                psLinuxMemArea->ui32ByteSize,
 
823
                        LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
 
824
                                                psOffsetStruct->ui32PID,
 
825
                                                psOffsetStruct->pszName,
 
826
                                                psLinuxMemArea->ui32AreaFlags,
 
827
                        HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
 
828
}
 
829
 
 
830
#else 
 
831
 
 
832
static off_t
 
833
PrintMMapRegistrations(IMG_CHAR *buffer, size_t size, off_t off)
 
834
{
 
835
    LinuxMemArea *psLinuxMemArea;
 
836
    off_t Ret;
 
837
        
 
838
    LinuxLockMutex(&g_sMMapMutex);
 
839
 
 
840
    if(!off)
 
841
    {
 
842
                Ret = printAppend(buffer, size, 0,
 
843
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
 
844
                                                  "Allocations registered for mmap: %lu\n"
 
845
                          "In total these areas correspond to %lu bytes\n"
 
846
                          "psLinuxMemArea "
 
847
                                                  "UserVAddr "
 
848
                                                  "KernelVAddr "
 
849
                                                  "CpuPAddr "
 
850
                          "MMapOffset "
 
851
                          "ByteLength "
 
852
                          "LinuxMemType             "
 
853
                                                  "Pid   Name     Flags\n",
 
854
#else
 
855
                          "<mmap_header>\n"
 
856
                          "\t<count>%lu</count>\n"
 
857
                          "\t<bytes>%lu</bytes>\n"
 
858
                          "</mmap_header>\n",
 
859
#endif
 
860
                                                  g_ui32RegisteredAreas,
 
861
                          g_ui32TotalByteSize
 
862
                          );
 
863
 
 
864
        goto unlock_and_return;
 
865
    }
 
866
 
 
867
    if (size < 135) 
 
868
    {
 
869
                Ret = 0;
 
870
        goto unlock_and_return;
 
871
    }
 
872
        
 
873
    PVR_ASSERT(off != 0);
 
874
    list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
 
875
    {
 
876
        PKV_OFFSET_STRUCT psOffsetStruct;
 
877
 
 
878
        list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
 
879
        {
 
880
            off--;
 
881
            if (off == 0)
 
882
            {
 
883
                IMG_UINT32 ui32RealByteSize;
 
884
                IMG_UINT32 ui32ByteOffset;
 
885
 
 
886
                PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
 
887
 
 
888
                DetermineUsersSizeAndByteOffset(psLinuxMemArea,
 
889
                                   &ui32RealByteSize,
 
890
                                   &ui32ByteOffset);
 
891
 
 
892
                Ret =  printAppend (buffer, size, 0,
 
893
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
 
894
                                                "%-8p       %08lx %-8p %08lx %08lx   %-8ld   %-24s %-5lu %-8s %08lx(%s)\n",
 
895
#else
 
896
                        "<mmap_record>\n"
 
897
                                                "\t<pointer>%-8p</pointer>\n"
 
898
                        "\t<user_virtual>%-8lx</user_virtual>\n"
 
899
                        "\t<kernel_virtual>%-8p</kernel_virtual>\n"
 
900
                        "\t<cpu_physical>%08lx</cpu_physical>\n"
 
901
                        "\t<mmap_offset>%08lx</mmap_offset>\n"
 
902
                        "\t<bytes>%-8ld</bytes>\n"
 
903
                        "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
 
904
                        "\t<pid>%-5lu</pid>\n"
 
905
                        "\t<name>%-8s</name>\n"
 
906
                        "\t<flags>%08lx</flags>\n"
 
907
                        "\t<flags_string>%s</flags_string>\n"
 
908
                        "</mmap_record>\n",
 
909
#endif
 
910
                        psLinuxMemArea,
 
911
                        psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
 
912
                                                LinuxMemAreaToCpuVAddr(psLinuxMemArea),
 
913
                        LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
 
914
                                                psOffsetStruct->ui32MMapOffset,
 
915
                                                psLinuxMemArea->ui32ByteSize,
 
916
                        LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
 
917
                                                psOffsetStruct->ui32PID,
 
918
                                                psOffsetStruct->pszName,
 
919
                                                psLinuxMemArea->ui32AreaFlags,
 
920
                        HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
 
921
                goto unlock_and_return;
 
922
            }
 
923
        }
 
924
    }
 
925
    Ret = END_OF_FILE;
 
926
 
 
927
unlock_and_return:
 
928
    LinuxUnLockMutex(&g_sMMapMutex);
 
929
    return Ret;
 
930
}
 
931
#endif 
 
932
#endif
 
933
 
 
934
 
 
935
PVRSRV_ERROR
 
936
PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
 
937
{
 
938
    PVRSRV_ERROR eError;
 
939
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
 
940
    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
 
941
#endif
 
942
 
 
943
    LinuxLockMutex(&g_sMMapMutex);
 
944
 
 
945
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
 
946
    PVR_DPF((PVR_DBG_MESSAGE,
 
947
             "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)",
 
948
             __FUNCTION__, pszName, psLinuxMemArea,  psLinuxMemArea->ui32AreaFlags));
 
949
#endif
 
950
 
 
951
    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
 
952
 
 
953
    
 
954
    if(psLinuxMemArea->bMMapRegistered)
 
955
    {
 
956
        PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
 
957
                __FUNCTION__, psLinuxMemArea));
 
958
        eError = PVRSRV_ERROR_INVALID_PARAMS;
 
959
        goto exit_unlock;
 
960
    }
 
961
 
 
962
    list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
 
963
 
 
964
    psLinuxMemArea->bMMapRegistered = IMG_TRUE;
 
965
 
 
966
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
967
    g_ui32RegisteredAreas++;
 
968
    
 
969
    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
 
970
    {
 
971
        g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
 
972
    }
 
973
#endif
 
974
 
 
975
    eError = PVRSRV_OK;
 
976
 
 
977
exit_unlock:
 
978
    LinuxUnLockMutex(&g_sMMapMutex);
 
979
 
 
980
    return eError;
 
981
}
 
982
 
 
983
 
 
984
PVRSRV_ERROR
 
985
PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
 
986
{
 
987
    PVRSRV_ERROR eError;
 
988
    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
 
989
 
 
990
    LinuxLockMutex(&g_sMMapMutex);
 
991
 
 
992
    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
 
993
 
 
994
    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
 
995
    {
 
996
        if (psOffsetStruct->ui32Mapped != 0)
 
997
        {
 
998
             PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %lu",  __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
 
999
                eError = PVRSRV_ERROR_GENERIC;
 
1000
                goto exit_unlock;
 
1001
        }
 
1002
        else
 
1003
        {
 
1004
              
 
1005
             PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped",  __FUNCTION__, psOffsetStruct));
 
1006
        }
 
1007
 
 
1008
        PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
 
1009
 
 
1010
        DestroyOffsetStruct(psOffsetStruct);
 
1011
    }
 
1012
 
 
1013
    list_del(&psLinuxMemArea->sMMapItem);
 
1014
 
 
1015
    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
 
1016
 
 
1017
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
1018
    g_ui32RegisteredAreas--;
 
1019
    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
 
1020
    {
 
1021
        g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
 
1022
    }
 
1023
#endif
 
1024
 
 
1025
    eError = PVRSRV_OK;
 
1026
 
 
1027
exit_unlock:
 
1028
    LinuxUnLockMutex(&g_sMMapMutex);
 
1029
    return eError;
 
1030
}
 
1031
 
 
1032
 
 
1033
PVRSRV_ERROR
 
1034
LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
 
1035
{
 
1036
    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
 
1037
 
 
1038
    return PVRSRV_OK;
 
1039
}
 
1040
 
 
1041
IMG_VOID
 
1042
LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
 
1043
{
 
1044
    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
 
1045
    IMG_BOOL bWarn = IMG_FALSE;
 
1046
    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
 
1047
 
 
1048
    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
 
1049
 
 
1050
    LinuxLockMutex(&g_sMMapMutex);
 
1051
 
 
1052
    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
 
1053
    {
 
1054
        if (psOffsetStruct->ui32PID == ui32PID)
 
1055
        {
 
1056
            if (!bWarn)
 
1057
            {
 
1058
                PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
 
1059
                bWarn = IMG_TRUE;
 
1060
            }
 
1061
            PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
 
1062
            PVR_ASSERT(psOffsetStruct->bOnMMapList);
 
1063
 
 
1064
            DestroyOffsetStruct(psOffsetStruct);
 
1065
        }
 
1066
    }
 
1067
 
 
1068
    LinuxUnLockMutex(&g_sMMapMutex);
 
1069
}
 
1070
 
 
1071
 
 
1072
PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
 
1073
{
 
1074
    PVRSRV_ERROR eError;
 
1075
 
 
1076
    eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
 
1077
    if (eError != PVRSRV_OK)
 
1078
    {
 
1079
        PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
 
1080
        return eError;
 
1081
    }
 
1082
 
 
1083
    return eError;
 
1084
}
 
1085
 
 
1086
 
 
1087
IMG_VOID
 
1088
PVRMMapInit(IMG_VOID)
 
1089
{
 
1090
    LinuxInitMutex(&g_sMMapMutex);
 
1091
 
 
1092
    g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
 
1093
    if (!g_psMemmapCache)
 
1094
    {
 
1095
        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
 
1096
        goto error;
 
1097
    }
 
1098
 
 
1099
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
1100
#ifdef PVR_PROC_USE_SEQ_FILE
 
1101
        g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL, 
 
1102
                                                  ProcSeqNextMMapRegistrations,
 
1103
                                                  ProcSeqShowMMapRegistrations,
 
1104
                                                  ProcSeqOff2ElementMMapRegistrations,
 
1105
                                                  ProcSeqStartstopMMapRegistations
 
1106
                                                 );
 
1107
#else  
 
1108
    CreateProcReadEntry("mmap", PrintMMapRegistrations);
 
1109
#endif    
 
1110
#endif  
 
1111
    return;
 
1112
 
 
1113
error:
 
1114
    PVRMMapCleanup();
 
1115
    return;
 
1116
}
 
1117
 
 
1118
 
 
1119
IMG_VOID
 
1120
PVRMMapCleanup(IMG_VOID)
 
1121
{
 
1122
    PVRSRV_ERROR eError;
 
1123
 
 
1124
    if (!list_empty(&g_sMMapAreaList))
 
1125
    {
 
1126
        LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
 
1127
 
 
1128
        PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
 
1129
        
 
1130
        PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
 
1131
        list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
 
1132
        {
 
1133
                eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
 
1134
                if (eError != PVRSRV_OK)
 
1135
                {
 
1136
                        PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
 
1137
                }
 
1138
                PVR_ASSERT(eError == PVRSRV_OK);
 
1139
 
 
1140
                LinuxMemAreaDeepFree(psLinuxMemArea);
 
1141
        }
 
1142
    }
 
1143
    PVR_ASSERT(list_empty((&g_sMMapAreaList)));
 
1144
 
 
1145
#if defined(DEBUG_LINUX_MMAP_AREAS)
 
1146
#ifdef PVR_PROC_USE_SEQ_FILE
 
1147
    RemoveProcEntrySeq(g_ProcMMap);
 
1148
#else
 
1149
    RemoveProcEntry("mmap");
 
1150
#endif 
 
1151
#endif 
 
1152
 
 
1153
    if(g_psMemmapCache)
 
1154
    {
 
1155
        KMemCacheDestroyWrapper(g_psMemmapCache);
 
1156
        g_psMemmapCache = NULL;
 
1157
    }
 
1158
}