summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/include/nvreftrack.h
blob: ceecaab0a523d9cf0dafe6bdd6527b56beb7fcd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
/*
 * Copyright (c) 2009 NVIDIA Corporation.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the NVIDIA Corporation nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

/** 
 * \file nvreftrack.h
 * \brief NVIDIA kernel object reference tracking utility
 *
 * \mainpage
 *
 * NvRefTrack implements a database of client to object
 * references. The sole purpose of the utility is to provide a
 * mechanism for freeing up kernel mode driver objects on abnormal
 * client termination.
 *
 * This utility is intended to be used together with the NV IDL
 * automatic call dispatcher generation. 'refadd' and 'refdel'
 * modifiers for function parameters instruct the IDL generation to
 * instrument the dispatcher functions with appropriate calls to
 * NvRtStoreObjRef() and NvRtFreeObjRef().
 *
 * The OS specific kernel driver's responsibility is to create the
 * NvRt context and to register and unregister clients (user mode
 * processes accessing the driver). Additionally the context and the
 * calling client handle need to be passed to the master dispatcher.
 */

#ifndef INCLUDED_NVREFTRACK_H
#define INCLUDED_NVREFTRACK_H

#include "nvcommon.h"
#include "nverror.h"

#ifndef NVRT_ENABLE_LEAK_PRINT
#define NVRT_ENABLE_LEAK_PRINT NV_DEBUG
#endif

/*---------------------------------------------------------*/
/** \defgroup objtype Tracked object types
 *
 * NvRefTrack must be able to identify the object types
 * stored in the database. As the IDL generator can not
 * produce a list of the types they are statically defined
 * here. Note that this list of enumerations is not actually
 * a part of the NvRefTrack public interface - it could be
 * stored separately. Ideally these enumerations would be
 * generated by the IDL dispatcher generator.
 *
 * The exact syntax of these enumerations is important, as
 * the IDL generator will refer to these names when creating
 * reference add/del code in the dispatcher.
 *
 * 1) There must a an enumeration for every package that
 *    contains objects to be tracked. The enumeration should
 *    be called NvRtObjType_<package>.
 * 2) For every object type tracked in the package (every
 *    object type that may have refadd and refdel modifiers
 *    in the idl description) there needs to be an entry in
 *    the enumeration called NvRtObjType_<package>_<type>.
 * 3) The enumerations should start from value 0 and fill
 *    the number space completely up to
 *    NvRtObjType_<package>_Num, which will be equal to the
 *    number of tracked object types in the package.
 */

/**
 * Tracked object types for package NvRm
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvRm_NvRmMemHandle = 0,
    NvRtObjType_NvRm_NvRmDmaHandle,
    NvRtObjType_NvRm_NvRmI2cHandle,
    NvRtObjType_NvRm_GpioHandle,
    NvRtObjType_NvRm_Num,
    NvRtObjType_NvRm_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvRm;

/**
 * Tracked handles for package NvRmGraphics
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvRmGraphics_NvRmChannelHandle = 0,
    NvRtObjType_NvRmGraphics_NvRmContextHandle,
    NvRtObjType_NvRmGraphics_Num,
    NvRtObjType_NvRmGraphics_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvRmGraphics;

/**
 * Tracked handles for package NvMM
 *
 * Tentative handles to track:
 * - NvMMManagerHandle, this does not exist - API failure?
 * - NvMMIRAMScratchHandle, this does not exist - API failure?
 *   Can possibly use references to CodecType, a bit dodgy
 * - pBlock, why is this not a handle?
 * - pClientId, why is this not a handle?
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvMM_NvmmPowerClientHandle = 0,
    NvRtObjType_NvMM_NvmmManagerHandle,
    NvRtObjType_NvMM_NvmmMgrBlockHandle,
    NvRtObjType_NvMM_Num,
    NvRtObjType_NvMM_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvMM;

/**
 * Tracked handles for package NvECPackage
 *
 * Tentative handles to track:
 * - NvEcHandle
 * - NvEcEventRegistrationHandle
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvECPackage_NvEcHandle = 0,
    NvRtObjType_NvECPackage_NvEcEventRegistrationHandle,
    NvRtObjType_NvECPackage_Num,
    NvRtObjType_NvECPackage_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvECPackage;

/**
 * Tracked handles for package NvStorManager
 *
 * Tentative handles to track:
 * - NvStorMgrFileHandle
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvStorManager_NvStorMgrFileHandle = 0,
    NvRtObjType_NvStorManager_Num,
    NvRtObjType_NvStorManager_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvStorManager;

/**
 * Tracked handles for package NvDDKAudio
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvDDKAudio_Num = 0,
    NvRtObjType_NvDDKAudio_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvDDKAudio;

/**
 * Tracked handles for package NvDispMgr
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvDispMgr_Client = 0,
    NvRtObjType_NvDispMgr_Num,
    NvRtObjType_NvDispMgr_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvDispMgr;

/**
 * Tracked object types for package NvDdkAes
 * \ingroup objtype
 */
