diff options
-rw-r--r-- | drivers/gpu/nvgpu/Makefile.nvgpu-t18x | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/hal_gp106.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/hw_xp_gp106.h | 137 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/hw_xve_gp106.h | 80 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/xve_gp106.c | 623 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/xve_gp106.h | 99 |
6 files changed, 944 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x index eb9d5977..17b33959 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x +++ b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x | |||
@@ -42,7 +42,8 @@ nvgpu-y += \ | |||
42 | $(nvgpu-t18x)/clk/clk.o \ | 42 | $(nvgpu-t18x)/clk/clk.o \ |
43 | $(nvgpu-t18x)/gp106/clk_gp106.o \ | 43 | $(nvgpu-t18x)/gp106/clk_gp106.o \ |
44 | $(nvgpu-t18x)/gp106/gp106_gating_reglist.o \ | 44 | $(nvgpu-t18x)/gp106/gp106_gating_reglist.o \ |
45 | $(nvgpu-t18x)/gp106/therm_gp106.o | 45 | $(nvgpu-t18x)/gp106/therm_gp106.o \ |
46 | $(nvgpu-t18x)/gp106/xve_gp106.o | ||
46 | 47 | ||
47 | nvgpu-$(CONFIG_TEGRA_GK20A) += $(nvgpu-t18x)/gp10b/platform_gp10b_tegra.o | 48 | nvgpu-$(CONFIG_TEGRA_GK20A) += $(nvgpu-t18x)/gp10b/platform_gp10b_tegra.o |
48 | 49 | ||
diff --git a/drivers/gpu/nvgpu/gp106/hal_gp106.c b/drivers/gpu/nvgpu/gp106/hal_gp106.c index d07da835..2217dfea 100644 --- a/drivers/gpu/nvgpu/gp106/hal_gp106.c +++ b/drivers/gpu/nvgpu/gp106/hal_gp106.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "gp10b/regops_gp10b.h" | 29 | #include "gp10b/regops_gp10b.h" |
30 | #include "gp10b/cde_gp10b.h" | 30 | #include "gp10b/cde_gp10b.h" |
31 | #include "gp106/therm_gp106.h" | 31 | #include "gp106/therm_gp106.h" |
32 | #include "gp106/xve_gp106.h" | ||
32 | 33 | ||
33 | #include "gm206/bios_gm206.h" | 34 | #include "gm206/bios_gm206.h" |
34 | 35 | ||
@@ -210,6 +211,8 @@ int gp106_init_hal(struct gk20a *g) | |||
210 | #endif | 211 | #endif |
211 | gm206_init_bios(gops); | 212 | gm206_init_bios(gops); |
212 | gp106_init_therm_ops(gops); | 213 | gp106_init_therm_ops(gops); |
214 | gp106_init_xve_ops(gops); | ||
215 | |||
213 | gops->name = "gp10x"; | 216 | gops->name = "gp10x"; |
214 | gops->get_litter_value = gp106_get_litter_value; | 217 | gops->get_litter_value = gp106_get_litter_value; |
215 | gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics; | 218 | gops->chip_init_gpu_characteristics = gk20a_init_gpu_characteristics; |
diff --git a/drivers/gpu/nvgpu/gp106/hw_xp_gp106.h b/drivers/gpu/nvgpu/gp106/hw_xp_gp106.h new file mode 100644 index 00000000..40b14da1 --- /dev/null +++ b/drivers/gpu/nvgpu/gp106/hw_xp_gp106.h | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
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, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | /* | ||
17 | * Function naming determines intended use: | ||
18 | * | ||
19 | * <x>_r(void) : Returns the offset for register <x>. | ||
20 | * | ||
21 | * <x>_o(void) : Returns the offset for element <x>. | ||
22 | * | ||
23 | * <x>_w(void) : Returns the word offset for word (4 byte) element <x>. | ||
24 | * | ||
25 | * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits. | ||
26 | * | ||
27 | * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted | ||
28 | * and masked to place it at field <y> of register <x>. This value | ||
29 | * can be |'d with others to produce a full register value for | ||
30 | * register <x>. | ||
31 | * | ||
32 | * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This | ||
33 | * value can be ~'d and then &'d to clear the value of field <y> for | ||
34 | * register <x>. | ||
35 | * | ||
36 | * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted | ||
37 | * to place it at field <y> of register <x>. This value can be |'d | ||
38 | * with others to produce a full register value for <x>. | ||
39 | * | ||
40 | * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register | ||
41 | * <x> value 'r' after being shifted to place its LSB at bit 0. | ||
42 | * This value is suitable for direct comparison with other unshifted | ||
43 | * values appropriate for use in field <y> of register <x>. | ||
44 | * | ||
45 | * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for | ||
46 | * field <y> of register <x>. This value is suitable for direct | ||
47 | * comparison with unshifted values appropriate for use in field <y> | ||
48 | * of register <x>. | ||
49 | */ | ||
50 | #ifndef _hw_xp_gp106_h_ | ||
51 | #define _hw_xp_gp106_h_ | ||
52 | |||
53 | static inline u32 xp_dl_mgr_r(u32 i) | ||
54 | { | ||
55 | return 0x0008b8c0 + i*4; | ||
56 | } | ||
57 | static inline u32 xp_dl_mgr_safe_timing_f(u32 v) | ||
58 | { | ||
59 | return (v & 0x1) << 2; | ||
60 | } | ||
61 | static inline u32 xp_pl_link_config_r(u32 i) | ||
62 | { | ||
63 | return 0x0008c040 + i*4; | ||
64 | } | ||
65 | static inline u32 xp_pl_link_config_ltssm_status_f(u32 v) | ||
66 | { | ||
67 | return (v & 0x1) << 4; | ||
68 | } | ||
69 | static inline u32 xp_pl_link_config_ltssm_status_idle_v(void) | ||
70 | { | ||
71 | return 0x00000000; | ||
72 | } | ||
73 | static inline u32 xp_pl_link_config_ltssm_directive_f(u32 v) | ||
74 | { | ||
75 | return (v & 0xf) << 0; | ||
76 | } | ||
77 | static inline u32 xp_pl_link_config_ltssm_directive_m(void) | ||
78 | { | ||
79 | return 0xf << 0; | ||
80 | } | ||
81 | static inline u32 xp_pl_link_config_ltssm_directive_normal_operations_v(void) | ||
82 | { | ||
83 | return 0x00000000; | ||
84 | } | ||
85 | static inline u32 xp_pl_link_config_ltssm_directive_change_speed_v(void) | ||
86 | { | ||
87 | return 0x00000001; | ||
88 | } | ||
89 | static inline u32 xp_pl_link_config_max_link_rate_f(u32 v) | ||
90 | { | ||
91 | return (v & 0x3) << 18; | ||
92 | } | ||
93 | static inline u32 xp_pl_link_config_max_link_rate_m(void) | ||
94 | { | ||
95 | return 0x3 << 18; | ||
96 | } | ||
97 | static inline u32 xp_pl_link_config_max_link_rate_2500_mtps_v(void) | ||
98 | { | ||
99 | return 0x00000002; | ||
100 | } | ||
101 | static inline u32 xp_pl_link_config_max_link_rate_5000_mtps_v(void) | ||
102 | { | ||
103 | return 0x00000001; | ||
104 | } | ||
105 | static inline u32 xp_pl_link_config_max_link_rate_8000_mtps_v(void) | ||
106 | { | ||
107 | return 0x00000000; | ||
108 | } | ||
109 | static inline u32 xp_pl_link_config_target_tx_width_f(u32 v) | ||
110 | { | ||
111 | return (v & 0x7) << 20; | ||
112 | } | ||
113 | static inline u32 xp_pl_link_config_target_tx_width_m(void) | ||
114 | { | ||
115 | return 0x7 << 20; | ||
116 | } | ||
117 | static inline u32 xp_pl_link_config_target_tx_width_x1_v(void) | ||
118 | { | ||
119 | return 0x00000007; | ||
120 | } | ||
121 | static inline u32 xp_pl_link_config_target_tx_width_x2_v(void) | ||
122 | { | ||
123 | return 0x00000006; | ||
124 | } | ||
125 | static inline u32 xp_pl_link_config_target_tx_width_x4_v(void) | ||
126 | { | ||
127 | return 0x00000005; | ||
128 | } | ||
129 | static inline u32 xp_pl_link_config_target_tx_width_x8_v(void) | ||
130 | { | ||
131 | return 0x00000004; | ||
132 | } | ||
133 | static inline u32 xp_pl_link_config_target_tx_width_x16_v(void) | ||
134 | { | ||
135 | return 0x00000000; | ||
136 | } | ||
137 | #endif | ||
diff --git a/drivers/gpu/nvgpu/gp106/hw_xve_gp106.h b/drivers/gpu/nvgpu/gp106/hw_xve_gp106.h index 74b6cf7c..24434ae0 100644 --- a/drivers/gpu/nvgpu/gp106/hw_xve_gp106.h +++ b/drivers/gpu/nvgpu/gp106/hw_xve_gp106.h | |||
@@ -66,4 +66,84 @@ static inline u32 xve_rom_ctrl_rom_shadow_enabled_f(void) | |||
66 | { | 66 | { |
67 | return 0x1; | 67 | return 0x1; |
68 | } | 68 | } |
69 | static inline u32 xve_link_control_status_r(void) | ||
70 | { | ||
71 | return 0x00000088; | ||
72 | } | ||
73 | static inline u32 xve_link_control_status_link_speed_m(void) | ||
74 | { | ||
75 | return 0xf << 16; | ||
76 | } | ||
77 | static inline u32 xve_link_control_status_link_speed_v(u32 r) | ||
78 | { | ||
79 | return (r >> 16) & 0xf; | ||
80 | } | ||
81 | static inline u32 xve_link_control_status_link_speed_link_speed_2p5_v(void) | ||
82 | { | ||
83 | return 0x00000001; | ||
84 | } | ||
85 | static inline u32 xve_link_control_status_link_speed_link_speed_5p0_v(void) | ||
86 | { | ||
87 | return 0x00000002; | ||
88 | } | ||
89 | static inline u32 xve_link_control_status_link_speed_link_speed_8p0_v(void) | ||
90 | { | ||
91 | return 0x00000003; | ||
92 | } | ||
93 | static inline u32 xve_link_control_status_link_width_m(void) | ||
94 | { | ||
95 | return 0x3f << 20; | ||
96 | } | ||
97 | static inline u32 xve_link_control_status_link_width_v(u32 r) | ||
98 | { | ||
99 | return (r >> 20) & 0x3f; | ||
100 | } | ||
101 | static inline u32 xve_link_control_status_link_width_x1_v(void) | ||
102 | { | ||
103 | return 0x00000001; | ||
104 | } | ||
105 | static inline u32 xve_link_control_status_link_width_x2_v(void) | ||
106 | { | ||
107 | return 0x00000002; | ||
108 | } | ||
109 | static inline u32 xve_link_control_status_link_width_x4_v(void) | ||
110 | { | ||
111 | return 0x00000004; | ||
112 | } | ||
113 | static inline u32 xve_link_control_status_link_width_x8_v(void) | ||
114 | { | ||
115 | return 0x00000008; | ||
116 | } | ||
117 | static inline u32 xve_link_control_status_link_width_x16_v(void) | ||
118 | { | ||
119 | return 0x00000010; | ||
120 | } | ||
121 | static inline u32 xve_priv_xv_r(void) | ||
122 | { | ||
123 | return 0x00000150; | ||
124 | } | ||
125 | static inline u32 xve_priv_xv_cya_l0s_enable_f(u32 v) | ||
126 | { | ||
127 | return (v & 0x1) << 7; | ||
128 | } | ||
129 | static inline u32 xve_priv_xv_cya_l0s_enable_m(void) | ||
130 | { | ||
131 | return 0x1 << 7; | ||
132 | } | ||
133 | static inline u32 xve_priv_xv_cya_l0s_enable_v(u32 r) | ||
134 | { | ||
135 | return (r >> 7) & 0x1; | ||
136 | } | ||
137 | static inline u32 xve_priv_xv_cya_l1_enable_f(u32 v) | ||
138 | { | ||
139 | return (v & 0x1) << 8; | ||
140 | } | ||
141 | static inline u32 xve_priv_xv_cya_l1_enable_m(void) | ||
142 | { | ||
143 | return 0x1 << 8; | ||
144 | } | ||
145 | static inline u32 xve_priv_xv_cya_l1_enable_v(u32 r) | ||
146 | { | ||
147 | return (r >> 8) & 0x1; | ||
148 | } | ||
69 | #endif | 149 | #endif |
diff --git a/drivers/gpu/nvgpu/gp106/xve_gp106.c b/drivers/gpu/nvgpu/gp106/xve_gp106.c new file mode 100644 index 00000000..23a02fbd --- /dev/null +++ b/drivers/gpu/nvgpu/gp106/xve_gp106.c | |||
@@ -0,0 +1,623 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
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, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/debugfs.h> | ||
20 | |||
21 | #include "gk20a/gk20a.h" | ||
22 | #include "gm206/bios_gm206.h" | ||
23 | #include "gp106/xve_gp106.h" | ||
24 | |||
25 | #include "gp106/hw_xp_gp106.h" | ||
26 | #include "gp106/hw_xve_gp106.h" | ||
27 | |||
28 | /** | ||
29 | * Init a timer and place the timeout data in @timeout. | ||
30 | */ | ||
31 | static void init_timeout(u32 timeout_ms, u32 *timeout) | ||
32 | { | ||
33 | *timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Returns 1 if the current time is after @timeout i.e: the timer timed | ||
38 | * out. Returns 0 if the timer still has time left. | ||
39 | */ | ||
40 | static int check_timeout(u32 *timeout) | ||
41 | { | ||
42 | unsigned long now = jiffies; | ||
43 | unsigned long timeout_l = (unsigned long)*timeout; | ||
44 | |||
45 | if (time_after(now, timeout_l)) | ||
46 | return 1; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static void xve_xve_writel_gp106(struct gk20a *g, u32 reg, u32 val) | ||
52 | { | ||
53 | gk20a_writel(g, NV_PCFG + reg, val); | ||
54 | } | ||
55 | |||
56 | static u32 xve_xve_readl_gp106(struct gk20a *g, u32 reg) | ||
57 | { | ||
58 | return gk20a_readl(g, NV_PCFG + reg); | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * Places one of: | ||
63 | * | ||
64 | * %GPU_XVE_SPEED_2P5 | ||
65 | * %GPU_XVE_SPEED_5P0 | ||
66 | * %GPU_XVE_SPEED_8P0 | ||
67 | * | ||
68 | * in the u32 pointed to by @xve_link_speed. If for some reason an unknown PCIe | ||
69 | * bus speed is detected then *@xve_link_speed is not touched and -ENODEV is | ||
70 | * returned. | ||
71 | */ | ||
72 | static int xve_get_speed_gp106(struct gk20a *g, u32 *xve_link_speed) | ||
73 | { | ||
74 | u32 status; | ||
75 | u32 link_speed, real_link_speed = 0; | ||
76 | |||
77 | status = g->ops.xve.xve_readl(g, xve_link_control_status_r()); | ||
78 | |||
79 | link_speed = xve_link_control_status_link_speed_v(status); | ||
80 | |||
81 | /* | ||
82 | * Can't use a switch statement becuase switch statements dont work with | ||
83 | * function calls. | ||
84 | */ | ||
85 | if (link_speed == xve_link_control_status_link_speed_link_speed_2p5_v()) | ||
86 | real_link_speed = GPU_XVE_SPEED_2P5; | ||
87 | if (link_speed == xve_link_control_status_link_speed_link_speed_5p0_v()) | ||
88 | real_link_speed = GPU_XVE_SPEED_5P0; | ||
89 | if (link_speed == xve_link_control_status_link_speed_link_speed_8p0_v()) | ||
90 | real_link_speed = GPU_XVE_SPEED_8P0; | ||
91 | |||
92 | if (!real_link_speed) { | ||
93 | pr_warn("%s: Unknown PCIe bus speed!\n", __func__); | ||
94 | return -ENODEV; | ||
95 | } | ||
96 | |||
97 | *xve_link_speed = real_link_speed; | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Set the mask for L0s in the XVE. | ||
103 | * | ||
104 | * When @status is non-zero the mask for L0s is set which _disables_ L0s. When | ||
105 | * @status is zero L0s is no longer masked and may be enabled. | ||
106 | */ | ||
107 | static void set_xve_l0s_mask(struct gk20a *g, bool status) | ||
108 | { | ||
109 | u32 xve_priv; | ||
110 | u32 status_bit = status ? 1 : 0; | ||
111 | |||
112 | xve_priv = g->ops.xve.xve_readl(g, xve_priv_xv_r()); | ||
113 | |||
114 | xve_priv = set_field(xve_priv, | ||
115 | xve_priv_xv_cya_l0s_enable_m(), | ||
116 | xve_priv_xv_cya_l0s_enable_f(status_bit)); | ||
117 | |||
118 | g->ops.xve.xve_writel(g, xve_priv_xv_r(), xve_priv); | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Set the mask for L1 in the XVE. | ||
123 | * | ||
124 | * When @status is non-zero the mask for L1 is set which _disables_ L0s. When | ||
125 | * @status is zero L1 is no longer masked and may be enabled. | ||
126 | */ | ||
127 | static void set_xve_l1_mask(struct gk20a *g, int status) | ||
128 | { | ||
129 | u32 xve_priv; | ||
130 | u32 status_bit = status ? 1 : 0; | ||
131 | |||
132 | xve_priv = g->ops.xve.xve_readl(g, xve_priv_xv_r()); | ||
133 | |||
134 | xve_priv = set_field(xve_priv, | ||
135 | xve_priv_xv_cya_l1_enable_m(), | ||
136 | xve_priv_xv_cya_l1_enable_f(status_bit)); | ||
137 | |||
138 | g->ops.xve.xve_writel(g, xve_priv_xv_r(), xve_priv); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * When doing the speed change disable power saving features. | ||
143 | */ | ||
144 | static void disable_aspm_gp106(struct gk20a *g) | ||
145 | { | ||
146 | u32 xve_priv; | ||
147 | |||
148 | xve_priv = g->ops.xve.xve_readl(g, xve_priv_xv_r()); | ||
149 | |||
150 | /* | ||
151 | * Store prior ASPM state so we can restore it later on. | ||
152 | */ | ||
153 | g->xve_l0s = xve_priv_xv_cya_l0s_enable_v(xve_priv); | ||
154 | g->xve_l1 = xve_priv_xv_cya_l1_enable_v(xve_priv); | ||
155 | |||
156 | set_xve_l0s_mask(g, true); | ||
157 | set_xve_l1_mask(g, true); | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * Restore the state saved by disable_aspm_gp106(). | ||
162 | */ | ||
163 | static void enable_aspm_gp106(struct gk20a *g) | ||
164 | { | ||
165 | set_xve_l0s_mask(g, g->xve_l0s); | ||
166 | set_xve_l1_mask(g, g->xve_l1); | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Error checking is done in xve_set_speed_gp106. | ||
171 | */ | ||
172 | static int __do_xve_set_speed_gp106(struct gk20a *g, u32 next_link_speed) | ||
173 | { | ||
174 | u32 current_link_speed, new_link_speed; | ||
175 | u32 dl_mgr, saved_dl_mgr; | ||
176 | u32 pl_link_config; | ||
177 | u32 link_control_status, link_speed_setting, link_width; | ||
178 | u32 timeout; | ||
179 | int attempts = 10, err_status = 0; | ||
180 | |||
181 | g->ops.xve.get_speed(g, ¤t_link_speed); | ||
182 | xv_sc_dbg(PRE_CHANGE, "Executing PCIe link change."); | ||
183 | xv_sc_dbg(PRE_CHANGE, " Current speed: %s", | ||
184 | xve_speed_to_str(current_link_speed)); | ||
185 | xv_sc_dbg(PRE_CHANGE, " Next speed: %s", | ||
186 | xve_speed_to_str(next_link_speed)); | ||
187 | xv_sc_dbg(PRE_CHANGE, " PL_LINK_CONFIG: 0x%08x", | ||
188 | gk20a_readl(g, xp_pl_link_config_r(0))); | ||
189 | |||
190 | xv_sc_dbg(DISABLE_ASPM, "Disabling ASPM..."); | ||
191 | disable_aspm_gp106(g); | ||
192 | xv_sc_dbg(DISABLE_ASPM, " Done!"); | ||
193 | |||
194 | xv_sc_dbg(DL_SAFE_MODE, "Putting DL in safe mode..."); | ||
195 | saved_dl_mgr = gk20a_readl(g, xp_dl_mgr_r(0)); | ||
196 | |||
197 | /* | ||
198 | * Put the DL in safe mode. | ||
199 | */ | ||
200 | dl_mgr = saved_dl_mgr; | ||
201 | dl_mgr |= xp_dl_mgr_safe_timing_f(1); | ||
202 | gk20a_writel(g, xp_dl_mgr_r(0), dl_mgr); | ||
203 | xv_sc_dbg(DL_SAFE_MODE, " Done!"); | ||
204 | |||
205 | init_timeout(GPU_XVE_TIMEOUT_MS, &timeout); | ||
206 | |||
207 | xv_sc_dbg(CHECK_LINK, "Checking for link idle..."); | ||
208 | while (1) { | ||
209 | pl_link_config = gk20a_readl(g, xp_pl_link_config_r(0)); | ||
210 | if ((xp_pl_link_config_ltssm_status_f(pl_link_config) == | ||
211 | xp_pl_link_config_ltssm_status_idle_v()) && | ||
212 | (xp_pl_link_config_ltssm_directive_f(pl_link_config) == | ||
213 | xp_pl_link_config_ltssm_directive_normal_operations_v())) | ||
214 | break; | ||
215 | |||
216 | if (check_timeout(&timeout)) { | ||
217 | err_status = -ETIMEDOUT; | ||
218 | break; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | if (err_status == -ETIMEDOUT) | ||
223 | /* TODO: debug message. */ | ||
224 | goto done; | ||
225 | |||
226 | xv_sc_dbg(CHECK_LINK, " Done"); | ||
227 | |||
228 | xv_sc_dbg(LINK_SETTINGS, "Preparing next link settings"); | ||
229 | pl_link_config &= ~xp_pl_link_config_max_link_rate_m(); | ||
230 | switch (next_link_speed) { | ||
231 | case GPU_XVE_SPEED_2P5: | ||
232 | link_speed_setting = | ||
233 | xve_link_control_status_link_speed_link_speed_2p5_v(); | ||
234 | pl_link_config |= xp_pl_link_config_max_link_rate_f( | ||
235 | xp_pl_link_config_max_link_rate_2500_mtps_v()); | ||
236 | break; | ||
237 | case GPU_XVE_SPEED_5P0: | ||
238 | link_speed_setting = | ||
239 | xve_link_control_status_link_speed_link_speed_5p0_v(); | ||
240 | pl_link_config |= xp_pl_link_config_max_link_rate_f( | ||
241 | xp_pl_link_config_max_link_rate_5000_mtps_v()); | ||
242 | break; | ||
243 | case GPU_XVE_SPEED_8P0: | ||
244 | link_speed_setting = | ||
245 | xve_link_control_status_link_speed_link_speed_8p0_v(); | ||
246 | pl_link_config |= xp_pl_link_config_max_link_rate_f( | ||
247 | xp_pl_link_config_max_link_rate_8000_mtps_v()); | ||
248 | break; | ||
249 | default: | ||
250 | BUG(); /* Should never be hit. */ | ||
251 | } | ||
252 | |||
253 | link_control_status = | ||
254 | g->ops.xve.xve_readl(g, xve_link_control_status_r()); | ||
255 | link_width = xve_link_control_status_link_width_v(link_control_status); | ||
256 | |||
257 | pl_link_config &= ~xp_pl_link_config_target_tx_width_m(); | ||
258 | |||
259 | /* Can't use a switch due to oddities in register definitions. */ | ||
260 | if (link_width == xve_link_control_status_link_width_x1_v()) | ||
261 | pl_link_config |= xp_pl_link_config_target_tx_width_f( | ||
262 | xp_pl_link_config_target_tx_width_x1_v()); | ||
263 | else if (link_width == xve_link_control_status_link_width_x2_v()) | ||
264 | pl_link_config |= xp_pl_link_config_target_tx_width_f( | ||
265 | xp_pl_link_config_target_tx_width_x2_v()); | ||
266 | else if (link_width == xve_link_control_status_link_width_x4_v()) | ||
267 | pl_link_config |= xp_pl_link_config_target_tx_width_f( | ||
268 | xp_pl_link_config_target_tx_width_x4_v()); | ||
269 | else if (link_width == xve_link_control_status_link_width_x8_v()) | ||
270 | pl_link_config |= xp_pl_link_config_target_tx_width_f( | ||
271 | xp_pl_link_config_target_tx_width_x8_v()); | ||
272 | else if (link_width == xve_link_control_status_link_width_x16_v()) | ||
273 | pl_link_config |= xp_pl_link_config_target_tx_width_f( | ||
274 | xp_pl_link_config_target_tx_width_x16_v()); | ||
275 | else | ||
276 | BUG(); | ||
277 | |||
278 | xv_sc_dbg(LINK_SETTINGS, " pl_link_config = 0x%08x", pl_link_config); | ||
279 | xv_sc_dbg(LINK_SETTINGS, " Done"); | ||
280 | |||
281 | xv_sc_dbg(EXEC_CHANGE, "Running link speed change..."); | ||
282 | |||
283 | init_timeout(GPU_XVE_TIMEOUT_MS, &timeout); | ||
284 | while (1) { | ||
285 | gk20a_writel(g, xp_pl_link_config_r(0), pl_link_config); | ||
286 | if (pl_link_config == | ||
287 | gk20a_readl(g, xp_pl_link_config_r(0))) | ||
288 | break; | ||
289 | |||
290 | if (check_timeout(&timeout)) { | ||
291 | err_status = -ETIMEDOUT; | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | if (err_status == -ETIMEDOUT) | ||
297 | goto done; | ||
298 | |||
299 | xv_sc_dbg(EXEC_CHANGE, " Wrote PL_LINK_CONFIG."); | ||
300 | |||
301 | pl_link_config = gk20a_readl(g, xp_pl_link_config_r(0)); | ||
302 | |||
303 | do { | ||
304 | pl_link_config = set_field(pl_link_config, | ||
305 | xp_pl_link_config_ltssm_directive_m(), | ||
306 | xp_pl_link_config_ltssm_directive_f( | ||
307 | xp_pl_link_config_ltssm_directive_change_speed_v())); | ||
308 | |||
309 | xv_sc_dbg(EXEC_CHANGE, " Executing change (0x%08x)!", | ||
310 | pl_link_config); | ||
311 | gk20a_writel(g, xp_pl_link_config_r(0), pl_link_config); | ||
312 | |||
313 | /* | ||
314 | * Read NV_XP_PL_LINK_CONFIG until the link has swapped to | ||
315 | * the target speed. | ||
316 | */ | ||
317 | init_timeout(GPU_XVE_TIMEOUT_MS, &timeout); | ||
318 | while (1) { | ||
319 | pl_link_config = gk20a_readl(g, xp_pl_link_config_r(0)); | ||
320 | if (pl_link_config != 0xfffffff && | ||
321 | (xp_pl_link_config_ltssm_status_f(pl_link_config) == | ||
322 | xp_pl_link_config_ltssm_status_idle_v()) && | ||
323 | (xp_pl_link_config_ltssm_directive_f(pl_link_config) == | ||
324 | xp_pl_link_config_ltssm_directive_normal_operations_v())) | ||
325 | break; | ||
326 | |||
327 | if (check_timeout(&timeout)) { | ||
328 | err_status = -ETIMEDOUT; | ||
329 | xv_sc_dbg(EXEC_CHANGE, " timeout; pl_link_config = 0x%x", | ||
330 | pl_link_config); | ||
331 | break; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | xv_sc_dbg(EXEC_CHANGE, " Change done... Checking status"); | ||
336 | |||
337 | if (pl_link_config == 0xffffffff) { | ||
338 | WARN(1, "GPU fell of PCI bus!?"); | ||
339 | |||
340 | /* | ||
341 | * The rest of the driver is probably about to | ||
342 | * explode... | ||
343 | */ | ||
344 | BUG(); | ||
345 | } | ||
346 | |||
347 | link_control_status = | ||
348 | g->ops.xve.xve_readl(g, xve_link_control_status_r()); | ||
349 | xv_sc_dbg(EXEC_CHANGE, " target %d vs current %d", | ||
350 | link_speed_setting, | ||
351 | xve_link_control_status_link_speed_v(link_control_status)); | ||
352 | |||
353 | if (err_status == -ETIMEDOUT) | ||
354 | xv_sc_dbg(EXEC_CHANGE, " Oops timed out?"); | ||
355 | } while (attempts-- > 0 && | ||
356 | link_speed_setting != | ||
357 | xve_link_control_status_link_speed_v(link_control_status)); | ||
358 | |||
359 | xv_sc_dbg(EXEC_VERIF, "Verifying speed change..."); | ||
360 | |||
361 | /* | ||
362 | * Check that the new link speed is actually active. If we failed to | ||
363 | * change to the new link speed then return to the link speed setting | ||
364 | * pre-speed change. | ||
365 | */ | ||
366 | new_link_speed = xve_link_control_status_link_speed_v( | ||
367 | link_control_status); | ||
368 | if (link_speed_setting != new_link_speed) { | ||
369 | u32 link_config = gk20a_readl(g, xp_pl_link_config_r(0)); | ||
370 | |||
371 | xv_sc_dbg(EXEC_VERIF, " Current and target speeds mismatch!"); | ||
372 | xv_sc_dbg(EXEC_VERIF, " LINK_CONTROL_STATUS: 0x%08x", | ||
373 | g->ops.xve.xve_readl(g, xve_link_control_status_r())); | ||
374 | xv_sc_dbg(EXEC_VERIF, " Link speed is %s - should be %s", | ||
375 | xve_speed_to_str(new_link_speed), | ||
376 | xve_speed_to_str(link_speed_setting)); | ||
377 | |||
378 | link_config &= ~xp_pl_link_config_max_link_rate_m(); | ||
379 | if (new_link_speed == | ||
380 | xve_link_control_status_link_speed_link_speed_2p5_v()) | ||
381 | link_config |= xp_pl_link_config_max_link_rate_f( | ||
382 | xp_pl_link_config_max_link_rate_2500_mtps_v()); | ||
383 | else if (new_link_speed == | ||
384 | xve_link_control_status_link_speed_link_speed_5p0_v()) | ||
385 | link_config |= xp_pl_link_config_max_link_rate_f( | ||
386 | xp_pl_link_config_max_link_rate_5000_mtps_v()); | ||
387 | else if (new_link_speed == | ||
388 | xve_link_control_status_link_speed_link_speed_8p0_v()) | ||
389 | link_config |= xp_pl_link_config_max_link_rate_f( | ||
390 | xp_pl_link_config_max_link_rate_8000_mtps_v()); | ||
391 | else | ||
392 | link_config |= xp_pl_link_config_max_link_rate_f( | ||
393 | xp_pl_link_config_max_link_rate_2500_mtps_v()); | ||
394 | |||
395 | gk20a_writel(g, xp_pl_link_config_r(0), link_config); | ||
396 | err_status = -ENODEV; | ||
397 | } else { | ||
398 | xv_sc_dbg(EXEC_VERIF, " Current and target speeds match!"); | ||
399 | err_status = 0; | ||
400 | } | ||
401 | |||
402 | done: | ||
403 | /* Restore safe timings. */ | ||
404 | xv_sc_dbg(CLEANUP, "Restoring saved DL settings..."); | ||
405 | gk20a_writel(g, xp_dl_mgr_r(0), saved_dl_mgr); | ||
406 | xv_sc_dbg(CLEANUP, " Done"); | ||
407 | |||
408 | xv_sc_dbg(CLEANUP, "Re-enabling ASPM settings..."); | ||
409 | enable_aspm_gp106(g); | ||
410 | xv_sc_dbg(CLEANUP, " Done"); | ||
411 | |||
412 | return err_status; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * Sets the PCIe link speed to @xve_link_speed which must be one of: | ||
417 | * | ||
418 | * %GPU_XVE_SPEED_2P5 | ||
419 | * %GPU_XVE_SPEED_5P0 | ||
420 | * %GPU_XVE_SPEED_8P0 | ||
421 | * | ||
422 | * If an error is encountered an appropriate error will be returned. | ||
423 | */ | ||
424 | static int xve_set_speed_gp106(struct gk20a *g, u32 next_link_speed) | ||
425 | { | ||
426 | u32 current_link_speed; | ||
427 | int err; | ||
428 | |||
429 | if ((next_link_speed & GPU_XVE_SPEED_MASK) == 0) | ||
430 | return -EINVAL; | ||
431 | |||
432 | err = g->ops.xve.get_speed(g, ¤t_link_speed); | ||
433 | if (err) | ||
434 | return err; | ||
435 | |||
436 | /* No-op. */ | ||
437 | if (current_link_speed == next_link_speed) | ||
438 | return 0; | ||
439 | |||
440 | return __do_xve_set_speed_gp106(g, next_link_speed); | ||
441 | } | ||
442 | |||
443 | /** | ||
444 | * Places a bitmask of available speeds for gp106 in @speed_mask. | ||
445 | */ | ||
446 | static void xve_available_speeds_gp106(struct gk20a *g, u32 *speed_mask) | ||
447 | { | ||
448 | *speed_mask = GPU_XVE_SPEED_2P5 | GPU_XVE_SPEED_5P0; | ||
449 | } | ||
450 | |||
451 | static ssize_t xve_link_speed_write(struct file *filp, | ||
452 | const char __user *buff, | ||
453 | size_t len, loff_t *off) | ||
454 | { | ||
455 | struct gk20a *g = ((struct seq_file *)filp->private_data)->private; | ||
456 | char kbuff[16]; | ||
457 | u32 buff_size, check_len; | ||
458 | u32 link_speed = 0; | ||
459 | int ret; | ||
460 | |||
461 | buff_size = min_t(size_t, 16, len); | ||
462 | |||
463 | memset(kbuff, 0, 16); | ||
464 | if (copy_from_user(kbuff, buff, buff_size)) | ||
465 | return -EFAULT; | ||
466 | |||
467 | check_len = strlen("Gen1"); | ||
468 | if (strncmp(kbuff, "Gen1", check_len) == 0) | ||
469 | link_speed = GPU_XVE_SPEED_2P5; | ||
470 | else if (strncmp(kbuff, "Gen2", check_len) == 0) | ||
471 | link_speed = GPU_XVE_SPEED_5P0; | ||
472 | else if (strncmp(kbuff, "Gen3", check_len) == 0) | ||
473 | link_speed = GPU_XVE_SPEED_8P0; | ||
474 | else | ||
475 | gk20a_err(g->dev, "%s: Unknown PCIe speed: %s\n", | ||
476 | __func__, kbuff); | ||
477 | |||
478 | if (!link_speed) | ||
479 | return -EINVAL; | ||
480 | |||
481 | /* Brief pause... To help rate limit this. */ | ||
482 | msleep(250); | ||
483 | |||
484 | /* | ||
485 | * And actually set the speed. Yay. | ||
486 | */ | ||
487 | ret = g->ops.xve.set_speed(g, link_speed); | ||
488 | if (ret) | ||
489 | return ret; | ||
490 | |||
491 | return len; | ||
492 | } | ||
493 | |||
494 | static int xve_link_speed_show(struct seq_file *s, void *unused) | ||
495 | { | ||
496 | struct gk20a *g = s->private; | ||
497 | u32 speed; | ||
498 | int err; | ||
499 | |||
500 | err = g->ops.xve.get_speed(g, &speed); | ||
501 | if (err) | ||
502 | return err; | ||
503 | |||
504 | seq_printf(s, "Current PCIe speed:\n %s\n", xve_speed_to_str(speed)); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static int xve_link_speed_open(struct inode *inode, struct file *file) | ||
510 | { | ||
511 | return single_open(file, xve_link_speed_show, inode->i_private); | ||
512 | } | ||
513 | |||
514 | static const struct file_operations xve_link_speed_fops = { | ||
515 | .open = xve_link_speed_open, | ||
516 | .read = seq_read, | ||
517 | .write = xve_link_speed_write, | ||
518 | .llseek = seq_lseek, | ||
519 | .release = single_release, | ||
520 | }; | ||
521 | |||
522 | static int xve_available_speeds_show(struct seq_file *s, void *unused) | ||
523 | { | ||
524 | struct gk20a *g = s->private; | ||
525 | u32 available_speeds; | ||
526 | |||
527 | g->ops.xve.available_speeds(g, &available_speeds); | ||
528 | |||
529 | seq_puts(s, "Available PCIe bus speeds:\n"); | ||
530 | if (available_speeds & GPU_XVE_SPEED_2P5) | ||
531 | seq_puts(s, " Gen1\n"); | ||
532 | if (available_speeds & GPU_XVE_SPEED_5P0) | ||
533 | seq_puts(s, " Gen2\n"); | ||
534 | if (available_speeds & GPU_XVE_SPEED_8P0) | ||
535 | seq_puts(s, " Gen3\n"); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static int xve_available_speeds_open(struct inode *inode, struct file *file) | ||
541 | { | ||
542 | return single_open(file, xve_available_speeds_show, inode->i_private); | ||
543 | } | ||
544 | |||
545 | static const struct file_operations xve_available_speeds_fops = { | ||
546 | .open = xve_available_speeds_open, | ||
547 | .read = seq_read, | ||
548 | .llseek = seq_lseek, | ||
549 | .release = single_release, | ||
550 | }; | ||
551 | |||
552 | static int xve_link_control_status_show(struct seq_file *s, void *unused) | ||
553 | { | ||
554 | struct gk20a *g = s->private; | ||
555 | u32 link_status; | ||
556 | |||
557 | link_status = g->ops.xve.xve_readl(g, xve_link_control_status_r()); | ||
558 | seq_printf(s, "0x%08x\n", link_status); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int xve_link_control_status_open(struct inode *inode, struct file *file) | ||
564 | { | ||
565 | return single_open(file, xve_link_control_status_show, inode->i_private); | ||
566 | } | ||
567 | |||
568 | static const struct file_operations xve_link_control_status_fops = { | ||
569 | .open = xve_link_control_status_open, | ||
570 | .read = seq_read, | ||
571 | .llseek = seq_lseek, | ||
572 | .release = single_release, | ||
573 | }; | ||
574 | |||
575 | static int xve_sw_init_gp106(struct device *dev) | ||
576 | { | ||
577 | int err = -ENODEV; | ||
578 | #ifdef CONFIG_DEBUG_FS | ||
579 | struct gk20a *g = get_gk20a(dev); | ||
580 | struct gk20a_platform *plat = gk20a_get_platform(dev); | ||
581 | struct dentry *gpu_root = plat->debugfs; | ||
582 | |||
583 | g->debugfs_xve = debugfs_create_dir("xve", gpu_root); | ||
584 | if (IS_ERR_OR_NULL(g->debugfs_xve)) | ||
585 | goto fail; | ||
586 | |||
587 | /* | ||
588 | * These are just debug nodes. If they fail to get made it's not worth | ||
589 | * worrying the higher level SW. | ||
590 | */ | ||
591 | debugfs_create_file("link_speed", S_IRUGO, | ||
592 | g->debugfs_xve, g, | ||
593 | &xve_link_speed_fops); | ||
594 | debugfs_create_file("available_speeds", S_IRUGO, | ||
595 | g->debugfs_xve, g, | ||
596 | &xve_available_speeds_fops); | ||
597 | debugfs_create_file("link_control_status", S_IRUGO, | ||
598 | g->debugfs_xve, g, | ||
599 | &xve_link_control_status_fops); | ||
600 | |||
601 | err = 0; | ||
602 | fail: | ||
603 | return err; | ||
604 | #else | ||
605 | return err; | ||
606 | #endif | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * Init the HAL functions and what not. xve_sw_init_gp106() is for initializing | ||
611 | * all the other stuff like debugfs nodes, etc. | ||
612 | */ | ||
613 | int gp106_init_xve_ops(struct gpu_ops *gops) | ||
614 | { | ||
615 | gops->xve.sw_init = xve_sw_init_gp106; | ||
616 | gops->xve.get_speed = xve_get_speed_gp106; | ||
617 | gops->xve.set_speed = xve_set_speed_gp106; | ||
618 | gops->xve.available_speeds = xve_available_speeds_gp106; | ||
619 | gops->xve.xve_readl = xve_xve_readl_gp106; | ||
620 | gops->xve.xve_writel = xve_xve_writel_gp106; | ||
621 | |||
622 | return 0; | ||
623 | } | ||
diff --git a/drivers/gpu/nvgpu/gp106/xve_gp106.h b/drivers/gpu/nvgpu/gp106/xve_gp106.h new file mode 100644 index 00000000..65c75bf0 --- /dev/null +++ b/drivers/gpu/nvgpu/gp106/xve_gp106.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
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, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __XVE_GP106_H__ | ||
18 | #define __XVE_GP106_H__ | ||
19 | |||
20 | #include "gk20a/gk20a.h" | ||
21 | |||
22 | int gp106_init_xve_ops(struct gpu_ops *gops); | ||
23 | |||
24 | /* | ||
25 | * Best guess for a reasonable timeout. | ||
26 | */ | ||
27 | #define GPU_XVE_TIMEOUT_MS 500 | ||
28 | |||
29 | /* | ||
30 | * For the available speeds bitmap. | ||
31 | */ | ||
32 | #define GPU_XVE_SPEED_2P5 (1 << 0) | ||
33 | #define GPU_XVE_SPEED_5P0 (1 << 1) | ||
34 | #define GPU_XVE_SPEED_8P0 (1 << 2) | ||
35 | #define GPU_XVE_NR_SPEEDS 3 | ||
36 | |||
37 | #define GPU_XVE_SPEED_MASK (GPU_XVE_SPEED_2P5 | \ | ||
38 | GPU_XVE_SPEED_5P0 | \ | ||
39 | GPU_XVE_SPEED_8P0) | ||
40 | |||
41 | /* | ||
42 | * The HW uses a 2 bit field where speed is defined by a number: | ||
43 | * | ||
44 | * NV_XVE_LINK_CONTROL_STATUS_LINK_SPEED_2P5 = 1 | ||
45 | * NV_XVE_LINK_CONTROL_STATUS_LINK_SPEED_5P0 = 2 | ||
46 | * NV_XVE_LINK_CONTROL_STATUS_LINK_SPEED_8P0 = 3 | ||
47 | * | ||
48 | * This isn't ideal for a bitmap with available speeds. So the external | ||
49 | * APIs think about speeds as a bit in a bitmap and this function converts | ||
50 | * from those bits to the actual HW speed setting. | ||
51 | * | ||
52 | * @speed_bit must have only 1 bit set and must be one of the 3 available | ||
53 | * HW speeds. Not all chips support all speeds so use available_speeds() to | ||
54 | * determine what a given chip supports. | ||
55 | */ | ||
56 | static inline u32 xve_speed_to_hw_speed_setting(u32 speed_bit) | ||
57 | { | ||
58 | if (!speed_bit || | ||
59 | !is_power_of_2(speed_bit) || | ||
60 | !(speed_bit & GPU_XVE_SPEED_MASK)) | ||
61 | return -EINVAL; | ||
62 | |||
63 | return ilog2(speed_bit) + 1; | ||
64 | } | ||
65 | |||
66 | static inline const char *xve_speed_to_str(u32 speed) | ||
67 | { | ||
68 | if (!speed || !is_power_of_2(speed) || | ||
69 | !(speed & GPU_XVE_SPEED_MASK)) | ||
70 | return "Unknown ???"; | ||
71 | |||
72 | return speed & GPU_XVE_SPEED_2P5 ? "Gen1" : | ||
73 | speed & GPU_XVE_SPEED_5P0 ? "Gen2" : | ||
74 | speed & GPU_XVE_SPEED_8P0 ? "Gen3" : | ||
75 | "Unknown ???"; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Debugging for the speed change. | ||
80 | */ | ||
81 | enum xv_speed_change_steps { | ||
82 | PRE_CHANGE = 0, | ||
83 | DISABLE_ASPM, | ||
84 | DL_SAFE_MODE, | ||
85 | CHECK_LINK, | ||
86 | LINK_SETTINGS, | ||
87 | EXEC_CHANGE, | ||
88 | EXEC_VERIF, | ||
89 | CLEANUP | ||
90 | }; | ||
91 | |||
92 | #define xv_dbg(fmt, args...) \ | ||
93 | gk20a_dbg(gpu_dbg_xv, fmt, ##args) | ||
94 | |||
95 | #define xv_sc_dbg(step, fmt, args...) \ | ||
96 | xv_dbg("[%d] %15s | " fmt, step, __stringify(step), ##args) | ||
97 | |||
98 | |||
99 | #endif | ||