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 ******************************************************************************/
29 #include "services_headers.h"
30 #include "buffer_manager.h"
32 #include "pvr_bridge_km.h"
34 #include <linux/pagemap.h>
36 static enum PVRSRV_ERROR AllocDeviceMem(void *hDevCookie, void *hDevMemHeap,
37 u32 ui32Flags, u32 ui32Size, u32 ui32Alignment,
38 struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
40 struct RESMAN_MAP_DEVICE_MEM_DATA {
41 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
42 struct PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
45 static inline void get_page_details(u32 vaddr, size_t byte_size,
46 u32 *page_offset_out, int *page_count_out)
48 size_t host_page_size;
52 host_page_size = PAGE_SIZE;
53 page_offset = vaddr & (host_page_size - 1);
54 page_count = PAGE_ALIGN(byte_size + page_offset) / host_page_size;
56 *page_offset_out = page_offset;
57 *page_count_out = page_count;
60 static inline int get_page_count(u32 vaddr, size_t byte_size)
65 get_page_details(vaddr, byte_size, &page_offset, &page_count);
70 enum PVRSRV_ERROR PVRSRVGetDeviceMemHeapsKM(void *hDevCookie,
71 struct PVRSRV_HEAP_INFO *psHeapInfo)
73 struct PVRSRV_DEVICE_NODE *psDeviceNode;
75 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
78 if (hDevCookie == NULL) {
79 PVR_DPF(PVR_DBG_ERROR,
80 "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid");
82 return PVRSRV_ERROR_INVALID_PARAMS;
85 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
87 ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
88 psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
90 PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
92 for (i = 0; i < ui32HeapCount; i++) {
93 psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
94 psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
95 psHeapInfo[i].sDevVAddrBase =
96 psDeviceMemoryHeap[i].sDevVAddrBase;
97 psHeapInfo[i].ui32HeapByteSize =
98 psDeviceMemoryHeap[i].ui32HeapSize;
99 psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
102 for (; i < PVRSRV_MAX_CLIENT_HEAPS; i++) {
103 OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
104 psHeapInfo[i].ui32HeapID = (u32) PVRSRV_UNDEFINED_HEAP_ID;
110 enum PVRSRV_ERROR PVRSRVCreateDeviceMemContextKM(void *hDevCookie,
111 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
112 void **phDevMemContext,
113 u32 *pui32ClientHeapCount,
114 struct PVRSRV_HEAP_INFO *psHeapInfo,
115 IMG_BOOL *pbCreated, IMG_BOOL *pbShared)
117 struct PVRSRV_DEVICE_NODE *psDeviceNode;
118 u32 ui32HeapCount, ui32ClientHeapCount = 0;
119 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
120 void *hDevMemContext;
122 struct IMG_DEV_PHYADDR sPDDevPAddr;
125 if (hDevCookie == NULL) {
126 PVR_DPF(PVR_DBG_ERROR,
127 "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid");
129 return PVRSRV_ERROR_INVALID_PARAMS;
132 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
134 ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
135 psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
137 PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
139 hDevMemContext = BM_CreateContext(psDeviceNode,
140 &sPDDevPAddr, psPerProc, pbCreated);
141 if (hDevMemContext == NULL) {
142 PVR_DPF(PVR_DBG_ERROR,
143 "PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext");
144 return PVRSRV_ERROR_OUT_OF_MEMORY;
147 for (i = 0; i < ui32HeapCount; i++) {
148 switch (psDeviceMemoryHeap[i].DevMemHeapType) {
149 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
150 psHeapInfo[ui32ClientHeapCount].ui32HeapID =
151 psDeviceMemoryHeap[i].ui32HeapID;
152 psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
153 psDeviceMemoryHeap[i].hDevMemHeap;
154 psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
155 psDeviceMemoryHeap[i].sDevVAddrBase;
156 psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize =
157 psDeviceMemoryHeap[i].ui32HeapSize;
158 psHeapInfo[ui32ClientHeapCount].ui32Attribs =
159 psDeviceMemoryHeap[i].ui32Attribs;
160 pbShared[ui32ClientHeapCount] = IMG_TRUE;
161 ui32ClientHeapCount++;
163 case DEVICE_MEMORY_HEAP_PERCONTEXT:
164 hDevMemHeap = BM_CreateHeap(hDevMemContext,
165 &psDeviceMemoryHeap[i]);
167 psHeapInfo[ui32ClientHeapCount].ui32HeapID =
168 psDeviceMemoryHeap[i].ui32HeapID;
169 psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
171 psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
172 psDeviceMemoryHeap[i].sDevVAddrBase;
173 psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize =
174 psDeviceMemoryHeap[i].ui32HeapSize;
175 psHeapInfo[ui32ClientHeapCount].ui32Attribs =
176 psDeviceMemoryHeap[i].ui32Attribs;
177 pbShared[ui32ClientHeapCount] = IMG_FALSE;
179 ui32ClientHeapCount++;
184 *pui32ClientHeapCount = ui32ClientHeapCount;
185 *phDevMemContext = hDevMemContext;
190 enum PVRSRV_ERROR PVRSRVDestroyDeviceMemContextKM(void *hDevCookie,
191 void *hDevMemContext,
192 IMG_BOOL *pbDestroyed)
196 PVR_UNREFERENCED_PARAMETER(hDevCookie);
198 destroyed = pvr_put_ctx(hDevMemContext);
200 *pbDestroyed = destroyed ? IMG_TRUE : IMG_FALSE;
205 enum PVRSRV_ERROR PVRSRVGetDeviceMemHeapInfoKM(void *hDevCookie,
206 void *hDevMemContext,
207 u32 *pui32ClientHeapCount,
208 struct PVRSRV_HEAP_INFO *psHeapInfo,
211 struct PVRSRV_DEVICE_NODE *psDeviceNode;
212 u32 ui32HeapCount, ui32ClientHeapCount = 0;
213 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
217 if (hDevCookie == NULL) {
218 PVR_DPF(PVR_DBG_ERROR,
219 "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid");
221 return PVRSRV_ERROR_INVALID_PARAMS;
224 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
226 ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
227 psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
229 PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
231 for (i = 0; i < ui32HeapCount; i++) {
232 switch (psDeviceMemoryHeap[i].DevMemHeapType) {
233 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
234 psHeapInfo[ui32ClientHeapCount].ui32HeapID =
235 psDeviceMemoryHeap[i].ui32HeapID;
236 psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
237 psDeviceMemoryHeap[i].hDevMemHeap;
238 psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
239 psDeviceMemoryHeap[i].sDevVAddrBase;
240 psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize =
241 psDeviceMemoryHeap[i].ui32HeapSize;
242 psHeapInfo[ui32ClientHeapCount].ui32Attribs =
243 psDeviceMemoryHeap[i].ui32Attribs;
244 pbShared[ui32ClientHeapCount] = IMG_TRUE;
245 ui32ClientHeapCount++;
247 case DEVICE_MEMORY_HEAP_PERCONTEXT:
248 hDevMemHeap = BM_CreateHeap(hDevMemContext,
249 &psDeviceMemoryHeap[i]);
250 psHeapInfo[ui32ClientHeapCount].ui32HeapID =
251 psDeviceMemoryHeap[i].ui32HeapID;
252 psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
254 psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
255 psDeviceMemoryHeap[i].sDevVAddrBase;
256 psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize =
257 psDeviceMemoryHeap[i].ui32HeapSize;
258 psHeapInfo[ui32ClientHeapCount].ui32Attribs =
259 psDeviceMemoryHeap[i].ui32Attribs;
260 pbShared[ui32ClientHeapCount] = IMG_FALSE;
262 ui32ClientHeapCount++;
266 *pui32ClientHeapCount = ui32ClientHeapCount;
271 static enum PVRSRV_ERROR AllocDeviceMem(void *hDevCookie, void *hDevMemHeap,
272 u32 ui32Flags, u32 ui32Size,
274 struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
276 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
279 struct PVRSRV_MEMBLK *psMemBlock;
282 PVR_UNREFERENCED_PARAMETER(hDevCookie);
286 if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
287 sizeof(struct PVRSRV_KERNEL_MEM_INFO),
288 (void **) &psMemInfo, NULL) != PVRSRV_OK) {
289 PVR_DPF(PVR_DBG_ERROR,
290 "AllocDeviceMem: Failed to alloc memory for block");
291 return PVRSRV_ERROR_OUT_OF_MEMORY;
294 OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
296 psMemBlock = &(psMemInfo->sMemBlk);
298 psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
300 bBMError = BM_Alloc(hDevMemHeap, NULL, ui32Size,
301 &psMemInfo->ui32Flags, ui32Alignment, &hBuffer);
304 PVR_DPF(PVR_DBG_ERROR, "AllocDeviceMem: BM_Alloc Failed");
305 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
306 sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo,
308 return PVRSRV_ERROR_OUT_OF_MEMORY;
311 psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
312 psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
314 psMemBlock->hBuffer = (void *)hBuffer;
315 psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
316 psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
317 psMemInfo->ui32AllocSize = ui32Size;
319 psMemInfo->pvSysBackupBuffer = NULL;
321 *ppsMemInfo = psMemInfo;
326 static enum PVRSRV_ERROR FreeDeviceMem(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
331 return PVRSRV_ERROR_INVALID_PARAMS;
333 hBuffer = psMemInfo->sMemBlk.hBuffer;
334 BM_Free(hBuffer, psMemInfo->ui32Flags);
336 if (psMemInfo->pvSysBackupBuffer)
337 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize,
338 psMemInfo->pvSysBackupBuffer, NULL);
340 OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct PVRSRV_KERNEL_MEM_INFO),
346 enum PVRSRV_ERROR PVRSRVAllocSyncInfoKM(void *hDevCookie, void *hDevMemContext,
347 struct PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo)
349 void *hSyncDevMemHeap;
350 struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
351 struct BM_CONTEXT *pBMContext;
352 enum PVRSRV_ERROR eError;
353 struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
354 struct PVRSRV_SYNC_DATA *psSyncData;
356 eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
357 sizeof(struct PVRSRV_KERNEL_SYNC_INFO),
358 (void **) &psKernelSyncInfo, NULL);
359 if (eError != PVRSRV_OK) {
360 PVR_DPF(PVR_DBG_ERROR,
361 "PVRSRVAllocSyncInfoKM: Failed to alloc memory");
362 return PVRSRV_ERROR_OUT_OF_MEMORY;
365 pBMContext = (struct BM_CONTEXT *)hDevMemContext;
366 psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
368 hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
369 ui32SyncHeapID].hDevMemHeap;
371 eError = AllocDeviceMem(hDevCookie, hSyncDevMemHeap,
372 PVRSRV_MEM_CACHE_CONSISTENT,
373 sizeof(struct PVRSRV_SYNC_DATA), sizeof(u32),
374 &psKernelSyncInfo->psSyncDataMemInfoKM);
376 if (eError != PVRSRV_OK) {
377 PVR_DPF(PVR_DBG_ERROR,
378 "PVRSRVAllocSyncInfoKM: Failed to alloc memory");
379 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
380 sizeof(struct PVRSRV_KERNEL_SYNC_INFO),
381 psKernelSyncInfo, NULL);
382 return PVRSRV_ERROR_OUT_OF_MEMORY;
385 psKernelSyncInfo->psSyncData =
386 psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
387 psSyncData = psKernelSyncInfo->psSyncData;
389 psSyncData->ui32WriteOpsPending = 0;
390 psSyncData->ui32WriteOpsComplete = 0;
391 psSyncData->ui32ReadOpsPending = 0;
392 psSyncData->ui32ReadOpsComplete = 0;
393 psSyncData->ui32LastOpDumpVal = 0;
394 psSyncData->ui32LastReadOpDumpVal = 0;
397 PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
398 psKernelSyncInfo->psSyncDataMemInfoKM, 0,
399 psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize,
400 0, MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
403 psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr =
404 psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr +
405 offsetof(struct PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
406 psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr =
407 psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr +
408 offsetof(struct PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
410 psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = NULL;
412 *ppsKernelSyncInfo = psKernelSyncInfo;
417 enum PVRSRV_ERROR PVRSRVFreeSyncInfoKM(
418 struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
420 FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
421 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
422 sizeof(struct PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo,
429 void get_syncinfo(struct PVRSRV_KERNEL_SYNC_INFO *syncinfo)
431 syncinfo->refcount++;
435 void put_syncinfo(struct PVRSRV_KERNEL_SYNC_INFO *syncinfo)
437 struct PVRSRV_DEVICE_NODE *dev = syncinfo->dev_cookie;
439 syncinfo->refcount--;
441 if (!syncinfo->refcount) {
442 HASH_Remove(dev->sync_table,
443 syncinfo->phys_addr.uiAddr);
444 PVRSRVFreeSyncInfoKM(syncinfo);
449 enum PVRSRV_ERROR alloc_or_reuse_syncinfo(void *dev_cookie,
450 void *mem_context_handle,
451 struct PVRSRV_KERNEL_SYNC_INFO **syncinfo,
452 struct IMG_SYS_PHYADDR *phys_addr)
454 enum PVRSRV_ERROR error;
455 struct PVRSRV_DEVICE_NODE *dev;
457 dev = (struct PVRSRV_DEVICE_NODE *) dev_cookie;
459 *syncinfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
460 HASH_Retrieve(dev->sync_table,
464 /* Dont' have one so create one */
465 error = PVRSRVAllocSyncInfoKM(dev_cookie, mem_context_handle,
468 if (error != PVRSRV_OK)
471 /* Setup our extra data */
472 (*syncinfo)->phys_addr.uiAddr = phys_addr->uiAddr;
473 (*syncinfo)->dev_cookie = dev_cookie;
474 (*syncinfo)->refcount = 1;
476 if (!HASH_Insert(dev->sync_table, phys_addr->uiAddr,
478 PVR_DPF(PVR_DBG_ERROR, "alloc_or_reuse_syncinfo: "
479 "Failed to add syncobject to hash table");
480 return PVRSRV_ERROR_GENERIC;
483 get_syncinfo(*syncinfo);
488 static enum PVRSRV_ERROR FreeDeviceMemCallBack(void *pvParam, u32 ui32Param)
490 enum PVRSRV_ERROR eError = PVRSRV_OK;
491 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
493 PVR_UNREFERENCED_PARAMETER(ui32Param);
495 psMemInfo->ui32RefCount--;
497 if (psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) {
498 void *hMemInfo = NULL;
500 if (psMemInfo->ui32RefCount != 0) {
501 PVR_DPF(PVR_DBG_ERROR, "FreeDeviceMemCallBack: "
502 "mappings are open in other processes");
503 return PVRSRV_ERROR_GENERIC;
506 eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
509 PVRSRV_HANDLE_TYPE_MEM_INFO);
510 if (eError != PVRSRV_OK) {
511 PVR_DPF(PVR_DBG_ERROR, "FreeDeviceMemCallBack: "
512 "can't find exported meminfo in the "
513 "global handle list");
517 eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
519 PVRSRV_HANDLE_TYPE_MEM_INFO);
520 if (eError != PVRSRV_OK) {
521 PVR_DPF(PVR_DBG_ERROR, "FreeDeviceMemCallBack: "
522 "PVRSRVReleaseHandle failed for exported meminfo");
527 PVR_ASSERT(psMemInfo->ui32RefCount == 0);
529 if (psMemInfo->psKernelSyncInfo)
530 eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
532 if (eError == PVRSRV_OK)
533 eError = FreeDeviceMem(psMemInfo);
538 enum PVRSRV_ERROR PVRSRVFreeDeviceMemKM(void *hDevCookie,
539 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
541 PVR_UNREFERENCED_PARAMETER(hDevCookie);
544 return PVRSRV_ERROR_INVALID_PARAMS;
546 if (psMemInfo->sMemBlk.hResItem != NULL)
547 ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
549 FreeDeviceMemCallBack(psMemInfo, 0);
554 enum PVRSRV_ERROR PVRSRVAllocDeviceMemKM(void *hDevCookie,
555 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
556 void *hDevMemHeap, u32 ui32Flags,
557 u32 ui32Size, u32 ui32Alignment,
558 struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
560 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
561 enum PVRSRV_ERROR eError;
562 struct BM_HEAP *psBMHeap;
563 void *hDevMemContext;
565 if (!hDevMemHeap || (ui32Size == 0))
566 return PVRSRV_ERROR_INVALID_PARAMS;
568 eError = AllocDeviceMem(hDevCookie, hDevMemHeap, ui32Flags, ui32Size,
569 ui32Alignment, &psMemInfo);
571 if (eError != PVRSRV_OK)
574 if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) {
575 psMemInfo->psKernelSyncInfo = NULL;
577 psBMHeap = (struct BM_HEAP *)hDevMemHeap;
578 hDevMemContext = (void *) psBMHeap->pBMContext;
579 eError = PVRSRVAllocSyncInfoKM(hDevCookie,
581 &psMemInfo->psKernelSyncInfo);
582 if (eError != PVRSRV_OK)
586 *ppsMemInfo = psMemInfo;
588 if (ui32Flags & PVRSRV_MEM_NO_RESMAN) {
589 psMemInfo->sMemBlk.hResItem = NULL;
591 psMemInfo->sMemBlk.hResItem =
592 ResManRegisterRes(psPerProc->hResManContext,
593 RESMAN_TYPE_DEVICEMEM_ALLOCATION,
594 psMemInfo, 0, FreeDeviceMemCallBack);
595 if (psMemInfo->sMemBlk.hResItem == NULL) {
596 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
601 psMemInfo->ui32RefCount++;
606 FreeDeviceMem(psMemInfo);
611 enum PVRSRV_ERROR PVRSRVDissociateDeviceMemKM(void *hDevCookie,
612 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
614 enum PVRSRV_ERROR eError;
615 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevCookie;
617 PVR_UNREFERENCED_PARAMETER(hDevCookie);
620 return PVRSRV_ERROR_INVALID_PARAMS;
622 eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem,
623 psDeviceNode->hResManContext);
625 PVR_ASSERT(eError == PVRSRV_OK);
630 enum PVRSRV_ERROR PVRSRVGetFreeDeviceMemKM(u32 ui32Flags, u32 *pui32Total,
631 u32 *pui32Free, u32 *pui32LargestBlock)
634 PVR_UNREFERENCED_PARAMETER(ui32Flags);
635 PVR_UNREFERENCED_PARAMETER(pui32Total);
636 PVR_UNREFERENCED_PARAMETER(pui32Free);
637 PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
642 enum PVRSRV_ERROR PVRSRVUnwrapExtMemoryKM(
643 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
646 return PVRSRV_ERROR_INVALID_PARAMS;
648 ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
653 static enum PVRSRV_ERROR UnwrapExtMemoryCallBack(void *pvParam, u32 ui32Param)
655 enum PVRSRV_ERROR eError = PVRSRV_OK;
656 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
659 PVR_UNREFERENCED_PARAMETER(ui32Param);
661 hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
663 if (psMemInfo->psKernelSyncInfo)
664 put_syncinfo(psMemInfo->psKernelSyncInfo);
666 if (psMemInfo->sMemBlk.psIntSysPAddr) {
669 page_count = get_page_count((u32)psMemInfo->pvLinAddrKM,
670 psMemInfo->ui32AllocSize);
672 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
673 page_count * sizeof(struct IMG_SYS_PHYADDR),
674 psMemInfo->sMemBlk.psIntSysPAddr, NULL);
677 if (eError == PVRSRV_OK) {
678 psMemInfo->ui32RefCount--;
679 eError = FreeDeviceMem(psMemInfo);
683 OSReleasePhysPageAddr(hOSWrapMem);
688 enum PVRSRV_ERROR PVRSRVWrapExtMemoryKM(void *hDevCookie,
689 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
690 void *hDevMemContext, u32 ui32ByteSize,
691 u32 ui32PageOffset, IMG_BOOL bPhysContig,
692 struct IMG_SYS_PHYADDR *psExtSysPAddr,
694 struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
696 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL;
697 struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
698 u32 ui32HostPageSize = HOST_PAGESIZE();
699 void *hDevMemHeap = NULL;
700 struct PVRSRV_DEVICE_NODE *psDeviceNode;
702 struct PVRSRV_MEMBLK *psMemBlock;
704 struct BM_HEAP *psBMHeap;
705 enum PVRSRV_ERROR eError;
706 void *pvPageAlignedCPUVAddr;
707 struct IMG_SYS_PHYADDR *psIntSysPAddr = NULL;
708 void *hOSWrapMem = NULL;
709 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
713 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
714 PVR_ASSERT(psDeviceNode != NULL);
716 if (psDeviceNode == NULL) {
717 PVR_DPF(PVR_DBG_ERROR,
718 "PVRSRVWrapExtMemoryKM: invalid parameter");
719 return PVRSRV_ERROR_INVALID_PARAMS;
723 get_page_details((u32)pvLinAddr, ui32ByteSize,
724 &ui32PageOffset, &page_count);
725 pvPageAlignedCPUVAddr = (void *)((u8 *) pvLinAddr -
728 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
729 page_count * sizeof(struct IMG_SYS_PHYADDR),
730 (void **)&psIntSysPAddr, NULL) != PVRSRV_OK) {
731 PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: "
732 "Failed to alloc memory for block");
733 return PVRSRV_ERROR_OUT_OF_MEMORY;
736 eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
737 page_count * ui32HostPageSize,
738 psIntSysPAddr, &hOSWrapMem);
739 if (eError != PVRSRV_OK) {
740 PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM:"
741 " Failed to alloc memory for block");
742 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
743 goto ErrorExitPhase1;
745 psExtSysPAddr = psIntSysPAddr;
746 bPhysContig = IMG_FALSE;
750 &((struct BM_CONTEXT *)hDevMemContext)->psDeviceNode->
752 psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
753 for (i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++) {
754 if (HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) ==
755 psDevMemoryInfo->ui32MappingHeapID) {
756 if (psDeviceMemoryHeap[i].DevMemHeapType ==
757 DEVICE_MEMORY_HEAP_PERCONTEXT) {
759 BM_CreateHeap(hDevMemContext,
760 &psDeviceMemoryHeap[i]);
763 psDevMemoryInfo->psDeviceMemoryHeap[i].
770 if (hDevMemHeap == NULL) {
771 PVR_DPF(PVR_DBG_ERROR,
772 "PVRSRVWrapExtMemoryKM: unable to find mapping heap");
773 eError = PVRSRV_ERROR_GENERIC;
774 goto ErrorExitPhase2;
777 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
778 sizeof(struct PVRSRV_KERNEL_MEM_INFO),
779 (void **) &psMemInfo, NULL) != PVRSRV_OK) {
780 PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: "
781 "Failed to alloc memory for block");
782 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
783 goto ErrorExitPhase2;
786 OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
787 psMemBlock = &(psMemInfo->sMemBlk);
789 bBMError = BM_Wrap(hDevMemHeap,
794 NULL, &psMemInfo->ui32Flags, &hBuffer);
796 PVR_DPF(PVR_DBG_ERROR,
797 "PVRSRVWrapExtMemoryKM: BM_Wrap Failed");
798 eError = PVRSRV_ERROR_BAD_MAPPING;
799 goto ErrorExitPhase3;
802 psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
803 psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
804 psMemBlock->hOSWrapMem = hOSWrapMem;
805 psMemBlock->psIntSysPAddr = psIntSysPAddr;
807 psMemBlock->hBuffer = (void *) hBuffer;
809 psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
810 psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
811 psMemInfo->ui32AllocSize = ui32ByteSize;
813 psMemInfo->pvSysBackupBuffer = NULL;
815 psBMHeap = (struct BM_HEAP *)hDevMemHeap;
816 hDevMemContext = (void *) psBMHeap->pBMContext;
817 eError = alloc_or_reuse_syncinfo(hDevCookie,
819 &psMemInfo->psKernelSyncInfo,
821 if (eError != PVRSRV_OK)
822 goto ErrorExitPhase4;
824 psMemInfo->ui32RefCount++;
826 psMemInfo->sMemBlk.hResItem =
827 ResManRegisterRes(psPerProc->hResManContext,
828 RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0,
829 UnwrapExtMemoryCallBack);
831 *ppsMemInfo = psMemInfo;
837 FreeDeviceMem(psMemInfo);
844 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
845 sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo,
851 OSReleasePhysPageAddr(hOSWrapMem);
855 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
856 page_count * sizeof(struct IMG_SYS_PHYADDR),
857 psIntSysPAddr, NULL);
863 enum PVRSRV_ERROR PVRSRVUnmapDeviceMemoryKM(
864 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
867 return PVRSRV_ERROR_INVALID_PARAMS;
869 ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
874 static enum PVRSRV_ERROR UnmapDeviceMemoryCallBack(void *pvParam, u32 ui32Param)
876 enum PVRSRV_ERROR eError;
877 struct RESMAN_MAP_DEVICE_MEM_DATA *psMapData = pvParam;
880 PVR_UNREFERENCED_PARAMETER(ui32Param);
882 page_count = get_page_count((u32)psMapData->psMemInfo->pvLinAddrKM,
883 psMapData->psMemInfo->ui32AllocSize);
885 if (psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
886 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
887 page_count * sizeof(struct IMG_SYS_PHYADDR),
888 psMapData->psMemInfo->sMemBlk.psIntSysPAddr, NULL);
890 eError = FreeDeviceMem(psMapData->psMemInfo);
891 if (eError != PVRSRV_OK) {
892 PVR_DPF(PVR_DBG_ERROR, "UnmapDeviceMemoryCallBack: "
893 "Failed to free DST meminfo");
897 psMapData->psSrcMemInfo->ui32RefCount--;
899 PVR_ASSERT(psMapData->psSrcMemInfo->ui32RefCount != (u32) (-1));
901 * Don't free the source MemInfo as we didn't allocate it
902 * and it's not our job as the process the allocated
903 * should also free it when it's finished
905 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
906 sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA), psMapData, NULL);
911 static inline int bm_is_continuous(const struct BM_BUF *buf)
913 return buf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr;
916 enum PVRSRV_ERROR PVRSRVMapDeviceMemoryKM(
917 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
918 struct PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
919 void *hDstDevMemHeap,
920 struct PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo)
922 enum PVRSRV_ERROR eError;
924 u32 ui32HostPageSize = HOST_PAGESIZE();
927 struct IMG_SYS_PHYADDR *psSysPAddr = NULL;
928 struct IMG_DEV_PHYADDR sDevPAddr;
929 struct BM_BUF *psBuf;
930 struct IMG_DEV_VIRTADDR sDevVAddr;
931 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL;
933 struct PVRSRV_MEMBLK *psMemBlock;
935 struct PVRSRV_DEVICE_NODE *psDeviceNode;
936 void *pvPageAlignedCPUVAddr;
937 struct RESMAN_MAP_DEVICE_MEM_DATA *psMapData = NULL;
939 if (!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo) {
940 PVR_DPF(PVR_DBG_ERROR,
941 "PVRSRVMapDeviceMemoryKM: invalid parameters");
942 return PVRSRV_ERROR_INVALID_PARAMS;
945 *ppsDstMemInfo = NULL;
947 get_page_details((u32)psSrcMemInfo->pvLinAddrKM,
948 psSrcMemInfo->ui32AllocSize,
949 &ui32PageOffset, &page_count);
950 pvPageAlignedCPUVAddr =
951 (void *) ((u8 *) psSrcMemInfo->pvLinAddrKM -
954 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
955 page_count * sizeof(struct IMG_SYS_PHYADDR),
956 (void **) &psSysPAddr, NULL) != PVRSRV_OK) {
957 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: "
958 "Failed to alloc memory for block");
959 return PVRSRV_ERROR_OUT_OF_MEMORY;
962 psBuf = psSrcMemInfo->sMemBlk.hBuffer;
964 psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
966 sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - ui32PageOffset;
967 for (i = 0; i < page_count; i++) {
969 BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
970 if (eError != PVRSRV_OK) {
971 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: "
972 "Failed to retrieve page list from device");
977 SysDevPAddrToSysPAddr(psDeviceNode->sDevId.eDeviceType,
980 sDevVAddr.uiAddr += ui32HostPageSize;
983 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
984 sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA),
985 (void **)&psMapData, NULL) != PVRSRV_OK) {
986 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: "
987 "Failed to alloc resman map data");
988 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
992 if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
993 sizeof(struct PVRSRV_KERNEL_MEM_INFO),
994 (void **)&psMemInfo, NULL) != PVRSRV_OK) {
995 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: "
996 "Failed to alloc memory for block");
997 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1001 OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
1003 psMemBlock = &(psMemInfo->sMemBlk);
1005 bBMError = BM_Wrap(hDstDevMemHeap, psSrcMemInfo->ui32AllocSize,
1006 ui32PageOffset, bm_is_continuous(psBuf), psSysPAddr,
1007 pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags,
1011 PVR_DPF(PVR_DBG_ERROR,
1012 "PVRSRVMapDeviceMemoryKM: BM_Wrap Failed");
1013 eError = PVRSRV_ERROR_BAD_MAPPING;
1017 psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
1018 psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
1020 psMemBlock->hBuffer = (void *) hBuffer;
1022 psMemBlock->psIntSysPAddr = psSysPAddr;
1024 psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
1026 psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
1027 psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize;
1028 psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
1030 psMemInfo->pvSysBackupBuffer = NULL;
1032 psSrcMemInfo->ui32RefCount++;
1034 psMapData->psMemInfo = psMemInfo;
1035 psMapData->psSrcMemInfo = psSrcMemInfo;
1037 psMemInfo->sMemBlk.hResItem =
1038 ResManRegisterRes(psPerProc->hResManContext,
1039 RESMAN_TYPE_DEVICEMEM_MAPPING, psMapData, 0,
1040 UnmapDeviceMemoryCallBack);
1042 *ppsDstMemInfo = psMemInfo;
1049 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
1050 sizeof(struct IMG_SYS_PHYADDR), psSysPAddr, NULL);
1054 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
1055 sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo,
1060 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
1061 sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA), psMapData,
1068 enum PVRSRV_ERROR PVRSRVUnmapDeviceClassMemoryKM(
1069 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
1072 return PVRSRV_ERROR_INVALID_PARAMS;
1074 ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
1079 static enum PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(void *pvParam,
1082 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
1084 PVR_UNREFERENCED_PARAMETER(ui32Param);
1086 return FreeDeviceMem(psMemInfo);
1089 enum PVRSRV_ERROR PVRSRVMapDeviceClassMemoryKM(
1090 struct PVRSRV_PER_PROCESS_DATA *psPerProc,
1091 void *hDevMemContext, void *hDeviceClassBuffer,
1092 struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
1095 enum PVRSRV_ERROR eError;
1096 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
1097 struct PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
1098 struct IMG_SYS_PHYADDR *psSysPAddr;
1099 void *pvCPUVAddr, *pvPageAlignedCPUVAddr;
1100 IMG_BOOL bPhysContig;
1101 struct BM_CONTEXT *psBMContext;
1102 struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
1103 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
1104 void *hDevMemHeap = NULL;
1107 u32 ui32PageSize = HOST_PAGESIZE();
1109 struct PVRSRV_MEMBLK *psMemBlock;
1113 if (!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo ||
1115 PVR_DPF(PVR_DBG_ERROR,
1116 "PVRSRVMapDeviceClassMemoryKM: invalid parameters");
1117 return PVRSRV_ERROR_INVALID_PARAMS;
1120 psDeviceClassBuffer = (struct PVRSRV_DEVICECLASS_BUFFER *)
1124 psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->
1126 psDeviceClassBuffer->
1127 hExtBuffer, &psSysPAddr,
1129 (void __iomem **)&pvCPUVAddr,
1130 phOSMapInfo, &bPhysContig);
1131 if (eError != PVRSRV_OK) {
1132 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: "
1133 "unable to get buffer address");
1134 return PVRSRV_ERROR_GENERIC;
1137 psBMContext = (struct BM_CONTEXT *)psDeviceClassBuffer->hDevMemContext;
1138 psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo;
1139 psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
1140 for (i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++) {
1141 if (HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) ==
1142 psDevMemoryInfo->ui32MappingHeapID) {
1143 if (psDeviceMemoryHeap[i].DevMemHeapType ==
1144 DEVICE_MEMORY_HEAP_PERCONTEXT)
1146 BM_CreateHeap(hDevMemContext,
1147 &psDeviceMemoryHeap[i]);
1150 psDevMemoryInfo->psDeviceMemoryHeap[i].
1156 if (hDevMemHeap == NULL) {
1157 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: "
1158 "unable to find mapping heap");
1159 return PVRSRV_ERROR_GENERIC;
1162 ui32Offset = ((u32)pvCPUVAddr) & (ui32PageSize - 1);
1163 pvPageAlignedCPUVAddr = (void *)((u8 *)pvCPUVAddr - ui32Offset);
1165 if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
1166 sizeof(struct PVRSRV_KERNEL_MEM_INFO),
1167 (void **)&psMemInfo, NULL) != PVRSRV_OK) {
1168 PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: "
1169 "Failed to alloc memory for block");
1170 return PVRSRV_ERROR_OUT_OF_MEMORY;
1173 OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
1175 psMemBlock = &(psMemInfo->sMemBlk);
1177 bBMError = BM_Wrap(hDevMemHeap, ui32ByteSize, ui32Offset, bPhysContig,
1178 psSysPAddr, pvPageAlignedCPUVAddr,
1179 &psMemInfo->ui32Flags, &hBuffer);
1182 PVR_DPF(PVR_DBG_ERROR,
1183 "PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed");
1184 OSFreeMem(PVRSRV_PAGEABLE_SELECT,
1185 sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo,
1187 return PVRSRV_ERROR_BAD_MAPPING;
1190 psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
1191 psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
1193 psMemBlock->hBuffer = (void *) hBuffer;
1195 psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
1197 psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
1198 psMemInfo->ui32AllocSize = ui32ByteSize;
1199 psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
1201 psMemInfo->pvSysBackupBuffer = NULL;
1203 psMemInfo->sMemBlk.hResItem =
1204 ResManRegisterRes(psPerProc->hResManContext,
1205 RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0,
1206 UnmapDeviceClassMemoryCallBack);
1208 *ppsMemInfo = psMemInfo;