aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/pvr/pvr_bridge_k.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/pvr_bridge_k.c')
-rw-r--r--drivers/gpu/pvr/pvr_bridge_k.c570
1 files changed, 570 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/pvr_bridge_k.c b/drivers/gpu/pvr/pvr_bridge_k.c
new file mode 100644
index 00000000000..81a0201113b
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_bridge_k.c
@@ -0,0 +1,570 @@
1/**********************************************************************
2 *
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
20 *
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24 *
25 ******************************************************************************/
26
27#include "img_defs.h"
28#include "services.h"
29#include "pvr_bridge.h"
30#include "perproc.h"
31#include "mutex.h"
32#include "syscommon.h"
33#include "pvr_debug.h"
34#include "proc.h"
35#include "private_data.h"
36#include "linkage.h"
37#include "pvr_bridge_km.h"
38
39#if defined(SUPPORT_DRI_DRM)
40#include <drm/drmP.h>
41#include "pvr_drm.h"
42#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
43#include "env_perproc.h"
44#endif
45#endif
46
47#if defined(SUPPORT_VGX)
48#include "vgx_bridge.h"
49#endif
50
51#if defined(SUPPORT_SGX)
52#include "sgx_bridge.h"
53#endif
54
55#include "bridged_pvr_bridge.h"
56
57#ifdef MODULE_TEST
58#include "pvr_test_bridge.h"
59#include "kern_test.h"
60#endif
61
62
63#if defined(SUPPORT_DRI_DRM)
64#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
65#else
66#define PRIVATE_DATA(pFile) ((pFile)->private_data)
67#endif
68
69#if defined(DEBUG_BRIDGE_KM)
70
71static struct proc_dir_entry *g_ProcBridgeStats =0;
72static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
73static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
74static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
75static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
76
77#endif
78
79extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
80
81#if defined(SUPPORT_MEMINFO_IDS)
82static IMG_UINT64 ui64Stamp;
83#endif
84
85PVRSRV_ERROR
86LinuxBridgeInit(IMG_VOID)
87{
88#if defined(DEBUG_BRIDGE_KM)
89 {
90 g_ProcBridgeStats = CreateProcReadEntrySeq(
91 "bridge_stats",
92 NULL,
93 ProcSeqNextBridgeStats,
94 ProcSeqShowBridgeStats,
95 ProcSeqOff2ElementBridgeStats,
96 ProcSeqStartstopBridgeStats
97 );
98 if(!g_ProcBridgeStats)
99 {
100 return PVRSRV_ERROR_OUT_OF_MEMORY;
101 }
102 }
103#endif
104 return CommonBridgeInit();
105}
106
107IMG_VOID
108LinuxBridgeDeInit(IMG_VOID)
109{
110#if defined(DEBUG_BRIDGE_KM)
111 RemoveProcEntrySeq(g_ProcBridgeStats);
112#endif
113}
114
115#if defined(DEBUG_BRIDGE_KM)
116
117static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
118{
119 if(start)
120 {
121 LinuxLockMutex(&gPVRSRVLock);
122 }
123 else
124 {
125 LinuxUnLockMutex(&gPVRSRVLock);
126 }
127}
128
129
130static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
131{
132 if(!off)
133 {
134 return PVR_PROC_SEQ_START_TOKEN;
135 }
136
137 if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
138 {
139 return (void*)0;
140 }
141
142
143 return (void*)&g_BridgeDispatchTable[off-1];
144}
145
146static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
147{
148 return ProcSeqOff2ElementBridgeStats(sfile,off);
149}
150
151
152static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
153{
154 PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
155
156 if(el == PVR_PROC_SEQ_START_TOKEN)
157 {
158 seq_printf(sfile,
159 "Total ioctl call count = %u\n"
160 "Total number of bytes copied via copy_from_user = %u\n"
161 "Total number of bytes copied via copy_to_user = %u\n"
162 "Total number of bytes copied via copy_*_user = %u\n\n"
163 "%-45s | %-40s | %10s | %20s | %10s\n",
164 g_BridgeGlobalStats.ui32IOCTLCount,
165 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
166 g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
167 g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
168 "Bridge Name",
169 "Wrapper Function",
170 "Call Count",
171 "copy_from_user Bytes",
172 "copy_to_user Bytes"
173 );
174 return;
175 }
176
177 seq_printf(sfile,
178 "%-45s %-40s %-10u %-20u %-10u\n",
179 psEntry->pszIOCName,
180 psEntry->pszFunctionName,
181 psEntry->ui32CallCount,
182 psEntry->ui32CopyFromUserTotalBytes,
183 psEntry->ui32CopyToUserTotalBytes);
184}
185
186#endif
187
188
189#if defined(SUPPORT_DRI_DRM)
190IMG_INT
191PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
192#else
193IMG_INT32
194PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg)
195#endif
196{
197 IMG_UINT32 cmd;
198#if !defined(SUPPORT_DRI_DRM)
199 PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
200 PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
201#endif
202 PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
203 IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
204 PVRSRV_PER_PROCESS_DATA *psPerProc;
205 IMG_INT err = -EFAULT;
206
207 LinuxLockMutex(&gPVRSRVLock);
208
209#if defined(SUPPORT_DRI_DRM)
210 PVR_UNREFERENCED_PARAMETER(dev);
211
212 psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
213 PVR_ASSERT(psBridgePackageKM != IMG_NULL);
214#else
215 PVR_UNREFERENCED_PARAMETER(ioctlCmd);
216
217 psBridgePackageKM = &sBridgePackageKM;
218
219 if(!OSAccessOK(PVR_VERIFY_WRITE,
220 psBridgePackageUM,
221 sizeof(PVRSRV_BRIDGE_PACKAGE)))
222 {
223 PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
224 __FUNCTION__));
225
226 goto unlock_and_return;
227 }
228
229
230 if(OSCopyFromUser(IMG_NULL,
231 psBridgePackageKM,
232 psBridgePackageUM,
233 sizeof(PVRSRV_BRIDGE_PACKAGE))
234 != PVRSRV_OK)
235 {
236 goto unlock_and_return;
237 }
238#endif
239
240 cmd = psBridgePackageKM->ui32BridgeID;
241
242#if defined(MODULE_TEST)
243 switch (cmd)
244 {
245 case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
246 {
247 PVRSRV_ERROR eError = MemTest1();
248 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
249 {
250 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
251 pReturn->eError = eError;
252 }
253 }
254 err = 0;
255 goto unlock_and_return;
256 case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
257 {
258 PVRSRV_ERROR eError = MemTest2();
259 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
260 {
261 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
262 pReturn->eError = eError;
263 }
264 }
265 err = 0;
266 goto unlock_and_return;
267
268 case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
269 {
270 PVRSRV_ERROR eError = ResourceTest();
271 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
272 {
273 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
274 pReturn->eError = eError;
275 }
276 }
277 err = 0;
278 goto unlock_and_return;
279
280 case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
281 {
282 PVRSRV_ERROR eError = EventObjectTest();
283 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
284 {
285 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
286 pReturn->eError = eError;
287 }
288 }
289 err = 0;
290 goto unlock_and_return;
291
292 case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
293 {
294 PVRSRV_ERROR eError = MemMappingTest();
295 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
296 {
297 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
298 pReturn->eError = eError;
299 }
300 }
301 err = 0;
302 goto unlock_and_return;
303
304 case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
305 {
306 PVRSRV_ERROR eError = ProcessIDTest();
307 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
308 {
309 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
310 pReturn->eError = eError;
311 }
312 }
313 err = 0;
314 goto unlock_and_return;
315
316 case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
317 {
318 PVRSRV_ERROR eError = ClockusWaitusTest();
319 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
320 {
321 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
322 pReturn->eError = eError;
323 }
324 }
325 err = 0;
326 goto unlock_and_return;
327
328 case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
329 {
330 PVRSRV_ERROR eError = TimerTest();
331 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
332 {
333 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
334 pReturn->eError = eError;
335 }
336 }
337 err = 0;
338 goto unlock_and_return;
339
340 case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
341 {
342 PVRSRV_ERROR eError = PrivSrvTest();
343 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
344 {
345 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
346 pReturn->eError = eError;
347 }
348 }
349 err = 0;
350 goto unlock_and_return;
351 case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA:
352 {
353 IMG_UINT32 ui32PID;
354 PVRSRV_PER_PROCESS_DATA *psPerProc;
355 PVRSRV_ERROR eError;
356
357 ui32PID = OSGetCurrentProcessIDKM();
358
359 PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID);
360
361 psPerProc = PVRSRVPerProcessData(ui32PID);
362
363 eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc);
364
365 *(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError;
366 err = 0;
367 goto unlock_and_return;
368 }
369
370
371 case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
372 {
373 PVRSRV_ERROR eError = PowerMgmtTest();
374 if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
375 {
376 PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
377 pReturn->eError = eError;
378 }
379 }
380 err = 0;
381 goto unlock_and_return;
382
383 }
384#endif
385
386 if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
387 {
388 PVRSRV_ERROR eError;
389
390 eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
391 (IMG_PVOID *)&psPerProc,
392 psBridgePackageKM->hKernelServices,
393 PVRSRV_HANDLE_TYPE_PERPROC_DATA);
394 if(eError != PVRSRV_OK)
395 {
396 PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
397 __FUNCTION__, eError));
398 goto unlock_and_return;
399 }
400
401 if(psPerProc->ui32PID != ui32PID)
402 {
403 PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
404 "belonging to process %d", __FUNCTION__, ui32PID,
405 psPerProc->ui32PID));
406 goto unlock_and_return;
407 }
408 }
409 else
410 {
411
412 psPerProc = PVRSRVPerProcessData(ui32PID);
413 if(psPerProc == IMG_NULL)
414 {
415 PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
416 "Couldn't create per-process data area"));
417 goto unlock_and_return;
418 }
419 }
420
421 psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
422
423#if defined(PVR_SECURE_FD_EXPORT)
424 switch(cmd)
425 {
426 case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
427 {
428 PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
429
430 if(psPrivateData->hKernelMemInfo)
431 {
432 PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
433 "per file descriptor", __FUNCTION__));
434 err = -EINVAL;
435 goto unlock_and_return;
436 }
437 break;
438 }
439
440 case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
441 {
442 PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
443 (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn;
444 PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
445
446 if(!psPrivateData->hKernelMemInfo)
447 {
448 PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
449 "associated MemInfo handle", __FUNCTION__));
450 err = -EINVAL;
451 goto unlock_and_return;
452 }
453
454 psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo;
455 break;
456 }
457
458 default:
459 {
460 PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
461
462 if(psPrivateData->hKernelMemInfo)
463 {
464 PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
465 "to use privileged service", __FUNCTION__));
466 goto unlock_and_return;
467 }
468 break;
469 }
470 }
471#endif
472#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
473 switch(cmd)
474 {
475 case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
476 case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
477 {
478 PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
479 int authenticated = pFile->authenticated;
480 PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
481
482 if (authenticated)
483 {
484 break;
485 }
486
487
488 psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
489 if (psEnvPerProc == IMG_NULL)
490 {
491 PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
492 err = -EFAULT;
493 goto unlock_and_return;
494 }
495
496 list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
497 {
498 struct drm_file *psDRMFile = psPrivateData->psDRMFile;
499
500 if (pFile->master == psDRMFile->master)
501 {
502 authenticated |= psDRMFile->authenticated;
503 if (authenticated)
504 {
505 break;
506 }
507 }
508 }
509
510 if (!authenticated)
511 {
512 PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
513 err = -EPERM;
514 goto unlock_and_return;
515 }
516 break;
517 }
518 default:
519 break;
520 }
521#endif
522
523 err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
524 if(err != PVRSRV_OK)
525 goto unlock_and_return;
526
527 switch(cmd)
528 {
529#if defined(PVR_SECURE_FD_EXPORT)
530 case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
531 {
532 PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
533 (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
534 PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
535
536 psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo;
537#if defined(SUPPORT_MEMINFO_IDS)
538 psExportDeviceMemOUT->ui64Stamp = psPrivateData->ui64Stamp = ++ui64Stamp;
539#endif
540 break;
541 }
542#endif
543
544#if defined(SUPPORT_MEMINFO_IDS)
545 case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
546 {
547 PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
548 (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
549 PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
550 psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp = psPrivateData->ui64Stamp;
551 break;
552 }
553
554 case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
555 {
556 PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
557 (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
558 psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp;
559 break;
560 }
561#endif
562
563 default:
564 break;
565 }
566
567unlock_and_return:
568 LinuxUnLockMutex(&gPVRSRVLock);
569 return err;
570}