summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index 30c0f2fb..1d6fb0e9 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -1712,7 +1712,7 @@ static int __exit gk20a_remove(struct platform_device *pdev)
1712 platform->remove(dev); 1712 platform->remove(dev);
1713 1713
1714 set_gk20a(pdev, NULL); 1714 set_gk20a(pdev, NULL);
1715 kfree(g); 1715 gk20a_put(g);
1716 1716
1717 gk20a_dbg_fn("removed"); 1717 gk20a_dbg_fn("removed");
1718 1718
@@ -2274,6 +2274,68 @@ int gk20a_read_ptimer(struct gk20a *g, u64 *value)
2274 return -EBUSY; 2274 return -EBUSY;
2275} 2275}
2276 2276
2277/*
2278 * Free the gk20a struct.
2279 */
2280static void gk20a_free_cb(struct kref *refcount)
2281{
2282 struct gk20a *g = container_of(refcount,
2283 struct gk20a, refcount);
2284
2285 gk20a_dbg(gpu_dbg_shutdown, "Freeing GK20A struct!");
2286 kfree(g);
2287}
2288
2289/**
2290 * gk20a_get() - Increment ref count on driver
2291 *
2292 * @g The driver to increment
2293 * This will fail if the driver is in the process of being released. In that
2294 * case it will return NULL. Otherwise a pointer to the driver passed in will
2295 * be returned.
2296 */
2297struct gk20a * __must_check gk20a_get(struct gk20a *g)
2298{
2299 int success;
2300
2301 /*
2302 * Handle the possibility we are still freeing the gk20a struct while
2303 * gk20a_get() is called. Unlikely but plausible race condition. Ideally
2304 * the code will never be in such a situation that this race is
2305 * possible.
2306 */
2307 success = kref_get_unless_zero(&g->refcount);
2308
2309 gk20a_dbg(gpu_dbg_shutdown, "GET: refs currently %d %s",
2310 atomic_read(&g->refcount.refcount), success ? "" : "(FAILED)");
2311
2312 return success ? g : NULL;
2313}
2314
2315/**
2316 * gk20a_put() - Decrement ref count on driver
2317 *
2318 * @g - The driver to decrement
2319 *
2320 * Decrement the driver ref-count. If neccesary also free the underlying driver
2321 * memory
2322 */
2323void gk20a_put(struct gk20a *g)
2324{
2325 /*
2326 * Note - this is racy, two instances of this could run before the
2327 * actual kref_put(0 runs, you could see something like:
2328 *
2329 * ... PUT: refs currently 2
2330 * ... PUT: refs currently 2
2331 * ... Freeing GK20A struct!
2332 */
2333 gk20a_dbg(gpu_dbg_shutdown, "PUT: refs currently %d",
2334 atomic_read(&g->refcount.refcount));
2335
2336 kref_put(&g->refcount, gk20a_free_cb);
2337}
2338
2277MODULE_LICENSE("GPL v2"); 2339MODULE_LICENSE("GPL v2");
2278module_init(gk20a_init); 2340module_init(gk20a_init);
2279module_exit(gk20a_exit); 2341module_exit(gk20a_exit);