diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_arb.c | 67 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | 18 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/pci.c | 4 |
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 | ||
409 | static void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm) | 410 | static 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 | ||
456 | void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) | 457 | void 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 | ||
462 | static int nvgpu_clk_arb_install_fd(struct gk20a *g, | 485 | static 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 | ||
603 | int nvgpu_clk_arb_install_event_fd(struct gk20a *g, | 628 | int 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: | |||
973 | void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g) | 998 | void 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 | ||
980 | static void nvgpu_clk_arb_run_vf_table_cb(struct work_struct *work) | 1005 | static 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 | ||
1496 | fdput_fd: | 1522 | fdput_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 | ||
40 | struct gk20a_ctrl_priv { | 40 | struct 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 | |||
79 | int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp) | 86 | int 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 | ||