RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / services / server / common / connection_server.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Server side connection management
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Handles connections coming from the client and the management
6                 connection based information
7 @License        Dual MIT/GPLv2
8
9 The contents of this file are subject to the MIT license as set out below.
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20
21 Alternatively, the contents of this file may be used under the terms of
22 the GNU General Public License Version 2 ("GPL") in which case the provisions
23 of GPL are applicable instead of those above.
24
25 If you wish to allow use of your version of this file only under the terms of
26 GPL, and not to allow others to use your version of this file under the terms
27 of the MIT license, indicate your decision by deleting the provisions above
28 and replace them with the notice and other provisions required by GPL as set
29 out in the file called "GPL-COPYING" included in this distribution. If you do
30 not delete the provisions above, a recipient may use your version of this file
31 under the terms of either the MIT license or GPL.
32
33 This License is also included in this distribution in the file called
34 "MIT-COPYING".
35
36 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
37 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
40 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
41 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 */ /**************************************************************************/
44
45 #include "handle.h"
46 #include "pvrsrv.h"
47 #include "connection_server.h"
48 #include "osconnection_server.h"
49 #include "allocmem.h"
50 #include "pvr_debug.h"
51 #include "sync_server.h"
52 #include "process_stats.h"
53 #include "pdump_km.h"
54 #include "lists.h"
55
56 /* PID associated with Connection currently being purged by Cleanup thread */
57 static IMG_PID gCurrentPurgeConnectionPid = 0;
58
59 static PVRSRV_ERROR ConnectionDataDestroy(CONNECTION_DATA *psConnection)
60 {
61         PVRSRV_ERROR eError;
62
63         if (psConnection == IMG_NULL)
64         {
65                 PVR_DPF((PVR_DBG_ERROR, "ConnectionDestroy: Missing connection!"));
66                 PVR_ASSERT(0);
67                 return PVRSRV_ERROR_INVALID_PARAMS;
68         }
69
70         /* Close the process statistics */
71 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
72         if (psConnection->hProcessStats != IMG_NULL)
73         {
74                 PVRSRVStatsDeregisterProcess(psConnection->hProcessStats);
75                 psConnection->hProcessStats = IMG_NULL;
76         }
77 #endif
78
79         /* Free handle base for this connection */
80         if (psConnection->psHandleBase != IMG_NULL)
81         {
82                 PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
83                 IMG_UINT64 ui64MaxBridgeTime;
84
85                 if(psPVRSRVData->bUnload)
86                 {
87                         /* driver is unloading so do not allow the bridge lock to be released */
88                         ui64MaxBridgeTime = 0;
89                 }
90                 else
91                 {
92                         ui64MaxBridgeTime = CONNECTION_DEFERRED_CLEANUP_TIMESLICE_NS;
93                 }
94
95                 eError = PVRSRVFreeHandleBase(psConnection->psHandleBase, ui64MaxBridgeTime);
96                 if (eError != PVRSRV_OK)
97                 {
98                         if (eError != PVRSRV_ERROR_RETRY)
99                         {
100                                 PVR_DPF((PVR_DBG_ERROR,
101                                          "ConnectionDataDestroy: Couldn't free handle base for connection (%d)",
102                                          eError));
103                         }
104
105                         return eError;
106                 }
107
108                 psConnection->psHandleBase = IMG_NULL;
109         }
110
111         if (psConnection->psSyncConnectionData != IMG_NULL)
112         {
113                 SyncUnregisterConnection(psConnection->psSyncConnectionData);
114                 psConnection->psSyncConnectionData = IMG_NULL;
115         }
116
117         if (psConnection->psPDumpConnectionData != IMG_NULL)
118         {
119                 PDumpUnregisterConnection(psConnection->psPDumpConnectionData);
120                 psConnection->psPDumpConnectionData = IMG_NULL;
121         }
122
123         /* Call environment specific connection data deinit function */
124         if (psConnection->hOsPrivateData != IMG_NULL)
125         {
126                 eError = OSConnectionPrivateDataDeInit(psConnection->hOsPrivateData);
127                 if (eError != PVRSRV_OK)
128                 {
129                         PVR_DPF((PVR_DBG_ERROR,
130                                  "PVRSRVConnectionDataDestroy: OSConnectionPrivateDataDeInit failed (%d)",
131                                  eError));
132
133                         return eError;
134                 }
135
136                 psConnection->hOsPrivateData = IMG_NULL;
137         }
138
139         OSFreeMem(psConnection);
140
141         return PVRSRV_OK;
142 }
143
144 PVRSRV_ERROR PVRSRVConnectionConnect(IMG_PVOID *ppvPrivData, IMG_PVOID pvOSData)
145 {
146         CONNECTION_DATA *psConnection;
147         PVRSRV_ERROR eError;
148
149         /* Allocate connection data area */
150         psConnection = OSAllocZMem(sizeof(*psConnection));
151         if (psConnection == IMG_NULL)
152         {
153                 PVR_DPF((PVR_DBG_ERROR,
154                          "PVRSRVConnectionConnect: Couldn't allocate connection data"));
155                 return PVRSRV_ERROR_OUT_OF_MEMORY;
156         }
157
158         /* Call environment specific connection data init function */
159         eError = OSConnectionPrivateDataInit(&psConnection->hOsPrivateData, pvOSData);
160         if (eError != PVRSRV_OK)
161         {
162                  PVR_DPF((PVR_DBG_ERROR,
163                           "PVRSRVConnectionConnect: OSConnectionPrivateDataInit failed (%d)",
164                           eError));
165                 goto failure;
166         }
167
168         psConnection->pid = OSGetCurrentProcessID();
169
170         /* Register this connection with the sync core */
171         eError = SyncRegisterConnection(&psConnection->psSyncConnectionData);
172         if (eError != PVRSRV_OK)
173         {
174                 PVR_DPF((PVR_DBG_ERROR,
175                          "PVRSRVConnectionConnect: Couldn't register the sync data"));
176                 goto failure;
177         }
178
179         /*
180          * Register this connection with the pdump core. Pass in the sync connection data
181          * as it will be needed later when we only get passed in the PDump connection data.
182          */
183         eError = PDumpRegisterConnection(psConnection->psSyncConnectionData,
184                                          &psConnection->psPDumpConnectionData);
185         if (eError != PVRSRV_OK)
186         {
187                 PVR_DPF((PVR_DBG_ERROR,
188                          "PVRSRVConnectionConnect: Couldn't register the PDump data"));
189                 goto failure;
190         }
191
192         /* Allocate handle base for this connection */
193         eError = PVRSRVAllocHandleBase(&psConnection->psHandleBase);
194         if (eError != PVRSRV_OK)
195         {
196                 PVR_DPF((PVR_DBG_ERROR,
197                          "PVRSRVConnectionConnect: Couldn't allocate handle base for connection (%d)",
198                          eError));
199                 goto failure;
200         }
201
202         /* Allocate process statistics */
203 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
204         eError = PVRSRVStatsRegisterProcess(&psConnection->hProcessStats);
205         if (eError != PVRSRV_OK)
206         {
207                 PVR_DPF((PVR_DBG_ERROR,
208                          "PVRSRVConnectionConnect: Couldn't register process statistics (%d)",
209                          eError));
210                 goto failure;
211         }
212 #endif
213
214         *ppvPrivData = psConnection;
215
216         return eError;
217
218 failure:
219         ConnectionDataDestroy(psConnection);
220
221         return eError;
222 }
223
224 static PVRSRV_ERROR _CleanupThreadPurgeConnectionData(void *pvConnectionData)
225 {
226         PVRSRV_ERROR eErrorConnection, eErrorKernel;
227         CONNECTION_DATA *psConnectionData = pvConnectionData;
228
229         OSAcquireBridgeLock();
230
231         gCurrentPurgeConnectionPid = psConnectionData->pid;
232
233         eErrorConnection = ConnectionDataDestroy(psConnectionData);
234         if (eErrorConnection != PVRSRV_OK)
235         {
236                 if (eErrorConnection == PVRSRV_ERROR_RETRY)
237                 {
238                         PVR_DPF((PVR_DBG_MESSAGE,
239                                  "_CleanupThreadPurgeConnectionData: Failed to purge connection data %p "
240                                  "(deferring destruction)",
241                                  psConnectionData));
242                 }
243         }
244         else
245         {
246                 PVR_DPF((PVR_DBG_MESSAGE,
247                          "_CleanupThreadPurgeConnectionData: Connection data %p deferred destruction finished",
248                          psConnectionData));
249         }
250
251         /* Check if possible resize the global handle base */
252         eErrorKernel = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
253         if (eErrorKernel != PVRSRV_OK)
254         {
255                 PVR_DPF((PVR_DBG_ERROR,
256                          "_CleanupThreadPurgeConnectionData: Purge of global handle pool failed (%d)",
257                          eErrorKernel));
258         }
259
260         gCurrentPurgeConnectionPid = 0;
261
262         OSReleaseBridgeLock();
263
264         return eErrorConnection;
265 }
266
267 void PVRSRVConnectionDisconnect(void *pvDataPtr)
268 {
269         CONNECTION_DATA *psConnectionData = pvDataPtr;
270
271         /* Notify the PDump core if the pdump control client is disconnecting */
272         if (psConnectionData->ui32ClientFlags & SRV_FLAGS_PDUMPCTRL)
273         {
274                 PDumpDisconnectionNotify();
275         }
276
277         /* Defer the release of the connection data */
278         psConnectionData->sCleanupThreadFn.pfnFree = _CleanupThreadPurgeConnectionData;
279         psConnectionData->sCleanupThreadFn.pvData = psConnectionData;
280         psConnectionData->sCleanupThreadFn.ui32RetryCount = CLEANUP_THREAD_RETRY_COUNT_DEFAULT;
281         PVRSRVCleanupThreadAddWork(&psConnectionData->sCleanupThreadFn);
282 }
283
284 PVRSRV_ERROR PVRSRVConnectionInit(void)
285 {
286         return PVRSRV_OK;
287 }
288
289 PVRSRV_ERROR PVRSRVConnectionDeInit(void)
290 {
291         return PVRSRV_OK;
292 }
293
294 IMG_PID PVRSRVGetPurgeConnectionPid(void)
295 {
296         return gCurrentPurgeConnectionPid;
297 }