@@ -327,6 +327,8 @@ struct fastrpc_user {
327327 spinlock_t lock ;
328328 /* lock for allocations */
329329 struct mutex mutex ;
330+ /* Reference count */
331+ struct kref refcount ;
330332};
331333
332334static void fastrpc_free_map (struct kref * ref )
@@ -495,15 +497,36 @@ static void fastrpc_channel_ctx_put(struct fastrpc_channel_ctx *cctx)
495497 kref_put (& cctx -> refcount , fastrpc_channel_ctx_free );
496498}
497499
500+ static void fastrpc_user_free (struct kref * ref )
501+ {
502+ struct fastrpc_user * fl = container_of (ref , struct fastrpc_user , refcount );
503+
504+ fastrpc_channel_ctx_put (fl -> cctx );
505+ mutex_destroy (& fl -> mutex );
506+ kfree (fl );
507+ }
508+
509+ static void fastrpc_user_get (struct fastrpc_user * fl )
510+ {
511+ kref_get (& fl -> refcount );
512+ }
513+
514+ static void fastrpc_user_put (struct fastrpc_user * fl )
515+ {
516+ kref_put (& fl -> refcount , fastrpc_user_free );
517+ }
518+
498519static void fastrpc_context_free (struct kref * ref )
499520{
500521 struct fastrpc_invoke_ctx * ctx ;
501522 struct fastrpc_channel_ctx * cctx ;
523+ struct fastrpc_user * fl ;
502524 unsigned long flags ;
503525 int i ;
504526
505527 ctx = container_of (ref , struct fastrpc_invoke_ctx , refcount );
506528 cctx = ctx -> cctx ;
529+ fl = ctx -> fl ;
507530
508531 for (i = 0 ; i < ctx -> nbufs ; i ++ )
509532 fastrpc_map_put (ctx -> maps [i ]);
@@ -519,6 +542,8 @@ static void fastrpc_context_free(struct kref *ref)
519542 kfree (ctx -> olaps );
520543 kfree (ctx );
521544
545+ /* Release the reference taken in fastrpc_context_alloc() */
546+ fastrpc_user_put (fl );
522547 fastrpc_channel_ctx_put (cctx );
523548}
524549
@@ -628,6 +653,8 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
628653
629654 /* Released in fastrpc_context_put() */
630655 fastrpc_channel_ctx_get (cctx );
656+ /* Take a reference to user, released in fastrpc_context_free() */
657+ fastrpc_user_get (user );
631658
632659 ctx -> sc = sc ;
633660 ctx -> retval = -1 ;
@@ -658,6 +685,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
658685 spin_lock (& user -> lock );
659686 list_del (& ctx -> node );
660687 spin_unlock (& user -> lock );
688+ fastrpc_user_put (user );
661689 fastrpc_channel_ctx_put (cctx );
662690 kfree (ctx -> maps );
663691 kfree (ctx -> olaps );
@@ -1675,11 +1703,9 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
16751703 }
16761704
16771705 fastrpc_session_free (cctx , fl -> sctx );
1678- fastrpc_channel_ctx_put (cctx );
1679-
1680- mutex_destroy (& fl -> mutex );
1681- kfree (fl );
16821706 file -> private_data = NULL ;
1707+ /* Release the reference taken in fastrpc_device_open */
1708+ fastrpc_user_put (fl );
16831709
16841710 return 0 ;
16851711}
@@ -1723,6 +1749,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
17231749 spin_lock_irqsave (& cctx -> lock , flags );
17241750 list_add_tail (& fl -> user , & cctx -> users );
17251751 spin_unlock_irqrestore (& cctx -> lock , flags );
1752+ kref_init (& fl -> refcount );
17261753
17271754 return 0 ;
17281755}
0 commit comments