gpu: pvr: kick: check for duplicate src syncs
authorLuc Verhaegen <libv@codethink.co.uk>
Wed, 18 May 2011 08:01:40 +0000 (10:01 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 20 May 2012 18:43:05 +0000 (21:43 +0300)
When duplicate syncs are present, we deadlock; so check and throw an error
message. Was already fixed in userspace as part of #253237, this now shores
up the kernel too.

Fixes: NB#254225

Signed-off-by: Luc Verhaegen <libv@codethink.co.uk>
pvr/sgxkick.c

index 0a951e0..c3891a6 100644 (file)
@@ -160,31 +160,50 @@ enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle, struct SGX_CCB_KICK *psCCBKick,
                }
        }
 
                }
        }
 
-       psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
-       for (i = 0; i < SGX_MAX_SRC_SYNCS; i++) {
-               if (i >= psCCBKick->ui32NumSrcSyncs) {
-                       pvr_trcmd_clear_syn(&ktrace->src_syn[i]);
-                       continue;
+       /* check for duplicates while creating the new list */
+       psTACmd->ui32NumSrcSyncs = 0;
+       for (i = 0; ((i < SGX_MAX_SRC_SYNCS) &&
+                    (i < psCCBKick->ui32NumSrcSyncs)); i++) {
+               int j;
+
+               psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+                       psCCBKick->ahSrcKernelSyncInfo[i];
+
+               for (j = 0; j < i; j++) {
+                       struct PVRSRV_KERNEL_SYNC_INFO *tmp =
+                               psCCBKick->ahSrcKernelSyncInfo[j];
+                       if (tmp->psSyncData == psSyncInfo->psSyncData) {
+                               pr_err("%s: Duplicate SRC Sync detected: %p\n",
+                                      __func__, tmp->psSyncData);
+                               break;
+                       }
                }
                }
+               if (j != i)
+                       continue;
 
 
-               psSyncInfo =
-                   (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
-                   ahSrcKernelSyncInfo[i];
+               /* beat the 80 char limit. */
+               j = psTACmd->ui32NumSrcSyncs;
 
 
-               psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr =
+               psTACmd->asSrcSyncs[j].sWriteOpsCompleteDevVAddr =
                        psSyncInfo->sWriteOpsCompleteDevVAddr;
                        psSyncInfo->sWriteOpsCompleteDevVAddr;
-               psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr =
+               psTACmd->asSrcSyncs[j].sReadOpsCompleteDevVAddr =
                        psSyncInfo->sReadOpsCompleteDevVAddr;
 
                        psSyncInfo->sReadOpsCompleteDevVAddr;
 
-               psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal =
+               psTACmd->asSrcSyncs[j].ui32ReadOpsPendingVal =
                        psSyncInfo->psSyncData->ui32ReadOpsPending++;
 
                        psSyncInfo->psSyncData->ui32ReadOpsPending++;
 
-               psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal =
+               psTACmd->asSrcSyncs[j].ui32WriteOpsPendingVal =
                        psSyncInfo->psSyncData->ui32WriteOpsPending;
 
                        psSyncInfo->psSyncData->ui32WriteOpsPending;
 
-               pvr_trcmd_set_syn(&ktrace->src_syn[i], psSyncInfo);
+               pvr_trcmd_set_syn(&ktrace->src_syn[j], psSyncInfo);
+
+               psTACmd->ui32NumSrcSyncs++;
        }
 
        }
 
+       /* clear the remaining src syncs */
+       for (i = psTACmd->ui32NumSrcSyncs; i < SGX_MAX_SRC_SYNCS; i++)
+               pvr_trcmd_clear_syn(&ktrace->src_syn[i]);
+
        if (psCCBKick->bFirstKickOrResume &&
            psCCBKick->ui32NumDstSyncObjects > 0) {
                struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
        if (psCCBKick->bFirstKickOrResume &&
            psCCBKick->ui32NumDstSyncObjects > 0) {
                struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =