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 ******************************************************************************/
28 #include "services_headers.h"
30 #include "sgxinfokm.h"
32 #include "sgxapi_km.h"
33 #include "pvr_pdump.h"
35 #include "sgx_bridge_km.h"
37 #include "pvr_debug.h"
40 #include "pvr_trace_cmd.h"
42 enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle, struct SGX_CCB_KICK *psCCBKick,
43 struct PVRSRV_PER_PROCESS_DATA *proc)
45 enum PVRSRV_ERROR eError;
46 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
47 struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
48 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hCCBKernelMemInfo;
49 struct SGXMKIF_CMDTA_SHARED *psTACmd;
51 struct PVRSRV_DEVICE_NODE *psDeviceNode;
52 struct PVRSRV_SGXDEV_INFO *psDevInfo;
53 struct pvr_trcmd_sgxkick *ktrace;
56 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
57 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
59 if (psCCBKick->bKickRender)
60 ++psDevInfo->ui32KickTARenderCounter;
61 ++psDevInfo->ui32KickTACounter;
63 if (!CCB_OFFSET_IS_VALID
64 (struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick,
66 PVR_DPF(PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset");
67 return PVRSRV_ERROR_INVALID_PARAMS;
70 CCB_DATA_FROM_OFFSET(struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo,
71 psCCBKick, ui32CCBOffset);
73 trcmd_type = psCCBKick->bFirstKickOrResume ?
74 PVR_TRCMD_SGX_FIRSTKICK : PVR_TRCMD_SGX_KICK;
76 ktrace = pvr_trcmd_alloc(trcmd_type, proc->ui32PID, proc->name,
79 if (psCCBKick->hTA3DSyncInfo) {
81 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
82 psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr =
83 psSyncInfo->sWriteOpsCompleteDevVAddr;
85 psTACmd->sTA3DDependency.ui32WriteOpsPendingVal =
86 psSyncInfo->psSyncData->ui32WriteOpsPending;
88 if (psCCBKick->bTADependency)
89 psSyncInfo->psSyncData->ui32WriteOpsPending++;
91 pvr_trcmd_set_syn(&ktrace->ta3d_syn, psSyncInfo);
93 pvr_trcmd_clear_syn(&ktrace->ta3d_syn);
96 if (psCCBKick->hTASyncInfo != NULL) {
97 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
98 psCCBKick->hTASyncInfo;
100 psTACmd->sTATQSyncReadOpsCompleteDevVAddr =
101 psSyncInfo->sReadOpsCompleteDevVAddr;
102 psTACmd->sTATQSyncWriteOpsCompleteDevVAddr =
103 psSyncInfo->sWriteOpsCompleteDevVAddr;
105 psTACmd->ui32TATQSyncReadOpsPendingVal =
106 psSyncInfo->psSyncData->ui32ReadOpsPending++;
107 psTACmd->ui32TATQSyncWriteOpsPendingVal =
108 psSyncInfo->psSyncData->ui32WriteOpsPending;
110 pvr_trcmd_set_syn(&ktrace->tatq_syn, psSyncInfo);
112 pvr_trcmd_clear_syn(&ktrace->tatq_syn);
115 if (psCCBKick->h3DSyncInfo != NULL) {
116 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
117 psCCBKick->h3DSyncInfo;
119 psTACmd->s3DTQSyncReadOpsCompleteDevVAddr =
120 psSyncInfo->sReadOpsCompleteDevVAddr;
121 psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr =
122 psSyncInfo->sWriteOpsCompleteDevVAddr;
124 psTACmd->ui323DTQSyncReadOpsPendingVal =
125 psSyncInfo->psSyncData->ui32ReadOpsPending++;
126 psTACmd->ui323DTQSyncWriteOpsPendingVal =
127 psSyncInfo->psSyncData->ui32WriteOpsPending;
129 pvr_trcmd_set_syn(&ktrace->_3dtq_syn, psSyncInfo);
131 pvr_trcmd_clear_syn(&ktrace->_3dtq_syn);
134 psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
135 if (psCCBKick->ui32NumTAStatusVals != 0) {
136 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
137 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
138 psCCBKick->ahTAStatusSyncInfo[i];
140 psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr =
141 psSyncInfo->sReadOpsCompleteDevVAddr;
143 psTACmd->sCtlTAStatusInfo[i].ui32StatusValue =
144 psSyncInfo->psSyncData->ui32ReadOpsPending;
148 psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
149 if (psCCBKick->ui32Num3DStatusVals != 0) {
150 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
152 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
153 ah3DStatusSyncInfo[i];
155 psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr =
156 psSyncInfo->sReadOpsCompleteDevVAddr;
158 psTACmd->sCtl3DStatusInfo[i].ui32StatusValue =
159 psSyncInfo->psSyncData->ui32ReadOpsPending;
163 psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
164 for (i = 0; i < SGX_MAX_SRC_SYNCS; i++) {
165 if (i >= psCCBKick->ui32NumSrcSyncs) {
166 pvr_trcmd_clear_syn(&ktrace->src_syn[i]);
171 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
172 ahSrcKernelSyncInfo[i];
174 psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr =
175 psSyncInfo->sWriteOpsCompleteDevVAddr;
176 psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr =
177 psSyncInfo->sReadOpsCompleteDevVAddr;
179 psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal =
180 psSyncInfo->psSyncData->ui32ReadOpsPending++;
182 psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal =
183 psSyncInfo->psSyncData->ui32WriteOpsPending;
185 pvr_trcmd_set_syn(&ktrace->src_syn[i], psSyncInfo);
188 if (psCCBKick->bFirstKickOrResume &&
189 psCCBKick->ui32NumDstSyncObjects > 0) {
190 struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
191 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
192 hKernelHWSyncListMemInfo;
193 struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
194 psHWDstSyncListMemInfo->pvLinAddrKM;
195 u32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
197 PVR_ASSERT(((struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
198 hKernelHWSyncListMemInfo)->ui32AllocSize >=
199 (sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST) +
200 (sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT) *
203 psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
205 if (PDumpIsCaptureFrameKM()) {
206 PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
208 psHWDstSyncListMemInfo, 0,
209 sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST),
210 0, MAKEUNIQUETAG(psHWDstSyncListMemInfo));
213 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
217 psHWDeviceSyncList->asSyncData[i].
218 sWriteOpsCompleteDevVAddr =
219 psSyncInfo->sWriteOpsCompleteDevVAddr;
221 psHWDeviceSyncList->asSyncData[i].
222 sReadOpsCompleteDevVAddr =
223 psSyncInfo->sReadOpsCompleteDevVAddr;
225 psHWDeviceSyncList->asSyncData[i].
226 ui32ReadOpsPendingVal =
227 psSyncInfo->psSyncData->ui32ReadOpsPending;
229 psHWDeviceSyncList->asSyncData[i].
230 ui32WriteOpsPendingVal =
231 psSyncInfo->psSyncData->
232 ui32WriteOpsPending++;
234 pvr_trcmd_set_syn(&ktrace->dst_syn, psSyncInfo);
237 if (PDumpIsCaptureFrameKM()) {
238 u32 ui32ModifiedValue;
239 u32 ui32SyncOffset = offsetof(
240 struct SGXMKIF_HWDEVICE_SYNC_LIST,
243 struct PVRSRV_DEVICE_SYNC_OBJECT));
244 u32 ui32WOpsOffset = ui32SyncOffset +
246 struct PVRSRV_DEVICE_SYNC_OBJECT,
247 ui32WriteOpsPendingVal);
248 u32 ui32ROpsOffset = ui32SyncOffset +
250 struct PVRSRV_DEVICE_SYNC_OBJECT,
251 ui32ReadOpsPendingVal);
253 PDUMPCOMMENT("HWDeviceSyncObject for RT: "
256 PDUMPMEM(NULL, psHWDstSyncListMemInfo,
257 ui32SyncOffset, sizeof(
258 struct PVRSRV_DEVICE_SYNC_OBJECT),
260 psHWDstSyncListMemInfo));
262 if ((psSyncInfo->psSyncData->
263 ui32LastOpDumpVal == 0) &&
264 (psSyncInfo->psSyncData->
265 ui32LastReadOpDumpVal == 0)) {
267 PDUMPCOMMENT("Init RT ROpsComplete\r\n",
269 PDUMPMEM(&psSyncInfo->psSyncData->
270 ui32LastReadOpDumpVal,
271 psSyncInfo->psSyncDataMemInfoKM,
274 ui32ReadOpsComplete),
275 sizeof(psSyncInfo->psSyncData->
276 ui32ReadOpsComplete),
278 MAKEUNIQUETAG(psSyncInfo->
279 psSyncDataMemInfoKM));
281 PDUMPCOMMENT("Init RT WOpsComplete\r\n");
282 PDUMPMEM(&psSyncInfo->psSyncData->
284 psSyncInfo->psSyncDataMemInfoKM,
285 offsetof(struct PVRSRV_SYNC_DATA,
286 ui32WriteOpsComplete),
287 sizeof(psSyncInfo->psSyncData->
288 ui32WriteOpsComplete),
289 0, MAKEUNIQUETAG(psSyncInfo->
290 psSyncDataMemInfoKM));
293 psSyncInfo->psSyncData->ui32LastOpDumpVal++;
295 ui32ModifiedValue = psSyncInfo->psSyncData->
296 ui32LastOpDumpVal - 1;
298 PDUMPCOMMENT("Modify RT %d WOpPendingVal "
299 "in HWDevSyncList\r\n", i);
301 PDUMPMEM(&ui32ModifiedValue,
302 psHWDstSyncListMemInfo, ui32WOpsOffset,
304 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
306 PDUMPCOMMENT("Modify RT %d ROpsPendingVal "
307 "in HWDevSyncList\r\n", i);
309 PDUMPMEM(&psSyncInfo->psSyncData->
310 ui32LastReadOpDumpVal,
311 psHWDstSyncListMemInfo,
312 ui32ROpsOffset, sizeof(u32), 0,
313 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
317 psHWDeviceSyncList->asSyncData[i].
318 sWriteOpsCompleteDevVAddr.uiAddr = 0;
319 psHWDeviceSyncList->asSyncData[i].
320 sReadOpsCompleteDevVAddr.uiAddr = 0;
322 psHWDeviceSyncList->asSyncData[i].
323 ui32ReadOpsPendingVal = 0;
324 psHWDeviceSyncList->asSyncData[i].
325 ui32WriteOpsPendingVal = 0;
327 pvr_trcmd_clear_syn(&ktrace->dst_syn);
330 pvr_trcmd_clear_syn(&ktrace->dst_syn);
333 if (PDumpIsCaptureFrameKM()) {
334 PDUMPCOMMENT("Shared part of TA command\r\n");
336 PDUMPMEM(psTACmd, psCCBMemInfo, psCCBKick->ui32CCBDumpWOff,
337 sizeof(struct SGXMKIF_CMDTA_SHARED), 0,
338 MAKEUNIQUETAG(psCCBMemInfo));
340 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
341 u32 ui32ModifiedValue;
343 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
344 ahSrcKernelSyncInfo[i];
346 if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
347 (psSyncInfo->psSyncData->ui32LastReadOpDumpVal ==
349 PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
350 PDUMPMEM(&psSyncInfo->psSyncData->
351 ui32LastReadOpDumpVal,
352 psSyncInfo->psSyncDataMemInfoKM,
353 offsetof(struct PVRSRV_SYNC_DATA,
354 ui32ReadOpsComplete),
355 sizeof(psSyncInfo->psSyncData->
356 ui32ReadOpsComplete), 0,
357 MAKEUNIQUETAG(psSyncInfo->
358 psSyncDataMemInfoKM));
359 PDUMPCOMMENT("Init RT WOpsComplete\r\n");
360 PDUMPMEM(&psSyncInfo->psSyncData->
362 psSyncInfo->psSyncDataMemInfoKM,
363 offsetof(struct PVRSRV_SYNC_DATA,
364 ui32WriteOpsComplete),
365 sizeof(psSyncInfo->psSyncData->
366 ui32WriteOpsComplete), 0,
367 MAKEUNIQUETAG(psSyncInfo->
368 psSyncDataMemInfoKM));
371 psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
374 psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
376 PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
378 PDUMPMEM(&ui32ModifiedValue,
380 psCCBKick->ui32CCBDumpWOff +
381 offsetof(struct SGXMKIF_CMDTA_SHARED,
384 sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
385 offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
386 ui32ReadOpsPendingVal), sizeof(u32),
387 0, MAKEUNIQUETAG(psCCBMemInfo));
389 PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
391 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
393 psCCBKick->ui32CCBDumpWOff +
394 offsetof(struct SGXMKIF_CMDTA_SHARED,
397 sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
398 offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
399 ui32WriteOpsPendingVal), sizeof(u32),
400 0, MAKEUNIQUETAG(psCCBMemInfo));
404 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
406 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
407 ahTAStatusSyncInfo[i];
408 PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
409 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
411 psCCBKick->ui32CCBDumpWOff +
412 offsetof(struct SGXMKIF_CMDTA_SHARED,
413 sCtlTAStatusInfo[i].ui32StatusValue),
414 sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
417 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
418 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
419 psCCBKick->ah3DStatusSyncInfo[i];
421 PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
423 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
425 psCCBKick->ui32CCBDumpWOff +
426 offsetof(struct SGXMKIF_CMDTA_SHARED,
427 sCtl3DStatusInfo[i].ui32StatusValue),
428 sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
433 pvr_trcmd_set_data(&ktrace->ctx, psCCBKick->sCommand.ui32Data[1]);
436 /* to aid in determining the next power down delay */
437 sgx_mark_new_command(psDeviceNode);
439 eError = SGXScheduleCCBCommandKM(hDevHandle, psCCBKick->eCommand,
440 &psCCBKick->sCommand, KERNEL_ID, 0);
441 if (eError == PVRSRV_ERROR_RETRY) {
442 if (psCCBKick->bFirstKickOrResume &&
443 psCCBKick->ui32NumDstSyncObjects > 0) {
444 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
445 psCCBKick->sDstSyncHandle;
447 psSyncInfo->psSyncData->ui32WriteOpsPending--;
449 if (PDumpIsCaptureFrameKM())
450 psSyncInfo->psSyncData->
456 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
458 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
459 ahSrcKernelSyncInfo[i];
460 psSyncInfo->psSyncData->ui32ReadOpsPending--;
464 } else if (PVRSRV_OK != eError) {
465 PVR_DPF(PVR_DBG_ERROR,
466 "SGXDoKickKM: SGXScheduleCCBCommandKM failed.");
470 #if defined(NO_HARDWARE)
472 if (psCCBKick->hTA3DSyncInfo) {
474 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
476 if (psCCBKick->bTADependency) {
477 psSyncInfo->psSyncData->ui32WriteOpsComplete =
478 psSyncInfo->psSyncData->ui32WriteOpsPending;
482 if (psCCBKick->hTASyncInfo != NULL) {
484 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
486 psSyncInfo->psSyncData->ui32ReadOpsComplete =
487 psSyncInfo->psSyncData->ui32ReadOpsPending;
490 if (psCCBKick->h3DSyncInfo != NULL) {
492 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
494 psSyncInfo->psSyncData->ui32ReadOpsComplete =
495 psSyncInfo->psSyncData->ui32ReadOpsPending;
498 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
500 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
501 ahTAStatusSyncInfo[i];
502 psSyncInfo->psSyncData->ui32ReadOpsComplete =
503 psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
506 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
508 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
509 ahSrcKernelSyncInfo[i];
511 psSyncInfo->psSyncData->ui32ReadOpsComplete =
512 psSyncInfo->psSyncData->ui32ReadOpsPending;
516 if (psCCBKick->bTerminateOrAbort) {
517 if (psCCBKick->ui32NumDstSyncObjects > 0) {
518 struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
519 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
520 hKernelHWSyncListMemInfo;
521 struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
522 psHWDstSyncListMemInfo->pvLinAddrKM;
525 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
528 psSyncInfo->psSyncData->ui32WriteOpsComplete =
529 psHWDeviceSyncList->asSyncData[0].
530 ui32WriteOpsPendingVal + 1;
533 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
535 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
536 ah3DStatusSyncInfo[i];
537 psSyncInfo->psSyncData->ui32ReadOpsComplete =
538 psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;