summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c68
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.h1
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c19
3 files changed, 58 insertions, 30 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index e487e079..f9b29396 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -47,6 +47,19 @@
47#define NVGPU_CHANNEL_MIN_TIMESLICE_US 1000 47#define NVGPU_CHANNEL_MIN_TIMESLICE_US 1000
48#define NVGPU_CHANNEL_MAX_TIMESLICE_US 50000 48#define NVGPU_CHANNEL_MAX_TIMESLICE_US 50000
49 49
50/*
51 * Although channels do have pointers back to the gk20a struct that they were
52 * created under in cases where the driver is killed that pointer can be bad.
53 * The channel memory can be freed before the release() function for a given
54 * channel is called. This happens when the driver dies and userspace doesn't
55 * get a chance to call release() until after the entire gk20a driver data is
56 * unloaded and freed.
57 */
58struct channel_priv {
59 struct gk20a *g;
60 struct channel_gk20a *c;
61};
62
50static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f); 63static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f);
51static void free_channel(struct fifo_gk20a *f, struct channel_gk20a *c); 64static void free_channel(struct fifo_gk20a *f, struct channel_gk20a *c);
52 65
@@ -392,7 +405,6 @@ void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a)
392 405
393 gk20a_dbg_fn(""); 406 gk20a_dbg_fn("");
394 407
395
396 if (atomic_cmpxchg(&ch_gk20a->bound, true, false)) { 408 if (atomic_cmpxchg(&ch_gk20a->bound, true, false)) {
397 gk20a_writel(g, ccsr_channel_inst_r(ch_gk20a->hw_chid), 409 gk20a_writel(g, ccsr_channel_inst_r(ch_gk20a->hw_chid),
398 ccsr_channel_inst_ptr_f(0) | 410 ccsr_channel_inst_ptr_f(0) |
@@ -1123,16 +1135,31 @@ void gk20a_channel_close(struct channel_gk20a *ch)
1123 gk20a_free_channel(ch); 1135 gk20a_free_channel(ch);
1124} 1136}
1125 1137
1126int gk20a_channel_release(struct inode *inode, struct file *filp) 1138struct channel_gk20a *gk20a_get_channel_from_file(int fd)
1127{ 1139{
1128 struct channel_gk20a *ch = (struct channel_gk20a *)filp->private_data; 1140 struct channel_priv *priv;
1129 struct gk20a *g = ch ? ch->g : NULL; 1141 struct file *f = fget(fd);
1130 int err;
1131 1142
1132 if (!ch) 1143 if (!f)
1133 return 0; 1144 return NULL;
1134 1145
1135 trace_gk20a_channel_release(dev_name(g->dev)); 1146 if (f->f_op != &gk20a_channel_ops) {
1147 fput(f);
1148 return NULL;
1149 }
1150
1151 priv = (struct channel_priv *)f->private_data;
1152 fput(f);
1153 return priv->c;
1154}
1155
1156int gk20a_channel_release(struct inode *inode, struct file *filp)
1157{
1158 struct channel_priv *priv = filp->private_data;
1159 struct channel_gk20a *ch = priv->c;
1160 struct gk20a *g = priv->g;
1161
1162 int err;
1136 1163
1137 err = gk20a_busy(g->dev); 1164 err = gk20a_busy(g->dev);
1138 if (err) { 1165 if (err) {
@@ -1140,6 +1167,9 @@ int gk20a_channel_release(struct inode *inode, struct file *filp)
1140 ch->hw_chid); 1167 ch->hw_chid);
1141 return err; 1168 return err;
1142 } 1169 }
1170
1171 trace_gk20a_channel_release(dev_name(g->dev));
1172
1143 gk20a_channel_close(ch); 1173 gk20a_channel_close(ch);
1144 gk20a_idle(g->dev); 1174 gk20a_idle(g->dev);
1145 1175
@@ -1279,15 +1309,20 @@ static int __gk20a_channel_open(struct gk20a *g, struct file *filp, s32 runlist_
1279{ 1309{
1280 int err; 1310 int err;
1281 struct channel_gk20a *ch; 1311 struct channel_gk20a *ch;
1312 struct channel_priv *priv;
1282 1313
1283 gk20a_dbg_fn(""); 1314 gk20a_dbg_fn("");
1284 1315
1285 trace_gk20a_channel_open(dev_name(g->dev)); 1316 trace_gk20a_channel_open(dev_name(g->dev));
1286 1317
1318 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1319 if (!priv)
1320 return -ENOMEM;
1321
1287 err = gk20a_busy(g->dev); 1322 err = gk20a_busy(g->dev);
1288 if (err) { 1323 if (err) {
1289 gk20a_err(dev_from_gk20a(g), "failed to power on, %d", err); 1324 gk20a_err(dev_from_gk20a(g), "failed to power on, %d", err);
1290 return err; 1325 goto fail_busy;
1291 } 1326 }
1292 /* All the user space channel should be non privilege */ 1327 /* All the user space channel should be non privilege */
1293 ch = gk20a_open_new_channel(g, runlist_id, false); 1328 ch = gk20a_open_new_channel(g, runlist_id, false);
@@ -1295,14 +1330,22 @@ static int __gk20a_channel_open(struct gk20a *g, struct file *filp, s32 runlist_
1295 if (!ch) { 1330 if (!ch) {
1296 gk20a_err(dev_from_gk20a(g), 1331 gk20a_err(dev_from_gk20a(g),
1297 "failed to get f"); 1332 "failed to get f");
1298 return -ENOMEM; 1333 err = -ENOMEM;
1334 goto fail_busy;
1299 } 1335 }
1300 1336
1301 gk20a_channel_trace_sched_param( 1337 gk20a_channel_trace_sched_param(
1302 trace_gk20a_channel_sched_defaults, ch); 1338 trace_gk20a_channel_sched_defaults, ch);
1303 1339
1304 filp->private_data = ch; 1340 priv->g = g;
1341 priv->c = ch;
1342
1343 filp->private_data = priv;
1305 return 0; 1344 return 0;
1345
1346fail_busy:
1347 kfree(priv);
1348 return err;
1306} 1349}
1307 1350
1308int gk20a_channel_open(struct inode *inode, struct file *filp) 1351int gk20a_channel_open(struct inode *inode, struct file *filp)
@@ -3421,7 +3464,8 @@ void gk20a_init_channel(struct gpu_ops *gops)
3421long gk20a_channel_ioctl(struct file *filp, 3464long gk20a_channel_ioctl(struct file *filp,
3422 unsigned int cmd, unsigned long arg) 3465 unsigned int cmd, unsigned long arg)
3423{ 3466{
3424 struct channel_gk20a *ch = filp->private_data; 3467 struct channel_priv *priv = filp->private_data;
3468 struct channel_gk20a *ch = priv->c;
3425 struct device *dev = ch->g->dev; 3469 struct device *dev = ch->g->dev;
3426 u8 buf[NVGPU_IOCTL_CHANNEL_MAX_ARG_SIZE] = {0}; 3470 u8 buf[NVGPU_IOCTL_CHANNEL_MAX_ARG_SIZE] = {0};
3427 int err = 0; 3471 int err = 0;
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
index 66052950..0ad1bbaa 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
@@ -39,6 +39,7 @@ struct gk20a_fence;
39#include "fence_gk20a.h" 39#include "fence_gk20a.h"
40 40
41extern const struct file_operations gk20a_event_id_ops; 41extern const struct file_operations gk20a_event_id_ops;
42extern const struct file_operations gk20a_channel_ops;
42 43
43struct notification { 44struct notification {
44 struct { 45 struct {
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index 086f756b..156d33ed 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -168,7 +168,7 @@ static inline void set_gk20a(struct platform_device *pdev, struct gk20a *gk20a)
168 gk20a_get_platform(&pdev->dev)->g = gk20a; 168 gk20a_get_platform(&pdev->dev)->g = gk20a;
169} 169}
170 170
171static const struct file_operations gk20a_channel_ops = { 171const struct file_operations gk20a_channel_ops = {
172 .owner = THIS_MODULE, 172 .owner = THIS_MODULE,
173 .release = gk20a_channel_release, 173 .release = gk20a_channel_release,
174 .open = gk20a_channel_open, 174 .open = gk20a_channel_open,
@@ -1280,23 +1280,6 @@ fail:
1280 return err; 1280 return err;
1281} 1281}
1282 1282
1283struct channel_gk20a *gk20a_get_channel_from_file(int fd)
1284{
1285 struct channel_gk20a *ch;
1286 struct file *f = fget(fd);
1287 if (!f)
1288 return NULL;
1289
1290 if (f->f_op != &gk20a_channel_ops) {
1291 fput(f);
1292 return NULL;
1293 }
1294
1295 ch = (struct channel_gk20a *)f->private_data;
1296 fput(f);
1297 return ch;
1298}
1299
1300static int gk20a_pm_railgate(struct device *dev) 1283static int gk20a_pm_railgate(struct device *dev)
1301{ 1284{
1302 struct gk20a_platform *platform = dev_get_drvdata(dev); 1285 struct gk20a_platform *platform = dev_get_drvdata(dev);