Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions drivers/misc/fastrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ struct fastrpc_user {
spinlock_t lock;
/* lock for allocations */
struct mutex mutex;
/* Reference count */
struct kref refcount;
};

static void fastrpc_free_map(struct kref *ref)
Expand Down Expand Up @@ -495,15 +497,36 @@ static void fastrpc_channel_ctx_put(struct fastrpc_channel_ctx *cctx)
kref_put(&cctx->refcount, fastrpc_channel_ctx_free);
}

static void fastrpc_user_free(struct kref *ref)
{
struct fastrpc_user *fl = container_of(ref, struct fastrpc_user, refcount);

fastrpc_channel_ctx_put(fl->cctx);
mutex_destroy(&fl->mutex);
kfree(fl);
}

static void fastrpc_user_get(struct fastrpc_user *fl)
{
kref_get(&fl->refcount);
}

static void fastrpc_user_put(struct fastrpc_user *fl)
{
kref_put(&fl->refcount, fastrpc_user_free);
}

static void fastrpc_context_free(struct kref *ref)
{
struct fastrpc_invoke_ctx *ctx;
struct fastrpc_channel_ctx *cctx;
struct fastrpc_user *fl;
unsigned long flags;
int i;

ctx = container_of(ref, struct fastrpc_invoke_ctx, refcount);
cctx = ctx->cctx;
fl = ctx->fl;

for (i = 0; i < ctx->nbufs; i++)
fastrpc_map_put(ctx->maps[i]);
Expand All @@ -519,6 +542,8 @@ static void fastrpc_context_free(struct kref *ref)
kfree(ctx->olaps);
kfree(ctx);

/* Release the reference taken in fastrpc_context_alloc() */
fastrpc_user_put(fl);
fastrpc_channel_ctx_put(cctx);
}

Expand Down Expand Up @@ -628,6 +653,8 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(

/* Released in fastrpc_context_put() */
fastrpc_channel_ctx_get(cctx);
/* Take a reference to user, released in fastrpc_context_free() */
fastrpc_user_get(user);

ctx->sc = sc;
ctx->retval = -1;
Expand Down Expand Up @@ -658,6 +685,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
spin_lock(&user->lock);
list_del(&ctx->node);
spin_unlock(&user->lock);
fastrpc_user_put(user);
fastrpc_channel_ctx_put(cctx);
kfree(ctx->maps);
kfree(ctx->olaps);
Expand Down Expand Up @@ -1675,11 +1703,9 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
}

fastrpc_session_free(cctx, fl->sctx);
fastrpc_channel_ctx_put(cctx);

mutex_destroy(&fl->mutex);
kfree(fl);
file->private_data = NULL;
/* Release the reference taken in fastrpc_device_open */
fastrpc_user_put(fl);

return 0;
}
Expand Down Expand Up @@ -1723,6 +1749,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
spin_lock_irqsave(&cctx->lock, flags);
list_add_tail(&fl->user, &cctx->users);
spin_unlock_irqrestore(&cctx->lock, flags);
kref_init(&fl->refcount);

return 0;
}
Expand Down