diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | 111 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 10 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/dbg_vgpu.c | 84 |
3 files changed, 171 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 | ||
1625 | static 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 | |||
1641 | static 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 | |||
1656 | static 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 | |||
1629 | static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, | 1670 | static 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 | } |
1724 | exit: | 1767 | exit: |
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; | |||
28 | struct gk20a_ctxsw_trace; | 28 | struct gk20a_ctxsw_trace; |
29 | struct acr_desc; | 29 | struct acr_desc; |
30 | struct nvgpu_mem_alloc_tracker; | 30 | struct nvgpu_mem_alloc_tracker; |
31 | struct 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 | ||
103 | static 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 | |||
119 | static 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 | |||
139 | static 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 | |||
162 | static 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 | |||
103 | void vgpu_init_dbg_session_ops(struct gpu_ops *gops) | 179 | void 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 | } |