diff options
Diffstat (limited to 'include/os/linux/pci.c')
-rw-r--r-- | include/os/linux/pci.c | 854 |
1 files changed, 0 insertions, 854 deletions
diff --git a/include/os/linux/pci.c b/include/os/linux/pci.c deleted file mode 100644 index 07071d1..0000000 --- a/include/os/linux/pci.c +++ /dev/null | |||
@@ -1,854 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016-2018, 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/pci.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | #include <linux/of_platform.h> | ||
21 | #include <linux/of_address.h> | ||
22 | |||
23 | #include <nvgpu/nvhost.h> | ||
24 | #include <nvgpu/nvgpu_common.h> | ||
25 | #include <nvgpu/kmem.h> | ||
26 | #include <nvgpu/enabled.h> | ||
27 | #include <nvgpu/nvlink.h> | ||
28 | #include <nvgpu/soc.h> | ||
29 | #include <nvgpu/sim.h> | ||
30 | #include <nvgpu/gk20a.h> | ||
31 | |||
32 | #include "nvlink.h" | ||
33 | #include "clk/clk.h" | ||
34 | #include "clk/clk_mclk.h" | ||
35 | #include "module.h" | ||
36 | #include "intr.h" | ||
37 | #include "sysfs.h" | ||
38 | #include "os_linux.h" | ||
39 | #include "platform_gk20a.h" | ||
40 | |||
41 | #include "pci.h" | ||
42 | #include "pci_usermode.h" | ||
43 | |||
44 | #include "driver_common.h" | ||
45 | |||
46 | #define PCI_INTERFACE_NAME "card-%s%%s" | ||
47 | |||
48 | static int nvgpu_pci_tegra_probe(struct device *dev) | ||
49 | { | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int nvgpu_pci_tegra_remove(struct device *dev) | ||
54 | { | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static bool nvgpu_pci_tegra_is_railgated(struct device *pdev) | ||
59 | { | ||
60 | return false; | ||
61 | } | ||
62 | |||
63 | static long nvgpu_pci_clk_round_rate(struct device *dev, unsigned long rate) | ||
64 | { | ||
65 | long ret = (long)rate; | ||
66 | |||
67 | if (rate == UINT_MAX) | ||
68 | ret = BOOT_GPC2CLK_MHZ * 1000000UL; | ||
69 | |||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static struct gk20a_platform nvgpu_pci_device[] = { | ||
74 | { /* DEVICE=0x1c35 */ | ||
75 | /* ptimer src frequency in hz */ | ||
76 | .ptimer_src_freq = 31250000, | ||
77 | |||
78 | .probe = nvgpu_pci_tegra_probe, | ||
79 | .remove = nvgpu_pci_tegra_remove, | ||
80 | |||
81 | /* power management configuration */ | ||
82 | .railgate_delay_init = 500, | ||
83 | .can_railgate_init = false, | ||
84 | .can_elpg_init = true, | ||
85 | .enable_elpg = true, | ||
86 | .enable_elcg = false, | ||
87 | .enable_slcg = true, | ||
88 | .enable_blcg = true, | ||
89 | .enable_mscg = true, | ||
90 | .can_slcg = true, | ||
91 | .can_blcg = true, | ||
92 | .can_elcg = true, | ||
93 | |||
94 | .disable_aspm = true, | ||
95 | |||
96 | /* power management callbacks */ | ||
97 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
98 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
99 | |||
100 | .ch_wdt_timeout_ms = 7000, | ||
101 | |||
102 | .honors_aperture = true, | ||
103 | .dma_mask = DMA_BIT_MASK(40), | ||
104 | .vbios_min_version = 0x86063000, | ||
105 | .hardcode_sw_threshold = true, | ||
106 | .ina3221_dcb_index = 0, | ||
107 | .ina3221_i2c_address = 0x84, | ||
108 | .ina3221_i2c_port = 0x2, | ||
109 | }, | ||
110 | { /* DEVICE=0x1c36 */ | ||
111 | /* ptimer src frequency in hz */ | ||
112 | .ptimer_src_freq = 31250000, | ||
113 | |||
114 | .probe = nvgpu_pci_tegra_probe, | ||
115 | .remove = nvgpu_pci_tegra_remove, | ||
116 | |||
117 | /* power management configuration */ | ||
118 | .railgate_delay_init = 500, | ||
119 | .can_railgate_init = false, | ||
120 | .can_elpg_init = true, | ||
121 | .enable_elpg = true, | ||
122 | .enable_elcg = false, | ||
123 | .enable_slcg = true, | ||
124 | .enable_blcg = true, | ||
125 | .enable_mscg = true, | ||
126 | .can_slcg = true, | ||
127 | .can_blcg = true, | ||
128 | .can_elcg = true, | ||
129 | |||
130 | .disable_aspm = true, | ||
131 | |||
132 | /* power management callbacks */ | ||
133 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
134 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
135 | |||
136 | .ch_wdt_timeout_ms = 7000, | ||
137 | |||
138 | .honors_aperture = true, | ||
139 | .dma_mask = DMA_BIT_MASK(40), | ||
140 | .vbios_min_version = 0x86062d00, | ||
141 | .hardcode_sw_threshold = true, | ||
142 | .ina3221_dcb_index = 0, | ||
143 | .ina3221_i2c_address = 0x84, | ||
144 | .ina3221_i2c_port = 0x2, | ||
145 | }, | ||
146 | { /* DEVICE=0x1c37 */ | ||
147 | /* ptimer src frequency in hz */ | ||
148 | .ptimer_src_freq = 31250000, | ||
149 | |||
150 | .probe = nvgpu_pci_tegra_probe, | ||
151 | .remove = nvgpu_pci_tegra_remove, | ||
152 | |||
153 | /* power management configuration */ | ||
154 | .railgate_delay_init = 500, | ||
155 | .can_railgate_init = false, | ||
156 | .can_elpg_init = true, | ||
157 | .enable_elpg = true, | ||
158 | .enable_elcg = false, | ||
159 | .enable_slcg = true, | ||
160 | .enable_blcg = true, | ||
161 | .enable_mscg = true, | ||
162 | .can_slcg = true, | ||
163 | .can_blcg = true, | ||
164 | .can_elcg = true, | ||
165 | |||
166 | .disable_aspm = true, | ||
167 | |||
168 | /* power management callbacks */ | ||
169 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
170 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
171 | |||
172 | .ch_wdt_timeout_ms = 7000, | ||
173 | |||
174 | .honors_aperture = true, | ||
175 | .dma_mask = DMA_BIT_MASK(40), | ||
176 | .vbios_min_version = 0x86063000, | ||
177 | .hardcode_sw_threshold = true, | ||
178 | .ina3221_dcb_index = 0, | ||
179 | .ina3221_i2c_address = 0x84, | ||
180 | .ina3221_i2c_port = 0x2, | ||
181 | }, | ||
182 | { /* DEVICE=0x1c75 */ | ||
183 | /* ptimer src frequency in hz */ | ||
184 | .ptimer_src_freq = 31250000, | ||
185 | |||
186 | .probe = nvgpu_pci_tegra_probe, | ||
187 | .remove = nvgpu_pci_tegra_remove, | ||
188 | |||
189 | /* power management configuration */ | ||
190 | .railgate_delay_init = 500, | ||
191 | .can_railgate_init = false, | ||
192 | .can_elpg_init = true, | ||
193 | .enable_elpg = true, | ||
194 | .enable_elcg = false, | ||
195 | .enable_slcg = true, | ||
196 | .enable_blcg = true, | ||
197 | .enable_mscg = true, | ||
198 | .can_slcg = true, | ||
199 | .can_blcg = true, | ||
200 | .can_elcg = true, | ||
201 | |||
202 | .disable_aspm = true, | ||
203 | |||
204 | /* power management callbacks */ | ||
205 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
206 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
207 | |||
208 | .ch_wdt_timeout_ms = 7000, | ||
209 | |||
210 | .honors_aperture = true, | ||
211 | .dma_mask = DMA_BIT_MASK(40), | ||
212 | .vbios_min_version = 0x86065300, | ||
213 | .hardcode_sw_threshold = false, | ||
214 | .ina3221_dcb_index = 1, | ||
215 | .ina3221_i2c_address = 0x80, | ||
216 | .ina3221_i2c_port = 0x1, | ||
217 | }, | ||
218 | { /* DEVICE=PG503 SKU 201 */ | ||
219 | /* ptimer src frequency in hz */ | ||
220 | .ptimer_src_freq = 31250000, | ||
221 | |||
222 | .probe = nvgpu_pci_tegra_probe, | ||
223 | .remove = nvgpu_pci_tegra_remove, | ||
224 | |||
225 | /* power management configuration */ | ||
226 | .railgate_delay_init = 500, | ||
227 | .can_railgate_init = false, | ||
228 | .can_elpg_init = false, | ||
229 | .enable_elpg = false, | ||
230 | .enable_elcg = false, | ||
231 | .enable_slcg = false, | ||
232 | .enable_blcg = false, | ||
233 | .enable_mscg = false, | ||
234 | .can_slcg = false, | ||
235 | .can_blcg = false, | ||
236 | .can_elcg = false, | ||
237 | |||
238 | .disable_aspm = true, | ||
239 | |||
240 | /* power management callbacks */ | ||
241 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
242 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
243 | |||
244 | .ch_wdt_timeout_ms = 7000, | ||
245 | |||
246 | .honors_aperture = true, | ||
247 | .dma_mask = DMA_BIT_MASK(40), | ||
248 | .vbios_min_version = 0x88001e00, | ||
249 | .hardcode_sw_threshold = false, | ||
250 | .run_preos = true, | ||
251 | }, | ||
252 | { /* DEVICE=PG503 SKU 200 ES */ | ||
253 | /* ptimer src frequency in hz */ | ||
254 | .ptimer_src_freq = 31250000, | ||
255 | |||
256 | .probe = nvgpu_pci_tegra_probe, | ||
257 | .remove = nvgpu_pci_tegra_remove, | ||
258 | |||
259 | /* power management configuration */ | ||
260 | .railgate_delay_init = 500, | ||
261 | .can_railgate_init = false, | ||
262 | .can_elpg_init = false, | ||
263 | .enable_elpg = false, | ||
264 | .enable_elcg = false, | ||
265 | .enable_slcg = false, | ||
266 | .enable_blcg = false, | ||
267 | .enable_mscg = false, | ||
268 | .can_slcg = false, | ||
269 | .can_blcg = false, | ||
270 | .can_elcg = false, | ||
271 | |||
272 | .disable_aspm = true, | ||
273 | |||
274 | /* power management callbacks */ | ||
275 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
276 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
277 | |||
278 | .ch_wdt_timeout_ms = 7000, | ||
279 | |||
280 | .honors_aperture = true, | ||
281 | .dma_mask = DMA_BIT_MASK(40), | ||
282 | .vbios_min_version = 0x88001e00, | ||
283 | .hardcode_sw_threshold = false, | ||
284 | .run_preos = true, | ||
285 | }, | ||
286 | { | ||
287 | /* ptimer src frequency in hz */ | ||
288 | .ptimer_src_freq = 31250000, | ||
289 | |||
290 | .probe = nvgpu_pci_tegra_probe, | ||
291 | .remove = nvgpu_pci_tegra_remove, | ||
292 | |||
293 | /* power management configuration */ | ||
294 | .railgate_delay_init = 500, | ||
295 | .can_railgate_init = false, | ||
296 | .can_elpg_init = false, | ||
297 | .enable_elpg = false, | ||
298 | .enable_elcg = false, | ||
299 | .enable_slcg = false, | ||
300 | .enable_blcg = false, | ||
301 | .enable_mscg = false, | ||
302 | .can_slcg = false, | ||
303 | .can_blcg = false, | ||
304 | .can_elcg = false, | ||
305 | |||
306 | .disable_aspm = true, | ||
307 | |||
308 | /* power management callbacks */ | ||
309 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
310 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
311 | |||
312 | .ch_wdt_timeout_ms = 7000, | ||
313 | |||
314 | .honors_aperture = true, | ||
315 | .dma_mask = DMA_BIT_MASK(40), | ||
316 | .vbios_min_version = 0x88000126, | ||
317 | .hardcode_sw_threshold = false, | ||
318 | .run_preos = true, | ||
319 | .has_syncpoints = true, | ||
320 | }, | ||
321 | { /* SKU250 */ | ||
322 | /* ptimer src frequency in hz */ | ||
323 | .ptimer_src_freq = 31250000, | ||
324 | |||
325 | .probe = nvgpu_pci_tegra_probe, | ||
326 | .remove = nvgpu_pci_tegra_remove, | ||
327 | |||
328 | /* power management configuration */ | ||
329 | .railgate_delay_init = 500, | ||
330 | .can_railgate_init = false, | ||
331 | .can_elpg_init = false, | ||
332 | .enable_elpg = false, | ||
333 | .enable_elcg = false, | ||
334 | .enable_slcg = true, | ||
335 | .enable_blcg = true, | ||
336 | .enable_mscg = false, | ||
337 | .can_slcg = true, | ||
338 | .can_blcg = true, | ||
339 | .can_elcg = false, | ||
340 | |||
341 | .disable_aspm = true, | ||
342 | |||
343 | /* power management callbacks */ | ||
344 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
345 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
346 | |||
347 | .ch_wdt_timeout_ms = 7000, | ||
348 | |||
349 | .honors_aperture = true, | ||
350 | .dma_mask = DMA_BIT_MASK(40), | ||
351 | .vbios_min_version = 0x1, | ||
352 | .hardcode_sw_threshold = false, | ||
353 | .run_preos = true, | ||
354 | .has_syncpoints = true, | ||
355 | }, | ||
356 | { /* SKU 0x1e3f */ | ||
357 | /* ptimer src frequency in hz */ | ||
358 | .ptimer_src_freq = 31250000, | ||
359 | |||
360 | .probe = nvgpu_pci_tegra_probe, | ||
361 | .remove = nvgpu_pci_tegra_remove, | ||
362 | |||
363 | /* power management configuration */ | ||
364 | .railgate_delay_init = 500, | ||
365 | .can_railgate_init = false, | ||
366 | .can_elpg_init = false, | ||
367 | .enable_elpg = false, | ||
368 | .enable_elcg = false, | ||
369 | .enable_slcg = false, | ||
370 | .enable_blcg = false, | ||
371 | .enable_mscg = false, | ||
372 | .can_slcg = false, | ||
373 | .can_blcg = false, | ||
374 | .can_elcg = false, | ||
375 | |||
376 | .disable_aspm = true, | ||
377 | |||
378 | /* power management callbacks */ | ||
379 | .is_railgated = nvgpu_pci_tegra_is_railgated, | ||
380 | .clk_round_rate = nvgpu_pci_clk_round_rate, | ||
381 | |||
382 | /* | ||
383 | * WAR: PCIE X1 is very slow, set to very high value till nvlink is up | ||
384 | */ | ||
385 | .ch_wdt_timeout_ms = 30000, | ||
386 | |||
387 | .honors_aperture = true, | ||
388 | .dma_mask = DMA_BIT_MASK(40), | ||
389 | .vbios_min_version = 0x1, | ||
390 | .hardcode_sw_threshold = false, | ||
391 | .unified_memory = false, | ||
392 | }, | ||
393 | |||
394 | }; | ||
395 | |||
396 | static struct pci_device_id nvgpu_pci_table[] = { | ||
397 | { | ||
398 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1c35), | ||
399 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
400 | .class_mask = 0xff << 16, | ||
401 | .driver_data = 0, | ||
402 | }, | ||
403 | { | ||
404 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1c36), | ||
405 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
406 | .class_mask = 0xff << 16, | ||
407 | .driver_data = 1, | ||
408 | }, | ||
409 | { | ||
410 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1c37), | ||
411 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
412 | .class_mask = 0xff << 16, | ||
413 | .driver_data = 2, | ||
414 | }, | ||
415 | { | ||
416 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1c75), | ||
417 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
418 | .class_mask = 0xff << 16, | ||
419 | .driver_data = 3, | ||
420 | }, | ||
421 | { | ||
422 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1db1), | ||
423 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
424 | .class_mask = 0xff << 16, | ||
425 | .driver_data = 4, | ||
426 | }, | ||
427 | { | ||
428 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1db0), | ||
429 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
430 | .class_mask = 0xff << 16, | ||
431 | .driver_data = 5, | ||
432 | }, | ||
433 | { | ||
434 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1dbe), | ||
435 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
436 | .class_mask = 0xff << 16, | ||
437 | .driver_data = 6, | ||
438 | }, | ||
439 | { | ||
440 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1df1), | ||
441 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
442 | .class_mask = 0xff << 16, | ||
443 | .driver_data = 7, | ||
444 | }, | ||
445 | { | ||
446 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x1e3f), | ||
447 | .class = PCI_BASE_CLASS_DISPLAY << 16, | ||
448 | .class_mask = 0xff << 16, | ||
449 | .driver_data = 8, | ||
450 | }, | ||
451 | {} | ||
452 | }; | ||
453 | |||
454 | static irqreturn_t nvgpu_pci_isr(int irq, void *dev_id) | ||
455 | { | ||
456 | struct gk20a *g = dev_id; | ||
457 | irqreturn_t ret_stall; | ||
458 | irqreturn_t ret_nonstall; | ||
459 | |||
460 | ret_stall = nvgpu_intr_stall(g); | ||
461 | ret_nonstall = nvgpu_intr_nonstall(g); | ||
462 | |||
463 | #if defined(CONFIG_PCI_MSI) | ||
464 | /* Send MSI EOI */ | ||
465 | if (g->ops.xve.rearm_msi && g->msi_enabled) | ||
466 | g->ops.xve.rearm_msi(g); | ||
467 | #endif | ||
468 | |||
469 | return (ret_stall == IRQ_NONE) ? ret_nonstall : IRQ_WAKE_THREAD; | ||
470 | } | ||
471 | |||
472 | static irqreturn_t nvgpu_pci_intr_thread(int irq, void *dev_id) | ||
473 | { | ||
474 | struct gk20a *g = dev_id; | ||
475 | |||
476 | return nvgpu_intr_thread_stall(g); | ||
477 | } | ||
478 | |||
479 | static int nvgpu_pci_init_support(struct pci_dev *pdev) | ||
480 | { | ||
481 | int err = 0; | ||
482 | struct gk20a *g = get_gk20a(&pdev->dev); | ||
483 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
484 | struct device *dev = &pdev->dev; | ||
485 | |||
486 | l->regs = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 0), | ||
487 | pci_resource_len(pdev, 0)); | ||
488 | if (IS_ERR(l->regs)) { | ||
489 | nvgpu_err(g, "failed to remap gk20a registers"); | ||
490 | err = PTR_ERR(l->regs); | ||
491 | goto fail; | ||
492 | } | ||
493 | |||
494 | l->regs_bus_addr = pci_resource_start(pdev, 0); | ||
495 | if (!l->regs_bus_addr) { | ||
496 | nvgpu_err(g, "failed to read register bus offset"); | ||
497 | err = -ENODEV; | ||
498 | goto fail; | ||
499 | } | ||
500 | |||
501 | l->bar1 = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 1), | ||
502 | pci_resource_len(pdev, 1)); | ||
503 | if (IS_ERR(l->bar1)) { | ||
504 | nvgpu_err(g, "failed to remap gk20a bar1"); | ||
505 | err = PTR_ERR(l->bar1); | ||
506 | goto fail; | ||
507 | } | ||
508 | |||
509 | err = nvgpu_init_sim_support_linux_pci(g); | ||
510 | if (err) | ||
511 | goto fail; | ||
512 | err = nvgpu_init_sim_support_pci(g); | ||
513 | if (err) | ||
514 | goto fail_sim; | ||
515 | |||
516 | nvgpu_pci_init_usermode_support(l); | ||
517 | |||
518 | return 0; | ||
519 | |||
520 | fail_sim: | ||
521 | nvgpu_remove_sim_support_linux_pci(g); | ||
522 | fail: | ||
523 | if (l->regs) | ||
524 | l->regs = NULL; | ||
525 | |||
526 | if (l->bar1) | ||
527 | l->bar1 = NULL; | ||
528 | |||
529 | return err; | ||
530 | } | ||
531 | |||
532 | static char *nvgpu_pci_devnode(struct device *dev, umode_t *mode) | ||
533 | { | ||
534 | if (mode) | ||
535 | *mode = S_IRUGO | S_IWUGO; | ||
536 | return kasprintf(GFP_KERNEL, "nvgpu-pci/%s", dev_name(dev)); | ||
537 | } | ||
538 | |||
539 | static struct class nvgpu_pci_class = { | ||
540 | .owner = THIS_MODULE, | ||
541 | .name = "nvidia-pci-gpu", | ||
542 | .devnode = nvgpu_pci_devnode, | ||
543 | }; | ||
544 | |||
545 | #ifdef CONFIG_PM | ||
546 | static int nvgpu_pci_pm_runtime_resume(struct device *dev) | ||
547 | { | ||
548 | return gk20a_pm_finalize_poweron(dev); | ||
549 | } | ||
550 | |||
551 | static int nvgpu_pci_pm_runtime_suspend(struct device *dev) | ||
552 | { | ||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | static int nvgpu_pci_pm_resume(struct device *dev) | ||
557 | { | ||
558 | return gk20a_pm_finalize_poweron(dev); | ||
559 | } | ||
560 | |||
561 | static int nvgpu_pci_pm_suspend(struct device *dev) | ||
562 | { | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static const struct dev_pm_ops nvgpu_pci_pm_ops = { | ||
567 | .runtime_resume = nvgpu_pci_pm_runtime_resume, | ||
568 | .runtime_suspend = nvgpu_pci_pm_runtime_suspend, | ||
569 | .resume = nvgpu_pci_pm_resume, | ||
570 | .suspend = nvgpu_pci_pm_suspend, | ||
571 | }; | ||
572 | #endif | ||
573 | |||
574 | static int nvgpu_pci_pm_init(struct device *dev) | ||
575 | { | ||
576 | #ifdef CONFIG_PM | ||
577 | struct gk20a *g = get_gk20a(dev); | ||
578 | |||
579 | if (!nvgpu_is_enabled(g, NVGPU_CAN_RAILGATE)) { | ||
580 | pm_runtime_disable(dev); | ||
581 | } else { | ||
582 | if (g->railgate_delay) | ||
583 | pm_runtime_set_autosuspend_delay(dev, | ||
584 | g->railgate_delay); | ||
585 | |||
586 | /* | ||
587 | * set gpu dev's use_autosuspend flag to allow | ||
588 | * runtime power management of GPU | ||
589 | */ | ||
590 | pm_runtime_use_autosuspend(dev); | ||
591 | |||
592 | /* | ||
593 | * runtime PM for PCI devices is forbidden | ||
594 | * by default, so unblock RTPM of GPU | ||
595 | */ | ||
596 | pm_runtime_put_noidle(dev); | ||
597 | pm_runtime_allow(dev); | ||
598 | } | ||
599 | #endif | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int nvgpu_pci_pm_deinit(struct device *dev) | ||
604 | { | ||
605 | #ifdef CONFIG_PM | ||
606 | struct gk20a *g = get_gk20a(dev); | ||
607 | |||
608 | if (!nvgpu_is_enabled(g, NVGPU_CAN_RAILGATE)) | ||
609 | pm_runtime_enable(dev); | ||
610 | else | ||
611 | pm_runtime_forbid(dev); | ||
612 | #endif | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static int nvgpu_pci_probe(struct pci_dev *pdev, | ||
617 | const struct pci_device_id *pent) | ||
618 | { | ||
619 | struct gk20a_platform *platform = NULL; | ||
620 | struct nvgpu_os_linux *l; | ||
621 | struct gk20a *g; | ||
622 | int err; | ||
623 | char nodefmt[64]; | ||
624 | struct device_node *np; | ||
625 | |||
626 | /* make sure driver_data is a sane index */ | ||
627 | if (pent->driver_data >= sizeof(nvgpu_pci_device) / | ||
628 | sizeof(nvgpu_pci_device[0])) { | ||
629 | return -EINVAL; | ||
630 | } | ||
631 | |||
632 | l = kzalloc(sizeof(*l), GFP_KERNEL); | ||
633 | if (!l) { | ||
634 | dev_err(&pdev->dev, "couldn't allocate gk20a support"); | ||
635 | return -ENOMEM; | ||
636 | } | ||
637 | |||
638 | hash_init(l->ecc_sysfs_stats_htable); | ||
639 | |||
640 | g = &l->g; | ||
641 | |||
642 | g->log_mask = NVGPU_DEFAULT_DBG_MASK; | ||
643 | |||
644 | nvgpu_init_gk20a(g); | ||
645 | |||
646 | nvgpu_kmem_init(g); | ||
647 | |||
648 | /* Allocate memory to hold platform data*/ | ||
649 | platform = (struct gk20a_platform *)nvgpu_kzalloc( g, | ||
650 | sizeof(struct gk20a_platform)); | ||
651 | if (!platform) { | ||
652 | dev_err(&pdev->dev, "couldn't allocate platform data"); | ||
653 | err = -ENOMEM; | ||
654 | goto err_free_l; | ||
655 | } | ||
656 | |||
657 | /* copy detected device data to allocated platform space*/ | ||
658 | memcpy((void *)platform, (void *)&nvgpu_pci_device[pent->driver_data], | ||
659 | sizeof(struct gk20a_platform)); | ||
660 | |||
661 | pci_set_drvdata(pdev, platform); | ||
662 | |||
663 | err = nvgpu_init_enabled_flags(g); | ||
664 | if (err) | ||
665 | goto err_free_platform; | ||
666 | |||
667 | platform->g = g; | ||
668 | l->dev = &pdev->dev; | ||
669 | |||
670 | np = nvgpu_get_node(g); | ||
671 | if (of_dma_is_coherent(np)) { | ||
672 | __nvgpu_set_enabled(g, NVGPU_USE_COHERENT_SYSMEM, true); | ||
673 | __nvgpu_set_enabled(g, NVGPU_SUPPORT_IO_COHERENCE, true); | ||
674 | } | ||
675 | |||
676 | err = pci_enable_device(pdev); | ||
677 | if (err) | ||
678 | goto err_free_platform; | ||
679 | pci_set_master(pdev); | ||
680 | |||
681 | g->pci_vendor_id = pdev->vendor; | ||
682 | g->pci_device_id = pdev->device; | ||
683 | g->pci_subsystem_vendor_id = pdev->subsystem_vendor; | ||
684 | g->pci_subsystem_device_id = pdev->subsystem_device; | ||
685 | g->pci_class = (pdev->class >> 8) & 0xFFFFU; // we only want base/sub | ||
686 | g->pci_revision = pdev->revision; | ||
687 | |||
688 | g->ina3221_dcb_index = platform->ina3221_dcb_index; | ||
689 | g->ina3221_i2c_address = platform->ina3221_i2c_address; | ||
690 | g->ina3221_i2c_port = platform->ina3221_i2c_port; | ||
691 | g->hardcode_sw_threshold = platform->hardcode_sw_threshold; | ||
692 | |||
693 | #if defined(CONFIG_PCI_MSI) | ||
694 | err = pci_enable_msi(pdev); | ||
695 | if (err) { | ||
696 | nvgpu_err(g, | ||
697 | "MSI could not be enabled, falling back to legacy"); | ||
698 | g->msi_enabled = false; | ||
699 | } else | ||
700 | g->msi_enabled = true; | ||
701 | #endif | ||
702 | |||
703 | g->irq_stall = pdev->irq; | ||
704 | g->irq_nonstall = pdev->irq; | ||
705 | if (g->irq_stall < 0) { | ||
706 | err = -ENXIO; | ||
707 | goto err_disable_msi; | ||
708 | } | ||
709 | |||
710 | err = devm_request_threaded_irq(&pdev->dev, | ||
711 | g->irq_stall, | ||
712 | nvgpu_pci_isr, | ||
713 | nvgpu_pci_intr_thread, | ||
714 | #if defined(CONFIG_PCI_MSI) | ||
715 | g->msi_enabled ? 0 : | ||
716 | #endif | ||
717 | IRQF_SHARED, "nvgpu", g); | ||
718 | if (err) { | ||
719 | nvgpu_err(g, | ||
720 | "failed to request irq @ %d", g->irq_stall); | ||
721 | goto err_disable_msi; | ||
722 | } | ||
723 | disable_irq(g->irq_stall); | ||
724 | |||
725 | err = nvgpu_pci_init_support(pdev); | ||
726 | if (err) | ||
727 | goto err_free_irq; | ||
728 | |||
729 | if (strchr(dev_name(&pdev->dev), '%')) { | ||
730 | nvgpu_err(g, "illegal character in device name"); | ||
731 | err = -EINVAL; | ||
732 | goto err_free_irq; | ||
733 | } | ||
734 | |||
735 | snprintf(nodefmt, sizeof(nodefmt), | ||
736 | PCI_INTERFACE_NAME, dev_name(&pdev->dev)); | ||
737 | |||
738 | err = nvgpu_probe(g, "gpu_pci", nodefmt, &nvgpu_pci_class); | ||
739 | if (err) | ||
740 | goto err_free_irq; | ||
741 | |||
742 | err = nvgpu_pci_pm_init(&pdev->dev); | ||
743 | if (err) { | ||
744 | nvgpu_err(g, "pm init failed"); | ||
745 | goto err_free_irq; | ||
746 | } | ||
747 | |||
748 | err = nvgpu_nvlink_probe(g); | ||
749 | /* | ||
750 | * ENODEV is a legal error which means there is no NVLINK | ||
751 | * any other error is fatal | ||
752 | */ | ||
753 | if (err) { | ||
754 | if (err != -ENODEV) { | ||
755 | nvgpu_err(g, "fatal error probing nvlink, bailing out"); | ||
756 | goto err_free_irq; | ||
757 | } | ||
758 | /* Enable Semaphore SHIM on nvlink only for now. */ | ||
759 | __nvgpu_set_enabled(g, NVGPU_SUPPORT_NVLINK, false); | ||
760 | __nvgpu_set_enabled(g, NVGPU_HAS_SYNCPOINTS, false); | ||
761 | } else { | ||
762 | err = nvgpu_nvhost_syncpt_init(g); | ||
763 | if (err) { | ||
764 | if (err != -ENOSYS) { | ||
765 | nvgpu_err(g, "syncpt init failed"); | ||
766 | goto err_free_irq; | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | |||
771 | return 0; | ||
772 | |||
773 | err_free_irq: | ||
774 | nvgpu_free_irq(g); | ||
775 | err_disable_msi: | ||
776 | #if defined(CONFIG_PCI_MSI) | ||
777 | if (g->msi_enabled) | ||
778 | pci_disable_msi(pdev); | ||
779 | #endif | ||
780 | err_free_platform: | ||
781 | nvgpu_kfree(g, platform); | ||
782 | err_free_l: | ||
783 | kfree(l); | ||
784 | return err; | ||
785 | } | ||
786 | |||
787 | static void nvgpu_pci_remove(struct pci_dev *pdev) | ||
788 | { | ||
789 | struct gk20a *g = get_gk20a(&pdev->dev); | ||
790 | struct device *dev = dev_from_gk20a(g); | ||
791 | int err; | ||
792 | |||
793 | /* no support yet for unbind if DGPU is in VGPU mode */ | ||
794 | if (gk20a_gpu_is_virtual(dev)) | ||
795 | return; | ||
796 | |||
797 | err = nvgpu_nvlink_deinit(g); | ||
798 | WARN(err, "gpu failed to remove nvlink"); | ||
799 | |||
800 | gk20a_driver_start_unload(g); | ||
801 | |||
802 | err = nvgpu_quiesce(g); | ||
803 | /* TODO: handle failure to idle */ | ||
804 | WARN(err, "gpu failed to idle during driver removal"); | ||
805 | |||
806 | nvgpu_free_irq(g); | ||
807 | |||
808 | nvgpu_remove(dev, &nvgpu_pci_class); | ||
809 | |||
810 | #if defined(CONFIG_PCI_MSI) | ||
811 | if (g->msi_enabled) | ||
812 | pci_disable_msi(pdev); | ||
813 | else { | ||
814 | /* IRQ does not need to be enabled in MSI as the line is not | ||
815 | * shared | ||
816 | */ | ||
817 | enable_irq(g->irq_stall); | ||
818 | } | ||
819 | #endif | ||
820 | nvgpu_pci_pm_deinit(&pdev->dev); | ||
821 | |||
822 | /* free allocated platform data space */ | ||
823 | gk20a_get_platform(&pdev->dev)->g = NULL; | ||
824 | nvgpu_kfree(g, gk20a_get_platform(&pdev->dev)); | ||
825 | |||
826 | gk20a_put(g); | ||
827 | } | ||
828 | |||
829 | static struct pci_driver nvgpu_pci_driver = { | ||
830 | .name = "nvgpu", | ||
831 | .id_table = nvgpu_pci_table, | ||
832 | .probe = nvgpu_pci_probe, | ||
833 | .remove = nvgpu_pci_remove, | ||
834 | #ifdef CONFIG_PM | ||
835 | .driver.pm = &nvgpu_pci_pm_ops, | ||
836 | #endif | ||
837 | }; | ||
838 | |||
839 | int __init nvgpu_pci_init(void) | ||
840 | { | ||
841 | int ret; | ||
842 | |||
843 | ret = class_register(&nvgpu_pci_class); | ||
844 | if (ret) | ||
845 | return ret; | ||
846 | |||
847 | return pci_register_driver(&nvgpu_pci_driver); | ||
848 | } | ||
849 | |||
850 | void __exit nvgpu_pci_exit(void) | ||
851 | { | ||
852 | pci_unregister_driver(&nvgpu_pci_driver); | ||
853 | class_unregister(&nvgpu_pci_class); | ||
854 | } | ||