1d38ceaf9SAlex Deucher /*
2d38ceaf9SAlex Deucher  * Copyright 2008 Advanced Micro Devices, Inc.
3d38ceaf9SAlex Deucher  * Copyright 2008 Red Hat Inc.
4d38ceaf9SAlex Deucher  * Copyright 2009 Jerome Glisse.
5d38ceaf9SAlex Deucher  *
6d38ceaf9SAlex Deucher  * Permission is hereby granted, free of charge, to any person obtaining a
7d38ceaf9SAlex Deucher  * copy of this software and associated documentation files (the "Software"),
8d38ceaf9SAlex Deucher  * to deal in the Software without restriction, including without limitation
9d38ceaf9SAlex Deucher  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10d38ceaf9SAlex Deucher  * and/or sell copies of the Software, and to permit persons to whom the
11d38ceaf9SAlex Deucher  * Software is furnished to do so, subject to the following conditions:
12d38ceaf9SAlex Deucher  *
13d38ceaf9SAlex Deucher  * The above copyright notice and this permission notice shall be included in
14d38ceaf9SAlex Deucher  * all copies or substantial portions of the Software.
15d38ceaf9SAlex Deucher  *
16d38ceaf9SAlex Deucher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d38ceaf9SAlex Deucher  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d38ceaf9SAlex Deucher  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19d38ceaf9SAlex Deucher  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20d38ceaf9SAlex Deucher  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21d38ceaf9SAlex Deucher  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22d38ceaf9SAlex Deucher  * OTHER DEALINGS IN THE SOFTWARE.
23d38ceaf9SAlex Deucher  *
24d38ceaf9SAlex Deucher  * Authors: Dave Airlie
25d38ceaf9SAlex Deucher  *          Alex Deucher
26d38ceaf9SAlex Deucher  *          Jerome Glisse
27d38ceaf9SAlex Deucher  */
28ea1d2a38SThomas Zimmermann 
29ea1d2a38SThomas Zimmermann #include <linux/aperture.h>
30b1ddf548SRex Zhu #include <linux/power_supply.h>
310875dc9eSChunming Zhou #include <linux/kthread.h>
32fdf2f6c5SSam Ravnborg #include <linux/module.h>
33d38ceaf9SAlex Deucher #include <linux/console.h>
34d38ceaf9SAlex Deucher #include <linux/slab.h>
354a74c38cSPhilip Yang #include <linux/iommu.h>
36901e2be2SAlex Deucher #include <linux/pci.h>
3708a2fd23SRamesh Errabolu #include <linux/pci-p2pdma.h>
38d37a3929SOrlando Chamberlain #include <linux/apple-gmux.h>
39fdf2f6c5SSam Ravnborg 
404562236bSHarry Wentland #include <drm/drm_atomic_helper.h>
414cf50baeSThomas Zimmermann #include <drm/drm_client_event.h>
42973ad627SThomas Zimmermann #include <drm/drm_crtc_helper.h>
43fcd70cd3SDaniel Vetter #include <drm/drm_probe_helper.h>
44d38ceaf9SAlex Deucher #include <drm/amdgpu_drm.h>
457b1c6263SAlex Deucher #include <linux/device.h>
46d38ceaf9SAlex Deucher #include <linux/vgaarb.h>
47d38ceaf9SAlex Deucher #include <linux/vga_switcheroo.h>
48d38ceaf9SAlex Deucher #include <linux/efi.h>
49d38ceaf9SAlex Deucher #include "amdgpu.h"
50f4b373f4STom St Denis #include "amdgpu_trace.h"
51d38ceaf9SAlex Deucher #include "amdgpu_i2c.h"
52d38ceaf9SAlex Deucher #include "atom.h"
53d38ceaf9SAlex Deucher #include "amdgpu_atombios.h"
54a5bde2f9SAlex Deucher #include "amdgpu_atomfirmware.h"
55d0dd7f0cSAlex Deucher #include "amd_pcie.h"
5633f34802SKen Wang #ifdef CONFIG_DRM_AMDGPU_SI
5733f34802SKen Wang #include "si.h"
5833f34802SKen Wang #endif
59a2e73f56SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_CIK
60a2e73f56SAlex Deucher #include "cik.h"
61a2e73f56SAlex Deucher #endif
62aaa36a97SAlex Deucher #include "vi.h"
63460826e6SKen Wang #include "soc15.h"
640a5b8c7bSHuang Rui #include "nv.h"
65d38ceaf9SAlex Deucher #include "bif/bif_4_1_d.h"
66bec86378SMonk Liu #include <linux/firmware.h>
6789041940SGavin Wan #include "amdgpu_vf_error.h"
68d38ceaf9SAlex Deucher 
69ba997709SYong Zhao #include "amdgpu_amdkfd.h"
70d2f52ac8SRex Zhu #include "amdgpu_pm.h"
71d38ceaf9SAlex Deucher 
725183411bSAndrey Grodzovsky #include "amdgpu_xgmi.h"
73c030f2e4Sxinhui pan #include "amdgpu_ras.h"
749c7c85f7SJonathan Kim #include "amdgpu_pmu.h"
75bd607166SKent Russell #include "amdgpu_fru_eeprom.h"
7604442bf7SLijo Lazar #include "amdgpu_reset.h"
7785150626SVictor Lu #include "amdgpu_virt.h"
789022f01bSSunil Khatri #include "amdgpu_dev_coredump.h"
795183411bSAndrey Grodzovsky 
80d5ea093eSAndrey Grodzovsky #include <linux/suspend.h>
81c6a6e2dbSAndrey Grodzovsky #include <drm/task_barrier.h>
823f12acc8SEvan Quan #include <linux/pm_runtime.h>
83d5ea093eSAndrey Grodzovsky 
84f89f8c6bSAndrey Grodzovsky #include <drm/drm_drv.h>
85f89f8c6bSAndrey Grodzovsky 
863ad5dcfeSKai-Heng Feng #if IS_ENABLED(CONFIG_X86)
873ad5dcfeSKai-Heng Feng #include <asm/intel-family.h>
883ad5dcfeSKai-Heng Feng #endif
893ad5dcfeSKai-Heng Feng 
90e2a75f88SAlex Deucher MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
913f76dcedSAlex Deucher MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
922d2e5e7eSAlex Deucher MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
93ad5a67a7SLikun Gao MODULE_FIRMWARE("amdgpu/picasso_gpu_info.bin");
9454c4d17eSFeifei Xu MODULE_FIRMWARE("amdgpu/raven2_gpu_info.bin");
9565e60f6eSLe Ma MODULE_FIRMWARE("amdgpu/arcturus_gpu_info.bin");
9642b325e5SXiaojie Yuan MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
97e2a75f88SAlex Deucher 
982dc80b00SShirish S #define AMDGPU_RESUME_MS		2000
997258fa31SSurbhi Kakarya #define AMDGPU_MAX_RETRY_LIMIT		2
1007258fa31SSurbhi Kakarya #define AMDGPU_RETRY_SRIOV_RESET(r) ((r) == -EBUSY || (r) == -ETIMEDOUT || (r) == -EINVAL)
101ad390542SHawking Zhang #define AMDGPU_PCIE_INDEX_FALLBACK (0x38 >> 2)
102ad390542SHawking Zhang #define AMDGPU_PCIE_INDEX_HI_FALLBACK (0x44 >> 2)
103ad390542SHawking Zhang #define AMDGPU_PCIE_DATA_FALLBACK (0x3C >> 2)
1042dc80b00SShirish S 
1057e0aa706SLijo Lazar #define AMDGPU_VBIOS_SKIP (1U << 0)
1066e8ca38eSLijo Lazar #define AMDGPU_VBIOS_OPTIONAL (1U << 1)
1077e0aa706SLijo Lazar 
108b7cdb41eSMario Limonciello static const struct drm_driver amdgpu_kms_driver;
109b7cdb41eSMario Limonciello 
110050091abSYong Zhao const char *amdgpu_asic_name[] = {
111da69c161SKen Wang 	"TAHITI",
112da69c161SKen Wang 	"PITCAIRN",
113da69c161SKen Wang 	"VERDE",
114da69c161SKen Wang 	"OLAND",
115da69c161SKen Wang 	"HAINAN",
116d38ceaf9SAlex Deucher 	"BONAIRE",
117d38ceaf9SAlex Deucher 	"KAVERI",
118d38ceaf9SAlex Deucher 	"KABINI",
119d38ceaf9SAlex Deucher 	"HAWAII",
120d38ceaf9SAlex Deucher 	"MULLINS",
121d38ceaf9SAlex Deucher 	"TOPAZ",
122d38ceaf9SAlex Deucher 	"TONGA",
12348299f95SDavid Zhang 	"FIJI",
124d38ceaf9SAlex Deucher 	"CARRIZO",
125139f4917SSamuel Li 	"STONEY",
1262cc0c0b5SFlora Cui 	"POLARIS10",
1272cc0c0b5SFlora Cui 	"POLARIS11",
128c4642a47SJunwei Zhang 	"POLARIS12",
12948ff108dSLeo Liu 	"VEGAM",
130d4196f01SKen Wang 	"VEGA10",
1318fab806aSFeifei Xu 	"VEGA12",
132956fcddcSFeifei Xu 	"VEGA20",
1332ca8a5d2SChunming Zhou 	"RAVEN",
134d6c3b24eSLe Ma 	"ARCTURUS",
1351eee4228SHuang Rui 	"RENOIR",
136d46b417aSLe Ma 	"ALDEBARAN",
137852a6626SHuang Rui 	"NAVI10",
138d0f56dc2STao Zhou 	"CYAN_SKILLFISH",
13987dbad02SXiaojie Yuan 	"NAVI14",
1409802f5d7SXiaojie Yuan 	"NAVI12",
141ccaf72d3SLikun Gao 	"SIENNA_CICHLID",
142ddd8fbe7SJiansong Chen 	"NAVY_FLOUNDER",
1434f1e9a76SHuang Rui 	"VANGOGH",
144a2468e04STao Zhou 	"DIMGREY_CAVEFISH",
1456f169591SChengming Gui 	"BEIGE_GOBY",
146ee9236b7SAaron Liu 	"YELLOW_CARP",
1473ae695d6SAlex Deucher 	"IP DISCOVERY",
148d38ceaf9SAlex Deucher 	"LAST",
149d38ceaf9SAlex Deucher };
150d38ceaf9SAlex Deucher 
151ee2003d5SPratap Nirujogi #define AMDGPU_IP_BLK_MASK_ALL GENMASK(AMD_IP_BLOCK_TYPE_NUM  - 1, 0)
15214f2fe34SLijo Lazar /*
15314f2fe34SLijo Lazar  * Default init level where all blocks are expected to be initialized. This is
15414f2fe34SLijo Lazar  * the level of initialization expected by default and also after a full reset
15514f2fe34SLijo Lazar  * of the device.
15614f2fe34SLijo Lazar  */
15714f2fe34SLijo Lazar struct amdgpu_init_level amdgpu_init_default = {
15814f2fe34SLijo Lazar 	.level = AMDGPU_INIT_LEVEL_DEFAULT,
15914f2fe34SLijo Lazar 	.hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
16014f2fe34SLijo Lazar };
16114f2fe34SLijo Lazar 
162a86e0c0eSLijo Lazar struct amdgpu_init_level amdgpu_init_recovery = {
163a86e0c0eSLijo Lazar 	.level = AMDGPU_INIT_LEVEL_RESET_RECOVERY,
164a86e0c0eSLijo Lazar 	.hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
165a86e0c0eSLijo Lazar };
166a86e0c0eSLijo Lazar 
16714f2fe34SLijo Lazar /*
16814f2fe34SLijo Lazar  * Minimal blocks needed to be initialized before a XGMI hive can be reset. This
16914f2fe34SLijo Lazar  * is used for cases like reset on initialization where the entire hive needs to
17014f2fe34SLijo Lazar  * be reset before first use.
17114f2fe34SLijo Lazar  */
17214f2fe34SLijo Lazar struct amdgpu_init_level amdgpu_init_minimal_xgmi = {
17314f2fe34SLijo Lazar 	.level = AMDGPU_INIT_LEVEL_MINIMAL_XGMI,
17414f2fe34SLijo Lazar 	.hwini_ip_block_mask =
17514f2fe34SLijo Lazar 		BIT(AMD_IP_BLOCK_TYPE_GMC) | BIT(AMD_IP_BLOCK_TYPE_SMC) |
176631af731SLijo Lazar 		BIT(AMD_IP_BLOCK_TYPE_COMMON) | BIT(AMD_IP_BLOCK_TYPE_IH) |
177631af731SLijo Lazar 		BIT(AMD_IP_BLOCK_TYPE_PSP)
17814f2fe34SLijo Lazar };
17914f2fe34SLijo Lazar 
amdgpu_ip_member_of_hwini(struct amdgpu_device * adev,enum amd_ip_block_type block)18014f2fe34SLijo Lazar static inline bool amdgpu_ip_member_of_hwini(struct amdgpu_device *adev,
18114f2fe34SLijo Lazar 					     enum amd_ip_block_type block)
18214f2fe34SLijo Lazar {
18314f2fe34SLijo Lazar 	return (adev->init_lvl->hwini_ip_block_mask & (1U << block)) != 0;
18414f2fe34SLijo Lazar }
18514f2fe34SLijo Lazar 
amdgpu_set_init_level(struct amdgpu_device * adev,enum amdgpu_init_lvl_id lvl)18614f2fe34SLijo Lazar void amdgpu_set_init_level(struct amdgpu_device *adev,
18714f2fe34SLijo Lazar 			   enum amdgpu_init_lvl_id lvl)
18814f2fe34SLijo Lazar {
18914f2fe34SLijo Lazar 	switch (lvl) {
19014f2fe34SLijo Lazar 	case AMDGPU_INIT_LEVEL_MINIMAL_XGMI:
19114f2fe34SLijo Lazar 		adev->init_lvl = &amdgpu_init_minimal_xgmi;
19214f2fe34SLijo Lazar 		break;
193a86e0c0eSLijo Lazar 	case AMDGPU_INIT_LEVEL_RESET_RECOVERY:
194a86e0c0eSLijo Lazar 		adev->init_lvl = &amdgpu_init_recovery;
195a86e0c0eSLijo Lazar 		break;
19614f2fe34SLijo Lazar 	case AMDGPU_INIT_LEVEL_DEFAULT:
19714f2fe34SLijo Lazar 		fallthrough;
19814f2fe34SLijo Lazar 	default:
19914f2fe34SLijo Lazar 		adev->init_lvl = &amdgpu_init_default;
20014f2fe34SLijo Lazar 		break;
20114f2fe34SLijo Lazar 	}
20214f2fe34SLijo Lazar }
20314f2fe34SLijo Lazar 
204ab66c832SZhigang Luo static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev);
2052965e635SMario Limonciello static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mode,
2062965e635SMario Limonciello 				     void *data);
207ab66c832SZhigang Luo 
208dcea6e65SKent Russell /**
209dcea6e65SKent Russell  * DOC: pcie_replay_count
210dcea6e65SKent Russell  *
211dcea6e65SKent Russell  * The amdgpu driver provides a sysfs API for reporting the total number
212a567db80SRandy Dunlap  * of PCIe replays (NAKs).
213dcea6e65SKent Russell  * The file pcie_replay_count is used for this and returns the total
214a567db80SRandy Dunlap  * number of replays as a sum of the NAKs generated and NAKs received.
215dcea6e65SKent Russell  */
216dcea6e65SKent Russell 
amdgpu_device_get_pcie_replay_count(struct device * dev,struct device_attribute * attr,char * buf)217dcea6e65SKent Russell static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev,
218dcea6e65SKent Russell 		struct device_attribute *attr, char *buf)
219dcea6e65SKent Russell {
220dcea6e65SKent Russell 	struct drm_device *ddev = dev_get_drvdata(dev);
2211348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(ddev);
222dcea6e65SKent Russell 	uint64_t cnt = amdgpu_asic_get_pcie_replay_count(adev);
223dcea6e65SKent Russell 
22436000c7aSTian Tao 	return sysfs_emit(buf, "%llu\n", cnt);
225dcea6e65SKent Russell }
226dcea6e65SKent Russell 
227b8920e1eSSrinivasan Shanmugam static DEVICE_ATTR(pcie_replay_count, 0444,
228dcea6e65SKent Russell 		amdgpu_device_get_pcie_replay_count, NULL);
229dcea6e65SKent Russell 
amdgpu_device_attr_sysfs_init(struct amdgpu_device * adev)2309c05636cSVictor Skvortsov static int amdgpu_device_attr_sysfs_init(struct amdgpu_device *adev)
2319c05636cSVictor Skvortsov {
2329c05636cSVictor Skvortsov 	int ret = 0;
2339c05636cSVictor Skvortsov 
2349c05636cSVictor Skvortsov 	if (!amdgpu_sriov_vf(adev))
2359c05636cSVictor Skvortsov 		ret = sysfs_create_file(&adev->dev->kobj,
2369c05636cSVictor Skvortsov 					&dev_attr_pcie_replay_count.attr);
2379c05636cSVictor Skvortsov 
2389c05636cSVictor Skvortsov 	return ret;
2399c05636cSVictor Skvortsov }
2409c05636cSVictor Skvortsov 
amdgpu_device_attr_sysfs_fini(struct amdgpu_device * adev)2419c05636cSVictor Skvortsov static void amdgpu_device_attr_sysfs_fini(struct amdgpu_device *adev)
2429c05636cSVictor Skvortsov {
2439c05636cSVictor Skvortsov 	if (!amdgpu_sriov_vf(adev))
2449c05636cSVictor Skvortsov 		sysfs_remove_file(&adev->dev->kobj,
2459c05636cSVictor Skvortsov 				  &dev_attr_pcie_replay_count.attr);
2469c05636cSVictor Skvortsov }
2479c05636cSVictor Skvortsov 
amdgpu_sysfs_reg_state_get(struct file * f,struct kobject * kobj,const struct bin_attribute * attr,char * buf,loff_t ppos,size_t count)248af39e6f4SLijo Lazar static ssize_t amdgpu_sysfs_reg_state_get(struct file *f, struct kobject *kobj,
2492d0f5001SThomas Weißschuh 					  const struct bin_attribute *attr, char *buf,
250af39e6f4SLijo Lazar 					  loff_t ppos, size_t count)
251af39e6f4SLijo Lazar {
252af39e6f4SLijo Lazar 	struct device *dev = kobj_to_dev(kobj);
253af39e6f4SLijo Lazar 	struct drm_device *ddev = dev_get_drvdata(dev);
254af39e6f4SLijo Lazar 	struct amdgpu_device *adev = drm_to_adev(ddev);
255af39e6f4SLijo Lazar 	ssize_t bytes_read;
256af39e6f4SLijo Lazar 
257af39e6f4SLijo Lazar 	switch (ppos) {
258af39e6f4SLijo Lazar 	case AMDGPU_SYS_REG_STATE_XGMI:
259af39e6f4SLijo Lazar 		bytes_read = amdgpu_asic_get_reg_state(
260af39e6f4SLijo Lazar 			adev, AMDGPU_REG_STATE_TYPE_XGMI, buf, count);
261af39e6f4SLijo Lazar 		break;
262af39e6f4SLijo Lazar 	case AMDGPU_SYS_REG_STATE_WAFL:
263af39e6f4SLijo Lazar 		bytes_read = amdgpu_asic_get_reg_state(
264af39e6f4SLijo Lazar 			adev, AMDGPU_REG_STATE_TYPE_WAFL, buf, count);
265af39e6f4SLijo Lazar 		break;
266af39e6f4SLijo Lazar 	case AMDGPU_SYS_REG_STATE_PCIE:
267af39e6f4SLijo Lazar 		bytes_read = amdgpu_asic_get_reg_state(
268af39e6f4SLijo Lazar 			adev, AMDGPU_REG_STATE_TYPE_PCIE, buf, count);
269af39e6f4SLijo Lazar 		break;
270af39e6f4SLijo Lazar 	case AMDGPU_SYS_REG_STATE_USR:
271af39e6f4SLijo Lazar 		bytes_read = amdgpu_asic_get_reg_state(
272af39e6f4SLijo Lazar 			adev, AMDGPU_REG_STATE_TYPE_USR, buf, count);
273af39e6f4SLijo Lazar 		break;
274af39e6f4SLijo Lazar 	case AMDGPU_SYS_REG_STATE_USR_1:
275af39e6f4SLijo Lazar 		bytes_read = amdgpu_asic_get_reg_state(
276af39e6f4SLijo Lazar 			adev, AMDGPU_REG_STATE_TYPE_USR_1, buf, count);
277af39e6f4SLijo Lazar 		break;
278af39e6f4SLijo Lazar 	default:
279af39e6f4SLijo Lazar 		return -EINVAL;
280af39e6f4SLijo Lazar 	}
281af39e6f4SLijo Lazar 
282af39e6f4SLijo Lazar 	return bytes_read;
283af39e6f4SLijo Lazar }
284af39e6f4SLijo Lazar 
2852d0f5001SThomas Weißschuh static const BIN_ATTR(reg_state, 0444, amdgpu_sysfs_reg_state_get, NULL,
286af39e6f4SLijo Lazar 		      AMDGPU_SYS_REG_STATE_END);
287af39e6f4SLijo Lazar 
amdgpu_reg_state_sysfs_init(struct amdgpu_device * adev)288af39e6f4SLijo Lazar int amdgpu_reg_state_sysfs_init(struct amdgpu_device *adev)
289af39e6f4SLijo Lazar {
290af39e6f4SLijo Lazar 	int ret;
291af39e6f4SLijo Lazar 
292af39e6f4SLijo Lazar 	if (!amdgpu_asic_get_reg_state_supported(adev))
293af39e6f4SLijo Lazar 		return 0;
294af39e6f4SLijo Lazar 
295af39e6f4SLijo Lazar 	ret = sysfs_create_bin_file(&adev->dev->kobj, &bin_attr_reg_state);
296af39e6f4SLijo Lazar 
297af39e6f4SLijo Lazar 	return ret;
298af39e6f4SLijo Lazar }
299af39e6f4SLijo Lazar 
amdgpu_reg_state_sysfs_fini(struct amdgpu_device * adev)300af39e6f4SLijo Lazar void amdgpu_reg_state_sysfs_fini(struct amdgpu_device *adev)
301af39e6f4SLijo Lazar {
302af39e6f4SLijo Lazar 	if (!amdgpu_asic_get_reg_state_supported(adev))
303af39e6f4SLijo Lazar 		return;
304af39e6f4SLijo Lazar 	sysfs_remove_bin_file(&adev->dev->kobj, &bin_attr_reg_state);
305af39e6f4SLijo Lazar }
306af39e6f4SLijo Lazar 
amdgpu_ip_block_suspend(struct amdgpu_ip_block * ip_block)307e095026fSSunil Khatri int amdgpu_ip_block_suspend(struct amdgpu_ip_block *ip_block)
308e095026fSSunil Khatri {
309e095026fSSunil Khatri 	int r;
310e095026fSSunil Khatri 
311e095026fSSunil Khatri 	if (ip_block->version->funcs->suspend) {
312e095026fSSunil Khatri 		r = ip_block->version->funcs->suspend(ip_block);
313e095026fSSunil Khatri 		if (r) {
314e095026fSSunil Khatri 			dev_err(ip_block->adev->dev,
315e095026fSSunil Khatri 				"suspend of IP block <%s> failed %d\n",
316e095026fSSunil Khatri 				ip_block->version->funcs->name, r);
317e095026fSSunil Khatri 			return r;
318e095026fSSunil Khatri 		}
319e095026fSSunil Khatri 	}
320e095026fSSunil Khatri 
321e095026fSSunil Khatri 	ip_block->status.hw = false;
322e095026fSSunil Khatri 	return 0;
323e095026fSSunil Khatri }
324e095026fSSunil Khatri 
amdgpu_ip_block_resume(struct amdgpu_ip_block * ip_block)325502d7630SSunil Khatri int amdgpu_ip_block_resume(struct amdgpu_ip_block *ip_block)
326502d7630SSunil Khatri {
327502d7630SSunil Khatri 	int r;
328502d7630SSunil Khatri 
329502d7630SSunil Khatri 	if (ip_block->version->funcs->resume) {
330502d7630SSunil Khatri 		r = ip_block->version->funcs->resume(ip_block);
331502d7630SSunil Khatri 		if (r) {
332502d7630SSunil Khatri 			dev_err(ip_block->adev->dev,
333502d7630SSunil Khatri 				"resume of IP block <%s> failed %d\n",
334502d7630SSunil Khatri 				ip_block->version->funcs->name, r);
335502d7630SSunil Khatri 			return r;
336502d7630SSunil Khatri 		}
337502d7630SSunil Khatri 	}
338502d7630SSunil Khatri 
339502d7630SSunil Khatri 	ip_block->status.hw = true;
340502d7630SSunil Khatri 	return 0;
341502d7630SSunil Khatri }
342502d7630SSunil Khatri 
3434798db85SLijo Lazar /**
3444798db85SLijo Lazar  * DOC: board_info
3454798db85SLijo Lazar  *
3464798db85SLijo Lazar  * The amdgpu driver provides a sysfs API for giving board related information.
3474798db85SLijo Lazar  * It provides the form factor information in the format
3484798db85SLijo Lazar  *
3494798db85SLijo Lazar  *   type : form factor
3504798db85SLijo Lazar  *
3514798db85SLijo Lazar  * Possible form factor values
3524798db85SLijo Lazar  *
3534798db85SLijo Lazar  * - "cem"		- PCIE CEM card
3544798db85SLijo Lazar  * - "oam"		- Open Compute Accelerator Module
3554798db85SLijo Lazar  * - "unknown"	- Not known
3564798db85SLijo Lazar  *
3574798db85SLijo Lazar  */
3584798db85SLijo Lazar 
amdgpu_device_get_board_info(struct device * dev,struct device_attribute * attr,char * buf)35976da73f0SLijo Lazar static ssize_t amdgpu_device_get_board_info(struct device *dev,
36076da73f0SLijo Lazar 					    struct device_attribute *attr,
36176da73f0SLijo Lazar 					    char *buf)
36276da73f0SLijo Lazar {
36376da73f0SLijo Lazar 	struct drm_device *ddev = dev_get_drvdata(dev);
36476da73f0SLijo Lazar 	struct amdgpu_device *adev = drm_to_adev(ddev);
36576da73f0SLijo Lazar 	enum amdgpu_pkg_type pkg_type = AMDGPU_PKG_TYPE_CEM;
36676da73f0SLijo Lazar 	const char *pkg;
36776da73f0SLijo Lazar 
36876da73f0SLijo Lazar 	if (adev->smuio.funcs && adev->smuio.funcs->get_pkg_type)
36976da73f0SLijo Lazar 		pkg_type = adev->smuio.funcs->get_pkg_type(adev);
37076da73f0SLijo Lazar 
37176da73f0SLijo Lazar 	switch (pkg_type) {
37276da73f0SLijo Lazar 	case AMDGPU_PKG_TYPE_CEM:
37376da73f0SLijo Lazar 		pkg = "cem";
37476da73f0SLijo Lazar 		break;
37576da73f0SLijo Lazar 	case AMDGPU_PKG_TYPE_OAM:
37676da73f0SLijo Lazar 		pkg = "oam";
37776da73f0SLijo Lazar 		break;
37876da73f0SLijo Lazar 	default:
37976da73f0SLijo Lazar 		pkg = "unknown";
38076da73f0SLijo Lazar 		break;
38176da73f0SLijo Lazar 	}
38276da73f0SLijo Lazar 
38376da73f0SLijo Lazar 	return sysfs_emit(buf, "%s : %s\n", "type", pkg);
38476da73f0SLijo Lazar }
38576da73f0SLijo Lazar 
38676da73f0SLijo Lazar static DEVICE_ATTR(board_info, 0444, amdgpu_device_get_board_info, NULL);
38776da73f0SLijo Lazar 
38876da73f0SLijo Lazar static struct attribute *amdgpu_board_attrs[] = {
38976da73f0SLijo Lazar 	&dev_attr_board_info.attr,
39076da73f0SLijo Lazar 	NULL,
39176da73f0SLijo Lazar };
39276da73f0SLijo Lazar 
amdgpu_board_attrs_is_visible(struct kobject * kobj,struct attribute * attr,int n)39376da73f0SLijo Lazar static umode_t amdgpu_board_attrs_is_visible(struct kobject *kobj,
39476da73f0SLijo Lazar 					     struct attribute *attr, int n)
39576da73f0SLijo Lazar {
39676da73f0SLijo Lazar 	struct device *dev = kobj_to_dev(kobj);
39776da73f0SLijo Lazar 	struct drm_device *ddev = dev_get_drvdata(dev);
39876da73f0SLijo Lazar 	struct amdgpu_device *adev = drm_to_adev(ddev);
39976da73f0SLijo Lazar 
40076da73f0SLijo Lazar 	if (adev->flags & AMD_IS_APU)
40176da73f0SLijo Lazar 		return 0;
40276da73f0SLijo Lazar 
40376da73f0SLijo Lazar 	return attr->mode;
40476da73f0SLijo Lazar }
40576da73f0SLijo Lazar 
40676da73f0SLijo Lazar static const struct attribute_group amdgpu_board_attrs_group = {
40776da73f0SLijo Lazar 	.attrs = amdgpu_board_attrs,
40876da73f0SLijo Lazar 	.is_visible = amdgpu_board_attrs_is_visible
40976da73f0SLijo Lazar };
41076da73f0SLijo Lazar 
4115494d864SAlex Deucher static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
4125494d864SAlex Deucher 
413bd607166SKent Russell 
414bd607166SKent Russell /**
415b98c6299SAlex Deucher  * amdgpu_device_supports_px - Is the device a dGPU with ATPX power control
416fd496ca8SAlex Deucher  *
417fd496ca8SAlex Deucher  * @dev: drm_device pointer
418fd496ca8SAlex Deucher  *
419b98c6299SAlex Deucher  * Returns true if the device is a dGPU with ATPX power control,
420fd496ca8SAlex Deucher  * otherwise return false.
421fd496ca8SAlex Deucher  */
amdgpu_device_supports_px(struct drm_device * dev)422b98c6299SAlex Deucher bool amdgpu_device_supports_px(struct drm_device *dev)
423fd496ca8SAlex Deucher {
424fd496ca8SAlex Deucher 	struct amdgpu_device *adev = drm_to_adev(dev);
425fd496ca8SAlex Deucher 
426b98c6299SAlex Deucher 	if ((adev->flags & AMD_IS_PX) && !amdgpu_is_atpx_hybrid())
427fd496ca8SAlex Deucher 		return true;
428fd496ca8SAlex Deucher 	return false;
429fd496ca8SAlex Deucher }
430fd496ca8SAlex Deucher 
431fd496ca8SAlex Deucher /**
4320330b848SAlex Deucher  * amdgpu_device_supports_boco - Is the device a dGPU with ACPI power resources
433e3ecdffaSAlex Deucher  *
434e3ecdffaSAlex Deucher  * @dev: drm_device pointer
435e3ecdffaSAlex Deucher  *
436b98c6299SAlex Deucher  * Returns true if the device is a dGPU with ACPI power control,
437e3ecdffaSAlex Deucher  * otherwise return false.
438e3ecdffaSAlex Deucher  */
amdgpu_device_supports_boco(struct drm_device * dev)43931af062aSAlex Deucher bool amdgpu_device_supports_boco(struct drm_device *dev)
440d38ceaf9SAlex Deucher {
4411348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
442d38ceaf9SAlex Deucher 
4431ad5bdc2SMario Limonciello 	if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
4441ad5bdc2SMario Limonciello 		return false;
4451ad5bdc2SMario Limonciello 
446b98c6299SAlex Deucher 	if (adev->has_pr3 ||
447b98c6299SAlex Deucher 	    ((adev->flags & AMD_IS_PX) && amdgpu_is_atpx_hybrid()))
448d38ceaf9SAlex Deucher 		return true;
449d38ceaf9SAlex Deucher 	return false;
450d38ceaf9SAlex Deucher }
451d38ceaf9SAlex Deucher 
452e35e2b11STianci.Yin /**
453a69cba42SAlex Deucher  * amdgpu_device_supports_baco - Does the device support BACO
454a69cba42SAlex Deucher  *
455a69cba42SAlex Deucher  * @dev: drm_device pointer
456a69cba42SAlex Deucher  *
457b2207dc6SMa Jun  * Return:
458a567db80SRandy Dunlap  * 1 if the device supports BACO;
459a567db80SRandy Dunlap  * 3 if the device supports MACO (only works if BACO is supported)
460b2207dc6SMa Jun  * otherwise return 0.
461a69cba42SAlex Deucher  */
amdgpu_device_supports_baco(struct drm_device * dev)462b2207dc6SMa Jun int amdgpu_device_supports_baco(struct drm_device *dev)
463a69cba42SAlex Deucher {
4641348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
465a69cba42SAlex Deucher 
466a69cba42SAlex Deucher 	return amdgpu_asic_supports_baco(adev);
467a69cba42SAlex Deucher }
468a69cba42SAlex Deucher 
amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device * adev)46913478532SMa Jun void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev)
47013478532SMa Jun {
47113478532SMa Jun 	struct drm_device *dev;
47213478532SMa Jun 	int bamaco_support;
47313478532SMa Jun 
47413478532SMa Jun 	dev = adev_to_drm(adev);
47513478532SMa Jun 
47613478532SMa Jun 	adev->pm.rpm_mode = AMDGPU_RUNPM_NONE;
47713478532SMa Jun 	bamaco_support = amdgpu_device_supports_baco(dev);
47813478532SMa Jun 
47913478532SMa Jun 	switch (amdgpu_runtime_pm) {
48013478532SMa Jun 	case 2:
48113478532SMa Jun 		if (bamaco_support & MACO_SUPPORT) {
48213478532SMa Jun 			adev->pm.rpm_mode = AMDGPU_RUNPM_BAMACO;
48313478532SMa Jun 			dev_info(adev->dev, "Forcing BAMACO for runtime pm\n");
48413478532SMa Jun 		} else if (bamaco_support == BACO_SUPPORT) {
48513478532SMa Jun 			adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
48613478532SMa Jun 			dev_info(adev->dev, "Requested mode BAMACO not available,fallback to use BACO\n");
48713478532SMa Jun 		}
48813478532SMa Jun 		break;
48913478532SMa Jun 	case 1:
49013478532SMa Jun 		if (bamaco_support & BACO_SUPPORT) {
49113478532SMa Jun 			adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
49213478532SMa Jun 			dev_info(adev->dev, "Forcing BACO for runtime pm\n");
49313478532SMa Jun 		}
49413478532SMa Jun 		break;
49513478532SMa Jun 	case -1:
49613478532SMa Jun 	case -2:
49713478532SMa Jun 		if (amdgpu_device_supports_px(dev)) { /* enable PX as runtime mode */
49813478532SMa Jun 			adev->pm.rpm_mode = AMDGPU_RUNPM_PX;
49913478532SMa Jun 			dev_info(adev->dev, "Using ATPX for runtime pm\n");
50013478532SMa Jun 		} else if (amdgpu_device_supports_boco(dev)) { /* enable boco as runtime mode */
50113478532SMa Jun 			adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO;
50213478532SMa Jun 			dev_info(adev->dev, "Using BOCO for runtime pm\n");
50313478532SMa Jun 		} else {
50413478532SMa Jun 			if (!bamaco_support)
50513478532SMa Jun 				goto no_runtime_pm;
50613478532SMa Jun 
50713478532SMa Jun 			switch (adev->asic_type) {
50813478532SMa Jun 			case CHIP_VEGA20:
50913478532SMa Jun 			case CHIP_ARCTURUS:
51013478532SMa Jun 				/* BACO are not supported on vega20 and arctrus */
51113478532SMa Jun 				break;
51213478532SMa Jun 			case CHIP_VEGA10:
51313478532SMa Jun 				/* enable BACO as runpm mode if noretry=0 */
51413478532SMa Jun 				if (!adev->gmc.noretry)
51513478532SMa Jun 					adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
51613478532SMa Jun 				break;
51713478532SMa Jun 			default:
51813478532SMa Jun 				/* enable BACO as runpm mode on CI+ */
51913478532SMa Jun 				adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
52013478532SMa Jun 				break;
52113478532SMa Jun 			}
52213478532SMa Jun 
52313478532SMa Jun 			if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) {
52413478532SMa Jun 				if (bamaco_support & MACO_SUPPORT) {
52513478532SMa Jun 					adev->pm.rpm_mode = AMDGPU_RUNPM_BAMACO;
52613478532SMa Jun 					dev_info(adev->dev, "Using BAMACO for runtime pm\n");
52713478532SMa Jun 				} else {
52813478532SMa Jun 					dev_info(adev->dev, "Using BACO for runtime pm\n");
52913478532SMa Jun 				}
53013478532SMa Jun 			}
53113478532SMa Jun 		}
53213478532SMa Jun 		break;
53313478532SMa Jun 	case 0:
53413478532SMa Jun 		dev_info(adev->dev, "runtime pm is manually disabled\n");
53513478532SMa Jun 		break;
53613478532SMa Jun 	default:
53713478532SMa Jun 		break;
53813478532SMa Jun 	}
53913478532SMa Jun 
54013478532SMa Jun no_runtime_pm:
54113478532SMa Jun 	if (adev->pm.rpm_mode == AMDGPU_RUNPM_NONE)
54213478532SMa Jun 		dev_info(adev->dev, "Runtime PM not available\n");
54313478532SMa Jun }
5443fa8f89dSSathishkumar S /**
5453fa8f89dSSathishkumar S  * amdgpu_device_supports_smart_shift - Is the device dGPU with
5463fa8f89dSSathishkumar S  * smart shift support
5473fa8f89dSSathishkumar S  *
5483fa8f89dSSathishkumar S  * @dev: drm_device pointer
5493fa8f89dSSathishkumar S  *
5503fa8f89dSSathishkumar S  * Returns true if the device is a dGPU with Smart Shift support,
5513fa8f89dSSathishkumar S  * otherwise returns false.
5523fa8f89dSSathishkumar S  */
amdgpu_device_supports_smart_shift(struct drm_device * dev)5533fa8f89dSSathishkumar S bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
5543fa8f89dSSathishkumar S {
5553fa8f89dSSathishkumar S 	return (amdgpu_device_supports_boco(dev) &&
5563fa8f89dSSathishkumar S 		amdgpu_acpi_is_power_shift_control_supported());
5573fa8f89dSSathishkumar S }
5583fa8f89dSSathishkumar S 
5596e3cd2a9SMauro Carvalho Chehab /*
5606e3cd2a9SMauro Carvalho Chehab  * VRAM access helper functions
5616e3cd2a9SMauro Carvalho Chehab  */
5626e3cd2a9SMauro Carvalho Chehab 
563a69cba42SAlex Deucher /**
564048af66bSKevin Wang  * amdgpu_device_mm_access - access vram by MM_INDEX/MM_DATA
565e35e2b11STianci.Yin  *
566e35e2b11STianci.Yin  * @adev: amdgpu_device pointer
567e35e2b11STianci.Yin  * @pos: offset of the buffer in vram
568e35e2b11STianci.Yin  * @buf: virtual address of the buffer in system memory
569e35e2b11STianci.Yin  * @size: read/write size, sizeof(@buf) must > @size
570e35e2b11STianci.Yin  * @write: true - write to vram, otherwise - read from vram
571e35e2b11STianci.Yin  */
amdgpu_device_mm_access(struct amdgpu_device * adev,loff_t pos,void * buf,size_t size,bool write)572048af66bSKevin Wang void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
573048af66bSKevin Wang 			     void *buf, size_t size, bool write)
574e35e2b11STianci.Yin {
575e35e2b11STianci.Yin 	unsigned long flags;
576048af66bSKevin Wang 	uint32_t hi = ~0, tmp = 0;
577048af66bSKevin Wang 	uint32_t *data = buf;
578ce05ac56SChristian König 	uint64_t last;
579f89f8c6bSAndrey Grodzovsky 	int idx;
580e35e2b11STianci.Yin 
581c58a863bSGuchun Chen 	if (!drm_dev_enter(adev_to_drm(adev), &idx))
582f89f8c6bSAndrey Grodzovsky 		return;
5839d11eb0dSChristian König 
584048af66bSKevin Wang 	BUG_ON(!IS_ALIGNED(pos, 4) || !IS_ALIGNED(size, 4));
585048af66bSKevin Wang 
586048af66bSKevin Wang 	spin_lock_irqsave(&adev->mmio_idx_lock, flags);
587048af66bSKevin Wang 	for (last = pos + size; pos < last; pos += 4) {
588048af66bSKevin Wang 		tmp = pos >> 31;
589048af66bSKevin Wang 
590048af66bSKevin Wang 		WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
591048af66bSKevin Wang 		if (tmp != hi) {
592048af66bSKevin Wang 			WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
593048af66bSKevin Wang 			hi = tmp;
594048af66bSKevin Wang 		}
595048af66bSKevin Wang 		if (write)
596048af66bSKevin Wang 			WREG32_NO_KIQ(mmMM_DATA, *data++);
597048af66bSKevin Wang 		else
598048af66bSKevin Wang 			*data++ = RREG32_NO_KIQ(mmMM_DATA);
599048af66bSKevin Wang 	}
600048af66bSKevin Wang 
601048af66bSKevin Wang 	spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
602048af66bSKevin Wang 	drm_dev_exit(idx);
603048af66bSKevin Wang }
604048af66bSKevin Wang 
605048af66bSKevin Wang /**
606a567db80SRandy Dunlap  * amdgpu_device_aper_access - access vram by vram aperture
607048af66bSKevin Wang  *
608048af66bSKevin Wang  * @adev: amdgpu_device pointer
609048af66bSKevin Wang  * @pos: offset of the buffer in vram
610048af66bSKevin Wang  * @buf: virtual address of the buffer in system memory
611048af66bSKevin Wang  * @size: read/write size, sizeof(@buf) must > @size
612048af66bSKevin Wang  * @write: true - write to vram, otherwise - read from vram
613048af66bSKevin Wang  *
614048af66bSKevin Wang  * The return value means how many bytes have been transferred.
615048af66bSKevin Wang  */
amdgpu_device_aper_access(struct amdgpu_device * adev,loff_t pos,void * buf,size_t size,bool write)616048af66bSKevin Wang size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
617048af66bSKevin Wang 				 void *buf, size_t size, bool write)
618048af66bSKevin Wang {
6199d11eb0dSChristian König #ifdef CONFIG_64BIT
620048af66bSKevin Wang 	void __iomem *addr;
621048af66bSKevin Wang 	size_t count = 0;
622048af66bSKevin Wang 	uint64_t last;
623048af66bSKevin Wang 
624048af66bSKevin Wang 	if (!adev->mman.aper_base_kaddr)
625048af66bSKevin Wang 		return 0;
626048af66bSKevin Wang 
6279d11eb0dSChristian König 	last = min(pos + size, adev->gmc.visible_vram_size);
6289d11eb0dSChristian König 	if (last > pos) {
629048af66bSKevin Wang 		addr = adev->mman.aper_base_kaddr + pos;
630048af66bSKevin Wang 		count = last - pos;
6319d11eb0dSChristian König 
6329d11eb0dSChristian König 		if (write) {
6339d11eb0dSChristian König 			memcpy_toio(addr, buf, count);
6344c452b5cSSrinivasan Shanmugam 			/* Make sure HDP write cache flush happens without any reordering
6354c452b5cSSrinivasan Shanmugam 			 * after the system memory contents are sent over PCIe device
6364c452b5cSSrinivasan Shanmugam 			 */
6379d11eb0dSChristian König 			mb();
638810085ddSEric Huang 			amdgpu_device_flush_hdp(adev, NULL);
6399d11eb0dSChristian König 		} else {
640810085ddSEric Huang 			amdgpu_device_invalidate_hdp(adev, NULL);
6414c452b5cSSrinivasan Shanmugam 			/* Make sure HDP read cache is invalidated before issuing a read
6424c452b5cSSrinivasan Shanmugam 			 * to the PCIe device
6434c452b5cSSrinivasan Shanmugam 			 */
6449d11eb0dSChristian König 			mb();
6459d11eb0dSChristian König 			memcpy_fromio(buf, addr, count);
6469d11eb0dSChristian König 		}
6479d11eb0dSChristian König 
648048af66bSKevin Wang 	}
6499d11eb0dSChristian König 
650048af66bSKevin Wang 	return count;
651048af66bSKevin Wang #else
652048af66bSKevin Wang 	return 0;
653048af66bSKevin Wang #endif
654048af66bSKevin Wang }
655048af66bSKevin Wang 
656048af66bSKevin Wang /**
657048af66bSKevin Wang  * amdgpu_device_vram_access - read/write a buffer in vram
658048af66bSKevin Wang  *
659048af66bSKevin Wang  * @adev: amdgpu_device pointer
660048af66bSKevin Wang  * @pos: offset of the buffer in vram
661048af66bSKevin Wang  * @buf: virtual address of the buffer in system memory
662048af66bSKevin Wang  * @size: read/write size, sizeof(@buf) must > @size
663048af66bSKevin Wang  * @write: true - write to vram, otherwise - read from vram
664048af66bSKevin Wang  */
amdgpu_device_vram_access(struct amdgpu_device * adev,loff_t pos,void * buf,size_t size,bool write)665048af66bSKevin Wang void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
666048af66bSKevin Wang 			       void *buf, size_t size, bool write)
667048af66bSKevin Wang {
668048af66bSKevin Wang 	size_t count;
669048af66bSKevin Wang 
670048af66bSKevin Wang 	/* try to using vram apreature to access vram first */
671048af66bSKevin Wang 	count = amdgpu_device_aper_access(adev, pos, buf, size, write);
6729d11eb0dSChristian König 	size -= count;
673048af66bSKevin Wang 	if (size) {
674048af66bSKevin Wang 		/* using MM to access rest vram */
675048af66bSKevin Wang 		pos += count;
676048af66bSKevin Wang 		buf += count;
677048af66bSKevin Wang 		amdgpu_device_mm_access(adev, pos, buf, size, write);
6789d11eb0dSChristian König 	}
679e35e2b11STianci.Yin }
680e35e2b11STianci.Yin 
681d38ceaf9SAlex Deucher /*
682f7ee1874SHawking Zhang  * register access helper functions.
683d38ceaf9SAlex Deucher  */
68456b53c0bSDennis Li 
68556b53c0bSDennis Li /* Check if hw access should be skipped because of hotplug or device error */
amdgpu_device_skip_hw_access(struct amdgpu_device * adev)68656b53c0bSDennis Li bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev)
68756b53c0bSDennis Li {
6887afefb81SAndrey Grodzovsky 	if (adev->no_hw_access)
68956b53c0bSDennis Li 		return true;
69056b53c0bSDennis Li 
69156b53c0bSDennis Li #ifdef CONFIG_LOCKDEP
69256b53c0bSDennis Li 	/*
69356b53c0bSDennis Li 	 * This is a bit complicated to understand, so worth a comment. What we assert
69456b53c0bSDennis Li 	 * here is that the GPU reset is not running on another thread in parallel.
69556b53c0bSDennis Li 	 *
69656b53c0bSDennis Li 	 * For this we trylock the read side of the reset semaphore, if that succeeds
697a567db80SRandy Dunlap 	 * we know that the reset is not running in parallel.
69856b53c0bSDennis Li 	 *
69956b53c0bSDennis Li 	 * If the trylock fails we assert that we are either already holding the read
70056b53c0bSDennis Li 	 * side of the lock or are the reset thread itself and hold the write side of
70156b53c0bSDennis Li 	 * the lock.
70256b53c0bSDennis Li 	 */
70356b53c0bSDennis Li 	if (in_task()) {
704d0fb18b5SAndrey Grodzovsky 		if (down_read_trylock(&adev->reset_domain->sem))
705d0fb18b5SAndrey Grodzovsky 			up_read(&adev->reset_domain->sem);
70656b53c0bSDennis Li 		else
707d0fb18b5SAndrey Grodzovsky 			lockdep_assert_held(&adev->reset_domain->sem);
70856b53c0bSDennis Li 	}
70956b53c0bSDennis Li #endif
71056b53c0bSDennis Li 	return false;
71156b53c0bSDennis Li }
71256b53c0bSDennis Li 
713e3ecdffaSAlex Deucher /**
714f7ee1874SHawking Zhang  * amdgpu_device_rreg - read a memory mapped IO or indirect register
715e3ecdffaSAlex Deucher  *
716e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
717e3ecdffaSAlex Deucher  * @reg: dword aligned register offset
718e3ecdffaSAlex Deucher  * @acc_flags: access flags which require special behavior
719e3ecdffaSAlex Deucher  *
720e3ecdffaSAlex Deucher  * Returns the 32 bit value from the offset specified.
721e3ecdffaSAlex Deucher  */
amdgpu_device_rreg(struct amdgpu_device * adev,uint32_t reg,uint32_t acc_flags)722f7ee1874SHawking Zhang uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
723f7ee1874SHawking Zhang 			    uint32_t reg, uint32_t acc_flags)
724d38ceaf9SAlex Deucher {
725f4b373f4STom St Denis 	uint32_t ret;
726f4b373f4STom St Denis 
72756b53c0bSDennis Li 	if (amdgpu_device_skip_hw_access(adev))
728bf36b52eSAndrey Grodzovsky 		return 0;
729bf36b52eSAndrey Grodzovsky 
730f7ee1874SHawking Zhang 	if ((reg * 4) < adev->rmmio_size) {
731f7ee1874SHawking Zhang 		if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
732f7ee1874SHawking Zhang 		    amdgpu_sriov_runtime(adev) &&
733d0fb18b5SAndrey Grodzovsky 		    down_read_trylock(&adev->reset_domain->sem)) {
73485150626SVictor Lu 			ret = amdgpu_kiq_rreg(adev, reg, 0);
735d0fb18b5SAndrey Grodzovsky 			up_read(&adev->reset_domain->sem);
736f7ee1874SHawking Zhang 		} else {
737f4b373f4STom St Denis 			ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
738f7ee1874SHawking Zhang 		}
739f7ee1874SHawking Zhang 	} else {
740f7ee1874SHawking Zhang 		ret = adev->pcie_rreg(adev, reg * 4);
741e78b579dSHawking Zhang 	}
74281202807SDennis Li 
743f7ee1874SHawking Zhang 	trace_amdgpu_device_rreg(adev->pdev->device, reg, ret);
744f7ee1874SHawking Zhang 
745f4b373f4STom St Denis 	return ret;
746d38ceaf9SAlex Deucher }
747d38ceaf9SAlex Deucher 
748421a2a30SMonk Liu /*
749421a2a30SMonk Liu  * MMIO register read with bytes helper functions
750421a2a30SMonk Liu  * @offset:bytes offset from MMIO start
751421a2a30SMonk Liu  */
752421a2a30SMonk Liu 
753e3ecdffaSAlex Deucher /**
754e3ecdffaSAlex Deucher  * amdgpu_mm_rreg8 - read a memory mapped IO register
755e3ecdffaSAlex Deucher  *
756e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
757e3ecdffaSAlex Deucher  * @offset: byte aligned register offset
758e3ecdffaSAlex Deucher  *
759e3ecdffaSAlex Deucher  * Returns the 8 bit value from the offset specified.
760e3ecdffaSAlex Deucher  */
amdgpu_mm_rreg8(struct amdgpu_device * adev,uint32_t offset)7617cbbc745SAndrey Grodzovsky uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset)
7627cbbc745SAndrey Grodzovsky {
76356b53c0bSDennis Li 	if (amdgpu_device_skip_hw_access(adev))
764bf36b52eSAndrey Grodzovsky 		return 0;
765bf36b52eSAndrey Grodzovsky 
766421a2a30SMonk Liu 	if (offset < adev->rmmio_size)
767421a2a30SMonk Liu 		return (readb(adev->rmmio + offset));
768421a2a30SMonk Liu 	BUG();
769421a2a30SMonk Liu }
770421a2a30SMonk Liu 
77185150626SVictor Lu 
77285150626SVictor Lu /**
77385150626SVictor Lu  * amdgpu_device_xcc_rreg - read a memory mapped IO or indirect register with specific XCC
77485150626SVictor Lu  *
77585150626SVictor Lu  * @adev: amdgpu_device pointer
77685150626SVictor Lu  * @reg: dword aligned register offset
77785150626SVictor Lu  * @acc_flags: access flags which require special behavior
77885150626SVictor Lu  * @xcc_id: xcc accelerated compute core id
77985150626SVictor Lu  *
78085150626SVictor Lu  * Returns the 32 bit value from the offset specified.
78185150626SVictor Lu  */
amdgpu_device_xcc_rreg(struct amdgpu_device * adev,uint32_t reg,uint32_t acc_flags,uint32_t xcc_id)78285150626SVictor Lu uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev,
78385150626SVictor Lu 				uint32_t reg, uint32_t acc_flags,
78485150626SVictor Lu 				uint32_t xcc_id)
78585150626SVictor Lu {
78685150626SVictor Lu 	uint32_t ret, rlcg_flag;
78785150626SVictor Lu 
78885150626SVictor Lu 	if (amdgpu_device_skip_hw_access(adev))
78985150626SVictor Lu 		return 0;
79085150626SVictor Lu 
79185150626SVictor Lu 	if ((reg * 4) < adev->rmmio_size) {
79285150626SVictor Lu 		if (amdgpu_sriov_vf(adev) &&
79385150626SVictor Lu 		    !amdgpu_sriov_runtime(adev) &&
79485150626SVictor Lu 		    adev->gfx.rlc.rlcg_reg_access_supported &&
79585150626SVictor Lu 		    amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags,
79685150626SVictor Lu 							 GC_HWIP, false,
79785150626SVictor Lu 							 &rlcg_flag)) {
798e21e0b78SVictor Zhao 			ret = amdgpu_virt_rlcg_reg_rw(adev, reg, 0, rlcg_flag, GET_INST(GC, xcc_id));
79985150626SVictor Lu 		} else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
80085150626SVictor Lu 		    amdgpu_sriov_runtime(adev) &&
80185150626SVictor Lu 		    down_read_trylock(&adev->reset_domain->sem)) {
80285150626SVictor Lu 			ret = amdgpu_kiq_rreg(adev, reg, xcc_id);
80385150626SVictor Lu 			up_read(&adev->reset_domain->sem);
80485150626SVictor Lu 		} else {
80585150626SVictor Lu 			ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
80685150626SVictor Lu 		}
80785150626SVictor Lu 	} else {
80885150626SVictor Lu 		ret = adev->pcie_rreg(adev, reg * 4);
80985150626SVictor Lu 	}
81085150626SVictor Lu 
81185150626SVictor Lu 	return ret;
81285150626SVictor Lu }
81385150626SVictor Lu 
814421a2a30SMonk Liu /*
815421a2a30SMonk Liu  * MMIO register write with bytes helper functions
816421a2a30SMonk Liu  * @offset:bytes offset from MMIO start
817421a2a30SMonk Liu  * @value: the value want to be written to the register
818421a2a30SMonk Liu  */
819b8920e1eSSrinivasan Shanmugam 
820e3ecdffaSAlex Deucher /**
821e3ecdffaSAlex Deucher  * amdgpu_mm_wreg8 - read a memory mapped IO register
822e3ecdffaSAlex Deucher  *
823e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
824e3ecdffaSAlex Deucher  * @offset: byte aligned register offset
825e3ecdffaSAlex Deucher  * @value: 8 bit value to write
826e3ecdffaSAlex Deucher  *
827e3ecdffaSAlex Deucher  * Writes the value specified to the offset specified.
828e3ecdffaSAlex Deucher  */
amdgpu_mm_wreg8(struct amdgpu_device * adev,uint32_t offset,uint8_t value)8297cbbc745SAndrey Grodzovsky void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value)
8307cbbc745SAndrey Grodzovsky {
83156b53c0bSDennis Li 	if (amdgpu_device_skip_hw_access(adev))
832bf36b52eSAndrey Grodzovsky 		return;
833bf36b52eSAndrey Grodzovsky 
834421a2a30SMonk Liu 	if (offset < adev->rmmio_size)
835421a2a30SMonk Liu 		writeb(value, adev->rmmio + offset);
836421a2a30SMonk Liu 	else
837421a2a30SMonk Liu 		BUG();
838421a2a30SMonk Liu }
839421a2a30SMonk Liu 
840e3ecdffaSAlex Deucher /**
841f7ee1874SHawking Zhang  * amdgpu_device_wreg - write to a memory mapped IO or indirect register
8422e0cc4d4SMonk Liu  *
8432e0cc4d4SMonk Liu  * @adev: amdgpu_device pointer
8442e0cc4d4SMonk Liu  * @reg: dword aligned register offset
8452e0cc4d4SMonk Liu  * @v: 32 bit value to write to the register
8462e0cc4d4SMonk Liu  * @acc_flags: access flags which require special behavior
8472e0cc4d4SMonk Liu  *
8482e0cc4d4SMonk Liu  * Writes the value specified to the offset specified.
8492e0cc4d4SMonk Liu  */
amdgpu_device_wreg(struct amdgpu_device * adev,uint32_t reg,uint32_t v,uint32_t acc_flags)850f7ee1874SHawking Zhang void amdgpu_device_wreg(struct amdgpu_device *adev,
851f7ee1874SHawking Zhang 			uint32_t reg, uint32_t v,
8522e0cc4d4SMonk Liu 			uint32_t acc_flags)
8532e0cc4d4SMonk Liu {
85456b53c0bSDennis Li 	if (amdgpu_device_skip_hw_access(adev))
855bf36b52eSAndrey Grodzovsky 		return;
856bf36b52eSAndrey Grodzovsky 
857f7ee1874SHawking Zhang 	if ((reg * 4) < adev->rmmio_size) {
858f7ee1874SHawking Zhang 		if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
859f7ee1874SHawking Zhang 		    amdgpu_sriov_runtime(adev) &&
860d0fb18b5SAndrey Grodzovsky 		    down_read_trylock(&adev->reset_domain->sem)) {
86185150626SVictor Lu 			amdgpu_kiq_wreg(adev, reg, v, 0);
862d0fb18b5SAndrey Grodzovsky 			up_read(&adev->reset_domain->sem);
863f7ee1874SHawking Zhang 		} else {
864f7ee1874SHawking Zhang 			writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
865f7ee1874SHawking Zhang 		}
866f7ee1874SHawking Zhang 	} else {
867f7ee1874SHawking Zhang 		adev->pcie_wreg(adev, reg * 4, v);
86881202807SDennis Li 	}
8692e0cc4d4SMonk Liu 
870f7ee1874SHawking Zhang 	trace_amdgpu_device_wreg(adev->pdev->device, reg, v);
8712e0cc4d4SMonk Liu }
8722e0cc4d4SMonk Liu 
87303f2abb0SYann Dirson /**
8744cc9f86fSTom St Denis  * amdgpu_mm_wreg_mmio_rlc -  write register either with direct/indirect mmio or with RLC path if in range
8752e0cc4d4SMonk Liu  *
87671579346SRajneesh Bhardwaj  * @adev: amdgpu_device pointer
87771579346SRajneesh Bhardwaj  * @reg: mmio/rlc register
87871579346SRajneesh Bhardwaj  * @v: value to write
8798057a9d6SLee Jones  * @xcc_id: xcc accelerated compute core id
88071579346SRajneesh Bhardwaj  *
88171579346SRajneesh Bhardwaj  * this function is invoked only for the debugfs register access
88203f2abb0SYann Dirson  */
amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device * adev,uint32_t reg,uint32_t v,uint32_t xcc_id)883f7ee1874SHawking Zhang void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
8848ed49dd1SVictor Lu 			     uint32_t reg, uint32_t v,
8858ed49dd1SVictor Lu 			     uint32_t xcc_id)
8862e0cc4d4SMonk Liu {
88756b53c0bSDennis Li 	if (amdgpu_device_skip_hw_access(adev))
888bf36b52eSAndrey Grodzovsky 		return;
889bf36b52eSAndrey Grodzovsky 
8902e0cc4d4SMonk Liu 	if (amdgpu_sriov_fullaccess(adev) &&
8912e0cc4d4SMonk Liu 	    adev->gfx.rlc.funcs &&
8922e0cc4d4SMonk Liu 	    adev->gfx.rlc.funcs->is_rlcg_access_range) {
8932e0cc4d4SMonk Liu 		if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg))
8948ed49dd1SVictor Lu 			return amdgpu_sriov_wreg(adev, reg, v, 0, 0, xcc_id);
8954cc9f86fSTom St Denis 	} else if ((reg * 4) >= adev->rmmio_size) {
8964cc9f86fSTom St Denis 		adev->pcie_wreg(adev, reg * 4, v);
897f7ee1874SHawking Zhang 	} else {
898f7ee1874SHawking Zhang 		writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
8992e0cc4d4SMonk Liu 	}
9002e0cc4d4SMonk Liu }
9012e0cc4d4SMonk Liu 
9022e0cc4d4SMonk Liu /**
90385150626SVictor Lu  * amdgpu_device_xcc_wreg - write to a memory mapped IO or indirect register with specific XCC
90485150626SVictor Lu  *
90585150626SVictor Lu  * @adev: amdgpu_device pointer
90685150626SVictor Lu  * @reg: dword aligned register offset
90785150626SVictor Lu  * @v: 32 bit value to write to the register
90885150626SVictor Lu  * @acc_flags: access flags which require special behavior
90985150626SVictor Lu  * @xcc_id: xcc accelerated compute core id
91085150626SVictor Lu  *
91185150626SVictor Lu  * Writes the value specified to the offset specified.
91285150626SVictor Lu  */
amdgpu_device_xcc_wreg(struct amdgpu_device * adev,uint32_t reg,uint32_t v,uint32_t acc_flags,uint32_t xcc_id)91385150626SVictor Lu void amdgpu_device_xcc_wreg(struct amdgpu_device *adev,
91485150626SVictor Lu 			uint32_t reg, uint32_t v,
91585150626SVictor Lu 			uint32_t acc_flags, uint32_t xcc_id)
91685150626SVictor Lu {
91785150626SVictor Lu 	uint32_t rlcg_flag;
91885150626SVictor Lu 
91985150626SVictor Lu 	if (amdgpu_device_skip_hw_access(adev))
92085150626SVictor Lu 		return;
92185150626SVictor Lu 
92285150626SVictor Lu 	if ((reg * 4) < adev->rmmio_size) {
92385150626SVictor Lu 		if (amdgpu_sriov_vf(adev) &&
92485150626SVictor Lu 		    !amdgpu_sriov_runtime(adev) &&
92585150626SVictor Lu 		    adev->gfx.rlc.rlcg_reg_access_supported &&
92685150626SVictor Lu 		    amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags,
92785150626SVictor Lu 							 GC_HWIP, true,
92885150626SVictor Lu 							 &rlcg_flag)) {
929e21e0b78SVictor Zhao 			amdgpu_virt_rlcg_reg_rw(adev, reg, v, rlcg_flag, GET_INST(GC, xcc_id));
93085150626SVictor Lu 		} else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
93185150626SVictor Lu 		    amdgpu_sriov_runtime(adev) &&
93285150626SVictor Lu 		    down_read_trylock(&adev->reset_domain->sem)) {
93385150626SVictor Lu 			amdgpu_kiq_wreg(adev, reg, v, xcc_id);
93485150626SVictor Lu 			up_read(&adev->reset_domain->sem);
93585150626SVictor Lu 		} else {
93685150626SVictor Lu 			writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
93785150626SVictor Lu 		}
93885150626SVictor Lu 	} else {
93985150626SVictor Lu 		adev->pcie_wreg(adev, reg * 4, v);
94085150626SVictor Lu 	}
94185150626SVictor Lu }
94285150626SVictor Lu 
94385150626SVictor Lu /**
9441bba3683SHawking Zhang  * amdgpu_device_indirect_rreg - read an indirect register
9451bba3683SHawking Zhang  *
9461bba3683SHawking Zhang  * @adev: amdgpu_device pointer
94722f453fbSLee Jones  * @reg_addr: indirect register address to read from
9481bba3683SHawking Zhang  *
9491bba3683SHawking Zhang  * Returns the value of indirect register @reg_addr
9501bba3683SHawking Zhang  */
amdgpu_device_indirect_rreg(struct amdgpu_device * adev,u32 reg_addr)9511bba3683SHawking Zhang u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
9521bba3683SHawking Zhang 				u32 reg_addr)
9531bba3683SHawking Zhang {
95465ba96e9SHawking Zhang 	unsigned long flags, pcie_index, pcie_data;
9551bba3683SHawking Zhang 	void __iomem *pcie_index_offset;
9561bba3683SHawking Zhang 	void __iomem *pcie_data_offset;
95765ba96e9SHawking Zhang 	u32 r;
95865ba96e9SHawking Zhang 
95965ba96e9SHawking Zhang 	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
96065ba96e9SHawking Zhang 	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
9611bba3683SHawking Zhang 
9621bba3683SHawking Zhang 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
9631bba3683SHawking Zhang 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
9641bba3683SHawking Zhang 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
9651bba3683SHawking Zhang 
9661bba3683SHawking Zhang 	writel(reg_addr, pcie_index_offset);
9671bba3683SHawking Zhang 	readl(pcie_index_offset);
9681bba3683SHawking Zhang 	r = readl(pcie_data_offset);
9691bba3683SHawking Zhang 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
9701bba3683SHawking Zhang 
9711bba3683SHawking Zhang 	return r;
9721bba3683SHawking Zhang }
9731bba3683SHawking Zhang 
amdgpu_device_indirect_rreg_ext(struct amdgpu_device * adev,u64 reg_addr)9740c552ed3SLe Ma u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
9750c552ed3SLe Ma 				    u64 reg_addr)
9760c552ed3SLe Ma {
9770c552ed3SLe Ma 	unsigned long flags, pcie_index, pcie_index_hi, pcie_data;
9780c552ed3SLe Ma 	u32 r;
9790c552ed3SLe Ma 	void __iomem *pcie_index_offset;
9800c552ed3SLe Ma 	void __iomem *pcie_index_hi_offset;
9810c552ed3SLe Ma 	void __iomem *pcie_data_offset;
9820c552ed3SLe Ma 
983ad390542SHawking Zhang 	if (unlikely(!adev->nbio.funcs)) {
984ad390542SHawking Zhang 		pcie_index = AMDGPU_PCIE_INDEX_FALLBACK;
985ad390542SHawking Zhang 		pcie_data = AMDGPU_PCIE_DATA_FALLBACK;
986ad390542SHawking Zhang 	} else {
9870c552ed3SLe Ma 		pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
9880c552ed3SLe Ma 		pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
989ad390542SHawking Zhang 	}
990ad390542SHawking Zhang 
991ad390542SHawking Zhang 	if (reg_addr >> 32) {
992ad390542SHawking Zhang 		if (unlikely(!adev->nbio.funcs))
993ad390542SHawking Zhang 			pcie_index_hi = AMDGPU_PCIE_INDEX_HI_FALLBACK;
9940c552ed3SLe Ma 		else
995ad390542SHawking Zhang 			pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
996ad390542SHawking Zhang 	} else {
9970c552ed3SLe Ma 		pcie_index_hi = 0;
998ad390542SHawking Zhang 	}
9990c552ed3SLe Ma 
10000c552ed3SLe Ma 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
10010c552ed3SLe Ma 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
10020c552ed3SLe Ma 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
10030c552ed3SLe Ma 	if (pcie_index_hi != 0)
10040c552ed3SLe Ma 		pcie_index_hi_offset = (void __iomem *)adev->rmmio +
10050c552ed3SLe Ma 				pcie_index_hi * 4;
10060c552ed3SLe Ma 
10070c552ed3SLe Ma 	writel(reg_addr, pcie_index_offset);
10080c552ed3SLe Ma 	readl(pcie_index_offset);
10090c552ed3SLe Ma 	if (pcie_index_hi != 0) {
10100c552ed3SLe Ma 		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
10110c552ed3SLe Ma 		readl(pcie_index_hi_offset);
10120c552ed3SLe Ma 	}
10130c552ed3SLe Ma 	r = readl(pcie_data_offset);
10140c552ed3SLe Ma 
10150c552ed3SLe Ma 	/* clear the high bits */
10160c552ed3SLe Ma 	if (pcie_index_hi != 0) {
10170c552ed3SLe Ma 		writel(0, pcie_index_hi_offset);
10180c552ed3SLe Ma 		readl(pcie_index_hi_offset);
10190c552ed3SLe Ma 	}
10200c552ed3SLe Ma 
10210c552ed3SLe Ma 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
10220c552ed3SLe Ma 
10230c552ed3SLe Ma 	return r;
10240c552ed3SLe Ma }
10250c552ed3SLe Ma 
10261bba3683SHawking Zhang /**
10271bba3683SHawking Zhang  * amdgpu_device_indirect_rreg64 - read a 64bits indirect register
10281bba3683SHawking Zhang  *
10291bba3683SHawking Zhang  * @adev: amdgpu_device pointer
103022f453fbSLee Jones  * @reg_addr: indirect register address to read from
10311bba3683SHawking Zhang  *
10321bba3683SHawking Zhang  * Returns the value of indirect register @reg_addr
10331bba3683SHawking Zhang  */
amdgpu_device_indirect_rreg64(struct amdgpu_device * adev,u32 reg_addr)10341bba3683SHawking Zhang u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
10351bba3683SHawking Zhang 				  u32 reg_addr)
10361bba3683SHawking Zhang {
103765ba96e9SHawking Zhang 	unsigned long flags, pcie_index, pcie_data;
10381bba3683SHawking Zhang 	void __iomem *pcie_index_offset;
10391bba3683SHawking Zhang 	void __iomem *pcie_data_offset;
104065ba96e9SHawking Zhang 	u64 r;
104165ba96e9SHawking Zhang 
104265ba96e9SHawking Zhang 	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
104365ba96e9SHawking Zhang 	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
10441bba3683SHawking Zhang 
10451bba3683SHawking Zhang 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
10461bba3683SHawking Zhang 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
10471bba3683SHawking Zhang 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
10481bba3683SHawking Zhang 
10491bba3683SHawking Zhang 	/* read low 32 bits */
10501bba3683SHawking Zhang 	writel(reg_addr, pcie_index_offset);
10511bba3683SHawking Zhang 	readl(pcie_index_offset);
10521bba3683SHawking Zhang 	r = readl(pcie_data_offset);
10531bba3683SHawking Zhang 	/* read high 32 bits */
10541bba3683SHawking Zhang 	writel(reg_addr + 4, pcie_index_offset);
10551bba3683SHawking Zhang 	readl(pcie_index_offset);
10561bba3683SHawking Zhang 	r |= ((u64)readl(pcie_data_offset) << 32);
10571bba3683SHawking Zhang 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
10581bba3683SHawking Zhang 
10591bba3683SHawking Zhang 	return r;
10601bba3683SHawking Zhang }
10611bba3683SHawking Zhang 
amdgpu_device_indirect_rreg64_ext(struct amdgpu_device * adev,u64 reg_addr)1062a76b2870SCandice Li u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev,
1063a76b2870SCandice Li 				  u64 reg_addr)
1064a76b2870SCandice Li {
1065a76b2870SCandice Li 	unsigned long flags, pcie_index, pcie_data;
1066a76b2870SCandice Li 	unsigned long pcie_index_hi = 0;
1067a76b2870SCandice Li 	void __iomem *pcie_index_offset;
1068a76b2870SCandice Li 	void __iomem *pcie_index_hi_offset;
1069a76b2870SCandice Li 	void __iomem *pcie_data_offset;
1070a76b2870SCandice Li 	u64 r;
1071a76b2870SCandice Li 
1072a76b2870SCandice Li 	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
1073a76b2870SCandice Li 	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
1074a76b2870SCandice Li 	if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
1075a76b2870SCandice Li 		pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
1076a76b2870SCandice Li 
1077a76b2870SCandice Li 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
1078a76b2870SCandice Li 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
1079a76b2870SCandice Li 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
1080a76b2870SCandice Li 	if (pcie_index_hi != 0)
1081a76b2870SCandice Li 		pcie_index_hi_offset = (void __iomem *)adev->rmmio +
1082a76b2870SCandice Li 			pcie_index_hi * 4;
1083a76b2870SCandice Li 
1084a76b2870SCandice Li 	/* read low 32 bits */
1085a76b2870SCandice Li 	writel(reg_addr, pcie_index_offset);
1086a76b2870SCandice Li 	readl(pcie_index_offset);
1087a76b2870SCandice Li 	if (pcie_index_hi != 0) {
1088a76b2870SCandice Li 		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
1089a76b2870SCandice Li 		readl(pcie_index_hi_offset);
1090a76b2870SCandice Li 	}
1091a76b2870SCandice Li 	r = readl(pcie_data_offset);
1092a76b2870SCandice Li 	/* read high 32 bits */
1093a76b2870SCandice Li 	writel(reg_addr + 4, pcie_index_offset);
1094a76b2870SCandice Li 	readl(pcie_index_offset);
1095a76b2870SCandice Li 	if (pcie_index_hi != 0) {
1096a76b2870SCandice Li 		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
1097a76b2870SCandice Li 		readl(pcie_index_hi_offset);
1098a76b2870SCandice Li 	}
1099a76b2870SCandice Li 	r |= ((u64)readl(pcie_data_offset) << 32);
1100a76b2870SCandice Li 
1101a76b2870SCandice Li 	/* clear the high bits */
1102a76b2870SCandice Li 	if (pcie_index_hi != 0) {
1103a76b2870SCandice Li 		writel(0, pcie_index_hi_offset);
1104a76b2870SCandice Li 		readl(pcie_index_hi_offset);
1105a76b2870SCandice Li 	}
1106a76b2870SCandice Li 
1107a76b2870SCandice Li 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
1108a76b2870SCandice Li 
1109a76b2870SCandice Li 	return r;
1110a76b2870SCandice Li }
1111a76b2870SCandice Li 
11121bba3683SHawking Zhang /**
11131bba3683SHawking Zhang  * amdgpu_device_indirect_wreg - write an indirect register address
11141bba3683SHawking Zhang  *
11151bba3683SHawking Zhang  * @adev: amdgpu_device pointer
11161bba3683SHawking Zhang  * @reg_addr: indirect register offset
11171bba3683SHawking Zhang  * @reg_data: indirect register data
11181bba3683SHawking Zhang  *
11191bba3683SHawking Zhang  */
amdgpu_device_indirect_wreg(struct amdgpu_device * adev,u32 reg_addr,u32 reg_data)11201bba3683SHawking Zhang void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
11211bba3683SHawking Zhang 				 u32 reg_addr, u32 reg_data)
11221bba3683SHawking Zhang {
112365ba96e9SHawking Zhang 	unsigned long flags, pcie_index, pcie_data;
11241bba3683SHawking Zhang 	void __iomem *pcie_index_offset;
11251bba3683SHawking Zhang 	void __iomem *pcie_data_offset;
11261bba3683SHawking Zhang 
112765ba96e9SHawking Zhang 	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
112865ba96e9SHawking Zhang 	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
112965ba96e9SHawking Zhang 
11301bba3683SHawking Zhang 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
11311bba3683SHawking Zhang 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
11321bba3683SHawking Zhang 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
11331bba3683SHawking Zhang 
11341bba3683SHawking Zhang 	writel(reg_addr, pcie_index_offset);
11351bba3683SHawking Zhang 	readl(pcie_index_offset);
11361bba3683SHawking Zhang 	writel(reg_data, pcie_data_offset);
11371bba3683SHawking Zhang 	readl(pcie_data_offset);
11381bba3683SHawking Zhang 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
11391bba3683SHawking Zhang }
11401bba3683SHawking Zhang 
amdgpu_device_indirect_wreg_ext(struct amdgpu_device * adev,u64 reg_addr,u32 reg_data)11410c552ed3SLe Ma void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
11420c552ed3SLe Ma 				     u64 reg_addr, u32 reg_data)
11430c552ed3SLe Ma {
11440c552ed3SLe Ma 	unsigned long flags, pcie_index, pcie_index_hi, pcie_data;
11450c552ed3SLe Ma 	void __iomem *pcie_index_offset;
11460c552ed3SLe Ma 	void __iomem *pcie_index_hi_offset;
11470c552ed3SLe Ma 	void __iomem *pcie_data_offset;
11480c552ed3SLe Ma 
11490c552ed3SLe Ma 	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
11500c552ed3SLe Ma 	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
1151d57e24aaSCandice Li 	if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
11520c552ed3SLe Ma 		pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
11530c552ed3SLe Ma 	else
11540c552ed3SLe Ma 		pcie_index_hi = 0;
11550c552ed3SLe Ma 
11560c552ed3SLe Ma 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
11570c552ed3SLe Ma 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
11580c552ed3SLe Ma 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
11590c552ed3SLe Ma 	if (pcie_index_hi != 0)
11600c552ed3SLe Ma 		pcie_index_hi_offset = (void __iomem *)adev->rmmio +
11610c552ed3SLe Ma 				pcie_index_hi * 4;
11620c552ed3SLe Ma 
11630c552ed3SLe Ma 	writel(reg_addr, pcie_index_offset);
11640c552ed3SLe Ma 	readl(pcie_index_offset);
11650c552ed3SLe Ma 	if (pcie_index_hi != 0) {
11660c552ed3SLe Ma 		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
11670c552ed3SLe Ma 		readl(pcie_index_hi_offset);
11680c552ed3SLe Ma 	}
11690c552ed3SLe Ma 	writel(reg_data, pcie_data_offset);
11700c552ed3SLe Ma 	readl(pcie_data_offset);
11710c552ed3SLe Ma 
11720c552ed3SLe Ma 	/* clear the high bits */
11730c552ed3SLe Ma 	if (pcie_index_hi != 0) {
11740c552ed3SLe Ma 		writel(0, pcie_index_hi_offset);
11750c552ed3SLe Ma 		readl(pcie_index_hi_offset);
11760c552ed3SLe Ma 	}
11770c552ed3SLe Ma 
11780c552ed3SLe Ma 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
11790c552ed3SLe Ma }
11800c552ed3SLe Ma 
11811bba3683SHawking Zhang /**
11821bba3683SHawking Zhang  * amdgpu_device_indirect_wreg64 - write a 64bits indirect register address
11831bba3683SHawking Zhang  *
11841bba3683SHawking Zhang  * @adev: amdgpu_device pointer
11851bba3683SHawking Zhang  * @reg_addr: indirect register offset
11861bba3683SHawking Zhang  * @reg_data: indirect register data
11871bba3683SHawking Zhang  *
11881bba3683SHawking Zhang  */
amdgpu_device_indirect_wreg64(struct amdgpu_device * adev,u32 reg_addr,u64 reg_data)11891bba3683SHawking Zhang void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
11901bba3683SHawking Zhang 				   u32 reg_addr, u64 reg_data)
11911bba3683SHawking Zhang {
119265ba96e9SHawking Zhang 	unsigned long flags, pcie_index, pcie_data;
11931bba3683SHawking Zhang 	void __iomem *pcie_index_offset;
11941bba3683SHawking Zhang 	void __iomem *pcie_data_offset;
11951bba3683SHawking Zhang 
119665ba96e9SHawking Zhang 	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
119765ba96e9SHawking Zhang 	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
119865ba96e9SHawking Zhang 
11991bba3683SHawking Zhang 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
12001bba3683SHawking Zhang 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
12011bba3683SHawking Zhang 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
12021bba3683SHawking Zhang 
12031bba3683SHawking Zhang 	/* write low 32 bits */
12041bba3683SHawking Zhang 	writel(reg_addr, pcie_index_offset);
12051bba3683SHawking Zhang 	readl(pcie_index_offset);
12061bba3683SHawking Zhang 	writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset);
12071bba3683SHawking Zhang 	readl(pcie_data_offset);
12081bba3683SHawking Zhang 	/* write high 32 bits */
12091bba3683SHawking Zhang 	writel(reg_addr + 4, pcie_index_offset);
12101bba3683SHawking Zhang 	readl(pcie_index_offset);
12111bba3683SHawking Zhang 	writel((u32)(reg_data >> 32), pcie_data_offset);
12121bba3683SHawking Zhang 	readl(pcie_data_offset);
12131bba3683SHawking Zhang 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
12141bba3683SHawking Zhang }
12151bba3683SHawking Zhang 
amdgpu_device_indirect_wreg64_ext(struct amdgpu_device * adev,u64 reg_addr,u64 reg_data)1216a76b2870SCandice Li void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev,
1217a76b2870SCandice Li 				   u64 reg_addr, u64 reg_data)
1218a76b2870SCandice Li {
1219a76b2870SCandice Li 	unsigned long flags, pcie_index, pcie_data;
1220a76b2870SCandice Li 	unsigned long pcie_index_hi = 0;
1221a76b2870SCandice Li 	void __iomem *pcie_index_offset;
1222a76b2870SCandice Li 	void __iomem *pcie_index_hi_offset;
1223a76b2870SCandice Li 	void __iomem *pcie_data_offset;
1224a76b2870SCandice Li 
1225a76b2870SCandice Li 	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
1226a76b2870SCandice Li 	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
1227a76b2870SCandice Li 	if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
1228a76b2870SCandice Li 		pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
1229a76b2870SCandice Li 
1230a76b2870SCandice Li 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
1231a76b2870SCandice Li 	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
1232a76b2870SCandice Li 	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
1233a76b2870SCandice Li 	if (pcie_index_hi != 0)
1234a76b2870SCandice Li 		pcie_index_hi_offset = (void __iomem *)adev->rmmio +
1235a76b2870SCandice Li 				pcie_index_hi * 4;
1236a76b2870SCandice Li 
1237a76b2870SCandice Li 	/* write low 32 bits */
1238a76b2870SCandice Li 	writel(reg_addr, pcie_index_offset);
1239a76b2870SCandice Li 	readl(pcie_index_offset);
1240a76b2870SCandice Li 	if (pcie_index_hi != 0) {
1241a76b2870SCandice Li 		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
1242a76b2870SCandice Li 		readl(pcie_index_hi_offset);
1243a76b2870SCandice Li 	}
1244a76b2870SCandice Li 	writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset);
1245a76b2870SCandice Li 	readl(pcie_data_offset);
1246a76b2870SCandice Li 	/* write high 32 bits */
1247a76b2870SCandice Li 	writel(reg_addr + 4, pcie_index_offset);
1248a76b2870SCandice Li 	readl(pcie_index_offset);
1249a76b2870SCandice Li 	if (pcie_index_hi != 0) {
1250a76b2870SCandice Li 		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
1251a76b2870SCandice Li 		readl(pcie_index_hi_offset);
1252a76b2870SCandice Li 	}
1253a76b2870SCandice Li 	writel((u32)(reg_data >> 32), pcie_data_offset);
1254a76b2870SCandice Li 	readl(pcie_data_offset);
1255a76b2870SCandice Li 
1256a76b2870SCandice Li 	/* clear the high bits */
1257a76b2870SCandice Li 	if (pcie_index_hi != 0) {
1258a76b2870SCandice Li 		writel(0, pcie_index_hi_offset);
1259a76b2870SCandice Li 		readl(pcie_index_hi_offset);
1260a76b2870SCandice Li 	}
1261a76b2870SCandice Li 
1262a76b2870SCandice Li 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
1263a76b2870SCandice Li }
1264a76b2870SCandice Li 
12651bba3683SHawking Zhang /**
1266dabc114eSHawking Zhang  * amdgpu_device_get_rev_id - query device rev_id
1267dabc114eSHawking Zhang  *
1268dabc114eSHawking Zhang  * @adev: amdgpu_device pointer
1269dabc114eSHawking Zhang  *
1270dabc114eSHawking Zhang  * Return device rev_id
1271dabc114eSHawking Zhang  */
amdgpu_device_get_rev_id(struct amdgpu_device * adev)1272dabc114eSHawking Zhang u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev)
1273dabc114eSHawking Zhang {
1274dabc114eSHawking Zhang 	return adev->nbio.funcs->get_rev_id(adev);
1275dabc114eSHawking Zhang }
1276dabc114eSHawking Zhang 
1277dabc114eSHawking Zhang /**
1278d38ceaf9SAlex Deucher  * amdgpu_invalid_rreg - dummy reg read function
1279d38ceaf9SAlex Deucher  *
1280982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
1281d38ceaf9SAlex Deucher  * @reg: offset of register
1282d38ceaf9SAlex Deucher  *
1283d38ceaf9SAlex Deucher  * Dummy register read function.  Used for register blocks
1284d38ceaf9SAlex Deucher  * that certain asics don't have (all asics).
1285d38ceaf9SAlex Deucher  * Returns the value in the register.
1286d38ceaf9SAlex Deucher  */
amdgpu_invalid_rreg(struct amdgpu_device * adev,uint32_t reg)1287d38ceaf9SAlex Deucher static uint32_t amdgpu_invalid_rreg(struct amdgpu_device *adev, uint32_t reg)
1288d38ceaf9SAlex Deucher {
1289d38ceaf9SAlex Deucher 	DRM_ERROR("Invalid callback to read register 0x%04X\n", reg);
1290d38ceaf9SAlex Deucher 	BUG();
1291d38ceaf9SAlex Deucher 	return 0;
1292d38ceaf9SAlex Deucher }
1293d38ceaf9SAlex Deucher 
amdgpu_invalid_rreg_ext(struct amdgpu_device * adev,uint64_t reg)12940c552ed3SLe Ma static uint32_t amdgpu_invalid_rreg_ext(struct amdgpu_device *adev, uint64_t reg)
12950c552ed3SLe Ma {
12960c552ed3SLe Ma 	DRM_ERROR("Invalid callback to read register 0x%llX\n", reg);
12970c552ed3SLe Ma 	BUG();
12980c552ed3SLe Ma 	return 0;
12990c552ed3SLe Ma }
13000c552ed3SLe Ma 
1301d38ceaf9SAlex Deucher /**
1302d38ceaf9SAlex Deucher  * amdgpu_invalid_wreg - dummy reg write function
1303d38ceaf9SAlex Deucher  *
1304982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
1305d38ceaf9SAlex Deucher  * @reg: offset of register
1306d38ceaf9SAlex Deucher  * @v: value to write to the register
1307d38ceaf9SAlex Deucher  *
1308d38ceaf9SAlex Deucher  * Dummy register read function.  Used for register blocks
1309d38ceaf9SAlex Deucher  * that certain asics don't have (all asics).
1310d38ceaf9SAlex Deucher  */
amdgpu_invalid_wreg(struct amdgpu_device * adev,uint32_t reg,uint32_t v)1311d38ceaf9SAlex Deucher static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
1312d38ceaf9SAlex Deucher {
1313d38ceaf9SAlex Deucher 	DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n",
1314d38ceaf9SAlex Deucher 		  reg, v);
1315d38ceaf9SAlex Deucher 	BUG();
1316d38ceaf9SAlex Deucher }
1317d38ceaf9SAlex Deucher 
amdgpu_invalid_wreg_ext(struct amdgpu_device * adev,uint64_t reg,uint32_t v)13180c552ed3SLe Ma static void amdgpu_invalid_wreg_ext(struct amdgpu_device *adev, uint64_t reg, uint32_t v)
13190c552ed3SLe Ma {
13200c552ed3SLe Ma 	DRM_ERROR("Invalid callback to write register 0x%llX with 0x%08X\n",
13210c552ed3SLe Ma 		  reg, v);
13220c552ed3SLe Ma 	BUG();
13230c552ed3SLe Ma }
13240c552ed3SLe Ma 
1325d38ceaf9SAlex Deucher /**
13264fa1c6a6STao Zhou  * amdgpu_invalid_rreg64 - dummy 64 bit reg read function
13274fa1c6a6STao Zhou  *
1328982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
13294fa1c6a6STao Zhou  * @reg: offset of register
13304fa1c6a6STao Zhou  *
13314fa1c6a6STao Zhou  * Dummy register read function.  Used for register blocks
13324fa1c6a6STao Zhou  * that certain asics don't have (all asics).
13334fa1c6a6STao Zhou  * Returns the value in the register.
13344fa1c6a6STao Zhou  */
amdgpu_invalid_rreg64(struct amdgpu_device * adev,uint32_t reg)13354fa1c6a6STao Zhou static uint64_t amdgpu_invalid_rreg64(struct amdgpu_device *adev, uint32_t reg)
13364fa1c6a6STao Zhou {
13374fa1c6a6STao Zhou 	DRM_ERROR("Invalid callback to read 64 bit register 0x%04X\n", reg);
13384fa1c6a6STao Zhou 	BUG();
13394fa1c6a6STao Zhou 	return 0;
13404fa1c6a6STao Zhou }
13414fa1c6a6STao Zhou 
amdgpu_invalid_rreg64_ext(struct amdgpu_device * adev,uint64_t reg)1342a76b2870SCandice Li static uint64_t amdgpu_invalid_rreg64_ext(struct amdgpu_device *adev, uint64_t reg)
1343a76b2870SCandice Li {
1344a76b2870SCandice Li 	DRM_ERROR("Invalid callback to read register 0x%llX\n", reg);
1345a76b2870SCandice Li 	BUG();
1346a76b2870SCandice Li 	return 0;
1347a76b2870SCandice Li }
1348a76b2870SCandice Li 
13494fa1c6a6STao Zhou /**
13504fa1c6a6STao Zhou  * amdgpu_invalid_wreg64 - dummy reg write function
13514fa1c6a6STao Zhou  *
1352982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
13534fa1c6a6STao Zhou  * @reg: offset of register
13544fa1c6a6STao Zhou  * @v: value to write to the register
13554fa1c6a6STao Zhou  *
13564fa1c6a6STao Zhou  * Dummy register read function.  Used for register blocks
13574fa1c6a6STao Zhou  * that certain asics don't have (all asics).
13584fa1c6a6STao Zhou  */
amdgpu_invalid_wreg64(struct amdgpu_device * adev,uint32_t reg,uint64_t v)13594fa1c6a6STao Zhou static void amdgpu_invalid_wreg64(struct amdgpu_device *adev, uint32_t reg, uint64_t v)
13604fa1c6a6STao Zhou {
13614fa1c6a6STao Zhou 	DRM_ERROR("Invalid callback to write 64 bit register 0x%04X with 0x%08llX\n",
13624fa1c6a6STao Zhou 		  reg, v);
13634fa1c6a6STao Zhou 	BUG();
13644fa1c6a6STao Zhou }
13654fa1c6a6STao Zhou 
amdgpu_invalid_wreg64_ext(struct amdgpu_device * adev,uint64_t reg,uint64_t v)1366a76b2870SCandice Li static void amdgpu_invalid_wreg64_ext(struct amdgpu_device *adev, uint64_t reg, uint64_t v)
1367a76b2870SCandice Li {
1368a76b2870SCandice Li 	DRM_ERROR("Invalid callback to write 64 bit register 0x%llX with 0x%08llX\n",
1369a76b2870SCandice Li 		  reg, v);
1370a76b2870SCandice Li 	BUG();
1371a76b2870SCandice Li }
1372a76b2870SCandice Li 
13734fa1c6a6STao Zhou /**
1374d38ceaf9SAlex Deucher  * amdgpu_block_invalid_rreg - dummy reg read function
1375d38ceaf9SAlex Deucher  *
1376982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
1377d38ceaf9SAlex Deucher  * @block: offset of instance
1378d38ceaf9SAlex Deucher  * @reg: offset of register
1379d38ceaf9SAlex Deucher  *
1380d38ceaf9SAlex Deucher  * Dummy register read function.  Used for register blocks
1381d38ceaf9SAlex Deucher  * that certain asics don't have (all asics).
1382d38ceaf9SAlex Deucher  * Returns the value in the register.
1383d38ceaf9SAlex Deucher  */
amdgpu_block_invalid_rreg(struct amdgpu_device * adev,uint32_t block,uint32_t reg)1384d38ceaf9SAlex Deucher static uint32_t amdgpu_block_invalid_rreg(struct amdgpu_device *adev,
1385d38ceaf9SAlex Deucher 					  uint32_t block, uint32_t reg)
1386d38ceaf9SAlex Deucher {
1387d38ceaf9SAlex Deucher 	DRM_ERROR("Invalid callback to read register 0x%04X in block 0x%04X\n",
1388d38ceaf9SAlex Deucher 		  reg, block);
1389d38ceaf9SAlex Deucher 	BUG();
1390d38ceaf9SAlex Deucher 	return 0;
1391d38ceaf9SAlex Deucher }
1392d38ceaf9SAlex Deucher 
1393d38ceaf9SAlex Deucher /**
1394d38ceaf9SAlex Deucher  * amdgpu_block_invalid_wreg - dummy reg write function
1395d38ceaf9SAlex Deucher  *
1396982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
1397d38ceaf9SAlex Deucher  * @block: offset of instance
1398d38ceaf9SAlex Deucher  * @reg: offset of register
1399d38ceaf9SAlex Deucher  * @v: value to write to the register
1400d38ceaf9SAlex Deucher  *
1401d38ceaf9SAlex Deucher  * Dummy register read function.  Used for register blocks
1402d38ceaf9SAlex Deucher  * that certain asics don't have (all asics).
1403d38ceaf9SAlex Deucher  */
amdgpu_block_invalid_wreg(struct amdgpu_device * adev,uint32_t block,uint32_t reg,uint32_t v)1404d38ceaf9SAlex Deucher static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev,
1405d38ceaf9SAlex Deucher 				      uint32_t block,
1406d38ceaf9SAlex Deucher 				      uint32_t reg, uint32_t v)
1407d38ceaf9SAlex Deucher {
1408d38ceaf9SAlex Deucher 	DRM_ERROR("Invalid block callback to write register 0x%04X in block 0x%04X with 0x%08X\n",
1409d38ceaf9SAlex Deucher 		  reg, block, v);
1410d38ceaf9SAlex Deucher 	BUG();
1411d38ceaf9SAlex Deucher }
1412d38ceaf9SAlex Deucher 
amdgpu_device_get_vbios_flags(struct amdgpu_device * adev)14136e8ca38eSLijo Lazar static uint32_t amdgpu_device_get_vbios_flags(struct amdgpu_device *adev)
14146e8ca38eSLijo Lazar {
14156e8ca38eSLijo Lazar 	if (hweight32(adev->aid_mask) && (adev->flags & AMD_IS_APU))
14166e8ca38eSLijo Lazar 		return AMDGPU_VBIOS_SKIP;
14176e8ca38eSLijo Lazar 
1418cc0e91a7SLijo Lazar 	if (hweight32(adev->aid_mask) && amdgpu_passthrough(adev))
1419cc0e91a7SLijo Lazar 		return AMDGPU_VBIOS_OPTIONAL;
1420cc0e91a7SLijo Lazar 
14216e8ca38eSLijo Lazar 	return 0;
14226e8ca38eSLijo Lazar }
14236e8ca38eSLijo Lazar 
1424e3ecdffaSAlex Deucher /**
14254d2997abSAlex Deucher  * amdgpu_device_asic_init - Wrapper for atom asic_init
14264d2997abSAlex Deucher  *
1427982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
14284d2997abSAlex Deucher  *
14294d2997abSAlex Deucher  * Does any asic specific work and then calls atom asic init.
14304d2997abSAlex Deucher  */
amdgpu_device_asic_init(struct amdgpu_device * adev)14314d2997abSAlex Deucher static int amdgpu_device_asic_init(struct amdgpu_device *adev)
14324d2997abSAlex Deucher {
14336e8ca38eSLijo Lazar 	uint32_t flags;
14346e8ca38eSLijo Lazar 	bool optional;
14357656168aSLijo Lazar 	int ret;
14367656168aSLijo Lazar 
14374d2997abSAlex Deucher 	amdgpu_asic_pre_asic_init(adev);
14386e8ca38eSLijo Lazar 	flags = amdgpu_device_get_vbios_flags(adev);
14396e8ca38eSLijo Lazar 	optional = !!(flags & (AMDGPU_VBIOS_OPTIONAL | AMDGPU_VBIOS_SKIP));
14404d2997abSAlex Deucher 
14414e8303cfSLijo Lazar 	if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
14425f571c61SHawking Zhang 	    amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) ||
14430b58a55aSLe Ma 	    amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0) ||
14444e8303cfSLijo Lazar 	    amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 0)) {
14457656168aSLijo Lazar 		amdgpu_psp_wait_for_bootloader(adev);
14466e8ca38eSLijo Lazar 		if (optional && !adev->bios)
14476e8ca38eSLijo Lazar 			return 0;
14486e8ca38eSLijo Lazar 
14497656168aSLijo Lazar 		ret = amdgpu_atomfirmware_asic_init(adev, true);
14507656168aSLijo Lazar 		return ret;
14517656168aSLijo Lazar 	} else {
14526e8ca38eSLijo Lazar 		if (optional && !adev->bios)
14536e8ca38eSLijo Lazar 			return 0;
14546e8ca38eSLijo Lazar 
14554d2997abSAlex Deucher 		return amdgpu_atom_asic_init(adev->mode_info.atom_context);
14564d2997abSAlex Deucher 	}
14574d2997abSAlex Deucher 
14587656168aSLijo Lazar 	return 0;
14597656168aSLijo Lazar }
14607656168aSLijo Lazar 
14614d2997abSAlex Deucher /**
14627ccfd79fSChristian König  * amdgpu_device_mem_scratch_init - allocate the VRAM scratch page
1463e3ecdffaSAlex Deucher  *
1464982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
1465e3ecdffaSAlex Deucher  *
1466e3ecdffaSAlex Deucher  * Allocates a scratch page of VRAM for use by various things in the
1467e3ecdffaSAlex Deucher  * driver.
1468e3ecdffaSAlex Deucher  */
amdgpu_device_mem_scratch_init(struct amdgpu_device * adev)14697ccfd79fSChristian König static int amdgpu_device_mem_scratch_init(struct amdgpu_device *adev)
1470d38ceaf9SAlex Deucher {
14717ccfd79fSChristian König 	return amdgpu_bo_create_kernel(adev, AMDGPU_GPU_PAGE_SIZE, PAGE_SIZE,
14727ccfd79fSChristian König 				       AMDGPU_GEM_DOMAIN_VRAM |
14737ccfd79fSChristian König 				       AMDGPU_GEM_DOMAIN_GTT,
14747ccfd79fSChristian König 				       &adev->mem_scratch.robj,
14757ccfd79fSChristian König 				       &adev->mem_scratch.gpu_addr,
14767ccfd79fSChristian König 				       (void **)&adev->mem_scratch.ptr);
1477d38ceaf9SAlex Deucher }
1478d38ceaf9SAlex Deucher 
1479e3ecdffaSAlex Deucher /**
14807ccfd79fSChristian König  * amdgpu_device_mem_scratch_fini - Free the VRAM scratch page
1481e3ecdffaSAlex Deucher  *
1482982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
1483e3ecdffaSAlex Deucher  *
1484e3ecdffaSAlex Deucher  * Frees the VRAM scratch page.
1485e3ecdffaSAlex Deucher  */
amdgpu_device_mem_scratch_fini(struct amdgpu_device * adev)14867ccfd79fSChristian König static void amdgpu_device_mem_scratch_fini(struct amdgpu_device *adev)
1487d38ceaf9SAlex Deucher {
14887ccfd79fSChristian König 	amdgpu_bo_free_kernel(&adev->mem_scratch.robj, NULL, NULL);
1489d38ceaf9SAlex Deucher }
1490d38ceaf9SAlex Deucher 
1491d38ceaf9SAlex Deucher /**
14929c3f2b54SAlex Deucher  * amdgpu_device_program_register_sequence - program an array of registers.
1493d38ceaf9SAlex Deucher  *
1494d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
1495d38ceaf9SAlex Deucher  * @registers: pointer to the register array
1496d38ceaf9SAlex Deucher  * @array_size: size of the register array
1497d38ceaf9SAlex Deucher  *
1498b8920e1eSSrinivasan Shanmugam  * Programs an array or registers with and or masks.
1499d38ceaf9SAlex Deucher  * This is a helper for setting golden registers.
1500d38ceaf9SAlex Deucher  */
amdgpu_device_program_register_sequence(struct amdgpu_device * adev,const u32 * registers,const u32 array_size)15019c3f2b54SAlex Deucher void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
1502d38ceaf9SAlex Deucher 					     const u32 *registers,
1503d38ceaf9SAlex Deucher 					     const u32 array_size)
1504d38ceaf9SAlex Deucher {
1505d38ceaf9SAlex Deucher 	u32 tmp, reg, and_mask, or_mask;
1506d38ceaf9SAlex Deucher 	int i;
1507d38ceaf9SAlex Deucher 
1508d38ceaf9SAlex Deucher 	if (array_size % 3)
1509d38ceaf9SAlex Deucher 		return;
1510d38ceaf9SAlex Deucher 
1511d38ceaf9SAlex Deucher 	for (i = 0; i < array_size; i += 3) {
1512d38ceaf9SAlex Deucher 		reg = registers[i + 0];
1513d38ceaf9SAlex Deucher 		and_mask = registers[i + 1];
1514d38ceaf9SAlex Deucher 		or_mask = registers[i + 2];
1515d38ceaf9SAlex Deucher 
1516d38ceaf9SAlex Deucher 		if (and_mask == 0xffffffff) {
1517d38ceaf9SAlex Deucher 			tmp = or_mask;
1518d38ceaf9SAlex Deucher 		} else {
1519d38ceaf9SAlex Deucher 			tmp = RREG32(reg);
1520d38ceaf9SAlex Deucher 			tmp &= ~and_mask;
1521e0d07657SHawking Zhang 			if (adev->family >= AMDGPU_FAMILY_AI)
1522e0d07657SHawking Zhang 				tmp |= (or_mask & and_mask);
1523e0d07657SHawking Zhang 			else
1524d38ceaf9SAlex Deucher 				tmp |= or_mask;
1525d38ceaf9SAlex Deucher 		}
1526d38ceaf9SAlex Deucher 		WREG32(reg, tmp);
1527d38ceaf9SAlex Deucher 	}
1528d38ceaf9SAlex Deucher }
1529d38ceaf9SAlex Deucher 
1530e3ecdffaSAlex Deucher /**
1531e3ecdffaSAlex Deucher  * amdgpu_device_pci_config_reset - reset the GPU
1532e3ecdffaSAlex Deucher  *
1533e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
1534e3ecdffaSAlex Deucher  *
1535e3ecdffaSAlex Deucher  * Resets the GPU using the pci config reset sequence.
1536e3ecdffaSAlex Deucher  * Only applicable to asics prior to vega10.
1537e3ecdffaSAlex Deucher  */
amdgpu_device_pci_config_reset(struct amdgpu_device * adev)15388111c387SAlex Deucher void amdgpu_device_pci_config_reset(struct amdgpu_device *adev)
1539d38ceaf9SAlex Deucher {
1540d38ceaf9SAlex Deucher 	pci_write_config_dword(adev->pdev, 0x7c, AMDGPU_ASIC_RESET_DATA);
1541d38ceaf9SAlex Deucher }
1542d38ceaf9SAlex Deucher 
1543af484df8SAlex Deucher /**
1544af484df8SAlex Deucher  * amdgpu_device_pci_reset - reset the GPU using generic PCI means
1545af484df8SAlex Deucher  *
1546af484df8SAlex Deucher  * @adev: amdgpu_device pointer
1547af484df8SAlex Deucher  *
1548af484df8SAlex Deucher  * Resets the GPU using generic pci reset interfaces (FLR, SBR, etc.).
1549af484df8SAlex Deucher  */
amdgpu_device_pci_reset(struct amdgpu_device * adev)1550af484df8SAlex Deucher int amdgpu_device_pci_reset(struct amdgpu_device *adev)
1551af484df8SAlex Deucher {
1552af484df8SAlex Deucher 	return pci_reset_function(adev->pdev);
1553af484df8SAlex Deucher }
1554af484df8SAlex Deucher 
1555d38ceaf9SAlex Deucher /*
155606ec9070SAlex Deucher  * amdgpu_device_wb_*()
1557455a7bc2SAlex Xie  * Writeback is the method by which the GPU updates special pages in memory
1558ea81a173SAlex Xie  * with the status of certain GPU events (fences, ring pointers,etc.).
1559d38ceaf9SAlex Deucher  */
1560d38ceaf9SAlex Deucher 
1561d38ceaf9SAlex Deucher /**
156206ec9070SAlex Deucher  * amdgpu_device_wb_fini - Disable Writeback and free memory
1563d38ceaf9SAlex Deucher  *
1564d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
1565d38ceaf9SAlex Deucher  *
1566d38ceaf9SAlex Deucher  * Disables Writeback and frees the Writeback memory (all asics).
1567d38ceaf9SAlex Deucher  * Used at driver shutdown.
1568d38ceaf9SAlex Deucher  */
amdgpu_device_wb_fini(struct amdgpu_device * adev)156906ec9070SAlex Deucher static void amdgpu_device_wb_fini(struct amdgpu_device *adev)
1570d38ceaf9SAlex Deucher {
1571d38ceaf9SAlex Deucher 	if (adev->wb.wb_obj) {
1572a76ed485SAlex Deucher 		amdgpu_bo_free_kernel(&adev->wb.wb_obj,
1573a76ed485SAlex Deucher 				      &adev->wb.gpu_addr,
1574a76ed485SAlex Deucher 				      (void **)&adev->wb.wb);
1575d38ceaf9SAlex Deucher 		adev->wb.wb_obj = NULL;
1576d38ceaf9SAlex Deucher 	}
1577d38ceaf9SAlex Deucher }
1578d38ceaf9SAlex Deucher 
1579d38ceaf9SAlex Deucher /**
158006ec9070SAlex Deucher  * amdgpu_device_wb_init - Init Writeback driver info and allocate memory
1581d38ceaf9SAlex Deucher  *
1582d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
1583d38ceaf9SAlex Deucher  *
1584455a7bc2SAlex Xie  * Initializes writeback and allocates writeback memory (all asics).
1585d38ceaf9SAlex Deucher  * Used at driver startup.
1586d38ceaf9SAlex Deucher  * Returns 0 on success or an -error on failure.
1587d38ceaf9SAlex Deucher  */
amdgpu_device_wb_init(struct amdgpu_device * adev)158806ec9070SAlex Deucher static int amdgpu_device_wb_init(struct amdgpu_device *adev)
1589d38ceaf9SAlex Deucher {
1590d38ceaf9SAlex Deucher 	int r;
1591d38ceaf9SAlex Deucher 
1592d38ceaf9SAlex Deucher 	if (adev->wb.wb_obj == NULL) {
159397407b63SAlex Deucher 		/* AMDGPU_MAX_WB * sizeof(uint32_t) * 8 = AMDGPU_MAX_WB 256bit slots */
159497407b63SAlex Deucher 		r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t) * 8,
1595a76ed485SAlex Deucher 					    PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
1596a76ed485SAlex Deucher 					    &adev->wb.wb_obj, &adev->wb.gpu_addr,
1597a76ed485SAlex Deucher 					    (void **)&adev->wb.wb);
1598d38ceaf9SAlex Deucher 		if (r) {
1599d38ceaf9SAlex Deucher 			dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
1600d38ceaf9SAlex Deucher 			return r;
1601d38ceaf9SAlex Deucher 		}
1602d38ceaf9SAlex Deucher 
1603d38ceaf9SAlex Deucher 		adev->wb.num_wb = AMDGPU_MAX_WB;
1604d38ceaf9SAlex Deucher 		memset(&adev->wb.used, 0, sizeof(adev->wb.used));
1605d38ceaf9SAlex Deucher 
1606d38ceaf9SAlex Deucher 		/* clear wb memory */
160773469585SMonk Liu 		memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);
1608d38ceaf9SAlex Deucher 	}
1609d38ceaf9SAlex Deucher 
1610d38ceaf9SAlex Deucher 	return 0;
1611d38ceaf9SAlex Deucher }
1612d38ceaf9SAlex Deucher 
1613d38ceaf9SAlex Deucher /**
1614131b4b36SAlex Deucher  * amdgpu_device_wb_get - Allocate a wb entry
1615d38ceaf9SAlex Deucher  *
1616d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
1617d38ceaf9SAlex Deucher  * @wb: wb index
1618d38ceaf9SAlex Deucher  *
1619d38ceaf9SAlex Deucher  * Allocate a wb slot for use by the driver (all asics).
1620d38ceaf9SAlex Deucher  * Returns 0 on success or -EINVAL on failure.
1621d38ceaf9SAlex Deucher  */
amdgpu_device_wb_get(struct amdgpu_device * adev,u32 * wb)1622131b4b36SAlex Deucher int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
1623d38ceaf9SAlex Deucher {
1624497d7ceeSAlex Deucher 	unsigned long flags, offset;
162597407b63SAlex Deucher 
1626497d7ceeSAlex Deucher 	spin_lock_irqsave(&adev->wb.lock, flags);
1627497d7ceeSAlex Deucher 	offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
1628d38ceaf9SAlex Deucher 	if (offset < adev->wb.num_wb) {
1629d38ceaf9SAlex Deucher 		__set_bit(offset, adev->wb.used);
1630497d7ceeSAlex Deucher 		spin_unlock_irqrestore(&adev->wb.lock, flags);
163163ae07caSMonk Liu 		*wb = offset << 3; /* convert to dw offset */
16320915fdbcSMonk Liu 		return 0;
16330915fdbcSMonk Liu 	} else {
1634497d7ceeSAlex Deucher 		spin_unlock_irqrestore(&adev->wb.lock, flags);
16350915fdbcSMonk Liu 		return -EINVAL;
16360915fdbcSMonk Liu 	}
16370915fdbcSMonk Liu }
16380915fdbcSMonk Liu 
16397014285aSKen Wang /**
1640131b4b36SAlex Deucher  * amdgpu_device_wb_free - Free a wb entry
1641d38ceaf9SAlex Deucher  *
1642d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
1643d38ceaf9SAlex Deucher  * @wb: wb index
1644d38ceaf9SAlex Deucher  *
1645d38ceaf9SAlex Deucher  * Free a wb slot allocated for use by the driver (all asics)
1646d38ceaf9SAlex Deucher  */
amdgpu_device_wb_free(struct amdgpu_device * adev,u32 wb)1647131b4b36SAlex Deucher void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
1648d38ceaf9SAlex Deucher {
1649497d7ceeSAlex Deucher 	unsigned long flags;
1650497d7ceeSAlex Deucher 
165173469585SMonk Liu 	wb >>= 3;
1652497d7ceeSAlex Deucher 	spin_lock_irqsave(&adev->wb.lock, flags);
1653d38ceaf9SAlex Deucher 	if (wb < adev->wb.num_wb)
165473469585SMonk Liu 		__clear_bit(wb, adev->wb.used);
1655497d7ceeSAlex Deucher 	spin_unlock_irqrestore(&adev->wb.lock, flags);
1656d38ceaf9SAlex Deucher }
1657d38ceaf9SAlex Deucher 
1658d38ceaf9SAlex Deucher /**
1659d6895ad3SChristian König  * amdgpu_device_resize_fb_bar - try to resize FB BAR
1660d6895ad3SChristian König  *
1661d6895ad3SChristian König  * @adev: amdgpu_device pointer
1662d6895ad3SChristian König  *
1663d6895ad3SChristian König  * Try to resize FB BAR to make all VRAM CPU accessible. We try very hard not
1664d6895ad3SChristian König  * to fail, but if any of the BARs is not accessible after the size we abort
1665d6895ad3SChristian König  * driver loading by returning -ENODEV.
1666d6895ad3SChristian König  */
amdgpu_device_resize_fb_bar(struct amdgpu_device * adev)1667d6895ad3SChristian König int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
1668d6895ad3SChristian König {
1669453f617aSNirmoy Das 	int rbar_size = pci_rebar_bytes_to_size(adev->gmc.real_vram_size);
167031b8adabSChristian König 	struct pci_bus *root;
167131b8adabSChristian König 	struct resource *res;
1672b8920e1eSSrinivasan Shanmugam 	unsigned int i;
1673d6895ad3SChristian König 	u16 cmd;
1674d6895ad3SChristian König 	int r;
1675d6895ad3SChristian König 
1676822130b5SArnd Bergmann 	if (!IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT))
1677822130b5SArnd Bergmann 		return 0;
1678822130b5SArnd Bergmann 
16790c03b912Spding 	/* Bypass for VF */
16800c03b912Spding 	if (amdgpu_sriov_vf(adev))
16810c03b912Spding 		return 0;
16820c03b912Spding 
16835235053fSAlex Deucher 	/* resizing on Dell G5 SE platforms causes problems with runtime pm */
16845235053fSAlex Deucher 	if ((amdgpu_runtime_pm != 0) &&
16855235053fSAlex Deucher 	    adev->pdev->vendor == PCI_VENDOR_ID_ATI &&
16865235053fSAlex Deucher 	    adev->pdev->device == 0x731f &&
16875235053fSAlex Deucher 	    adev->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
16885235053fSAlex Deucher 		return 0;
16895235053fSAlex Deucher 
1690e372baebSMa Jun 	/* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */
1691e372baebSMa Jun 	if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR))
1692e372baebSMa Jun 		DRM_WARN("System can't access extended configuration space, please check!!\n");
1693e372baebSMa Jun 
1694b7221f2bSAlex Deucher 	/* skip if the bios has already enabled large BAR */
1695b7221f2bSAlex Deucher 	if (adev->gmc.real_vram_size &&
1696b7221f2bSAlex Deucher 	    (pci_resource_len(adev->pdev, 0) >= adev->gmc.real_vram_size))
1697b7221f2bSAlex Deucher 		return 0;
1698b7221f2bSAlex Deucher 
169931b8adabSChristian König 	/* Check if the root BUS has 64bit memory resources */
170031b8adabSChristian König 	root = adev->pdev->bus;
170131b8adabSChristian König 	while (root->parent)
170231b8adabSChristian König 		root = root->parent;
170331b8adabSChristian König 
170431b8adabSChristian König 	pci_bus_for_each_resource(root, res, i) {
17050ebb7c54SChristian König 		if (res && res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) &&
170631b8adabSChristian König 		    res->start > 0x100000000ull)
170731b8adabSChristian König 			break;
170831b8adabSChristian König 	}
170931b8adabSChristian König 
171031b8adabSChristian König 	/* Trying to resize is pointless without a root hub window above 4GB */
171131b8adabSChristian König 	if (!res)
171231b8adabSChristian König 		return 0;
171331b8adabSChristian König 
1714453f617aSNirmoy Das 	/* Limit the BAR size to what is available */
1715453f617aSNirmoy Das 	rbar_size = min(fls(pci_rebar_get_possible_sizes(adev->pdev, 0)) - 1,
1716453f617aSNirmoy Das 			rbar_size);
1717453f617aSNirmoy Das 
1718d6895ad3SChristian König 	/* Disable memory decoding while we change the BAR addresses and size */
1719d6895ad3SChristian König 	pci_read_config_word(adev->pdev, PCI_COMMAND, &cmd);
1720d6895ad3SChristian König 	pci_write_config_word(adev->pdev, PCI_COMMAND,
1721d6895ad3SChristian König 			      cmd & ~PCI_COMMAND_MEMORY);
1722d6895ad3SChristian König 
1723d6895ad3SChristian König 	/* Free the VRAM and doorbell BAR, we most likely need to move both. */
172443c064dbSShashank Sharma 	amdgpu_doorbell_fini(adev);
1725d6895ad3SChristian König 	if (adev->asic_type >= CHIP_BONAIRE)
1726d6895ad3SChristian König 		pci_release_resource(adev->pdev, 2);
1727d6895ad3SChristian König 
1728d6895ad3SChristian König 	pci_release_resource(adev->pdev, 0);
1729d6895ad3SChristian König 
1730d6895ad3SChristian König 	r = pci_resize_resource(adev->pdev, 0, rbar_size);
1731d6895ad3SChristian König 	if (r == -ENOSPC)
1732d6895ad3SChristian König 		DRM_INFO("Not enough PCI address space for a large BAR.");
1733d6895ad3SChristian König 	else if (r && r != -ENOTSUPP)
1734d6895ad3SChristian König 		DRM_ERROR("Problem resizing BAR0 (%d).", r);
1735d6895ad3SChristian König 
1736d6895ad3SChristian König 	pci_assign_unassigned_bus_resources(adev->pdev->bus);
1737d6895ad3SChristian König 
1738d6895ad3SChristian König 	/* When the doorbell or fb BAR isn't available we have no chance of
1739d6895ad3SChristian König 	 * using the device.
1740d6895ad3SChristian König 	 */
174143c064dbSShashank Sharma 	r = amdgpu_doorbell_init(adev);
1742d6895ad3SChristian König 	if (r || (pci_resource_flags(adev->pdev, 0) & IORESOURCE_UNSET))
1743d6895ad3SChristian König 		return -ENODEV;
1744d6895ad3SChristian König 
1745d6895ad3SChristian König 	pci_write_config_word(adev->pdev, PCI_COMMAND, cmd);
1746d6895ad3SChristian König 
1747d6895ad3SChristian König 	return 0;
1748d6895ad3SChristian König }
1749a05502e5SHorace Chen 
1750a05502e5SHorace Chen /*
1751d38ceaf9SAlex Deucher  * GPU helpers function.
1752d38ceaf9SAlex Deucher  */
1753d38ceaf9SAlex Deucher /**
175439c640c0SAlex Deucher  * amdgpu_device_need_post - check if the hw need post or not
1755d38ceaf9SAlex Deucher  *
1756d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
1757d38ceaf9SAlex Deucher  *
1758c836fec5SJim Qu  * Check if the asic has been initialized (all asics) at driver startup
1759c836fec5SJim Qu  * or post is needed if  hw reset is performed.
1760c836fec5SJim Qu  * Returns true if need or false if not.
1761d38ceaf9SAlex Deucher  */
amdgpu_device_need_post(struct amdgpu_device * adev)176239c640c0SAlex Deucher bool amdgpu_device_need_post(struct amdgpu_device *adev)
1763d38ceaf9SAlex Deucher {
17647e0aa706SLijo Lazar 	uint32_t reg, flags;
1765d38ceaf9SAlex Deucher 
1766bec86378SMonk Liu 	if (amdgpu_sriov_vf(adev))
1767bec86378SMonk Liu 		return false;
1768bec86378SMonk Liu 
17697e0aa706SLijo Lazar 	flags = amdgpu_device_get_vbios_flags(adev);
17707e0aa706SLijo Lazar 	if (flags & AMDGPU_VBIOS_SKIP)
17719535a86aSShiwu Zhang 		return false;
17726e8ca38eSLijo Lazar 	if ((flags & AMDGPU_VBIOS_OPTIONAL) && !adev->bios)
17739535a86aSShiwu Zhang 		return false;
17749535a86aSShiwu Zhang 
1775bec86378SMonk Liu 	if (amdgpu_passthrough(adev)) {
17761da2c326SMonk Liu 		/* for FIJI: In whole GPU pass-through virtualization case, after VM reboot
17771da2c326SMonk Liu 		 * some old smc fw still need driver do vPost otherwise gpu hang, while
17781da2c326SMonk Liu 		 * those smc fw version above 22.15 doesn't have this flaw, so we force
17791da2c326SMonk Liu 		 * vpost executed for smc version below 22.15
1780bec86378SMonk Liu 		 */
1781bec86378SMonk Liu 		if (adev->asic_type == CHIP_FIJI) {
1782bec86378SMonk Liu 			int err;
1783bec86378SMonk Liu 			uint32_t fw_ver;
1784b8920e1eSSrinivasan Shanmugam 
1785bec86378SMonk Liu 			err = request_firmware(&adev->pm.fw, "amdgpu/fiji_smc.bin", adev->dev);
1786a567db80SRandy Dunlap 			/* force vPost if error occurred */
1787bec86378SMonk Liu 			if (err)
1788bec86378SMonk Liu 				return true;
1789bec86378SMonk Liu 
1790bec86378SMonk Liu 			fw_ver = *((uint32_t *)adev->pm.fw->data + 69);
17918a44fdd3SSrinivasan Shanmugam 			release_firmware(adev->pm.fw);
17921da2c326SMonk Liu 			if (fw_ver < 0x00160e00)
1793bec86378SMonk Liu 				return true;
1794bec86378SMonk Liu 		}
17951da2c326SMonk Liu 	}
179691fe77ebSpding 
1797e3c1b071Sshaoyunl 	/* Don't post if we need to reset whole hive on init */
17985839d27dSLijo Lazar 	if (adev->init_lvl->level == AMDGPU_INIT_LEVEL_MINIMAL_XGMI)
1799e3c1b071Sshaoyunl 		return false;
1800e3c1b071Sshaoyunl 
180191fe77ebSpding 	if (adev->has_hw_reset) {
180291fe77ebSpding 		adev->has_hw_reset = false;
180391fe77ebSpding 		return true;
180491fe77ebSpding 	}
180591fe77ebSpding 
180691fe77ebSpding 	/* bios scratch used on CIK+ */
180791fe77ebSpding 	if (adev->asic_type >= CHIP_BONAIRE)
180891fe77ebSpding 		return amdgpu_atombios_scratch_need_asic_init(adev);
180991fe77ebSpding 
181091fe77ebSpding 	/* check MEM_SIZE for older asics */
181191fe77ebSpding 	reg = amdgpu_asic_get_config_memsize(adev);
181291fe77ebSpding 
181391fe77ebSpding 	if ((reg != 0) && (reg != 0xffffffff))
181491fe77ebSpding 		return false;
181591fe77ebSpding 
181691fe77ebSpding 	return true;
18171da2c326SMonk Liu }
1818bec86378SMonk Liu 
18195d1eb4c4SMario Limonciello /*
1820bb0f8429SMario Limonciello  * Check whether seamless boot is supported.
1821bb0f8429SMario Limonciello  *
18227f4ce7b5SMario Limonciello  * So far we only support seamless boot on DCE 3.0 or later.
18237f4ce7b5SMario Limonciello  * If users report that it works on older ASICS as well, we may
18247f4ce7b5SMario Limonciello  * loosen this.
1825bb0f8429SMario Limonciello  */
amdgpu_device_seamless_boot_supported(struct amdgpu_device * adev)1826bb0f8429SMario Limonciello bool amdgpu_device_seamless_boot_supported(struct amdgpu_device *adev)
1827bb0f8429SMario Limonciello {
18285dc270d3SMario Limonciello 	switch (amdgpu_seamless) {
18295dc270d3SMario Limonciello 	case -1:
18305dc270d3SMario Limonciello 		break;
18315dc270d3SMario Limonciello 	case 1:
18325dc270d3SMario Limonciello 		return true;
18335dc270d3SMario Limonciello 	case 0:
18345dc270d3SMario Limonciello 		return false;
18355dc270d3SMario Limonciello 	default:
18365dc270d3SMario Limonciello 		DRM_ERROR("Invalid value for amdgpu.seamless: %d\n",
18375dc270d3SMario Limonciello 			  amdgpu_seamless);
18385dc270d3SMario Limonciello 		return false;
18395dc270d3SMario Limonciello 	}
18405dc270d3SMario Limonciello 
18413657a1d5SMario Limonciello 	if (!(adev->flags & AMD_IS_APU))
18423657a1d5SMario Limonciello 		return false;
18433657a1d5SMario Limonciello 
18445dc270d3SMario Limonciello 	if (adev->mman.keep_stolen_vga_memory)
18455dc270d3SMario Limonciello 		return false;
18465dc270d3SMario Limonciello 
1847ed342a2eSLijo Lazar 	return amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0);
1848bb0f8429SMario Limonciello }
1849bb0f8429SMario Limonciello 
1850bb0f8429SMario Limonciello /*
18512757a848SMario Limonciello  * Intel hosts such as Rocket Lake, Alder Lake, Raptor Lake and Sapphire Rapids
18522757a848SMario Limonciello  * don't support dynamic speed switching. Until we have confirmation from Intel
18532757a848SMario Limonciello  * that a specific host supports it, it's safer that we keep it disabled for all.
18545d1eb4c4SMario Limonciello  *
18555d1eb4c4SMario Limonciello  * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
18565d1eb4c4SMario Limonciello  * https://gitlab.freedesktop.org/drm/amd/-/issues/2663
18575d1eb4c4SMario Limonciello  */
amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device * adev)1858d9b3a066SMario Limonciello static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev)
18595d1eb4c4SMario Limonciello {
18605d1eb4c4SMario Limonciello #if IS_ENABLED(CONFIG_X86)
18615d1eb4c4SMario Limonciello 	struct cpuinfo_x86 *c = &cpu_data(0);
18625d1eb4c4SMario Limonciello 
1863d9b3a066SMario Limonciello 	/* eGPU change speeds based on USB4 fabric conditions */
1864d9b3a066SMario Limonciello 	if (dev_is_removable(adev->dev))
1865d9b3a066SMario Limonciello 		return true;
1866d9b3a066SMario Limonciello 
18675d1eb4c4SMario Limonciello 	if (c->x86_vendor == X86_VENDOR_INTEL)
18685d1eb4c4SMario Limonciello 		return false;
18695d1eb4c4SMario Limonciello #endif
18705d1eb4c4SMario Limonciello 	return true;
18715d1eb4c4SMario Limonciello }
18725d1eb4c4SMario Limonciello 
18730ab5d711SMario Limonciello /**
18740ab5d711SMario Limonciello  * amdgpu_device_should_use_aspm - check if the device should program ASPM
18750ab5d711SMario Limonciello  *
18760ab5d711SMario Limonciello  * @adev: amdgpu_device pointer
18770ab5d711SMario Limonciello  *
18780ab5d711SMario Limonciello  * Confirm whether the module parameter and pcie bridge agree that ASPM should
18790ab5d711SMario Limonciello  * be set for this device.
18800ab5d711SMario Limonciello  *
18810ab5d711SMario Limonciello  * Returns true if it should be used or false if not.
18820ab5d711SMario Limonciello  */
amdgpu_device_should_use_aspm(struct amdgpu_device * adev)18830ab5d711SMario Limonciello bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
18840ab5d711SMario Limonciello {
18850ab5d711SMario Limonciello 	switch (amdgpu_aspm) {
18860ab5d711SMario Limonciello 	case -1:
18870ab5d711SMario Limonciello 		break;
18880ab5d711SMario Limonciello 	case 0:
18890ab5d711SMario Limonciello 		return false;
18900ab5d711SMario Limonciello 	case 1:
18910ab5d711SMario Limonciello 		return true;
18920ab5d711SMario Limonciello 	default:
18930ab5d711SMario Limonciello 		return false;
18940ab5d711SMario Limonciello 	}
18951a6513deSMario Limonciello 	if (adev->flags & AMD_IS_APU)
18961a6513deSMario Limonciello 		return false;
18972757a848SMario Limonciello 	if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK))
18982757a848SMario Limonciello 		return false;
18990ab5d711SMario Limonciello 	return pcie_aspm_enabled(adev->pdev);
19000ab5d711SMario Limonciello }
19010ab5d711SMario Limonciello 
1902d38ceaf9SAlex Deucher /* if we get transitioned to only one device, take VGA back */
1903d38ceaf9SAlex Deucher /**
190406ec9070SAlex Deucher  * amdgpu_device_vga_set_decode - enable/disable vga decode
1905d38ceaf9SAlex Deucher  *
1906bf44e8ceSChristoph Hellwig  * @pdev: PCI device pointer
1907d38ceaf9SAlex Deucher  * @state: enable/disable vga decode
1908d38ceaf9SAlex Deucher  *
1909d38ceaf9SAlex Deucher  * Enable/disable vga decode (all asics).
1910d38ceaf9SAlex Deucher  * Returns VGA resource flags.
1911d38ceaf9SAlex Deucher  */
amdgpu_device_vga_set_decode(struct pci_dev * pdev,bool state)1912bf44e8ceSChristoph Hellwig static unsigned int amdgpu_device_vga_set_decode(struct pci_dev *pdev,
1913bf44e8ceSChristoph Hellwig 		bool state)
1914d38ceaf9SAlex Deucher {
1915bf44e8ceSChristoph Hellwig 	struct amdgpu_device *adev = drm_to_adev(pci_get_drvdata(pdev));
1916b8920e1eSSrinivasan Shanmugam 
1917d38ceaf9SAlex Deucher 	amdgpu_asic_set_vga_state(adev, state);
1918d38ceaf9SAlex Deucher 	if (state)
1919d38ceaf9SAlex Deucher 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
1920d38ceaf9SAlex Deucher 		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
1921d38ceaf9SAlex Deucher 	else
1922d38ceaf9SAlex Deucher 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
1923d38ceaf9SAlex Deucher }
1924d38ceaf9SAlex Deucher 
1925e3ecdffaSAlex Deucher /**
1926e3ecdffaSAlex Deucher  * amdgpu_device_check_block_size - validate the vm block size
1927e3ecdffaSAlex Deucher  *
1928e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
1929e3ecdffaSAlex Deucher  *
1930e3ecdffaSAlex Deucher  * Validates the vm block size specified via module parameter.
1931e3ecdffaSAlex Deucher  * The vm block size defines number of bits in page table versus page directory,
1932e3ecdffaSAlex Deucher  * a page is 4KB so we have 12 bits offset, minimum 9 bits in the
1933e3ecdffaSAlex Deucher  * page table and the remaining bits are in the page directory.
1934e3ecdffaSAlex Deucher  */
amdgpu_device_check_block_size(struct amdgpu_device * adev)193506ec9070SAlex Deucher static void amdgpu_device_check_block_size(struct amdgpu_device *adev)
1936a1adf8beSChunming Zhou {
1937a1adf8beSChunming Zhou 	/* defines number of bits in page table versus page directory,
1938a1adf8beSChunming Zhou 	 * a page is 4KB so we have 12 bits offset, minimum 9 bits in the
1939b8920e1eSSrinivasan Shanmugam 	 * page table and the remaining bits are in the page directory
1940b8920e1eSSrinivasan Shanmugam 	 */
1941bab4fee7SJunwei Zhang 	if (amdgpu_vm_block_size == -1)
1942bab4fee7SJunwei Zhang 		return;
1943a1adf8beSChunming Zhou 
1944bab4fee7SJunwei Zhang 	if (amdgpu_vm_block_size < 9) {
1945a1adf8beSChunming Zhou 		dev_warn(adev->dev, "VM page table size (%d) too small\n",
1946a1adf8beSChunming Zhou 			 amdgpu_vm_block_size);
1947bab4fee7SJunwei Zhang 		amdgpu_vm_block_size = -1;
1948a1adf8beSChunming Zhou 	}
194997489129SChristian König }
1950a1adf8beSChunming Zhou 
1951e3ecdffaSAlex Deucher /**
1952e3ecdffaSAlex Deucher  * amdgpu_device_check_vm_size - validate the vm size
1953e3ecdffaSAlex Deucher  *
1954e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
1955e3ecdffaSAlex Deucher  *
1956e3ecdffaSAlex Deucher  * Validates the vm size in GB specified via module parameter.
1957e3ecdffaSAlex Deucher  * The VM size is the size of the GPU virtual memory space in GB.
1958e3ecdffaSAlex Deucher  */
amdgpu_device_check_vm_size(struct amdgpu_device * adev)195906ec9070SAlex Deucher static void amdgpu_device_check_vm_size(struct amdgpu_device *adev)
196083ca145dSZhang, Jerry {
196164dab074SAlex Deucher 	/* no need to check the default value */
196264dab074SAlex Deucher 	if (amdgpu_vm_size == -1)
196364dab074SAlex Deucher 		return;
196464dab074SAlex Deucher 
196583ca145dSZhang, Jerry 	if (amdgpu_vm_size < 1) {
196683ca145dSZhang, Jerry 		dev_warn(adev->dev, "VM size (%d) too small, min is 1GB\n",
196783ca145dSZhang, Jerry 			 amdgpu_vm_size);
1968bab4fee7SJunwei Zhang 		amdgpu_vm_size = -1;
196983ca145dSZhang, Jerry 	}
1970f3368128SChristian König }
197183ca145dSZhang, Jerry 
amdgpu_device_check_smu_prv_buffer_size(struct amdgpu_device * adev)19727951e376SRex Zhu static void amdgpu_device_check_smu_prv_buffer_size(struct amdgpu_device *adev)
19737951e376SRex Zhu {
19747951e376SRex Zhu 	struct sysinfo si;
1975a9d4fe2fSNirmoy Das 	bool is_os_64 = (sizeof(void *) == 8);
19767951e376SRex Zhu 	uint64_t total_memory;
19777951e376SRex Zhu 	uint64_t dram_size_seven_GB = 0x1B8000000;
19787951e376SRex Zhu 	uint64_t dram_size_three_GB = 0xB8000000;
19797951e376SRex Zhu 
19807951e376SRex Zhu 	if (amdgpu_smu_memory_pool_size == 0)
19817951e376SRex Zhu 		return;
19827951e376SRex Zhu 
19837951e376SRex Zhu 	if (!is_os_64) {
19847951e376SRex Zhu 		DRM_WARN("Not 64-bit OS, feature not supported\n");
19857951e376SRex Zhu 		goto def_value;
19867951e376SRex Zhu 	}
19877951e376SRex Zhu 	si_meminfo(&si);
19887951e376SRex Zhu 	total_memory = (uint64_t)si.totalram * si.mem_unit;
19897951e376SRex Zhu 
19907951e376SRex Zhu 	if ((amdgpu_smu_memory_pool_size == 1) ||
19917951e376SRex Zhu 		(amdgpu_smu_memory_pool_size == 2)) {
19927951e376SRex Zhu 		if (total_memory < dram_size_three_GB)
19937951e376SRex Zhu 			goto def_value1;
19947951e376SRex Zhu 	} else if ((amdgpu_smu_memory_pool_size == 4) ||
19957951e376SRex Zhu 		(amdgpu_smu_memory_pool_size == 8)) {
19967951e376SRex Zhu 		if (total_memory < dram_size_seven_GB)
19977951e376SRex Zhu 			goto def_value1;
19987951e376SRex Zhu 	} else {
19997951e376SRex Zhu 		DRM_WARN("Smu memory pool size not supported\n");
20007951e376SRex Zhu 		goto def_value;
20017951e376SRex Zhu 	}
20027951e376SRex Zhu 	adev->pm.smu_prv_buffer_size = amdgpu_smu_memory_pool_size << 28;
20037951e376SRex Zhu 
20047951e376SRex Zhu 	return;
20057951e376SRex Zhu 
20067951e376SRex Zhu def_value1:
20077951e376SRex Zhu 	DRM_WARN("No enough system memory\n");
20087951e376SRex Zhu def_value:
20097951e376SRex Zhu 	adev->pm.smu_prv_buffer_size = 0;
20107951e376SRex Zhu }
20117951e376SRex Zhu 
amdgpu_device_init_apu_flags(struct amdgpu_device * adev)20129f6a7857SHuang Rui static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev)
20139f6a7857SHuang Rui {
20149f6a7857SHuang Rui 	if (!(adev->flags & AMD_IS_APU) ||
20159f6a7857SHuang Rui 	    adev->asic_type < CHIP_RAVEN)
20169f6a7857SHuang Rui 		return 0;
20179f6a7857SHuang Rui 
20189f6a7857SHuang Rui 	switch (adev->asic_type) {
20199f6a7857SHuang Rui 	case CHIP_RAVEN:
20209f6a7857SHuang Rui 		if (adev->pdev->device == 0x15dd)
20219f6a7857SHuang Rui 			adev->apu_flags |= AMD_APU_IS_RAVEN;
20229f6a7857SHuang Rui 		if (adev->pdev->device == 0x15d8)
20239f6a7857SHuang Rui 			adev->apu_flags |= AMD_APU_IS_PICASSO;
20249f6a7857SHuang Rui 		break;
20259f6a7857SHuang Rui 	case CHIP_RENOIR:
20269f6a7857SHuang Rui 		if ((adev->pdev->device == 0x1636) ||
20279f6a7857SHuang Rui 		    (adev->pdev->device == 0x164c))
20289f6a7857SHuang Rui 			adev->apu_flags |= AMD_APU_IS_RENOIR;
20299f6a7857SHuang Rui 		else
20309f6a7857SHuang Rui 			adev->apu_flags |= AMD_APU_IS_GREEN_SARDINE;
20319f6a7857SHuang Rui 		break;
20329f6a7857SHuang Rui 	case CHIP_VANGOGH:
20339f6a7857SHuang Rui 		adev->apu_flags |= AMD_APU_IS_VANGOGH;
20349f6a7857SHuang Rui 		break;
20359f6a7857SHuang Rui 	case CHIP_YELLOW_CARP:
20369f6a7857SHuang Rui 		break;
2037d0f56dc2STao Zhou 	case CHIP_CYAN_SKILLFISH:
2038dfcc3e8cSAlex Deucher 		if ((adev->pdev->device == 0x13FE) ||
2039dfcc3e8cSAlex Deucher 		    (adev->pdev->device == 0x143F))
2040d0f56dc2STao Zhou 			adev->apu_flags |= AMD_APU_IS_CYAN_SKILLFISH2;
2041d0f56dc2STao Zhou 		break;
20429f6a7857SHuang Rui 	default:
20434eaf21b7SPrike Liang 		break;
20449f6a7857SHuang Rui 	}
20459f6a7857SHuang Rui 
20469f6a7857SHuang Rui 	return 0;
20479f6a7857SHuang Rui }
20489f6a7857SHuang Rui 
2049d38ceaf9SAlex Deucher /**
205006ec9070SAlex Deucher  * amdgpu_device_check_arguments - validate module params
2051d38ceaf9SAlex Deucher  *
2052d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
2053d38ceaf9SAlex Deucher  *
2054d38ceaf9SAlex Deucher  * Validates certain module parameters and updates
2055d38ceaf9SAlex Deucher  * the associated values used by the driver (all asics).
2056d38ceaf9SAlex Deucher  */
amdgpu_device_check_arguments(struct amdgpu_device * adev)2057912dfc84SEvan Quan static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
2058d38ceaf9SAlex Deucher {
205996595204SSrinivasan Shanmugam 	int i;
206096595204SSrinivasan Shanmugam 
20615b011235SChunming Zhou 	if (amdgpu_sched_jobs < 4) {
20625b011235SChunming Zhou 		dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n",
20635b011235SChunming Zhou 			 amdgpu_sched_jobs);
20645b011235SChunming Zhou 		amdgpu_sched_jobs = 4;
206576117507SAlex Deucher 	} else if (!is_power_of_2(amdgpu_sched_jobs)) {
20665b011235SChunming Zhou 		dev_warn(adev->dev, "sched jobs (%d) must be a power of 2\n",
20675b011235SChunming Zhou 			 amdgpu_sched_jobs);
20685b011235SChunming Zhou 		amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs);
20695b011235SChunming Zhou 	}
2070d38ceaf9SAlex Deucher 
207183e74db6SAlex Deucher 	if (amdgpu_gart_size != -1 && amdgpu_gart_size < 32) {
2072f9321cc4SChristian König 		/* gart size must be greater or equal to 32M */
2073d38ceaf9SAlex Deucher 		dev_warn(adev->dev, "gart size (%d) too small\n",
2074d38ceaf9SAlex Deucher 			 amdgpu_gart_size);
207583e74db6SAlex Deucher 		amdgpu_gart_size = -1;
2076d38ceaf9SAlex Deucher 	}
2077d38ceaf9SAlex Deucher 
207836d38372SChristian König 	if (amdgpu_gtt_size != -1 && amdgpu_gtt_size < 32) {
207936d38372SChristian König 		/* gtt size must be greater or equal to 32M */
208036d38372SChristian König 		dev_warn(adev->dev, "gtt size (%d) too small\n",
208136d38372SChristian König 				 amdgpu_gtt_size);
208236d38372SChristian König 		amdgpu_gtt_size = -1;
2083d38ceaf9SAlex Deucher 	}
2084d38ceaf9SAlex Deucher 
2085d07f14beSRoger He 	/* valid range is between 4 and 9 inclusive */
2086d07f14beSRoger He 	if (amdgpu_vm_fragment_size != -1 &&
2087d07f14beSRoger He 	    (amdgpu_vm_fragment_size > 9 || amdgpu_vm_fragment_size < 4)) {
2088d07f14beSRoger He 		dev_warn(adev->dev, "valid range is between 4 and 9\n");
2089d07f14beSRoger He 		amdgpu_vm_fragment_size = -1;
2090d07f14beSRoger He 	}
2091d07f14beSRoger He 
20925d5bd5e3SKevin Wang 	if (amdgpu_sched_hw_submission < 2) {
20935d5bd5e3SKevin Wang 		dev_warn(adev->dev, "sched hw submission jobs (%d) must be at least 2\n",
20945d5bd5e3SKevin Wang 			 amdgpu_sched_hw_submission);
20955d5bd5e3SKevin Wang 		amdgpu_sched_hw_submission = 2;
20965d5bd5e3SKevin Wang 	} else if (!is_power_of_2(amdgpu_sched_hw_submission)) {
20975d5bd5e3SKevin Wang 		dev_warn(adev->dev, "sched hw submission jobs (%d) must be a power of 2\n",
20985d5bd5e3SKevin Wang 			 amdgpu_sched_hw_submission);
20995d5bd5e3SKevin Wang 		amdgpu_sched_hw_submission = roundup_pow_of_two(amdgpu_sched_hw_submission);
21005d5bd5e3SKevin Wang 	}
21015d5bd5e3SKevin Wang 
21022656fd23SAndrey Grodzovsky 	if (amdgpu_reset_method < -1 || amdgpu_reset_method > 4) {
21032656fd23SAndrey Grodzovsky 		dev_warn(adev->dev, "invalid option for reset method, reverting to default\n");
21042656fd23SAndrey Grodzovsky 		amdgpu_reset_method = -1;
21052656fd23SAndrey Grodzovsky 	}
21062656fd23SAndrey Grodzovsky 
21077951e376SRex Zhu 	amdgpu_device_check_smu_prv_buffer_size(adev);
21087951e376SRex Zhu 
210906ec9070SAlex Deucher 	amdgpu_device_check_vm_size(adev);
2110d38ceaf9SAlex Deucher 
211106ec9070SAlex Deucher 	amdgpu_device_check_block_size(adev);
21126a7f76e7SChristian König 
211319aede77SAlex Deucher 	adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
2114912dfc84SEvan Quan 
211596595204SSrinivasan Shanmugam 	for (i = 0; i < MAX_XCP; i++)
211696595204SSrinivasan Shanmugam 		adev->enforce_isolation[i] = !!enforce_isolation;
211796595204SSrinivasan Shanmugam 
2118e3c00faaSMa Feng 	return 0;
2119d38ceaf9SAlex Deucher }
2120d38ceaf9SAlex Deucher 
2121d38ceaf9SAlex Deucher /**
2122d38ceaf9SAlex Deucher  * amdgpu_switcheroo_set_state - set switcheroo state
2123d38ceaf9SAlex Deucher  *
2124d38ceaf9SAlex Deucher  * @pdev: pci dev pointer
21251694467bSLukas Wunner  * @state: vga_switcheroo state
2126d38ceaf9SAlex Deucher  *
212712024b17Swangjianli  * Callback for the switcheroo driver.  Suspends or resumes
2128d38ceaf9SAlex Deucher  * the asics before or after it is powered up using ACPI methods.
2129d38ceaf9SAlex Deucher  */
amdgpu_switcheroo_set_state(struct pci_dev * pdev,enum vga_switcheroo_state state)21308aba21b7SLuben Tuikov static void amdgpu_switcheroo_set_state(struct pci_dev *pdev,
21318aba21b7SLuben Tuikov 					enum vga_switcheroo_state state)
2132d38ceaf9SAlex Deucher {
2133d38ceaf9SAlex Deucher 	struct drm_device *dev = pci_get_drvdata(pdev);
2134de185019SAlex Deucher 	int r;
2135d38ceaf9SAlex Deucher 
2136b98c6299SAlex Deucher 	if (amdgpu_device_supports_px(dev) && state == VGA_SWITCHEROO_OFF)
2137d38ceaf9SAlex Deucher 		return;
2138d38ceaf9SAlex Deucher 
2139d38ceaf9SAlex Deucher 	if (state == VGA_SWITCHEROO_ON) {
2140dd4fa6c1SAurabindo Pillai 		pr_info("switched on\n");
2141d38ceaf9SAlex Deucher 		/* don't suspend or resume card normally */
2142d38ceaf9SAlex Deucher 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
2143d38ceaf9SAlex Deucher 
21448f66090bSThomas Zimmermann 		pci_set_power_state(pdev, PCI_D0);
21458f66090bSThomas Zimmermann 		amdgpu_device_load_pci_state(pdev);
21468f66090bSThomas Zimmermann 		r = pci_enable_device(pdev);
2147de185019SAlex Deucher 		if (r)
2148de185019SAlex Deucher 			DRM_WARN("pci_enable_device failed (%d)\n", r);
2149de185019SAlex Deucher 		amdgpu_device_resume(dev, true);
2150d38ceaf9SAlex Deucher 
2151d38ceaf9SAlex Deucher 		dev->switch_power_state = DRM_SWITCH_POWER_ON;
2152d38ceaf9SAlex Deucher 	} else {
2153dd4fa6c1SAurabindo Pillai 		pr_info("switched off\n");
2154d38ceaf9SAlex Deucher 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
21555095d541SMario Limonciello 		amdgpu_device_prepare(dev);
2156de185019SAlex Deucher 		amdgpu_device_suspend(dev, true);
21578f66090bSThomas Zimmermann 		amdgpu_device_cache_pci_state(pdev);
2158de185019SAlex Deucher 		/* Shut down the device */
21598f66090bSThomas Zimmermann 		pci_disable_device(pdev);
21608f66090bSThomas Zimmermann 		pci_set_power_state(pdev, PCI_D3cold);
2161d38ceaf9SAlex Deucher 		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
2162d38ceaf9SAlex Deucher 	}
2163d38ceaf9SAlex Deucher }
2164d38ceaf9SAlex Deucher 
2165d38ceaf9SAlex Deucher /**
2166d38ceaf9SAlex Deucher  * amdgpu_switcheroo_can_switch - see if switcheroo state can change
2167d38ceaf9SAlex Deucher  *
2168d38ceaf9SAlex Deucher  * @pdev: pci dev pointer
2169d38ceaf9SAlex Deucher  *
2170d38ceaf9SAlex Deucher  * Callback for the switcheroo driver.  Check of the switcheroo
2171d38ceaf9SAlex Deucher  * state can be changed.
2172d38ceaf9SAlex Deucher  * Returns true if the state can be changed, false if not.
2173d38ceaf9SAlex Deucher  */
amdgpu_switcheroo_can_switch(struct pci_dev * pdev)2174d38ceaf9SAlex Deucher static bool amdgpu_switcheroo_can_switch(struct pci_dev *pdev)
2175d38ceaf9SAlex Deucher {
2176d38ceaf9SAlex Deucher 	struct drm_device *dev = pci_get_drvdata(pdev);
2177d38ceaf9SAlex Deucher 
2178d38ceaf9SAlex Deucher        /*
2179d38ceaf9SAlex Deucher 	* FIXME: open_count is protected by drm_global_mutex but that would lead to
2180d38ceaf9SAlex Deucher 	* locking inversion with the driver load path. And the access here is
2181d38ceaf9SAlex Deucher 	* completely racy anyway. So don't bother with locking for now.
2182d38ceaf9SAlex Deucher 	*/
21837e13ad89SChris Wilson 	return atomic_read(&dev->open_count) == 0;
2184d38ceaf9SAlex Deucher }
2185d38ceaf9SAlex Deucher 
2186d38ceaf9SAlex Deucher static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = {
2187d38ceaf9SAlex Deucher 	.set_gpu_state = amdgpu_switcheroo_set_state,
2188d38ceaf9SAlex Deucher 	.reprobe = NULL,
2189d38ceaf9SAlex Deucher 	.can_switch = amdgpu_switcheroo_can_switch,
2190d38ceaf9SAlex Deucher };
2191d38ceaf9SAlex Deucher 
2192e3ecdffaSAlex Deucher /**
2193e3ecdffaSAlex Deucher  * amdgpu_device_ip_set_clockgating_state - set the CG state
2194e3ecdffaSAlex Deucher  *
219587e3f136SDarren Powell  * @dev: amdgpu_device pointer
2196e3ecdffaSAlex Deucher  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
2197e3ecdffaSAlex Deucher  * @state: clockgating state (gate or ungate)
2198e3ecdffaSAlex Deucher  *
2199e3ecdffaSAlex Deucher  * Sets the requested clockgating state for all instances of
2200e3ecdffaSAlex Deucher  * the hardware IP specified.
2201e3ecdffaSAlex Deucher  * Returns the error code from the last instance.
2202e3ecdffaSAlex Deucher  */
amdgpu_device_ip_set_clockgating_state(void * dev,enum amd_ip_block_type block_type,enum amd_clockgating_state state)220343fa561fSRex Zhu int amdgpu_device_ip_set_clockgating_state(void *dev,
22045fc3aeebSyanyang1 					   enum amd_ip_block_type block_type,
22055fc3aeebSyanyang1 					   enum amd_clockgating_state state)
2206d38ceaf9SAlex Deucher {
220743fa561fSRex Zhu 	struct amdgpu_device *adev = dev;
2208d38ceaf9SAlex Deucher 	int i, r = 0;
2209d38ceaf9SAlex Deucher 
2210d38ceaf9SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
2211a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
22129ecbe7f5SAlex Deucher 			continue;
2213c722865aSRex Zhu 		if (adev->ip_blocks[i].version->type != block_type)
2214c722865aSRex Zhu 			continue;
2215c722865aSRex Zhu 		if (!adev->ip_blocks[i].version->funcs->set_clockgating_state)
2216c722865aSRex Zhu 			continue;
2217c722865aSRex Zhu 		r = adev->ip_blocks[i].version->funcs->set_clockgating_state(
2218f2ba8c3dSBoyuan Zhang 			&adev->ip_blocks[i], state);
2219d38ceaf9SAlex Deucher 		if (r)
2220c722865aSRex Zhu 			DRM_ERROR("set_clockgating_state of IP block <%s> failed %d\n",
2221c722865aSRex Zhu 				  adev->ip_blocks[i].version->funcs->name, r);
2222d38ceaf9SAlex Deucher 	}
2223d38ceaf9SAlex Deucher 	return r;
2224d38ceaf9SAlex Deucher }
2225d38ceaf9SAlex Deucher 
2226e3ecdffaSAlex Deucher /**
2227e3ecdffaSAlex Deucher  * amdgpu_device_ip_set_powergating_state - set the PG state
2228e3ecdffaSAlex Deucher  *
222987e3f136SDarren Powell  * @dev: amdgpu_device pointer
2230e3ecdffaSAlex Deucher  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
2231e3ecdffaSAlex Deucher  * @state: powergating state (gate or ungate)
2232e3ecdffaSAlex Deucher  *
2233e3ecdffaSAlex Deucher  * Sets the requested powergating state for all instances of
2234e3ecdffaSAlex Deucher  * the hardware IP specified.
2235e3ecdffaSAlex Deucher  * Returns the error code from the last instance.
2236e3ecdffaSAlex Deucher  */
amdgpu_device_ip_set_powergating_state(void * dev,enum amd_ip_block_type block_type,enum amd_powergating_state state)223743fa561fSRex Zhu int amdgpu_device_ip_set_powergating_state(void *dev,
22385fc3aeebSyanyang1 					   enum amd_ip_block_type block_type,
22395fc3aeebSyanyang1 					   enum amd_powergating_state state)
2240d38ceaf9SAlex Deucher {
224143fa561fSRex Zhu 	struct amdgpu_device *adev = dev;
2242d38ceaf9SAlex Deucher 	int i, r = 0;
2243d38ceaf9SAlex Deucher 
2244d38ceaf9SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
2245a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
22469ecbe7f5SAlex Deucher 			continue;
2247c722865aSRex Zhu 		if (adev->ip_blocks[i].version->type != block_type)
2248c722865aSRex Zhu 			continue;
2249c722865aSRex Zhu 		if (!adev->ip_blocks[i].version->funcs->set_powergating_state)
2250c722865aSRex Zhu 			continue;
2251c722865aSRex Zhu 		r = adev->ip_blocks[i].version->funcs->set_powergating_state(
225280d80511SBoyuan Zhang 			&adev->ip_blocks[i], state);
2253d38ceaf9SAlex Deucher 		if (r)
2254c722865aSRex Zhu 			DRM_ERROR("set_powergating_state of IP block <%s> failed %d\n",
2255c722865aSRex Zhu 				  adev->ip_blocks[i].version->funcs->name, r);
2256d38ceaf9SAlex Deucher 	}
2257d38ceaf9SAlex Deucher 	return r;
2258d38ceaf9SAlex Deucher }
2259d38ceaf9SAlex Deucher 
2260e3ecdffaSAlex Deucher /**
2261e3ecdffaSAlex Deucher  * amdgpu_device_ip_get_clockgating_state - get the CG state
2262e3ecdffaSAlex Deucher  *
2263e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
2264e3ecdffaSAlex Deucher  * @flags: clockgating feature flags
2265e3ecdffaSAlex Deucher  *
2266e3ecdffaSAlex Deucher  * Walks the list of IPs on the device and updates the clockgating
2267e3ecdffaSAlex Deucher  * flags for each IP.
2268e3ecdffaSAlex Deucher  * Updates @flags with the feature flags for each hardware IP where
2269e3ecdffaSAlex Deucher  * clockgating is enabled.
2270e3ecdffaSAlex Deucher  */
amdgpu_device_ip_get_clockgating_state(struct amdgpu_device * adev,u64 * flags)22712990a1fcSAlex Deucher void amdgpu_device_ip_get_clockgating_state(struct amdgpu_device *adev,
227225faeddcSEvan Quan 					    u64 *flags)
22736cb2d4e4SHuang Rui {
22746cb2d4e4SHuang Rui 	int i;
22756cb2d4e4SHuang Rui 
22766cb2d4e4SHuang Rui 	for (i = 0; i < adev->num_ip_blocks; i++) {
22776cb2d4e4SHuang Rui 		if (!adev->ip_blocks[i].status.valid)
22786cb2d4e4SHuang Rui 			continue;
22796cb2d4e4SHuang Rui 		if (adev->ip_blocks[i].version->funcs->get_clockgating_state)
22803521276aSSunil Khatri 			adev->ip_blocks[i].version->funcs->get_clockgating_state(
22813521276aSSunil Khatri 				&adev->ip_blocks[i], flags);
22826cb2d4e4SHuang Rui 	}
22836cb2d4e4SHuang Rui }
22846cb2d4e4SHuang Rui 
2285e3ecdffaSAlex Deucher /**
2286e3ecdffaSAlex Deucher  * amdgpu_device_ip_wait_for_idle - wait for idle
2287e3ecdffaSAlex Deucher  *
2288e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
2289e3ecdffaSAlex Deucher  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
2290e3ecdffaSAlex Deucher  *
2291e3ecdffaSAlex Deucher  * Waits for the request hardware IP to be idle.
2292e3ecdffaSAlex Deucher  * Returns 0 for success or a negative error code on failure.
2293e3ecdffaSAlex Deucher  */
amdgpu_device_ip_wait_for_idle(struct amdgpu_device * adev,enum amd_ip_block_type block_type)22942990a1fcSAlex Deucher int amdgpu_device_ip_wait_for_idle(struct amdgpu_device *adev,
22955dbbb60bSAlex Deucher 				   enum amd_ip_block_type block_type)
22965dbbb60bSAlex Deucher {
22975dbbb60bSAlex Deucher 	int i, r;
22985dbbb60bSAlex Deucher 
22995dbbb60bSAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
2300a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
23019ecbe7f5SAlex Deucher 			continue;
2302a1255107SAlex Deucher 		if (adev->ip_blocks[i].version->type == block_type) {
2303780002b6SSunil Khatri 			if (adev->ip_blocks[i].version->funcs->wait_for_idle) {
2304780002b6SSunil Khatri 				r = adev->ip_blocks[i].version->funcs->wait_for_idle(
2305780002b6SSunil Khatri 								&adev->ip_blocks[i]);
23065dbbb60bSAlex Deucher 				if (r)
23075dbbb60bSAlex Deucher 					return r;
2308780002b6SSunil Khatri 			}
23095dbbb60bSAlex Deucher 			break;
23105dbbb60bSAlex Deucher 		}
23115dbbb60bSAlex Deucher 	}
23125dbbb60bSAlex Deucher 	return 0;
23135dbbb60bSAlex Deucher 
23145dbbb60bSAlex Deucher }
23155dbbb60bSAlex Deucher 
2316e3ecdffaSAlex Deucher /**
2317dc443aa4SAsad Kamal  * amdgpu_device_ip_is_valid - is the hardware IP enabled
2318e3ecdffaSAlex Deucher  *
2319e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
2320e3ecdffaSAlex Deucher  * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
2321e3ecdffaSAlex Deucher  *
2322dc443aa4SAsad Kamal  * Check if the hardware IP is enable or not.
2323dc443aa4SAsad Kamal  * Returns true if it the IP is enable, false if not.
2324e3ecdffaSAlex Deucher  */
amdgpu_device_ip_is_valid(struct amdgpu_device * adev,enum amd_ip_block_type block_type)2325dc443aa4SAsad Kamal bool amdgpu_device_ip_is_valid(struct amdgpu_device *adev,
23265dbbb60bSAlex Deucher 			       enum amd_ip_block_type block_type)
23275dbbb60bSAlex Deucher {
23285dbbb60bSAlex Deucher 	int i;
23295dbbb60bSAlex Deucher 
23305dbbb60bSAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
2331a1255107SAlex Deucher 		if (adev->ip_blocks[i].version->type == block_type)
2332dc443aa4SAsad Kamal 			return adev->ip_blocks[i].status.valid;
23335dbbb60bSAlex Deucher 	}
2334dc443aa4SAsad Kamal 	return false;
23355dbbb60bSAlex Deucher 
23365dbbb60bSAlex Deucher }
23375dbbb60bSAlex Deucher 
2338e3ecdffaSAlex Deucher /**
2339e3ecdffaSAlex Deucher  * amdgpu_device_ip_get_ip_block - get a hw IP pointer
2340e3ecdffaSAlex Deucher  *
2341e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
234287e3f136SDarren Powell  * @type: Type of hardware IP (SMU, GFX, UVD, etc.)
2343e3ecdffaSAlex Deucher  *
2344e3ecdffaSAlex Deucher  * Returns a pointer to the hardware IP block structure
2345e3ecdffaSAlex Deucher  * if it exists for the asic, otherwise NULL.
2346e3ecdffaSAlex Deucher  */
23472990a1fcSAlex Deucher struct amdgpu_ip_block *
amdgpu_device_ip_get_ip_block(struct amdgpu_device * adev,enum amd_ip_block_type type)23482990a1fcSAlex Deucher amdgpu_device_ip_get_ip_block(struct amdgpu_device *adev,
23495fc3aeebSyanyang1 			      enum amd_ip_block_type type)
2350d38ceaf9SAlex Deucher {
2351d38ceaf9SAlex Deucher 	int i;
2352d38ceaf9SAlex Deucher 
2353d38ceaf9SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++)
2354a1255107SAlex Deucher 		if (adev->ip_blocks[i].version->type == type)
2355d38ceaf9SAlex Deucher 			return &adev->ip_blocks[i];
2356d38ceaf9SAlex Deucher 
2357d38ceaf9SAlex Deucher 	return NULL;
2358d38ceaf9SAlex Deucher }
2359d38ceaf9SAlex Deucher 
2360d38ceaf9SAlex Deucher /**
23612990a1fcSAlex Deucher  * amdgpu_device_ip_block_version_cmp
2362d38ceaf9SAlex Deucher  *
2363d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
23645fc3aeebSyanyang1  * @type: enum amd_ip_block_type
2365d38ceaf9SAlex Deucher  * @major: major version
2366d38ceaf9SAlex Deucher  * @minor: minor version
2367d38ceaf9SAlex Deucher  *
2368d38ceaf9SAlex Deucher  * return 0 if equal or greater
2369d38ceaf9SAlex Deucher  * return 1 if smaller or the ip_block doesn't exist
2370d38ceaf9SAlex Deucher  */
amdgpu_device_ip_block_version_cmp(struct amdgpu_device * adev,enum amd_ip_block_type type,u32 major,u32 minor)23712990a1fcSAlex Deucher int amdgpu_device_ip_block_version_cmp(struct amdgpu_device *adev,
23725fc3aeebSyanyang1 				       enum amd_ip_block_type type,
2373d38ceaf9SAlex Deucher 				       u32 major, u32 minor)
2374d38ceaf9SAlex Deucher {
23752990a1fcSAlex Deucher 	struct amdgpu_ip_block *ip_block = amdgpu_device_ip_get_ip_block(adev, type);
2376d38ceaf9SAlex Deucher 
2377a1255107SAlex Deucher 	if (ip_block && ((ip_block->version->major > major) ||
2378a1255107SAlex Deucher 			((ip_block->version->major == major) &&
2379a1255107SAlex Deucher 			(ip_block->version->minor >= minor))))
2380d38ceaf9SAlex Deucher 		return 0;
2381d38ceaf9SAlex Deucher 
2382d38ceaf9SAlex Deucher 	return 1;
2383d38ceaf9SAlex Deucher }
2384d38ceaf9SAlex Deucher 
2385a1255107SAlex Deucher /**
23862990a1fcSAlex Deucher  * amdgpu_device_ip_block_add
2387a1255107SAlex Deucher  *
2388a1255107SAlex Deucher  * @adev: amdgpu_device pointer
2389a1255107SAlex Deucher  * @ip_block_version: pointer to the IP to add
2390a1255107SAlex Deucher  *
2391a1255107SAlex Deucher  * Adds the IP block driver information to the collection of IPs
2392a1255107SAlex Deucher  * on the asic.
2393a1255107SAlex Deucher  */
amdgpu_device_ip_block_add(struct amdgpu_device * adev,const struct amdgpu_ip_block_version * ip_block_version)23942990a1fcSAlex Deucher int amdgpu_device_ip_block_add(struct amdgpu_device *adev,
2395a1255107SAlex Deucher 			       const struct amdgpu_ip_block_version *ip_block_version)
2396a1255107SAlex Deucher {
2397a1255107SAlex Deucher 	if (!ip_block_version)
2398a1255107SAlex Deucher 		return -EINVAL;
2399a1255107SAlex Deucher 
24007bd939d0SLikun GAO 	switch (ip_block_version->type) {
24017bd939d0SLikun GAO 	case AMD_IP_BLOCK_TYPE_VCN:
24027bd939d0SLikun GAO 		if (adev->harvest_ip_mask & AMD_HARVEST_IP_VCN_MASK)
24037bd939d0SLikun GAO 			return 0;
24047bd939d0SLikun GAO 		break;
24057bd939d0SLikun GAO 	case AMD_IP_BLOCK_TYPE_JPEG:
24067bd939d0SLikun GAO 		if (adev->harvest_ip_mask & AMD_HARVEST_IP_JPEG_MASK)
24077bd939d0SLikun GAO 			return 0;
24087bd939d0SLikun GAO 		break;
24097bd939d0SLikun GAO 	default:
24107bd939d0SLikun GAO 		break;
24117bd939d0SLikun GAO 	}
24127bd939d0SLikun GAO 
2413a0db1ea0SLijo Lazar 	dev_info(adev->dev, "detected ip block number %d <%s>\n",
2414a0db1ea0SLijo Lazar 		 adev->num_ip_blocks, ip_block_version->funcs->name);
2415a0bae357SHuang Rui 
241637b99322SSunil Khatri 	adev->ip_blocks[adev->num_ip_blocks].adev = adev;
241737b99322SSunil Khatri 
2418a1255107SAlex Deucher 	adev->ip_blocks[adev->num_ip_blocks++].version = ip_block_version;
2419a1255107SAlex Deucher 
2420a1255107SAlex Deucher 	return 0;
2421a1255107SAlex Deucher }
2422a1255107SAlex Deucher 
2423e3ecdffaSAlex Deucher /**
2424e3ecdffaSAlex Deucher  * amdgpu_device_enable_virtual_display - enable virtual display feature
2425e3ecdffaSAlex Deucher  *
2426e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
2427e3ecdffaSAlex Deucher  *
2428e3ecdffaSAlex Deucher  * Enabled the virtual display feature if the user has enabled it via
2429e3ecdffaSAlex Deucher  * the module parameter virtual_display.  This feature provides a virtual
2430e3ecdffaSAlex Deucher  * display hardware on headless boards or in virtualized environments.
2431e3ecdffaSAlex Deucher  * This function parses and validates the configuration string specified by
2432a567db80SRandy Dunlap  * the user and configures the virtual display configuration (number of
2433e3ecdffaSAlex Deucher  * virtual connectors, crtcs, etc.) specified.
2434e3ecdffaSAlex Deucher  */
amdgpu_device_enable_virtual_display(struct amdgpu_device * adev)2435483ef985SAlex Deucher static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
24369accf2fdSEmily Deng {
24379accf2fdSEmily Deng 	adev->enable_virtual_display = false;
24389accf2fdSEmily Deng 
24399accf2fdSEmily Deng 	if (amdgpu_virtual_display) {
24408f66090bSThomas Zimmermann 		const char *pci_address_name = pci_name(adev->pdev);
24410f66356dSEmily Deng 		char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname;
24429accf2fdSEmily Deng 
24439accf2fdSEmily Deng 		pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL);
24449accf2fdSEmily Deng 		pciaddstr_tmp = pciaddstr;
24450f66356dSEmily Deng 		while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) {
24460f66356dSEmily Deng 			pciaddname = strsep(&pciaddname_tmp, ",");
2447967de2a9SYintian Tao 			if (!strcmp("all", pciaddname)
2448967de2a9SYintian Tao 			    || !strcmp(pci_address_name, pciaddname)) {
24490f66356dSEmily Deng 				long num_crtc;
24500f66356dSEmily Deng 				int res = -1;
24510f66356dSEmily Deng 
24529accf2fdSEmily Deng 				adev->enable_virtual_display = true;
24530f66356dSEmily Deng 
24540f66356dSEmily Deng 				if (pciaddname_tmp)
24550f66356dSEmily Deng 					res = kstrtol(pciaddname_tmp, 10,
24560f66356dSEmily Deng 						      &num_crtc);
24570f66356dSEmily Deng 
24580f66356dSEmily Deng 				if (!res) {
24590f66356dSEmily Deng 					if (num_crtc < 1)
24600f66356dSEmily Deng 						num_crtc = 1;
24610f66356dSEmily Deng 					if (num_crtc > 6)
24620f66356dSEmily Deng 						num_crtc = 6;
24630f66356dSEmily Deng 					adev->mode_info.num_crtc = num_crtc;
24640f66356dSEmily Deng 				} else {
24650f66356dSEmily Deng 					adev->mode_info.num_crtc = 1;
24660f66356dSEmily Deng 				}
24679accf2fdSEmily Deng 				break;
24689accf2fdSEmily Deng 			}
24699accf2fdSEmily Deng 		}
24709accf2fdSEmily Deng 
24710f66356dSEmily Deng 		DRM_INFO("virtual display string:%s, %s:virtual_display:%d, num_crtc:%d\n",
24729accf2fdSEmily Deng 			 amdgpu_virtual_display, pci_address_name,
24730f66356dSEmily Deng 			 adev->enable_virtual_display, adev->mode_info.num_crtc);
24749accf2fdSEmily Deng 
24759accf2fdSEmily Deng 		kfree(pciaddstr);
24769accf2fdSEmily Deng 	}
24779accf2fdSEmily Deng }
24789accf2fdSEmily Deng 
amdgpu_device_set_sriov_virtual_display(struct amdgpu_device * adev)247925263da3SAlex Deucher void amdgpu_device_set_sriov_virtual_display(struct amdgpu_device *adev)
248025263da3SAlex Deucher {
248125263da3SAlex Deucher 	if (amdgpu_sriov_vf(adev) && !adev->enable_virtual_display) {
248225263da3SAlex Deucher 		adev->mode_info.num_crtc = 1;
248325263da3SAlex Deucher 		adev->enable_virtual_display = true;
248425263da3SAlex Deucher 		DRM_INFO("virtual_display:%d, num_crtc:%d\n",
248525263da3SAlex Deucher 			 adev->enable_virtual_display, adev->mode_info.num_crtc);
248625263da3SAlex Deucher 	}
248725263da3SAlex Deucher }
248825263da3SAlex Deucher 
2489e3ecdffaSAlex Deucher /**
2490e3ecdffaSAlex Deucher  * amdgpu_device_parse_gpu_info_fw - parse gpu info firmware
2491e3ecdffaSAlex Deucher  *
2492e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
2493e3ecdffaSAlex Deucher  *
2494e3ecdffaSAlex Deucher  * Parses the asic configuration parameters specified in the gpu info
2495a567db80SRandy Dunlap  * firmware and makes them available to the driver for use in configuring
2496e3ecdffaSAlex Deucher  * the asic.
2497e3ecdffaSAlex Deucher  * Returns 0 on success, -EINVAL on failure.
2498e3ecdffaSAlex Deucher  */
amdgpu_device_parse_gpu_info_fw(struct amdgpu_device * adev)2499e2a75f88SAlex Deucher static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
2500e2a75f88SAlex Deucher {
2501e2a75f88SAlex Deucher 	const char *chip_name;
2502e2a75f88SAlex Deucher 	int err;
2503e2a75f88SAlex Deucher 	const struct gpu_info_firmware_header_v1_0 *hdr;
2504e2a75f88SAlex Deucher 
2505ab4fe3e1SHuang Rui 	adev->firmware.gpu_info_fw = NULL;
2506ab4fe3e1SHuang Rui 
2507fb915c87SAlex Deucher 	if (adev->mman.discovery_bin)
2508258620d0SAlex Deucher 		return 0;
2509258620d0SAlex Deucher 
2510e2a75f88SAlex Deucher 	switch (adev->asic_type) {
2511e2a75f88SAlex Deucher 	default:
2512e2a75f88SAlex Deucher 		return 0;
2513e2a75f88SAlex Deucher 	case CHIP_VEGA10:
2514e2a75f88SAlex Deucher 		chip_name = "vega10";
2515e2a75f88SAlex Deucher 		break;
25163f76dcedSAlex Deucher 	case CHIP_VEGA12:
25173f76dcedSAlex Deucher 		chip_name = "vega12";
25183f76dcedSAlex Deucher 		break;
25192d2e5e7eSAlex Deucher 	case CHIP_RAVEN:
252054f78a76SAlex Deucher 		if (adev->apu_flags & AMD_APU_IS_RAVEN2)
252154c4d17eSFeifei Xu 			chip_name = "raven2";
252254f78a76SAlex Deucher 		else if (adev->apu_flags & AMD_APU_IS_PICASSO)
2523741deadeSAlex Deucher 			chip_name = "picasso";
252454c4d17eSFeifei Xu 		else
25252d2e5e7eSAlex Deucher 			chip_name = "raven";
25262d2e5e7eSAlex Deucher 		break;
252765e60f6eSLe Ma 	case CHIP_ARCTURUS:
252865e60f6eSLe Ma 		chip_name = "arcturus";
252965e60f6eSLe Ma 		break;
253042b325e5SXiaojie Yuan 	case CHIP_NAVI12:
253142b325e5SXiaojie Yuan 		chip_name = "navi12";
253242b325e5SXiaojie Yuan 		break;
2533e2a75f88SAlex Deucher 	}
2534e2a75f88SAlex Deucher 
2535a777c9d7SYang Wang 	err = amdgpu_ucode_request(adev, &adev->firmware.gpu_info_fw,
2536ea5d4934SMario Limonciello 				   AMDGPU_UCODE_OPTIONAL,
2537a777c9d7SYang Wang 				   "amdgpu/%s_gpu_info.bin", chip_name);
2538e2a75f88SAlex Deucher 	if (err) {
2539e2a75f88SAlex Deucher 		dev_err(adev->dev,
2540a777c9d7SYang Wang 			"Failed to get gpu_info firmware \"%s_gpu_info.bin\"\n",
2541a777c9d7SYang Wang 			chip_name);
2542e2a75f88SAlex Deucher 		goto out;
2543e2a75f88SAlex Deucher 	}
2544e2a75f88SAlex Deucher 
2545ab4fe3e1SHuang Rui 	hdr = (const struct gpu_info_firmware_header_v1_0 *)adev->firmware.gpu_info_fw->data;
2546e2a75f88SAlex Deucher 	amdgpu_ucode_print_gpu_info_hdr(&hdr->header);
2547e2a75f88SAlex Deucher 
2548e2a75f88SAlex Deucher 	switch (hdr->version_major) {
2549e2a75f88SAlex Deucher 	case 1:
2550e2a75f88SAlex Deucher 	{
2551e2a75f88SAlex Deucher 		const struct gpu_info_firmware_v1_0 *gpu_info_fw =
2552ab4fe3e1SHuang Rui 			(const struct gpu_info_firmware_v1_0 *)(adev->firmware.gpu_info_fw->data +
2553e2a75f88SAlex Deucher 								le32_to_cpu(hdr->header.ucode_array_offset_bytes));
2554e2a75f88SAlex Deucher 
2555cc375d8cSTianci.Yin 		/*
2556a567db80SRandy Dunlap 		 * Should be dropped when DAL no longer needs it.
2557cc375d8cSTianci.Yin 		 */
2558cc375d8cSTianci.Yin 		if (adev->asic_type == CHIP_NAVI12)
2559ec51d3faSXiaojie Yuan 			goto parse_soc_bounding_box;
2560ec51d3faSXiaojie Yuan 
2561b5ab16bfSAlex Deucher 		adev->gfx.config.max_shader_engines = le32_to_cpu(gpu_info_fw->gc_num_se);
2562b5ab16bfSAlex Deucher 		adev->gfx.config.max_cu_per_sh = le32_to_cpu(gpu_info_fw->gc_num_cu_per_sh);
2563b5ab16bfSAlex Deucher 		adev->gfx.config.max_sh_per_se = le32_to_cpu(gpu_info_fw->gc_num_sh_per_se);
2564b5ab16bfSAlex Deucher 		adev->gfx.config.max_backends_per_se = le32_to_cpu(gpu_info_fw->gc_num_rb_per_se);
2565e2a75f88SAlex Deucher 		adev->gfx.config.max_texture_channel_caches =
2566b5ab16bfSAlex Deucher 			le32_to_cpu(gpu_info_fw->gc_num_tccs);
2567b5ab16bfSAlex Deucher 		adev->gfx.config.max_gprs = le32_to_cpu(gpu_info_fw->gc_num_gprs);
2568b5ab16bfSAlex Deucher 		adev->gfx.config.max_gs_threads = le32_to_cpu(gpu_info_fw->gc_num_max_gs_thds);
2569b5ab16bfSAlex Deucher 		adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gpu_info_fw->gc_gs_table_depth);
2570b5ab16bfSAlex Deucher 		adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gpu_info_fw->gc_gsprim_buff_depth);
2571e2a75f88SAlex Deucher 		adev->gfx.config.double_offchip_lds_buf =
2572b5ab16bfSAlex Deucher 			le32_to_cpu(gpu_info_fw->gc_double_offchip_lds_buffer);
2573b5ab16bfSAlex Deucher 		adev->gfx.cu_info.wave_front_size = le32_to_cpu(gpu_info_fw->gc_wave_size);
257451fd0370SHawking Zhang 		adev->gfx.cu_info.max_waves_per_simd =
257551fd0370SHawking Zhang 			le32_to_cpu(gpu_info_fw->gc_max_waves_per_simd);
257651fd0370SHawking Zhang 		adev->gfx.cu_info.max_scratch_slots_per_cu =
257751fd0370SHawking Zhang 			le32_to_cpu(gpu_info_fw->gc_max_scratch_slots_per_cu);
257851fd0370SHawking Zhang 		adev->gfx.cu_info.lds_size = le32_to_cpu(gpu_info_fw->gc_lds_size);
257948321c3dSHarry Wentland 		if (hdr->version_minor >= 1) {
258035c2e910SHawking Zhang 			const struct gpu_info_firmware_v1_1 *gpu_info_fw =
258135c2e910SHawking Zhang 				(const struct gpu_info_firmware_v1_1 *)(adev->firmware.gpu_info_fw->data +
258235c2e910SHawking Zhang 									le32_to_cpu(hdr->header.ucode_array_offset_bytes));
258335c2e910SHawking Zhang 			adev->gfx.config.num_sc_per_sh =
258435c2e910SHawking Zhang 				le32_to_cpu(gpu_info_fw->num_sc_per_sh);
258535c2e910SHawking Zhang 			adev->gfx.config.num_packer_per_sc =
258635c2e910SHawking Zhang 				le32_to_cpu(gpu_info_fw->num_packer_per_sc);
258735c2e910SHawking Zhang 		}
2588ec51d3faSXiaojie Yuan 
2589ec51d3faSXiaojie Yuan parse_soc_bounding_box:
2590ec51d3faSXiaojie Yuan 		/*
2591ec51d3faSXiaojie Yuan 		 * soc bounding box info is not integrated in disocovery table,
2592258620d0SAlex Deucher 		 * we always need to parse it from gpu info firmware if needed.
2593ec51d3faSXiaojie Yuan 		 */
259448321c3dSHarry Wentland 		if (hdr->version_minor == 2) {
259548321c3dSHarry Wentland 			const struct gpu_info_firmware_v1_2 *gpu_info_fw =
259648321c3dSHarry Wentland 				(const struct gpu_info_firmware_v1_2 *)(adev->firmware.gpu_info_fw->data +
259748321c3dSHarry Wentland 									le32_to_cpu(hdr->header.ucode_array_offset_bytes));
259848321c3dSHarry Wentland 			adev->dm.soc_bounding_box = &gpu_info_fw->soc_bounding_box;
259948321c3dSHarry Wentland 		}
2600e2a75f88SAlex Deucher 		break;
2601e2a75f88SAlex Deucher 	}
2602e2a75f88SAlex Deucher 	default:
2603e2a75f88SAlex Deucher 		dev_err(adev->dev,
2604e2a75f88SAlex Deucher 			"Unsupported gpu_info table %d\n", hdr->header.ucode_version);
2605e2a75f88SAlex Deucher 		err = -EINVAL;
2606e2a75f88SAlex Deucher 		goto out;
2607e2a75f88SAlex Deucher 	}
2608e2a75f88SAlex Deucher out:
2609e2a75f88SAlex Deucher 	return err;
2610e2a75f88SAlex Deucher }
2611e2a75f88SAlex Deucher 
2612e3ecdffaSAlex Deucher /**
2613e3ecdffaSAlex Deucher  * amdgpu_device_ip_early_init - run early init for hardware IPs
2614e3ecdffaSAlex Deucher  *
2615e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
2616e3ecdffaSAlex Deucher  *
2617e3ecdffaSAlex Deucher  * Early initialization pass for hardware IPs.  The hardware IPs that make
2618e3ecdffaSAlex Deucher  * up each asic are discovered each IP's early_init callback is run.  This
2619e3ecdffaSAlex Deucher  * is the first stage in initializing the asic.
2620e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
2621e3ecdffaSAlex Deucher  */
amdgpu_device_ip_early_init(struct amdgpu_device * adev)262206ec9070SAlex Deucher static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
2623d38ceaf9SAlex Deucher {
26243b37e272SYifan Zhang 	struct amdgpu_ip_block *ip_block;
2625901e2be2SAlex Deucher 	struct pci_dev *parent;
26267e0aa706SLijo Lazar 	bool total, skip_bios;
26277e0aa706SLijo Lazar 	uint32_t bios_flags;
2628aaa36a97SAlex Deucher 	int i, r;
2629d38ceaf9SAlex Deucher 
2630483ef985SAlex Deucher 	amdgpu_device_enable_virtual_display(adev);
2631a6be7570SEmily Deng 
263200a979f3SWenhui Sheng 	if (amdgpu_sriov_vf(adev)) {
263300a979f3SWenhui Sheng 		r = amdgpu_virt_request_full_gpu(adev, true);
2634aaa36a97SAlex Deucher 		if (r)
2635aaa36a97SAlex Deucher 			return r;
263600a979f3SWenhui Sheng 	}
263700a979f3SWenhui Sheng 
2638aaa36a97SAlex Deucher 	switch (adev->asic_type) {
263933f34802SKen Wang #ifdef CONFIG_DRM_AMDGPU_SI
264033f34802SKen Wang 	case CHIP_VERDE:
264133f34802SKen Wang 	case CHIP_TAHITI:
264233f34802SKen Wang 	case CHIP_PITCAIRN:
264333f34802SKen Wang 	case CHIP_OLAND:
264433f34802SKen Wang 	case CHIP_HAINAN:
2645295d0dafSKen Wang 		adev->family = AMDGPU_FAMILY_SI;
264633f34802SKen Wang 		r = si_set_ip_blocks(adev);
264733f34802SKen Wang 		if (r)
264833f34802SKen Wang 			return r;
264933f34802SKen Wang 		break;
265033f34802SKen Wang #endif
2651a2e73f56SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_CIK
2652a2e73f56SAlex Deucher 	case CHIP_BONAIRE:
2653a2e73f56SAlex Deucher 	case CHIP_HAWAII:
2654a2e73f56SAlex Deucher 	case CHIP_KAVERI:
2655a2e73f56SAlex Deucher 	case CHIP_KABINI:
2656a2e73f56SAlex Deucher 	case CHIP_MULLINS:
2657e1ad2d53SAlex Deucher 		if (adev->flags & AMD_IS_APU)
2658a2e73f56SAlex Deucher 			adev->family = AMDGPU_FAMILY_KV;
2659e1ad2d53SAlex Deucher 		else
2660e1ad2d53SAlex Deucher 			adev->family = AMDGPU_FAMILY_CI;
2661a2e73f56SAlex Deucher 
2662a2e73f56SAlex Deucher 		r = cik_set_ip_blocks(adev);
2663a2e73f56SAlex Deucher 		if (r)
2664a2e73f56SAlex Deucher 			return r;
2665a2e73f56SAlex Deucher 		break;
2666a2e73f56SAlex Deucher #endif
2667da87c30bSAlex Deucher 	case CHIP_TOPAZ:
2668da87c30bSAlex Deucher 	case CHIP_TONGA:
2669da87c30bSAlex Deucher 	case CHIP_FIJI:
2670da87c30bSAlex Deucher 	case CHIP_POLARIS10:
2671da87c30bSAlex Deucher 	case CHIP_POLARIS11:
2672da87c30bSAlex Deucher 	case CHIP_POLARIS12:
2673da87c30bSAlex Deucher 	case CHIP_VEGAM:
2674da87c30bSAlex Deucher 	case CHIP_CARRIZO:
2675da87c30bSAlex Deucher 	case CHIP_STONEY:
2676da87c30bSAlex Deucher 		if (adev->flags & AMD_IS_APU)
2677da87c30bSAlex Deucher 			adev->family = AMDGPU_FAMILY_CZ;
2678da87c30bSAlex Deucher 		else
2679da87c30bSAlex Deucher 			adev->family = AMDGPU_FAMILY_VI;
2680da87c30bSAlex Deucher 
2681da87c30bSAlex Deucher 		r = vi_set_ip_blocks(adev);
2682da87c30bSAlex Deucher 		if (r)
2683da87c30bSAlex Deucher 			return r;
2684da87c30bSAlex Deucher 		break;
2685d38ceaf9SAlex Deucher 	default:
268663352b7fSAlex Deucher 		r = amdgpu_discovery_set_ip_blocks(adev);
268763352b7fSAlex Deucher 		if (r)
268863352b7fSAlex Deucher 			return r;
268963352b7fSAlex Deucher 		break;
2690d38ceaf9SAlex Deucher 	}
2691d38ceaf9SAlex Deucher 
2692901e2be2SAlex Deucher 	if (amdgpu_has_atpx() &&
2693901e2be2SAlex Deucher 	    (amdgpu_is_atpx_hybrid() ||
2694901e2be2SAlex Deucher 	     amdgpu_has_atpx_dgpu_power_cntl()) &&
2695901e2be2SAlex Deucher 	    ((adev->flags & AMD_IS_APU) == 0) &&
26967b1c6263SAlex Deucher 	    !dev_is_removable(&adev->pdev->dev))
2697901e2be2SAlex Deucher 		adev->flags |= AMD_IS_PX;
2698901e2be2SAlex Deucher 
269985ac2021SAlex Deucher 	if (!(adev->flags & AMD_IS_APU)) {
2700c4c8955bSMario Limonciello 		parent = pcie_find_root_port(adev->pdev);
2701901e2be2SAlex Deucher 		adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
270285ac2021SAlex Deucher 	}
2703901e2be2SAlex Deucher 
27041884734aSpding 
27053b94fb10SLikun Gao 	adev->pm.pp_feature = amdgpu_pp_feature_mask;
2706a35ad98bSShirish S 	if (amdgpu_sriov_vf(adev) || sched_policy == KFD_SCHED_POLICY_NO_HWS)
270700544006SHuang Rui 		adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
27084215a119SHorace Chen 	if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)
27094215a119SHorace Chen 		adev->pm.pp_feature &= ~PP_OVERDRIVE_MASK;
2710d9b3a066SMario Limonciello 	if (!amdgpu_device_pcie_dynamic_switching_supported(adev))
2711fbf1035bSMario Limonciello 		adev->pm.pp_feature &= ~PP_PCIE_DPM_MASK;
271200f54b97SHuang Rui 
2713ced69502SMario Limonciello 	total = true;
2714d38ceaf9SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
2715146b085eSSunil Khatri 		ip_block = &adev->ip_blocks[i];
2716146b085eSSunil Khatri 
2717d38ceaf9SAlex Deucher 		if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
27180c451bafSLe Ma 			DRM_WARN("disabled ip block: %d <%s>\n",
2719ed8cf00cSHuang Rui 				  i, adev->ip_blocks[i].version->funcs->name);
2720a1255107SAlex Deucher 			adev->ip_blocks[i].status.valid = false;
2721146b085eSSunil Khatri 		} else if (ip_block->version->funcs->early_init) {
2722146b085eSSunil Khatri 			r = ip_block->version->funcs->early_init(ip_block);
27232c1a2784SAlex Deucher 			if (r == -ENOENT) {
2724a1255107SAlex Deucher 				adev->ip_blocks[i].status.valid = false;
27252c1a2784SAlex Deucher 			} else if (r) {
2726a1255107SAlex Deucher 				DRM_ERROR("early_init of IP block <%s> failed %d\n",
2727a1255107SAlex Deucher 					  adev->ip_blocks[i].version->funcs->name, r);
2728ced69502SMario Limonciello 				total = false;
27292c1a2784SAlex Deucher 			} else {
2730a1255107SAlex Deucher 				adev->ip_blocks[i].status.valid = true;
27312c1a2784SAlex Deucher 			}
2732974e6b64SAlex Deucher 		} else {
2733a1255107SAlex Deucher 			adev->ip_blocks[i].status.valid = true;
2734974e6b64SAlex Deucher 		}
273521a249caSAlex Deucher 		/* get the vbios after the asic_funcs are set up */
273621a249caSAlex Deucher 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON) {
27376e29c227SAlex Deucher 			r = amdgpu_device_parse_gpu_info_fw(adev);
27386e29c227SAlex Deucher 			if (r)
27396e29c227SAlex Deucher 				return r;
27406e29c227SAlex Deucher 
27417e0aa706SLijo Lazar 			bios_flags = amdgpu_device_get_vbios_flags(adev);
27427e0aa706SLijo Lazar 			skip_bios = !!(bios_flags & AMDGPU_VBIOS_SKIP);
274321a249caSAlex Deucher 			/* Read BIOS */
27447e0aa706SLijo Lazar 			if (!skip_bios) {
27456e8ca38eSLijo Lazar 				bool optional =
27466e8ca38eSLijo Lazar 					!!(bios_flags & AMDGPU_VBIOS_OPTIONAL);
27476e8ca38eSLijo Lazar 				if (!amdgpu_get_bios(adev) && !optional)
274821a249caSAlex Deucher 					return -EINVAL;
274921a249caSAlex Deucher 
27506e8ca38eSLijo Lazar 				if (optional && !adev->bios)
27516e8ca38eSLijo Lazar 					dev_info(
27526e8ca38eSLijo Lazar 						adev->dev,
27536e8ca38eSLijo Lazar 						"VBIOS image optional, proceeding without VBIOS image");
27546e8ca38eSLijo Lazar 
27556e8ca38eSLijo Lazar 				if (adev->bios) {
275621a249caSAlex Deucher 					r = amdgpu_atombios_init(adev);
275721a249caSAlex Deucher 					if (r) {
27586e8ca38eSLijo Lazar 						dev_err(adev->dev,
27596e8ca38eSLijo Lazar 							"amdgpu_atombios_init failed\n");
27606e8ca38eSLijo Lazar 						amdgpu_vf_error_put(
27616e8ca38eSLijo Lazar 							adev,
27626e8ca38eSLijo Lazar 							AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL,
27636e8ca38eSLijo Lazar 							0, 0);
276421a249caSAlex Deucher 						return r;
276521a249caSAlex Deucher 					}
27669535a86aSShiwu Zhang 				}
27676e8ca38eSLijo Lazar 			}
276877eabc6fSPeng Ju Zhou 
276977eabc6fSPeng Ju Zhou 			/*get pf2vf msg info at it's earliest time*/
277077eabc6fSPeng Ju Zhou 			if (amdgpu_sriov_vf(adev))
277177eabc6fSPeng Ju Zhou 				amdgpu_virt_init_data_exchange(adev);
277277eabc6fSPeng Ju Zhou 
277321a249caSAlex Deucher 		}
2774d38ceaf9SAlex Deucher 	}
2775ced69502SMario Limonciello 	if (!total)
2776ced69502SMario Limonciello 		return -ENODEV;
2777d38ceaf9SAlex Deucher 
277835750679SLijo Lazar 	if (adev->gmc.xgmi.supported)
277935750679SLijo Lazar 		amdgpu_xgmi_early_init(adev);
278035750679SLijo Lazar 
27813b37e272SYifan Zhang 	ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GFX);
27823b37e272SYifan Zhang 	if (ip_block->status.valid != false)
278300fa4035SSreekant Somasekharan 		amdgpu_amdkfd_device_probe(adev);
27843b37e272SYifan Zhang 
2785395d1fb9SNicolai Hähnle 	adev->cg_flags &= amdgpu_cg_mask;
2786395d1fb9SNicolai Hähnle 	adev->pg_flags &= amdgpu_pg_mask;
2787395d1fb9SNicolai Hähnle 
2788d38ceaf9SAlex Deucher 	return 0;
2789d38ceaf9SAlex Deucher }
2790d38ceaf9SAlex Deucher 
amdgpu_device_ip_hw_init_phase1(struct amdgpu_device * adev)27910a4f2520SRex Zhu static int amdgpu_device_ip_hw_init_phase1(struct amdgpu_device *adev)
27920a4f2520SRex Zhu {
27930a4f2520SRex Zhu 	int i, r;
27940a4f2520SRex Zhu 
27950a4f2520SRex Zhu 	for (i = 0; i < adev->num_ip_blocks; i++) {
27960a4f2520SRex Zhu 		if (!adev->ip_blocks[i].status.sw)
27970a4f2520SRex Zhu 			continue;
27980a4f2520SRex Zhu 		if (adev->ip_blocks[i].status.hw)
27990a4f2520SRex Zhu 			continue;
280014f2fe34SLijo Lazar 		if (!amdgpu_ip_member_of_hwini(
280114f2fe34SLijo Lazar 			    adev, adev->ip_blocks[i].version->type))
280214f2fe34SLijo Lazar 			continue;
28030a4f2520SRex Zhu 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
28042d11fd3fSTrigger Huang 		    (amdgpu_sriov_vf(adev) && (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)) ||
28050a4f2520SRex Zhu 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
280658608034SSunil Khatri 			r = adev->ip_blocks[i].version->funcs->hw_init(&adev->ip_blocks[i]);
28070a4f2520SRex Zhu 			if (r) {
28080a4f2520SRex Zhu 				DRM_ERROR("hw_init of IP block <%s> failed %d\n",
28090a4f2520SRex Zhu 					  adev->ip_blocks[i].version->funcs->name, r);
28100a4f2520SRex Zhu 				return r;
28110a4f2520SRex Zhu 			}
28120a4f2520SRex Zhu 			adev->ip_blocks[i].status.hw = true;
28130a4f2520SRex Zhu 		}
28140a4f2520SRex Zhu 	}
28150a4f2520SRex Zhu 
28160a4f2520SRex Zhu 	return 0;
28170a4f2520SRex Zhu }
28180a4f2520SRex Zhu 
amdgpu_device_ip_hw_init_phase2(struct amdgpu_device * adev)28190a4f2520SRex Zhu static int amdgpu_device_ip_hw_init_phase2(struct amdgpu_device *adev)
28200a4f2520SRex Zhu {
28210a4f2520SRex Zhu 	int i, r;
28220a4f2520SRex Zhu 
28230a4f2520SRex Zhu 	for (i = 0; i < adev->num_ip_blocks; i++) {
28240a4f2520SRex Zhu 		if (!adev->ip_blocks[i].status.sw)
28250a4f2520SRex Zhu 			continue;
28260a4f2520SRex Zhu 		if (adev->ip_blocks[i].status.hw)
28270a4f2520SRex Zhu 			continue;
282814f2fe34SLijo Lazar 		if (!amdgpu_ip_member_of_hwini(
282914f2fe34SLijo Lazar 			    adev, adev->ip_blocks[i].version->type))
283014f2fe34SLijo Lazar 			continue;
283158608034SSunil Khatri 		r = adev->ip_blocks[i].version->funcs->hw_init(&adev->ip_blocks[i]);
28320a4f2520SRex Zhu 		if (r) {
28330a4f2520SRex Zhu 			DRM_ERROR("hw_init of IP block <%s> failed %d\n",
28340a4f2520SRex Zhu 				  adev->ip_blocks[i].version->funcs->name, r);
28350a4f2520SRex Zhu 			return r;
28360a4f2520SRex Zhu 		}
28370a4f2520SRex Zhu 		adev->ip_blocks[i].status.hw = true;
28380a4f2520SRex Zhu 	}
28390a4f2520SRex Zhu 
28400a4f2520SRex Zhu 	return 0;
28410a4f2520SRex Zhu }
28420a4f2520SRex Zhu 
amdgpu_device_fw_loading(struct amdgpu_device * adev)28437a3e0bb2SRex Zhu static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
28447a3e0bb2SRex Zhu {
28457a3e0bb2SRex Zhu 	int r = 0;
28467a3e0bb2SRex Zhu 	int i;
284780f41f84SPrike Liang 	uint32_t smu_version;
28487a3e0bb2SRex Zhu 
28497a3e0bb2SRex Zhu 	if (adev->asic_type >= CHIP_VEGA10) {
28507a3e0bb2SRex Zhu 		for (i = 0; i < adev->num_ip_blocks; i++) {
2851482f0e53SMonk Liu 			if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_PSP)
2852482f0e53SMonk Liu 				continue;
2853482f0e53SMonk Liu 
285414f2fe34SLijo Lazar 			if (!amdgpu_ip_member_of_hwini(adev,
285514f2fe34SLijo Lazar 						       AMD_IP_BLOCK_TYPE_PSP))
285614f2fe34SLijo Lazar 				break;
285714f2fe34SLijo Lazar 
2858e3c1b071Sshaoyunl 			if (!adev->ip_blocks[i].status.sw)
2859e3c1b071Sshaoyunl 				continue;
2860e3c1b071Sshaoyunl 
2861482f0e53SMonk Liu 			/* no need to do the fw loading again if already done*/
2862482f0e53SMonk Liu 			if (adev->ip_blocks[i].status.hw == true)
2863482f0e53SMonk Liu 				break;
2864482f0e53SMonk Liu 
286553b3f8f4SDennis Li 			if (amdgpu_in_reset(adev) || adev->in_suspend) {
2866502d7630SSunil Khatri 				r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
2867502d7630SSunil Khatri 				if (r)
28687a3e0bb2SRex Zhu 					return r;
28697a3e0bb2SRex Zhu 			} else {
287058608034SSunil Khatri 				r = adev->ip_blocks[i].version->funcs->hw_init(&adev->ip_blocks[i]);
28717a3e0bb2SRex Zhu 				if (r) {
28727a3e0bb2SRex Zhu 					DRM_ERROR("hw_init of IP block <%s> failed %d\n",
28737a3e0bb2SRex Zhu 							  adev->ip_blocks[i].version->funcs->name, r);
28747a3e0bb2SRex Zhu 					return r;
28757a3e0bb2SRex Zhu 				}
28767a3e0bb2SRex Zhu 				adev->ip_blocks[i].status.hw = true;
2877502d7630SSunil Khatri 			}
2878482f0e53SMonk Liu 			break;
28797a3e0bb2SRex Zhu 		}
28807a3e0bb2SRex Zhu 	}
2881482f0e53SMonk Liu 
28828973d9ecSEmily Deng 	if (!amdgpu_sriov_vf(adev) || adev->asic_type == CHIP_TONGA)
288380f41f84SPrike Liang 		r = amdgpu_pm_load_smu_firmware(adev, &smu_version);
28847a3e0bb2SRex Zhu 
28857a3e0bb2SRex Zhu 	return r;
28867a3e0bb2SRex Zhu }
28877a3e0bb2SRex Zhu 
amdgpu_device_init_schedulers(struct amdgpu_device * adev)28885fd8518dSAndrey Grodzovsky static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
28895fd8518dSAndrey Grodzovsky {
2890796a9f55SPhilipp Stanner 	struct drm_sched_init_args args = {
2891796a9f55SPhilipp Stanner 		.ops = &amdgpu_sched_ops,
2892796a9f55SPhilipp Stanner 		.num_rqs = DRM_SCHED_PRIORITY_COUNT,
2893796a9f55SPhilipp Stanner 		.timeout_wq = adev->reset_domain->wq,
2894796a9f55SPhilipp Stanner 		.dev = adev->dev,
2895796a9f55SPhilipp Stanner 	};
28965fd8518dSAndrey Grodzovsky 	long timeout;
28975fd8518dSAndrey Grodzovsky 	int r, i;
28985fd8518dSAndrey Grodzovsky 
28995fd8518dSAndrey Grodzovsky 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
29005fd8518dSAndrey Grodzovsky 		struct amdgpu_ring *ring = adev->rings[i];
29015fd8518dSAndrey Grodzovsky 
29025fd8518dSAndrey Grodzovsky 		/* No need to setup the GPU scheduler for rings that don't need it */
29035fd8518dSAndrey Grodzovsky 		if (!ring || ring->no_scheduler)
29045fd8518dSAndrey Grodzovsky 			continue;
29055fd8518dSAndrey Grodzovsky 
29065fd8518dSAndrey Grodzovsky 		switch (ring->funcs->type) {
29075fd8518dSAndrey Grodzovsky 		case AMDGPU_RING_TYPE_GFX:
29085fd8518dSAndrey Grodzovsky 			timeout = adev->gfx_timeout;
29095fd8518dSAndrey Grodzovsky 			break;
29105fd8518dSAndrey Grodzovsky 		case AMDGPU_RING_TYPE_COMPUTE:
29115fd8518dSAndrey Grodzovsky 			timeout = adev->compute_timeout;
29125fd8518dSAndrey Grodzovsky 			break;
29135fd8518dSAndrey Grodzovsky 		case AMDGPU_RING_TYPE_SDMA:
29145fd8518dSAndrey Grodzovsky 			timeout = adev->sdma_timeout;
29155fd8518dSAndrey Grodzovsky 			break;
29165fd8518dSAndrey Grodzovsky 		default:
29175fd8518dSAndrey Grodzovsky 			timeout = adev->video_timeout;
29185fd8518dSAndrey Grodzovsky 			break;
29195fd8518dSAndrey Grodzovsky 		}
29205fd8518dSAndrey Grodzovsky 
2921796a9f55SPhilipp Stanner 		args.timeout = timeout;
2922796a9f55SPhilipp Stanner 		args.credit_limit = ring->num_hw_submission;
2923796a9f55SPhilipp Stanner 		args.score = ring->sched_score;
2924796a9f55SPhilipp Stanner 		args.name = ring->name;
2925796a9f55SPhilipp Stanner 
2926796a9f55SPhilipp Stanner 		r = drm_sched_init(&ring->sched, &args);
29275fd8518dSAndrey Grodzovsky 		if (r) {
29285fd8518dSAndrey Grodzovsky 			DRM_ERROR("Failed to create scheduler on ring %s.\n",
29295fd8518dSAndrey Grodzovsky 				  ring->name);
29305fd8518dSAndrey Grodzovsky 			return r;
29315fd8518dSAndrey Grodzovsky 		}
2932037b98a2SAlex Deucher 		r = amdgpu_uvd_entity_init(adev, ring);
2933037b98a2SAlex Deucher 		if (r) {
2934037b98a2SAlex Deucher 			DRM_ERROR("Failed to create UVD scheduling entity on ring %s.\n",
2935037b98a2SAlex Deucher 				  ring->name);
2936037b98a2SAlex Deucher 			return r;
2937037b98a2SAlex Deucher 		}
2938037b98a2SAlex Deucher 		r = amdgpu_vce_entity_init(adev, ring);
2939037b98a2SAlex Deucher 		if (r) {
2940037b98a2SAlex Deucher 			DRM_ERROR("Failed to create VCE scheduling entity on ring %s.\n",
2941037b98a2SAlex Deucher 				  ring->name);
2942037b98a2SAlex Deucher 			return r;
2943037b98a2SAlex Deucher 		}
29445fd8518dSAndrey Grodzovsky 	}
29455fd8518dSAndrey Grodzovsky 
2946d425c6f4SJames Zhu 	amdgpu_xcp_update_partition_sched_list(adev);
2947d425c6f4SJames Zhu 
29485fd8518dSAndrey Grodzovsky 	return 0;
29495fd8518dSAndrey Grodzovsky }
29505fd8518dSAndrey Grodzovsky 
29515fd8518dSAndrey Grodzovsky 
2952e3ecdffaSAlex Deucher /**
2953e3ecdffaSAlex Deucher  * amdgpu_device_ip_init - run init for hardware IPs
2954e3ecdffaSAlex Deucher  *
2955e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
2956e3ecdffaSAlex Deucher  *
2957e3ecdffaSAlex Deucher  * Main initialization pass for hardware IPs.  The list of all the hardware
2958e3ecdffaSAlex Deucher  * IPs that make up the asic is walked and the sw_init and hw_init callbacks
2959e3ecdffaSAlex Deucher  * are run.  sw_init initializes the software state associated with each IP
2960e3ecdffaSAlex Deucher  * and hw_init initializes the hardware associated with each IP.
2961e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
2962e3ecdffaSAlex Deucher  */
amdgpu_device_ip_init(struct amdgpu_device * adev)296306ec9070SAlex Deucher static int amdgpu_device_ip_init(struct amdgpu_device *adev)
2964d38ceaf9SAlex Deucher {
2965631af731SLijo Lazar 	bool init_badpage;
2966d38ceaf9SAlex Deucher 	int i, r;
2967d38ceaf9SAlex Deucher 
2968c030f2e4Sxinhui pan 	r = amdgpu_ras_init(adev);
2969c030f2e4Sxinhui pan 	if (r)
2970c030f2e4Sxinhui pan 		return r;
2971c030f2e4Sxinhui pan 
2972d38ceaf9SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
2973a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
2974d38ceaf9SAlex Deucher 			continue;
2975df6e463dSSunil Khatri 		if (adev->ip_blocks[i].version->funcs->sw_init) {
2976d5347e8dSSunil Khatri 			r = adev->ip_blocks[i].version->funcs->sw_init(&adev->ip_blocks[i]);
29772c1a2784SAlex Deucher 			if (r) {
2978a1255107SAlex Deucher 				DRM_ERROR("sw_init of IP block <%s> failed %d\n",
2979a1255107SAlex Deucher 					  adev->ip_blocks[i].version->funcs->name, r);
298072d3f592SEmily Deng 				goto init_failed;
29812c1a2784SAlex Deucher 			}
2982df6e463dSSunil Khatri 		}
2983a1255107SAlex Deucher 		adev->ip_blocks[i].status.sw = true;
2984bfca0289SShaoyun Liu 
298514f2fe34SLijo Lazar 		if (!amdgpu_ip_member_of_hwini(
298614f2fe34SLijo Lazar 			    adev, adev->ip_blocks[i].version->type))
298714f2fe34SLijo Lazar 			continue;
298814f2fe34SLijo Lazar 
2989c1c39032SAlex Deucher 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON) {
2990c1c39032SAlex Deucher 			/* need to do common hw init early so everything is set up for gmc */
299158608034SSunil Khatri 			r = adev->ip_blocks[i].version->funcs->hw_init(&adev->ip_blocks[i]);
2992c1c39032SAlex Deucher 			if (r) {
2993c1c39032SAlex Deucher 				DRM_ERROR("hw_init %d failed %d\n", i, r);
2994c1c39032SAlex Deucher 				goto init_failed;
2995c1c39032SAlex Deucher 			}
2996c1c39032SAlex Deucher 			adev->ip_blocks[i].status.hw = true;
2997c1c39032SAlex Deucher 		} else if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
2998d38ceaf9SAlex Deucher 			/* need to do gmc hw init early so we can allocate gpu mem */
2999892deb48SVictor Skvortsov 			/* Try to reserve bad pages early */
3000892deb48SVictor Skvortsov 			if (amdgpu_sriov_vf(adev))
3001892deb48SVictor Skvortsov 				amdgpu_virt_exchange_data(adev);
3002892deb48SVictor Skvortsov 
30037ccfd79fSChristian König 			r = amdgpu_device_mem_scratch_init(adev);
30042c1a2784SAlex Deucher 			if (r) {
30057ccfd79fSChristian König 				DRM_ERROR("amdgpu_mem_scratch_init failed %d\n", r);
300672d3f592SEmily Deng 				goto init_failed;
30072c1a2784SAlex Deucher 			}
300858608034SSunil Khatri 			r = adev->ip_blocks[i].version->funcs->hw_init(&adev->ip_blocks[i]);
30092c1a2784SAlex Deucher 			if (r) {
30102c1a2784SAlex Deucher 				DRM_ERROR("hw_init %d failed %d\n", i, r);
301172d3f592SEmily Deng 				goto init_failed;
30122c1a2784SAlex Deucher 			}
301306ec9070SAlex Deucher 			r = amdgpu_device_wb_init(adev);
30142c1a2784SAlex Deucher 			if (r) {
301506ec9070SAlex Deucher 				DRM_ERROR("amdgpu_device_wb_init failed %d\n", r);
301672d3f592SEmily Deng 				goto init_failed;
30172c1a2784SAlex Deucher 			}
3018a1255107SAlex Deucher 			adev->ip_blocks[i].status.hw = true;
30192493664fSMonk Liu 
30202493664fSMonk Liu 			/* right after GMC hw init, we create CSA */
302102ff519eSAlex Deucher 			if (adev->gfx.mcbp) {
30221e256e27SRex Zhu 				r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj,
302358ab2c08SChristian König 							       AMDGPU_GEM_DOMAIN_VRAM |
302458ab2c08SChristian König 							       AMDGPU_GEM_DOMAIN_GTT,
30251e256e27SRex Zhu 							       AMDGPU_CSA_SIZE);
30262493664fSMonk Liu 				if (r) {
30272493664fSMonk Liu 					DRM_ERROR("allocate CSA failed %d\n", r);
302872d3f592SEmily Deng 					goto init_failed;
30292493664fSMonk Liu 				}
30302493664fSMonk Liu 			}
3031c8031019SArunpravin Paneer Selvam 
3032c8031019SArunpravin Paneer Selvam 			r = amdgpu_seq64_init(adev);
3033c8031019SArunpravin Paneer Selvam 			if (r) {
3034c8031019SArunpravin Paneer Selvam 				DRM_ERROR("allocate seq64 failed %d\n", r);
3035c8031019SArunpravin Paneer Selvam 				goto init_failed;
3036c8031019SArunpravin Paneer Selvam 			}
3037d38ceaf9SAlex Deucher 		}
3038d38ceaf9SAlex Deucher 	}
3039d38ceaf9SAlex Deucher 
3040c9ffa427SYintian Tao 	if (amdgpu_sriov_vf(adev))
304122c16d25SJingwen Chen 		amdgpu_virt_init_data_exchange(adev);
3042c9ffa427SYintian Tao 
3043533aed27SAndrey Grodzovsky 	r = amdgpu_ib_pool_init(adev);
3044533aed27SAndrey Grodzovsky 	if (r) {
3045533aed27SAndrey Grodzovsky 		dev_err(adev->dev, "IB initialization failed (%d).\n", r);
3046533aed27SAndrey Grodzovsky 		amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_IB_INIT_FAIL, 0, r);
3047533aed27SAndrey Grodzovsky 		goto init_failed;
3048533aed27SAndrey Grodzovsky 	}
3049533aed27SAndrey Grodzovsky 
3050c8963ea4SRex Zhu 	r = amdgpu_ucode_create_bo(adev); /* create ucode bo when sw_init complete*/
3051c8963ea4SRex Zhu 	if (r)
305272d3f592SEmily Deng 		goto init_failed;
30530a4f2520SRex Zhu 
30540a4f2520SRex Zhu 	r = amdgpu_device_ip_hw_init_phase1(adev);
30550a4f2520SRex Zhu 	if (r)
305672d3f592SEmily Deng 		goto init_failed;
30570a4f2520SRex Zhu 
30587a3e0bb2SRex Zhu 	r = amdgpu_device_fw_loading(adev);
30597a3e0bb2SRex Zhu 	if (r)
306072d3f592SEmily Deng 		goto init_failed;
30617a3e0bb2SRex Zhu 
30620a4f2520SRex Zhu 	r = amdgpu_device_ip_hw_init_phase2(adev);
30630a4f2520SRex Zhu 	if (r)
306472d3f592SEmily Deng 		goto init_failed;
3065d38ceaf9SAlex Deucher 
3066121a2bc6SAndrey Grodzovsky 	/*
3067121a2bc6SAndrey Grodzovsky 	 * retired pages will be loaded from eeprom and reserved here,
3068121a2bc6SAndrey Grodzovsky 	 * it should be called after amdgpu_device_ip_hw_init_phase2  since
3069121a2bc6SAndrey Grodzovsky 	 * for some ASICs the RAS EEPROM code relies on SMU fully functioning
3070121a2bc6SAndrey Grodzovsky 	 * for I2C communication which only true at this point.
3071b82e65a9SGuchun Chen 	 *
3072b82e65a9SGuchun Chen 	 * amdgpu_ras_recovery_init may fail, but the upper only cares the
3073b82e65a9SGuchun Chen 	 * failure from bad gpu situation and stop amdgpu init process
3074b82e65a9SGuchun Chen 	 * accordingly. For other failed cases, it will still release all
3075b82e65a9SGuchun Chen 	 * the resource and print error message, rather than returning one
3076b82e65a9SGuchun Chen 	 * negative value to upper level.
3077121a2bc6SAndrey Grodzovsky 	 *
3078121a2bc6SAndrey Grodzovsky 	 * Note: theoretically, this should be called before all vram allocations
3079121a2bc6SAndrey Grodzovsky 	 * to protect retired page from abusing
3080121a2bc6SAndrey Grodzovsky 	 */
3081631af731SLijo Lazar 	init_badpage = (adev->init_lvl->level != AMDGPU_INIT_LEVEL_MINIMAL_XGMI);
3082631af731SLijo Lazar 	r = amdgpu_ras_recovery_init(adev, init_badpage);
3083b82e65a9SGuchun Chen 	if (r)
3084b82e65a9SGuchun Chen 		goto init_failed;
3085121a2bc6SAndrey Grodzovsky 
3086cfbb6b00SAndrey Grodzovsky 	/**
3087cfbb6b00SAndrey Grodzovsky 	 * In case of XGMI grab extra reference for reset domain for this device
3088cfbb6b00SAndrey Grodzovsky 	 */
3089a4c63cafSAndrey Grodzovsky 	if (adev->gmc.xgmi.num_physical_nodes > 1) {
3090cfbb6b00SAndrey Grodzovsky 		if (amdgpu_xgmi_add_device(adev) == 0) {
30912efc30f0SVignesh Chander 			if (!amdgpu_sriov_vf(adev)) {
3092cfbb6b00SAndrey Grodzovsky 				struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
3093a4c63cafSAndrey Grodzovsky 
3094dfd0287bSLiang He 				if (WARN_ON(!hive)) {
3095dfd0287bSLiang He 					r = -ENOENT;
3096dfd0287bSLiang He 					goto init_failed;
3097dfd0287bSLiang He 				}
3098dfd0287bSLiang He 
3099cfbb6b00SAndrey Grodzovsky 				if (!hive->reset_domain ||
3100cfbb6b00SAndrey Grodzovsky 				    !amdgpu_reset_get_reset_domain(hive->reset_domain)) {
3101cfbb6b00SAndrey Grodzovsky 					r = -ENOENT;
31029dfa4860SYiPeng Chai 					amdgpu_put_xgmi_hive(hive);
3103a4c63cafSAndrey Grodzovsky 					goto init_failed;
3104a4c63cafSAndrey Grodzovsky 				}
3105a4c63cafSAndrey Grodzovsky 
3106cfbb6b00SAndrey Grodzovsky 				/* Drop the early temporary reset domain we created for device */
3107cfbb6b00SAndrey Grodzovsky 				amdgpu_reset_put_reset_domain(adev->reset_domain);
3108cfbb6b00SAndrey Grodzovsky 				adev->reset_domain = hive->reset_domain;
31099dfa4860SYiPeng Chai 				amdgpu_put_xgmi_hive(hive);
3110a4c63cafSAndrey Grodzovsky 			}
3111a4c63cafSAndrey Grodzovsky 		}
311246c67660Sshaoyunl 	}
3113a4c63cafSAndrey Grodzovsky 
31145fd8518dSAndrey Grodzovsky 	r = amdgpu_device_init_schedulers(adev);
31155fd8518dSAndrey Grodzovsky 	if (r)
31165fd8518dSAndrey Grodzovsky 		goto init_failed;
3117e3c1b071Sshaoyunl 
3118b7043800SAlex Deucher 	if (adev->mman.buffer_funcs_ring->sched.ready)
3119b7043800SAlex Deucher 		amdgpu_ttm_set_buffer_funcs_status(adev, true);
3120b7043800SAlex Deucher 
3121e3c1b071Sshaoyunl 	/* Don't init kfd if whole hive need to be reset during init */
31225839d27dSLijo Lazar 	if (adev->init_lvl->level != AMDGPU_INIT_LEVEL_MINIMAL_XGMI) {
312384b4dd3fSPhilip Yang 		kgd2kfd_init_zone_device(adev);
31241884734aSpding 		amdgpu_amdkfd_device_init(adev);
312584b4dd3fSPhilip Yang 	}
3126c6332b97Spding 
3127bd607166SKent Russell 	amdgpu_fru_get_product_info(adev);
3128bd607166SKent Russell 
3129a91d91b6STony Yi 	if (!amdgpu_sriov_vf(adev) || amdgpu_sriov_ras_cper_en(adev))
313092d5d2a0SHawking Zhang 		r = amdgpu_cper_init(adev);
313192d5d2a0SHawking Zhang 
313272d3f592SEmily Deng init_failed:
3133c6332b97Spding 
313472d3f592SEmily Deng 	return r;
3135d38ceaf9SAlex Deucher }
3136d38ceaf9SAlex Deucher 
3137e3ecdffaSAlex Deucher /**
3138e3ecdffaSAlex Deucher  * amdgpu_device_fill_reset_magic - writes reset magic to gart pointer
3139e3ecdffaSAlex Deucher  *
3140e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3141e3ecdffaSAlex Deucher  *
3142e3ecdffaSAlex Deucher  * Writes a reset magic value to the gart pointer in VRAM.  The driver calls
3143e3ecdffaSAlex Deucher  * this function before a GPU reset.  If the value is retained after a
3144a567db80SRandy Dunlap  * GPU reset, VRAM has not been lost. Some GPU resets may destroy VRAM contents.
3145e3ecdffaSAlex Deucher  */
amdgpu_device_fill_reset_magic(struct amdgpu_device * adev)314606ec9070SAlex Deucher static void amdgpu_device_fill_reset_magic(struct amdgpu_device *adev)
31470c49e0b8SChunming Zhou {
31480c49e0b8SChunming Zhou 	memcpy(adev->reset_magic, adev->gart.ptr, AMDGPU_RESET_MAGIC_NUM);
31490c49e0b8SChunming Zhou }
31500c49e0b8SChunming Zhou 
3151e3ecdffaSAlex Deucher /**
3152e3ecdffaSAlex Deucher  * amdgpu_device_check_vram_lost - check if vram is valid
3153e3ecdffaSAlex Deucher  *
3154e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3155e3ecdffaSAlex Deucher  *
3156e3ecdffaSAlex Deucher  * Checks the reset magic value written to the gart pointer in VRAM.
3157e3ecdffaSAlex Deucher  * The driver calls this after a GPU reset to see if the contents of
3158e3ecdffaSAlex Deucher  * VRAM is lost or now.
3159e3ecdffaSAlex Deucher  * returns true if vram is lost, false if not.
3160e3ecdffaSAlex Deucher  */
amdgpu_device_check_vram_lost(struct amdgpu_device * adev)316106ec9070SAlex Deucher static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev)
31620c49e0b8SChunming Zhou {
3163dadce777SEvan Quan 	if (memcmp(adev->gart.ptr, adev->reset_magic,
3164dadce777SEvan Quan 			AMDGPU_RESET_MAGIC_NUM))
3165dadce777SEvan Quan 		return true;
3166dadce777SEvan Quan 
316753b3f8f4SDennis Li 	if (!amdgpu_in_reset(adev))
3168dadce777SEvan Quan 		return false;
3169dadce777SEvan Quan 
3170dadce777SEvan Quan 	/*
3171dadce777SEvan Quan 	 * For all ASICs with baco/mode1 reset, the VRAM is
3172dadce777SEvan Quan 	 * always assumed to be lost.
3173dadce777SEvan Quan 	 */
3174dadce777SEvan Quan 	switch (amdgpu_asic_reset_method(adev)) {
3175dadce777SEvan Quan 	case AMD_RESET_METHOD_BACO:
3176dadce777SEvan Quan 	case AMD_RESET_METHOD_MODE1:
3177dadce777SEvan Quan 		return true;
3178dadce777SEvan Quan 	default:
3179dadce777SEvan Quan 		return false;
3180dadce777SEvan Quan 	}
31810c49e0b8SChunming Zhou }
31820c49e0b8SChunming Zhou 
3183e3ecdffaSAlex Deucher /**
31841112a46bSRex Zhu  * amdgpu_device_set_cg_state - set clockgating for amdgpu device
3185e3ecdffaSAlex Deucher  *
3186e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3187b8b72130Syu kuai  * @state: clockgating state (gate or ungate)
3188e3ecdffaSAlex Deucher  *
3189e3ecdffaSAlex Deucher  * The list of all the hardware IPs that make up the asic is walked and the
31901112a46bSRex Zhu  * set_clockgating_state callbacks are run.
31911112a46bSRex Zhu  * Late initialization pass enabling clockgating for hardware IPs.
31921112a46bSRex Zhu  * Fini or suspend, pass disabling clockgating for hardware IPs.
3193e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
3194e3ecdffaSAlex Deucher  */
3195fdd34271SRex Zhu 
amdgpu_device_set_cg_state(struct amdgpu_device * adev,enum amd_clockgating_state state)31965d89bb2dSLijo Lazar int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
31971112a46bSRex Zhu 			       enum amd_clockgating_state state)
31982dc80b00SShirish S {
31991112a46bSRex Zhu 	int i, j, r;
32002dc80b00SShirish S 
32014a2ba394SShaoyun Liu 	if (amdgpu_emu_mode == 1)
32024a2ba394SShaoyun Liu 		return 0;
32034a2ba394SShaoyun Liu 
32041112a46bSRex Zhu 	for (j = 0; j < adev->num_ip_blocks; j++) {
32051112a46bSRex Zhu 		i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
3206a2d31dc3SRex Zhu 		if (!adev->ip_blocks[i].status.late_initialized)
32072dc80b00SShirish S 			continue;
320847198eb7SAlex Deucher 		/* skip CG for GFX, SDMA on S0ix */
32095d70a549SPratik Vishwakarma 		if (adev->in_s0ix &&
321047198eb7SAlex Deucher 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
321147198eb7SAlex Deucher 		     adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
32125d70a549SPratik Vishwakarma 			continue;
32132dc80b00SShirish S 		/* skip CG for VCE/UVD, it's handled specially */
32142dc80b00SShirish S 		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
321557716327SRex Zhu 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
321634319b32SRex Zhu 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCN &&
321752f2e779SLeo Liu 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_JPEG &&
321857716327SRex Zhu 		    adev->ip_blocks[i].version->funcs->set_clockgating_state) {
32192dc80b00SShirish S 			/* enable clockgating to save power */
3220f2ba8c3dSBoyuan Zhang 			r = adev->ip_blocks[i].version->funcs->set_clockgating_state(&adev->ip_blocks[i],
32211112a46bSRex Zhu 										     state);
32222dc80b00SShirish S 			if (r) {
32232dc80b00SShirish S 				DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n",
32242dc80b00SShirish S 					  adev->ip_blocks[i].version->funcs->name, r);
32252dc80b00SShirish S 				return r;
32262dc80b00SShirish S 			}
32272dc80b00SShirish S 		}
32282dc80b00SShirish S 	}
322906b18f61SHuang Rui 
3230c9f96fd5SRex Zhu 	return 0;
3231c9f96fd5SRex Zhu }
323206b18f61SHuang Rui 
amdgpu_device_set_pg_state(struct amdgpu_device * adev,enum amd_powergating_state state)32335d89bb2dSLijo Lazar int amdgpu_device_set_pg_state(struct amdgpu_device *adev,
32345d89bb2dSLijo Lazar 			       enum amd_powergating_state state)
3235c9f96fd5SRex Zhu {
32361112a46bSRex Zhu 	int i, j, r;
3237c9f96fd5SRex Zhu 
3238c9f96fd5SRex Zhu 	if (amdgpu_emu_mode == 1)
3239c9f96fd5SRex Zhu 		return 0;
3240c9f96fd5SRex Zhu 
32411112a46bSRex Zhu 	for (j = 0; j < adev->num_ip_blocks; j++) {
32421112a46bSRex Zhu 		i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
3243a2d31dc3SRex Zhu 		if (!adev->ip_blocks[i].status.late_initialized)
3244c9f96fd5SRex Zhu 			continue;
324547198eb7SAlex Deucher 		/* skip PG for GFX, SDMA on S0ix */
32465d70a549SPratik Vishwakarma 		if (adev->in_s0ix &&
324747198eb7SAlex Deucher 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
324847198eb7SAlex Deucher 		     adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
32495d70a549SPratik Vishwakarma 			continue;
3250c9f96fd5SRex Zhu 		/* skip CG for VCE/UVD, it's handled specially */
3251c9f96fd5SRex Zhu 		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
3252c9f96fd5SRex Zhu 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
3253c9f96fd5SRex Zhu 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCN &&
325452f2e779SLeo Liu 		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_JPEG &&
3255c9f96fd5SRex Zhu 		    adev->ip_blocks[i].version->funcs->set_powergating_state) {
3256c9f96fd5SRex Zhu 			/* enable powergating to save power */
325780d80511SBoyuan Zhang 			r = adev->ip_blocks[i].version->funcs->set_powergating_state(&adev->ip_blocks[i],
32581112a46bSRex Zhu 											state);
3259c9f96fd5SRex Zhu 			if (r) {
3260c9f96fd5SRex Zhu 				DRM_ERROR("set_powergating_state(gate) of IP block <%s> failed %d\n",
3261c9f96fd5SRex Zhu 					  adev->ip_blocks[i].version->funcs->name, r);
3262c9f96fd5SRex Zhu 				return r;
3263c9f96fd5SRex Zhu 			}
3264c9f96fd5SRex Zhu 		}
3265c9f96fd5SRex Zhu 	}
32662dc80b00SShirish S 	return 0;
32672dc80b00SShirish S }
32682dc80b00SShirish S 
amdgpu_device_enable_mgpu_fan_boost(void)3269beff74bcSAlex Deucher static int amdgpu_device_enable_mgpu_fan_boost(void)
3270beff74bcSAlex Deucher {
3271beff74bcSAlex Deucher 	struct amdgpu_gpu_instance *gpu_ins;
3272beff74bcSAlex Deucher 	struct amdgpu_device *adev;
3273beff74bcSAlex Deucher 	int i, ret = 0;
3274beff74bcSAlex Deucher 
3275beff74bcSAlex Deucher 	mutex_lock(&mgpu_info.mutex);
3276beff74bcSAlex Deucher 
3277beff74bcSAlex Deucher 	/*
3278beff74bcSAlex Deucher 	 * MGPU fan boost feature should be enabled
3279beff74bcSAlex Deucher 	 * only when there are two or more dGPUs in
3280beff74bcSAlex Deucher 	 * the system
3281beff74bcSAlex Deucher 	 */
3282beff74bcSAlex Deucher 	if (mgpu_info.num_dgpu < 2)
3283beff74bcSAlex Deucher 		goto out;
3284beff74bcSAlex Deucher 
3285beff74bcSAlex Deucher 	for (i = 0; i < mgpu_info.num_dgpu; i++) {
3286beff74bcSAlex Deucher 		gpu_ins = &(mgpu_info.gpu_ins[i]);
3287beff74bcSAlex Deucher 		adev = gpu_ins->adev;
3288beff74bcSAlex Deucher 		if (!(adev->flags & AMD_IS_APU) &&
3289f10bb940SEvan Quan 		    !gpu_ins->mgpu_fan_enabled) {
3290beff74bcSAlex Deucher 			ret = amdgpu_dpm_enable_mgpu_fan_boost(adev);
3291beff74bcSAlex Deucher 			if (ret)
3292beff74bcSAlex Deucher 				break;
3293beff74bcSAlex Deucher 
3294beff74bcSAlex Deucher 			gpu_ins->mgpu_fan_enabled = 1;
3295beff74bcSAlex Deucher 		}
3296beff74bcSAlex Deucher 	}
3297beff74bcSAlex Deucher 
3298beff74bcSAlex Deucher out:
3299beff74bcSAlex Deucher 	mutex_unlock(&mgpu_info.mutex);
3300beff74bcSAlex Deucher 
3301beff74bcSAlex Deucher 	return ret;
3302beff74bcSAlex Deucher }
3303beff74bcSAlex Deucher 
3304e3ecdffaSAlex Deucher /**
3305e3ecdffaSAlex Deucher  * amdgpu_device_ip_late_init - run late init for hardware IPs
3306e3ecdffaSAlex Deucher  *
3307e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3308e3ecdffaSAlex Deucher  *
3309e3ecdffaSAlex Deucher  * Late initialization pass for hardware IPs.  The list of all the hardware
3310e3ecdffaSAlex Deucher  * IPs that make up the asic is walked and the late_init callbacks are run.
3311e3ecdffaSAlex Deucher  * late_init covers any special initialization that an IP requires
3312e3ecdffaSAlex Deucher  * after all of the have been initialized or something that needs to happen
3313e3ecdffaSAlex Deucher  * late in the init process.
3314e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
3315e3ecdffaSAlex Deucher  */
amdgpu_device_ip_late_init(struct amdgpu_device * adev)331606ec9070SAlex Deucher static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
3317d38ceaf9SAlex Deucher {
331860599a03SEvan Quan 	struct amdgpu_gpu_instance *gpu_instance;
3319d38ceaf9SAlex Deucher 	int i = 0, r;
3320d38ceaf9SAlex Deucher 
3321d38ceaf9SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
332273f847dbSRex Zhu 		if (!adev->ip_blocks[i].status.hw)
3323d38ceaf9SAlex Deucher 			continue;
3324a1255107SAlex Deucher 		if (adev->ip_blocks[i].version->funcs->late_init) {
33253138ab2cSSunil Khatri 			r = adev->ip_blocks[i].version->funcs->late_init(&adev->ip_blocks[i]);
33262c1a2784SAlex Deucher 			if (r) {
3327a1255107SAlex Deucher 				DRM_ERROR("late_init of IP block <%s> failed %d\n",
3328a1255107SAlex Deucher 					  adev->ip_blocks[i].version->funcs->name, r);
3329d38ceaf9SAlex Deucher 				return r;
3330d38ceaf9SAlex Deucher 			}
3331d38ceaf9SAlex Deucher 		}
333273f847dbSRex Zhu 		adev->ip_blocks[i].status.late_initialized = true;
3333b0b00ff1SArindam Nath 	}
33342dc80b00SShirish S 
3335867e24caSyipechai 	r = amdgpu_ras_late_init(adev);
3336867e24caSyipechai 	if (r) {
3337867e24caSyipechai 		DRM_ERROR("amdgpu_ras_late_init failed %d", r);
3338867e24caSyipechai 		return r;
3339867e24caSyipechai 	}
3340867e24caSyipechai 
3341e283f4fbSLijo Lazar 	if (!amdgpu_reset_in_recovery(adev))
3342a891d239SDennis Li 		amdgpu_ras_set_error_query_ready(adev, true);
3343a891d239SDennis Li 
33441112a46bSRex Zhu 	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
33451112a46bSRex Zhu 	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);
3346916ac57fSRex Zhu 
334706ec9070SAlex Deucher 	amdgpu_device_fill_reset_magic(adev);
3348d38ceaf9SAlex Deucher 
3349beff74bcSAlex Deucher 	r = amdgpu_device_enable_mgpu_fan_boost();
3350beff74bcSAlex Deucher 	if (r)
3351beff74bcSAlex Deucher 		DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
3352beff74bcSAlex Deucher 
33534da8b639Ssashank saye 	/* For passthrough configuration on arcturus and aldebaran, enable special handling SBR */
335447fc644fSSrinivasan Shanmugam 	if (amdgpu_passthrough(adev) &&
335547fc644fSSrinivasan Shanmugam 	    ((adev->asic_type == CHIP_ARCTURUS && adev->gmc.xgmi.num_physical_nodes > 1) ||
33564da8b639Ssashank saye 	     adev->asic_type == CHIP_ALDEBARAN))
3357bc143d8bSEvan Quan 		amdgpu_dpm_handle_passthrough_sbr(adev, true);
335860599a03SEvan Quan 
335960599a03SEvan Quan 	if (adev->gmc.xgmi.num_physical_nodes > 1) {
336060599a03SEvan Quan 		mutex_lock(&mgpu_info.mutex);
336160599a03SEvan Quan 
336260599a03SEvan Quan 		/*
336360599a03SEvan Quan 		 * Reset device p-state to low as this was booted with high.
336460599a03SEvan Quan 		 *
336560599a03SEvan Quan 		 * This should be performed only after all devices from the same
336660599a03SEvan Quan 		 * hive get initialized.
336760599a03SEvan Quan 		 *
336860599a03SEvan Quan 		 * However, it's unknown how many device in the hive in advance.
336960599a03SEvan Quan 		 * As this is counted one by one during devices initializations.
337060599a03SEvan Quan 		 *
337160599a03SEvan Quan 		 * So, we wait for all XGMI interlinked devices initialized.
337260599a03SEvan Quan 		 * This may bring some delays as those devices may come from
337360599a03SEvan Quan 		 * different hives. But that should be OK.
337460599a03SEvan Quan 		 */
337560599a03SEvan Quan 		if (mgpu_info.num_dgpu == adev->gmc.xgmi.num_physical_nodes) {
337660599a03SEvan Quan 			for (i = 0; i < mgpu_info.num_gpu; i++) {
337760599a03SEvan Quan 				gpu_instance = &(mgpu_info.gpu_ins[i]);
337860599a03SEvan Quan 				if (gpu_instance->adev->flags & AMD_IS_APU)
337960599a03SEvan Quan 					continue;
338060599a03SEvan Quan 
3381d84a430dSJonathan Kim 				r = amdgpu_xgmi_set_pstate(gpu_instance->adev,
3382d84a430dSJonathan Kim 						AMDGPU_XGMI_PSTATE_MIN);
338360599a03SEvan Quan 				if (r) {
338460599a03SEvan Quan 					DRM_ERROR("pstate setting failed (%d).\n", r);
338560599a03SEvan Quan 					break;
338660599a03SEvan Quan 				}
338760599a03SEvan Quan 			}
338860599a03SEvan Quan 		}
338960599a03SEvan Quan 
339060599a03SEvan Quan 		mutex_unlock(&mgpu_info.mutex);
339160599a03SEvan Quan 	}
339260599a03SEvan Quan 
3393d38ceaf9SAlex Deucher 	return 0;
3394d38ceaf9SAlex Deucher }
3395d38ceaf9SAlex Deucher 
amdgpu_ip_block_hw_fini(struct amdgpu_ip_block * ip_block)3396dad01f93SSunil Khatri static void amdgpu_ip_block_hw_fini(struct amdgpu_ip_block *ip_block)
3397dad01f93SSunil Khatri {
3398dad01f93SSunil Khatri 	int r;
3399dad01f93SSunil Khatri 
3400dac64cb3SDan Carpenter 	if (!ip_block->version->funcs->hw_fini) {
3401dad01f93SSunil Khatri 		DRM_ERROR("hw_fini of IP block <%s> not defined\n",
3402dad01f93SSunil Khatri 			  ip_block->version->funcs->name);
3403dad01f93SSunil Khatri 	} else {
3404dad01f93SSunil Khatri 		r = ip_block->version->funcs->hw_fini(ip_block);
3405dad01f93SSunil Khatri 		/* XXX handle errors */
3406dad01f93SSunil Khatri 		if (r) {
3407dad01f93SSunil Khatri 			DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
3408dad01f93SSunil Khatri 				  ip_block->version->funcs->name, r);
3409dad01f93SSunil Khatri 		}
3410dad01f93SSunil Khatri 	}
3411dad01f93SSunil Khatri 
3412dad01f93SSunil Khatri 	ip_block->status.hw = false;
3413dad01f93SSunil Khatri }
3414dad01f93SSunil Khatri 
3415613aa3eaSLang Yu /**
3416613aa3eaSLang Yu  * amdgpu_device_smu_fini_early - smu hw_fini wrapper
3417613aa3eaSLang Yu  *
3418613aa3eaSLang Yu  * @adev: amdgpu_device pointer
3419613aa3eaSLang Yu  *
3420613aa3eaSLang Yu  * For ASICs need to disable SMC first
3421613aa3eaSLang Yu  */
amdgpu_device_smu_fini_early(struct amdgpu_device * adev)3422613aa3eaSLang Yu static void amdgpu_device_smu_fini_early(struct amdgpu_device *adev)
3423613aa3eaSLang Yu {
3424dad01f93SSunil Khatri 	int i;
3425613aa3eaSLang Yu 
34264e8303cfSLijo Lazar 	if (amdgpu_ip_version(adev, GC_HWIP, 0) > IP_VERSION(9, 0, 0))
3427613aa3eaSLang Yu 		return;
3428613aa3eaSLang Yu 
3429613aa3eaSLang Yu 	for (i = 0; i < adev->num_ip_blocks; i++) {
3430613aa3eaSLang Yu 		if (!adev->ip_blocks[i].status.hw)
3431613aa3eaSLang Yu 			continue;
3432613aa3eaSLang Yu 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
3433dad01f93SSunil Khatri 			amdgpu_ip_block_hw_fini(&adev->ip_blocks[i]);
3434613aa3eaSLang Yu 			break;
3435613aa3eaSLang Yu 		}
3436613aa3eaSLang Yu 	}
3437613aa3eaSLang Yu }
3438613aa3eaSLang Yu 
amdgpu_device_ip_fini_early(struct amdgpu_device * adev)3439e9669fb7SAndrey Grodzovsky static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
3440d38ceaf9SAlex Deucher {
3441d38ceaf9SAlex Deucher 	int i, r;
3442d38ceaf9SAlex Deucher 
3443e9669fb7SAndrey Grodzovsky 	for (i = 0; i < adev->num_ip_blocks; i++) {
3444e9669fb7SAndrey Grodzovsky 		if (!adev->ip_blocks[i].version->funcs->early_fini)
3445e9669fb7SAndrey Grodzovsky 			continue;
34465278a159SStanley.Yang 
344790410d39SSunil Khatri 		r = adev->ip_blocks[i].version->funcs->early_fini(&adev->ip_blocks[i]);
3448e9669fb7SAndrey Grodzovsky 		if (r) {
3449e9669fb7SAndrey Grodzovsky 			DRM_DEBUG("early_fini of IP block <%s> failed %d\n",
3450e9669fb7SAndrey Grodzovsky 				  adev->ip_blocks[i].version->funcs->name, r);
3451e9669fb7SAndrey Grodzovsky 		}
3452e9669fb7SAndrey Grodzovsky 	}
3453c030f2e4Sxinhui pan 
345405df1f01SRex Zhu 	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
3455fdd34271SRex Zhu 	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
3456fdd34271SRex Zhu 
34577270e895STianci.Yin 	amdgpu_amdkfd_suspend(adev, false);
34587270e895STianci.Yin 
3459a567db80SRandy Dunlap 	/* Workaround for ASICs need to disable SMC first */
3460613aa3eaSLang Yu 	amdgpu_device_smu_fini_early(adev);
34613e96dbfdSAlex Deucher 
3462d38ceaf9SAlex Deucher 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
3463a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.hw)
3464d38ceaf9SAlex Deucher 			continue;
34658201a67aSRex Zhu 
3466dad01f93SSunil Khatri 		amdgpu_ip_block_hw_fini(&adev->ip_blocks[i]);
3467d38ceaf9SAlex Deucher 	}
3468d38ceaf9SAlex Deucher 
34696effad8aSGuchun Chen 	if (amdgpu_sriov_vf(adev)) {
34706effad8aSGuchun Chen 		if (amdgpu_virt_release_full_gpu(adev, false))
34716effad8aSGuchun Chen 			DRM_ERROR("failed to release exclusive mode on fini\n");
34726effad8aSGuchun Chen 	}
34736effad8aSGuchun Chen 
3474e9669fb7SAndrey Grodzovsky 	return 0;
3475e9669fb7SAndrey Grodzovsky }
3476e9669fb7SAndrey Grodzovsky 
3477e9669fb7SAndrey Grodzovsky /**
3478e9669fb7SAndrey Grodzovsky  * amdgpu_device_ip_fini - run fini for hardware IPs
3479e9669fb7SAndrey Grodzovsky  *
3480e9669fb7SAndrey Grodzovsky  * @adev: amdgpu_device pointer
3481e9669fb7SAndrey Grodzovsky  *
3482e9669fb7SAndrey Grodzovsky  * Main teardown pass for hardware IPs.  The list of all the hardware
3483e9669fb7SAndrey Grodzovsky  * IPs that make up the asic is walked and the hw_fini and sw_fini callbacks
3484e9669fb7SAndrey Grodzovsky  * are run.  hw_fini tears down the hardware associated with each IP
3485e9669fb7SAndrey Grodzovsky  * and sw_fini tears down any software state associated with each IP.
3486e9669fb7SAndrey Grodzovsky  * Returns 0 on success, negative error code on failure.
3487e9669fb7SAndrey Grodzovsky  */
amdgpu_device_ip_fini(struct amdgpu_device * adev)3488e9669fb7SAndrey Grodzovsky static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
3489e9669fb7SAndrey Grodzovsky {
3490e9669fb7SAndrey Grodzovsky 	int i, r;
3491e9669fb7SAndrey Grodzovsky 
349292d5d2a0SHawking Zhang 	amdgpu_cper_fini(adev);
349392d5d2a0SHawking Zhang 
3494e9669fb7SAndrey Grodzovsky 	if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done)
3495e9669fb7SAndrey Grodzovsky 		amdgpu_virt_release_ras_err_handler_data(adev);
3496e9669fb7SAndrey Grodzovsky 
3497e9669fb7SAndrey Grodzovsky 	if (adev->gmc.xgmi.num_physical_nodes > 1)
3498e9669fb7SAndrey Grodzovsky 		amdgpu_xgmi_remove_device(adev);
3499e9669fb7SAndrey Grodzovsky 
3500e9669fb7SAndrey Grodzovsky 	amdgpu_amdkfd_device_fini_sw(adev);
35019950cda2SAlex Deucher 
3502d38ceaf9SAlex Deucher 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
3503a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.sw)
3504d38ceaf9SAlex Deucher 			continue;
3505c12aba3aSMonk Liu 
3506c12aba3aSMonk Liu 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
3507c8963ea4SRex Zhu 			amdgpu_ucode_free_bo(adev);
35081e256e27SRex Zhu 			amdgpu_free_static_csa(&adev->virt.csa_obj);
3509c12aba3aSMonk Liu 			amdgpu_device_wb_fini(adev);
35107ccfd79fSChristian König 			amdgpu_device_mem_scratch_fini(adev);
3511533aed27SAndrey Grodzovsky 			amdgpu_ib_pool_fini(adev);
3512c8031019SArunpravin Paneer Selvam 			amdgpu_seq64_fini(adev);
3513e7afa85aSZhenGuo Yin 			amdgpu_doorbell_fini(adev);
3514c12aba3aSMonk Liu 		}
3515278b8fbfSSunil Khatri 		if (adev->ip_blocks[i].version->funcs->sw_fini) {
351636aa9ab9SSunil Khatri 			r = adev->ip_blocks[i].version->funcs->sw_fini(&adev->ip_blocks[i]);
3517d38ceaf9SAlex Deucher 			/* XXX handle errors */
35182c1a2784SAlex Deucher 			if (r) {
3519a1255107SAlex Deucher 				DRM_DEBUG("sw_fini of IP block <%s> failed %d\n",
3520a1255107SAlex Deucher 					  adev->ip_blocks[i].version->funcs->name, r);
35212c1a2784SAlex Deucher 			}
3522278b8fbfSSunil Khatri 		}
3523a1255107SAlex Deucher 		adev->ip_blocks[i].status.sw = false;
3524a1255107SAlex Deucher 		adev->ip_blocks[i].status.valid = false;
3525d38ceaf9SAlex Deucher 	}
3526d38ceaf9SAlex Deucher 
3527a6dcfd9cSMonk Liu 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
3528a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.late_initialized)
35298a2eef1dSGrazvydas Ignotas 			continue;
3530a1255107SAlex Deucher 		if (adev->ip_blocks[i].version->funcs->late_fini)
353147d827f9SSunil Khatri 			adev->ip_blocks[i].version->funcs->late_fini(&adev->ip_blocks[i]);
3532a1255107SAlex Deucher 		adev->ip_blocks[i].status.late_initialized = false;
3533a6dcfd9cSMonk Liu 	}
3534a6dcfd9cSMonk Liu 
3535c030f2e4Sxinhui pan 	amdgpu_ras_fini(adev);
3536c030f2e4Sxinhui pan 
3537d38ceaf9SAlex Deucher 	return 0;
3538d38ceaf9SAlex Deucher }
3539d38ceaf9SAlex Deucher 
3540e3ecdffaSAlex Deucher /**
3541beff74bcSAlex Deucher  * amdgpu_device_delayed_init_work_handler - work handler for IB tests
3542e3ecdffaSAlex Deucher  *
35431112a46bSRex Zhu  * @work: work_struct.
3544e3ecdffaSAlex Deucher  */
amdgpu_device_delayed_init_work_handler(struct work_struct * work)3545beff74bcSAlex Deucher static void amdgpu_device_delayed_init_work_handler(struct work_struct *work)
35462dc80b00SShirish S {
35472dc80b00SShirish S 	struct amdgpu_device *adev =
3548beff74bcSAlex Deucher 		container_of(work, struct amdgpu_device, delayed_init_work.work);
3549916ac57fSRex Zhu 	int r;
3550916ac57fSRex Zhu 
3551916ac57fSRex Zhu 	r = amdgpu_ib_ring_tests(adev);
3552916ac57fSRex Zhu 	if (r)
3553916ac57fSRex Zhu 		DRM_ERROR("ib ring test failed (%d).\n", r);
35542dc80b00SShirish S }
35552dc80b00SShirish S 
amdgpu_device_delay_enable_gfx_off(struct work_struct * work)35561e317b99SRex Zhu static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)
35571e317b99SRex Zhu {
35581e317b99SRex Zhu 	struct amdgpu_device *adev =
35591e317b99SRex Zhu 		container_of(work, struct amdgpu_device, gfx.gfx_off_delay_work.work);
35601e317b99SRex Zhu 
356190a92662SMichel Dänzer 	WARN_ON_ONCE(adev->gfx.gfx_off_state);
356290a92662SMichel Dänzer 	WARN_ON_ONCE(adev->gfx.gfx_off_req_count);
356390a92662SMichel Dänzer 
3564ff69bba0SBoyuan Zhang 	if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, true, 0))
35651e317b99SRex Zhu 		adev->gfx.gfx_off_state = true;
35661e317b99SRex Zhu }
35671e317b99SRex Zhu 
3568e3ecdffaSAlex Deucher /**
3569e7854a03SAlex Deucher  * amdgpu_device_ip_suspend_phase1 - run suspend for hardware IPs (phase 1)
3570e3ecdffaSAlex Deucher  *
3571e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3572e3ecdffaSAlex Deucher  *
3573e3ecdffaSAlex Deucher  * Main suspend function for hardware IPs.  The list of all the hardware
3574e3ecdffaSAlex Deucher  * IPs that make up the asic is walked, clockgating is disabled and the
3575e3ecdffaSAlex Deucher  * suspend callbacks are run.  suspend puts the hardware and software state
3576e3ecdffaSAlex Deucher  * in each IP into a state suitable for suspend.
3577e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
3578e3ecdffaSAlex Deucher  */
amdgpu_device_ip_suspend_phase1(struct amdgpu_device * adev)3579e7854a03SAlex Deucher static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev)
3580e7854a03SAlex Deucher {
3581e7854a03SAlex Deucher 	int i, r;
3582e7854a03SAlex Deucher 
3583ced1ba97SPrike Liang 	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
3584ced1ba97SPrike Liang 	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
358505df1f01SRex Zhu 
3586b31d6adaSEvan Quan 	/*
3587b31d6adaSEvan Quan 	 * Per PMFW team's suggestion, driver needs to handle gfxoff
3588b31d6adaSEvan Quan 	 * and df cstate features disablement for gpu reset(e.g. Mode1Reset)
3589b31d6adaSEvan Quan 	 * scenario. Add the missing df cstate disablement here.
3590b31d6adaSEvan Quan 	 */
3591b31d6adaSEvan Quan 	if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW))
3592b31d6adaSEvan Quan 		dev_warn(adev->dev, "Failed to disallow df cstate");
3593b31d6adaSEvan Quan 
3594e7854a03SAlex Deucher 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
3595e7854a03SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
3596e7854a03SAlex Deucher 			continue;
35972b9f7848SNirmoy Das 
3598e7854a03SAlex Deucher 		/* displays are handled separately */
35992b9f7848SNirmoy Das 		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_DCE)
36002b9f7848SNirmoy Das 			continue;
36012b9f7848SNirmoy Das 
3602e7854a03SAlex Deucher 		/* XXX handle errors */
3603e095026fSSunil Khatri 		r = amdgpu_ip_block_suspend(&adev->ip_blocks[i]);
3604e095026fSSunil Khatri 		if (r)
3605482f0e53SMonk Liu 			return r;
3606e7854a03SAlex Deucher 	}
36072b9f7848SNirmoy Das 
3608e7854a03SAlex Deucher 	return 0;
3609e7854a03SAlex Deucher }
3610e7854a03SAlex Deucher 
3611e7854a03SAlex Deucher /**
3612e7854a03SAlex Deucher  * amdgpu_device_ip_suspend_phase2 - run suspend for hardware IPs (phase 2)
3613e7854a03SAlex Deucher  *
3614e7854a03SAlex Deucher  * @adev: amdgpu_device pointer
3615e7854a03SAlex Deucher  *
3616e7854a03SAlex Deucher  * Main suspend function for hardware IPs.  The list of all the hardware
3617e7854a03SAlex Deucher  * IPs that make up the asic is walked, clockgating is disabled and the
3618e7854a03SAlex Deucher  * suspend callbacks are run.  suspend puts the hardware and software state
3619e7854a03SAlex Deucher  * in each IP into a state suitable for suspend.
3620e7854a03SAlex Deucher  * Returns 0 on success, negative error code on failure.
3621e7854a03SAlex Deucher  */
amdgpu_device_ip_suspend_phase2(struct amdgpu_device * adev)3622e7854a03SAlex Deucher static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
3623d38ceaf9SAlex Deucher {
3624d38ceaf9SAlex Deucher 	int i, r;
3625d38ceaf9SAlex Deucher 
3626557f42a2SAlex Deucher 	if (adev->in_s0ix)
3627bc143d8bSEvan Quan 		amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D3Entry);
362834416931SAlex Deucher 
3629d38ceaf9SAlex Deucher 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
3630a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
3631d38ceaf9SAlex Deucher 			continue;
3632e7854a03SAlex Deucher 		/* displays are handled in phase1 */
3633e7854a03SAlex Deucher 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)
3634e7854a03SAlex Deucher 			continue;
3635bff77e86SLe Ma 		/* PSP lost connection when err_event_athub occurs */
3636bff77e86SLe Ma 		if (amdgpu_ras_intr_triggered() &&
3637bff77e86SLe Ma 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
3638bff77e86SLe Ma 			adev->ip_blocks[i].status.hw = false;
3639bff77e86SLe Ma 			continue;
3640bff77e86SLe Ma 		}
3641e3c1b071Sshaoyunl 
3642e3c1b071Sshaoyunl 		/* skip unnecessary suspend if we do not initialize them yet */
36435839d27dSLijo Lazar 		if (!amdgpu_ip_member_of_hwini(
36445839d27dSLijo Lazar 			    adev, adev->ip_blocks[i].version->type))
3645e3c1b071Sshaoyunl 			continue;
3646557f42a2SAlex Deucher 
364735a54408SAlex Deucher 		/* Since we skip suspend for S0i3, we need to cancel the delayed
364835a54408SAlex Deucher 		 * idle work here as the suspend callback never gets called.
364935a54408SAlex Deucher 		 */
365035a54408SAlex Deucher 		if (adev->in_s0ix &&
365135a54408SAlex Deucher 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX &&
365235a54408SAlex Deucher 		    amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 0, 0))
365335a54408SAlex Deucher 			cancel_delayed_work_sync(&adev->gfx.idle_work);
3654afa6646bSAlex Deucher 		/* skip suspend of gfx/mes and psp for S0ix
365532ff160dSAlex Deucher 		 * gfx is in gfxoff state, so on resume it will exit gfxoff just
365632ff160dSAlex Deucher 		 * like at runtime. PSP is also part of the always on hardware
365732ff160dSAlex Deucher 		 * so no need to suspend it.
365832ff160dSAlex Deucher 		 */
3659557f42a2SAlex Deucher 		if (adev->in_s0ix &&
366032ff160dSAlex Deucher 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP ||
3661afa6646bSAlex Deucher 		     adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
3662afa6646bSAlex Deucher 		     adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_MES))
3663557f42a2SAlex Deucher 			continue;
3664557f42a2SAlex Deucher 
36652a7798eaSAlex Deucher 		/* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
36662a7798eaSAlex Deucher 		if (adev->in_s0ix &&
36674e8303cfSLijo Lazar 		    (amdgpu_ip_version(adev, SDMA0_HWIP, 0) >=
36684e8303cfSLijo Lazar 		     IP_VERSION(5, 0, 0)) &&
36694e8303cfSLijo Lazar 		    (adev->ip_blocks[i].version->type ==
36704e8303cfSLijo Lazar 		     AMD_IP_BLOCK_TYPE_SDMA))
36712a7798eaSAlex Deucher 			continue;
36722a7798eaSAlex Deucher 
3673e11c7750STim Huang 		/* Once swPSP provides the IMU, RLC FW binaries to TOS during cold-boot.
3674e11c7750STim Huang 		 * These are in TMR, hence are expected to be reused by PSP-TOS to reload
3675e11c7750STim Huang 		 * from this location and RLC Autoload automatically also gets loaded
3676e11c7750STim Huang 		 * from here based on PMFW -> PSP message during re-init sequence.
3677e11c7750STim Huang 		 * Therefore, the psp suspend & resume should be skipped to avoid destroy
3678e11c7750STim Huang 		 * the TMR and reload FWs again for IMU enabled APU ASICs.
3679e11c7750STim Huang 		 */
3680e11c7750STim Huang 		if (amdgpu_in_reset(adev) &&
3681e11c7750STim Huang 		    (adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs &&
3682e11c7750STim Huang 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
3683e11c7750STim Huang 			continue;
3684e11c7750STim Huang 
3685d38ceaf9SAlex Deucher 		/* XXX handle errors */
3686e095026fSSunil Khatri 		r = amdgpu_ip_block_suspend(&adev->ip_blocks[i]);
3687876923fbSxinhui pan 		adev->ip_blocks[i].status.hw = false;
3688e095026fSSunil Khatri 
3689a3a09142SAlex Deucher 		/* handle putting the SMC in the appropriate state */
369086b93fd6SJack Zhang 		if (!amdgpu_sriov_vf(adev)) {
3691a3a09142SAlex Deucher 			if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
36929530273eSEvan Quan 				r = amdgpu_dpm_set_mp1_state(adev, adev->mp1_state);
3693a3a09142SAlex Deucher 				if (r) {
3694a3a09142SAlex Deucher 					DRM_ERROR("SMC failed to set mp1 state %d, %d\n",
3695a3a09142SAlex Deucher 							adev->mp1_state, r);
3696482f0e53SMonk Liu 					return r;
3697a3a09142SAlex Deucher 				}
3698a3a09142SAlex Deucher 			}
369986b93fd6SJack Zhang 		}
3700d38ceaf9SAlex Deucher 	}
3701d38ceaf9SAlex Deucher 
3702d38ceaf9SAlex Deucher 	return 0;
3703d38ceaf9SAlex Deucher }
3704d38ceaf9SAlex Deucher 
3705e7854a03SAlex Deucher /**
3706e7854a03SAlex Deucher  * amdgpu_device_ip_suspend - run suspend for hardware IPs
3707e7854a03SAlex Deucher  *
3708e7854a03SAlex Deucher  * @adev: amdgpu_device pointer
3709e7854a03SAlex Deucher  *
3710e7854a03SAlex Deucher  * Main suspend function for hardware IPs.  The list of all the hardware
3711e7854a03SAlex Deucher  * IPs that make up the asic is walked, clockgating is disabled and the
3712e7854a03SAlex Deucher  * suspend callbacks are run.  suspend puts the hardware and software state
3713e7854a03SAlex Deucher  * in each IP into a state suitable for suspend.
3714e7854a03SAlex Deucher  * Returns 0 on success, negative error code on failure.
3715e7854a03SAlex Deucher  */
amdgpu_device_ip_suspend(struct amdgpu_device * adev)3716e7854a03SAlex Deucher int amdgpu_device_ip_suspend(struct amdgpu_device *adev)
3717e7854a03SAlex Deucher {
3718e7854a03SAlex Deucher 	int r;
3719e7854a03SAlex Deucher 
37203c73683cSJingwen Chen 	if (amdgpu_sriov_vf(adev)) {
37213c73683cSJingwen Chen 		amdgpu_virt_fini_data_exchange(adev);
3722e7819644SYintian Tao 		amdgpu_virt_request_full_gpu(adev, false);
37233c73683cSJingwen Chen 	}
3724e7819644SYintian Tao 
3725b7043800SAlex Deucher 	amdgpu_ttm_set_buffer_funcs_status(adev, false);
3726b7043800SAlex Deucher 
3727e7854a03SAlex Deucher 	r = amdgpu_device_ip_suspend_phase1(adev);
3728e7854a03SAlex Deucher 	if (r)
3729e7854a03SAlex Deucher 		return r;
3730e7854a03SAlex Deucher 	r = amdgpu_device_ip_suspend_phase2(adev);
3731e7854a03SAlex Deucher 
3732e7819644SYintian Tao 	if (amdgpu_sriov_vf(adev))
3733e7819644SYintian Tao 		amdgpu_virt_release_full_gpu(adev, false);
3734e7819644SYintian Tao 
3735e7854a03SAlex Deucher 	return r;
3736e7854a03SAlex Deucher }
3737e7854a03SAlex Deucher 
amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device * adev)373806ec9070SAlex Deucher static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
3739a90ad3c2SMonk Liu {
3740a90ad3c2SMonk Liu 	int i, r;
3741a90ad3c2SMonk Liu 
37422cb681b6SMonk Liu 	static enum amd_ip_block_type ip_order[] = {
37432cb681b6SMonk Liu 		AMD_IP_BLOCK_TYPE_COMMON,
3744c1c39032SAlex Deucher 		AMD_IP_BLOCK_TYPE_GMC,
374539186aefSEmily Deng 		AMD_IP_BLOCK_TYPE_PSP,
37462cb681b6SMonk Liu 		AMD_IP_BLOCK_TYPE_IH,
37472cb681b6SMonk Liu 	};
37482cb681b6SMonk Liu 
374995ea3dbcSJack Zhang 	for (i = 0; i < adev->num_ip_blocks; i++) {
37502cb681b6SMonk Liu 		int j;
37512cb681b6SMonk Liu 		struct amdgpu_ip_block *block;
37522cb681b6SMonk Liu 
37534cd2a96dSJiawei 		block = &adev->ip_blocks[i];
37544cd2a96dSJiawei 		block->status.hw = false;
37552cb681b6SMonk Liu 
37564cd2a96dSJiawei 		for (j = 0; j < ARRAY_SIZE(ip_order); j++) {
37574cd2a96dSJiawei 
37584cd2a96dSJiawei 			if (block->version->type != ip_order[j] ||
37592cb681b6SMonk Liu 				!block->status.valid)
3760a90ad3c2SMonk Liu 				continue;
3761a90ad3c2SMonk Liu 
376258608034SSunil Khatri 			r = block->version->funcs->hw_init(&adev->ip_blocks[i]);
3763f3bb57b6SYiqing Yao 			if (r) {
3764f3bb57b6SYiqing Yao 				dev_err(adev->dev, "RE-INIT-early: %s failed\n",
3765f3bb57b6SYiqing Yao 					 block->version->funcs->name);
3766c41d1cf6SMonk Liu 				return r;
3767f3bb57b6SYiqing Yao 			}
3768482f0e53SMonk Liu 			block->status.hw = true;
3769a90ad3c2SMonk Liu 		}
3770a90ad3c2SMonk Liu 	}
3771a90ad3c2SMonk Liu 
3772a90ad3c2SMonk Liu 	return 0;
3773a90ad3c2SMonk Liu }
3774a90ad3c2SMonk Liu 
amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device * adev)377506ec9070SAlex Deucher static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
3776a90ad3c2SMonk Liu {
3777f3bb57b6SYiqing Yao 	struct amdgpu_ip_block *block;
3778f3bb57b6SYiqing Yao 	int i, r = 0;
3779a90ad3c2SMonk Liu 
37802cb681b6SMonk Liu 	static enum amd_ip_block_type ip_order[] = {
37812cb681b6SMonk Liu 		AMD_IP_BLOCK_TYPE_SMC,
37822cb681b6SMonk Liu 		AMD_IP_BLOCK_TYPE_DCE,
37832cb681b6SMonk Liu 		AMD_IP_BLOCK_TYPE_GFX,
37842cb681b6SMonk Liu 		AMD_IP_BLOCK_TYPE_SDMA,
3785ec64350dSYiPeng Chai 		AMD_IP_BLOCK_TYPE_MES,
3786257deb8cSFrank Min 		AMD_IP_BLOCK_TYPE_UVD,
3787d83c7a07SJane Jian 		AMD_IP_BLOCK_TYPE_VCE,
3788d2cdc014SYifan Zha 		AMD_IP_BLOCK_TYPE_VCN,
3789d2cdc014SYifan Zha 		AMD_IP_BLOCK_TYPE_JPEG
37902cb681b6SMonk Liu 	};
37912cb681b6SMonk Liu 
37922cb681b6SMonk Liu 	for (i = 0; i < ARRAY_SIZE(ip_order); i++) {
3793f3bb57b6SYiqing Yao 		block = amdgpu_device_ip_get_ip_block(adev, ip_order[i]);
37942cb681b6SMonk Liu 
3795f3bb57b6SYiqing Yao 		if (!block)
3796a90ad3c2SMonk Liu 			continue;
3797a90ad3c2SMonk Liu 
3798f3bb57b6SYiqing Yao 		if (block->status.valid && !block->status.hw) {
3799502d7630SSunil Khatri 			if (block->version->type == AMD_IP_BLOCK_TYPE_SMC) {
3800f3bb57b6SYiqing Yao 				r = amdgpu_ip_block_resume(block);
3801502d7630SSunil Khatri 			} else {
3802f3bb57b6SYiqing Yao 				r = block->version->funcs->hw_init(block);
3803f3bb57b6SYiqing Yao 			}
3804f3bb57b6SYiqing Yao 
3805502d7630SSunil Khatri 			if (r) {
3806f3bb57b6SYiqing Yao 				dev_err(adev->dev, "RE-INIT-late: %s failed\n",
3807f3bb57b6SYiqing Yao 					 block->version->funcs->name);
3808f3bb57b6SYiqing Yao 				break;
3809502d7630SSunil Khatri 			}
3810482f0e53SMonk Liu 			block->status.hw = true;
3811a90ad3c2SMonk Liu 		}
3812a90ad3c2SMonk Liu 	}
3813a90ad3c2SMonk Liu 
3814f3bb57b6SYiqing Yao 	return r;
3815a90ad3c2SMonk Liu }
3816a90ad3c2SMonk Liu 
3817e3ecdffaSAlex Deucher /**
3818e3ecdffaSAlex Deucher  * amdgpu_device_ip_resume_phase1 - run resume for hardware IPs
3819e3ecdffaSAlex Deucher  *
3820e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3821e3ecdffaSAlex Deucher  *
3822e3ecdffaSAlex Deucher  * First resume function for hardware IPs.  The list of all the hardware
3823e3ecdffaSAlex Deucher  * IPs that make up the asic is walked and the resume callbacks are run for
3824e3ecdffaSAlex Deucher  * COMMON, GMC, and IH.  resume puts the hardware into a functional state
3825e3ecdffaSAlex Deucher  * after a suspend and updates the software state as necessary.  This
3826e3ecdffaSAlex Deucher  * function is also used for restoring the GPU after a GPU reset.
3827e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
3828e3ecdffaSAlex Deucher  */
amdgpu_device_ip_resume_phase1(struct amdgpu_device * adev)382906ec9070SAlex Deucher static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
3830d38ceaf9SAlex Deucher {
3831d38ceaf9SAlex Deucher 	int i, r;
3832d38ceaf9SAlex Deucher 
3833d38ceaf9SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
3834482f0e53SMonk Liu 		if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
3835d38ceaf9SAlex Deucher 			continue;
3836fcf0649fSChunming Zhou 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
3837fcf0649fSChunming Zhou 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
3838d7274ec7SBokun Zhang 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
3839d7274ec7SBokun Zhang 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP && amdgpu_sriov_vf(adev))) {
3840482f0e53SMonk Liu 
3841502d7630SSunil Khatri 			r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
3842502d7630SSunil Khatri 			if (r)
3843fcf0649fSChunming Zhou 				return r;
3844fcf0649fSChunming Zhou 		}
3845fcf0649fSChunming Zhou 	}
3846d38ceaf9SAlex Deucher 
3847fcf0649fSChunming Zhou 	return 0;
3848fcf0649fSChunming Zhou }
3849fcf0649fSChunming Zhou 
3850e3ecdffaSAlex Deucher /**
3851e3ecdffaSAlex Deucher  * amdgpu_device_ip_resume_phase2 - run resume for hardware IPs
3852e3ecdffaSAlex Deucher  *
3853e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3854e3ecdffaSAlex Deucher  *
385573dae652SAlex Deucher  * Second resume function for hardware IPs.  The list of all the hardware
3856e3ecdffaSAlex Deucher  * IPs that make up the asic is walked and the resume callbacks are run for
3857e3ecdffaSAlex Deucher  * all blocks except COMMON, GMC, and IH.  resume puts the hardware into a
3858e3ecdffaSAlex Deucher  * functional state after a suspend and updates the software state as
3859e3ecdffaSAlex Deucher  * necessary.  This function is also used for restoring the GPU after a GPU
3860e3ecdffaSAlex Deucher  * reset.
3861e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
3862e3ecdffaSAlex Deucher  */
amdgpu_device_ip_resume_phase2(struct amdgpu_device * adev)386306ec9070SAlex Deucher static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
3864fcf0649fSChunming Zhou {
3865fcf0649fSChunming Zhou 	int i, r;
3866fcf0649fSChunming Zhou 
3867fcf0649fSChunming Zhou 	for (i = 0; i < adev->num_ip_blocks; i++) {
3868482f0e53SMonk Liu 		if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
3869fcf0649fSChunming Zhou 			continue;
3870d38ceaf9SAlex Deucher 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
3871d38ceaf9SAlex Deucher 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
38727a3e0bb2SRex Zhu 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
387373dae652SAlex Deucher 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE ||
38747a3e0bb2SRex Zhu 		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
3875d38ceaf9SAlex Deucher 			continue;
3876502d7630SSunil Khatri 		r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
3877502d7630SSunil Khatri 		if (r)
3878d38ceaf9SAlex Deucher 			return r;
3879d38ceaf9SAlex Deucher 	}
3880d38ceaf9SAlex Deucher 
3881d38ceaf9SAlex Deucher 	return 0;
3882d38ceaf9SAlex Deucher }
3883d38ceaf9SAlex Deucher 
3884e3ecdffaSAlex Deucher /**
388573dae652SAlex Deucher  * amdgpu_device_ip_resume_phase3 - run resume for hardware IPs
388673dae652SAlex Deucher  *
388773dae652SAlex Deucher  * @adev: amdgpu_device pointer
388873dae652SAlex Deucher  *
388973dae652SAlex Deucher  * Third resume function for hardware IPs.  The list of all the hardware
389073dae652SAlex Deucher  * IPs that make up the asic is walked and the resume callbacks are run for
389173dae652SAlex Deucher  * all DCE.  resume puts the hardware into a functional state after a suspend
389273dae652SAlex Deucher  * and updates the software state as necessary.  This function is also used
389373dae652SAlex Deucher  * for restoring the GPU after a GPU reset.
389473dae652SAlex Deucher  *
389573dae652SAlex Deucher  * Returns 0 on success, negative error code on failure.
389673dae652SAlex Deucher  */
amdgpu_device_ip_resume_phase3(struct amdgpu_device * adev)389773dae652SAlex Deucher static int amdgpu_device_ip_resume_phase3(struct amdgpu_device *adev)
389873dae652SAlex Deucher {
389973dae652SAlex Deucher 	int i, r;
390073dae652SAlex Deucher 
390173dae652SAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
390273dae652SAlex Deucher 		if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
390373dae652SAlex Deucher 			continue;
390473dae652SAlex Deucher 		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) {
390573dae652SAlex Deucher 			r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
390673dae652SAlex Deucher 			if (r)
390773dae652SAlex Deucher 				return r;
390873dae652SAlex Deucher 		}
390973dae652SAlex Deucher 	}
391073dae652SAlex Deucher 
391173dae652SAlex Deucher 	return 0;
391273dae652SAlex Deucher }
391373dae652SAlex Deucher 
391473dae652SAlex Deucher /**
3915e3ecdffaSAlex Deucher  * amdgpu_device_ip_resume - run resume for hardware IPs
3916e3ecdffaSAlex Deucher  *
3917e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3918e3ecdffaSAlex Deucher  *
3919e3ecdffaSAlex Deucher  * Main resume function for hardware IPs.  The hardware IPs
3920e3ecdffaSAlex Deucher  * are split into two resume functions because they are
3921b8920e1eSSrinivasan Shanmugam  * also used in recovering from a GPU reset and some additional
3922e3ecdffaSAlex Deucher  * steps need to be take between them.  In this case (S3/S4) they are
3923e3ecdffaSAlex Deucher  * run sequentially.
3924e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
3925e3ecdffaSAlex Deucher  */
amdgpu_device_ip_resume(struct amdgpu_device * adev)392606ec9070SAlex Deucher static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
3927d38ceaf9SAlex Deucher {
3928fcf0649fSChunming Zhou 	int r;
3929d38ceaf9SAlex Deucher 
393006ec9070SAlex Deucher 	r = amdgpu_device_ip_resume_phase1(adev);
3931fcf0649fSChunming Zhou 	if (r)
3932d38ceaf9SAlex Deucher 		return r;
39337a3e0bb2SRex Zhu 
39347a3e0bb2SRex Zhu 	r = amdgpu_device_fw_loading(adev);
39357a3e0bb2SRex Zhu 	if (r)
39367a3e0bb2SRex Zhu 		return r;
39377a3e0bb2SRex Zhu 
393806ec9070SAlex Deucher 	r = amdgpu_device_ip_resume_phase2(adev);
3939d38ceaf9SAlex Deucher 
3940b7043800SAlex Deucher 	if (adev->mman.buffer_funcs_ring->sched.ready)
3941b7043800SAlex Deucher 		amdgpu_ttm_set_buffer_funcs_status(adev, true);
3942b7043800SAlex Deucher 
394373dae652SAlex Deucher 	if (r)
394473dae652SAlex Deucher 		return r;
394573dae652SAlex Deucher 
394673dae652SAlex Deucher 	amdgpu_fence_driver_hw_init(adev);
394773dae652SAlex Deucher 
394873dae652SAlex Deucher 	r = amdgpu_device_ip_resume_phase3(adev);
394973dae652SAlex Deucher 
3950fcf0649fSChunming Zhou 	return r;
3951d38ceaf9SAlex Deucher }
3952d38ceaf9SAlex Deucher 
3953e3ecdffaSAlex Deucher /**
3954e3ecdffaSAlex Deucher  * amdgpu_device_detect_sriov_bios - determine if the board supports SR-IOV
3955e3ecdffaSAlex Deucher  *
3956e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
3957e3ecdffaSAlex Deucher  *
3958e3ecdffaSAlex Deucher  * Query the VBIOS data tables to determine if the board supports SR-IOV.
3959e3ecdffaSAlex Deucher  */
amdgpu_device_detect_sriov_bios(struct amdgpu_device * adev)39604e99a44eSMonk Liu static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
3961048765adSAndres Rodriguez {
39626867e1b5SMonk Liu 	if (amdgpu_sriov_vf(adev)) {
3963a5bde2f9SAlex Deucher 		if (adev->is_atom_fw) {
396458ff791aSHawking Zhang 			if (amdgpu_atomfirmware_gpu_virtualization_supported(adev))
3965a5bde2f9SAlex Deucher 				adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
3966a5bde2f9SAlex Deucher 		} else {
39674e99a44eSMonk Liu 			if (amdgpu_atombios_has_gpu_virtualization_table(adev))
39685a5099cbSXiangliang Yu 				adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
3969048765adSAndres Rodriguez 		}
39706867e1b5SMonk Liu 
39716867e1b5SMonk Liu 		if (!(adev->virt.caps & AMDGPU_SRIOV_CAPS_SRIOV_VBIOS))
39726867e1b5SMonk Liu 			amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_NO_VBIOS, 0, 0);
39736867e1b5SMonk Liu 	}
3974a5bde2f9SAlex Deucher }
3975048765adSAndres Rodriguez 
3976e3ecdffaSAlex Deucher /**
3977e3ecdffaSAlex Deucher  * amdgpu_device_asic_has_dc_support - determine if DC supports the asic
3978e3ecdffaSAlex Deucher  *
3979e3ecdffaSAlex Deucher  * @asic_type: AMD asic type
3980e3ecdffaSAlex Deucher  *
3981e3ecdffaSAlex Deucher  * Check if there is DC (new modesetting infrastructre) support for an asic.
3982e3ecdffaSAlex Deucher  * returns true if DC has support, false if not.
3983e3ecdffaSAlex Deucher  */
amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)39844562236bSHarry Wentland bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
39854562236bSHarry Wentland {
39864562236bSHarry Wentland 	switch (asic_type) {
39870637d417SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_SI
39880637d417SAlex Deucher 	case CHIP_HAINAN:
39890637d417SAlex Deucher #endif
39900637d417SAlex Deucher 	case CHIP_TOPAZ:
39910637d417SAlex Deucher 		/* chips with no display hardware */
39920637d417SAlex Deucher 		return false;
39934562236bSHarry Wentland #if defined(CONFIG_DRM_AMD_DC)
399464200c46SMauro Rossi 	case CHIP_TAHITI:
399564200c46SMauro Rossi 	case CHIP_PITCAIRN:
399664200c46SMauro Rossi 	case CHIP_VERDE:
399764200c46SMauro Rossi 	case CHIP_OLAND:
39982d32ffd6SAlex Deucher 		/*
39992d32ffd6SAlex Deucher 		 * We have systems in the wild with these ASICs that require
40002d32ffd6SAlex Deucher 		 * LVDS and VGA support which is not supported with DC.
40012d32ffd6SAlex Deucher 		 *
40022d32ffd6SAlex Deucher 		 * Fallback to the non-DC driver here by default so as not to
40032d32ffd6SAlex Deucher 		 * cause regressions.
40042d32ffd6SAlex Deucher 		 */
40052d32ffd6SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_SI)
40062d32ffd6SAlex Deucher 		return amdgpu_dc > 0;
40072d32ffd6SAlex Deucher #else
40082d32ffd6SAlex Deucher 		return false;
400964200c46SMauro Rossi #endif
40104562236bSHarry Wentland 	case CHIP_BONAIRE:
40110d6fbccbSAlex Deucher 	case CHIP_KAVERI:
4012367e6687SAlex Deucher 	case CHIP_KABINI:
4013367e6687SAlex Deucher 	case CHIP_MULLINS:
4014d9fda248SHarry Wentland 		/*
4015d9fda248SHarry Wentland 		 * We have systems in the wild with these ASICs that require
4016b5a0168eSAlex Deucher 		 * VGA support which is not supported with DC.
4017d9fda248SHarry Wentland 		 *
4018d9fda248SHarry Wentland 		 * Fallback to the non-DC driver here by default so as not to
4019d9fda248SHarry Wentland 		 * cause regressions.
4020d9fda248SHarry Wentland 		 */
4021d9fda248SHarry Wentland 		return amdgpu_dc > 0;
4022f7f12b25SAlex Deucher 	default:
4023fd187853SHawking Zhang 		return amdgpu_dc != 0;
4024f7f12b25SAlex Deucher #else
40254562236bSHarry Wentland 	default:
402693b09a9aSSimon Ser 		if (amdgpu_dc > 0)
4027b8920e1eSSrinivasan Shanmugam 			DRM_INFO_ONCE("Display Core has been requested via kernel parameter but isn't supported by ASIC, ignoring\n");
40284562236bSHarry Wentland 		return false;
4029f7f12b25SAlex Deucher #endif
40304562236bSHarry Wentland 	}
40314562236bSHarry Wentland }
40324562236bSHarry Wentland 
40334562236bSHarry Wentland /**
40344562236bSHarry Wentland  * amdgpu_device_has_dc_support - check if dc is supported
40354562236bSHarry Wentland  *
4036982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
40374562236bSHarry Wentland  *
40384562236bSHarry Wentland  * Returns true for supported, false for not supported
40394562236bSHarry Wentland  */
amdgpu_device_has_dc_support(struct amdgpu_device * adev)40404562236bSHarry Wentland bool amdgpu_device_has_dc_support(struct amdgpu_device *adev)
40414562236bSHarry Wentland {
404225263da3SAlex Deucher 	if (adev->enable_virtual_display ||
4043abaf210cSAsher Song 	    (adev->harvest_ip_mask & AMD_HARVEST_IP_DMU_MASK))
40442555039dSXiangliang Yu 		return false;
40452555039dSXiangliang Yu 
40464562236bSHarry Wentland 	return amdgpu_device_asic_has_dc_support(adev->asic_type);
40474562236bSHarry Wentland }
40484562236bSHarry Wentland 
amdgpu_device_xgmi_reset_func(struct work_struct * __work)4049d4535e2cSAndrey Grodzovsky static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
4050d4535e2cSAndrey Grodzovsky {
4051d4535e2cSAndrey Grodzovsky 	struct amdgpu_device *adev =
4052d4535e2cSAndrey Grodzovsky 		container_of(__work, struct amdgpu_device, xgmi_reset_work);
4053d95e8e97SDennis Li 	struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
4054d4535e2cSAndrey Grodzovsky 
4055c6a6e2dbSAndrey Grodzovsky 	/* It's a bug to not have a hive within this function */
4056c6a6e2dbSAndrey Grodzovsky 	if (WARN_ON(!hive))
4057c6a6e2dbSAndrey Grodzovsky 		return;
4058c6a6e2dbSAndrey Grodzovsky 
4059c6a6e2dbSAndrey Grodzovsky 	/*
4060c6a6e2dbSAndrey Grodzovsky 	 * Use task barrier to synchronize all xgmi reset works across the
4061c6a6e2dbSAndrey Grodzovsky 	 * hive. task_barrier_enter and task_barrier_exit will block
4062c6a6e2dbSAndrey Grodzovsky 	 * until all the threads running the xgmi reset works reach
4063c6a6e2dbSAndrey Grodzovsky 	 * those points. task_barrier_full will do both blocks.
4064c6a6e2dbSAndrey Grodzovsky 	 */
4065c6a6e2dbSAndrey Grodzovsky 	if (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
4066c6a6e2dbSAndrey Grodzovsky 
4067c6a6e2dbSAndrey Grodzovsky 		task_barrier_enter(&hive->tb);
40684a580877SLuben Tuikov 		adev->asic_reset_res = amdgpu_device_baco_enter(adev_to_drm(adev));
4069c6a6e2dbSAndrey Grodzovsky 
4070c6a6e2dbSAndrey Grodzovsky 		if (adev->asic_reset_res)
4071c6a6e2dbSAndrey Grodzovsky 			goto fail;
4072c6a6e2dbSAndrey Grodzovsky 
4073c6a6e2dbSAndrey Grodzovsky 		task_barrier_exit(&hive->tb);
40744a580877SLuben Tuikov 		adev->asic_reset_res = amdgpu_device_baco_exit(adev_to_drm(adev));
4075c6a6e2dbSAndrey Grodzovsky 
4076c6a6e2dbSAndrey Grodzovsky 		if (adev->asic_reset_res)
4077c6a6e2dbSAndrey Grodzovsky 			goto fail;
407843c4d576SJohn Clements 
407921226f02STao Zhou 		amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__MMHUB);
4080c6a6e2dbSAndrey Grodzovsky 	} else {
4081c6a6e2dbSAndrey Grodzovsky 
4082c6a6e2dbSAndrey Grodzovsky 		task_barrier_full(&hive->tb);
4083d4535e2cSAndrey Grodzovsky 		adev->asic_reset_res =  amdgpu_asic_reset(adev);
4084c6a6e2dbSAndrey Grodzovsky 	}
4085ce316fa5SLe Ma 
4086c6a6e2dbSAndrey Grodzovsky fail:
4087d4535e2cSAndrey Grodzovsky 	if (adev->asic_reset_res)
4088fed184e9SEvan Quan 		DRM_WARN("ASIC reset failed with error, %d for drm dev, %s",
40894a580877SLuben Tuikov 			 adev->asic_reset_res, adev_to_drm(adev)->unique);
4090d95e8e97SDennis Li 	amdgpu_put_xgmi_hive(hive);
4091d4535e2cSAndrey Grodzovsky }
4092d4535e2cSAndrey Grodzovsky 
amdgpu_device_get_job_timeout_settings(struct amdgpu_device * adev)409371f98027SAlex Deucher static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
409471f98027SAlex Deucher {
409571f98027SAlex Deucher 	char *input = amdgpu_lockup_timeout;
409671f98027SAlex Deucher 	char *timeout_setting = NULL;
409771f98027SAlex Deucher 	int index = 0;
409871f98027SAlex Deucher 	long timeout;
409971f98027SAlex Deucher 	int ret = 0;
410071f98027SAlex Deucher 
410171f98027SAlex Deucher 	/*
410267387dfeSAlex Deucher 	 * By default timeout for non compute jobs is 10000
410367387dfeSAlex Deucher 	 * and 60000 for compute jobs.
410471f98027SAlex Deucher 	 * In SR-IOV or passthrough mode, timeout for compute
4105b7b2a316SJiawei 	 * jobs are 60000 by default.
410671f98027SAlex Deucher 	 */
410771f98027SAlex Deucher 	adev->gfx_timeout = msecs_to_jiffies(10000);
410871f98027SAlex Deucher 	adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
41099882e278SEmily.Deng 	if (amdgpu_sriov_vf(adev))
41109882e278SEmily.Deng 		adev->compute_timeout = amdgpu_sriov_is_pp_one_vf(adev) ?
41119882e278SEmily.Deng 					msecs_to_jiffies(60000) : msecs_to_jiffies(10000);
411271f98027SAlex Deucher 	else
411367387dfeSAlex Deucher 		adev->compute_timeout =  msecs_to_jiffies(60000);
411471f98027SAlex Deucher 
4115f440ff44SWambui Karuga 	if (strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
411671f98027SAlex Deucher 		while ((timeout_setting = strsep(&input, ",")) &&
4117f440ff44SWambui Karuga 				strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
411871f98027SAlex Deucher 			ret = kstrtol(timeout_setting, 0, &timeout);
411971f98027SAlex Deucher 			if (ret)
412071f98027SAlex Deucher 				return ret;
412171f98027SAlex Deucher 
412271f98027SAlex Deucher 			if (timeout == 0) {
412371f98027SAlex Deucher 				index++;
412471f98027SAlex Deucher 				continue;
412571f98027SAlex Deucher 			} else if (timeout < 0) {
412671f98027SAlex Deucher 				timeout = MAX_SCHEDULE_TIMEOUT;
4127127aedf9SChristian König 				dev_warn(adev->dev, "lockup timeout disabled");
4128127aedf9SChristian König 				add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
412971f98027SAlex Deucher 			} else {
413071f98027SAlex Deucher 				timeout = msecs_to_jiffies(timeout);
413171f98027SAlex Deucher 			}
413271f98027SAlex Deucher 
413371f98027SAlex Deucher 			switch (index++) {
413471f98027SAlex Deucher 			case 0:
413571f98027SAlex Deucher 				adev->gfx_timeout = timeout;
413671f98027SAlex Deucher 				break;
413771f98027SAlex Deucher 			case 1:
413871f98027SAlex Deucher 				adev->compute_timeout = timeout;
413971f98027SAlex Deucher 				break;
414071f98027SAlex Deucher 			case 2:
414171f98027SAlex Deucher 				adev->sdma_timeout = timeout;
414271f98027SAlex Deucher 				break;
414371f98027SAlex Deucher 			case 3:
414471f98027SAlex Deucher 				adev->video_timeout = timeout;
414571f98027SAlex Deucher 				break;
414671f98027SAlex Deucher 			default:
414771f98027SAlex Deucher 				break;
414871f98027SAlex Deucher 			}
414971f98027SAlex Deucher 		}
415071f98027SAlex Deucher 		/*
415171f98027SAlex Deucher 		 * There is only one value specified and
415271f98027SAlex Deucher 		 * it should apply to all non-compute jobs.
415371f98027SAlex Deucher 		 */
4154bcccee89SEmily Deng 		if (index == 1) {
415571f98027SAlex Deucher 			adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
4156bcccee89SEmily Deng 			if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
4157bcccee89SEmily Deng 				adev->compute_timeout = adev->gfx_timeout;
4158bcccee89SEmily Deng 		}
415971f98027SAlex Deucher 	}
416071f98027SAlex Deucher 
416171f98027SAlex Deucher 	return ret;
416271f98027SAlex Deucher }
4163d4535e2cSAndrey Grodzovsky 
41644a74c38cSPhilip Yang /**
41654a74c38cSPhilip Yang  * amdgpu_device_check_iommu_direct_map - check if RAM direct mapped to GPU
41664a74c38cSPhilip Yang  *
41674a74c38cSPhilip Yang  * @adev: amdgpu_device pointer
41684a74c38cSPhilip Yang  *
41694a74c38cSPhilip Yang  * RAM direct mapped to GPU if IOMMU is not enabled or is pass through mode
41704a74c38cSPhilip Yang  */
amdgpu_device_check_iommu_direct_map(struct amdgpu_device * adev)41714a74c38cSPhilip Yang static void amdgpu_device_check_iommu_direct_map(struct amdgpu_device *adev)
41724a74c38cSPhilip Yang {
41734a74c38cSPhilip Yang 	struct iommu_domain *domain;
41744a74c38cSPhilip Yang 
41754a74c38cSPhilip Yang 	domain = iommu_get_domain_for_dev(adev->dev);
41764a74c38cSPhilip Yang 	if (!domain || domain->type == IOMMU_DOMAIN_IDENTITY)
41774a74c38cSPhilip Yang 		adev->ram_is_direct_mapped = true;
41784a74c38cSPhilip Yang }
41794a74c38cSPhilip Yang 
418075f0efbcSRahul Jain #if defined(CONFIG_HSA_AMD_P2P)
418175f0efbcSRahul Jain /**
418275f0efbcSRahul Jain  * amdgpu_device_check_iommu_remap - Check if DMA remapping is enabled.
418375f0efbcSRahul Jain  *
418475f0efbcSRahul Jain  * @adev: amdgpu_device pointer
418575f0efbcSRahul Jain  *
418675f0efbcSRahul Jain  * return if IOMMU remapping bar address
418775f0efbcSRahul Jain  */
amdgpu_device_check_iommu_remap(struct amdgpu_device * adev)418875f0efbcSRahul Jain static bool amdgpu_device_check_iommu_remap(struct amdgpu_device *adev)
418975f0efbcSRahul Jain {
419075f0efbcSRahul Jain 	struct iommu_domain *domain;
419175f0efbcSRahul Jain 
419275f0efbcSRahul Jain 	domain = iommu_get_domain_for_dev(adev->dev);
419375f0efbcSRahul Jain 	if (domain && (domain->type == IOMMU_DOMAIN_DMA ||
419475f0efbcSRahul Jain 		domain->type ==	IOMMU_DOMAIN_DMA_FQ))
419575f0efbcSRahul Jain 		return true;
419675f0efbcSRahul Jain 
419775f0efbcSRahul Jain 	return false;
419875f0efbcSRahul Jain }
419975f0efbcSRahul Jain #endif
420075f0efbcSRahul Jain 
amdgpu_device_set_mcbp(struct amdgpu_device * adev)420102ff519eSAlex Deucher static void amdgpu_device_set_mcbp(struct amdgpu_device *adev)
420202ff519eSAlex Deucher {
420302ff519eSAlex Deucher 	if (amdgpu_mcbp == 1)
420402ff519eSAlex Deucher 		adev->gfx.mcbp = true;
42051e9e15dcSJiadong Zhu 	else if (amdgpu_mcbp == 0)
42061e9e15dcSJiadong Zhu 		adev->gfx.mcbp = false;
420750a7c876SAlex Deucher 
420802ff519eSAlex Deucher 	if (amdgpu_sriov_vf(adev))
420902ff519eSAlex Deucher 		adev->gfx.mcbp = true;
421002ff519eSAlex Deucher 
421102ff519eSAlex Deucher 	if (adev->gfx.mcbp)
421202ff519eSAlex Deucher 		DRM_INFO("MCBP is enabled\n");
421302ff519eSAlex Deucher }
421402ff519eSAlex Deucher 
4215d38ceaf9SAlex Deucher /**
4216d38ceaf9SAlex Deucher  * amdgpu_device_init - initialize the driver
4217d38ceaf9SAlex Deucher  *
4218d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
4219d38ceaf9SAlex Deucher  * @flags: driver flags
4220d38ceaf9SAlex Deucher  *
4221d38ceaf9SAlex Deucher  * Initializes the driver info and hw (all asics).
4222d38ceaf9SAlex Deucher  * Returns 0 for success or an error on failure.
4223d38ceaf9SAlex Deucher  * Called at driver startup.
4224d38ceaf9SAlex Deucher  */
amdgpu_device_init(struct amdgpu_device * adev,uint32_t flags)4225d38ceaf9SAlex Deucher int amdgpu_device_init(struct amdgpu_device *adev,
4226d38ceaf9SAlex Deucher 		       uint32_t flags)
4227d38ceaf9SAlex Deucher {
42288aba21b7SLuben Tuikov 	struct drm_device *ddev = adev_to_drm(adev);
42298aba21b7SLuben Tuikov 	struct pci_dev *pdev = adev->pdev;
4230d38ceaf9SAlex Deucher 	int r, i;
4231b98c6299SAlex Deucher 	bool px = false;
423295844d20SMarek Olšák 	u32 max_MBps;
423359e9fff1Slyndonli 	int tmp;
4234d38ceaf9SAlex Deucher 
4235d38ceaf9SAlex Deucher 	adev->shutdown = false;
4236d38ceaf9SAlex Deucher 	adev->flags = flags;
42374e66d7d2SYong Zhao 
42384e66d7d2SYong Zhao 	if (amdgpu_force_asic_type >= 0 && amdgpu_force_asic_type < CHIP_LAST)
42394e66d7d2SYong Zhao 		adev->asic_type = amdgpu_force_asic_type;
42404e66d7d2SYong Zhao 	else
42412f7d10b3SJammy Zhou 		adev->asic_type = flags & AMD_ASIC_MASK;
42424e66d7d2SYong Zhao 
4243d38ceaf9SAlex Deucher 	adev->usec_timeout = AMDGPU_MAX_USEC_TIMEOUT;
4244593aa2d2SShaoyun Liu 	if (amdgpu_emu_mode == 1)
42458bdab6bbSYong Zhao 		adev->usec_timeout *= 10;
4246770d13b1SChristian König 	adev->gmc.gart_size = 512 * 1024 * 1024;
4247d38ceaf9SAlex Deucher 	adev->accel_working = false;
4248d38ceaf9SAlex Deucher 	adev->num_rings = 0;
424968ce8b24SChristian König 	RCU_INIT_POINTER(adev->gang_submit, dma_fence_get_stub());
4250d38ceaf9SAlex Deucher 	adev->mman.buffer_funcs = NULL;
4251d38ceaf9SAlex Deucher 	adev->mman.buffer_funcs_ring = NULL;
4252d38ceaf9SAlex Deucher 	adev->vm_manager.vm_pte_funcs = NULL;
42530c88b430SNirmoy Das 	adev->vm_manager.vm_pte_num_scheds = 0;
4254132f34e4SChristian König 	adev->gmc.gmc_funcs = NULL;
42557bd939d0SLikun GAO 	adev->harvest_ip_mask = 0x0;
4256f54d1867SChris Wilson 	adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS);
4257b8866c26SAndres Rodriguez 	bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
4258d38ceaf9SAlex Deucher 
4259d38ceaf9SAlex Deucher 	adev->smc_rreg = &amdgpu_invalid_rreg;
4260d38ceaf9SAlex Deucher 	adev->smc_wreg = &amdgpu_invalid_wreg;
4261d38ceaf9SAlex Deucher 	adev->pcie_rreg = &amdgpu_invalid_rreg;
4262d38ceaf9SAlex Deucher 	adev->pcie_wreg = &amdgpu_invalid_wreg;
42630c552ed3SLe Ma 	adev->pcie_rreg_ext = &amdgpu_invalid_rreg_ext;
42640c552ed3SLe Ma 	adev->pcie_wreg_ext = &amdgpu_invalid_wreg_ext;
426536b9a952SHuang Rui 	adev->pciep_rreg = &amdgpu_invalid_rreg;
426636b9a952SHuang Rui 	adev->pciep_wreg = &amdgpu_invalid_wreg;
42674fa1c6a6STao Zhou 	adev->pcie_rreg64 = &amdgpu_invalid_rreg64;
42684fa1c6a6STao Zhou 	adev->pcie_wreg64 = &amdgpu_invalid_wreg64;
4269a76b2870SCandice Li 	adev->pcie_rreg64_ext = &amdgpu_invalid_rreg64_ext;
4270a76b2870SCandice Li 	adev->pcie_wreg64_ext = &amdgpu_invalid_wreg64_ext;
4271d38ceaf9SAlex Deucher 	adev->uvd_ctx_rreg = &amdgpu_invalid_rreg;
4272d38ceaf9SAlex Deucher 	adev->uvd_ctx_wreg = &amdgpu_invalid_wreg;
4273d38ceaf9SAlex Deucher 	adev->didt_rreg = &amdgpu_invalid_rreg;
4274d38ceaf9SAlex Deucher 	adev->didt_wreg = &amdgpu_invalid_wreg;
4275ccdbb20aSRex Zhu 	adev->gc_cac_rreg = &amdgpu_invalid_rreg;
4276ccdbb20aSRex Zhu 	adev->gc_cac_wreg = &amdgpu_invalid_wreg;
4277d38ceaf9SAlex Deucher 	adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg;
4278d38ceaf9SAlex Deucher 	adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg;
4279d38ceaf9SAlex Deucher 
42803e39ab90SAlex Deucher 	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n",
4281d38ceaf9SAlex Deucher 		 amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device,
42823e39ab90SAlex Deucher 		 pdev->subsystem_vendor, pdev->subsystem_device, pdev->revision);
4283d38ceaf9SAlex Deucher 
4284d38ceaf9SAlex Deucher 	/* mutex initialization are all done here so we
4285b8920e1eSSrinivasan Shanmugam 	 * can recall function without having locking issues
4286b8920e1eSSrinivasan Shanmugam 	 */
42870e5ca0d1SHuang Rui 	mutex_init(&adev->firmware.mutex);
4288d38ceaf9SAlex Deucher 	mutex_init(&adev->pm.mutex);
4289d38ceaf9SAlex Deucher 	mutex_init(&adev->gfx.gpu_clock_mutex);
4290d38ceaf9SAlex Deucher 	mutex_init(&adev->srbm_mutex);
4291b8866c26SAndres Rodriguez 	mutex_init(&adev->gfx.pipe_reserve_mutex);
4292d23ee13fSRex Zhu 	mutex_init(&adev->gfx.gfx_off_mutex);
429398a54e88SLe Ma 	mutex_init(&adev->gfx.partition_mutex);
4294d38ceaf9SAlex Deucher 	mutex_init(&adev->grbm_idx_mutex);
4295d38ceaf9SAlex Deucher 	mutex_init(&adev->mn_lock);
4296e23b74aaSAlex Deucher 	mutex_init(&adev->virt.vf_errors.lock);
4297d38ceaf9SAlex Deucher 	hash_init(adev->mn_hash);
429832eaeae0SAlex Deucher 	mutex_init(&adev->psp.mutex);
4299bd052211SPan, Xinhui 	mutex_init(&adev->notifier_lock);
43008cda7a4fSAlex Deucher 	mutex_init(&adev->pm.stable_pstate_ctx_lock);
4301f113cc32SAlex Deucher 	mutex_init(&adev->benchmark_mutex);
430276acba7bSAlex Deucher 	mutex_init(&adev->gfx.reset_sem_mutex);
4303e189be9bSSrinivasan Shanmugam 	/* Initialize the mutex for cleaner shader isolation between GFX and compute processes */
4304e189be9bSSrinivasan Shanmugam 	mutex_init(&adev->enforce_isolation_mutex);
4305bd22e44aSChristian König 	for (i = 0; i < MAX_XCP; ++i) {
4306bd22e44aSChristian König 		adev->isolation[i].spearhead = dma_fence_get_stub();
4307bd22e44aSChristian König 		amdgpu_sync_create(&adev->isolation[i].active);
4308bd22e44aSChristian König 		amdgpu_sync_create(&adev->isolation[i].prev);
4309bd22e44aSChristian König 	}
4310afefd6f2SSrinivasan Shanmugam 	mutex_init(&adev->gfx.kfd_sch_mutex);
4311553673a3SAlex Deucher 	mutex_init(&adev->gfx.workload_profile_mutex);
4312ca6575a3SAlex Deucher 	mutex_init(&adev->vcn.workload_profile_mutex);
4313d38ceaf9SAlex Deucher 
43144eaf21b7SPrike Liang 	amdgpu_device_init_apu_flags(adev);
43159f6a7857SHuang Rui 
4316912dfc84SEvan Quan 	r = amdgpu_device_check_arguments(adev);
4317912dfc84SEvan Quan 	if (r)
4318912dfc84SEvan Quan 		return r;
4319d38ceaf9SAlex Deucher 
4320d38ceaf9SAlex Deucher 	spin_lock_init(&adev->mmio_idx_lock);
4321d38ceaf9SAlex Deucher 	spin_lock_init(&adev->smc_idx_lock);
4322d38ceaf9SAlex Deucher 	spin_lock_init(&adev->pcie_idx_lock);
4323d38ceaf9SAlex Deucher 	spin_lock_init(&adev->uvd_ctx_idx_lock);
4324d38ceaf9SAlex Deucher 	spin_lock_init(&adev->didt_idx_lock);
4325ccdbb20aSRex Zhu 	spin_lock_init(&adev->gc_cac_idx_lock);
432616abb5d2SEvan Quan 	spin_lock_init(&adev->se_cac_idx_lock);
4327d38ceaf9SAlex Deucher 	spin_lock_init(&adev->audio_endpt_idx_lock);
432895844d20SMarek Olšák 	spin_lock_init(&adev->mm_stats.lock);
4329dc0297f3SSrinivasan Shanmugam 	spin_lock_init(&adev->virt.rlcg_reg_lock);
4330497d7ceeSAlex Deucher 	spin_lock_init(&adev->wb.lock);
4331d38ceaf9SAlex Deucher 
4332655ce9cbSshaoyunl 	INIT_LIST_HEAD(&adev->reset_list);
4333655ce9cbSshaoyunl 
43346492e1b0Syipechai 	INIT_LIST_HEAD(&adev->ras_list);
43356492e1b0Syipechai 
43363e38b634SEvan Quan 	INIT_LIST_HEAD(&adev->pm.od_kobj_list);
43373e38b634SEvan Quan 
4338beff74bcSAlex Deucher 	INIT_DELAYED_WORK(&adev->delayed_init_work,
4339beff74bcSAlex Deucher 			  amdgpu_device_delayed_init_work_handler);
43401e317b99SRex Zhu 	INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work,
43411e317b99SRex Zhu 			  amdgpu_device_delay_enable_gfx_off);
4342afefd6f2SSrinivasan Shanmugam 	/*
4343afefd6f2SSrinivasan Shanmugam 	 * Initialize the enforce_isolation work structures for each XCP
4344afefd6f2SSrinivasan Shanmugam 	 * partition.  This work handler is responsible for enforcing shader
4345afefd6f2SSrinivasan Shanmugam 	 * isolation on AMD GPUs.  It counts the number of emitted fences for
4346afefd6f2SSrinivasan Shanmugam 	 * each GFX and compute ring.  If there are any fences, it schedules
4347afefd6f2SSrinivasan Shanmugam 	 * the `enforce_isolation_work` to be run after a delay.  If there are
4348afefd6f2SSrinivasan Shanmugam 	 * no fences, it signals the Kernel Fusion Driver (KFD) to resume the
4349afefd6f2SSrinivasan Shanmugam 	 * runqueue.
4350afefd6f2SSrinivasan Shanmugam 	 */
4351afefd6f2SSrinivasan Shanmugam 	for (i = 0; i < MAX_XCP; i++) {
4352afefd6f2SSrinivasan Shanmugam 		INIT_DELAYED_WORK(&adev->gfx.enforce_isolation[i].work,
4353afefd6f2SSrinivasan Shanmugam 				  amdgpu_gfx_enforce_isolation_handler);
4354afefd6f2SSrinivasan Shanmugam 		adev->gfx.enforce_isolation[i].adev = adev;
4355afefd6f2SSrinivasan Shanmugam 		adev->gfx.enforce_isolation[i].xcp_id = i;
4356afefd6f2SSrinivasan Shanmugam 	}
43572dc80b00SShirish S 
4358d4535e2cSAndrey Grodzovsky 	INIT_WORK(&adev->xgmi_reset_work, amdgpu_device_xgmi_reset_func);
4359d4535e2cSAndrey Grodzovsky 
4360d23ee13fSRex Zhu 	adev->gfx.gfx_off_req_count = 1;
43610ad7347aSAndré Almeida 	adev->gfx.gfx_off_residency = 0;
43620ad7347aSAndré Almeida 	adev->gfx.gfx_off_entrycount = 0;
4363b6e79d9aSJason Yan 	adev->pm.ac_power = power_supply_is_system_supplied() > 0;
4364b1ddf548SRex Zhu 
4365b265bdbdSEvan Quan 	atomic_set(&adev->throttling_logging_enabled, 1);
4366b265bdbdSEvan Quan 	/*
4367b265bdbdSEvan Quan 	 * If throttling continues, logging will be performed every minute
4368b265bdbdSEvan Quan 	 * to avoid log flooding. "-1" is subtracted since the thermal
4369b265bdbdSEvan Quan 	 * throttling interrupt comes every second. Thus, the total logging
4370b265bdbdSEvan Quan 	 * interval is 59 seconds(retelimited printk interval) + 1(waiting
4371b265bdbdSEvan Quan 	 * for throttling interrupt) = 60 seconds.
4372b265bdbdSEvan Quan 	 */
4373b265bdbdSEvan Quan 	ratelimit_state_init(&adev->throttling_logging_rs, (60 - 1) * HZ, 1);
437484a2947eSVictor Skvortsov 
4375b265bdbdSEvan Quan 	ratelimit_set_flags(&adev->throttling_logging_rs, RATELIMIT_MSG_ON_RELEASE);
4376b265bdbdSEvan Quan 
43770fa49558SAlex Xie 	/* Registers mapping */
43780fa49558SAlex Xie 	/* TODO: block userspace mapping of io register */
4379da69c161SKen Wang 	if (adev->asic_type >= CHIP_BONAIRE) {
4380d38ceaf9SAlex Deucher 		adev->rmmio_base = pci_resource_start(adev->pdev, 5);
4381d38ceaf9SAlex Deucher 		adev->rmmio_size = pci_resource_len(adev->pdev, 5);
4382da69c161SKen Wang 	} else {
4383da69c161SKen Wang 		adev->rmmio_base = pci_resource_start(adev->pdev, 2);
4384da69c161SKen Wang 		adev->rmmio_size = pci_resource_len(adev->pdev, 2);
4385da69c161SKen Wang 	}
43865c1354bdSChunming Zhou 
43876c08e0efSEvan Quan 	for (i = 0; i < AMD_IP_BLOCK_TYPE_NUM; i++)
43886c08e0efSEvan Quan 		atomic_set(&adev->pm.pwr_state[i], POWER_STATE_UNKNOWN);
43896c08e0efSEvan Quan 
4390d38ceaf9SAlex Deucher 	adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size);
4391b8920e1eSSrinivasan Shanmugam 	if (!adev->rmmio)
4392d38ceaf9SAlex Deucher 		return -ENOMEM;
4393b8920e1eSSrinivasan Shanmugam 
4394d38ceaf9SAlex Deucher 	DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base);
4395b8920e1eSSrinivasan Shanmugam 	DRM_INFO("register mmio size: %u\n", (unsigned int)adev->rmmio_size);
4396d38ceaf9SAlex Deucher 
4397436afdfaSPhilip Yang 	/*
4398436afdfaSPhilip Yang 	 * Reset domain needs to be present early, before XGMI hive discovered
4399a567db80SRandy Dunlap 	 * (if any) and initialized to use reset sem and in_gpu reset flag
4400436afdfaSPhilip Yang 	 * early on during init and before calling to RREG32.
4401436afdfaSPhilip Yang 	 */
4402436afdfaSPhilip Yang 	adev->reset_domain = amdgpu_reset_create_reset_domain(SINGLE_DEVICE, "amdgpu-reset-dev");
440303c6284dSMa Jun 	if (!adev->reset_domain)
440403c6284dSMa Jun 		return -ENOMEM;
4405436afdfaSPhilip Yang 
44063aa0115dSMonk Liu 	/* detect hw virtualization here */
4407a91d91b6STony Yi 	amdgpu_virt_init(adev);
44083aa0115dSMonk Liu 
440904e85958STong Liu01 	amdgpu_device_get_pcie_info(adev);
441004e85958STong Liu01 
4411dffa11b4SMonk Liu 	r = amdgpu_device_get_job_timeout_settings(adev);
4412a190d1c7SXiaojie Yuan 	if (r) {
4413dffa11b4SMonk Liu 		dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n");
441403c6284dSMa Jun 		return r;
4415a190d1c7SXiaojie Yuan 	}
4416a190d1c7SXiaojie Yuan 
4417bf909454SPierre-Eric Pelloux-Prayer 	amdgpu_device_set_mcbp(adev);
4418bf909454SPierre-Eric Pelloux-Prayer 
441914f2fe34SLijo Lazar 	/*
442014f2fe34SLijo Lazar 	 * By default, use default mode where all blocks are expected to be
442114f2fe34SLijo Lazar 	 * initialized. At present a 'swinit' of blocks is required to be
442214f2fe34SLijo Lazar 	 * completed before the need for a different level is detected.
442314f2fe34SLijo Lazar 	 */
442414f2fe34SLijo Lazar 	amdgpu_set_init_level(adev, AMDGPU_INIT_LEVEL_DEFAULT);
4425d38ceaf9SAlex Deucher 	/* early init functions */
442606ec9070SAlex Deucher 	r = amdgpu_device_ip_early_init(adev);
4427d38ceaf9SAlex Deucher 	if (r)
442803c6284dSMa Jun 		return r;
4429d38ceaf9SAlex Deucher 
44309deacd6cSAlex Deucher 	/*
44319deacd6cSAlex Deucher 	 * No need to remove conflicting FBs for non-display class devices.
44329deacd6cSAlex Deucher 	 * This prevents the sysfb from being freed accidently.
44339deacd6cSAlex Deucher 	 */
44349deacd6cSAlex Deucher 	if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA ||
44359deacd6cSAlex Deucher 	    (pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) {
4436b7cdb41eSMario Limonciello 		/* Get rid of things like offb */
4437ea1d2a38SThomas Zimmermann 		r = aperture_remove_conflicting_pci_devices(adev->pdev, amdgpu_kms_driver.name);
4438b7cdb41eSMario Limonciello 		if (r)
443903c6284dSMa Jun 			return r;
44409deacd6cSAlex Deucher 	}
4441b7cdb41eSMario Limonciello 
44424d33e704SSunil Khatri 	/* Enable TMZ based on IP_VERSION */
44434d33e704SSunil Khatri 	amdgpu_gmc_tmz_set(adev);
44444d33e704SSunil Khatri 
44453e2daccaSDanijel Slivka 	if (amdgpu_sriov_vf(adev) &&
44463e2daccaSDanijel Slivka 	    amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
44473e2daccaSDanijel Slivka 		/* VF MMIO access (except mailbox range) from CPU
44483e2daccaSDanijel Slivka 		 * will be blocked during sriov runtime
44493e2daccaSDanijel Slivka 		 */
44503e2daccaSDanijel Slivka 		adev->virt.caps |= AMDGPU_VF_MMIO_ACCESS_PROTECT;
44513e2daccaSDanijel Slivka 
4452957b0787SYifan Zhang 	amdgpu_gmc_noretry_set(adev);
44534a0165f0SVictor Skvortsov 	/* Need to get xgmi info early to decide the reset behavior*/
44544a0165f0SVictor Skvortsov 	if (adev->gmc.xgmi.supported) {
44554a0165f0SVictor Skvortsov 		r = adev->gfxhub.funcs->get_xgmi_info(adev);
44564a0165f0SVictor Skvortsov 		if (r)
445703c6284dSMa Jun 			return r;
44584a0165f0SVictor Skvortsov 	}
44594a0165f0SVictor Skvortsov 
44608e6d0b69Sshaoyunl 	/* enable PCIE atomic ops */
4461b4520bfdSGavin Wan 	if (amdgpu_sriov_vf(adev)) {
4462b4520bfdSGavin Wan 		if (adev->virt.fw_reserve.p_pf2vf)
44638e6d0b69Sshaoyunl 			adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
4464e15c9d06SBokun Zhang 						      adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_support_flags ==
44658e6d0b69Sshaoyunl 				(PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64);
44660e768043SYifan Zhang 	/* APUs w/ gfx9 onwards doesn't reply on PCIe atomics, rather it is a
44670e768043SYifan Zhang 	 * internal path natively support atomics, set have_atomics_support to true.
44680e768043SYifan Zhang 	 */
4469b4520bfdSGavin Wan 	} else if ((adev->flags & AMD_IS_APU) &&
44704e8303cfSLijo Lazar 		   (amdgpu_ip_version(adev, GC_HWIP, 0) >
44714e8303cfSLijo Lazar 		    IP_VERSION(9, 0, 0))) {
44720e768043SYifan Zhang 		adev->have_atomics_support = true;
4473b4520bfdSGavin Wan 	} else {
44748e6d0b69Sshaoyunl 		adev->have_atomics_support =
44758e6d0b69Sshaoyunl 			!pci_enable_atomic_ops_to_root(adev->pdev,
44768e6d0b69Sshaoyunl 					  PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
44778e6d0b69Sshaoyunl 					  PCI_EXP_DEVCAP2_ATOMIC_COMP64);
4478b4520bfdSGavin Wan 	}
4479b4520bfdSGavin Wan 
44808e6d0b69Sshaoyunl 	if (!adev->have_atomics_support)
44818e6d0b69Sshaoyunl 		dev_info(adev->dev, "PCIE atomic ops is not supported\n");
44828e6d0b69Sshaoyunl 
44836585661dSOak Zeng 	/* doorbell bar mapping and doorbell index init*/
448443c064dbSShashank Sharma 	amdgpu_doorbell_init(adev);
44856585661dSOak Zeng 
44869475a943SShaoyun Liu 	if (amdgpu_emu_mode == 1) {
44879475a943SShaoyun Liu 		/* post the asic on emulation mode */
44889475a943SShaoyun Liu 		emu_soc_asic_init(adev);
4489bfca0289SShaoyun Liu 		goto fence_driver_init;
44909475a943SShaoyun Liu 	}
4491bfca0289SShaoyun Liu 
449204442bf7SLijo Lazar 	amdgpu_reset_init(adev);
449304442bf7SLijo Lazar 
44944e99a44eSMonk Liu 	/* detect if we are with an SRIOV vbios */
4495b4520bfdSGavin Wan 	if (adev->bios)
44964e99a44eSMonk Liu 		amdgpu_device_detect_sriov_bios(adev);
4497048765adSAndres Rodriguez 
449895e8e59eSAlex Deucher 	/* check if we need to reset the asic
449995e8e59eSAlex Deucher 	 *  E.g., driver was not cleanly unloaded previously, etc.
450095e8e59eSAlex Deucher 	 */
4501f14899fdSwentalou 	if (!amdgpu_sriov_vf(adev) && amdgpu_asic_need_reset_on_init(adev)) {
4502e3c1b071Sshaoyunl 		if (adev->gmc.xgmi.num_physical_nodes) {
4503e3c1b071Sshaoyunl 			dev_info(adev->dev, "Pending hive reset.\n");
45045839d27dSLijo Lazar 			amdgpu_set_init_level(adev,
45055839d27dSLijo Lazar 					      AMDGPU_INIT_LEVEL_MINIMAL_XGMI);
45067c1d9e10SKenneth Feng 		} else if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) &&
45077c1d9e10SKenneth Feng 				   !amdgpu_device_has_display_hardware(adev)) {
45087c1d9e10SKenneth Feng 					r = psp_gpu_reset(adev);
4509e3c1b071Sshaoyunl 		} else {
451059e9fff1Slyndonli 				tmp = amdgpu_reset_method;
451159e9fff1Slyndonli 				/* It should do a default reset when loading or reloading the driver,
451259e9fff1Slyndonli 				 * regardless of the module parameter reset_method.
451359e9fff1Slyndonli 				 */
451459e9fff1Slyndonli 				amdgpu_reset_method = AMD_RESET_METHOD_NONE;
451595e8e59eSAlex Deucher 				r = amdgpu_asic_reset(adev);
451659e9fff1Slyndonli 				amdgpu_reset_method = tmp;
45177c1d9e10SKenneth Feng 		}
45187c1d9e10SKenneth Feng 
451995e8e59eSAlex Deucher 		if (r) {
452095e8e59eSAlex Deucher 		  dev_err(adev->dev, "asic reset on init failed\n");
452195e8e59eSAlex Deucher 		  goto failed;
452295e8e59eSAlex Deucher 		}
452395e8e59eSAlex Deucher 	}
452495e8e59eSAlex Deucher 
4525d38ceaf9SAlex Deucher 	/* Post card if necessary */
452639c640c0SAlex Deucher 	if (amdgpu_device_need_post(adev)) {
4527d38ceaf9SAlex Deucher 		if (!adev->bios) {
4528bec86378SMonk Liu 			dev_err(adev->dev, "no vBIOS found\n");
452983ba126aSAlex Deucher 			r = -EINVAL;
453083ba126aSAlex Deucher 			goto failed;
4531d38ceaf9SAlex Deucher 		}
4532bec86378SMonk Liu 		DRM_INFO("GPU posting now...\n");
45334d2997abSAlex Deucher 		r = amdgpu_device_asic_init(adev);
45344e99a44eSMonk Liu 		if (r) {
45354e99a44eSMonk Liu 			dev_err(adev->dev, "gpu post error!\n");
45364e99a44eSMonk Liu 			goto failed;
45374e99a44eSMonk Liu 		}
4538d38ceaf9SAlex Deucher 	}
4539d38ceaf9SAlex Deucher 
45409535a86aSShiwu Zhang 	if (adev->bios) {
454188b64e95SAlex Deucher 		if (adev->is_atom_fw) {
454288b64e95SAlex Deucher 			/* Initialize clocks */
454388b64e95SAlex Deucher 			r = amdgpu_atomfirmware_get_clock_info(adev);
454488b64e95SAlex Deucher 			if (r) {
454588b64e95SAlex Deucher 				dev_err(adev->dev, "amdgpu_atomfirmware_get_clock_info failed\n");
4546e23b74aaSAlex Deucher 				amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
454788b64e95SAlex Deucher 				goto failed;
454888b64e95SAlex Deucher 			}
454988b64e95SAlex Deucher 		} else {
4550d38ceaf9SAlex Deucher 			/* Initialize clocks */
4551d38ceaf9SAlex Deucher 			r = amdgpu_atombios_get_clock_info(adev);
45522c1a2784SAlex Deucher 			if (r) {
45532c1a2784SAlex Deucher 				dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n");
4554e23b74aaSAlex Deucher 				amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
455589041940SGavin Wan 				goto failed;
45562c1a2784SAlex Deucher 			}
4557d38ceaf9SAlex Deucher 			/* init i2c buses */
45581c0b144bSAlex Deucher 			amdgpu_i2c_init(adev);
4559a5bde2f9SAlex Deucher 		}
45609535a86aSShiwu Zhang 	}
4561d38ceaf9SAlex Deucher 
4562bfca0289SShaoyun Liu fence_driver_init:
4563d38ceaf9SAlex Deucher 	/* Fence driver */
4564067f44c8SGuchun Chen 	r = amdgpu_fence_driver_sw_init(adev);
45652c1a2784SAlex Deucher 	if (r) {
4566067f44c8SGuchun Chen 		dev_err(adev->dev, "amdgpu_fence_driver_sw_init failed\n");
4567e23b74aaSAlex Deucher 		amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0);
456883ba126aSAlex Deucher 		goto failed;
45692c1a2784SAlex Deucher 	}
4570d38ceaf9SAlex Deucher 
4571d38ceaf9SAlex Deucher 	/* init the mode config */
45724a580877SLuben Tuikov 	drm_mode_config_init(adev_to_drm(adev));
4573d38ceaf9SAlex Deucher 
457406ec9070SAlex Deucher 	r = amdgpu_device_ip_init(adev);
4575d38ceaf9SAlex Deucher 	if (r) {
457606ec9070SAlex Deucher 		dev_err(adev->dev, "amdgpu_device_ip_init failed\n");
4577e23b74aaSAlex Deucher 		amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0);
4578970fd197SStanley.Yang 		goto release_ras_con;
4579d38ceaf9SAlex Deucher 	}
4580d38ceaf9SAlex Deucher 
45818d35a259SLikun Gao 	amdgpu_fence_driver_hw_init(adev);
45828d35a259SLikun Gao 
4583d69b8971SYong Zhao 	dev_info(adev->dev,
4584d69b8971SYong Zhao 		"SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n",
4585d7f72fe4SYong Zhao 			adev->gfx.config.max_shader_engines,
4586d7f72fe4SYong Zhao 			adev->gfx.config.max_sh_per_se,
4587d7f72fe4SYong Zhao 			adev->gfx.config.max_cu_per_sh,
4588d7f72fe4SYong Zhao 			adev->gfx.cu_info.number);
4589d7f72fe4SYong Zhao 
4590d38ceaf9SAlex Deucher 	adev->accel_working = true;
4591d38ceaf9SAlex Deucher 
4592e59c0205SAlex Xie 	amdgpu_vm_check_compute_bug(adev);
4593e59c0205SAlex Xie 
459495844d20SMarek Olšák 	/* Initialize the buffer migration limit. */
459595844d20SMarek Olšák 	if (amdgpu_moverate >= 0)
459695844d20SMarek Olšák 		max_MBps = amdgpu_moverate;
459795844d20SMarek Olšák 	else
459895844d20SMarek Olšák 		max_MBps = 8; /* Allow 8 MB/s. */
459995844d20SMarek Olšák 	/* Get a log2 for easy divisions. */
460095844d20SMarek Olšák 	adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
460195844d20SMarek Olšák 
4602b0adca4dSEvan Quan 	/*
4603b0adca4dSEvan Quan 	 * Register gpu instance before amdgpu_device_enable_mgpu_fan_boost.
4604b0adca4dSEvan Quan 	 * Otherwise the mgpu fan boost feature will be skipped due to the
4605b0adca4dSEvan Quan 	 * gpu instance is counted less.
4606b0adca4dSEvan Quan 	 */
4607b0adca4dSEvan Quan 	amdgpu_register_gpu_instance(adev);
4608b0adca4dSEvan Quan 
4609d38ceaf9SAlex Deucher 	/* enable clockgating, etc. after ib tests, etc. since some blocks require
4610d38ceaf9SAlex Deucher 	 * explicit gating rather than handling it automatically.
4611d38ceaf9SAlex Deucher 	 */
46125839d27dSLijo Lazar 	if (adev->init_lvl->level != AMDGPU_INIT_LEVEL_MINIMAL_XGMI) {
461306ec9070SAlex Deucher 		r = amdgpu_device_ip_late_init(adev);
46142c1a2784SAlex Deucher 		if (r) {
461506ec9070SAlex Deucher 			dev_err(adev->dev, "amdgpu_device_ip_late_init failed\n");
4616e23b74aaSAlex Deucher 			amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_LATE_INIT_FAIL, 0, r);
4617970fd197SStanley.Yang 			goto release_ras_con;
46182c1a2784SAlex Deucher 		}
4619108c6a63Sxinhui pan 		/* must succeed. */
4620511fdbc3Sxinhui pan 		amdgpu_ras_resume(adev);
4621beff74bcSAlex Deucher 		queue_delayed_work(system_wq, &adev->delayed_init_work,
4622beff74bcSAlex Deucher 				   msecs_to_jiffies(AMDGPU_RESUME_MS));
4623e3c1b071Sshaoyunl 	}
4624beff74bcSAlex Deucher 
462538eecbe0SChong Li 	if (amdgpu_sriov_vf(adev)) {
462638eecbe0SChong Li 		amdgpu_virt_release_full_gpu(adev, true);
46272c738637SMonk Liu 		flush_delayed_work(&adev->delayed_init_work);
462838eecbe0SChong Li 	}
46292c738637SMonk Liu 
463090bcb9b5SEvan Quan 	/*
463190bcb9b5SEvan Quan 	 * Place those sysfs registering after `late_init`. As some of those
463290bcb9b5SEvan Quan 	 * operations performed in `late_init` might affect the sysfs
463390bcb9b5SEvan Quan 	 * interfaces creating.
463490bcb9b5SEvan Quan 	 */
463590bcb9b5SEvan Quan 	r = amdgpu_atombios_sysfs_init(adev);
463690bcb9b5SEvan Quan 	if (r)
463790bcb9b5SEvan Quan 		drm_err(&adev->ddev,
463890bcb9b5SEvan Quan 			"registering atombios sysfs failed (%d).\n", r);
463990bcb9b5SEvan Quan 
464090bcb9b5SEvan Quan 	r = amdgpu_pm_sysfs_init(adev);
464190bcb9b5SEvan Quan 	if (r)
464290bcb9b5SEvan Quan 		DRM_ERROR("registering pm sysfs failed (%d).\n", r);
464390bcb9b5SEvan Quan 
464490bcb9b5SEvan Quan 	r = amdgpu_ucode_sysfs_init(adev);
464590bcb9b5SEvan Quan 	if (r) {
464690bcb9b5SEvan Quan 		adev->ucode_sysfs_en = false;
464790bcb9b5SEvan Quan 		DRM_ERROR("Creating firmware sysfs failed (%d).\n", r);
464890bcb9b5SEvan Quan 	} else
464990bcb9b5SEvan Quan 		adev->ucode_sysfs_en = true;
465090bcb9b5SEvan Quan 
46519c05636cSVictor Skvortsov 	r = amdgpu_device_attr_sysfs_init(adev);
46525aea5327SLuben Tuikov 	if (r)
465377f3a5cdSNirmoy Das 		dev_err(adev->dev, "Could not create amdgpu device attr\n");
4654bd607166SKent Russell 
465576da73f0SLijo Lazar 	r = devm_device_add_group(adev->dev, &amdgpu_board_attrs_group);
465676da73f0SLijo Lazar 	if (r)
465776da73f0SLijo Lazar 		dev_err(adev->dev,
465876da73f0SLijo Lazar 			"Could not create amdgpu board attributes\n");
465976da73f0SLijo Lazar 
46607957ec80SLijo Lazar 	amdgpu_fru_sysfs_init(adev);
4661af39e6f4SLijo Lazar 	amdgpu_reg_state_sysfs_init(adev);
46624ae86dc8SLijo Lazar 	amdgpu_xcp_cfg_sysfs_init(adev);
46637957ec80SLijo Lazar 
4664d155bef0SArnd Bergmann 	if (IS_ENABLED(CONFIG_PERF_EVENTS))
46659c7c85f7SJonathan Kim 		r = amdgpu_pmu_init(adev);
46669c7c85f7SJonathan Kim 	if (r)
46679c7c85f7SJonathan Kim 		dev_err(adev->dev, "amdgpu_pmu_init failed\n");
46689c7c85f7SJonathan Kim 
4669c1dd4aa6SAndrey Grodzovsky 	/* Have stored pci confspace at hand for restore in sudden PCI error */
4670c1dd4aa6SAndrey Grodzovsky 	if (amdgpu_device_cache_pci_state(adev->pdev))
4671c1dd4aa6SAndrey Grodzovsky 		pci_restore_state(pdev);
4672c1dd4aa6SAndrey Grodzovsky 
46738c3dd61cSKai-Heng Feng 	/* if we have > 1 VGA cards, then disable the amdgpu VGA resources */
46748c3dd61cSKai-Heng Feng 	/* this will fail for cards that aren't VGA class devices, just
4675b8920e1eSSrinivasan Shanmugam 	 * ignore it
4676b8920e1eSSrinivasan Shanmugam 	 */
46778c3dd61cSKai-Heng Feng 	if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
4678bf44e8ceSChristoph Hellwig 		vga_client_register(adev->pdev, amdgpu_device_vga_set_decode);
46798c3dd61cSKai-Heng Feng 
4680d37a3929SOrlando Chamberlain 	px = amdgpu_device_supports_px(ddev);
4681d37a3929SOrlando Chamberlain 
46827b1c6263SAlex Deucher 	if (px || (!dev_is_removable(&adev->pdev->dev) &&
4683d37a3929SOrlando Chamberlain 				apple_gmux_detect(NULL, NULL)))
46848c3dd61cSKai-Heng Feng 		vga_switcheroo_register_client(adev->pdev,
46858c3dd61cSKai-Heng Feng 					       &amdgpu_switcheroo_ops, px);
4686d37a3929SOrlando Chamberlain 
4687d37a3929SOrlando Chamberlain 	if (px)
46888c3dd61cSKai-Heng Feng 		vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
46898c3dd61cSKai-Heng Feng 
46905839d27dSLijo Lazar 	if (adev->init_lvl->level == AMDGPU_INIT_LEVEL_MINIMAL_XGMI)
4691631af731SLijo Lazar 		amdgpu_xgmi_reset_on_init(adev);
4692e3c1b071Sshaoyunl 
46934a74c38cSPhilip Yang 	amdgpu_device_check_iommu_direct_map(adev);
46944a74c38cSPhilip Yang 
46952965e635SMario Limonciello 	adev->pm_nb.notifier_call = amdgpu_device_pm_notifier;
46962965e635SMario Limonciello 	r = register_pm_notifier(&adev->pm_nb);
46972965e635SMario Limonciello 	if (r)
46982965e635SMario Limonciello 		goto failed;
46992965e635SMario Limonciello 
4700d38ceaf9SAlex Deucher 	return 0;
470183ba126aSAlex Deucher 
4702970fd197SStanley.Yang release_ras_con:
470338eecbe0SChong Li 	if (amdgpu_sriov_vf(adev))
470438eecbe0SChong Li 		amdgpu_virt_release_full_gpu(adev, true);
470538eecbe0SChong Li 
470638eecbe0SChong Li 	/* failed in exclusive mode due to timeout */
470738eecbe0SChong Li 	if (amdgpu_sriov_vf(adev) &&
470838eecbe0SChong Li 		!amdgpu_sriov_runtime(adev) &&
470938eecbe0SChong Li 		amdgpu_virt_mmio_blocked(adev) &&
471038eecbe0SChong Li 		!amdgpu_virt_wait_reset(adev)) {
471138eecbe0SChong Li 		dev_err(adev->dev, "VF exclusive mode timeout\n");
471238eecbe0SChong Li 		/* Don't send request since VF is inactive. */
471338eecbe0SChong Li 		adev->virt.caps &= ~AMDGPU_SRIOV_CAPS_RUNTIME;
471438eecbe0SChong Li 		adev->virt.ops = NULL;
471538eecbe0SChong Li 		r = -EAGAIN;
471638eecbe0SChong Li 	}
4717970fd197SStanley.Yang 	amdgpu_release_ras_context(adev);
4718970fd197SStanley.Yang 
471983ba126aSAlex Deucher failed:
472089041940SGavin Wan 	amdgpu_vf_error_trans_all(adev);
47218840a387Spding 
472283ba126aSAlex Deucher 	return r;
4723d38ceaf9SAlex Deucher }
4724d38ceaf9SAlex Deucher 
amdgpu_device_unmap_mmio(struct amdgpu_device * adev)472507775fc1SAndrey Grodzovsky static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
472607775fc1SAndrey Grodzovsky {
472762d5f9f7SLeslie Shi 
472807775fc1SAndrey Grodzovsky 	/* Clear all CPU mappings pointing to this device */
472907775fc1SAndrey Grodzovsky 	unmap_mapping_range(adev->ddev.anon_inode->i_mapping, 0, 0, 1);
473007775fc1SAndrey Grodzovsky 
473107775fc1SAndrey Grodzovsky 	/* Unmap all mapped bars - Doorbell, registers and VRAM */
473243c064dbSShashank Sharma 	amdgpu_doorbell_fini(adev);
473307775fc1SAndrey Grodzovsky 
473407775fc1SAndrey Grodzovsky 	iounmap(adev->rmmio);
473507775fc1SAndrey Grodzovsky 	adev->rmmio = NULL;
473607775fc1SAndrey Grodzovsky 	if (adev->mman.aper_base_kaddr)
473707775fc1SAndrey Grodzovsky 		iounmap(adev->mman.aper_base_kaddr);
473807775fc1SAndrey Grodzovsky 	adev->mman.aper_base_kaddr = NULL;
473907775fc1SAndrey Grodzovsky 
474007775fc1SAndrey Grodzovsky 	/* Memory manager related */
4741a0ba1279SLijo Lazar 	if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
474207775fc1SAndrey Grodzovsky 		arch_phys_wc_del(adev->gmc.vram_mtrr);
474307775fc1SAndrey Grodzovsky 		arch_io_free_memtype_wc(adev->gmc.aper_base, adev->gmc.aper_size);
474407775fc1SAndrey Grodzovsky 	}
474507775fc1SAndrey Grodzovsky }
474607775fc1SAndrey Grodzovsky 
4747d38ceaf9SAlex Deucher /**
4748bbe04decSIsabella Basso  * amdgpu_device_fini_hw - tear down the driver
4749d38ceaf9SAlex Deucher  *
4750d38ceaf9SAlex Deucher  * @adev: amdgpu_device pointer
4751d38ceaf9SAlex Deucher  *
4752d38ceaf9SAlex Deucher  * Tear down the driver info (all asics).
4753d38ceaf9SAlex Deucher  * Called at driver shutdown.
4754d38ceaf9SAlex Deucher  */
amdgpu_device_fini_hw(struct amdgpu_device * adev)475572c8c97bSAndrey Grodzovsky void amdgpu_device_fini_hw(struct amdgpu_device *adev)
4756d38ceaf9SAlex Deucher {
4757aac89168SDennis Li 	dev_info(adev->dev, "amdgpu: finishing device.\n");
47589f875167SJesse Zhang 	flush_delayed_work(&adev->delayed_init_work);
4759af76ca8eSVictor Zhao 
4760af76ca8eSVictor Zhao 	if (adev->mman.initialized)
4761af76ca8eSVictor Zhao 		drain_workqueue(adev->mman.bdev.wq);
4762d0d13fe8SYintian Tao 	adev->shutdown = true;
47639f875167SJesse Zhang 
47642965e635SMario Limonciello 	unregister_pm_notifier(&adev->pm_nb);
47652965e635SMario Limonciello 
4766752c683dSMonk Liu 	/* make sure IB test finished before entering exclusive mode
4767752c683dSMonk Liu 	 * to avoid preemption on IB test
4768b8920e1eSSrinivasan Shanmugam 	 */
4769519b8b76SBokun Zhang 	if (amdgpu_sriov_vf(adev)) {
4770752c683dSMonk Liu 		amdgpu_virt_request_full_gpu(adev, false);
4771519b8b76SBokun Zhang 		amdgpu_virt_fini_data_exchange(adev);
4772519b8b76SBokun Zhang 	}
4773752c683dSMonk Liu 
4774e5b03032SMikita Lipski 	/* disable all interrupts */
4775e5b03032SMikita Lipski 	amdgpu_irq_disable_all(adev);
4776ff97cba8SMikita Lipski 	if (adev->mode_info.mode_config_initialized) {
47771053b9c9SFlora Cui 		if (!drm_drv_uses_atomic_modeset(adev_to_drm(adev)))
47784a580877SLuben Tuikov 			drm_helper_force_disable_all(adev_to_drm(adev));
4779ff97cba8SMikita Lipski 		else
47804a580877SLuben Tuikov 			drm_atomic_helper_shutdown(adev_to_drm(adev));
4781ff97cba8SMikita Lipski 	}
47828d35a259SLikun Gao 	amdgpu_fence_driver_hw_fini(adev);
478372c8c97bSAndrey Grodzovsky 
478453e9d836SGuchun Chen 	if (adev->pm.sysfs_initialized)
478558e955d9SEmily Deng 		amdgpu_pm_sysfs_fini(adev);
478672c8c97bSAndrey Grodzovsky 	if (adev->ucode_sysfs_en)
478772c8c97bSAndrey Grodzovsky 		amdgpu_ucode_sysfs_fini(adev);
47889c05636cSVictor Skvortsov 	amdgpu_device_attr_sysfs_fini(adev);
47897957ec80SLijo Lazar 	amdgpu_fru_sysfs_fini(adev);
479072c8c97bSAndrey Grodzovsky 
4791af39e6f4SLijo Lazar 	amdgpu_reg_state_sysfs_fini(adev);
47924ae86dc8SLijo Lazar 	amdgpu_xcp_cfg_sysfs_fini(adev);
4793af39e6f4SLijo Lazar 
4794232d1d43SStanley.Yang 	/* disable ras feature must before hw fini */
4795232d1d43SStanley.Yang 	amdgpu_ras_pre_fini(adev);
4796232d1d43SStanley.Yang 
4797b7043800SAlex Deucher 	amdgpu_ttm_set_buffer_funcs_status(adev, false);
4798b7043800SAlex Deucher 
4799e9669fb7SAndrey Grodzovsky 	amdgpu_device_ip_fini_early(adev);
4800d10d0daaSAndrey Grodzovsky 
4801a3848df6SYuBiao Wang 	amdgpu_irq_fini_hw(adev);
4802a3848df6SYuBiao Wang 
4803b6fd6e0fSSurbhi Kakarya 	if (adev->mman.initialized)
4804894c6890SAndrey Grodzovsky 		ttm_device_clear_dma_mappings(&adev->mman.bdev);
4805894c6890SAndrey Grodzovsky 
4806d10d0daaSAndrey Grodzovsky 	amdgpu_gart_dummy_page_fini(adev);
480707775fc1SAndrey Grodzovsky 
480839934d3eSVitaly Prosyak 	if (drm_dev_is_unplugged(adev_to_drm(adev)))
480907775fc1SAndrey Grodzovsky 		amdgpu_device_unmap_mmio(adev);
481087172e89SLeslie Shi 
481172c8c97bSAndrey Grodzovsky }
481272c8c97bSAndrey Grodzovsky 
amdgpu_device_fini_sw(struct amdgpu_device * adev)481372c8c97bSAndrey Grodzovsky void amdgpu_device_fini_sw(struct amdgpu_device *adev)
481472c8c97bSAndrey Grodzovsky {
4815bd22e44aSChristian König 	int i, idx;
4816d37a3929SOrlando Chamberlain 	bool px;
481762d5f9f7SLeslie Shi 
4818a5c5d8d5SLang Yu 	amdgpu_device_ip_fini(adev);
4819b61badd2SVitaly Prosyak 	amdgpu_fence_driver_sw_fini(adev);
4820b31d3063SMario Limonciello 	amdgpu_ucode_release(&adev->firmware.gpu_info_fw);
4821d38ceaf9SAlex Deucher 	adev->accel_working = false;
482268ce8b24SChristian König 	dma_fence_put(rcu_dereference_protected(adev->gang_submit, true));
4823bd22e44aSChristian König 	for (i = 0; i < MAX_XCP; ++i) {
4824bd22e44aSChristian König 		dma_fence_put(adev->isolation[i].spearhead);
4825bd22e44aSChristian König 		amdgpu_sync_free(&adev->isolation[i].active);
4826bd22e44aSChristian König 		amdgpu_sync_free(&adev->isolation[i].prev);
4827bd22e44aSChristian König 	}
482804442bf7SLijo Lazar 
482904442bf7SLijo Lazar 	amdgpu_reset_fini(adev);
483004442bf7SLijo Lazar 
4831d38ceaf9SAlex Deucher 	/* free i2c buses */
4832d38ceaf9SAlex Deucher 	amdgpu_i2c_fini(adev);
4833bfca0289SShaoyun Liu 
48346e8ca38eSLijo Lazar 	if (adev->bios) {
4835bfca0289SShaoyun Liu 		if (amdgpu_emu_mode != 1)
4836d38ceaf9SAlex Deucher 			amdgpu_atombios_fini(adev);
4837e986e896SLijo Lazar 		amdgpu_bios_release(adev);
48386e8ca38eSLijo Lazar 	}
4839d37a3929SOrlando Chamberlain 
48408a2b5139SLijo Lazar 	kfree(adev->fru_info);
48418a2b5139SLijo Lazar 	adev->fru_info = NULL;
48428a2b5139SLijo Lazar 
4843b5aaa82eSFlora Cui 	kfree(adev->xcp_mgr);
4844b5aaa82eSFlora Cui 	adev->xcp_mgr = NULL;
4845b5aaa82eSFlora Cui 
4846d37a3929SOrlando Chamberlain 	px = amdgpu_device_supports_px(adev_to_drm(adev));
4847d37a3929SOrlando Chamberlain 
48487b1c6263SAlex Deucher 	if (px || (!dev_is_removable(&adev->pdev->dev) &&
4849d37a3929SOrlando Chamberlain 				apple_gmux_detect(NULL, NULL)))
4850d38ceaf9SAlex Deucher 		vga_switcheroo_unregister_client(adev->pdev);
4851d37a3929SOrlando Chamberlain 
4852d37a3929SOrlando Chamberlain 	if (px)
485383ba126aSAlex Deucher 		vga_switcheroo_fini_domain_pm_ops(adev->dev);
4854d37a3929SOrlando Chamberlain 
485538d6be81SAlex Deucher 	if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
4856b8779475SChristoph Hellwig 		vga_client_unregister(adev->pdev);
4857e9bc1bf7SYintian Tao 
485862d5f9f7SLeslie Shi 	if (drm_dev_enter(adev_to_drm(adev), &idx)) {
485962d5f9f7SLeslie Shi 
486062d5f9f7SLeslie Shi 		iounmap(adev->rmmio);
486162d5f9f7SLeslie Shi 		adev->rmmio = NULL;
486262d5f9f7SLeslie Shi 		drm_dev_exit(idx);
486362d5f9f7SLeslie Shi 	}
486462d5f9f7SLeslie Shi 
4865d155bef0SArnd Bergmann 	if (IS_ENABLED(CONFIG_PERF_EVENTS))
48669c7c85f7SJonathan Kim 		amdgpu_pmu_fini(adev);
486772de33f8SAlex Deucher 	if (adev->mman.discovery_bin)
4868a190d1c7SXiaojie Yuan 		amdgpu_discovery_fini(adev);
486972c8c97bSAndrey Grodzovsky 
4870cfbb6b00SAndrey Grodzovsky 	amdgpu_reset_put_reset_domain(adev->reset_domain);
4871cfbb6b00SAndrey Grodzovsky 	adev->reset_domain = NULL;
4872cfbb6b00SAndrey Grodzovsky 
487372c8c97bSAndrey Grodzovsky 	kfree(adev->pci_state);
487472c8c97bSAndrey Grodzovsky 
4875d38ceaf9SAlex Deucher }
4876d38ceaf9SAlex Deucher 
487758144d28SNirmoy Das /**
487858144d28SNirmoy Das  * amdgpu_device_evict_resources - evict device resources
487958144d28SNirmoy Das  * @adev: amdgpu device object
488058144d28SNirmoy Das  *
488158144d28SNirmoy Das  * Evicts all ttm device resources(vram BOs, gart table) from the lru list
488258144d28SNirmoy Das  * of the vram memory type. Mainly used for evicting device resources
488358144d28SNirmoy Das  * at suspend time.
488458144d28SNirmoy Das  *
488558144d28SNirmoy Das  */
amdgpu_device_evict_resources(struct amdgpu_device * adev)48867863c155SMario Limonciello static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
488758144d28SNirmoy Das {
48887863c155SMario Limonciello 	int ret;
48897863c155SMario Limonciello 
4890c2ee5c2fSMario Limonciello 	/* No need to evict vram on APUs unless going to S4 */
4891c2ee5c2fSMario Limonciello 	if (!adev->in_s4 && (adev->flags & AMD_IS_APU))
48927863c155SMario Limonciello 		return 0;
489358144d28SNirmoy Das 
48947863c155SMario Limonciello 	ret = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
48957863c155SMario Limonciello 	if (ret)
489658144d28SNirmoy Das 		DRM_WARN("evicting device resources failed\n");
48977863c155SMario Limonciello 	return ret;
489858144d28SNirmoy Das }
4899d38ceaf9SAlex Deucher 
4900d38ceaf9SAlex Deucher /*
4901d38ceaf9SAlex Deucher  * Suspend & resume.
4902d38ceaf9SAlex Deucher  */
4903d38ceaf9SAlex Deucher /**
49042965e635SMario Limonciello  * amdgpu_device_pm_notifier - Notification block for Suspend/Hibernate events
49052965e635SMario Limonciello  * @nb: notifier block
49062965e635SMario Limonciello  * @mode: suspend mode
49072965e635SMario Limonciello  * @data: data
49082965e635SMario Limonciello  *
49092965e635SMario Limonciello  * This function is called when the system is about to suspend or hibernate.
4910*4aaffc85SAlex Deucher  * It is used to set the appropriate flags so that eviction can be optimized
4911*4aaffc85SAlex Deucher  * in the pm prepare callback.
49122965e635SMario Limonciello  */
amdgpu_device_pm_notifier(struct notifier_block * nb,unsigned long mode,void * data)49132965e635SMario Limonciello static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mode,
49142965e635SMario Limonciello 				     void *data)
49152965e635SMario Limonciello {
49162965e635SMario Limonciello 	struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, pm_nb);
49172965e635SMario Limonciello 
49182965e635SMario Limonciello 	switch (mode) {
49192965e635SMario Limonciello 	case PM_HIBERNATION_PREPARE:
49202965e635SMario Limonciello 		adev->in_s4 = true;
4921*4aaffc85SAlex Deucher 		break;
4922*4aaffc85SAlex Deucher 	case PM_POST_HIBERNATION:
4923*4aaffc85SAlex Deucher 		adev->in_s4 = false;
49242965e635SMario Limonciello 		break;
49252965e635SMario Limonciello 	}
49262965e635SMario Limonciello 
49272965e635SMario Limonciello 	return NOTIFY_DONE;
49282965e635SMario Limonciello }
49292965e635SMario Limonciello 
49302965e635SMario Limonciello /**
49315095d541SMario Limonciello  * amdgpu_device_prepare - prepare for device suspend
49325095d541SMario Limonciello  *
49335095d541SMario Limonciello  * @dev: drm dev pointer
49345095d541SMario Limonciello  *
49355095d541SMario Limonciello  * Prepare to put the hw in the suspend state (all asics).
49365095d541SMario Limonciello  * Returns 0 for success or an error on failure.
49375095d541SMario Limonciello  * Called at driver suspend.
49385095d541SMario Limonciello  */
amdgpu_device_prepare(struct drm_device * dev)49395095d541SMario Limonciello int amdgpu_device_prepare(struct drm_device *dev)
49405095d541SMario Limonciello {
49415095d541SMario Limonciello 	struct amdgpu_device *adev = drm_to_adev(dev);
4942cb11ca32SMario Limonciello 	int i, r;
49435095d541SMario Limonciello 
49445095d541SMario Limonciello 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
49455095d541SMario Limonciello 		return 0;
49465095d541SMario Limonciello 
49475095d541SMario Limonciello 	/* Evict the majority of BOs before starting suspend sequence */
49485095d541SMario Limonciello 	r = amdgpu_device_evict_resources(adev);
49495095d541SMario Limonciello 	if (r)
4950d0ce1aaaSAlex Deucher 		return r;
49515095d541SMario Limonciello 
49520355b24bSMario Limonciello 	flush_delayed_work(&adev->gfx.gfx_off_delay_work);
49530355b24bSMario Limonciello 
4954cb11ca32SMario Limonciello 	for (i = 0; i < adev->num_ip_blocks; i++) {
4955cb11ca32SMario Limonciello 		if (!adev->ip_blocks[i].status.valid)
4956cb11ca32SMario Limonciello 			continue;
4957cb11ca32SMario Limonciello 		if (!adev->ip_blocks[i].version->funcs->prepare_suspend)
4958cb11ca32SMario Limonciello 			continue;
495994b2e07aSSunil Khatri 		r = adev->ip_blocks[i].version->funcs->prepare_suspend(&adev->ip_blocks[i]);
4960cb11ca32SMario Limonciello 		if (r)
4961d0ce1aaaSAlex Deucher 			return r;
4962cb11ca32SMario Limonciello 	}
4963cb11ca32SMario Limonciello 
49645095d541SMario Limonciello 	return 0;
49655095d541SMario Limonciello }
49665095d541SMario Limonciello 
49675095d541SMario Limonciello /**
4968810ddc3aSAlex Deucher  * amdgpu_device_suspend - initiate device suspend
4969d38ceaf9SAlex Deucher  *
497087e3f136SDarren Powell  * @dev: drm dev pointer
49714cf50baeSThomas Zimmermann  * @notify_clients: notify in-kernel DRM clients
4972d38ceaf9SAlex Deucher  *
4973d38ceaf9SAlex Deucher  * Puts the hw in the suspend state (all asics).
4974d38ceaf9SAlex Deucher  * Returns 0 for success or an error on failure.
4975d38ceaf9SAlex Deucher  * Called at driver suspend.
4976d38ceaf9SAlex Deucher  */
amdgpu_device_suspend(struct drm_device * dev,bool notify_clients)49774cf50baeSThomas Zimmermann int amdgpu_device_suspend(struct drm_device *dev, bool notify_clients)
4978d38ceaf9SAlex Deucher {
4979a2e15b0eSAlex Deucher 	struct amdgpu_device *adev = drm_to_adev(dev);
4980d7274ec7SBokun Zhang 	int r = 0;
4981d38ceaf9SAlex Deucher 
4982d38ceaf9SAlex Deucher 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
4983d38ceaf9SAlex Deucher 		return 0;
4984d38ceaf9SAlex Deucher 
498544779b43SRex Zhu 	adev->in_suspend = true;
49863fa8f89dSSathishkumar S 
4987d7274ec7SBokun Zhang 	if (amdgpu_sriov_vf(adev)) {
4988d7274ec7SBokun Zhang 		amdgpu_virt_fini_data_exchange(adev);
4989d7274ec7SBokun Zhang 		r = amdgpu_virt_request_full_gpu(adev, false);
4990d7274ec7SBokun Zhang 		if (r)
4991d7274ec7SBokun Zhang 			return r;
4992d7274ec7SBokun Zhang 	}
4993d7274ec7SBokun Zhang 
49943fa8f89dSSathishkumar S 	if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))
49953fa8f89dSSathishkumar S 		DRM_WARN("smart shift update failed\n");
49963fa8f89dSSathishkumar S 
49974cf50baeSThomas Zimmermann 	if (notify_clients)
49984cf50baeSThomas Zimmermann 		drm_client_dev_suspend(adev_to_drm(adev), false);
49995f818173SShirish S 
5000beff74bcSAlex Deucher 	cancel_delayed_work_sync(&adev->delayed_init_work);
5001a5459475SRex Zhu 
50025e6932feSxinhui pan 	amdgpu_ras_suspend(adev);
50035e6932feSxinhui pan 
50042196927bSLee Jones 	amdgpu_device_ip_suspend_phase1(adev);
5005fe1053b7SAlex Deucher 
5006c004d44eSMukul Joshi 	if (!adev->in_s0ix)
5007ad887af9SAlex Deucher 		amdgpu_amdkfd_suspend(adev, adev->in_runpm);
500894fa5660SEvan Quan 
50097863c155SMario Limonciello 	r = amdgpu_device_evict_resources(adev);
50107863c155SMario Limonciello 	if (r)
50117863c155SMario Limonciello 		return r;
5012d38ceaf9SAlex Deucher 
5013dab96d8bSAlex Deucher 	amdgpu_ttm_set_buffer_funcs_status(adev, false);
5014dab96d8bSAlex Deucher 
50158d35a259SLikun Gao 	amdgpu_fence_driver_hw_fini(adev);
5016d38ceaf9SAlex Deucher 
50172196927bSLee Jones 	amdgpu_device_ip_suspend_phase2(adev);
5018d38ceaf9SAlex Deucher 
5019d7274ec7SBokun Zhang 	if (amdgpu_sriov_vf(adev))
5020d7274ec7SBokun Zhang 		amdgpu_virt_release_full_gpu(adev, false);
5021d7274ec7SBokun Zhang 
50222e9b1523SPerry Yuan 	r = amdgpu_dpm_notify_rlc_state(adev, false);
50232e9b1523SPerry Yuan 	if (r)
50242e9b1523SPerry Yuan 		return r;
50252e9b1523SPerry Yuan 
5026d38ceaf9SAlex Deucher 	return 0;
5027d38ceaf9SAlex Deucher }
5028d38ceaf9SAlex Deucher 
5029d38ceaf9SAlex Deucher /**
5030810ddc3aSAlex Deucher  * amdgpu_device_resume - initiate device resume
5031d38ceaf9SAlex Deucher  *
503287e3f136SDarren Powell  * @dev: drm dev pointer
50334cf50baeSThomas Zimmermann  * @notify_clients: notify in-kernel DRM clients
5034d38ceaf9SAlex Deucher  *
5035d38ceaf9SAlex Deucher  * Bring the hw back to operating state (all asics).
5036d38ceaf9SAlex Deucher  * Returns 0 for success or an error on failure.
5037d38ceaf9SAlex Deucher  * Called at driver resume.
5038d38ceaf9SAlex Deucher  */
amdgpu_device_resume(struct drm_device * dev,bool notify_clients)50394cf50baeSThomas Zimmermann int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
5040d38ceaf9SAlex Deucher {
50411348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
504203161a6eSHuang Rui 	int r = 0;
5043d38ceaf9SAlex Deucher 
5044d7274ec7SBokun Zhang 	if (amdgpu_sriov_vf(adev)) {
5045d7274ec7SBokun Zhang 		r = amdgpu_virt_request_full_gpu(adev, true);
5046d7274ec7SBokun Zhang 		if (r)
5047d7274ec7SBokun Zhang 			return r;
5048d7274ec7SBokun Zhang 	}
5049d7274ec7SBokun Zhang 
5050d38ceaf9SAlex Deucher 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
5051d38ceaf9SAlex Deucher 		return 0;
5052d38ceaf9SAlex Deucher 
505362498733SAlex Deucher 	if (adev->in_s0ix)
5054bc143d8bSEvan Quan 		amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D0Entry);
5055628c36d7SPrike Liang 
5056d38ceaf9SAlex Deucher 	/* post card */
505739c640c0SAlex Deucher 	if (amdgpu_device_need_post(adev)) {
50584d2997abSAlex Deucher 		r = amdgpu_device_asic_init(adev);
505974b0b157Sjimqu 		if (r)
5060aac89168SDennis Li 			dev_err(adev->dev, "amdgpu asic init failed\n");
506174b0b157Sjimqu 	}
5062d38ceaf9SAlex Deucher 
506306ec9070SAlex Deucher 	r = amdgpu_device_ip_resume(adev);
5064d7274ec7SBokun Zhang 
5065e6707218SRex Zhu 	if (r) {
5066aac89168SDennis Li 		dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
50673c22c1eaSShikang Fan 		goto exit;
5068e6707218SRex Zhu 	}
50695ceb54c6SAlex Deucher 
5070c004d44eSMukul Joshi 	if (!adev->in_s0ix) {
5071ad887af9SAlex Deucher 		r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
5072ba997709SYong Zhao 		if (r)
50733c22c1eaSShikang Fan 			goto exit;
50745d3a2d95SAlex Deucher 	}
5075756e6880SAlex Deucher 
50768ed79c40STim Huang 	r = amdgpu_device_ip_late_init(adev);
50778ed79c40STim Huang 	if (r)
50788ed79c40STim Huang 		goto exit;
50798ed79c40STim Huang 
50808ed79c40STim Huang 	queue_delayed_work(system_wq, &adev->delayed_init_work,
50818ed79c40STim Huang 			   msecs_to_jiffies(AMDGPU_RESUME_MS));
50823c22c1eaSShikang Fan exit:
50833c22c1eaSShikang Fan 	if (amdgpu_sriov_vf(adev)) {
50843c22c1eaSShikang Fan 		amdgpu_virt_init_data_exchange(adev);
50853c22c1eaSShikang Fan 		amdgpu_virt_release_full_gpu(adev, true);
50863c22c1eaSShikang Fan 	}
50873c22c1eaSShikang Fan 
50883c22c1eaSShikang Fan 	if (r)
50893c22c1eaSShikang Fan 		return r;
50903c22c1eaSShikang Fan 
509196a5d8d4SLeo Liu 	/* Make sure IB tests flushed */
5092beff74bcSAlex Deucher 	flush_delayed_work(&adev->delayed_init_work);
509396a5d8d4SLeo Liu 
50944cf50baeSThomas Zimmermann 	if (notify_clients)
50954cf50baeSThomas Zimmermann 		drm_client_dev_resume(adev_to_drm(adev), false);
5096d38ceaf9SAlex Deucher 
50975e6932feSxinhui pan 	amdgpu_ras_resume(adev);
50985e6932feSxinhui pan 
5099d09ef243SAlex Deucher 	if (adev->mode_info.num_crtc) {
510023a1a9e5SLyude 		/*
510123a1a9e5SLyude 		 * Most of the connector probing functions try to acquire runtime pm
510223a1a9e5SLyude 		 * refs to ensure that the GPU is powered on when connector polling is
510323a1a9e5SLyude 		 * performed. Since we're calling this from a runtime PM callback,
510423a1a9e5SLyude 		 * trying to acquire rpm refs will cause us to deadlock.
510523a1a9e5SLyude 		 *
510623a1a9e5SLyude 		 * Since we're guaranteed to be holding the rpm lock, it's safe to
510723a1a9e5SLyude 		 * temporarily disable the rpm helpers so this doesn't deadlock us.
510823a1a9e5SLyude 		 */
510923a1a9e5SLyude #ifdef CONFIG_PM
511023a1a9e5SLyude 		dev->dev->power.disable_depth++;
511123a1a9e5SLyude #endif
5112d09ef243SAlex Deucher 		if (!adev->dc_enabled)
511354fb2a5cSAlex Deucher 			drm_helper_hpd_irq_event(dev);
51144562236bSHarry Wentland 		else
51154562236bSHarry Wentland 			drm_kms_helper_hotplug_event(dev);
511623a1a9e5SLyude #ifdef CONFIG_PM
511723a1a9e5SLyude 		dev->dev->power.disable_depth--;
511823a1a9e5SLyude #endif
5119d09ef243SAlex Deucher 	}
512044779b43SRex Zhu 	adev->in_suspend = false;
512144779b43SRex Zhu 
5122dc907c9dSJack Xiao 	if (adev->enable_mes)
5123dc907c9dSJack Xiao 		amdgpu_mes_self_test(adev);
5124dc907c9dSJack Xiao 
51253fa8f89dSSathishkumar S 	if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0))
51263fa8f89dSSathishkumar S 		DRM_WARN("smart shift update failed\n");
51273fa8f89dSSathishkumar S 
51284d3b9ae5SShirish S 	return 0;
5129d38ceaf9SAlex Deucher }
5130d38ceaf9SAlex Deucher 
5131e3ecdffaSAlex Deucher /**
5132e3ecdffaSAlex Deucher  * amdgpu_device_ip_check_soft_reset - did soft reset succeed
5133e3ecdffaSAlex Deucher  *
5134e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
5135e3ecdffaSAlex Deucher  *
5136e3ecdffaSAlex Deucher  * The list of all the hardware IPs that make up the asic is walked and
5137e3ecdffaSAlex Deucher  * the check_soft_reset callbacks are run.  check_soft_reset determines
5138e3ecdffaSAlex Deucher  * if the asic is still hung or not.
5139e3ecdffaSAlex Deucher  * Returns true if any of the IPs are still in a hung state, false if not.
5140e3ecdffaSAlex Deucher  */
amdgpu_device_ip_check_soft_reset(struct amdgpu_device * adev)514106ec9070SAlex Deucher static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev)
514263fbf42fSChunming Zhou {
514363fbf42fSChunming Zhou 	int i;
514463fbf42fSChunming Zhou 	bool asic_hang = false;
514563fbf42fSChunming Zhou 
5146f993d628SMonk Liu 	if (amdgpu_sriov_vf(adev))
5147f993d628SMonk Liu 		return true;
5148f993d628SMonk Liu 
51498bc04c29SAlex Deucher 	if (amdgpu_asic_need_full_reset(adev))
51508bc04c29SAlex Deucher 		return true;
51518bc04c29SAlex Deucher 
515263fbf42fSChunming Zhou 	for (i = 0; i < adev->num_ip_blocks; i++) {
5153a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
515463fbf42fSChunming Zhou 			continue;
5155a1255107SAlex Deucher 		if (adev->ip_blocks[i].version->funcs->check_soft_reset)
5156a1255107SAlex Deucher 			adev->ip_blocks[i].status.hang =
51576a9456e0SSunil Khatri 				adev->ip_blocks[i].version->funcs->check_soft_reset(
51586a9456e0SSunil Khatri 					&adev->ip_blocks[i]);
5159a1255107SAlex Deucher 		if (adev->ip_blocks[i].status.hang) {
5160aac89168SDennis Li 			dev_info(adev->dev, "IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name);
516163fbf42fSChunming Zhou 			asic_hang = true;
516263fbf42fSChunming Zhou 		}
516363fbf42fSChunming Zhou 	}
516463fbf42fSChunming Zhou 	return asic_hang;
516563fbf42fSChunming Zhou }
516663fbf42fSChunming Zhou 
5167e3ecdffaSAlex Deucher /**
5168e3ecdffaSAlex Deucher  * amdgpu_device_ip_pre_soft_reset - prepare for soft reset
5169e3ecdffaSAlex Deucher  *
5170e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
5171e3ecdffaSAlex Deucher  *
5172e3ecdffaSAlex Deucher  * The list of all the hardware IPs that make up the asic is walked and the
5173e3ecdffaSAlex Deucher  * pre_soft_reset callbacks are run if the block is hung.  pre_soft_reset
5174e3ecdffaSAlex Deucher  * handles any IP specific hardware or software state changes that are
5175e3ecdffaSAlex Deucher  * necessary for a soft reset to succeed.
5176e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
5177e3ecdffaSAlex Deucher  */
amdgpu_device_ip_pre_soft_reset(struct amdgpu_device * adev)517806ec9070SAlex Deucher static int amdgpu_device_ip_pre_soft_reset(struct amdgpu_device *adev)
5179d31a501eSChunming Zhou {
5180d31a501eSChunming Zhou 	int i, r = 0;
5181d31a501eSChunming Zhou 
5182d31a501eSChunming Zhou 	for (i = 0; i < adev->num_ip_blocks; i++) {
5183a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
5184d31a501eSChunming Zhou 			continue;
5185a1255107SAlex Deucher 		if (adev->ip_blocks[i].status.hang &&
5186a1255107SAlex Deucher 		    adev->ip_blocks[i].version->funcs->pre_soft_reset) {
51879d5ee7ceSSunil Khatri 			r = adev->ip_blocks[i].version->funcs->pre_soft_reset(&adev->ip_blocks[i]);
5188d31a501eSChunming Zhou 			if (r)
5189d31a501eSChunming Zhou 				return r;
5190d31a501eSChunming Zhou 		}
5191d31a501eSChunming Zhou 	}
5192d31a501eSChunming Zhou 
5193d31a501eSChunming Zhou 	return 0;
5194d31a501eSChunming Zhou }
5195d31a501eSChunming Zhou 
5196e3ecdffaSAlex Deucher /**
5197e3ecdffaSAlex Deucher  * amdgpu_device_ip_need_full_reset - check if a full asic reset is needed
5198e3ecdffaSAlex Deucher  *
5199e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
5200e3ecdffaSAlex Deucher  *
5201e3ecdffaSAlex Deucher  * Some hardware IPs cannot be soft reset.  If they are hung, a full gpu
5202e3ecdffaSAlex Deucher  * reset is necessary to recover.
5203e3ecdffaSAlex Deucher  * Returns true if a full asic reset is required, false if not.
5204e3ecdffaSAlex Deucher  */
amdgpu_device_ip_need_full_reset(struct amdgpu_device * adev)520506ec9070SAlex Deucher static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev)
520635d782feSChunming Zhou {
5207da146d3bSAlex Deucher 	int i;
5208da146d3bSAlex Deucher 
52098bc04c29SAlex Deucher 	if (amdgpu_asic_need_full_reset(adev))
52108bc04c29SAlex Deucher 		return true;
52118bc04c29SAlex Deucher 
5212da146d3bSAlex Deucher 	for (i = 0; i < adev->num_ip_blocks; i++) {
5213a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
5214da146d3bSAlex Deucher 			continue;
5215a1255107SAlex Deucher 		if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) ||
5216a1255107SAlex Deucher 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) ||
5217a1255107SAlex Deucher 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) ||
521898512bb8SKen Wang 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) ||
521998512bb8SKen Wang 		     adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
5220a1255107SAlex Deucher 			if (adev->ip_blocks[i].status.hang) {
5221aac89168SDennis Li 				dev_info(adev->dev, "Some block need full reset!\n");
522235d782feSChunming Zhou 				return true;
522335d782feSChunming Zhou 			}
5224da146d3bSAlex Deucher 		}
5225da146d3bSAlex Deucher 	}
522635d782feSChunming Zhou 	return false;
522735d782feSChunming Zhou }
522835d782feSChunming Zhou 
5229e3ecdffaSAlex Deucher /**
5230e3ecdffaSAlex Deucher  * amdgpu_device_ip_soft_reset - do a soft reset
5231e3ecdffaSAlex Deucher  *
5232e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
5233e3ecdffaSAlex Deucher  *
5234e3ecdffaSAlex Deucher  * The list of all the hardware IPs that make up the asic is walked and the
5235e3ecdffaSAlex Deucher  * soft_reset callbacks are run if the block is hung.  soft_reset handles any
5236e3ecdffaSAlex Deucher  * IP specific hardware or software state changes that are necessary to soft
5237e3ecdffaSAlex Deucher  * reset the IP.
5238e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
5239e3ecdffaSAlex Deucher  */
amdgpu_device_ip_soft_reset(struct amdgpu_device * adev)524006ec9070SAlex Deucher static int amdgpu_device_ip_soft_reset(struct amdgpu_device *adev)
524135d782feSChunming Zhou {
524235d782feSChunming Zhou 	int i, r = 0;
524335d782feSChunming Zhou 
524435d782feSChunming Zhou 	for (i = 0; i < adev->num_ip_blocks; i++) {
5245a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
524635d782feSChunming Zhou 			continue;
5247a1255107SAlex Deucher 		if (adev->ip_blocks[i].status.hang &&
5248a1255107SAlex Deucher 		    adev->ip_blocks[i].version->funcs->soft_reset) {
52490ef2a1e7SSunil Khatri 			r = adev->ip_blocks[i].version->funcs->soft_reset(&adev->ip_blocks[i]);
525035d782feSChunming Zhou 			if (r)
525135d782feSChunming Zhou 				return r;
525235d782feSChunming Zhou 		}
525335d782feSChunming Zhou 	}
525435d782feSChunming Zhou 
525535d782feSChunming Zhou 	return 0;
525635d782feSChunming Zhou }
525735d782feSChunming Zhou 
5258e3ecdffaSAlex Deucher /**
5259e3ecdffaSAlex Deucher  * amdgpu_device_ip_post_soft_reset - clean up from soft reset
5260e3ecdffaSAlex Deucher  *
5261e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
5262e3ecdffaSAlex Deucher  *
5263e3ecdffaSAlex Deucher  * The list of all the hardware IPs that make up the asic is walked and the
5264e3ecdffaSAlex Deucher  * post_soft_reset callbacks are run if the asic was hung.  post_soft_reset
5265e3ecdffaSAlex Deucher  * handles any IP specific hardware or software state changes that are
5266e3ecdffaSAlex Deucher  * necessary after the IP has been soft reset.
5267e3ecdffaSAlex Deucher  * Returns 0 on success, negative error code on failure.
5268e3ecdffaSAlex Deucher  */
amdgpu_device_ip_post_soft_reset(struct amdgpu_device * adev)526906ec9070SAlex Deucher static int amdgpu_device_ip_post_soft_reset(struct amdgpu_device *adev)
527035d782feSChunming Zhou {
527135d782feSChunming Zhou 	int i, r = 0;
527235d782feSChunming Zhou 
527335d782feSChunming Zhou 	for (i = 0; i < adev->num_ip_blocks; i++) {
5274a1255107SAlex Deucher 		if (!adev->ip_blocks[i].status.valid)
527535d782feSChunming Zhou 			continue;
5276a1255107SAlex Deucher 		if (adev->ip_blocks[i].status.hang &&
5277a1255107SAlex Deucher 		    adev->ip_blocks[i].version->funcs->post_soft_reset)
5278e15ec812SSunil Khatri 			r = adev->ip_blocks[i].version->funcs->post_soft_reset(&adev->ip_blocks[i]);
527935d782feSChunming Zhou 		if (r)
528035d782feSChunming Zhou 			return r;
528135d782feSChunming Zhou 	}
528235d782feSChunming Zhou 
528335d782feSChunming Zhou 	return 0;
528435d782feSChunming Zhou }
528535d782feSChunming Zhou 
5286e3ecdffaSAlex Deucher /**
528706ec9070SAlex Deucher  * amdgpu_device_reset_sriov - reset ASIC for SR-IOV vf
52885740682eSMonk Liu  *
5289982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
529025c01191SYunxiang Li  * @reset_context: amdgpu reset context pointer
52915740682eSMonk Liu  *
52925740682eSMonk Liu  * do VF FLR and reinitialize Asic
52933f48c681SColin Ian King  * return 0 means succeeded otherwise failed
529453cdccd5SChunming Zhou  */
amdgpu_device_reset_sriov(struct amdgpu_device * adev,struct amdgpu_reset_context * reset_context)5295e3ecdffaSAlex Deucher static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
529625c01191SYunxiang Li 				     struct amdgpu_reset_context *reset_context)
52975740682eSMonk Liu {
52985740682eSMonk Liu 	int r;
5299a5f67c93SZhigang Luo 	struct amdgpu_hive_info *hive = NULL;
53005740682eSMonk Liu 
530125c01191SYunxiang Li 	if (test_bit(AMDGPU_HOST_FLR, &reset_context->flags)) {
5302cbda2758SVignesh Chander 		if (!amdgpu_ras_get_fed_status(adev))
53035c0a1cddSYunxiang Li 			amdgpu_virt_ready_to_reset(adev);
53045c0a1cddSYunxiang Li 		amdgpu_virt_wait_reset(adev);
530525c01191SYunxiang Li 		clear_bit(AMDGPU_HOST_FLR, &reset_context->flags);
53065740682eSMonk Liu 		r = amdgpu_virt_request_full_gpu(adev, true);
530725c01191SYunxiang Li 	} else {
53085740682eSMonk Liu 		r = amdgpu_virt_reset_gpu(adev);
530925c01191SYunxiang Li 	}
53105740682eSMonk Liu 	if (r)
53115740682eSMonk Liu 		return r;
531225c01191SYunxiang Li 
5313e1ee2111SLijo Lazar 	amdgpu_ras_clear_err_state(adev);
5314f734b213SEmily Deng 	amdgpu_irq_gpu_reset_resume_helper(adev);
53155740682eSMonk Liu 
531683f24a8fSHorace Chen 	/* some sw clean up VF needs to do before recover */
531783f24a8fSHorace Chen 	amdgpu_virt_post_reset(adev);
531883f24a8fSHorace Chen 
53195740682eSMonk Liu 	/* Resume IP prior to SMC */
532006ec9070SAlex Deucher 	r = amdgpu_device_ip_reinit_early_sriov(adev);
53215740682eSMonk Liu 	if (r)
53226e4aa08fSYunxiang Li 		return r;
53235740682eSMonk Liu 
5324c9ffa427SYintian Tao 	amdgpu_virt_init_data_exchange(adev);
53255740682eSMonk Liu 
53267a3e0bb2SRex Zhu 	r = amdgpu_device_fw_loading(adev);
53277a3e0bb2SRex Zhu 	if (r)
53287a3e0bb2SRex Zhu 		return r;
53297a3e0bb2SRex Zhu 
53305740682eSMonk Liu 	/* now we are okay to resume SMC/CP/SDMA */
533106ec9070SAlex Deucher 	r = amdgpu_device_ip_reinit_late_sriov(adev);
53325740682eSMonk Liu 	if (r)
53336e4aa08fSYunxiang Li 		return r;
53345740682eSMonk Liu 
5335a5f67c93SZhigang Luo 	hive = amdgpu_get_xgmi_hive(adev);
5336a5f67c93SZhigang Luo 	/* Update PSP FW topology after reset */
5337a5f67c93SZhigang Luo 	if (hive && adev->gmc.xgmi.num_physical_nodes > 1)
5338a5f67c93SZhigang Luo 		r = amdgpu_xgmi_update_topology(hive, adev);
5339a5f67c93SZhigang Luo 	if (hive)
5340a5f67c93SZhigang Luo 		amdgpu_put_xgmi_hive(hive);
53416e4aa08fSYunxiang Li 	if (r)
53426e4aa08fSYunxiang Li 		return r;
5343a5f67c93SZhigang Luo 
53445740682eSMonk Liu 	r = amdgpu_ib_ring_tests(adev);
53456e4aa08fSYunxiang Li 	if (r)
53466e4aa08fSYunxiang Li 		return r;
53479c12f5cdSJack Xiao 
53487181faaaSChristian König 	if (adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST)
5349e3526257SMonk Liu 		amdgpu_inc_vram_lost(adev);
53506e4aa08fSYunxiang Li 
53516e4aa08fSYunxiang Li 	/* need to be called during full access so we can't do it later like
53526e4aa08fSYunxiang Li 	 * bare-metal does.
53536e4aa08fSYunxiang Li 	 */
53546e4aa08fSYunxiang Li 	amdgpu_amdkfd_post_reset(adev);
5355437f3e0bSHorace Chen 	amdgpu_virt_release_full_gpu(adev, true);
53565740682eSMonk Liu 
53574752cac3SYunxiang Li 	/* Aldebaran and gfx_11_0_3 support ras in SRIOV, so need resume ras during reset */
53584752cac3SYunxiang Li 	if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2) ||
53594752cac3SYunxiang Li 	    amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
53605f571c61SHawking Zhang 	    amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) ||
5361d7f5c13eSEllen Pan 	    amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0) ||
53624752cac3SYunxiang Li 	    amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 3))
53634752cac3SYunxiang Li 		amdgpu_ras_resume(adev);
536484a2947eSVictor Skvortsov 
536584a2947eSVictor Skvortsov 	amdgpu_virt_ras_telemetry_post_reset(adev);
536684a2947eSVictor Skvortsov 
53676e4aa08fSYunxiang Li 	return 0;
53685740682eSMonk Liu }
53695740682eSMonk Liu 
53705740682eSMonk Liu /**
53710859eb54SShikang Fan  * amdgpu_device_has_job_running - check if there is any unfinished job
53729a1cddd6Sjqdeng  *
5373982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
53749a1cddd6Sjqdeng  *
53750859eb54SShikang Fan  * check if there is any job running on the device when guest driver receives
53760859eb54SShikang Fan  * FLR notification from host driver. If there are still jobs running, then
53770859eb54SShikang Fan  * the guest driver will not respond the FLR reset. Instead, let the job hit
53780859eb54SShikang Fan  * the timeout and guest driver then issue the reset request.
53799a1cddd6Sjqdeng  */
amdgpu_device_has_job_running(struct amdgpu_device * adev)53809a1cddd6Sjqdeng bool amdgpu_device_has_job_running(struct amdgpu_device *adev)
53819a1cddd6Sjqdeng {
53829a1cddd6Sjqdeng 	int i;
53839a1cddd6Sjqdeng 
53849a1cddd6Sjqdeng 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
53859a1cddd6Sjqdeng 		struct amdgpu_ring *ring = adev->rings[i];
53869a1cddd6Sjqdeng 
53879749c868SMa Jun 		if (!amdgpu_ring_sched_ready(ring))
53889a1cddd6Sjqdeng 			continue;
53899a1cddd6Sjqdeng 
53900859eb54SShikang Fan 		if (amdgpu_fence_count_emitted(ring))
53919a1cddd6Sjqdeng 			return true;
53929a1cddd6Sjqdeng 	}
53939a1cddd6Sjqdeng 	return false;
53949a1cddd6Sjqdeng }
53959a1cddd6Sjqdeng 
53969a1cddd6Sjqdeng /**
539712938fadSChristian König  * amdgpu_device_should_recover_gpu - check if we should try GPU recovery
539812938fadSChristian König  *
5399982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
540012938fadSChristian König  *
540112938fadSChristian König  * Check amdgpu_gpu_recovery and SRIOV status to see if we should try to recover
540212938fadSChristian König  * a hung GPU.
540312938fadSChristian König  */
amdgpu_device_should_recover_gpu(struct amdgpu_device * adev)540412938fadSChristian König bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
540512938fadSChristian König {
5406d3ef9d57SChengming Gui 
5407d3ef9d57SChengming Gui 	if (amdgpu_gpu_recovery == 0)
5408d3ef9d57SChengming Gui 		goto disabled;
5409d3ef9d57SChengming Gui 
54101a11a65dSYiPeng Chai 	/* Skip soft reset check in fatal error mode */
54111a11a65dSYiPeng Chai 	if (!amdgpu_ras_is_poison_mode_supported(adev))
54121a11a65dSYiPeng Chai 		return true;
54131a11a65dSYiPeng Chai 
54143ba7b418SAndrey Grodzovsky 	if (amdgpu_sriov_vf(adev))
54153ba7b418SAndrey Grodzovsky 		return true;
54163ba7b418SAndrey Grodzovsky 
54173ba7b418SAndrey Grodzovsky 	if (amdgpu_gpu_recovery == -1) {
54183ba7b418SAndrey Grodzovsky 		switch (adev->asic_type) {
5419b3523c45SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_SI
5420b3523c45SAlex Deucher 		case CHIP_VERDE:
5421b3523c45SAlex Deucher 		case CHIP_TAHITI:
5422b3523c45SAlex Deucher 		case CHIP_PITCAIRN:
5423b3523c45SAlex Deucher 		case CHIP_OLAND:
5424b3523c45SAlex Deucher 		case CHIP_HAINAN:
5425b3523c45SAlex Deucher #endif
5426b3523c45SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_CIK
5427b3523c45SAlex Deucher 		case CHIP_KAVERI:
5428b3523c45SAlex Deucher 		case CHIP_KABINI:
5429b3523c45SAlex Deucher 		case CHIP_MULLINS:
5430b3523c45SAlex Deucher #endif
5431b3523c45SAlex Deucher 		case CHIP_CARRIZO:
5432b3523c45SAlex Deucher 		case CHIP_STONEY:
5433b3523c45SAlex Deucher 		case CHIP_CYAN_SKILLFISH:
54343ba7b418SAndrey Grodzovsky 			goto disabled;
5435b3523c45SAlex Deucher 		default:
5436b3523c45SAlex Deucher 			break;
54373ba7b418SAndrey Grodzovsky 		}
543812938fadSChristian König 	}
543912938fadSChristian König 
544012938fadSChristian König 	return true;
54413ba7b418SAndrey Grodzovsky 
54423ba7b418SAndrey Grodzovsky disabled:
5443aac89168SDennis Li 		dev_info(adev->dev, "GPU recovery disabled.\n");
54443ba7b418SAndrey Grodzovsky 		return false;
544512938fadSChristian König }
544612938fadSChristian König 
amdgpu_device_mode1_reset(struct amdgpu_device * adev)54475c03e584SFeifei Xu int amdgpu_device_mode1_reset(struct amdgpu_device *adev)
54485c03e584SFeifei Xu {
54495c03e584SFeifei Xu 	u32 i;
54505c03e584SFeifei Xu 	int ret = 0;
54515c03e584SFeifei Xu 
54526e8ca38eSLijo Lazar 	if (adev->bios)
54535c03e584SFeifei Xu 		amdgpu_atombios_scratch_regs_engine_hung(adev, true);
54545c03e584SFeifei Xu 
54555c03e584SFeifei Xu 	dev_info(adev->dev, "GPU mode1 reset\n");
54565c03e584SFeifei Xu 
5457e779af8eSLijo Lazar 	/* Cache the state before bus master disable. The saved config space
5458e779af8eSLijo Lazar 	 * values are used in other cases like restore after mode-2 reset.
5459e779af8eSLijo Lazar 	 */
5460e779af8eSLijo Lazar 	amdgpu_device_cache_pci_state(adev->pdev);
5461e779af8eSLijo Lazar 
54625c03e584SFeifei Xu 	/* disable BM */
54635c03e584SFeifei Xu 	pci_clear_master(adev->pdev);
54645c03e584SFeifei Xu 
54655c03e584SFeifei Xu 	if (amdgpu_dpm_is_mode1_reset_supported(adev)) {
54665c03e584SFeifei Xu 		dev_info(adev->dev, "GPU smu mode1 reset\n");
54675c03e584SFeifei Xu 		ret = amdgpu_dpm_mode1_reset(adev);
54685c03e584SFeifei Xu 	} else {
54695c03e584SFeifei Xu 		dev_info(adev->dev, "GPU psp mode1 reset\n");
54705c03e584SFeifei Xu 		ret = psp_gpu_reset(adev);
54715c03e584SFeifei Xu 	}
54725c03e584SFeifei Xu 
54735c03e584SFeifei Xu 	if (ret)
54747d442437SHawking Zhang 		goto mode1_reset_failed;
54755c03e584SFeifei Xu 
54765c03e584SFeifei Xu 	amdgpu_device_load_pci_state(adev->pdev);
54777656168aSLijo Lazar 	ret = amdgpu_psp_wait_for_bootloader(adev);
54787656168aSLijo Lazar 	if (ret)
54797d442437SHawking Zhang 		goto mode1_reset_failed;
54805c03e584SFeifei Xu 
54815c03e584SFeifei Xu 	/* wait for asic to come out of reset */
54825c03e584SFeifei Xu 	for (i = 0; i < adev->usec_timeout; i++) {
54835c03e584SFeifei Xu 		u32 memsize = adev->nbio.funcs->get_memsize(adev);
54845c03e584SFeifei Xu 
54855c03e584SFeifei Xu 		if (memsize != 0xffffffff)
54865c03e584SFeifei Xu 			break;
54875c03e584SFeifei Xu 		udelay(1);
54885c03e584SFeifei Xu 	}
54895c03e584SFeifei Xu 
54907d442437SHawking Zhang 	if (i >= adev->usec_timeout) {
54917d442437SHawking Zhang 		ret = -ETIMEDOUT;
54927d442437SHawking Zhang 		goto mode1_reset_failed;
54937d442437SHawking Zhang 	}
54947d442437SHawking Zhang 
54956e8ca38eSLijo Lazar 	if (adev->bios)
54965c03e584SFeifei Xu 		amdgpu_atombios_scratch_regs_engine_hung(adev, false);
54977656168aSLijo Lazar 
54987d442437SHawking Zhang 	return 0;
54997d442437SHawking Zhang 
55007d442437SHawking Zhang mode1_reset_failed:
55017d442437SHawking Zhang 	dev_err(adev->dev, "GPU mode1 reset failed\n");
55025c03e584SFeifei Xu 	return ret;
55035c03e584SFeifei Xu }
550426bc5340SAndrey Grodzovsky 
amdgpu_device_pre_asic_reset(struct amdgpu_device * adev,struct amdgpu_reset_context * reset_context)5505e3c1b071Sshaoyunl int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
550604442bf7SLijo Lazar 				 struct amdgpu_reset_context *reset_context)
55075740682eSMonk Liu {
55085c1e6fa4SHuang Rui 	int i, r = 0;
550904442bf7SLijo Lazar 	struct amdgpu_job *job = NULL;
551013d8850aSSunil Khatri 	struct amdgpu_device *tmp_adev = reset_context->reset_req_dev;
551104442bf7SLijo Lazar 	bool need_full_reset =
551204442bf7SLijo Lazar 		test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
551304442bf7SLijo Lazar 
551404442bf7SLijo Lazar 	if (reset_context->reset_req_dev == adev)
551504442bf7SLijo Lazar 		job = reset_context->job;
551671182665SMonk Liu 
5517f83cec3bSVictor Skvortsov 	if (amdgpu_sriov_vf(adev))
5518f83cec3bSVictor Skvortsov 		amdgpu_virt_pre_reset(adev);
5519b602ca5fSTiecheng Zhou 
55209e225fb9SAndrey Grodzovsky 	amdgpu_fence_driver_isr_toggle(adev, true);
55219e225fb9SAndrey Grodzovsky 
552271182665SMonk Liu 	/* block all schedulers and reset given job's ring */
55235740682eSMonk Liu 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
55245740682eSMonk Liu 		struct amdgpu_ring *ring = adev->rings[i];
55255740682eSMonk Liu 
55269749c868SMa Jun 		if (!amdgpu_ring_sched_ready(ring))
55275740682eSMonk Liu 			continue;
55285740682eSMonk Liu 
5529b8920e1eSSrinivasan Shanmugam 		/* Clear job fence from fence drv to avoid force_completion
5530b8920e1eSSrinivasan Shanmugam 		 * leave NULL and vm flush fence in fence drv
5531b8920e1eSSrinivasan Shanmugam 		 */
55325c1e6fa4SHuang Rui 		amdgpu_fence_driver_clear_job_fences(ring);
5533c530b02fSJack Zhang 
55345740682eSMonk Liu 		/* after all hw jobs are reset, hw fence is meaningless, so force_completion */
55355740682eSMonk Liu 		amdgpu_fence_driver_force_completion(ring);
55365740682eSMonk Liu 	}
55375740682eSMonk Liu 
55389e225fb9SAndrey Grodzovsky 	amdgpu_fence_driver_isr_toggle(adev, false);
55399e225fb9SAndrey Grodzovsky 
5540ff99849bSJingwen Chen 	if (job && job->vm)
5541222b5f04SAndrey Grodzovsky 		drm_sched_increase_karma(&job->base);
5542222b5f04SAndrey Grodzovsky 
554304442bf7SLijo Lazar 	r = amdgpu_reset_prepare_hwcontext(adev, reset_context);
5544404b277bSLijo Lazar 	/* If reset handler not implemented, continue; otherwise return */
5545b8920e1eSSrinivasan Shanmugam 	if (r == -EOPNOTSUPP)
5546404b277bSLijo Lazar 		r = 0;
5547404b277bSLijo Lazar 	else
554804442bf7SLijo Lazar 		return r;
554904442bf7SLijo Lazar 
55501d721ed6SAndrey Grodzovsky 	/* Don't suspend on bare metal if we are not going to HW reset the ASIC */
555126bc5340SAndrey Grodzovsky 	if (!amdgpu_sriov_vf(adev)) {
555226bc5340SAndrey Grodzovsky 
555326bc5340SAndrey Grodzovsky 		if (!need_full_reset)
555426bc5340SAndrey Grodzovsky 			need_full_reset = amdgpu_device_ip_need_full_reset(adev);
555526bc5340SAndrey Grodzovsky 
5556360cd081SLikun Gao 		if (!need_full_reset && amdgpu_gpu_recovery &&
5557360cd081SLikun Gao 		    amdgpu_device_ip_check_soft_reset(adev)) {
555826bc5340SAndrey Grodzovsky 			amdgpu_device_ip_pre_soft_reset(adev);
555926bc5340SAndrey Grodzovsky 			r = amdgpu_device_ip_soft_reset(adev);
556026bc5340SAndrey Grodzovsky 			amdgpu_device_ip_post_soft_reset(adev);
556126bc5340SAndrey Grodzovsky 			if (r || amdgpu_device_ip_check_soft_reset(adev)) {
5562aac89168SDennis Li 				dev_info(adev->dev, "soft reset failed, will fallback to full reset!\n");
556326bc5340SAndrey Grodzovsky 				need_full_reset = true;
556426bc5340SAndrey Grodzovsky 			}
556526bc5340SAndrey Grodzovsky 		}
556626bc5340SAndrey Grodzovsky 
556713d8850aSSunil Khatri 		if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) {
556813d8850aSSunil Khatri 			dev_info(tmp_adev->dev, "Dumping IP State\n");
556913d8850aSSunil Khatri 			/* Trigger ip dump before we reset the asic */
557013d8850aSSunil Khatri 			for (i = 0; i < tmp_adev->num_ip_blocks; i++)
557113d8850aSSunil Khatri 				if (tmp_adev->ip_blocks[i].version->funcs->dump_ip_state)
557213d8850aSSunil Khatri 					tmp_adev->ip_blocks[i].version->funcs
5573fa73462dSSunil Khatri 						->dump_ip_state((void *)&tmp_adev->ip_blocks[i]);
557413d8850aSSunil Khatri 			dev_info(tmp_adev->dev, "Dumping IP State Completed\n");
557513d8850aSSunil Khatri 		}
557613d8850aSSunil Khatri 
557726bc5340SAndrey Grodzovsky 		if (need_full_reset)
557826bc5340SAndrey Grodzovsky 			r = amdgpu_device_ip_suspend(adev);
557904442bf7SLijo Lazar 		if (need_full_reset)
558004442bf7SLijo Lazar 			set_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
558104442bf7SLijo Lazar 		else
558204442bf7SLijo Lazar 			clear_bit(AMDGPU_NEED_FULL_RESET,
558304442bf7SLijo Lazar 				  &reset_context->flags);
558426bc5340SAndrey Grodzovsky 	}
558526bc5340SAndrey Grodzovsky 
558626bc5340SAndrey Grodzovsky 	return r;
558726bc5340SAndrey Grodzovsky }
558826bc5340SAndrey Grodzovsky 
amdgpu_device_reinit_after_reset(struct amdgpu_reset_context * reset_context)55896e37ae8bSLijo Lazar int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
559026bc5340SAndrey Grodzovsky {
55916e37ae8bSLijo Lazar 	struct list_head *device_list_handle;
55926e37ae8bSLijo Lazar 	bool full_reset, vram_lost = false;
55936e37ae8bSLijo Lazar 	struct amdgpu_device *tmp_adev;
5594a86e0c0eSLijo Lazar 	int r, init_level;
559526bc5340SAndrey Grodzovsky 
55966e37ae8bSLijo Lazar 	device_list_handle = reset_context->reset_device_list;
5597ea137071SAhmad Rehman 
55986e37ae8bSLijo Lazar 	if (!device_list_handle)
55996e37ae8bSLijo Lazar 		return -EINVAL;
56006e37ae8bSLijo Lazar 
56016e37ae8bSLijo Lazar 	full_reset = test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
56026e37ae8bSLijo Lazar 
5603a86e0c0eSLijo Lazar 	/**
5604a86e0c0eSLijo Lazar 	 * If it's reset on init, it's default init level, otherwise keep level
5605a86e0c0eSLijo Lazar 	 * as recovery level.
5606a86e0c0eSLijo Lazar 	 */
5607a86e0c0eSLijo Lazar 	if (reset_context->method == AMD_RESET_METHOD_ON_INIT)
5608a86e0c0eSLijo Lazar 			init_level = AMDGPU_INIT_LEVEL_DEFAULT;
5609a86e0c0eSLijo Lazar 	else
5610a86e0c0eSLijo Lazar 			init_level = AMDGPU_INIT_LEVEL_RESET_RECOVERY;
5611a86e0c0eSLijo Lazar 
5612404b277bSLijo Lazar 	r = 0;
5613655ce9cbSshaoyunl 	list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
5614a86e0c0eSLijo Lazar 		amdgpu_set_init_level(tmp_adev, init_level);
56156e37ae8bSLijo Lazar 		if (full_reset) {
561626bc5340SAndrey Grodzovsky 			/* post card */
5617e1ee2111SLijo Lazar 			amdgpu_ras_clear_err_state(tmp_adev);
5618e3c1b071Sshaoyunl 			r = amdgpu_device_asic_init(tmp_adev);
5619e3c1b071Sshaoyunl 			if (r) {
5620aac89168SDennis Li 				dev_warn(tmp_adev->dev, "asic atom init failed!");
5621e3c1b071Sshaoyunl 			} else {
562226bc5340SAndrey Grodzovsky 				dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n");
56239cec53c1SJames Zhu 
562426bc5340SAndrey Grodzovsky 				r = amdgpu_device_ip_resume_phase1(tmp_adev);
562526bc5340SAndrey Grodzovsky 				if (r)
562626bc5340SAndrey Grodzovsky 					goto out;
562726bc5340SAndrey Grodzovsky 
562826bc5340SAndrey Grodzovsky 				vram_lost = amdgpu_device_check_vram_lost(tmp_adev);
5629a7691785SAndré Almeida 
5630ea137071SAhmad Rehman 				if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags))
56316122f5c7STrigger Huang 					amdgpu_coredump(tmp_adev, false, vram_lost, reset_context->job);
5632a7691785SAndré Almeida 
563326bc5340SAndrey Grodzovsky 				if (vram_lost) {
563477e7f829SAndrey Grodzovsky 					DRM_INFO("VRAM is lost due to GPU reset!\n");
5635e3526257SMonk Liu 					amdgpu_inc_vram_lost(tmp_adev);
563626bc5340SAndrey Grodzovsky 				}
563726bc5340SAndrey Grodzovsky 
563826bc5340SAndrey Grodzovsky 				r = amdgpu_device_fw_loading(tmp_adev);
563926bc5340SAndrey Grodzovsky 				if (r)
564026bc5340SAndrey Grodzovsky 					return r;
564126bc5340SAndrey Grodzovsky 
5642c45e38f2SLijo Lazar 				r = amdgpu_xcp_restore_partition_mode(
5643c45e38f2SLijo Lazar 					tmp_adev->xcp_mgr);
5644c45e38f2SLijo Lazar 				if (r)
5645c45e38f2SLijo Lazar 					goto out;
5646c45e38f2SLijo Lazar 
564726bc5340SAndrey Grodzovsky 				r = amdgpu_device_ip_resume_phase2(tmp_adev);
564826bc5340SAndrey Grodzovsky 				if (r)
564926bc5340SAndrey Grodzovsky 					goto out;
565026bc5340SAndrey Grodzovsky 
5651b7043800SAlex Deucher 				if (tmp_adev->mman.buffer_funcs_ring->sched.ready)
5652b7043800SAlex Deucher 					amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true);
5653b7043800SAlex Deucher 
565473dae652SAlex Deucher 				r = amdgpu_device_ip_resume_phase3(tmp_adev);
565573dae652SAlex Deucher 				if (r)
565673dae652SAlex Deucher 					goto out;
565773dae652SAlex Deucher 
565826bc5340SAndrey Grodzovsky 				if (vram_lost)
565926bc5340SAndrey Grodzovsky 					amdgpu_device_fill_reset_magic(tmp_adev);
566026bc5340SAndrey Grodzovsky 
5661fdafb359SEvan Quan 				/*
5662fdafb359SEvan Quan 				 * Add this ASIC as tracked as reset was already
5663fdafb359SEvan Quan 				 * complete successfully.
5664fdafb359SEvan Quan 				 */
5665fdafb359SEvan Quan 				amdgpu_register_gpu_instance(tmp_adev);
5666fdafb359SEvan Quan 
566704442bf7SLijo Lazar 				if (!reset_context->hive &&
566804442bf7SLijo Lazar 				    tmp_adev->gmc.xgmi.num_physical_nodes > 1)
5669e3c1b071Sshaoyunl 					amdgpu_xgmi_add_device(tmp_adev);
5670e3c1b071Sshaoyunl 
56717c04ca50Sxinhui pan 				r = amdgpu_device_ip_late_init(tmp_adev);
56727c04ca50Sxinhui pan 				if (r)
56737c04ca50Sxinhui pan 					goto out;
56747c04ca50Sxinhui pan 
56754cf50baeSThomas Zimmermann 				drm_client_dev_resume(adev_to_drm(tmp_adev), false);
5676565d1941SEvan Quan 
5677e8fbaf03SGuchun Chen 				/*
5678e8fbaf03SGuchun Chen 				 * The GPU enters bad state once faulty pages
5679e8fbaf03SGuchun Chen 				 * by ECC has reached the threshold, and ras
5680e8fbaf03SGuchun Chen 				 * recovery is scheduled next. So add one check
5681e8fbaf03SGuchun Chen 				 * here to break recovery if it indeed exceeds
5682e8fbaf03SGuchun Chen 				 * bad page threshold, and remind user to
5683e8fbaf03SGuchun Chen 				 * retire this GPU or setting one bigger
5684e8fbaf03SGuchun Chen 				 * bad_page_threshold value to fix this once
5685e8fbaf03SGuchun Chen 				 * probing driver again.
5686e8fbaf03SGuchun Chen 				 */
5687dd3e2962STao Zhou 				if (!amdgpu_ras_is_rma(tmp_adev)) {
5688e79a04d5Sxinhui pan 					/* must succeed. */
5689511fdbc3Sxinhui pan 					amdgpu_ras_resume(tmp_adev);
5690e8fbaf03SGuchun Chen 				} else {
5691e8fbaf03SGuchun Chen 					r = -EINVAL;
5692e8fbaf03SGuchun Chen 					goto out;
5693e8fbaf03SGuchun Chen 				}
5694e79a04d5Sxinhui pan 
569526bc5340SAndrey Grodzovsky 				/* Update PSP FW topology after reset */
569604442bf7SLijo Lazar 				if (reset_context->hive &&
569704442bf7SLijo Lazar 				    tmp_adev->gmc.xgmi.num_physical_nodes > 1)
569804442bf7SLijo Lazar 					r = amdgpu_xgmi_update_topology(
569904442bf7SLijo Lazar 						reset_context->hive, tmp_adev);
570026bc5340SAndrey Grodzovsky 			}
570126bc5340SAndrey Grodzovsky 		}
570226bc5340SAndrey Grodzovsky 
570326bc5340SAndrey Grodzovsky out:
570426bc5340SAndrey Grodzovsky 		if (!r) {
5705a86e0c0eSLijo Lazar 			/* IP init is complete now, set level as default */
5706a86e0c0eSLijo Lazar 			amdgpu_set_init_level(tmp_adev,
5707a86e0c0eSLijo Lazar 					      AMDGPU_INIT_LEVEL_DEFAULT);
570826bc5340SAndrey Grodzovsky 			amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
570926bc5340SAndrey Grodzovsky 			r = amdgpu_ib_ring_tests(tmp_adev);
571026bc5340SAndrey Grodzovsky 			if (r) {
571126bc5340SAndrey Grodzovsky 				dev_err(tmp_adev->dev, "ib ring test failed (%d).\n", r);
571226bc5340SAndrey Grodzovsky 				r = -EAGAIN;
571326bc5340SAndrey Grodzovsky 				goto end;
571426bc5340SAndrey Grodzovsky 			}
571526bc5340SAndrey Grodzovsky 		}
571626bc5340SAndrey Grodzovsky 
57177181faaaSChristian König 		if (r)
571826bc5340SAndrey Grodzovsky 			tmp_adev->asic_reset_res = r;
571926bc5340SAndrey Grodzovsky 	}
572026bc5340SAndrey Grodzovsky 
572126bc5340SAndrey Grodzovsky end:
57226e37ae8bSLijo Lazar 	return r;
57236e37ae8bSLijo Lazar }
57246e37ae8bSLijo Lazar 
amdgpu_do_asic_reset(struct list_head * device_list_handle,struct amdgpu_reset_context * reset_context)57256e37ae8bSLijo Lazar int amdgpu_do_asic_reset(struct list_head *device_list_handle,
57266e37ae8bSLijo Lazar 			 struct amdgpu_reset_context *reset_context)
57276e37ae8bSLijo Lazar {
57286e37ae8bSLijo Lazar 	struct amdgpu_device *tmp_adev = NULL;
57296e37ae8bSLijo Lazar 	bool need_full_reset, skip_hw_reset;
57306e37ae8bSLijo Lazar 	int r = 0;
57316e37ae8bSLijo Lazar 
57326e37ae8bSLijo Lazar 	/* Try reset handler method first */
57336e37ae8bSLijo Lazar 	tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
57346e37ae8bSLijo Lazar 				    reset_list);
57356e37ae8bSLijo Lazar 
57366e37ae8bSLijo Lazar 	reset_context->reset_device_list = device_list_handle;
57376e37ae8bSLijo Lazar 	r = amdgpu_reset_perform_reset(tmp_adev, reset_context);
57386e37ae8bSLijo Lazar 	/* If reset handler not implemented, continue; otherwise return */
57396e37ae8bSLijo Lazar 	if (r == -EOPNOTSUPP)
57406e37ae8bSLijo Lazar 		r = 0;
57416e37ae8bSLijo Lazar 	else
57426e37ae8bSLijo Lazar 		return r;
57436e37ae8bSLijo Lazar 
57446e37ae8bSLijo Lazar 	/* Reset handler not implemented, use the default method */
57456e37ae8bSLijo Lazar 	need_full_reset =
57466e37ae8bSLijo Lazar 		test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
57476e37ae8bSLijo Lazar 	skip_hw_reset = test_bit(AMDGPU_SKIP_HW_RESET, &reset_context->flags);
57486e37ae8bSLijo Lazar 
57496e37ae8bSLijo Lazar 	/*
57506e37ae8bSLijo Lazar 	 * ASIC reset has to be done on all XGMI hive nodes ASAP
57516e37ae8bSLijo Lazar 	 * to allow proper links negotiation in FW (within 1 sec)
57526e37ae8bSLijo Lazar 	 */
57536e37ae8bSLijo Lazar 	if (!skip_hw_reset && need_full_reset) {
57546e37ae8bSLijo Lazar 		list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
57556e37ae8bSLijo Lazar 			/* For XGMI run all resets in parallel to speed up the process */
57566e37ae8bSLijo Lazar 			if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
57576e37ae8bSLijo Lazar 				if (!queue_work(system_unbound_wq,
57586e37ae8bSLijo Lazar 						&tmp_adev->xgmi_reset_work))
57596e37ae8bSLijo Lazar 					r = -EALREADY;
57606e37ae8bSLijo Lazar 			} else
57616e37ae8bSLijo Lazar 				r = amdgpu_asic_reset(tmp_adev);
57626e37ae8bSLijo Lazar 
57636e37ae8bSLijo Lazar 			if (r) {
57646e37ae8bSLijo Lazar 				dev_err(tmp_adev->dev,
57656e37ae8bSLijo Lazar 					"ASIC reset failed with error, %d for drm dev, %s",
57666e37ae8bSLijo Lazar 					r, adev_to_drm(tmp_adev)->unique);
57676e37ae8bSLijo Lazar 				goto out;
57686e37ae8bSLijo Lazar 			}
57696e37ae8bSLijo Lazar 		}
57706e37ae8bSLijo Lazar 
57716e37ae8bSLijo Lazar 		/* For XGMI wait for all resets to complete before proceed */
57726e37ae8bSLijo Lazar 		if (!r) {
57736e37ae8bSLijo Lazar 			list_for_each_entry(tmp_adev, device_list_handle,
57746e37ae8bSLijo Lazar 					    reset_list) {
57756e37ae8bSLijo Lazar 				if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
57766e37ae8bSLijo Lazar 					flush_work(&tmp_adev->xgmi_reset_work);
57776e37ae8bSLijo Lazar 					r = tmp_adev->asic_reset_res;
57786e37ae8bSLijo Lazar 					if (r)
57796e37ae8bSLijo Lazar 						break;
57806e37ae8bSLijo Lazar 				}
57816e37ae8bSLijo Lazar 			}
57826e37ae8bSLijo Lazar 		}
57836e37ae8bSLijo Lazar 	}
57846e37ae8bSLijo Lazar 
57856e37ae8bSLijo Lazar 	if (!r && amdgpu_ras_intr_triggered()) {
57866e37ae8bSLijo Lazar 		list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
57876e37ae8bSLijo Lazar 			amdgpu_ras_reset_error_count(tmp_adev,
57886e37ae8bSLijo Lazar 						     AMDGPU_RAS_BLOCK__MMHUB);
57896e37ae8bSLijo Lazar 		}
57906e37ae8bSLijo Lazar 
57916e37ae8bSLijo Lazar 		amdgpu_ras_intr_cleared();
57926e37ae8bSLijo Lazar 	}
57936e37ae8bSLijo Lazar 
57946e37ae8bSLijo Lazar 	r = amdgpu_device_reinit_after_reset(reset_context);
57956e37ae8bSLijo Lazar 	if (r == -EAGAIN)
579604442bf7SLijo Lazar 		set_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
579704442bf7SLijo Lazar 	else
579804442bf7SLijo Lazar 		clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
57996e37ae8bSLijo Lazar 
58006e37ae8bSLijo Lazar out:
580126bc5340SAndrey Grodzovsky 	return r;
580226bc5340SAndrey Grodzovsky }
580326bc5340SAndrey Grodzovsky 
amdgpu_device_set_mp1_state(struct amdgpu_device * adev)5804e923be99SAndrey Grodzovsky static void amdgpu_device_set_mp1_state(struct amdgpu_device *adev)
580526bc5340SAndrey Grodzovsky {
58061d721ed6SAndrey Grodzovsky 
5807a3a09142SAlex Deucher 	switch (amdgpu_asic_reset_method(adev)) {
5808a3a09142SAlex Deucher 	case AMD_RESET_METHOD_MODE1:
5809a3a09142SAlex Deucher 		adev->mp1_state = PP_MP1_STATE_SHUTDOWN;
5810a3a09142SAlex Deucher 		break;
5811a3a09142SAlex Deucher 	case AMD_RESET_METHOD_MODE2:
5812a3a09142SAlex Deucher 		adev->mp1_state = PP_MP1_STATE_RESET;
5813a3a09142SAlex Deucher 		break;
5814a3a09142SAlex Deucher 	default:
5815a3a09142SAlex Deucher 		adev->mp1_state = PP_MP1_STATE_NONE;
5816a3a09142SAlex Deucher 		break;
5817a3a09142SAlex Deucher 	}
581826bc5340SAndrey Grodzovsky }
581926bc5340SAndrey Grodzovsky 
amdgpu_device_unset_mp1_state(struct amdgpu_device * adev)5820e923be99SAndrey Grodzovsky static void amdgpu_device_unset_mp1_state(struct amdgpu_device *adev)
582126bc5340SAndrey Grodzovsky {
582289041940SGavin Wan 	amdgpu_vf_error_trans_all(adev);
5823a3a09142SAlex Deucher 	adev->mp1_state = PP_MP1_STATE_NONE;
582491fb309dSHorace Chen }
582591fb309dSHorace Chen 
amdgpu_device_resume_display_audio(struct amdgpu_device * adev)58263f12acc8SEvan Quan static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev)
58273f12acc8SEvan Quan {
58283f12acc8SEvan Quan 	struct pci_dev *p = NULL;
58293f12acc8SEvan Quan 
58303f12acc8SEvan Quan 	p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus),
58313f12acc8SEvan Quan 			adev->pdev->bus->number, 1);
58323f12acc8SEvan Quan 	if (p) {
58333f12acc8SEvan Quan 		pm_runtime_enable(&(p->dev));
58343f12acc8SEvan Quan 		pm_runtime_resume(&(p->dev));
58353f12acc8SEvan Quan 	}
5836b85e285eSYang Yingliang 
5837b85e285eSYang Yingliang 	pci_dev_put(p);
58383f12acc8SEvan Quan }
58393f12acc8SEvan Quan 
amdgpu_device_suspend_display_audio(struct amdgpu_device * adev)58403f12acc8SEvan Quan static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev)
58413f12acc8SEvan Quan {
58423f12acc8SEvan Quan 	enum amd_reset_method reset_method;
58433f12acc8SEvan Quan 	struct pci_dev *p = NULL;
58443f12acc8SEvan Quan 	u64 expires;
58453f12acc8SEvan Quan 
58463f12acc8SEvan Quan 	/*
58473f12acc8SEvan Quan 	 * For now, only BACO and mode1 reset are confirmed
58483f12acc8SEvan Quan 	 * to suffer the audio issue without proper suspended.
58493f12acc8SEvan Quan 	 */
58503f12acc8SEvan Quan 	reset_method = amdgpu_asic_reset_method(adev);
58513f12acc8SEvan Quan 	if ((reset_method != AMD_RESET_METHOD_BACO) &&
58523f12acc8SEvan Quan 	     (reset_method != AMD_RESET_METHOD_MODE1))
58533f12acc8SEvan Quan 		return -EINVAL;
58543f12acc8SEvan Quan 
58553f12acc8SEvan Quan 	p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus),
58563f12acc8SEvan Quan 			adev->pdev->bus->number, 1);
58573f12acc8SEvan Quan 	if (!p)
58583f12acc8SEvan Quan 		return -ENODEV;
58593f12acc8SEvan Quan 
58603f12acc8SEvan Quan 	expires = pm_runtime_autosuspend_expiration(&(p->dev));
58613f12acc8SEvan Quan 	if (!expires)
58623f12acc8SEvan Quan 		/*
58633f12acc8SEvan Quan 		 * If we cannot get the audio device autosuspend delay,
58643f12acc8SEvan Quan 		 * a fixed 4S interval will be used. Considering 3S is
58653f12acc8SEvan Quan 		 * the audio controller default autosuspend delay setting.
58663f12acc8SEvan Quan 		 * 4S used here is guaranteed to cover that.
58673f12acc8SEvan Quan 		 */
586854b7feb9SNathan Chancellor 		expires = ktime_get_mono_fast_ns() + NSEC_PER_SEC * 4ULL;
58693f12acc8SEvan Quan 
58703f12acc8SEvan Quan 	while (!pm_runtime_status_suspended(&(p->dev))) {
58713f12acc8SEvan Quan 		if (!pm_runtime_suspend(&(p->dev)))
58723f12acc8SEvan Quan 			break;
58733f12acc8SEvan Quan 
58743f12acc8SEvan Quan 		if (expires < ktime_get_mono_fast_ns()) {
58753f12acc8SEvan Quan 			dev_warn(adev->dev, "failed to suspend display audio\n");
5876b85e285eSYang Yingliang 			pci_dev_put(p);
58773f12acc8SEvan Quan 			/* TODO: abort the succeeding gpu reset? */
58783f12acc8SEvan Quan 			return -ETIMEDOUT;
58793f12acc8SEvan Quan 		}
58803f12acc8SEvan Quan 	}
58813f12acc8SEvan Quan 
58823f12acc8SEvan Quan 	pm_runtime_disable(&(p->dev));
58833f12acc8SEvan Quan 
5884b85e285eSYang Yingliang 	pci_dev_put(p);
58853f12acc8SEvan Quan 	return 0;
58863f12acc8SEvan Quan }
58873f12acc8SEvan Quan 
amdgpu_device_stop_pending_resets(struct amdgpu_device * adev)5888d193b12bSKent Russell static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev)
5889247c7b0dSAndrey Grodzovsky {
5890247c7b0dSAndrey Grodzovsky 	struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
5891247c7b0dSAndrey Grodzovsky 
5892247c7b0dSAndrey Grodzovsky #if defined(CONFIG_DEBUG_FS)
5893247c7b0dSAndrey Grodzovsky 	if (!amdgpu_sriov_vf(adev))
5894247c7b0dSAndrey Grodzovsky 		cancel_work(&adev->reset_work);
5895247c7b0dSAndrey Grodzovsky #endif
5896247c7b0dSAndrey Grodzovsky 
5897247c7b0dSAndrey Grodzovsky 	if (adev->kfd.dev)
5898247c7b0dSAndrey Grodzovsky 		cancel_work(&adev->kfd.reset_work);
5899247c7b0dSAndrey Grodzovsky 
5900247c7b0dSAndrey Grodzovsky 	if (amdgpu_sriov_vf(adev))
5901247c7b0dSAndrey Grodzovsky 		cancel_work(&adev->virt.flr_work);
5902247c7b0dSAndrey Grodzovsky 
5903247c7b0dSAndrey Grodzovsky 	if (con && adev->ras_enabled)
5904247c7b0dSAndrey Grodzovsky 		cancel_work(&con->recovery_work);
5905247c7b0dSAndrey Grodzovsky 
5906247c7b0dSAndrey Grodzovsky }
5907247c7b0dSAndrey Grodzovsky 
amdgpu_device_health_check(struct list_head * device_list_handle)5908dfe9c3cdSLijo Lazar static int amdgpu_device_health_check(struct list_head *device_list_handle)
5909dfe9c3cdSLijo Lazar {
5910dfe9c3cdSLijo Lazar 	struct amdgpu_device *tmp_adev;
5911dfe9c3cdSLijo Lazar 	int ret = 0;
5912dfe9c3cdSLijo Lazar 	u32 status;
5913dfe9c3cdSLijo Lazar 
5914dfe9c3cdSLijo Lazar 	list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
5915dfe9c3cdSLijo Lazar 		pci_read_config_dword(tmp_adev->pdev, PCI_COMMAND, &status);
5916dfe9c3cdSLijo Lazar 		if (PCI_POSSIBLE_ERROR(status)) {
5917dfe9c3cdSLijo Lazar 			dev_err(tmp_adev->dev, "device lost from bus!");
5918dfe9c3cdSLijo Lazar 			ret = -ENODEV;
5919dfe9c3cdSLijo Lazar 		}
5920dfe9c3cdSLijo Lazar 	}
5921dfe9c3cdSLijo Lazar 
5922dfe9c3cdSLijo Lazar 	return ret;
5923dfe9c3cdSLijo Lazar }
5924dfe9c3cdSLijo Lazar 
592526bc5340SAndrey Grodzovsky /**
59266e9c65f7SAlex Deucher  * amdgpu_device_gpu_recover - reset the asic and recover scheduler
592726bc5340SAndrey Grodzovsky  *
5928982a820bSMauro Carvalho Chehab  * @adev: amdgpu_device pointer
592926bc5340SAndrey Grodzovsky  * @job: which job trigger hang
593080bd2de1SLee Jones  * @reset_context: amdgpu reset context pointer
593126bc5340SAndrey Grodzovsky  *
593226bc5340SAndrey Grodzovsky  * Attempt to reset the GPU if it has hung (all asics).
593326bc5340SAndrey Grodzovsky  * Attempt to do soft-reset or full-reset and reinitialize Asic
593426bc5340SAndrey Grodzovsky  * Returns 0 for success or an error on failure.
593526bc5340SAndrey Grodzovsky  */
593626bc5340SAndrey Grodzovsky 
amdgpu_device_gpu_recover(struct amdgpu_device * adev,struct amdgpu_job * job,struct amdgpu_reset_context * reset_context)5937cf727044SAndrey Grodzovsky int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
5938f1549c09SLikun Gao 			      struct amdgpu_job *job,
5939f1549c09SLikun Gao 			      struct amdgpu_reset_context *reset_context)
594026bc5340SAndrey Grodzovsky {
594126bc5340SAndrey Grodzovsky 	struct list_head device_list, *device_list_handle =  NULL;
59427dd8c205SEvan Quan 	bool job_signaled = false;
59431d721ed6SAndrey Grodzovsky 	struct amdgpu_hive_info *hive = NULL;
59441d721ed6SAndrey Grodzovsky 	struct amdgpu_device *tmp_adev = NULL;
59451d721ed6SAndrey Grodzovsky 	int i, r = 0;
5946bb5c7235SWenhui Sheng 	bool need_emergency_restart = false;
59473f12acc8SEvan Quan 	bool audio_suspended = false;
59486e4aa08fSYunxiang Li 	int retry_limit = AMDGPU_MAX_RETRY_LIMIT;
594926bc5340SAndrey Grodzovsky 
59506e3cd2a9SMauro Carvalho Chehab 	/*
5951e1ee2111SLijo Lazar 	 * If it reaches here because of hang/timeout and a RAS error is
5952e1ee2111SLijo Lazar 	 * detected at the same time, let RAS recovery take care of it.
5953e1ee2111SLijo Lazar 	 */
5954e1ee2111SLijo Lazar 	if (amdgpu_ras_is_err_state(adev, AMDGPU_RAS_BLOCK__ANY) &&
5955fccb446fSLijo Lazar 	    !amdgpu_sriov_vf(adev) &&
5956e1ee2111SLijo Lazar 	    reset_context->src != AMDGPU_RESET_SRC_RAS) {
5957e1ee2111SLijo Lazar 		dev_dbg(adev->dev,
5958e1ee2111SLijo Lazar 			"Gpu recovery from source: %d yielding to RAS error recovery handling",
5959e1ee2111SLijo Lazar 			reset_context->src);
5960e1ee2111SLijo Lazar 		return 0;
5961e1ee2111SLijo Lazar 	}
5962e1ee2111SLijo Lazar 	/*
5963bb5c7235SWenhui Sheng 	 * Special case: RAS triggered and full reset isn't supported
5964bb5c7235SWenhui Sheng 	 */
5965bb5c7235SWenhui Sheng 	need_emergency_restart = amdgpu_ras_need_emergency_restart(adev);
5966bb5c7235SWenhui Sheng 
5967d5ea093eSAndrey Grodzovsky 	/*
5968d5ea093eSAndrey Grodzovsky 	 * Flush RAM to disk so that after reboot
5969d5ea093eSAndrey Grodzovsky 	 * the user can read log and see why the system rebooted.
5970d5ea093eSAndrey Grodzovsky 	 */
597180285ae1SStanley.Yang 	if (need_emergency_restart && amdgpu_ras_get_context(adev) &&
597280285ae1SStanley.Yang 		amdgpu_ras_get_context(adev)->reboot) {
5973d5ea093eSAndrey Grodzovsky 		DRM_WARN("Emergency reboot.");
5974d5ea093eSAndrey Grodzovsky 
5975d5ea093eSAndrey Grodzovsky 		ksys_sync_helper();
5976d5ea093eSAndrey Grodzovsky 		emergency_restart();
5977d5ea093eSAndrey Grodzovsky 	}
5978d5ea093eSAndrey Grodzovsky 
5979b823821fSLe Ma 	dev_info(adev->dev, "GPU %s begin!\n",
5980bb5c7235SWenhui Sheng 		need_emergency_restart ? "jobs stop":"reset");
598126bc5340SAndrey Grodzovsky 
5982175ac6ecSZhigang Luo 	if (!amdgpu_sriov_vf(adev))
5983d95e8e97SDennis Li 		hive = amdgpu_get_xgmi_hive(adev);
5984681260dfSAndrey Grodzovsky 	if (hive)
598553b3f8f4SDennis Li 		mutex_lock(&hive->hive_lock);
598626bc5340SAndrey Grodzovsky 
5987f1549c09SLikun Gao 	reset_context->job = job;
5988f1549c09SLikun Gao 	reset_context->hive = hive;
598926bc5340SAndrey Grodzovsky 	/*
59909e94d22cSEvan Quan 	 * Build list of devices to reset.
59919e94d22cSEvan Quan 	 * In case we are in XGMI hive mode, resort the device list
59929e94d22cSEvan Quan 	 * to put adev in the 1st position.
599326bc5340SAndrey Grodzovsky 	 */
59949e94d22cSEvan Quan 	INIT_LIST_HEAD(&device_list);
5995b1f7810bSJesse Zhang 	if (!amdgpu_sriov_vf(adev) && (adev->gmc.xgmi.num_physical_nodes > 1) && hive) {
599683d29a5fSYiPeng Chai 		list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
5997655ce9cbSshaoyunl 			list_add_tail(&tmp_adev->reset_list, &device_list);
5998087a3e13SChristian König 			if (adev->shutdown)
599983d29a5fSYiPeng Chai 				tmp_adev->shutdown = true;
600083d29a5fSYiPeng Chai 		}
6001655ce9cbSshaoyunl 		if (!list_is_first(&adev->reset_list, &device_list))
6002655ce9cbSshaoyunl 			list_rotate_to_front(&adev->reset_list, &device_list);
6003655ce9cbSshaoyunl 		device_list_handle = &device_list;
600426bc5340SAndrey Grodzovsky 	} else {
6005655ce9cbSshaoyunl 		list_add_tail(&adev->reset_list, &device_list);
600626bc5340SAndrey Grodzovsky 		device_list_handle = &device_list;
600726bc5340SAndrey Grodzovsky 	}
600826bc5340SAndrey Grodzovsky 
6009dfe9c3cdSLijo Lazar 	if (!amdgpu_sriov_vf(adev)) {
6010dfe9c3cdSLijo Lazar 		r = amdgpu_device_health_check(device_list_handle);
6011dfe9c3cdSLijo Lazar 		if (r)
6012dfe9c3cdSLijo Lazar 			goto end_reset;
6013dfe9c3cdSLijo Lazar 	}
6014dfe9c3cdSLijo Lazar 
6015e923be99SAndrey Grodzovsky 	/* We need to lock reset domain only once both for XGMI and single device */
6016e923be99SAndrey Grodzovsky 	tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
6017e923be99SAndrey Grodzovsky 				    reset_list);
60183675c2f2SAndrey Grodzovsky 	amdgpu_device_lock_reset_domain(tmp_adev->reset_domain);
6019e923be99SAndrey Grodzovsky 
602012ffa55dSAndrey Grodzovsky 	/* block all schedulers and reset given job's ring */
6021655ce9cbSshaoyunl 	list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
6022f287a3c5SAndrey Grodzovsky 
6023e923be99SAndrey Grodzovsky 		amdgpu_device_set_mp1_state(tmp_adev);
6024f287a3c5SAndrey Grodzovsky 
60253f12acc8SEvan Quan 		/*
60263f12acc8SEvan Quan 		 * Try to put the audio codec into suspend state
60273f12acc8SEvan Quan 		 * before gpu reset started.
60283f12acc8SEvan Quan 		 *
60293f12acc8SEvan Quan 		 * Due to the power domain of the graphics device
60303f12acc8SEvan Quan 		 * is shared with AZ power domain. Without this,
60313f12acc8SEvan Quan 		 * we may change the audio hardware from behind
60323f12acc8SEvan Quan 		 * the audio driver's back. That will trigger
60333f12acc8SEvan Quan 		 * some audio codec errors.
60343f12acc8SEvan Quan 		 */
60353f12acc8SEvan Quan 		if (!amdgpu_device_suspend_display_audio(tmp_adev))
60363f12acc8SEvan Quan 			audio_suspended = true;
60373f12acc8SEvan Quan 
60389e94d22cSEvan Quan 		amdgpu_ras_set_error_query_ready(tmp_adev, false);
60399e94d22cSEvan Quan 
604052fb44cfSEvan Quan 		cancel_delayed_work_sync(&tmp_adev->delayed_init_work);
604152fb44cfSEvan Quan 
6042dbe2c4c8SEric Huang 		amdgpu_amdkfd_pre_reset(tmp_adev, reset_context);
60439e94d22cSEvan Quan 
6044fdafb359SEvan Quan 		/*
6045a567db80SRandy Dunlap 		 * Mark these ASICs to be reset as untracked first
6046fdafb359SEvan Quan 		 * And add them back after reset completed
6047fdafb359SEvan Quan 		 */
6048fdafb359SEvan Quan 		amdgpu_unregister_gpu_instance(tmp_adev);
6049fdafb359SEvan Quan 
60504cf50baeSThomas Zimmermann 		drm_client_dev_suspend(adev_to_drm(tmp_adev), false);
6051565d1941SEvan Quan 
6052f1c1314bSxinhui pan 		/* disable ras on ALL IPs */
6053bb5c7235SWenhui Sheng 		if (!need_emergency_restart &&
6054b823821fSLe Ma 		      amdgpu_device_ip_need_full_reset(tmp_adev))
6055f1c1314bSxinhui pan 			amdgpu_ras_suspend(tmp_adev);
6056f1c1314bSxinhui pan 
60571d721ed6SAndrey Grodzovsky 		for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
60581d721ed6SAndrey Grodzovsky 			struct amdgpu_ring *ring = tmp_adev->rings[i];
60591d721ed6SAndrey Grodzovsky 
60609749c868SMa Jun 			if (!amdgpu_ring_sched_ready(ring))
60611d721ed6SAndrey Grodzovsky 				continue;
60621d721ed6SAndrey Grodzovsky 
60630b2d2c2eSAndrey Grodzovsky 			drm_sched_stop(&ring->sched, job ? &job->base : NULL);
60647c6e68c7SAndrey Grodzovsky 
6065bb5c7235SWenhui Sheng 			if (need_emergency_restart)
60667c6e68c7SAndrey Grodzovsky 				amdgpu_job_stop_all_jobs_on_sched(&ring->sched);
60671d721ed6SAndrey Grodzovsky 		}
60688f8c80f4SJingwen Chen 		atomic_inc(&tmp_adev->gpu_reset_counter);
60691d721ed6SAndrey Grodzovsky 	}
60701d721ed6SAndrey Grodzovsky 
6071bb5c7235SWenhui Sheng 	if (need_emergency_restart)
60727c6e68c7SAndrey Grodzovsky 		goto skip_sched_resume;
60737c6e68c7SAndrey Grodzovsky 
60741d721ed6SAndrey Grodzovsky 	/*
60751d721ed6SAndrey Grodzovsky 	 * Must check guilty signal here since after this point all old
60761d721ed6SAndrey Grodzovsky 	 * HW fences are force signaled.
60771d721ed6SAndrey Grodzovsky 	 *
60781d721ed6SAndrey Grodzovsky 	 * job->base holds a reference to parent fence
60791d721ed6SAndrey Grodzovsky 	 */
6080f6a3f660SAndrey Grodzovsky 	if (job && dma_fence_is_signaled(&job->hw_fence)) {
60811d721ed6SAndrey Grodzovsky 		job_signaled = true;
60821d721ed6SAndrey Grodzovsky 		dev_info(adev->dev, "Guilty job already signaled, skipping HW reset");
60831d721ed6SAndrey Grodzovsky 		goto skip_hw_reset;
60841d721ed6SAndrey Grodzovsky 	}
60851d721ed6SAndrey Grodzovsky 
608626bc5340SAndrey Grodzovsky retry:	/* Rest of adevs pre asic reset from XGMI hive. */
6087655ce9cbSshaoyunl 	list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
6088f1549c09SLikun Gao 		r = amdgpu_device_pre_asic_reset(tmp_adev, reset_context);
608926bc5340SAndrey Grodzovsky 		/*TODO Should we stop ?*/
609026bc5340SAndrey Grodzovsky 		if (r) {
6091aac89168SDennis Li 			dev_err(tmp_adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ",
60924a580877SLuben Tuikov 				  r, adev_to_drm(tmp_adev)->unique);
609326bc5340SAndrey Grodzovsky 			tmp_adev->asic_reset_res = r;
609426bc5340SAndrey Grodzovsky 		}
609526bc5340SAndrey Grodzovsky 	}
609626bc5340SAndrey Grodzovsky 
609726bc5340SAndrey Grodzovsky 	/* Actual ASIC resets if needed.*/
60984f30d920Sshaoyunl 	/* Host driver will handle XGMI hive reset for SRIOV */
609926bc5340SAndrey Grodzovsky 	if (amdgpu_sriov_vf(adev)) {
6100cbda2758SVignesh Chander 		if (amdgpu_ras_get_fed_status(adev) || amdgpu_virt_rcvd_ras_interrupt(adev)) {
6101cbda2758SVignesh Chander 			dev_dbg(adev->dev, "Detected RAS error, wait for FLR completion\n");
6102cbda2758SVignesh Chander 			amdgpu_ras_set_fed(adev, true);
6103cbda2758SVignesh Chander 			set_bit(AMDGPU_HOST_FLR, &reset_context->flags);
6104cbda2758SVignesh Chander 		}
6105cbda2758SVignesh Chander 
610625c01191SYunxiang Li 		r = amdgpu_device_reset_sriov(adev, reset_context);
61076e4aa08fSYunxiang Li 		if (AMDGPU_RETRY_SRIOV_RESET(r) && (retry_limit--) > 0) {
61086e4aa08fSYunxiang Li 			amdgpu_virt_release_full_gpu(adev, true);
61096e4aa08fSYunxiang Li 			goto retry;
61106e4aa08fSYunxiang Li 		}
611126bc5340SAndrey Grodzovsky 		if (r)
611226bc5340SAndrey Grodzovsky 			adev->asic_reset_res = r;
611326bc5340SAndrey Grodzovsky 	} else {
6114f1549c09SLikun Gao 		r = amdgpu_do_asic_reset(device_list_handle, reset_context);
6115b98a1648SVictor Zhao 		if (r && r == -EAGAIN)
611626bc5340SAndrey Grodzovsky 			goto retry;
6117dac6b808SVictor Zhao 	}
611826bc5340SAndrey Grodzovsky 
6119f4322b9fSYunxiang Li 	list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
6120f4322b9fSYunxiang Li 		/*
6121f4322b9fSYunxiang Li 		 * Drop any pending non scheduler resets queued before reset is done.
6122f4322b9fSYunxiang Li 		 * Any reset scheduled after this point would be valid. Scheduler resets
6123f4322b9fSYunxiang Li 		 * were already dropped during drm_sched_stop and no new ones can come
6124f4322b9fSYunxiang Li 		 * in before drm_sched_start.
6125f4322b9fSYunxiang Li 		 */
6126f4322b9fSYunxiang Li 		amdgpu_device_stop_pending_resets(tmp_adev);
6127f4322b9fSYunxiang Li 	}
6128f4322b9fSYunxiang Li 
61291d721ed6SAndrey Grodzovsky skip_hw_reset:
61301d721ed6SAndrey Grodzovsky 
613126bc5340SAndrey Grodzovsky 	/* Post ASIC reset for all devs .*/
6132655ce9cbSshaoyunl 	list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
61337c6e68c7SAndrey Grodzovsky 
61341d721ed6SAndrey Grodzovsky 		for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
61351d721ed6SAndrey Grodzovsky 			struct amdgpu_ring *ring = tmp_adev->rings[i];
61361d721ed6SAndrey Grodzovsky 
61379749c868SMa Jun 			if (!amdgpu_ring_sched_ready(ring))
61381d721ed6SAndrey Grodzovsky 				continue;
61391d721ed6SAndrey Grodzovsky 
6140b2ef8087SChristian König 			drm_sched_start(&ring->sched, 0);
61411d721ed6SAndrey Grodzovsky 		}
61421d721ed6SAndrey Grodzovsky 
6143b8920e1eSSrinivasan Shanmugam 		if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled)
61444a580877SLuben Tuikov 			drm_helper_resume_force_mode(adev_to_drm(tmp_adev));
61451d721ed6SAndrey Grodzovsky 
61467258fa31SSurbhi Kakarya 		if (tmp_adev->asic_reset_res)
61477258fa31SSurbhi Kakarya 			r = tmp_adev->asic_reset_res;
61487258fa31SSurbhi Kakarya 
61491d721ed6SAndrey Grodzovsky 		tmp_adev->asic_reset_res = 0;
615026bc5340SAndrey Grodzovsky 
615126bc5340SAndrey Grodzovsky 		if (r) {
6152b3a3c9a6STao Zhou 			/* bad news, how to tell it to userspace ?
6153b3a3c9a6STao Zhou 			 * for ras error, we should report GPU bad status instead of
6154b3a3c9a6STao Zhou 			 * reset failure
6155b3a3c9a6STao Zhou 			 */
6156b3a3c9a6STao Zhou 			if (reset_context->src != AMDGPU_RESET_SRC_RAS ||
6157b3a3c9a6STao Zhou 			    !amdgpu_ras_eeprom_check_err_threshold(tmp_adev))
6158b3a3c9a6STao Zhou 				dev_info(tmp_adev->dev, "GPU reset(%d) failed\n",
6159b3a3c9a6STao Zhou 					atomic_read(&tmp_adev->gpu_reset_counter));
616026bc5340SAndrey Grodzovsky 			amdgpu_vf_error_put(tmp_adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r);
616126bc5340SAndrey Grodzovsky 		} else {
616212ffa55dSAndrey Grodzovsky 			dev_info(tmp_adev->dev, "GPU reset(%d) succeeded!\n", atomic_read(&tmp_adev->gpu_reset_counter));
61633fa8f89dSSathishkumar S 			if (amdgpu_acpi_smart_shift_update(adev_to_drm(tmp_adev), AMDGPU_SS_DEV_D0))
61643fa8f89dSSathishkumar S 				DRM_WARN("smart shift update failed\n");
616526bc5340SAndrey Grodzovsky 		}
61667c6e68c7SAndrey Grodzovsky 	}
616726bc5340SAndrey Grodzovsky 
61687c6e68c7SAndrey Grodzovsky skip_sched_resume:
6169655ce9cbSshaoyunl 	list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
6170428890a3Sshaoyunl 		/* unlock kfd: SRIOV would do it separately */
6171c004d44eSMukul Joshi 		if (!need_emergency_restart && !amdgpu_sriov_vf(tmp_adev))
61727c6e68c7SAndrey Grodzovsky 			amdgpu_amdkfd_post_reset(tmp_adev);
61738e2712e7Sshaoyunl 
61748e2712e7Sshaoyunl 		/* kfd_post_reset will do nothing if kfd device is not initialized,
61758e2712e7Sshaoyunl 		 * need to bring up kfd here if it's not be initialized before
61768e2712e7Sshaoyunl 		 */
61778e2712e7Sshaoyunl 		if (!adev->kfd.init_complete)
61788e2712e7Sshaoyunl 			amdgpu_amdkfd_device_init(adev);
61798e2712e7Sshaoyunl 
61803f12acc8SEvan Quan 		if (audio_suspended)
61813f12acc8SEvan Quan 			amdgpu_device_resume_display_audio(tmp_adev);
6182e923be99SAndrey Grodzovsky 
6183e923be99SAndrey Grodzovsky 		amdgpu_device_unset_mp1_state(tmp_adev);
6184d293470eSYiPeng Chai 
6185d293470eSYiPeng Chai 		amdgpu_ras_set_error_query_ready(tmp_adev, true);
618626bc5340SAndrey Grodzovsky 	}
618726bc5340SAndrey Grodzovsky 
6188e923be99SAndrey Grodzovsky 	tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
6189e923be99SAndrey Grodzovsky 					    reset_list);
6190e923be99SAndrey Grodzovsky 	amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain);
6191e923be99SAndrey Grodzovsky 
6192dfe9c3cdSLijo Lazar end_reset:
61939e94d22cSEvan Quan 	if (hive) {
61949e94d22cSEvan Quan 		mutex_unlock(&hive->hive_lock);
6195d95e8e97SDennis Li 		amdgpu_put_xgmi_hive(hive);
61969e94d22cSEvan Quan 	}
619726bc5340SAndrey Grodzovsky 
6198f287a3c5SAndrey Grodzovsky 	if (r)
619926bc5340SAndrey Grodzovsky 		dev_info(adev->dev, "GPU reset end with ret = %d\n", r);
6200ab9a0b1fSAndrey Grodzovsky 
6201ab9a0b1fSAndrey Grodzovsky 	atomic_set(&adev->reset_domain->reset_res, r);
62026fe52b63SAndré Almeida 
62036fe52b63SAndré Almeida 	if (!r)
62046fe52b63SAndré Almeida 		drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE);
62056fe52b63SAndré Almeida 
6206d38ceaf9SAlex Deucher 	return r;
6207d38ceaf9SAlex Deucher }
6208d38ceaf9SAlex Deucher 
6209e3ecdffaSAlex Deucher /**
6210466a7d11SMario Limonciello  * amdgpu_device_partner_bandwidth - find the bandwidth of appropriate partner
6211466a7d11SMario Limonciello  *
6212466a7d11SMario Limonciello  * @adev: amdgpu_device pointer
6213466a7d11SMario Limonciello  * @speed: pointer to the speed of the link
6214466a7d11SMario Limonciello  * @width: pointer to the width of the link
6215466a7d11SMario Limonciello  *
6216466a7d11SMario Limonciello  * Evaluate the hierarchy to find the speed and bandwidth capabilities of the
6217466a7d11SMario Limonciello  * first physical partner to an AMD dGPU.
6218466a7d11SMario Limonciello  * This will exclude any virtual switches and links.
6219466a7d11SMario Limonciello  */
amdgpu_device_partner_bandwidth(struct amdgpu_device * adev,enum pci_bus_speed * speed,enum pcie_link_width * width)6220466a7d11SMario Limonciello static void amdgpu_device_partner_bandwidth(struct amdgpu_device *adev,
6221466a7d11SMario Limonciello 					    enum pci_bus_speed *speed,
6222466a7d11SMario Limonciello 					    enum pcie_link_width *width)
6223466a7d11SMario Limonciello {
6224466a7d11SMario Limonciello 	struct pci_dev *parent = adev->pdev;
6225466a7d11SMario Limonciello 
6226466a7d11SMario Limonciello 	if (!speed || !width)
6227466a7d11SMario Limonciello 		return;
6228466a7d11SMario Limonciello 
6229466a7d11SMario Limonciello 	*speed = PCI_SPEED_UNKNOWN;
6230466a7d11SMario Limonciello 	*width = PCIE_LNK_WIDTH_UNKNOWN;
6231466a7d11SMario Limonciello 
623287dfeb47SAlex Deucher 	if (amdgpu_device_pcie_dynamic_switching_supported(adev)) {
6233466a7d11SMario Limonciello 		while ((parent = pci_upstream_bridge(parent))) {
6234466a7d11SMario Limonciello 			/* skip upstream/downstream switches internal to dGPU*/
6235466a7d11SMario Limonciello 			if (parent->vendor == PCI_VENDOR_ID_ATI)
6236466a7d11SMario Limonciello 				continue;
6237466a7d11SMario Limonciello 			*speed = pcie_get_speed_cap(parent);
6238466a7d11SMario Limonciello 			*width = pcie_get_width_cap(parent);
6239466a7d11SMario Limonciello 			break;
6240466a7d11SMario Limonciello 		}
624187dfeb47SAlex Deucher 	} else {
624287dfeb47SAlex Deucher 		/* use the current speeds rather than max if switching is not supported */
624387dfeb47SAlex Deucher 		pcie_bandwidth_available(adev->pdev, NULL, speed, width);
624487dfeb47SAlex Deucher 	}
6245466a7d11SMario Limonciello }
6246466a7d11SMario Limonciello 
6247466a7d11SMario Limonciello /**
6248757e8b95SAlex Deucher  * amdgpu_device_gpu_bandwidth - find the bandwidth of the GPU
6249757e8b95SAlex Deucher  *
6250757e8b95SAlex Deucher  * @adev: amdgpu_device pointer
6251757e8b95SAlex Deucher  * @speed: pointer to the speed of the link
6252757e8b95SAlex Deucher  * @width: pointer to the width of the link
6253757e8b95SAlex Deucher  *
6254757e8b95SAlex Deucher  * Evaluate the hierarchy to find the speed and bandwidth capabilities of the
6255757e8b95SAlex Deucher  * AMD dGPU which may be a virtual upstream bridge.
6256757e8b95SAlex Deucher  */
amdgpu_device_gpu_bandwidth(struct amdgpu_device * adev,enum pci_bus_speed * speed,enum pcie_link_width * width)6257757e8b95SAlex Deucher static void amdgpu_device_gpu_bandwidth(struct amdgpu_device *adev,
6258757e8b95SAlex Deucher 					enum pci_bus_speed *speed,
6259757e8b95SAlex Deucher 					enum pcie_link_width *width)
6260757e8b95SAlex Deucher {
6261757e8b95SAlex Deucher 	struct pci_dev *parent = adev->pdev;
6262757e8b95SAlex Deucher 
6263757e8b95SAlex Deucher 	if (!speed || !width)
6264757e8b95SAlex Deucher 		return;
6265757e8b95SAlex Deucher 
6266757e8b95SAlex Deucher 	parent = pci_upstream_bridge(parent);
6267757e8b95SAlex Deucher 	if (parent && parent->vendor == PCI_VENDOR_ID_ATI) {
6268757e8b95SAlex Deucher 		/* use the upstream/downstream switches internal to dGPU */
6269757e8b95SAlex Deucher 		*speed = pcie_get_speed_cap(parent);
6270757e8b95SAlex Deucher 		*width = pcie_get_width_cap(parent);
6271757e8b95SAlex Deucher 		while ((parent = pci_upstream_bridge(parent))) {
6272757e8b95SAlex Deucher 			if (parent->vendor == PCI_VENDOR_ID_ATI) {
6273757e8b95SAlex Deucher 				/* use the upstream/downstream switches internal to dGPU */
6274757e8b95SAlex Deucher 				*speed = pcie_get_speed_cap(parent);
6275757e8b95SAlex Deucher 				*width = pcie_get_width_cap(parent);
6276757e8b95SAlex Deucher 			}
6277757e8b95SAlex Deucher 		}
6278757e8b95SAlex Deucher 	} else {
6279757e8b95SAlex Deucher 		/* use the device itself */
6280dc915275SSrinivasan Shanmugam 		*speed = pcie_get_speed_cap(adev->pdev);
6281dc915275SSrinivasan Shanmugam 		*width = pcie_get_width_cap(adev->pdev);
6282757e8b95SAlex Deucher 	}
6283757e8b95SAlex Deucher }
6284757e8b95SAlex Deucher 
6285757e8b95SAlex Deucher /**
6286e3ecdffaSAlex Deucher  * amdgpu_device_get_pcie_info - fence pcie info about the PCIE slot
6287e3ecdffaSAlex Deucher  *
6288e3ecdffaSAlex Deucher  * @adev: amdgpu_device pointer
6289e3ecdffaSAlex Deucher  *
6290a567db80SRandy Dunlap  * Fetches and stores in the driver the PCIE capabilities (gen speed
6291e3ecdffaSAlex Deucher  * and lanes) of the slot the device is in. Handles APUs and
6292e3ecdffaSAlex Deucher  * virtualized environments where PCIE config space may not be available.
6293e3ecdffaSAlex Deucher  */
amdgpu_device_get_pcie_info(struct amdgpu_device * adev)62945494d864SAlex Deucher static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
6295d0dd7f0cSAlex Deucher {
6296c5313457SHarish Kasiviswanathan 	enum pci_bus_speed speed_cap, platform_speed_cap;
6297757e8b95SAlex Deucher 	enum pcie_link_width platform_link_width, link_width;
6298d0dd7f0cSAlex Deucher 
6299cd474ba0SAlex Deucher 	if (amdgpu_pcie_gen_cap)
6300cd474ba0SAlex Deucher 		adev->pm.pcie_gen_mask = amdgpu_pcie_gen_cap;
6301d0dd7f0cSAlex Deucher 
6302cd474ba0SAlex Deucher 	if (amdgpu_pcie_lane_cap)
6303cd474ba0SAlex Deucher 		adev->pm.pcie_mlw_mask = amdgpu_pcie_lane_cap;
6304d0dd7f0cSAlex Deucher 
6305cd474ba0SAlex Deucher 	/* covers APUs as well */
630604e85958STong Liu01 	if (pci_is_root_bus(adev->pdev->bus) && !amdgpu_passthrough(adev)) {
6307cd474ba0SAlex Deucher 		if (adev->pm.pcie_gen_mask == 0)
6308cd474ba0SAlex Deucher 			adev->pm.pcie_gen_mask = AMDGPU_DEFAULT_PCIE_GEN_MASK;
6309cd474ba0SAlex Deucher 		if (adev->pm.pcie_mlw_mask == 0)
6310cd474ba0SAlex Deucher 			adev->pm.pcie_mlw_mask = AMDGPU_DEFAULT_PCIE_MLW_MASK;
6311d0dd7f0cSAlex Deucher 		return;
6312cd474ba0SAlex Deucher 	}
6313d0dd7f0cSAlex Deucher 
6314c5313457SHarish Kasiviswanathan 	if (adev->pm.pcie_gen_mask && adev->pm.pcie_mlw_mask)
6315c5313457SHarish Kasiviswanathan 		return;
6316c5313457SHarish Kasiviswanathan 
6317466a7d11SMario Limonciello 	amdgpu_device_partner_bandwidth(adev, &platform_speed_cap,
6318466a7d11SMario Limonciello 					&platform_link_width);
6319757e8b95SAlex Deucher 	amdgpu_device_gpu_bandwidth(adev, &speed_cap, &link_width);
6320c5313457SHarish Kasiviswanathan 
6321cd474ba0SAlex Deucher 	if (adev->pm.pcie_gen_mask == 0) {
63225d9a6330SAlex Deucher 		/* asic caps */
63235d9a6330SAlex Deucher 		if (speed_cap == PCI_SPEED_UNKNOWN) {
63245d9a6330SAlex Deucher 			adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
6325d0dd7f0cSAlex Deucher 						  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
6326d0dd7f0cSAlex Deucher 						  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
6327cd474ba0SAlex Deucher 		} else {
63282b3a1f51SFeifei Xu 			if (speed_cap == PCIE_SPEED_32_0GT)
63292b3a1f51SFeifei Xu 				adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63302b3a1f51SFeifei Xu 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
63312b3a1f51SFeifei Xu 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3 |
63322b3a1f51SFeifei Xu 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4 |
63332b3a1f51SFeifei Xu 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN5);
63342b3a1f51SFeifei Xu 			else if (speed_cap == PCIE_SPEED_16_0GT)
63355d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63365d9a6330SAlex Deucher 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
63375d9a6330SAlex Deucher 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3 |
63385d9a6330SAlex Deucher 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4);
63395d9a6330SAlex Deucher 			else if (speed_cap == PCIE_SPEED_8_0GT)
63405d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63415d9a6330SAlex Deucher 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
63425d9a6330SAlex Deucher 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
63435d9a6330SAlex Deucher 			else if (speed_cap == PCIE_SPEED_5_0GT)
63445d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63455d9a6330SAlex Deucher 							  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2);
63465d9a6330SAlex Deucher 			else
63475d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1;
63485d9a6330SAlex Deucher 		}
63495d9a6330SAlex Deucher 		/* platform caps */
6350c5313457SHarish Kasiviswanathan 		if (platform_speed_cap == PCI_SPEED_UNKNOWN) {
63515d9a6330SAlex Deucher 			adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63525d9a6330SAlex Deucher 						   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2);
63535d9a6330SAlex Deucher 		} else {
63542b3a1f51SFeifei Xu 			if (platform_speed_cap == PCIE_SPEED_32_0GT)
63552b3a1f51SFeifei Xu 				adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63562b3a1f51SFeifei Xu 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
63572b3a1f51SFeifei Xu 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 |
63582b3a1f51SFeifei Xu 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4 |
63592b3a1f51SFeifei Xu 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5);
63602b3a1f51SFeifei Xu 			else if (platform_speed_cap == PCIE_SPEED_16_0GT)
63615d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63625d9a6330SAlex Deucher 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
63635d9a6330SAlex Deucher 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 |
63645d9a6330SAlex Deucher 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4);
6365c5313457SHarish Kasiviswanathan 			else if (platform_speed_cap == PCIE_SPEED_8_0GT)
63665d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63675d9a6330SAlex Deucher 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
63685d9a6330SAlex Deucher 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3);
6369c5313457SHarish Kasiviswanathan 			else if (platform_speed_cap == PCIE_SPEED_5_0GT)
63705d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
63715d9a6330SAlex Deucher 							   CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2);
63725d9a6330SAlex Deucher 			else
63735d9a6330SAlex Deucher 				adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1;
63745d9a6330SAlex Deucher 
6375d0dd7f0cSAlex Deucher 		}
6376cd474ba0SAlex Deucher 	}
6377cd474ba0SAlex Deucher 	if (adev->pm.pcie_mlw_mask == 0) {
6378757e8b95SAlex Deucher 		/* asic caps */
6379757e8b95SAlex Deucher 		if (link_width == PCIE_LNK_WIDTH_UNKNOWN) {
6380757e8b95SAlex Deucher 			adev->pm.pcie_mlw_mask |= AMDGPU_DEFAULT_ASIC_PCIE_MLW_MASK;
6381757e8b95SAlex Deucher 		} else {
6382757e8b95SAlex Deucher 			switch (link_width) {
6383757e8b95SAlex Deucher 			case PCIE_LNK_X32:
6384757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X32 |
6385757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X16 |
6386757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X12 |
6387757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X8 |
6388757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X4 |
6389757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X2 |
6390757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X1);
6391757e8b95SAlex Deucher 				break;
6392757e8b95SAlex Deucher 			case PCIE_LNK_X16:
6393757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X16 |
6394757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X12 |
6395757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X8 |
6396757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X4 |
6397757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X2 |
6398757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X1);
6399757e8b95SAlex Deucher 				break;
6400757e8b95SAlex Deucher 			case PCIE_LNK_X12:
6401757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X12 |
6402757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X8 |
6403757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X4 |
6404757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X2 |
6405757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X1);
6406757e8b95SAlex Deucher 				break;
6407757e8b95SAlex Deucher 			case PCIE_LNK_X8:
6408757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X8 |
6409757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X4 |
6410757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X2 |
6411757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X1);
6412757e8b95SAlex Deucher 				break;
6413757e8b95SAlex Deucher 			case PCIE_LNK_X4:
6414757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X4 |
6415757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X2 |
6416757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X1);
6417757e8b95SAlex Deucher 				break;
6418757e8b95SAlex Deucher 			case PCIE_LNK_X2:
6419757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X2 |
6420757e8b95SAlex Deucher 							   CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X1);
6421757e8b95SAlex Deucher 				break;
6422757e8b95SAlex Deucher 			case PCIE_LNK_X1:
6423757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= CAIL_ASIC_PCIE_LINK_WIDTH_SUPPORT_X1;
6424757e8b95SAlex Deucher 				break;
6425757e8b95SAlex Deucher 			default:
6426757e8b95SAlex Deucher 				break;
6427757e8b95SAlex Deucher 			}
6428757e8b95SAlex Deucher 		}
6429757e8b95SAlex Deucher 		/* platform caps */
6430c5313457SHarish Kasiviswanathan 		if (platform_link_width == PCIE_LNK_WIDTH_UNKNOWN) {
64315d9a6330SAlex Deucher 			adev->pm.pcie_mlw_mask |= AMDGPU_DEFAULT_PCIE_MLW_MASK;
64325d9a6330SAlex Deucher 		} else {
6433c5313457SHarish Kasiviswanathan 			switch (platform_link_width) {
64345d9a6330SAlex Deucher 			case PCIE_LNK_X32:
6435757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 |
6436d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
6437d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
6438d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
6439d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
6440d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
6441d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
6442d0dd7f0cSAlex Deucher 				break;
64435d9a6330SAlex Deucher 			case PCIE_LNK_X16:
6444757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
6445d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
6446d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
6447d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
6448d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
6449d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
6450d0dd7f0cSAlex Deucher 				break;
64515d9a6330SAlex Deucher 			case PCIE_LNK_X12:
6452757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
6453d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
6454d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
6455d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
6456d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
6457d0dd7f0cSAlex Deucher 				break;
64585d9a6330SAlex Deucher 			case PCIE_LNK_X8:
6459757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
6460d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
6461d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
6462d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
6463d0dd7f0cSAlex Deucher 				break;
64645d9a6330SAlex Deucher 			case PCIE_LNK_X4:
6465757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
6466d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
6467d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
6468d0dd7f0cSAlex Deucher 				break;
64695d9a6330SAlex Deucher 			case PCIE_LNK_X2:
6470757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
6471d0dd7f0cSAlex Deucher 							   CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
6472d0dd7f0cSAlex Deucher 				break;
64735d9a6330SAlex Deucher 			case PCIE_LNK_X1:
6474757e8b95SAlex Deucher 				adev->pm.pcie_mlw_mask |= CAIL_PCIE_LINK_WIDTH_SUPPORT_X1;
6475d0dd7f0cSAlex Deucher 				break;
6476d0dd7f0cSAlex Deucher 			default:
6477d0dd7f0cSAlex Deucher 				break;
6478d0dd7f0cSAlex Deucher 			}
6479cd474ba0SAlex Deucher 		}
6480d0dd7f0cSAlex Deucher 	}
6481d0dd7f0cSAlex Deucher }
6482d38ceaf9SAlex Deucher 
648308a2fd23SRamesh Errabolu /**
648408a2fd23SRamesh Errabolu  * amdgpu_device_is_peer_accessible - Check peer access through PCIe BAR
648508a2fd23SRamesh Errabolu  *
648608a2fd23SRamesh Errabolu  * @adev: amdgpu_device pointer
648708a2fd23SRamesh Errabolu  * @peer_adev: amdgpu_device pointer for peer device trying to access @adev
648808a2fd23SRamesh Errabolu  *
648908a2fd23SRamesh Errabolu  * Return true if @peer_adev can access (DMA) @adev through the PCIe
649008a2fd23SRamesh Errabolu  * BAR, i.e. @adev is "large BAR" and the BAR matches the DMA mask of
649108a2fd23SRamesh Errabolu  * @peer_adev.
649208a2fd23SRamesh Errabolu  */
amdgpu_device_is_peer_accessible(struct amdgpu_device * adev,struct amdgpu_device * peer_adev)649308a2fd23SRamesh Errabolu bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
649408a2fd23SRamesh Errabolu 				      struct amdgpu_device *peer_adev)
649508a2fd23SRamesh Errabolu {
649608a2fd23SRamesh Errabolu #ifdef CONFIG_HSA_AMD_P2P
6497bb66ecbfSLijo Lazar 	bool p2p_access =
6498bb66ecbfSLijo Lazar 		!adev->gmc.xgmi.connected_to_cpu &&
6499bb66ecbfSLijo Lazar 		!(pci_p2pdma_distance(adev->pdev, peer_adev->dev, false) < 0);
65008e29057eSRamesh Errabolu 	if (!p2p_access)
65018e29057eSRamesh Errabolu 		dev_info(adev->dev, "PCIe P2P access from peer device %s is not supported by the chipset\n",
65028e29057eSRamesh Errabolu 			pci_name(peer_adev->pdev));
650308a2fd23SRamesh Errabolu 
650475f0efbcSRahul Jain 	bool is_large_bar = adev->gmc.visible_vram_size &&
650575f0efbcSRahul Jain 		adev->gmc.real_vram_size == adev->gmc.visible_vram_size;
650675f0efbcSRahul Jain 	bool p2p_addressable = amdgpu_device_check_iommu_remap(peer_adev);
650775f0efbcSRahul Jain 
650875f0efbcSRahul Jain 	if (!p2p_addressable) {
650975f0efbcSRahul Jain 		uint64_t address_mask = peer_adev->dev->dma_mask ?
651075f0efbcSRahul Jain 			~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
651175f0efbcSRahul Jain 		resource_size_t aper_limit =
651275f0efbcSRahul Jain 			adev->gmc.aper_base + adev->gmc.aper_size - 1;
651375f0efbcSRahul Jain 
651475f0efbcSRahul Jain 		p2p_addressable = !(adev->gmc.aper_base & address_mask ||
651575f0efbcSRahul Jain 				     aper_limit & address_mask);
651675f0efbcSRahul Jain 	}
651728b0ef92SBob Zhou 	return pcie_p2p && is_large_bar && p2p_access && p2p_addressable;
651808a2fd23SRamesh Errabolu #else
651908a2fd23SRamesh Errabolu 	return false;
652008a2fd23SRamesh Errabolu #endif
652108a2fd23SRamesh Errabolu }
652208a2fd23SRamesh Errabolu 
amdgpu_device_baco_enter(struct drm_device * dev)6523361dbd01SAlex Deucher int amdgpu_device_baco_enter(struct drm_device *dev)
6524361dbd01SAlex Deucher {
65251348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
65267a22677bSLe Ma 	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
6527361dbd01SAlex Deucher 
65286ab68650SGuchun Chen 	if (!amdgpu_device_supports_baco(dev))
6529361dbd01SAlex Deucher 		return -ENOTSUPP;
6530361dbd01SAlex Deucher 
65318ab0d6f0SLuben Tuikov 	if (ras && adev->ras_enabled &&
6532acdae216SLuben Tuikov 	    adev->nbio.funcs->enable_doorbell_interrupt)
65337a22677bSLe Ma 		adev->nbio.funcs->enable_doorbell_interrupt(adev, false);
65347a22677bSLe Ma 
65359530273eSEvan Quan 	return amdgpu_dpm_baco_enter(adev);
6536361dbd01SAlex Deucher }
6537361dbd01SAlex Deucher 
amdgpu_device_baco_exit(struct drm_device * dev)6538361dbd01SAlex Deucher int amdgpu_device_baco_exit(struct drm_device *dev)
6539361dbd01SAlex Deucher {
65401348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
65417a22677bSLe Ma 	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
65429530273eSEvan Quan 	int ret = 0;
6543361dbd01SAlex Deucher 
65446ab68650SGuchun Chen 	if (!amdgpu_device_supports_baco(dev))
6545361dbd01SAlex Deucher 		return -ENOTSUPP;
6546361dbd01SAlex Deucher 
65479530273eSEvan Quan 	ret = amdgpu_dpm_baco_exit(adev);
6548361dbd01SAlex Deucher 	if (ret)
6549361dbd01SAlex Deucher 		return ret;
6550361dbd01SAlex Deucher 
65518ab0d6f0SLuben Tuikov 	if (ras && adev->ras_enabled &&
6552acdae216SLuben Tuikov 	    adev->nbio.funcs->enable_doorbell_interrupt)
65537a22677bSLe Ma 		adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
6554361dbd01SAlex Deucher 
65550cdb3f97SFriedrich Vock 	if (amdgpu_passthrough(adev) && adev->nbio.funcs &&
65561bece222SChengzhe Liu 	    adev->nbio.funcs->clear_doorbell_interrupt)
65571bece222SChengzhe Liu 		adev->nbio.funcs->clear_doorbell_interrupt(adev);
65581bece222SChengzhe Liu 
6559361dbd01SAlex Deucher 	return 0;
6560361dbd01SAlex Deucher }
6561c9a6b82fSAndrey Grodzovsky 
6562c9a6b82fSAndrey Grodzovsky /**
6563c9a6b82fSAndrey Grodzovsky  * amdgpu_pci_error_detected - Called when a PCI error is detected.
6564c9a6b82fSAndrey Grodzovsky  * @pdev: PCI device struct
6565c9a6b82fSAndrey Grodzovsky  * @state: PCI channel state
6566c9a6b82fSAndrey Grodzovsky  *
6567c9a6b82fSAndrey Grodzovsky  * Description: Called when a PCI error is detected.
6568c9a6b82fSAndrey Grodzovsky  *
6569c9a6b82fSAndrey Grodzovsky  * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT.
6570c9a6b82fSAndrey Grodzovsky  */
amdgpu_pci_error_detected(struct pci_dev * pdev,pci_channel_state_t state)6571c9a6b82fSAndrey Grodzovsky pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
6572c9a6b82fSAndrey Grodzovsky {
6573c9a6b82fSAndrey Grodzovsky 	struct drm_device *dev = pci_get_drvdata(pdev);
6574c9a6b82fSAndrey Grodzovsky 	struct amdgpu_device *adev = drm_to_adev(dev);
6575acd89fcaSAndrey Grodzovsky 	int i;
6576c9a6b82fSAndrey Grodzovsky 
6577c9a6b82fSAndrey Grodzovsky 	DRM_INFO("PCI error: detected callback, state(%d)!!\n", state);
6578c9a6b82fSAndrey Grodzovsky 
65796894305cSAndrey Grodzovsky 	if (adev->gmc.xgmi.num_physical_nodes > 1) {
65806894305cSAndrey Grodzovsky 		DRM_WARN("No support for XGMI hive yet...");
65816894305cSAndrey Grodzovsky 		return PCI_ERS_RESULT_DISCONNECT;
65826894305cSAndrey Grodzovsky 	}
65836894305cSAndrey Grodzovsky 
6584e17e27f9SGuchun Chen 	adev->pci_channel_state = state;
6585e17e27f9SGuchun Chen 
6586c9a6b82fSAndrey Grodzovsky 	switch (state) {
6587c9a6b82fSAndrey Grodzovsky 	case pci_channel_io_normal:
6588c9a6b82fSAndrey Grodzovsky 		return PCI_ERS_RESULT_CAN_RECOVER;
6589c9a6b82fSAndrey Grodzovsky 	/* Fatal error, prepare for slot reset */
6590acd89fcaSAndrey Grodzovsky 	case pci_channel_io_frozen:
6591acd89fcaSAndrey Grodzovsky 		/*
6592d0fb18b5SAndrey Grodzovsky 		 * Locking adev->reset_domain->sem will prevent any external access
6593acd89fcaSAndrey Grodzovsky 		 * to GPU during PCI error recovery
6594acd89fcaSAndrey Grodzovsky 		 */
65953675c2f2SAndrey Grodzovsky 		amdgpu_device_lock_reset_domain(adev->reset_domain);
6596e923be99SAndrey Grodzovsky 		amdgpu_device_set_mp1_state(adev);
6597acd89fcaSAndrey Grodzovsky 
6598acd89fcaSAndrey Grodzovsky 		/*
6599acd89fcaSAndrey Grodzovsky 		 * Block any work scheduling as we do for regular GPU reset
6600acd89fcaSAndrey Grodzovsky 		 * for the duration of the recovery
6601acd89fcaSAndrey Grodzovsky 		 */
6602acd89fcaSAndrey Grodzovsky 		for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
6603acd89fcaSAndrey Grodzovsky 			struct amdgpu_ring *ring = adev->rings[i];
6604acd89fcaSAndrey Grodzovsky 
66059749c868SMa Jun 			if (!amdgpu_ring_sched_ready(ring))
6606acd89fcaSAndrey Grodzovsky 				continue;
6607acd89fcaSAndrey Grodzovsky 
6608acd89fcaSAndrey Grodzovsky 			drm_sched_stop(&ring->sched, NULL);
6609acd89fcaSAndrey Grodzovsky 		}
66108f8c80f4SJingwen Chen 		atomic_inc(&adev->gpu_reset_counter);
6611c9a6b82fSAndrey Grodzovsky 		return PCI_ERS_RESULT_NEED_RESET;
6612c9a6b82fSAndrey Grodzovsky 	case pci_channel_io_perm_failure:
6613c9a6b82fSAndrey Grodzovsky 		/* Permanent error, prepare for device removal */
6614c9a6b82fSAndrey Grodzovsky 		return PCI_ERS_RESULT_DISCONNECT;
6615c9a6b82fSAndrey Grodzovsky 	}
6616c9a6b82fSAndrey Grodzovsky 
6617c9a6b82fSAndrey Grodzovsky 	return PCI_ERS_RESULT_NEED_RESET;
6618c9a6b82fSAndrey Grodzovsky }
6619c9a6b82fSAndrey Grodzovsky 
6620c9a6b82fSAndrey Grodzovsky /**
6621c9a6b82fSAndrey Grodzovsky  * amdgpu_pci_mmio_enabled - Enable MMIO and dump debug registers
6622c9a6b82fSAndrey Grodzovsky  * @pdev: pointer to PCI device
6623c9a6b82fSAndrey Grodzovsky  */
amdgpu_pci_mmio_enabled(struct pci_dev * pdev)6624c9a6b82fSAndrey Grodzovsky pci_ers_result_t amdgpu_pci_mmio_enabled(struct pci_dev *pdev)
6625c9a6b82fSAndrey Grodzovsky {
6626c9a6b82fSAndrey Grodzovsky 
6627c9a6b82fSAndrey Grodzovsky 	DRM_INFO("PCI error: mmio enabled callback!!\n");
6628c9a6b82fSAndrey Grodzovsky 
6629c9a6b82fSAndrey Grodzovsky 	/* TODO - dump whatever for debugging purposes */
6630c9a6b82fSAndrey Grodzovsky 
6631c9a6b82fSAndrey Grodzovsky 	/* This called only if amdgpu_pci_error_detected returns
6632c9a6b82fSAndrey Grodzovsky 	 * PCI_ERS_RESULT_CAN_RECOVER. Read/write to the device still
6633c9a6b82fSAndrey Grodzovsky 	 * works, no need to reset slot.
6634c9a6b82fSAndrey Grodzovsky 	 */
6635c9a6b82fSAndrey Grodzovsky 
6636c9a6b82fSAndrey Grodzovsky 	return PCI_ERS_RESULT_RECOVERED;
6637c9a6b82fSAndrey Grodzovsky }
6638c9a6b82fSAndrey Grodzovsky 
6639c9a6b82fSAndrey Grodzovsky /**
6640c9a6b82fSAndrey Grodzovsky  * amdgpu_pci_slot_reset - Called when PCI slot has been reset.
6641c9a6b82fSAndrey Grodzovsky  * @pdev: PCI device struct
6642c9a6b82fSAndrey Grodzovsky  *
6643c9a6b82fSAndrey Grodzovsky  * Description: This routine is called by the pci error recovery
6644c9a6b82fSAndrey Grodzovsky  * code after the PCI slot has been reset, just before we
6645c9a6b82fSAndrey Grodzovsky  * should resume normal operations.
6646c9a6b82fSAndrey Grodzovsky  */
amdgpu_pci_slot_reset(struct pci_dev * pdev)6647c9a6b82fSAndrey Grodzovsky pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
6648c9a6b82fSAndrey Grodzovsky {
6649c9a6b82fSAndrey Grodzovsky 	struct drm_device *dev = pci_get_drvdata(pdev);
6650c9a6b82fSAndrey Grodzovsky 	struct amdgpu_device *adev = drm_to_adev(dev);
6651362c7b91SAndrey Grodzovsky 	int r, i;
665204442bf7SLijo Lazar 	struct amdgpu_reset_context reset_context;
6653362c7b91SAndrey Grodzovsky 	u32 memsize;
66547ac71382SAndrey Grodzovsky 	struct list_head device_list;
6655601429ccSStanley.Yang 
6656601429ccSStanley.Yang 	/* PCI error slot reset should be skipped During RAS recovery */
66575f571c61SHawking Zhang 	if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
66585f571c61SHawking Zhang 	    amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
66597e437167STao Zhou 	    amdgpu_ras_in_recovery(adev))
6660601429ccSStanley.Yang 		return PCI_ERS_RESULT_RECOVERED;
6661c9a6b82fSAndrey Grodzovsky 
6662c9a6b82fSAndrey Grodzovsky 	DRM_INFO("PCI error: slot reset callback!!\n");
6663c9a6b82fSAndrey Grodzovsky 
666404442bf7SLijo Lazar 	memset(&reset_context, 0, sizeof(reset_context));
666504442bf7SLijo Lazar 
66667ac71382SAndrey Grodzovsky 	INIT_LIST_HEAD(&device_list);
6667655ce9cbSshaoyunl 	list_add_tail(&adev->reset_list, &device_list);
66687ac71382SAndrey Grodzovsky 
6669362c7b91SAndrey Grodzovsky 	/* wait for asic to come out of reset */
6670362c7b91SAndrey Grodzovsky 	msleep(500);
6671362c7b91SAndrey Grodzovsky 
66727ac71382SAndrey Grodzovsky 	/* Restore PCI confspace */
6673c1dd4aa6SAndrey Grodzovsky 	amdgpu_device_load_pci_state(pdev);
6674c9a6b82fSAndrey Grodzovsky 
6675362c7b91SAndrey Grodzovsky 	/* confirm  ASIC came out of reset */
6676362c7b91SAndrey Grodzovsky 	for (i = 0; i < adev->usec_timeout; i++) {
6677362c7b91SAndrey Grodzovsky 		memsize = amdgpu_asic_get_config_memsize(adev);
6678362c7b91SAndrey Grodzovsky 
6679362c7b91SAndrey Grodzovsky 		if (memsize != 0xffffffff)
6680362c7b91SAndrey Grodzovsky 			break;
6681362c7b91SAndrey Grodzovsky 		udelay(1);
6682362c7b91SAndrey Grodzovsky 	}
6683362c7b91SAndrey Grodzovsky 	if (memsize == 0xffffffff) {
6684362c7b91SAndrey Grodzovsky 		r = -ETIME;
6685362c7b91SAndrey Grodzovsky 		goto out;
6686362c7b91SAndrey Grodzovsky 	}
6687362c7b91SAndrey Grodzovsky 
668804442bf7SLijo Lazar 	reset_context.method = AMD_RESET_METHOD_NONE;
668904442bf7SLijo Lazar 	reset_context.reset_req_dev = adev;
669004442bf7SLijo Lazar 	set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
669104442bf7SLijo Lazar 	set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
669204442bf7SLijo Lazar 
66937afefb81SAndrey Grodzovsky 	adev->no_hw_access = true;
669404442bf7SLijo Lazar 	r = amdgpu_device_pre_asic_reset(adev, &reset_context);
66957afefb81SAndrey Grodzovsky 	adev->no_hw_access = false;
6696c9a6b82fSAndrey Grodzovsky 	if (r)
6697c9a6b82fSAndrey Grodzovsky 		goto out;
6698c9a6b82fSAndrey Grodzovsky 
669904442bf7SLijo Lazar 	r = amdgpu_do_asic_reset(&device_list, &reset_context);
6700c9a6b82fSAndrey Grodzovsky 
6701c9a6b82fSAndrey Grodzovsky out:
6702c9a6b82fSAndrey Grodzovsky 	if (!r) {
6703c1dd4aa6SAndrey Grodzovsky 		if (amdgpu_device_cache_pci_state(adev->pdev))
6704c1dd4aa6SAndrey Grodzovsky 			pci_restore_state(adev->pdev);
6705c1dd4aa6SAndrey Grodzovsky 
6706c9a6b82fSAndrey Grodzovsky 		DRM_INFO("PCIe error recovery succeeded\n");
6707c9a6b82fSAndrey Grodzovsky 	} else {
6708c9a6b82fSAndrey Grodzovsky 		DRM_ERROR("PCIe error recovery failed, err:%d", r);
6709e923be99SAndrey Grodzovsky 		amdgpu_device_unset_mp1_state(adev);
6710e923be99SAndrey Grodzovsky 		amdgpu_device_unlock_reset_domain(adev->reset_domain);
6711c9a6b82fSAndrey Grodzovsky 	}
6712c9a6b82fSAndrey Grodzovsky 
6713c9a6b82fSAndrey Grodzovsky 	return r ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
6714c9a6b82fSAndrey Grodzovsky }
6715c9a6b82fSAndrey Grodzovsky 
6716c9a6b82fSAndrey Grodzovsky /**
6717c9a6b82fSAndrey Grodzovsky  * amdgpu_pci_resume() - resume normal ops after PCI reset
6718c9a6b82fSAndrey Grodzovsky  * @pdev: pointer to PCI device
6719c9a6b82fSAndrey Grodzovsky  *
6720c9a6b82fSAndrey Grodzovsky  * Called when the error recovery driver tells us that its
6721505199a3SAlex Deucher  * OK to resume normal operation.
6722c9a6b82fSAndrey Grodzovsky  */
amdgpu_pci_resume(struct pci_dev * pdev)6723c9a6b82fSAndrey Grodzovsky void amdgpu_pci_resume(struct pci_dev *pdev)
6724c9a6b82fSAndrey Grodzovsky {
6725c9a6b82fSAndrey Grodzovsky 	struct drm_device *dev = pci_get_drvdata(pdev);
6726c9a6b82fSAndrey Grodzovsky 	struct amdgpu_device *adev = drm_to_adev(dev);
6727acd89fcaSAndrey Grodzovsky 	int i;
6728c9a6b82fSAndrey Grodzovsky 
6729c9a6b82fSAndrey Grodzovsky 
6730c9a6b82fSAndrey Grodzovsky 	DRM_INFO("PCI error: resume callback!!\n");
6731acd89fcaSAndrey Grodzovsky 
6732e17e27f9SGuchun Chen 	/* Only continue execution for the case of pci_channel_io_frozen */
6733e17e27f9SGuchun Chen 	if (adev->pci_channel_state != pci_channel_io_frozen)
6734e17e27f9SGuchun Chen 		return;
6735e17e27f9SGuchun Chen 
6736acd89fcaSAndrey Grodzovsky 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
6737acd89fcaSAndrey Grodzovsky 		struct amdgpu_ring *ring = adev->rings[i];
6738acd89fcaSAndrey Grodzovsky 
67399749c868SMa Jun 		if (!amdgpu_ring_sched_ready(ring))
6740acd89fcaSAndrey Grodzovsky 			continue;
6741acd89fcaSAndrey Grodzovsky 
6742b2ef8087SChristian König 		drm_sched_start(&ring->sched, 0);
6743acd89fcaSAndrey Grodzovsky 	}
6744acd89fcaSAndrey Grodzovsky 
6745e923be99SAndrey Grodzovsky 	amdgpu_device_unset_mp1_state(adev);
6746e923be99SAndrey Grodzovsky 	amdgpu_device_unlock_reset_domain(adev->reset_domain);
6747c9a6b82fSAndrey Grodzovsky }
6748c1dd4aa6SAndrey Grodzovsky 
amdgpu_device_cache_pci_state(struct pci_dev * pdev)6749c1dd4aa6SAndrey Grodzovsky bool amdgpu_device_cache_pci_state(struct pci_dev *pdev)
6750c1dd4aa6SAndrey Grodzovsky {
6751c1dd4aa6SAndrey Grodzovsky 	struct drm_device *dev = pci_get_drvdata(pdev);
6752c1dd4aa6SAndrey Grodzovsky 	struct amdgpu_device *adev = drm_to_adev(dev);
6753c1dd4aa6SAndrey Grodzovsky 	int r;
6754c1dd4aa6SAndrey Grodzovsky 
6755afe260dfSVictor Zhao 	if (amdgpu_sriov_vf(adev))
6756afe260dfSVictor Zhao 		return false;
6757afe260dfSVictor Zhao 
6758c1dd4aa6SAndrey Grodzovsky 	r = pci_save_state(pdev);
6759c1dd4aa6SAndrey Grodzovsky 	if (!r) {
6760c1dd4aa6SAndrey Grodzovsky 		kfree(adev->pci_state);
6761c1dd4aa6SAndrey Grodzovsky 
6762c1dd4aa6SAndrey Grodzovsky 		adev->pci_state = pci_store_saved_state(pdev);
6763c1dd4aa6SAndrey Grodzovsky 
6764c1dd4aa6SAndrey Grodzovsky 		if (!adev->pci_state) {
6765c1dd4aa6SAndrey Grodzovsky 			DRM_ERROR("Failed to store PCI saved state");
6766c1dd4aa6SAndrey Grodzovsky 			return false;
6767c1dd4aa6SAndrey Grodzovsky 		}
6768c1dd4aa6SAndrey Grodzovsky 	} else {
6769c1dd4aa6SAndrey Grodzovsky 		DRM_WARN("Failed to save PCI state, err:%d\n", r);
6770c1dd4aa6SAndrey Grodzovsky 		return false;
6771c1dd4aa6SAndrey Grodzovsky 	}
6772c1dd4aa6SAndrey Grodzovsky 
6773c1dd4aa6SAndrey Grodzovsky 	return true;
6774c1dd4aa6SAndrey Grodzovsky }
6775c1dd4aa6SAndrey Grodzovsky 
amdgpu_device_load_pci_state(struct pci_dev * pdev)6776c1dd4aa6SAndrey Grodzovsky bool amdgpu_device_load_pci_state(struct pci_dev *pdev)
6777c1dd4aa6SAndrey Grodzovsky {
6778c1dd4aa6SAndrey Grodzovsky 	struct drm_device *dev = pci_get_drvdata(pdev);
6779c1dd4aa6SAndrey Grodzovsky 	struct amdgpu_device *adev = drm_to_adev(dev);
6780c1dd4aa6SAndrey Grodzovsky 	int r;
6781c1dd4aa6SAndrey Grodzovsky 
6782c1dd4aa6SAndrey Grodzovsky 	if (!adev->pci_state)
6783c1dd4aa6SAndrey Grodzovsky 		return false;
6784c1dd4aa6SAndrey Grodzovsky 
6785c1dd4aa6SAndrey Grodzovsky 	r = pci_load_saved_state(pdev, adev->pci_state);
6786c1dd4aa6SAndrey Grodzovsky 
6787c1dd4aa6SAndrey Grodzovsky 	if (!r) {
6788c1dd4aa6SAndrey Grodzovsky 		pci_restore_state(pdev);
6789c1dd4aa6SAndrey Grodzovsky 	} else {
6790c1dd4aa6SAndrey Grodzovsky 		DRM_WARN("Failed to load PCI state, err:%d\n", r);
6791c1dd4aa6SAndrey Grodzovsky 		return false;
6792c1dd4aa6SAndrey Grodzovsky 	}
6793c1dd4aa6SAndrey Grodzovsky 
6794c1dd4aa6SAndrey Grodzovsky 	return true;
6795c1dd4aa6SAndrey Grodzovsky }
6796c1dd4aa6SAndrey Grodzovsky 
amdgpu_device_flush_hdp(struct amdgpu_device * adev,struct amdgpu_ring * ring)6797810085ddSEric Huang void amdgpu_device_flush_hdp(struct amdgpu_device *adev,
6798810085ddSEric Huang 		struct amdgpu_ring *ring)
6799810085ddSEric Huang {
6800810085ddSEric Huang #ifdef CONFIG_X86_64
6801b818a5d3SAlex Deucher 	if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev))
6802810085ddSEric Huang 		return;
6803810085ddSEric Huang #endif
6804810085ddSEric Huang 	if (adev->gmc.xgmi.connected_to_cpu)
6805810085ddSEric Huang 		return;
6806c1dd4aa6SAndrey Grodzovsky 
6807810085ddSEric Huang 	if (ring && ring->funcs->emit_hdp_flush)
6808810085ddSEric Huang 		amdgpu_ring_emit_hdp_flush(ring);
6809810085ddSEric Huang 	else
6810810085ddSEric Huang 		amdgpu_asic_flush_hdp(adev, ring);
6811810085ddSEric Huang }
6812810085ddSEric Huang 
amdgpu_device_invalidate_hdp(struct amdgpu_device * adev,struct amdgpu_ring * ring)6813810085ddSEric Huang void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
6814810085ddSEric Huang 		struct amdgpu_ring *ring)
6815810085ddSEric Huang {
6816810085ddSEric Huang #ifdef CONFIG_X86_64
6817b818a5d3SAlex Deucher 	if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev))
6818810085ddSEric Huang 		return;
6819810085ddSEric Huang #endif
6820810085ddSEric Huang 	if (adev->gmc.xgmi.connected_to_cpu)
6821810085ddSEric Huang 		return;
6822810085ddSEric Huang 
6823810085ddSEric Huang 	amdgpu_asic_invalidate_hdp(adev, ring);
6824810085ddSEric Huang }
682534f3a4a9SLang Yu 
amdgpu_in_reset(struct amdgpu_device * adev)682689a7a870SAndrey Grodzovsky int amdgpu_in_reset(struct amdgpu_device *adev)
682789a7a870SAndrey Grodzovsky {
682889a7a870SAndrey Grodzovsky 	return atomic_read(&adev->reset_domain->in_gpu_reset);
682989a7a870SAndrey Grodzovsky }
683089a7a870SAndrey Grodzovsky 
683134f3a4a9SLang Yu /**
683234f3a4a9SLang Yu  * amdgpu_device_halt() - bring hardware to some kind of halt state
683334f3a4a9SLang Yu  *
683434f3a4a9SLang Yu  * @adev: amdgpu_device pointer
683534f3a4a9SLang Yu  *
683634f3a4a9SLang Yu  * Bring hardware to some kind of halt state so that no one can touch it
683734f3a4a9SLang Yu  * any more. It will help to maintain error context when error occurred.
683834f3a4a9SLang Yu  * Compare to a simple hang, the system will keep stable at least for SSH
683934f3a4a9SLang Yu  * access. Then it should be trivial to inspect the hardware state and
684034f3a4a9SLang Yu  * see what's going on. Implemented as following:
684134f3a4a9SLang Yu  *
684234f3a4a9SLang Yu  * 1. drm_dev_unplug() makes device inaccessible to user space(IOCTLs, etc),
684334f3a4a9SLang Yu  *    clears all CPU mappings to device, disallows remappings through page faults
684434f3a4a9SLang Yu  * 2. amdgpu_irq_disable_all() disables all interrupts
684534f3a4a9SLang Yu  * 3. amdgpu_fence_driver_hw_fini() signals all HW fences
684634f3a4a9SLang Yu  * 4. set adev->no_hw_access to avoid potential crashes after setp 5
684734f3a4a9SLang Yu  * 5. amdgpu_device_unmap_mmio() clears all MMIO mappings
684834f3a4a9SLang Yu  * 6. pci_disable_device() and pci_wait_for_pending_transaction()
684934f3a4a9SLang Yu  *    flush any in flight DMA operations
685034f3a4a9SLang Yu  */
amdgpu_device_halt(struct amdgpu_device * adev)685134f3a4a9SLang Yu void amdgpu_device_halt(struct amdgpu_device *adev)
685234f3a4a9SLang Yu {
685334f3a4a9SLang Yu 	struct pci_dev *pdev = adev->pdev;
6854e0f943b4SGuchun Chen 	struct drm_device *ddev = adev_to_drm(adev);
685534f3a4a9SLang Yu 
68562c1c7ba4SJames Zhu 	amdgpu_xcp_dev_unplug(adev);
685734f3a4a9SLang Yu 	drm_dev_unplug(ddev);
685834f3a4a9SLang Yu 
685934f3a4a9SLang Yu 	amdgpu_irq_disable_all(adev);
686034f3a4a9SLang Yu 
686134f3a4a9SLang Yu 	amdgpu_fence_driver_hw_fini(adev);
686234f3a4a9SLang Yu 
686334f3a4a9SLang Yu 	adev->no_hw_access = true;
686434f3a4a9SLang Yu 
686534f3a4a9SLang Yu 	amdgpu_device_unmap_mmio(adev);
686634f3a4a9SLang Yu 
686734f3a4a9SLang Yu 	pci_disable_device(pdev);
686834f3a4a9SLang Yu 	pci_wait_for_pending_transaction(pdev);
686934f3a4a9SLang Yu }
687086700a40SXiaojian Du 
amdgpu_device_pcie_port_rreg(struct amdgpu_device * adev,u32 reg)687186700a40SXiaojian Du u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev,
687286700a40SXiaojian Du 				u32 reg)
687386700a40SXiaojian Du {
687486700a40SXiaojian Du 	unsigned long flags, address, data;
687586700a40SXiaojian Du 	u32 r;
687686700a40SXiaojian Du 
687786700a40SXiaojian Du 	address = adev->nbio.funcs->get_pcie_port_index_offset(adev);
687886700a40SXiaojian Du 	data = adev->nbio.funcs->get_pcie_port_data_offset(adev);
687986700a40SXiaojian Du 
688086700a40SXiaojian Du 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
688186700a40SXiaojian Du 	WREG32(address, reg * 4);
688286700a40SXiaojian Du 	(void)RREG32(address);
688386700a40SXiaojian Du 	r = RREG32(data);
688486700a40SXiaojian Du 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
688586700a40SXiaojian Du 	return r;
688686700a40SXiaojian Du }
688786700a40SXiaojian Du 
amdgpu_device_pcie_port_wreg(struct amdgpu_device * adev,u32 reg,u32 v)688886700a40SXiaojian Du void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev,
688986700a40SXiaojian Du 				u32 reg, u32 v)
689086700a40SXiaojian Du {
689186700a40SXiaojian Du 	unsigned long flags, address, data;
689286700a40SXiaojian Du 
689386700a40SXiaojian Du 	address = adev->nbio.funcs->get_pcie_port_index_offset(adev);
689486700a40SXiaojian Du 	data = adev->nbio.funcs->get_pcie_port_data_offset(adev);
689586700a40SXiaojian Du 
689686700a40SXiaojian Du 	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
689786700a40SXiaojian Du 	WREG32(address, reg * 4);
689886700a40SXiaojian Du 	(void)RREG32(address);
689986700a40SXiaojian Du 	WREG32(data, v);
690086700a40SXiaojian Du 	(void)RREG32(data);
690186700a40SXiaojian Du 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
690286700a40SXiaojian Du }
690368ce8b24SChristian König 
690468ce8b24SChristian König /**
6905a6328c9cSChristian König  * amdgpu_device_get_gang - return a reference to the current gang
6906a6328c9cSChristian König  * @adev: amdgpu_device pointer
6907a6328c9cSChristian König  *
6908a6328c9cSChristian König  * Returns: A new reference to the current gang leader.
6909a6328c9cSChristian König  */
amdgpu_device_get_gang(struct amdgpu_device * adev)6910a6328c9cSChristian König struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev)
6911a6328c9cSChristian König {
6912a6328c9cSChristian König 	struct dma_fence *fence;
6913a6328c9cSChristian König 
6914a6328c9cSChristian König 	rcu_read_lock();
6915a6328c9cSChristian König 	fence = dma_fence_get_rcu_safe(&adev->gang_submit);
6916a6328c9cSChristian König 	rcu_read_unlock();
6917a6328c9cSChristian König 	return fence;
6918a6328c9cSChristian König }
6919a6328c9cSChristian König 
6920a6328c9cSChristian König /**
692168ce8b24SChristian König  * amdgpu_device_switch_gang - switch to a new gang
692268ce8b24SChristian König  * @adev: amdgpu_device pointer
692368ce8b24SChristian König  * @gang: the gang to switch to
692468ce8b24SChristian König  *
692568ce8b24SChristian König  * Try to switch to a new gang.
692668ce8b24SChristian König  * Returns: NULL if we switched to the new gang or a reference to the current
692768ce8b24SChristian König  * gang leader.
692868ce8b24SChristian König  */
amdgpu_device_switch_gang(struct amdgpu_device * adev,struct dma_fence * gang)692968ce8b24SChristian König struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev,
693068ce8b24SChristian König 					    struct dma_fence *gang)
693168ce8b24SChristian König {
693268ce8b24SChristian König 	struct dma_fence *old = NULL;
693368ce8b24SChristian König 
69340d9a9509SChristian König 	dma_fence_get(gang);
693568ce8b24SChristian König 	do {
693668ce8b24SChristian König 		dma_fence_put(old);
6937a6328c9cSChristian König 		old = amdgpu_device_get_gang(adev);
693868ce8b24SChristian König 		if (old == gang)
693968ce8b24SChristian König 			break;
694068ce8b24SChristian König 
69410d9a9509SChristian König 		if (!dma_fence_is_signaled(old)) {
69420d9a9509SChristian König 			dma_fence_put(gang);
694368ce8b24SChristian König 			return old;
69440d9a9509SChristian König 		}
694568ce8b24SChristian König 
694668ce8b24SChristian König 	} while (cmpxchg((struct dma_fence __force **)&adev->gang_submit,
694768ce8b24SChristian König 			 old, gang) != old);
694868ce8b24SChristian König 
69490d9a9509SChristian König 	/*
69500d9a9509SChristian König 	 * Drop it once for the exchanged reference in adev and once for the
69510d9a9509SChristian König 	 * thread local reference acquired in amdgpu_device_get_gang().
69520d9a9509SChristian König 	 */
69530d9a9509SChristian König 	dma_fence_put(old);
695468ce8b24SChristian König 	dma_fence_put(old);
695568ce8b24SChristian König 	return NULL;
695668ce8b24SChristian König }
6957220c8cc8SAlex Deucher 
6958bd22e44aSChristian König /**
6959bd22e44aSChristian König  * amdgpu_device_enforce_isolation - enforce HW isolation
6960bd22e44aSChristian König  * @adev: the amdgpu device pointer
6961bd22e44aSChristian König  * @ring: the HW ring the job is supposed to run on
6962bd22e44aSChristian König  * @job: the job which is about to be pushed to the HW ring
6963bd22e44aSChristian König  *
6964bd22e44aSChristian König  * Makes sure that only one client at a time can use the GFX block.
6965bd22e44aSChristian König  * Returns: The dependency to wait on before the job can be pushed to the HW.
6966bd22e44aSChristian König  * The function is called multiple times until NULL is returned.
6967bd22e44aSChristian König  */
amdgpu_device_enforce_isolation(struct amdgpu_device * adev,struct amdgpu_ring * ring,struct amdgpu_job * job)6968bd22e44aSChristian König struct dma_fence *amdgpu_device_enforce_isolation(struct amdgpu_device *adev,
6969bd22e44aSChristian König 						  struct amdgpu_ring *ring,
6970bd22e44aSChristian König 						  struct amdgpu_job *job)
6971bd22e44aSChristian König {
6972bd22e44aSChristian König 	struct amdgpu_isolation *isolation = &adev->isolation[ring->xcp_id];
6973bd22e44aSChristian König 	struct drm_sched_fence *f = job->base.s_fence;
6974bd22e44aSChristian König 	struct dma_fence *dep;
6975bd22e44aSChristian König 	void *owner;
6976bd22e44aSChristian König 	int r;
6977bd22e44aSChristian König 
6978bd22e44aSChristian König 	/*
6979bd22e44aSChristian König 	 * For now enforce isolation only for the GFX block since we only need
6980bd22e44aSChristian König 	 * the cleaner shader on those rings.
6981bd22e44aSChristian König 	 */
6982bd22e44aSChristian König 	if (ring->funcs->type != AMDGPU_RING_TYPE_GFX &&
6983bd22e44aSChristian König 	    ring->funcs->type != AMDGPU_RING_TYPE_COMPUTE)
6984bd22e44aSChristian König 		return NULL;
6985bd22e44aSChristian König 
6986bd22e44aSChristian König 	/*
6987bd22e44aSChristian König 	 * All submissions where enforce isolation is false are handled as if
6988bd22e44aSChristian König 	 * they come from a single client. Use ~0l as the owner to distinct it
6989bd22e44aSChristian König 	 * from kernel submissions where the owner is NULL.
6990bd22e44aSChristian König 	 */
6991bd22e44aSChristian König 	owner = job->enforce_isolation ? f->owner : (void *)~0l;
6992bd22e44aSChristian König 
6993bd22e44aSChristian König 	mutex_lock(&adev->enforce_isolation_mutex);
6994bd22e44aSChristian König 
6995bd22e44aSChristian König 	/*
6996bd22e44aSChristian König 	 * The "spearhead" submission is the first one which changes the
6997bd22e44aSChristian König 	 * ownership to its client. We always need to wait for it to be
6998bd22e44aSChristian König 	 * pushed to the HW before proceeding with anything.
6999bd22e44aSChristian König 	 */
7000bd22e44aSChristian König 	if (&f->scheduled != isolation->spearhead &&
7001bd22e44aSChristian König 	    !dma_fence_is_signaled(isolation->spearhead)) {
7002bd22e44aSChristian König 		dep = isolation->spearhead;
7003bd22e44aSChristian König 		goto out_grab_ref;
7004bd22e44aSChristian König 	}
7005bd22e44aSChristian König 
7006bd22e44aSChristian König 	if (isolation->owner != owner) {
7007bd22e44aSChristian König 
7008bd22e44aSChristian König 		/*
7009bd22e44aSChristian König 		 * Wait for any gang to be assembled before switching to a
7010bd22e44aSChristian König 		 * different owner or otherwise we could deadlock the
7011bd22e44aSChristian König 		 * submissions.
7012bd22e44aSChristian König 		 */
7013bd22e44aSChristian König 		if (!job->gang_submit) {
7014bd22e44aSChristian König 			dep = amdgpu_device_get_gang(adev);
7015bd22e44aSChristian König 			if (!dma_fence_is_signaled(dep))
7016bd22e44aSChristian König 				goto out_return_dep;
7017bd22e44aSChristian König 			dma_fence_put(dep);
7018bd22e44aSChristian König 		}
7019bd22e44aSChristian König 
7020bd22e44aSChristian König 		dma_fence_put(isolation->spearhead);
7021bd22e44aSChristian König 		isolation->spearhead = dma_fence_get(&f->scheduled);
7022bd22e44aSChristian König 		amdgpu_sync_move(&isolation->active, &isolation->prev);
70231bb1314dSChristian König 		trace_amdgpu_isolation(isolation->owner, owner);
7024bd22e44aSChristian König 		isolation->owner = owner;
7025bd22e44aSChristian König 	}
7026bd22e44aSChristian König 
7027bd22e44aSChristian König 	/*
7028bd22e44aSChristian König 	 * Specifying the ring here helps to pipeline submissions even when
7029bd22e44aSChristian König 	 * isolation is enabled. If that is not desired for testing NULL can be
7030bd22e44aSChristian König 	 * used instead of the ring to enforce a CPU round trip while switching
7031bd22e44aSChristian König 	 * between clients.
7032bd22e44aSChristian König 	 */
7033bd22e44aSChristian König 	dep = amdgpu_sync_peek_fence(&isolation->prev, ring);
7034bd22e44aSChristian König 	r = amdgpu_sync_fence(&isolation->active, &f->finished, GFP_NOWAIT);
7035bd22e44aSChristian König 	if (r)
7036bd22e44aSChristian König 		DRM_WARN("OOM tracking isolation\n");
7037bd22e44aSChristian König 
7038bd22e44aSChristian König out_grab_ref:
7039bd22e44aSChristian König 	dma_fence_get(dep);
7040bd22e44aSChristian König out_return_dep:
7041bd22e44aSChristian König 	mutex_unlock(&adev->enforce_isolation_mutex);
7042bd22e44aSChristian König 	return dep;
7043bd22e44aSChristian König }
7044bd22e44aSChristian König 
amdgpu_device_has_display_hardware(struct amdgpu_device * adev)7045220c8cc8SAlex Deucher bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev)
7046220c8cc8SAlex Deucher {
7047220c8cc8SAlex Deucher 	switch (adev->asic_type) {
7048220c8cc8SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_SI
7049220c8cc8SAlex Deucher 	case CHIP_HAINAN:
7050220c8cc8SAlex Deucher #endif
7051220c8cc8SAlex Deucher 	case CHIP_TOPAZ:
7052220c8cc8SAlex Deucher 		/* chips with no display hardware */
7053220c8cc8SAlex Deucher 		return false;
7054220c8cc8SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_SI
7055220c8cc8SAlex Deucher 	case CHIP_TAHITI:
7056220c8cc8SAlex Deucher 	case CHIP_PITCAIRN:
7057220c8cc8SAlex Deucher 	case CHIP_VERDE:
7058220c8cc8SAlex Deucher 	case CHIP_OLAND:
7059220c8cc8SAlex Deucher #endif
7060220c8cc8SAlex Deucher #ifdef CONFIG_DRM_AMDGPU_CIK
7061220c8cc8SAlex Deucher 	case CHIP_BONAIRE:
7062220c8cc8SAlex Deucher 	case CHIP_HAWAII:
7063220c8cc8SAlex Deucher 	case CHIP_KAVERI:
7064220c8cc8SAlex Deucher 	case CHIP_KABINI:
7065220c8cc8SAlex Deucher 	case CHIP_MULLINS:
7066220c8cc8SAlex Deucher #endif
7067220c8cc8SAlex Deucher 	case CHIP_TONGA:
7068220c8cc8SAlex Deucher 	case CHIP_FIJI:
7069220c8cc8SAlex Deucher 	case CHIP_POLARIS10:
7070220c8cc8SAlex Deucher 	case CHIP_POLARIS11:
7071220c8cc8SAlex Deucher 	case CHIP_POLARIS12:
7072220c8cc8SAlex Deucher 	case CHIP_VEGAM:
7073220c8cc8SAlex Deucher 	case CHIP_CARRIZO:
7074220c8cc8SAlex Deucher 	case CHIP_STONEY:
7075220c8cc8SAlex Deucher 		/* chips with display hardware */
7076220c8cc8SAlex Deucher 		return true;
7077220c8cc8SAlex Deucher 	default:
7078220c8cc8SAlex Deucher 		/* IP discovery */
70794e8303cfSLijo Lazar 		if (!amdgpu_ip_version(adev, DCE_HWIP, 0) ||
7080220c8cc8SAlex Deucher 		    (adev->harvest_ip_mask & AMD_HARVEST_IP_DMU_MASK))
7081220c8cc8SAlex Deucher 			return false;
7082220c8cc8SAlex Deucher 		return true;
7083220c8cc8SAlex Deucher 	}
7084220c8cc8SAlex Deucher }
708581283feeSJames Zhu 
amdgpu_device_wait_on_rreg(struct amdgpu_device * adev,uint32_t inst,uint32_t reg_addr,char reg_name[],uint32_t expected_value,uint32_t mask)708681283feeSJames Zhu uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev,
708781283feeSJames Zhu 		uint32_t inst, uint32_t reg_addr, char reg_name[],
708881283feeSJames Zhu 		uint32_t expected_value, uint32_t mask)
708981283feeSJames Zhu {
709081283feeSJames Zhu 	uint32_t ret = 0;
709181283feeSJames Zhu 	uint32_t old_ = 0;
709281283feeSJames Zhu 	uint32_t tmp_ = RREG32(reg_addr);
709381283feeSJames Zhu 	uint32_t loop = adev->usec_timeout;
709481283feeSJames Zhu 
709581283feeSJames Zhu 	while ((tmp_ & (mask)) != (expected_value)) {
709681283feeSJames Zhu 		if (old_ != tmp_) {
709781283feeSJames Zhu 			loop = adev->usec_timeout;
709881283feeSJames Zhu 			old_ = tmp_;
709981283feeSJames Zhu 		} else
710081283feeSJames Zhu 			udelay(1);
710181283feeSJames Zhu 		tmp_ = RREG32(reg_addr);
710281283feeSJames Zhu 		loop--;
710381283feeSJames Zhu 		if (!loop) {
710481283feeSJames Zhu 			DRM_WARN("Register(%d) [%s] failed to reach value 0x%08x != 0x%08xn",
710581283feeSJames Zhu 				  inst, reg_name, (uint32_t)expected_value,
710681283feeSJames Zhu 				  (uint32_t)(tmp_ & (mask)));
710781283feeSJames Zhu 			ret = -ETIMEDOUT;
710881283feeSJames Zhu 			break;
710981283feeSJames Zhu 		}
711081283feeSJames Zhu 	}
711181283feeSJames Zhu 	return ret;
711281283feeSJames Zhu }
71136c8d1f4bS[email protected] 
amdgpu_get_soft_full_reset_mask(struct amdgpu_ring * ring)71146c8d1f4bS[email protected] ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring)
71156c8d1f4bS[email protected] {
71166c8d1f4bS[email protected] 	ssize_t size = 0;
71176c8d1f4bS[email protected] 
71186c8d1f4bS[email protected] 	if (!ring || !ring->adev)
71196c8d1f4bS[email protected] 		return size;
71206c8d1f4bS[email protected] 
71216c8d1f4bS[email protected] 	if (amdgpu_device_should_recover_gpu(ring->adev))
71226c8d1f4bS[email protected] 		size |= AMDGPU_RESET_TYPE_FULL;
71236c8d1f4bS[email protected] 
71246c8d1f4bS[email protected] 	if (unlikely(!ring->adev->debug_disable_soft_recovery) &&
71256c8d1f4bS[email protected] 	    !amdgpu_sriov_vf(ring->adev) && ring->funcs->soft_recovery)
71266c8d1f4bS[email protected] 		size |= AMDGPU_RESET_TYPE_SOFT_RESET;
71276c8d1f4bS[email protected] 
71286c8d1f4bS[email protected] 	return size;
71296c8d1f4bS[email protected] }
71306c8d1f4bS[email protected] 
amdgpu_show_reset_mask(char * buf,uint32_t supported_reset)71316c8d1f4bS[email protected] ssize_t amdgpu_show_reset_mask(char *buf, uint32_t supported_reset)
71326c8d1f4bS[email protected] {
71336c8d1f4bS[email protected] 	ssize_t size = 0;
71346c8d1f4bS[email protected] 
71356c8d1f4bS[email protected] 	if (supported_reset == 0) {
71366c8d1f4bS[email protected] 		size += sysfs_emit_at(buf, size, "unsupported");
71376c8d1f4bS[email protected] 		size += sysfs_emit_at(buf, size, "\n");
71386c8d1f4bS[email protected] 		return size;
71396c8d1f4bS[email protected] 
71406c8d1f4bS[email protected] 	}
71416c8d1f4bS[email protected] 
71426c8d1f4bS[email protected] 	if (supported_reset & AMDGPU_RESET_TYPE_SOFT_RESET)
71436c8d1f4bS[email protected] 		size += sysfs_emit_at(buf, size, "soft ");
71446c8d1f4bS[email protected] 
71456c8d1f4bS[email protected] 	if (supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)
71466c8d1f4bS[email protected] 		size += sysfs_emit_at(buf, size, "queue ");
71476c8d1f4bS[email protected] 
71486c8d1f4bS[email protected] 	if (supported_reset & AMDGPU_RESET_TYPE_PER_PIPE)
71496c8d1f4bS[email protected] 		size += sysfs_emit_at(buf, size, "pipe ");
71506c8d1f4bS[email protected] 
71516c8d1f4bS[email protected] 	if (supported_reset & AMDGPU_RESET_TYPE_FULL)
71526c8d1f4bS[email protected] 		size += sysfs_emit_at(buf, size, "full ");
71536c8d1f4bS[email protected] 
71546c8d1f4bS[email protected] 	size += sysfs_emit_at(buf, size, "\n");
71556c8d1f4bS[email protected] 	return size;
71566c8d1f4bS[email protected] }
7157