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 <linux/workqueue.h>
31 #include <linux/slab.h>
32 #include <linux/sched.h>
36 #include "services_headers.h"
37 #include "buffer_manager.h"
38 #include "sgxapi_km.h"
40 #include "sgxinfokm.h"
41 #include "sgxconfig.h"
42 #include "sysconfig.h"
43 #include "pvr_bridge_km.h"
44 #include "sgx_bridge_km.h"
54 #include "pvrversion.h"
55 #include "sgx_options.h"
57 static IMG_BOOL SGX_ISRHandler(void *pvData);
59 static u32 gui32EventStatusServicesByISR;
61 static enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
62 struct PVRSRV_DEVICE_NODE *psDeviceNode);
64 static void SGXCommandComplete(struct PVRSRV_DEVICE_NODE *psDeviceNode)
68 SGXScheduleProcessQueuesKM(psDeviceNode);
71 static u32 DeinitDevInfo(struct PVRSRV_SGXDEV_INFO *psDevInfo)
73 if (psDevInfo->psKernelCCBInfo != NULL)
74 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
75 sizeof(struct PVRSRV_SGX_CCB_INFO),
76 psDevInfo->psKernelCCBInfo, NULL);
81 static enum PVRSRV_ERROR InitDevInfo(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
82 struct PVRSRV_DEVICE_NODE *psDeviceNode,
83 struct SGX_BRIDGE_INIT_INFO *psInitInfo)
85 struct PVRSRV_SGXDEV_INFO *psDevInfo =
86 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
87 enum PVRSRV_ERROR eError;
89 struct PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = NULL;
91 PVR_UNREFERENCED_PARAMETER(psPerProc);
92 psDevInfo->sScripts = psInitInfo->sScripts;
94 psDevInfo->psKernelCCBMemInfo =
95 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
96 psDevInfo->psKernelCCB =
97 (struct PVRSRV_SGX_KERNEL_CCB *)psDevInfo->psKernelCCBMemInfo->
100 psDevInfo->psKernelCCBCtlMemInfo =
101 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
102 psDevInfo->psKernelCCBCtl =
103 (struct PVRSRV_SGX_CCB_CTL *)psDevInfo->psKernelCCBCtlMemInfo->
106 psDevInfo->psKernelCCBEventKickerMemInfo =
107 (struct PVRSRV_KERNEL_MEM_INFO *)
108 psInitInfo->hKernelCCBEventKickerMemInfo;
109 psDevInfo->pui32KernelCCBEventKicker =
110 (u32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
112 psDevInfo->psKernelSGXHostCtlMemInfo =
113 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
114 hKernelSGXHostCtlMemInfo;
115 psDevInfo->psSGXHostCtl = (struct SGXMKIF_HOST_CTL __force __iomem *)
116 psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
118 psDevInfo->psKernelSGXTA3DCtlMemInfo =
119 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
120 hKernelSGXTA3DCtlMemInfo;
122 psDevInfo->psKernelSGXMiscMemInfo =
123 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
125 psDevInfo->psKernelHWPerfCBMemInfo =
126 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
127 #ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
128 psDevInfo->psKernelEDMStatusBufferMemInfo =
129 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
130 hKernelEDMStatusBufferMemInfo;
133 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
134 sizeof(struct PVRSRV_SGX_CCB_INFO),
135 (void **)&psKernelCCBInfo, NULL);
136 if (eError != PVRSRV_OK) {
137 PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory");
138 goto failed_allockernelccb;
141 OSMemSet(psKernelCCBInfo, 0, sizeof(struct PVRSRV_SGX_CCB_INFO));
142 psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
143 psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
144 psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
145 psKernelCCBInfo->pui32WriteOffset =
146 &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
147 psKernelCCBInfo->pui32ReadOffset =
148 &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
149 psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
151 psDevInfo->ui32HostKickAddress = psInitInfo->ui32HostKickAddress;
153 psDevInfo->ui32GetMiscInfoAddress = psInitInfo->ui32GetMiscInfoAddress;
155 psDevInfo->bForcePTOff = IMG_FALSE;
157 psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
159 psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
160 psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
161 psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
162 psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
164 OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData,
165 sizeof(psDevInfo->asSGXDevData));
169 failed_allockernelccb:
170 DeinitDevInfo(psDevInfo);
175 static enum PVRSRV_ERROR SGXRunScript(struct PVRSRV_SGXDEV_INFO *psDevInfo,
176 union SGX_INIT_COMMAND *psScript,
177 u32 ui32NumInitCommands)
180 union SGX_INIT_COMMAND *psComm;
182 for (ui32PC = 0, psComm = psScript;
183 ui32PC < ui32NumInitCommands; ui32PC++, psComm++) {
184 switch (psComm->eOp) {
185 case SGX_INIT_OP_WRITE_HW_REG:
187 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
188 psComm->sWriteHWReg.ui32Offset,
189 psComm->sWriteHWReg.ui32Value);
190 PDUMPREG(psComm->sWriteHWReg.ui32Offset,
191 psComm->sWriteHWReg.ui32Value);
195 case SGX_INIT_OP_PDUMP_HW_REG:
197 PDUMPREG(psComm->sPDumpHWReg.ui32Offset,
198 psComm->sPDumpHWReg.ui32Value);
202 case SGX_INIT_OP_HALT:
206 case SGX_INIT_OP_ILLEGAL:
210 PVR_DPF(PVR_DBG_ERROR,
211 "SGXRunScript: PC %d: Illegal command: %d",
212 ui32PC, psComm->eOp);
213 return PVRSRV_ERROR_GENERIC;
219 return PVRSRV_ERROR_GENERIC;
222 enum PVRSRV_ERROR SGXInitialise(struct PVRSRV_SGXDEV_INFO *psDevInfo,
223 IMG_BOOL bHardwareRecovery)
225 enum PVRSRV_ERROR eError;
227 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
228 "SGX initialisation script part 1\n");
230 SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1,
231 SGX_MAX_INIT_COMMANDS);
232 if (eError != PVRSRV_OK) {
233 PVR_DPF(PVR_DBG_ERROR,
234 "SGXInitialise: SGXRunScript (part 1) failed (%d)",
236 return PVRSRV_ERROR_GENERIC;
238 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
239 "End of SGX initialisation script part 1\n");
241 SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
245 *psDevInfo->pui32KernelCCBEventKicker = 0;
247 PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
248 sizeof(*psDevInfo->pui32KernelCCBEventKicker),
249 PDUMP_FLAGS_CONTINUOUS,
250 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
253 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
254 "SGX initialisation script part 2\n");
256 SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2,
257 SGX_MAX_INIT_COMMANDS);
258 if (eError != PVRSRV_OK) {
259 PVR_DPF(PVR_DBG_ERROR,
260 "SGXInitialise: SGXRunScript (part 2) failed (%d)",
262 return PVRSRV_ERROR_GENERIC;
264 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
265 "End of SGX initialisation script part 2\n");
267 SGXStartTimer(psDevInfo, (IMG_BOOL)!bHardwareRecovery);
269 if (bHardwareRecovery) {
270 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
271 psDevInfo->psSGXHostCtl;
273 if (PollForValueKM(&psSGXHostCtl->ui32InterruptClearFlags, 0,
274 PVRSRV_USSE_EDM_INTERRUPT_HWR,
275 MAX_HW_TIME_US / WAIT_TRY_COUNT, 1000) != PVRSRV_OK) {
276 PVR_DPF(PVR_DBG_ERROR, "SGXInitialise: "
277 "Wait for uKernel HW Recovery failed");
279 return PVRSRV_ERROR_RETRY;
283 PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset ==
284 psDevInfo->psKernelCCBCtl->ui32WriteOffset);
289 enum PVRSRV_ERROR SGXDeinitialise(void *hDevCookie)
291 struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
293 enum PVRSRV_ERROR eError;
295 if (psDevInfo->pvRegsBaseKM == NULL)
298 eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands,
299 SGX_MAX_DEINIT_COMMANDS);
300 if (eError != PVRSRV_OK) {
301 PVR_DPF(PVR_DBG_ERROR,
302 "SGXDeinitialise: SGXRunScript failed (%d)", eError);
303 return PVRSRV_ERROR_GENERIC;
309 static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
311 struct PVRSRV_SGXDEV_INFO *psDevInfo;
312 void *hKernelDevMemContext;
313 struct IMG_DEV_PHYADDR sPDDevPAddr;
315 struct PVRSRV_DEVICE_NODE *psDeviceNode = (struct PVRSRV_DEVICE_NODE *)
317 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap =
318 psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
319 enum PVRSRV_ERROR eError;
321 PDUMPCOMMENT("SGX Initialisation Part 1");
323 PDUMPCOMMENT("SGX Core Version Information: %s",
324 SGX_CORE_FRIENDLY_NAME);
325 PDUMPCOMMENT("SGX Core Revision Information: multi rev support");
327 if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
328 sizeof(struct PVRSRV_SGXDEV_INFO),
329 (void **)&psDevInfo, NULL) != PVRSRV_OK) {
330 PVR_DPF(PVR_DBG_ERROR,
331 "DevInitSGXPart1 : Failed to alloc memory for DevInfo");
332 return PVRSRV_ERROR_OUT_OF_MEMORY;
334 OSMemSet(psDevInfo, 0, sizeof(struct PVRSRV_SGXDEV_INFO));
336 psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
337 psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
339 psDeviceNode->pvDevice = (void *) psDevInfo;
341 psDevInfo->pvDeviceMemoryHeap = (void *) psDeviceMemoryHeap;
343 hKernelDevMemContext = BM_CreateContext(psDeviceNode, &sPDDevPAddr,
346 psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
348 for (i = 0; i < psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) {
351 switch (psDeviceMemoryHeap[i].DevMemHeapType) {
352 case DEVICE_MEMORY_HEAP_KERNEL:
353 case DEVICE_MEMORY_HEAP_SHARED:
354 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
357 BM_CreateHeap(hKernelDevMemContext,
358 &psDeviceMemoryHeap[i]);
360 psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
366 eError = MMU_BIFResetPDAlloc(psDevInfo);
367 if (eError != PVRSRV_OK) {
368 PVR_DPF(PVR_DBG_ERROR,
369 "DevInitSGX : Failed to alloc memory for BIF reset");
370 return PVRSRV_ERROR_GENERIC;
376 enum PVRSRV_ERROR SGXGetInfoForSrvinitKM(void *hDevHandle,
377 struct SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
379 struct PVRSRV_DEVICE_NODE *psDeviceNode;
380 struct PVRSRV_SGXDEV_INFO *psDevInfo;
381 enum PVRSRV_ERROR eError;
383 PDUMPCOMMENT("SGXGetInfoForSrvinit");
385 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
386 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
388 psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
391 PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
392 if (eError != PVRSRV_OK) {
393 PVR_DPF(PVR_DBG_ERROR, "SGXGetInfoForSrvinit: "
394 "PVRSRVGetDeviceMemHeapsKM failed (%d)",
396 return PVRSRV_ERROR_GENERIC;
402 enum PVRSRV_ERROR DevInitSGXPart2KM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
404 struct SGX_BRIDGE_INIT_INFO *psInitInfo)
406 struct PVRSRV_DEVICE_NODE *psDeviceNode;
407 struct PVRSRV_SGXDEV_INFO *psDevInfo;
408 enum PVRSRV_ERROR eError;
409 struct SGX_DEVICE_MAP *psSGXDeviceMap;
410 enum PVR_POWER_STATE eDefaultPowerState;
413 PDUMPCOMMENT("SGX Initialisation Part 2");
415 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
416 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
418 eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
419 if (eError != PVRSRV_OK) {
420 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
421 "Failed to load EDM program");
422 goto failed_init_dev_info;
426 eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
427 (void **) &psSGXDeviceMap);
428 if (eError != PVRSRV_OK) {
429 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
430 "Failed to get device memory map!");
431 return PVRSRV_ERROR_INIT_FAILURE;
434 if (psSGXDeviceMap->pvRegsCpuVBase) {
435 psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
437 psDevInfo->pvRegsBaseKM =
438 OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
439 psSGXDeviceMap->ui32RegsSize,
440 PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
442 if (!psDevInfo->pvRegsBaseKM) {
443 PVR_DPF(PVR_DBG_ERROR,
444 "DevInitSGXPart2KM: Failed to map in regs\n");
445 return PVRSRV_ERROR_BAD_MAPPING;
448 psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
449 psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
451 psDeviceNode->pvISRData = psDeviceNode;
453 PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
456 l = readl(&psDevInfo->psSGXHostCtl->ui32PowerStatus);
457 l |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
458 writel(l, &psDevInfo->psSGXHostCtl->ui32PowerStatus);
460 eDefaultPowerState = PVRSRV_POWER_STATE_D3;
462 eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
464 SGXPostPowerStateExt,
465 SGXPreClockSpeedChange,
466 SGXPostClockSpeedChange,
467 (void *) psDeviceNode,
468 PVRSRV_POWER_STATE_D3,
470 if (eError != PVRSRV_OK) {
471 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
472 "failed to register device with power manager");
476 OSMemSet(psDevInfo->psKernelCCB, 0,
477 sizeof(struct PVRSRV_SGX_KERNEL_CCB));
478 OSMemSet(psDevInfo->psKernelCCBCtl, 0,
479 sizeof(struct PVRSRV_SGX_CCB_CTL));
480 OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0,
481 sizeof(*psDevInfo->pui32KernelCCBEventKicker));
482 PDUMPCOMMENT("Initialise Kernel CCB");
483 PDUMPMEM(NULL, psDevInfo->psKernelCCBMemInfo, 0,
484 sizeof(struct PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
485 MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
486 PDUMPCOMMENT("Initialise Kernel CCB Control");
487 PDUMPMEM(NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
488 sizeof(struct PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
489 MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
490 PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
491 PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
492 sizeof(*psDevInfo->pui32KernelCCBEventKicker),
493 PDUMP_FLAGS_CONTINUOUS,
494 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
496 psDevInfo->hTimer = SGXOSTimerInit(psDeviceNode);
497 if (!psDevInfo->hTimer)
498 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM : "
499 "Failed to initialize HW recovery timer");
503 failed_init_dev_info:
507 static enum PVRSRV_ERROR DevDeInitSGX(void *pvDeviceNode)
509 struct PVRSRV_DEVICE_NODE *psDeviceNode =
510 (struct PVRSRV_DEVICE_NODE *)pvDeviceNode;
511 struct PVRSRV_SGXDEV_INFO *psDevInfo =
512 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
513 enum PVRSRV_ERROR eError;
515 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
516 struct SGX_DEVICE_MAP *psSGXDeviceMap;
519 PVR_DPF(PVR_DBG_ERROR, "DevDeInitSGX: Null DevInfo");
522 if (psDevInfo->hTimer) {
523 SGXOSTimerCancel(psDevInfo->hTimer);
524 SGXOSTimerDeInit(psDevInfo->hTimer);
525 psDevInfo->hTimer = NULL;
528 MMU_BIFResetPDFree(psDevInfo);
530 DeinitDevInfo(psDevInfo);
534 (struct DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
536 ui32Heap < psDeviceNode->sDevMemoryInfo.ui32HeapCount;
538 switch (psDeviceMemoryHeap[ui32Heap].DevMemHeapType) {
539 case DEVICE_MEMORY_HEAP_KERNEL:
540 case DEVICE_MEMORY_HEAP_SHARED:
541 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
543 if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap !=
545 BM_DestroyHeap(psDeviceMemoryHeap
546 [ui32Heap].hDevMemHeap);
552 if (!pvr_put_ctx(psDeviceNode->sDevMemoryInfo.pBMKernelContext))
553 pr_err("%s: kernel context still in use, can't free it",
556 eError = PVRSRVRemovePowerDevice(
557 ((struct PVRSRV_DEVICE_NODE *)pvDeviceNode)->
558 sDevId.ui32DeviceIndex);
559 if (eError != PVRSRV_OK)
562 eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
563 (void **)&psSGXDeviceMap);
564 if (eError != PVRSRV_OK) {
565 PVR_DPF(PVR_DBG_ERROR,
566 "DevDeInitSGX: Failed to get device memory map!");
570 if (!psSGXDeviceMap->pvRegsCpuVBase)
571 if (psDevInfo->pvRegsBaseKM != NULL)
572 OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
573 psDevInfo->ui32RegSize,
574 PVRSRV_HAP_KERNEL_ONLY |
578 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
579 sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
581 psDeviceNode->pvDevice = NULL;
583 if (psDeviceMemoryHeap != NULL)
584 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
585 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
586 psDeviceNode->sDevMemoryInfo.ui32HeapCount,
587 psDeviceMemoryHeap, NULL);
592 #ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
594 #define SGXMK_TRACE_BUFFER_SIZE 512
596 static void dump_edm(struct PVRSRV_SGXDEV_INFO *psDevInfo)
599 psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
600 u32 last_code, write_offset;
603 last_code = *trace_buffer;
605 write_offset = *trace_buffer;
607 pr_err("Last SGX microkernel status code: 0x%x\n", last_code);
610 /* Dump the status values */
612 for (i = 0; i < SGXMK_TRACE_BUFFER_SIZE; i++) {
614 buf = trace_buffer + (((write_offset + i) %
615 SGXMK_TRACE_BUFFER_SIZE) * 4);
616 pr_err("(MKT%u) %8.8X %8.8X %8.8X %8.8X\n", i,
617 buf[2], buf[3], buf[1], buf[0]);
621 static void dump_edm(struct PVRSRV_SGXDEV_INFO *psDevInfo) {}
624 static void dump_process_info(struct PVRSRV_DEVICE_NODE *dev)
626 struct PVRSRV_SGXDEV_INFO *dev_info = dev->pvDevice;
627 u32 page_dir = readl(dev_info->pvRegsBaseKM +
628 EUR_CR_BIF_DIR_LIST_BASE0);
629 struct BM_CONTEXT *bm_ctx;
630 struct RESMAN_CONTEXT *res_ctx = NULL;
632 bm_ctx = bm_find_context(dev->sDevMemoryInfo.pBMContext, page_dir);
634 res_ctx = pvr_get_resman_ctx(bm_ctx);
637 struct task_struct *tsk;
638 struct PVRSRV_PER_PROCESS_DATA *proc;
641 proc = pvr_get_proc_by_ctx(res_ctx);
644 tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
645 pr_err("PID = %d, process name = %s\n", pid, tsk->comm);
650 static void dump_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
652 pr_err("EVENT_STATUS = 0x%08X\n"
653 "EVENT_STATUS2 = 0x%08X\n"
654 "BIF_CTRL = 0x%08X\n"
655 "BIF_INT_STAT = 0x%08X\n"
656 "BIF_MEM_REQ_STAT = 0x%08X\n"
657 "BIF_FAULT = 0x%08X\n"
658 "CLKGATECTL = 0x%08X\n",
659 readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS),
660 readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS2),
661 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_CTRL),
662 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_INT_STAT),
663 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
664 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_FAULT),
665 readl(psDevInfo->pvRegsBaseKM + EUR_CR_CLKGATECTL));
668 /* Should be called with pvr_lock held */
669 void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode)
671 enum PVRSRV_ERROR eError;
672 struct PVRSRV_SGXDEV_INFO *psDevInfo =
673 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
674 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
675 psDevInfo->psSGXHostCtl;
677 int max_retries = 10;
679 BUG_ON(!pvr_is_locked());
681 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
682 l |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
683 writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
685 pr_err("%s: SGX Hardware Recovery triggered\n", __func__);
687 dump_process_info(psDeviceNode);
688 dump_sgx_registers(psDevInfo);
694 eError = SGXInitialise(psDevInfo, IMG_TRUE);
695 if (eError != PVRSRV_ERROR_RETRY)
697 } while (max_retries--);
699 if (eError != PVRSRV_OK) {
700 pr_err("%s: recovery failed (%d). Disabling the driver",
711 SGXScheduleProcessQueues(psDeviceNode);
713 PVRSRVProcessQueues(IMG_TRUE);
716 static unsigned long sgx_reset_forced;
718 static void SGXOSTimer(struct work_struct *work)
720 struct timer_work_data *data = container_of(work,
721 struct timer_work_data,
723 struct PVRSRV_DEVICE_NODE *psDeviceNode = data->psDeviceNode;
724 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
725 static u32 ui32EDMTasks;
726 static u32 ui32LockupCounter;
727 static u32 ui32NumResets;
728 u32 ui32CurrentEDMTasks;
729 IMG_BOOL bLockup = IMG_FALSE;
730 IMG_BOOL bPoweredDown;
734 if (!data->armed || pvr_is_disabled()) {
739 psDevInfo->ui32TimeStamp++;
741 #if defined(NO_HARDWARE)
742 bPoweredDown = IMG_TRUE;
744 bPoweredDown = (IMG_BOOL) !SGXIsDevicePowered(psDeviceNode);
748 ui32LockupCounter = 0;
751 ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM,
752 psDevInfo->ui32EDMTaskReg0);
753 if (psDevInfo->ui32EDMTaskReg1 != 0)
754 ui32CurrentEDMTasks ^=
755 OSReadHWReg(psDevInfo->pvRegsBaseKM,
756 psDevInfo->ui32EDMTaskReg1);
757 if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
758 (psDevInfo->ui32NumResets == ui32NumResets)) {
760 if (ui32LockupCounter == 3) {
761 ui32LockupCounter = 0;
762 PVR_DPF(PVR_DBG_ERROR, "SGXOSTimer() "
763 "detected SGX lockup (0x%x tasks)",
769 ui32LockupCounter = 0;
770 ui32EDMTasks = ui32CurrentEDMTasks;
771 ui32NumResets = psDevInfo->ui32NumResets;
776 bLockup |= cmpxchg(&sgx_reset_forced, 1, 0);
779 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
780 psDevInfo->psSGXHostCtl;
784 l = readl(&psSGXHostCtl->ui32HostDetectedLockups);
786 writel(l, &psSGXHostCtl->ui32HostDetectedLockups);
788 HWRecoveryResetSGX(psDeviceNode);
792 queue_delayed_work(data->work_queue, &data->work,
793 msecs_to_jiffies(data->interval));
798 struct timer_work_data *
799 SGXOSTimerInit(struct PVRSRV_DEVICE_NODE *psDeviceNode)
801 struct timer_work_data *data;
803 data = kzalloc(sizeof(struct timer_work_data), GFP_KERNEL);
807 data->work_queue = create_workqueue("SGXOSTimer");
808 if (!data->work_queue) {
813 data->interval = 150;
814 data->psDeviceNode = psDeviceNode;
815 INIT_DELAYED_WORK(&data->work, SGXOSTimer);
820 void SGXOSTimerDeInit(struct timer_work_data *data)
823 destroy_workqueue(data->work_queue);
827 enum PVRSRV_ERROR SGXOSTimerEnable(struct timer_work_data *data)
830 return PVRSRV_ERROR_GENERIC;
832 if (queue_delayed_work(data->work_queue, &data->work,
833 msecs_to_jiffies(data->interval))) {
838 return PVRSRV_ERROR_GENERIC;
841 enum PVRSRV_ERROR SGXOSTimerCancel(struct timer_work_data *data)
844 return PVRSRV_ERROR_GENERIC;
847 cancel_delayed_work(&data->work);
852 int sgx_force_reset(void)
854 return !cmpxchg(&sgx_reset_forced, 0, 1);
857 static IMG_BOOL SGX_ISRHandler(void *pvData)
859 IMG_BOOL bInterruptProcessed = IMG_FALSE;
862 u32 ui32EventStatus, ui32EventEnable;
863 u32 ui32EventClear = 0;
864 struct PVRSRV_DEVICE_NODE *psDeviceNode;
865 struct PVRSRV_SGXDEV_INFO *psDevInfo;
867 if (pvData == NULL) {
868 PVR_DPF(PVR_DBG_ERROR,
869 "SGX_ISRHandler: Invalid params\n");
870 return bInterruptProcessed;
873 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)pvData;
874 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
877 OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
878 ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM,
879 EUR_CR_EVENT_HOST_ENABLE);
881 gui32EventStatusServicesByISR = ui32EventStatus;
883 ui32EventStatus &= ui32EventEnable;
885 if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
886 ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
888 if (ui32EventClear) {
889 bInterruptProcessed = IMG_TRUE;
892 EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
894 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
895 EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
899 return bInterruptProcessed;
902 static void SGX_MISRHandler(void *pvData)
904 struct PVRSRV_DEVICE_NODE *psDeviceNode =
905 (struct PVRSRV_DEVICE_NODE *)pvData;
906 struct PVRSRV_SGXDEV_INFO *psDevInfo =
907 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
908 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
909 psDevInfo->psSGXHostCtl;
912 enum PVRSRV_ERROR err;
914 dev_idx = psDeviceNode->sDevId.ui32DeviceIndex;
918 err = PVRSRVSetDevicePowerStateKM(dev_idx, PVRSRV_POWER_STATE_D0);
919 BUG_ON(err != PVRSRV_OK);
921 l1 = readl(&psSGXHostCtl->ui32InterruptFlags);
922 l2 = readl(&psSGXHostCtl->ui32InterruptClearFlags);
924 if ((l1 & PVRSRV_USSE_EDM_INTERRUPT_HWR) &&
925 !(l2 & PVRSRV_USSE_EDM_INTERRUPT_HWR))
926 HWRecoveryResetSGX(psDeviceNode);
928 if (psDeviceNode->bReProcessDeviceCommandComplete)
929 SGXScheduleProcessQueues(psDeviceNode);
931 SGXTestActivePowerEvent(psDeviceNode);
936 enum PVRSRV_ERROR SGXRegisterDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode)
938 struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
939 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
941 psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
942 psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
944 psDeviceNode->pfnInitDevice = DevInitSGXPart1;
945 psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
947 psDeviceNode->pfnInitDeviceCompatCheck = SGXDevInitCompatCheck;
949 psDeviceNode->pfnMMUInitialise = MMU_Initialise;
950 psDeviceNode->pfnMMUFinalise = MMU_Finalise;
951 psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
952 psDeviceNode->pfnMMUCreate = MMU_Create;
953 psDeviceNode->pfnMMUDelete = MMU_Delete;
954 psDeviceNode->pfnMMUAlloc = MMU_Alloc;
955 psDeviceNode->pfnMMUFree = MMU_Free;
956 psDeviceNode->pfnMMUMapPages = MMU_MapPages;
957 psDeviceNode->pfnMMUMapShadow = MMU_MapShadow;
958 psDeviceNode->pfnMMUUnmapPages = MMU_UnmapPages;
959 psDeviceNode->pfnMMUMapScatter = MMU_MapScatter;
960 psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
961 psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
963 psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
964 psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
966 psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
968 psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
970 psDevMemoryInfo->ui32AddressSpaceSizeLog2 =
971 SGX_FEATURE_ADDRESS_SPACE_SIZE;
973 psDevMemoryInfo->ui32Flags = 0;
974 psDevMemoryInfo->ui32HeapCount = SGX_MAX_HEAP_ID;
975 psDevMemoryInfo->ui32SyncHeapID = SGX_SYNCINFO_HEAP_ID;
977 psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_HEAP_ID;
979 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
980 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
981 psDevMemoryInfo->ui32HeapCount,
982 (void **) &psDevMemoryInfo->psDeviceMemoryHeap,
983 NULL) != PVRSRV_OK) {
984 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterDevice : "
985 "Failed to alloc memory for "
986 "struct DEVICE_MEMORY_HEAP_INFO");
987 return PVRSRV_ERROR_OUT_OF_MEMORY;
989 OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0,
990 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
991 psDevMemoryInfo->ui32HeapCount);
993 psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
995 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapID =
996 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
997 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].sDevVAddrBase.uiAddr =
998 SGX_GENERAL_HEAP_BASE;
999 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapSize =
1000 SGX_GENERAL_HEAP_SIZE;
1001 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32Attribs =
1002 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1003 PVRSRV_HAP_SINGLE_PROCESS;
1004 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszName = "General";
1005 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszBSName = "General BS";
1006 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].DevMemHeapType =
1007 DEVICE_MEMORY_HEAP_PERCONTEXT;
1009 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32DataPageSize =
1012 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapID =
1013 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
1014 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].sDevVAddrBase.uiAddr =
1015 SGX_TADATA_HEAP_BASE;
1016 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapSize =
1017 SGX_TADATA_HEAP_SIZE;
1018 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32Attribs =
1019 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
1020 | PVRSRV_HAP_MULTI_PROCESS;
1021 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszName = "TA Data";
1022 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszBSName = "TA Data BS";
1023 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].DevMemHeapType =
1024 DEVICE_MEMORY_HEAP_PERCONTEXT;
1026 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32DataPageSize =
1029 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapID =
1030 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
1031 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
1032 SGX_KERNEL_CODE_HEAP_BASE;
1033 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapSize =
1034 SGX_KERNEL_CODE_HEAP_SIZE;
1035 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32Attribs =
1036 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1037 PVRSRV_HAP_MULTI_PROCESS;
1038 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel Code";
1039 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName =
1041 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].DevMemHeapType =
1042 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1044 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32DataPageSize =
1047 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapID =
1048 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
1049 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
1050 SGX_KERNEL_DATA_HEAP_BASE;
1051 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapSize =
1052 SGX_KERNEL_DATA_HEAP_SIZE;
1053 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32Attribs =
1054 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1055 PVRSRV_HAP_MULTI_PROCESS;
1056 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszName = "KernelData";
1057 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszBSName = "KernelData BS";
1058 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].DevMemHeapType =
1059 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1061 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32DataPageSize =
1064 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapID =
1065 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
1066 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1067 SGX_PIXELSHADER_HEAP_BASE;
1068 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapSize =
1069 SGX_PIXELSHADER_HEAP_SIZE;
1070 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32Attribs =
1071 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1072 PVRSRV_HAP_SINGLE_PROCESS;
1073 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszName = "PixelShaderUSSE";
1074 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszBSName =
1075 "PixelShaderUSSE BS";
1076 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].DevMemHeapType =
1077 DEVICE_MEMORY_HEAP_PERCONTEXT;
1079 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32DataPageSize =
1082 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapID =
1083 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
1084 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1085 SGX_VERTEXSHADER_HEAP_BASE;
1086 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapSize =
1087 SGX_VERTEXSHADER_HEAP_SIZE;
1088 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32Attribs =
1089 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1090 PVRSRV_HAP_SINGLE_PROCESS;
1091 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszName =
1093 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszBSName =
1094 "VertexShaderUSSE BS";
1095 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].DevMemHeapType =
1096 DEVICE_MEMORY_HEAP_PERCONTEXT;
1098 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32DataPageSize =
1101 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapID =
1102 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
1103 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].sDevVAddrBase.uiAddr =
1104 SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
1105 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapSize =
1106 SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
1107 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32Attribs =
1108 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1109 PVRSRV_HAP_SINGLE_PROCESS;
1110 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszName =
1112 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszBSName =
1113 "PDSPixelCodeData BS";
1114 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].DevMemHeapType =
1115 DEVICE_MEMORY_HEAP_PERCONTEXT;
1117 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32DataPageSize =
1120 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapID =
1121 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
1122 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].sDevVAddrBase.
1123 uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
1124 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapSize =
1125 SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
1126 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32Attribs =
1127 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1128 PVRSRV_HAP_SINGLE_PROCESS;
1129 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszName =
1130 "PDSVertexCodeData";
1131 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszBSName =
1132 "PDSVertexCodeData BS";
1133 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].DevMemHeapType =
1134 DEVICE_MEMORY_HEAP_PERCONTEXT;
1136 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32DataPageSize =
1139 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapID =
1140 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
1141 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].sDevVAddrBase.uiAddr =
1142 SGX_SYNCINFO_HEAP_BASE;
1143 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapSize =
1144 SGX_SYNCINFO_HEAP_SIZE;
1146 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32Attribs =
1147 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1148 PVRSRV_HAP_MULTI_PROCESS;
1149 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszName = "CacheCoherent";
1150 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszBSName = "CacheCoherent BS";
1152 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].DevMemHeapType =
1153 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1155 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32DataPageSize =
1158 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapID =
1159 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
1160 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].sDevVAddrBase.uiAddr =
1161 SGX_3DPARAMETERS_HEAP_BASE;
1162 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapSize =
1163 SGX_3DPARAMETERS_HEAP_SIZE;
1164 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszName = "3DParameters";
1165 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszBSName =
1167 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
1168 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1169 PVRSRV_HAP_SINGLE_PROCESS;
1170 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
1171 DEVICE_MEMORY_HEAP_PERCONTEXT;
1173 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32DataPageSize =
1179 enum PVRSRV_ERROR SGXGetClientInfoKM(void *hDevCookie,
1180 struct SGX_CLIENT_INFO *psClientInfo)
1182 struct PVRSRV_SGXDEV_INFO *psDevInfo =
1183 (struct PVRSRV_SGXDEV_INFO *)
1184 ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
1186 psDevInfo->ui32ClientRefCount++;
1188 if (psDevInfo->ui32ClientRefCount == 1)
1189 psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
1191 psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
1193 OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData,
1194 sizeof(psClientInfo->asDevData));
1199 enum PVRSRV_ERROR SGXDevInitCompatCheck(struct PVRSRV_DEVICE_NODE *psDeviceNode)
1201 struct PVRSRV_SGXDEV_INFO *psDevInfo;
1202 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
1203 enum PVRSRV_ERROR eError;
1204 #if !defined(NO_HARDWARE)
1205 u32 ui32BuildOptions, ui32BuildOptionsMismatch;
1206 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1209 if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX) {
1210 PVR_DPF(PVR_DBG_ERROR,
1211 "SGXDevInitCompatCheck: Device not of type SGX");
1212 eError = PVRSRV_ERROR_INVALID_PARAMS;
1215 psDevInfo = psDeviceNode->pvDevice;
1216 psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
1218 #if !defined(NO_HARDWARE)
1220 eError = SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
1221 if (eError != PVRSRV_OK) {
1222 PVR_DPF(PVR_DBG_ERROR, "SGXDevInitCompatCheck: "
1223 "Unable to validate device DDK version");
1227 &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->pvLinAddrKM))->
1229 if ((psSGXFeatures->ui32DDKVersion !=
1230 ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8) |
1231 PVRVERSION_BRANCH)) ||
1232 (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD)) {
1233 PVR_DPF(PVR_DBG_ERROR, "SGXDevInitCompatCheck: "
1234 "Incompatible driver DDK revision (%ld)"
1235 "/device DDK revision (%ld).",
1236 PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
1237 eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
1240 PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
1241 "driver DDK (%ld) and device DDK (%ld) match",
1242 PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
1245 ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
1246 if (ui32BuildOptions != (SGX_BUILD_OPTIONS)) {
1247 ui32BuildOptionsMismatch =
1248 ui32BuildOptions ^ (SGX_BUILD_OPTIONS);
1249 if (((SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch) != 0)
1250 PVR_DPF(PVR_DBG_ERROR, "SGXInit: "
1251 "Mismatch in driver and microkernel build "
1252 "options; extra options present in driver: "
1254 (SGX_BUILD_OPTIONS) &
1255 ui32BuildOptionsMismatch);
1257 if ((ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
1258 PVR_DPF(PVR_DBG_ERROR, "SGXInit: "
1259 "Mismatch in driver and microkernel build "
1260 "options; extra options present in "
1261 "microkernel: (0x%lx)",
1262 ui32BuildOptions & ui32BuildOptionsMismatch);
1263 eError = PVRSRV_ERROR_BUILD_MISMATCH;
1266 PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
1267 "Driver and microkernel build options match.");
1277 enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
1278 struct PVRSRV_DEVICE_NODE *psDeviceNode)
1280 enum PVRSRV_ERROR eError;
1281 struct SGXMKIF_COMMAND sCommandData;
1282 struct PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
1283 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1285 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1286 psDevInfo->psKernelSGXMiscMemInfo;
1288 if (!psMemInfo->pvLinAddrKM) {
1289 PVR_DPF(PVR_DBG_ERROR, "SGXGetMiscInfoKM: Invalid address.");
1290 return PVRSRV_ERROR_INVALID_PARAMS;
1292 psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
1293 psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
1294 psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
1296 OSMemSet(psMemInfo->pvLinAddrKM, 0,
1297 sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
1299 sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
1301 OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
1305 eError = SGXScheduleCCBCommandKM(psDeviceNode,
1306 SGXMKIF_COMMAND_REQUEST_SGXMISCINFO,
1307 &sCommandData, KERNEL_ID, 0);
1309 if (eError != PVRSRV_OK) {
1310 PVR_DPF(PVR_DBG_ERROR,
1311 "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed.");
1315 #if !defined(NO_HARDWARE)
1317 IMG_BOOL bTimeout = IMG_TRUE;
1319 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
1320 if ((psSGXMiscInfoInt->
1321 ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) !=
1323 bTimeout = IMG_FALSE;
1327 END_LOOP_UNTIL_TIMEOUT();
1330 return PVRSRV_ERROR_TIMEOUT;
1337 enum PVRSRV_ERROR SGXGetMiscInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
1338 struct SGX_MISC_INFO *psMiscInfo,
1339 struct PVRSRV_DEVICE_NODE *psDeviceNode)
1341 switch (psMiscInfo->eRequest) {
1342 case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
1344 psMiscInfo->uData.ui32SGXClockSpeed =
1345 psDevInfo->ui32CoreClockSpeed;
1349 case SGX_MISC_INFO_REQUEST_SGXREV:
1351 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1352 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1353 psDevInfo->psKernelSGXMiscMemInfo;
1355 SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
1357 &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->
1358 pvLinAddrKM))->sSGXFeatures;
1360 psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
1362 PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
1363 "Core 0x%lx, sw ID 0x%lx, "
1365 psSGXFeatures->ui32CoreRev,
1366 psSGXFeatures->ui32CoreIdSW,
1367 psSGXFeatures->ui32CoreRevSW);
1368 PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
1369 "DDK version 0x%lx, DDK build 0x%lx\n",
1370 psSGXFeatures->ui32DDKVersion,
1371 psSGXFeatures->ui32DDKBuild);
1376 case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
1378 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1379 psDevInfo->psKernelSGXMiscMemInfo;
1380 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1382 psSGXFeatures = &((struct PVRSRV_SGX_MISCINFO_INFO *)(
1383 psMemInfo->pvLinAddrKM))->sSGXFeatures;
1385 OSMemSet(psMemInfo->pvLinAddrKM, 0,
1386 sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
1388 psSGXFeatures->ui32DDKVersion =
1389 (PVRVERSION_MAJ << 16) |
1390 (PVRVERSION_MIN << 8) | PVRVERSION_BRANCH;
1391 psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
1393 psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
1397 case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
1399 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1400 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1401 unsigned ui32MatchingFlags;
1403 if ((psMiscInfo->uData.ui32NewHWPerfStatus &
1404 ~(PVRSRV_SGX_HWPERF_GRAPHICS_ON |
1405 PVRSRV_SGX_HWPERF_MK_EXECUTION_ON)) != 0) {
1406 return PVRSRV_ERROR_INVALID_PARAMS;
1410 ui32MatchingFlags = readl(&psDevInfo->
1411 psSGXHostCtl->ui32HWPerfFlags);
1412 ui32MatchingFlags &=
1413 psMiscInfo->uData.ui32NewHWPerfStatus;
1414 if ((ui32MatchingFlags & PVRSRV_SGX_HWPERF_GRAPHICS_ON)
1416 psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffff;
1418 if ((ui32MatchingFlags &
1419 PVRSRV_SGX_HWPERF_MK_EXECUTION_ON) == 0UL) {
1420 psHWPerfCB->ui32OrdinalMK_EXECUTION =
1425 writel(psMiscInfo->uData.ui32NewHWPerfStatus,
1426 &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1429 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
1430 "SGX ukernel HWPerf status %u\n",
1431 readl(&psDevInfo->psSGXHostCtl->
1433 PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
1434 offsetof(struct SGXMKIF_HOST_CTL,
1436 sizeof(psDevInfo->psSGXHostCtl->
1438 PDUMP_FLAGS_CONTINUOUS,
1439 MAKEUNIQUETAG(psDevInfo->
1440 psKernelSGXHostCtlMemInfo));
1445 case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
1448 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1449 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1452 psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffffUL;
1455 l = readl(&psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1456 l |= PVRSRV_SGX_HWPERF_GRAPHICS_ON;
1457 writel(l, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1462 case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
1465 writel(0, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1470 case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
1472 struct SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
1473 &psMiscInfo->uData.sRetrieveCB;
1474 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1475 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1479 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff
1480 && i < psRetrieve->ui32ArraySize; i++) {
1481 struct SGXMKIF_HWPERF_CB_ENTRY *psData =
1482 &psHWPerfCB->psHWPerfCBData[psHWPerfCB->
1485 psRetrieve->psHWPerfData[i].ui32FrameNo =
1486 psData->ui32FrameNo;
1487 psRetrieve->psHWPerfData[i].ui32Type =
1489 PVRSRV_SGX_HWPERF_TYPE_OP_MASK);
1490 psRetrieve->psHWPerfData[i].ui32StartTime =
1492 psRetrieve->psHWPerfData[i].ui32StartTimeWraps =
1493 psData->ui32TimeWraps;
1494 psRetrieve->psHWPerfData[i].ui32EndTime =
1496 psRetrieve->psHWPerfData[i].ui32EndTimeWraps =
1497 psData->ui32TimeWraps;
1498 psRetrieve->psHWPerfData[i].ui32ClockSpeed =
1499 psDevInfo->ui32CoreClockSpeed;
1500 psRetrieve->psHWPerfData[i].ui32TimeMax =
1501 psDevInfo->ui32uKernelTimerClock;
1502 psHWPerfCB->ui32Roff =
1503 (psHWPerfCB->ui32Roff + 1) &
1504 (SGXMKIF_HWPERF_CB_SIZE - 1);
1506 psRetrieve->ui32DataCount = i;
1507 psRetrieve->ui32Time = OSClockus();
1512 return PVRSRV_ERROR_INVALID_PARAMS;
1517 enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg,
1518 u32 *pui32Old, IMG_BOOL bNew, u32 ui32New,
1519 u32 ui32NewReset, u32 ui32CountersReg,
1520 u32 *pui32Time, IMG_BOOL *pbActive,
1521 struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs)
1523 struct SYS_DATA *psSysData;
1524 struct PVRSRV_POWER_DEV *psPowerDevice;
1525 IMG_BOOL bPowered = IMG_FALSE;
1526 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
1527 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1530 psDevInfo->ui32HWGroupRequested = ui32New;
1531 psDevInfo->ui32HWReset |= ui32NewReset;
1533 if (SysAcquireData(&psSysData) != PVRSRV_OK)
1534 return PVRSRV_ERROR_GENERIC;
1536 psPowerDevice = psSysData->psPowerDeviceList;
1537 while (psPowerDevice) {
1538 if (psPowerDevice->ui32DeviceIndex ==
1539 psDeviceNode->sDevId.ui32DeviceIndex) {
1541 (IMG_BOOL)(psPowerDevice->eCurrentPowerState ==
1542 PVRSRV_POWER_STATE_D0);
1546 psPowerDevice = psPowerDevice->psNext;
1549 *pbActive = bPowered;
1554 struct PVRSRV_SGXDEV_DIFF_INFO sNew,
1555 *psPrev = &psDevInfo->sDiffInfo;
1558 sNew.ui32Time[0] = OSClockus();
1559 *pui32Time = sNew.ui32Time[0];
1560 if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) {
1563 OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
1565 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1566 sNew.aui32Counters[i] =
1567 OSReadHWReg(psDevInfo->pvRegsBaseKM,
1568 ui32CountersReg + (i * 4));
1571 if (psDevInfo->ui32HWGroupRequested != *pui32Old) {
1572 if (psDevInfo->ui32HWReset != 0) {
1573 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
1576 ui32HWGroupRequested |
1577 psDevInfo->ui32HWReset);
1578 psDevInfo->ui32HWReset = 0;
1580 OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg,
1581 psDevInfo->ui32HWGroupRequested);
1584 sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter;
1585 sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
1587 sNew.ui32Time[1] = readl(
1588 &psDevInfo->psSGXHostCtl->ui32TimeWraps);
1590 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1591 psDiffs->aui32Counters[i] =
1592 sNew.aui32Counters[i] -
1593 psPrev->aui32Counters[i];
1596 psDiffs->ui32Marker[0] =
1597 sNew.ui32Marker[0] - psPrev->ui32Marker[0];
1598 psDiffs->ui32Marker[1] =
1599 sNew.ui32Marker[1] - psPrev->ui32Marker[1];
1601 psDiffs->ui32Time[0] =
1602 sNew.ui32Time[0] - psPrev->ui32Time[0];
1603 psDiffs->ui32Time[1] =
1604 sNew.ui32Time[1] - psPrev->ui32Time[1];
1608 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i)
1609 psDiffs->aui32Counters[i] = 0;
1611 psDiffs->ui32Marker[0] = 0;
1612 psDiffs->ui32Marker[1] = 0;
1614 psDiffs->ui32Time[0] = 0;
1615 psDiffs->ui32Time[1] = 0;
1619 SGXTestActivePowerEvent(psDeviceNode);
1626 enum PVRSRV_ERROR SGXReadHWPerfCBKM(void *hDevHandle, u32 ui32ArraySize,
1627 struct PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
1628 u32 *pui32DataCount, u32 *pui32ClockSpeed,
1629 u32 *pui32HostTimeStamp)
1631 enum PVRSRV_ERROR eError = PVRSRV_OK;
1632 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
1633 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1634 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1635 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1639 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
1641 struct SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry =
1642 &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
1644 psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
1645 psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
1646 psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
1647 psClientHWPerfEntry[i].ui32Clocksx16 =
1648 SGXConvertTimeStamp(psDevInfo, psMKPerfEntry->ui32TimeWraps,
1649 psMKPerfEntry->ui32Time);
1650 OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0],
1651 &psMKPerfEntry->ui32Counters[0],
1652 sizeof(psMKPerfEntry->ui32Counters));
1654 psHWPerfCB->ui32Roff =
1655 (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
1658 *pui32DataCount = i;
1659 *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
1660 *pui32HostTimeStamp = OSClockus();