diff options
Diffstat (limited to 'drivers/gpu/nvgpu/clk')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_arb.c | 67 |
1 files changed, 46 insertions, 21 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 | } |