typedef enum
{
    NvRtObjType_NvDdkAes_NvDdkAesHandle = 0,
    NvRtObjType_NvDdkAes_Num,
    NvRtObjType_NvDdkAes_ForceWord = 0x7FFFFFFF
} NvRtObjType_NvDdkAes;

/*---------------------------------------------------------*/
/** \defgroup os_driver Public interface for os driver */

#if NVRT_ENABLE_LEAK_PRINT
#define NVRT_LEAK(driver, objtype, ptr) \
    NvOsDebugPrintf("[%s] Leaked reference on client exit: (%s) 0x%08x\n", \
                    driver, objtype, ptr);
#else
#define NVRT_LEAK(driver, objtype, ptr)
#endif


typedef struct NvRtRec* NvRtHandle;
typedef NvU32 NvRtClientHandle;
typedef NvU32 NvRtObjRefHandle;

typedef struct
{
    NvRtHandle Rt;
    NvRtClientHandle Client;
    NvU32 PackageIdx;
} NvDispatchCtx;


#if defined(__cplusplus)
extern "C"
{
#endif

 /** 
 * Create a reference tracking database.
 *
 * The OS driver should create a single database upon driver init for
 * all the IDL packages that the driver is responsible for. The
 * created handle should be stored in the global driver context.
 *
 * @param NumPackages            Number of IDL packages that the driver is
 *                               responsible for.
 * @param NumObjTypesPerPackage  A list of the amount of tracked handles
 *                               for each of the IDL packages. The order
 *                               of the list needs to match the package
 *                               indices passed in to the reference
 *                               manipulation functions. The XXX_Num value
 *                               of the object type enumerations can be used
 *                               in constructing the list.
 * @param RtOut                  A newly created reference database handle.
 * @return                       NvSuccess on success.
 *
 * \ingroup os_driver
 */    
NvError NvRtCreate(
    NvU32 NumPackages,
    const NvU32* NumObjTypesPerPackage,
    NvRtHandle* RtOut);

/**
 * Destroy a reference tracking database.
 *
 * This frees all resources associated to a reference database and should
 * be called on driver deinitialization. Note that this function makes no
 * attempt at freeing any outstanding references, the user must make sure
 * that references to driver objects have been freed prior to destroying
 * the database.
 *
 * @param Rt    The reference database handle.
 *
 * \ingroup os_driver
 */
void NvRtDestroy(
    NvRtHandle Rt);

/**
 * Register a new client to the reference database.
 *
 * For all practical purposes, a client refers to a single entity in the
 * system that uses the driver via the IDL interface and may terminate
 * unexpectedly, without freeing the driver resource references it holds.
 * It makes no sense, for example, to register potential kernel-side users
 * of the driver into the database as it should be impossible to terminate
 * such a client unexpectedly without resulting in a complete system failure.
 * Most commonly, but not necessarily, client == usermode process.
 *
 * The client ID returned by this function in the location pointed to by the
 * ClientOut parameter must be stored in a way that it can be passed along
 * to the master dispatcher function (in the NvDispatchCtx struct) for all
 * calls originating from the client. This may, for example, be the return
 * value from a file handle open (XXX_Open) operation passed back as the
 * "open context" parameter into XXX_Ioctl calls.
 *
 * @param Rt            The reference database handle.
 * @param ClientOut     A unique ID for the newly registered client. This
 *                      value never equals 0 on success.
 * @return              NvSuccess on success.
 *
 * \ingroup os_driver
 */
NvError NvRtRegisterClient(
    NvRtHandle Rt,
    NvRtClientHandle* ClientOut);

/**
 * Add a reference to the already registered client.
 *
 * Multiple references to a client may be needed when a single client
 * can be accessed from multiple entities (processes). 
 *
 * @param Rt            The reference database handle.
 * @param Client        The unique ID of the client.
 * @return              NvSuccess on success.
 *
 * \ingroup os_driver
 */
NvError NvRtAddClientRef(
    NvRtHandle Rt,
    NvRtClientHandle Client);
        
/**
 * Unregister a client from the reference database.
 *
 * As client handles are refcounted the caller and nvreftrack must
 * conspire to know when to process possibly leaked resources. The library
 * signals the caller about the correct time to free leaked resources by
 * returning NV_TRUE (standing for: yes, please do cleanup now).
 *
 * Upon a return value of NV_TRUE, it is the responsibility of the OS driver to
 * iterate over the possibly remaining references and implement the tearing
 * down of those references appropriately. This is accomplished by calling
 * NvRtFreeObjRef() until no further object pointers are returned by it for
 * the given (client, package, objtype). After doing the cleanup, the caller
 * should call NvRtUnregisterClient() once more to actually free the client
 * handle.
 * 
 * @param Rt            The reference database handle.
 * @param Client        The unique ID of the Client.
 * @return              NV_TRUE if the caller should clean up leaked objects
 *                      and call NvRtUnregisterClient() again, NV_FALSE
 *                      otherwise.
 *
 * \ingroup os_driver
 */    
NvBool NvRtUnregisterClient(
    NvRtHandle Rt,
    NvRtClientHandle Client);

/**
 * Set/Get opaque user data associated to a client
 *
 * \ingroup os_driver
 */    
    
void NvRtSetClientUserData(
    NvRtHandle Rt,
    NvRtClientHandle Client,
    void* UserData);    
void* NvRtGetClientUserData(
    NvRtHandle Rt,
    NvRtClientHandle Client);
    
/*---------------------------------------------------------*/
/** \defgroup idl_iface Interface used by generated IDL code
 *
 * These functions are mainly intended to be called from the
 * generated IDL dispatcher code. It is of course possible
 * to use this interface directly from handwritten driver
 * code as well.
 *
 * An exception to this rule is the NvRtFreeObjRef(), which
 * the os driver uses to iterate over remaining object
 * references of a client to be unregistered.
 **/

/**
 * Allocate an object reference handle.
 *
 * Adding an object reference is broken into two parts,
 * NvRtAllocObjRef() and NvRtStoreObjRef(). This is so that all
 * resource allocations for the object reference can be done in
 * advance to eliminate the need to be able to rollback a driver
 * object reference add in the generated IDL code.
 *
 * The caller must call one of NvRtDiscardObjRef() or
 * NvRtStoreObjRef() for a NvRtObjRefHandle returned by this
 * function. Failure to do so will unrecoverably leak the object
 * reference handle.
 * 
 * @param Ctx           The dispatcher context, filled by the OS driver
 * @param ObjRef        A new handle to an object reference
 *
 * \ingroup idl_iface
 */        
NvError NvRtAllocObjRef(
    const NvDispatchCtx* Ctx,
    NvRtObjRefHandle* ObjRef);

    
/**
 * Discard an object reference handle.
 *
 * Frees a previously allocated object reference handle without storing
 * anything in the database.
 * 
 * @param Ctx           The dispatcher context, filled by the OS driver
 * @param ObjRef        An object reference handle
 *
 * \ingroup idl_iface
 */        
void NvRtDiscardObjRef(
    const NvDispatchCtx* Ctx,
    NvRtObjRefHandle ObjRef);

/**
 * Store an object reference to the database.
 *
 * This function adds an object reference to the database. An object
 * is identified via the the attributes (Ctx.PackageIdx, ObjType,
 * ObjPtr).  The reference is created from Ctx.Client. It is
 * completely valid to have multiple references to a given object from
 * the same client, or from multiple clients.
 *
 * After calling this function the NvRtObjRefHandle acquired by a call
 * to NvRtAllocObjRef becomes invalid and may no longer be used for
 * any other purpose.
 *
 * It is the caller's responsibility to make sure that the object type
 * is within range of the allocated object types for the package. In
 * practice if the NvRtObjType enumeration is well defined and the
 * NvRt database correctly initialized with the maximum amount of
 * objects for the package this should not be an issue.
 *
 * @param Ctx           The dispatcher context, filled by the OS driver
 * @param ObjRef        An object reference handle
 * @param ObjType       The NvRtObjType of the object to be stored
 * @param ObjPtr        A opaque pointer uniquely identifying the object
 *                      that this reference points to. NULL is not allowed.
 *
 * \ingroup idl_iface
 */        
void NvRtStoreObjRef(
    const NvDispatchCtx* Ctx,
    NvRtObjRefHandle ObjRef,
    NvU32 ObjType,
    void* ObjPtr);

/**
 * Find and free an object reference.
 *
 * The NvRt API provides no way of enumerating or querying the object
 * database without simultaneously freeing the object reference as
 * well.  This is intentional - the utility is built for a very
 * specific purpose and optimized to do that in a fast and robust way.
 *
 * This function is used to free a previously stored object
 * reference. Upon locating an object reference from Ctx.Client to
 * (Ctx.PackageIdx, ObjType, ObjPtr) it immediately frees the object
 * reference from the database.
 *
 * Passing in NULL as ObjPtr means 'match any', the function will locate and
 * free the first object reference from Ctx.Client to (Ctx.PackageIdx,
 * ObjType). This can be used to free all outstanding references from a client,
 * iterate over all packages and object types that the client may have used,
 * call NvRtFreeObjRef() with a NULL ObjPtr parameter and free the returned
 * ObjPtr reference until no more references are returned.
 *
 * In any case, if an object reference was found and freed the ObjPtr
 * of the reference is returned. A NULL return value means that no reference
 * matching the criteria was found. Note that if the generated IDL code works
 * correctly this function should never get called with a ObjPtr parameter that
 * can't be found from the database.
 *
 * @param Ctx           The dispatcher context, filled by the OS driver
 * @param ObjType       The NvRtObjType of the object to be found
 * @param ObjPtr        A opaque pointer of the object to be found
 * @return              The ObjPtr of the reference free'd, NULL if not found
 *
 * \ingroup idl_iface
 */        
void* NvRtFreeObjRef(
    const NvDispatchCtx* Ctx,
    NvU32 ObjType,
    void* ObjPtr);

#if defined(__cplusplus)
}
#endif
    
#endif