summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/clk/clk_arb.c67
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c18
-rw-r--r--drivers/gpu/nvgpu/pci.c4
3 files changed, 63 insertions, 26 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c
index 44b442d8..30447d3e 100644
--- a/drivers/gpu/nvgpu/clk/clk_arb.c
+++ b/drivers/gpu/nvgpu/clk/clk_arb.c
@@ -403,7 +403,8 @@ void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm)
403 struct nvgpu_clk_arb *arb = g->clk_arb; 403 struct nvgpu_clk_arb *arb = g->clk_arb;
404 404
405 nvgpu_clk_arb_set_global_alarm(g, alarm); 405 nvgpu_clk_arb_set_global_alarm(g, alarm);
406 queue_work(arb->update_work_queue, &arb->update_fn_work); 406 if (arb->update_work_queue)
407 queue_work(arb->update_work_queue, &arb->update_fn_work);
407} 408}
408 409
409static void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm) 410static void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm)
@@ -455,8 +456,30 @@ static void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm)
455 456
456void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) 457void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g)
457{ 458{
459 struct nvgpu_clk_arb *arb = g->clk_arb;
460 int index;
461
462 if (arb) {
463 cancel_work_sync(&arb->vf_table_fn_work);
464 destroy_workqueue(arb->vf_table_work_queue);
465 arb->vf_table_work_queue = NULL;
466
467 cancel_work_sync(&arb->update_fn_work);
468 destroy_workqueue(arb->update_work_queue);
469 arb->update_work_queue = NULL;
470
471 kfree(arb->gpc2clk_f_points);
472 kfree(arb->mclk_f_points);
473
474 for (index = 0; index < 2; index++) {
475 kfree(arb->vf_table_pool[index].gpc2clk_points);
476 kfree(arb->vf_table_pool[index].mclk_points);
477 }
478 }
479
458 nvgpu_mutex_destroy(&g->clk_arb->pstate_lock); 480 nvgpu_mutex_destroy(&g->clk_arb->pstate_lock);
459 kfree(g->clk_arb); 481 kfree(g->clk_arb);
482 g->clk_arb = NULL;
460} 483}
461 484
462static int nvgpu_clk_arb_install_fd(struct gk20a *g, 485static int nvgpu_clk_arb_install_fd(struct gk20a *g,
@@ -575,9 +598,11 @@ static void nvgpu_clk_arb_free_session(struct kref *refcount)
575 598
576 gk20a_dbg_fn(""); 599 gk20a_dbg_fn("");
577 600
578 nvgpu_spinlock_acquire(&arb->sessions_lock); 601 if (arb) {
579 list_del_rcu(&session->link); 602 nvgpu_spinlock_acquire(&arb->sessions_lock);
580 nvgpu_spinlock_release(&arb->sessions_lock); 603 list_del_rcu(&session->link);
604 nvgpu_spinlock_release(&arb->sessions_lock);
605 }
581 606
582 head = llist_del_all(&session->targets); 607 head = llist_del_all(&session->targets);
583 llist_for_each_entry_safe(dev, tmp, head, node) { 608 llist_for_each_entry_safe(dev, tmp, head, node) {
@@ -596,8 +621,8 @@ void nvgpu_clk_arb_release_session(struct gk20a *g,
596 621
597 session->zombie = true; 622 session->zombie = true;
598 kref_put(&session->refcount, nvgpu_clk_arb_free_session); 623 kref_put(&session->refcount, nvgpu_clk_arb_free_session);
599 624 if (arb && arb->update_work_queue)
600 queue_work(arb->update_work_queue, &arb->update_fn_work); 625 queue_work(arb->update_work_queue, &arb->update_fn_work);
601} 626}
602 627
603int nvgpu_clk_arb_install_event_fd(struct gk20a *g, 628int nvgpu_clk_arb_install_event_fd(struct gk20a *g,
@@ -964,8 +989,8 @@ exit_vf_table:
964 if (status < 0) 989 if (status < 0)
965 nvgpu_clk_arb_set_global_alarm(g, 990 nvgpu_clk_arb_set_global_alarm(g,
966 EVENT(ALARM_VF_TABLE_UPDATE_FAILED)); 991 EVENT(ALARM_VF_TABLE_UPDATE_FAILED));
967 992 if (arb->update_work_queue)
968 queue_work(arb->update_work_queue, &arb->update_fn_work); 993 queue_work(arb->update_work_queue, &arb->update_fn_work);
969 994
970 return status; 995 return status;
971} 996}
@@ -973,8 +998,8 @@ exit_vf_table:
973void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g) 998void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g)
974{ 999{
975 struct nvgpu_clk_arb *arb = g->clk_arb; 1000 struct nvgpu_clk_arb *arb = g->clk_arb;
976 1001 if (arb->vf_table_work_queue)
977 queue_work(arb->vf_table_work_queue, &arb->vf_table_fn_work); 1002 queue_work(arb->vf_table_work_queue, &arb->vf_table_fn_work);
978} 1003}
979 1004
980static void nvgpu_clk_arb_run_vf_table_cb(struct work_struct *work) 1005static void nvgpu_clk_arb_run_vf_table_cb(struct work_struct *work)
@@ -991,8 +1016,9 @@ static void nvgpu_clk_arb_run_vf_table_cb(struct work_struct *work)
991 "failed to cache VF table"); 1016 "failed to cache VF table");
992 nvgpu_clk_arb_set_global_alarm(g, 1017 nvgpu_clk_arb_set_global_alarm(g,
993 EVENT(ALARM_VF_TABLE_UPDATE_FAILED)); 1018 EVENT(ALARM_VF_TABLE_UPDATE_FAILED));
994 1019 if (arb->update_work_queue)
995 queue_work(arb->update_work_queue, &arb->update_fn_work); 1020 queue_work(arb->update_work_queue,
1021 &arb->update_fn_work);
996 1022
997 return; 1023 return;
998 } 1024 }
@@ -1490,8 +1516,8 @@ int nvgpu_clk_arb_commit_request_fd(struct gk20a *g,
1490 } 1516 }
1491 kref_get(&dev->refcount); 1517 kref_get(&dev->refcount);
1492 llist_add(&dev->node, &session->targets); 1518 llist_add(&dev->node, &session->targets);
1493 1519 if (arb->update_work_queue)
1494 queue_work(arb->update_work_queue, &arb->update_fn_work); 1520 queue_work(arb->update_work_queue, &arb->update_fn_work);
1495 1521
1496fdput_fd: 1522fdput_fd:
1497 fdput(fd); 1523 fdput(fd);
@@ -1568,15 +1594,12 @@ static int nvgpu_clk_arb_release_completion_dev(struct inode *inode,
1568{ 1594{
1569 struct nvgpu_clk_dev *dev = filp->private_data; 1595 struct nvgpu_clk_dev *dev = filp->private_data;
1570 struct nvgpu_clk_session *session = dev->session; 1596 struct nvgpu_clk_session *session = dev->session;
1571 struct nvgpu_clk_arb *arb;
1572 1597
1573 arb = session->g->clk_arb;
1574 1598
1575 gk20a_dbg_fn(""); 1599 gk20a_dbg_fn("");
1576 1600
1577 kref_put(&session->refcount, nvgpu_clk_arb_free_session); 1601 kref_put(&session->refcount, nvgpu_clk_arb_free_session);
1578 kref_put(&dev->refcount, nvgpu_clk_arb_free_fd); 1602 kref_put(&dev->refcount, nvgpu_clk_arb_free_fd);
1579
1580 return 0; 1603 return 0;
1581} 1604}
1582 1605
@@ -1591,15 +1614,17 @@ static int nvgpu_clk_arb_release_event_dev(struct inode *inode,
1591 1614
1592 gk20a_dbg_fn(""); 1615 gk20a_dbg_fn("");
1593 1616
1594 nvgpu_spinlock_acquire(&arb->users_lock); 1617 if (arb) {
1595 list_del_rcu(&dev->link); 1618 nvgpu_spinlock_acquire(&arb->users_lock);
1596 nvgpu_spinlock_release(&arb->users_lock); 1619 list_del_rcu(&dev->link);
1620 nvgpu_spinlock_release(&arb->users_lock);
1621 }
1597 1622
1598 synchronize_rcu(); 1623 synchronize_rcu();
1599 kref_put(&session->refcount, nvgpu_clk_arb_free_session); 1624 kref_put(&session->refcount, nvgpu_clk_arb_free_session);
1600 1625
1601 nvgpu_clk_notification_queue_free(&dev->queue); 1626 nvgpu_clk_notification_queue_free(&dev->queue);
1602 kfree(dev); 1627 kref_put(&dev->refcount, nvgpu_clk_arb_free_fd);
1603 1628
1604 return 0; 1629 return 0;
1605} 1630}
diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
index 5a4a2251..753623fa 100644
--- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
@@ -39,6 +39,7 @@
39 39
40struct gk20a_ctrl_priv { 40struct gk20a_ctrl_priv {
41 struct device *dev; 41 struct device *dev;
42 struct gk20a *g;
42#ifdef CONFIG_ARCH_TEGRA_18x_SOC 43#ifdef CONFIG_ARCH_TEGRA_18x_SOC
43 struct nvgpu_clk_session *clk_session; 44 struct nvgpu_clk_session *clk_session;
44#endif 45#endif
@@ -58,35 +59,42 @@ int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp)
58 priv = kzalloc(sizeof(struct gk20a_ctrl_priv), GFP_KERNEL); 59 priv = kzalloc(sizeof(struct gk20a_ctrl_priv), GFP_KERNEL);
59 if (!priv) 60 if (!priv)
60 return -ENOMEM; 61 return -ENOMEM;
61
62 filp->private_data = priv; 62 filp->private_data = priv;
63 priv->dev = g->dev; 63 priv->dev = g->dev;
64 /*
65 * We dont close the arbiter fd's after driver teardown to support
66 * GPU_LOST events, so we store g here, instead of dereferencing the
67 * dev structure on teardown
68 */
69 priv->g = g;
64 70
65 if (!g->gr.sw_ready) { 71 if (!g->gr.sw_ready) {
66 err = gk20a_busy(g->dev); 72 err = gk20a_busy(g->dev);
67 if (err) 73 if (err)
68 return err; 74 return err;
69
70 gk20a_idle(g->dev); 75 gk20a_idle(g->dev);
71 } 76 }
72 77
73#ifdef CONFIG_ARCH_TEGRA_18x_SOC 78#ifdef CONFIG_ARCH_TEGRA_18x_SOC
74 err = nvgpu_clk_arb_init_session(g, &priv->clk_session); 79 err = nvgpu_clk_arb_init_session(g, &priv->clk_session);
80 if (err)
81 return err;
75#endif 82#endif
83
76 return err; 84 return err;
77} 85}
78
79int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp) 86int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp)
80{ 87{
81 struct gk20a_ctrl_priv *priv = filp->private_data; 88 struct gk20a_ctrl_priv *priv = filp->private_data;
89 struct gk20a *g = priv->g;
82 90
83 gk20a_dbg_fn(""); 91 gk20a_dbg_fn("");
84 92
85#ifdef CONFIG_ARCH_TEGRA_18x_SOC 93#ifdef CONFIG_ARCH_TEGRA_18x_SOC
86 if (priv->clk_session) 94 if (priv->clk_session)
87 nvgpu_clk_arb_release_session(gk20a_from_dev(priv->dev), 95 nvgpu_clk_arb_release_session(g, priv->clk_session);
88 priv->clk_session);
89#endif 96#endif
97
90 kfree(priv); 98 kfree(priv);
91 99
92 return 0; 100 return 0;
diff --git a/drivers/gpu/nvgpu/pci.c b/drivers/gpu/nvgpu/pci.c
index 69e16267..7ef626c2 100644
--- a/drivers/gpu/nvgpu/pci.c
+++ b/drivers/gpu/nvgpu/pci.c
@@ -460,6 +460,10 @@ static void nvgpu_pci_remove(struct pci_dev *pdev)
460 gk20a_wait_for_idle(&pdev->dev); 460 gk20a_wait_for_idle(&pdev->dev);
461 gk20a_dbg(gpu_dbg_shutdown, "Driver idle.\n"); 461 gk20a_dbg(gpu_dbg_shutdown, "Driver idle.\n");
462 462
463#ifdef CONFIG_ARCH_TEGRA_18x_SOC
464 nvgpu_clk_arb_cleanup_arbiter(g);
465#endif
466
463 gk20a_user_deinit(g->dev, &nvgpu_pci_class); 467 gk20a_user_deinit(g->dev, &nvgpu_pci_class);
464 gk20a_dbg(gpu_dbg_shutdown, "User de-init done.\b"); 468 gk20a_dbg(gpu_dbg_shutdown, "User de-init done.\b");
465 469