summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/common/nvgpu_common.c2
-rw-r--r--drivers/gpu/nvgpu/gk20a/as_gk20a.c11
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c35
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c18
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c18
-rw-r--r--drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c10
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c64
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h4
-rw-r--r--drivers/gpu/nvgpu/gk20a/sched_gk20a.c23
-rw-r--r--drivers/gpu/nvgpu/gk20a/tsg_gk20a.c38
-rw-r--r--drivers/gpu/nvgpu/pci.c3
-rw-r--r--drivers/gpu/nvgpu/vgpu/vgpu.c5
12 files changed, 190 insertions, 41 deletions
diff --git a/drivers/gpu/nvgpu/common/nvgpu_common.c b/drivers/gpu/nvgpu/common/nvgpu_common.c
index 16640aa6..f1109684 100644
--- a/drivers/gpu/nvgpu/common/nvgpu_common.c
+++ b/drivers/gpu/nvgpu/common/nvgpu_common.c
@@ -172,6 +172,8 @@ int nvgpu_probe(struct gk20a *g,
172 172
173 g->remove_support = gk20a_remove_support; 173 g->remove_support = gk20a_remove_support;
174 174
175 kref_init(&g->refcount);
176
175 return 0; 177 return 0;
176} 178}
177 179
diff --git a/drivers/gpu/nvgpu/gk20a/as_gk20a.c b/drivers/gpu/nvgpu/gk20a/as_gk20a.c
index e4bd8b73..a3c8c1ec 100644
--- a/drivers/gpu/nvgpu/gk20a/as_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/as_gk20a.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * GK20A Address Spaces 2 * GK20A Address Spaces
3 * 3 *
4 * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -46,6 +46,9 @@ int gk20a_as_alloc_share(struct gk20a_as *as,
46 int err = 0; 46 int err = 0;
47 47
48 gk20a_dbg_fn(""); 48 gk20a_dbg_fn("");
49 g = gk20a_get(g);
50 if (!g)
51 return -ENODEV;
49 52
50 *out = NULL; 53 *out = NULL;
51 as_share = kzalloc(sizeof(*as_share), GFP_KERNEL); 54 as_share = kzalloc(sizeof(*as_share), GFP_KERNEL);
@@ -85,15 +88,19 @@ int gk20a_as_release_share(struct gk20a_as_share *as_share)
85 gk20a_dbg_fn(""); 88 gk20a_dbg_fn("");
86 89
87 err = gk20a_busy(g->dev); 90 err = gk20a_busy(g->dev);
91
88 if (err) 92 if (err)
89 return err; 93 goto release_fail;
90 94
91 err = gk20a_vm_release_share(as_share); 95 err = gk20a_vm_release_share(as_share);
92 96
93 gk20a_idle(g->dev); 97 gk20a_idle(g->dev);
94 98
99release_fail:
95 release_as_share_id(as_share->as, as_share->id); 100 release_as_share_id(as_share->as, as_share->id);
101 gk20a_put(g);
96 kfree(as_share); 102 kfree(as_share);
103
97 return err; 104 return err;
98} 105}
99 106
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 73cc18d2..c09539ff 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -1234,7 +1234,7 @@ int gk20a_channel_release(struct inode *inode, struct file *filp)
1234 err = gk20a_busy(g->dev); 1234 err = gk20a_busy(g->dev);
1235 if (err) { 1235 if (err) {
1236 gk20a_err(dev_from_gk20a(g), "failed to release a channel!"); 1236 gk20a_err(dev_from_gk20a(g), "failed to release a channel!");
1237 return err; 1237 goto channel_release;
1238 } 1238 }
1239 1239
1240 trace_gk20a_channel_release(dev_name(g->dev)); 1240 trace_gk20a_channel_release(dev_name(g->dev));
@@ -1242,6 +1242,8 @@ int gk20a_channel_release(struct inode *inode, struct file *filp)
1242 gk20a_channel_close(ch); 1242 gk20a_channel_close(ch);
1243 gk20a_idle(g->dev); 1243 gk20a_idle(g->dev);
1244 1244
1245channel_release:
1246 gk20a_put(g);
1245 kfree(filp->private_data); 1247 kfree(filp->private_data);
1246 filp->private_data = NULL; 1248 filp->private_data = NULL;
1247 return 0; 1249 return 0;
@@ -1382,11 +1384,17 @@ static int __gk20a_channel_open(struct gk20a *g, struct file *filp, s32 runlist_
1382 1384
1383 gk20a_dbg_fn(""); 1385 gk20a_dbg_fn("");
1384 1386
1387 g = gk20a_get(g);
1388 if (!g)
1389 return -ENODEV;
1390
1385 trace_gk20a_channel_open(dev_name(g->dev)); 1391 trace_gk20a_channel_open(dev_name(g->dev));
1386 1392
1387 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 1393 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1388 if (!priv) 1394 if (!priv) {
1389 return -ENOMEM; 1395 err = -ENOMEM;
1396 goto free_ref;
1397 }
1390 1398
1391 err = gk20a_busy(g->dev); 1399 err = gk20a_busy(g->dev);
1392 if (err) { 1400 if (err) {
@@ -1414,6 +1422,8 @@ static int __gk20a_channel_open(struct gk20a *g, struct file *filp, s32 runlist_
1414 1422
1415fail_busy: 1423fail_busy:
1416 kfree(priv); 1424 kfree(priv);
1425free_ref:
1426 gk20a_put(g);
1417 return err; 1427 return err;
1418} 1428}
1419 1429
@@ -3509,6 +3519,7 @@ static int gk20a_event_id_release(struct inode *inode, struct file *filp)
3509 } 3519 }
3510 3520
3511 nvgpu_mutex_destroy(&event_id_data->lock); 3521 nvgpu_mutex_destroy(&event_id_data->lock);
3522 gk20a_put(g);
3512 kfree(event_id_data); 3523 kfree(event_id_data);
3513 filp->private_data = NULL; 3524 filp->private_data = NULL;
3514 3525
@@ -3573,20 +3584,28 @@ static int gk20a_channel_event_id_enable(struct channel_gk20a *ch,
3573 int event_id, 3584 int event_id,
3574 int *fd) 3585 int *fd)
3575{ 3586{
3587 struct gk20a *g;
3576 int err = 0; 3588 int err = 0;
3577 int local_fd; 3589 int local_fd;
3578 struct file *file; 3590 struct file *file;
3579 char *name; 3591 char *name;
3580 struct gk20a_event_id_data *event_id_data; 3592 struct gk20a_event_id_data *event_id_data;
3581 3593
3594 g = gk20a_get(ch->g);
3595 if (!g)
3596 return -ENODEV;
3597
3582 err = gk20a_channel_get_event_data_from_id(ch, 3598 err = gk20a_channel_get_event_data_from_id(ch,
3583 event_id, &event_id_data); 3599 event_id, &event_id_data);
3584 if (err == 0) /* We already have event enabled */ 3600 if (err == 0) {
3585 return -EINVAL; 3601 /* We already have event enabled */
3602 err = -EINVAL;
3603 goto free_ref;
3604 }
3586 3605
3587 err = get_unused_fd_flags(O_RDWR); 3606 err = get_unused_fd_flags(O_RDWR);
3588 if (err < 0) 3607 if (err < 0)
3589 return err; 3608 goto free_ref;
3590 local_fd = err; 3609 local_fd = err;
3591 3610
3592 name = kasprintf(GFP_KERNEL, "nvgpu-event%d-fd%d", 3611 name = kasprintf(GFP_KERNEL, "nvgpu-event%d-fd%d",
@@ -3605,7 +3624,7 @@ static int gk20a_channel_event_id_enable(struct channel_gk20a *ch,
3605 err = -ENOMEM; 3624 err = -ENOMEM;
3606 goto clean_up_file; 3625 goto clean_up_file;
3607 } 3626 }
3608 event_id_data->g = ch->g; 3627 event_id_data->g = g;
3609 event_id_data->id = ch->hw_chid; 3628 event_id_data->id = ch->hw_chid;
3610 event_id_data->is_tsg = false; 3629 event_id_data->is_tsg = false;
3611 event_id_data->event_id = event_id; 3630 event_id_data->event_id = event_id;
@@ -3633,6 +3652,8 @@ clean_up_file:
3633 fput(file); 3652 fput(file);
3634clean_up: 3653clean_up:
3635 put_unused_fd(local_fd); 3654 put_unused_fd(local_fd);
3655free_ref:
3656 gk20a_put(g);
3636 return err; 3657 return err;
3637} 3658}
3638 3659
diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
index 753623fa..e6626c4a 100644
--- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
@@ -55,10 +55,15 @@ int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp)
55 55
56 g = container_of(inode->i_cdev, 56 g = container_of(inode->i_cdev,
57 struct gk20a, ctrl.cdev); 57 struct gk20a, ctrl.cdev);
58 g = gk20a_get(g);
59 if (!g)
60 return -ENODEV;
58 61
59 priv = kzalloc(sizeof(struct gk20a_ctrl_priv), GFP_KERNEL); 62 priv = kzalloc(sizeof(struct gk20a_ctrl_priv), GFP_KERNEL);
60 if (!priv) 63 if (!priv) {
61 return -ENOMEM; 64 err = -ENOMEM;
65 goto free_ref;
66 }
62 filp->private_data = priv; 67 filp->private_data = priv;
63 priv->dev = g->dev; 68 priv->dev = g->dev;
64 /* 69 /*
@@ -71,16 +76,16 @@ int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp)
71 if (!g->gr.sw_ready) { 76 if (!g->gr.sw_ready) {
72 err = gk20a_busy(g->dev); 77 err = gk20a_busy(g->dev);
73 if (err) 78 if (err)
74 return err; 79 goto free_ref;
75 gk20a_idle(g->dev); 80 gk20a_idle(g->dev);
76 } 81 }
77 82
78#ifdef CONFIG_ARCH_TEGRA_18x_SOC 83#ifdef CONFIG_ARCH_TEGRA_18x_SOC
79 err = nvgpu_clk_arb_init_session(g, &priv->clk_session); 84 err = nvgpu_clk_arb_init_session(g, &priv->clk_session);
80 if (err)
81 return err;
82#endif 85#endif
83 86free_ref:
87 if (err)
88 gk20a_put(g);
84 return err; 89 return err;
85} 90}
86int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp) 91int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp)
@@ -95,6 +100,7 @@ int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp)
95 nvgpu_clk_arb_release_session(g, priv->clk_session); 100 nvgpu_clk_arb_release_session(g, priv->clk_session);
96#endif 101#endif
97 102
103 gk20a_put(g);
98 kfree(priv); 104 kfree(priv);
99 105
100 return 0; 106 return 0;
diff --git a/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c
index e33477f6..4ad2abd6 100644
--- a/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c
@@ -276,14 +276,20 @@ int gk20a_ctxsw_dev_open(struct inode *inode, struct file *filp)
276 const int vmid = 0; 276 const int vmid = 0;
277 277
278 g = container_of(inode->i_cdev, struct gk20a, ctxsw.cdev); 278 g = container_of(inode->i_cdev, struct gk20a, ctxsw.cdev);
279 g = gk20a_get(g);
280 if (!g)
281 return -ENODEV;
282
279 gk20a_dbg(gpu_dbg_fn|gpu_dbg_ctxsw, "g=%p", g); 283 gk20a_dbg(gpu_dbg_fn|gpu_dbg_ctxsw, "g=%p", g);
280 284
281 if (!capable(CAP_SYS_ADMIN)) 285 if (!capable(CAP_SYS_ADMIN)) {
282 return -EPERM; 286 err = -EPERM;
287 goto free_ref;
288 }
283 289
284 err = gk20a_busy(g->dev); 290 err = gk20a_busy(g->dev);
285 if (err) 291 if (err)
286 return err; 292 goto free_ref;
287 293
288 trace = g->ctxsw_trace; 294 trace = g->ctxsw_trace;
289 if (!trace) { 295 if (!trace) {
@@ -325,7 +331,9 @@ done:
325 331
326idle: 332idle:
327 gk20a_idle(g->dev); 333 gk20a_idle(g->dev);
328 334free_ref:
335 if (err)
336 gk20a_put(g);
329 return err; 337 return err;
330} 338}
331 339
@@ -346,7 +354,7 @@ int gk20a_ctxsw_dev_release(struct inode *inode, struct file *filp)
346 dev->g->ops.fecs_trace.free_user_buffer(dev->g); 354 dev->g->ops.fecs_trace.free_user_buffer(dev->g);
347 dev->hdr = NULL; 355 dev->hdr = NULL;
348 } 356 }
349 357 gk20a_put(g);
350 return 0; 358 return 0;
351} 359}
352 360
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
index 821951ad..7eb742ed 100644
--- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
@@ -101,13 +101,17 @@ static int gk20a_dbg_gpu_do_dev_open(struct inode *inode,
101 else 101 else
102 g = container_of(inode->i_cdev, 102 g = container_of(inode->i_cdev,
103 struct gk20a, prof.cdev); 103 struct gk20a, prof.cdev);
104 g = gk20a_get(g);
105 if (!g)
106 return -ENODEV;
107
104 dev = g->dev; 108 dev = g->dev;
105 109
106 gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, "dbg session: %s", dev_name(dev)); 110 gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, "dbg session: %s", dev_name(dev));
107 111
108 err = alloc_session(&dbg_session); 112 err = alloc_session(&dbg_session);
109 if (err) 113 if (err)
110 return err; 114 goto free_ref;
111 115
112 filp->private_data = dbg_session; 116 filp->private_data = dbg_session;
113 dbg_session->dev = dev; 117 dbg_session->dev = dev;
@@ -133,6 +137,8 @@ err_destroy_lock:
133 nvgpu_mutex_destroy(&dbg_session->ch_list_lock); 137 nvgpu_mutex_destroy(&dbg_session->ch_list_lock);
134err_free_session: 138err_free_session:
135 kfree(dbg_session); 139 kfree(dbg_session);
140free_ref:
141 gk20a_put(g);
136 return err; 142 return err;
137} 143}
138 144
@@ -494,6 +500,8 @@ int gk20a_dbg_gpu_dev_release(struct inode *inode, struct file *filp)
494 nvgpu_mutex_destroy(&dbg_s->ioctl_lock); 500 nvgpu_mutex_destroy(&dbg_s->ioctl_lock);
495 501
496 kfree(dbg_s); 502 kfree(dbg_s);
503 gk20a_put(g);
504
497 return 0; 505 return 0;
498} 506}
499 507
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);
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index a4f0799a..3ba05e84 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -857,6 +857,7 @@ struct gk20a {
857 atomic_t nonstall_ops; 857 atomic_t nonstall_ops;
858 struct work_struct nonstall_fn_work; 858 struct work_struct nonstall_fn_work;
859 struct workqueue_struct *nonstall_work_queue; 859 struct workqueue_struct *nonstall_work_queue;
860 struct kref refcount;
860 861
861 struct resource *reg_mem; 862 struct resource *reg_mem;
862 void __iomem *regs; 863 void __iomem *regs;
@@ -1468,6 +1469,9 @@ static inline void gk20a_channel_trace_sched_param(
1468 1469
1469void nvgpu_wait_for_deferred_interrupts(struct gk20a *g); 1470void nvgpu_wait_for_deferred_interrupts(struct gk20a *g);
1470 1471
1472struct gk20a * __must_check gk20a_get(struct gk20a *g);
1473void gk20a_put(struct gk20a *g);
1474
1471#ifdef CONFIG_DEBUG_FS 1475#ifdef CONFIG_DEBUG_FS
1472int gk20a_railgating_debugfs_init(struct device *dev); 1476int gk20a_railgating_debugfs_init(struct device *dev);
1473#endif 1477#endif
diff --git a/drivers/gpu/nvgpu/gk20a/sched_gk20a.c b/drivers/gpu/nvgpu/gk20a/sched_gk20a.c
index 6fdc2774..a73e7993 100644
--- a/drivers/gpu/nvgpu/gk20a/sched_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/sched_gk20a.c
@@ -377,21 +377,28 @@ int gk20a_sched_dev_open(struct inode *inode, struct file *filp)
377{ 377{
378 struct gk20a *g = container_of(inode->i_cdev, 378 struct gk20a *g = container_of(inode->i_cdev,
379 struct gk20a, sched.cdev); 379 struct gk20a, sched.cdev);
380 struct gk20a_sched_ctrl *sched = &g->sched_ctrl; 380 struct gk20a_sched_ctrl *sched;
381 int err; 381 int err = 0;
382
383 g = gk20a_get(g);
384 if (!g)
385 return -ENODEV;
386 sched = &g->sched_ctrl;
382 387
383 gk20a_dbg(gpu_dbg_fn | gpu_dbg_sched, "g=%p", g); 388 gk20a_dbg(gpu_dbg_fn | gpu_dbg_sched, "g=%p", g);
384 389
385 if (!sched->sw_ready) { 390 if (!sched->sw_ready) {
386 err = gk20a_busy(g->dev); 391 err = gk20a_busy(g->dev);
387 if (err) 392 if (err)
388 return err; 393 goto free_ref;
389 394
390 gk20a_idle(g->dev); 395 gk20a_idle(g->dev);
391 } 396 }
392 397
393 if (!nvgpu_mutex_tryacquire(&sched->busy_lock)) 398 if (!nvgpu_mutex_tryacquire(&sched->busy_lock)) {
394 return -EBUSY; 399 err = -EBUSY;
400 goto free_ref;
401 }
395 402
396 memcpy(sched->recent_tsg_bitmap, sched->active_tsg_bitmap, 403 memcpy(sched->recent_tsg_bitmap, sched->active_tsg_bitmap,
397 sched->bitmap_size); 404 sched->bitmap_size);
@@ -400,7 +407,10 @@ int gk20a_sched_dev_open(struct inode *inode, struct file *filp)
400 filp->private_data = sched; 407 filp->private_data = sched;
401 gk20a_dbg(gpu_dbg_sched, "filp=%p sched=%p", filp, sched); 408 gk20a_dbg(gpu_dbg_sched, "filp=%p sched=%p", filp, sched);
402 409
403 return 0; 410free_ref:
411 if (err)
412 gk20a_put(g);
413 return err;
404} 414}
405 415
406long gk20a_sched_dev_ioctl(struct file *filp, unsigned int cmd, 416long gk20a_sched_dev_ioctl(struct file *filp, unsigned int cmd,
@@ -511,6 +521,7 @@ int gk20a_sched_dev_release(struct inode *inode, struct file *filp)
511 nvgpu_mutex_release(&sched->control_lock); 521 nvgpu_mutex_release(&sched->control_lock);
512 522
513 nvgpu_mutex_release(&sched->busy_lock); 523 nvgpu_mutex_release(&sched->busy_lock);
524 gk20a_put(g);
514 return 0; 525 return 0;
515} 526}
516 527
diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
index e1424f2b..270fed85 100644
--- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c
@@ -259,15 +259,23 @@ static int gk20a_tsg_event_id_enable(struct tsg_gk20a *tsg,
259 struct file *file; 259 struct file *file;
260 char *name; 260 char *name;
261 struct gk20a_event_id_data *event_id_data; 261 struct gk20a_event_id_data *event_id_data;
262 struct gk20a *g;
263
264 g = gk20a_get(tsg->g);
265 if (!g)
266 return -ENODEV;
262 267
263 err = gk20a_tsg_get_event_data_from_id(tsg, 268 err = gk20a_tsg_get_event_data_from_id(tsg,
264 event_id, &event_id_data); 269 event_id, &event_id_data);
265 if (err == 0) /* We already have event enabled */ 270 if (err == 0) {
266 return -EINVAL; 271 /* We already have event enabled */
272 err = -EINVAL;
273 goto free_ref;
274 }
267 275
268 err = get_unused_fd_flags(O_RDWR); 276 err = get_unused_fd_flags(O_RDWR);
269 if (err < 0) 277 if (err < 0)
270 return err; 278 goto free_ref;
271 local_fd = err; 279 local_fd = err;
272 280
273 name = kasprintf(GFP_KERNEL, "nvgpu-event%d-fd%d", 281 name = kasprintf(GFP_KERNEL, "nvgpu-event%d-fd%d",
@@ -286,7 +294,7 @@ static int gk20a_tsg_event_id_enable(struct tsg_gk20a *tsg,
286 err = -ENOMEM; 294 err = -ENOMEM;
287 goto clean_up_file; 295 goto clean_up_file;
288 } 296 }
289 event_id_data->g = tsg->g; 297 event_id_data->g = g;
290 event_id_data->id = tsg->tsgid; 298 event_id_data->id = tsg->tsgid;
291 event_id_data->is_tsg = true; 299 event_id_data->is_tsg = true;
292 event_id_data->event_id = event_id; 300 event_id_data->event_id = event_id;
@@ -315,6 +323,8 @@ clean_up_file:
315 fput(file); 323 fput(file);
316clean_up: 324clean_up:
317 put_unused_fd(local_fd); 325 put_unused_fd(local_fd);
326free_ref:
327 gk20a_put(g);
318 return err; 328 return err;
319} 329}
320 330
@@ -410,18 +420,25 @@ int gk20a_tsg_open(struct gk20a *g, struct file *filp)
410 struct device *dev; 420 struct device *dev;
411 int err; 421 int err;
412 422
423 g = gk20a_get(g);
424 if (!g)
425 return -ENODEV;
426
413 dev = dev_from_gk20a(g); 427 dev = dev_from_gk20a(g);
414 428
415 gk20a_dbg(gpu_dbg_fn, "tsg: %s", dev_name(dev)); 429 gk20a_dbg(gpu_dbg_fn, "tsg: %s", dev_name(dev));
416 430
417 priv = kmalloc(sizeof(*priv), GFP_KERNEL); 431 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
418 if (!priv) 432 if (!priv) {
419 return -ENOMEM; 433 err = -ENOMEM;
434 goto free_ref;
435 }
420 436
421 tsg = acquire_unused_tsg(&g->fifo); 437 tsg = acquire_unused_tsg(&g->fifo);
422 if (!tsg) { 438 if (!tsg) {
423 kfree(priv); 439 kfree(priv);
424 return -ENOMEM; 440 err = -ENOMEM;
441 goto free_ref;
425 } 442 }
426 443
427 tsg->g = g; 444 tsg->g = g;
@@ -458,6 +475,8 @@ int gk20a_tsg_open(struct gk20a *g, struct file *filp)
458 475
459clean_up: 476clean_up:
460 kref_put(&tsg->refcount, gk20a_tsg_release); 477 kref_put(&tsg->refcount, gk20a_tsg_release);
478free_ref:
479 gk20a_put(g);
461 return err; 480 return err;
462} 481}
463 482
@@ -505,16 +524,13 @@ void gk20a_tsg_release(struct kref *ref)
505 tsg->runlist_id = ~0; 524 tsg->runlist_id = ~0;
506 525
507 gk20a_dbg(gpu_dbg_fn, "tsg released %d\n", tsg->tsgid); 526 gk20a_dbg(gpu_dbg_fn, "tsg released %d\n", tsg->tsgid);
527 gk20a_put(g);
508} 528}
509 529
510int gk20a_tsg_dev_release(struct inode *inode, struct file *filp) 530int gk20a_tsg_dev_release(struct inode *inode, struct file *filp)
511{ 531{
512 struct tsg_private *priv = filp->private_data; 532 struct tsg_private *priv = filp->private_data;
513 struct tsg_gk20a *tsg = priv->tsg; 533 struct tsg_gk20a *tsg = priv->tsg;
514 struct gk20a *g = priv->g;
515
516 if (g->driver_is_dying)
517 return -ENODEV;
518 534
519 kref_put(&tsg->refcount, gk20a_tsg_release); 535 kref_put(&tsg->refcount, gk20a_tsg_release);
520 kfree(priv); 536 kfree(priv);
diff --git a/drivers/gpu/nvgpu/pci.c b/drivers/gpu/nvgpu/pci.c
index 7ef626c2..0ed621ce 100644
--- a/drivers/gpu/nvgpu/pci.c
+++ b/drivers/gpu/nvgpu/pci.c
@@ -481,7 +481,8 @@ static void nvgpu_pci_remove(struct pci_dev *pdev)
481 481
482 enable_irq(g->irq_stall); 482 enable_irq(g->irq_stall);
483 483
484 kfree(g); 484 gk20a_get_platform(&pdev->dev)->g = NULL;
485 gk20a_put(g);
485} 486}
486 487
487static struct pci_driver nvgpu_pci_driver = { 488static struct pci_driver nvgpu_pci_driver = {
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c
index d5eb05ac..a97c179f 100644
--- a/drivers/gpu/nvgpu/vgpu/vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/vgpu.c
@@ -638,6 +638,8 @@ int vgpu_probe(struct platform_device *pdev)
638 vgpu_create_sysfs(dev); 638 vgpu_create_sysfs(dev);
639 gk20a_init_gr(gk20a); 639 gk20a_init_gr(gk20a);
640 640
641 kref_init(&gk20a->refcount);
642
641 return 0; 643 return 0;
642} 644}
643 645
@@ -656,6 +658,7 @@ int vgpu_remove(struct platform_device *pdev)
656 gk20a_user_deinit(dev, &nvgpu_class); 658 gk20a_user_deinit(dev, &nvgpu_class);
657 vgpu_remove_sysfs(dev); 659 vgpu_remove_sysfs(dev);
658 gk20a_get_platform(dev)->g = NULL; 660 gk20a_get_platform(dev)->g = NULL;
659 kfree(g); 661 gk20a_put(g);
662
660 return 0; 663 return 0;
661} 664}