1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
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.
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.
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.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
27 #include <linux/version.h>
30 #include <asm/system.h>
32 #include <linux/pagemap.h>
33 #include <linux/hugetlb.h>
34 #include <linux/slab.h>
35 #include <linux/vmalloc.h>
36 #include <linux/delay.h>
37 #include <linux/pci.h>
39 #include <linux/string.h>
40 #include <linux/sched.h>
41 #include <linux/interrupt.h>
42 #include <linux/hardirq.h>
43 #include <linux/timer.h>
44 #include <linux/capability.h>
45 #include <linux/uaccess.h>
46 #include <linux/spinlock.h>
48 #include "img_types.h"
49 #include "services_headers.h"
57 #define EVENT_OBJECT_TIMEOUT_MS (100)
59 #define HOST_ALLOC_MEM_USING_KMALLOC ((void *)0)
60 #define HOST_ALLOC_MEM_USING_VMALLOC ((void *)1)
62 #define LINUX_KMALLOC_LIMIT PAGE_SIZE /* 4k */
64 #if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
65 enum PVRSRV_ERROR OSAllocMem(u32 ui32Flags, u32 ui32Size,
66 void **ppvCpuVAddr, void **phBlockAlloc)
68 enum PVRSRV_ERROR _OSAllocMem(u32 ui32Flags, u32 ui32Size,
69 void **ppvCpuVAddr, void **phBlockAlloc,
70 char *pszFilename, u32 ui32Line)
75 PVR_UNREFERENCED_PARAMETER(ui32Flags);
77 /* determine whether to go straight to vmalloc */
78 ui32Threshold = LINUX_KMALLOC_LIMIT;
80 if (ui32Size > ui32Threshold) {
81 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
82 *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED,
83 pszFilename, ui32Line);
85 *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
88 return PVRSRV_ERROR_OUT_OF_MEMORY;
91 *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
93 /* default - try kmalloc first */
95 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
96 *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
98 *ppvCpuVAddr = KMallocWrapper(ui32Size);
102 return PVRSRV_ERROR_OUT_OF_MEMORY;
105 *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
112 #if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
113 void OSFreeMem(u32 ui32Flags, u32 ui32Size, void *pvCpuVAddr, void *hBlockAlloc)
115 void _OSFreeMem(u32 ui32Flags, u32 ui32Size, void *pvCpuVAddr,
116 void *hBlockAlloc, char *pszFilename, u32 ui32Line)
119 PVR_UNREFERENCED_PARAMETER(ui32Flags);
121 if (ui32Size > LINUX_KMALLOC_LIMIT) {
122 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
123 _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
125 VFreeWrapper(pvCpuVAddr);
128 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
129 _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
131 KFreeWrapper(pvCpuVAddr);
136 enum PVRSRV_ERROR OSAllocPages(u32 ui32AllocFlags, u32 ui32Size,
137 u32 ui32PageSize, void **ppvCpuVAddr,
138 void **phOSMemHandle)
140 struct LinuxMemArea *psLinuxMemArea;
142 PVR_UNREFERENCED_PARAMETER(ui32PageSize);
144 switch (ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) {
145 case PVRSRV_HAP_KERNEL_ONLY:
148 NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
150 return PVRSRV_ERROR_OUT_OF_MEMORY;
153 case PVRSRV_HAP_SINGLE_PROCESS:
156 NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
158 return PVRSRV_ERROR_OUT_OF_MEMORY;
159 PVRMMapRegisterArea(psLinuxMemArea);
163 case PVRSRV_HAP_MULTI_PROCESS:
166 NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
168 return PVRSRV_ERROR_OUT_OF_MEMORY;
169 PVRMMapRegisterArea(psLinuxMemArea);
173 PVR_DPF(PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n",
176 *phOSMemHandle = (void *) 0;
177 return PVRSRV_ERROR_INVALID_PARAMS;
180 if (ui32AllocFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
181 inv_cache_mem_area(psLinuxMemArea);
183 *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
184 *phOSMemHandle = psLinuxMemArea;
189 enum PVRSRV_ERROR OSFreePages(u32 ui32AllocFlags, u32 ui32Bytes,
190 void *pvCpuVAddr, void *hOSMemHandle)
192 struct LinuxMemArea *psLinuxMemArea;
193 PVR_UNREFERENCED_PARAMETER(ui32Bytes);
194 PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
196 psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
198 switch (ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) {
199 case PVRSRV_HAP_KERNEL_ONLY:
201 case PVRSRV_HAP_SINGLE_PROCESS:
202 case PVRSRV_HAP_MULTI_PROCESS:
203 if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK) {
204 PVR_DPF(PVR_DBG_ERROR,
205 "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%ld, "
206 "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
207 ui32AllocFlags, ui32Bytes, pvCpuVAddr,
209 return PVRSRV_ERROR_GENERIC;
213 PVR_DPF(PVR_DBG_ERROR, "%s: invalid flags 0x%x\n",
214 __func__, ui32AllocFlags);
215 return PVRSRV_ERROR_INVALID_PARAMS;
218 LinuxMemAreaDeepFree(psLinuxMemArea);
223 enum PVRSRV_ERROR OSGetSubMemHandle(void *hOSMemHandle, u32 ui32ByteOffset,
224 u32 ui32Bytes, u32 ui32Flags,
225 void **phOSMemHandleRet)
227 struct LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
228 enum PVRSRV_ERROR eError;
230 psParentLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
233 NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
234 if (!psLinuxMemArea) {
235 *phOSMemHandleRet = NULL;
236 return PVRSRV_ERROR_OUT_OF_MEMORY;
238 *phOSMemHandleRet = psLinuxMemArea;
240 if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
243 eError = PVRMMapRegisterArea(psLinuxMemArea);
244 if (eError != PVRSRV_OK)
245 goto failed_register_area;
249 failed_register_area:
250 *phOSMemHandleRet = NULL;
251 LinuxMemAreaDeepFree(psLinuxMemArea);
255 enum PVRSRV_ERROR OSReleaseSubMemHandle(void *hOSMemHandle, u32 ui32Flags)
257 struct LinuxMemArea *psLinuxMemArea;
258 enum PVRSRV_ERROR eError;
260 psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
261 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
263 if ((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0) {
264 eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
265 if (eError != PVRSRV_OK)
268 LinuxMemAreaDeepFree(psLinuxMemArea);
273 struct IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(void *hOSMemHandle,
276 PVR_ASSERT(hOSMemHandle);
278 return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
281 void OSMemCopy(void *pvDst, void *pvSrc, u32 ui32Size)
283 memcpy(pvDst, pvSrc, ui32Size);
286 void OSMemSet(void *pvDest, u8 ui8Value, u32 ui32Size)
288 memset(pvDest, (int)ui8Value, (size_t) ui32Size);
291 char *OSStringCopy(char *pszDest, const char *pszSrc)
293 return strcpy(pszDest, pszSrc);
296 s32 OSSNPrintf(char *pStr, u32 ui32Size, const char *pszFormat, ...)
301 va_start(argList, pszFormat);
302 iCount = vsnprintf(pStr, (size_t) ui32Size, pszFormat, argList);
308 enum PVRSRV_ERROR OSInitEnvData(void **ppvEnvSpecificData)
310 struct ENV_DATA *psEnvData;
312 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct ENV_DATA),
313 (void *)&psEnvData, NULL) != PVRSRV_OK)
314 return PVRSRV_ERROR_GENERIC;
316 memset(psEnvData, 0, sizeof(*psEnvData));
318 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
319 PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
320 &psEnvData->pvBridgeData, NULL) != PVRSRV_OK) {
321 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct ENV_DATA),
323 return PVRSRV_ERROR_GENERIC;
326 psEnvData->bMISRInstalled = IMG_FALSE;
327 psEnvData->bLISRInstalled = IMG_FALSE;
329 *ppvEnvSpecificData = psEnvData;
334 enum PVRSRV_ERROR OSDeInitEnvData(void *pvEnvSpecificData)
336 struct ENV_DATA *psEnvData = (struct ENV_DATA *)pvEnvSpecificData;
338 PVR_ASSERT(!psEnvData->bMISRInstalled);
339 PVR_ASSERT(!psEnvData->bLISRInstalled);
341 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
342 PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
343 psEnvData->pvBridgeData, NULL);
345 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct ENV_DATA),
346 pvEnvSpecificData, NULL);
351 void OSReleaseThreadQuanta(void)
358 u32 time, j = jiffies;
360 time = j * (1000000 / HZ);
365 void OSWaitus(u32 ui32Timeus)
370 u32 OSGetCurrentProcessIDKM(void)
375 return (u32) task_tgid_nr(current);
378 u32 OSGetPageSize(void)
383 static irqreturn_t DeviceISRWrapper(int irq, void *dev_id)
385 struct PVRSRV_DEVICE_NODE *psDeviceNode;
386 IMG_BOOL bStatus = IMG_FALSE;
387 PVR_UNREFERENCED_PARAMETER(irq);
389 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)dev_id;
391 PVR_DPF(PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n");
395 bStatus = PVRSRVDeviceLISR(psDeviceNode);
398 struct SYS_DATA *psSysData = psDeviceNode->psSysData;
399 struct ENV_DATA *psEnvData =
400 (struct ENV_DATA *)psSysData->pvEnvSpecificData;
402 queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
406 return bStatus ? IRQ_HANDLED : IRQ_NONE;
409 enum PVRSRV_ERROR OSInstallDeviceLISR(void *pvSysData,
411 char *pszISRName, void *pvDeviceNode)
413 struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
414 struct ENV_DATA *psEnvData =
415 (struct ENV_DATA *)psSysData->pvEnvSpecificData;
417 if (psEnvData->bLISRInstalled) {
418 PVR_DPF(PVR_DBG_ERROR, "OSInstallDeviceLISR: "
419 "An ISR has already been installed: IRQ %d cookie %x",
420 psEnvData->ui32IRQ, psEnvData->pvISRCookie);
421 return PVRSRV_ERROR_GENERIC;
424 PVR_TRACE("Installing device LISR %s on IRQ %d with cookie %x",
425 pszISRName, ui32Irq, pvDeviceNode);
427 if (request_irq(ui32Irq, DeviceISRWrapper,
428 IRQF_SHARED, pszISRName, pvDeviceNode)) {
429 PVR_DPF(PVR_DBG_ERROR, "OSInstallDeviceLISR: "
430 "Couldn't install device LISR on IRQ %d",
433 return PVRSRV_ERROR_GENERIC;
436 psEnvData->ui32IRQ = ui32Irq;
437 psEnvData->pvISRCookie = pvDeviceNode;
438 psEnvData->bLISRInstalled = IMG_TRUE;
443 enum PVRSRV_ERROR OSUninstallDeviceLISR(void *pvSysData)
445 struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
446 struct ENV_DATA *psEnvData =
447 (struct ENV_DATA *)psSysData->pvEnvSpecificData;
449 if (!psEnvData->bLISRInstalled) {
450 PVR_DPF(PVR_DBG_ERROR,
451 "OSUninstallDeviceLISR: No LISR has been installed");
452 return PVRSRV_ERROR_GENERIC;
455 PVR_TRACE("Uninstalling device LISR on IRQ %d with cookie %x",
456 psEnvData->ui32IRQ, psEnvData->pvISRCookie);
458 free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
460 psEnvData->bLISRInstalled = IMG_FALSE;
465 static void MISRWrapper(struct work_struct *work)
467 struct ENV_DATA *psEnvData = container_of(work, struct ENV_DATA,
469 struct SYS_DATA *psSysData = (struct SYS_DATA *)psEnvData->pvSysData;
470 PVRSRVMISR(psSysData);
473 enum PVRSRV_ERROR OSInstallMISR(void *pvSysData)
475 struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
476 struct ENV_DATA *psEnvData =
477 (struct ENV_DATA *)psSysData->pvEnvSpecificData;
479 if (psEnvData->bMISRInstalled) {
480 PVR_DPF(PVR_DBG_ERROR,
481 "OSInstallMISR: An MISR has already been installed");
482 return PVRSRV_ERROR_GENERIC;
485 PVR_TRACE("Installing MISR with cookie %x", pvSysData);
487 psEnvData->pvSysData = pvSysData;
488 psEnvData->psMISRWorkqueue = create_singlethread_workqueue("sgx_misr");
489 INIT_WORK(&psEnvData->sMISRWork, MISRWrapper);
491 psEnvData->bMISRInstalled = IMG_TRUE;
496 enum PVRSRV_ERROR OSUninstallMISR(void *pvSysData)
498 struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
499 struct ENV_DATA *psEnvData =
500 (struct ENV_DATA *)psSysData->pvEnvSpecificData;
502 if (!psEnvData->bMISRInstalled) {
503 PVR_DPF(PVR_DBG_ERROR,
504 "OSUninstallMISR: No MISR has been installed");
505 return PVRSRV_ERROR_GENERIC;
508 PVR_TRACE("Uninstalling MISR");
510 flush_workqueue(psEnvData->psMISRWorkqueue);
511 destroy_workqueue(psEnvData->psMISRWorkqueue);
513 psEnvData->bMISRInstalled = IMG_FALSE;
518 enum PVRSRV_ERROR OSScheduleMISR(void *pvSysData)
520 struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
521 struct ENV_DATA *psEnvData =
522 (struct ENV_DATA *)psSysData->pvEnvSpecificData;
524 if (psEnvData->bMISRInstalled)
525 queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
531 struct IMG_CPU_PHYADDR OSMapLinToCPUPhys(void *pvLinAddr)
533 struct IMG_CPU_PHYADDR CpuPAddr;
535 CpuPAddr.uiAddr = (u32) VMallocToPhys(pvLinAddr);
540 void __iomem *OSMapPhysToLin(struct IMG_CPU_PHYADDR BasePAddr, u32 ui32Bytes,
541 u32 ui32MappingFlags, void **phOSMemHandle)
544 *phOSMemHandle = (void *) 0;
546 if (ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) {
547 void __iomem *pvIORemapCookie;
549 IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
550 if (pvIORemapCookie == NULL)
552 return pvIORemapCookie;
554 PVR_DPF(PVR_DBG_ERROR, "OSMapPhysToLin "
555 "should only be used with PVRSRV_HAP_KERNEL_ONLY "
556 "(Use OSReservePhys otherwise)");
563 OSUnMapPhysToLin(void __iomem *pvLinAddr, u32 ui32Bytes,
564 u32 ui32MappingFlags, void *hPageAlloc)
566 PVR_TRACE("%s: unmapping %d bytes from 0x%08x", __func__,
567 ui32Bytes, pvLinAddr);
569 PVR_UNREFERENCED_PARAMETER(hPageAlloc);
570 PVR_UNREFERENCED_PARAMETER(ui32Bytes);
572 if (ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) {
573 IOUnmapWrapper(pvLinAddr);
576 PVR_DPF(PVR_DBG_ERROR, "OSUnMapPhysToLin "
577 "should only be used with PVRSRV_HAP_KERNEL_ONLY "
578 " (Use OSUnReservePhys otherwise)");
584 static enum PVRSRV_ERROR RegisterExternalMem(struct IMG_SYS_PHYADDR *pBasePAddr,
585 void *pvCPUVAddr, u32 ui32Bytes, IMG_BOOL bPhysContig,
586 u32 ui32MappingFlags, void **phOSMemHandle)
588 struct LinuxMemArea *psLinuxMemArea;
590 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
591 case PVRSRV_HAP_KERNEL_ONLY:
594 NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
595 ui32Bytes, bPhysContig,
599 return PVRSRV_ERROR_GENERIC;
602 case PVRSRV_HAP_SINGLE_PROCESS:
605 NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
606 ui32Bytes, bPhysContig,
610 return PVRSRV_ERROR_GENERIC;
611 PVRMMapRegisterArea(psLinuxMemArea);
614 case PVRSRV_HAP_MULTI_PROCESS:
617 NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
618 ui32Bytes, bPhysContig,
622 return PVRSRV_ERROR_GENERIC;
623 PVRMMapRegisterArea(psLinuxMemArea);
627 PVR_DPF(PVR_DBG_ERROR, "OSRegisterMem : invalid flags 0x%x\n",
629 *phOSMemHandle = (void *) 0;
630 return PVRSRV_ERROR_GENERIC;
633 *phOSMemHandle = (void *) psLinuxMemArea;
638 enum PVRSRV_ERROR OSRegisterMem(struct IMG_CPU_PHYADDR BasePAddr,
639 void *pvCPUVAddr, u32 ui32Bytes,
640 u32 ui32MappingFlags, void **phOSMemHandle)
642 struct IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
644 return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE,
645 ui32MappingFlags, phOSMemHandle);
648 enum PVRSRV_ERROR OSRegisterDiscontigMem(struct IMG_SYS_PHYADDR *pBasePAddr,
649 void *pvCPUVAddr, u32 ui32Bytes,
650 u32 ui32MappingFlags,
651 void **phOSMemHandle)
653 return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes,
654 IMG_FALSE, ui32MappingFlags, phOSMemHandle);
657 enum PVRSRV_ERROR OSUnRegisterMem(void *pvCpuVAddr, u32 ui32Bytes,
658 u32 ui32MappingFlags, void *hOSMemHandle)
660 struct LinuxMemArea *psLinuxMemArea = (struct LinuxMemArea *)
663 PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
664 PVR_UNREFERENCED_PARAMETER(ui32Bytes);
666 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
667 case PVRSRV_HAP_KERNEL_ONLY:
669 case PVRSRV_HAP_SINGLE_PROCESS:
670 case PVRSRV_HAP_MULTI_PROCESS:
672 if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) !=
674 PVR_DPF(PVR_DBG_ERROR,
675 "%s(%p, %d, 0x%08X, %p) FAILED!",
676 __func__, pvCpuVAddr, ui32Bytes,
677 ui32MappingFlags, hOSMemHandle);
679 return PVRSRV_ERROR_GENERIC;
685 PVR_DPF(PVR_DBG_ERROR,
686 "OSUnRegisterMem : invalid flags 0x%x",
688 return PVRSRV_ERROR_INVALID_PARAMS;
692 LinuxMemAreaDeepFree(psLinuxMemArea);
697 enum PVRSRV_ERROR OSUnRegisterDiscontigMem(void *pvCpuVAddr, u32 ui32Bytes,
698 u32 ui32Flags, void *hOSMemHandle)
700 return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
703 enum PVRSRV_ERROR OSReservePhys(struct IMG_CPU_PHYADDR BasePAddr,
704 u32 ui32Bytes, u32 ui32MappingFlags, void **ppvCpuVAddr,
705 void **phOSMemHandle)
707 struct LinuxMemArea *psLinuxMemArea;
709 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
710 case PVRSRV_HAP_KERNEL_ONLY:
713 NewIORemapLinuxMemArea(BasePAddr, ui32Bytes,
716 return PVRSRV_ERROR_GENERIC;
719 case PVRSRV_HAP_SINGLE_PROCESS:
722 NewIOLinuxMemArea(BasePAddr, ui32Bytes,
725 return PVRSRV_ERROR_GENERIC;
726 PVRMMapRegisterArea(psLinuxMemArea);
729 case PVRSRV_HAP_MULTI_PROCESS:
732 NewIORemapLinuxMemArea(BasePAddr, ui32Bytes,
735 return PVRSRV_ERROR_GENERIC;
736 PVRMMapRegisterArea(psLinuxMemArea);
740 PVR_DPF(PVR_DBG_ERROR, "OSMapPhysToLin : invalid flags 0x%x\n",
743 *phOSMemHandle = (void *) 0;
744 return PVRSRV_ERROR_GENERIC;
747 *phOSMemHandle = (void *) psLinuxMemArea;
748 *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
753 enum PVRSRV_ERROR OSUnReservePhys(void *pvCpuVAddr,
754 u32 ui32Bytes, u32 ui32MappingFlags, void *hOSMemHandle)
756 struct LinuxMemArea *psLinuxMemArea;
757 PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
758 PVR_UNREFERENCED_PARAMETER(ui32Bytes);
760 psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
762 switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
763 case PVRSRV_HAP_KERNEL_ONLY:
765 case PVRSRV_HAP_SINGLE_PROCESS:
766 case PVRSRV_HAP_MULTI_PROCESS:
768 if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) !=
770 PVR_DPF(PVR_DBG_ERROR,
771 "%s(%p, %d, 0x%08X, %p) FAILED!",
772 __func__, pvCpuVAddr, ui32Bytes,
773 ui32MappingFlags, hOSMemHandle);
774 return PVRSRV_ERROR_GENERIC;
780 PVR_DPF(PVR_DBG_ERROR,
781 "OSUnMapPhysToLin : invalid flags 0x%x",
783 return PVRSRV_ERROR_INVALID_PARAMS;
787 LinuxMemAreaDeepFree(psLinuxMemArea);
792 enum PVRSRV_ERROR OSBaseAllocContigMemory(u32 ui32Size, void **pvLinAddr,
793 struct IMG_CPU_PHYADDR *psPhysAddr)
795 #if !defined(NO_HARDWARE)
796 PVR_UNREFERENCED_PARAMETER(ui32Size);
797 PVR_UNREFERENCED_PARAMETER(pvLinAddr);
798 PVR_UNREFERENCED_PARAMETER(psPhysAddr);
799 PVR_DPF(PVR_DBG_ERROR, "%s: Not available", __func__);
801 return PVRSRV_ERROR_OUT_OF_MEMORY;
805 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
806 pvKernLinAddr = _KMallocWrapper(ui32Size, __FILE__, __LINE__);
808 pvKernLinAddr = KMallocWrapper(ui32Size);
811 return PVRSRV_ERROR_OUT_OF_MEMORY;
813 *pvLinAddr = pvKernLinAddr;
815 psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
821 enum PVRSRV_ERROR OSBaseFreeContigMemory(u32 ui32Size, void *pvLinAddr,
822 struct IMG_CPU_PHYADDR psPhysAddr)
824 #if !defined(NO_HARDWARE)
825 PVR_UNREFERENCED_PARAMETER(ui32Size);
826 PVR_UNREFERENCED_PARAMETER(pvLinAddr);
827 PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
829 PVR_DPF(PVR_DBG_WARNING, "%s: Not available", __func__);
831 PVR_UNREFERENCED_PARAMETER(ui32Size);
832 PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
834 KFreeWrapper(pvLinAddr);
839 u32 OSReadHWReg(void __iomem *pvLinRegBaseAddr, u32 ui32Offset)
841 #if !defined(NO_HARDWARE)
842 return (u32)readl(pvLinRegBaseAddr + ui32Offset);
844 return *(u32 *)((u8 *) pvLinRegBaseAddr + ui32Offset);
848 void OSWriteHWReg(void __iomem *pvLinRegBaseAddr, u32 ui32Offset, u32 ui32Value)
850 #if !defined(NO_HARDWARE)
851 writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
853 *(u32 *)((u8 *)pvLinRegBaseAddr + ui32Offset) = ui32Value;
857 #define OS_MAX_TIMERS 8
859 struct TIMER_CALLBACK_DATA {
861 void (*pfnTimerFunc)(void *);
863 struct timer_list sTimer;
868 static struct TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
869 static DEFINE_SPINLOCK(sTimerStructLock);
870 static void OSTimerCallbackWrapper(unsigned long ui32Data)
872 struct TIMER_CALLBACK_DATA *psTimerCBData =
873 (struct TIMER_CALLBACK_DATA *)ui32Data;
875 if (!psTimerCBData->bActive)
878 psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
880 mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
883 void *OSAddTimer(void (*pfnTimerFunc)(void *), void *pvData, u32 ui32MsTimeout)
885 struct TIMER_CALLBACK_DATA *psTimerCBData;
887 unsigned long ulLockFlags;
890 PVR_DPF(PVR_DBG_ERROR, "OSAddTimer: passed invalid callback");
894 spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
895 for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++) {
896 psTimerCBData = &sTimers[ui32i];
897 if (!psTimerCBData->bInUse) {
898 psTimerCBData->bInUse = IMG_TRUE;
902 spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
904 if (ui32i >= OS_MAX_TIMERS) {
905 PVR_DPF(PVR_DBG_ERROR, "OSAddTimer: all timers are in use");
909 psTimerCBData->pfnTimerFunc = pfnTimerFunc;
910 psTimerCBData->pvData = pvData;
911 psTimerCBData->bActive = IMG_FALSE;
913 psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
914 ? 1 : ((HZ * ui32MsTimeout) / 1000);
916 init_timer(&psTimerCBData->sTimer);
918 psTimerCBData->sTimer.function = OSTimerCallbackWrapper;
919 psTimerCBData->sTimer.data = (u32) psTimerCBData;
920 psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
922 return (void *)(ui32i + 1);
925 static inline struct TIMER_CALLBACK_DATA *GetTimerStructure(void *hTimer)
927 u32 ui32i = ((u32) hTimer) - 1;
928 PVR_ASSERT(ui32i < OS_MAX_TIMERS);
929 return &sTimers[ui32i];
932 enum PVRSRV_ERROR OSRemoveTimer(void *hTimer)
934 struct TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
936 PVR_ASSERT(psTimerCBData->bInUse);
937 PVR_ASSERT(!psTimerCBData->bActive);
939 /* free timer callback data struct */
940 psTimerCBData->bInUse = IMG_FALSE;
945 enum PVRSRV_ERROR OSEnableTimer(void *hTimer)
947 struct TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
949 PVR_ASSERT(psTimerCBData->bInUse);
950 PVR_ASSERT(!psTimerCBData->bActive);
952 psTimerCBData->bActive = IMG_TRUE;
954 add_timer(&psTimerCBData->sTimer);
959 enum PVRSRV_ERROR OSDisableTimer(void *hTimer)
961 struct TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
963 PVR_ASSERT(psTimerCBData->bInUse);
964 PVR_ASSERT(psTimerCBData->bActive);
966 psTimerCBData->bActive = IMG_FALSE;
968 del_timer_sync(&psTimerCBData->sTimer);
973 enum PVRSRV_ERROR OSEventObjectCreate(const char *pszName,
974 struct PVRSRV_EVENTOBJECT *psEventObject)
976 enum PVRSRV_ERROR eError = PVRSRV_OK;
980 strncpy(psEventObject->szName, pszName,
981 EVENTOBJNAME_MAXLENGTH);
983 static u16 ui16NameIndex;
984 snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH,
985 "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
988 if (LinuxEventObjectListCreate(&psEventObject->hOSEventKM) !=
990 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
993 PVR_DPF(PVR_DBG_ERROR, "OSEventObjectCreate: "
994 "psEventObject is not a valid pointer");
995 eError = PVRSRV_ERROR_GENERIC;
1002 enum PVRSRV_ERROR OSEventObjectDestroy(struct PVRSRV_EVENTOBJECT *psEventObject)
1004 enum PVRSRV_ERROR eError = PVRSRV_OK;
1006 if (psEventObject) {
1007 if (psEventObject->hOSEventKM) {
1008 LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
1010 PVR_DPF(PVR_DBG_ERROR, "OSEventObjectDestroy: "
1011 "hOSEventKM is not a valid pointer");
1012 eError = PVRSRV_ERROR_INVALID_PARAMS;
1015 PVR_DPF(PVR_DBG_ERROR, "OSEventObjectDestroy: "
1016 "psEventObject is not a valid pointer");
1017 eError = PVRSRV_ERROR_INVALID_PARAMS;
1023 enum PVRSRV_ERROR OSEventObjectWait(void *hOSEventKM)
1025 enum PVRSRV_ERROR eError;
1029 LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
1031 PVR_DPF(PVR_DBG_ERROR,
1032 "OSEventObjectWait: hOSEventKM is not a valid handle");
1033 eError = PVRSRV_ERROR_INVALID_PARAMS;
1039 enum PVRSRV_ERROR OSEventObjectOpen(struct PVRSRV_EVENTOBJECT *psEventObject,
1042 enum PVRSRV_ERROR eError = PVRSRV_OK;
1044 if (psEventObject) {
1045 if (LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) !=
1047 PVR_DPF(PVR_DBG_ERROR, "LinuxEventObjectAdd: failed");
1048 eError = PVRSRV_ERROR_INVALID_PARAMS;
1052 PVR_DPF(PVR_DBG_ERROR, "OSEventObjectCreate: "
1053 "psEventObject is not a valid pointer");
1054 eError = PVRSRV_ERROR_INVALID_PARAMS;
1060 enum PVRSRV_ERROR OSEventObjectClose(struct PVRSRV_EVENTOBJECT *psEventObject,
1063 enum PVRSRV_ERROR eError = PVRSRV_OK;
1065 if (psEventObject) {
1066 if (LinuxEventObjectDelete
1067 (psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK) {
1068 PVR_DPF(PVR_DBG_ERROR,
1069 "LinuxEventObjectDelete: failed");
1070 eError = PVRSRV_ERROR_INVALID_PARAMS;
1074 PVR_DPF(PVR_DBG_ERROR, "OSEventObjectDestroy: "
1075 "psEventObject is not a valid pointer");
1076 eError = PVRSRV_ERROR_INVALID_PARAMS;
1083 enum PVRSRV_ERROR OSEventObjectSignal(void *hOSEventKM)
1085 enum PVRSRV_ERROR eError;
1088 eError = LinuxEventObjectSignal(hOSEventKM);
1090 PVR_DPF(PVR_DBG_ERROR, "OSEventObjectSignal: "
1091 "hOSEventKM is not a valid handle");
1092 eError = PVRSRV_ERROR_INVALID_PARAMS;
1098 IMG_BOOL OSProcHasPrivSrvInit(void)
1100 return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
1103 enum PVRSRV_ERROR OSCopyToUser(void *pvProcess, void __user *pvDest,
1104 const void *pvSrc, u32 ui32Bytes)
1106 PVR_UNREFERENCED_PARAMETER(pvProcess);
1108 if (copy_to_user(pvDest, pvSrc, ui32Bytes) == 0)
1111 return PVRSRV_ERROR_GENERIC;
1114 enum PVRSRV_ERROR OSCopyFromUser(void *pvProcess, void *pvDest,
1115 const void __user *pvSrc, u32 ui32Bytes)
1117 PVR_UNREFERENCED_PARAMETER(pvProcess);
1119 if (copy_from_user(pvDest, pvSrc, ui32Bytes) == 0)
1122 return PVRSRV_ERROR_GENERIC;
1125 IMG_BOOL OSAccessOK(enum IMG_VERIFY_TEST eVerification,
1126 const void __user *pvUserPtr, u32 ui32Bytes)
1130 if (eVerification == PVR_VERIFY_READ) {
1131 linuxType = VERIFY_READ;
1133 PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
1134 linuxType = VERIFY_WRITE;
1137 return access_ok(linuxType, pvUserPtr, ui32Bytes);
1142 WRAP_TYPE_GET_USER_PAGES,
1143 WRAP_TYPE_FIND_VMA_PAGES,
1144 WRAP_TYPE_FIND_VMA_PFN
1147 struct sWrapMemInfo {
1148 enum eWrapMemType eType;
1150 struct page **ppsPages;
1151 struct IMG_SYS_PHYADDR *psPhysAddr;
1154 #if defined(CONFIG_PVR_DEBUG_EXTRA)
1156 u32 ulBeyondEndAddr;
1157 struct vm_area_struct *psVMArea;
1161 static void CheckPagesContiguous(struct sWrapMemInfo *psInfo)
1166 BUG_ON(psInfo == NULL);
1168 psInfo->iContiguous = 1;
1170 for (i = 0, ui32AddrChk = psInfo->psPhysAddr[0].uiAddr;
1171 i < psInfo->iNumPages; i++, ui32AddrChk += PAGE_SIZE)
1172 if (psInfo->psPhysAddr[i].uiAddr != ui32AddrChk) {
1173 psInfo->iContiguous = 0;
1178 static struct page *CPUVAddrToPage(struct vm_area_struct *psVMArea,
1185 struct mm_struct *psMM = psVMArea->vm_mm;
1187 spinlock_t *psPTLock;
1188 struct page *psPage;
1190 psPGD = pgd_offset(psMM, ulCPUVAddr);
1191 if (pgd_none(*psPGD) || pgd_bad(*psPGD))
1194 psPUD = pud_offset(psPGD, ulCPUVAddr);
1195 if (pud_none(*psPUD) || pud_bad(*psPUD))
1198 psPMD = pmd_offset(psPUD, ulCPUVAddr);
1199 if (pmd_none(*psPMD) || pmd_bad(*psPMD))
1204 psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr,
1206 if ((pte_none(*psPTE) != 0) || (pte_present(*psPTE) == 0) ||
1207 (pte_write(*psPTE) == 0))
1210 ulPFN = pte_pfn(*psPTE);
1211 if (!pfn_valid(ulPFN))
1214 psPage = pfn_to_page(ulPFN);
1219 pte_unmap_unlock(psPTE, psPTLock);
1224 enum PVRSRV_ERROR OSReleasePhysPageAddr(void *hOSWrapMem)
1226 struct sWrapMemInfo *psInfo = (struct sWrapMemInfo *)hOSWrapMem;
1229 BUG_ON(psInfo == NULL);
1231 switch (psInfo->eType) {
1232 case WRAP_TYPE_CLEANUP:
1234 case WRAP_TYPE_FIND_VMA_PFN:
1236 case WRAP_TYPE_GET_USER_PAGES:
1238 for (i = 0; i < psInfo->iNumPages; i++) {
1239 struct page *psPage = psInfo->ppsPages[i];
1241 if (!PageReserved(psPage))
1242 SetPageDirty(psPage);
1243 page_cache_release(psPage);
1247 case WRAP_TYPE_FIND_VMA_PAGES:
1249 for (i = 0; i < psInfo->iNumPages; i++)
1250 put_page_testzero(psInfo->ppsPages[i]);
1255 PVR_DPF(PVR_DBG_ERROR,
1256 "OSReleasePhysPageAddr: Unknown wrap type (%d)",
1258 return PVRSRV_ERROR_GENERIC;
1262 if (psInfo->ppsPages != NULL)
1263 kfree(psInfo->ppsPages);
1265 if (psInfo->psPhysAddr != NULL)
1266 kfree(psInfo->psPhysAddr);
1273 enum PVRSRV_ERROR OSAcquirePhysPageAddr(void *pvCPUVAddr, u32 ui32Bytes,
1274 struct IMG_SYS_PHYADDR *psSysPAddr,
1277 u32 ulStartAddrOrig = (u32) pvCPUVAddr;
1278 u32 ulAddrRangeOrig = (u32) ui32Bytes;
1279 u32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
1282 u32 ulBeyondEndAddr;
1284 int iNumPagesMapped;
1286 struct vm_area_struct *psVMArea;
1287 struct sWrapMemInfo *psInfo;
1289 ulStartAddr = ulStartAddrOrig & PAGE_MASK;
1290 ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
1291 ulAddrRange = ulBeyondEndAddr - ulStartAddr;
1293 psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
1294 if (psInfo == NULL) {
1295 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1296 "Couldn't allocate information structure");
1297 return PVRSRV_ERROR_OUT_OF_MEMORY;
1299 memset(psInfo, 0, sizeof(*psInfo));
1301 #if defined(CONFIG_PVR_DEBUG_EXTRA)
1302 psInfo->ulStartAddr = ulStartAddrOrig;
1303 psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
1306 psInfo->iNumPages = (int)(ulAddrRange >> PAGE_SHIFT);
1307 psInfo->iPageOffset = (int)(ulStartAddrOrig & ~PAGE_MASK);
1309 psInfo->psPhysAddr =
1310 kmalloc((size_t) psInfo->iNumPages * sizeof(*psInfo->psPhysAddr),
1312 if (psInfo->psPhysAddr == NULL) {
1313 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1314 "Couldn't allocate page array");
1319 kmalloc((size_t) psInfo->iNumPages * sizeof(*psInfo->ppsPages),
1321 if (psInfo->ppsPages == NULL) {
1322 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1323 "Couldn't allocate page array");
1327 down_read(¤t->mm->mmap_sem);
1329 iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr,
1330 psInfo->iNumPages, 1, 0,
1331 psInfo->ppsPages, NULL);
1332 up_read(¤t->mm->mmap_sem);
1335 if (iNumPagesMapped >= 0) {
1336 if (iNumPagesMapped != psInfo->iNumPages) {
1337 PVR_TRACE("OSAcquirePhysPageAddr: "
1338 "Couldn't map all the pages needed "
1339 "(wanted: %d, got %d)",
1340 psInfo->iNumPages, iNumPagesMapped);
1342 for (i = 0; i < iNumPagesMapped; i++)
1343 page_cache_release(psInfo->ppsPages[i]);
1348 for (i = 0; i < psInfo->iNumPages; i++) {
1349 struct IMG_CPU_PHYADDR CPUPhysAddr;
1351 CPUPhysAddr.uiAddr =
1352 page_to_pfn(psInfo->ppsPages[i]) << PAGE_SHIFT;
1353 psInfo->psPhysAddr[i] =
1354 SysCpuPAddrToSysPAddr(CPUPhysAddr);
1355 psSysPAddr[i] = psInfo->psPhysAddr[i];
1359 psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
1364 PVR_TRACE("OSAcquirePhysPageAddr: "
1365 "get_user_pages failed (%d), trying something else",
1368 down_read(¤t->mm->mmap_sem);
1370 psVMArea = find_vma(current->mm, ulStartAddrOrig);
1371 if (psVMArea == NULL) {
1372 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1373 "Couldn't find memory region "
1374 "containing start address %lx",
1377 goto error_release_mmap_sem;
1379 #if defined(CONFIG_PVR_DEBUG_EXTRA)
1380 psInfo->psVMArea = psVMArea;
1383 if (ulStartAddrOrig < psVMArea->vm_start) {
1384 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1385 "Start address %lx is outside of the "
1386 "region returned by find_vma",
1388 goto error_release_mmap_sem;
1391 if (ulBeyondEndAddrOrig > psVMArea->vm_end) {
1392 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1393 "End address %lx is outside of the region "
1394 "returned by find_vma",
1395 ulBeyondEndAddrOrig);
1396 goto error_release_mmap_sem;
1399 if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) !=
1400 (VM_IO | VM_RESERVED)) {
1401 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1402 "Memory region does not represent memory "
1403 "mapped I/O (VMA flags: 0x%lx)",
1404 psVMArea->vm_flags);
1405 goto error_release_mmap_sem;
1408 if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) !=
1409 (VM_READ | VM_WRITE)) {
1410 PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
1411 "No read/write access to memory region "
1412 "(VMA flags: 0x%lx)",
1413 psVMArea->vm_flags);
1414 goto error_release_mmap_sem;
1417 for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig;
1418 ulAddr += PAGE_SIZE, i++) {
1419 struct page *psPage;
1421 BUG_ON(i >= psInfo->iNumPages);
1423 psPage = CPUVAddrToPage(psVMArea, ulAddr);
1424 if (psPage == NULL) {
1427 PVR_TRACE("OSAcquirePhysPageAddr: "
1428 "Couldn't lookup page structure "
1429 "for address 0x%lx, trying something else",
1432 for (j = 0; j < i; j++)
1433 put_page_testzero(psInfo->ppsPages[j]);
1437 psInfo->ppsPages[i] = psPage;
1440 BUG_ON(i > psInfo->iNumPages);
1441 if (i == psInfo->iNumPages) {
1442 for (i = 0; i < psInfo->iNumPages; i++) {
1443 struct page *psPage = psInfo->ppsPages[i];
1444 struct IMG_CPU_PHYADDR CPUPhysAddr;
1446 CPUPhysAddr.uiAddr = page_to_pfn(psPage) << PAGE_SHIFT;
1448 psInfo->psPhysAddr[i] =
1449 SysCpuPAddrToSysPAddr(CPUPhysAddr);
1450 psSysPAddr[i] = psInfo->psPhysAddr[i];
1453 psInfo->eType = WRAP_TYPE_FIND_VMA_PAGES;
1456 if ((psVMArea->vm_flags & VM_PFNMAP) == 0) {
1457 PVR_DPF(PVR_DBG_WARNING, "OSAcquirePhysPageAddr: "
1458 "Region isn't a raw PFN mapping. "
1460 goto error_release_mmap_sem;
1463 for (ulAddr = ulStartAddrOrig, i = 0;
1464 ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++) {
1465 struct IMG_CPU_PHYADDR CPUPhysAddr;
1467 CPUPhysAddr.uiAddr = ((ulAddr - psVMArea->vm_start) +
1468 (psVMArea->vm_pgoff << PAGE_SHIFT)) & PAGE_MASK;
1470 psInfo->psPhysAddr[i] =
1471 SysCpuPAddrToSysPAddr(CPUPhysAddr);
1472 psSysPAddr[i] = psInfo->psPhysAddr[i];
1474 BUG_ON(i != psInfo->iNumPages);
1476 psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
1478 PVR_DPF(PVR_DBG_WARNING, "OSAcquirePhysPageAddr: "
1479 "Region can't be locked down");
1482 up_read(¤t->mm->mmap_sem);
1485 CheckPagesContiguous(psInfo);
1487 *phOSWrapMem = (void *) psInfo;
1491 error_release_mmap_sem:
1492 up_read(¤t->mm->mmap_sem);
1495 psInfo->eType = WRAP_TYPE_CLEANUP;
1496 OSReleasePhysPageAddr((void *)psInfo);
1497 return PVRSRV_ERROR_GENERIC;