gpu: pvr: V2: Find and fix all incorrect sync counter completion checks
[sgx.git] / pvr / sgxtransfer.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
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.
8  *
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.
13  *
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.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27
28 #include <stddef.h>
29
30 #include "sgxdefs.h"
31 #include "services_headers.h"
32 #include "buffer_manager.h"
33 #include "sgxinfo.h"
34 #include "sysconfig.h"
35 #include "pvr_pdump.h"
36 #include "mmu.h"
37 #include "pvr_bridge.h"
38 #include "sgx_bridge_km.h"
39 #include "sgxinfokm.h"
40 #include "osfunc.h"
41 #include "pvr_debug.h"
42 #include "sgxutils.h"
43 #include "perproc.h"
44 #include "pvr_trace_cmd.h"
45
46 enum PVRSRV_ERROR SGXSubmitTransferKM(void *hDevHandle,
47                                         struct PVRSRV_TRANSFER_SGX_KICK *psKick,
48                                         struct PVRSRV_PER_PROCESS_DATA *proc)
49 {
50         struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
51             (struct PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
52         struct SGXMKIF_COMMAND sCommand = { 0 };
53         struct SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
54         struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
55         struct pvr_trcmd_sgxtransfer *ttrace;
56         enum PVRSRV_ERROR eError;
57
58         if (!CCB_OFFSET_IS_VALID
59             (struct SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick,
60              ui32SharedCmdCCBOffset)) {
61                 PVR_DPF(PVR_DBG_ERROR,
62                          "SGXSubmitTransferKM: Invalid CCB offset");
63                 return PVRSRV_ERROR_INVALID_PARAMS;
64         }
65
66         psSharedTransferCmd =
67             CCB_DATA_FROM_OFFSET(struct SGXMKIF_TRANSFERCMD_SHARED,
68                                  psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
69
70         pvr_trcmd_lock();
71         ttrace = pvr_trcmd_alloc(PVR_TRCMD_TFER_KICK, proc->ui32PID, proc->name,
72                                  sizeof(*ttrace));
73
74         if (psKick->hTASyncInfo != NULL) {
75                 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
76                         psKick->hTASyncInfo;
77
78                 psSharedTransferCmd->ui32TASyncWriteOpsPendingVal =
79                     psSyncInfo->psSyncData->ui32WriteOpsPending++;
80                 psSharedTransferCmd->ui32TASyncReadOpsPendingVal =
81                     psSyncInfo->psSyncData->ui32ReadOpsPending;
82
83                 psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr =
84                     psSyncInfo->sWriteOpsCompleteDevVAddr;
85                 psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr =
86                     psSyncInfo->sReadOpsCompleteDevVAddr;
87
88                 pvr_trcmd_set_syn(&ttrace->ta_syn, psSyncInfo);
89         } else {
90                 psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
91                 psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
92
93                 pvr_trcmd_clear_syn(&ttrace->ta_syn);
94         }
95
96         if (psKick->h3DSyncInfo != NULL) {
97                 psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
98                                                         psKick->h3DSyncInfo;
99
100                 psSharedTransferCmd->ui323DSyncWriteOpsPendingVal =
101                     psSyncInfo->psSyncData->ui32WriteOpsPending++;
102                 psSharedTransferCmd->ui323DSyncReadOpsPendingVal =
103                     psSyncInfo->psSyncData->ui32ReadOpsPending;
104
105                 psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr =
106                     psSyncInfo->sWriteOpsCompleteDevVAddr;
107                 psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr =
108                     psSyncInfo->sReadOpsCompleteDevVAddr;
109
110                 pvr_trcmd_set_syn(&ttrace->_3d_syn, psSyncInfo);
111         } else {
112                 psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
113                 psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
114
115                 pvr_trcmd_clear_syn(&ttrace->_3d_syn);
116         }
117
118         if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) {
119                 if (psKick->ui32NumSrcSync > 0) {
120                         psSyncInfo =
121                             (struct PVRSRV_KERNEL_SYNC_INFO *)
122                                                 psKick->ahSrcSyncInfo[0];
123
124                         psSharedTransferCmd->ui32SrcWriteOpPendingVal =
125                             psSyncInfo->psSyncData->ui32WriteOpsPending;
126                         psSharedTransferCmd->ui32SrcReadOpPendingVal =
127                             psSyncInfo->psSyncData->ui32ReadOpsPending;
128
129                         psSharedTransferCmd->sSrcWriteOpsCompleteDevAddr =
130                             psSyncInfo->sWriteOpsCompleteDevVAddr;
131                         psSharedTransferCmd->sSrcReadOpsCompleteDevAddr =
132                             psSyncInfo->sReadOpsCompleteDevVAddr;
133                 }
134                 if (psKick->ui32NumDstSync > 0) {
135                         psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
136                                                 psKick->ahDstSyncInfo[0];
137                         psSharedTransferCmd->ui32DstWriteOpPendingVal =
138                             psSyncInfo->psSyncData->ui32WriteOpsPending;
139                         psSharedTransferCmd->ui32DstReadOpPendingVal =
140                             psSyncInfo->psSyncData->ui32ReadOpsPending;
141                         psSharedTransferCmd->sDstWriteOpsCompleteDevAddr =
142                             psSyncInfo->sWriteOpsCompleteDevVAddr;
143                         psSharedTransferCmd->sDstReadOpsCompleteDevAddr =
144                             psSyncInfo->sReadOpsCompleteDevVAddr;
145                 }
146
147                 if (psKick->ui32NumSrcSync > 0) {
148                         psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
149                                                 psKick->ahSrcSyncInfo[0];
150                         psSyncInfo->psSyncData->ui32ReadOpsPending++;
151
152                         pvr_trcmd_set_syn(&ttrace->src_syn, psSyncInfo);
153                 } else {
154                         pvr_trcmd_clear_syn(&ttrace->src_syn);
155                 }
156
157                 if (psKick->ui32NumDstSync > 0) {
158                         psSyncInfo =
159                             (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
160                                                             ahDstSyncInfo[0];
161                         psSyncInfo->psSyncData->ui32WriteOpsPending++;
162
163                         pvr_trcmd_set_syn(&ttrace->dst_syn, psSyncInfo);
164                 } else {
165                         pvr_trcmd_clear_syn(&ttrace->dst_syn);
166                 }
167         } else {
168                 pvr_trcmd_clear_syn(&ttrace->src_syn);
169                 pvr_trcmd_clear_syn(&ttrace->dst_syn);
170         }
171
172         if (psKick->ui32NumDstSync > 1 || psKick->ui32NumSrcSync > 1) {
173                 PVR_DPF(PVR_DBG_ERROR,
174                         "Transfer command doesn't support "
175                         "more than 1 sync object per src/dst\ndst: %d, src: %d",
176                          psKick->ui32NumDstSync, psKick->ui32NumSrcSync);
177         }
178 #if defined(PDUMP)
179         if (PDumpIsCaptureFrameKM() ||
180             ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) {
181                 PDUMPCOMMENT("Shared part of transfer command\r\n");
182                 PDUMPMEM(psSharedTransferCmd,
183                          psCCBMemInfo,
184                          psKick->ui32CCBDumpWOff,
185                          sizeof(struct SGXMKIF_TRANSFERCMD_SHARED),
186                          psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo));
187
188                 if ((psKick->ui32NumSrcSync > 0) &&
189                     ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
190                      0UL)) {
191                         psSyncInfo = psKick->ahSrcSyncInfo[0];
192
193                         PDUMPCOMMENT
194                             ("Hack src surface write op in transfer cmd\r\n");
195                         PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
196                                  psCCBMemInfo,
197                                  psKick->ui32CCBDumpWOff +
198                                  offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
199                                             ui32SrcWriteOpPendingVal),
200                                  sizeof(psSyncInfo->psSyncData->
201                                         ui32LastOpDumpVal),
202                                  psKick->ui32PDumpFlags,
203                                  MAKEUNIQUETAG(psCCBMemInfo));
204
205                         PDUMPCOMMENT
206                             ("Hack src surface read op in transfer cmd\r\n");
207                         PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
208                                  psCCBMemInfo,
209                                  psKick->ui32CCBDumpWOff +
210                                  offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
211                                           ui32SrcReadOpPendingVal),
212                                  sizeof(psSyncInfo->psSyncData->
213                                         ui32LastReadOpDumpVal),
214                                  psKick->ui32PDumpFlags,
215                                  MAKEUNIQUETAG(psCCBMemInfo));
216                 }
217                 if ((psKick->ui32NumDstSync > 0) &&
218                     ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
219                       0UL)) {
220                         psSyncInfo = psKick->ahDstSyncInfo[0];
221
222                         PDUMPCOMMENT
223                             ("Hack dest surface write op in transfer cmd\r\n");
224                         PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
225                                  psCCBMemInfo,
226                                  psKick->ui32CCBDumpWOff +
227                                  offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
228                                           ui32DstWriteOpPendingVal),
229                                  sizeof(psSyncInfo->psSyncData->
230                                         ui32LastOpDumpVal),
231                                  psKick->ui32PDumpFlags,
232                                  MAKEUNIQUETAG(psCCBMemInfo));
233
234                         PDUMPCOMMENT
235                             ("Hack dest surface read op in transfer cmd\r\n");
236                         PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
237                                  psCCBMemInfo,
238                                  psKick->ui32CCBDumpWOff +
239                                  offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
240                                           ui32DstReadOpPendingVal),
241                                  sizeof(psSyncInfo->psSyncData->
242                                         ui32LastReadOpDumpVal),
243                                  psKick->ui32PDumpFlags,
244                                  MAKEUNIQUETAG(psCCBMemInfo));
245                 }
246
247                 if ((psKick->ui32NumSrcSync > 0) &&
248                     ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
249                      0UL)) {
250                         psSyncInfo =
251                             (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
252                                                             ahSrcSyncInfo[0];
253                         psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
254
255                 }
256
257                 if ((psKick->ui32NumDstSync > 0) &&
258                     ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
259                      0UL)) {
260                         psSyncInfo =
261                             (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
262                                                             ahDstSyncInfo[0];
263                         psSyncInfo->psSyncData->ui32LastOpDumpVal++;
264                 }
265         }
266 #endif
267
268         sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_TRANSFERCMD;
269         sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
270
271         pvr_trcmd_set_data(&ttrace->ctx,
272                            psKick->sHWTransferContextDevVAddr.uiAddr);
273         pvr_trcmd_unlock();
274
275         /* To aid in determining the next power down delay */
276         sgx_mark_new_command(hDevHandle);
277
278         eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_COMMAND_EDM_KICK,
279                                     &sCommand, KERNEL_ID,
280                                     psKick->ui32PDumpFlags);
281
282 #if defined(NO_HARDWARE)
283         if (!(psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE)) {
284                 u32 i;
285
286                 for (i = 0; i < psKick->ui32NumSrcSync; i++) {
287                         psSyncInfo =
288                             (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
289                                                             ahSrcSyncInfo[i];
290                         psSyncInfo->psSyncData->ui32ReadOpsComplete =
291                             psSyncInfo->psSyncData->ui32ReadOpsPending;
292                 }
293
294                 for (i = 0; i < psKick->ui32NumDstSync; i++) {
295                         psSyncInfo =
296                             (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
297                                                             ahDstSyncInfo[i];
298                         psSyncInfo->psSyncData->ui32WriteOpsComplete =
299                             psSyncInfo->psSyncData->ui32WriteOpsPending;
300
301                 }
302
303                 if (psKick->hTASyncInfo != NULL) {
304                         psSyncInfo =
305                             (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
306                                                             hTASyncInfo;
307
308                         psSyncInfo->psSyncData->ui32WriteOpsComplete =
309                             psSyncInfo->psSyncData->ui32WriteOpsPending;
310                 }
311
312                 if (psKick->h3DSyncInfo != NULL) {
313                         psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
314                                                     h3DSyncInfo;
315
316                         psSyncInfo->psSyncData->ui32WriteOpsComplete =
317                             psSyncInfo->psSyncData->ui32WriteOpsPending;
318                 }
319         }
320 #endif
321
322         return eError;
323 }
324