summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gp106/xve_gp106.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gp106/xve_gp106.c')
-rw-r--r--drivers/gpu/nvgpu/gp106/xve_gp106.c623
1 files changed, 623 insertions, 0 deletions
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 */
31static 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 */
40static 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
51static void xve_xve_writel_gp106(struct gk20a *g, u32 reg, u32 val)
52{
53 gk20a_writel(g, NV_PCFG + reg, val);
54}
55
56static 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 */
72static 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 */
107static 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 */
127static 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 */
144static 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 */
163static 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 */
172static 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, &current_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
402done:
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 */
424static 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, &current_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 */
446static 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
451static 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
494static 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
509static 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
514static 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
522static 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
540static 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
545static 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
552static 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
563static 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
568static 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
575static 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;
602fail:
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 */
613int 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}