diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_device.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2021 |
1 files changed, 2021 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c new file mode 100644 index 000000000000..99f158e1baff --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -0,0 +1,2021 @@ | |||
1 | /* | ||
2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
3 | * Copyright 2008 Red Hat Inc. | ||
4 | * Copyright 2009 Jerome Glisse. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in | ||
14 | * all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | * Authors: Dave Airlie | ||
25 | * Alex Deucher | ||
26 | * Jerome Glisse | ||
27 | */ | ||
28 | #include <linux/console.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/debugfs.h> | ||
31 | #include <drm/drmP.h> | ||
32 | #include <drm/drm_crtc_helper.h> | ||
33 | #include <drm/amdgpu_drm.h> | ||
34 | #include <linux/vgaarb.h> | ||
35 | #include <linux/vga_switcheroo.h> | ||
36 | #include <linux/efi.h> | ||
37 | #include "amdgpu.h" | ||
38 | #include "amdgpu_i2c.h" | ||
39 | #include "atom.h" | ||
40 | #include "amdgpu_atombios.h" | ||
41 | #ifdef CONFIG_DRM_AMDGPU_CIK | ||
42 | #include "cik.h" | ||
43 | #endif | ||
44 | #include "vi.h" | ||
45 | #include "bif/bif_4_1_d.h" | ||
46 | |||
47 | static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev); | ||
48 | static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev); | ||
49 | |||
50 | static const char *amdgpu_asic_name[] = { | ||
51 | "BONAIRE", | ||
52 | "KAVERI", | ||
53 | "KABINI", | ||
54 | "HAWAII", | ||
55 | "MULLINS", | ||
56 | "TOPAZ", | ||
57 | "TONGA", | ||
58 | "CARRIZO", | ||
59 | "LAST", | ||
60 | }; | ||
61 | |||
62 | bool amdgpu_device_is_px(struct drm_device *dev) | ||
63 | { | ||
64 | struct amdgpu_device *adev = dev->dev_private; | ||
65 | |||
66 | if (adev->flags & AMDGPU_IS_PX) | ||
67 | return true; | ||
68 | return false; | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * MMIO register access helper functions. | ||
73 | */ | ||
74 | uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, | ||
75 | bool always_indirect) | ||
76 | { | ||
77 | if ((reg * 4) < adev->rmmio_size && !always_indirect) | ||
78 | return readl(((void __iomem *)adev->rmmio) + (reg * 4)); | ||
79 | else { | ||
80 | unsigned long flags; | ||
81 | uint32_t ret; | ||
82 | |||
83 | spin_lock_irqsave(&adev->mmio_idx_lock, flags); | ||
84 | writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4)); | ||
85 | ret = readl(((void __iomem *)adev->rmmio) + (mmMM_DATA * 4)); | ||
86 | spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, | ||
93 | bool always_indirect) | ||
94 | { | ||
95 | if ((reg * 4) < adev->rmmio_size && !always_indirect) | ||
96 | writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | ||
97 | else { | ||
98 | unsigned long flags; | ||
99 | |||
100 | spin_lock_irqsave(&adev->mmio_idx_lock, flags); | ||
101 | writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4)); | ||
102 | writel(v, ((void __iomem *)adev->rmmio) + (mmMM_DATA * 4)); | ||
103 | spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg) | ||
108 | { | ||
109 | if ((reg * 4) < adev->rio_mem_size) | ||
110 | return ioread32(adev->rio_mem + (reg * 4)); | ||
111 | else { | ||
112 | iowrite32((reg * 4), adev->rio_mem + (mmMM_INDEX * 4)); | ||
113 | return ioread32(adev->rio_mem + (mmMM_DATA * 4)); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v) | ||
118 | { | ||
119 | |||
120 | if ((reg * 4) < adev->rio_mem_size) | ||
121 | iowrite32(v, adev->rio_mem + (reg * 4)); | ||
122 | else { | ||
123 | iowrite32((reg * 4), adev->rio_mem + (mmMM_INDEX * 4)); | ||
124 | iowrite32(v, adev->rio_mem + (mmMM_DATA * 4)); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * amdgpu_mm_rdoorbell - read a doorbell dword | ||
130 | * | ||
131 | * @adev: amdgpu_device pointer | ||
132 | * @index: doorbell index | ||
133 | * | ||
134 | * Returns the value in the doorbell aperture at the | ||
135 | * requested doorbell index (CIK). | ||
136 | */ | ||
137 | u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index) | ||
138 | { | ||
139 | if (index < adev->doorbell.num_doorbells) { | ||
140 | return readl(adev->doorbell.ptr + index); | ||
141 | } else { | ||
142 | DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", index); | ||
143 | return 0; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * amdgpu_mm_wdoorbell - write a doorbell dword | ||
149 | * | ||
150 | * @adev: amdgpu_device pointer | ||
151 | * @index: doorbell index | ||
152 | * @v: value to write | ||
153 | * | ||
154 | * Writes @v to the doorbell aperture at the | ||
155 | * requested doorbell index (CIK). | ||
156 | */ | ||
157 | void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v) | ||
158 | { | ||
159 | if (index < adev->doorbell.num_doorbells) { | ||
160 | writel(v, adev->doorbell.ptr + index); | ||
161 | } else { | ||
162 | DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", index); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * amdgpu_invalid_rreg - dummy reg read function | ||
168 | * | ||
169 | * @adev: amdgpu device pointer | ||
170 | * @reg: offset of register | ||
171 | * | ||
172 | * Dummy register read function. Used for register blocks | ||
173 | * that certain asics don't have (all asics). | ||
174 | * Returns the value in the register. | ||
175 | */ | ||
176 | static uint32_t amdgpu_invalid_rreg(struct amdgpu_device *adev, uint32_t reg) | ||
177 | { | ||
178 | DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); | ||
179 | BUG(); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * amdgpu_invalid_wreg - dummy reg write function | ||
185 | * | ||
186 | * @adev: amdgpu device pointer | ||
187 | * @reg: offset of register | ||
188 | * @v: value to write to the register | ||
189 | * | ||
190 | * Dummy register read function. Used for register blocks | ||
191 | * that certain asics don't have (all asics). | ||
192 | */ | ||
193 | static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) | ||
194 | { | ||
195 | DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", | ||
196 | reg, v); | ||
197 | BUG(); | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * amdgpu_block_invalid_rreg - dummy reg read function | ||
202 | * | ||
203 | * @adev: amdgpu device pointer | ||
204 | * @block: offset of instance | ||
205 | * @reg: offset of register | ||
206 | * | ||
207 | * Dummy register read function. Used for register blocks | ||
208 | * that certain asics don't have (all asics). | ||
209 | * Returns the value in the register. | ||
210 | */ | ||
211 | static uint32_t amdgpu_block_invalid_rreg(struct amdgpu_device *adev, | ||
212 | uint32_t block, uint32_t reg) | ||
213 | { | ||
214 | DRM_ERROR("Invalid callback to read register 0x%04X in block 0x%04X\n", | ||
215 | reg, block); | ||
216 | BUG(); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * amdgpu_block_invalid_wreg - dummy reg write function | ||
222 | * | ||
223 | * @adev: amdgpu device pointer | ||
224 | * @block: offset of instance | ||
225 | * @reg: offset of register | ||
226 | * @v: value to write to the register | ||
227 | * | ||
228 | * Dummy register read function. Used for register blocks | ||
229 | * that certain asics don't have (all asics). | ||
230 | */ | ||
231 | static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev, | ||
232 | uint32_t block, | ||
233 | uint32_t reg, uint32_t v) | ||
234 | { | ||
235 | DRM_ERROR("Invalid block callback to write register 0x%04X in block 0x%04X with 0x%08X\n", | ||
236 | reg, block, v); | ||
237 | BUG(); | ||
238 | } | ||
239 | |||
240 | static int amdgpu_vram_scratch_init(struct amdgpu_device *adev) | ||
241 | { | ||
242 | int r; | ||
243 | |||
244 | if (adev->vram_scratch.robj == NULL) { | ||
245 | r = amdgpu_bo_create(adev, AMDGPU_GPU_PAGE_SIZE, | ||
246 | PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, 0, | ||
247 | NULL, &adev->vram_scratch.robj); | ||
248 | if (r) { | ||
249 | return r; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | r = amdgpu_bo_reserve(adev->vram_scratch.robj, false); | ||
254 | if (unlikely(r != 0)) | ||
255 | return r; | ||
256 | r = amdgpu_bo_pin(adev->vram_scratch.robj, | ||
257 | AMDGPU_GEM_DOMAIN_VRAM, &adev->vram_scratch.gpu_addr); | ||
258 | if (r) { | ||
259 | amdgpu_bo_unreserve(adev->vram_scratch.robj); | ||
260 | return r; | ||
261 | } | ||
262 | r = amdgpu_bo_kmap(adev->vram_scratch.robj, | ||
263 | (void **)&adev->vram_scratch.ptr); | ||
264 | if (r) | ||
265 | amdgpu_bo_unpin(adev->vram_scratch.robj); | ||
266 | amdgpu_bo_unreserve(adev->vram_scratch.robj); | ||
267 | |||
268 | return r; | ||
269 | } | ||
270 | |||
271 | static void amdgpu_vram_scratch_fini(struct amdgpu_device *adev) | ||
272 | { | ||
273 | int r; | ||
274 | |||
275 | if (adev->vram_scratch.robj == NULL) { | ||
276 | return; | ||
277 | } | ||
278 | r = amdgpu_bo_reserve(adev->vram_scratch.robj, false); | ||
279 | if (likely(r == 0)) { | ||
280 | amdgpu_bo_kunmap(adev->vram_scratch.robj); | ||
281 | amdgpu_bo_unpin(adev->vram_scratch.robj); | ||
282 | amdgpu_bo_unreserve(adev->vram_scratch.robj); | ||
283 | } | ||
284 | amdgpu_bo_unref(&adev->vram_scratch.robj); | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * amdgpu_program_register_sequence - program an array of registers. | ||
289 | * | ||
290 | * @adev: amdgpu_device pointer | ||
291 | * @registers: pointer to the register array | ||
292 | * @array_size: size of the register array | ||
293 | * | ||
294 | * Programs an array or registers with and and or masks. | ||
295 | * This is a helper for setting golden registers. | ||
296 | */ | ||
297 | void amdgpu_program_register_sequence(struct amdgpu_device *adev, | ||
298 | const u32 *registers, | ||
299 | const u32 array_size) | ||
300 | { | ||
301 | u32 tmp, reg, and_mask, or_mask; | ||
302 | int i; | ||
303 | |||
304 | if (array_size % 3) | ||
305 | return; | ||
306 | |||
307 | for (i = 0; i < array_size; i +=3) { | ||
308 | reg = registers[i + 0]; | ||
309 | and_mask = registers[i + 1]; | ||
310 | or_mask = registers[i + 2]; | ||
311 | |||
312 | if (and_mask == 0xffffffff) { | ||
313 | tmp = or_mask; | ||
314 | } else { | ||
315 | tmp = RREG32(reg); | ||
316 | tmp &= ~and_mask; | ||
317 | tmp |= or_mask; | ||
318 | } | ||
319 | WREG32(reg, tmp); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | void amdgpu_pci_config_reset(struct amdgpu_device *adev) | ||
324 | { | ||
325 | pci_write_config_dword(adev->pdev, 0x7c, AMDGPU_ASIC_RESET_DATA); | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * GPU doorbell aperture helpers function. | ||
330 | */ | ||
331 | /** | ||
332 | * amdgpu_doorbell_init - Init doorbell driver information. | ||
333 | * | ||
334 | * @adev: amdgpu_device pointer | ||
335 | * | ||
336 | * Init doorbell driver information (CIK) | ||
337 | * Returns 0 on success, error on failure. | ||
338 | */ | ||
339 | static int amdgpu_doorbell_init(struct amdgpu_device *adev) | ||
340 | { | ||
341 | /* doorbell bar mapping */ | ||
342 | adev->doorbell.base = pci_resource_start(adev->pdev, 2); | ||
343 | adev->doorbell.size = pci_resource_len(adev->pdev, 2); | ||
344 | |||
345 | adev->doorbell.num_doorbells = min_t(u32, adev->doorbell.size / sizeof(u32), | ||
346 | AMDGPU_DOORBELL_MAX_ASSIGNMENT+1); | ||
347 | if (adev->doorbell.num_doorbells == 0) | ||
348 | return -EINVAL; | ||
349 | |||
350 | adev->doorbell.ptr = ioremap(adev->doorbell.base, adev->doorbell.num_doorbells * sizeof(u32)); | ||
351 | if (adev->doorbell.ptr == NULL) { | ||
352 | return -ENOMEM; | ||
353 | } | ||
354 | DRM_INFO("doorbell mmio base: 0x%08X\n", (uint32_t)adev->doorbell.base); | ||
355 | DRM_INFO("doorbell mmio size: %u\n", (unsigned)adev->doorbell.size); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * amdgpu_doorbell_fini - Tear down doorbell driver information. | ||
362 | * | ||
363 | * @adev: amdgpu_device pointer | ||
364 | * | ||
365 | * Tear down doorbell driver information (CIK) | ||
366 | */ | ||
367 | static void amdgpu_doorbell_fini(struct amdgpu_device *adev) | ||
368 | { | ||
369 | iounmap(adev->doorbell.ptr); | ||
370 | adev->doorbell.ptr = NULL; | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * amdgpu_doorbell_get_kfd_info - Report doorbell configuration required to | ||
375 | * setup amdkfd | ||
376 | * | ||
377 | * @adev: amdgpu_device pointer | ||
378 | * @aperture_base: output returning doorbell aperture base physical address | ||
379 | * @aperture_size: output returning doorbell aperture size in bytes | ||
380 | * @start_offset: output returning # of doorbell bytes reserved for amdgpu. | ||
381 | * | ||
382 | * amdgpu and amdkfd share the doorbell aperture. amdgpu sets it up, | ||
383 | * takes doorbells required for its own rings and reports the setup to amdkfd. | ||
384 | * amdgpu reserved doorbells are at the start of the doorbell aperture. | ||
385 | */ | ||
386 | void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev, | ||
387 | phys_addr_t *aperture_base, | ||
388 | size_t *aperture_size, | ||
389 | size_t *start_offset) | ||
390 | { | ||
391 | /* | ||
392 | * The first num_doorbells are used by amdgpu. | ||
393 | * amdkfd takes whatever's left in the aperture. | ||
394 | */ | ||
395 | if (adev->doorbell.size > adev->doorbell.num_doorbells * sizeof(u32)) { | ||
396 | *aperture_base = adev->doorbell.base; | ||
397 | *aperture_size = adev->doorbell.size; | ||
398 | *start_offset = adev->doorbell.num_doorbells * sizeof(u32); | ||
399 | } else { | ||
400 | *aperture_base = 0; | ||
401 | *aperture_size = 0; | ||
402 | *start_offset = 0; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * amdgpu_wb_*() | ||
408 | * Writeback is the the method by which the the GPU updates special pages | ||
409 | * in memory with the status of certain GPU events (fences, ring pointers, | ||
410 | * etc.). | ||
411 | */ | ||
412 | |||
413 | /** | ||
414 | * amdgpu_wb_fini - Disable Writeback and free memory | ||
415 | * | ||
416 | * @adev: amdgpu_device pointer | ||
417 | * | ||
418 | * Disables Writeback and frees the Writeback memory (all asics). | ||
419 | * Used at driver shutdown. | ||
420 | */ | ||
421 | static void amdgpu_wb_fini(struct amdgpu_device *adev) | ||
422 | { | ||
423 | if (adev->wb.wb_obj) { | ||
424 | if (!amdgpu_bo_reserve(adev->wb.wb_obj, false)) { | ||
425 | amdgpu_bo_kunmap(adev->wb.wb_obj); | ||
426 | amdgpu_bo_unpin(adev->wb.wb_obj); | ||
427 | amdgpu_bo_unreserve(adev->wb.wb_obj); | ||
428 | } | ||
429 | amdgpu_bo_unref(&adev->wb.wb_obj); | ||
430 | adev->wb.wb = NULL; | ||
431 | adev->wb.wb_obj = NULL; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * amdgpu_wb_init- Init Writeback driver info and allocate memory | ||
437 | * | ||
438 | * @adev: amdgpu_device pointer | ||
439 | * | ||
440 | * Disables Writeback and frees the Writeback memory (all asics). | ||
441 | * Used at driver startup. | ||
442 | * Returns 0 on success or an -error on failure. | ||
443 | */ | ||
444 | static int amdgpu_wb_init(struct amdgpu_device *adev) | ||
445 | { | ||
446 | int r; | ||
447 | |||
448 | if (adev->wb.wb_obj == NULL) { | ||
449 | r = amdgpu_bo_create(adev, AMDGPU_MAX_WB * 4, PAGE_SIZE, true, | ||
450 | AMDGPU_GEM_DOMAIN_GTT, 0, NULL, &adev->wb.wb_obj); | ||
451 | if (r) { | ||
452 | dev_warn(adev->dev, "(%d) create WB bo failed\n", r); | ||
453 | return r; | ||
454 | } | ||
455 | r = amdgpu_bo_reserve(adev->wb.wb_obj, false); | ||
456 | if (unlikely(r != 0)) { | ||
457 | amdgpu_wb_fini(adev); | ||
458 | return r; | ||
459 | } | ||
460 | r = amdgpu_bo_pin(adev->wb.wb_obj, AMDGPU_GEM_DOMAIN_GTT, | ||
461 | &adev->wb.gpu_addr); | ||
462 | if (r) { | ||
463 | amdgpu_bo_unreserve(adev->wb.wb_obj); | ||
464 | dev_warn(adev->dev, "(%d) pin WB bo failed\n", r); | ||
465 | amdgpu_wb_fini(adev); | ||
466 | return r; | ||
467 | } | ||
468 | r = amdgpu_bo_kmap(adev->wb.wb_obj, (void **)&adev->wb.wb); | ||
469 | amdgpu_bo_unreserve(adev->wb.wb_obj); | ||
470 | if (r) { | ||
471 | dev_warn(adev->dev, "(%d) map WB bo failed\n", r); | ||
472 | amdgpu_wb_fini(adev); | ||
473 | return r; | ||
474 | } | ||
475 | |||
476 | adev->wb.num_wb = AMDGPU_MAX_WB; | ||
477 | memset(&adev->wb.used, 0, sizeof(adev->wb.used)); | ||
478 | |||
479 | /* clear wb memory */ | ||
480 | memset((char *)adev->wb.wb, 0, AMDGPU_GPU_PAGE_SIZE); | ||
481 | } | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * amdgpu_wb_get - Allocate a wb entry | ||
488 | * | ||
489 | * @adev: amdgpu_device pointer | ||
490 | * @wb: wb index | ||
491 | * | ||
492 | * Allocate a wb slot for use by the driver (all asics). | ||
493 | * Returns 0 on success or -EINVAL on failure. | ||
494 | */ | ||
495 | int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb) | ||
496 | { | ||
497 | unsigned long offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb); | ||
498 | if (offset < adev->wb.num_wb) { | ||
499 | __set_bit(offset, adev->wb.used); | ||
500 | *wb = offset; | ||
501 | return 0; | ||
502 | } else { | ||
503 | return -EINVAL; | ||
504 | } | ||
505 | } | ||
506 | |||
507 | /** | ||
508 | * amdgpu_wb_free - Free a wb entry | ||
509 | * | ||
510 | * @adev: amdgpu_device pointer | ||
511 | * @wb: wb index | ||
512 | * | ||
513 | * Free a wb slot allocated for use by the driver (all asics) | ||
514 | */ | ||
515 | void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb) | ||
516 | { | ||
517 | if (wb < adev->wb.num_wb) | ||
518 | __clear_bit(wb, adev->wb.used); | ||
519 | } | ||
520 | |||
521 | /** | ||
522 | * amdgpu_vram_location - try to find VRAM location | ||
523 | * @adev: amdgpu device structure holding all necessary informations | ||
524 | * @mc: memory controller structure holding memory informations | ||
525 | * @base: base address at which to put VRAM | ||
526 | * | ||
527 | * Function will place try to place VRAM at base address provided | ||
528 | * as parameter (which is so far either PCI aperture address or | ||
529 | * for IGP TOM base address). | ||
530 | * | ||
531 | * If there is not enough space to fit the unvisible VRAM in the 32bits | ||
532 | * address space then we limit the VRAM size to the aperture. | ||
533 | * | ||
534 | * Note: We don't explicitly enforce VRAM start to be aligned on VRAM size, | ||
535 | * this shouldn't be a problem as we are using the PCI aperture as a reference. | ||
536 | * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but | ||
537 | * not IGP. | ||
538 | * | ||
539 | * Note: we use mc_vram_size as on some board we need to program the mc to | ||
540 | * cover the whole aperture even if VRAM size is inferior to aperture size | ||
541 | * Novell bug 204882 + along with lots of ubuntu ones | ||
542 | * | ||
543 | * Note: when limiting vram it's safe to overwritte real_vram_size because | ||
544 | * we are not in case where real_vram_size is inferior to mc_vram_size (ie | ||
545 | * note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu | ||
546 | * ones) | ||
547 | * | ||
548 | * Note: IGP TOM addr should be the same as the aperture addr, we don't | ||
549 | * explicitly check for that thought. | ||
550 | * | ||
551 | * FIXME: when reducing VRAM size align new size on power of 2. | ||
552 | */ | ||
553 | void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base) | ||
554 | { | ||
555 | uint64_t limit = (uint64_t)amdgpu_vram_limit << 20; | ||
556 | |||
557 | mc->vram_start = base; | ||
558 | if (mc->mc_vram_size > (adev->mc.mc_mask - base + 1)) { | ||
559 | dev_warn(adev->dev, "limiting VRAM to PCI aperture size\n"); | ||
560 | mc->real_vram_size = mc->aper_size; | ||
561 | mc->mc_vram_size = mc->aper_size; | ||
562 | } | ||
563 | mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; | ||
564 | if (limit && limit < mc->real_vram_size) | ||
565 | mc->real_vram_size = limit; | ||
566 | dev_info(adev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", | ||
567 | mc->mc_vram_size >> 20, mc->vram_start, | ||
568 | mc->vram_end, mc->real_vram_size >> 20); | ||
569 | } | ||
570 | |||
571 | /** | ||
572 | * amdgpu_gtt_location - try to find GTT location | ||
573 | * @adev: amdgpu device structure holding all necessary informations | ||
574 | * @mc: memory controller structure holding memory informations | ||
575 | * | ||
576 | * Function will place try to place GTT before or after VRAM. | ||
577 | * | ||
578 | * If GTT size is bigger than space left then we ajust GTT size. | ||
579 | * Thus function will never fails. | ||
580 | * | ||
581 | * FIXME: when reducing GTT size align new size on power of 2. | ||
582 | */ | ||
583 | void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) | ||
584 | { | ||
585 | u64 size_af, size_bf; | ||
586 | |||
587 | size_af = ((adev->mc.mc_mask - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; | ||
588 | size_bf = mc->vram_start & ~mc->gtt_base_align; | ||
589 | if (size_bf > size_af) { | ||
590 | if (mc->gtt_size > size_bf) { | ||
591 | dev_warn(adev->dev, "limiting GTT\n"); | ||
592 | mc->gtt_size = size_bf; | ||
593 | } | ||
594 | mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size; | ||
595 | } else { | ||
596 | if (mc->gtt_size > size_af) { | ||
597 | dev_warn(adev->dev, "limiting GTT\n"); | ||
598 | mc->gtt_size = size_af; | ||
599 | } | ||
600 | mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; | ||
601 | } | ||
602 | mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; | ||
603 | dev_info(adev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n", | ||
604 | mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * GPU helpers function. | ||
609 | */ | ||
610 | /** | ||
611 | * amdgpu_card_posted - check if the hw has already been initialized | ||
612 | * | ||
613 | * @adev: amdgpu_device pointer | ||
614 | * | ||
615 | * Check if the asic has been initialized (all asics). | ||
616 | * Used at driver startup. | ||
617 | * Returns true if initialized or false if not. | ||
618 | */ | ||
619 | bool amdgpu_card_posted(struct amdgpu_device *adev) | ||
620 | { | ||
621 | uint32_t reg; | ||
622 | |||
623 | /* then check MEM_SIZE, in case the crtcs are off */ | ||
624 | reg = RREG32(mmCONFIG_MEMSIZE); | ||
625 | |||
626 | if (reg) | ||
627 | return true; | ||
628 | |||
629 | return false; | ||
630 | |||
631 | } | ||
632 | |||
633 | /** | ||
634 | * amdgpu_boot_test_post_card - check and possibly initialize the hw | ||
635 | * | ||
636 | * @adev: amdgpu_device pointer | ||
637 | * | ||
638 | * Check if the asic is initialized and if not, attempt to initialize | ||
639 | * it (all asics). | ||
640 | * Returns true if initialized or false if not. | ||
641 | */ | ||
642 | bool amdgpu_boot_test_post_card(struct amdgpu_device *adev) | ||
643 | { | ||
644 | if (amdgpu_card_posted(adev)) | ||
645 | return true; | ||
646 | |||
647 | if (adev->bios) { | ||
648 | DRM_INFO("GPU not posted. posting now...\n"); | ||
649 | if (adev->is_atom_bios) | ||
650 | amdgpu_atom_asic_init(adev->mode_info.atom_context); | ||
651 | return true; | ||
652 | } else { | ||
653 | dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n"); | ||
654 | return false; | ||
655 | } | ||
656 | } | ||
657 | |||
658 | /** | ||
659 | * amdgpu_dummy_page_init - init dummy page used by the driver | ||
660 | * | ||
661 | * @adev: amdgpu_device pointer | ||
662 | * | ||
663 | * Allocate the dummy page used by the driver (all asics). | ||
664 | * This dummy page is used by the driver as a filler for gart entries | ||
665 | * when pages are taken out of the GART | ||
666 | * Returns 0 on sucess, -ENOMEM on failure. | ||
667 | */ | ||
668 | int amdgpu_dummy_page_init(struct amdgpu_device *adev) | ||
669 | { | ||
670 | if (adev->dummy_page.page) | ||
671 | return 0; | ||
672 | adev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); | ||
673 | if (adev->dummy_page.page == NULL) | ||
674 | return -ENOMEM; | ||
675 | adev->dummy_page.addr = pci_map_page(adev->pdev, adev->dummy_page.page, | ||
676 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
677 | if (pci_dma_mapping_error(adev->pdev, adev->dummy_page.addr)) { | ||
678 | dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n"); | ||
679 | __free_page(adev->dummy_page.page); | ||
680 | adev->dummy_page.page = NULL; | ||
681 | return -ENOMEM; | ||
682 | } | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | /** | ||
687 | * amdgpu_dummy_page_fini - free dummy page used by the driver | ||
688 | * | ||
689 | * @adev: amdgpu_device pointer | ||
690 | * | ||
691 | * Frees the dummy page used by the driver (all asics). | ||
692 | */ | ||
693 | void amdgpu_dummy_page_fini(struct amdgpu_device *adev) | ||
694 | { | ||
695 | if (adev->dummy_page.page == NULL) | ||
696 | return; | ||
697 | pci_unmap_page(adev->pdev, adev->dummy_page.addr, | ||
698 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
699 | __free_page(adev->dummy_page.page); | ||
700 | adev->dummy_page.page = NULL; | ||
701 | } | ||
702 | |||
703 | |||
704 | /* ATOM accessor methods */ | ||
705 | /* | ||
706 | * ATOM is an interpreted byte code stored in tables in the vbios. The | ||
707 | * driver registers callbacks to access registers and the interpreter | ||
708 | * in the driver parses the tables and executes then to program specific | ||
709 | * actions (set display modes, asic init, etc.). See amdgpu_atombios.c, | ||
710 | * atombios.h, and atom.c | ||
711 | */ | ||
712 | |||
713 | /** | ||
714 | * cail_pll_read - read PLL register | ||
715 | * | ||
716 | * @info: atom card_info pointer | ||
717 | * @reg: PLL register offset | ||
718 | * | ||
719 | * Provides a PLL register accessor for the atom interpreter (r4xx+). | ||
720 | * Returns the value of the PLL register. | ||
721 | */ | ||
722 | static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) | ||
723 | { | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | /** | ||
728 | * cail_pll_write - write PLL register | ||
729 | * | ||
730 | * @info: atom card_info pointer | ||
731 | * @reg: PLL register offset | ||
732 | * @val: value to write to the pll register | ||
733 | * | ||
734 | * Provides a PLL register accessor for the atom interpreter (r4xx+). | ||
735 | */ | ||
736 | static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) | ||
737 | { | ||
738 | |||
739 | } | ||
740 | |||
741 | /** | ||
742 | * cail_mc_read - read MC (Memory Controller) register | ||
743 | * | ||
744 | * @info: atom card_info pointer | ||
745 | * @reg: MC register offset | ||
746 | * | ||
747 | * Provides an MC register accessor for the atom interpreter (r4xx+). | ||
748 | * Returns the value of the MC register. | ||
749 | */ | ||
750 | static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) | ||
751 | { | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | /** | ||
756 | * cail_mc_write - write MC (Memory Controller) register | ||
757 | * | ||
758 | * @info: atom card_info pointer | ||
759 | * @reg: MC register offset | ||
760 | * @val: value to write to the pll register | ||
761 | * | ||
762 | * Provides a MC register accessor for the atom interpreter (r4xx+). | ||
763 | */ | ||
764 | static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) | ||
765 | { | ||
766 | |||
767 | } | ||
768 | |||
769 | /** | ||
770 | * cail_reg_write - write MMIO register | ||
771 | * | ||
772 | * @info: atom card_info pointer | ||
773 | * @reg: MMIO register offset | ||
774 | * @val: value to write to the pll register | ||
775 | * | ||
776 | * Provides a MMIO register accessor for the atom interpreter (r4xx+). | ||
777 | */ | ||
778 | static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) | ||
779 | { | ||
780 | struct amdgpu_device *adev = info->dev->dev_private; | ||
781 | |||
782 | WREG32(reg, val); | ||
783 | } | ||
784 | |||
785 | /** | ||
786 | * cail_reg_read - read MMIO register | ||
787 | * | ||
788 | * @info: atom card_info pointer | ||
789 | * @reg: MMIO register offset | ||
790 | * | ||
791 | * Provides an MMIO register accessor for the atom interpreter (r4xx+). | ||
792 | * Returns the value of the MMIO register. | ||
793 | */ | ||
794 | static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) | ||
795 | { | ||
796 | struct amdgpu_device *adev = info->dev->dev_private; | ||
797 | uint32_t r; | ||
798 | |||
799 | r = RREG32(reg); | ||
800 | return r; | ||
801 | } | ||
802 | |||
803 | /** | ||
804 | * cail_ioreg_write - write IO register | ||
805 | * | ||
806 | * @info: atom card_info pointer | ||
807 | * @reg: IO register offset | ||
808 | * @val: value to write to the pll register | ||
809 | * | ||
810 | * Provides a IO register accessor for the atom interpreter (r4xx+). | ||
811 | */ | ||
812 | static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) | ||
813 | { | ||
814 | struct amdgpu_device *adev = info->dev->dev_private; | ||
815 | |||
816 | WREG32_IO(reg, val); | ||
817 | } | ||
818 | |||
819 | /** | ||
820 | * cail_ioreg_read - read IO register | ||
821 | * | ||
822 | * @info: atom card_info pointer | ||
823 | * @reg: IO register offset | ||
824 | * | ||
825 | * Provides an IO register accessor for the atom interpreter (r4xx+). | ||
826 | * Returns the value of the IO register. | ||
827 | */ | ||
828 | static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) | ||
829 | { | ||
830 | struct amdgpu_device *adev = info->dev->dev_private; | ||
831 | uint32_t r; | ||
832 | |||
833 | r = RREG32_IO(reg); | ||
834 | return r; | ||
835 | } | ||
836 | |||
837 | /** | ||
838 | * amdgpu_atombios_fini - free the driver info and callbacks for atombios | ||
839 | * | ||
840 | * @adev: amdgpu_device pointer | ||
841 | * | ||
842 | * Frees the driver info and register access callbacks for the ATOM | ||
843 | * interpreter (r4xx+). | ||
844 | * Called at driver shutdown. | ||
845 | */ | ||
846 | static void amdgpu_atombios_fini(struct amdgpu_device *adev) | ||
847 | { | ||
848 | if (adev->mode_info.atom_context) | ||
849 | kfree(adev->mode_info.atom_context->scratch); | ||
850 | kfree(adev->mode_info.atom_context); | ||
851 | adev->mode_info.atom_context = NULL; | ||
852 | kfree(adev->mode_info.atom_card_info); | ||
853 | adev->mode_info.atom_card_info = NULL; | ||
854 | } | ||
855 | |||
856 | /** | ||
857 | * amdgpu_atombios_init - init the driver info and callbacks for atombios | ||
858 | * | ||
859 | * @adev: amdgpu_device pointer | ||
860 | * | ||
861 | * Initializes the driver info and register access callbacks for the | ||
862 | * ATOM interpreter (r4xx+). | ||
863 | * Returns 0 on sucess, -ENOMEM on failure. | ||
864 | * Called at driver startup. | ||
865 | */ | ||
866 | static int amdgpu_atombios_init(struct amdgpu_device *adev) | ||
867 | { | ||
868 | struct card_info *atom_card_info = | ||
869 | kzalloc(sizeof(struct card_info), GFP_KERNEL); | ||
870 | |||
871 | if (!atom_card_info) | ||
872 | return -ENOMEM; | ||
873 | |||
874 | adev->mode_info.atom_card_info = atom_card_info; | ||
875 | atom_card_info->dev = adev->ddev; | ||
876 | atom_card_info->reg_read = cail_reg_read; | ||
877 | atom_card_info->reg_write = cail_reg_write; | ||
878 | /* needed for iio ops */ | ||
879 | if (adev->rio_mem) { | ||
880 | atom_card_info->ioreg_read = cail_ioreg_read; | ||
881 | atom_card_info->ioreg_write = cail_ioreg_write; | ||
882 | } else { | ||
883 | DRM_ERROR("Unable to find PCI I/O BAR; using MMIO for ATOM IIO\n"); | ||
884 | atom_card_info->ioreg_read = cail_reg_read; | ||
885 | atom_card_info->ioreg_write = cail_reg_write; | ||
886 | } | ||
887 | atom_card_info->mc_read = cail_mc_read; | ||
888 | atom_card_info->mc_write = cail_mc_write; | ||
889 | atom_card_info->pll_read = cail_pll_read; | ||
890 | atom_card_info->pll_write = cail_pll_write; | ||
891 | |||
892 | adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info, adev->bios); | ||
893 | if (!adev->mode_info.atom_context) { | ||
894 | amdgpu_atombios_fini(adev); | ||
895 | return -ENOMEM; | ||
896 | } | ||
897 | |||
898 | mutex_init(&adev->mode_info.atom_context->mutex); | ||
899 | amdgpu_atombios_scratch_regs_init(adev); | ||
900 | amdgpu_atom_allocate_fb_scratch(adev->mode_info.atom_context); | ||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | /* if we get transitioned to only one device, take VGA back */ | ||
905 | /** | ||
906 | * amdgpu_vga_set_decode - enable/disable vga decode | ||
907 | * | ||
908 | * @cookie: amdgpu_device pointer | ||
909 | * @state: enable/disable vga decode | ||
910 | * | ||
911 | * Enable/disable vga decode (all asics). | ||
912 | * Returns VGA resource flags. | ||
913 | */ | ||
914 | static unsigned int amdgpu_vga_set_decode(void *cookie, bool state) | ||
915 | { | ||
916 | struct amdgpu_device *adev = cookie; | ||
917 | amdgpu_asic_set_vga_state(adev, state); | ||
918 | if (state) | ||
919 | return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | | ||
920 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | ||
921 | else | ||
922 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | ||
923 | } | ||
924 | |||
925 | /** | ||
926 | * amdgpu_check_pot_argument - check that argument is a power of two | ||
927 | * | ||
928 | * @arg: value to check | ||
929 | * | ||
930 | * Validates that a certain argument is a power of two (all asics). | ||
931 | * Returns true if argument is valid. | ||
932 | */ | ||
933 | static bool amdgpu_check_pot_argument(int arg) | ||
934 | { | ||
935 | return (arg & (arg - 1)) == 0; | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * amdgpu_check_arguments - validate module params | ||
940 | * | ||
941 | * @adev: amdgpu_device pointer | ||
942 | * | ||
943 | * Validates certain module parameters and updates | ||
944 | * the associated values used by the driver (all asics). | ||
945 | */ | ||
946 | static void amdgpu_check_arguments(struct amdgpu_device *adev) | ||
947 | { | ||
948 | /* vramlimit must be a power of two */ | ||
949 | if (!amdgpu_check_pot_argument(amdgpu_vram_limit)) { | ||
950 | dev_warn(adev->dev, "vram limit (%d) must be a power of 2\n", | ||
951 | amdgpu_vram_limit); | ||
952 | amdgpu_vram_limit = 0; | ||
953 | } | ||
954 | |||
955 | if (amdgpu_gart_size != -1) { | ||
956 | /* gtt size must be power of two and greater or equal to 32M */ | ||
957 | if (amdgpu_gart_size < 32) { | ||
958 | dev_warn(adev->dev, "gart size (%d) too small\n", | ||
959 | amdgpu_gart_size); | ||
960 | amdgpu_gart_size = -1; | ||
961 | } else if (!amdgpu_check_pot_argument(amdgpu_gart_size)) { | ||
962 | dev_warn(adev->dev, "gart size (%d) must be a power of 2\n", | ||
963 | amdgpu_gart_size); | ||
964 | amdgpu_gart_size = -1; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | if (!amdgpu_check_pot_argument(amdgpu_vm_size)) { | ||
969 | dev_warn(adev->dev, "VM size (%d) must be a power of 2\n", | ||
970 | amdgpu_vm_size); | ||
971 | amdgpu_vm_size = 8; | ||
972 | } | ||
973 | |||
974 | if (amdgpu_vm_size < 1) { | ||
975 | dev_warn(adev->dev, "VM size (%d) too small, min is 1GB\n", | ||
976 | amdgpu_vm_size); | ||
977 | amdgpu_vm_size = 8; | ||
978 | } | ||
979 | |||
980 | /* | ||
981 | * Max GPUVM size for Cayman, SI and CI are 40 bits. | ||
982 | */ | ||
983 | if (amdgpu_vm_size > 1024) { | ||
984 | dev_warn(adev->dev, "VM size (%d) too large, max is 1TB\n", | ||
985 | amdgpu_vm_size); | ||
986 | amdgpu_vm_size = 8; | ||
987 | } | ||
988 | |||
989 | /* defines number of bits in page table versus page directory, | ||
990 | * a page is 4KB so we have 12 bits offset, minimum 9 bits in the | ||
991 | * page table and the remaining bits are in the page directory */ | ||
992 | if (amdgpu_vm_block_size == -1) { | ||
993 | |||
994 | /* Total bits covered by PD + PTs */ | ||
995 | unsigned bits = ilog2(amdgpu_vm_size) + 18; | ||
996 | |||
997 | /* Make sure the PD is 4K in size up to 8GB address space. | ||
998 | Above that split equal between PD and PTs */ | ||
999 | if (amdgpu_vm_size <= 8) | ||
1000 | amdgpu_vm_block_size = bits - 9; | ||
1001 | else | ||
1002 | amdgpu_vm_block_size = (bits + 3) / 2; | ||
1003 | |||
1004 | } else if (amdgpu_vm_block_size < 9) { | ||
1005 | dev_warn(adev->dev, "VM page table size (%d) too small\n", | ||
1006 | amdgpu_vm_block_size); | ||
1007 | amdgpu_vm_block_size = 9; | ||
1008 | } | ||
1009 | |||
1010 | if (amdgpu_vm_block_size > 24 || | ||
1011 | (amdgpu_vm_size * 1024) < (1ull << amdgpu_vm_block_size)) { | ||
1012 | dev_warn(adev->dev, "VM page table size (%d) too large\n", | ||
1013 | amdgpu_vm_block_size); | ||
1014 | amdgpu_vm_block_size = 9; | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | /** | ||
1019 | * amdgpu_switcheroo_set_state - set switcheroo state | ||
1020 | * | ||
1021 | * @pdev: pci dev pointer | ||
1022 | * @state: vga switcheroo state | ||
1023 | * | ||
1024 | * Callback for the switcheroo driver. Suspends or resumes the | ||
1025 | * the asics before or after it is powered up using ACPI methods. | ||
1026 | */ | ||
1027 | static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) | ||
1028 | { | ||
1029 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
1030 | |||
1031 | if (amdgpu_device_is_px(dev) && state == VGA_SWITCHEROO_OFF) | ||
1032 | return; | ||
1033 | |||
1034 | if (state == VGA_SWITCHEROO_ON) { | ||
1035 | unsigned d3_delay = dev->pdev->d3_delay; | ||
1036 | |||
1037 | printk(KERN_INFO "amdgpu: switched on\n"); | ||
1038 | /* don't suspend or resume card normally */ | ||
1039 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | ||
1040 | |||
1041 | amdgpu_resume_kms(dev, true, true); | ||
1042 | |||
1043 | dev->pdev->d3_delay = d3_delay; | ||
1044 | |||
1045 | dev->switch_power_state = DRM_SWITCH_POWER_ON; | ||
1046 | drm_kms_helper_poll_enable(dev); | ||
1047 | } else { | ||
1048 | printk(KERN_INFO "amdgpu: switched off\n"); | ||
1049 | drm_kms_helper_poll_disable(dev); | ||
1050 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | ||
1051 | amdgpu_suspend_kms(dev, true, true); | ||
1052 | dev->switch_power_state = DRM_SWITCH_POWER_OFF; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | /** | ||
1057 | * amdgpu_switcheroo_can_switch - see if switcheroo state can change | ||
1058 | * | ||
1059 | * @pdev: pci dev pointer | ||
1060 | * | ||
1061 | * Callback for the switcheroo driver. Check of the switcheroo | ||
1062 | * state can be changed. | ||
1063 | * Returns true if the state can be changed, false if not. | ||
1064 | */ | ||
1065 | static bool amdgpu_switcheroo_can_switch(struct pci_dev *pdev) | ||
1066 | { | ||
1067 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
1068 | |||
1069 | /* | ||
1070 | * FIXME: open_count is protected by drm_global_mutex but that would lead to | ||
1071 | * locking inversion with the driver load path. And the access here is | ||
1072 | * completely racy anyway. So don't bother with locking for now. | ||
1073 | */ | ||
1074 | return dev->open_count == 0; | ||
1075 | } | ||
1076 | |||
1077 | static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = { | ||
1078 | .set_gpu_state = amdgpu_switcheroo_set_state, | ||
1079 | .reprobe = NULL, | ||
1080 | .can_switch = amdgpu_switcheroo_can_switch, | ||
1081 | }; | ||
1082 | |||
1083 | int amdgpu_set_clockgating_state(struct amdgpu_device *adev, | ||
1084 | enum amd_ip_block_type block_type, | ||
1085 | enum amd_clockgating_state state) | ||
1086 | { | ||
1087 | int i, r = 0; | ||
1088 | |||
1089 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
1090 | if (adev->ip_blocks[i].type == block_type) { | ||
1091 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | ||
1092 | state); | ||
1093 | if (r) | ||
1094 | return r; | ||
1095 | } | ||
1096 | } | ||
1097 | return r; | ||
1098 | } | ||
1099 | |||
1100 | int amdgpu_set_powergating_state(struct amdgpu_device *adev, | ||
1101 | enum amd_ip_block_type block_type, | ||
1102 | enum amd_powergating_state state) | ||
1103 | { | ||
1104 | int i, r = 0; | ||
1105 | |||
1106 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
1107 | if (adev->ip_blocks[i].type == block_type) { | ||
1108 | r = adev->ip_blocks[i].funcs->set_powergating_state((void *)adev, | ||
1109 | state); | ||
1110 | if (r) | ||
1111 | return r; | ||
1112 | } | ||
1113 | } | ||
1114 | return r; | ||
1115 | } | ||
1116 | |||
1117 | const struct amdgpu_ip_block_version * amdgpu_get_ip_block( | ||
1118 | struct amdgpu_device *adev, | ||
1119 | enum amd_ip_block_type type) | ||
1120 | { | ||
1121 | int i; | ||
1122 | |||
1123 | for (i = 0; i < adev->num_ip_blocks; i++) | ||
1124 | if (adev->ip_blocks[i].type == type) | ||
1125 | return &adev->ip_blocks[i]; | ||
1126 | |||
1127 | return NULL; | ||
1128 | } | ||
1129 | |||
1130 | /** | ||
1131 | * amdgpu_ip_block_version_cmp | ||
1132 | * | ||
1133 | * @adev: amdgpu_device pointer | ||
1134 | * @type: enum amd_ip_block_type | ||
1135 | * @major: major version | ||
1136 | * @minor: minor version | ||
1137 | * | ||
1138 | * return 0 if equal or greater | ||
1139 | * return 1 if smaller or the ip_block doesn't exist | ||
1140 | */ | ||
1141 | int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev, | ||
1142 | enum amd_ip_block_type type, | ||
1143 | u32 major, u32 minor) | ||
1144 | { | ||
1145 | const struct amdgpu_ip_block_version *ip_block; | ||
1146 | ip_block = amdgpu_get_ip_block(adev, type); | ||
1147 | |||
1148 | if (ip_block && ((ip_block->major > major) || | ||
1149 | ((ip_block->major == major) && | ||
1150 | (ip_block->minor >= minor)))) | ||
1151 | return 0; | ||
1152 | |||
1153 | return 1; | ||
1154 | } | ||
1155 | |||
1156 | static int amdgpu_early_init(struct amdgpu_device *adev) | ||
1157 | { | ||
1158 | int i, r; | ||
1159 | |||
1160 | switch (adev->asic_type) { | ||
1161 | case CHIP_TOPAZ: | ||
1162 | case CHIP_TONGA: | ||
1163 | case CHIP_CARRIZO: | ||
1164 | if (adev->asic_type == CHIP_CARRIZO) | ||
1165 | adev->family = AMDGPU_FAMILY_CZ; | ||
1166 | else | ||
1167 | adev->family = AMDGPU_FAMILY_VI; | ||
1168 | |||
1169 | r = vi_set_ip_blocks(adev); | ||
1170 | if (r) | ||
1171 | return r; | ||
1172 | break; | ||
1173 | #ifdef CONFIG_DRM_AMDGPU_CIK | ||
1174 | case CHIP_BONAIRE: | ||
1175 | case CHIP_HAWAII: | ||
1176 | case CHIP_KAVERI: | ||
1177 | case CHIP_KABINI: | ||
1178 | case CHIP_MULLINS: | ||
1179 | if ((adev->asic_type == CHIP_BONAIRE) || (adev->asic_type == CHIP_HAWAII)) | ||
1180 | adev->family = AMDGPU_FAMILY_CI; | ||
1181 | else | ||
1182 | adev->family = AMDGPU_FAMILY_KV; | ||
1183 | |||
1184 | r = cik_set_ip_blocks(adev); | ||
1185 | if (r) | ||
1186 | return r; | ||
1187 | break; | ||
1188 | #endif | ||
1189 | default: | ||
1190 | /* FIXME: not supported yet */ | ||
1191 | return -EINVAL; | ||
1192 | } | ||
1193 | |||
1194 | adev->ip_block_status = kcalloc(adev->num_ip_blocks, | ||
1195 | sizeof(struct amdgpu_ip_block_status), GFP_KERNEL); | ||
1196 | if (adev->ip_block_status == NULL) | ||
1197 | return -ENOMEM; | ||
1198 | |||
1199 | if (adev->ip_blocks == NULL) { | ||
1200 | DRM_ERROR("No IP blocks found!\n"); | ||
1201 | return r; | ||
1202 | } | ||
1203 | |||
1204 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
1205 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { | ||
1206 | DRM_ERROR("disabled ip block: %d\n", i); | ||
1207 | adev->ip_block_status[i].valid = false; | ||
1208 | } else { | ||
1209 | if (adev->ip_blocks[i].funcs->early_init) { | ||
1210 | r = adev->ip_blocks[i].funcs->early_init((void *)adev); | ||
1211 | if (r == -ENOENT) | ||
1212 | adev->ip_block_status[i].valid = false; | ||
1213 | else if (r) | ||
1214 | return r; | ||
1215 | else | ||
1216 | adev->ip_block_status[i].valid = true; | ||
1217 | } else { | ||
1218 | adev->ip_block_status[i].valid = true; | ||
1219 | } | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1223 | return 0; | ||
1224 | } | ||
1225 | |||
1226 | static int amdgpu_init(struct amdgpu_device *adev) | ||
1227 | { | ||
1228 | int i, r; | ||
1229 | |||
1230 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
1231 | if (!adev->ip_block_status[i].valid) | ||
1232 | continue; | ||
1233 | r = adev->ip_blocks[i].funcs->sw_init((void *)adev); | ||
1234 | if (r) | ||
1235 | return r; | ||
1236 | adev->ip_block_status[i].sw = true; | ||
1237 | /* need to do gmc hw init early so we can allocate gpu mem */ | ||
1238 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { | ||
1239 | r = amdgpu_vram_scratch_init(adev); | ||
1240 | if (r) | ||
1241 | return r; | ||
1242 | r = adev->ip_blocks[i].funcs->hw_init((void *)adev); | ||
1243 | if (r) | ||
1244 | return r; | ||
1245 | r = amdgpu_wb_init(adev); | ||
1246 | if (r) | ||
1247 | return r; | ||
1248 | adev->ip_block_status[i].hw = true; | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
1253 | if (!adev->ip_block_status[i].sw) | ||
1254 | continue; | ||
1255 | /* gmc hw init is done early */ | ||
1256 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) | ||
1257 | continue; | ||
1258 | r = adev->ip_blocks[i].funcs->hw_init((void *)adev); | ||
1259 | if (r) | ||
1260 | return r; | ||
1261 | adev->ip_block_status[i].hw = true; | ||
1262 | } | ||
1263 | |||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1267 | static int amdgpu_late_init(struct amdgpu_device *adev) | ||
1268 | { | ||
1269 | int i = 0, r; | ||
1270 | |||
1271 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
1272 | if (!adev->ip_block_status[i].valid) | ||
1273 | continue; | ||
1274 | /* enable clockgating to save power */ | ||
1275 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | ||
1276 | AMD_CG_STATE_GATE); | ||
1277 | if (r) | ||
1278 | return r; | ||
1279 | if (adev->ip_blocks[i].funcs->late_init) { | ||
1280 | r = adev->ip_blocks[i].funcs->late_init((void *)adev); | ||
1281 | if (r) | ||
1282 | return r; | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | return 0; | ||
1287 | } | ||
1288 | |||
1289 | static int amdgpu_fini(struct amdgpu_device *adev) | ||
1290 | { | ||
1291 | int i, r; | ||
1292 | |||
1293 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | ||
1294 | if (!adev->ip_block_status[i].hw) | ||
1295 | continue; | ||
1296 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { | ||
1297 | amdgpu_wb_fini(adev); | ||
1298 | amdgpu_vram_scratch_fini(adev); | ||
1299 | } | ||
1300 | /* ungate blocks before hw fini so that we can shutdown the blocks safely */ | ||
1301 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | ||
1302 | AMD_CG_STATE_UNGATE); | ||
1303 | if (r) | ||
1304 | return r; | ||
1305 | r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); | ||
1306 | /* XXX handle errors */ | ||
1307 | adev->ip_block_status[i].hw = false; | ||
1308 | } | ||
1309 | |||
1310 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | ||
1311 | if (!adev->ip_block_status[i].sw) | ||
1312 | continue; | ||
1313 | r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); | ||
1314 | /* XXX handle errors */ | ||
1315 | adev->ip_block_status[i].sw = false; | ||
1316 | adev->ip_block_status[i].valid = false; | ||
1317 | } | ||
1318 | |||
1319 | return 0; | ||
1320 | } | ||
1321 | |||
1322 | static int amdgpu_suspend(struct amdgpu_device *adev) | ||
1323 | { | ||
1324 | int i, r; | ||
1325 | |||
1326 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | ||
1327 | if (!adev->ip_block_status[i].valid) | ||
1328 | continue; | ||
1329 | /* ungate blocks so that suspend can properly shut them down */ | ||
1330 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | ||
1331 | AMD_CG_STATE_UNGATE); | ||
1332 | /* XXX handle errors */ | ||
1333 | r = adev->ip_blocks[i].funcs->suspend(adev); | ||
1334 | /* XXX handle errors */ | ||
1335 | } | ||
1336 | |||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | static int amdgpu_resume(struct amdgpu_device *adev) | ||
1341 | { | ||
1342 | int i, r; | ||
1343 | |||
1344 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
1345 | if (!adev->ip_block_status[i].valid) | ||
1346 | continue; | ||
1347 | r = adev->ip_blocks[i].funcs->resume(adev); | ||
1348 | if (r) | ||
1349 | return r; | ||
1350 | } | ||
1351 | |||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | /** | ||
1356 | * amdgpu_device_init - initialize the driver | ||
1357 | * | ||
1358 | * @adev: amdgpu_device pointer | ||
1359 | * @pdev: drm dev pointer | ||
1360 | * @pdev: pci dev pointer | ||
1361 | * @flags: driver flags | ||
1362 | * | ||
1363 | * Initializes the driver info and hw (all asics). | ||
1364 | * Returns 0 for success or an error on failure. | ||
1365 | * Called at driver startup. | ||
1366 | */ | ||
1367 | int amdgpu_device_init(struct amdgpu_device *adev, | ||
1368 | struct drm_device *ddev, | ||
1369 | struct pci_dev *pdev, | ||
1370 | uint32_t flags) | ||
1371 | { | ||
1372 | int r, i; | ||
1373 | bool runtime = false; | ||
1374 | |||
1375 | adev->shutdown = false; | ||
1376 | adev->dev = &pdev->dev; | ||
1377 | adev->ddev = ddev; | ||
1378 | adev->pdev = pdev; | ||
1379 | adev->flags = flags; | ||
1380 | adev->asic_type = flags & AMDGPU_ASIC_MASK; | ||
1381 | adev->is_atom_bios = false; | ||
1382 | adev->usec_timeout = AMDGPU_MAX_USEC_TIMEOUT; | ||
1383 | adev->mc.gtt_size = 512 * 1024 * 1024; | ||
1384 | adev->accel_working = false; | ||
1385 | adev->num_rings = 0; | ||
1386 | adev->mman.buffer_funcs = NULL; | ||
1387 | adev->mman.buffer_funcs_ring = NULL; | ||
1388 | adev->vm_manager.vm_pte_funcs = NULL; | ||
1389 | adev->vm_manager.vm_pte_funcs_ring = NULL; | ||
1390 | adev->gart.gart_funcs = NULL; | ||
1391 | adev->fence_context = fence_context_alloc(AMDGPU_MAX_RINGS); | ||
1392 | |||
1393 | adev->smc_rreg = &amdgpu_invalid_rreg; | ||
1394 | adev->smc_wreg = &amdgpu_invalid_wreg; | ||
1395 | adev->pcie_rreg = &amdgpu_invalid_rreg; | ||
1396 | adev->pcie_wreg = &amdgpu_invalid_wreg; | ||
1397 | adev->uvd_ctx_rreg = &amdgpu_invalid_rreg; | ||
1398 | adev->uvd_ctx_wreg = &amdgpu_invalid_wreg; | ||
1399 | adev->didt_rreg = &amdgpu_invalid_rreg; | ||
1400 | adev->didt_wreg = &amdgpu_invalid_wreg; | ||
1401 | adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg; | ||
1402 | adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg; | ||
1403 | |||
1404 | DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n", | ||
1405 | amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device, | ||
1406 | pdev->subsystem_vendor, pdev->subsystem_device, pdev->revision); | ||
1407 | |||
1408 | /* mutex initialization are all done here so we | ||
1409 | * can recall function without having locking issues */ | ||
1410 | mutex_init(&adev->ring_lock); | ||
1411 | atomic_set(&adev->irq.ih.lock, 0); | ||
1412 | mutex_init(&adev->gem.mutex); | ||
1413 | mutex_init(&adev->pm.mutex); | ||
1414 | mutex_init(&adev->gfx.gpu_clock_mutex); | ||
1415 | mutex_init(&adev->srbm_mutex); | ||
1416 | mutex_init(&adev->grbm_idx_mutex); | ||
1417 | init_rwsem(&adev->exclusive_lock); | ||
1418 | mutex_init(&adev->mn_lock); | ||
1419 | hash_init(adev->mn_hash); | ||
1420 | |||
1421 | amdgpu_check_arguments(adev); | ||
1422 | |||
1423 | /* Registers mapping */ | ||
1424 | /* TODO: block userspace mapping of io register */ | ||
1425 | spin_lock_init(&adev->mmio_idx_lock); | ||
1426 | spin_lock_init(&adev->smc_idx_lock); | ||
1427 | spin_lock_init(&adev->pcie_idx_lock); | ||
1428 | spin_lock_init(&adev->uvd_ctx_idx_lock); | ||
1429 | spin_lock_init(&adev->didt_idx_lock); | ||
1430 | spin_lock_init(&adev->audio_endpt_idx_lock); | ||
1431 | |||
1432 | adev->rmmio_base = pci_resource_start(adev->pdev, 5); | ||
1433 | adev->rmmio_size = pci_resource_len(adev->pdev, 5); | ||
1434 | adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); | ||
1435 | if (adev->rmmio == NULL) { | ||
1436 | return -ENOMEM; | ||
1437 | } | ||
1438 | DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base); | ||
1439 | DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size); | ||
1440 | |||
1441 | /* doorbell bar mapping */ | ||
1442 | amdgpu_doorbell_init(adev); | ||
1443 | |||
1444 | /* io port mapping */ | ||
1445 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
1446 | if (pci_resource_flags(adev->pdev, i) & IORESOURCE_IO) { | ||
1447 | adev->rio_mem_size = pci_resource_len(adev->pdev, i); | ||
1448 | adev->rio_mem = pci_iomap(adev->pdev, i, adev->rio_mem_size); | ||
1449 | break; | ||
1450 | } | ||
1451 | } | ||
1452 | if (adev->rio_mem == NULL) | ||
1453 | DRM_ERROR("Unable to find PCI I/O BAR\n"); | ||
1454 | |||
1455 | /* early init functions */ | ||
1456 | r = amdgpu_early_init(adev); | ||
1457 | if (r) | ||
1458 | return r; | ||
1459 | |||
1460 | /* if we have > 1 VGA cards, then disable the amdgpu VGA resources */ | ||
1461 | /* this will fail for cards that aren't VGA class devices, just | ||
1462 | * ignore it */ | ||
1463 | vga_client_register(adev->pdev, adev, NULL, amdgpu_vga_set_decode); | ||
1464 | |||
1465 | if (amdgpu_runtime_pm == 1) | ||
1466 | runtime = true; | ||
1467 | if (amdgpu_device_is_px(ddev)) | ||
1468 | runtime = true; | ||
1469 | vga_switcheroo_register_client(adev->pdev, &amdgpu_switcheroo_ops, runtime); | ||
1470 | if (runtime) | ||
1471 | vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain); | ||
1472 | |||
1473 | /* Read BIOS */ | ||
1474 | if (!amdgpu_get_bios(adev)) | ||
1475 | return -EINVAL; | ||
1476 | /* Must be an ATOMBIOS */ | ||
1477 | if (!adev->is_atom_bios) { | ||
1478 | dev_err(adev->dev, "Expecting atombios for GPU\n"); | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | r = amdgpu_atombios_init(adev); | ||
1482 | if (r) | ||
1483 | return r; | ||
1484 | |||
1485 | /* Post card if necessary */ | ||
1486 | if (!amdgpu_card_posted(adev)) { | ||
1487 | if (!adev->bios) { | ||
1488 | dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n"); | ||
1489 | return -EINVAL; | ||
1490 | } | ||
1491 | DRM_INFO("GPU not posted. posting now...\n"); | ||
1492 | amdgpu_atom_asic_init(adev->mode_info.atom_context); | ||
1493 | } | ||
1494 | |||
1495 | /* Initialize clocks */ | ||
1496 | r = amdgpu_atombios_get_clock_info(adev); | ||
1497 | if (r) | ||
1498 | return r; | ||
1499 | /* init i2c buses */ | ||
1500 | amdgpu_atombios_i2c_init(adev); | ||
1501 | |||
1502 | /* Fence driver */ | ||
1503 | r = amdgpu_fence_driver_init(adev); | ||
1504 | if (r) | ||
1505 | return r; | ||
1506 | |||
1507 | /* init the mode config */ | ||
1508 | drm_mode_config_init(adev->ddev); | ||
1509 | |||
1510 | r = amdgpu_init(adev); | ||
1511 | if (r) { | ||
1512 | amdgpu_fini(adev); | ||
1513 | return r; | ||
1514 | } | ||
1515 | |||
1516 | adev->accel_working = true; | ||
1517 | |||
1518 | amdgpu_fbdev_init(adev); | ||
1519 | |||
1520 | r = amdgpu_ib_pool_init(adev); | ||
1521 | if (r) { | ||
1522 | dev_err(adev->dev, "IB initialization failed (%d).\n", r); | ||
1523 | return r; | ||
1524 | } | ||
1525 | |||
1526 | r = amdgpu_ib_ring_tests(adev); | ||
1527 | if (r) | ||
1528 | DRM_ERROR("ib ring test failed (%d).\n", r); | ||
1529 | |||
1530 | r = amdgpu_gem_debugfs_init(adev); | ||
1531 | if (r) { | ||
1532 | DRM_ERROR("registering gem debugfs failed (%d).\n", r); | ||
1533 | } | ||
1534 | |||
1535 | r = amdgpu_debugfs_regs_init(adev); | ||
1536 | if (r) { | ||
1537 | DRM_ERROR("registering register debugfs failed (%d).\n", r); | ||
1538 | } | ||
1539 | |||
1540 | if ((amdgpu_testing & 1)) { | ||
1541 | if (adev->accel_working) | ||
1542 | amdgpu_test_moves(adev); | ||
1543 | else | ||
1544 | DRM_INFO("amdgpu: acceleration disabled, skipping move tests\n"); | ||
1545 | } | ||
1546 | if ((amdgpu_testing & 2)) { | ||
1547 | if (adev->accel_working) | ||
1548 | amdgpu_test_syncing(adev); | ||
1549 | else | ||
1550 | DRM_INFO("amdgpu: acceleration disabled, skipping sync tests\n"); | ||
1551 | } | ||
1552 | if (amdgpu_benchmarking) { | ||
1553 | if (adev->accel_working) | ||
1554 | amdgpu_benchmark(adev, amdgpu_benchmarking); | ||
1555 | else | ||
1556 | DRM_INFO("amdgpu: acceleration disabled, skipping benchmarks\n"); | ||
1557 | } | ||
1558 | |||
1559 | /* enable clockgating, etc. after ib tests, etc. since some blocks require | ||
1560 | * explicit gating rather than handling it automatically. | ||
1561 | */ | ||
1562 | r = amdgpu_late_init(adev); | ||
1563 | if (r) | ||
1564 | return r; | ||
1565 | |||
1566 | return 0; | ||
1567 | } | ||
1568 | |||
1569 | static void amdgpu_debugfs_remove_files(struct amdgpu_device *adev); | ||
1570 | |||
1571 | /** | ||
1572 | * amdgpu_device_fini - tear down the driver | ||
1573 | * | ||
1574 | * @adev: amdgpu_device pointer | ||
1575 | * | ||
1576 | * Tear down the driver info (all asics). | ||
1577 | * Called at driver shutdown. | ||
1578 | */ | ||
1579 | void amdgpu_device_fini(struct amdgpu_device *adev) | ||
1580 | { | ||
1581 | int r; | ||
1582 | |||
1583 | DRM_INFO("amdgpu: finishing device.\n"); | ||
1584 | adev->shutdown = true; | ||
1585 | /* evict vram memory */ | ||
1586 | amdgpu_bo_evict_vram(adev); | ||
1587 | amdgpu_ib_pool_fini(adev); | ||
1588 | amdgpu_fence_driver_fini(adev); | ||
1589 | amdgpu_fbdev_fini(adev); | ||
1590 | r = amdgpu_fini(adev); | ||
1591 | kfree(adev->ip_block_status); | ||
1592 | adev->ip_block_status = NULL; | ||
1593 | adev->accel_working = false; | ||
1594 | /* free i2c buses */ | ||
1595 | amdgpu_i2c_fini(adev); | ||
1596 | amdgpu_atombios_fini(adev); | ||
1597 | kfree(adev->bios); | ||
1598 | adev->bios = NULL; | ||
1599 | vga_switcheroo_unregister_client(adev->pdev); | ||
1600 | vga_client_register(adev->pdev, NULL, NULL, NULL); | ||
1601 | if (adev->rio_mem) | ||
1602 | pci_iounmap(adev->pdev, adev->rio_mem); | ||
1603 | adev->rio_mem = NULL; | ||
1604 | iounmap(adev->rmmio); | ||
1605 | adev->rmmio = NULL; | ||
1606 | amdgpu_doorbell_fini(adev); | ||
1607 | amdgpu_debugfs_regs_cleanup(adev); | ||
1608 | amdgpu_debugfs_remove_files(adev); | ||
1609 | } | ||
1610 | |||
1611 | |||
1612 | /* | ||
1613 | * Suspend & resume. | ||
1614 | */ | ||
1615 | /** | ||
1616 | * amdgpu_suspend_kms - initiate device suspend | ||
1617 | * | ||
1618 | * @pdev: drm dev pointer | ||
1619 | * @state: suspend state | ||
1620 | * | ||
1621 | * Puts the hw in the suspend state (all asics). | ||
1622 | * Returns 0 for success or an error on failure. | ||
1623 | * Called at driver suspend. | ||
1624 | */ | ||
1625 | int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) | ||
1626 | { | ||
1627 | struct amdgpu_device *adev; | ||
1628 | struct drm_crtc *crtc; | ||
1629 | struct drm_connector *connector; | ||
1630 | int i, r; | ||
1631 | bool force_completion = false; | ||
1632 | |||
1633 | if (dev == NULL || dev->dev_private == NULL) { | ||
1634 | return -ENODEV; | ||
1635 | } | ||
1636 | |||
1637 | adev = dev->dev_private; | ||
1638 | |||
1639 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) | ||
1640 | return 0; | ||
1641 | |||
1642 | drm_kms_helper_poll_disable(dev); | ||
1643 | |||
1644 | /* turn off display hw */ | ||
1645 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
1646 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | ||
1647 | } | ||
1648 | |||
1649 | /* unpin the front buffers */ | ||
1650 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
1651 | struct amdgpu_framebuffer *rfb = to_amdgpu_framebuffer(crtc->primary->fb); | ||
1652 | struct amdgpu_bo *robj; | ||
1653 | |||
1654 | if (rfb == NULL || rfb->obj == NULL) { | ||
1655 | continue; | ||
1656 | } | ||
1657 | robj = gem_to_amdgpu_bo(rfb->obj); | ||
1658 | /* don't unpin kernel fb objects */ | ||
1659 | if (!amdgpu_fbdev_robj_is_fb(adev, robj)) { | ||
1660 | r = amdgpu_bo_reserve(robj, false); | ||
1661 | if (r == 0) { | ||
1662 | amdgpu_bo_unpin(robj); | ||
1663 | amdgpu_bo_unreserve(robj); | ||
1664 | } | ||
1665 | } | ||
1666 | } | ||
1667 | /* evict vram memory */ | ||
1668 | amdgpu_bo_evict_vram(adev); | ||
1669 | |||
1670 | /* wait for gpu to finish processing current batch */ | ||
1671 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { | ||
1672 | struct amdgpu_ring *ring = adev->rings[i]; | ||
1673 | if (!ring) | ||
1674 | continue; | ||
1675 | |||
1676 | r = amdgpu_fence_wait_empty(ring); | ||
1677 | if (r) { | ||
1678 | /* delay GPU reset to resume */ | ||
1679 | force_completion = true; | ||
1680 | } | ||
1681 | } | ||
1682 | if (force_completion) { | ||
1683 | amdgpu_fence_driver_force_completion(adev); | ||
1684 | } | ||
1685 | |||
1686 | r = amdgpu_suspend(adev); | ||
1687 | |||
1688 | /* evict remaining vram memory */ | ||
1689 | amdgpu_bo_evict_vram(adev); | ||
1690 | |||
1691 | pci_save_state(dev->pdev); | ||
1692 | if (suspend) { | ||
1693 | /* Shut down the device */ | ||
1694 | pci_disable_device(dev->pdev); | ||
1695 | pci_set_power_state(dev->pdev, PCI_D3hot); | ||
1696 | } | ||
1697 | |||
1698 | if (fbcon) { | ||
1699 | console_lock(); | ||
1700 | amdgpu_fbdev_set_suspend(adev, 1); | ||
1701 | console_unlock(); | ||
1702 | } | ||
1703 | return 0; | ||
1704 | } | ||
1705 | |||
1706 | /** | ||
1707 | * amdgpu_resume_kms - initiate device resume | ||
1708 | * | ||
1709 | * @pdev: drm dev pointer | ||
1710 | * | ||
1711 | * Bring the hw back to operating state (all asics). | ||
1712 | * Returns 0 for success or an error on failure. | ||
1713 | * Called at driver resume. | ||
1714 | */ | ||
1715 | int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) | ||
1716 | { | ||
1717 | struct drm_connector *connector; | ||
1718 | struct amdgpu_device *adev = dev->dev_private; | ||
1719 | int r; | ||
1720 | |||
1721 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) | ||
1722 | return 0; | ||
1723 | |||
1724 | if (fbcon) { | ||
1725 | console_lock(); | ||
1726 | } | ||
1727 | if (resume) { | ||
1728 | pci_set_power_state(dev->pdev, PCI_D0); | ||
1729 | pci_restore_state(dev->pdev); | ||
1730 | if (pci_enable_device(dev->pdev)) { | ||
1731 | if (fbcon) | ||
1732 | console_unlock(); | ||
1733 | return -1; | ||
1734 | } | ||
1735 | } | ||
1736 | |||
1737 | /* post card */ | ||
1738 | amdgpu_atom_asic_init(adev->mode_info.atom_context); | ||
1739 | |||
1740 | r = amdgpu_resume(adev); | ||
1741 | |||
1742 | r = amdgpu_ib_ring_tests(adev); | ||
1743 | if (r) | ||
1744 | DRM_ERROR("ib ring test failed (%d).\n", r); | ||
1745 | |||
1746 | r = amdgpu_late_init(adev); | ||
1747 | if (r) | ||
1748 | return r; | ||
1749 | |||
1750 | /* blat the mode back in */ | ||
1751 | if (fbcon) { | ||
1752 | drm_helper_resume_force_mode(dev); | ||
1753 | /* turn on display hw */ | ||
1754 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
1755 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | ||
1756 | } | ||
1757 | } | ||
1758 | |||
1759 | drm_kms_helper_poll_enable(dev); | ||
1760 | |||
1761 | if (fbcon) { | ||
1762 | amdgpu_fbdev_set_suspend(adev, 0); | ||
1763 | console_unlock(); | ||
1764 | } | ||
1765 | |||
1766 | return 0; | ||
1767 | } | ||
1768 | |||
1769 | /** | ||
1770 | * amdgpu_gpu_reset - reset the asic | ||
1771 | * | ||
1772 | * @adev: amdgpu device pointer | ||
1773 | * | ||
1774 | * Attempt the reset the GPU if it has hung (all asics). | ||
1775 | * Returns 0 for success or an error on failure. | ||
1776 | */ | ||
1777 | int amdgpu_gpu_reset(struct amdgpu_device *adev) | ||
1778 | { | ||
1779 | unsigned ring_sizes[AMDGPU_MAX_RINGS]; | ||
1780 | uint32_t *ring_data[AMDGPU_MAX_RINGS]; | ||
1781 | |||
1782 | bool saved = false; | ||
1783 | |||
1784 | int i, r; | ||
1785 | int resched; | ||
1786 | |||
1787 | down_write(&adev->exclusive_lock); | ||
1788 | |||
1789 | if (!adev->needs_reset) { | ||
1790 | up_write(&adev->exclusive_lock); | ||
1791 | return 0; | ||
1792 | } | ||
1793 | |||
1794 | adev->needs_reset = false; | ||
1795 | atomic_inc(&adev->gpu_reset_counter); | ||
1796 | |||
1797 | /* block TTM */ | ||
1798 | resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); | ||
1799 | |||
1800 | r = amdgpu_suspend(adev); | ||
1801 | |||
1802 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { | ||
1803 | struct amdgpu_ring *ring = adev->rings[i]; | ||
1804 | if (!ring) | ||
1805 | continue; | ||
1806 | |||
1807 | ring_sizes[i] = amdgpu_ring_backup(ring, &ring_data[i]); | ||
1808 | if (ring_sizes[i]) { | ||
1809 | saved = true; | ||
1810 | dev_info(adev->dev, "Saved %d dwords of commands " | ||
1811 | "on ring %d.\n", ring_sizes[i], i); | ||
1812 | } | ||
1813 | } | ||
1814 | |||
1815 | retry: | ||
1816 | r = amdgpu_asic_reset(adev); | ||
1817 | if (!r) { | ||
1818 | dev_info(adev->dev, "GPU reset succeeded, trying to resume\n"); | ||
1819 | r = amdgpu_resume(adev); | ||
1820 | } | ||
1821 | |||
1822 | if (!r) { | ||
1823 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { | ||
1824 | struct amdgpu_ring *ring = adev->rings[i]; | ||
1825 | if (!ring) | ||
1826 | continue; | ||
1827 | |||
1828 | amdgpu_ring_restore(ring, ring_sizes[i], ring_data[i]); | ||
1829 | ring_sizes[i] = 0; | ||
1830 | ring_data[i] = NULL; | ||
1831 | } | ||
1832 | |||
1833 | r = amdgpu_ib_ring_tests(adev); | ||
1834 | if (r) { | ||
1835 | dev_err(adev->dev, "ib ring test failed (%d).\n", r); | ||
1836 | if (saved) { | ||
1837 | saved = false; | ||
1838 | r = amdgpu_suspend(adev); | ||
1839 | goto retry; | ||
1840 | } | ||
1841 | } | ||
1842 | } else { | ||
1843 | amdgpu_fence_driver_force_completion(adev); | ||
1844 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { | ||
1845 | if (adev->rings[i]) | ||
1846 | kfree(ring_data[i]); | ||
1847 | } | ||
1848 | } | ||
1849 | |||
1850 | drm_helper_resume_force_mode(adev->ddev); | ||
1851 | |||
1852 | ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); | ||
1853 | if (r) { | ||
1854 | /* bad news, how to tell it to userspace ? */ | ||
1855 | dev_info(adev->dev, "GPU reset failed\n"); | ||
1856 | } | ||
1857 | |||
1858 | up_write(&adev->exclusive_lock); | ||
1859 | return r; | ||
1860 | } | ||
1861 | |||
1862 | |||
1863 | /* | ||
1864 | * Debugfs | ||
1865 | */ | ||
1866 | int amdgpu_debugfs_add_files(struct amdgpu_device *adev, | ||
1867 | struct drm_info_list *files, | ||
1868 | unsigned nfiles) | ||
1869 | { | ||
1870 | unsigned i; | ||
1871 | |||
1872 | for (i = 0; i < adev->debugfs_count; i++) { | ||
1873 | if (adev->debugfs[i].files == files) { | ||
1874 | /* Already registered */ | ||
1875 | return 0; | ||
1876 | } | ||
1877 | } | ||
1878 | |||
1879 | i = adev->debugfs_count + 1; | ||
1880 | if (i > AMDGPU_DEBUGFS_MAX_COMPONENTS) { | ||
1881 | DRM_ERROR("Reached maximum number of debugfs components.\n"); | ||
1882 | DRM_ERROR("Report so we increase " | ||
1883 | "AMDGPU_DEBUGFS_MAX_COMPONENTS.\n"); | ||
1884 | return -EINVAL; | ||
1885 | } | ||
1886 | adev->debugfs[adev->debugfs_count].files = files; | ||
1887 | adev->debugfs[adev->debugfs_count].num_files = nfiles; | ||
1888 | adev->debugfs_count = i; | ||
1889 | #if defined(CONFIG_DEBUG_FS) | ||
1890 | drm_debugfs_create_files(files, nfiles, | ||
1891 | adev->ddev->control->debugfs_root, | ||
1892 | adev->ddev->control); | ||
1893 | drm_debugfs_create_files(files, nfiles, | ||
1894 | adev->ddev->primary->debugfs_root, | ||
1895 | adev->ddev->primary); | ||
1896 | #endif | ||
1897 | return 0; | ||
1898 | } | ||
1899 | |||
1900 | static void amdgpu_debugfs_remove_files(struct amdgpu_device *adev) | ||
1901 | { | ||
1902 | #if defined(CONFIG_DEBUG_FS) | ||
1903 | unsigned i; | ||
1904 | |||
1905 | for (i = 0; i < adev->debugfs_count; i++) { | ||
1906 | drm_debugfs_remove_files(adev->debugfs[i].files, | ||
1907 | adev->debugfs[i].num_files, | ||
1908 | adev->ddev->control); | ||
1909 | drm_debugfs_remove_files(adev->debugfs[i].files, | ||
1910 | adev->debugfs[i].num_files, | ||
1911 | adev->ddev->primary); | ||
1912 | } | ||
1913 | #endif | ||
1914 | } | ||
1915 | |||
1916 | #if defined(CONFIG_DEBUG_FS) | ||
1917 | |||
1918 | static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, | ||
1919 | size_t size, loff_t *pos) | ||
1920 | { | ||
1921 | struct amdgpu_device *adev = f->f_inode->i_private; | ||
1922 | ssize_t result = 0; | ||
1923 | int r; | ||
1924 | |||
1925 | if (size & 0x3 || *pos & 0x3) | ||
1926 | return -EINVAL; | ||
1927 | |||
1928 | while (size) { | ||
1929 | uint32_t value; | ||
1930 | |||
1931 | if (*pos > adev->rmmio_size) | ||
1932 | return result; | ||
1933 | |||
1934 | value = RREG32(*pos >> 2); | ||
1935 | r = put_user(value, (uint32_t *)buf); | ||
1936 | if (r) | ||
1937 | return r; | ||
1938 | |||
1939 | result += 4; | ||
1940 | buf += 4; | ||
1941 | *pos += 4; | ||
1942 | size -= 4; | ||
1943 | } | ||
1944 | |||
1945 | return result; | ||
1946 | } | ||
1947 | |||
1948 | static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, | ||
1949 | size_t size, loff_t *pos) | ||
1950 | { | ||
1951 | struct amdgpu_device *adev = f->f_inode->i_private; | ||
1952 | ssize_t result = 0; | ||
1953 | int r; | ||
1954 | |||
1955 | if (size & 0x3 || *pos & 0x3) | ||
1956 | return -EINVAL; | ||
1957 | |||
1958 | while (size) { | ||
1959 | uint32_t value; | ||
1960 | |||
1961 | if (*pos > adev->rmmio_size) | ||
1962 | return result; | ||
1963 | |||
1964 | r = get_user(value, (uint32_t *)buf); | ||
1965 | if (r) | ||
1966 | return r; | ||
1967 | |||
1968 | WREG32(*pos >> 2, value); | ||
1969 | |||
1970 | result += 4; | ||
1971 | buf += 4; | ||
1972 | *pos += 4; | ||
1973 | size -= 4; | ||
1974 | } | ||
1975 | |||
1976 | return result; | ||
1977 | } | ||
1978 | |||
1979 | static const struct file_operations amdgpu_debugfs_regs_fops = { | ||
1980 | .owner = THIS_MODULE, | ||
1981 | .read = amdgpu_debugfs_regs_read, | ||
1982 | .write = amdgpu_debugfs_regs_write, | ||
1983 | .llseek = default_llseek | ||
1984 | }; | ||
1985 | |||
1986 | static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) | ||
1987 | { | ||
1988 | struct drm_minor *minor = adev->ddev->primary; | ||
1989 | struct dentry *ent, *root = minor->debugfs_root; | ||
1990 | |||
1991 | ent = debugfs_create_file("amdgpu_regs", S_IFREG | S_IRUGO, root, | ||
1992 | adev, &amdgpu_debugfs_regs_fops); | ||
1993 | if (IS_ERR(ent)) | ||
1994 | return PTR_ERR(ent); | ||
1995 | i_size_write(ent->d_inode, adev->rmmio_size); | ||
1996 | adev->debugfs_regs = ent; | ||
1997 | |||
1998 | return 0; | ||
1999 | } | ||
2000 | |||
2001 | static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) | ||
2002 | { | ||
2003 | debugfs_remove(adev->debugfs_regs); | ||
2004 | adev->debugfs_regs = NULL; | ||
2005 | } | ||
2006 | |||
2007 | int amdgpu_debugfs_init(struct drm_minor *minor) | ||
2008 | { | ||
2009 | return 0; | ||
2010 | } | ||
2011 | |||
2012 | void amdgpu_debugfs_cleanup(struct drm_minor *minor) | ||
2013 | { | ||
2014 | } | ||
2015 | #else | ||
2016 | static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) | ||
2017 | { | ||
2018 | return 0; | ||
2019 | } | ||
2020 | static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) { } | ||
2021 | #endif | ||