return 0;
}
+/* Convert the IOCTL parameter from "old" to "new" format. */
+static int kick_compat_conv(struct PVRSRV_BRIDGE_IN_DOKICK *kick,
+ size_t in_size)
+{
+ struct SGX_CCB_KICK *ccb;
+ size_t diff;
+
+ ccb = &kick->sCCBKick;
+
+ diff = sizeof(ccb->ah3DStatusSyncInfo[0]) *
+ (SGX_MAX_3D_STATUS_VALS - SGX_MAX_3D_STATUS_VALS_OLD);
+ if (sizeof(*kick) - in_size != diff)
+ return -EINVAL;
+
+ /* Trailing size at the end of struct to move. */
+ diff = sizeof(*kick) - offsetof(typeof(*kick),
+ sCCBKick.ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS]);
+ memmove(&kick->sCCBKick.ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS],
+ &kick->sCCBKick.ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS_OLD],
+ diff);
+
+ return 0;
+}
+
int SGXDoKickBW(u32 ui32BridgeID,
struct PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
struct PVRSRV_BRIDGE_RETURN *psRetOUT,
struct PVRSRV_PER_PROCESS_DATA *psPerProc)
{
void *hDevCookieInt;
+ int max_3dstat_vals;
u32 i;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+ max_3dstat_vals = SGX_MAX_3D_STATUS_VALS;
+ if (unlikely(in_size) != sizeof(*psDoKickIN)) {
+ max_3dstat_vals = SGX_MAX_3D_STATUS_VALS_OLD;
+ if (kick_compat_conv(psDoKickIN, in_size) != 0) {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return -EINVAL;
+ }
+
+ }
psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevCookieInt,
psDoKickIN->hDevCookie,
return 0;
}
- psRetOUT->eError = SGXDoKickKM(hDevCookieInt, &psDoKickIN->sCCBKick);
+ psRetOUT->eError = SGXDoKickKM(hDevCookieInt, &psDoKickIN->sCCBKick,
+ max_3dstat_vals);
return 0;
}
struct PVRSRV_TRANSFER_SGX_KICK *psKick);
-enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle,
- struct SGX_CCB_KICK *psCCBKick);
+enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle, struct SGX_CCB_KICK *psCCBKick,
+ int max_3dstat_val);
enum PVRSRV_ERROR SGXGetPhysPageAddrKM(void *hDevMemHeap,
struct IMG_DEV_VIRTADDR sDevVAddr,
#define SGX_MAX_HEAP_ID 10
#define SGX_MAX_TA_STATUS_VALS 32
-#define SGX_MAX_3D_STATUS_VALS 2
+#define SGX_MAX_3D_STATUS_VALS_OLD 2
+#define SGX_MAX_3D_STATUS_VALS 4
#define SGX_MAX_SRC_SYNCS 4
struct PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
struct CTL_STATUS sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+ /*
+ * Note that the actual size of sCtl3DStatusInfo changes based
+ * on the IOCTL ABI version used.
+ */
struct CTL_STATUS sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
struct PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependency;
#include "pvr_debug.h"
#include "sgxutils.h"
-enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle,
- struct SGX_CCB_KICK *psCCBKick)
+enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle, struct SGX_CCB_KICK *psCCBKick,
+ int max_3dstat_vals)
{
enum PVRSRV_ERROR eError;
struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
psCCBKick, ui32CCBOffset);
if (psCCBKick->hTA3DSyncInfo) {
+ struct PVRSRV_DEVICE_SYNC_OBJECT *ta3d_dep;
+
psSyncInfo =
(struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
- psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr =
+
+ ta3d_dep = &psTACmd->sTA3DDependency;
+ /*
+ * Ugly hack to account for the two possible sizes of
+ * struct SGXMKIF_CMDTA_SHARED which is based on the
+ * corresponding IOCTL ABI version used.
+ */
+ if (max_3dstat_vals != SGX_MAX_3D_STATUS_VALS)
+ ta3d_dep = (struct PVRSRV_DEVICE_SYNC_OBJECT *)
+ ((u8 *)ta3d_dep - sizeof(struct CTL_STATUS) *
+ (SGX_MAX_3D_STATUS_VALS - max_3dstat_vals));
+
+ ta3d_dep->sWriteOpsCompleteDevVAddr =
psSyncInfo->sWriteOpsCompleteDevVAddr;
- psTACmd->sTA3DDependency.ui32WriteOpsPendingVal =
+ ta3d_dep->ui32WriteOpsPendingVal =
psSyncInfo->psSyncData->ui32WriteOpsPending;
if (psCCBKick->bTADependency)