summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/gk20a.c
diff options
context:
space:
mode:
authorDavid Nieto <dmartineznie@nvidia.com>2017-02-13 14:22:59 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2017-03-20 19:39:55 -0400
commit74fe1caa2b56aab24c17ad4dd2524128fc237894 (patch)
tree0793bb92b67d64690658f3f7cd1a8e1ea93206ba /drivers/gpu/nvgpu/gk20a/gk20a.c
parent469308becaff326da02fcf791e803e812e1cf9f8 (diff)
gpu: nvgpu: Add refcounting to driver fds
The main driver structure is not refcounted properly, so when the driver unload, file desciptors associated to the driver are kept open with dangling references to the main object. This change adds referencing to the gk20a structure. bug 200277762 JIRA: EVLR-1023 Change-Id: Id892e9e1677a344789e99bf649088c076f0bf8de Signed-off-by: David Nieto <dmartineznie@nvidia.com> Reviewed-on: http://git-master/r/1317420 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
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);