summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2016-10-18 18:23:44 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2016-12-19 18:39:58 -0500
commit28fce3e72bd5231da0e648fb940e04b0ef49ca22 (patch)
tree7e53a771b6d5d25123c27bd9ba7942d917d10398 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c
parentca2c4995278f42835d4667cc486172e38e0186d6 (diff)
gpu: nvgpu: Use struct to hold gk20a pointer
The private_data field in the file pointer passed to release() for channels originally pointed directly to the referenced channel. The problem with this is that when the driver is killed and the channel mmeory is freed that pointer becomes invalid. The necessity of that channel is to get access to the gk20a struct that owns the channel. This can instead be accomplished by making a new private data struct that has a pointer to the gk20a struct directly instead of requiring the channel to be valid. This lets the release() function work even if the channels are gone (though in such cases the release function doesn't do very much). Change-Id: I5e50bb5b6dd08d38974f8e7b46ba125e9a3f1922 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1246586 (cherry picked from commit 14b7c380c74d2caeb04c47ad3e33332a423a84bb) Reviewed-on: http://git-master/r/1261913 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c68
1 files changed, 56 insertions, 12 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;