summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2014-04-20 05:58:20 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:09:43 -0400
commitd4030081a867865be95cd3ede1407f0d35d5c761 (patch)
tree87ff7f9646b1cc53b6f04a1c629ae2f333ef8c9a /drivers/gpu/nvgpu/gk20a/channel_gk20a.c
parent9984dff23326dbf28f89f2de23bc00edd4c519f9 (diff)
gpu: nvgpu: gk20a: add submit_lock
Add submit mutex lock to avoid race conditions between submitting a job, removing a job and submitting WFI With this lock make below operations atomic : during submit_gpfifo() - 1. getting new syncpt 2. inserting syncpt increment 3. submitting gpfifo 4. setting job completion interrupt during submit_wfi() - 1. getting new syncpt 2. inserting syncpt increment when idle during channel_update() - 1. checking the submit job completion 2. freeing the job if it is completed Bug 1305024 Change-Id: I0e3c0b8906d83fd59642344626ffdf24fad2aaab Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/397670 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 1570e12c..b7bd55ea 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -1268,12 +1268,6 @@ static int gk20a_channel_submit_wfi(struct channel_gk20a *c)
1268 if (c->has_timedout) 1268 if (c->has_timedout)
1269 return -ETIMEDOUT; 1269 return -ETIMEDOUT;
1270 1270
1271 if (!c->sync) {
1272 c->sync = gk20a_channel_sync_create(c);
1273 if (!c->sync)
1274 return -ENOMEM;
1275 }
1276
1277 update_gp_get(g, c); 1271 update_gp_get(g, c);
1278 free_count = gp_free_count(c); 1272 free_count = gp_free_count(c);
1279 if (unlikely(!free_count)) { 1273 if (unlikely(!free_count)) {
@@ -1282,9 +1276,21 @@ static int gk20a_channel_submit_wfi(struct channel_gk20a *c)
1282 return -EAGAIN; 1276 return -EAGAIN;
1283 } 1277 }
1284 1278
1279 mutex_lock(&c->submit_lock);
1280
1281 if (!c->sync) {
1282 c->sync = gk20a_channel_sync_create(c);
1283 if (!c->sync) {
1284 mutex_unlock(&c->submit_lock);
1285 return -ENOMEM;
1286 }
1287 }
1288
1285 err = c->sync->incr_wfi(c->sync, &cmd, &c->last_submit_fence); 1289 err = c->sync->incr_wfi(c->sync, &cmd, &c->last_submit_fence);
1286 if (unlikely(err)) 1290 if (unlikely(err)) {
1291 mutex_unlock(&c->submit_lock);
1287 return err; 1292 return err;
1293 }
1288 1294
1289 WARN_ON(!c->last_submit_fence.wfi); 1295 WARN_ON(!c->last_submit_fence.wfi);
1290 1296
@@ -1301,6 +1307,8 @@ static int gk20a_channel_submit_wfi(struct channel_gk20a *c)
1301 c->userd_gpu_va + 4 * ram_userd_gp_put_w(), 1307 c->userd_gpu_va + 4 * ram_userd_gp_put_w(),
1302 c->gpfifo.put); 1308 c->gpfifo.put);
1303 1309
1310 mutex_unlock(&c->submit_lock);
1311
1304 gk20a_dbg_info("post-submit put %d, get %d, size %d", 1312 gk20a_dbg_info("post-submit put %d, get %d, size %d",
1305 c->gpfifo.put, c->gpfifo.get, c->gpfifo.entry_num); 1313 c->gpfifo.put, c->gpfifo.get, c->gpfifo.entry_num);
1306 1314
@@ -1393,6 +1401,7 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed)
1393 1401
1394 wake_up(&c->submit_wq); 1402 wake_up(&c->submit_wq);
1395 1403
1404 mutex_lock(&c->submit_lock);
1396 mutex_lock(&c->jobs_lock); 1405 mutex_lock(&c->jobs_lock);
1397 list_for_each_entry_safe(job, n, &c->jobs, list) { 1406 list_for_each_entry_safe(job, n, &c->jobs, list) {
1398 bool completed = WARN_ON(!c->sync) || 1407 bool completed = WARN_ON(!c->sync) ||
@@ -1411,6 +1420,7 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed)
1411 gk20a_idle(g->dev); 1420 gk20a_idle(g->dev);
1412 } 1421 }
1413 mutex_unlock(&c->jobs_lock); 1422 mutex_unlock(&c->jobs_lock);
1423 mutex_unlock(&c->submit_lock);
1414 1424
1415 for (i = 0; i < nr_completed; i++) 1425 for (i = 0; i < nr_completed; i++)
1416 gk20a_idle(c->g->dev); 1426 gk20a_idle(c->g->dev);
@@ -1452,12 +1462,6 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
1452 !fence) 1462 !fence)
1453 return -EINVAL; 1463 return -EINVAL;
1454 1464
1455 if (!c->sync) {
1456 c->sync = gk20a_channel_sync_create(c);
1457 if (!c->sync)
1458 return -ENOMEM;
1459 }
1460
1461#ifdef CONFIG_DEBUG_FS 1465#ifdef CONFIG_DEBUG_FS
1462 /* update debug settings */ 1466 /* update debug settings */
1463 if (g->ops.ltc.sync_debugfs) 1467 if (g->ops.ltc.sync_debugfs)
@@ -1510,6 +1514,17 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
1510 goto clean_up; 1514 goto clean_up;
1511 } 1515 }
1512 1516
1517 mutex_lock(&c->submit_lock);
1518
1519 if (!c->sync) {
1520 c->sync = gk20a_channel_sync_create(c);
1521 if (!c->sync) {
1522 err = -ENOMEM;
1523 mutex_unlock(&c->submit_lock);
1524 goto clean_up;
1525 }
1526 }
1527
1513 /* 1528 /*
1514 * optionally insert syncpt wait in the beginning of gpfifo submission 1529 * optionally insert syncpt wait in the beginning of gpfifo submission
1515 * when user requested and the wait hasn't expired. 1530 * when user requested and the wait hasn't expired.
@@ -1525,8 +1540,10 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
1525 err = c->sync->wait_syncpt(c->sync, fence->syncpt_id, 1540 err = c->sync->wait_syncpt(c->sync, fence->syncpt_id,
1526 fence->value, &wait_cmd); 1541 fence->value, &wait_cmd);
1527 } 1542 }
1528 if (err) 1543 if (err) {
1544 mutex_unlock(&c->submit_lock);
1529 goto clean_up; 1545 goto clean_up;
1546 }
1530 1547
1531 1548
1532 /* always insert syncpt increment at end of gpfifo submission 1549 /* always insert syncpt increment at end of gpfifo submission
@@ -1544,8 +1561,10 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
1544 else 1561 else
1545 err = c->sync->incr(c->sync, &incr_cmd, 1562 err = c->sync->incr(c->sync, &incr_cmd,
1546 &c->last_submit_fence); 1563 &c->last_submit_fence);
1547 if (err) 1564 if (err) {
1565 mutex_unlock(&c->submit_lock);
1548 goto clean_up; 1566 goto clean_up;
1567 }
1549 1568
1550 if (wait_cmd) { 1569 if (wait_cmd) {
1551 c->gpfifo.cpu_va[c->gpfifo.put].entry0 = 1570 c->gpfifo.cpu_va[c->gpfifo.put].entry0 =
@@ -1587,12 +1606,6 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
1587 incr_cmd->gp_put = c->gpfifo.put; 1606 incr_cmd->gp_put = c->gpfifo.put;
1588 } 1607 }
1589 1608
1590 trace_gk20a_channel_submitted_gpfifo(c->g->dev->name,
1591 c->hw_chid,
1592 num_entries,
1593 flags,
1594 fence->syncpt_id, fence->value);
1595
1596 /* TODO! Check for errors... */ 1609 /* TODO! Check for errors... */
1597 gk20a_channel_add_job(c, &c->last_submit_fence); 1610 gk20a_channel_add_job(c, &c->last_submit_fence);
1598 1611
@@ -1601,6 +1614,14 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
1601 c->userd_gpu_va + 4 * ram_userd_gp_put_w(), 1614 c->userd_gpu_va + 4 * ram_userd_gp_put_w(),
1602 c->gpfifo.put); 1615 c->gpfifo.put);
1603 1616
1617 mutex_unlock(&c->submit_lock);
1618
1619 trace_gk20a_channel_submitted_gpfifo(c->g->dev->name,
1620 c->hw_chid,
1621 num_entries,
1622 flags,
1623 fence->syncpt_id, fence->value);
1624
1604 gk20a_dbg_info("post-submit put %d, get %d, size %d", 1625 gk20a_dbg_info("post-submit put %d, get %d, size %d",
1605 c->gpfifo.put, c->gpfifo.get, c->gpfifo.entry_num); 1626 c->gpfifo.put, c->gpfifo.get, c->gpfifo.entry_num);
1606 1627
@@ -1629,6 +1650,7 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid)
1629 c->bound = false; 1650 c->bound = false;
1630 c->remove_support = gk20a_remove_channel_support; 1651 c->remove_support = gk20a_remove_channel_support;
1631 mutex_init(&c->jobs_lock); 1652 mutex_init(&c->jobs_lock);
1653 mutex_init(&c->submit_lock);
1632 INIT_LIST_HEAD(&c->jobs); 1654 INIT_LIST_HEAD(&c->jobs);
1633#if defined(CONFIG_GK20A_CYCLE_STATS) 1655#if defined(CONFIG_GK20A_CYCLE_STATS)
1634 mutex_init(&c->cyclestate.cyclestate_buffer_mutex); 1656 mutex_init(&c->cyclestate.cyclestate_buffer_mutex);