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>
34 #include <linux/vmalloc.h>
38 #include "services_headers.h"
39 #include "buffer_manager.h"
40 #include "sgxapi_km.h"
42 #include "sgxinfokm.h"
43 #include "sgxconfig.h"
44 #include "sysconfig.h"
45 #include "pvr_bridge_km.h"
46 #include "sgx_bridge_km.h"
48 #include "bridged_support.h"
50 #include "pvr_pdump.h"
58 #include "pvrversion.h"
59 #include "sgx_options.h"
61 #ifdef CONFIG_DEBUG_FS
62 #include "pvr_debugfs.h"
65 static IMG_BOOL SGX_ISRHandler(void *pvData);
67 static u32 gui32EventStatusServicesByISR;
69 static enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
70 struct PVRSRV_DEVICE_NODE *psDeviceNode);
72 static void SGXCommandComplete(struct PVRSRV_DEVICE_NODE *psDeviceNode)
76 SGXScheduleProcessQueuesKM(psDeviceNode);
79 static u32 DeinitDevInfo(struct PVRSRV_SGXDEV_INFO *psDevInfo)
81 if (psDevInfo->psKernelCCBInfo != NULL)
82 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
83 sizeof(struct PVRSRV_SGX_CCB_INFO),
84 psDevInfo->psKernelCCBInfo, NULL);
89 static enum PVRSRV_ERROR InitDevInfo(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
90 struct PVRSRV_DEVICE_NODE *psDeviceNode,
91 struct SGX_BRIDGE_INIT_INFO *psInitInfo)
93 struct PVRSRV_SGXDEV_INFO *psDevInfo =
94 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
95 enum PVRSRV_ERROR eError;
97 struct PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = NULL;
99 PVR_UNREFERENCED_PARAMETER(psPerProc);
100 psDevInfo->sScripts = psInitInfo->sScripts;
102 psDevInfo->psKernelCCBMemInfo =
103 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
104 psDevInfo->psKernelCCB =
105 (struct PVRSRV_SGX_KERNEL_CCB *)psDevInfo->psKernelCCBMemInfo->
108 psDevInfo->psKernelCCBCtlMemInfo =
109 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
110 psDevInfo->psKernelCCBCtl =
111 (struct PVRSRV_SGX_CCB_CTL *)psDevInfo->psKernelCCBCtlMemInfo->
114 psDevInfo->psKernelCCBEventKickerMemInfo =
115 (struct PVRSRV_KERNEL_MEM_INFO *)
116 psInitInfo->hKernelCCBEventKickerMemInfo;
117 psDevInfo->pui32KernelCCBEventKicker =
118 (u32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
120 psDevInfo->psKernelSGXHostCtlMemInfo =
121 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
122 hKernelSGXHostCtlMemInfo;
123 psDevInfo->psSGXHostCtl = (struct SGXMKIF_HOST_CTL __force __iomem *)
124 psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
126 psDevInfo->psKernelSGXTA3DCtlMemInfo =
127 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
128 hKernelSGXTA3DCtlMemInfo;
130 psDevInfo->psKernelSGXMiscMemInfo =
131 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
133 psDevInfo->psKernelHWPerfCBMemInfo =
134 (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
135 psDevInfo->psKernelEDMStatusBufferMemInfo =
136 psInitInfo->hKernelEDMStatusBufferMemInfo;
138 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
139 sizeof(struct PVRSRV_SGX_CCB_INFO),
140 (void **)&psKernelCCBInfo, NULL);
141 if (eError != PVRSRV_OK) {
142 PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory");
143 goto failed_allockernelccb;
146 OSMemSet(psKernelCCBInfo, 0, sizeof(struct PVRSRV_SGX_CCB_INFO));
147 psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
148 psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
149 psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
150 psKernelCCBInfo->pui32WriteOffset =
151 &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
152 psKernelCCBInfo->pui32ReadOffset =
153 &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
154 psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
156 psDevInfo->ui32HostKickAddress = psInitInfo->ui32HostKickAddress;
158 psDevInfo->ui32GetMiscInfoAddress = psInitInfo->ui32GetMiscInfoAddress;
160 psDevInfo->bForcePTOff = IMG_FALSE;
162 psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
164 psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
165 psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
166 psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
167 psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
169 OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData,
170 sizeof(psDevInfo->asSGXDevData));
172 psDevInfo->state_buf_ofs = psInitInfo->state_buf_ofs;
176 failed_allockernelccb:
177 DeinitDevInfo(psDevInfo);
182 static enum PVRSRV_ERROR SGXRunScript(struct PVRSRV_SGXDEV_INFO *psDevInfo,
183 union SGX_INIT_COMMAND *psScript,
184 u32 ui32NumInitCommands)
187 union SGX_INIT_COMMAND *psComm;
189 for (ui32PC = 0, psComm = psScript;
190 ui32PC < ui32NumInitCommands; ui32PC++, psComm++) {
191 switch (psComm->eOp) {
192 case SGX_INIT_OP_WRITE_HW_REG:
194 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
195 psComm->sWriteHWReg.ui32Offset,
196 psComm->sWriteHWReg.ui32Value);
197 PDUMPREG(psComm->sWriteHWReg.ui32Offset,
198 psComm->sWriteHWReg.ui32Value);
202 case SGX_INIT_OP_PDUMP_HW_REG:
204 PDUMPREG(psComm->sPDumpHWReg.ui32Offset,
205 psComm->sPDumpHWReg.ui32Value);
209 case SGX_INIT_OP_HALT:
213 case SGX_INIT_OP_ILLEGAL:
217 PVR_DPF(PVR_DBG_ERROR,
218 "SGXRunScript: PC %d: Illegal command: %d",
219 ui32PC, psComm->eOp);
220 return PVRSRV_ERROR_GENERIC;
226 return PVRSRV_ERROR_GENERIC;
229 enum PVRSRV_ERROR SGXInitialise(struct PVRSRV_SGXDEV_INFO *psDevInfo,
230 IMG_BOOL bHardwareRecovery)
232 enum PVRSRV_ERROR eError;
234 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
235 "SGX initialisation script part 1\n");
237 SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1,
238 SGX_MAX_INIT_COMMANDS);
239 if (eError != PVRSRV_OK) {
240 PVR_DPF(PVR_DBG_ERROR,
241 "SGXInitialise: SGXRunScript (part 1) failed (%d)",
243 return PVRSRV_ERROR_GENERIC;
245 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
246 "End of SGX initialisation script part 1\n");
248 SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
252 *psDevInfo->pui32KernelCCBEventKicker = 0;
254 PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
255 sizeof(*psDevInfo->pui32KernelCCBEventKicker),
256 PDUMP_FLAGS_CONTINUOUS,
257 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
260 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
261 "SGX initialisation script part 2\n");
263 SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2,
264 SGX_MAX_INIT_COMMANDS);
265 if (eError != PVRSRV_OK) {
266 PVR_DPF(PVR_DBG_ERROR,
267 "SGXInitialise: SGXRunScript (part 2) failed (%d)",
269 return PVRSRV_ERROR_GENERIC;
271 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
272 "End of SGX initialisation script part 2\n");
274 SGXStartTimer(psDevInfo, (IMG_BOOL)!bHardwareRecovery);
276 if (bHardwareRecovery) {
277 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
278 psDevInfo->psSGXHostCtl;
280 if (PollForValueKM(&psSGXHostCtl->ui32InterruptClearFlags, 0,
281 PVRSRV_USSE_EDM_INTERRUPT_HWR,
282 MAX_HW_TIME_US / WAIT_TRY_COUNT, 1000) != PVRSRV_OK) {
283 PVR_DPF(PVR_DBG_ERROR, "SGXInitialise: "
284 "Wait for uKernel HW Recovery failed");
286 return PVRSRV_ERROR_RETRY;
290 PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset ==
291 psDevInfo->psKernelCCBCtl->ui32WriteOffset);
296 enum PVRSRV_ERROR SGXDeinitialise(void *hDevCookie)
298 struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
300 enum PVRSRV_ERROR eError;
302 if (psDevInfo->pvRegsBaseKM == NULL)
305 eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands,
306 SGX_MAX_DEINIT_COMMANDS);
307 if (eError != PVRSRV_OK) {
308 PVR_DPF(PVR_DBG_ERROR,
309 "SGXDeinitialise: SGXRunScript failed (%d)", eError);
310 return PVRSRV_ERROR_GENERIC;
316 static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
318 struct PVRSRV_SGXDEV_INFO *psDevInfo;
319 void *hKernelDevMemContext;
320 struct IMG_DEV_PHYADDR sPDDevPAddr;
322 struct PVRSRV_DEVICE_NODE *psDeviceNode = (struct PVRSRV_DEVICE_NODE *)
324 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap =
325 psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
326 enum PVRSRV_ERROR eError;
328 PDUMPCOMMENT("SGX Initialisation Part 1");
330 PDUMPCOMMENT("SGX Core Version Information: %s",
331 SGX_CORE_FRIENDLY_NAME);
332 PDUMPCOMMENT("SGX Core Revision Information: multi rev support");
334 if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
335 sizeof(struct PVRSRV_SGXDEV_INFO),
336 (void **)&psDevInfo, NULL) != PVRSRV_OK) {
337 PVR_DPF(PVR_DBG_ERROR,
338 "DevInitSGXPart1 : Failed to alloc memory for DevInfo");
339 return PVRSRV_ERROR_OUT_OF_MEMORY;
341 OSMemSet(psDevInfo, 0, sizeof(struct PVRSRV_SGXDEV_INFO));
343 psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
344 psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
346 psDeviceNode->pvDevice = (void *) psDevInfo;
348 psDevInfo->pvDeviceMemoryHeap = (void *) psDeviceMemoryHeap;
350 hKernelDevMemContext = BM_CreateContext(psDeviceNode, &sPDDevPAddr,
352 if (!hKernelDevMemContext)
355 psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
357 for (i = 0; i < psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) {
360 switch (psDeviceMemoryHeap[i].DevMemHeapType) {
361 case DEVICE_MEMORY_HEAP_KERNEL:
362 case DEVICE_MEMORY_HEAP_SHARED:
363 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
366 BM_CreateHeap(hKernelDevMemContext,
367 &psDeviceMemoryHeap[i]);
372 psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
378 eError = MMU_BIFResetPDAlloc(psDevInfo);
379 if (eError != PVRSRV_OK) {
380 PVR_DPF(PVR_DBG_ERROR,
381 "DevInitSGX : Failed to alloc memory for BIF reset");
391 type = psDeviceMemoryHeap[i].DevMemHeapType;
392 if (type != DEVICE_MEMORY_HEAP_KERNEL &&
393 type != DEVICE_MEMORY_HEAP_SHARED &&
394 type != DEVICE_MEMORY_HEAP_SHARED_EXPORTED)
396 BM_DestroyHeap(psDeviceMemoryHeap[i].hDevMemHeap);
398 BM_DestroyContext(hKernelDevMemContext);
400 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
401 sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
403 return PVRSRV_ERROR_GENERIC;
406 enum PVRSRV_ERROR SGXGetInfoForSrvinitKM(void *hDevHandle,
407 struct SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
409 struct PVRSRV_DEVICE_NODE *psDeviceNode;
410 struct PVRSRV_SGXDEV_INFO *psDevInfo;
411 enum PVRSRV_ERROR eError;
413 PDUMPCOMMENT("SGXGetInfoForSrvinit");
415 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
416 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
418 psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
421 PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
422 if (eError != PVRSRV_OK) {
423 PVR_DPF(PVR_DBG_ERROR, "SGXGetInfoForSrvinit: "
424 "PVRSRVGetDeviceMemHeapsKM failed (%d)",
426 return PVRSRV_ERROR_GENERIC;
432 enum PVRSRV_ERROR DevInitSGXPart2KM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
434 struct SGX_BRIDGE_INIT_INFO *psInitInfo)
436 struct PVRSRV_DEVICE_NODE *psDeviceNode;
437 struct PVRSRV_SGXDEV_INFO *psDevInfo;
438 enum PVRSRV_ERROR eError;
439 struct SGX_DEVICE_MAP *psSGXDeviceMap;
440 enum PVR_POWER_STATE eDefaultPowerState;
443 PDUMPCOMMENT("SGX Initialisation Part 2");
445 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
446 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
448 eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
449 if (eError != PVRSRV_OK) {
450 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
451 "Failed to load EDM program");
452 goto failed_init_dev_info;
456 eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
457 (void **) &psSGXDeviceMap);
458 if (eError != PVRSRV_OK) {
459 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
460 "Failed to get device memory map!");
461 return PVRSRV_ERROR_INIT_FAILURE;
464 if (psSGXDeviceMap->pvRegsCpuVBase) {
465 psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
467 psDevInfo->pvRegsBaseKM =
468 OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
469 psSGXDeviceMap->ui32RegsSize,
470 PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
472 if (!psDevInfo->pvRegsBaseKM) {
473 PVR_DPF(PVR_DBG_ERROR,
474 "DevInitSGXPart2KM: Failed to map in regs\n");
475 return PVRSRV_ERROR_BAD_MAPPING;
478 psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
479 psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
481 psDeviceNode->pvISRData = psDeviceNode;
483 PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
486 l = readl(&psDevInfo->psSGXHostCtl->ui32PowerStatus);
487 l |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
488 writel(l, &psDevInfo->psSGXHostCtl->ui32PowerStatus);
490 eDefaultPowerState = PVRSRV_POWER_STATE_D3;
492 eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
494 SGXPostPowerStateExt,
495 SGXPreClockSpeedChange,
496 SGXPostClockSpeedChange,
497 (void *) psDeviceNode,
498 PVRSRV_POWER_STATE_D3,
500 if (eError != PVRSRV_OK) {
501 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
502 "failed to register device with power manager");
506 OSMemSet(psDevInfo->psKernelCCB, 0,
507 sizeof(struct PVRSRV_SGX_KERNEL_CCB));
508 OSMemSet(psDevInfo->psKernelCCBCtl, 0,
509 sizeof(struct PVRSRV_SGX_CCB_CTL));
510 OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0,
511 sizeof(*psDevInfo->pui32KernelCCBEventKicker));
512 PDUMPCOMMENT("Initialise Kernel CCB");
513 PDUMPMEM(NULL, psDevInfo->psKernelCCBMemInfo, 0,
514 sizeof(struct PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
515 MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
516 PDUMPCOMMENT("Initialise Kernel CCB Control");
517 PDUMPMEM(NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
518 sizeof(struct PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
519 MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
520 PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
521 PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
522 sizeof(*psDevInfo->pui32KernelCCBEventKicker),
523 PDUMP_FLAGS_CONTINUOUS,
524 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
526 psDevInfo->hTimer = SGXOSTimerInit(psDeviceNode);
527 if (!psDevInfo->hTimer)
528 PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM : "
529 "Failed to initialize HW recovery timer");
533 failed_init_dev_info:
537 static enum PVRSRV_ERROR DevDeInitSGX(void *pvDeviceNode)
539 struct PVRSRV_DEVICE_NODE *psDeviceNode =
540 (struct PVRSRV_DEVICE_NODE *)pvDeviceNode;
541 struct PVRSRV_SGXDEV_INFO *psDevInfo =
542 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
543 enum PVRSRV_ERROR eError;
545 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
546 struct SGX_DEVICE_MAP *psSGXDeviceMap;
549 PVR_DPF(PVR_DBG_ERROR, "DevDeInitSGX: Null DevInfo");
552 if (psDevInfo->hTimer) {
553 SGXOSTimerCancel(psDevInfo->hTimer);
554 SGXOSTimerDeInit(psDevInfo->hTimer);
555 psDevInfo->hTimer = NULL;
558 MMU_BIFResetPDFree(psDevInfo);
560 DeinitDevInfo(psDevInfo);
564 (struct DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
566 ui32Heap < psDeviceNode->sDevMemoryInfo.ui32HeapCount;
568 switch (psDeviceMemoryHeap[ui32Heap].DevMemHeapType) {
569 case DEVICE_MEMORY_HEAP_KERNEL:
570 case DEVICE_MEMORY_HEAP_SHARED:
571 case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
573 if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap !=
575 BM_DestroyHeap(psDeviceMemoryHeap
576 [ui32Heap].hDevMemHeap);
582 if (!pvr_put_ctx(psDeviceNode->sDevMemoryInfo.pBMKernelContext))
583 pr_err("%s: kernel context still in use, can't free it",
586 eError = PVRSRVRemovePowerDevice(
587 ((struct PVRSRV_DEVICE_NODE *)pvDeviceNode)->
588 sDevId.ui32DeviceIndex);
589 if (eError != PVRSRV_OK)
592 eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
593 (void **)&psSGXDeviceMap);
594 if (eError != PVRSRV_OK) {
595 PVR_DPF(PVR_DBG_ERROR,
596 "DevDeInitSGX: Failed to get device memory map!");
600 if (!psSGXDeviceMap->pvRegsCpuVBase)
601 if (psDevInfo->pvRegsBaseKM != NULL)
602 OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
603 psDevInfo->ui32RegSize,
604 PVRSRV_HAP_KERNEL_ONLY |
608 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
609 sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
611 psDeviceNode->pvDevice = NULL;
613 if (psDeviceMemoryHeap != NULL)
614 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
615 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
616 psDeviceNode->sDevMemoryInfo.ui32HeapCount,
617 psDeviceMemoryHeap, NULL);
622 static struct PVRSRV_PER_PROCESS_DATA *find_cur_proc_data(
623 struct PVRSRV_DEVICE_NODE *dev)
625 struct PVRSRV_SGXDEV_INFO *dev_info = dev->pvDevice;
626 u32 page_dir = readl(dev_info->pvRegsBaseKM +
627 EUR_CR_BIF_DIR_LIST_BASE0);
628 struct BM_CONTEXT *bm_ctx;
629 struct RESMAN_CONTEXT *res_ctx = NULL;
630 struct PVRSRV_PER_PROCESS_DATA *proc_data = NULL;
632 bm_ctx = bm_find_context(dev->sDevMemoryInfo.pBMContext, page_dir);
634 res_ctx = pvr_get_resman_ctx(bm_ctx);
637 proc_data = pvr_get_proc_by_ctx(res_ctx);
642 static void pr_err_process_info(struct PVRSRV_PER_PROCESS_DATA *proc)
644 struct task_struct *tsk;
652 tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
653 pr_err("PID = %d, process name = %s\n", pid, tsk->comm);
657 static void pr_err_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
659 pr_err("EVENT_STATUS = 0x%08X\n"
660 "EVENT_STATUS2 = 0x%08X\n"
661 "BIF_CTRL = 0x%08X\n"
662 "BIF_INT_STAT = 0x%08X\n"
663 "BIF_MEM_REQ_STAT = 0x%08X\n"
664 "BIF_FAULT = 0x%08X\n"
665 "CLKGATECTL = 0x%08X\n",
666 readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS),
667 readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS2),
668 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_CTRL),
669 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_INT_STAT),
670 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
671 readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_FAULT),
672 readl(psDevInfo->pvRegsBaseKM + EUR_CR_CLKGATECTL));
675 /* Should be called with pvr_lock held */
677 HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode, const char *caller)
679 enum PVRSRV_ERROR eError;
680 struct PVRSRV_SGXDEV_INFO *psDevInfo =
681 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
682 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
683 psDevInfo->psSGXHostCtl;
684 struct PVRSRV_PER_PROCESS_DATA *proc;
686 int max_retries = 10;
688 BUG_ON(!pvr_is_locked());
690 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
691 l |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
692 writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
694 pr_err("SGX Hardware Recovery triggered (from %s)\n", caller);
696 proc = find_cur_proc_data(psDeviceNode);
698 pr_err_process_info(proc);
699 pr_err_sgx_registers(psDevInfo);
700 #ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
701 edm_trace_print(psDevInfo, NULL, 0);
704 #ifdef CONFIG_DEBUG_FS
705 pvr_hwrec_dump(proc, psDevInfo);
711 eError = SGXInitialise(psDevInfo, IMG_TRUE);
712 if (eError != PVRSRV_ERROR_RETRY)
714 } while (max_retries--);
716 if (eError != PVRSRV_OK) {
717 pr_err("%s: recovery failed (%d). Disabling the driver",
728 SGXScheduleProcessQueues(psDeviceNode);
730 PVRSRVProcessQueues(IMG_TRUE);
733 static unsigned long sgx_reset_forced;
735 static void SGXOSTimer(struct work_struct *work)
737 struct timer_work_data *data = container_of(work,
738 struct timer_work_data,
740 struct PVRSRV_DEVICE_NODE *psDeviceNode = data->psDeviceNode;
741 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
742 static u32 ui32EDMTasks;
743 static u32 ui32LockupCounter;
744 static u32 ui32NumResets;
745 u32 ui32CurrentEDMTasks;
746 IMG_BOOL bLockup = IMG_FALSE;
747 IMG_BOOL bPoweredDown;
751 if (!data->armed || pvr_is_disabled()) {
756 psDevInfo->ui32TimeStamp++;
758 #if defined(NO_HARDWARE)
759 bPoweredDown = IMG_TRUE;
761 bPoweredDown = (IMG_BOOL) !SGXIsDevicePowered(psDeviceNode);
765 ui32LockupCounter = 0;
768 ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM,
769 psDevInfo->ui32EDMTaskReg0);
770 if (psDevInfo->ui32EDMTaskReg1 != 0)
771 ui32CurrentEDMTasks ^=
772 OSReadHWReg(psDevInfo->pvRegsBaseKM,
773 psDevInfo->ui32EDMTaskReg1);
774 if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
775 (psDevInfo->ui32NumResets == ui32NumResets)) {
777 if (ui32LockupCounter == 3) {
778 ui32LockupCounter = 0;
779 PVR_DPF(PVR_DBG_ERROR, "SGXOSTimer() "
780 "detected SGX lockup (0x%x tasks)",
786 ui32LockupCounter = 0;
787 ui32EDMTasks = ui32CurrentEDMTasks;
788 ui32NumResets = psDevInfo->ui32NumResets;
793 bLockup |= cmpxchg(&sgx_reset_forced, 1, 0);
796 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
797 psDevInfo->psSGXHostCtl;
801 l = readl(&psSGXHostCtl->ui32HostDetectedLockups);
803 writel(l, &psSGXHostCtl->ui32HostDetectedLockups);
805 HWRecoveryResetSGX(psDeviceNode, __func__);
809 queue_delayed_work(data->work_queue, &data->work,
810 msecs_to_jiffies(data->interval));
815 struct timer_work_data *
816 SGXOSTimerInit(struct PVRSRV_DEVICE_NODE *psDeviceNode)
818 struct timer_work_data *data;
820 data = kzalloc(sizeof(struct timer_work_data), GFP_KERNEL);
824 data->work_queue = create_workqueue("SGXOSTimer");
825 if (!data->work_queue) {
830 data->interval = 150;
831 data->psDeviceNode = psDeviceNode;
832 INIT_DELAYED_WORK(&data->work, SGXOSTimer);
837 void SGXOSTimerDeInit(struct timer_work_data *data)
840 destroy_workqueue(data->work_queue);
844 enum PVRSRV_ERROR SGXOSTimerEnable(struct timer_work_data *data)
847 return PVRSRV_ERROR_GENERIC;
849 if (queue_delayed_work(data->work_queue, &data->work,
850 msecs_to_jiffies(data->interval))) {
855 return PVRSRV_ERROR_GENERIC;
858 enum PVRSRV_ERROR SGXOSTimerCancel(struct timer_work_data *data)
861 return PVRSRV_ERROR_GENERIC;
864 cancel_delayed_work(&data->work);
869 int sgx_force_reset(void)
871 return !cmpxchg(&sgx_reset_forced, 0, 1);
874 static IMG_BOOL SGX_ISRHandler(void *pvData)
876 IMG_BOOL bInterruptProcessed = IMG_FALSE;
879 u32 ui32EventStatus, ui32EventEnable;
880 u32 ui32EventClear = 0;
881 struct PVRSRV_DEVICE_NODE *psDeviceNode;
882 struct PVRSRV_SGXDEV_INFO *psDevInfo;
884 if (pvData == NULL) {
885 PVR_DPF(PVR_DBG_ERROR,
886 "SGX_ISRHandler: Invalid params\n");
887 return bInterruptProcessed;
890 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)pvData;
891 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
894 OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
895 ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM,
896 EUR_CR_EVENT_HOST_ENABLE);
898 gui32EventStatusServicesByISR = ui32EventStatus;
900 ui32EventStatus &= ui32EventEnable;
902 if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
903 ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
905 if (ui32EventClear) {
906 bInterruptProcessed = IMG_TRUE;
909 EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
911 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
912 EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
916 return bInterruptProcessed;
919 static void SGX_MISRHandler(void *pvData)
921 struct PVRSRV_DEVICE_NODE *psDeviceNode =
922 (struct PVRSRV_DEVICE_NODE *)pvData;
923 struct PVRSRV_SGXDEV_INFO *psDevInfo =
924 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
925 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
926 psDevInfo->psSGXHostCtl;
929 enum PVRSRV_ERROR err;
931 dev_idx = psDeviceNode->sDevId.ui32DeviceIndex;
935 err = PVRSRVSetDevicePowerStateKM(dev_idx, PVRSRV_POWER_STATE_D0);
936 BUG_ON(err != PVRSRV_OK);
938 l1 = readl(&psSGXHostCtl->ui32InterruptFlags);
939 l2 = readl(&psSGXHostCtl->ui32InterruptClearFlags);
941 if ((l1 & PVRSRV_USSE_EDM_INTERRUPT_HWR) &&
942 !(l2 & PVRSRV_USSE_EDM_INTERRUPT_HWR))
943 HWRecoveryResetSGX(psDeviceNode, __func__);
945 if (psDeviceNode->bReProcessDeviceCommandComplete)
946 SGXScheduleProcessQueues(psDeviceNode);
948 SGXTestActivePowerEvent(psDeviceNode);
953 enum PVRSRV_ERROR SGXRegisterDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode)
955 struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
956 struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
958 psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
959 psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
961 psDeviceNode->pfnInitDevice = DevInitSGXPart1;
962 psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
964 psDeviceNode->pfnInitDeviceCompatCheck = SGXDevInitCompatCheck;
966 psDeviceNode->pfnMMUInitialise = MMU_Initialise;
967 psDeviceNode->pfnMMUFinalise = MMU_Finalise;
968 psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
969 psDeviceNode->pfnMMUCreate = MMU_Create;
970 psDeviceNode->pfnMMUDelete = MMU_Delete;
971 psDeviceNode->pfnMMUAlloc = MMU_Alloc;
972 psDeviceNode->pfnMMUFree = MMU_Free;
973 psDeviceNode->pfnMMUMapPages = MMU_MapPages;
974 psDeviceNode->pfnMMUMapShadow = MMU_MapShadow;
975 psDeviceNode->pfnMMUUnmapPages = MMU_UnmapPages;
976 psDeviceNode->pfnMMUMapScatter = MMU_MapScatter;
977 psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
978 psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
980 psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
981 psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
983 psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
985 psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
987 psDevMemoryInfo->ui32AddressSpaceSizeLog2 =
988 SGX_FEATURE_ADDRESS_SPACE_SIZE;
990 psDevMemoryInfo->ui32Flags = 0;
991 psDevMemoryInfo->ui32HeapCount = SGX_MAX_HEAP_ID;
992 psDevMemoryInfo->ui32SyncHeapID = SGX_SYNCINFO_HEAP_ID;
994 psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_HEAP_ID;
996 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
997 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
998 psDevMemoryInfo->ui32HeapCount,
999 (void **) &psDevMemoryInfo->psDeviceMemoryHeap,
1000 NULL) != PVRSRV_OK) {
1001 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterDevice : "
1002 "Failed to alloc memory for "
1003 "struct DEVICE_MEMORY_HEAP_INFO");
1004 return PVRSRV_ERROR_OUT_OF_MEMORY;
1006 OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0,
1007 sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
1008 psDevMemoryInfo->ui32HeapCount);
1010 psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
1012 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapID =
1013 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
1014 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].sDevVAddrBase.uiAddr =
1015 SGX_GENERAL_HEAP_BASE;
1016 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapSize =
1017 SGX_GENERAL_HEAP_SIZE;
1018 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32Attribs =
1019 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1020 PVRSRV_HAP_SINGLE_PROCESS;
1021 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszName = "General";
1022 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszBSName = "General BS";
1023 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].DevMemHeapType =
1024 DEVICE_MEMORY_HEAP_PERCONTEXT;
1026 psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32DataPageSize =
1029 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapID =
1030 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
1031 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].sDevVAddrBase.uiAddr =
1032 SGX_TADATA_HEAP_BASE;
1033 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapSize =
1034 SGX_TADATA_HEAP_SIZE;
1035 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32Attribs =
1036 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
1037 | PVRSRV_HAP_MULTI_PROCESS;
1038 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszName = "TA Data";
1039 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszBSName = "TA Data BS";
1040 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].DevMemHeapType =
1041 DEVICE_MEMORY_HEAP_PERCONTEXT;
1043 psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32DataPageSize =
1046 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapID =
1047 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
1048 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
1049 SGX_KERNEL_CODE_HEAP_BASE;
1050 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapSize =
1051 SGX_KERNEL_CODE_HEAP_SIZE;
1052 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32Attribs =
1053 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1054 PVRSRV_HAP_MULTI_PROCESS;
1055 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel Code";
1056 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName =
1058 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].DevMemHeapType =
1059 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1061 psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32DataPageSize =
1064 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapID =
1065 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
1066 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
1067 SGX_KERNEL_DATA_HEAP_BASE;
1068 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapSize =
1069 SGX_KERNEL_DATA_HEAP_SIZE;
1070 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32Attribs =
1071 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1072 PVRSRV_HAP_MULTI_PROCESS;
1073 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszName = "KernelData";
1074 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszBSName = "KernelData BS";
1075 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].DevMemHeapType =
1076 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1078 psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32DataPageSize =
1081 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapID =
1082 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
1083 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1084 SGX_PIXELSHADER_HEAP_BASE;
1085 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapSize =
1086 SGX_PIXELSHADER_HEAP_SIZE;
1087 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32Attribs =
1088 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1089 PVRSRV_HAP_SINGLE_PROCESS;
1090 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszName = "PixelShaderUSSE";
1091 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszBSName =
1092 "PixelShaderUSSE BS";
1093 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].DevMemHeapType =
1094 DEVICE_MEMORY_HEAP_PERCONTEXT;
1096 psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32DataPageSize =
1099 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapID =
1100 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
1101 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
1102 SGX_VERTEXSHADER_HEAP_BASE;
1103 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapSize =
1104 SGX_VERTEXSHADER_HEAP_SIZE;
1105 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32Attribs =
1106 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1107 PVRSRV_HAP_SINGLE_PROCESS;
1108 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszName =
1110 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszBSName =
1111 "VertexShaderUSSE BS";
1112 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].DevMemHeapType =
1113 DEVICE_MEMORY_HEAP_PERCONTEXT;
1115 psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32DataPageSize =
1118 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapID =
1119 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
1120 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].sDevVAddrBase.uiAddr =
1121 SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
1122 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapSize =
1123 SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
1124 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32Attribs =
1125 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1126 PVRSRV_HAP_SINGLE_PROCESS;
1127 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszName =
1129 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszBSName =
1130 "PDSPixelCodeData BS";
1131 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].DevMemHeapType =
1132 DEVICE_MEMORY_HEAP_PERCONTEXT;
1134 psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32DataPageSize =
1137 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapID =
1138 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
1139 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].sDevVAddrBase.
1140 uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
1141 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapSize =
1142 SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
1143 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32Attribs =
1144 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1145 PVRSRV_HAP_SINGLE_PROCESS;
1146 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszName =
1147 "PDSVertexCodeData";
1148 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszBSName =
1149 "PDSVertexCodeData BS";
1150 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].DevMemHeapType =
1151 DEVICE_MEMORY_HEAP_PERCONTEXT;
1153 psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32DataPageSize =
1156 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapID =
1157 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
1158 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].sDevVAddrBase.uiAddr =
1159 SGX_SYNCINFO_HEAP_BASE;
1160 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapSize =
1161 SGX_SYNCINFO_HEAP_SIZE;
1163 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32Attribs =
1164 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1165 PVRSRV_HAP_MULTI_PROCESS;
1166 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszName = "CacheCoherent";
1167 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszBSName = "CacheCoherent BS";
1169 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].DevMemHeapType =
1170 DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
1172 psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32DataPageSize =
1175 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapID =
1176 HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
1177 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].sDevVAddrBase.uiAddr =
1178 SGX_3DPARAMETERS_HEAP_BASE;
1179 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapSize =
1180 SGX_3DPARAMETERS_HEAP_SIZE;
1181 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszName = "3DParameters";
1182 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszBSName =
1184 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
1185 PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
1186 PVRSRV_HAP_SINGLE_PROCESS;
1187 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
1188 DEVICE_MEMORY_HEAP_PERCONTEXT;
1190 psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32DataPageSize =
1196 enum PVRSRV_ERROR SGXGetClientInfoKM(void *hDevCookie,
1197 struct SGX_CLIENT_INFO *psClientInfo)
1199 struct PVRSRV_SGXDEV_INFO *psDevInfo =
1200 (struct PVRSRV_SGXDEV_INFO *)
1201 ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
1203 psDevInfo->ui32ClientRefCount++;
1205 if (psDevInfo->ui32ClientRefCount == 1)
1206 psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
1208 psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
1210 OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData,
1211 sizeof(psClientInfo->asDevData));
1216 enum PVRSRV_ERROR SGXDevInitCompatCheck(struct PVRSRV_DEVICE_NODE *psDeviceNode)
1218 struct PVRSRV_SGXDEV_INFO *psDevInfo;
1219 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
1220 enum PVRSRV_ERROR eError;
1221 #if !defined(NO_HARDWARE)
1224 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1227 if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX) {
1228 PVR_DPF(PVR_DBG_ERROR,
1229 "SGXDevInitCompatCheck: Device not of type SGX");
1230 eError = PVRSRV_ERROR_INVALID_PARAMS;
1233 psDevInfo = psDeviceNode->pvDevice;
1234 psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
1236 #if !defined(NO_HARDWARE)
1238 eError = SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
1239 if (eError != PVRSRV_OK) {
1240 pr_err("pvr: unable to validate device DDK version\n");
1244 &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->pvLinAddrKM))->
1246 if ((psSGXFeatures->ui32DDKVersion !=
1247 ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8) |
1248 PVRVERSION_BRANCH)) ||
1249 (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD)) {
1250 pr_err("pvr: incompatible driver DDK revision (%d)"
1251 "/device DDK revision (%d).\n",
1252 PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
1253 eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
1256 PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
1257 "driver DDK (%ld) and device DDK (%ld) match",
1258 PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
1261 opts = psSGXFeatures->ui32BuildOptions;
1262 opt_mismatch = opts ^ SGX_BUILD_OPTIONS;
1263 /* we support the ABIs both with and without EDM tracing option */
1264 opt_mismatch &= ~PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET;
1266 if (SGX_BUILD_OPTIONS & opt_mismatch)
1267 pr_err("pvr: mismatch in driver and microkernel build "
1268 "options; extra options present in driver: "
1269 "(0x%x)", SGX_BUILD_OPTIONS & opt_mismatch);
1271 if (opts & opt_mismatch)
1272 pr_err("pvr: Mismatch in driver and microkernel build "
1273 "options; extra options present in "
1274 "microkernel: (0x%x)", opts & opt_mismatch);
1275 eError = PVRSRV_ERROR_BUILD_MISMATCH;
1278 PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
1279 "Driver and microkernel build options match.");
1289 enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
1290 struct PVRSRV_DEVICE_NODE *psDeviceNode)
1292 enum PVRSRV_ERROR eError;
1293 struct SGXMKIF_COMMAND sCommandData;
1294 struct PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
1295 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1297 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1298 psDevInfo->psKernelSGXMiscMemInfo;
1300 if (!psMemInfo->pvLinAddrKM) {
1301 PVR_DPF(PVR_DBG_ERROR, "SGXGetMiscInfoKM: Invalid address.");
1302 return PVRSRV_ERROR_INVALID_PARAMS;
1304 psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
1305 psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
1306 psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
1308 OSMemSet(psMemInfo->pvLinAddrKM, 0,
1309 sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
1311 sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
1313 OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
1317 eError = SGXScheduleCCBCommandKM(psDeviceNode,
1318 SGXMKIF_COMMAND_REQUEST_SGXMISCINFO,
1319 &sCommandData, KERNEL_ID, 0);
1321 if (eError != PVRSRV_OK) {
1322 PVR_DPF(PVR_DBG_ERROR,
1323 "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed.");
1327 #if !defined(NO_HARDWARE)
1329 IMG_BOOL bTimeout = IMG_TRUE;
1331 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
1332 if ((psSGXMiscInfoInt->
1333 ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) !=
1335 bTimeout = IMG_FALSE;
1339 END_LOOP_UNTIL_TIMEOUT();
1342 return PVRSRV_ERROR_TIMEOUT;
1349 enum PVRSRV_ERROR SGXGetMiscInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
1350 struct SGX_MISC_INFO *psMiscInfo,
1351 struct PVRSRV_DEVICE_NODE *psDeviceNode)
1353 switch (psMiscInfo->eRequest) {
1354 case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
1356 psMiscInfo->uData.ui32SGXClockSpeed =
1357 psDevInfo->ui32CoreClockSpeed;
1361 case SGX_MISC_INFO_REQUEST_SGXREV:
1363 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1364 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1365 psDevInfo->psKernelSGXMiscMemInfo;
1367 SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
1369 &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->
1370 pvLinAddrKM))->sSGXFeatures;
1372 psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
1374 PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
1375 "Core 0x%lx, sw ID 0x%lx, "
1377 psSGXFeatures->ui32CoreRev,
1378 psSGXFeatures->ui32CoreIdSW,
1379 psSGXFeatures->ui32CoreRevSW);
1380 PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
1381 "DDK version 0x%lx, DDK build 0x%lx\n",
1382 psSGXFeatures->ui32DDKVersion,
1383 psSGXFeatures->ui32DDKBuild);
1388 case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
1390 struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
1391 psDevInfo->psKernelSGXMiscMemInfo;
1392 struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
1394 psSGXFeatures = &((struct PVRSRV_SGX_MISCINFO_INFO *)(
1395 psMemInfo->pvLinAddrKM))->sSGXFeatures;
1397 OSMemSet(psMemInfo->pvLinAddrKM, 0,
1398 sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
1400 psSGXFeatures->ui32DDKVersion =
1401 (PVRVERSION_MAJ << 16) |
1402 (PVRVERSION_MIN << 8) | PVRVERSION_BRANCH;
1403 psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
1405 psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
1409 case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
1411 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1412 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1413 unsigned ui32MatchingFlags;
1415 if ((psMiscInfo->uData.ui32NewHWPerfStatus &
1416 ~(PVRSRV_SGX_HWPERF_GRAPHICS_ON |
1417 PVRSRV_SGX_HWPERF_MK_EXECUTION_ON)) != 0) {
1418 return PVRSRV_ERROR_INVALID_PARAMS;
1422 ui32MatchingFlags = readl(&psDevInfo->
1423 psSGXHostCtl->ui32HWPerfFlags);
1424 ui32MatchingFlags &=
1425 psMiscInfo->uData.ui32NewHWPerfStatus;
1426 if ((ui32MatchingFlags & PVRSRV_SGX_HWPERF_GRAPHICS_ON)
1428 psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffff;
1430 if ((ui32MatchingFlags &
1431 PVRSRV_SGX_HWPERF_MK_EXECUTION_ON) == 0UL) {
1432 psHWPerfCB->ui32OrdinalMK_EXECUTION =
1437 writel(psMiscInfo->uData.ui32NewHWPerfStatus,
1438 &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1441 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
1442 "SGX ukernel HWPerf status %u\n",
1443 readl(&psDevInfo->psSGXHostCtl->
1445 PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
1446 offsetof(struct SGXMKIF_HOST_CTL,
1448 sizeof(psDevInfo->psSGXHostCtl->
1450 PDUMP_FLAGS_CONTINUOUS,
1451 MAKEUNIQUETAG(psDevInfo->
1452 psKernelSGXHostCtlMemInfo));
1457 case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
1460 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1461 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1464 psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffffUL;
1467 l = readl(&psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1468 l |= PVRSRV_SGX_HWPERF_GRAPHICS_ON;
1469 writel(l, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1474 case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
1477 writel(0, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
1482 case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
1484 struct SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
1485 &psMiscInfo->uData.sRetrieveCB;
1486 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1487 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1491 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff
1492 && i < psRetrieve->ui32ArraySize; i++) {
1493 struct SGXMKIF_HWPERF_CB_ENTRY *psData =
1494 &psHWPerfCB->psHWPerfCBData[psHWPerfCB->
1497 psRetrieve->psHWPerfData[i].ui32FrameNo =
1498 psData->ui32FrameNo;
1499 psRetrieve->psHWPerfData[i].ui32Type =
1501 PVRSRV_SGX_HWPERF_TYPE_OP_MASK);
1502 psRetrieve->psHWPerfData[i].ui32StartTime =
1504 psRetrieve->psHWPerfData[i].ui32StartTimeWraps =
1505 psData->ui32TimeWraps;
1506 psRetrieve->psHWPerfData[i].ui32EndTime =
1508 psRetrieve->psHWPerfData[i].ui32EndTimeWraps =
1509 psData->ui32TimeWraps;
1510 psRetrieve->psHWPerfData[i].ui32ClockSpeed =
1511 psDevInfo->ui32CoreClockSpeed;
1512 psRetrieve->psHWPerfData[i].ui32TimeMax =
1513 psDevInfo->ui32uKernelTimerClock;
1514 psHWPerfCB->ui32Roff =
1515 (psHWPerfCB->ui32Roff + 1) &
1516 (SGXMKIF_HWPERF_CB_SIZE - 1);
1518 psRetrieve->ui32DataCount = i;
1519 psRetrieve->ui32Time = OSClockus();
1524 return PVRSRV_ERROR_INVALID_PARAMS;
1531 static bool sgxps_active;
1532 static unsigned long sgxps_timeout;
1534 IMG_BOOL isSGXPerfServerActive(void)
1539 if (time_before_eq((unsigned long)OSClockus(), sgxps_timeout))
1542 sgxps_active = false;
1543 PVR_DPF(DBGPRIV_WARNING, "pvr: perf server inactive\n");
1549 void SGXPerfServerMonitor(u32 u32TimeStamp)
1551 if (!sgxps_active) {
1552 PVR_DPF(DBGPRIV_WARNING, "pvr: perf server active\n");
1553 sgxps_active = true;
1556 /* turn off after 1 second of inactivity */
1557 sgxps_timeout = u32TimeStamp + 1000000;
1561 enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg,
1562 u32 *pui32Old, IMG_BOOL bNew, u32 ui32New,
1563 u32 ui32NewReset, u32 ui32CountersReg,
1564 u32 *pui32Time, IMG_BOOL *pbActive,
1565 struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs)
1567 struct SYS_DATA *psSysData;
1568 struct PVRSRV_POWER_DEV *psPowerDevice;
1569 IMG_BOOL bPowered = IMG_FALSE;
1570 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
1571 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1574 psDevInfo->ui32HWGroupRequested = ui32New;
1575 psDevInfo->ui32HWReset |= ui32NewReset;
1577 if (SysAcquireData(&psSysData) != PVRSRV_OK)
1578 return PVRSRV_ERROR_GENERIC;
1580 psPowerDevice = psSysData->psPowerDeviceList;
1581 while (psPowerDevice) {
1582 if (psPowerDevice->ui32DeviceIndex ==
1583 psDeviceNode->sDevId.ui32DeviceIndex) {
1585 (IMG_BOOL)(psPowerDevice->eCurrentPowerState ==
1586 PVRSRV_POWER_STATE_D0);
1590 psPowerDevice = psPowerDevice->psNext;
1593 *pbActive = bPowered;
1598 struct PVRSRV_SGXDEV_DIFF_INFO sNew,
1599 *psPrev = &psDevInfo->sDiffInfo;
1602 sNew.ui32Time[0] = OSClockus();
1603 *pui32Time = sNew.ui32Time[0];
1604 if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) {
1606 SGXPerfServerMonitor(*pui32Time);
1609 OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
1611 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1612 sNew.aui32Counters[i] =
1613 OSReadHWReg(psDevInfo->pvRegsBaseKM,
1614 ui32CountersReg + (i * 4));
1617 if (psDevInfo->ui32HWGroupRequested != *pui32Old) {
1618 if (psDevInfo->ui32HWReset != 0) {
1619 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
1622 ui32HWGroupRequested |
1623 psDevInfo->ui32HWReset);
1624 psDevInfo->ui32HWReset = 0;
1626 OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg,
1627 psDevInfo->ui32HWGroupRequested);
1630 sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter;
1631 sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
1633 sNew.ui32Time[1] = readl(
1634 &psDevInfo->psSGXHostCtl->ui32TimeWraps);
1636 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
1637 psDiffs->aui32Counters[i] =
1638 sNew.aui32Counters[i] -
1639 psPrev->aui32Counters[i];
1642 psDiffs->ui32Marker[0] =
1643 sNew.ui32Marker[0] - psPrev->ui32Marker[0];
1644 psDiffs->ui32Marker[1] =
1645 sNew.ui32Marker[1] - psPrev->ui32Marker[1];
1647 psDiffs->ui32Time[0] =
1648 sNew.ui32Time[0] - psPrev->ui32Time[0];
1649 psDiffs->ui32Time[1] =
1650 sNew.ui32Time[1] - psPrev->ui32Time[1];
1654 for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i)
1655 psDiffs->aui32Counters[i] = 0;
1657 psDiffs->ui32Marker[0] = 0;
1658 psDiffs->ui32Marker[1] = 0;
1660 psDiffs->ui32Time[0] = 0;
1661 psDiffs->ui32Time[1] = 0;
1665 SGXTestActivePowerEvent(psDeviceNode);
1672 enum PVRSRV_ERROR SGXReadHWPerfCBKM(void *hDevHandle, u32 ui32ArraySize,
1673 struct PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
1674 u32 *pui32DataCount, u32 *pui32ClockSpeed,
1675 u32 *pui32HostTimeStamp)
1677 enum PVRSRV_ERROR eError = PVRSRV_OK;
1678 struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
1679 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1680 struct SGXMKIF_HWPERF_CB *psHWPerfCB =
1681 psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
1685 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
1687 struct SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry =
1688 &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
1690 psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
1691 psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
1692 psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
1693 psClientHWPerfEntry[i].ui32Clocksx16 =
1694 SGXConvertTimeStamp(psDevInfo, psMKPerfEntry->ui32TimeWraps,
1695 psMKPerfEntry->ui32Time);
1696 OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0],
1697 &psMKPerfEntry->ui32Counters[0],
1698 sizeof(psMKPerfEntry->ui32Counters));
1700 psHWPerfCB->ui32Roff =
1701 (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
1704 *pui32DataCount = i;
1705 *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
1706 *pui32HostTimeStamp = OSClockus();