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