From 0a1ef819672e272bdc22f1ca28ce2caaf0ac07dc Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 14 Dec 2010 03:04:33 +0200 Subject: [PATCH] gpu: pvr: make the IOCTL i/f compatible for old ABI users The previous patch breaks the IOCTL i/f for current user space code. This change will notice such calls based on the IOCTL parameter size and fix up the param struct accordingly. This patch can be reverted once applications are converted to use the new ABI. Signed-off-by: Imre Deak --- pvr/bridged_pvr_bridge.c | 2 +- pvr/bridged_sgx_bridge.c | 39 +++++++++++++++++++++++++++++++++++++-- pvr/bridged_sgx_bridge.h | 6 +++--- pvr/perproc.h | 5 +++++ pvr/sgx_bridge_km.h | 3 ++- pvr/sgxinit.c | 10 +++++++--- 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/pvr/bridged_pvr_bridge.c b/pvr/bridged_pvr_bridge.c index 7409816..f95335f 100644 --- a/pvr/bridged_pvr_bridge.c +++ b/pvr/bridged_pvr_bridge.c @@ -3225,7 +3225,7 @@ static int bridged_ioctl(struct file *filp, u32 cmd, void *in, void *out, err = SGXGetInfoForSrvinitBW(cmd, in, out, per_proc); break; case PVRSRV_BRIDGE_SGX_DEVINITPART2: - err = SGXDevInitPart2BW(cmd, in, out, per_proc); + err = SGXDevInitPart2BW(cmd, in, out, in_size, per_proc); break; case PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC: diff --git a/pvr/bridged_sgx_bridge.c b/pvr/bridged_sgx_bridge.c index dabcaa4..37c2b89 100644 --- a/pvr/bridged_sgx_bridge.c +++ b/pvr/bridged_sgx_bridge.c @@ -519,7 +519,8 @@ int SGXReadDiffCountersBW(u32 ui32BridgeID, psSGXReadDiffCountersIN->ui32CountersReg, &psSGXReadDiffCountersOUT->ui32Time, &psSGXReadDiffCountersOUT->bActive, - &psSGXReadDiffCountersOUT->sDiffs); + &psSGXReadDiffCountersOUT->sDiffs, + psPerProc->edm_compat_abi); return 0; } @@ -571,9 +572,38 @@ int SGXReadHWPerfCBBW(u32 ui32BridgeID, return 0; } +static int fixup_compat_format(struct PVRSRV_PER_PROCESS_DATA *psPerProc, + struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *info, + size_t size) +{ + void **edm_buf; + + if (size == sizeof(*info)) { + psPerProc->edm_compat_abi = 0; + return 0; + } + + edm_buf = &info->sInitInfo.hKernelEDMStatusBufferMemInfo; + + if (size + sizeof(*edm_buf) != sizeof(*info)) + return -EFAULT; + + /* + * remainder of the compat struct size after the + * hKernelEDMStatusBufferMemInfo field + */ + size -= offsetof(struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2, + sInitInfo.hKernelEDMStatusBufferMemInfo); + memmove(edm_buf + 1, edm_buf, size); + *edm_buf = NULL; + psPerProc->edm_compat_abi = 1; + + return 0; +} + int SGXDevInitPart2BW(u32 ui32BridgeID, struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN, - struct PVRSRV_BRIDGE_RETURN *psRetOUT, + struct PVRSRV_BRIDGE_RETURN *psRetOUT, size_t in_size, struct PVRSRV_PER_PROCESS_DATA *psPerProc) { void *hDevCookieInt; @@ -592,6 +622,11 @@ int SGXDevInitPart2BW(u32 ui32BridgeID, return 0; } + if (fixup_compat_format(psPerProc, psSGXDevInitPart2IN, in_size) < 0) { + psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS; + return 0; + } + psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt, psSGXDevInitPart2IN->hDevCookie, diff --git a/pvr/bridged_sgx_bridge.h b/pvr/bridged_sgx_bridge.h index c2a8c47..4806cb4 100644 --- a/pvr/bridged_sgx_bridge.h +++ b/pvr/bridged_sgx_bridge.h @@ -76,9 +76,9 @@ int SGXReadHWPerfCBBW(u32 ui32BridgeID, struct PVRSRV_PER_PROCESS_DATA *psPerProc); int SGXDevInitPart2BW(u32 ui32BridgeID, - struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN, - struct PVRSRV_BRIDGE_RETURN *psRetOUT, - struct PVRSRV_PER_PROCESS_DATA *psPerProc); + struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN, + struct PVRSRV_BRIDGE_RETURN *psRetOUT, size_t in_size, + struct PVRSRV_PER_PROCESS_DATA *psPerProc); int SGXRegisterHWRenderContextBW(u32 ui32BridgeID, struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT diff --git a/pvr/perproc.h b/pvr/perproc.h index a89b0e4..11b132a 100644 --- a/pvr/perproc.h +++ b/pvr/perproc.h @@ -45,6 +45,11 @@ struct PVRSRV_PER_PROCESS_DATA { IMG_BOOL bInitProcess; void *hOsPrivateData; + + int edm_compat_abi; /* + * set if old ABI is used to pass the + * EDM trace buffer address. + */ }; struct PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(u32 ui32PID); diff --git a/pvr/sgx_bridge_km.h b/pvr/sgx_bridge_km.h index 3389b0c..2990521 100644 --- a/pvr/sgx_bridge_km.h +++ b/pvr/sgx_bridge_km.h @@ -61,7 +61,8 @@ enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg, u32 *pui32Old, IMG_BOOL bNew, u32 ui32New, u32 ui32NewReset, u32 ui32CountersReg, u32 *pui32Time, IMG_BOOL *pbActive, - struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs); + struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs, + int edm_compat_abi); enum PVRSRV_ERROR SGXReadHWPerfCBKM(void *hDevHandle, u32 ui32ArraySize, struct PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData, u32 *pui32DataCount, u32 *pui32ClockSpeed, diff --git a/pvr/sgxinit.c b/pvr/sgxinit.c index ace786c..4fa29c6 100644 --- a/pvr/sgxinit.c +++ b/pvr/sgxinit.c @@ -1515,7 +1515,8 @@ enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg, u32 *pui32Old, IMG_BOOL bNew, u32 ui32New, u32 ui32NewReset, u32 ui32CountersReg, u32 *pui32Time, IMG_BOOL *pbActive, - struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs) + struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs, + int edm_compat_abi) { struct SYS_DATA *psSysData; struct PVRSRV_POWER_DEV *psPowerDevice; @@ -1555,6 +1556,7 @@ enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg, sNew.ui32Time[0] = OSClockus(); *pui32Time = sNew.ui32Time[0]; if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) { + u32 __iomem *time_wraps; *pui32Old = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg); @@ -1581,8 +1583,10 @@ enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg, sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter; sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter; - sNew.ui32Time[1] = readl( - &psDevInfo->psSGXHostCtl->ui32TimeWraps); + time_wraps = &psDevInfo->psSGXHostCtl->ui32TimeWraps; + if (edm_compat_abi) + time_wraps -= 1; + sNew.ui32Time[1] = readl(time_wraps); for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) { psDiffs->aui32Counters[i] = -- 2.39.5