xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_device.c (revision 2ec7304030bccf420e4e85aec5c59ea8785fdecb)
1*2ec73040Sriastradh /*	$NetBSD: amdgpu_device.c,v 1.21 2024/07/01 12:09:52 riastradh Exp $	*/
2efa246c0Sriastradh 
3efa246c0Sriastradh /*
4efa246c0Sriastradh  * Copyright 2008 Advanced Micro Devices, Inc.
5efa246c0Sriastradh  * Copyright 2008 Red Hat Inc.
6efa246c0Sriastradh  * Copyright 2009 Jerome Glisse.
7efa246c0Sriastradh  *
8efa246c0Sriastradh  * Permission is hereby granted, free of charge, to any person obtaining a
9efa246c0Sriastradh  * copy of this software and associated documentation files (the "Software"),
10efa246c0Sriastradh  * to deal in the Software without restriction, including without limitation
11efa246c0Sriastradh  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12efa246c0Sriastradh  * and/or sell copies of the Software, and to permit persons to whom the
13efa246c0Sriastradh  * Software is furnished to do so, subject to the following conditions:
14efa246c0Sriastradh  *
15efa246c0Sriastradh  * The above copyright notice and this permission notice shall be included in
16efa246c0Sriastradh  * all copies or substantial portions of the Software.
17efa246c0Sriastradh  *
18efa246c0Sriastradh  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19efa246c0Sriastradh  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20efa246c0Sriastradh  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21efa246c0Sriastradh  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
22efa246c0Sriastradh  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23efa246c0Sriastradh  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24efa246c0Sriastradh  * OTHER DEALINGS IN THE SOFTWARE.
25efa246c0Sriastradh  *
26efa246c0Sriastradh  * Authors: Dave Airlie
27efa246c0Sriastradh  *          Alex Deucher
28efa246c0Sriastradh  *          Jerome Glisse
29efa246c0Sriastradh  */
30efa246c0Sriastradh #include <sys/cdefs.h>
31*2ec73040Sriastradh __KERNEL_RCSID(0, "$NetBSD: amdgpu_device.c,v 1.21 2024/07/01 12:09:52 riastradh Exp $");
32efa246c0Sriastradh 
3341ec0267Sriastradh #include <linux/power_supply.h>
3441ec0267Sriastradh #include <linux/kthread.h>
3541ec0267Sriastradh #include <linux/module.h>
36efa246c0Sriastradh #include <linux/console.h>
37efa246c0Sriastradh #include <linux/slab.h>
38dc219e9cSriastradh #include <linux/reboot.h>
3941ec0267Sriastradh 
4041ec0267Sriastradh #include <drm/drm_atomic_helper.h>
4141ec0267Sriastradh #include <drm/drm_probe_helper.h>
42efa246c0Sriastradh #include <drm/amdgpu_drm.h>
43efa246c0Sriastradh #include <linux/vgaarb.h>
44efa246c0Sriastradh #include <linux/vga_switcheroo.h>
45efa246c0Sriastradh #include <linux/efi.h>
46efa246c0Sriastradh #include "amdgpu.h"
4741ec0267Sriastradh #include "amdgpu_trace.h"
48efa246c0Sriastradh #include "amdgpu_i2c.h"
49efa246c0Sriastradh #include "atom.h"
50efa246c0Sriastradh #include "amdgpu_atombios.h"
5141ec0267Sriastradh #include "amdgpu_atomfirmware.h"
5241ec0267Sriastradh #include "amd_pcie.h"
5341ec0267Sriastradh #ifdef CONFIG_DRM_AMDGPU_SI
5441ec0267Sriastradh #include "si.h"
5541ec0267Sriastradh #endif
56efa246c0Sriastradh #ifdef CONFIG_DRM_AMDGPU_CIK
57efa246c0Sriastradh #include "cik.h"
58efa246c0Sriastradh #endif
59efa246c0Sriastradh #include "vi.h"
6041ec0267Sriastradh #include "soc15.h"
6141ec0267Sriastradh #include "nv.h"
62efa246c0Sriastradh #include "bif/bif_4_1_d.h"
6341ec0267Sriastradh #include <linux/pci.h>
6441ec0267Sriastradh #include <linux/firmware.h>
6541ec0267Sriastradh #include "amdgpu_vf_error.h"
66efa246c0Sriastradh 
6741ec0267Sriastradh #include "amdgpu_amdkfd.h"
6841ec0267Sriastradh #include "amdgpu_pm.h"
6941ec0267Sriastradh 
7041ec0267Sriastradh #include "amdgpu_xgmi.h"
7141ec0267Sriastradh #include "amdgpu_ras.h"
7241ec0267Sriastradh #include "amdgpu_pmu.h"
7341ec0267Sriastradh 
7441ec0267Sriastradh #include <linux/suspend.h>
7541ec0267Sriastradh #include <drm/task_barrier.h>
761b46a69aSriastradh #include <linux/nbsd-namespace.h>
771b46a69aSriastradh 
7841ec0267Sriastradh MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
7941ec0267Sriastradh MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
8041ec0267Sriastradh MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
8141ec0267Sriastradh MODULE_FIRMWARE("amdgpu/picasso_gpu_info.bin");
8241ec0267Sriastradh MODULE_FIRMWARE("amdgpu/raven2_gpu_info.bin");
8341ec0267Sriastradh MODULE_FIRMWARE("amdgpu/arcturus_gpu_info.bin");
8441ec0267Sriastradh MODULE_FIRMWARE("amdgpu/renoir_gpu_info.bin");
8541ec0267Sriastradh MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
8641ec0267Sriastradh MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin");
8741ec0267Sriastradh MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
88efa246c0Sriastradh 
8941ec0267Sriastradh #define AMDGPU_RESUME_MS		2000
9041ec0267Sriastradh 
9141ec0267Sriastradh const char *amdgpu_asic_name[] = {
9241ec0267Sriastradh 	"TAHITI",
9341ec0267Sriastradh 	"PITCAIRN",
9441ec0267Sriastradh 	"VERDE",
9541ec0267Sriastradh 	"OLAND",
9641ec0267Sriastradh 	"HAINAN",
97efa246c0Sriastradh 	"BONAIRE",
98efa246c0Sriastradh 	"KAVERI",
99efa246c0Sriastradh 	"KABINI",
100efa246c0Sriastradh 	"HAWAII",
101efa246c0Sriastradh 	"MULLINS",
102efa246c0Sriastradh 	"TOPAZ",
103efa246c0Sriastradh 	"TONGA",
104efa246c0Sriastradh 	"FIJI",
105efa246c0Sriastradh 	"CARRIZO",
106efa246c0Sriastradh 	"STONEY",
10741ec0267Sriastradh 	"POLARIS10",
10841ec0267Sriastradh 	"POLARIS11",
10941ec0267Sriastradh 	"POLARIS12",
11041ec0267Sriastradh 	"VEGAM",
11141ec0267Sriastradh 	"VEGA10",
11241ec0267Sriastradh 	"VEGA12",
11341ec0267Sriastradh 	"VEGA20",
11441ec0267Sriastradh 	"RAVEN",
11541ec0267Sriastradh 	"ARCTURUS",
11641ec0267Sriastradh 	"RENOIR",
11741ec0267Sriastradh 	"NAVI10",
11841ec0267Sriastradh 	"NAVI14",
11941ec0267Sriastradh 	"NAVI12",
120efa246c0Sriastradh 	"LAST",
121efa246c0Sriastradh };
122efa246c0Sriastradh 
12318c728deSriastradh #ifndef __NetBSD__		/* XXX amdgpu sysfs */
12418c728deSriastradh 
12541ec0267Sriastradh /**
12641ec0267Sriastradh  * DOC: pcie_replay_count
12741ec0267Sriastradh  *
12841ec0267Sriastradh  * The amdgpu driver provides a sysfs API for reporting the total number
12941ec0267Sriastradh  * of PCIe replays (NAKs)
13041ec0267Sriastradh  * The file pcie_replay_count is used for this and returns the total
13141ec0267Sriastradh  * number of replays as a sum of the NAKs generated and NAKs received
13241ec0267Sriastradh  */
13341ec0267Sriastradh 
amdgpu_device_get_pcie_replay_count(struct device * dev,struct device_attribute * attr,char * buf)13441ec0267Sriastradh static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev,
13541ec0267Sriastradh 		struct device_attribute *attr, char *buf)
13641ec0267Sriastradh {
13741ec0267Sriastradh 	struct drm_device *ddev = dev_get_drvdata(dev);
13841ec0267Sriastradh 	struct amdgpu_device *adev = ddev->dev_private;
13941ec0267Sriastradh 	uint64_t cnt = amdgpu_asic_get_pcie_replay_count(adev);
14041ec0267Sriastradh 
14141ec0267Sriastradh 	return snprintf(buf, PAGE_SIZE, "%llu\n", cnt);
14241ec0267Sriastradh }
14341ec0267Sriastradh 
14441ec0267Sriastradh static DEVICE_ATTR(pcie_replay_count, S_IRUGO,
14541ec0267Sriastradh 		amdgpu_device_get_pcie_replay_count, NULL);
14641ec0267Sriastradh 
14718c728deSriastradh #endif	/* __NetBSD__ */
14818c728deSriastradh 
14941ec0267Sriastradh static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
15041ec0267Sriastradh 
15141ec0267Sriastradh /**
15241ec0267Sriastradh  * amdgpu_device_supports_boco - Is the device a dGPU with HG/PX power control
15341ec0267Sriastradh  *
15441ec0267Sriastradh  * @dev: drm_device pointer
15541ec0267Sriastradh  *
15641ec0267Sriastradh  * Returns true if the device is a dGPU with HG/PX power control,
15741ec0267Sriastradh  * otherwise return false.
15841ec0267Sriastradh  */
amdgpu_device_supports_boco(struct drm_device * dev)15941ec0267Sriastradh bool amdgpu_device_supports_boco(struct drm_device *dev)
160efa246c0Sriastradh {
161efa246c0Sriastradh 	struct amdgpu_device *adev = dev->dev_private;
162efa246c0Sriastradh 
163efa246c0Sriastradh 	if (adev->flags & AMD_IS_PX)
164efa246c0Sriastradh 		return true;
165efa246c0Sriastradh 	return false;
166efa246c0Sriastradh }
167efa246c0Sriastradh 
16841ec0267Sriastradh /**
16941ec0267Sriastradh  * amdgpu_device_supports_baco - Does the device support BACO
17041ec0267Sriastradh  *
17141ec0267Sriastradh  * @dev: drm_device pointer
17241ec0267Sriastradh  *
17341ec0267Sriastradh  * Returns true if the device supporte BACO,
17441ec0267Sriastradh  * otherwise return false.
17541ec0267Sriastradh  */
amdgpu_device_supports_baco(struct drm_device * dev)17641ec0267Sriastradh bool amdgpu_device_supports_baco(struct drm_device *dev)
17741ec0267Sriastradh {
17841ec0267Sriastradh 	struct amdgpu_device *adev = dev->dev_private;
17941ec0267Sriastradh 
18041ec0267Sriastradh 	return amdgpu_asic_supports_baco(adev);
18141ec0267Sriastradh }
18241ec0267Sriastradh 
18341ec0267Sriastradh /**
18441ec0267Sriastradh  * VRAM access helper functions.
18541ec0267Sriastradh  *
18641ec0267Sriastradh  * amdgpu_device_vram_access - read/write a buffer in vram
18741ec0267Sriastradh  *
18841ec0267Sriastradh  * @adev: amdgpu_device pointer
18941ec0267Sriastradh  * @pos: offset of the buffer in vram
19041ec0267Sriastradh  * @buf: virtual address of the buffer in system memory
19141ec0267Sriastradh  * @size: read/write size, sizeof(@buf) must > @size
19241ec0267Sriastradh  * @write: true - write to vram, otherwise - read from vram
19341ec0267Sriastradh  */
amdgpu_device_vram_access(struct amdgpu_device * adev,loff_t pos,uint32_t * buf,size_t size,bool write)19441ec0267Sriastradh void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
19541ec0267Sriastradh 			       uint32_t *buf, size_t size, bool write)
19641ec0267Sriastradh {
19741ec0267Sriastradh 	uint64_t last;
19841ec0267Sriastradh 	unsigned long flags;
19941ec0267Sriastradh 
20041ec0267Sriastradh 	last = size - 4;
20141ec0267Sriastradh 	for (last += pos; pos <= last; pos += 4) {
20241ec0267Sriastradh 		spin_lock_irqsave(&adev->mmio_idx_lock, flags);
20341ec0267Sriastradh 		WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
20441ec0267Sriastradh 		WREG32_NO_KIQ(mmMM_INDEX_HI, pos >> 31);
20541ec0267Sriastradh 		if (write)
20641ec0267Sriastradh 			WREG32_NO_KIQ(mmMM_DATA, *buf++);
20741ec0267Sriastradh 		else
20841ec0267Sriastradh 			*buf++ = RREG32_NO_KIQ(mmMM_DATA);
20941ec0267Sriastradh 		spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
21041ec0267Sriastradh 	}
21141ec0267Sriastradh }
21241ec0267Sriastradh 
213efa246c0Sriastradh /*
214efa246c0Sriastradh  * MMIO register access helper functions.
215efa246c0Sriastradh  */
21641ec0267Sriastradh /**
21741ec0267Sriastradh  * amdgpu_mm_rreg - read a memory mapped IO register
21841ec0267Sriastradh  *
21941ec0267Sriastradh  * @adev: amdgpu_device pointer
22041ec0267Sriastradh  * @reg: dword aligned register offset
22141ec0267Sriastradh  * @acc_flags: access flags which require special behavior
22241ec0267Sriastradh  *
22341ec0267Sriastradh  * Returns the 32 bit value from the offset specified.
22441ec0267Sriastradh  */
amdgpu_mm_rreg(struct amdgpu_device * adev,uint32_t reg,uint32_t acc_flags)225efa246c0Sriastradh uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
22641ec0267Sriastradh 			uint32_t acc_flags)
227efa246c0Sriastradh {
22841ec0267Sriastradh 	uint32_t ret;
22941ec0267Sriastradh 
23041ec0267Sriastradh 	if ((acc_flags & AMDGPU_REGS_KIQ) || (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)))
23141ec0267Sriastradh 		return amdgpu_kiq_rreg(adev, reg);
23241ec0267Sriastradh 
23341ec0267Sriastradh 	if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX))
2340d50c49dSriastradh #ifdef __NetBSD__
2350d50c49dSriastradh 		return bus_space_read_4(adev->rmmiot, adev->rmmioh, 4*reg);
2360d50c49dSriastradh #else
23741ec0267Sriastradh 		ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
2380d50c49dSriastradh #endif
239efa246c0Sriastradh 	else {
240efa246c0Sriastradh 		unsigned long flags;
241efa246c0Sriastradh 
242efa246c0Sriastradh 		spin_lock_irqsave(&adev->mmio_idx_lock, flags);
2430d50c49dSriastradh #ifdef __NetBSD__
2440d50c49dSriastradh 		bus_space_write_4(adev->rmmiot, adev->rmmioh, 4*mmMM_INDEX,
2450d50c49dSriastradh 		    4*reg);
2460d50c49dSriastradh 		ret = bus_space_read_4(adev->rmmiot, adev->rmmioh,
24745e24dc2Sriastradh 		    4*mmMM_DATA);
2480d50c49dSriastradh #else
249efa246c0Sriastradh 		writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4));
250efa246c0Sriastradh 		ret = readl(((void __iomem *)adev->rmmio) + (mmMM_DATA * 4));
2510d50c49dSriastradh #endif
252efa246c0Sriastradh 		spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
25341ec0267Sriastradh 	}
25441ec0267Sriastradh 	trace_amdgpu_mm_rreg(adev->pdev->device, reg, ret);
255efa246c0Sriastradh 	return ret;
256efa246c0Sriastradh }
25741ec0267Sriastradh 
25841ec0267Sriastradh /*
25941ec0267Sriastradh  * MMIO register read with bytes helper functions
26041ec0267Sriastradh  * @offset:bytes offset from MMIO start
26141ec0267Sriastradh  *
26241ec0267Sriastradh */
26341ec0267Sriastradh 
26441ec0267Sriastradh /**
26541ec0267Sriastradh  * amdgpu_mm_rreg8 - read a memory mapped IO register
26641ec0267Sriastradh  *
26741ec0267Sriastradh  * @adev: amdgpu_device pointer
26841ec0267Sriastradh  * @offset: byte aligned register offset
26941ec0267Sriastradh  *
27041ec0267Sriastradh  * Returns the 8 bit value from the offset specified.
27141ec0267Sriastradh  */
amdgpu_mm_rreg8(struct amdgpu_device * adev,uint32_t offset)27241ec0267Sriastradh uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) {
27341ec0267Sriastradh 	if (offset < adev->rmmio_size)
27418c728deSriastradh #ifdef __NetBSD__
275d42a0131Sriastradh 		return bus_space_read_1(adev->rmmiot, adev->rmmioh, offset);
27618c728deSriastradh #else
27741ec0267Sriastradh 		return (readb(adev->rmmio + offset));
27818c728deSriastradh #endif
27941ec0267Sriastradh 	BUG();
280efa246c0Sriastradh }
281efa246c0Sriastradh 
28241ec0267Sriastradh /*
28341ec0267Sriastradh  * MMIO register write with bytes helper functions
28441ec0267Sriastradh  * @offset:bytes offset from MMIO start
28541ec0267Sriastradh  * @value: the value want to be written to the register
28641ec0267Sriastradh  *
28741ec0267Sriastradh */
28841ec0267Sriastradh /**
28941ec0267Sriastradh  * amdgpu_mm_wreg8 - read a memory mapped IO register
29041ec0267Sriastradh  *
29141ec0267Sriastradh  * @adev: amdgpu_device pointer
29241ec0267Sriastradh  * @offset: byte aligned register offset
29341ec0267Sriastradh  * @value: 8 bit value to write
29441ec0267Sriastradh  *
29541ec0267Sriastradh  * Writes the value specified to the offset specified.
29641ec0267Sriastradh  */
amdgpu_mm_wreg8(struct amdgpu_device * adev,uint32_t offset,uint8_t value)29741ec0267Sriastradh void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) {
29841ec0267Sriastradh 	if (offset < adev->rmmio_size)
29918c728deSriastradh #ifdef __NetBSD__
300d42a0131Sriastradh 		bus_space_write_1(adev->rmmiot, adev->rmmioh, offset, value);
30118c728deSriastradh #else
30241ec0267Sriastradh 		writeb(value, adev->rmmio + offset);
30318c728deSriastradh #endif
30441ec0267Sriastradh 	else
30541ec0267Sriastradh 		BUG();
30641ec0267Sriastradh }
30741ec0267Sriastradh 
30841ec0267Sriastradh /**
30941ec0267Sriastradh  * amdgpu_mm_wreg - write to a memory mapped IO register
31041ec0267Sriastradh  *
31141ec0267Sriastradh  * @adev: amdgpu_device pointer
31241ec0267Sriastradh  * @reg: dword aligned register offset
31341ec0267Sriastradh  * @v: 32 bit value to write to the register
31441ec0267Sriastradh  * @acc_flags: access flags which require special behavior
31541ec0267Sriastradh  *
31641ec0267Sriastradh  * Writes the value specified to the offset specified.
31741ec0267Sriastradh  */
amdgpu_mm_wreg(struct amdgpu_device * adev,uint32_t reg,uint32_t v,uint32_t acc_flags)318efa246c0Sriastradh void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
31941ec0267Sriastradh 		    uint32_t acc_flags)
320efa246c0Sriastradh {
32141ec0267Sriastradh 	trace_amdgpu_mm_wreg(adev->pdev->device, reg, v);
32241ec0267Sriastradh 
32341ec0267Sriastradh 	if (adev->asic_type >= CHIP_VEGA10 && reg == 0) {
32441ec0267Sriastradh 		adev->last_mm_index = v;
32541ec0267Sriastradh 	}
32641ec0267Sriastradh 
32741ec0267Sriastradh 	if ((acc_flags & AMDGPU_REGS_KIQ) || (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)))
32841ec0267Sriastradh 		return amdgpu_kiq_wreg(adev, reg, v);
32941ec0267Sriastradh 
33041ec0267Sriastradh 	if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX))
3310d50c49dSriastradh #ifdef __NetBSD__
3320d50c49dSriastradh 		bus_space_write_4(adev->rmmiot, adev->rmmioh, 4*reg, v);
3330d50c49dSriastradh #else
334efa246c0Sriastradh 		writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
3350d50c49dSriastradh #endif
336efa246c0Sriastradh 	else {
337efa246c0Sriastradh 		unsigned long flags;
338efa246c0Sriastradh 
339efa246c0Sriastradh 		spin_lock_irqsave(&adev->mmio_idx_lock, flags);
3400d50c49dSriastradh #ifdef __NetBSD__
3410d50c49dSriastradh 		bus_space_write_4(adev->rmmiot, adev->rmmioh, 4*mmMM_INDEX,
3420d50c49dSriastradh 		    reg*4);
3430d50c49dSriastradh 		bus_space_write_4(adev->rmmiot, adev->rmmioh, 4*mmMM_DATA, v);
3440d50c49dSriastradh #else
345efa246c0Sriastradh 		writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4));
346efa246c0Sriastradh 		writel(v, ((void __iomem *)adev->rmmio) + (mmMM_DATA * 4));
3470d50c49dSriastradh #endif
348efa246c0Sriastradh 		spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
349efa246c0Sriastradh 	}
35041ec0267Sriastradh 
35141ec0267Sriastradh 	if (adev->asic_type >= CHIP_VEGA10 && reg == 1 && adev->last_mm_index == 0x5702C) {
35241ec0267Sriastradh 		udelay(500);
35341ec0267Sriastradh 	}
354efa246c0Sriastradh }
355efa246c0Sriastradh 
35641ec0267Sriastradh /**
35741ec0267Sriastradh  * amdgpu_io_rreg - read an IO register
35841ec0267Sriastradh  *
35941ec0267Sriastradh  * @adev: amdgpu_device pointer
36041ec0267Sriastradh  * @reg: dword aligned register offset
36141ec0267Sriastradh  *
36241ec0267Sriastradh  * Returns the 32 bit value from the offset specified.
36341ec0267Sriastradh  */
amdgpu_io_rreg(struct amdgpu_device * adev,u32 reg)364efa246c0Sriastradh u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg)
365efa246c0Sriastradh {
366efa246c0Sriastradh 	if ((reg * 4) < adev->rio_mem_size)
3670d50c49dSriastradh #ifdef __NetBSD__
3680d50c49dSriastradh 		return bus_space_read_4(adev->rio_memt, adev->rio_memh, 4*reg);
3690d50c49dSriastradh #else
370efa246c0Sriastradh 		return ioread32(adev->rio_mem + (reg * 4));
3710d50c49dSriastradh #endif
372efa246c0Sriastradh 	else {
3730d50c49dSriastradh #ifdef __NetBSD__
3740d50c49dSriastradh 		bus_space_write_4(adev->rio_memt, adev->rio_memh, 4*mmMM_INDEX,
3750d50c49dSriastradh 		    4*reg);
3760d50c49dSriastradh 		return bus_space_read_4(adev->rio_memt, adev->rio_memh,
3770d50c49dSriastradh 		    4*mmMM_DATA);
3780d50c49dSriastradh #else
379efa246c0Sriastradh 		iowrite32((reg * 4), adev->rio_mem + (mmMM_INDEX * 4));
380efa246c0Sriastradh 		return ioread32(adev->rio_mem + (mmMM_DATA * 4));
3810d50c49dSriastradh #endif
382efa246c0Sriastradh 	}
383efa246c0Sriastradh }
384efa246c0Sriastradh 
38541ec0267Sriastradh /**
38641ec0267Sriastradh  * amdgpu_io_wreg - write to an IO register
38741ec0267Sriastradh  *
38841ec0267Sriastradh  * @adev: amdgpu_device pointer
38941ec0267Sriastradh  * @reg: dword aligned register offset
39041ec0267Sriastradh  * @v: 32 bit value to write to the register
39141ec0267Sriastradh  *
39241ec0267Sriastradh  * Writes the value specified to the offset specified.
39341ec0267Sriastradh  */
amdgpu_io_wreg(struct amdgpu_device * adev,u32 reg,u32 v)394efa246c0Sriastradh void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
395efa246c0Sriastradh {
39641ec0267Sriastradh 	if (adev->asic_type >= CHIP_VEGA10 && reg == 0) {
39741ec0267Sriastradh 		adev->last_mm_index = v;
39841ec0267Sriastradh 	}
399efa246c0Sriastradh 
400efa246c0Sriastradh 	if ((reg * 4) < adev->rio_mem_size)
4010d50c49dSriastradh #ifdef __NetBSD__
4020d50c49dSriastradh 		bus_space_write_4(adev->rio_memt, adev->rio_memh, 4*reg, v);
4030d50c49dSriastradh #else
404efa246c0Sriastradh 		iowrite32(v, adev->rio_mem + (reg * 4));
4050d50c49dSriastradh #endif
406efa246c0Sriastradh 	else {
4070d50c49dSriastradh #ifdef __NetBSD__
4080d50c49dSriastradh 		bus_space_write_4(adev->rio_memt, adev->rio_memh, 4*mmMM_INDEX,
4090d50c49dSriastradh 		    4*reg);
4100d50c49dSriastradh 		bus_space_write_4(adev->rio_memt, adev->rio_memh, 4*mmMM_DATA,
4110d50c49dSriastradh 		    v);
4120d50c49dSriastradh #else
413efa246c0Sriastradh 		iowrite32((reg * 4), adev->rio_mem + (mmMM_INDEX * 4));
414efa246c0Sriastradh 		iowrite32(v, adev->rio_mem + (mmMM_DATA * 4));
4150d50c49dSriastradh #endif
416efa246c0Sriastradh 	}
41741ec0267Sriastradh 
41841ec0267Sriastradh 	if (adev->asic_type >= CHIP_VEGA10 && reg == 1 && adev->last_mm_index == 0x5702C) {
41941ec0267Sriastradh 		udelay(500);
42041ec0267Sriastradh 	}
421efa246c0Sriastradh }
422efa246c0Sriastradh 
423efa246c0Sriastradh /**
424efa246c0Sriastradh  * amdgpu_mm_rdoorbell - read a doorbell dword
425efa246c0Sriastradh  *
426efa246c0Sriastradh  * @adev: amdgpu_device pointer
427efa246c0Sriastradh  * @index: doorbell index
428efa246c0Sriastradh  *
429efa246c0Sriastradh  * Returns the value in the doorbell aperture at the
430efa246c0Sriastradh  * requested doorbell index (CIK).
431efa246c0Sriastradh  */
amdgpu_mm_rdoorbell(struct amdgpu_device * adev,u32 index)432efa246c0Sriastradh u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index)
433efa246c0Sriastradh {
434efa246c0Sriastradh 	if (index < adev->doorbell.num_doorbells) {
4350d50c49dSriastradh #ifdef __NetBSD__
4360d50c49dSriastradh 		return bus_space_read_4(adev->doorbell.bst, adev->doorbell.bsh,
4370d50c49dSriastradh 		    4*index);
4380d50c49dSriastradh #else
439efa246c0Sriastradh 		return readl(adev->doorbell.ptr + index);
4400d50c49dSriastradh #endif
441efa246c0Sriastradh 	} else {
442efa246c0Sriastradh 		DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", index);
443efa246c0Sriastradh 		return 0;
444efa246c0Sriastradh 	}
445efa246c0Sriastradh }
446efa246c0Sriastradh 
447efa246c0Sriastradh /**
448efa246c0Sriastradh  * amdgpu_mm_wdoorbell - write a doorbell dword
449efa246c0Sriastradh  *
450efa246c0Sriastradh  * @adev: amdgpu_device pointer
451efa246c0Sriastradh  * @index: doorbell index
452efa246c0Sriastradh  * @v: value to write
453efa246c0Sriastradh  *
454efa246c0Sriastradh  * Writes @v to the doorbell aperture at the
455efa246c0Sriastradh  * requested doorbell index (CIK).
456efa246c0Sriastradh  */
amdgpu_mm_wdoorbell(struct amdgpu_device * adev,u32 index,u32 v)457efa246c0Sriastradh void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v)
458efa246c0Sriastradh {
459efa246c0Sriastradh 	if (index < adev->doorbell.num_doorbells) {
4600d50c49dSriastradh #ifdef __NetBSD__
4610d50c49dSriastradh 		bus_space_write_4(adev->doorbell.bst, adev->doorbell.bsh,
4620d50c49dSriastradh 		    4*index, v);
4630d50c49dSriastradh #else
464efa246c0Sriastradh 		writel(v, adev->doorbell.ptr + index);
4650d50c49dSriastradh #endif
466efa246c0Sriastradh 	} else {
467efa246c0Sriastradh 		DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", index);
468efa246c0Sriastradh 	}
469efa246c0Sriastradh }
470efa246c0Sriastradh 
471efa246c0Sriastradh /**
47241ec0267Sriastradh  * amdgpu_mm_rdoorbell64 - read a doorbell Qword
47341ec0267Sriastradh  *
47441ec0267Sriastradh  * @adev: amdgpu_device pointer
47541ec0267Sriastradh  * @index: doorbell index
47641ec0267Sriastradh  *
47741ec0267Sriastradh  * Returns the value in the doorbell aperture at the
47841ec0267Sriastradh  * requested doorbell index (VEGA10+).
47941ec0267Sriastradh  */
amdgpu_mm_rdoorbell64(struct amdgpu_device * adev,u32 index)48041ec0267Sriastradh u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index)
48141ec0267Sriastradh {
48241ec0267Sriastradh 	if (index < adev->doorbell.num_doorbells) {
48318c728deSriastradh #ifdef __NetBSD__
484b545a4abSriastradh #ifdef _LP64
48518c728deSriastradh 		return bus_space_read_8(adev->doorbell.bst, adev->doorbell.bsh,
486be8f7ff5Sriastradh 		    4*index);
48718c728deSriastradh #else
488b545a4abSriastradh 		uint64_t lo, hi;
489b545a4abSriastradh #if _BYTE_ORDER == _LITTLE_ENDIAN
490b545a4abSriastradh 		lo = bus_space_read_4(adev->doorbell.bst, adev->doorbell.bsh,
491be8f7ff5Sriastradh 		    4*index);
492b545a4abSriastradh 		hi = bus_space_read_4(adev->doorbell.bst, adev->doorbell.bsh,
493be8f7ff5Sriastradh 		    4*index + 4);
494b545a4abSriastradh #else
495b545a4abSriastradh 		hi = bus_space_read_4(adev->doorbell.bst, adev->doorbell.bsh,
496be8f7ff5Sriastradh 		    4*index);
497b545a4abSriastradh 		lo = bus_space_read_4(adev->doorbell.bst, adev->doorbell.bsh,
498be8f7ff5Sriastradh 		    4*index + 4);
499b545a4abSriastradh #endif
500b545a4abSriastradh 		return lo | (hi << 32);
501b545a4abSriastradh #endif
502b545a4abSriastradh #else
50341ec0267Sriastradh 		return atomic64_read((atomic64_t *)(adev->doorbell.ptr + index));
50418c728deSriastradh #endif
50541ec0267Sriastradh 	} else {
50641ec0267Sriastradh 		DRM_ERROR("reading beyond doorbell aperture: 0x%08x!\n", index);
50741ec0267Sriastradh 		return 0;
50841ec0267Sriastradh 	}
50941ec0267Sriastradh }
51041ec0267Sriastradh 
51141ec0267Sriastradh /**
51241ec0267Sriastradh  * amdgpu_mm_wdoorbell64 - write a doorbell Qword
51341ec0267Sriastradh  *
51441ec0267Sriastradh  * @adev: amdgpu_device pointer
51541ec0267Sriastradh  * @index: doorbell index
51641ec0267Sriastradh  * @v: value to write
51741ec0267Sriastradh  *
51841ec0267Sriastradh  * Writes @v to the doorbell aperture at the
51941ec0267Sriastradh  * requested doorbell index (VEGA10+).
52041ec0267Sriastradh  */
amdgpu_mm_wdoorbell64(struct amdgpu_device * adev,u32 index,u64 v)52141ec0267Sriastradh void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v)
52241ec0267Sriastradh {
52341ec0267Sriastradh 	if (index < adev->doorbell.num_doorbells) {
52418c728deSriastradh #ifdef __NetBSD__
525b545a4abSriastradh #ifdef _LP64
52618c728deSriastradh 		bus_space_write_8(adev->doorbell.bst, adev->doorbell.bsh,
527be8f7ff5Sriastradh 		    4*index, v);
52818c728deSriastradh #else
529f05f0733Sriastradh 		/*
530f05f0733Sriastradh 		 * XXX This might not be as atomic as one might hope...
531f05f0733Sriastradh 		 */
532b545a4abSriastradh #if _BYTE_ORDER == _LITTLE_ENDIAN
533b545a4abSriastradh 		bus_space_write_4(adev->doorbell.bst, adev->doorbell.bsh,
534be8f7ff5Sriastradh 		    4*index, v & 0xffffffffU);
535b545a4abSriastradh 		bus_space_write_4(adev->doorbell.bst, adev->doorbell.bsh,
536be8f7ff5Sriastradh 		    4*index + 4, v >> 32);
537b545a4abSriastradh #else
538b545a4abSriastradh 		bus_space_write_4(adev->doorbell.bst, adev->doorbell.bsh,
539be8f7ff5Sriastradh 		    4*index, v >> 32);
540b545a4abSriastradh 		bus_space_write_4(adev->doorbell.bst, adev->doorbell.bsh,
541be8f7ff5Sriastradh 		    4*index + 4, v & 0xffffffffU);
542b545a4abSriastradh #endif
543b545a4abSriastradh #endif
544b545a4abSriastradh #else
54541ec0267Sriastradh 		atomic64_set((atomic64_t *)(adev->doorbell.ptr + index), v);
54618c728deSriastradh #endif
54741ec0267Sriastradh 	} else {
54841ec0267Sriastradh 		DRM_ERROR("writing beyond doorbell aperture: 0x%08x!\n", index);
54941ec0267Sriastradh 	}
55041ec0267Sriastradh }
55141ec0267Sriastradh 
55241ec0267Sriastradh /**
553efa246c0Sriastradh  * amdgpu_invalid_rreg - dummy reg read function
554efa246c0Sriastradh  *
555efa246c0Sriastradh  * @adev: amdgpu device pointer
556efa246c0Sriastradh  * @reg: offset of register
557efa246c0Sriastradh  *
558efa246c0Sriastradh  * Dummy register read function.  Used for register blocks
559efa246c0Sriastradh  * that certain asics don't have (all asics).
560efa246c0Sriastradh  * Returns the value in the register.
561efa246c0Sriastradh  */
amdgpu_invalid_rreg(struct amdgpu_device * adev,uint32_t reg)562efa246c0Sriastradh static uint32_t amdgpu_invalid_rreg(struct amdgpu_device *adev, uint32_t reg)
563efa246c0Sriastradh {
564efa246c0Sriastradh 	DRM_ERROR("Invalid callback to read register 0x%04X\n", reg);
565efa246c0Sriastradh 	BUG();
566efa246c0Sriastradh 	return 0;
567efa246c0Sriastradh }
568efa246c0Sriastradh 
569efa246c0Sriastradh /**
570efa246c0Sriastradh  * amdgpu_invalid_wreg - dummy reg write function
571efa246c0Sriastradh  *
572efa246c0Sriastradh  * @adev: amdgpu device pointer
573efa246c0Sriastradh  * @reg: offset of register
574efa246c0Sriastradh  * @v: value to write to the register
575efa246c0Sriastradh  *
576efa246c0Sriastradh  * Dummy register read function.  Used for register blocks
577efa246c0Sriastradh  * that certain asics don't have (all asics).
578efa246c0Sriastradh  */
amdgpu_invalid_wreg(struct amdgpu_device * adev,uint32_t reg,uint32_t v)579efa246c0Sriastradh static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
580efa246c0Sriastradh {
581efa246c0Sriastradh 	DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n",
582efa246c0Sriastradh 		  reg, v);
583efa246c0Sriastradh 	BUG();
584efa246c0Sriastradh }
585efa246c0Sriastradh 
586efa246c0Sriastradh /**
58741ec0267Sriastradh  * amdgpu_invalid_rreg64 - dummy 64 bit reg read function
58841ec0267Sriastradh  *
58941ec0267Sriastradh  * @adev: amdgpu device pointer
59041ec0267Sriastradh  * @reg: offset of register
59141ec0267Sriastradh  *
59241ec0267Sriastradh  * Dummy register read function.  Used for register blocks
59341ec0267Sriastradh  * that certain asics don't have (all asics).
59441ec0267Sriastradh  * Returns the value in the register.
59541ec0267Sriastradh  */
amdgpu_invalid_rreg64(struct amdgpu_device * adev,uint32_t reg)59641ec0267Sriastradh static uint64_t amdgpu_invalid_rreg64(struct amdgpu_device *adev, uint32_t reg)
59741ec0267Sriastradh {
59841ec0267Sriastradh 	DRM_ERROR("Invalid callback to read 64 bit register 0x%04X\n", reg);
59941ec0267Sriastradh 	BUG();
60041ec0267Sriastradh 	return 0;
60141ec0267Sriastradh }
60241ec0267Sriastradh 
60341ec0267Sriastradh /**
60441ec0267Sriastradh  * amdgpu_invalid_wreg64 - dummy reg write function
60541ec0267Sriastradh  *
60641ec0267Sriastradh  * @adev: amdgpu device pointer
60741ec0267Sriastradh  * @reg: offset of register
60841ec0267Sriastradh  * @v: value to write to the register
60941ec0267Sriastradh  *
61041ec0267Sriastradh  * Dummy register read function.  Used for register blocks
61141ec0267Sriastradh  * that certain asics don't have (all asics).
61241ec0267Sriastradh  */
amdgpu_invalid_wreg64(struct amdgpu_device * adev,uint32_t reg,uint64_t v)61341ec0267Sriastradh static void amdgpu_invalid_wreg64(struct amdgpu_device *adev, uint32_t reg, uint64_t v)
61441ec0267Sriastradh {
615e1719879Sriastradh 	DRM_ERROR("Invalid callback to write 64 bit register 0x%04X with 0x%08"PRIX64"\n",
61641ec0267Sriastradh 		  reg, v);
61741ec0267Sriastradh 	BUG();
61841ec0267Sriastradh }
61941ec0267Sriastradh 
62041ec0267Sriastradh /**
621efa246c0Sriastradh  * amdgpu_block_invalid_rreg - dummy reg read function
622efa246c0Sriastradh  *
623efa246c0Sriastradh  * @adev: amdgpu device pointer
624efa246c0Sriastradh  * @block: offset of instance
625efa246c0Sriastradh  * @reg: offset of register
626efa246c0Sriastradh  *
627efa246c0Sriastradh  * Dummy register read function.  Used for register blocks
628efa246c0Sriastradh  * that certain asics don't have (all asics).
629efa246c0Sriastradh  * Returns the value in the register.
630efa246c0Sriastradh  */
amdgpu_block_invalid_rreg(struct amdgpu_device * adev,uint32_t block,uint32_t reg)631efa246c0Sriastradh static uint32_t amdgpu_block_invalid_rreg(struct amdgpu_device *adev,
632efa246c0Sriastradh 					  uint32_t block, uint32_t reg)
633efa246c0Sriastradh {
634efa246c0Sriastradh 	DRM_ERROR("Invalid callback to read register 0x%04X in block 0x%04X\n",
635efa246c0Sriastradh 		  reg, block);
636efa246c0Sriastradh 	BUG();
637efa246c0Sriastradh 	return 0;
638efa246c0Sriastradh }
639efa246c0Sriastradh 
640efa246c0Sriastradh /**
641efa246c0Sriastradh  * amdgpu_block_invalid_wreg - dummy reg write function
642efa246c0Sriastradh  *
643efa246c0Sriastradh  * @adev: amdgpu device pointer
644efa246c0Sriastradh  * @block: offset of instance
645efa246c0Sriastradh  * @reg: offset of register
646efa246c0Sriastradh  * @v: value to write to the register
647efa246c0Sriastradh  *
648efa246c0Sriastradh  * Dummy register read function.  Used for register blocks
649efa246c0Sriastradh  * that certain asics don't have (all asics).
650efa246c0Sriastradh  */
amdgpu_block_invalid_wreg(struct amdgpu_device * adev,uint32_t block,uint32_t reg,uint32_t v)651efa246c0Sriastradh static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev,
652efa246c0Sriastradh 				      uint32_t block,
653efa246c0Sriastradh 				      uint32_t reg, uint32_t v)
654efa246c0Sriastradh {
655efa246c0Sriastradh 	DRM_ERROR("Invalid block callback to write register 0x%04X in block 0x%04X with 0x%08X\n",
656efa246c0Sriastradh 		  reg, block, v);
657efa246c0Sriastradh 	BUG();
658efa246c0Sriastradh }
659efa246c0Sriastradh 
66041ec0267Sriastradh /**
66141ec0267Sriastradh  * amdgpu_device_vram_scratch_init - allocate the VRAM scratch page
66241ec0267Sriastradh  *
66341ec0267Sriastradh  * @adev: amdgpu device pointer
66441ec0267Sriastradh  *
66541ec0267Sriastradh  * Allocates a scratch page of VRAM for use by various things in the
66641ec0267Sriastradh  * driver.
66741ec0267Sriastradh  */
amdgpu_device_vram_scratch_init(struct amdgpu_device * adev)66841ec0267Sriastradh static int amdgpu_device_vram_scratch_init(struct amdgpu_device *adev)
669efa246c0Sriastradh {
67041ec0267Sriastradh 	return amdgpu_bo_create_kernel(adev, AMDGPU_GPU_PAGE_SIZE,
67141ec0267Sriastradh 				       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
67241ec0267Sriastradh 				       &adev->vram_scratch.robj,
67341ec0267Sriastradh 				       &adev->vram_scratch.gpu_addr,
6740d50c49dSriastradh 				       (void **)__UNVOLATILE(&adev->vram_scratch.ptr));
675efa246c0Sriastradh }
676efa246c0Sriastradh 
677efa246c0Sriastradh /**
67841ec0267Sriastradh  * amdgpu_device_vram_scratch_fini - Free the VRAM scratch page
67941ec0267Sriastradh  *
68041ec0267Sriastradh  * @adev: amdgpu device pointer
68141ec0267Sriastradh  *
68241ec0267Sriastradh  * Frees the VRAM scratch page.
68341ec0267Sriastradh  */
amdgpu_device_vram_scratch_fini(struct amdgpu_device * adev)68441ec0267Sriastradh static void amdgpu_device_vram_scratch_fini(struct amdgpu_device *adev)
68541ec0267Sriastradh {
68641ec0267Sriastradh 	amdgpu_bo_free_kernel(&adev->vram_scratch.robj, NULL, NULL);
68741ec0267Sriastradh }
68841ec0267Sriastradh 
68941ec0267Sriastradh /**
69041ec0267Sriastradh  * amdgpu_device_program_register_sequence - program an array of registers.
691efa246c0Sriastradh  *
692efa246c0Sriastradh  * @adev: amdgpu_device pointer
693efa246c0Sriastradh  * @registers: pointer to the register array
694efa246c0Sriastradh  * @array_size: size of the register array
695efa246c0Sriastradh  *
696efa246c0Sriastradh  * Programs an array or registers with and and or masks.
697efa246c0Sriastradh  * This is a helper for setting golden registers.
698efa246c0Sriastradh  */
amdgpu_device_program_register_sequence(struct amdgpu_device * adev,const u32 * registers,const u32 array_size)69941ec0267Sriastradh void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
700efa246c0Sriastradh 					     const u32 *registers,
701efa246c0Sriastradh 					     const u32 array_size)
702efa246c0Sriastradh {
703efa246c0Sriastradh 	u32 tmp, reg, and_mask, or_mask;
704efa246c0Sriastradh 	int i;
705efa246c0Sriastradh 
706efa246c0Sriastradh 	if (array_size % 3)
707efa246c0Sriastradh 		return;
708efa246c0Sriastradh 
709efa246c0Sriastradh 	for (i = 0; i < array_size; i +=3) {
710efa246c0Sriastradh 		reg = registers[i + 0];
711efa246c0Sriastradh 		and_mask = registers[i + 1];
712efa246c0Sriastradh 		or_mask = registers[i + 2];
713efa246c0Sriastradh 
714efa246c0Sriastradh 		if (and_mask == 0xffffffff) {
715efa246c0Sriastradh 			tmp = or_mask;
716efa246c0Sriastradh 		} else {
717efa246c0Sriastradh 			tmp = RREG32(reg);
718efa246c0Sriastradh 			tmp &= ~and_mask;
71941ec0267Sriastradh 			if (adev->family >= AMDGPU_FAMILY_AI)
72041ec0267Sriastradh 				tmp |= (or_mask & and_mask);
72141ec0267Sriastradh 			else
722efa246c0Sriastradh 				tmp |= or_mask;
723efa246c0Sriastradh 		}
724efa246c0Sriastradh 		WREG32(reg, tmp);
725efa246c0Sriastradh 	}
726efa246c0Sriastradh }
727efa246c0Sriastradh 
72841ec0267Sriastradh /**
72941ec0267Sriastradh  * amdgpu_device_pci_config_reset - reset the GPU
73041ec0267Sriastradh  *
73141ec0267Sriastradh  * @adev: amdgpu_device pointer
73241ec0267Sriastradh  *
73341ec0267Sriastradh  * Resets the GPU using the pci config reset sequence.
73441ec0267Sriastradh  * Only applicable to asics prior to vega10.
73541ec0267Sriastradh  */
amdgpu_device_pci_config_reset(struct amdgpu_device * adev)73641ec0267Sriastradh void amdgpu_device_pci_config_reset(struct amdgpu_device *adev)
737efa246c0Sriastradh {
738efa246c0Sriastradh 	pci_write_config_dword(adev->pdev, 0x7c, AMDGPU_ASIC_RESET_DATA);
739efa246c0Sriastradh }
740efa246c0Sriastradh 
741efa246c0Sriastradh /*
742efa246c0Sriastradh  * GPU doorbell aperture helpers function.
743efa246c0Sriastradh  */
744efa246c0Sriastradh /**
74541ec0267Sriastradh  * amdgpu_device_doorbell_init - Init doorbell driver information.
746efa246c0Sriastradh  *
747efa246c0Sriastradh  * @adev: amdgpu_device pointer
748efa246c0Sriastradh  *
749efa246c0Sriastradh  * Init doorbell driver information (CIK)
750efa246c0Sriastradh  * Returns 0 on success, error on failure.
751efa246c0Sriastradh  */
amdgpu_device_doorbell_init(struct amdgpu_device * adev)75241ec0267Sriastradh static int amdgpu_device_doorbell_init(struct amdgpu_device *adev)
753efa246c0Sriastradh {
75441ec0267Sriastradh 
75541ec0267Sriastradh 	/* No doorbell on SI hardware generation */
75641ec0267Sriastradh 	if (adev->asic_type < CHIP_BONAIRE) {
75741ec0267Sriastradh 		adev->doorbell.base = 0;
75841ec0267Sriastradh 		adev->doorbell.size = 0;
75941ec0267Sriastradh 		adev->doorbell.num_doorbells = 0;
760e1719879Sriastradh #ifndef __NetBSD__
76141ec0267Sriastradh 		adev->doorbell.ptr = NULL;
762e1719879Sriastradh #endif
76341ec0267Sriastradh 		return 0;
76441ec0267Sriastradh 	}
76541ec0267Sriastradh 
76641ec0267Sriastradh 	if (pci_resource_flags(adev->pdev, 2) & IORESOURCE_UNSET)
76741ec0267Sriastradh 		return -EINVAL;
76841ec0267Sriastradh 
76941ec0267Sriastradh 	amdgpu_asic_init_doorbell_index(adev);
7700d50c49dSriastradh 
771efa246c0Sriastradh 	/* doorbell bar mapping */
772efa246c0Sriastradh 	adev->doorbell.base = pci_resource_start(adev->pdev, 2);
773efa246c0Sriastradh 	adev->doorbell.size = pci_resource_len(adev->pdev, 2);
774efa246c0Sriastradh 
775efa246c0Sriastradh 	adev->doorbell.num_doorbells = min_t(u32, adev->doorbell.size / sizeof(u32),
77641ec0267Sriastradh 					     adev->doorbell_index.max_assignment+1);
777efa246c0Sriastradh 	if (adev->doorbell.num_doorbells == 0)
778efa246c0Sriastradh 		return -EINVAL;
779efa246c0Sriastradh 
78041ec0267Sriastradh 	/* For Vega, reserve and map two pages on doorbell BAR since SDMA
78141ec0267Sriastradh 	 * paging queue doorbell use the second page. The
78241ec0267Sriastradh 	 * AMDGPU_DOORBELL64_MAX_ASSIGNMENT definition assumes all the
78341ec0267Sriastradh 	 * doorbells are in the first page. So with paging queue enabled,
78441ec0267Sriastradh 	 * the max num_doorbells should + 1 page (0x400 in dword)
78541ec0267Sriastradh 	 */
78641ec0267Sriastradh 	if (adev->asic_type >= CHIP_VEGA10)
78741ec0267Sriastradh 		adev->doorbell.num_doorbells += 0x400;
78841ec0267Sriastradh 
7890d50c49dSriastradh #ifdef __NetBSD__
79041ec0267Sriastradh 	int r;
7910d50c49dSriastradh 	adev->doorbell.bst = adev->pdev->pd_pa.pa_memt;
7920d50c49dSriastradh 	/* XXX errno NetBSD->Linux */
7930d50c49dSriastradh 	r = -bus_space_map(adev->doorbell.bst, adev->doorbell.base,
7940d50c49dSriastradh 	    adev->doorbell.num_doorbells * sizeof(u32), 0,
7950d50c49dSriastradh 	    &adev->doorbell.bsh);
7960d50c49dSriastradh 	if (r)
7970d50c49dSriastradh 		return r;
7980d50c49dSriastradh #else
79941ec0267Sriastradh 	adev->doorbell.ptr = ioremap(adev->doorbell.base,
80041ec0267Sriastradh 				     adev->doorbell.num_doorbells *
80141ec0267Sriastradh 				     sizeof(u32));
80241ec0267Sriastradh 	if (adev->doorbell.ptr == NULL)
803efa246c0Sriastradh 		return -ENOMEM;
8040d50c49dSriastradh #endif
805efa246c0Sriastradh 
806efa246c0Sriastradh 	return 0;
807efa246c0Sriastradh }
808efa246c0Sriastradh 
809efa246c0Sriastradh /**
81041ec0267Sriastradh  * amdgpu_device_doorbell_fini - Tear down doorbell driver information.
811efa246c0Sriastradh  *
812efa246c0Sriastradh  * @adev: amdgpu_device pointer
813efa246c0Sriastradh  *
814efa246c0Sriastradh  * Tear down doorbell driver information (CIK)
815efa246c0Sriastradh  */
amdgpu_device_doorbell_fini(struct amdgpu_device * adev)81641ec0267Sriastradh static void amdgpu_device_doorbell_fini(struct amdgpu_device *adev)
817efa246c0Sriastradh {
8180d50c49dSriastradh #ifdef __NetBSD__
819333afef5Sriastradh 	if (adev->doorbell.num_doorbells) {
8200d50c49dSriastradh 		bus_space_unmap(adev->doorbell.bst, adev->doorbell.bsh,
8210d50c49dSriastradh 		    adev->doorbell.num_doorbells * sizeof(u32));
822333afef5Sriastradh 		adev->doorbell.num_doorbells = 0;
823333afef5Sriastradh 	}
8240d50c49dSriastradh #else
825efa246c0Sriastradh 	iounmap(adev->doorbell.ptr);
826efa246c0Sriastradh 	adev->doorbell.ptr = NULL;
8270d50c49dSriastradh #endif
828efa246c0Sriastradh }
829efa246c0Sriastradh 
83041ec0267Sriastradh 
831efa246c0Sriastradh 
832efa246c0Sriastradh /*
83341ec0267Sriastradh  * amdgpu_device_wb_*()
83441ec0267Sriastradh  * Writeback is the method by which the GPU updates special pages in memory
83541ec0267Sriastradh  * with the status of certain GPU events (fences, ring pointers,etc.).
836efa246c0Sriastradh  */
837efa246c0Sriastradh 
838efa246c0Sriastradh /**
83941ec0267Sriastradh  * amdgpu_device_wb_fini - Disable Writeback and free memory
840efa246c0Sriastradh  *
841efa246c0Sriastradh  * @adev: amdgpu_device pointer
842efa246c0Sriastradh  *
843efa246c0Sriastradh  * Disables Writeback and frees the Writeback memory (all asics).
844efa246c0Sriastradh  * Used at driver shutdown.
845efa246c0Sriastradh  */
amdgpu_device_wb_fini(struct amdgpu_device * adev)84641ec0267Sriastradh static void amdgpu_device_wb_fini(struct amdgpu_device *adev)
847efa246c0Sriastradh {
848efa246c0Sriastradh 	if (adev->wb.wb_obj) {
84941ec0267Sriastradh 		amdgpu_bo_free_kernel(&adev->wb.wb_obj,
85041ec0267Sriastradh 				      &adev->wb.gpu_addr,
851e1719879Sriastradh 				      (void **)__UNVOLATILE(&adev->wb.wb));
852efa246c0Sriastradh 		adev->wb.wb_obj = NULL;
853efa246c0Sriastradh 	}
854efa246c0Sriastradh }
855efa246c0Sriastradh 
856efa246c0Sriastradh /**
85741ec0267Sriastradh  * amdgpu_device_wb_init- Init Writeback driver info and allocate memory
858efa246c0Sriastradh  *
859efa246c0Sriastradh  * @adev: amdgpu_device pointer
860efa246c0Sriastradh  *
86141ec0267Sriastradh  * Initializes writeback and allocates writeback memory (all asics).
862efa246c0Sriastradh  * Used at driver startup.
863efa246c0Sriastradh  * Returns 0 on success or an -error on failure.
864efa246c0Sriastradh  */
amdgpu_device_wb_init(struct amdgpu_device * adev)86541ec0267Sriastradh static int amdgpu_device_wb_init(struct amdgpu_device *adev)
866efa246c0Sriastradh {
867efa246c0Sriastradh 	int r;
868efa246c0Sriastradh 
869efa246c0Sriastradh 	if (adev->wb.wb_obj == NULL) {
87041ec0267Sriastradh 		/* AMDGPU_MAX_WB * sizeof(uint32_t) * 8 = AMDGPU_MAX_WB 256bit slots */
87141ec0267Sriastradh 		r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t) * 8,
87241ec0267Sriastradh 					    PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
87341ec0267Sriastradh 					    &adev->wb.wb_obj, &adev->wb.gpu_addr,
874e1719879Sriastradh 					    (void **)__UNVOLATILE(&adev->wb.wb));
875efa246c0Sriastradh 		if (r) {
876efa246c0Sriastradh 			dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
877efa246c0Sriastradh 			return r;
878efa246c0Sriastradh 		}
879efa246c0Sriastradh 
880efa246c0Sriastradh 		adev->wb.num_wb = AMDGPU_MAX_WB;
881efa246c0Sriastradh 		memset(&adev->wb.used, 0, sizeof(adev->wb.used));
882efa246c0Sriastradh 
883efa246c0Sriastradh 		/* clear wb memory */
884e1719879Sriastradh 		memset(__UNVOLATILE(adev->wb.wb), 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);
885efa246c0Sriastradh 	}
886efa246c0Sriastradh 
887efa246c0Sriastradh 	return 0;
888efa246c0Sriastradh }
889efa246c0Sriastradh 
890efa246c0Sriastradh /**
89141ec0267Sriastradh  * amdgpu_device_wb_get - Allocate a wb entry
892efa246c0Sriastradh  *
893efa246c0Sriastradh  * @adev: amdgpu_device pointer
894efa246c0Sriastradh  * @wb: wb index
895efa246c0Sriastradh  *
896efa246c0Sriastradh  * Allocate a wb slot for use by the driver (all asics).
897efa246c0Sriastradh  * Returns 0 on success or -EINVAL on failure.
898efa246c0Sriastradh  */
amdgpu_device_wb_get(struct amdgpu_device * adev,u32 * wb)89941ec0267Sriastradh int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
900efa246c0Sriastradh {
901efa246c0Sriastradh 	unsigned long offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
90241ec0267Sriastradh 
903efa246c0Sriastradh 	if (offset < adev->wb.num_wb) {
904efa246c0Sriastradh 		__set_bit(offset, adev->wb.used);
90541ec0267Sriastradh 		*wb = offset << 3; /* convert to dw offset */
906efa246c0Sriastradh 		return 0;
907efa246c0Sriastradh 	} else {
908efa246c0Sriastradh 		return -EINVAL;
909efa246c0Sriastradh 	}
910efa246c0Sriastradh }
911efa246c0Sriastradh 
912efa246c0Sriastradh /**
91341ec0267Sriastradh  * amdgpu_device_wb_free - Free a wb entry
914efa246c0Sriastradh  *
915efa246c0Sriastradh  * @adev: amdgpu_device pointer
916efa246c0Sriastradh  * @wb: wb index
917efa246c0Sriastradh  *
918efa246c0Sriastradh  * Free a wb slot allocated for use by the driver (all asics)
919efa246c0Sriastradh  */
amdgpu_device_wb_free(struct amdgpu_device * adev,u32 wb)92041ec0267Sriastradh void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
921efa246c0Sriastradh {
92241ec0267Sriastradh 	wb >>= 3;
923efa246c0Sriastradh 	if (wb < adev->wb.num_wb)
924efa246c0Sriastradh 		__clear_bit(wb, adev->wb.used);
925efa246c0Sriastradh }
926efa246c0Sriastradh 
927efa246c0Sriastradh /**
92841ec0267Sriastradh  * amdgpu_device_resize_fb_bar - try to resize FB BAR
929efa246c0Sriastradh  *
93041ec0267Sriastradh  * @adev: amdgpu_device pointer
931efa246c0Sriastradh  *
93241ec0267Sriastradh  * Try to resize FB BAR to make all VRAM CPU accessible. We try very hard not
93341ec0267Sriastradh  * to fail, but if any of the BARs is not accessible after the size we abort
93441ec0267Sriastradh  * driver loading by returning -ENODEV.
935efa246c0Sriastradh  */
amdgpu_device_resize_fb_bar(struct amdgpu_device * adev)93641ec0267Sriastradh int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
937efa246c0Sriastradh {
93841ec0267Sriastradh 	u64 space_needed = roundup_pow_of_two(adev->gmc.real_vram_size);
93941ec0267Sriastradh 	u32 rbar_size = order_base_2(((space_needed >> 20) | 1)) - 1;
94041ec0267Sriastradh 	struct pci_bus *root;
94141ec0267Sriastradh 	struct resource *res;
94241ec0267Sriastradh 	unsigned i;
94341ec0267Sriastradh 	u16 cmd;
94441ec0267Sriastradh 	int r;
945efa246c0Sriastradh 
94641ec0267Sriastradh 	/* Bypass for VF */
94741ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
94841ec0267Sriastradh 		return 0;
94941ec0267Sriastradh 
950dc219e9cSriastradh #ifdef __NetBSD__		/* XXX amdgpu fb resize */
951dc219e9cSriastradh 	__USE(space_needed);
952dc219e9cSriastradh 	__USE(rbar_size);
953dc219e9cSriastradh 	__USE(root);
954dc219e9cSriastradh 	__USE(res);
955dc219e9cSriastradh 	__USE(i);
956dc219e9cSriastradh 	__USE(cmd);
957dc219e9cSriastradh 	__USE(r);
958dc219e9cSriastradh #else
959e1719879Sriastradh 
96041ec0267Sriastradh 	/* Check if the root BUS has 64bit memory resources */
96141ec0267Sriastradh 	root = adev->pdev->bus;
96241ec0267Sriastradh 	while (root->parent)
96341ec0267Sriastradh 		root = root->parent;
96441ec0267Sriastradh 
96541ec0267Sriastradh 	pci_bus_for_each_resource(root, res, i) {
96641ec0267Sriastradh 		if (res && res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) &&
96741ec0267Sriastradh 		    res->start > 0x100000000ull)
96841ec0267Sriastradh 			break;
969efa246c0Sriastradh 	}
970efa246c0Sriastradh 
97141ec0267Sriastradh 	/* Trying to resize is pointless without a root hub window above 4GB */
97241ec0267Sriastradh 	if (!res)
97341ec0267Sriastradh 		return 0;
97441ec0267Sriastradh 
97541ec0267Sriastradh 	/* Disable memory decoding while we change the BAR addresses and size */
97641ec0267Sriastradh 	pci_read_config_word(adev->pdev, PCI_COMMAND, &cmd);
97741ec0267Sriastradh 	pci_write_config_word(adev->pdev, PCI_COMMAND,
97841ec0267Sriastradh 			      cmd & ~PCI_COMMAND_MEMORY);
97941ec0267Sriastradh 
98041ec0267Sriastradh 	/* Free the VRAM and doorbell BAR, we most likely need to move both. */
98141ec0267Sriastradh 	amdgpu_device_doorbell_fini(adev);
98241ec0267Sriastradh 	if (adev->asic_type >= CHIP_BONAIRE)
98341ec0267Sriastradh 		pci_release_resource(adev->pdev, 2);
98441ec0267Sriastradh 
98541ec0267Sriastradh 	pci_release_resource(adev->pdev, 0);
98641ec0267Sriastradh 
98741ec0267Sriastradh 	r = pci_resize_resource(adev->pdev, 0, rbar_size);
98841ec0267Sriastradh 	if (r == -ENOSPC)
98941ec0267Sriastradh 		DRM_INFO("Not enough PCI address space for a large BAR.");
99041ec0267Sriastradh 	else if (r && r != -ENOTSUPP)
99141ec0267Sriastradh 		DRM_ERROR("Problem resizing BAR0 (%d).", r);
99241ec0267Sriastradh 
99341ec0267Sriastradh 	pci_assign_unassigned_bus_resources(adev->pdev->bus);
99441ec0267Sriastradh 
99541ec0267Sriastradh 	/* When the doorbell or fb BAR isn't available we have no chance of
99641ec0267Sriastradh 	 * using the device.
997efa246c0Sriastradh 	 */
99841ec0267Sriastradh 	r = amdgpu_device_doorbell_init(adev);
99941ec0267Sriastradh 	if (r || (pci_resource_flags(adev->pdev, 0) & IORESOURCE_UNSET))
100041ec0267Sriastradh 		return -ENODEV;
1001efa246c0Sriastradh 
100241ec0267Sriastradh 	pci_write_config_word(adev->pdev, PCI_COMMAND, cmd);
100341ec0267Sriastradh 
1004e1719879Sriastradh #endif
1005e1719879Sriastradh 
100641ec0267Sriastradh 	return 0;
1007efa246c0Sriastradh }
1008efa246c0Sriastradh 
1009efa246c0Sriastradh /*
1010efa246c0Sriastradh  * GPU helpers function.
1011efa246c0Sriastradh  */
1012efa246c0Sriastradh /**
101341ec0267Sriastradh  * amdgpu_device_need_post - check if the hw need post or not
1014efa246c0Sriastradh  *
1015efa246c0Sriastradh  * @adev: amdgpu_device pointer
1016efa246c0Sriastradh  *
101741ec0267Sriastradh  * Check if the asic has been initialized (all asics) at driver startup
101841ec0267Sriastradh  * or post is needed if  hw reset is performed.
101941ec0267Sriastradh  * Returns true if need or false if not.
1020efa246c0Sriastradh  */
amdgpu_device_need_post(struct amdgpu_device * adev)102141ec0267Sriastradh bool amdgpu_device_need_post(struct amdgpu_device *adev)
1022efa246c0Sriastradh {
1023efa246c0Sriastradh 	uint32_t reg;
1024efa246c0Sriastradh 
102541ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
1026efa246c0Sriastradh 		return false;
1027efa246c0Sriastradh 
102841ec0267Sriastradh 	if (amdgpu_passthrough(adev)) {
102941ec0267Sriastradh 		/* for FIJI: In whole GPU pass-through virtualization case, after VM reboot
103041ec0267Sriastradh 		 * some old smc fw still need driver do vPost otherwise gpu hang, while
103141ec0267Sriastradh 		 * those smc fw version above 22.15 doesn't have this flaw, so we force
103241ec0267Sriastradh 		 * vpost executed for smc version below 22.15
103341ec0267Sriastradh 		 */
103441ec0267Sriastradh 		if (adev->asic_type == CHIP_FIJI) {
103541ec0267Sriastradh 			int err;
103641ec0267Sriastradh 			uint32_t fw_ver;
103741ec0267Sriastradh 			err = request_firmware(&adev->pm.fw, "amdgpu/fiji_smc.bin", adev->dev);
103841ec0267Sriastradh 			/* force vPost if error occured */
103941ec0267Sriastradh 			if (err)
104041ec0267Sriastradh 				return true;
104141ec0267Sriastradh 
104241ec0267Sriastradh 			fw_ver = *((uint32_t *)adev->pm.fw->data + 69);
104341ec0267Sriastradh 			if (fw_ver < 0x00160e00)
104441ec0267Sriastradh 				return true;
104541ec0267Sriastradh 		}
1046efa246c0Sriastradh 	}
1047efa246c0Sriastradh 
104841ec0267Sriastradh 	if (adev->has_hw_reset) {
104941ec0267Sriastradh 		adev->has_hw_reset = false;
1050efa246c0Sriastradh 		return true;
105141ec0267Sriastradh 	}
1052efa246c0Sriastradh 
105341ec0267Sriastradh 	/* bios scratch used on CIK+ */
105441ec0267Sriastradh 	if (adev->asic_type >= CHIP_BONAIRE)
105541ec0267Sriastradh 		return amdgpu_atombios_scratch_need_asic_init(adev);
105641ec0267Sriastradh 
105741ec0267Sriastradh 	/* check MEM_SIZE for older asics */
105841ec0267Sriastradh 	reg = amdgpu_asic_get_config_memsize(adev);
105941ec0267Sriastradh 
106041ec0267Sriastradh 	if ((reg != 0) && (reg != 0xffffffff))
1061efa246c0Sriastradh 		return false;
1062efa246c0Sriastradh 
106341ec0267Sriastradh 	return true;
1064efa246c0Sriastradh }
1065efa246c0Sriastradh 
10660d50c49dSriastradh #ifndef __NetBSD__		/* XXX amdgpu vga */
1067efa246c0Sriastradh /* if we get transitioned to only one device, take VGA back */
1068efa246c0Sriastradh /**
106941ec0267Sriastradh  * amdgpu_device_vga_set_decode - enable/disable vga decode
1070efa246c0Sriastradh  *
1071efa246c0Sriastradh  * @cookie: amdgpu_device pointer
1072efa246c0Sriastradh  * @state: enable/disable vga decode
1073efa246c0Sriastradh  *
1074efa246c0Sriastradh  * Enable/disable vga decode (all asics).
1075efa246c0Sriastradh  * Returns VGA resource flags.
1076efa246c0Sriastradh  */
amdgpu_device_vga_set_decode(void * cookie,bool state)107741ec0267Sriastradh static unsigned int amdgpu_device_vga_set_decode(void *cookie, bool state)
1078efa246c0Sriastradh {
1079efa246c0Sriastradh 	struct amdgpu_device *adev = cookie;
1080efa246c0Sriastradh 	amdgpu_asic_set_vga_state(adev, state);
1081efa246c0Sriastradh 	if (state)
1082efa246c0Sriastradh 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
1083efa246c0Sriastradh 		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
1084efa246c0Sriastradh 	else
1085efa246c0Sriastradh 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
1086efa246c0Sriastradh }
10870d50c49dSriastradh #endif	/* __NetBSD__ */
1088efa246c0Sriastradh 
1089efa246c0Sriastradh /**
109041ec0267Sriastradh  * amdgpu_device_check_block_size - validate the vm block size
1091efa246c0Sriastradh  *
109241ec0267Sriastradh  * @adev: amdgpu_device pointer
1093efa246c0Sriastradh  *
109441ec0267Sriastradh  * Validates the vm block size specified via module parameter.
109541ec0267Sriastradh  * The vm block size defines number of bits in page table versus page directory,
109641ec0267Sriastradh  * a page is 4KB so we have 12 bits offset, minimum 9 bits in the
109741ec0267Sriastradh  * page table and the remaining bits are in the page directory.
1098efa246c0Sriastradh  */
amdgpu_device_check_block_size(struct amdgpu_device * adev)109941ec0267Sriastradh static void amdgpu_device_check_block_size(struct amdgpu_device *adev)
1100efa246c0Sriastradh {
110141ec0267Sriastradh 	/* defines number of bits in page table versus page directory,
110241ec0267Sriastradh 	 * a page is 4KB so we have 12 bits offset, minimum 9 bits in the
110341ec0267Sriastradh 	 * page table and the remaining bits are in the page directory */
110441ec0267Sriastradh 	if (amdgpu_vm_block_size == -1)
110541ec0267Sriastradh 		return;
110641ec0267Sriastradh 
110741ec0267Sriastradh 	if (amdgpu_vm_block_size < 9) {
110841ec0267Sriastradh 		dev_warn(adev->dev, "VM page table size (%d) too small\n",
110941ec0267Sriastradh 			 amdgpu_vm_block_size);
111041ec0267Sriastradh 		amdgpu_vm_block_size = -1;
111141ec0267Sriastradh 	}
1112efa246c0Sriastradh }
1113efa246c0Sriastradh 
1114efa246c0Sriastradh /**
111541ec0267Sriastradh  * amdgpu_device_check_vm_size - validate the vm size
111641ec0267Sriastradh  *
111741ec0267Sriastradh  * @adev: amdgpu_device pointer
111841ec0267Sriastradh  *
111941ec0267Sriastradh  * Validates the vm size in GB specified via module parameter.
112041ec0267Sriastradh  * The VM size is the size of the GPU virtual memory space in GB.
112141ec0267Sriastradh  */
amdgpu_device_check_vm_size(struct amdgpu_device * adev)112241ec0267Sriastradh static void amdgpu_device_check_vm_size(struct amdgpu_device *adev)
112341ec0267Sriastradh {
112441ec0267Sriastradh 	/* no need to check the default value */
112541ec0267Sriastradh 	if (amdgpu_vm_size == -1)
112641ec0267Sriastradh 		return;
112741ec0267Sriastradh 
112841ec0267Sriastradh 	if (amdgpu_vm_size < 1) {
112941ec0267Sriastradh 		dev_warn(adev->dev, "VM size (%d) too small, min is 1GB\n",
113041ec0267Sriastradh 			 amdgpu_vm_size);
113141ec0267Sriastradh 		amdgpu_vm_size = -1;
113241ec0267Sriastradh 	}
113341ec0267Sriastradh }
113441ec0267Sriastradh 
amdgpu_device_check_smu_prv_buffer_size(struct amdgpu_device * adev)113541ec0267Sriastradh static void amdgpu_device_check_smu_prv_buffer_size(struct amdgpu_device *adev)
113641ec0267Sriastradh {
113741ec0267Sriastradh 	struct sysinfo si;
113841ec0267Sriastradh 	bool is_os_64 = (sizeof(void *) == 8);
113941ec0267Sriastradh 	uint64_t total_memory;
114041ec0267Sriastradh 	uint64_t dram_size_seven_GB = 0x1B8000000;
114141ec0267Sriastradh 	uint64_t dram_size_three_GB = 0xB8000000;
114241ec0267Sriastradh 
114341ec0267Sriastradh 	if (amdgpu_smu_memory_pool_size == 0)
114441ec0267Sriastradh 		return;
114541ec0267Sriastradh 
114641ec0267Sriastradh 	if (!is_os_64) {
114741ec0267Sriastradh 		DRM_WARN("Not 64-bit OS, feature not supported\n");
114841ec0267Sriastradh 		goto def_value;
114941ec0267Sriastradh 	}
115041ec0267Sriastradh 	si_meminfo(&si);
115141ec0267Sriastradh 	total_memory = (uint64_t)si.totalram * si.mem_unit;
115241ec0267Sriastradh 
115341ec0267Sriastradh 	if ((amdgpu_smu_memory_pool_size == 1) ||
115441ec0267Sriastradh 		(amdgpu_smu_memory_pool_size == 2)) {
115541ec0267Sriastradh 		if (total_memory < dram_size_three_GB)
115641ec0267Sriastradh 			goto def_value1;
115741ec0267Sriastradh 	} else if ((amdgpu_smu_memory_pool_size == 4) ||
115841ec0267Sriastradh 		(amdgpu_smu_memory_pool_size == 8)) {
115941ec0267Sriastradh 		if (total_memory < dram_size_seven_GB)
116041ec0267Sriastradh 			goto def_value1;
116141ec0267Sriastradh 	} else {
116241ec0267Sriastradh 		DRM_WARN("Smu memory pool size not supported\n");
116341ec0267Sriastradh 		goto def_value;
116441ec0267Sriastradh 	}
116541ec0267Sriastradh 	adev->pm.smu_prv_buffer_size = amdgpu_smu_memory_pool_size << 28;
116641ec0267Sriastradh 
116741ec0267Sriastradh 	return;
116841ec0267Sriastradh 
116941ec0267Sriastradh def_value1:
117041ec0267Sriastradh 	DRM_WARN("No enough system memory\n");
117141ec0267Sriastradh def_value:
117241ec0267Sriastradh 	adev->pm.smu_prv_buffer_size = 0;
117341ec0267Sriastradh }
117441ec0267Sriastradh 
117541ec0267Sriastradh /**
117641ec0267Sriastradh  * amdgpu_device_check_arguments - validate module params
1177efa246c0Sriastradh  *
1178efa246c0Sriastradh  * @adev: amdgpu_device pointer
1179efa246c0Sriastradh  *
1180efa246c0Sriastradh  * Validates certain module parameters and updates
1181efa246c0Sriastradh  * the associated values used by the driver (all asics).
1182efa246c0Sriastradh  */
amdgpu_device_check_arguments(struct amdgpu_device * adev)118341ec0267Sriastradh static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
1184efa246c0Sriastradh {
118541ec0267Sriastradh 	if (amdgpu_sched_jobs < 4) {
118641ec0267Sriastradh 		dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n",
118741ec0267Sriastradh 			 amdgpu_sched_jobs);
118841ec0267Sriastradh 		amdgpu_sched_jobs = 4;
118941ec0267Sriastradh 	} else if (!is_power_of_2(amdgpu_sched_jobs)){
119041ec0267Sriastradh 		dev_warn(adev->dev, "sched jobs (%d) must be a power of 2\n",
119141ec0267Sriastradh 			 amdgpu_sched_jobs);
119241ec0267Sriastradh 		amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs);
1193efa246c0Sriastradh 	}
1194efa246c0Sriastradh 
119541ec0267Sriastradh 	if (amdgpu_gart_size != -1 && amdgpu_gart_size < 32) {
119641ec0267Sriastradh 		/* gart size must be greater or equal to 32M */
1197efa246c0Sriastradh 		dev_warn(adev->dev, "gart size (%d) too small\n",
1198efa246c0Sriastradh 			 amdgpu_gart_size);
1199efa246c0Sriastradh 		amdgpu_gart_size = -1;
1200efa246c0Sriastradh 	}
1201efa246c0Sriastradh 
120241ec0267Sriastradh 	if (amdgpu_gtt_size != -1 && amdgpu_gtt_size < 32) {
120341ec0267Sriastradh 		/* gtt size must be greater or equal to 32M */
120441ec0267Sriastradh 		dev_warn(adev->dev, "gtt size (%d) too small\n",
120541ec0267Sriastradh 				 amdgpu_gtt_size);
120641ec0267Sriastradh 		amdgpu_gtt_size = -1;
1207efa246c0Sriastradh 	}
1208efa246c0Sriastradh 
120941ec0267Sriastradh 	/* valid range is between 4 and 9 inclusive */
121041ec0267Sriastradh 	if (amdgpu_vm_fragment_size != -1 &&
121141ec0267Sriastradh 	    (amdgpu_vm_fragment_size > 9 || amdgpu_vm_fragment_size < 4)) {
121241ec0267Sriastradh 		dev_warn(adev->dev, "valid range is between 4 and 9\n");
121341ec0267Sriastradh 		amdgpu_vm_fragment_size = -1;
1214efa246c0Sriastradh 	}
1215efa246c0Sriastradh 
121641ec0267Sriastradh 	amdgpu_device_check_smu_prv_buffer_size(adev);
1217efa246c0Sriastradh 
121841ec0267Sriastradh 	amdgpu_device_check_vm_size(adev);
1219efa246c0Sriastradh 
122041ec0267Sriastradh 	amdgpu_device_check_block_size(adev);
1221efa246c0Sriastradh 
122241ec0267Sriastradh 	adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
1223efa246c0Sriastradh 
122441ec0267Sriastradh 	return 0;
1225efa246c0Sriastradh }
1226efa246c0Sriastradh 
12270d50c49dSriastradh #ifndef __NetBSD__		/* XXX amdgpu vga */
1228efa246c0Sriastradh /**
1229efa246c0Sriastradh  * amdgpu_switcheroo_set_state - set switcheroo state
1230efa246c0Sriastradh  *
1231efa246c0Sriastradh  * @pdev: pci dev pointer
1232efa246c0Sriastradh  * @state: vga_switcheroo state
1233efa246c0Sriastradh  *
1234efa246c0Sriastradh  * Callback for the switcheroo driver.  Suspends or resumes the
1235efa246c0Sriastradh  * the asics before or after it is powered up using ACPI methods.
1236efa246c0Sriastradh  */
amdgpu_switcheroo_set_state(struct pci_dev * pdev,enum vga_switcheroo_state state)1237efa246c0Sriastradh static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
1238efa246c0Sriastradh {
1239efa246c0Sriastradh 	struct drm_device *dev = pci_get_drvdata(pdev);
124041ec0267Sriastradh 	int r;
1241efa246c0Sriastradh 
124241ec0267Sriastradh 	if (amdgpu_device_supports_boco(dev) && state == VGA_SWITCHEROO_OFF)
1243efa246c0Sriastradh 		return;
1244efa246c0Sriastradh 
1245efa246c0Sriastradh 	if (state == VGA_SWITCHEROO_ON) {
124641ec0267Sriastradh 		pr_info("amdgpu: switched on\n");
1247efa246c0Sriastradh 		/* don't suspend or resume card normally */
1248efa246c0Sriastradh 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
1249efa246c0Sriastradh 
125041ec0267Sriastradh #ifndef __NetBSD__		/* pmf handles this for us.  */
125141ec0267Sriastradh 		pci_set_power_state(dev->pdev, PCI_D0);
125241ec0267Sriastradh 		pci_restore_state(dev->pdev);
125341ec0267Sriastradh 		r = pci_enable_device(dev->pdev);
125441ec0267Sriastradh 		if (r)
125541ec0267Sriastradh 			DRM_WARN("pci_enable_device failed (%d)\n", r);
125641ec0267Sriastradh #endif
125741ec0267Sriastradh 		amdgpu_device_resume(dev, true);
1258efa246c0Sriastradh 
1259efa246c0Sriastradh 		dev->switch_power_state = DRM_SWITCH_POWER_ON;
1260efa246c0Sriastradh 		drm_kms_helper_poll_enable(dev);
1261efa246c0Sriastradh 	} else {
126241ec0267Sriastradh 		pr_info("amdgpu: switched off\n");
1263efa246c0Sriastradh 		drm_kms_helper_poll_disable(dev);
1264efa246c0Sriastradh 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
126541ec0267Sriastradh 		amdgpu_device_suspend(dev, true);
126641ec0267Sriastradh #ifndef __NetBSD__		/* pmf handles this for us.  */
126741ec0267Sriastradh 		pci_save_state(dev->pdev);
126841ec0267Sriastradh 		/* Shut down the device */
126941ec0267Sriastradh 		pci_disable_device(dev->pdev);
127041ec0267Sriastradh 		pci_set_power_state(dev->pdev, PCI_D3cold);
1271efa246c0Sriastradh 		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
127241ec0267Sriastradh #endif
1273efa246c0Sriastradh 	}
1274efa246c0Sriastradh }
1275efa246c0Sriastradh 
1276efa246c0Sriastradh /**
1277efa246c0Sriastradh  * amdgpu_switcheroo_can_switch - see if switcheroo state can change
1278efa246c0Sriastradh  *
1279efa246c0Sriastradh  * @pdev: pci dev pointer
1280efa246c0Sriastradh  *
1281efa246c0Sriastradh  * Callback for the switcheroo driver.  Check of the switcheroo
1282efa246c0Sriastradh  * state can be changed.
1283efa246c0Sriastradh  * Returns true if the state can be changed, false if not.
1284efa246c0Sriastradh  */
amdgpu_switcheroo_can_switch(struct pci_dev * pdev)1285efa246c0Sriastradh static bool amdgpu_switcheroo_can_switch(struct pci_dev *pdev)
1286efa246c0Sriastradh {
1287efa246c0Sriastradh 	struct drm_device *dev = pci_get_drvdata(pdev);
1288efa246c0Sriastradh 
1289efa246c0Sriastradh 	/*
1290efa246c0Sriastradh 	* FIXME: open_count is protected by drm_global_mutex but that would lead to
1291efa246c0Sriastradh 	* locking inversion with the driver load path. And the access here is
1292efa246c0Sriastradh 	* completely racy anyway. So don't bother with locking for now.
1293efa246c0Sriastradh 	*/
1294efa246c0Sriastradh 	return dev->open_count == 0;
1295efa246c0Sriastradh }
1296efa246c0Sriastradh 
1297efa246c0Sriastradh static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = {
1298efa246c0Sriastradh 	.set_gpu_state = amdgpu_switcheroo_set_state,
1299efa246c0Sriastradh 	.reprobe = NULL,
1300efa246c0Sriastradh 	.can_switch = amdgpu_switcheroo_can_switch,
1301efa246c0Sriastradh };
13020d50c49dSriastradh #endif	/* __NetBSD__ */
1303efa246c0Sriastradh 
130441ec0267Sriastradh /**
130541ec0267Sriastradh  * amdgpu_device_ip_set_clockgating_state - set the CG state
130641ec0267Sriastradh  *
130741ec0267Sriastradh  * @dev: amdgpu_device pointer
130841ec0267Sriastradh  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
130941ec0267Sriastradh  * @state: clockgating state (gate or ungate)
131041ec0267Sriastradh  *
131141ec0267Sriastradh  * Sets the requested clockgating state for all instances of
131241ec0267Sriastradh  * the hardware IP specified.
131341ec0267Sriastradh  * Returns the error code from the last instance.
131441ec0267Sriastradh  */
amdgpu_device_ip_set_clockgating_state(void * dev,enum amd_ip_block_type block_type,enum amd_clockgating_state state)131541ec0267Sriastradh int amdgpu_device_ip_set_clockgating_state(void *dev,
1316efa246c0Sriastradh 					   enum amd_ip_block_type block_type,
1317efa246c0Sriastradh 					   enum amd_clockgating_state state)
1318efa246c0Sriastradh {
131941ec0267Sriastradh 	struct amdgpu_device *adev = dev;
1320efa246c0Sriastradh 	int i, r = 0;
1321efa246c0Sriastradh 
1322efa246c0Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
132341ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
132441ec0267Sriastradh 			continue;
132541ec0267Sriastradh 		if (adev->ip_blocks[i].version->type != block_type)
132641ec0267Sriastradh 			continue;
132741ec0267Sriastradh 		if (!adev->ip_blocks[i].version->funcs->set_clockgating_state)
132841ec0267Sriastradh 			continue;
132941ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->set_clockgating_state(
133041ec0267Sriastradh 			(void *)adev, state);
1331efa246c0Sriastradh 		if (r)
133241ec0267Sriastradh 			DRM_ERROR("set_clockgating_state of IP block <%s> failed %d\n",
133341ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
1334efa246c0Sriastradh 	}
1335efa246c0Sriastradh 	return r;
1336efa246c0Sriastradh }
1337efa246c0Sriastradh 
133841ec0267Sriastradh /**
133941ec0267Sriastradh  * amdgpu_device_ip_set_powergating_state - set the PG state
134041ec0267Sriastradh  *
134141ec0267Sriastradh  * @dev: amdgpu_device pointer
134241ec0267Sriastradh  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
134341ec0267Sriastradh  * @state: powergating state (gate or ungate)
134441ec0267Sriastradh  *
134541ec0267Sriastradh  * Sets the requested powergating state for all instances of
134641ec0267Sriastradh  * the hardware IP specified.
134741ec0267Sriastradh  * Returns the error code from the last instance.
134841ec0267Sriastradh  */
amdgpu_device_ip_set_powergating_state(void * dev,enum amd_ip_block_type block_type,enum amd_powergating_state state)134941ec0267Sriastradh int amdgpu_device_ip_set_powergating_state(void *dev,
1350efa246c0Sriastradh 					   enum amd_ip_block_type block_type,
1351efa246c0Sriastradh 					   enum amd_powergating_state state)
1352efa246c0Sriastradh {
135341ec0267Sriastradh 	struct amdgpu_device *adev = dev;
1354efa246c0Sriastradh 	int i, r = 0;
1355efa246c0Sriastradh 
1356efa246c0Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
135741ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
135841ec0267Sriastradh 			continue;
135941ec0267Sriastradh 		if (adev->ip_blocks[i].version->type != block_type)
136041ec0267Sriastradh 			continue;
136141ec0267Sriastradh 		if (!adev->ip_blocks[i].version->funcs->set_powergating_state)
136241ec0267Sriastradh 			continue;
136341ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->set_powergating_state(
136441ec0267Sriastradh 			(void *)adev, state);
1365efa246c0Sriastradh 		if (r)
136641ec0267Sriastradh 			DRM_ERROR("set_powergating_state of IP block <%s> failed %d\n",
136741ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
1368efa246c0Sriastradh 	}
1369efa246c0Sriastradh 	return r;
1370efa246c0Sriastradh }
1371efa246c0Sriastradh 
137241ec0267Sriastradh /**
137341ec0267Sriastradh  * amdgpu_device_ip_get_clockgating_state - get the CG state
137441ec0267Sriastradh  *
137541ec0267Sriastradh  * @adev: amdgpu_device pointer
137641ec0267Sriastradh  * @flags: clockgating feature flags
137741ec0267Sriastradh  *
137841ec0267Sriastradh  * Walks the list of IPs on the device and updates the clockgating
137941ec0267Sriastradh  * flags for each IP.
138041ec0267Sriastradh  * Updates @flags with the feature flags for each hardware IP where
138141ec0267Sriastradh  * clockgating is enabled.
138241ec0267Sriastradh  */
amdgpu_device_ip_get_clockgating_state(struct amdgpu_device * adev,u32 * flags)138341ec0267Sriastradh void amdgpu_device_ip_get_clockgating_state(struct amdgpu_device *adev,
138441ec0267Sriastradh 					    u32 *flags)
138541ec0267Sriastradh {
138641ec0267Sriastradh 	int i;
138741ec0267Sriastradh 
138841ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
138941ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
139041ec0267Sriastradh 			continue;
139141ec0267Sriastradh 		if (adev->ip_blocks[i].version->funcs->get_clockgating_state)
139241ec0267Sriastradh 			adev->ip_blocks[i].version->funcs->get_clockgating_state((void *)adev, flags);
139341ec0267Sriastradh 	}
139441ec0267Sriastradh }
139541ec0267Sriastradh 
139641ec0267Sriastradh /**
139741ec0267Sriastradh  * amdgpu_device_ip_wait_for_idle - wait for idle
139841ec0267Sriastradh  *
139941ec0267Sriastradh  * @adev: amdgpu_device pointer
140041ec0267Sriastradh  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
140141ec0267Sriastradh  *
140241ec0267Sriastradh  * Waits for the request hardware IP to be idle.
140341ec0267Sriastradh  * Returns 0 for success or a negative error code on failure.
140441ec0267Sriastradh  */
amdgpu_device_ip_wait_for_idle(struct amdgpu_device * adev,enum amd_ip_block_type block_type)140541ec0267Sriastradh int amdgpu_device_ip_wait_for_idle(struct amdgpu_device *adev,
140641ec0267Sriastradh 				   enum amd_ip_block_type block_type)
140741ec0267Sriastradh {
140841ec0267Sriastradh 	int i, r;
140941ec0267Sriastradh 
141041ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
141141ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
141241ec0267Sriastradh 			continue;
141341ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == block_type) {
141441ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->wait_for_idle((void *)adev);
141541ec0267Sriastradh 			if (r)
141641ec0267Sriastradh 				return r;
141741ec0267Sriastradh 			break;
141841ec0267Sriastradh 		}
141941ec0267Sriastradh 	}
142041ec0267Sriastradh 	return 0;
142141ec0267Sriastradh 
142241ec0267Sriastradh }
142341ec0267Sriastradh 
142441ec0267Sriastradh /**
142541ec0267Sriastradh  * amdgpu_device_ip_is_idle - is the hardware IP idle
142641ec0267Sriastradh  *
142741ec0267Sriastradh  * @adev: amdgpu_device pointer
142841ec0267Sriastradh  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
142941ec0267Sriastradh  *
143041ec0267Sriastradh  * Check if the hardware IP is idle or not.
143141ec0267Sriastradh  * Returns true if it the IP is idle, false if not.
143241ec0267Sriastradh  */
amdgpu_device_ip_is_idle(struct amdgpu_device * adev,enum amd_ip_block_type block_type)143341ec0267Sriastradh bool amdgpu_device_ip_is_idle(struct amdgpu_device *adev,
143441ec0267Sriastradh 			      enum amd_ip_block_type block_type)
143541ec0267Sriastradh {
143641ec0267Sriastradh 	int i;
143741ec0267Sriastradh 
143841ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
143941ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
144041ec0267Sriastradh 			continue;
144141ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == block_type)
144241ec0267Sriastradh 			return adev->ip_blocks[i].version->funcs->is_idle((void *)adev);
144341ec0267Sriastradh 	}
144441ec0267Sriastradh 	return true;
144541ec0267Sriastradh 
144641ec0267Sriastradh }
144741ec0267Sriastradh 
144841ec0267Sriastradh /**
144941ec0267Sriastradh  * amdgpu_device_ip_get_ip_block - get a hw IP pointer
145041ec0267Sriastradh  *
145141ec0267Sriastradh  * @adev: amdgpu_device pointer
145241ec0267Sriastradh  * @type: Type of hardware IP (SMU, GFX, UVD, etc.)
145341ec0267Sriastradh  *
145441ec0267Sriastradh  * Returns a pointer to the hardware IP block structure
145541ec0267Sriastradh  * if it exists for the asic, otherwise NULL.
145641ec0267Sriastradh  */
145741ec0267Sriastradh struct amdgpu_ip_block *
amdgpu_device_ip_get_ip_block(struct amdgpu_device * adev,enum amd_ip_block_type type)145841ec0267Sriastradh amdgpu_device_ip_get_ip_block(struct amdgpu_device *adev,
1459efa246c0Sriastradh 			      enum amd_ip_block_type type)
1460efa246c0Sriastradh {
1461efa246c0Sriastradh 	int i;
1462efa246c0Sriastradh 
1463efa246c0Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++)
146441ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == type)
1465efa246c0Sriastradh 			return &adev->ip_blocks[i];
1466efa246c0Sriastradh 
1467efa246c0Sriastradh 	return NULL;
1468efa246c0Sriastradh }
1469efa246c0Sriastradh 
1470efa246c0Sriastradh /**
147141ec0267Sriastradh  * amdgpu_device_ip_block_version_cmp
1472efa246c0Sriastradh  *
1473efa246c0Sriastradh  * @adev: amdgpu_device pointer
1474efa246c0Sriastradh  * @type: enum amd_ip_block_type
1475efa246c0Sriastradh  * @major: major version
1476efa246c0Sriastradh  * @minor: minor version
1477efa246c0Sriastradh  *
1478efa246c0Sriastradh  * return 0 if equal or greater
1479efa246c0Sriastradh  * return 1 if smaller or the ip_block doesn't exist
1480efa246c0Sriastradh  */
amdgpu_device_ip_block_version_cmp(struct amdgpu_device * adev,enum amd_ip_block_type type,u32 major,u32 minor)148141ec0267Sriastradh int amdgpu_device_ip_block_version_cmp(struct amdgpu_device *adev,
1482efa246c0Sriastradh 				       enum amd_ip_block_type type,
1483efa246c0Sriastradh 				       u32 major, u32 minor)
1484efa246c0Sriastradh {
148541ec0267Sriastradh 	struct amdgpu_ip_block *ip_block = amdgpu_device_ip_get_ip_block(adev, type);
1486efa246c0Sriastradh 
148741ec0267Sriastradh 	if (ip_block && ((ip_block->version->major > major) ||
148841ec0267Sriastradh 			((ip_block->version->major == major) &&
148941ec0267Sriastradh 			(ip_block->version->minor >= minor))))
1490efa246c0Sriastradh 		return 0;
1491efa246c0Sriastradh 
1492efa246c0Sriastradh 	return 1;
1493efa246c0Sriastradh }
1494efa246c0Sriastradh 
149541ec0267Sriastradh /**
149641ec0267Sriastradh  * amdgpu_device_ip_block_add
149741ec0267Sriastradh  *
149841ec0267Sriastradh  * @adev: amdgpu_device pointer
149941ec0267Sriastradh  * @ip_block_version: pointer to the IP to add
150041ec0267Sriastradh  *
150141ec0267Sriastradh  * Adds the IP block driver information to the collection of IPs
150241ec0267Sriastradh  * on the asic.
150341ec0267Sriastradh  */
amdgpu_device_ip_block_add(struct amdgpu_device * adev,const struct amdgpu_ip_block_version * ip_block_version)150441ec0267Sriastradh int amdgpu_device_ip_block_add(struct amdgpu_device *adev,
150541ec0267Sriastradh 			       const struct amdgpu_ip_block_version *ip_block_version)
1506efa246c0Sriastradh {
150741ec0267Sriastradh 	if (!ip_block_version)
150841ec0267Sriastradh 		return -EINVAL;
150941ec0267Sriastradh 
151041ec0267Sriastradh 	DRM_INFO("add ip block number %d <%s>\n", adev->num_ip_blocks,
151141ec0267Sriastradh 		  ip_block_version->funcs->name);
151241ec0267Sriastradh 
151341ec0267Sriastradh 	adev->ip_blocks[adev->num_ip_blocks++].version = ip_block_version;
151441ec0267Sriastradh 
151541ec0267Sriastradh 	return 0;
151641ec0267Sriastradh }
151741ec0267Sriastradh 
151841ec0267Sriastradh /**
151941ec0267Sriastradh  * amdgpu_device_enable_virtual_display - enable virtual display feature
152041ec0267Sriastradh  *
152141ec0267Sriastradh  * @adev: amdgpu_device pointer
152241ec0267Sriastradh  *
152341ec0267Sriastradh  * Enabled the virtual display feature if the user has enabled it via
152441ec0267Sriastradh  * the module parameter virtual_display.  This feature provides a virtual
152541ec0267Sriastradh  * display hardware on headless boards or in virtualized environments.
152641ec0267Sriastradh  * This function parses and validates the configuration string specified by
152741ec0267Sriastradh  * the user and configues the virtual display configuration (number of
152841ec0267Sriastradh  * virtual connectors, crtcs, etc.) specified.
152941ec0267Sriastradh  */
amdgpu_device_enable_virtual_display(struct amdgpu_device * adev)153041ec0267Sriastradh static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
153141ec0267Sriastradh {
153241ec0267Sriastradh 	adev->enable_virtual_display = false;
153341ec0267Sriastradh 
153441ec0267Sriastradh 	if (amdgpu_virtual_display) {
153541ec0267Sriastradh 		struct drm_device *ddev = adev->ddev;
153641ec0267Sriastradh 		const char *pci_address_name = pci_name(ddev->pdev);
153741ec0267Sriastradh 		char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname;
153841ec0267Sriastradh 
153941ec0267Sriastradh 		pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL);
154041ec0267Sriastradh 		pciaddstr_tmp = pciaddstr;
154141ec0267Sriastradh 		while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) {
154241ec0267Sriastradh 			pciaddname = strsep(&pciaddname_tmp, ",");
154341ec0267Sriastradh 			if (!strcmp("all", pciaddname)
154441ec0267Sriastradh 			    || !strcmp(pci_address_name, pciaddname)) {
154541ec0267Sriastradh 				long num_crtc;
154641ec0267Sriastradh 				int res = -1;
154741ec0267Sriastradh 
154841ec0267Sriastradh 				adev->enable_virtual_display = true;
154941ec0267Sriastradh 
155041ec0267Sriastradh 				if (pciaddname_tmp)
155141ec0267Sriastradh 					res = kstrtol(pciaddname_tmp, 10,
155241ec0267Sriastradh 						      &num_crtc);
155341ec0267Sriastradh 
155441ec0267Sriastradh 				if (!res) {
155541ec0267Sriastradh 					if (num_crtc < 1)
155641ec0267Sriastradh 						num_crtc = 1;
155741ec0267Sriastradh 					if (num_crtc > 6)
155841ec0267Sriastradh 						num_crtc = 6;
155941ec0267Sriastradh 					adev->mode_info.num_crtc = num_crtc;
156041ec0267Sriastradh 				} else {
156141ec0267Sriastradh 					adev->mode_info.num_crtc = 1;
156241ec0267Sriastradh 				}
156341ec0267Sriastradh 				break;
156441ec0267Sriastradh 			}
156541ec0267Sriastradh 		}
156641ec0267Sriastradh 
156741ec0267Sriastradh 		DRM_INFO("virtual display string:%s, %s:virtual_display:%d, num_crtc:%d\n",
156841ec0267Sriastradh 			 amdgpu_virtual_display, pci_address_name,
156941ec0267Sriastradh 			 adev->enable_virtual_display, adev->mode_info.num_crtc);
157041ec0267Sriastradh 
157141ec0267Sriastradh 		kfree(pciaddstr);
157241ec0267Sriastradh 	}
157341ec0267Sriastradh }
157441ec0267Sriastradh 
157541ec0267Sriastradh /**
157641ec0267Sriastradh  * amdgpu_device_parse_gpu_info_fw - parse gpu info firmware
157741ec0267Sriastradh  *
157841ec0267Sriastradh  * @adev: amdgpu_device pointer
157941ec0267Sriastradh  *
158041ec0267Sriastradh  * Parses the asic configuration parameters specified in the gpu info
158141ec0267Sriastradh  * firmware and makes them availale to the driver for use in configuring
158241ec0267Sriastradh  * the asic.
158341ec0267Sriastradh  * Returns 0 on success, -EINVAL on failure.
158441ec0267Sriastradh  */
amdgpu_device_parse_gpu_info_fw(struct amdgpu_device * adev)158541ec0267Sriastradh static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
158641ec0267Sriastradh {
158741ec0267Sriastradh 	const char *chip_name;
158841ec0267Sriastradh 	char fw_name[30];
158941ec0267Sriastradh 	int err;
159041ec0267Sriastradh 	const struct gpu_info_firmware_header_v1_0 *hdr;
159141ec0267Sriastradh 
159241ec0267Sriastradh 	adev->firmware.gpu_info_fw = NULL;
1593efa246c0Sriastradh 
1594efa246c0Sriastradh 	switch (adev->asic_type) {
1595efa246c0Sriastradh 	case CHIP_TOPAZ:
1596efa246c0Sriastradh 	case CHIP_TONGA:
1597efa246c0Sriastradh 	case CHIP_FIJI:
159841ec0267Sriastradh 	case CHIP_POLARIS10:
159941ec0267Sriastradh 	case CHIP_POLARIS11:
160041ec0267Sriastradh 	case CHIP_POLARIS12:
160141ec0267Sriastradh 	case CHIP_VEGAM:
160241ec0267Sriastradh 	case CHIP_CARRIZO:
160341ec0267Sriastradh 	case CHIP_STONEY:
160441ec0267Sriastradh #ifdef CONFIG_DRM_AMDGPU_SI
160541ec0267Sriastradh 	case CHIP_VERDE:
160641ec0267Sriastradh 	case CHIP_TAHITI:
160741ec0267Sriastradh 	case CHIP_PITCAIRN:
160841ec0267Sriastradh 	case CHIP_OLAND:
160941ec0267Sriastradh 	case CHIP_HAINAN:
161041ec0267Sriastradh #endif
161141ec0267Sriastradh #ifdef CONFIG_DRM_AMDGPU_CIK
161241ec0267Sriastradh 	case CHIP_BONAIRE:
161341ec0267Sriastradh 	case CHIP_HAWAII:
161441ec0267Sriastradh 	case CHIP_KAVERI:
161541ec0267Sriastradh 	case CHIP_KABINI:
161641ec0267Sriastradh 	case CHIP_MULLINS:
161741ec0267Sriastradh #endif
161841ec0267Sriastradh 	case CHIP_VEGA20:
161941ec0267Sriastradh 	default:
162041ec0267Sriastradh 		return 0;
162141ec0267Sriastradh 	case CHIP_VEGA10:
162241ec0267Sriastradh 		chip_name = "vega10";
162341ec0267Sriastradh 		break;
162441ec0267Sriastradh 	case CHIP_VEGA12:
162541ec0267Sriastradh 		chip_name = "vega12";
162641ec0267Sriastradh 		break;
162741ec0267Sriastradh 	case CHIP_RAVEN:
162841ec0267Sriastradh 		if (adev->rev_id >= 8)
162941ec0267Sriastradh 			chip_name = "raven2";
163041ec0267Sriastradh 		else if (adev->pdev->device == 0x15d8)
163141ec0267Sriastradh 			chip_name = "picasso";
163241ec0267Sriastradh 		else
163341ec0267Sriastradh 			chip_name = "raven";
163441ec0267Sriastradh 		break;
163541ec0267Sriastradh 	case CHIP_ARCTURUS:
163641ec0267Sriastradh 		chip_name = "arcturus";
163741ec0267Sriastradh 		break;
163841ec0267Sriastradh 	case CHIP_RENOIR:
163941ec0267Sriastradh 		chip_name = "renoir";
164041ec0267Sriastradh 		break;
164141ec0267Sriastradh 	case CHIP_NAVI10:
164241ec0267Sriastradh 		chip_name = "navi10";
164341ec0267Sriastradh 		break;
164441ec0267Sriastradh 	case CHIP_NAVI14:
164541ec0267Sriastradh 		chip_name = "navi14";
164641ec0267Sriastradh 		break;
164741ec0267Sriastradh 	case CHIP_NAVI12:
164841ec0267Sriastradh 		chip_name = "navi12";
164941ec0267Sriastradh 		break;
165041ec0267Sriastradh 	}
165141ec0267Sriastradh 
165241ec0267Sriastradh 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
165341ec0267Sriastradh 	err = request_firmware(&adev->firmware.gpu_info_fw, fw_name, adev->dev);
165441ec0267Sriastradh 	if (err) {
165541ec0267Sriastradh 		dev_err(adev->dev,
165641ec0267Sriastradh 			"Failed to load gpu_info firmware \"%s\"\n",
165741ec0267Sriastradh 			fw_name);
165841ec0267Sriastradh 		goto out;
165941ec0267Sriastradh 	}
166041ec0267Sriastradh 	err = amdgpu_ucode_validate(adev->firmware.gpu_info_fw);
166141ec0267Sriastradh 	if (err) {
166241ec0267Sriastradh 		dev_err(adev->dev,
166341ec0267Sriastradh 			"Failed to validate gpu_info firmware \"%s\"\n",
166441ec0267Sriastradh 			fw_name);
166541ec0267Sriastradh 		goto out;
166641ec0267Sriastradh 	}
166741ec0267Sriastradh 
166841ec0267Sriastradh 	hdr = (const struct gpu_info_firmware_header_v1_0 *)adev->firmware.gpu_info_fw->data;
166941ec0267Sriastradh 	amdgpu_ucode_print_gpu_info_hdr(&hdr->header);
167041ec0267Sriastradh 
167141ec0267Sriastradh 	switch (hdr->version_major) {
167241ec0267Sriastradh 	case 1:
167341ec0267Sriastradh 	{
167441ec0267Sriastradh 		const struct gpu_info_firmware_v1_0 *gpu_info_fw =
167541ec0267Sriastradh 			(const struct gpu_info_firmware_v1_0 *)(adev->firmware.gpu_info_fw->data +
167641ec0267Sriastradh 								le32_to_cpu(hdr->header.ucode_array_offset_bytes));
167741ec0267Sriastradh 
167841ec0267Sriastradh 		if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10)
167941ec0267Sriastradh 			goto parse_soc_bounding_box;
168041ec0267Sriastradh 
168141ec0267Sriastradh 		adev->gfx.config.max_shader_engines = le32_to_cpu(gpu_info_fw->gc_num_se);
168241ec0267Sriastradh 		adev->gfx.config.max_cu_per_sh = le32_to_cpu(gpu_info_fw->gc_num_cu_per_sh);
168341ec0267Sriastradh 		adev->gfx.config.max_sh_per_se = le32_to_cpu(gpu_info_fw->gc_num_sh_per_se);
168441ec0267Sriastradh 		adev->gfx.config.max_backends_per_se = le32_to_cpu(gpu_info_fw->gc_num_rb_per_se);
168541ec0267Sriastradh 		adev->gfx.config.max_texture_channel_caches =
168641ec0267Sriastradh 			le32_to_cpu(gpu_info_fw->gc_num_tccs);
168741ec0267Sriastradh 		adev->gfx.config.max_gprs = le32_to_cpu(gpu_info_fw->gc_num_gprs);
168841ec0267Sriastradh 		adev->gfx.config.max_gs_threads = le32_to_cpu(gpu_info_fw->gc_num_max_gs_thds);
168941ec0267Sriastradh 		adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gpu_info_fw->gc_gs_table_depth);
169041ec0267Sriastradh 		adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gpu_info_fw->gc_gsprim_buff_depth);
169141ec0267Sriastradh 		adev->gfx.config.double_offchip_lds_buf =
169241ec0267Sriastradh 			le32_to_cpu(gpu_info_fw->gc_double_offchip_lds_buffer);
169341ec0267Sriastradh 		adev->gfx.cu_info.wave_front_size = le32_to_cpu(gpu_info_fw->gc_wave_size);
169441ec0267Sriastradh 		adev->gfx.cu_info.max_waves_per_simd =
169541ec0267Sriastradh 			le32_to_cpu(gpu_info_fw->gc_max_waves_per_simd);
169641ec0267Sriastradh 		adev->gfx.cu_info.max_scratch_slots_per_cu =
169741ec0267Sriastradh 			le32_to_cpu(gpu_info_fw->gc_max_scratch_slots_per_cu);
169841ec0267Sriastradh 		adev->gfx.cu_info.lds_size = le32_to_cpu(gpu_info_fw->gc_lds_size);
169941ec0267Sriastradh 		if (hdr->version_minor >= 1) {
170041ec0267Sriastradh 			const struct gpu_info_firmware_v1_1 *gpu_info_fw =
170141ec0267Sriastradh 				(const struct gpu_info_firmware_v1_1 *)(adev->firmware.gpu_info_fw->data +
170241ec0267Sriastradh 									le32_to_cpu(hdr->header.ucode_array_offset_bytes));
170341ec0267Sriastradh 			adev->gfx.config.num_sc_per_sh =
170441ec0267Sriastradh 				le32_to_cpu(gpu_info_fw->num_sc_per_sh);
170541ec0267Sriastradh 			adev->gfx.config.num_packer_per_sc =
170641ec0267Sriastradh 				le32_to_cpu(gpu_info_fw->num_packer_per_sc);
170741ec0267Sriastradh 		}
170841ec0267Sriastradh 
170941ec0267Sriastradh parse_soc_bounding_box:
171041ec0267Sriastradh 		/*
171141ec0267Sriastradh 		 * soc bounding box info is not integrated in disocovery table,
171241ec0267Sriastradh 		 * we always need to parse it from gpu info firmware.
171341ec0267Sriastradh 		 */
171441ec0267Sriastradh 		if (hdr->version_minor == 2) {
171541ec0267Sriastradh 			const struct gpu_info_firmware_v1_2 *gpu_info_fw =
171641ec0267Sriastradh 				(const struct gpu_info_firmware_v1_2 *)(adev->firmware.gpu_info_fw->data +
171741ec0267Sriastradh 									le32_to_cpu(hdr->header.ucode_array_offset_bytes));
171841ec0267Sriastradh 			adev->dm.soc_bounding_box = &gpu_info_fw->soc_bounding_box;
171941ec0267Sriastradh 		}
172041ec0267Sriastradh 		break;
172141ec0267Sriastradh 	}
172241ec0267Sriastradh 	default:
172341ec0267Sriastradh 		dev_err(adev->dev,
172441ec0267Sriastradh 			"Unsupported gpu_info table %d\n", hdr->header.ucode_version);
172541ec0267Sriastradh 		err = -EINVAL;
172641ec0267Sriastradh 		goto out;
172741ec0267Sriastradh 	}
172841ec0267Sriastradh out:
172941ec0267Sriastradh 	return err;
173041ec0267Sriastradh }
173141ec0267Sriastradh 
173241ec0267Sriastradh /**
173341ec0267Sriastradh  * amdgpu_device_ip_early_init - run early init for hardware IPs
173441ec0267Sriastradh  *
173541ec0267Sriastradh  * @adev: amdgpu_device pointer
173641ec0267Sriastradh  *
173741ec0267Sriastradh  * Early initialization pass for hardware IPs.  The hardware IPs that make
173841ec0267Sriastradh  * up each asic are discovered each IP's early_init callback is run.  This
173941ec0267Sriastradh  * is the first stage in initializing the asic.
174041ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
174141ec0267Sriastradh  */
amdgpu_device_ip_early_init(struct amdgpu_device * adev)174241ec0267Sriastradh static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
174341ec0267Sriastradh {
174441ec0267Sriastradh 	int i, r;
174541ec0267Sriastradh 
174641ec0267Sriastradh 	amdgpu_device_enable_virtual_display(adev);
174741ec0267Sriastradh 
174841ec0267Sriastradh 	switch (adev->asic_type) {
174941ec0267Sriastradh 	case CHIP_TOPAZ:
175041ec0267Sriastradh 	case CHIP_TONGA:
175141ec0267Sriastradh 	case CHIP_FIJI:
175241ec0267Sriastradh 	case CHIP_POLARIS10:
175341ec0267Sriastradh 	case CHIP_POLARIS11:
175441ec0267Sriastradh 	case CHIP_POLARIS12:
175541ec0267Sriastradh 	case CHIP_VEGAM:
1756efa246c0Sriastradh 	case CHIP_CARRIZO:
1757efa246c0Sriastradh 	case CHIP_STONEY:
1758efa246c0Sriastradh 		if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
1759efa246c0Sriastradh 			adev->family = AMDGPU_FAMILY_CZ;
1760efa246c0Sriastradh 		else
1761efa246c0Sriastradh 			adev->family = AMDGPU_FAMILY_VI;
1762efa246c0Sriastradh 
1763efa246c0Sriastradh 		r = vi_set_ip_blocks(adev);
1764efa246c0Sriastradh 		if (r)
1765efa246c0Sriastradh 			return r;
1766efa246c0Sriastradh 		break;
176741ec0267Sriastradh #ifdef CONFIG_DRM_AMDGPU_SI
176841ec0267Sriastradh 	case CHIP_VERDE:
176941ec0267Sriastradh 	case CHIP_TAHITI:
177041ec0267Sriastradh 	case CHIP_PITCAIRN:
177141ec0267Sriastradh 	case CHIP_OLAND:
177241ec0267Sriastradh 	case CHIP_HAINAN:
177341ec0267Sriastradh 		adev->family = AMDGPU_FAMILY_SI;
177441ec0267Sriastradh 		r = si_set_ip_blocks(adev);
177541ec0267Sriastradh 		if (r)
177641ec0267Sriastradh 			return r;
177741ec0267Sriastradh 		break;
177841ec0267Sriastradh #endif
1779efa246c0Sriastradh #ifdef CONFIG_DRM_AMDGPU_CIK
1780efa246c0Sriastradh 	case CHIP_BONAIRE:
1781efa246c0Sriastradh 	case CHIP_HAWAII:
1782efa246c0Sriastradh 	case CHIP_KAVERI:
1783efa246c0Sriastradh 	case CHIP_KABINI:
1784efa246c0Sriastradh 	case CHIP_MULLINS:
1785efa246c0Sriastradh 		if ((adev->asic_type == CHIP_BONAIRE) || (adev->asic_type == CHIP_HAWAII))
1786efa246c0Sriastradh 			adev->family = AMDGPU_FAMILY_CI;
1787efa246c0Sriastradh 		else
1788efa246c0Sriastradh 			adev->family = AMDGPU_FAMILY_KV;
1789efa246c0Sriastradh 
1790efa246c0Sriastradh 		r = cik_set_ip_blocks(adev);
1791efa246c0Sriastradh 		if (r)
1792efa246c0Sriastradh 			return r;
1793efa246c0Sriastradh 		break;
1794efa246c0Sriastradh #endif
179541ec0267Sriastradh 	case CHIP_VEGA10:
179641ec0267Sriastradh 	case CHIP_VEGA12:
179741ec0267Sriastradh 	case CHIP_VEGA20:
179841ec0267Sriastradh 	case CHIP_RAVEN:
179941ec0267Sriastradh 	case CHIP_ARCTURUS:
180041ec0267Sriastradh 	case CHIP_RENOIR:
180141ec0267Sriastradh 		if (adev->asic_type == CHIP_RAVEN ||
180241ec0267Sriastradh 		    adev->asic_type == CHIP_RENOIR)
180341ec0267Sriastradh 			adev->family = AMDGPU_FAMILY_RV;
180441ec0267Sriastradh 		else
180541ec0267Sriastradh 			adev->family = AMDGPU_FAMILY_AI;
180641ec0267Sriastradh 
180741ec0267Sriastradh 		r = soc15_set_ip_blocks(adev);
180841ec0267Sriastradh 		if (r)
180941ec0267Sriastradh 			return r;
181041ec0267Sriastradh 		break;
181141ec0267Sriastradh 	case  CHIP_NAVI10:
181241ec0267Sriastradh 	case  CHIP_NAVI14:
181341ec0267Sriastradh 	case  CHIP_NAVI12:
181441ec0267Sriastradh 		adev->family = AMDGPU_FAMILY_NV;
181541ec0267Sriastradh 
181641ec0267Sriastradh 		r = nv_set_ip_blocks(adev);
181741ec0267Sriastradh 		if (r)
181841ec0267Sriastradh 			return r;
181941ec0267Sriastradh 		break;
1820efa246c0Sriastradh 	default:
1821efa246c0Sriastradh 		/* FIXME: not supported yet */
1822efa246c0Sriastradh 		return -EINVAL;
1823efa246c0Sriastradh 	}
1824efa246c0Sriastradh 
182541ec0267Sriastradh 	r = amdgpu_device_parse_gpu_info_fw(adev);
182641ec0267Sriastradh 	if (r)
1827efa246c0Sriastradh 		return r;
182841ec0267Sriastradh 
182941ec0267Sriastradh 	if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10)
183041ec0267Sriastradh 		amdgpu_discovery_get_gfx_info(adev);
183141ec0267Sriastradh 
183241ec0267Sriastradh 	amdgpu_amdkfd_device_probe(adev);
183341ec0267Sriastradh 
183441ec0267Sriastradh 	if (amdgpu_sriov_vf(adev)) {
183541ec0267Sriastradh 		r = amdgpu_virt_request_full_gpu(adev, true);
183641ec0267Sriastradh 		if (r)
183741ec0267Sriastradh 			return -EAGAIN;
1838efa246c0Sriastradh 	}
1839efa246c0Sriastradh 
184041ec0267Sriastradh 	adev->pm.pp_feature = amdgpu_pp_feature_mask;
184141ec0267Sriastradh 	if (amdgpu_sriov_vf(adev) || sched_policy == KFD_SCHED_POLICY_NO_HWS)
184241ec0267Sriastradh 		adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
184341ec0267Sriastradh 
1844efa246c0Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
1845efa246c0Sriastradh 		if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
184641ec0267Sriastradh 			DRM_ERROR("disabled ip block: %d <%s>\n",
184741ec0267Sriastradh 				  i, adev->ip_blocks[i].version->funcs->name);
184841ec0267Sriastradh 			adev->ip_blocks[i].status.valid = false;
1849efa246c0Sriastradh 		} else {
185041ec0267Sriastradh 			if (adev->ip_blocks[i].version->funcs->early_init) {
185141ec0267Sriastradh 				r = adev->ip_blocks[i].version->funcs->early_init((void *)adev);
185241ec0267Sriastradh 				if (r == -ENOENT) {
185341ec0267Sriastradh 					adev->ip_blocks[i].status.valid = false;
185441ec0267Sriastradh 				} else if (r) {
185541ec0267Sriastradh 					DRM_ERROR("early_init of IP block <%s> failed %d\n",
185641ec0267Sriastradh 						  adev->ip_blocks[i].version->funcs->name, r);
1857efa246c0Sriastradh 					return r;
1858efa246c0Sriastradh 				} else {
185941ec0267Sriastradh 					adev->ip_blocks[i].status.valid = true;
186041ec0267Sriastradh 				}
186141ec0267Sriastradh 			} else {
186241ec0267Sriastradh 				adev->ip_blocks[i].status.valid = true;
186341ec0267Sriastradh 			}
186441ec0267Sriastradh 		}
186541ec0267Sriastradh 		/* get the vbios after the asic_funcs are set up */
186641ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON) {
186741ec0267Sriastradh 			/* Read BIOS */
186841ec0267Sriastradh 			if (!amdgpu_get_bios(adev))
186941ec0267Sriastradh 				return -EINVAL;
187041ec0267Sriastradh 
187141ec0267Sriastradh 			r = amdgpu_atombios_init(adev);
187241ec0267Sriastradh 			if (r) {
187341ec0267Sriastradh 				dev_err(adev->dev, "amdgpu_atombios_init failed\n");
187441ec0267Sriastradh 				amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0);
187541ec0267Sriastradh 				return r;
1876efa246c0Sriastradh 			}
1877efa246c0Sriastradh 		}
1878efa246c0Sriastradh 	}
1879efa246c0Sriastradh 
188041ec0267Sriastradh 	adev->cg_flags &= amdgpu_cg_mask;
188141ec0267Sriastradh 	adev->pg_flags &= amdgpu_pg_mask;
188241ec0267Sriastradh 
1883efa246c0Sriastradh 	return 0;
1884efa246c0Sriastradh }
1885efa246c0Sriastradh 
amdgpu_device_ip_hw_init_phase1(struct amdgpu_device * adev)188641ec0267Sriastradh static int amdgpu_device_ip_hw_init_phase1(struct amdgpu_device *adev)
1887efa246c0Sriastradh {
1888efa246c0Sriastradh 	int i, r;
1889efa246c0Sriastradh 
1890efa246c0Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
189141ec0267Sriastradh 		if (!adev->ip_blocks[i].status.sw)
1892efa246c0Sriastradh 			continue;
189341ec0267Sriastradh 		if (adev->ip_blocks[i].status.hw)
189441ec0267Sriastradh 			continue;
189541ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
189641ec0267Sriastradh 		    (amdgpu_sriov_vf(adev) && (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)) ||
189741ec0267Sriastradh 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
189841ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->hw_init(adev);
189941ec0267Sriastradh 			if (r) {
190041ec0267Sriastradh 				DRM_ERROR("hw_init of IP block <%s> failed %d\n",
190141ec0267Sriastradh 					  adev->ip_blocks[i].version->funcs->name, r);
1902efa246c0Sriastradh 				return r;
1903efa246c0Sriastradh 			}
190441ec0267Sriastradh 			adev->ip_blocks[i].status.hw = true;
1905efa246c0Sriastradh 		}
1906efa246c0Sriastradh 	}
1907efa246c0Sriastradh 
1908efa246c0Sriastradh 	return 0;
1909efa246c0Sriastradh }
1910efa246c0Sriastradh 
amdgpu_device_ip_hw_init_phase2(struct amdgpu_device * adev)191141ec0267Sriastradh static int amdgpu_device_ip_hw_init_phase2(struct amdgpu_device *adev)
1912efa246c0Sriastradh {
191341ec0267Sriastradh 	int i, r;
191441ec0267Sriastradh 
191541ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
191641ec0267Sriastradh 		if (!adev->ip_blocks[i].status.sw)
191741ec0267Sriastradh 			continue;
191841ec0267Sriastradh 		if (adev->ip_blocks[i].status.hw)
191941ec0267Sriastradh 			continue;
192041ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->hw_init(adev);
192141ec0267Sriastradh 		if (r) {
192241ec0267Sriastradh 			DRM_ERROR("hw_init of IP block <%s> failed %d\n",
192341ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
192441ec0267Sriastradh 			return r;
192541ec0267Sriastradh 		}
192641ec0267Sriastradh 		adev->ip_blocks[i].status.hw = true;
192741ec0267Sriastradh 	}
192841ec0267Sriastradh 
192941ec0267Sriastradh 	return 0;
193041ec0267Sriastradh }
193141ec0267Sriastradh 
amdgpu_device_fw_loading(struct amdgpu_device * adev)193241ec0267Sriastradh static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
193341ec0267Sriastradh {
193441ec0267Sriastradh 	int r = 0;
193541ec0267Sriastradh 	int i;
193641ec0267Sriastradh 	uint32_t smu_version;
193741ec0267Sriastradh 
193841ec0267Sriastradh 	if (adev->asic_type >= CHIP_VEGA10) {
193941ec0267Sriastradh 		for (i = 0; i < adev->num_ip_blocks; i++) {
194041ec0267Sriastradh 			if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_PSP)
194141ec0267Sriastradh 				continue;
194241ec0267Sriastradh 
194341ec0267Sriastradh 			/* no need to do the fw loading again if already done*/
194441ec0267Sriastradh 			if (adev->ip_blocks[i].status.hw == true)
194541ec0267Sriastradh 				break;
194641ec0267Sriastradh 
194741ec0267Sriastradh 			if (adev->in_gpu_reset || adev->in_suspend) {
194841ec0267Sriastradh 				r = adev->ip_blocks[i].version->funcs->resume(adev);
194941ec0267Sriastradh 				if (r) {
195041ec0267Sriastradh 					DRM_ERROR("resume of IP block <%s> failed %d\n",
195141ec0267Sriastradh 							  adev->ip_blocks[i].version->funcs->name, r);
195241ec0267Sriastradh 					return r;
195341ec0267Sriastradh 				}
195441ec0267Sriastradh 			} else {
195541ec0267Sriastradh 				r = adev->ip_blocks[i].version->funcs->hw_init(adev);
195641ec0267Sriastradh 				if (r) {
195741ec0267Sriastradh 					DRM_ERROR("hw_init of IP block <%s> failed %d\n",
195841ec0267Sriastradh 							  adev->ip_blocks[i].version->funcs->name, r);
195941ec0267Sriastradh 					return r;
196041ec0267Sriastradh 				}
196141ec0267Sriastradh 			}
196241ec0267Sriastradh 
196341ec0267Sriastradh 			adev->ip_blocks[i].status.hw = true;
196441ec0267Sriastradh 			break;
196541ec0267Sriastradh 		}
196641ec0267Sriastradh 	}
196741ec0267Sriastradh 
196841ec0267Sriastradh 	if (!amdgpu_sriov_vf(adev) || adev->asic_type == CHIP_TONGA)
196941ec0267Sriastradh 		r = amdgpu_pm_load_smu_firmware(adev, &smu_version);
197041ec0267Sriastradh 
197141ec0267Sriastradh 	return r;
197241ec0267Sriastradh }
197341ec0267Sriastradh 
197441ec0267Sriastradh /**
197541ec0267Sriastradh  * amdgpu_device_ip_init - run init for hardware IPs
197641ec0267Sriastradh  *
197741ec0267Sriastradh  * @adev: amdgpu_device pointer
197841ec0267Sriastradh  *
197941ec0267Sriastradh  * Main initialization pass for hardware IPs.  The list of all the hardware
198041ec0267Sriastradh  * IPs that make up the asic is walked and the sw_init and hw_init callbacks
198141ec0267Sriastradh  * are run.  sw_init initializes the software state associated with each IP
198241ec0267Sriastradh  * and hw_init initializes the hardware associated with each IP.
198341ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
198441ec0267Sriastradh  */
amdgpu_device_ip_init(struct amdgpu_device * adev)198541ec0267Sriastradh static int amdgpu_device_ip_init(struct amdgpu_device *adev)
198641ec0267Sriastradh {
198741ec0267Sriastradh 	int i, r;
198841ec0267Sriastradh 
198941ec0267Sriastradh 	r = amdgpu_ras_init(adev);
199041ec0267Sriastradh 	if (r)
199141ec0267Sriastradh 		return r;
199241ec0267Sriastradh 
199341ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
199441ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
199541ec0267Sriastradh 			continue;
199641ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->sw_init((void *)adev);
199741ec0267Sriastradh 		if (r) {
199841ec0267Sriastradh 			DRM_ERROR("sw_init of IP block <%s> failed %d\n",
199941ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
200041ec0267Sriastradh 			goto init_failed;
200141ec0267Sriastradh 		}
200241ec0267Sriastradh 		adev->ip_blocks[i].status.sw = true;
200341ec0267Sriastradh 
200441ec0267Sriastradh 		/* need to do gmc hw init early so we can allocate gpu mem */
200541ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
200641ec0267Sriastradh 			r = amdgpu_device_vram_scratch_init(adev);
200741ec0267Sriastradh 			if (r) {
200841ec0267Sriastradh 				DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
200941ec0267Sriastradh 				goto init_failed;
201041ec0267Sriastradh 			}
201141ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
201241ec0267Sriastradh 			if (r) {
201341ec0267Sriastradh 				DRM_ERROR("hw_init %d failed %d\n", i, r);
201441ec0267Sriastradh 				goto init_failed;
201541ec0267Sriastradh 			}
201641ec0267Sriastradh 			r = amdgpu_device_wb_init(adev);
201741ec0267Sriastradh 			if (r) {
201841ec0267Sriastradh 				DRM_ERROR("amdgpu_device_wb_init failed %d\n", r);
201941ec0267Sriastradh 				goto init_failed;
202041ec0267Sriastradh 			}
202141ec0267Sriastradh 			adev->ip_blocks[i].status.hw = true;
202241ec0267Sriastradh 
202341ec0267Sriastradh 			/* right after GMC hw init, we create CSA */
202441ec0267Sriastradh 			if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
202541ec0267Sriastradh 				r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj,
202641ec0267Sriastradh 								AMDGPU_GEM_DOMAIN_VRAM,
202741ec0267Sriastradh 								AMDGPU_CSA_SIZE);
202841ec0267Sriastradh 				if (r) {
202941ec0267Sriastradh 					DRM_ERROR("allocate CSA failed %d\n", r);
203041ec0267Sriastradh 					goto init_failed;
203141ec0267Sriastradh 				}
203241ec0267Sriastradh 			}
203341ec0267Sriastradh 		}
203441ec0267Sriastradh 	}
203541ec0267Sriastradh 
203641ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
203741ec0267Sriastradh 		amdgpu_virt_init_data_exchange(adev);
203841ec0267Sriastradh 
203941ec0267Sriastradh 	r = amdgpu_ib_pool_init(adev);
204041ec0267Sriastradh 	if (r) {
204141ec0267Sriastradh 		dev_err(adev->dev, "IB initialization failed (%d).\n", r);
204241ec0267Sriastradh 		amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_IB_INIT_FAIL, 0, r);
204341ec0267Sriastradh 		goto init_failed;
204441ec0267Sriastradh 	}
204541ec0267Sriastradh 
204641ec0267Sriastradh 	r = amdgpu_ucode_create_bo(adev); /* create ucode bo when sw_init complete*/
204741ec0267Sriastradh 	if (r)
204841ec0267Sriastradh 		goto init_failed;
204941ec0267Sriastradh 
205041ec0267Sriastradh 	r = amdgpu_device_ip_hw_init_phase1(adev);
205141ec0267Sriastradh 	if (r)
205241ec0267Sriastradh 		goto init_failed;
205341ec0267Sriastradh 
205441ec0267Sriastradh 	r = amdgpu_device_fw_loading(adev);
205541ec0267Sriastradh 	if (r)
205641ec0267Sriastradh 		goto init_failed;
205741ec0267Sriastradh 
205841ec0267Sriastradh 	r = amdgpu_device_ip_hw_init_phase2(adev);
205941ec0267Sriastradh 	if (r)
206041ec0267Sriastradh 		goto init_failed;
206141ec0267Sriastradh 
206241ec0267Sriastradh 	/*
206341ec0267Sriastradh 	 * retired pages will be loaded from eeprom and reserved here,
206441ec0267Sriastradh 	 * it should be called after amdgpu_device_ip_hw_init_phase2  since
206541ec0267Sriastradh 	 * for some ASICs the RAS EEPROM code relies on SMU fully functioning
206641ec0267Sriastradh 	 * for I2C communication which only true at this point.
206741ec0267Sriastradh 	 * recovery_init may fail, but it can free all resources allocated by
206841ec0267Sriastradh 	 * itself and its failure should not stop amdgpu init process.
206941ec0267Sriastradh 	 *
207041ec0267Sriastradh 	 * Note: theoretically, this should be called before all vram allocations
207141ec0267Sriastradh 	 * to protect retired page from abusing
207241ec0267Sriastradh 	 */
207341ec0267Sriastradh 	amdgpu_ras_recovery_init(adev);
207441ec0267Sriastradh 
207541ec0267Sriastradh 	if (adev->gmc.xgmi.num_physical_nodes > 1)
207641ec0267Sriastradh 		amdgpu_xgmi_add_device(adev);
207741ec0267Sriastradh 	amdgpu_amdkfd_device_init(adev);
207841ec0267Sriastradh 
207941ec0267Sriastradh init_failed:
208041ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
208141ec0267Sriastradh 		amdgpu_virt_release_full_gpu(adev, true);
208241ec0267Sriastradh 
208341ec0267Sriastradh 	return r;
208441ec0267Sriastradh }
208541ec0267Sriastradh 
208641ec0267Sriastradh /**
208741ec0267Sriastradh  * amdgpu_device_fill_reset_magic - writes reset magic to gart pointer
208841ec0267Sriastradh  *
208941ec0267Sriastradh  * @adev: amdgpu_device pointer
209041ec0267Sriastradh  *
209141ec0267Sriastradh  * Writes a reset magic value to the gart pointer in VRAM.  The driver calls
209241ec0267Sriastradh  * this function before a GPU reset.  If the value is retained after a
209341ec0267Sriastradh  * GPU reset, VRAM has not been lost.  Some GPU resets may destry VRAM contents.
209441ec0267Sriastradh  */
amdgpu_device_fill_reset_magic(struct amdgpu_device * adev)209541ec0267Sriastradh static void amdgpu_device_fill_reset_magic(struct amdgpu_device *adev)
209641ec0267Sriastradh {
209741ec0267Sriastradh 	memcpy(adev->reset_magic, adev->gart.ptr, AMDGPU_RESET_MAGIC_NUM);
209841ec0267Sriastradh }
209941ec0267Sriastradh 
210041ec0267Sriastradh /**
210141ec0267Sriastradh  * amdgpu_device_check_vram_lost - check if vram is valid
210241ec0267Sriastradh  *
210341ec0267Sriastradh  * @adev: amdgpu_device pointer
210441ec0267Sriastradh  *
210541ec0267Sriastradh  * Checks the reset magic value written to the gart pointer in VRAM.
210641ec0267Sriastradh  * The driver calls this after a GPU reset to see if the contents of
210741ec0267Sriastradh  * VRAM is lost or now.
210841ec0267Sriastradh  * returns true if vram is lost, false if not.
210941ec0267Sriastradh  */
amdgpu_device_check_vram_lost(struct amdgpu_device * adev)211041ec0267Sriastradh static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev)
211141ec0267Sriastradh {
211241ec0267Sriastradh 	return !!memcmp(adev->gart.ptr, adev->reset_magic,
211341ec0267Sriastradh 			AMDGPU_RESET_MAGIC_NUM);
211441ec0267Sriastradh }
211541ec0267Sriastradh 
211641ec0267Sriastradh /**
211741ec0267Sriastradh  * amdgpu_device_set_cg_state - set clockgating for amdgpu device
211841ec0267Sriastradh  *
211941ec0267Sriastradh  * @adev: amdgpu_device pointer
212041ec0267Sriastradh  * @state: clockgating state (gate or ungate)
212141ec0267Sriastradh  *
212241ec0267Sriastradh  * The list of all the hardware IPs that make up the asic is walked and the
212341ec0267Sriastradh  * set_clockgating_state callbacks are run.
212441ec0267Sriastradh  * Late initialization pass enabling clockgating for hardware IPs.
212541ec0267Sriastradh  * Fini or suspend, pass disabling clockgating for hardware IPs.
212641ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
212741ec0267Sriastradh  */
212841ec0267Sriastradh 
amdgpu_device_set_cg_state(struct amdgpu_device * adev,enum amd_clockgating_state state)212941ec0267Sriastradh static int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
213041ec0267Sriastradh 						enum amd_clockgating_state state)
213141ec0267Sriastradh {
213241ec0267Sriastradh 	int i, j, r;
213341ec0267Sriastradh 
213441ec0267Sriastradh 	if (amdgpu_emu_mode == 1)
213541ec0267Sriastradh 		return 0;
213641ec0267Sriastradh 
213741ec0267Sriastradh 	for (j = 0; j < adev->num_ip_blocks; j++) {
213841ec0267Sriastradh 		i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
213941ec0267Sriastradh 		if (!adev->ip_blocks[i].status.late_initialized)
214041ec0267Sriastradh 			continue;
214141ec0267Sriastradh 		/* skip CG for VCE/UVD, it's handled specially */
214241ec0267Sriastradh 		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
214341ec0267Sriastradh 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
214441ec0267Sriastradh 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCN &&
214541ec0267Sriastradh 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_JPEG &&
214641ec0267Sriastradh 		    adev->ip_blocks[i].version->funcs->set_clockgating_state) {
214741ec0267Sriastradh 			/* enable clockgating to save power */
214841ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
214941ec0267Sriastradh 										     state);
215041ec0267Sriastradh 			if (r) {
215141ec0267Sriastradh 				DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n",
215241ec0267Sriastradh 					  adev->ip_blocks[i].version->funcs->name, r);
215341ec0267Sriastradh 				return r;
215441ec0267Sriastradh 			}
215541ec0267Sriastradh 		}
215641ec0267Sriastradh 	}
215741ec0267Sriastradh 
215841ec0267Sriastradh 	return 0;
215941ec0267Sriastradh }
216041ec0267Sriastradh 
amdgpu_device_set_pg_state(struct amdgpu_device * adev,enum amd_powergating_state state)216141ec0267Sriastradh static int amdgpu_device_set_pg_state(struct amdgpu_device *adev, enum amd_powergating_state state)
216241ec0267Sriastradh {
216341ec0267Sriastradh 	int i, j, r;
216441ec0267Sriastradh 
216541ec0267Sriastradh 	if (amdgpu_emu_mode == 1)
216641ec0267Sriastradh 		return 0;
216741ec0267Sriastradh 
216841ec0267Sriastradh 	for (j = 0; j < adev->num_ip_blocks; j++) {
216941ec0267Sriastradh 		i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
217041ec0267Sriastradh 		if (!adev->ip_blocks[i].status.late_initialized)
217141ec0267Sriastradh 			continue;
217241ec0267Sriastradh 		/* skip CG for VCE/UVD, it's handled specially */
217341ec0267Sriastradh 		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
217441ec0267Sriastradh 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
217541ec0267Sriastradh 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCN &&
217641ec0267Sriastradh 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_JPEG &&
217741ec0267Sriastradh 		    adev->ip_blocks[i].version->funcs->set_powergating_state) {
217841ec0267Sriastradh 			/* enable powergating to save power */
217941ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->set_powergating_state((void *)adev,
218041ec0267Sriastradh 											state);
218141ec0267Sriastradh 			if (r) {
218241ec0267Sriastradh 				DRM_ERROR("set_powergating_state(gate) of IP block <%s> failed %d\n",
218341ec0267Sriastradh 					  adev->ip_blocks[i].version->funcs->name, r);
218441ec0267Sriastradh 				return r;
218541ec0267Sriastradh 			}
218641ec0267Sriastradh 		}
218741ec0267Sriastradh 	}
218841ec0267Sriastradh 	return 0;
218941ec0267Sriastradh }
219041ec0267Sriastradh 
amdgpu_device_enable_mgpu_fan_boost(void)219141ec0267Sriastradh static int amdgpu_device_enable_mgpu_fan_boost(void)
219241ec0267Sriastradh {
219341ec0267Sriastradh 	struct amdgpu_gpu_instance *gpu_ins;
219441ec0267Sriastradh 	struct amdgpu_device *adev;
219541ec0267Sriastradh 	int i, ret = 0;
219641ec0267Sriastradh 
219741ec0267Sriastradh 	mutex_lock(&mgpu_info.mutex);
219841ec0267Sriastradh 
219941ec0267Sriastradh 	/*
220041ec0267Sriastradh 	 * MGPU fan boost feature should be enabled
220141ec0267Sriastradh 	 * only when there are two or more dGPUs in
220241ec0267Sriastradh 	 * the system
220341ec0267Sriastradh 	 */
220441ec0267Sriastradh 	if (mgpu_info.num_dgpu < 2)
220541ec0267Sriastradh 		goto out;
220641ec0267Sriastradh 
220741ec0267Sriastradh 	for (i = 0; i < mgpu_info.num_dgpu; i++) {
220841ec0267Sriastradh 		gpu_ins = &(mgpu_info.gpu_ins[i]);
220941ec0267Sriastradh 		adev = gpu_ins->adev;
221041ec0267Sriastradh 		if (!(adev->flags & AMD_IS_APU) &&
221141ec0267Sriastradh 		    !gpu_ins->mgpu_fan_enabled &&
221241ec0267Sriastradh 		    adev->powerplay.pp_funcs &&
221341ec0267Sriastradh 		    adev->powerplay.pp_funcs->enable_mgpu_fan_boost) {
221441ec0267Sriastradh 			ret = amdgpu_dpm_enable_mgpu_fan_boost(adev);
221541ec0267Sriastradh 			if (ret)
221641ec0267Sriastradh 				break;
221741ec0267Sriastradh 
221841ec0267Sriastradh 			gpu_ins->mgpu_fan_enabled = 1;
221941ec0267Sriastradh 		}
222041ec0267Sriastradh 	}
222141ec0267Sriastradh 
222241ec0267Sriastradh out:
222341ec0267Sriastradh 	mutex_unlock(&mgpu_info.mutex);
222441ec0267Sriastradh 
222541ec0267Sriastradh 	return ret;
222641ec0267Sriastradh }
222741ec0267Sriastradh 
222841ec0267Sriastradh /**
222941ec0267Sriastradh  * amdgpu_device_ip_late_init - run late init for hardware IPs
223041ec0267Sriastradh  *
223141ec0267Sriastradh  * @adev: amdgpu_device pointer
223241ec0267Sriastradh  *
223341ec0267Sriastradh  * Late initialization pass for hardware IPs.  The list of all the hardware
223441ec0267Sriastradh  * IPs that make up the asic is walked and the late_init callbacks are run.
223541ec0267Sriastradh  * late_init covers any special initialization that an IP requires
223641ec0267Sriastradh  * after all of the have been initialized or something that needs to happen
223741ec0267Sriastradh  * late in the init process.
223841ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
223941ec0267Sriastradh  */
amdgpu_device_ip_late_init(struct amdgpu_device * adev)224041ec0267Sriastradh static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
224141ec0267Sriastradh {
224241ec0267Sriastradh 	struct amdgpu_gpu_instance *gpu_instance;
2243efa246c0Sriastradh 	int i = 0, r;
2244efa246c0Sriastradh 
2245efa246c0Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
224641ec0267Sriastradh 		if (!adev->ip_blocks[i].status.hw)
2247efa246c0Sriastradh 			continue;
224841ec0267Sriastradh 		if (adev->ip_blocks[i].version->funcs->late_init) {
224941ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->late_init((void *)adev);
225041ec0267Sriastradh 			if (r) {
225141ec0267Sriastradh 				DRM_ERROR("late_init of IP block <%s> failed %d\n",
225241ec0267Sriastradh 					  adev->ip_blocks[i].version->funcs->name, r);
2253efa246c0Sriastradh 				return r;
2254efa246c0Sriastradh 			}
2255efa246c0Sriastradh 		}
225641ec0267Sriastradh 		adev->ip_blocks[i].status.late_initialized = true;
2257efa246c0Sriastradh 	}
2258efa246c0Sriastradh 
225941ec0267Sriastradh 	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
226041ec0267Sriastradh 	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);
2261efa246c0Sriastradh 
226241ec0267Sriastradh 	amdgpu_device_fill_reset_magic(adev);
226341ec0267Sriastradh 
226441ec0267Sriastradh 	r = amdgpu_device_enable_mgpu_fan_boost();
2265efa246c0Sriastradh 	if (r)
226641ec0267Sriastradh 		DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
2267efa246c0Sriastradh 
226841ec0267Sriastradh 
226941ec0267Sriastradh 	if (adev->gmc.xgmi.num_physical_nodes > 1) {
227041ec0267Sriastradh 		mutex_lock(&mgpu_info.mutex);
227141ec0267Sriastradh 
227241ec0267Sriastradh 		/*
227341ec0267Sriastradh 		 * Reset device p-state to low as this was booted with high.
227441ec0267Sriastradh 		 *
227541ec0267Sriastradh 		 * This should be performed only after all devices from the same
227641ec0267Sriastradh 		 * hive get initialized.
227741ec0267Sriastradh 		 *
227841ec0267Sriastradh 		 * However, it's unknown how many device in the hive in advance.
227941ec0267Sriastradh 		 * As this is counted one by one during devices initializations.
228041ec0267Sriastradh 		 *
228141ec0267Sriastradh 		 * So, we wait for all XGMI interlinked devices initialized.
228241ec0267Sriastradh 		 * This may bring some delays as those devices may come from
228341ec0267Sriastradh 		 * different hives. But that should be OK.
228441ec0267Sriastradh 		 */
228541ec0267Sriastradh 		if (mgpu_info.num_dgpu == adev->gmc.xgmi.num_physical_nodes) {
228641ec0267Sriastradh 			for (i = 0; i < mgpu_info.num_gpu; i++) {
228741ec0267Sriastradh 				gpu_instance = &(mgpu_info.gpu_ins[i]);
228841ec0267Sriastradh 				if (gpu_instance->adev->flags & AMD_IS_APU)
2289efa246c0Sriastradh 					continue;
229041ec0267Sriastradh 
229141ec0267Sriastradh 				r = amdgpu_xgmi_set_pstate(gpu_instance->adev, 0);
229241ec0267Sriastradh 				if (r) {
229341ec0267Sriastradh 					DRM_ERROR("pstate setting failed (%d).\n", r);
229441ec0267Sriastradh 					break;
229541ec0267Sriastradh 				}
229641ec0267Sriastradh 			}
2297efa246c0Sriastradh 		}
2298efa246c0Sriastradh 
229941ec0267Sriastradh 		mutex_unlock(&mgpu_info.mutex);
2300efa246c0Sriastradh 	}
2301efa246c0Sriastradh 
2302efa246c0Sriastradh 	return 0;
2303efa246c0Sriastradh }
2304efa246c0Sriastradh 
2305efa246c0Sriastradh /**
230641ec0267Sriastradh  * amdgpu_device_ip_fini - run fini for hardware IPs
230741ec0267Sriastradh  *
230841ec0267Sriastradh  * @adev: amdgpu_device pointer
230941ec0267Sriastradh  *
231041ec0267Sriastradh  * Main teardown pass for hardware IPs.  The list of all the hardware
231141ec0267Sriastradh  * IPs that make up the asic is walked and the hw_fini and sw_fini callbacks
231241ec0267Sriastradh  * are run.  hw_fini tears down the hardware associated with each IP
231341ec0267Sriastradh  * and sw_fini tears down any software state associated with each IP.
231441ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
231541ec0267Sriastradh  */
amdgpu_device_ip_fini(struct amdgpu_device * adev)231641ec0267Sriastradh static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
231741ec0267Sriastradh {
231841ec0267Sriastradh 	int i, r;
231941ec0267Sriastradh 
232041ec0267Sriastradh 	amdgpu_ras_pre_fini(adev);
232141ec0267Sriastradh 
232241ec0267Sriastradh 	if (adev->gmc.xgmi.num_physical_nodes > 1)
232341ec0267Sriastradh 		amdgpu_xgmi_remove_device(adev);
232441ec0267Sriastradh 
232541ec0267Sriastradh 	amdgpu_amdkfd_device_fini(adev);
232641ec0267Sriastradh 
232741ec0267Sriastradh 	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
232841ec0267Sriastradh 	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
232941ec0267Sriastradh 
233041ec0267Sriastradh 	/* need to disable SMC first */
233141ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
233241ec0267Sriastradh 		if (!adev->ip_blocks[i].status.hw)
233341ec0267Sriastradh 			continue;
233441ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
233541ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
233641ec0267Sriastradh 			/* XXX handle errors */
233741ec0267Sriastradh 			if (r) {
233841ec0267Sriastradh 				DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
233941ec0267Sriastradh 					  adev->ip_blocks[i].version->funcs->name, r);
234041ec0267Sriastradh 			}
234141ec0267Sriastradh 			adev->ip_blocks[i].status.hw = false;
234241ec0267Sriastradh 			break;
234341ec0267Sriastradh 		}
234441ec0267Sriastradh 	}
234541ec0267Sriastradh 
234641ec0267Sriastradh 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
234741ec0267Sriastradh 		if (!adev->ip_blocks[i].status.hw)
234841ec0267Sriastradh 			continue;
234941ec0267Sriastradh 
235041ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
235141ec0267Sriastradh 		/* XXX handle errors */
235241ec0267Sriastradh 		if (r) {
235341ec0267Sriastradh 			DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
235441ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
235541ec0267Sriastradh 		}
235641ec0267Sriastradh 
235741ec0267Sriastradh 		adev->ip_blocks[i].status.hw = false;
235841ec0267Sriastradh 	}
235941ec0267Sriastradh 
236041ec0267Sriastradh 
236141ec0267Sriastradh 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
236241ec0267Sriastradh 		if (!adev->ip_blocks[i].status.sw)
236341ec0267Sriastradh 			continue;
236441ec0267Sriastradh 
236541ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
236641ec0267Sriastradh 			amdgpu_ucode_free_bo(adev);
236741ec0267Sriastradh 			amdgpu_free_static_csa(&adev->virt.csa_obj);
236841ec0267Sriastradh 			amdgpu_device_wb_fini(adev);
236941ec0267Sriastradh 			amdgpu_device_vram_scratch_fini(adev);
237041ec0267Sriastradh 			amdgpu_ib_pool_fini(adev);
237141ec0267Sriastradh 		}
237241ec0267Sriastradh 
237341ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev);
237441ec0267Sriastradh 		/* XXX handle errors */
237541ec0267Sriastradh 		if (r) {
237641ec0267Sriastradh 			DRM_DEBUG("sw_fini of IP block <%s> failed %d\n",
237741ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
237841ec0267Sriastradh 		}
237941ec0267Sriastradh 		adev->ip_blocks[i].status.sw = false;
238041ec0267Sriastradh 		adev->ip_blocks[i].status.valid = false;
238141ec0267Sriastradh 	}
238241ec0267Sriastradh 
238341ec0267Sriastradh 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
238441ec0267Sriastradh 		if (!adev->ip_blocks[i].status.late_initialized)
238541ec0267Sriastradh 			continue;
238641ec0267Sriastradh 		if (adev->ip_blocks[i].version->funcs->late_fini)
238741ec0267Sriastradh 			adev->ip_blocks[i].version->funcs->late_fini((void *)adev);
238841ec0267Sriastradh 		adev->ip_blocks[i].status.late_initialized = false;
238941ec0267Sriastradh 	}
239041ec0267Sriastradh 
239141ec0267Sriastradh 	amdgpu_ras_fini(adev);
239241ec0267Sriastradh 
239341ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
239441ec0267Sriastradh 		if (amdgpu_virt_release_full_gpu(adev, false))
239541ec0267Sriastradh 			DRM_ERROR("failed to release exclusive mode on fini\n");
239641ec0267Sriastradh 
239741ec0267Sriastradh 	return 0;
239841ec0267Sriastradh }
239941ec0267Sriastradh 
240041ec0267Sriastradh /**
240141ec0267Sriastradh  * amdgpu_device_delayed_init_work_handler - work handler for IB tests
240241ec0267Sriastradh  *
240341ec0267Sriastradh  * @work: work_struct.
240441ec0267Sriastradh  */
amdgpu_device_delayed_init_work_handler(struct work_struct * work)240541ec0267Sriastradh static void amdgpu_device_delayed_init_work_handler(struct work_struct *work)
240641ec0267Sriastradh {
240741ec0267Sriastradh 	struct amdgpu_device *adev =
240841ec0267Sriastradh 		container_of(work, struct amdgpu_device, delayed_init_work.work);
240941ec0267Sriastradh 	int r;
241041ec0267Sriastradh 
241141ec0267Sriastradh 	r = amdgpu_ib_ring_tests(adev);
241241ec0267Sriastradh 	if (r)
241341ec0267Sriastradh 		DRM_ERROR("ib ring test failed (%d).\n", r);
241441ec0267Sriastradh }
241541ec0267Sriastradh 
amdgpu_device_delay_enable_gfx_off(struct work_struct * work)241641ec0267Sriastradh static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)
241741ec0267Sriastradh {
241841ec0267Sriastradh 	struct amdgpu_device *adev =
241941ec0267Sriastradh 		container_of(work, struct amdgpu_device, gfx.gfx_off_delay_work.work);
242041ec0267Sriastradh 
242141ec0267Sriastradh 	mutex_lock(&adev->gfx.gfx_off_mutex);
242241ec0267Sriastradh 	if (!adev->gfx.gfx_off_state && !adev->gfx.gfx_off_req_count) {
242341ec0267Sriastradh 		if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, true))
242441ec0267Sriastradh 			adev->gfx.gfx_off_state = true;
242541ec0267Sriastradh 	}
242641ec0267Sriastradh 	mutex_unlock(&adev->gfx.gfx_off_mutex);
242741ec0267Sriastradh }
242841ec0267Sriastradh 
242941ec0267Sriastradh /**
243041ec0267Sriastradh  * amdgpu_device_ip_suspend_phase1 - run suspend for hardware IPs (phase 1)
243141ec0267Sriastradh  *
243241ec0267Sriastradh  * @adev: amdgpu_device pointer
243341ec0267Sriastradh  *
243441ec0267Sriastradh  * Main suspend function for hardware IPs.  The list of all the hardware
243541ec0267Sriastradh  * IPs that make up the asic is walked, clockgating is disabled and the
243641ec0267Sriastradh  * suspend callbacks are run.  suspend puts the hardware and software state
243741ec0267Sriastradh  * in each IP into a state suitable for suspend.
243841ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
243941ec0267Sriastradh  */
amdgpu_device_ip_suspend_phase1(struct amdgpu_device * adev)244041ec0267Sriastradh static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev)
244141ec0267Sriastradh {
244241ec0267Sriastradh 	int i, r;
244341ec0267Sriastradh 
244441ec0267Sriastradh 	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
244541ec0267Sriastradh 	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
244641ec0267Sriastradh 
244741ec0267Sriastradh 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
244841ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
244941ec0267Sriastradh 			continue;
245041ec0267Sriastradh 		/* displays are handled separately */
245141ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) {
245241ec0267Sriastradh 			/* XXX handle errors */
245341ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->suspend(adev);
245441ec0267Sriastradh 			/* XXX handle errors */
245541ec0267Sriastradh 			if (r) {
245641ec0267Sriastradh 				DRM_ERROR("suspend of IP block <%s> failed %d\n",
245741ec0267Sriastradh 					  adev->ip_blocks[i].version->funcs->name, r);
245841ec0267Sriastradh 				return r;
245941ec0267Sriastradh 			}
246041ec0267Sriastradh 			adev->ip_blocks[i].status.hw = false;
246141ec0267Sriastradh 		}
246241ec0267Sriastradh 	}
246341ec0267Sriastradh 
246441ec0267Sriastradh 	return 0;
246541ec0267Sriastradh }
246641ec0267Sriastradh 
246741ec0267Sriastradh /**
246841ec0267Sriastradh  * amdgpu_device_ip_suspend_phase2 - run suspend for hardware IPs (phase 2)
246941ec0267Sriastradh  *
247041ec0267Sriastradh  * @adev: amdgpu_device pointer
247141ec0267Sriastradh  *
247241ec0267Sriastradh  * Main suspend function for hardware IPs.  The list of all the hardware
247341ec0267Sriastradh  * IPs that make up the asic is walked, clockgating is disabled and the
247441ec0267Sriastradh  * suspend callbacks are run.  suspend puts the hardware and software state
247541ec0267Sriastradh  * in each IP into a state suitable for suspend.
247641ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
247741ec0267Sriastradh  */
amdgpu_device_ip_suspend_phase2(struct amdgpu_device * adev)247841ec0267Sriastradh static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
247941ec0267Sriastradh {
248041ec0267Sriastradh 	int i, r __unused;
248141ec0267Sriastradh 
248241ec0267Sriastradh 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
248341ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
248441ec0267Sriastradh 			continue;
248541ec0267Sriastradh 		/* displays are handled in phase1 */
248641ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)
248741ec0267Sriastradh 			continue;
248841ec0267Sriastradh 		/* PSP lost connection when err_event_athub occurs */
248941ec0267Sriastradh 		if (amdgpu_ras_intr_triggered() &&
249041ec0267Sriastradh 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
249141ec0267Sriastradh 			adev->ip_blocks[i].status.hw = false;
249241ec0267Sriastradh 			continue;
249341ec0267Sriastradh 		}
249441ec0267Sriastradh 		/* XXX handle errors */
249541ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->suspend(adev);
249641ec0267Sriastradh 		/* XXX handle errors */
249741ec0267Sriastradh 		if (r) {
249841ec0267Sriastradh 			DRM_ERROR("suspend of IP block <%s> failed %d\n",
249941ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
250041ec0267Sriastradh 		}
250141ec0267Sriastradh 		adev->ip_blocks[i].status.hw = false;
250241ec0267Sriastradh 		/* handle putting the SMC in the appropriate state */
250341ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
250441ec0267Sriastradh 			r = amdgpu_dpm_set_mp1_state(adev, adev->mp1_state);
250541ec0267Sriastradh 			if (r) {
250641ec0267Sriastradh 				DRM_ERROR("SMC failed to set mp1 state %d, %d\n",
250741ec0267Sriastradh 					  adev->mp1_state, r);
250841ec0267Sriastradh 				return r;
250941ec0267Sriastradh 			}
251041ec0267Sriastradh 		}
251141ec0267Sriastradh 
251241ec0267Sriastradh 		adev->ip_blocks[i].status.hw = false;
251341ec0267Sriastradh 	}
251441ec0267Sriastradh 
251541ec0267Sriastradh 	return 0;
251641ec0267Sriastradh }
251741ec0267Sriastradh 
251841ec0267Sriastradh /**
251941ec0267Sriastradh  * amdgpu_device_ip_suspend - run suspend for hardware IPs
252041ec0267Sriastradh  *
252141ec0267Sriastradh  * @adev: amdgpu_device pointer
252241ec0267Sriastradh  *
252341ec0267Sriastradh  * Main suspend function for hardware IPs.  The list of all the hardware
252441ec0267Sriastradh  * IPs that make up the asic is walked, clockgating is disabled and the
252541ec0267Sriastradh  * suspend callbacks are run.  suspend puts the hardware and software state
252641ec0267Sriastradh  * in each IP into a state suitable for suspend.
252741ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
252841ec0267Sriastradh  */
amdgpu_device_ip_suspend(struct amdgpu_device * adev)252941ec0267Sriastradh int amdgpu_device_ip_suspend(struct amdgpu_device *adev)
253041ec0267Sriastradh {
253141ec0267Sriastradh 	int r;
253241ec0267Sriastradh 
253341ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
253441ec0267Sriastradh 		amdgpu_virt_request_full_gpu(adev, false);
253541ec0267Sriastradh 
253641ec0267Sriastradh 	r = amdgpu_device_ip_suspend_phase1(adev);
253741ec0267Sriastradh 	if (r)
253841ec0267Sriastradh 		return r;
253941ec0267Sriastradh 	r = amdgpu_device_ip_suspend_phase2(adev);
254041ec0267Sriastradh 
254141ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
254241ec0267Sriastradh 		amdgpu_virt_release_full_gpu(adev, false);
254341ec0267Sriastradh 
254441ec0267Sriastradh 	return r;
254541ec0267Sriastradh }
254641ec0267Sriastradh 
amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device * adev)254741ec0267Sriastradh static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
254841ec0267Sriastradh {
254941ec0267Sriastradh 	int i, r;
255041ec0267Sriastradh 
255141ec0267Sriastradh 	static enum amd_ip_block_type ip_order[] = {
255241ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_GMC,
255341ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_COMMON,
255441ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_PSP,
255541ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_IH,
255641ec0267Sriastradh 	};
255741ec0267Sriastradh 
255841ec0267Sriastradh 	for (i = 0; i < ARRAY_SIZE(ip_order); i++) {
255941ec0267Sriastradh 		int j;
256041ec0267Sriastradh 		struct amdgpu_ip_block *block;
256141ec0267Sriastradh 
256241ec0267Sriastradh 		for (j = 0; j < adev->num_ip_blocks; j++) {
256341ec0267Sriastradh 			block = &adev->ip_blocks[j];
256441ec0267Sriastradh 
256541ec0267Sriastradh 			block->status.hw = false;
256641ec0267Sriastradh 			if (block->version->type != ip_order[i] ||
256741ec0267Sriastradh 				!block->status.valid)
256841ec0267Sriastradh 				continue;
256941ec0267Sriastradh 
257041ec0267Sriastradh 			r = block->version->funcs->hw_init(adev);
257141ec0267Sriastradh 			DRM_INFO("RE-INIT-early: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
257241ec0267Sriastradh 			if (r)
257341ec0267Sriastradh 				return r;
257441ec0267Sriastradh 			block->status.hw = true;
257541ec0267Sriastradh 		}
257641ec0267Sriastradh 	}
257741ec0267Sriastradh 
257841ec0267Sriastradh 	return 0;
257941ec0267Sriastradh }
258041ec0267Sriastradh 
amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device * adev)258141ec0267Sriastradh static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
258241ec0267Sriastradh {
258341ec0267Sriastradh 	int i, r;
258441ec0267Sriastradh 
258541ec0267Sriastradh 	static enum amd_ip_block_type ip_order[] = {
258641ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_SMC,
258741ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_DCE,
258841ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_GFX,
258941ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_SDMA,
259041ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_UVD,
259141ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_VCE,
259241ec0267Sriastradh 		AMD_IP_BLOCK_TYPE_VCN
259341ec0267Sriastradh 	};
259441ec0267Sriastradh 
259541ec0267Sriastradh 	for (i = 0; i < ARRAY_SIZE(ip_order); i++) {
259641ec0267Sriastradh 		int j;
259741ec0267Sriastradh 		struct amdgpu_ip_block *block;
259841ec0267Sriastradh 
259941ec0267Sriastradh 		for (j = 0; j < adev->num_ip_blocks; j++) {
260041ec0267Sriastradh 			block = &adev->ip_blocks[j];
260141ec0267Sriastradh 
260241ec0267Sriastradh 			if (block->version->type != ip_order[i] ||
260341ec0267Sriastradh 				!block->status.valid ||
260441ec0267Sriastradh 				block->status.hw)
260541ec0267Sriastradh 				continue;
260641ec0267Sriastradh 
260741ec0267Sriastradh 			if (block->version->type == AMD_IP_BLOCK_TYPE_SMC)
260841ec0267Sriastradh 				r = block->version->funcs->resume(adev);
260941ec0267Sriastradh 			else
261041ec0267Sriastradh 				r = block->version->funcs->hw_init(adev);
261141ec0267Sriastradh 
261241ec0267Sriastradh 			DRM_INFO("RE-INIT-late: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
261341ec0267Sriastradh 			if (r)
261441ec0267Sriastradh 				return r;
261541ec0267Sriastradh 			block->status.hw = true;
261641ec0267Sriastradh 		}
261741ec0267Sriastradh 	}
261841ec0267Sriastradh 
261941ec0267Sriastradh 	return 0;
262041ec0267Sriastradh }
262141ec0267Sriastradh 
262241ec0267Sriastradh /**
262341ec0267Sriastradh  * amdgpu_device_ip_resume_phase1 - run resume for hardware IPs
262441ec0267Sriastradh  *
262541ec0267Sriastradh  * @adev: amdgpu_device pointer
262641ec0267Sriastradh  *
262741ec0267Sriastradh  * First resume function for hardware IPs.  The list of all the hardware
262841ec0267Sriastradh  * IPs that make up the asic is walked and the resume callbacks are run for
262941ec0267Sriastradh  * COMMON, GMC, and IH.  resume puts the hardware into a functional state
263041ec0267Sriastradh  * after a suspend and updates the software state as necessary.  This
263141ec0267Sriastradh  * function is also used for restoring the GPU after a GPU reset.
263241ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
263341ec0267Sriastradh  */
amdgpu_device_ip_resume_phase1(struct amdgpu_device * adev)263441ec0267Sriastradh static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
263541ec0267Sriastradh {
263641ec0267Sriastradh 	int i, r;
263741ec0267Sriastradh 
263841ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
263941ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
264041ec0267Sriastradh 			continue;
264141ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
264241ec0267Sriastradh 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
264341ec0267Sriastradh 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
264441ec0267Sriastradh 
264541ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->resume(adev);
264641ec0267Sriastradh 			if (r) {
264741ec0267Sriastradh 				DRM_ERROR("resume of IP block <%s> failed %d\n",
264841ec0267Sriastradh 					  adev->ip_blocks[i].version->funcs->name, r);
264941ec0267Sriastradh 				return r;
265041ec0267Sriastradh 			}
265141ec0267Sriastradh 			adev->ip_blocks[i].status.hw = true;
265241ec0267Sriastradh 		}
265341ec0267Sriastradh 	}
265441ec0267Sriastradh 
265541ec0267Sriastradh 	return 0;
265641ec0267Sriastradh }
265741ec0267Sriastradh 
265841ec0267Sriastradh /**
265941ec0267Sriastradh  * amdgpu_device_ip_resume_phase2 - run resume for hardware IPs
266041ec0267Sriastradh  *
266141ec0267Sriastradh  * @adev: amdgpu_device pointer
266241ec0267Sriastradh  *
266341ec0267Sriastradh  * First resume function for hardware IPs.  The list of all the hardware
266441ec0267Sriastradh  * IPs that make up the asic is walked and the resume callbacks are run for
266541ec0267Sriastradh  * all blocks except COMMON, GMC, and IH.  resume puts the hardware into a
266641ec0267Sriastradh  * functional state after a suspend and updates the software state as
266741ec0267Sriastradh  * necessary.  This function is also used for restoring the GPU after a GPU
266841ec0267Sriastradh  * reset.
266941ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
267041ec0267Sriastradh  */
amdgpu_device_ip_resume_phase2(struct amdgpu_device * adev)267141ec0267Sriastradh static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
267241ec0267Sriastradh {
267341ec0267Sriastradh 	int i, r;
267441ec0267Sriastradh 
267541ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
267641ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
267741ec0267Sriastradh 			continue;
267841ec0267Sriastradh 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
267941ec0267Sriastradh 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
268041ec0267Sriastradh 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
268141ec0267Sriastradh 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
268241ec0267Sriastradh 			continue;
268341ec0267Sriastradh 		r = adev->ip_blocks[i].version->funcs->resume(adev);
268441ec0267Sriastradh 		if (r) {
268541ec0267Sriastradh 			DRM_ERROR("resume of IP block <%s> failed %d\n",
268641ec0267Sriastradh 				  adev->ip_blocks[i].version->funcs->name, r);
268741ec0267Sriastradh 			return r;
268841ec0267Sriastradh 		}
268941ec0267Sriastradh 		adev->ip_blocks[i].status.hw = true;
269041ec0267Sriastradh 	}
269141ec0267Sriastradh 
269241ec0267Sriastradh 	return 0;
269341ec0267Sriastradh }
269441ec0267Sriastradh 
269541ec0267Sriastradh /**
269641ec0267Sriastradh  * amdgpu_device_ip_resume - run resume for hardware IPs
269741ec0267Sriastradh  *
269841ec0267Sriastradh  * @adev: amdgpu_device pointer
269941ec0267Sriastradh  *
270041ec0267Sriastradh  * Main resume function for hardware IPs.  The hardware IPs
270141ec0267Sriastradh  * are split into two resume functions because they are
270241ec0267Sriastradh  * are also used in in recovering from a GPU reset and some additional
270341ec0267Sriastradh  * steps need to be take between them.  In this case (S3/S4) they are
270441ec0267Sriastradh  * run sequentially.
270541ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
270641ec0267Sriastradh  */
amdgpu_device_ip_resume(struct amdgpu_device * adev)270741ec0267Sriastradh static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
270841ec0267Sriastradh {
270941ec0267Sriastradh 	int r;
271041ec0267Sriastradh 
271141ec0267Sriastradh 	r = amdgpu_device_ip_resume_phase1(adev);
271241ec0267Sriastradh 	if (r)
271341ec0267Sriastradh 		return r;
271441ec0267Sriastradh 
271541ec0267Sriastradh 	r = amdgpu_device_fw_loading(adev);
271641ec0267Sriastradh 	if (r)
271741ec0267Sriastradh 		return r;
271841ec0267Sriastradh 
271941ec0267Sriastradh 	r = amdgpu_device_ip_resume_phase2(adev);
272041ec0267Sriastradh 
272141ec0267Sriastradh 	return r;
272241ec0267Sriastradh }
272341ec0267Sriastradh 
272441ec0267Sriastradh /**
272541ec0267Sriastradh  * amdgpu_device_detect_sriov_bios - determine if the board supports SR-IOV
272641ec0267Sriastradh  *
272741ec0267Sriastradh  * @adev: amdgpu_device pointer
272841ec0267Sriastradh  *
272941ec0267Sriastradh  * Query the VBIOS data tables to determine if the board supports SR-IOV.
273041ec0267Sriastradh  */
amdgpu_device_detect_sriov_bios(struct amdgpu_device * adev)273141ec0267Sriastradh static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
273241ec0267Sriastradh {
273341ec0267Sriastradh 	if (amdgpu_sriov_vf(adev)) {
273441ec0267Sriastradh 		if (adev->is_atom_fw) {
273541ec0267Sriastradh 			if (amdgpu_atomfirmware_gpu_supports_virtualization(adev))
273641ec0267Sriastradh 				adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
273741ec0267Sriastradh 		} else {
273841ec0267Sriastradh 			if (amdgpu_atombios_has_gpu_virtualization_table(adev))
273941ec0267Sriastradh 				adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
274041ec0267Sriastradh 		}
274141ec0267Sriastradh 
274241ec0267Sriastradh 		if (!(adev->virt.caps & AMDGPU_SRIOV_CAPS_SRIOV_VBIOS))
274341ec0267Sriastradh 			amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_NO_VBIOS, 0, 0);
274441ec0267Sriastradh 	}
274541ec0267Sriastradh }
274641ec0267Sriastradh 
274741ec0267Sriastradh /**
274841ec0267Sriastradh  * amdgpu_device_asic_has_dc_support - determine if DC supports the asic
274941ec0267Sriastradh  *
275041ec0267Sriastradh  * @asic_type: AMD asic type
275141ec0267Sriastradh  *
275241ec0267Sriastradh  * Check if there is DC (new modesetting infrastructre) support for an asic.
275341ec0267Sriastradh  * returns true if DC has support, false if not.
275441ec0267Sriastradh  */
amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)275541ec0267Sriastradh bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
275641ec0267Sriastradh {
275741ec0267Sriastradh 	switch (asic_type) {
275841ec0267Sriastradh #if defined(CONFIG_DRM_AMD_DC)
275941ec0267Sriastradh 	case CHIP_BONAIRE:
276041ec0267Sriastradh 	case CHIP_KAVERI:
276141ec0267Sriastradh 	case CHIP_KABINI:
276241ec0267Sriastradh 	case CHIP_MULLINS:
276341ec0267Sriastradh 		/*
276441ec0267Sriastradh 		 * We have systems in the wild with these ASICs that require
276541ec0267Sriastradh 		 * LVDS and VGA support which is not supported with DC.
276641ec0267Sriastradh 		 *
276741ec0267Sriastradh 		 * Fallback to the non-DC driver here by default so as not to
276841ec0267Sriastradh 		 * cause regressions.
276941ec0267Sriastradh 		 */
277041ec0267Sriastradh 		return amdgpu_dc > 0;
277141ec0267Sriastradh 	case CHIP_HAWAII:
277241ec0267Sriastradh 	case CHIP_CARRIZO:
277341ec0267Sriastradh 	case CHIP_STONEY:
277441ec0267Sriastradh 	case CHIP_POLARIS10:
277541ec0267Sriastradh 	case CHIP_POLARIS11:
277641ec0267Sriastradh 	case CHIP_POLARIS12:
277741ec0267Sriastradh 	case CHIP_VEGAM:
277841ec0267Sriastradh 	case CHIP_TONGA:
277941ec0267Sriastradh 	case CHIP_FIJI:
278041ec0267Sriastradh 	case CHIP_VEGA10:
278141ec0267Sriastradh 	case CHIP_VEGA12:
278241ec0267Sriastradh 	case CHIP_VEGA20:
278341ec0267Sriastradh #if defined(CONFIG_DRM_AMD_DC_DCN)
278441ec0267Sriastradh 	case CHIP_RAVEN:
278541ec0267Sriastradh 	case CHIP_NAVI10:
278641ec0267Sriastradh 	case CHIP_NAVI14:
278741ec0267Sriastradh 	case CHIP_NAVI12:
278841ec0267Sriastradh 	case CHIP_RENOIR:
278941ec0267Sriastradh #endif
279041ec0267Sriastradh 		return amdgpu_dc != 0;
279141ec0267Sriastradh #endif
279241ec0267Sriastradh 	default:
279341ec0267Sriastradh 		if (amdgpu_dc > 0)
279441ec0267Sriastradh 			DRM_INFO("Display Core has been requested via kernel parameter "
279541ec0267Sriastradh 					 "but isn't supported by ASIC, ignoring\n");
279641ec0267Sriastradh 		return false;
279741ec0267Sriastradh 	}
279841ec0267Sriastradh }
279941ec0267Sriastradh 
280041ec0267Sriastradh /**
280141ec0267Sriastradh  * amdgpu_device_has_dc_support - check if dc is supported
280241ec0267Sriastradh  *
280341ec0267Sriastradh  * @adev: amdgpu_device_pointer
280441ec0267Sriastradh  *
280541ec0267Sriastradh  * Returns true for supported, false for not supported
280641ec0267Sriastradh  */
amdgpu_device_has_dc_support(struct amdgpu_device * adev)280741ec0267Sriastradh bool amdgpu_device_has_dc_support(struct amdgpu_device *adev)
280841ec0267Sriastradh {
280941ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
281041ec0267Sriastradh 		return false;
281141ec0267Sriastradh 
281241ec0267Sriastradh 	return amdgpu_device_asic_has_dc_support(adev->asic_type);
281341ec0267Sriastradh }
281441ec0267Sriastradh 
281541ec0267Sriastradh 
amdgpu_device_xgmi_reset_func(struct work_struct * __work)281641ec0267Sriastradh static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
281741ec0267Sriastradh {
281841ec0267Sriastradh 	struct amdgpu_device *adev =
281941ec0267Sriastradh 		container_of(__work, struct amdgpu_device, xgmi_reset_work);
282041ec0267Sriastradh 	struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0);
282141ec0267Sriastradh 
282241ec0267Sriastradh 	/* It's a bug to not have a hive within this function */
282341ec0267Sriastradh 	if (WARN_ON(!hive))
282441ec0267Sriastradh 		return;
282541ec0267Sriastradh 
282641ec0267Sriastradh 	/*
282741ec0267Sriastradh 	 * Use task barrier to synchronize all xgmi reset works across the
282841ec0267Sriastradh 	 * hive. task_barrier_enter and task_barrier_exit will block
282941ec0267Sriastradh 	 * until all the threads running the xgmi reset works reach
283041ec0267Sriastradh 	 * those points. task_barrier_full will do both blocks.
283141ec0267Sriastradh 	 */
283241ec0267Sriastradh 	if (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
283341ec0267Sriastradh 
283441ec0267Sriastradh 		task_barrier_enter(&hive->tb);
283541ec0267Sriastradh 		adev->asic_reset_res = amdgpu_device_baco_enter(adev->ddev);
283641ec0267Sriastradh 
283741ec0267Sriastradh 		if (adev->asic_reset_res)
283841ec0267Sriastradh 			goto fail;
283941ec0267Sriastradh 
284041ec0267Sriastradh 		task_barrier_exit(&hive->tb);
284141ec0267Sriastradh 		adev->asic_reset_res = amdgpu_device_baco_exit(adev->ddev);
284241ec0267Sriastradh 
284341ec0267Sriastradh 		if (adev->asic_reset_res)
284441ec0267Sriastradh 			goto fail;
284541ec0267Sriastradh 	} else {
284641ec0267Sriastradh 
284741ec0267Sriastradh 		task_barrier_full(&hive->tb);
284841ec0267Sriastradh 		adev->asic_reset_res =  amdgpu_asic_reset(adev);
284941ec0267Sriastradh 	}
285041ec0267Sriastradh 
285141ec0267Sriastradh fail:
285241ec0267Sriastradh 	if (adev->asic_reset_res)
285341ec0267Sriastradh 		DRM_WARN("ASIC reset failed with error, %d for drm dev, %s",
285441ec0267Sriastradh 			 adev->asic_reset_res, adev->ddev->unique);
285541ec0267Sriastradh }
285641ec0267Sriastradh 
amdgpu_device_get_job_timeout_settings(struct amdgpu_device * adev)285741ec0267Sriastradh static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
285841ec0267Sriastradh {
285941ec0267Sriastradh 	char *input = amdgpu_lockup_timeout;
286041ec0267Sriastradh 	char *timeout_setting = NULL;
286141ec0267Sriastradh 	int index = 0;
286241ec0267Sriastradh 	long timeout;
286341ec0267Sriastradh 	int ret = 0;
286441ec0267Sriastradh 
286541ec0267Sriastradh 	/*
286641ec0267Sriastradh 	 * By default timeout for non compute jobs is 10000.
286741ec0267Sriastradh 	 * And there is no timeout enforced on compute jobs.
286841ec0267Sriastradh 	 * In SR-IOV or passthrough mode, timeout for compute
286941ec0267Sriastradh 	 * jobs are 10000 by default.
287041ec0267Sriastradh 	 */
287141ec0267Sriastradh 	adev->gfx_timeout = msecs_to_jiffies(10000);
287241ec0267Sriastradh 	adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
287341ec0267Sriastradh 	if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
287441ec0267Sriastradh 		adev->compute_timeout = adev->gfx_timeout;
287541ec0267Sriastradh 	else
287641ec0267Sriastradh 		adev->compute_timeout = MAX_SCHEDULE_TIMEOUT;
287741ec0267Sriastradh 
287841ec0267Sriastradh 	if (strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
287941ec0267Sriastradh 		while ((timeout_setting = strsep(&input, ",")) &&
288041ec0267Sriastradh 				strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
288141ec0267Sriastradh 			ret = kstrtol(timeout_setting, 0, &timeout);
288241ec0267Sriastradh 			if (ret)
288341ec0267Sriastradh 				return ret;
288441ec0267Sriastradh 
288541ec0267Sriastradh 			if (timeout == 0) {
288641ec0267Sriastradh 				index++;
288741ec0267Sriastradh 				continue;
288841ec0267Sriastradh 			} else if (timeout < 0) {
288941ec0267Sriastradh 				timeout = MAX_SCHEDULE_TIMEOUT;
289041ec0267Sriastradh 			} else {
289141ec0267Sriastradh 				timeout = msecs_to_jiffies(timeout);
289241ec0267Sriastradh 			}
289341ec0267Sriastradh 
289441ec0267Sriastradh 			switch (index++) {
289541ec0267Sriastradh 			case 0:
289641ec0267Sriastradh 				adev->gfx_timeout = timeout;
289741ec0267Sriastradh 				break;
289841ec0267Sriastradh 			case 1:
289941ec0267Sriastradh 				adev->compute_timeout = timeout;
290041ec0267Sriastradh 				break;
290141ec0267Sriastradh 			case 2:
290241ec0267Sriastradh 				adev->sdma_timeout = timeout;
290341ec0267Sriastradh 				break;
290441ec0267Sriastradh 			case 3:
290541ec0267Sriastradh 				adev->video_timeout = timeout;
290641ec0267Sriastradh 				break;
290741ec0267Sriastradh 			default:
290841ec0267Sriastradh 				break;
290941ec0267Sriastradh 			}
291041ec0267Sriastradh 		}
291141ec0267Sriastradh 		/*
291241ec0267Sriastradh 		 * There is only one value specified and
291341ec0267Sriastradh 		 * it should apply to all non-compute jobs.
291441ec0267Sriastradh 		 */
291541ec0267Sriastradh 		if (index == 1) {
291641ec0267Sriastradh 			adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
291741ec0267Sriastradh 			if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
291841ec0267Sriastradh 				adev->compute_timeout = adev->gfx_timeout;
291941ec0267Sriastradh 		}
292041ec0267Sriastradh 	}
292141ec0267Sriastradh 
292241ec0267Sriastradh 	return ret;
292341ec0267Sriastradh }
292441ec0267Sriastradh 
292541ec0267Sriastradh /**
2926efa246c0Sriastradh  * amdgpu_device_init - initialize the driver
2927efa246c0Sriastradh  *
2928efa246c0Sriastradh  * @adev: amdgpu_device pointer
292941ec0267Sriastradh  * @ddev: drm dev pointer
2930efa246c0Sriastradh  * @pdev: pci dev pointer
2931efa246c0Sriastradh  * @flags: driver flags
2932efa246c0Sriastradh  *
2933efa246c0Sriastradh  * Initializes the driver info and hw (all asics).
2934efa246c0Sriastradh  * Returns 0 for success or an error on failure.
2935efa246c0Sriastradh  * Called at driver startup.
2936efa246c0Sriastradh  */
amdgpu_device_init(struct amdgpu_device * adev,struct drm_device * ddev,struct pci_dev * pdev,uint32_t flags)2937efa246c0Sriastradh int amdgpu_device_init(struct amdgpu_device *adev,
2938efa246c0Sriastradh 		       struct drm_device *ddev,
2939efa246c0Sriastradh 		       struct pci_dev *pdev,
2940efa246c0Sriastradh 		       uint32_t flags)
2941efa246c0Sriastradh {
2942efa246c0Sriastradh 	int r, i;
294341ec0267Sriastradh 	bool boco = false;
294441ec0267Sriastradh 	u32 max_MBps;
2945efa246c0Sriastradh 
2946efa246c0Sriastradh 	adev->shutdown = false;
29470d50c49dSriastradh 	adev->dev = pci_dev_dev(pdev);
2948efa246c0Sriastradh 	adev->ddev = ddev;
2949efa246c0Sriastradh 	adev->pdev = pdev;
2950efa246c0Sriastradh 	adev->flags = flags;
295141ec0267Sriastradh 
295241ec0267Sriastradh 	if (amdgpu_force_asic_type >= 0 && amdgpu_force_asic_type < CHIP_LAST)
295341ec0267Sriastradh 		adev->asic_type = amdgpu_force_asic_type;
295441ec0267Sriastradh 	else
2955efa246c0Sriastradh 		adev->asic_type = flags & AMD_ASIC_MASK;
295641ec0267Sriastradh 
2957efa246c0Sriastradh 	adev->usec_timeout = AMDGPU_MAX_USEC_TIMEOUT;
295841ec0267Sriastradh 	if (amdgpu_emu_mode == 1)
295941ec0267Sriastradh 		adev->usec_timeout *= 2;
296041ec0267Sriastradh 	adev->gmc.gart_size = 512 * 1024 * 1024;
2961efa246c0Sriastradh 	adev->accel_working = false;
2962efa246c0Sriastradh 	adev->num_rings = 0;
2963efa246c0Sriastradh 	adev->mman.buffer_funcs = NULL;
2964efa246c0Sriastradh 	adev->mman.buffer_funcs_ring = NULL;
2965efa246c0Sriastradh 	adev->vm_manager.vm_pte_funcs = NULL;
296641ec0267Sriastradh 	adev->vm_manager.vm_pte_num_scheds = 0;
296741ec0267Sriastradh 	adev->gmc.gmc_funcs = NULL;
296841ec0267Sriastradh 	adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS);
296941ec0267Sriastradh 	bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
2970efa246c0Sriastradh 
2971efa246c0Sriastradh 	adev->smc_rreg = &amdgpu_invalid_rreg;
2972efa246c0Sriastradh 	adev->smc_wreg = &amdgpu_invalid_wreg;
2973efa246c0Sriastradh 	adev->pcie_rreg = &amdgpu_invalid_rreg;
2974efa246c0Sriastradh 	adev->pcie_wreg = &amdgpu_invalid_wreg;
297541ec0267Sriastradh 	adev->pciep_rreg = &amdgpu_invalid_rreg;
297641ec0267Sriastradh 	adev->pciep_wreg = &amdgpu_invalid_wreg;
297741ec0267Sriastradh 	adev->pcie_rreg64 = &amdgpu_invalid_rreg64;
297841ec0267Sriastradh 	adev->pcie_wreg64 = &amdgpu_invalid_wreg64;
2979efa246c0Sriastradh 	adev->uvd_ctx_rreg = &amdgpu_invalid_rreg;
2980efa246c0Sriastradh 	adev->uvd_ctx_wreg = &amdgpu_invalid_wreg;
2981efa246c0Sriastradh 	adev->didt_rreg = &amdgpu_invalid_rreg;
2982efa246c0Sriastradh 	adev->didt_wreg = &amdgpu_invalid_wreg;
298341ec0267Sriastradh 	adev->gc_cac_rreg = &amdgpu_invalid_rreg;
298441ec0267Sriastradh 	adev->gc_cac_wreg = &amdgpu_invalid_wreg;
2985efa246c0Sriastradh 	adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg;
2986efa246c0Sriastradh 	adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg;
2987efa246c0Sriastradh 
2988efa246c0Sriastradh 	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n",
2989efa246c0Sriastradh 		 amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device,
2990efa246c0Sriastradh 		 pdev->subsystem_vendor, pdev->subsystem_device, pdev->revision);
2991efa246c0Sriastradh 
2992efa246c0Sriastradh 	/* mutex initialization are all done here so we
2993efa246c0Sriastradh 	 * can recall function without having locking issues */
29941b46a69aSriastradh 	atomic_set(&adev->irq.ih.lock, 0);
299541ec0267Sriastradh 	mutex_init(&adev->firmware.mutex);
2996efa246c0Sriastradh 	mutex_init(&adev->pm.mutex);
2997efa246c0Sriastradh 	mutex_init(&adev->gfx.gpu_clock_mutex);
2998efa246c0Sriastradh 	mutex_init(&adev->srbm_mutex);
299941ec0267Sriastradh 	mutex_init(&adev->gfx.pipe_reserve_mutex);
300041ec0267Sriastradh 	mutex_init(&adev->gfx.gfx_off_mutex);
3001efa246c0Sriastradh 	mutex_init(&adev->grbm_idx_mutex);
3002efa246c0Sriastradh 	mutex_init(&adev->mn_lock);
300341ec0267Sriastradh 	mutex_init(&adev->virt.vf_errors.lock);
3004efa246c0Sriastradh 	hash_init(adev->mn_hash);
300541ec0267Sriastradh 	mutex_init(&adev->lock_reset);
300641ec0267Sriastradh 	mutex_init(&adev->psp.mutex);
300741ec0267Sriastradh 	mutex_init(&adev->notifier_lock);
3008efa246c0Sriastradh 
3009efa246c0Sriastradh 	spin_lock_init(&adev->mmio_idx_lock);
3010efa246c0Sriastradh 	spin_lock_init(&adev->smc_idx_lock);
3011efa246c0Sriastradh 	spin_lock_init(&adev->pcie_idx_lock);
3012efa246c0Sriastradh 	spin_lock_init(&adev->uvd_ctx_idx_lock);
3013efa246c0Sriastradh 	spin_lock_init(&adev->didt_idx_lock);
301441ec0267Sriastradh 	spin_lock_init(&adev->gc_cac_idx_lock);
301541ec0267Sriastradh 	spin_lock_init(&adev->se_cac_idx_lock);
3016efa246c0Sriastradh 	spin_lock_init(&adev->audio_endpt_idx_lock);
301741ec0267Sriastradh 	spin_lock_init(&adev->mm_stats.lock);
301841ec0267Sriastradh 
301941ec0267Sriastradh 	INIT_LIST_HEAD(&adev->shadow_list);
302041ec0267Sriastradh 	mutex_init(&adev->shadow_list_lock);
302141ec0267Sriastradh 
302241ec0267Sriastradh 	INIT_LIST_HEAD(&adev->ring_lru_list);
302341ec0267Sriastradh 	spin_lock_init(&adev->ring_lru_list_lock);
302441ec0267Sriastradh 
302541ec0267Sriastradh 	INIT_DELAYED_WORK(&adev->delayed_init_work,
302641ec0267Sriastradh 			  amdgpu_device_delayed_init_work_handler);
302741ec0267Sriastradh 	INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work,
302841ec0267Sriastradh 			  amdgpu_device_delay_enable_gfx_off);
302941ec0267Sriastradh 
303041ec0267Sriastradh 	INIT_WORK(&adev->xgmi_reset_work, amdgpu_device_xgmi_reset_func);
303141ec0267Sriastradh 
303207eb61ceSriastradh 	r = amdgpu_device_check_arguments(adev);
303307eb61ceSriastradh 	if (r)
303407eb61ceSriastradh 		return r;
303507eb61ceSriastradh 
303641ec0267Sriastradh 	adev->gfx.gfx_off_req_count = 1;
303741ec0267Sriastradh 	adev->pm.ac_power = power_supply_is_system_supplied() > 0 ? true : false;
303841ec0267Sriastradh 
303941ec0267Sriastradh 	/* Registers mapping */
304041ec0267Sriastradh 	/* TODO: block userspace mapping of io register */
304141ec0267Sriastradh 	if (adev->asic_type >= CHIP_BONAIRE) {
304241ec0267Sriastradh 		adev->rmmio_base = pci_resource_start(adev->pdev, 5);
304341ec0267Sriastradh 		adev->rmmio_size = pci_resource_len(adev->pdev, 5);
304441ec0267Sriastradh 	} else {
304541ec0267Sriastradh 		adev->rmmio_base = pci_resource_start(adev->pdev, 2);
304641ec0267Sriastradh 		adev->rmmio_size = pci_resource_len(adev->pdev, 2);
304741ec0267Sriastradh 	}
3048efa246c0Sriastradh 
30490d50c49dSriastradh #ifdef __NetBSD__
3050*2ec73040Sriastradh 	const int bar = (adev->asic_type >= CHIP_BONAIRE ? 5 : 2);
3051*2ec73040Sriastradh 	if (pci_mapreg_map(&adev->pdev->pd_pa, PCI_BAR(bar),
30520d50c49dSriastradh 		pci_mapreg_type(adev->pdev->pd_pa.pa_pc,
3053*2ec73040Sriastradh 		    adev->pdev->pd_pa.pa_tag, PCI_BAR(bar)),
30540d50c49dSriastradh 		0,
30550d50c49dSriastradh 		&adev->rmmiot, &adev->rmmioh,
30560d50c49dSriastradh 		&adev->rmmio_base, &adev->rmmio_size))
30570d50c49dSriastradh 		return -EIO;
30580d50c49dSriastradh 	DRM_INFO("register mmio base: 0x%8"PRIXMAX"\n",
30590d50c49dSriastradh 	    (uintmax_t)adev->rmmio_base);
30600d50c49dSriastradh 	DRM_INFO("register mmio size: %"PRIuMAX"\n",
30610d50c49dSriastradh 	    (uintmax_t)adev->rmmio_size);
30620d50c49dSriastradh #else
3063efa246c0Sriastradh 	adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size);
3064efa246c0Sriastradh 	if (adev->rmmio == NULL) {
3065efa246c0Sriastradh 		return -ENOMEM;
3066efa246c0Sriastradh 	}
3067efa246c0Sriastradh 	DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base);
3068efa246c0Sriastradh 	DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size);
30690d50c49dSriastradh #endif
3070efa246c0Sriastradh 
3071efa246c0Sriastradh 	/* io port mapping */
3072efa246c0Sriastradh 	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
30730d50c49dSriastradh #ifdef __NetBSD__
30740d50c49dSriastradh 		if (pci_mapreg_map(&adev->pdev->pd_pa, PCI_BAR(i),
30750d50c49dSriastradh 			PCI_MAPREG_TYPE_IO, 0,
30760d50c49dSriastradh 			&adev->rio_memt, &adev->rio_memh,
30770d50c49dSriastradh 			NULL, &adev->rio_mem_size) == 0)
30780d50c49dSriastradh 			break;
30790d50c49dSriastradh #else
3080efa246c0Sriastradh 		if (pci_resource_flags(adev->pdev, i) & IORESOURCE_IO) {
3081efa246c0Sriastradh 			adev->rio_mem_size = pci_resource_len(adev->pdev, i);
3082efa246c0Sriastradh 			adev->rio_mem = pci_iomap(adev->pdev, i, adev->rio_mem_size);
3083efa246c0Sriastradh 			break;
3084efa246c0Sriastradh 		}
30850d50c49dSriastradh #endif
3086efa246c0Sriastradh 	}
30870d50c49dSriastradh #ifdef __NetBSD__
30880d50c49dSriastradh 	if (i == DEVICE_COUNT_RESOURCE)
30890d50c49dSriastradh #else
3090efa246c0Sriastradh 	if (adev->rio_mem == NULL)
30910d50c49dSriastradh #endif
309241ec0267Sriastradh 		DRM_INFO("PCI I/O BAR is not found.\n");
309341ec0267Sriastradh 
309441ec0267Sriastradh 	/* enable PCIE atomic ops */
309541ec0267Sriastradh 	r = pci_enable_atomic_ops_to_root(adev->pdev,
309641ec0267Sriastradh 					  PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
309741ec0267Sriastradh 					  PCI_EXP_DEVCAP2_ATOMIC_COMP64);
309841ec0267Sriastradh 	if (r) {
309941ec0267Sriastradh 		adev->have_atomics_support = false;
310041ec0267Sriastradh 		DRM_INFO("PCIE atomic ops is not supported\n");
310141ec0267Sriastradh 	} else {
310241ec0267Sriastradh 		adev->have_atomics_support = true;
310341ec0267Sriastradh 	}
310441ec0267Sriastradh 
310541ec0267Sriastradh 	amdgpu_device_get_pcie_info(adev);
310641ec0267Sriastradh 
310741ec0267Sriastradh 	if (amdgpu_mcbp)
310841ec0267Sriastradh 		DRM_INFO("MCBP is enabled\n");
310941ec0267Sriastradh 
311041ec0267Sriastradh 	if (amdgpu_mes && adev->asic_type >= CHIP_NAVI10)
311141ec0267Sriastradh 		adev->enable_mes = true;
311241ec0267Sriastradh 
311341ec0267Sriastradh 	if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10) {
311441ec0267Sriastradh 		r = amdgpu_discovery_init(adev);
311541ec0267Sriastradh 		if (r) {
311641ec0267Sriastradh 			dev_err(adev->dev, "amdgpu_discovery_init failed\n");
311741ec0267Sriastradh 			return r;
311841ec0267Sriastradh 		}
311941ec0267Sriastradh 	}
3120efa246c0Sriastradh 
3121efa246c0Sriastradh 	/* early init functions */
312241ec0267Sriastradh 	r = amdgpu_device_ip_early_init(adev);
3123efa246c0Sriastradh 	if (r)
3124efa246c0Sriastradh 		return r;
3125efa246c0Sriastradh 
312641ec0267Sriastradh 	r = amdgpu_device_get_job_timeout_settings(adev);
312741ec0267Sriastradh 	if (r) {
312841ec0267Sriastradh 		dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n");
312941ec0267Sriastradh 		return r;
313041ec0267Sriastradh 	}
313141ec0267Sriastradh 
313241ec0267Sriastradh 	/* doorbell bar mapping and doorbell index init*/
313341ec0267Sriastradh 	amdgpu_device_doorbell_init(adev);
313441ec0267Sriastradh 
31350d50c49dSriastradh #ifndef __NetBSD__		/* XXX amdgpu vga */
3136efa246c0Sriastradh 	/* if we have > 1 VGA cards, then disable the amdgpu VGA resources */
3137efa246c0Sriastradh 	/* this will fail for cards that aren't VGA class devices, just
3138efa246c0Sriastradh 	 * ignore it */
313941ec0267Sriastradh 	vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode);
3140efa246c0Sriastradh 
314141ec0267Sriastradh 	if (amdgpu_device_supports_boco(ddev))
314241ec0267Sriastradh 		boco = true;
314341ec0267Sriastradh 	if (amdgpu_has_atpx() &&
314441ec0267Sriastradh 	    (amdgpu_is_atpx_hybrid() ||
314541ec0267Sriastradh 	     amdgpu_has_atpx_dgpu_power_cntl()) &&
314641ec0267Sriastradh 	    !pci_is_thunderbolt_attached(adev->pdev))
314741ec0267Sriastradh 		vga_switcheroo_register_client(adev->pdev,
314841ec0267Sriastradh 					       &amdgpu_switcheroo_ops, boco);
314941ec0267Sriastradh 	if (boco)
3150efa246c0Sriastradh 		vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
31510d50c49dSriastradh #endif
3152efa246c0Sriastradh 
315341ec0267Sriastradh 	if (amdgpu_emu_mode == 1) {
315441ec0267Sriastradh 		/* post the asic on emulation mode */
315541ec0267Sriastradh 		emu_soc_asic_init(adev);
315641ec0267Sriastradh 		goto fence_driver_init;
3157efa246c0Sriastradh 	}
315841ec0267Sriastradh 
315941ec0267Sriastradh 	/* detect if we are with an SRIOV vbios */
316041ec0267Sriastradh 	amdgpu_device_detect_sriov_bios(adev);
316141ec0267Sriastradh 
316241ec0267Sriastradh 	/* check if we need to reset the asic
316341ec0267Sriastradh 	 *  E.g., driver was not cleanly unloaded previously, etc.
316441ec0267Sriastradh 	 */
316541ec0267Sriastradh 	if (!amdgpu_sriov_vf(adev) && amdgpu_asic_need_reset_on_init(adev)) {
316641ec0267Sriastradh 		r = amdgpu_asic_reset(adev);
316741ec0267Sriastradh 		if (r) {
316841ec0267Sriastradh 			dev_err(adev->dev, "asic reset on init failed\n");
316941ec0267Sriastradh 			goto failed;
317041ec0267Sriastradh 		}
317141ec0267Sriastradh 	}
3172efa246c0Sriastradh 
3173efa246c0Sriastradh 	/* Post card if necessary */
317441ec0267Sriastradh 	if (amdgpu_device_need_post(adev)) {
3175efa246c0Sriastradh 		if (!adev->bios) {
317641ec0267Sriastradh 			dev_err(adev->dev, "no vBIOS found\n");
317741ec0267Sriastradh 			r = -EINVAL;
317841ec0267Sriastradh 			goto failed;
3179efa246c0Sriastradh 		}
318041ec0267Sriastradh 		DRM_INFO("GPU posting now...\n");
318141ec0267Sriastradh 		r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
318241ec0267Sriastradh 		if (r) {
318341ec0267Sriastradh 			dev_err(adev->dev, "gpu post error!\n");
318441ec0267Sriastradh 			goto failed;
318541ec0267Sriastradh 		}
3186efa246c0Sriastradh 	}
3187efa246c0Sriastradh 
318841ec0267Sriastradh 	if (adev->is_atom_fw) {
318941ec0267Sriastradh 		/* Initialize clocks */
319041ec0267Sriastradh 		r = amdgpu_atomfirmware_get_clock_info(adev);
319141ec0267Sriastradh 		if (r) {
319241ec0267Sriastradh 			dev_err(adev->dev, "amdgpu_atomfirmware_get_clock_info failed\n");
319341ec0267Sriastradh 			amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
319441ec0267Sriastradh 			goto failed;
319541ec0267Sriastradh 		}
319641ec0267Sriastradh 	} else {
3197efa246c0Sriastradh 		/* Initialize clocks */
3198efa246c0Sriastradh 		r = amdgpu_atombios_get_clock_info(adev);
319941ec0267Sriastradh 		if (r) {
320041ec0267Sriastradh 			dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n");
320141ec0267Sriastradh 			amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
320241ec0267Sriastradh 			goto failed;
320341ec0267Sriastradh 		}
3204efa246c0Sriastradh 		/* init i2c buses */
320541ec0267Sriastradh 		if (!amdgpu_device_has_dc_support(adev))
3206efa246c0Sriastradh 			amdgpu_atombios_i2c_init(adev);
320741ec0267Sriastradh 	}
3208efa246c0Sriastradh 
320941ec0267Sriastradh fence_driver_init:
3210efa246c0Sriastradh 	/* Fence driver */
3211efa246c0Sriastradh 	r = amdgpu_fence_driver_init(adev);
321241ec0267Sriastradh 	if (r) {
321341ec0267Sriastradh 		dev_err(adev->dev, "amdgpu_fence_driver_init failed\n");
321441ec0267Sriastradh 		amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0);
321541ec0267Sriastradh 		goto failed;
321641ec0267Sriastradh 	}
3217efa246c0Sriastradh 
3218efa246c0Sriastradh 	/* init the mode config */
3219efa246c0Sriastradh 	drm_mode_config_init(adev->ddev);
3220efa246c0Sriastradh 
322141ec0267Sriastradh 	r = amdgpu_device_ip_init(adev);
3222efa246c0Sriastradh 	if (r) {
322341ec0267Sriastradh 		/* failed in exclusive mode due to timeout */
322441ec0267Sriastradh 		if (amdgpu_sriov_vf(adev) &&
322541ec0267Sriastradh 		    !amdgpu_sriov_runtime(adev) &&
322641ec0267Sriastradh 		    amdgpu_virt_mmio_blocked(adev) &&
322741ec0267Sriastradh 		    !amdgpu_virt_wait_reset(adev)) {
322841ec0267Sriastradh 			dev_err(adev->dev, "VF exclusive mode timeout\n");
322941ec0267Sriastradh 			/* Don't send request since VF is inactive. */
323041ec0267Sriastradh 			adev->virt.caps &= ~AMDGPU_SRIOV_CAPS_RUNTIME;
323141ec0267Sriastradh 			adev->virt.ops = NULL;
323241ec0267Sriastradh 			r = -EAGAIN;
323341ec0267Sriastradh 			goto failed;
3234efa246c0Sriastradh 		}
323541ec0267Sriastradh 		dev_err(adev->dev, "amdgpu_device_ip_init failed\n");
323641ec0267Sriastradh 		amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0);
323741ec0267Sriastradh 		goto failed;
323841ec0267Sriastradh 	}
323941ec0267Sriastradh 
324041ec0267Sriastradh 	DRM_DEBUG("SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n",
324141ec0267Sriastradh 			adev->gfx.config.max_shader_engines,
324241ec0267Sriastradh 			adev->gfx.config.max_sh_per_se,
324341ec0267Sriastradh 			adev->gfx.config.max_cu_per_sh,
324441ec0267Sriastradh 			adev->gfx.cu_info.number);
324541ec0267Sriastradh 
324641ec0267Sriastradh 	amdgpu_ctx_init_sched(adev);
3247efa246c0Sriastradh 
3248efa246c0Sriastradh 	adev->accel_working = true;
3249efa246c0Sriastradh 
325041ec0267Sriastradh 	amdgpu_vm_check_compute_bug(adev);
325141ec0267Sriastradh 
325241ec0267Sriastradh 	/* Initialize the buffer migration limit. */
325341ec0267Sriastradh 	if (amdgpu_moverate >= 0)
325441ec0267Sriastradh 		max_MBps = amdgpu_moverate;
325541ec0267Sriastradh 	else
325641ec0267Sriastradh 		max_MBps = 8; /* Allow 8 MB/s. */
325741ec0267Sriastradh 	/* Get a log2 for easy divisions. */
325841ec0267Sriastradh 	adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
325941ec0267Sriastradh 
3260efa246c0Sriastradh 	amdgpu_fbdev_init(adev);
3261efa246c0Sriastradh 
326241ec0267Sriastradh 	r = amdgpu_pm_sysfs_init(adev);
3263efa246c0Sriastradh 	if (r) {
326441ec0267Sriastradh 		adev->pm_sysfs_en = false;
326541ec0267Sriastradh 		DRM_ERROR("registering pm debugfs failed (%d).\n", r);
326641ec0267Sriastradh 	} else
326741ec0267Sriastradh 		adev->pm_sysfs_en = true;
3268efa246c0Sriastradh 
326941ec0267Sriastradh 	r = amdgpu_ucode_sysfs_init(adev);
3270efa246c0Sriastradh 	if (r) {
327141ec0267Sriastradh 		adev->ucode_sysfs_en = false;
327241ec0267Sriastradh 		DRM_ERROR("Creating firmware sysfs failed (%d).\n", r);
327341ec0267Sriastradh 	} else
327441ec0267Sriastradh 		adev->ucode_sysfs_en = true;
327541ec0267Sriastradh 
327641ec0267Sriastradh 	r = amdgpu_debugfs_gem_init(adev);
3277efa246c0Sriastradh 	if (r)
3278efa246c0Sriastradh 		DRM_ERROR("registering gem debugfs failed (%d).\n", r);
3279efa246c0Sriastradh 
3280efa246c0Sriastradh 	r = amdgpu_debugfs_regs_init(adev);
328141ec0267Sriastradh 	if (r)
3282efa246c0Sriastradh 		DRM_ERROR("registering register debugfs failed (%d).\n", r);
328341ec0267Sriastradh 
328441ec0267Sriastradh 	r = amdgpu_debugfs_firmware_init(adev);
328541ec0267Sriastradh 	if (r)
328641ec0267Sriastradh 		DRM_ERROR("registering firmware debugfs failed (%d).\n", r);
328741ec0267Sriastradh 
328841ec0267Sriastradh 	r = amdgpu_debugfs_init(adev);
328941ec0267Sriastradh 	if (r)
329041ec0267Sriastradh 		DRM_ERROR("Creating debugfs files failed (%d).\n", r);
3291efa246c0Sriastradh 
3292efa246c0Sriastradh 	if ((amdgpu_testing & 1)) {
3293efa246c0Sriastradh 		if (adev->accel_working)
3294efa246c0Sriastradh 			amdgpu_test_moves(adev);
3295efa246c0Sriastradh 		else
3296efa246c0Sriastradh 			DRM_INFO("amdgpu: acceleration disabled, skipping move tests\n");
3297efa246c0Sriastradh 	}
3298efa246c0Sriastradh 	if (amdgpu_benchmarking) {
3299efa246c0Sriastradh 		if (adev->accel_working)
3300efa246c0Sriastradh 			amdgpu_benchmark(adev, amdgpu_benchmarking);
3301efa246c0Sriastradh 		else
3302efa246c0Sriastradh 			DRM_INFO("amdgpu: acceleration disabled, skipping benchmarks\n");
3303efa246c0Sriastradh 	}
3304efa246c0Sriastradh 
330541ec0267Sriastradh 	/*
330641ec0267Sriastradh 	 * Register gpu instance before amdgpu_device_enable_mgpu_fan_boost.
330741ec0267Sriastradh 	 * Otherwise the mgpu fan boost feature will be skipped due to the
330841ec0267Sriastradh 	 * gpu instance is counted less.
330941ec0267Sriastradh 	 */
331041ec0267Sriastradh 	amdgpu_register_gpu_instance(adev);
331141ec0267Sriastradh 
3312efa246c0Sriastradh 	/* enable clockgating, etc. after ib tests, etc. since some blocks require
3313efa246c0Sriastradh 	 * explicit gating rather than handling it automatically.
3314efa246c0Sriastradh 	 */
331541ec0267Sriastradh 	r = amdgpu_device_ip_late_init(adev);
331641ec0267Sriastradh 	if (r) {
331741ec0267Sriastradh 		dev_err(adev->dev, "amdgpu_device_ip_late_init failed\n");
331841ec0267Sriastradh 		amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_LATE_INIT_FAIL, 0, r);
331941ec0267Sriastradh 		goto failed;
3320efa246c0Sriastradh 	}
3321efa246c0Sriastradh 
332241ec0267Sriastradh 	/* must succeed. */
332341ec0267Sriastradh 	amdgpu_ras_resume(adev);
332441ec0267Sriastradh 
332541ec0267Sriastradh 	queue_delayed_work(system_wq, &adev->delayed_init_work,
332641ec0267Sriastradh 			   msecs_to_jiffies(AMDGPU_RESUME_MS));
332741ec0267Sriastradh 
332818c728deSriastradh #ifndef __NetBSD__		/* XXX amdgpu sysfs */
332941ec0267Sriastradh 	r = device_create_file(adev->dev, &dev_attr_pcie_replay_count);
333041ec0267Sriastradh 	if (r) {
333141ec0267Sriastradh 		dev_err(adev->dev, "Could not create pcie_replay_count");
333241ec0267Sriastradh 		return r;
333341ec0267Sriastradh 	}
333418c728deSriastradh #endif
333541ec0267Sriastradh 
333641ec0267Sriastradh 	if (IS_ENABLED(CONFIG_PERF_EVENTS))
333741ec0267Sriastradh 		r = amdgpu_pmu_init(adev);
333841ec0267Sriastradh 	if (r)
333941ec0267Sriastradh 		dev_err(adev->dev, "amdgpu_pmu_init failed\n");
334041ec0267Sriastradh 
334141ec0267Sriastradh 	return 0;
334241ec0267Sriastradh 
334341ec0267Sriastradh failed:
334441ec0267Sriastradh 	amdgpu_vf_error_trans_all(adev);
334541ec0267Sriastradh 	if (boco)
334641ec0267Sriastradh 		vga_switcheroo_fini_domain_pm_ops(adev->dev);
334741ec0267Sriastradh 
334841ec0267Sriastradh 	return r;
334941ec0267Sriastradh }
3350efa246c0Sriastradh 
3351efa246c0Sriastradh /**
3352efa246c0Sriastradh  * amdgpu_device_fini - tear down the driver
3353efa246c0Sriastradh  *
3354efa246c0Sriastradh  * @adev: amdgpu_device pointer
3355efa246c0Sriastradh  *
3356efa246c0Sriastradh  * Tear down the driver info (all asics).
3357efa246c0Sriastradh  * Called at driver shutdown.
3358efa246c0Sriastradh  */
amdgpu_device_fini(struct amdgpu_device * adev)3359efa246c0Sriastradh void amdgpu_device_fini(struct amdgpu_device *adev)
3360efa246c0Sriastradh {
33610d50c49dSriastradh 	int r __unused;
3362efa246c0Sriastradh 
3363efa246c0Sriastradh 	DRM_INFO("amdgpu: finishing device.\n");
336441ec0267Sriastradh 	flush_delayed_work(&adev->delayed_init_work);
3365efa246c0Sriastradh 	adev->shutdown = true;
336641ec0267Sriastradh 
336741ec0267Sriastradh 	/* disable all interrupts */
336841ec0267Sriastradh 	amdgpu_irq_disable_all(adev);
336941ec0267Sriastradh 	if (adev->mode_info.mode_config_initialized){
337041ec0267Sriastradh 		if (!amdgpu_device_has_dc_support(adev))
337141ec0267Sriastradh 			drm_helper_force_disable_all(adev->ddev);
337241ec0267Sriastradh 		else
337341ec0267Sriastradh 			drm_atomic_helper_shutdown(adev->ddev);
337441ec0267Sriastradh 	}
3375efa246c0Sriastradh 	amdgpu_fence_driver_fini(adev);
337641ec0267Sriastradh 	if (adev->pm_sysfs_en)
337741ec0267Sriastradh 		amdgpu_pm_sysfs_fini(adev);
3378efa246c0Sriastradh 	amdgpu_fbdev_fini(adev);
337941ec0267Sriastradh 	r = amdgpu_device_ip_fini(adev);
338041ec0267Sriastradh 	if (adev->firmware.gpu_info_fw) {
338141ec0267Sriastradh 		release_firmware(adev->firmware.gpu_info_fw);
338241ec0267Sriastradh 		adev->firmware.gpu_info_fw = NULL;
338341ec0267Sriastradh 	}
3384efa246c0Sriastradh 	adev->accel_working = false;
3385efa246c0Sriastradh 	/* free i2c buses */
338641ec0267Sriastradh 	if (!amdgpu_device_has_dc_support(adev))
3387efa246c0Sriastradh 		amdgpu_i2c_fini(adev);
338841ec0267Sriastradh 
338941ec0267Sriastradh 	if (amdgpu_emu_mode != 1)
3390efa246c0Sriastradh 		amdgpu_atombios_fini(adev);
339141ec0267Sriastradh 
3392efa246c0Sriastradh 	kfree(adev->bios);
3393efa246c0Sriastradh 	adev->bios = NULL;
33940d50c49dSriastradh #ifndef __NetBSD__		/* XXX amdgpu vga */
339541ec0267Sriastradh 	if (amdgpu_has_atpx() &&
339641ec0267Sriastradh 	    (amdgpu_is_atpx_hybrid() ||
339741ec0267Sriastradh 	     amdgpu_has_atpx_dgpu_power_cntl()) &&
339841ec0267Sriastradh 	    !pci_is_thunderbolt_attached(adev->pdev))
3399efa246c0Sriastradh 		vga_switcheroo_unregister_client(adev->pdev);
340041ec0267Sriastradh 	if (amdgpu_device_supports_boco(adev->ddev))
340141ec0267Sriastradh 		vga_switcheroo_fini_domain_pm_ops(adev->dev);
3402efa246c0Sriastradh 	vga_client_register(adev->pdev, NULL, NULL, NULL);
34030d50c49dSriastradh #endif
34040d50c49dSriastradh #ifdef __NetBSD__
34050d50c49dSriastradh 	if (adev->rio_mem_size)
34060d50c49dSriastradh 		bus_space_unmap(adev->rio_memt, adev->rio_memh,
34070d50c49dSriastradh 		    adev->rio_mem_size);
34080d50c49dSriastradh 	adev->rio_mem_size = 0;
34090d50c49dSriastradh 	bus_space_unmap(adev->rmmiot, adev->rmmioh, adev->rmmio_size);
34100d50c49dSriastradh #else
3411efa246c0Sriastradh 	if (adev->rio_mem)
3412efa246c0Sriastradh 		pci_iounmap(adev->pdev, adev->rio_mem);
3413efa246c0Sriastradh 	adev->rio_mem = NULL;
3414efa246c0Sriastradh 	iounmap(adev->rmmio);
3415efa246c0Sriastradh 	adev->rmmio = NULL;
34160d50c49dSriastradh #endif
341741ec0267Sriastradh 	amdgpu_device_doorbell_fini(adev);
341841ec0267Sriastradh 
3419efa246c0Sriastradh 	amdgpu_debugfs_regs_cleanup(adev);
3420dc219e9cSriastradh #ifndef __NetBSD__		/* XXX amdgpu sysfs */
342141ec0267Sriastradh 	device_remove_file(adev->dev, &dev_attr_pcie_replay_count);
3422dc219e9cSriastradh #endif
342341ec0267Sriastradh 	if (adev->ucode_sysfs_en)
342441ec0267Sriastradh 		amdgpu_ucode_sysfs_fini(adev);
342541ec0267Sriastradh 	if (IS_ENABLED(CONFIG_PERF_EVENTS))
342641ec0267Sriastradh 		amdgpu_pmu_fini(adev);
342741ec0267Sriastradh 	amdgpu_debugfs_preempt_cleanup(adev);
342841ec0267Sriastradh 	if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10)
342941ec0267Sriastradh 		amdgpu_discovery_fini(adev);
343041ec0267Sriastradh 	spin_lock_destroy(&adev->ring_lru_list_lock);
343141ec0267Sriastradh 	mutex_destroy(&adev->shadow_list_lock);
343241ec0267Sriastradh 	spin_lock_destroy(&adev->mm_stats.lock);
34330d50c49dSriastradh 	spin_lock_destroy(&adev->audio_endpt_idx_lock);
343441ec0267Sriastradh 	spin_lock_destroy(&adev->se_cac_idx_lock);
343541ec0267Sriastradh 	spin_lock_destroy(&adev->gc_cac_idx_lock);
34360d50c49dSriastradh 	spin_lock_destroy(&adev->didt_idx_lock);
34370d50c49dSriastradh 	spin_lock_destroy(&adev->uvd_ctx_idx_lock);
34380d50c49dSriastradh 	spin_lock_destroy(&adev->pcie_idx_lock);
34390d50c49dSriastradh 	spin_lock_destroy(&adev->smc_idx_lock);
34400d50c49dSriastradh 	spin_lock_destroy(&adev->mmio_idx_lock);
344141ec0267Sriastradh 	mutex_destroy(&adev->notifier_lock);
344241ec0267Sriastradh 	mutex_destroy(&adev->psp.mutex);
344341ec0267Sriastradh 	mutex_destroy(&adev->lock_reset);
344441ec0267Sriastradh 	/* hash_destroy(adev->mn_hash)? */
344541ec0267Sriastradh 	mutex_destroy(&adev->virt.vf_errors.lock);
34460d50c49dSriastradh 	mutex_destroy(&adev->mn_lock);
34470d50c49dSriastradh 	mutex_destroy(&adev->grbm_idx_mutex);
344841ec0267Sriastradh 	mutex_destroy(&adev->gfx.gfx_off_mutex);
344941ec0267Sriastradh 	mutex_destroy(&adev->gfx.pipe_reserve_mutex);
34500d50c49dSriastradh 	mutex_destroy(&adev->srbm_mutex);
34510d50c49dSriastradh 	mutex_destroy(&adev->gfx.gpu_clock_mutex);
34520d50c49dSriastradh 	mutex_destroy(&adev->pm.mutex);
345341ec0267Sriastradh 	mutex_destroy(&adev->firmware.mutex);
3454efa246c0Sriastradh }
3455efa246c0Sriastradh 
3456efa246c0Sriastradh 
3457efa246c0Sriastradh /*
3458efa246c0Sriastradh  * Suspend & resume.
3459efa246c0Sriastradh  */
3460efa246c0Sriastradh /**
346141ec0267Sriastradh  * amdgpu_device_suspend - initiate device suspend
3462efa246c0Sriastradh  *
346341ec0267Sriastradh  * @dev: drm dev pointer
346441ec0267Sriastradh  * @suspend: suspend state
346541ec0267Sriastradh  * @fbcon : notify the fbdev of suspend
3466efa246c0Sriastradh  *
3467efa246c0Sriastradh  * Puts the hw in the suspend state (all asics).
3468efa246c0Sriastradh  * Returns 0 for success or an error on failure.
3469efa246c0Sriastradh  * Called at driver suspend.
3470efa246c0Sriastradh  */
amdgpu_device_suspend(struct drm_device * dev,bool fbcon)347141ec0267Sriastradh int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
3472efa246c0Sriastradh {
3473efa246c0Sriastradh 	struct amdgpu_device *adev;
3474efa246c0Sriastradh 	struct drm_crtc *crtc;
3475efa246c0Sriastradh 	struct drm_connector *connector;
347641ec0267Sriastradh 	struct drm_connector_list_iter iter;
3477efa246c0Sriastradh 	int r;
3478efa246c0Sriastradh 
3479efa246c0Sriastradh 	if (dev == NULL || dev->dev_private == NULL) {
3480efa246c0Sriastradh 		return -ENODEV;
3481efa246c0Sriastradh 	}
3482efa246c0Sriastradh 
3483efa246c0Sriastradh 	adev = dev->dev_private;
3484efa246c0Sriastradh 
3485efa246c0Sriastradh 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
3486efa246c0Sriastradh 		return 0;
3487efa246c0Sriastradh 
348841ec0267Sriastradh 	adev->in_suspend = true;
3489efa246c0Sriastradh 	drm_kms_helper_poll_disable(dev);
3490efa246c0Sriastradh 
349141ec0267Sriastradh 	if (fbcon)
349241ec0267Sriastradh 		amdgpu_fbdev_set_suspend(adev, 1);
349341ec0267Sriastradh 
349441ec0267Sriastradh 	cancel_delayed_work_sync(&adev->delayed_init_work);
349541ec0267Sriastradh 
349641ec0267Sriastradh 	if (!amdgpu_device_has_dc_support(adev)) {
3497efa246c0Sriastradh 		/* turn off display hw */
3498efa246c0Sriastradh 		drm_modeset_lock_all(dev);
349941ec0267Sriastradh 		drm_connector_list_iter_begin(dev, &iter);
350041ec0267Sriastradh 		drm_for_each_connector_iter(connector, &iter)
350141ec0267Sriastradh 			drm_helper_connector_dpms(connector,
350241ec0267Sriastradh 						  DRM_MODE_DPMS_OFF);
350341ec0267Sriastradh 		drm_connector_list_iter_end(&iter);
3504efa246c0Sriastradh 		drm_modeset_unlock_all(dev);
3505efa246c0Sriastradh 			/* unpin the front buffers and cursors */
3506efa246c0Sriastradh 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
3507efa246c0Sriastradh 			struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
350841ec0267Sriastradh 			struct drm_framebuffer *fb = crtc->primary->fb;
3509efa246c0Sriastradh 			struct amdgpu_bo *robj;
3510efa246c0Sriastradh 
351141ec0267Sriastradh 			if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
3512efa246c0Sriastradh 				struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
351341ec0267Sriastradh 				r = amdgpu_bo_reserve(aobj, true);
3514efa246c0Sriastradh 				if (r == 0) {
3515efa246c0Sriastradh 					amdgpu_bo_unpin(aobj);
3516efa246c0Sriastradh 					amdgpu_bo_unreserve(aobj);
3517efa246c0Sriastradh 				}
3518efa246c0Sriastradh 			}
3519efa246c0Sriastradh 
352041ec0267Sriastradh 			if (fb == NULL || fb->obj[0] == NULL) {
3521efa246c0Sriastradh 				continue;
3522efa246c0Sriastradh 			}
352341ec0267Sriastradh 			robj = gem_to_amdgpu_bo(fb->obj[0]);
3524efa246c0Sriastradh 			/* don't unpin kernel fb objects */
3525efa246c0Sriastradh 			if (!amdgpu_fbdev_robj_is_fb(adev, robj)) {
352641ec0267Sriastradh 				r = amdgpu_bo_reserve(robj, true);
3527efa246c0Sriastradh 				if (r == 0) {
3528efa246c0Sriastradh 					amdgpu_bo_unpin(robj);
3529efa246c0Sriastradh 					amdgpu_bo_unreserve(robj);
3530efa246c0Sriastradh 				}
3531efa246c0Sriastradh 			}
3532efa246c0Sriastradh 		}
353341ec0267Sriastradh 	}
353441ec0267Sriastradh 
353541ec0267Sriastradh 	amdgpu_amdkfd_suspend(adev);
353641ec0267Sriastradh 
353741ec0267Sriastradh 	amdgpu_ras_suspend(adev);
353841ec0267Sriastradh 
353941ec0267Sriastradh 	r = amdgpu_device_ip_suspend_phase1(adev);
354041ec0267Sriastradh 
3541efa246c0Sriastradh 	/* evict vram memory */
3542efa246c0Sriastradh 	amdgpu_bo_evict_vram(adev);
3543efa246c0Sriastradh 
3544efa246c0Sriastradh 	amdgpu_fence_driver_suspend(adev);
3545efa246c0Sriastradh 
354641ec0267Sriastradh 	r = amdgpu_device_ip_suspend_phase2(adev);
3547efa246c0Sriastradh 
354841ec0267Sriastradh 	/* evict remaining vram memory
354941ec0267Sriastradh 	 * This second call to evict vram is to evict the gart page table
355041ec0267Sriastradh 	 * using the CPU.
355141ec0267Sriastradh 	 */
3552efa246c0Sriastradh 	amdgpu_bo_evict_vram(adev);
3553efa246c0Sriastradh 
3554efa246c0Sriastradh 	return 0;
3555efa246c0Sriastradh }
3556efa246c0Sriastradh 
3557efa246c0Sriastradh /**
355841ec0267Sriastradh  * amdgpu_device_resume - initiate device resume
3559efa246c0Sriastradh  *
356041ec0267Sriastradh  * @dev: drm dev pointer
356141ec0267Sriastradh  * @resume: resume state
356241ec0267Sriastradh  * @fbcon : notify the fbdev of resume
3563efa246c0Sriastradh  *
3564efa246c0Sriastradh  * Bring the hw back to operating state (all asics).
3565efa246c0Sriastradh  * Returns 0 for success or an error on failure.
3566efa246c0Sriastradh  * Called at driver resume.
3567efa246c0Sriastradh  */
amdgpu_device_resume(struct drm_device * dev,bool fbcon)356841ec0267Sriastradh int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
3569efa246c0Sriastradh {
3570efa246c0Sriastradh 	struct drm_connector *connector;
357141ec0267Sriastradh 	struct drm_connector_list_iter iter;
3572efa246c0Sriastradh 	struct amdgpu_device *adev = dev->dev_private;
3573efa246c0Sriastradh 	struct drm_crtc *crtc;
357441ec0267Sriastradh 	int r = 0;
3575efa246c0Sriastradh 
3576efa246c0Sriastradh 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
3577efa246c0Sriastradh 		return 0;
3578efa246c0Sriastradh 
3579efa246c0Sriastradh 	/* post card */
358041ec0267Sriastradh 	if (amdgpu_device_need_post(adev)) {
358141ec0267Sriastradh 		r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
3582efa246c0Sriastradh 		if (r)
358341ec0267Sriastradh 			DRM_ERROR("amdgpu asic init failed\n");
3584efa246c0Sriastradh 	}
3585efa246c0Sriastradh 
358641ec0267Sriastradh 	r = amdgpu_device_ip_resume(adev);
3587efa246c0Sriastradh 	if (r) {
358841ec0267Sriastradh 		DRM_ERROR("amdgpu_device_ip_resume failed (%d).\n", r);
3589efa246c0Sriastradh 		return r;
3590efa246c0Sriastradh 	}
359141ec0267Sriastradh 	amdgpu_fence_driver_resume(adev);
3592efa246c0Sriastradh 
359341ec0267Sriastradh 
359441ec0267Sriastradh 	r = amdgpu_device_ip_late_init(adev);
359541ec0267Sriastradh 	if (r)
359641ec0267Sriastradh 		return r;
359741ec0267Sriastradh 
359841ec0267Sriastradh 	queue_delayed_work(system_wq, &adev->delayed_init_work,
359941ec0267Sriastradh 			   msecs_to_jiffies(AMDGPU_RESUME_MS));
360041ec0267Sriastradh 
360141ec0267Sriastradh 	if (!amdgpu_device_has_dc_support(adev)) {
3602efa246c0Sriastradh 		/* pin cursors */
3603efa246c0Sriastradh 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
3604efa246c0Sriastradh 			struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
3605efa246c0Sriastradh 
360641ec0267Sriastradh 			if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
3607efa246c0Sriastradh 				struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
360841ec0267Sriastradh 				r = amdgpu_bo_reserve(aobj, true);
3609efa246c0Sriastradh 				if (r == 0) {
361041ec0267Sriastradh 					r = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM);
3611efa246c0Sriastradh 					if (r != 0)
3612efa246c0Sriastradh 						DRM_ERROR("Failed to pin cursor BO (%d)\n", r);
361341ec0267Sriastradh 					amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj);
3614efa246c0Sriastradh 					amdgpu_bo_unreserve(aobj);
3615efa246c0Sriastradh 				}
3616efa246c0Sriastradh 			}
3617efa246c0Sriastradh 		}
361841ec0267Sriastradh 	}
361941ec0267Sriastradh 	r = amdgpu_amdkfd_resume(adev);
362041ec0267Sriastradh 	if (r)
362141ec0267Sriastradh 		return r;
362241ec0267Sriastradh 
362341ec0267Sriastradh 	/* Make sure IB tests flushed */
362441ec0267Sriastradh 	flush_delayed_work(&adev->delayed_init_work);
3625efa246c0Sriastradh 
3626efa246c0Sriastradh 	/* blat the mode back in */
3627efa246c0Sriastradh 	if (fbcon) {
362841ec0267Sriastradh 		if (!amdgpu_device_has_dc_support(adev)) {
362941ec0267Sriastradh 			/* pre DCE11 */
3630efa246c0Sriastradh 			drm_helper_resume_force_mode(dev);
363141ec0267Sriastradh 
3632efa246c0Sriastradh 			/* turn on display hw */
3633efa246c0Sriastradh 			drm_modeset_lock_all(dev);
363441ec0267Sriastradh 
363541ec0267Sriastradh 			drm_connector_list_iter_begin(dev, &iter);
363641ec0267Sriastradh 			drm_for_each_connector_iter(connector, &iter)
363741ec0267Sriastradh 				drm_helper_connector_dpms(connector,
363841ec0267Sriastradh 							  DRM_MODE_DPMS_ON);
363941ec0267Sriastradh 			drm_connector_list_iter_end(&iter);
364041ec0267Sriastradh 
3641efa246c0Sriastradh 			drm_modeset_unlock_all(dev);
3642efa246c0Sriastradh 		}
364341ec0267Sriastradh 		amdgpu_fbdev_set_suspend(adev, 0);
364441ec0267Sriastradh 	}
3645efa246c0Sriastradh 
3646efa246c0Sriastradh 	drm_kms_helper_poll_enable(dev);
3647efa246c0Sriastradh 
364841ec0267Sriastradh 	amdgpu_ras_resume(adev);
364941ec0267Sriastradh 
3650efa246c0Sriastradh 	/*
3651efa246c0Sriastradh 	 * Most of the connector probing functions try to acquire runtime pm
3652efa246c0Sriastradh 	 * refs to ensure that the GPU is powered on when connector polling is
3653efa246c0Sriastradh 	 * performed. Since we're calling this from a runtime PM callback,
3654efa246c0Sriastradh 	 * trying to acquire rpm refs will cause us to deadlock.
3655efa246c0Sriastradh 	 *
3656efa246c0Sriastradh 	 * Since we're guaranteed to be holding the rpm lock, it's safe to
3657efa246c0Sriastradh 	 * temporarily disable the rpm helpers so this doesn't deadlock us.
3658efa246c0Sriastradh 	 */
3659efa246c0Sriastradh #ifdef CONFIG_PM
3660efa246c0Sriastradh 	dev->dev->power.disable_depth++;
3661efa246c0Sriastradh #endif
366241ec0267Sriastradh 	if (!amdgpu_device_has_dc_support(adev))
3663efa246c0Sriastradh 		drm_helper_hpd_irq_event(dev);
366441ec0267Sriastradh 	else
366541ec0267Sriastradh 		drm_kms_helper_hotplug_event(dev);
3666efa246c0Sriastradh #ifdef CONFIG_PM
3667efa246c0Sriastradh 	dev->dev->power.disable_depth--;
3668efa246c0Sriastradh #endif
366941ec0267Sriastradh 	adev->in_suspend = false;
3670efa246c0Sriastradh 
367141ec0267Sriastradh 	return 0;
367241ec0267Sriastradh }
367341ec0267Sriastradh 
367441ec0267Sriastradh /**
367541ec0267Sriastradh  * amdgpu_device_ip_check_soft_reset - did soft reset succeed
367641ec0267Sriastradh  *
367741ec0267Sriastradh  * @adev: amdgpu_device pointer
367841ec0267Sriastradh  *
367941ec0267Sriastradh  * The list of all the hardware IPs that make up the asic is walked and
368041ec0267Sriastradh  * the check_soft_reset callbacks are run.  check_soft_reset determines
368141ec0267Sriastradh  * if the asic is still hung or not.
368241ec0267Sriastradh  * Returns true if any of the IPs are still in a hung state, false if not.
368341ec0267Sriastradh  */
amdgpu_device_ip_check_soft_reset(struct amdgpu_device * adev)368441ec0267Sriastradh static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev)
368541ec0267Sriastradh {
368641ec0267Sriastradh 	int i;
368741ec0267Sriastradh 	bool asic_hang = false;
368841ec0267Sriastradh 
368941ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
369041ec0267Sriastradh 		return true;
369141ec0267Sriastradh 
369241ec0267Sriastradh 	if (amdgpu_asic_need_full_reset(adev))
369341ec0267Sriastradh 		return true;
369441ec0267Sriastradh 
369541ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
369641ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
369741ec0267Sriastradh 			continue;
369841ec0267Sriastradh 		if (adev->ip_blocks[i].version->funcs->check_soft_reset)
369941ec0267Sriastradh 			adev->ip_blocks[i].status.hang =
370041ec0267Sriastradh 				adev->ip_blocks[i].version->funcs->check_soft_reset(adev);
370141ec0267Sriastradh 		if (adev->ip_blocks[i].status.hang) {
370241ec0267Sriastradh 			DRM_INFO("IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name);
370341ec0267Sriastradh 			asic_hang = true;
370441ec0267Sriastradh 		}
370541ec0267Sriastradh 	}
370641ec0267Sriastradh 	return asic_hang;
370741ec0267Sriastradh }
370841ec0267Sriastradh 
370941ec0267Sriastradh /**
371041ec0267Sriastradh  * amdgpu_device_ip_pre_soft_reset - prepare for soft reset
371141ec0267Sriastradh  *
371241ec0267Sriastradh  * @adev: amdgpu_device pointer
371341ec0267Sriastradh  *
371441ec0267Sriastradh  * The list of all the hardware IPs that make up the asic is walked and the
371541ec0267Sriastradh  * pre_soft_reset callbacks are run if the block is hung.  pre_soft_reset
371641ec0267Sriastradh  * handles any IP specific hardware or software state changes that are
371741ec0267Sriastradh  * necessary for a soft reset to succeed.
371841ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
371941ec0267Sriastradh  */
amdgpu_device_ip_pre_soft_reset(struct amdgpu_device * adev)372041ec0267Sriastradh static int amdgpu_device_ip_pre_soft_reset(struct amdgpu_device *adev)
372141ec0267Sriastradh {
372241ec0267Sriastradh 	int i, r = 0;
372341ec0267Sriastradh 
372441ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
372541ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
372641ec0267Sriastradh 			continue;
372741ec0267Sriastradh 		if (adev->ip_blocks[i].status.hang &&
372841ec0267Sriastradh 		    adev->ip_blocks[i].version->funcs->pre_soft_reset) {
372941ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->pre_soft_reset(adev);
373041ec0267Sriastradh 			if (r)
373141ec0267Sriastradh 				return r;
373241ec0267Sriastradh 		}
3733efa246c0Sriastradh 	}
3734efa246c0Sriastradh 
3735efa246c0Sriastradh 	return 0;
3736efa246c0Sriastradh }
3737efa246c0Sriastradh 
3738efa246c0Sriastradh /**
373941ec0267Sriastradh  * amdgpu_device_ip_need_full_reset - check if a full asic reset is needed
374041ec0267Sriastradh  *
374141ec0267Sriastradh  * @adev: amdgpu_device pointer
374241ec0267Sriastradh  *
374341ec0267Sriastradh  * Some hardware IPs cannot be soft reset.  If they are hung, a full gpu
374441ec0267Sriastradh  * reset is necessary to recover.
374541ec0267Sriastradh  * Returns true if a full asic reset is required, false if not.
374641ec0267Sriastradh  */
amdgpu_device_ip_need_full_reset(struct amdgpu_device * adev)374741ec0267Sriastradh static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev)
374841ec0267Sriastradh {
374941ec0267Sriastradh 	int i;
375041ec0267Sriastradh 
375141ec0267Sriastradh 	if (amdgpu_asic_need_full_reset(adev))
375241ec0267Sriastradh 		return true;
375341ec0267Sriastradh 
375441ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
375541ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
375641ec0267Sriastradh 			continue;
375741ec0267Sriastradh 		if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) ||
375841ec0267Sriastradh 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) ||
375941ec0267Sriastradh 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) ||
376041ec0267Sriastradh 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) ||
376141ec0267Sriastradh 		     adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
376241ec0267Sriastradh 			if (adev->ip_blocks[i].status.hang) {
376341ec0267Sriastradh 				DRM_INFO("Some block need full reset!\n");
376441ec0267Sriastradh 				return true;
376541ec0267Sriastradh 			}
376641ec0267Sriastradh 		}
376741ec0267Sriastradh 	}
376841ec0267Sriastradh 	return false;
376941ec0267Sriastradh }
377041ec0267Sriastradh 
377141ec0267Sriastradh /**
377241ec0267Sriastradh  * amdgpu_device_ip_soft_reset - do a soft reset
377341ec0267Sriastradh  *
377441ec0267Sriastradh  * @adev: amdgpu_device pointer
377541ec0267Sriastradh  *
377641ec0267Sriastradh  * The list of all the hardware IPs that make up the asic is walked and the
377741ec0267Sriastradh  * soft_reset callbacks are run if the block is hung.  soft_reset handles any
377841ec0267Sriastradh  * IP specific hardware or software state changes that are necessary to soft
377941ec0267Sriastradh  * reset the IP.
378041ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
378141ec0267Sriastradh  */
amdgpu_device_ip_soft_reset(struct amdgpu_device * adev)378241ec0267Sriastradh static int amdgpu_device_ip_soft_reset(struct amdgpu_device *adev)
378341ec0267Sriastradh {
378441ec0267Sriastradh 	int i, r = 0;
378541ec0267Sriastradh 
378641ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
378741ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
378841ec0267Sriastradh 			continue;
378941ec0267Sriastradh 		if (adev->ip_blocks[i].status.hang &&
379041ec0267Sriastradh 		    adev->ip_blocks[i].version->funcs->soft_reset) {
379141ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->soft_reset(adev);
379241ec0267Sriastradh 			if (r)
379341ec0267Sriastradh 				return r;
379441ec0267Sriastradh 		}
379541ec0267Sriastradh 	}
379641ec0267Sriastradh 
379741ec0267Sriastradh 	return 0;
379841ec0267Sriastradh }
379941ec0267Sriastradh 
380041ec0267Sriastradh /**
380141ec0267Sriastradh  * amdgpu_device_ip_post_soft_reset - clean up from soft reset
380241ec0267Sriastradh  *
380341ec0267Sriastradh  * @adev: amdgpu_device pointer
380441ec0267Sriastradh  *
380541ec0267Sriastradh  * The list of all the hardware IPs that make up the asic is walked and the
380641ec0267Sriastradh  * post_soft_reset callbacks are run if the asic was hung.  post_soft_reset
380741ec0267Sriastradh  * handles any IP specific hardware or software state changes that are
380841ec0267Sriastradh  * necessary after the IP has been soft reset.
380941ec0267Sriastradh  * Returns 0 on success, negative error code on failure.
381041ec0267Sriastradh  */
amdgpu_device_ip_post_soft_reset(struct amdgpu_device * adev)381141ec0267Sriastradh static int amdgpu_device_ip_post_soft_reset(struct amdgpu_device *adev)
381241ec0267Sriastradh {
381341ec0267Sriastradh 	int i, r = 0;
381441ec0267Sriastradh 
381541ec0267Sriastradh 	for (i = 0; i < adev->num_ip_blocks; i++) {
381641ec0267Sriastradh 		if (!adev->ip_blocks[i].status.valid)
381741ec0267Sriastradh 			continue;
381841ec0267Sriastradh 		if (adev->ip_blocks[i].status.hang &&
381941ec0267Sriastradh 		    adev->ip_blocks[i].version->funcs->post_soft_reset)
382041ec0267Sriastradh 			r = adev->ip_blocks[i].version->funcs->post_soft_reset(adev);
382141ec0267Sriastradh 		if (r)
382241ec0267Sriastradh 			return r;
382341ec0267Sriastradh 	}
382441ec0267Sriastradh 
382541ec0267Sriastradh 	return 0;
382641ec0267Sriastradh }
382741ec0267Sriastradh 
382841ec0267Sriastradh /**
382941ec0267Sriastradh  * amdgpu_device_recover_vram - Recover some VRAM contents
383041ec0267Sriastradh  *
383141ec0267Sriastradh  * @adev: amdgpu_device pointer
383241ec0267Sriastradh  *
383341ec0267Sriastradh  * Restores the contents of VRAM buffers from the shadows in GTT.  Used to
383441ec0267Sriastradh  * restore things like GPUVM page tables after a GPU reset where
383541ec0267Sriastradh  * the contents of VRAM might be lost.
383641ec0267Sriastradh  *
383741ec0267Sriastradh  * Returns:
383841ec0267Sriastradh  * 0 on success, negative error code on failure.
383941ec0267Sriastradh  */
amdgpu_device_recover_vram(struct amdgpu_device * adev)384041ec0267Sriastradh static int amdgpu_device_recover_vram(struct amdgpu_device *adev)
384141ec0267Sriastradh {
384241ec0267Sriastradh 	struct dma_fence *fence = NULL, *next = NULL;
384341ec0267Sriastradh 	struct amdgpu_bo *shadow;
384441ec0267Sriastradh 	long r = 1, tmo;
384541ec0267Sriastradh 
384641ec0267Sriastradh 	if (amdgpu_sriov_runtime(adev))
384741ec0267Sriastradh 		tmo = msecs_to_jiffies(8000);
384841ec0267Sriastradh 	else
384941ec0267Sriastradh 		tmo = msecs_to_jiffies(100);
385041ec0267Sriastradh 
385141ec0267Sriastradh 	DRM_INFO("recover vram bo from shadow start\n");
385241ec0267Sriastradh 	mutex_lock(&adev->shadow_list_lock);
385341ec0267Sriastradh 	list_for_each_entry(shadow, &adev->shadow_list, shadow_list) {
385441ec0267Sriastradh 
385541ec0267Sriastradh 		/* No need to recover an evicted BO */
385641ec0267Sriastradh 		if (shadow->tbo.mem.mem_type != TTM_PL_TT ||
385741ec0267Sriastradh 		    shadow->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET ||
385841ec0267Sriastradh 		    shadow->parent->tbo.mem.mem_type != TTM_PL_VRAM)
385941ec0267Sriastradh 			continue;
386041ec0267Sriastradh 
386141ec0267Sriastradh 		r = amdgpu_bo_restore_shadow(shadow, &next);
386241ec0267Sriastradh 		if (r)
386341ec0267Sriastradh 			break;
386441ec0267Sriastradh 
386541ec0267Sriastradh 		if (fence) {
386641ec0267Sriastradh 			tmo = dma_fence_wait_timeout(fence, false, tmo);
386741ec0267Sriastradh 			dma_fence_put(fence);
386841ec0267Sriastradh 			fence = next;
386941ec0267Sriastradh 			if (tmo == 0) {
387041ec0267Sriastradh 				r = -ETIMEDOUT;
387141ec0267Sriastradh 				break;
387241ec0267Sriastradh 			} else if (tmo < 0) {
387341ec0267Sriastradh 				r = tmo;
387441ec0267Sriastradh 				break;
387541ec0267Sriastradh 			}
387641ec0267Sriastradh 		} else {
387741ec0267Sriastradh 			fence = next;
387841ec0267Sriastradh 		}
387941ec0267Sriastradh 	}
388041ec0267Sriastradh 	mutex_unlock(&adev->shadow_list_lock);
388141ec0267Sriastradh 
388241ec0267Sriastradh 	if (fence)
388341ec0267Sriastradh 		tmo = dma_fence_wait_timeout(fence, false, tmo);
388441ec0267Sriastradh 	dma_fence_put(fence);
388541ec0267Sriastradh 
388641ec0267Sriastradh 	if (r < 0 || tmo <= 0) {
388741ec0267Sriastradh 		DRM_ERROR("recover vram bo from shadow failed, r is %ld, tmo is %ld\n", r, tmo);
388841ec0267Sriastradh 		return -EIO;
388941ec0267Sriastradh 	}
389041ec0267Sriastradh 
389141ec0267Sriastradh 	DRM_INFO("recover vram bo from shadow done\n");
389241ec0267Sriastradh 	return 0;
389341ec0267Sriastradh }
389441ec0267Sriastradh 
389541ec0267Sriastradh 
389641ec0267Sriastradh /**
389741ec0267Sriastradh  * amdgpu_device_reset_sriov - reset ASIC for SR-IOV vf
389841ec0267Sriastradh  *
389941ec0267Sriastradh  * @adev: amdgpu device pointer
390041ec0267Sriastradh  * @from_hypervisor: request from hypervisor
390141ec0267Sriastradh  *
390241ec0267Sriastradh  * do VF FLR and reinitialize Asic
390341ec0267Sriastradh  * return 0 means succeeded otherwise failed
390441ec0267Sriastradh  */
amdgpu_device_reset_sriov(struct amdgpu_device * adev,bool from_hypervisor)390541ec0267Sriastradh static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
390641ec0267Sriastradh 				     bool from_hypervisor)
390741ec0267Sriastradh {
390841ec0267Sriastradh 	int r;
390941ec0267Sriastradh 
391041ec0267Sriastradh 	if (from_hypervisor)
391141ec0267Sriastradh 		r = amdgpu_virt_request_full_gpu(adev, true);
391241ec0267Sriastradh 	else
391341ec0267Sriastradh 		r = amdgpu_virt_reset_gpu(adev);
391441ec0267Sriastradh 	if (r)
391541ec0267Sriastradh 		return r;
391641ec0267Sriastradh 
391741ec0267Sriastradh 	/* Resume IP prior to SMC */
391841ec0267Sriastradh 	r = amdgpu_device_ip_reinit_early_sriov(adev);
391941ec0267Sriastradh 	if (r)
392041ec0267Sriastradh 		goto error;
392141ec0267Sriastradh 
392241ec0267Sriastradh 	amdgpu_virt_init_data_exchange(adev);
392341ec0267Sriastradh 	/* we need recover gart prior to run SMC/CP/SDMA resume */
392441ec0267Sriastradh 	amdgpu_gtt_mgr_recover(&adev->mman.bdev.man[TTM_PL_TT]);
392541ec0267Sriastradh 
392641ec0267Sriastradh 	r = amdgpu_device_fw_loading(adev);
392741ec0267Sriastradh 	if (r)
392841ec0267Sriastradh 		return r;
392941ec0267Sriastradh 
393041ec0267Sriastradh 	/* now we are okay to resume SMC/CP/SDMA */
393141ec0267Sriastradh 	r = amdgpu_device_ip_reinit_late_sriov(adev);
393241ec0267Sriastradh 	if (r)
393341ec0267Sriastradh 		goto error;
393441ec0267Sriastradh 
393541ec0267Sriastradh 	amdgpu_irq_gpu_reset_resume_helper(adev);
393641ec0267Sriastradh 	r = amdgpu_ib_ring_tests(adev);
393741ec0267Sriastradh 	amdgpu_amdkfd_post_reset(adev);
393841ec0267Sriastradh 
393941ec0267Sriastradh error:
394041ec0267Sriastradh 	amdgpu_virt_release_full_gpu(adev, true);
394141ec0267Sriastradh 	if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
394241ec0267Sriastradh 		amdgpu_inc_vram_lost(adev);
394341ec0267Sriastradh 		r = amdgpu_device_recover_vram(adev);
394441ec0267Sriastradh 	}
394541ec0267Sriastradh 
394641ec0267Sriastradh 	return r;
394741ec0267Sriastradh }
394841ec0267Sriastradh 
394941ec0267Sriastradh /**
395041ec0267Sriastradh  * amdgpu_device_should_recover_gpu - check if we should try GPU recovery
3951efa246c0Sriastradh  *
3952efa246c0Sriastradh  * @adev: amdgpu device pointer
3953efa246c0Sriastradh  *
395441ec0267Sriastradh  * Check amdgpu_gpu_recovery and SRIOV status to see if we should try to recover
395541ec0267Sriastradh  * a hung GPU.
3956efa246c0Sriastradh  */
amdgpu_device_should_recover_gpu(struct amdgpu_device * adev)395741ec0267Sriastradh bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
3958efa246c0Sriastradh {
395941ec0267Sriastradh 	if (!amdgpu_device_ip_check_soft_reset(adev)) {
396041ec0267Sriastradh 		DRM_INFO("Timeout, but no hardware hang detected.\n");
396141ec0267Sriastradh 		return false;
396241ec0267Sriastradh 	}
3963efa246c0Sriastradh 
396441ec0267Sriastradh 	if (amdgpu_gpu_recovery == 0)
396541ec0267Sriastradh 		goto disabled;
3966efa246c0Sriastradh 
396741ec0267Sriastradh 	if (amdgpu_sriov_vf(adev))
396841ec0267Sriastradh 		return true;
3969efa246c0Sriastradh 
397041ec0267Sriastradh 	if (amdgpu_gpu_recovery == -1) {
397141ec0267Sriastradh 		switch (adev->asic_type) {
397241ec0267Sriastradh 		case CHIP_BONAIRE:
397341ec0267Sriastradh 		case CHIP_HAWAII:
397441ec0267Sriastradh 		case CHIP_TOPAZ:
397541ec0267Sriastradh 		case CHIP_TONGA:
397641ec0267Sriastradh 		case CHIP_FIJI:
397741ec0267Sriastradh 		case CHIP_POLARIS10:
397841ec0267Sriastradh 		case CHIP_POLARIS11:
397941ec0267Sriastradh 		case CHIP_POLARIS12:
398041ec0267Sriastradh 		case CHIP_VEGAM:
398141ec0267Sriastradh 		case CHIP_VEGA20:
398241ec0267Sriastradh 		case CHIP_VEGA10:
398341ec0267Sriastradh 		case CHIP_VEGA12:
398441ec0267Sriastradh 		case CHIP_RAVEN:
398541ec0267Sriastradh 		case CHIP_ARCTURUS:
398641ec0267Sriastradh 		case CHIP_RENOIR:
398741ec0267Sriastradh 		case CHIP_NAVI10:
398841ec0267Sriastradh 		case CHIP_NAVI14:
398941ec0267Sriastradh 		case CHIP_NAVI12:
399041ec0267Sriastradh 			break;
399141ec0267Sriastradh 		default:
399241ec0267Sriastradh 			goto disabled;
399341ec0267Sriastradh 		}
399441ec0267Sriastradh 	}
3995efa246c0Sriastradh 
399641ec0267Sriastradh 	return true;
3997efa246c0Sriastradh 
399841ec0267Sriastradh disabled:
399941ec0267Sriastradh 		DRM_INFO("GPU recovery disabled.\n");
400041ec0267Sriastradh 		return false;
400141ec0267Sriastradh }
4002efa246c0Sriastradh 
400341ec0267Sriastradh 
amdgpu_device_pre_asic_reset(struct amdgpu_device * adev,struct amdgpu_job * job,bool * need_full_reset_arg)400441ec0267Sriastradh static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
400541ec0267Sriastradh 					struct amdgpu_job *job,
400641ec0267Sriastradh 					bool *need_full_reset_arg)
400741ec0267Sriastradh {
400841ec0267Sriastradh 	int i, r = 0;
400941ec0267Sriastradh 	bool need_full_reset  = *need_full_reset_arg;
401041ec0267Sriastradh 
401141ec0267Sriastradh 	/* block all schedulers and reset given job's ring */
4012efa246c0Sriastradh 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
4013efa246c0Sriastradh 		struct amdgpu_ring *ring = adev->rings[i];
401441ec0267Sriastradh 
401541ec0267Sriastradh 		if (!ring || !ring->sched.thread)
4016efa246c0Sriastradh 			continue;
4017efa246c0Sriastradh 
401841ec0267Sriastradh 		/* after all hw jobs are reset, hw fence is meaningless, so force_completion */
401941ec0267Sriastradh 		amdgpu_fence_driver_force_completion(ring);
402041ec0267Sriastradh 	}
402141ec0267Sriastradh 
402241ec0267Sriastradh 	if(job)
402341ec0267Sriastradh 		drm_sched_increase_karma(&job->base);
402441ec0267Sriastradh 
402541ec0267Sriastradh 	/* Don't suspend on bare metal if we are not going to HW reset the ASIC */
402641ec0267Sriastradh 	if (!amdgpu_sriov_vf(adev)) {
402741ec0267Sriastradh 
402841ec0267Sriastradh 		if (!need_full_reset)
402941ec0267Sriastradh 			need_full_reset = amdgpu_device_ip_need_full_reset(adev);
403041ec0267Sriastradh 
403141ec0267Sriastradh 		if (!need_full_reset) {
403241ec0267Sriastradh 			amdgpu_device_ip_pre_soft_reset(adev);
403341ec0267Sriastradh 			r = amdgpu_device_ip_soft_reset(adev);
403441ec0267Sriastradh 			amdgpu_device_ip_post_soft_reset(adev);
403541ec0267Sriastradh 			if (r || amdgpu_device_ip_check_soft_reset(adev)) {
403641ec0267Sriastradh 				DRM_INFO("soft reset failed, will fallback to full reset!\n");
403741ec0267Sriastradh 				need_full_reset = true;
4038efa246c0Sriastradh 			}
4039efa246c0Sriastradh 		}
4040efa246c0Sriastradh 
404141ec0267Sriastradh 		if (need_full_reset)
404241ec0267Sriastradh 			r = amdgpu_device_ip_suspend(adev);
4043efa246c0Sriastradh 
404441ec0267Sriastradh 		*need_full_reset_arg = need_full_reset;
4045efa246c0Sriastradh 	}
4046efa246c0Sriastradh 
4047efa246c0Sriastradh 	return r;
4048efa246c0Sriastradh }
4049efa246c0Sriastradh 
amdgpu_do_asic_reset(struct amdgpu_hive_info * hive,struct list_head * device_list_handle,bool * need_full_reset_arg)405041ec0267Sriastradh static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
405141ec0267Sriastradh 			       struct list_head *device_list_handle,
405241ec0267Sriastradh 			       bool *need_full_reset_arg)
405341ec0267Sriastradh {
405441ec0267Sriastradh 	struct amdgpu_device *tmp_adev = NULL;
405541ec0267Sriastradh 	bool need_full_reset = *need_full_reset_arg, vram_lost = false;
405641ec0267Sriastradh 	int r = 0;
4057efa246c0Sriastradh 
4058efa246c0Sriastradh 	/*
405941ec0267Sriastradh 	 * ASIC reset has to be done on all HGMI hive nodes ASAP
406041ec0267Sriastradh 	 * to allow proper links negotiation in FW (within 1 sec)
4061efa246c0Sriastradh 	 */
406241ec0267Sriastradh 	if (need_full_reset) {
406341ec0267Sriastradh 		list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
406441ec0267Sriastradh 			/* For XGMI run all resets in parallel to speed up the process */
406541ec0267Sriastradh 			if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
406641ec0267Sriastradh 				if (!queue_work(system_unbound_wq, &tmp_adev->xgmi_reset_work))
406741ec0267Sriastradh 					r = -EALREADY;
406841ec0267Sriastradh 			} else
406941ec0267Sriastradh 				r = amdgpu_asic_reset(tmp_adev);
4070efa246c0Sriastradh 
407141ec0267Sriastradh 			if (r) {
407241ec0267Sriastradh 				DRM_ERROR("ASIC reset failed with error, %d for drm dev, %s",
407341ec0267Sriastradh 					 r, tmp_adev->ddev->unique);
407441ec0267Sriastradh 				break;
4075efa246c0Sriastradh 			}
4076efa246c0Sriastradh 		}
4077efa246c0Sriastradh 
407841ec0267Sriastradh 		/* For XGMI wait for all resets to complete before proceed */
407941ec0267Sriastradh 		if (!r) {
408041ec0267Sriastradh 			list_for_each_entry(tmp_adev, device_list_handle,
408141ec0267Sriastradh 					    gmc.xgmi.head) {
408241ec0267Sriastradh 				if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
408341ec0267Sriastradh 					flush_work(&tmp_adev->xgmi_reset_work);
408441ec0267Sriastradh 					r = tmp_adev->asic_reset_res;
408541ec0267Sriastradh 					if (r)
408641ec0267Sriastradh 						break;
4087efa246c0Sriastradh 				}
408841ec0267Sriastradh 			}
408941ec0267Sriastradh 		}
4090efa246c0Sriastradh 	}
4091efa246c0Sriastradh 
409241ec0267Sriastradh 	if (!r && amdgpu_ras_intr_triggered())
409341ec0267Sriastradh 		amdgpu_ras_intr_cleared();
4094efa246c0Sriastradh 
409541ec0267Sriastradh 	list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
409641ec0267Sriastradh 		if (need_full_reset) {
409741ec0267Sriastradh 			/* post card */
409841ec0267Sriastradh 			if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context))
409941ec0267Sriastradh 				DRM_WARN("asic atom init failed!");
410041ec0267Sriastradh 
410141ec0267Sriastradh 			if (!r) {
410241ec0267Sriastradh 				dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n");
410341ec0267Sriastradh 				r = amdgpu_device_ip_resume_phase1(tmp_adev);
410441ec0267Sriastradh 				if (r)
410541ec0267Sriastradh 					goto out;
410641ec0267Sriastradh 
410741ec0267Sriastradh 				vram_lost = amdgpu_device_check_vram_lost(tmp_adev);
410841ec0267Sriastradh 				if (vram_lost) {
410941ec0267Sriastradh 					DRM_INFO("VRAM is lost due to GPU reset!\n");
411041ec0267Sriastradh 					amdgpu_inc_vram_lost(tmp_adev);
4111efa246c0Sriastradh 				}
4112efa246c0Sriastradh 
411341ec0267Sriastradh 				r = amdgpu_gtt_mgr_recover(
411441ec0267Sriastradh 					&tmp_adev->mman.bdev.man[TTM_PL_TT]);
411541ec0267Sriastradh 				if (r)
411641ec0267Sriastradh 					goto out;
4117efa246c0Sriastradh 
411841ec0267Sriastradh 				r = amdgpu_device_fw_loading(tmp_adev);
4119efa246c0Sriastradh 				if (r)
4120efa246c0Sriastradh 					return r;
4121efa246c0Sriastradh 
412241ec0267Sriastradh 				r = amdgpu_device_ip_resume_phase2(tmp_adev);
4123efa246c0Sriastradh 				if (r)
412441ec0267Sriastradh 					goto out;
412541ec0267Sriastradh 
412641ec0267Sriastradh 				if (vram_lost)
412741ec0267Sriastradh 					amdgpu_device_fill_reset_magic(tmp_adev);
412841ec0267Sriastradh 
412941ec0267Sriastradh 				/*
413041ec0267Sriastradh 				 * Add this ASIC as tracked as reset was already
413141ec0267Sriastradh 				 * complete successfully.
413241ec0267Sriastradh 				 */
413341ec0267Sriastradh 				amdgpu_register_gpu_instance(tmp_adev);
413441ec0267Sriastradh 
413541ec0267Sriastradh 				r = amdgpu_device_ip_late_init(tmp_adev);
413641ec0267Sriastradh 				if (r)
413741ec0267Sriastradh 					goto out;
413841ec0267Sriastradh 
413941ec0267Sriastradh 				/* must succeed. */
414041ec0267Sriastradh 				amdgpu_ras_resume(tmp_adev);
414141ec0267Sriastradh 
414241ec0267Sriastradh 				/* Update PSP FW topology after reset */
414341ec0267Sriastradh 				if (hive && tmp_adev->gmc.xgmi.num_physical_nodes > 1)
414441ec0267Sriastradh 					r = amdgpu_xgmi_update_topology(hive, tmp_adev);
414541ec0267Sriastradh 			}
414641ec0267Sriastradh 		}
414741ec0267Sriastradh 
414841ec0267Sriastradh 
414941ec0267Sriastradh out:
415041ec0267Sriastradh 		if (!r) {
415141ec0267Sriastradh 			amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
415241ec0267Sriastradh 			r = amdgpu_ib_ring_tests(tmp_adev);
415341ec0267Sriastradh 			if (r) {
415441ec0267Sriastradh 				dev_err(tmp_adev->dev, "ib ring test failed (%d).\n", r);
415541ec0267Sriastradh 				r = amdgpu_device_ip_suspend(tmp_adev);
415641ec0267Sriastradh 				need_full_reset = true;
415741ec0267Sriastradh 				r = -EAGAIN;
415841ec0267Sriastradh 				goto end;
415941ec0267Sriastradh 			}
416041ec0267Sriastradh 		}
416141ec0267Sriastradh 
416241ec0267Sriastradh 		if (!r)
416341ec0267Sriastradh 			r = amdgpu_device_recover_vram(tmp_adev);
416441ec0267Sriastradh 		else
416541ec0267Sriastradh 			tmp_adev->asic_reset_res = r;
416641ec0267Sriastradh 	}
416741ec0267Sriastradh 
416841ec0267Sriastradh end:
416941ec0267Sriastradh 	*need_full_reset_arg = need_full_reset;
4170efa246c0Sriastradh 	return r;
4171efa246c0Sriastradh }
4172efa246c0Sriastradh 
amdgpu_device_lock_adev(struct amdgpu_device * adev,bool trylock)417341ec0267Sriastradh static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock)
4174efa246c0Sriastradh {
417541ec0267Sriastradh 	if (trylock) {
417641ec0267Sriastradh 		if (!mutex_trylock(&adev->lock_reset))
417741ec0267Sriastradh 			return false;
417841ec0267Sriastradh 	} else
417941ec0267Sriastradh 		mutex_lock(&adev->lock_reset);
4180efa246c0Sriastradh 
418141ec0267Sriastradh 	atomic_inc(&adev->gpu_reset_counter);
418241ec0267Sriastradh 	adev->in_gpu_reset = true;
418341ec0267Sriastradh 	switch (amdgpu_asic_reset_method(adev)) {
418441ec0267Sriastradh 	case AMD_RESET_METHOD_MODE1:
418541ec0267Sriastradh 		adev->mp1_state = PP_MP1_STATE_SHUTDOWN;
418641ec0267Sriastradh 		break;
418741ec0267Sriastradh 	case AMD_RESET_METHOD_MODE2:
418841ec0267Sriastradh 		adev->mp1_state = PP_MP1_STATE_RESET;
418941ec0267Sriastradh 		break;
419041ec0267Sriastradh 	default:
419141ec0267Sriastradh 		adev->mp1_state = PP_MP1_STATE_NONE;
419241ec0267Sriastradh 		break;
419341ec0267Sriastradh 	}
4194efa246c0Sriastradh 
419541ec0267Sriastradh 	return true;
419641ec0267Sriastradh }
419741ec0267Sriastradh 
amdgpu_device_unlock_adev(struct amdgpu_device * adev)419841ec0267Sriastradh static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
419941ec0267Sriastradh {
420041ec0267Sriastradh 	amdgpu_vf_error_trans_all(adev);
420141ec0267Sriastradh 	adev->mp1_state = PP_MP1_STATE_NONE;
420241ec0267Sriastradh 	adev->in_gpu_reset = false;
420341ec0267Sriastradh 	mutex_unlock(&adev->lock_reset);
420441ec0267Sriastradh }
420541ec0267Sriastradh 
420641ec0267Sriastradh /**
420741ec0267Sriastradh  * amdgpu_device_gpu_recover - reset the asic and recover scheduler
420841ec0267Sriastradh  *
420941ec0267Sriastradh  * @adev: amdgpu device pointer
421041ec0267Sriastradh  * @job: which job trigger hang
421141ec0267Sriastradh  *
421241ec0267Sriastradh  * Attempt to reset the GPU if it has hung (all asics).
421341ec0267Sriastradh  * Attempt to do soft-reset or full-reset and reinitialize Asic
421441ec0267Sriastradh  * Returns 0 for success or an error on failure.
421541ec0267Sriastradh  */
421641ec0267Sriastradh 
amdgpu_device_gpu_recover(struct amdgpu_device * adev,struct amdgpu_job * job)421741ec0267Sriastradh int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
421841ec0267Sriastradh 			      struct amdgpu_job *job)
421941ec0267Sriastradh {
422041ec0267Sriastradh 	struct list_head device_list, *device_list_handle =  NULL;
422141ec0267Sriastradh 	bool need_full_reset, job_signaled;
422241ec0267Sriastradh 	struct amdgpu_hive_info *hive = NULL;
422341ec0267Sriastradh 	struct amdgpu_device *tmp_adev = NULL;
422441ec0267Sriastradh 	int i, r = 0;
422541ec0267Sriastradh 	bool in_ras_intr = amdgpu_ras_intr_triggered();
422641ec0267Sriastradh 	bool use_baco =
422741ec0267Sriastradh 		(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) ?
422841ec0267Sriastradh 		true : false;
422941ec0267Sriastradh 
423041ec0267Sriastradh 	/*
423141ec0267Sriastradh 	 * Flush RAM to disk so that after reboot
423241ec0267Sriastradh 	 * the user can read log and see why the system rebooted.
423341ec0267Sriastradh 	 */
423441ec0267Sriastradh 	if (in_ras_intr && !use_baco && amdgpu_ras_get_context(adev)->reboot) {
423541ec0267Sriastradh 
423641ec0267Sriastradh 		DRM_WARN("Emergency reboot.");
423741ec0267Sriastradh 
423841ec0267Sriastradh 		ksys_sync_helper();
423941ec0267Sriastradh 		emergency_restart();
424041ec0267Sriastradh 	}
424141ec0267Sriastradh 
424241ec0267Sriastradh 	need_full_reset = job_signaled = false;
424341ec0267Sriastradh 	INIT_LIST_HEAD(&device_list);
424441ec0267Sriastradh 
424541ec0267Sriastradh 	dev_info(adev->dev, "GPU %s begin!\n",
424641ec0267Sriastradh 		(in_ras_intr && !use_baco) ? "jobs stop":"reset");
424741ec0267Sriastradh 
424841ec0267Sriastradh 	cancel_delayed_work_sync(&adev->delayed_init_work);
424941ec0267Sriastradh 
425041ec0267Sriastradh 	hive = amdgpu_get_xgmi_hive(adev, false);
425141ec0267Sriastradh 
425241ec0267Sriastradh 	/*
425341ec0267Sriastradh 	 * Here we trylock to avoid chain of resets executing from
425441ec0267Sriastradh 	 * either trigger by jobs on different adevs in XGMI hive or jobs on
425541ec0267Sriastradh 	 * different schedulers for same device while this TO handler is running.
425641ec0267Sriastradh 	 * We always reset all schedulers for device and all devices for XGMI
425741ec0267Sriastradh 	 * hive so that should take care of them too.
425841ec0267Sriastradh 	 */
425941ec0267Sriastradh 
426041ec0267Sriastradh 	if (hive && !mutex_trylock(&hive->reset_lock)) {
4261dc219e9cSriastradh 		DRM_INFO("Bailing on TDR for s_job:%"PRIx64", hive: %"PRIx64" as another already in progress",
426241ec0267Sriastradh 			  job ? job->base.id : -1, hive->hive_id);
4263efa246c0Sriastradh 		return 0;
4264efa246c0Sriastradh 	}
4265efa246c0Sriastradh 
426641ec0267Sriastradh 	/* Start with adev pre asic reset first for soft reset check.*/
426741ec0267Sriastradh 	if (!amdgpu_device_lock_adev(adev, !hive)) {
4268dc219e9cSriastradh 		DRM_INFO("Bailing on TDR for s_job:%"PRIx64", as another already in progress",
426941ec0267Sriastradh 			  job ? job->base.id : -1);
4270efa246c0Sriastradh 		return 0;
4271efa246c0Sriastradh 	}
4272efa246c0Sriastradh 
427341ec0267Sriastradh 	/* Block kfd: SRIOV would do it separately */
427441ec0267Sriastradh 	if (!amdgpu_sriov_vf(adev))
427541ec0267Sriastradh                 amdgpu_amdkfd_pre_reset(adev);
427641ec0267Sriastradh 
427741ec0267Sriastradh 	/* Build list of devices to reset */
427841ec0267Sriastradh 	if  (adev->gmc.xgmi.num_physical_nodes > 1) {
427941ec0267Sriastradh 		if (!hive) {
428041ec0267Sriastradh 			/*unlock kfd: SRIOV would do it separately */
428141ec0267Sriastradh 			if (!amdgpu_sriov_vf(adev))
428241ec0267Sriastradh 		                amdgpu_amdkfd_post_reset(adev);
428341ec0267Sriastradh 			amdgpu_device_unlock_adev(adev);
428441ec0267Sriastradh 			return -ENODEV;
4285efa246c0Sriastradh 		}
428641ec0267Sriastradh 
428741ec0267Sriastradh 		/*
428841ec0267Sriastradh 		 * In case we are in XGMI hive mode device reset is done for all the
428941ec0267Sriastradh 		 * nodes in the hive to retrain all XGMI links and hence the reset
429041ec0267Sriastradh 		 * sequence is executed in loop on all nodes.
429141ec0267Sriastradh 		 */
429241ec0267Sriastradh 		device_list_handle = &hive->device_list;
429341ec0267Sriastradh 	} else {
429441ec0267Sriastradh 		list_add_tail(&adev->gmc.xgmi.head, &device_list);
429541ec0267Sriastradh 		device_list_handle = &device_list;
429641ec0267Sriastradh 	}
429741ec0267Sriastradh 
429841ec0267Sriastradh 	/* block all schedulers and reset given job's ring */
429941ec0267Sriastradh 	list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
430041ec0267Sriastradh 		if (tmp_adev != adev) {
430141ec0267Sriastradh 			amdgpu_device_lock_adev(tmp_adev, false);
430241ec0267Sriastradh 			if (!amdgpu_sriov_vf(tmp_adev))
430341ec0267Sriastradh 			                amdgpu_amdkfd_pre_reset(tmp_adev);
430441ec0267Sriastradh 		}
430541ec0267Sriastradh 
430641ec0267Sriastradh 		/*
430741ec0267Sriastradh 		 * Mark these ASICs to be reseted as untracked first
430841ec0267Sriastradh 		 * And add them back after reset completed
430941ec0267Sriastradh 		 */
431041ec0267Sriastradh 		amdgpu_unregister_gpu_instance(tmp_adev);
431141ec0267Sriastradh 
431241ec0267Sriastradh 		/* disable ras on ALL IPs */
431341ec0267Sriastradh 		if (!(in_ras_intr && !use_baco) &&
431441ec0267Sriastradh 		      amdgpu_device_ip_need_full_reset(tmp_adev))
431541ec0267Sriastradh 			amdgpu_ras_suspend(tmp_adev);
431641ec0267Sriastradh 
431741ec0267Sriastradh 		for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
431841ec0267Sriastradh 			struct amdgpu_ring *ring = tmp_adev->rings[i];
431941ec0267Sriastradh 
432041ec0267Sriastradh 			if (!ring || !ring->sched.thread)
432141ec0267Sriastradh 				continue;
432241ec0267Sriastradh 
432341ec0267Sriastradh 			drm_sched_stop(&ring->sched, job ? &job->base : NULL);
432441ec0267Sriastradh 
432541ec0267Sriastradh 			if (in_ras_intr && !use_baco)
432641ec0267Sriastradh 				amdgpu_job_stop_all_jobs_on_sched(&ring->sched);
432741ec0267Sriastradh 		}
432841ec0267Sriastradh 	}
432941ec0267Sriastradh 
433041ec0267Sriastradh 
433141ec0267Sriastradh 	if (in_ras_intr && !use_baco)
433241ec0267Sriastradh 		goto skip_sched_resume;
433341ec0267Sriastradh 
433441ec0267Sriastradh 	/*
433541ec0267Sriastradh 	 * Must check guilty signal here since after this point all old
433641ec0267Sriastradh 	 * HW fences are force signaled.
433741ec0267Sriastradh 	 *
433841ec0267Sriastradh 	 * job->base holds a reference to parent fence
433941ec0267Sriastradh 	 */
434041ec0267Sriastradh 	if (job && job->base.s_fence->parent &&
434141ec0267Sriastradh 	    dma_fence_is_signaled(job->base.s_fence->parent))
434241ec0267Sriastradh 		job_signaled = true;
434341ec0267Sriastradh 
434441ec0267Sriastradh 	if (job_signaled) {
434541ec0267Sriastradh 		dev_info(adev->dev, "Guilty job already signaled, skipping HW reset");
434641ec0267Sriastradh 		goto skip_hw_reset;
434741ec0267Sriastradh 	}
434841ec0267Sriastradh 
434941ec0267Sriastradh 
435041ec0267Sriastradh 	/* Guilty job will be freed after this*/
435141ec0267Sriastradh 	r = amdgpu_device_pre_asic_reset(adev, job, &need_full_reset);
435241ec0267Sriastradh 	if (r) {
435341ec0267Sriastradh 		/*TODO Should we stop ?*/
435441ec0267Sriastradh 		DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ",
435541ec0267Sriastradh 			  r, adev->ddev->unique);
435641ec0267Sriastradh 		adev->asic_reset_res = r;
435741ec0267Sriastradh 	}
435841ec0267Sriastradh 
435941ec0267Sriastradh retry:	/* Rest of adevs pre asic reset from XGMI hive. */
436041ec0267Sriastradh 	list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
436141ec0267Sriastradh 
436241ec0267Sriastradh 		if (tmp_adev == adev)
436341ec0267Sriastradh 			continue;
436441ec0267Sriastradh 
436541ec0267Sriastradh 		r = amdgpu_device_pre_asic_reset(tmp_adev,
436641ec0267Sriastradh 						 NULL,
436741ec0267Sriastradh 						 &need_full_reset);
436841ec0267Sriastradh 		/*TODO Should we stop ?*/
436941ec0267Sriastradh 		if (r) {
437041ec0267Sriastradh 			DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ",
437141ec0267Sriastradh 				  r, tmp_adev->ddev->unique);
437241ec0267Sriastradh 			tmp_adev->asic_reset_res = r;
437341ec0267Sriastradh 		}
437441ec0267Sriastradh 	}
437541ec0267Sriastradh 
437641ec0267Sriastradh 	/* Actual ASIC resets if needed.*/
437741ec0267Sriastradh 	/* TODO Implement XGMI hive reset logic for SRIOV */
437841ec0267Sriastradh 	if (amdgpu_sriov_vf(adev)) {
437941ec0267Sriastradh 		r = amdgpu_device_reset_sriov(adev, job ? false : true);
438041ec0267Sriastradh 		if (r)
438141ec0267Sriastradh 			adev->asic_reset_res = r;
438241ec0267Sriastradh 	} else {
438341ec0267Sriastradh 		r  = amdgpu_do_asic_reset(hive, device_list_handle, &need_full_reset);
438441ec0267Sriastradh 		if (r && r == -EAGAIN)
438541ec0267Sriastradh 			goto retry;
438641ec0267Sriastradh 	}
438741ec0267Sriastradh 
438841ec0267Sriastradh skip_hw_reset:
438941ec0267Sriastradh 
439041ec0267Sriastradh 	/* Post ASIC reset for all devs .*/
439141ec0267Sriastradh 	list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
439241ec0267Sriastradh 
439341ec0267Sriastradh 		for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
439441ec0267Sriastradh 			struct amdgpu_ring *ring = tmp_adev->rings[i];
439541ec0267Sriastradh 
439641ec0267Sriastradh 			if (!ring || !ring->sched.thread)
439741ec0267Sriastradh 				continue;
439841ec0267Sriastradh 
439941ec0267Sriastradh 			/* No point to resubmit jobs if we didn't HW reset*/
440041ec0267Sriastradh 			if (!tmp_adev->asic_reset_res && !job_signaled)
440141ec0267Sriastradh 				drm_sched_resubmit_jobs(&ring->sched);
440241ec0267Sriastradh 
440341ec0267Sriastradh 			drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res);
440441ec0267Sriastradh 		}
440541ec0267Sriastradh 
440641ec0267Sriastradh 		if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) {
440741ec0267Sriastradh 			drm_helper_resume_force_mode(tmp_adev->ddev);
440841ec0267Sriastradh 		}
440941ec0267Sriastradh 
441041ec0267Sriastradh 		tmp_adev->asic_reset_res = 0;
441141ec0267Sriastradh 
441241ec0267Sriastradh 		if (r) {
441341ec0267Sriastradh 			/* bad news, how to tell it to userspace ? */
441441ec0267Sriastradh 			dev_info(tmp_adev->dev, "GPU reset(%d) failed\n", atomic_read(&tmp_adev->gpu_reset_counter));
441541ec0267Sriastradh 			amdgpu_vf_error_put(tmp_adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r);
441641ec0267Sriastradh 		} else {
441741ec0267Sriastradh 			dev_info(tmp_adev->dev, "GPU reset(%d) succeeded!\n", atomic_read(&tmp_adev->gpu_reset_counter));
441841ec0267Sriastradh 		}
441941ec0267Sriastradh 	}
442041ec0267Sriastradh 
442141ec0267Sriastradh skip_sched_resume:
442241ec0267Sriastradh 	list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
442341ec0267Sriastradh 		/*unlock kfd: SRIOV would do it separately */
442441ec0267Sriastradh 		if (!(in_ras_intr && !use_baco) && !amdgpu_sriov_vf(tmp_adev))
442541ec0267Sriastradh 	                amdgpu_amdkfd_post_reset(tmp_adev);
442641ec0267Sriastradh 		amdgpu_device_unlock_adev(tmp_adev);
442741ec0267Sriastradh 	}
442841ec0267Sriastradh 
442941ec0267Sriastradh 	if (hive)
443041ec0267Sriastradh 		mutex_unlock(&hive->reset_lock);
443141ec0267Sriastradh 
443241ec0267Sriastradh 	if (r)
443341ec0267Sriastradh 		dev_info(adev->dev, "GPU reset end with ret = %d\n", r);
443441ec0267Sriastradh 	return r;
443541ec0267Sriastradh }
443641ec0267Sriastradh 
443741ec0267Sriastradh /**
443841ec0267Sriastradh  * amdgpu_device_get_pcie_info - fence pcie info about the PCIE slot
443941ec0267Sriastradh  *
444041ec0267Sriastradh  * @adev: amdgpu_device pointer
444141ec0267Sriastradh  *
444241ec0267Sriastradh  * Fetchs and stores in the driver the PCIE capabilities (gen speed
444341ec0267Sriastradh  * and lanes) of the slot the device is in. Handles APUs and
444441ec0267Sriastradh  * virtualized environments where PCIE config space may not be available.
444541ec0267Sriastradh  */
amdgpu_device_get_pcie_info(struct amdgpu_device * adev)444641ec0267Sriastradh static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
4447efa246c0Sriastradh {
444841ec0267Sriastradh 	struct pci_dev *pdev;
444941ec0267Sriastradh 	enum pci_bus_speed speed_cap, platform_speed_cap;
445041ec0267Sriastradh 	enum pcie_link_width platform_link_width;
445141ec0267Sriastradh 
445241ec0267Sriastradh 	if (amdgpu_pcie_gen_cap)
445341ec0267Sriastradh 		adev->pm.pcie_gen_mask = amdgpu_pcie_gen_cap;
445441ec0267Sriastradh 
445541ec0267Sriastradh 	if (amdgpu_pcie_lane_cap)
445641ec0267Sriastradh 		adev->pm.pcie_mlw_mask = amdgpu_pcie_lane_cap;
445741ec0267Sriastradh 
445841ec0267Sriastradh 	/* covers APUs as well */
445941ec0267Sriastradh 	if (pci_is_root_bus(adev->pdev->bus)) {
446041ec0267Sriastradh 		if (adev->pm.pcie_gen_mask == 0)
446141ec0267Sriastradh 			adev->pm.pcie_gen_mask = AMDGPU_DEFAULT_PCIE_GEN_MASK;
446241ec0267Sriastradh 		if (adev->pm.pcie_mlw_mask == 0)
446341ec0267Sriastradh 			adev->pm.pcie_mlw_mask = AMDGPU_DEFAULT_PCIE_MLW_MASK;
446441ec0267Sriastradh 		return;
446541ec0267Sriastradh 	}
446641ec0267Sriastradh 
446741ec0267Sriastradh 	if (adev->pm.pcie_gen_mask && adev->pm.pcie_mlw_mask)
446841ec0267Sriastradh 		return;
446941ec0267Sriastradh 
447041ec0267Sriastradh 	pcie_bandwidth_available(adev->pdev, NULL,
447141ec0267Sriastradh 				 &platform_speed_cap, &platform_link_width);
447241ec0267Sriastradh 
447341ec0267Sriastradh 	if (adev->pm.pcie_gen_mask == 0) {
447441ec0267Sriastradh 		/* asic caps */
447541ec0267Sriastradh 		pdev = adev->pdev;
447641ec0267Sriastradh 		speed_cap = pcie_get_speed_cap(pdev);
447741ec0267Sriastradh 		if (speed_cap == PCI_SPEED_UNKNOWN) {
447841ec0267Sriastradh 			adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
447941ec0267Sriastradh 						  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
448041ec0267Sriastradh 						  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
448141ec0267Sriastradh 		} else {
448241ec0267Sriastradh 			if (speed_cap == PCIE_SPEED_16_0GT)
448341ec0267Sriastradh 				adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
448441ec0267Sriastradh 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
448541ec0267Sriastradh 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3 |
448641ec0267Sriastradh 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4);
448741ec0267Sriastradh 			else if (speed_cap == PCIE_SPEED_8_0GT)
448841ec0267Sriastradh 				adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
448941ec0267Sriastradh 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
449041ec0267Sriastradh 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
449141ec0267Sriastradh 			else if (speed_cap == PCIE_SPEED_5_0GT)
449241ec0267Sriastradh 				adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
449341ec0267Sriastradh 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2);
449441ec0267Sriastradh 			else
449541ec0267Sriastradh 				adev->pm.pcie_gen_mask |= CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1;
449641ec0267Sriastradh 		}
449741ec0267Sriastradh 		/* platform caps */
449841ec0267Sriastradh 		if (platform_speed_cap == PCI_SPEED_UNKNOWN) {
449941ec0267Sriastradh 			adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
450041ec0267Sriastradh 						   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2);
450141ec0267Sriastradh 		} else {
450241ec0267Sriastradh 			if (platform_speed_cap == PCIE_SPEED_16_0GT)
450341ec0267Sriastradh 				adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
450441ec0267Sriastradh 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
450541ec0267Sriastradh 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 |
450641ec0267Sriastradh 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4);
450741ec0267Sriastradh 			else if (platform_speed_cap == PCIE_SPEED_8_0GT)
450841ec0267Sriastradh 				adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
450941ec0267Sriastradh 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
451041ec0267Sriastradh 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3);
451141ec0267Sriastradh 			else if (platform_speed_cap == PCIE_SPEED_5_0GT)
451241ec0267Sriastradh 				adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
451341ec0267Sriastradh 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2);
451441ec0267Sriastradh 			else
451541ec0267Sriastradh 				adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1;
451641ec0267Sriastradh 
451741ec0267Sriastradh 		}
451841ec0267Sriastradh 	}
451941ec0267Sriastradh 	if (adev->pm.pcie_mlw_mask == 0) {
452041ec0267Sriastradh 		if (platform_link_width == PCIE_LNK_WIDTH_UNKNOWN) {
452141ec0267Sriastradh 			adev->pm.pcie_mlw_mask |= AMDGPU_DEFAULT_PCIE_MLW_MASK;
452241ec0267Sriastradh 		} else {
452341ec0267Sriastradh 			switch (platform_link_width) {
452441ec0267Sriastradh 			case PCIE_LNK_X32:
452541ec0267Sriastradh 				adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 |
452641ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
452741ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
452841ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
452941ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
453041ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
453141ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
453241ec0267Sriastradh 				break;
453341ec0267Sriastradh 			case PCIE_LNK_X16:
453441ec0267Sriastradh 				adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
453541ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
453641ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
453741ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
453841ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
453941ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
454041ec0267Sriastradh 				break;
454141ec0267Sriastradh 			case PCIE_LNK_X12:
454241ec0267Sriastradh 				adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
454341ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
454441ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
454541ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
454641ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
454741ec0267Sriastradh 				break;
454841ec0267Sriastradh 			case PCIE_LNK_X8:
454941ec0267Sriastradh 				adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
455041ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
455141ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
455241ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
455341ec0267Sriastradh 				break;
455441ec0267Sriastradh 			case PCIE_LNK_X4:
455541ec0267Sriastradh 				adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
455641ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
455741ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
455841ec0267Sriastradh 				break;
455941ec0267Sriastradh 			case PCIE_LNK_X2:
456041ec0267Sriastradh 				adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
456141ec0267Sriastradh 							  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
456241ec0267Sriastradh 				break;
456341ec0267Sriastradh 			case PCIE_LNK_X1:
456441ec0267Sriastradh 				adev->pm.pcie_mlw_mask = CAIL_PCIE_LINK_WIDTH_SUPPORT_X1;
456541ec0267Sriastradh 				break;
456641ec0267Sriastradh 			default:
456741ec0267Sriastradh 				break;
456841ec0267Sriastradh 			}
456941ec0267Sriastradh 		}
457041ec0267Sriastradh 	}
457141ec0267Sriastradh }
457241ec0267Sriastradh 
amdgpu_device_baco_enter(struct drm_device * dev)457341ec0267Sriastradh int amdgpu_device_baco_enter(struct drm_device *dev)
457441ec0267Sriastradh {
457541ec0267Sriastradh 	struct amdgpu_device *adev = dev->dev_private;
457641ec0267Sriastradh 	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
457741ec0267Sriastradh 
457841ec0267Sriastradh 	if (!amdgpu_device_supports_baco(adev->ddev))
457941ec0267Sriastradh 		return -ENOTSUPP;
458041ec0267Sriastradh 
458141ec0267Sriastradh 	if (ras && ras->supported)
458241ec0267Sriastradh 		adev->nbio.funcs->enable_doorbell_interrupt(adev, false);
458341ec0267Sriastradh 
458441ec0267Sriastradh 	return amdgpu_dpm_baco_enter(adev);
458541ec0267Sriastradh }
458641ec0267Sriastradh 
amdgpu_device_baco_exit(struct drm_device * dev)458741ec0267Sriastradh int amdgpu_device_baco_exit(struct drm_device *dev)
458841ec0267Sriastradh {
458941ec0267Sriastradh 	struct amdgpu_device *adev = dev->dev_private;
459041ec0267Sriastradh 	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
459141ec0267Sriastradh 	int ret = 0;
459241ec0267Sriastradh 
459341ec0267Sriastradh 	if (!amdgpu_device_supports_baco(adev->ddev))
459441ec0267Sriastradh 		return -ENOTSUPP;
459541ec0267Sriastradh 
459641ec0267Sriastradh 	ret = amdgpu_dpm_baco_exit(adev);
459741ec0267Sriastradh 	if (ret)
459841ec0267Sriastradh 		return ret;
459941ec0267Sriastradh 
460041ec0267Sriastradh 	if (ras && ras->supported)
460141ec0267Sriastradh 		adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
460241ec0267Sriastradh 
4603efa246c0Sriastradh 	return 0;
4604efa246c0Sriastradh }
4605