summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Daifuku <pdaifuku@nvidia.com>2017-03-17 14:36:19 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-03-24 12:08:17 -0400
commitfd02ab4d540ef473df1fe189653cc521876663d6 (patch)
tree1c61ea5b63900808cf79903e72a0bf462814b077
parenta9fb2a4824a48f4ff193a1a54d1143ac0395aa95 (diff)
gpu: nvgpu: vgpu: profiler reservation support
Support for hwpm reservations in the virtual case: - Add session ops for checking and setting global and context reservations, and releasing reservations - in the native case, these just update reservation counts and flags - in the vgpu case, when the reservation count is 0, check with the RM server that a reservation is possible: for global reservations, no other guest can have a reservation; for context reservations, no other guest can have a global reservation - in the vgpu case, when the reservation count is decremented to 0, notify the RM server that the guest no longer has any reservations Bug 1775465 JIRA VFND-3428 Change-Id: Idf115b730e465e35d0745c96a8f8ab6b645c7cae Signed-off-by: Peter Daifuku <pdaifuku@nvidia.com> Reviewed-on: http://git-master/r/1323375 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c111
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h10
-rw-r--r--drivers/gpu/nvgpu/vgpu/dbg_vgpu.c84
-rw-r--r--include/linux/tegra_vgpu.h12
4 files changed, 183 insertions, 34 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
index 0efbcf06..db534318 100644
--- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c
@@ -431,8 +431,8 @@ int dbg_unbind_single_channel_gk20a(struct dbg_session_gk20a *dbg_s,
431 if ((prof_obj->session_id == dbg_s->id) && 431 if ((prof_obj->session_id == dbg_s->id) &&
432 (prof_obj->ch->hw_chid == chid)) { 432 (prof_obj->ch->hw_chid == chid)) {
433 if (prof_obj->has_reservation) { 433 if (prof_obj->has_reservation) {
434 g->profiler_reservation_count--; 434 g->ops.dbg_session_ops.
435 dbg_s->has_profiler_reservation = false; 435 release_profiler_reservation(dbg_s, prof_obj);
436 } 436 }
437 list_del(&prof_obj->prof_obj_entry); 437 list_del(&prof_obj->prof_obj_entry);
438 kfree(prof_obj); 438 kfree(prof_obj);
@@ -533,10 +533,9 @@ int gk20a_dbg_gpu_dev_release(struct inode *inode, struct file *filp)
533 list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects, 533 list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects,
534 prof_obj_entry) { 534 prof_obj_entry) {
535 if (prof_obj->session_id == dbg_s->id) { 535 if (prof_obj->session_id == dbg_s->id) {
536 if (prof_obj->has_reservation) { 536 if (prof_obj->has_reservation)
537 g->global_profiler_reservation_held = false; 537 g->ops.dbg_session_ops.
538 g->profiler_reservation_count--; 538 release_profiler_reservation(dbg_s, prof_obj);
539 }
540 list_del(&prof_obj->prof_obj_entry); 539 list_del(&prof_obj->prof_obj_entry);
541 kfree(prof_obj); 540 kfree(prof_obj);
542 } 541 }
@@ -1583,12 +1582,9 @@ static int nvgpu_ioctl_free_profiler_object(
1583 err = -EINVAL; 1582 err = -EINVAL;
1584 break; 1583 break;
1585 } 1584 }
1586 if (prof_obj->has_reservation) { 1585 if (prof_obj->has_reservation)
1587 if (prof_obj->ch == NULL) 1586 g->ops.dbg_session_ops.
1588 g->global_profiler_reservation_held = false; 1587 release_profiler_reservation(dbg_s, prof_obj);
1589 g->profiler_reservation_count--;
1590 dbg_s->has_profiler_reservation = false;
1591 }
1592 list_del(&prof_obj->prof_obj_entry); 1588 list_del(&prof_obj->prof_obj_entry);
1593 kfree(prof_obj); 1589 kfree(prof_obj);
1594 obj_found = true; 1590 obj_found = true;
@@ -1626,6 +1622,51 @@ static struct dbg_profiler_object_data *find_matching_prof_obj(
1626 return NULL; 1622 return NULL;
1627} 1623}
1628 1624
1625static bool nvgpu_check_and_set_global_reservation(
1626 struct dbg_session_gk20a *dbg_s,
1627 struct dbg_profiler_object_data *prof_obj)
1628{
1629 struct gk20a *g = dbg_s->g;
1630
1631 if (g->profiler_reservation_count == 0) {
1632 g->global_profiler_reservation_held = true;
1633 g->profiler_reservation_count = 1;
1634 dbg_s->has_profiler_reservation = true;
1635 prof_obj->has_reservation = true;
1636 return true;
1637 }
1638 return false;
1639}
1640
1641static bool nvgpu_check_and_set_context_reservation(
1642 struct dbg_session_gk20a *dbg_s,
1643 struct dbg_profiler_object_data *prof_obj)
1644{
1645 struct gk20a *g = dbg_s->g;
1646
1647 /* Assumes that we've already checked that no global reservation
1648 * is in effect.
1649 */
1650 g->profiler_reservation_count++;
1651 dbg_s->has_profiler_reservation = true;
1652 prof_obj->has_reservation = true;
1653 return true;
1654}
1655
1656static void nvgpu_release_profiler_reservation(struct dbg_session_gk20a *dbg_s,
1657 struct dbg_profiler_object_data *prof_obj)
1658{
1659 struct gk20a *g = dbg_s->g;
1660
1661 g->profiler_reservation_count--;
1662 if (g->profiler_reservation_count < 0)
1663 gk20a_err(dev_from_gk20a(g), "Negative reservation count!");
1664 dbg_s->has_profiler_reservation = false;
1665 prof_obj->has_reservation = false;
1666 if (prof_obj->ch == NULL)
1667 g->global_profiler_reservation_held = false;
1668}
1669
1629static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, 1670static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s,
1630 u32 profiler_handle) 1671 u32 profiler_handle)
1631{ 1672{
@@ -1661,17 +1702,12 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s,
1661 /* Global reservations are only allowed if there are no other 1702 /* Global reservations are only allowed if there are no other
1662 * global or per-context reservations currently held 1703 * global or per-context reservations currently held
1663 */ 1704 */
1664 if (g->profiler_reservation_count > 0) { 1705 if (!g->ops.dbg_session_ops.check_and_set_global_reservation(
1706 dbg_s, my_prof_obj)) {
1665 gk20a_err(dev_from_gk20a(g), 1707 gk20a_err(dev_from_gk20a(g),
1666 "global reserve: have existing reservation"); 1708 "global reserve: have existing reservation");
1667 err = -EBUSY; 1709 err = -EBUSY;
1668 goto exit;
1669 } 1710 }
1670
1671 my_prof_obj->has_reservation = true;
1672 g->global_profiler_reservation_held = true;
1673 g->profiler_reservation_count = 1;
1674 dbg_s->has_profiler_reservation = true;
1675 } else if (g->global_profiler_reservation_held) { 1711 } else if (g->global_profiler_reservation_held) {
1676 /* If there's a global reservation, 1712 /* If there's a global reservation,
1677 * we can't take a per-context one. 1713 * we can't take a per-context one.
@@ -1679,7 +1715,6 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s,
1679 gk20a_err(dev_from_gk20a(g), 1715 gk20a_err(dev_from_gk20a(g),
1680 "per-ctxt reserve: global reservation in effect"); 1716 "per-ctxt reserve: global reservation in effect");
1681 err = -EBUSY; 1717 err = -EBUSY;
1682 goto exit;
1683 } else if (gk20a_is_channel_marked_as_tsg(my_prof_obj->ch)) { 1718 } else if (gk20a_is_channel_marked_as_tsg(my_prof_obj->ch)) {
1684 /* TSG: check that another channel in the TSG 1719 /* TSG: check that another channel in the TSG
1685 * doesn't already have the reservation 1720 * doesn't already have the reservation
@@ -1697,9 +1732,13 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s,
1697 } 1732 }
1698 } 1733 }
1699 1734
1700 my_prof_obj->has_reservation = true; 1735 if (!g->ops.dbg_session_ops.check_and_set_context_reservation(
1701 g->profiler_reservation_count++; 1736 dbg_s, my_prof_obj)) {
1702 dbg_s->has_profiler_reservation = true; 1737 /* Another guest OS has the global reservation */
1738 gk20a_err(dev_from_gk20a(g),
1739 "per-ctxt reserve: global reservation in effect");
1740 err = -EBUSY;
1741 }
1703 } else { 1742 } else {
1704 /* channel: check that some other profiler object doesn't 1743 /* channel: check that some other profiler object doesn't
1705 * already have the reservation. 1744 * already have the reservation.
@@ -1717,9 +1756,13 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s,
1717 } 1756 }
1718 } 1757 }
1719 1758
1720 my_prof_obj->has_reservation = true; 1759 if (!g->ops.dbg_session_ops.check_and_set_context_reservation(
1721 g->profiler_reservation_count++; 1760 dbg_s, my_prof_obj)) {
1722 dbg_s->has_profiler_reservation = true; 1761 /* Another guest OS has the global reservation */
1762 gk20a_err(dev_from_gk20a(g),
1763 "per-ctxt reserve: global reservation in effect");
1764 err = -EBUSY;
1765 }
1723 } 1766 }
1724exit: 1767exit:
1725 nvgpu_mutex_release(&g->dbg_sessions_lock); 1768 nvgpu_mutex_release(&g->dbg_sessions_lock);
@@ -1746,13 +1789,9 @@ static int nvgpu_profiler_reserve_release(struct dbg_session_gk20a *dbg_s,
1746 goto exit; 1789 goto exit;
1747 } 1790 }
1748 1791
1749 if (prof_obj->has_reservation) { 1792 if (prof_obj->has_reservation)
1750 prof_obj->has_reservation = false; 1793 g->ops.dbg_session_ops.release_profiler_reservation(dbg_s, prof_obj);
1751 if (prof_obj->ch == NULL) 1794 else {
1752 g->global_profiler_reservation_held = false;
1753 g->profiler_reservation_count--;
1754 dbg_s->has_profiler_reservation = false;
1755 } else {
1756 gk20a_err(dev_from_gk20a(g), "No reservation found"); 1795 gk20a_err(dev_from_gk20a(g), "No reservation found");
1757 err = -EINVAL; 1796 err = -EINVAL;
1758 goto exit; 1797 goto exit;
@@ -1874,4 +1913,10 @@ void gk20a_init_dbg_session_ops(struct gpu_ops *gops)
1874{ 1913{
1875 gops->dbg_session_ops.exec_reg_ops = exec_regops_gk20a; 1914 gops->dbg_session_ops.exec_reg_ops = exec_regops_gk20a;
1876 gops->dbg_session_ops.dbg_set_powergate = dbg_set_powergate; 1915 gops->dbg_session_ops.dbg_set_powergate = dbg_set_powergate;
1916 gops->dbg_session_ops.check_and_set_global_reservation =
1917 nvgpu_check_and_set_global_reservation;
1918 gops->dbg_session_ops.check_and_set_context_reservation =
1919 nvgpu_check_and_set_context_reservation;
1920 gops->dbg_session_ops.release_profiler_reservation =
1921 nvgpu_release_profiler_reservation;
1877}; 1922};
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index 25bcd895..30f1b371 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -28,6 +28,7 @@ struct gk20a_fecs_trace;
28struct gk20a_ctxsw_trace; 28struct gk20a_ctxsw_trace;
29struct acr_desc; 29struct acr_desc;
30struct nvgpu_mem_alloc_tracker; 30struct nvgpu_mem_alloc_tracker;
31struct dbg_profiler_object_data;
31 32
32#include <linux/sched.h> 33#include <linux/sched.h>
33#include <nvgpu/lock.h> 34#include <nvgpu/lock.h>
@@ -758,6 +759,15 @@ struct gpu_ops {
758 u64 num_ops); 759 u64 num_ops);
759 int (*dbg_set_powergate)(struct dbg_session_gk20a *dbg_s, 760 int (*dbg_set_powergate)(struct dbg_session_gk20a *dbg_s,
760 u32 mode); 761 u32 mode);
762 bool (*check_and_set_global_reservation)(
763 struct dbg_session_gk20a *dbg_s,
764 struct dbg_profiler_object_data *prof_obj);
765 bool (*check_and_set_context_reservation)(
766 struct dbg_session_gk20a *dbg_s,
767 struct dbg_profiler_object_data *prof_obj);
768 void (*release_profiler_reservation)(
769 struct dbg_session_gk20a *dbg_s,
770 struct dbg_profiler_object_data *prof_obj);
761 } dbg_session_ops; 771 } dbg_session_ops;
762 struct { 772 struct {
763 void (*get_program_numbers)(struct gk20a *g, 773 void (*get_program_numbers)(struct gk20a *g,
diff --git a/drivers/gpu/nvgpu/vgpu/dbg_vgpu.c b/drivers/gpu/nvgpu/vgpu/dbg_vgpu.c
index 609b497a..a2e57ed5 100644
--- a/drivers/gpu/nvgpu/vgpu/dbg_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/dbg_vgpu.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. 2 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -100,8 +100,90 @@ static int vgpu_dbg_set_powergate(struct dbg_session_gk20a *dbg_s, __u32 mode)
100 return err; 100 return err;
101} 101}
102 102
103static int vgpu_sendrecv_prof_cmd(struct dbg_session_gk20a *dbg_s, u32 mode)
104{
105 struct tegra_vgpu_cmd_msg msg;
106 struct tegra_vgpu_prof_mgt_params *p = &msg.params.prof_management;
107 int err = 0;
108
109 msg.cmd = TEGRA_VGPU_CMD_PROF_MGT;
110 msg.handle = vgpu_get_handle(dbg_s->g);
111
112 p->mode = mode;
113
114 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
115 err = err ? err : msg.ret;
116 return err;
117}
118
119static bool vgpu_check_and_set_global_reservation(
120 struct dbg_session_gk20a *dbg_s,
121 struct dbg_profiler_object_data *prof_obj)
122{
123 struct gk20a *g = dbg_s->g;
124
125 if (g->profiler_reservation_count > 0)
126 return false;
127
128 /* Check that another guest OS doesn't already have a reservation */
129 if (!vgpu_sendrecv_prof_cmd(dbg_s, TEGRA_VGPU_PROF_GET_GLOBAL)) {
130 g->global_profiler_reservation_held = true;
131 g->profiler_reservation_count = 1;
132 dbg_s->has_profiler_reservation = true;
133 prof_obj->has_reservation = true;
134 return true;
135 }
136 return false;
137}
138
139static bool vgpu_check_and_set_context_reservation(
140 struct dbg_session_gk20a *dbg_s,
141 struct dbg_profiler_object_data *prof_obj)
142{
143 struct gk20a *g = dbg_s->g;
144
145 /* Assumes that we've already checked that no global reservation
146 * is in effect for this guest.
147 *
148 * If our reservation count is non-zero, then no other guest has the
149 * global reservation; if it is zero, need to check with RM server.
150 *
151 */
152 if ((g->profiler_reservation_count != 0) ||
153 !vgpu_sendrecv_prof_cmd(dbg_s, TEGRA_VGPU_PROF_GET_CONTEXT)) {
154 g->profiler_reservation_count++;
155 dbg_s->has_profiler_reservation = true;
156 prof_obj->has_reservation = true;
157 return true;
158 }
159 return false;
160}
161
162static void vgpu_release_profiler_reservation(
163 struct dbg_session_gk20a *dbg_s,
164 struct dbg_profiler_object_data *prof_obj)
165{
166 struct gk20a *g = dbg_s->g;
167
168 dbg_s->has_profiler_reservation = false;
169 prof_obj->has_reservation = false;
170 if (prof_obj->ch == NULL)
171 g->global_profiler_reservation_held = false;
172
173 /* If new reservation count is zero, notify server */
174 g->profiler_reservation_count--;
175 if (g->profiler_reservation_count == 0)
176 vgpu_sendrecv_prof_cmd(dbg_s, TEGRA_VGPU_PROF_RELEASE);
177}
178
103void vgpu_init_dbg_session_ops(struct gpu_ops *gops) 179void vgpu_init_dbg_session_ops(struct gpu_ops *gops)
104{ 180{
105 gops->dbg_session_ops.exec_reg_ops = vgpu_exec_regops; 181 gops->dbg_session_ops.exec_reg_ops = vgpu_exec_regops;
106 gops->dbg_session_ops.dbg_set_powergate = vgpu_dbg_set_powergate; 182 gops->dbg_session_ops.dbg_set_powergate = vgpu_dbg_set_powergate;
183 gops->dbg_session_ops.check_and_set_global_reservation =
184 vgpu_check_and_set_global_reservation;
185 gops->dbg_session_ops.check_and_set_context_reservation =
186 vgpu_check_and_set_context_reservation;
187 gops->dbg_session_ops.release_profiler_reservation =
188 vgpu_release_profiler_reservation;
107} 189}
diff --git a/include/linux/tegra_vgpu.h b/include/linux/tegra_vgpu.h
index c0964083..bb9bdcab 100644
--- a/include/linux/tegra_vgpu.h
+++ b/include/linux/tegra_vgpu.h
@@ -102,6 +102,7 @@ enum {
102 TEGRA_VGPU_CMD_SUSPEND_CONTEXTS = 66, 102 TEGRA_VGPU_CMD_SUSPEND_CONTEXTS = 66,
103 TEGRA_VGPU_CMD_RESUME_CONTEXTS = 67, 103 TEGRA_VGPU_CMD_RESUME_CONTEXTS = 67,
104 TEGRA_VGPU_CMD_CLEAR_SM_ERROR_STATE = 68, 104 TEGRA_VGPU_CMD_CLEAR_SM_ERROR_STATE = 68,
105 TEGRA_VGPU_CMD_PROF_MGT = 72,
105}; 106};
106 107
107struct tegra_vgpu_connect_params { 108struct tegra_vgpu_connect_params {
@@ -469,6 +470,16 @@ struct tegra_vgpu_clear_sm_error_state {
469 u32 sm_id; 470 u32 sm_id;
470}; 471};
471 472
473enum {
474 TEGRA_VGPU_PROF_GET_GLOBAL = 0,
475 TEGRA_VGPU_PROF_GET_CONTEXT,
476 TEGRA_VGPU_PROF_RELEASE
477};
478
479struct tegra_vgpu_prof_mgt_params {
480 u32 mode;
481};
482
472struct tegra_vgpu_cmd_msg { 483struct tegra_vgpu_cmd_msg {
473 u32 cmd; 484 u32 cmd;
474 int ret; 485 int ret;
@@ -518,6 +529,7 @@ struct tegra_vgpu_cmd_msg {
518 struct tegra_vgpu_suspend_resume_contexts suspend_contexts; 529 struct tegra_vgpu_suspend_resume_contexts suspend_contexts;
519 struct tegra_vgpu_suspend_resume_contexts resume_contexts; 530 struct tegra_vgpu_suspend_resume_contexts resume_contexts;
520 struct tegra_vgpu_clear_sm_error_state clear_sm_error_state; 531 struct tegra_vgpu_clear_sm_error_state clear_sm_error_state;
532 struct tegra_vgpu_prof_mgt_params prof_management;
521 char padding[192]; 533 char padding[192];
522 } params; 534 } params;
523}; 535};