108c6d859e4ab83f67140550e819407a5ce97919
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue / services / server / env / linux / pvr_bridge_k.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          PVR Bridge Module (kernel side)
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Receives calls from the user portion of services and
6                 despatches them to functions in the kernel portion.
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 #include "img_defs.h"
45 #include "pvr_bridge.h"
46 #include "connection_server.h"
47 #include "syscommon.h"
48 #include "pvr_debug.h"
49 #include "pvr_debugfs.h"
50 #include "private_data.h"
51 #include "linkage.h"
52 #include "driverlock.h"
53
54 #if defined(SUPPORT_DRM)
55 #include <drm/drmP.h>
56 #include "pvr_drm.h"
57 #if defined(PVR_DRM_SECURE_AUTH_EXPORT)
58 #include "env_connection.h"
59 #endif
60 #endif /* defined(SUPPORT_DRM) */
61
62 /* RGX: */
63 #if defined(SUPPORT_RGX)
64 #include "rgx_bridge.h"
65 #endif
66
67 #include "srvcore.h"
68 #include "common_srvcore_bridge.h"
69 #include "cache_defines.h"
70
71 #if defined(MODULE_TEST)
72 /************************************************************************/
73 // additional includes for services testing
74 /************************************************************************/
75 #include "pvr_test_bridge.h"
76 #include "kern_test.h"
77 /************************************************************************/
78 // end of additional includes
79 /************************************************************************/
80 #endif
81
82
83 #if defined(SUPPORT_DRM)
84 #define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
85 #else
86 #define PRIVATE_DATA(pFile) ((pFile)->private_data)
87 #endif
88
89 #if defined(DEBUG_BRIDGE_KM)
90 static PVR_DEBUGFS_ENTRY_DATA *gpsPVRDebugFSBridgeStatsEntry = NULL;
91 static struct seq_operations gsBridgeStatsReadOps;
92 #endif
93
94 PVRSRV_ERROR RegisterPDUMPFunctions(void);
95 #if defined(SUPPORT_DISPLAY_CLASS)
96 PVRSRV_ERROR RegisterDCFunctions(void);
97 #endif
98 PVRSRV_ERROR RegisterMMFunctions(void);
99 PVRSRV_ERROR RegisterCMMFunctions(void);
100 PVRSRV_ERROR RegisterPDUMPMMFunctions(void);
101 PVRSRV_ERROR RegisterPDUMPCMMFunctions(void);
102 PVRSRV_ERROR RegisterSRVCOREFunctions(void);
103 PVRSRV_ERROR RegisterSYNCFunctions(void);
104 #if defined(SUPPORT_INSECURE_EXPORT)
105 PVRSRV_ERROR RegisterSYNCEXPORTFunctions(void);
106 #endif
107 #if defined(SUPPORT_SECURE_EXPORT)
108 PVRSRV_ERROR RegisterSYNCSEXPORTFunctions(void);
109 #endif
110 #if defined (SUPPORT_RGX)
111 PVRSRV_ERROR RegisterRGXINITFunctions(void);
112 PVRSRV_ERROR RegisterRGXTA3DFunctions(void);
113 PVRSRV_ERROR RegisterRGXTQFunctions(void);
114 PVRSRV_ERROR RegisterRGXCMPFunctions(void);
115 PVRSRV_ERROR RegisterBREAKPOINTFunctions(void);
116 PVRSRV_ERROR RegisterDEBUGMISCFunctions(void);
117 PVRSRV_ERROR RegisterRGXPDUMPFunctions(void);
118 PVRSRV_ERROR RegisterRGXHWPERFFunctions(void);
119 #if defined(RGX_FEATURE_RAY_TRACING)
120 PVRSRV_ERROR RegisterRGXRAYFunctions(void);
121 #endif /* RGX_FEATURE_RAY_TRACING */
122 PVRSRV_ERROR RegisterREGCONFIGFunctions(void);
123 PVRSRV_ERROR RegisterTIMERQUERYFunctions(void);
124 #endif /* SUPPORT_RGX */
125 #if (CACHEFLUSH_TYPE == CACHEFLUSH_GENERIC)
126 PVRSRV_ERROR RegisterCACHEGENERICFunctions(void);
127 #endif
128 #if defined(SUPPORT_SECURE_EXPORT)
129 PVRSRV_ERROR RegisterSMMFunctions(void);
130 #endif
131 #if defined(SUPPORT_PMMIF)
132 PVRSRV_ERROR RegisterPMMIFFunctions(void);
133 #endif
134 PVRSRV_ERROR RegisterPVRTLFunctions(void);
135 #if defined(PVR_RI_DEBUG)
136 PVRSRV_ERROR RegisterRIFunctions(void);
137 #endif
138 #if defined(SUPPORT_ION)
139 PVRSRV_ERROR RegisterDMABUFFunctions(void);
140 #endif
141
142 /* These and their friends above will go when full bridge gen comes in */
143 PVRSRV_ERROR
144 LinuxBridgeInit(void);
145 void
146 LinuxBridgeDeInit(void);
147
148 PVRSRV_ERROR
149 LinuxBridgeInit(void)
150 {
151         PVRSRV_ERROR eError;
152 #if defined(DEBUG_BRIDGE_KM)
153         IMG_INT iResult;
154
155         iResult = PVRDebugFSCreateEntry("bridge_stats",
156                                         NULL,
157                                         &gsBridgeStatsReadOps,
158                                         NULL,
159                                         &g_BridgeDispatchTable[0],
160                     &gpsPVRDebugFSBridgeStatsEntry);
161         if (iResult != 0)
162         {
163                 return PVRSRV_ERROR_OUT_OF_MEMORY;
164         }
165 #endif
166
167         eError = RegisterSRVCOREFunctions();
168         if (eError != PVRSRV_OK)
169         {
170                 return eError;
171         }
172
173         eError = RegisterSYNCFunctions();
174         if (eError != PVRSRV_OK)
175         {
176                 return eError;
177         }
178
179 #if defined(SUPPORT_INSECURE_EXPORT)
180         eError = RegisterSYNCEXPORTFunctions();
181         if (eError != PVRSRV_OK)
182         {
183                 return eError;
184         }
185 #endif
186 #if defined(SUPPORT_SECURE_EXPORT)
187         eError = RegisterSYNCSEXPORTFunctions();
188         if (eError != PVRSRV_OK)
189         {
190                 return eError;
191         }
192 #endif
193
194         eError = RegisterPDUMPFunctions();
195         if (eError != PVRSRV_OK)
196         {
197                 return eError;
198         }
199         eError = RegisterMMFunctions();
200         if (eError != PVRSRV_OK)
201         {
202                 return eError;
203         }
204         eError = RegisterCMMFunctions();
205         if (eError != PVRSRV_OK)
206         {
207                 return eError;
208         }
209         eError = RegisterPDUMPMMFunctions();
210         if (eError != PVRSRV_OK)
211         {
212                 return eError;
213         }
214         eError = RegisterPDUMPCMMFunctions();
215         if (eError != PVRSRV_OK)
216         {
217                 return eError;
218         }
219
220 #if defined(SUPPORT_PMMIF)
221         eError = RegisterPMMIFFunctions();
222         if (eError != PVRSRV_OK)
223         {
224                 return eError;
225         }
226 #endif
227
228 #if defined(SUPPORT_ION)
229         eError = RegisterDMABUFFunctions();
230         if (eError != PVRSRV_OK)
231         {
232                 return eError;
233         }
234 #endif
235
236 #if defined(SUPPORT_DISPLAY_CLASS)
237         eError = RegisterDCFunctions();
238         if (eError != PVRSRV_OK)
239         {
240                 return eError;
241         }
242 #endif
243
244 #if (CACHEFLUSH_TYPE == CACHEFLUSH_GENERIC)
245         eError = RegisterCACHEGENERICFunctions();
246         if (eError != PVRSRV_OK)
247         {
248                 return eError;
249         }
250 #endif
251
252 #if defined(SUPPORT_SECURE_EXPORT)
253         eError = RegisterSMMFunctions();
254         if (eError != PVRSRV_OK)
255         {
256                 return eError;
257         }
258 #endif
259
260         eError = RegisterPVRTLFunctions();
261         if (eError != PVRSRV_OK)
262         {
263                 return eError;
264         }
265
266         #if defined(PVR_RI_DEBUG)
267         eError = RegisterRIFunctions();
268         if (eError != PVRSRV_OK)
269         {
270                 return eError;
271         }
272         #endif
273
274         #if defined (SUPPORT_RGX)
275         eError = RegisterRGXTQFunctions();
276         if (eError != PVRSRV_OK)
277         {
278                 return eError;
279         }
280
281         eError = RegisterRGXCMPFunctions();
282         if (eError != PVRSRV_OK)
283         {
284                 return eError;
285         }
286
287         eError = RegisterRGXINITFunctions();
288         if (eError != PVRSRV_OK)
289         {
290                 return eError;
291         }
292
293         eError = RegisterRGXTA3DFunctions();
294         if (eError != PVRSRV_OK)
295         {
296                 return eError;
297         }
298
299         eError = RegisterBREAKPOINTFunctions();
300         if (eError != PVRSRV_OK)
301         {
302                 return eError;
303         }
304
305         eError = RegisterDEBUGMISCFunctions();
306         if (eError != PVRSRV_OK)
307         {
308                 return eError;
309         }
310         
311         eError = RegisterRGXPDUMPFunctions();
312         if (eError != PVRSRV_OK)
313         {
314                 return eError;
315         }
316
317         eError = RegisterRGXHWPERFFunctions();
318         if (eError != PVRSRV_OK)
319         {
320                 return eError;
321         }
322
323 #if defined(RGX_FEATURE_RAY_TRACING)
324         eError = RegisterRGXRAYFunctions();
325         if (eError != PVRSRV_OK)
326         {
327                 return eError;
328         }
329 #endif /* RGX_FEATURE_RAY_TRACING */
330
331         eError = RegisterREGCONFIGFunctions();
332         if (eError != PVRSRV_OK)
333         {
334                 return eError;
335         }
336
337         eError = RegisterTIMERQUERYFunctions();
338         if (eError != PVRSRV_OK)
339         {
340                 return eError;
341         }
342
343 #endif /* SUPPORT_RGX */
344
345         return eError;
346 }
347
348 void
349 LinuxBridgeDeInit(void)
350 {
351 #if defined(DEBUG_BRIDGE_KM)
352     PVRDebugFSRemoveEntry(gpsPVRDebugFSBridgeStatsEntry);
353     gpsPVRDebugFSBridgeStatsEntry = NULL;
354 #endif
355 }
356
357 #if defined(DEBUG_BRIDGE_KM)
358 static void *BridgeStatsSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
359 {
360         PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psDispatchTable = (PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *)psSeqFile->private;
361
362         OSAcquireBridgeLock();
363
364         if (psDispatchTable == NULL || (*puiPosition) > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
365         {
366                 return NULL;
367         }
368
369         if ((*puiPosition) == 0) 
370         {
371                 return SEQ_START_TOKEN;
372         }
373
374         return &(psDispatchTable[(*puiPosition) - 1]);
375 }
376
377 static void BridgeStatsSeqStop(struct seq_file *psSeqFile, void *pvData)
378 {
379         PVR_UNREFERENCED_PARAMETER(psSeqFile);
380         PVR_UNREFERENCED_PARAMETER(pvData);
381
382         OSReleaseBridgeLock();
383 }
384
385 static void *BridgeStatsSeqNext(struct seq_file *psSeqFile,
386                                void *pvData,
387                                loff_t *puiPosition)
388 {
389         PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psDispatchTable = (PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *)psSeqFile->private;
390
391         PVR_UNREFERENCED_PARAMETER(pvData);
392
393         (*puiPosition)++;
394
395         if ((*puiPosition) > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
396         {
397                 return NULL;
398         }
399
400         return &(psDispatchTable[(*puiPosition) - 1]);
401 }
402
403 static int BridgeStatsSeqShow(struct seq_file *psSeqFile, void *pvData)
404 {
405         if (pvData == SEQ_START_TOKEN)
406         {
407                 seq_printf(psSeqFile,
408                            "Total ioctl call count = %u\n"
409                            "Total number of bytes copied via copy_from_user = %u\n"
410                            "Total number of bytes copied via copy_to_user = %u\n"
411                            "Total number of bytes copied via copy_*_user = %u\n\n"
412                            "%-60s | %-48s | %10s | %20s | %10s\n",
413                            g_BridgeGlobalStats.ui32IOCTLCount,
414                            g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
415                            g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
416                            g_BridgeGlobalStats.ui32TotalCopyFromUserBytes + g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
417                            "Bridge Name",
418                            "Wrapper Function",
419                            "Call Count",
420                            "copy_from_user Bytes",
421                            "copy_to_user Bytes");
422         }
423         else if (pvData != NULL)
424         {
425                 PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *)pvData;
426
427                 seq_printf(psSeqFile,
428                            "%-60s   %-48s   %-10u   %-20u   %-10u\n",
429                            psEntry->pszIOCName,
430                            psEntry->pszFunctionName,
431                            psEntry->ui32CallCount,
432                            psEntry->ui32CopyFromUserTotalBytes,
433                            psEntry->ui32CopyToUserTotalBytes);
434         }
435
436         return 0;
437 }
438
439 static struct seq_operations gsBridgeStatsReadOps =
440 {
441         .start = BridgeStatsSeqStart,
442         .stop = BridgeStatsSeqStop,
443         .next = BridgeStatsSeqNext,
444         .show = BridgeStatsSeqShow,
445 };
446 #endif /* defined(DEBUG_BRIDGE_KM) */
447
448
449 #if defined(SUPPORT_DRM)
450 int
451 PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile)
452 #else
453 long
454 PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsigned long arg)
455 #endif
456 {
457 #if !defined(SUPPORT_DRM)
458         PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
459         PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
460 #endif
461         PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
462         CONNECTION_DATA *psConnection;
463         IMG_INT err = -EFAULT;
464
465         OSAcquireBridgeLock();
466
467         psConnection = LinuxConnectionFromFile(pFile);
468         if(psConnection == IMG_NULL)
469         {
470                 PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __FUNCTION__));
471                 OSReleaseBridgeLock();
472                 return err;
473         }
474
475 #if defined(SUPPORT_DRM)
476         PVR_UNREFERENCED_PARAMETER(dev);
477
478         psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
479         PVR_ASSERT(psBridgePackageKM != IMG_NULL);
480 #else
481         PVR_UNREFERENCED_PARAMETER(ioctlCmd);
482
483         psBridgePackageKM = &sBridgePackageKM;
484
485         if(!OSAccessOK(PVR_VERIFY_WRITE,
486                                    psBridgePackageUM,
487                                    sizeof(PVRSRV_BRIDGE_PACKAGE)))
488         {
489                 PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
490                                  __FUNCTION__));
491
492                 goto unlock_and_return;
493         }
494         
495         
496         if(OSCopyFromUser(IMG_NULL,
497                                           psBridgePackageKM,
498                                           psBridgePackageUM,
499                                           sizeof(PVRSRV_BRIDGE_PACKAGE))
500           != PVRSRV_OK)
501         {
502                 goto unlock_and_return;
503         }
504 #endif
505
506 #if defined(DEBUG_BRIDGE_CALLS)
507         {
508                 IMG_UINT32 mangledID;
509                 mangledID = psBridgePackageKM->ui32BridgeID;
510
511                 psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
512
513                 PVR_DPF((PVR_DBG_WARNING, "Bridge ID (x%8x) %8u (mangled: x%8x) ", psBridgePackageKM->ui32BridgeID, psBridgePackageKM->ui32BridgeID, mangledID));
514         }
515 #else
516                 psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
517 #endif
518
519         err = BridgedDispatchKM(psConnection, psBridgePackageKM);
520
521 #if !defined(SUPPORT_DRM)
522 unlock_and_return:
523 #endif
524         OSReleaseBridgeLock();
525         return err;
526 }
527
528
529 #if defined(CONFIG_COMPAT)
530 #if defined(SUPPORT_DRM)
531 int
532 #else
533 long
534 #endif
535 PVRSRV_BridgeCompatDispatchKM(struct file *pFile,
536                               unsigned int unref__ ioctlCmd,
537                               unsigned long arg)
538 {
539         struct bridge_package_from_32
540         {
541                 IMG_UINT32                              bridge_id;                      /*!< ioctl/drvesc index */
542                 IMG_UINT32                              size;                           /*!< size of structure */
543                 IMG_UINT32                              addr_param_in;          /*!< input data buffer */ 
544                 IMG_UINT32                              in_buffer_size;         /*!< size of input data buffer */
545                 IMG_UINT32                              addr_param_out;         /*!< output data buffer */
546                 IMG_UINT32                              out_buffer_size;        /*!< size of output data buffer */
547         };
548
549         IMG_INT err = -EFAULT;
550         PVRSRV_BRIDGE_PACKAGE params_for_64;
551         struct bridge_package_from_32 params;
552         struct bridge_package_from_32 * const params_addr = &params;
553 #if defined(SUPPORT_DRM)
554         struct drm_file *file_priv;
555 #endif
556         CONNECTION_DATA *psConnection;
557
558         // make sure there is no padding inserted by compiler
559         PVR_ASSERT(sizeof(struct bridge_package_from_32) == 6 * sizeof(IMG_UINT32));
560
561         OSAcquireBridgeLock();
562
563 #if !defined(SUPPORT_DRM)
564         psConnection = LinuxConnectionFromFile(pFile);
565 #else
566         file_priv = pFile->private_data;
567         psConnection = LinuxConnectionFromFile(file_priv);
568 #endif
569         if(psConnection == IMG_NULL)
570         {
571                 PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __FUNCTION__));
572                 goto unlock_and_return;
573         }
574
575         if(!OSAccessOK(PVR_VERIFY_READ, (void *) arg,
576                                    sizeof(struct bridge_package_from_32)))
577         {
578                 PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
579                                  __FUNCTION__));
580
581                 goto unlock_and_return;
582         }
583         
584         if(OSCopyFromUser(NULL, params_addr, (void*) arg,
585                                           sizeof(struct bridge_package_from_32))
586            != PVRSRV_OK)
587         {
588                 goto unlock_and_return;
589         }
590
591         PVR_ASSERT(params_addr->size == sizeof(struct bridge_package_from_32));
592
593         params_addr->bridge_id = PVRSRV_GET_BRIDGE_ID(params_addr->bridge_id);
594
595 #if defined(DEBUG_BRIDGE_KM)
596         PVR_DPF((PVR_DBG_MESSAGE, "ioctl %s -> func %s",
597                 g_BridgeDispatchTable[params_addr->bridge_id].pszIOCName,
598                 g_BridgeDispatchTable[params_addr->bridge_id].pszFunctionName));
599 #endif
600
601         params_for_64.ui32BridgeID = params_addr->bridge_id;
602         params_for_64.ui32Size = sizeof(params_for_64);
603         params_for_64.pvParamIn = (void*) ((size_t) params_addr->addr_param_in);
604         params_for_64.pvParamOut = (void*) ((size_t) params_addr->addr_param_out);
605         params_for_64.ui32InBufferSize = params_addr->in_buffer_size;
606         params_for_64.ui32OutBufferSize = params_addr->out_buffer_size;
607
608         err = BridgedDispatchKM(psConnection, &params_for_64);
609         
610 unlock_and_return:
611         OSReleaseBridgeLock();
612         return err;
613 }
614 #endif /* defined(CONFIG_COMPAT) */