RK3368 GPU: Rogue N Init.
[firefly-linux-kernel-4.4.55.git] / drivers / staging / imgtec / rogue / tlserver.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          KM server Transport Layer implementation
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Main bridge APIs for Transport Layer client functions
6 @License        Dual MIT/GPLv2
7
8 The contents of this file are subject to the MIT license as set out below.
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
23
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
31
32 This License is also included in this distribution in the file called
33 "MIT-COPYING".
34
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */ /**************************************************************************/
43 #include <stddef.h>
44
45 #include "img_defs.h"
46
47 //#define PVR_DPF_FUNCTION_TRACE_ON 1
48 #undef PVR_DPF_FUNCTION_TRACE_ON
49 #include "pvr_debug.h"
50
51 #include "connection_server.h"
52 #include "allocmem.h"
53 #include "devicemem.h"
54
55 #include "tlintern.h"
56 #include "tlstream.h"
57 #include "tlserver.h"
58
59 #define NO_STREAM_WAIT_PERIOD 2000000ULL
60 #define NO_DATA_WAIT_PERIOD   1000000ULL
61 #define NO_ACQUIRE            0xffffffffU
62
63 #include "rgxhwperf.h"
64
65 /*
66  * Transport Layer Client API Kernel-Mode bridge implementation
67  */
68 PVRSRV_ERROR
69 TLServerOpenStreamKM(const IMG_CHAR*               pszName,
70                                      IMG_UINT32                    ui32Mode,
71                                      PTL_STREAM_DESC*      ppsSD,
72                                      PMR**                                 ppsTLPMR)
73 {
74         PVRSRV_ERROR    eError = PVRSRV_OK;
75         PVRSRV_ERROR    eErrorEO = PVRSRV_OK;
76         PTL_SNODE               psNode = 0;
77         TL_STREAM_DESC* psNewSD = 0;
78         IMG_HANDLE              hEvent;
79         IMG_BOOL                bIsWriteOnly = ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WO ?
80                                        IMG_TRUE : IMG_FALSE;
81         PTL_GLOBAL_DATA psGD = TLGGD();
82
83 #if defined(PVR_DPF_FUNCTION_TRACE_ON)
84     PVR_DPF((PVR_DBG_CALLTRACE, "--> %s:%d entered (%s, %x)", __func__, __LINE__, pszName, ui32Mode));
85 #endif
86
87         PVR_ASSERT(pszName);
88
89         /* Acquire TL_GLOBAL_DATA lock here, as if the following TLFindStreamNodeByName
90          * returns NON NULL PTL_SNODE, we try updating the global data client count and
91          * PTL_SNODE's psRDesc and we want to make sure the TL_SNODE is valid (eg. has
92          * not been deleted) while we are updating it
93          */
94         OSLockAcquire (psGD->hTLGDLock);
95
96         psNode = TLFindStreamNodeByName(pszName);
97         if ((psNode == NULL) && (ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WAIT))
98         {       /* Blocking code to wait for stream to be created if it does not exist */
99                 eError = OSEventObjectOpen(psGD->hTLEventObj, &hEvent);
100                 PVR_LOGG_IF_ERROR (eError, "OSEventObjectOpen", e0);
101
102                 do
103                 {
104                         if ((psNode = TLFindStreamNodeByName(pszName)) == NULL)
105                         {
106                                 PVR_DPF((PVR_DBG_MESSAGE, "Stream %s does not exist, waiting...", pszName));
107                                 
108                                 /* Release TL_GLOBAL_DATA lock before sleeping */
109                                 OSLockRelease (psGD->hTLGDLock);
110
111                                 /* Will exit OK or with timeout, both cases safe to ignore */
112                                 eErrorEO = OSEventObjectWaitTimeout(hEvent, NO_STREAM_WAIT_PERIOD);
113                                 
114                                 /* Acquire lock after waking up */
115                                 OSLockAcquire (psGD->hTLGDLock);
116                         }
117                 }
118                 while ((psNode == NULL) && (eErrorEO == PVRSRV_OK));
119
120                 eError = OSEventObjectClose(hEvent);
121                 PVR_LOGG_IF_ERROR (eError, "OSEventObjectClose", e0);
122         }
123
124         /* Make sure we have found a stream node after wait/search */
125         if (psNode == NULL)
126         {
127                 /* Did we exit the wait with timeout, inform caller */
128                 if (eErrorEO == PVRSRV_ERROR_TIMEOUT)
129                 {
130                         eError = eErrorEO;
131                 }
132                 else
133                 {
134                         eError = PVRSRV_ERROR_NOT_FOUND;
135                         PVR_DPF((PVR_DBG_ERROR, "Stream \"%s\" does not exist", pszName));
136                 }
137                 goto e0;
138         }
139
140         /* Allocate memory for the stream. The memory will be allocated with the
141          * first call. */
142         eError = TLAllocSharedMemIfNull(psNode->psStream);
143         if (eError != PVRSRV_OK)
144         {
145                 PVR_DPF((PVR_DBG_ERROR, "Failed to allocate memory for stream"
146                                 " \"%s\"", pszName));
147                 return eError;
148         }
149
150         if (bIsWriteOnly)
151         {
152
153                 /* If psWDesc == NULL it means that this is the first attempt
154                  * to open stream for write. If yes create the descriptor or increment
155                  * reference count otherwise. */
156                 if (psNode->psWDesc == NULL)
157                 {
158                         psNewSD = TLMakeStreamDesc(psNode, ui32Mode, NULL);
159                         psNode->psWDesc = psNewSD;
160                 }
161                 else
162                 {
163                         psNewSD = psNode->psWDesc;
164                         psNode->psWDesc->uiRefCount++;
165                 }
166
167                 if (!psNewSD)
168                 {
169                         PVR_DPF((PVR_DBG_ERROR, "Not possible to make a new stream"
170                                 " writer descriptor"));
171                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
172                         goto e1;
173                 }
174
175                 psNode->uiWRefCount++;
176         }
177         else
178         {
179                 // Only one reader per stream supported
180                 if (psNode->psRDesc != NULL)
181                 {
182                         PVR_DPF((PVR_DBG_ERROR, "Cannot open \"%s\" stream, stream already"
183                                 " opened", pszName));
184                         eError = PVRSRV_ERROR_ALREADY_OPEN;
185                         goto e0;
186                 }
187
188                 // Create an event handle for this client to wait on when no data in
189                 // stream buffer.
190                 eError = OSEventObjectOpen(psNode->hReadEventObj, &hEvent);
191                 if (eError != PVRSRV_OK)
192                 {
193                         PVR_DPF((PVR_DBG_ERROR, "Not possible to open node's event object"));
194                         eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;
195                         goto e0;
196                 }
197
198                 psNewSD = TLMakeStreamDesc(psNode, ui32Mode, hEvent);
199                 psNode->psRDesc = psNewSD;
200
201                 if (!psNewSD)
202                 {
203                         PVR_DPF((PVR_DBG_ERROR, "Not possible to make a new stream descriptor"));
204                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
205                         goto e1;
206                 }
207
208                 PVR_DPF((PVR_DBG_VERBOSE,
209                         "TLServerOpenStreamKM evList=%p, evObj=%p",
210                         psNode->hReadEventObj,
211                         psNode->psRDesc->hReadEvent));
212         }
213
214         // Copy the import handle back to the user mode API to enable access to
215         // the stream buffer from user-mode process.
216         eError = DevmemLocalGetImportHandle(TLStreamGetBufferPointer(psNode->psStream), (void**) ppsTLPMR);
217         PVR_LOGG_IF_ERROR(eError, "DevmemLocalGetImportHandle", e2);
218
219         psGD->uiClientCnt++;
220
221         /* Global data updated. Now release global lock */
222         OSLockRelease (psGD->hTLGDLock);
223
224         *ppsSD = psNewSD;
225
226         /* This callback is executed only on reader open. There are some actions
227          * executed on reader open that don't make much sense for writers e.g.
228          * injection on time synchronisation packet into the stream. */
229         if (!bIsWriteOnly && psNode->psStream->pfOnReaderOpenCallback != NULL)
230         {
231                 psNode->psStream->pfOnReaderOpenCallback(
232                         psNode->psStream->pvOnReaderOpenUserData);
233         }
234
235         if (bIsWriteOnly)
236         {
237                 /* Sending HWPerf event from TL is a temporary solution and this
238                  * will change once TL is expanded by event allowing to signal
239                  * stream opening. */
240                 RGX_HWPERF_HOST_CTRL(CLIENT_STREAM_OPEN,
241                                      OSGetCurrentClientProcessIDKM());
242         }
243
244         PVR_DPF((PVR_DBG_MESSAGE, "%s: Stream %s opened for %s", __func__, pszName,
245                 ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WO ? "write" : "read"));
246
247         PVR_DPF_RETURN_OK;
248
249 e2:
250         OSFreeMem(psNewSD);
251 e1:
252         OSEventObjectClose(hEvent);
253 e0:
254         OSLockRelease (psGD->hTLGDLock);
255         PVR_DPF_RETURN_RC (eError);
256 }
257
258 PVRSRV_ERROR
259 TLServerCloseStreamKM(PTL_STREAM_DESC psSD)
260 {
261         PVRSRV_ERROR    eError = PVRSRV_OK;
262         PTL_GLOBAL_DATA psGD = TLGGD();
263         PTL_SNODE               psNode = 0;
264         PTL_STREAM      psStream;
265         IMG_BOOL        bDestroyStream;
266         IMG_BOOL        bIsWriteOnly = psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO ?
267                                    IMG_TRUE : IMG_FALSE;
268
269         PVR_DPF_ENTERED;
270
271         PVR_ASSERT(psSD);
272
273         // Sanity check, quick exit if there are no streams
274         if (psGD->psHead == NULL)
275         {
276                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
277         }
278
279         // Check stream still valid
280         psNode = TLFindStreamNodeByDesc(psSD);
281         if ((psNode == NULL) || (psNode != psSD->psNode))
282         {
283                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
284         }
285
286         /* Since the descriptor is valid, the stream should not have been made NULL */
287         PVR_ASSERT (psNode->psStream);
288
289         /* Save the stream's reference in-case its destruction is required after this
290          * client is removed */
291         psStream = psNode->psStream;
292         
293         /* Acquire TL_GLOBAL_DATA lock as the following TLRemoveDescAndTryFreeStreamNode
294          * call will update the TL_SNODE's descriptor value */
295         OSLockAcquire (psGD->hTLGDLock);
296
297         /* Close event handle because event object list might be destroyed in
298          * TLUnrefDescAndTryFreeStreamNode(). */
299         if (!bIsWriteOnly)
300         {
301                 // Close and free the event handle resource used by this descriptor
302                 eError = OSEventObjectClose(psSD->hReadEvent);
303                 if (eError != PVRSRV_OK)
304                 {
305                         // Log error but continue as it seems best
306                         PVR_DPF((PVR_DBG_ERROR, "OSEventObjectClose() failed error %d",
307                                 eError));
308                         eError = PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
309                 }
310         }
311         else
312         {
313                 /* Sending HWPerf event from TL is a temporary solution and this
314                  * will change once TL is expanded by event allowing to signal
315                  * stream closing. */
316                 RGX_HWPERF_HOST_CTRL(CLIENT_STREAM_CLOSE,
317                                      OSGetCurrentClientProcessIDKM());
318         }
319
320         // Remove descriptor from stream object/list
321         bDestroyStream = TLUnrefDescAndTryFreeStreamNode (psNode, psSD);
322
323         // Assert the counter is sane after input data validated.
324         PVR_ASSERT(psGD->uiClientCnt > 0);
325         psGD->uiClientCnt--;
326
327         OSLockRelease (psGD->hTLGDLock);
328
329         /* Destroy the stream if its TL_SNODE was removed from TL_GLOBAL_DATA */
330         if (bDestroyStream)
331         {
332                 TLStreamDestroy (psStream);
333                 psStream = NULL;
334         }
335
336         PVR_DPF((PVR_DBG_VERBOSE, "%s: Stream closed", __func__));
337
338         /* Free the descriptor if ref count reaches 0. */
339         if (psSD->uiRefCount == 0)
340         {
341                 // Free the stream descriptor object
342                 OSFreeMem(psSD);
343         }
344
345         PVR_DPF_RETURN_RC(eError);
346 }
347
348 PVRSRV_ERROR
349 TLServerReserveStreamKM(PTL_STREAM_DESC psSD,
350                         IMG_UINT32* ui32BufferOffset,
351                         IMG_UINT32 ui32Size,
352                         IMG_UINT32 ui32SizeMin,
353                         IMG_UINT32* pui32Available)
354 {
355         TL_GLOBAL_DATA* psGD = TLGGD();
356         PTL_SNODE psNode = 0;
357         IMG_UINT8* pui8Buffer = NULL;
358         PVRSRV_ERROR eError;
359
360         PVR_DPF_ENTERED;
361
362         PVR_ASSERT(psSD);
363
364         if (!(psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO))
365         {
366                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
367         }
368
369         // Sanity check, quick exit if there are no streams
370         if (psGD->psHead == NULL)
371         {
372                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
373         }
374
375         /* Acquire the global lock. We have to be sure that no one modifies
376          * the list while we are looking for our stream. */
377         OSLockAcquire(psGD->hTLGDLock);
378         // Check stream still valid
379         psNode = TLFindAndGetStreamNodeByDesc(psSD);
380         OSLockRelease(psGD->hTLGDLock);
381
382         if ((psNode == NULL) || (psNode != psSD->psNode))
383         {
384                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
385         }
386
387
388         /* Since we have a valid stream descriptor, the stream should not have been
389          * made NULL by any producer context. */
390         PVR_ASSERT (psNode->psStream);
391
392         eError = TLStreamReserve2(psNode->psStream, &pui8Buffer, ui32Size,
393                                   ui32SizeMin, pui32Available);
394         if (eError != PVRSRV_OK)
395         {
396                 PVR_DPF((PVR_DBG_WARNING, "Failed to reserve the stream (%d).", eError));
397         }
398         else if (pui8Buffer == NULL)
399         {
400                 PVR_DPF((PVR_DBG_WARNING, "Not enough space in the stream."));
401                 eError = PVRSRV_ERROR_STREAM_RESERVE_TOO_BIG;
402         }
403         else
404         {
405                 *ui32BufferOffset = pui8Buffer - psNode->psStream->pbyBuffer;
406                 PVR_ASSERT(*ui32BufferOffset < psNode->psStream->ui32Size);
407         }
408
409         OSLockAcquire(psGD->hTLGDLock);
410         TLReturnStreamNode(psNode);
411         OSLockRelease(psGD->hTLGDLock);
412
413         PVR_DPF_RETURN_RC(eError);
414 }
415
416 PVRSRV_ERROR
417 TLServerCommitStreamKM(PTL_STREAM_DESC psSD,
418                        IMG_UINT32 ui32Size)
419 {
420         TL_GLOBAL_DATA* psGD = TLGGD();
421         PTL_SNODE psNode = 0;
422         PVRSRV_ERROR eError;
423
424         PVR_DPF_ENTERED;
425
426         PVR_ASSERT(psSD);
427
428         if (!(psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO))
429         {
430                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
431         }
432
433         // Sanity check, quick exit if there are no streams
434         if (psGD->psHead == NULL)
435         {
436                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
437         }
438
439         /* Acquire the global lock. We have to be sure that no one modifies
440          * the list while we are looking for our stream. */
441         OSLockAcquire(psGD->hTLGDLock);
442         // Check stream still valid
443         psNode = TLFindAndGetStreamNodeByDesc(psSD);
444         OSLockRelease(psGD->hTLGDLock);
445
446         if ((psNode == NULL) || (psNode != psSD->psNode))
447         {
448                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
449         }
450
451         /* Since we have a valid stream descriptor, the stream should not have been
452          * made NULL by any producer context. */
453         PVR_ASSERT (psNode->psStream);
454
455         eError = TLStreamCommit(psNode->psStream, ui32Size);
456         if (eError != PVRSRV_OK)
457         {
458                 PVR_DPF((PVR_DBG_ERROR, "Failed to commit data into stream."));
459         }
460
461         OSLockAcquire(psGD->hTLGDLock);
462         TLReturnStreamNode(psNode);
463         OSLockRelease(psGD->hTLGDLock);
464
465         PVR_DPF_RETURN_RC(eError);
466 }
467
468 PVRSRV_ERROR
469 TLServerDiscoverStreamsKM(const IMG_CHAR *pszNamePattern,
470                           IMG_UINT32 ui32Max,
471                           IMG_UINT32 *pui32Streams,
472                           IMG_UINT32 *pui32NumFound)
473 {
474         if (*pszNamePattern == '\0')
475                 return PVRSRV_ERROR_INVALID_PARAMS;
476
477         // Sanity check, quick exit if there are no streams
478         if (TLGGD()->psHead == NULL)
479         {
480                 *pui32NumFound = 0;
481                 return PVRSRV_OK;
482         }
483
484         OSLockAcquire(TLGGD()->hTLGDLock);
485         *pui32NumFound = TLDiscoverStreamNodes(pszNamePattern, pui32Streams,
486                                                ui32Max);
487         OSLockRelease(TLGGD()->hTLGDLock);
488
489         return PVRSRV_OK;
490 }
491
492 PVRSRV_ERROR
493 TLServerAcquireDataKM(PTL_STREAM_DESC psSD,
494                                           IMG_UINT32*     puiReadOffset,
495                                           IMG_UINT32*     puiReadLen)
496 {
497         PVRSRV_ERROR            eError = PVRSRV_OK;
498         TL_GLOBAL_DATA*         psGD = TLGGD();
499         IMG_UINT32                  uiTmpOffset = NO_ACQUIRE;
500         IMG_UINT32              uiTmpLen = 0;
501         PTL_SNODE                       psNode = 0;
502
503         PVR_DPF_ENTERED;
504
505         PVR_ASSERT(psSD);
506
507         // Sanity check, quick exit if there are no streams
508         if (psGD->psHead == NULL)
509         {
510                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
511         }
512
513         // Check stream still valid
514         psNode = TLFindStreamNodeByDesc(psSD);
515         if ((psNode == NULL) || (psNode != psSD->psNode))
516         {
517                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
518         }
519
520         /* If we are here, the stream will never be made NULL until this context itself
521          * calls TLRemoveDescAndTryFreeStreamNode(). This is because the producer will
522          * fail to make the stream NULL (by calling TLTryRemoveStreamAndFreeStreamNode)
523          * when a valid stream descriptor is present (i.e. a client is connected).
524          * Hence, no checks for stream being NON NULL are required after this. */
525         PVR_ASSERT (psNode->psStream);
526         
527         //PVR_DPF((PVR_DBG_VERBOSE, "TLServerAcquireDataKM evList=%p, evObj=%p", psSD->psNode->hReadEventObj, psSD->hReadEvent));
528
529         /* Check for data in the associated stream buffer, sleep/wait if none */
530         while (((uiTmpLen = TLStreamAcquireReadPos(psNode->psStream, &uiTmpOffset)) == 0) &&
531                (!(psSD->ui32Flags&PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING)) )
532         {
533                 PVR_DPF((PVR_DBG_VERBOSE, "TLAcquireDataKM sleeping..."));
534
535                 // Loop around if EndOfStream (nothing to read) and wait times out,
536                 // exit loop if not time out but data is ready for client
537                 while (TLStreamEOS(psNode->psStream))
538                 {
539                         eError = OSEventObjectWaitTimeout(psSD->hReadEvent, NO_DATA_WAIT_PERIOD);
540                         if (eError != PVRSRV_OK)
541                         {
542                                 /* Return timeout or other error condition to the caller who
543                                  * can choose to call again if desired. We don't block
544                                  * Indefinitely as we want the user mode application to have a
545                                  * chance to break out and end if it needs to, so we return the
546                                  * time out error code. */
547                                 PVR_DPF((PVR_DBG_VERBOSE, "TL Server timed out"));
548                                 PVR_DPF_RETURN_RC(eError);
549                         }
550                         else
551                         {
552                                 PVR_DPF((PVR_DBG_VERBOSE, "TL Server signalled"));
553                         }
554                 }
555         }
556
557         /* Data available now if we reach here in blocking more or we take the
558          * values as is in non-blocking mode which might be all zeros. */
559         *puiReadOffset = uiTmpOffset;
560         *puiReadLen = uiTmpLen;
561
562         PVR_DPF((PVR_DBG_VERBOSE, "TLAcquireDataKM return offset=%d, len=%d bytes", *puiReadOffset, *puiReadLen));
563
564         PVR_DPF_RETURN_OK;
565 }
566
567 PVRSRV_ERROR
568 TLServerReleaseDataKM(PTL_STREAM_DESC psSD,
569                                           IMG_UINT32      uiReadOffset,
570                                           IMG_UINT32      uiReadLen)
571 {
572         TL_GLOBAL_DATA*         psGD = TLGGD();
573         PTL_SNODE                       psNode = 0;
574
575         PVR_DPF_ENTERED;
576
577         /* Unreferenced in release builds */
578         PVR_UNREFERENCED_PARAMETER(uiReadOffset);
579
580         PVR_ASSERT(psSD);
581
582         // Sanity check, quick exit if there are no streams
583         if (psGD->psHead == NULL)
584         {
585                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
586         }
587
588         // Check stream still valid
589         psNode = TLFindStreamNodeByDesc(psSD);
590         if ((psNode == NULL) || (psNode != psSD->psNode))
591         {
592                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
593         }
594
595         /* Since we have a valid stream descriptor, the stream should not have been
596          * made NULL by any producer context. */
597         PVR_ASSERT (psNode->psStream);
598
599         PVR_DPF((PVR_DBG_VERBOSE, "TLReleaseDataKM uiReadOffset=%d, uiReadLen=%d", uiReadOffset, uiReadLen));
600
601         // Move read position on to free up space in stream buffer
602         TLStreamAdvanceReadPos(psNode->psStream, uiReadLen);
603
604         PVR_DPF_RETURN_OK;
605 }
606
607 PVRSRV_ERROR
608 TLServerWriteDataKM(PTL_STREAM_DESC psSD,
609                     IMG_UINT32 ui32Size,
610                     IMG_BYTE* pui8Data)
611 {
612         TL_GLOBAL_DATA* psGD = TLGGD();
613         PTL_SNODE psNode = 0;
614         PVRSRV_ERROR eError;
615
616         PVR_DPF_ENTERED;
617
618         PVR_ASSERT(psSD);
619
620         if (!(psSD->ui32Flags & PVRSRV_STREAM_FLAG_OPEN_WO))
621         {
622                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
623         }
624
625         // Sanity check, quick exit if there are no streams
626         if (psGD->psHead == NULL)
627         {
628                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
629         }
630
631         OSLockAcquire(psGD->hTLGDLock);
632         // Check stream still valid
633         psNode = TLFindAndGetStreamNodeByDesc(psSD);
634         OSLockRelease(psGD->hTLGDLock);
635
636         if ((psNode == NULL) || (psNode != psSD->psNode))
637         {
638                 PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
639         }
640
641         /* Since we have a valid stream descriptor, the stream should not have been
642          * made NULL by any producer context. */
643         PVR_ASSERT (psNode->psStream);
644
645         eError = TLStreamWrite(psNode->psStream, pui8Data, ui32Size);
646         if (eError != PVRSRV_OK)
647         {
648                 PVR_DPF((PVR_DBG_ERROR, "Failed to write data to the stream (%d).",
649                         eError));
650         }
651
652         OSLockAcquire(psGD->hTLGDLock);
653         TLReturnStreamNode(psNode);
654         OSLockRelease(psGD->hTLGDLock);
655
656         PVR_DPF_RETURN_RC(eError);
657 }
658
659 /*****************************************************************************
660  End of file (tlserver.c)
661 *****************************************************************************/
662