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 enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle,
41 struct SGX_CCB_KICK *psCCBKick)
43 enum PVRSRV_ERROR eError;
44 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
45 struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
46 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hCCBKernelMemInfo;
47 struct SGXMKIF_CMDTA_SHARED *psTACmd;
49 struct PVRSRV_DEVICE_NODE *psDeviceNode;
50 struct PVRSRV_SGXDEV_INFO *psDevInfo;
52 psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
53 psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
55 if (psCCBKick->bKickRender)
56 ++psDevInfo->ui32KickTARenderCounter;
57 ++psDevInfo->ui32KickTACounter;
59 if (!CCB_OFFSET_IS_VALID
60 (struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick,
62 PVR_DPF(PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset");
63 return PVRSRV_ERROR_INVALID_PARAMS;
66 CCB_DATA_FROM_OFFSET(struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo,
67 psCCBKick, ui32CCBOffset);
69 if (psCCBKick->hTA3DSyncInfo) {
71 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
72 psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr =
73 psSyncInfo->sWriteOpsCompleteDevVAddr;
75 psTACmd->sTA3DDependency.ui32WriteOpsPendingVal =
76 psSyncInfo->psSyncData->ui32WriteOpsPending;
78 if (psCCBKick->bTADependency)
79 psSyncInfo->psSyncData->ui32WriteOpsPending++;
82 if (psCCBKick->hTASyncInfo != NULL) {
83 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
84 psCCBKick->hTASyncInfo;
86 psTACmd->sTATQSyncReadOpsCompleteDevVAddr =
87 psSyncInfo->sReadOpsCompleteDevVAddr;
88 psTACmd->sTATQSyncWriteOpsCompleteDevVAddr =
89 psSyncInfo->sWriteOpsCompleteDevVAddr;
91 psTACmd->ui32TATQSyncReadOpsPendingVal =
92 psSyncInfo->psSyncData->ui32ReadOpsPending++;
93 psTACmd->ui32TATQSyncWriteOpsPendingVal =
94 psSyncInfo->psSyncData->ui32WriteOpsPending;
97 if (psCCBKick->h3DSyncInfo != NULL) {
98 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
99 psCCBKick->h3DSyncInfo;
101 psTACmd->s3DTQSyncReadOpsCompleteDevVAddr =
102 psSyncInfo->sReadOpsCompleteDevVAddr;
103 psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr =
104 psSyncInfo->sWriteOpsCompleteDevVAddr;
106 psTACmd->ui323DTQSyncReadOpsPendingVal =
107 psSyncInfo->psSyncData->ui32ReadOpsPending++;
108 psTACmd->ui323DTQSyncWriteOpsPendingVal =
109 psSyncInfo->psSyncData->ui32WriteOpsPending;
112 psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
113 if (psCCBKick->ui32NumTAStatusVals != 0) {
114 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
115 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
116 psCCBKick->ahTAStatusSyncInfo[i];
118 psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr =
119 psSyncInfo->sReadOpsCompleteDevVAddr;
121 psTACmd->sCtlTAStatusInfo[i].ui32StatusValue =
122 psSyncInfo->psSyncData->ui32ReadOpsPending;
126 psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
127 if (psCCBKick->ui32Num3DStatusVals != 0) {
128 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
130 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
131 ah3DStatusSyncInfo[i];
133 psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr =
134 psSyncInfo->sReadOpsCompleteDevVAddr;
136 psTACmd->sCtl3DStatusInfo[i].ui32StatusValue =
137 psSyncInfo->psSyncData->ui32ReadOpsPending;
141 psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
142 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
144 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
145 ahSrcKernelSyncInfo[i];
147 psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr =
148 psSyncInfo->sWriteOpsCompleteDevVAddr;
149 psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr =
150 psSyncInfo->sReadOpsCompleteDevVAddr;
152 psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal =
153 psSyncInfo->psSyncData->ui32ReadOpsPending++;
155 psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal =
156 psSyncInfo->psSyncData->ui32WriteOpsPending;
160 if (psCCBKick->bFirstKickOrResume &&
161 psCCBKick->ui32NumDstSyncObjects > 0) {
162 struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
163 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
164 hKernelHWSyncListMemInfo;
165 struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
166 psHWDstSyncListMemInfo->pvLinAddrKM;
167 u32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
169 PVR_ASSERT(((struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
170 hKernelHWSyncListMemInfo)->ui32AllocSize >=
171 (sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST) +
172 (sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT) *
175 psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
177 if (PDumpIsCaptureFrameKM()) {
178 PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
180 psHWDstSyncListMemInfo, 0,
181 sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST),
182 0, MAKEUNIQUETAG(psHWDstSyncListMemInfo));
185 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
189 psHWDeviceSyncList->asSyncData[i].
190 sWriteOpsCompleteDevVAddr =
191 psSyncInfo->sWriteOpsCompleteDevVAddr;
193 psHWDeviceSyncList->asSyncData[i].
194 sReadOpsCompleteDevVAddr =
195 psSyncInfo->sReadOpsCompleteDevVAddr;
197 psHWDeviceSyncList->asSyncData[i].
198 ui32ReadOpsPendingVal =
199 psSyncInfo->psSyncData->ui32ReadOpsPending;
201 psHWDeviceSyncList->asSyncData[i].
202 ui32WriteOpsPendingVal =
203 psSyncInfo->psSyncData->
204 ui32WriteOpsPending++;
207 if (PDumpIsCaptureFrameKM()) {
208 u32 ui32ModifiedValue;
209 u32 ui32SyncOffset = offsetof(
210 struct SGXMKIF_HWDEVICE_SYNC_LIST,
213 struct PVRSRV_DEVICE_SYNC_OBJECT));
214 u32 ui32WOpsOffset = ui32SyncOffset +
216 struct PVRSRV_DEVICE_SYNC_OBJECT,
217 ui32WriteOpsPendingVal);
218 u32 ui32ROpsOffset = ui32SyncOffset +
220 struct PVRSRV_DEVICE_SYNC_OBJECT,
221 ui32ReadOpsPendingVal);
223 PDUMPCOMMENT("HWDeviceSyncObject for RT: "
226 PDUMPMEM(NULL, psHWDstSyncListMemInfo,
227 ui32SyncOffset, sizeof(
228 struct PVRSRV_DEVICE_SYNC_OBJECT),
230 psHWDstSyncListMemInfo));
232 if ((psSyncInfo->psSyncData->
233 ui32LastOpDumpVal == 0) &&
234 (psSyncInfo->psSyncData->
235 ui32LastReadOpDumpVal == 0)) {
237 PDUMPCOMMENT("Init RT ROpsComplete\r\n",
239 PDUMPMEM(&psSyncInfo->psSyncData->
240 ui32LastReadOpDumpVal,
241 psSyncInfo->psSyncDataMemInfoKM,
244 ui32ReadOpsComplete),
245 sizeof(psSyncInfo->psSyncData->
246 ui32ReadOpsComplete),
248 MAKEUNIQUETAG(psSyncInfo->
249 psSyncDataMemInfoKM));
251 PDUMPCOMMENT("Init RT WOpsComplete\r\n");
252 PDUMPMEM(&psSyncInfo->psSyncData->
254 psSyncInfo->psSyncDataMemInfoKM,
255 offsetof(struct PVRSRV_SYNC_DATA,
256 ui32WriteOpsComplete),
257 sizeof(psSyncInfo->psSyncData->
258 ui32WriteOpsComplete),
259 0, MAKEUNIQUETAG(psSyncInfo->
260 psSyncDataMemInfoKM));
263 psSyncInfo->psSyncData->ui32LastOpDumpVal++;
265 ui32ModifiedValue = psSyncInfo->psSyncData->
266 ui32LastOpDumpVal - 1;
268 PDUMPCOMMENT("Modify RT %d WOpPendingVal "
269 "in HWDevSyncList\r\n", i);
271 PDUMPMEM(&ui32ModifiedValue,
272 psHWDstSyncListMemInfo, ui32WOpsOffset,
274 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
276 PDUMPCOMMENT("Modify RT %d ROpsPendingVal "
277 "in HWDevSyncList\r\n", i);
279 PDUMPMEM(&psSyncInfo->psSyncData->
280 ui32LastReadOpDumpVal,
281 psHWDstSyncListMemInfo,
282 ui32ROpsOffset, sizeof(u32), 0,
283 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
287 psHWDeviceSyncList->asSyncData[i].
288 sWriteOpsCompleteDevVAddr.uiAddr = 0;
289 psHWDeviceSyncList->asSyncData[i].
290 sReadOpsCompleteDevVAddr.uiAddr = 0;
292 psHWDeviceSyncList->asSyncData[i].
293 ui32ReadOpsPendingVal = 0;
294 psHWDeviceSyncList->asSyncData[i].
295 ui32WriteOpsPendingVal = 0;
299 if (PDumpIsCaptureFrameKM()) {
300 PDUMPCOMMENT("Shared part of TA command\r\n");
302 PDUMPMEM(psTACmd, psCCBMemInfo, psCCBKick->ui32CCBDumpWOff,
303 sizeof(struct SGXMKIF_CMDTA_SHARED), 0,
304 MAKEUNIQUETAG(psCCBMemInfo));
306 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
307 u32 ui32ModifiedValue;
309 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
310 ahSrcKernelSyncInfo[i];
312 if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
313 (psSyncInfo->psSyncData->ui32LastReadOpDumpVal ==
315 PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
316 PDUMPMEM(&psSyncInfo->psSyncData->
317 ui32LastReadOpDumpVal,
318 psSyncInfo->psSyncDataMemInfoKM,
319 offsetof(struct PVRSRV_SYNC_DATA,
320 ui32ReadOpsComplete),
321 sizeof(psSyncInfo->psSyncData->
322 ui32ReadOpsComplete), 0,
323 MAKEUNIQUETAG(psSyncInfo->
324 psSyncDataMemInfoKM));
325 PDUMPCOMMENT("Init RT WOpsComplete\r\n");
326 PDUMPMEM(&psSyncInfo->psSyncData->
328 psSyncInfo->psSyncDataMemInfoKM,
329 offsetof(struct PVRSRV_SYNC_DATA,
330 ui32WriteOpsComplete),
331 sizeof(psSyncInfo->psSyncData->
332 ui32WriteOpsComplete), 0,
333 MAKEUNIQUETAG(psSyncInfo->
334 psSyncDataMemInfoKM));
337 psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
340 psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
342 PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
344 PDUMPMEM(&ui32ModifiedValue,
346 psCCBKick->ui32CCBDumpWOff +
347 offsetof(struct SGXMKIF_CMDTA_SHARED,
350 sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
351 offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
352 ui32ReadOpsPendingVal), sizeof(u32),
353 0, MAKEUNIQUETAG(psCCBMemInfo));
355 PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
357 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
359 psCCBKick->ui32CCBDumpWOff +
360 offsetof(struct SGXMKIF_CMDTA_SHARED,
363 sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
364 offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
365 ui32WriteOpsPendingVal), sizeof(u32),
366 0, MAKEUNIQUETAG(psCCBMemInfo));
370 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
372 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
373 ahTAStatusSyncInfo[i];
374 PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
375 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
377 psCCBKick->ui32CCBDumpWOff +
378 offsetof(struct SGXMKIF_CMDTA_SHARED,
379 sCtlTAStatusInfo[i].ui32StatusValue),
380 sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
383 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
384 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
385 psCCBKick->ah3DStatusSyncInfo[i];
387 PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
389 PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
391 psCCBKick->ui32CCBDumpWOff +
392 offsetof(struct SGXMKIF_CMDTA_SHARED,
393 sCtl3DStatusInfo[i].ui32StatusValue),
394 sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
399 /* to aid in determining the next power down delay */
400 sgx_mark_new_command(psDeviceNode);
402 eError = SGXScheduleCCBCommandKM(hDevHandle, psCCBKick->eCommand,
403 &psCCBKick->sCommand, KERNEL_ID, 0);
404 if (eError == PVRSRV_ERROR_RETRY) {
405 if (psCCBKick->bFirstKickOrResume &&
406 psCCBKick->ui32NumDstSyncObjects > 0) {
407 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
408 psCCBKick->sDstSyncHandle;
410 psSyncInfo->psSyncData->ui32WriteOpsPending--;
412 if (PDumpIsCaptureFrameKM())
413 psSyncInfo->psSyncData->
419 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
421 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
422 ahSrcKernelSyncInfo[i];
423 psSyncInfo->psSyncData->ui32ReadOpsPending--;
427 } else if (PVRSRV_OK != eError) {
428 PVR_DPF(PVR_DBG_ERROR,
429 "SGXDoKickKM: SGXScheduleCCBCommandKM failed.");
433 #if defined(NO_HARDWARE)
435 if (psCCBKick->hTA3DSyncInfo) {
437 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
439 if (psCCBKick->bTADependency) {
440 psSyncInfo->psSyncData->ui32WriteOpsComplete =
441 psSyncInfo->psSyncData->ui32WriteOpsPending;
445 if (psCCBKick->hTASyncInfo != NULL) {
447 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
449 psSyncInfo->psSyncData->ui32ReadOpsComplete =
450 psSyncInfo->psSyncData->ui32ReadOpsPending;
453 if (psCCBKick->h3DSyncInfo != NULL) {
455 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
457 psSyncInfo->psSyncData->ui32ReadOpsComplete =
458 psSyncInfo->psSyncData->ui32ReadOpsPending;
461 for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
463 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
464 ahTAStatusSyncInfo[i];
465 psSyncInfo->psSyncData->ui32ReadOpsComplete =
466 psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
469 for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
471 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
472 ahSrcKernelSyncInfo[i];
474 psSyncInfo->psSyncData->ui32ReadOpsComplete =
475 psSyncInfo->psSyncData->ui32ReadOpsPending;
479 if (psCCBKick->bTerminateOrAbort) {
480 if (psCCBKick->ui32NumDstSyncObjects > 0) {
481 struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
482 (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
483 hKernelHWSyncListMemInfo;
484 struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
485 psHWDstSyncListMemInfo->pvLinAddrKM;
488 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
491 psSyncInfo->psSyncData->ui32WriteOpsComplete =
492 psHWDeviceSyncList->asSyncData[0].
493 ui32WriteOpsPendingVal + 1;
496 for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
498 (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
499 ah3DStatusSyncInfo[i];
500 psSyncInfo->psSyncData->ui32ReadOpsComplete =
501 psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;