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 psDevInfo->psKernelEDMStatusBufferMemInfo =
128 psInitInfo->hKernelEDMStatusBufferMemInfo;
130 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
131 sizeof(struct PVRSRV_SGX_CCB_INFO),
132 (void **)&psKernelCCBInfo, NULL);
133 if (eError != PVRSRV_OK) {
134 PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory");
135 goto failed_allockernelccb;
138 OSMemSet(psKernelCCBInfo, 0, sizeof(struct PVRSRV_SGX_CCB_INFO));
139 psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
140 psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
141 psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
142 psKernelCCBInfo->pui32WriteOffset =
143 &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
144 psKernelCCBInfo->pui32ReadOffset =
145 &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
146 psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
148 psDevInfo->ui32HostKickAddress = psInitInfo->ui32HostKickAddress;
150 psDevInfo->ui32GetMiscInfoAddress = psInitInfo->ui32GetMiscInfoAddress;
152 psDevInfo->bForcePTOff = IMG_FALSE;
154 psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
156 psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
157 psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
158 psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
159 psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
161 OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData,
162 sizeof(psDevInfo->asSGXDevData));
166 failed_allockernelccb:
167 DeinitDevInfo(psDevInfo);
172 static enum PVRSRV_ERROR SGXRunScript(struct PVRSRV_SGXDEV_INFO *psDevInfo,
173 union SGX_INIT_COMMAND *psScript,
174 u32 ui32NumInitCommands)
177 union SGX_INIT_COMMAND *psComm;
179 for (ui32PC = 0, psComm = psScript;
180 ui32PC < ui32NumInitCommands; ui32PC++, psComm++) {
181 switch (psComm->eOp) {
182 case SGX_INIT_OP_WRITE_HW_REG:
184 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
185 psComm->sWriteHWReg.ui32Offset,
186 psComm->sWriteHWReg.ui32Value);
187 PDUMPREG(psComm->sWriteHWReg.ui32Offset,
188 psComm->sWriteHWReg.ui32Value);
192 case SGX_INIT_OP_PDUMP_HW_REG:
194 PDUMPREG(psComm->sPDumpHWReg.ui32Offset,
195 psComm->sPDumpHWReg.ui32Value);
199 case SGX_INIT_OP_HALT:
203 case SGX_INIT_OP_ILLEGAL:
207 PVR_DPF(PVR_DBG_ERROR,
208 "SGXRunScript: PC %d: Illegal command: %d",
209 ui32PC, psComm->eOp);
210 return PVRSRV_ERROR_GENERIC;
216 return PVRSRV_ERROR_GENERIC;
219 enum PVRSRV_ERROR SGXInitialise(struct PVRSRV_SGXDEV_INFO *psDevInfo,
220 IMG_BOOL bHardwareRecovery)
222 enum PVRSRV_ERROR eError;
224 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
225 "SGX initialisation script part 1\n");
227 SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1,
228 SGX_MAX_INIT_COMMANDS);
229 if (eError != PVRSRV_OK) {
230 PVR_DPF(PVR_DBG_ERROR,
231 "SGXInitialise: SGXRunScript (part 1) failed (%d)",
233 return PVRSRV_ERROR_GENERIC;
235 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
236 "End of SGX initialisation script part 1\n");
238 SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
242 *psDevInfo->pui32KernelCCBEventKicker = 0;
244 PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
245 sizeof(*psDevInfo->pui32KernelCCBEventKicker),
246 PDUMP_FLAGS_CONTINUOUS,
247 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
250 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
251 "SGX initialisation script part 2\n");
253 SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2,
254 SGX_MAX_INIT_COMMANDS);
255 if (eError != PVRSRV_OK) {
256 PVR_DPF(PVR_DBG_ERROR,
257 "SGXInitialise: SGXRunScript (part 2) failed (%d)",
259 return PVRSRV_ERROR_GENERIC;
261 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
262 "End of SGX initialisation script part 2\n");
264 SGXStartTimer(psDevInfo, (IMG_BOOL)!bHardwareRecovery);
266 if (bHardwareRecovery) {
267 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
268 psDevInfo->psSGXHostCtl;
270 if (PollForValueKM(&psSGXHostCtl->ui32InterruptClearFlags, 0,
271 PVRSRV_USSE_EDM_INTERRUPT_HWR,
272 MAX_HW_TIME_US / WAIT_TRY_COUNT, 1000) != PVRSRV_OK) {
273 PVR_DPF(PVR_DBG_ERROR, "SGXInitialise: "
274 "Wait for uKernel HW Recovery failed");
276 return PVRSRV_ERROR_RETRY;
280 PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset ==
281 psDevInfo->psKernelCCBCtl->ui32WriteOffset);
286 enum PVRSRV_ERROR SGXDeinitialise(void *hDevCookie)
288 struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
290 enum PVRSRV_ERROR eError;
292 if (psDevInfo->pvRegsBaseKM == NULL)
295 eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands,
296 SGX_MAX_DEINIT_COMMANDS);
297 if (eError != PVRSRV_OK) {
298 PVR_DPF(PVR_DBG_ERROR,
299 "SGXDeinitialise: SGXRunScript failed (%d)", eError);
300 return PVRSRV_ERROR_GENERIC;
306 static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
308 struct PVRSRV_SGXDEV_INFO *psDevInfo;
309 void *hKernelDevMemContext;
310 struct IMG_DEV_PHYADDR sPDDevPAddr;
312 struct PVRSRV_DEVICE_NODE *psDeviceNode = (struct PVRSRV_DEVICE_NODE *)
314 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap =
315 psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
316 enum PVRSRV_ERROR eError;
318 PDUMPCOMMENT("SGX Initialisation Part 1");
320 PDUMPCOMMENT("SGX Core Version Information: %s",
321 SGX_CORE_FRIENDLY_NAME);
322 PDUMPCOMMENT("SGX Core Revision Information: multi rev support");
324 if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
325 sizeof(struct PVRSRV_SGXDEV_INFO),
326 (void **)&psDevInfo, NULL) != PVRSRV_OK) {
327 PVR_DPF(PVR_DBG_ERROR,
328 "DevInitSGXPart1 : Failed to alloc memory for DevInfo");
329 return PVRSRV_ERROR_OUT_OF_MEMORY;
331 OSMemSet(psDevInfo, 0, sizeof(struct PVRSRV_SGXDEV_INFO));
333 psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
334 psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
336 psDeviceNode->pvDevice = (void *) psDevInfo;
338 psDevInfo->pvDeviceMemoryHeap = (void *) psDeviceMemoryHeap;
340 hKernelDevMemContext = BM_CreateContext(psDeviceNode, &sPDDevPAddr,
343 psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
345 for (i = 0; i < psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) {
348 switch (psDeviceMemoryHeap[i].DevMemHeapType) {
349 case DEVICE_MEMORY_HEAP_KERNEL:
350 case DEVICE_MEMORY_HEAP_SHARED:
351 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
354 BM_CreateHeap(hKernelDevMemContext,
355 &psDeviceMemoryHeap[i]);
357 psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
363 eError = MMU_BIFResetPDAlloc(psDevInfo);
364 if (eError != PVRSRV_OK) {
365 PVR_DPF(PVR_DBG_ERROR,
366 "DevInitSGX : Failed to alloc memory for BIF reset");
367 return PVRSRV_ERROR_GENERIC;
373 enum PVRSRV_ERROR SGXGetInfoForSrvinitKM(void *hDevHandle,
374 struct SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
376 struct PVRSRV_DEVICE_NODE *psDeviceNode;
377 struct PVRSRV_SGXDEV_INFO *psDevInfo;
378 enum PVRSRV_ERROR eError;
380 PDUMPCOMMENT("SGXGetInfoForSrvinit");
382 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
383 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
385 psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
388 PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
389 if (eError != PVRSRV_OK) {
390 PVR_DPF(PVR_DBG_ERROR, "SGXGetInfoForSrvinit: "
391 "PVRSRVGetDeviceMemHeapsKM failed (%d)",
393 return PVRSRV_ERROR_GENERIC;
399 enum PVRSRV_ERROR DevInitSGXPart2KM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
401 struct SGX_BRIDGE_INIT_INFO *psInitInfo)
403 struct PVRSRV_DEVICE_NODE *psDeviceNode;
404 struct PVRSRV_SGXDEV_INFO *psDevInfo;
405 enum PVRSRV_ERROR eError;
406 struct SGX_DEVICE_MAP *psSGXDeviceMap;
407 enum PVR_POWER_STATE eDefaultPowerState;
410 PDUMPCOMMENT("SGX Initialisation Part 2");
412 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
413 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
415 eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
416 if (eError != PVRSRV_OK) {
417 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
418 "Failed to load EDM program");
419 goto failed_init_dev_info;
423 eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
424 (void **) &psSGXDeviceMap);
425 if (eError != PVRSRV_OK) {
426 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
427 "Failed to get device memory map!");
428 return PVRSRV_ERROR_INIT_FAILURE;
431 if (psSGXDeviceMap->pvRegsCpuVBase) {
432 psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
434 psDevInfo->pvRegsBaseKM =
435 OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
436 psSGXDeviceMap->ui32RegsSize,
437 PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
439 if (!psDevInfo->pvRegsBaseKM) {
440 PVR_DPF(PVR_DBG_ERROR,
441 "DevInitSGXPart2KM: Failed to map in regs\n");
442 return PVRSRV_ERROR_BAD_MAPPING;
445 psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
446 psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
448 psDeviceNode->pvISRData = psDeviceNode;
450 PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
453 l = readl(&psDevInfo->psSGXHostCtl->ui32PowerStatus);
454 l |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
455 writel(l, &psDevInfo->psSGXHostCtl->ui32PowerStatus);
457 eDefaultPowerState = PVRSRV_POWER_STATE_D3;
459 eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
461 SGXPostPowerStateExt,
462 SGXPreClockSpeedChange,
463 SGXPostClockSpeedChange,
464 (void *) psDeviceNode,
465 PVRSRV_POWER_STATE_D3,
467 if (eError != PVRSRV_OK) {
468 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
469 "failed to register device with power manager");
473 OSMemSet(psDevInfo->psKernelCCB, 0,
474 sizeof(struct PVRSRV_SGX_KERNEL_CCB));
475 OSMemSet(psDevInfo->psKernelCCBCtl, 0,
476 sizeof(struct PVRSRV_SGX_CCB_CTL));
477 OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0,
478 sizeof(*psDevInfo->pui32KernelCCBEventKicker));
479 PDUMPCOMMENT("Initialise Kernel CCB");
480 PDUMPMEM(NULL, psDevInfo->psKernelCCBMemInfo, 0,
481 sizeof(struct PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
482 MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
483 PDUMPCOMMENT("Initialise Kernel CCB Control");
484 PDUMPMEM(NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
485 sizeof(struct PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
486 MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
487 PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
488 PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
489 sizeof(*psDevInfo->pui32KernelCCBEventKicker),
490 PDUMP_FLAGS_CONTINUOUS,
491 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
493 psDevInfo->hTimer = SGXOSTimerInit(psDeviceNode);
494 if (!psDevInfo->hTimer)
495 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM : "
496 "Failed to initialize HW recovery timer");
500 failed_init_dev_info:
504 static enum PVRSRV_ERROR DevDeInitSGX(void *pvDeviceNode)
506 struct PVRSRV_DEVICE_NODE *psDeviceNode =
507 (struct PVRSRV_DEVICE_NODE *)pvDeviceNode;
508 struct PVRSRV_SGXDEV_INFO *psDevInfo =
509 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
510 enum PVRSRV_ERROR eError;
512 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
513 struct SGX_DEVICE_MAP *psSGXDeviceMap;
516 PVR_DPF(PVR_DBG_ERROR, "DevDeInitSGX: Null DevInfo");
519 if (psDevInfo->hTimer) {
520 SGXOSTimerCancel(psDevInfo->hTimer);
521 SGXOSTimerDeInit(psDevInfo->hTimer);
522 psDevInfo->hTimer = NULL;
525 MMU_BIFResetPDFree(psDevInfo);
527 DeinitDevInfo(psDevInfo);
531 (struct DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
533 ui32Heap < psDeviceNode->sDevMemoryInfo.ui32HeapCount;
535 switch (psDeviceMemoryHeap[ui32Heap].DevMemHeapType) {
536 case DEVICE_MEMORY_HEAP_KERNEL:
537 case DEVICE_MEMORY_HEAP_SHARED:
538 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
540 if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap !=
542 BM_DestroyHeap(psDeviceMemoryHeap
543 [ui32Heap].hDevMemHeap);
549 if (!pvr_put_ctx(psDeviceNode->sDevMemoryInfo.pBMKernelContext))
550 pr_err("%s: kernel context still in use, can't free it",
553 eError = PVRSRVRemovePowerDevice(
554 ((struct PVRSRV_DEVICE_NODE *)pvDeviceNode)->
555 sDevId.ui32DeviceIndex);
556 if (eError != PVRSRV_OK)
559 eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
560 (void **)&psSGXDeviceMap);
561 if (eError != PVRSRV_OK) {
562 PVR_DPF(PVR_DBG_ERROR,
563 "DevDeInitSGX: Failed to get device memory map!");
567 if (!psSGXDeviceMap->pvRegsCpuVBase)
568 if (psDevInfo->pvRegsBaseKM != NULL)
569 OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
570 psDevInfo->ui32RegSize,
571 PVRSRV_HAP_KERNEL_ONLY |
575 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
576 sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
578 psDeviceNode->pvDevice = NULL;
580 if (psDeviceMemoryHeap != NULL)
581 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
582 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
583 psDeviceNode->sDevMemoryInfo.ui32HeapCount,
584 psDeviceMemoryHeap, NULL);
589 #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined(CONFIG_DEBUG_FS)
591 static size_t __print_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, char *dst,
601 #define _PR(fmt, ...) do { \
603 p += snprintf(dst + p, dst_len - p, fmt, ## __VA_ARGS__); \
605 pr_err(fmt, ## __VA_ARGS__); \
608 if (!sdev->psKernelEDMStatusBufferMemInfo)
611 buf = sdev->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
613 _PR("Last SGX microkernel status code: 0x%x\n", *buf);
619 buf_end = buf + SGXMK_TRACE_BUFFER_SIZE * 4;
623 /* Dump the status values */
624 for (i = 0; i < SGXMK_TRACE_BUFFER_SIZE; i++) {
625 _PR("%3d %08X %08X %08X %08X\n",
626 i, buf[2], buf[3], buf[1], buf[0]);
632 return p > dst_len ? dst_len : p;
636 size_t snprint_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, char *buf,
639 return __print_edm_trace(sdev, buf, buf_size);
644 static void dump_edm(struct PVRSRV_SGXDEV_INFO *sdev)
646 #ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
647 __print_edm_trace(sdev, NULL, 0);
651 static void dump_process_info(struct PVRSRV_DEVICE_NODE *dev)
653 struct PVRSRV_SGXDEV_INFO *dev_info = dev->pvDevice;
654 u32 page_dir = readl(dev_info->pvRegsBaseKM +
655 EUR_CR_BIF_DIR_LIST_BASE0);
656 struct BM_CONTEXT *bm_ctx;
657 struct RESMAN_CONTEXT *res_ctx = NULL;
659 bm_ctx = bm_find_context(dev->sDevMemoryInfo.pBMContext, page_dir);
661 res_ctx = pvr_get_resman_ctx(bm_ctx);
664 struct task_struct *tsk;
665 struct PVRSRV_PER_PROCESS_DATA *proc;
668 proc = pvr_get_proc_by_ctx(res_ctx);
671 tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
672 pr_err("PID = %d, process name = %s\n", pid, tsk->comm);
677 static void dump_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
679 pr_err("EVENT_STATUS = 0x%08X\n"
680 "EVENT_STATUS2 = 0x%08X\n"
681 "BIF_CTRL = 0x%08X\n"
682 "BIF_INT_STAT = 0x%08X\n"
683 "BIF_MEM_REQ_STAT = 0x%08X\n"
684 "BIF_FAULT = 0x%08X\n"
685 "CLKGATECTL = 0x%08X\n",
686 readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS),
687 readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS2),
688 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_CTRL),
689 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_INT_STAT),
690 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
691 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_FAULT),
692 readl(psDevInfo->pvRegsBaseKM + EUR_CR_CLKGATECTL));
695 /* Should be called with pvr_lock held */
696 void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode)
698 enum PVRSRV_ERROR eError;
699 struct PVRSRV_SGXDEV_INFO *psDevInfo =
700 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
701 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
702 psDevInfo->psSGXHostCtl;
704 int max_retries = 10;
706 BUG_ON(!pvr_is_locked());
708 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
709 l |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
710 writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
712 pr_err("%s: SGX Hardware Recovery triggered\n", __func__);
714 dump_process_info(psDeviceNode);
715 dump_sgx_registers(psDevInfo);
721 eError = SGXInitialise(psDevInfo, IMG_TRUE);
722 if (eError != PVRSRV_ERROR_RETRY)
724 } while (max_retries--);
726 if (eError != PVRSRV_OK) {
727 pr_err("%s: recovery failed (%d). Disabling the driver",
738 SGXScheduleProcessQueues(psDeviceNode);
740 PVRSRVProcessQueues(IMG_TRUE);
743 static unsigned long sgx_reset_forced;
745 static void SGXOSTimer(struct work_struct *work)
747 struct timer_work_data *data = container_of(work,
748 struct timer_work_data,
750 struct PVRSRV_DEVICE_NODE *psDeviceNode = data->psDeviceNode;
751 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
752 static u32 ui32EDMTasks;
753 static u32 ui32LockupCounter;
754 static u32 ui32NumResets;
755 u32 ui32CurrentEDMTasks;
756 IMG_BOOL bLockup = IMG_FALSE;
757 IMG_BOOL bPoweredDown;
761 if (!data->armed || pvr_is_disabled()) {
766 psDevInfo->ui32TimeStamp++;
768 #if defined(NO_HARDWARE)
769 bPoweredDown = IMG_TRUE;
771 bPoweredDown = (IMG_BOOL) !SGXIsDevicePowered(psDeviceNode);
775 ui32LockupCounter = 0;
778 ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM,
779 psDevInfo->ui32EDMTaskReg0);
780 if (psDevInfo->ui32EDMTaskReg1 != 0)
781 ui32CurrentEDMTasks ^=
782 OSReadHWReg(psDevInfo->pvRegsBaseKM,
783 psDevInfo->ui32EDMTaskReg1);
784 if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
785 (psDevInfo->ui32NumResets == ui32NumResets)) {
787 if (ui32LockupCounter == 3) {
788 ui32LockupCounter = 0;
789 PVR_DPF(PVR_DBG_ERROR, "SGXOSTimer() "
790 "detected SGX lockup (0x%x tasks)",
796 ui32LockupCounter = 0;
797 ui32EDMTasks = ui32CurrentEDMTasks;
798 ui32NumResets = psDevInfo->ui32NumResets;
803 bLockup |= cmpxchg(&sgx_reset_forced, 1, 0);
806 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
807 psDevInfo->psSGXHostCtl;
811 l = readl(&psSGXHostCtl->ui32HostDetectedLockups);
813 writel(l, &psSGXHostCtl->ui32HostDetectedLockups);
815 HWRecoveryResetSGX(psDeviceNode);
819 queue_delayed_work(data->work_queue, &data->work,
820 msecs_to_jiffies(data->interval));
825 struct timer_work_data *
826 SGXOSTimerInit(struct PVRSRV_DEVICE_NODE *psDeviceNode)
828 struct timer_work_data *data;
830 data = kzalloc(sizeof(struct timer_work_data), GFP_KERNEL);
834 data->work_queue = create_workqueue("SGXOSTimer");
835 if (!data->work_queue) {
840 data->interval = 150;
841 data->psDeviceNode = psDeviceNode;
842 INIT_DELAYED_WORK(&data->work, SGXOSTimer);
847 void SGXOSTimerDeInit(struct timer_work_data *data)
850 destroy_workqueue(data->work_queue);
854 enum PVRSRV_ERROR SGXOSTimerEnable(struct timer_work_data *data)
857 return PVRSRV_ERROR_GENERIC;
859 if (queue_delayed_work(data->work_queue, &data->work,
860 msecs_to_jiffies(data->interval))) {
865 return PVRSRV_ERROR_GENERIC;
868 enum PVRSRV_ERROR SGXOSTimerCancel(struct timer_work_data *data)
871 return PVRSRV_ERROR_GENERIC;
874 cancel_delayed_work(&data->work);
879 int sgx_force_reset(void)
881 return !cmpxchg(&sgx_reset_forced, 0, 1);
884 static IMG_BOOL SGX_ISRHandler(void *pvData)
886 IMG_BOOL bInterruptProcessed = IMG_FALSE;
889 u32 ui32EventStatus, ui32EventEnable;
890 u32 ui32EventClear = 0;
891 struct PVRSRV_DEVICE_NODE *psDeviceNode;
892 struct PVRSRV_SGXDEV_INFO *psDevInfo;
894 if (pvData == NULL) {
895 PVR_DPF(PVR_DBG_ERROR,
896 "SGX_ISRHandler: Invalid params\n");
897 return bInterruptProcessed;
900 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)pvData;
901 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
904 OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
905 ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM,
906 EUR_CR_EVENT_HOST_ENABLE);
908 gui32EventStatusServicesByISR = ui32EventStatus;
910 ui32EventStatus &= ui32EventEnable;
912 if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
913 ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
915 if (ui32EventClear) {
916 bInterruptProcessed = IMG_TRUE;
919 EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
921 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
922 EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
926 return bInterruptProcessed;
929 static void SGX_MISRHandler(void *pvData)
931 struct PVRSRV_DEVICE_NODE *psDeviceNode =
932 (struct PVRSRV_DEVICE_NODE *)pvData;
933 struct PVRSRV_SGXDEV_INFO *psDevInfo =
934 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
935 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
936 psDevInfo->psSGXHostCtl;
939 enum PVRSRV_ERROR err;
941 dev_idx = psDeviceNode->sDevId.ui32DeviceIndex;
945 err = PVRSRVSetDevicePowerStateKM(dev_idx, PVRSRV_POWER_STATE_D0);
946 BUG_ON(err != PVRSRV_OK);
948 l1 = readl(&psSGXHostCtl->ui32InterruptFlags);
949 l2 = readl(&psSGXHostCtl->ui32InterruptClearFlags);
951 if ((l1 & PVRSRV_USSE_EDM_INTERRUPT_HWR) &&
952 !(l2 & PVRSRV_USSE_EDM_INTERRUPT_HWR))
953 HWRecoveryResetSGX(psDeviceNode);
955 if (psDeviceNode->bReProcessDeviceCommandComplete)
956 SGXScheduleProcessQueues(psDeviceNode);
958 SGXTestActivePowerEvent(psDeviceNode);
963 enum PVRSRV_ERROR SGXRegisterDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode)
965 struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
966 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
968 psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
969 psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
971 psDeviceNode->pfnInitDevice = DevInitSGXPart1;
972 psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
974 psDeviceNode->pfnInitDeviceCompatCheck = SGXDevInitCompatCheck;
976 psDeviceNode->pfnMMUInitialise = MMU_Initialise;
977 psDeviceNode->pfnMMUFinalise = MMU_Finalise;
978 psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
979 psDeviceNode->pfnMMUCreate = MMU_Create;
980 psDeviceNode->pfnMMUDelete = MMU_Delete;
981 psDeviceNode->pfnMMUAlloc = MMU_Alloc;
982 psDeviceNode->pfnMMUFree = MMU_Free;
983 psDeviceNode->pfnMMUMapPages = MMU_MapPages;
984 psDeviceNode->pfnMMUMapShadow = MMU_MapShadow;
985 psDeviceNode->pfnMMUUnmapPages = MMU_UnmapPages;
986 psDeviceNode->pfnMMUMapScatter = MMU_MapScatter;
987 psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
988 psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
990 psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
991 psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
993 psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
995 psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
997 psDevMemoryInfo->ui32AddressSpaceSizeLog2 =
998 SGX_FEATURE_ADDRESS_SPACE_SIZE;
1000 psDevMemoryInfo->ui32Flags = 0;
1001 psDevMemoryInfo->ui32HeapCount = SGX_MAX_HEAP_ID;
1002 psDevMemoryInfo->ui32SyncHeapID = SGX_SYNCINFO_HEAP_ID;
1004 psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_HEAP_ID;
1006 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1007 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
1008 psDevMemoryInfo->ui32HeapCount,
1009 (void **) &psDevMemoryInfo->psDeviceMemoryHeap,
1010 NULL) != PVRSRV_OK) {
1011 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterDevice : "
1012 "Failed to alloc memory for "
1013 "struct DEVICE_MEMORY_HEAP_INFO");
1014 return PVRSRV_ERROR_OUT_OF_MEMORY;
1016 OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0,
1017 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
1018 psDevMemoryInfo->ui32HeapCount);
1020 psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
1022 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapID =
1023 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
1024 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].sDevVAddrBase.uiAddr =
1025 SGX_GENERAL_HEAP_BASE;
1026 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapSize =
1027 SGX_GENERAL_HEAP_SIZE;
1028 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32Attribs =
1029 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1030 PVRSRV_HAP_SINGLE_PROCESS;
1031 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszName = "General";
1032 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszBSName = "General BS";
1033 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].DevMemHeapType =
1034 DEVICE_MEMORY_HEAP_PERCONTEXT;
1036 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32DataPageSize =
1039 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapID =
1040 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
1041 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].sDevVAddrBase.uiAddr =
1042 SGX_TADATA_HEAP_BASE;
1043 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapSize =
1044 SGX_TADATA_HEAP_SIZE;
1045 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32Attribs =
1046 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
1047 | PVRSRV_HAP_MULTI_PROCESS;
1048 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszName = "TA Data";
1049 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszBSName = "TA Data BS";
1050 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].DevMemHeapType =
1051 DEVICE_MEMORY_HEAP_PERCONTEXT;
1053 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32DataPageSize =
1056 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapID =
1057 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
1058 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
1059 SGX_KERNEL_CODE_HEAP_BASE;
1060 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapSize =
1061 SGX_KERNEL_CODE_HEAP_SIZE;
1062 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32Attribs =
1063 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1064 PVRSRV_HAP_MULTI_PROCESS;
1065 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel Code";
1066 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName =
1068 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].DevMemHeapType =
1069 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1071 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32DataPageSize =
1074 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapID =
1075 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
1076 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
1077 SGX_KERNEL_DATA_HEAP_BASE;
1078 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapSize =
1079 SGX_KERNEL_DATA_HEAP_SIZE;
1080 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32Attribs =
1081 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1082 PVRSRV_HAP_MULTI_PROCESS;
1083 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszName = "KernelData";
1084 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszBSName = "KernelData BS";
1085 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].DevMemHeapType =
1086 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1088 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32DataPageSize =
1091 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapID =
1092 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
1093 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1094 SGX_PIXELSHADER_HEAP_BASE;
1095 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapSize =
1096 SGX_PIXELSHADER_HEAP_SIZE;
1097 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32Attribs =
1098 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1099 PVRSRV_HAP_SINGLE_PROCESS;
1100 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszName = "PixelShaderUSSE";
1101 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszBSName =
1102 "PixelShaderUSSE BS";
1103 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].DevMemHeapType =
1104 DEVICE_MEMORY_HEAP_PERCONTEXT;
1106 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32DataPageSize =
1109 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapID =
1110 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
1111 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1112 SGX_VERTEXSHADER_HEAP_BASE;
1113 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapSize =
1114 SGX_VERTEXSHADER_HEAP_SIZE;
1115 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32Attribs =
1116 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1117 PVRSRV_HAP_SINGLE_PROCESS;
1118 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszName =
1120 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszBSName =
1121 "VertexShaderUSSE BS";
1122 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].DevMemHeapType =
1123 DEVICE_MEMORY_HEAP_PERCONTEXT;
1125 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32DataPageSize =
1128 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapID =
1129 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
1130 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].sDevVAddrBase.uiAddr =
1131 SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
1132 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapSize =
1133 SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
1134 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32Attribs =
1135 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1136 PVRSRV_HAP_SINGLE_PROCESS;
1137 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszName =
1139 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszBSName =
1140 "PDSPixelCodeData BS";
1141 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].DevMemHeapType =
1142 DEVICE_MEMORY_HEAP_PERCONTEXT;
1144 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32DataPageSize =
1147 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapID =
1148 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
1149 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].sDevVAddrBase.
1150 uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
1151 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapSize =
1152 SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
1153 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32Attribs =
1154 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1155 PVRSRV_HAP_SINGLE_PROCESS;
1156 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszName =
1157 "PDSVertexCodeData";
1158 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszBSName =
1159 "PDSVertexCodeData BS";
1160 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].DevMemHeapType =
1161 DEVICE_MEMORY_HEAP_PERCONTEXT;
1163 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32DataPageSize =
1166 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapID =
1167 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
1168 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].sDevVAddrBase.uiAddr =
1169 SGX_SYNCINFO_HEAP_BASE;
1170 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapSize =
1171 SGX_SYNCINFO_HEAP_SIZE;
1173 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32Attribs =
1174 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1175 PVRSRV_HAP_MULTI_PROCESS;
1176 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszName = "CacheCoherent";
1177 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszBSName = "CacheCoherent BS";
1179 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].DevMemHeapType =
1180 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1182 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32DataPageSize =
1185 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapID =
1186 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
1187 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].sDevVAddrBase.uiAddr =
1188 SGX_3DPARAMETERS_HEAP_BASE;
1189 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapSize =
1190 SGX_3DPARAMETERS_HEAP_SIZE;
1191 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszName = "3DParameters";
1192 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszBSName =
1194 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
1195 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1196 PVRSRV_HAP_SINGLE_PROCESS;
1197 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
1198 DEVICE_MEMORY_HEAP_PERCONTEXT;
1200 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32DataPageSize =
1206 enum PVRSRV_ERROR SGXGetClientInfoKM(void *hDevCookie,
1207 struct SGX_CLIENT_INFO *psClientInfo)
1209 struct PVRSRV_SGXDEV_INFO *psDevInfo =
1210 (struct PVRSRV_SGXDEV_INFO *)
1211 ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
1213 psDevInfo->ui32ClientRefCount++;
1215 if (psDevInfo->ui32ClientRefCount == 1)
1216 psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
1218 psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
1220 OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData,
1221 sizeof(psClientInfo->asDevData));
1226 enum PVRSRV_ERROR SGXDevInitCompatCheck(struct PVRSRV_DEVICE_NODE *psDeviceNode)
1228 struct PVRSRV_SGXDEV_INFO *psDevInfo;
1229 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
1230 enum PVRSRV_ERROR eError;
1231 #if !defined(NO_HARDWARE)
1234 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1237 if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX) {
1238 PVR_DPF(PVR_DBG_ERROR,
1239 "SGXDevInitCompatCheck: Device not of type SGX");
1240 eError = PVRSRV_ERROR_INVALID_PARAMS;
1243 psDevInfo = psDeviceNode->pvDevice;
1244 psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
1246 #if !defined(NO_HARDWARE)
1248 eError = SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
1249 if (eError != PVRSRV_OK) {
1250 pr_err("pvr: unable to validate device DDK version\n");
1254 &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->pvLinAddrKM))->
1256 if ((psSGXFeatures->ui32DDKVersion !=
1257 ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8) |
1258 PVRVERSION_BRANCH)) ||
1259 (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD)) {
1260 pr_err("pvr: incompatible driver DDK revision (%d)"
1261 "/device DDK revision (%d).\n",
1262 PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
1263 eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
1266 PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
1267 "driver DDK (%ld) and device DDK (%ld) match",
1268 PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
1271 opts = psSGXFeatures->ui32BuildOptions;
1272 opt_mismatch = opts ^ SGX_BUILD_OPTIONS;
1273 /* we support the ABIs both with and without EDM tracing option */
1274 opt_mismatch &= ~PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET;
1276 if (SGX_BUILD_OPTIONS & opt_mismatch)
1277 pr_err("pvr: mismatch in driver and microkernel build "
1278 "options; extra options present in driver: "
1279 "(0x%x)", SGX_BUILD_OPTIONS & opt_mismatch);
1281 if (opts & opt_mismatch)
1282 pr_err("pvr: Mismatch in driver and microkernel build "
1283 "options; extra options present in "
1284 "microkernel: (0x%x)", opts & opt_mismatch);
1285 eError = PVRSRV_ERROR_BUILD_MISMATCH;
1288 PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
1289 "Driver and microkernel build options match.");
1299 enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
1300 struct PVRSRV_DEVICE_NODE *psDeviceNode)
1302 enum PVRSRV_ERROR eError;
1303 struct SGXMKIF_COMMAND sCommandData;
1304 struct PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
1305 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1307 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1308 psDevInfo->psKernelSGXMiscMemInfo;
1310 if (!psMemInfo->pvLinAddrKM) {
1311 PVR_DPF(PVR_DBG_ERROR, "SGXGetMiscInfoKM: Invalid address.");
1312 return PVRSRV_ERROR_INVALID_PARAMS;
1314 psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
1315 psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
1316 psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
1318 OSMemSet(psMemInfo->pvLinAddrKM, 0,
1319 sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
1321 sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
1323 OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
1327 eError = SGXScheduleCCBCommandKM(psDeviceNode,
1328 SGXMKIF_COMMAND_REQUEST_SGXMISCINFO,
1329 &sCommandData, KERNEL_ID, 0);
1331 if (eError != PVRSRV_OK) {
1332 PVR_DPF(PVR_DBG_ERROR,
1333 "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed.");
1337 #if !defined(NO_HARDWARE)
1339 IMG_BOOL bTimeout = IMG_TRUE;
1341 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
1342 if ((psSGXMiscInfoInt->
1343 ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) !=
1345 bTimeout = IMG_FALSE;
1349 END_LOOP_UNTIL_TIMEOUT();
1352 return PVRSRV_ERROR_TIMEOUT;
1359 enum PVRSRV_ERROR SGXGetMiscInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
1360 struct SGX_MISC_INFO *psMiscInfo,
1361 struct PVRSRV_DEVICE_NODE *psDeviceNode)
1363 switch (psMiscInfo->eRequest) {
1364 case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
1366 psMiscInfo->uData.ui32SGXClockSpeed =
1367 psDevInfo->ui32CoreClockSpeed;
1371 case SGX_MISC_INFO_REQUEST_SGXREV:
1373 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1374 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1375 psDevInfo->psKernelSGXMiscMemInfo;
1377 SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
1379 &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->
1380 pvLinAddrKM))->sSGXFeatures;
1382 psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
1384 PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
1385 "Core 0x%lx, sw ID 0x%lx, "
1387 psSGXFeatures->ui32CoreRev,
1388 psSGXFeatures->ui32CoreIdSW,
1389 psSGXFeatures->ui32CoreRevSW);
1390 PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
1391 "DDK version 0x%lx, DDK build 0x%lx\n",
1392 psSGXFeatures->ui32DDKVersion,
1393 psSGXFeatures->ui32DDKBuild);
1398 case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
1400 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1401 psDevInfo->psKernelSGXMiscMemInfo;
1402 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1404 psSGXFeatures = &((struct PVRSRV_SGX_MISCINFO_INFO *)(
1405 psMemInfo->pvLinAddrKM))->sSGXFeatures;
1407 OSMemSet(psMemInfo->pvLinAddrKM, 0,
1408 sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
1410 psSGXFeatures->ui32DDKVersion =
1411 (PVRVERSION_MAJ << 16) |
1412 (PVRVERSION_MIN << 8) | PVRVERSION_BRANCH;
1413 psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
1415 psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
1419 case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
1421 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1422 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1423 unsigned ui32MatchingFlags;
1425 if ((psMiscInfo->uData.ui32NewHWPerfStatus &
1426 ~(PVRSRV_SGX_HWPERF_GRAPHICS_ON |
1427 PVRSRV_SGX_HWPERF_MK_EXECUTION_ON)) != 0) {
1428 return PVRSRV_ERROR_INVALID_PARAMS;
1432 ui32MatchingFlags = readl(&psDevInfo->
1433 psSGXHostCtl->ui32HWPerfFlags);
1434 ui32MatchingFlags &=
1435 psMiscInfo->uData.ui32NewHWPerfStatus;
1436 if ((ui32MatchingFlags & PVRSRV_SGX_HWPERF_GRAPHICS_ON)
1438 psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffff;
1440 if ((ui32MatchingFlags &
1441 PVRSRV_SGX_HWPERF_MK_EXECUTION_ON) == 0UL) {
1442 psHWPerfCB->ui32OrdinalMK_EXECUTION =
1447 writel(psMiscInfo->uData.ui32NewHWPerfStatus,
1448 &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1451 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
1452 "SGX ukernel HWPerf status %u\n",
1453 readl(&psDevInfo->psSGXHostCtl->
1455 PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
1456 offsetof(struct SGXMKIF_HOST_CTL,
1458 sizeof(psDevInfo->psSGXHostCtl->
1460 PDUMP_FLAGS_CONTINUOUS,
1461 MAKEUNIQUETAG(psDevInfo->
1462 psKernelSGXHostCtlMemInfo));
1467 case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
1470 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1471 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1474 psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffffUL;
1477 l = readl(&psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1478 l |= PVRSRV_SGX_HWPERF_GRAPHICS_ON;
1479 writel(l, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1484 case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
1487 writel(0, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1492 case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
1494 struct SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
1495 &psMiscInfo->uData.sRetrieveCB;
1496 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1497 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1501 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff
1502 && i < psRetrieve->ui32ArraySize; i++) {
1503 struct SGXMKIF_HWPERF_CB_ENTRY *psData =
1504 &psHWPerfCB->psHWPerfCBData[psHWPerfCB->
1507 psRetrieve->psHWPerfData[i].ui32FrameNo =
1508 psData->ui32FrameNo;
1509 psRetrieve->psHWPerfData[i].ui32Type =
1511 PVRSRV_SGX_HWPERF_TYPE_OP_MASK);
1512 psRetrieve->psHWPerfData[i].ui32StartTime =
1514 psRetrieve->psHWPerfData[i].ui32StartTimeWraps =
1515 psData->ui32TimeWraps;
1516 psRetrieve->psHWPerfData[i].ui32EndTime =
1518 psRetrieve->psHWPerfData[i].ui32EndTimeWraps =
1519 psData->ui32TimeWraps;
1520 psRetrieve->psHWPerfData[i].ui32ClockSpeed =
1521 psDevInfo->ui32CoreClockSpeed;
1522 psRetrieve->psHWPerfData[i].ui32TimeMax =
1523 psDevInfo->ui32uKernelTimerClock;
1524 psHWPerfCB->ui32Roff =
1525 (psHWPerfCB->ui32Roff + 1) &
1526 (SGXMKIF_HWPERF_CB_SIZE - 1);
1528 psRetrieve->ui32DataCount = i;
1529 psRetrieve->ui32Time = OSClockus();
1534 return PVRSRV_ERROR_INVALID_PARAMS;
1539 enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg,
1540 u32 *pui32Old, IMG_BOOL bNew, u32 ui32New,
1541 u32 ui32NewReset, u32 ui32CountersReg,
1542 u32 *pui32Time, IMG_BOOL *pbActive,
1543 struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs,
1546 struct SYS_DATA *psSysData;
1547 struct PVRSRV_POWER_DEV *psPowerDevice;
1548 IMG_BOOL bPowered = IMG_FALSE;
1549 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
1550 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1553 psDevInfo->ui32HWGroupRequested = ui32New;
1554 psDevInfo->ui32HWReset |= ui32NewReset;
1556 if (SysAcquireData(&psSysData) != PVRSRV_OK)
1557 return PVRSRV_ERROR_GENERIC;
1559 psPowerDevice = psSysData->psPowerDeviceList;
1560 while (psPowerDevice) {
1561 if (psPowerDevice->ui32DeviceIndex ==
1562 psDeviceNode->sDevId.ui32DeviceIndex) {
1564 (IMG_BOOL)(psPowerDevice->eCurrentPowerState ==
1565 PVRSRV_POWER_STATE_D0);
1569 psPowerDevice = psPowerDevice->psNext;
1572 *pbActive = bPowered;
1577 struct PVRSRV_SGXDEV_DIFF_INFO sNew,
1578 *psPrev = &psDevInfo->sDiffInfo;
1581 sNew.ui32Time[0] = OSClockus();
1582 *pui32Time = sNew.ui32Time[0];
1583 if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) {
1584 u32 __iomem *time_wraps;
1587 OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
1589 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1590 sNew.aui32Counters[i] =
1591 OSReadHWReg(psDevInfo->pvRegsBaseKM,
1592 ui32CountersReg + (i * 4));
1595 if (psDevInfo->ui32HWGroupRequested != *pui32Old) {
1596 if (psDevInfo->ui32HWReset != 0) {
1597 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
1600 ui32HWGroupRequested |
1601 psDevInfo->ui32HWReset);
1602 psDevInfo->ui32HWReset = 0;
1604 OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg,
1605 psDevInfo->ui32HWGroupRequested);
1608 sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter;
1609 sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
1611 time_wraps = &psDevInfo->psSGXHostCtl->ui32TimeWraps;
1614 sNew.ui32Time[1] = readl(time_wraps);
1616 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1617 psDiffs->aui32Counters[i] =
1618 sNew.aui32Counters[i] -
1619 psPrev->aui32Counters[i];
1622 psDiffs->ui32Marker[0] =
1623 sNew.ui32Marker[0] - psPrev->ui32Marker[0];
1624 psDiffs->ui32Marker[1] =
1625 sNew.ui32Marker[1] - psPrev->ui32Marker[1];
1627 psDiffs->ui32Time[0] =
1628 sNew.ui32Time[0] - psPrev->ui32Time[0];
1629 psDiffs->ui32Time[1] =
1630 sNew.ui32Time[1] - psPrev->ui32Time[1];
1634 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i)
1635 psDiffs->aui32Counters[i] = 0;
1637 psDiffs->ui32Marker[0] = 0;
1638 psDiffs->ui32Marker[1] = 0;
1640 psDiffs->ui32Time[0] = 0;
1641 psDiffs->ui32Time[1] = 0;
1645 SGXTestActivePowerEvent(psDeviceNode);
1652 enum PVRSRV_ERROR SGXReadHWPerfCBKM(void *hDevHandle, u32 ui32ArraySize,
1653 struct PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
1654 u32 *pui32DataCount, u32 *pui32ClockSpeed,
1655 u32 *pui32HostTimeStamp)
1657 enum PVRSRV_ERROR eError = PVRSRV_OK;
1658 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
1659 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1660 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1661 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1665 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
1667 struct SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry =
1668 &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
1670 psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
1671 psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
1672 psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
1673 psClientHWPerfEntry[i].ui32Clocksx16 =
1674 SGXConvertTimeStamp(psDevInfo, psMKPerfEntry->ui32TimeWraps,
1675 psMKPerfEntry->ui32Time);
1676 OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0],
1677 &psMKPerfEntry->ui32Counters[0],
1678 sizeof(psMKPerfEntry->ui32Counters));
1680 psHWPerfCB->ui32Roff =
1681 (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
1684 *pui32DataCount = i;
1685 *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
1686 *pui32HostTimeStamp = OSClockus();