xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c (revision 87832e937c808a7ebc41254b408362e3255c87c9)
1f9df67e9SHawking Zhang /*
2f9df67e9SHawking Zhang  * Copyright 2019 Advanced Micro Devices, Inc.
3f9df67e9SHawking Zhang  *
4f9df67e9SHawking Zhang  * Permission is hereby granted, free of charge, to any person obtaining a
5f9df67e9SHawking Zhang  * copy of this software and associated documentation files (the "Software"),
6f9df67e9SHawking Zhang  * to deal in the Software without restriction, including without limitation
7f9df67e9SHawking Zhang  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f9df67e9SHawking Zhang  * and/or sell copies of the Software, and to permit persons to whom the
9f9df67e9SHawking Zhang  * Software is furnished to do so, subject to the following conditions:
10f9df67e9SHawking Zhang  *
11f9df67e9SHawking Zhang  * The above copyright notice and this permission notice shall be included in
12f9df67e9SHawking Zhang  * all copies or substantial portions of the Software.
13f9df67e9SHawking Zhang  *
14f9df67e9SHawking Zhang  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15f9df67e9SHawking Zhang  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16f9df67e9SHawking Zhang  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17f9df67e9SHawking Zhang  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18f9df67e9SHawking Zhang  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19f9df67e9SHawking Zhang  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20f9df67e9SHawking Zhang  * OTHER DEALINGS IN THE SOFTWARE.
21f9df67e9SHawking Zhang  *
22f9df67e9SHawking Zhang  */
23f9df67e9SHawking Zhang #include <linux/firmware.h>
24d7929c1eSAlex Deucher #include <linux/pci.h>
253616d49dSAaron Liu 
263616d49dSAaron Liu #include <drm/drm_cache.h>
273616d49dSAaron Liu 
28f9df67e9SHawking Zhang #include "amdgpu.h"
29f9df67e9SHawking Zhang #include "amdgpu_atomfirmware.h"
30f9df67e9SHawking Zhang #include "gmc_v10_0.h"
3101eee24fSJohn Clements #include "umc_v8_7.h"
32f9df67e9SHawking Zhang 
33ea930000SAlex Sierra #include "athub/athub_2_0_0_sh_mask.h"
34ea930000SAlex Sierra #include "athub/athub_2_0_0_offset.h"
35f9df67e9SHawking Zhang #include "dcn/dcn_2_0_0_offset.h"
36f9df67e9SHawking Zhang #include "dcn/dcn_2_0_0_sh_mask.h"
37f9df67e9SHawking Zhang #include "oss/osssys_5_0_0_offset.h"
38f9df67e9SHawking Zhang #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
39f9df67e9SHawking Zhang #include "navi10_enum.h"
40f9df67e9SHawking Zhang 
41f9df67e9SHawking Zhang #include "soc15.h"
42ea930000SAlex Sierra #include "soc15d.h"
43f9df67e9SHawking Zhang #include "soc15_common.h"
44f9df67e9SHawking Zhang 
45f9df67e9SHawking Zhang #include "nbio_v2_3.h"
46f9df67e9SHawking Zhang 
47f9df67e9SHawking Zhang #include "gfxhub_v2_0.h"
480b3df16bSLikun Gao #include "gfxhub_v2_1.h"
49f9df67e9SHawking Zhang #include "mmhub_v2_0.h"
504d8d75a4SHuang Rui #include "mmhub_v2_3.h"
51f9df67e9SHawking Zhang #include "athub_v2_0.h"
52920a4cd3SLikun Gao #include "athub_v2_1.h"
53f9df67e9SHawking Zhang 
54d0fb18b5SAndrey Grodzovsky #include "amdgpu_reset.h"
55d0fb18b5SAndrey Grodzovsky 
gmc_v10_0_ecc_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * src,unsigned int type,enum amdgpu_interrupt_state state)5601eee24fSJohn Clements static int gmc_v10_0_ecc_interrupt_state(struct amdgpu_device *adev,
5701eee24fSJohn Clements 					 struct amdgpu_irq_src *src,
588612a435SSrinivasan Shanmugam 					 unsigned int type,
5901eee24fSJohn Clements 					 enum amdgpu_interrupt_state state)
6001eee24fSJohn Clements {
6101eee24fSJohn Clements 	return 0;
6201eee24fSJohn Clements }
6301eee24fSJohn Clements 
64f9df67e9SHawking Zhang static int
gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * src,unsigned int type,enum amdgpu_interrupt_state state)65f9df67e9SHawking Zhang gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
668612a435SSrinivasan Shanmugam 				   struct amdgpu_irq_src *src, unsigned int type,
67f9df67e9SHawking Zhang 				   enum amdgpu_interrupt_state state)
68f9df67e9SHawking Zhang {
69f9df67e9SHawking Zhang 	switch (state) {
70f9df67e9SHawking Zhang 	case AMDGPU_IRQ_STATE_DISABLE:
71f9df67e9SHawking Zhang 		/* MM HUB */
72f4caf584SHawking Zhang 		amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB0(0), false);
73f9df67e9SHawking Zhang 		/* GFX HUB */
74d5d29009SAlex Deucher 		/* This works because this interrupt is only
75d5d29009SAlex Deucher 		 * enabled at init/resume and disabled in
76d5d29009SAlex Deucher 		 * fini/suspend, so the overall state doesn't
77d5d29009SAlex Deucher 		 * change over the course of suspend/resume.
78d5d29009SAlex Deucher 		 */
79d5d29009SAlex Deucher 		if (!adev->in_s0ix)
80f4caf584SHawking Zhang 			amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB(0), false);
81f9df67e9SHawking Zhang 		break;
82f9df67e9SHawking Zhang 	case AMDGPU_IRQ_STATE_ENABLE:
83f9df67e9SHawking Zhang 		/* MM HUB */
84f4caf584SHawking Zhang 		amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB0(0), true);
85f9df67e9SHawking Zhang 		/* GFX HUB */
86d5d29009SAlex Deucher 		/* This works because this interrupt is only
87d5d29009SAlex Deucher 		 * enabled at init/resume and disabled in
88d5d29009SAlex Deucher 		 * fini/suspend, so the overall state doesn't
89d5d29009SAlex Deucher 		 * change over the course of suspend/resume.
90d5d29009SAlex Deucher 		 */
91d5d29009SAlex Deucher 		if (!adev->in_s0ix)
92f4caf584SHawking Zhang 			amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB(0), true);
93f9df67e9SHawking Zhang 		break;
94f9df67e9SHawking Zhang 	default:
95f9df67e9SHawking Zhang 		break;
96f9df67e9SHawking Zhang 	}
97f9df67e9SHawking Zhang 
98f9df67e9SHawking Zhang 	return 0;
99f9df67e9SHawking Zhang }
100f9df67e9SHawking Zhang 
gmc_v10_0_process_interrupt(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)101f9df67e9SHawking Zhang static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
102f9df67e9SHawking Zhang 				       struct amdgpu_irq_src *source,
103f9df67e9SHawking Zhang 				       struct amdgpu_iv_entry *entry)
104f9df67e9SHawking Zhang {
1056f38bdb8SLang Yu 	uint32_t vmhub_index = entry->client_id == SOC15_IH_CLIENTID_VMC ?
1066f38bdb8SLang Yu 			       AMDGPU_MMHUB0(0) : AMDGPU_GFXHUB(0);
1076f38bdb8SLang Yu 	struct amdgpu_vmhub *hub = &adev->vmhub[vmhub_index];
108a2a8857cSChristian König 	bool retry_fault = !!(entry->src_data[1] & 0x80);
109ff891a2eSPhilip Yang 	bool write_fault = !!(entry->src_data[1] & 0x20);
11045d87b85SChristian König 	struct amdgpu_task_info task_info;
111f9df67e9SHawking Zhang 	uint32_t status = 0;
112f9df67e9SHawking Zhang 	u64 addr;
113f9df67e9SHawking Zhang 
114f9df67e9SHawking Zhang 	addr = (u64)entry->src_data[0] << 12;
115f9df67e9SHawking Zhang 	addr |= ((u64)entry->src_data[1] & 0xf) << 44;
116f9df67e9SHawking Zhang 
117a2a8857cSChristian König 	if (retry_fault) {
118a2a8857cSChristian König 		/* Returning 1 here also prevents sending the IV to the KFD */
119a2a8857cSChristian König 
120a2a8857cSChristian König 		/* Process it onyl if it's the first fault for this address */
121a2a8857cSChristian König 		if (entry->ih != &adev->irq.ih_soft &&
1223c2d6ea2SPhilip Yang 		    amdgpu_gmc_filter_faults(adev, entry->ih, addr, entry->pasid,
123a2a8857cSChristian König 					     entry->timestamp))
124a2a8857cSChristian König 			return 1;
125a2a8857cSChristian König 
126a2a8857cSChristian König 		/* Delegate it to a different ring if the hardware hasn't
127a2a8857cSChristian König 		 * already done it.
128a2a8857cSChristian König 		 */
12958df0d71SSebastian Andrzej Siewior 		if (entry->ih == &adev->irq.ih) {
130a2a8857cSChristian König 			amdgpu_irq_delegate(adev, entry, 8);
131a2a8857cSChristian König 			return 1;
132a2a8857cSChristian König 		}
133a2a8857cSChristian König 
134a2a8857cSChristian König 		/* Try to handle the recoverable page faults by filling page
135a2a8857cSChristian König 		 * tables
136a2a8857cSChristian König 		 */
1375fb34bd9SAlex Sierra 		if (amdgpu_vm_handle_fault(adev, entry->pasid, 0, 0, addr, write_fault))
138a2a8857cSChristian König 			return 1;
139a2a8857cSChristian König 	}
140a2a8857cSChristian König 
141f9df67e9SHawking Zhang 	if (!amdgpu_sriov_vf(adev)) {
14253499173SXiaojie Yuan 		/*
14353499173SXiaojie Yuan 		 * Issue a dummy read to wait for the status register to
14453499173SXiaojie Yuan 		 * be updated to avoid reading an incorrect value due to
14553499173SXiaojie Yuan 		 * the new fast GRBM interface.
14653499173SXiaojie Yuan 		 */
147f4caf584SHawking Zhang 		if ((entry->vmid_src == AMDGPU_GFXHUB(0)) &&
1481d789535SAlex Deucher 		    (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 3, 0)))
14953499173SXiaojie Yuan 			RREG32(hub->vm_l2_pro_fault_status);
15053499173SXiaojie Yuan 
151f9df67e9SHawking Zhang 		status = RREG32(hub->vm_l2_pro_fault_status);
152f9df67e9SHawking Zhang 		WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
153f9df67e9SHawking Zhang 	}
154f9df67e9SHawking Zhang 
15545d87b85SChristian König 	if (!printk_ratelimit())
15645d87b85SChristian König 		return 0;
1575d36d4c9SYong Zhao 
1585d36d4c9SYong Zhao 	memset(&task_info, 0, sizeof(struct amdgpu_task_info));
1595d36d4c9SYong Zhao 	amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
1605d36d4c9SYong Zhao 
161f9df67e9SHawking Zhang 	dev_err(adev->dev,
1628612a435SSrinivasan Shanmugam 		"[%s] page fault (src_id:%u ring:%u vmid:%u pasid:%u, for process %s pid %d thread %s pid %d)\n",
163f9df67e9SHawking Zhang 		entry->vmid_src ? "mmhub" : "gfxhub",
164f9df67e9SHawking Zhang 		entry->src_id, entry->ring_id, entry->vmid,
1655d36d4c9SYong Zhao 		entry->pasid, task_info.process_name, task_info.tgid,
1665d36d4c9SYong Zhao 		task_info.task_name, task_info.pid);
167be14729aSYong Zhao 	dev_err(adev->dev, "  in page starting at address 0x%016llx from client 0x%x (%s)\n",
168be14729aSYong Zhao 		addr, entry->client_id,
169be14729aSYong Zhao 		soc15_ih_clientid_name[entry->client_id]);
17045d87b85SChristian König 
1712577db91SHuang Rui 	if (!amdgpu_sriov_vf(adev))
17245d87b85SChristian König 		hub->vmhub_funcs->print_l2_protection_fault_status(adev,
17345d87b85SChristian König 								   status);
174f9df67e9SHawking Zhang 
175f9df67e9SHawking Zhang 	return 0;
176f9df67e9SHawking Zhang }
177f9df67e9SHawking Zhang 
178f9df67e9SHawking Zhang static const struct amdgpu_irq_src_funcs gmc_v10_0_irq_funcs = {
179f9df67e9SHawking Zhang 	.set = gmc_v10_0_vm_fault_interrupt_state,
180f9df67e9SHawking Zhang 	.process = gmc_v10_0_process_interrupt,
181f9df67e9SHawking Zhang };
182f9df67e9SHawking Zhang 
18301eee24fSJohn Clements static const struct amdgpu_irq_src_funcs gmc_v10_0_ecc_funcs = {
18401eee24fSJohn Clements 	.set = gmc_v10_0_ecc_interrupt_state,
18501eee24fSJohn Clements 	.process = amdgpu_umc_process_ecc_irq,
18601eee24fSJohn Clements };
18701eee24fSJohn Clements 
gmc_v10_0_set_irq_funcs(struct amdgpu_device * adev)188f9df67e9SHawking Zhang static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev)
189f9df67e9SHawking Zhang {
190f9df67e9SHawking Zhang 	adev->gmc.vm_fault.num_types = 1;
191f9df67e9SHawking Zhang 	adev->gmc.vm_fault.funcs = &gmc_v10_0_irq_funcs;
19201eee24fSJohn Clements 
19301eee24fSJohn Clements 	if (!amdgpu_sriov_vf(adev)) {
19401eee24fSJohn Clements 		adev->gmc.ecc_irq.num_types = 1;
19501eee24fSJohn Clements 		adev->gmc.ecc_irq.funcs = &gmc_v10_0_ecc_funcs;
19601eee24fSJohn Clements 	}
197f9df67e9SHawking Zhang }
198f9df67e9SHawking Zhang 
199f271fe18Schangzhu /**
200f271fe18Schangzhu  * gmc_v10_0_use_invalidate_semaphore - judge whether to use semaphore
201f271fe18Schangzhu  *
202f271fe18Schangzhu  * @adev: amdgpu_device pointer
203f271fe18Schangzhu  * @vmhub: vmhub type
204f271fe18Schangzhu  *
205f271fe18Schangzhu  */
gmc_v10_0_use_invalidate_semaphore(struct amdgpu_device * adev,uint32_t vmhub)206f271fe18Schangzhu static bool gmc_v10_0_use_invalidate_semaphore(struct amdgpu_device *adev,
207f271fe18Schangzhu 				       uint32_t vmhub)
208f271fe18Schangzhu {
209f4caf584SHawking Zhang 	return ((vmhub == AMDGPU_MMHUB0(0)) &&
210f271fe18Schangzhu 		(!amdgpu_sriov_vf(adev)));
211f271fe18Schangzhu }
212f271fe18Schangzhu 
gmc_v10_0_get_atc_vmid_pasid_mapping_info(struct amdgpu_device * adev,uint8_t vmid,uint16_t * p_pasid)213ea930000SAlex Sierra static bool gmc_v10_0_get_atc_vmid_pasid_mapping_info(
214ea930000SAlex Sierra 					struct amdgpu_device *adev,
215ea930000SAlex Sierra 					uint8_t vmid, uint16_t *p_pasid)
216ea930000SAlex Sierra {
217ea930000SAlex Sierra 	uint32_t value;
218ea930000SAlex Sierra 
219ea930000SAlex Sierra 	value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
220ea930000SAlex Sierra 		     + vmid);
221ea930000SAlex Sierra 	*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
222ea930000SAlex Sierra 
223ea930000SAlex Sierra 	return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
224ea930000SAlex Sierra }
225ea930000SAlex Sierra 
226f9df67e9SHawking Zhang /*
227f9df67e9SHawking Zhang  * GART
228f9df67e9SHawking Zhang  * VMID 0 is the physical GPU addresses as used by the kernel.
229f9df67e9SHawking Zhang  * VMIDs 1-15 are used for userspace clients and are handled
230f9df67e9SHawking Zhang  * by the amdgpu vm/hsa code.
231f9df67e9SHawking Zhang  */
232f9df67e9SHawking Zhang 
gmc_v10_0_flush_vm_hub(struct amdgpu_device * adev,uint32_t vmid,unsigned int vmhub,uint32_t flush_type)233f9df67e9SHawking Zhang static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
234f9df67e9SHawking Zhang 				   unsigned int vmhub, uint32_t flush_type)
235f9df67e9SHawking Zhang {
236f271fe18Schangzhu 	bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(adev, vmhub);
237f9df67e9SHawking Zhang 	struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
238caa9f483SHuang Rui 	u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
23937c58ddfSFelix Kuehling 	u32 tmp;
240f9df67e9SHawking Zhang 	/* Use register 17 for GART */
2418612a435SSrinivasan Shanmugam 	const unsigned int eng = 17;
242f9df67e9SHawking Zhang 	unsigned int i;
2436ba3f59eSPeng Ju Zhou 	unsigned char hub_ip = 0;
2446ba3f59eSPeng Ju Zhou 
245f4caf584SHawking Zhang 	hub_ip = (vmhub == AMDGPU_GFXHUB(0)) ?
2466ba3f59eSPeng Ju Zhou 		   GC_HWIP : MMHUB_HWIP;
247f9df67e9SHawking Zhang 
248f920d1bbSchangzhu 	spin_lock(&adev->gmc.invalidate_lock);
249f920d1bbSchangzhu 	/*
250f920d1bbSchangzhu 	 * It may lose gpuvm invalidate acknowldege state across power-gating
251f920d1bbSchangzhu 	 * off cycle, add semaphore acquire before invalidation and semaphore
252f920d1bbSchangzhu 	 * release after invalidation to avoid entering power gated state
253f920d1bbSchangzhu 	 * to WA the Issue
254f920d1bbSchangzhu 	 */
255f920d1bbSchangzhu 
256f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
257f271fe18Schangzhu 	if (use_semaphore) {
258f920d1bbSchangzhu 		for (i = 0; i < adev->usec_timeout; i++) {
259f920d1bbSchangzhu 			/* a read return value of 1 means semaphore acuqire */
2606ba3f59eSPeng Ju Zhou 			tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
2616ba3f59eSPeng Ju Zhou 					 hub->eng_distance * eng, hub_ip);
2626ba3f59eSPeng Ju Zhou 
263f920d1bbSchangzhu 			if (tmp & 0x1)
264f920d1bbSchangzhu 				break;
265f920d1bbSchangzhu 			udelay(1);
266f920d1bbSchangzhu 		}
267f920d1bbSchangzhu 
268f920d1bbSchangzhu 		if (i >= adev->usec_timeout)
269f920d1bbSchangzhu 			DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
270f920d1bbSchangzhu 	}
271f920d1bbSchangzhu 
2726ba3f59eSPeng Ju Zhou 	WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req +
2736ba3f59eSPeng Ju Zhou 			  hub->eng_distance * eng,
2746ba3f59eSPeng Ju Zhou 			  inv_req, hub_ip);
275f9df67e9SHawking Zhang 
27653499173SXiaojie Yuan 	/*
27753499173SXiaojie Yuan 	 * Issue a dummy read to wait for the ACK register to be cleared
27853499173SXiaojie Yuan 	 * to avoid a false ACK due to the new fast GRBM interface.
27953499173SXiaojie Yuan 	 */
280f4caf584SHawking Zhang 	if ((vmhub == AMDGPU_GFXHUB(0)) &&
2811d789535SAlex Deucher 	    (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 3, 0)))
2826ba3f59eSPeng Ju Zhou 		RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req +
2836ba3f59eSPeng Ju Zhou 				  hub->eng_distance * eng, hub_ip);
28453499173SXiaojie Yuan 
285f9df67e9SHawking Zhang 	/* Wait for ACK with a delay.*/
286f9df67e9SHawking Zhang 	for (i = 0; i < adev->usec_timeout; i++) {
2876ba3f59eSPeng Ju Zhou 		tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_ack +
2886ba3f59eSPeng Ju Zhou 				  hub->eng_distance * eng, hub_ip);
2896ba3f59eSPeng Ju Zhou 
290f9df67e9SHawking Zhang 		tmp &= 1 << vmid;
291f9df67e9SHawking Zhang 		if (tmp)
292f9df67e9SHawking Zhang 			break;
293f9df67e9SHawking Zhang 
294f9df67e9SHawking Zhang 		udelay(1);
295f9df67e9SHawking Zhang 	}
296f9df67e9SHawking Zhang 
297f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
298f271fe18Schangzhu 	if (use_semaphore)
299f920d1bbSchangzhu 		/*
300f920d1bbSchangzhu 		 * add semaphore release after invalidation,
301f920d1bbSchangzhu 		 * write with 0 means semaphore release
302f920d1bbSchangzhu 		 */
3036ba3f59eSPeng Ju Zhou 		WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
3046ba3f59eSPeng Ju Zhou 				  hub->eng_distance * eng, 0, hub_ip);
305f920d1bbSchangzhu 
306f920d1bbSchangzhu 	spin_unlock(&adev->gmc.invalidate_lock);
307f920d1bbSchangzhu 
308f9df67e9SHawking Zhang 	if (i < adev->usec_timeout)
309f9df67e9SHawking Zhang 		return;
310f9df67e9SHawking Zhang 
311d9c7f753SPeng Ju Zhou 	DRM_ERROR("Timeout waiting for VM flush hub: %d!\n", vmhub);
312f9df67e9SHawking Zhang }
313f9df67e9SHawking Zhang 
314f9df67e9SHawking Zhang /**
315f9df67e9SHawking Zhang  * gmc_v10_0_flush_gpu_tlb - gart tlb flush callback
316f9df67e9SHawking Zhang  *
317f9df67e9SHawking Zhang  * @adev: amdgpu_device pointer
318f9df67e9SHawking Zhang  * @vmid: vm instance to flush
319185ef9efSLee Jones  * @vmhub: vmhub type
320185ef9efSLee Jones  * @flush_type: the flush type
321f9df67e9SHawking Zhang  *
322f9df67e9SHawking Zhang  * Flush the TLB for the requested page table.
323f9df67e9SHawking Zhang  */
gmc_v10_0_flush_gpu_tlb(struct amdgpu_device * adev,uint32_t vmid,uint32_t vmhub,uint32_t flush_type)3243ff98548SOak Zeng static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
3253ff98548SOak Zeng 					uint32_t vmhub, uint32_t flush_type)
326f9df67e9SHawking Zhang {
327f9df67e9SHawking Zhang 	struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
328f9df67e9SHawking Zhang 	struct dma_fence *fence;
329f9df67e9SHawking Zhang 	struct amdgpu_job *job;
330f9df67e9SHawking Zhang 
331f9df67e9SHawking Zhang 	int r;
332f9df67e9SHawking Zhang 
333f9df67e9SHawking Zhang 	/* flush hdp cache */
334bf087285SLikun Gao 	adev->hdp.funcs->flush_hdp(adev, NULL);
335f9df67e9SHawking Zhang 
3368db1015bSshaoyunl 	/* For SRIOV run time, driver shouldn't access the register through MMIO
3378db1015bSshaoyunl 	 * Directly use kiq to do the vm invalidation instead
3388db1015bSshaoyunl 	 */
339277bd337SLe Ma 	if (adev->gfx.kiq[0].ring.sched.ready && !adev->enable_mes &&
3408db1015bSshaoyunl 	    (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
341d0fb18b5SAndrey Grodzovsky 	    down_read_trylock(&adev->reset_domain->sem)) {
3428db1015bSshaoyunl 		struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
3438612a435SSrinivasan Shanmugam 		const unsigned int eng = 17;
344caa9f483SHuang Rui 		u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
345af6c5c4fSHuang Rui 		u32 req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
346af6c5c4fSHuang Rui 		u32 ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
3478db1015bSshaoyunl 
3488db1015bSshaoyunl 		amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
3498db1015bSshaoyunl 				1 << vmid);
35081202807SDennis Li 
351d0fb18b5SAndrey Grodzovsky 		up_read(&adev->reset_domain->sem);
3528db1015bSshaoyunl 		return;
3538db1015bSshaoyunl 	}
3548db1015bSshaoyunl 
355f9df67e9SHawking Zhang 	mutex_lock(&adev->mman.gtt_window_lock);
356f9df67e9SHawking Zhang 
357f4caf584SHawking Zhang 	if (vmhub == AMDGPU_MMHUB0(0)) {
358f4caf584SHawking Zhang 		gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_MMHUB0(0), 0);
3593ff98548SOak Zeng 		mutex_unlock(&adev->mman.gtt_window_lock);
3603ff98548SOak Zeng 		return;
3613ff98548SOak Zeng 	}
3623ff98548SOak Zeng 
363f4caf584SHawking Zhang 	BUG_ON(vmhub != AMDGPU_GFXHUB(0));
3643ff98548SOak Zeng 
365767acabdSKevin Wang 	if (!adev->mman.buffer_funcs_enabled ||
366767acabdSKevin Wang 	    !adev->ib_pool_ready ||
36753b3f8f4SDennis Li 	    amdgpu_in_reset(adev) ||
368e2195f7dSMonk Liu 	    ring->sched.ready == false) {
369f4caf584SHawking Zhang 		gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB(0), 0);
370f9df67e9SHawking Zhang 		mutex_unlock(&adev->mman.gtt_window_lock);
371f9df67e9SHawking Zhang 		return;
372f9df67e9SHawking Zhang 	}
373f9df67e9SHawking Zhang 
374f9df67e9SHawking Zhang 	/* The SDMA on Navi has a bug which can theoretically result in memory
375f9df67e9SHawking Zhang 	 * corruption if an invalidation happens at the same time as an VA
376f9df67e9SHawking Zhang 	 * translation. Avoid this by doing the invalidation from the SDMA
377f9df67e9SHawking Zhang 	 * itself.
378f9df67e9SHawking Zhang 	 */
37941ce6d6dSMukul Joshi 	r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.high_pr,
380f7d66fb2SChristian König 				     AMDGPU_FENCE_OWNER_UNDEFINED,
381f7d66fb2SChristian König 				     16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
3829ecefb19SChristian König 				     &job);
383f9df67e9SHawking Zhang 	if (r)
384f9df67e9SHawking Zhang 		goto error_alloc;
385f9df67e9SHawking Zhang 
386f9df67e9SHawking Zhang 	job->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gart.bo);
387f9df67e9SHawking Zhang 	job->vm_needs_flush = true;
3883f378758SPelloux-prayer, Pierre-eric 	job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop;
389f9df67e9SHawking Zhang 	amdgpu_ring_pad_ib(ring, &job->ibs[0]);
390f7d66fb2SChristian König 	fence = amdgpu_job_submit(job);
391f9df67e9SHawking Zhang 
392f9df67e9SHawking Zhang 	mutex_unlock(&adev->mman.gtt_window_lock);
393f9df67e9SHawking Zhang 
394f9df67e9SHawking Zhang 	dma_fence_wait(fence, false);
395f9df67e9SHawking Zhang 	dma_fence_put(fence);
396f9df67e9SHawking Zhang 
397f9df67e9SHawking Zhang 	return;
398f9df67e9SHawking Zhang 
399f9df67e9SHawking Zhang error_alloc:
400f9df67e9SHawking Zhang 	mutex_unlock(&adev->mman.gtt_window_lock);
401f9df67e9SHawking Zhang 	DRM_ERROR("Error flushing GPU TLB using the SDMA (%d)!\n", r);
402f9df67e9SHawking Zhang }
403f9df67e9SHawking Zhang 
404ea930000SAlex Sierra /**
405ea930000SAlex Sierra  * gmc_v10_0_flush_gpu_tlb_pasid - tlb flush via pasid
406ea930000SAlex Sierra  *
407ea930000SAlex Sierra  * @adev: amdgpu_device pointer
408ea930000SAlex Sierra  * @pasid: pasid to be flush
409185ef9efSLee Jones  * @flush_type: the flush type
410185ef9efSLee Jones  * @all_hub: Used with PACKET3_INVALIDATE_TLBS_ALL_HUB()
4111bae03aaSSrinivasan Shanmugam  * @inst: is used to select which instance of KIQ to use for the invalidation
412ea930000SAlex Sierra  *
413ea930000SAlex Sierra  * Flush the TLB for the requested pasid.
414ea930000SAlex Sierra  */
gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device * adev,uint16_t pasid,uint32_t flush_type,bool all_hub,uint32_t inst)415ea930000SAlex Sierra static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
416ea930000SAlex Sierra 					uint16_t pasid, uint32_t flush_type,
417f87f6864SMukul Joshi 					bool all_hub, uint32_t inst)
418ea930000SAlex Sierra {
419ea930000SAlex Sierra 	int vmid, i;
420ea930000SAlex Sierra 	signed long r;
421ea930000SAlex Sierra 	uint32_t seq;
422ea930000SAlex Sierra 	uint16_t queried_pasid;
423ea930000SAlex Sierra 	bool ret;
424373008bfSDusica Milinkovic 	u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout;
425277bd337SLe Ma 	struct amdgpu_ring *ring = &adev->gfx.kiq[0].ring;
426277bd337SLe Ma 	struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
427ea930000SAlex Sierra 
428ea930000SAlex Sierra 	if (amdgpu_emu_mode == 0 && ring->sched.ready) {
429277bd337SLe Ma 		spin_lock(&adev->gfx.kiq[0].ring_lock);
43036a1707aSAlex Sierra 		/* 2 dwords flush + 8 dwords fence */
43136a1707aSAlex Sierra 		amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size + 8);
432ea930000SAlex Sierra 		kiq->pmf->kiq_invalidate_tlbs(ring,
433ea930000SAlex Sierra 					pasid, flush_type, all_hub);
43404e4e2e9SYintian Tao 		r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
43504e4e2e9SYintian Tao 		if (r) {
43604e4e2e9SYintian Tao 			amdgpu_ring_undo(ring);
437277bd337SLe Ma 			spin_unlock(&adev->gfx.kiq[0].ring_lock);
43804e4e2e9SYintian Tao 			return -ETIME;
43904e4e2e9SYintian Tao 		}
44004e4e2e9SYintian Tao 
441ea930000SAlex Sierra 		amdgpu_ring_commit(ring);
442277bd337SLe Ma 		spin_unlock(&adev->gfx.kiq[0].ring_lock);
443373008bfSDusica Milinkovic 		r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
444ea930000SAlex Sierra 		if (r < 1) {
445aac89168SDennis Li 			dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
446ea930000SAlex Sierra 			return -ETIME;
447ea930000SAlex Sierra 		}
448ea930000SAlex Sierra 
449ea930000SAlex Sierra 		return 0;
450ea930000SAlex Sierra 	}
451ea930000SAlex Sierra 
45268fce5f0SNirmoy Das 	for (vmid = 1; vmid < AMDGPU_NUM_VMID; vmid++) {
453ea930000SAlex Sierra 
454ea930000SAlex Sierra 		ret = gmc_v10_0_get_atc_vmid_pasid_mapping_info(adev, vmid,
455ea930000SAlex Sierra 				&queried_pasid);
456ea930000SAlex Sierra 		if (ret	&& queried_pasid == pasid) {
457ea930000SAlex Sierra 			if (all_hub) {
458d9426c3dSLe Ma 				for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
459ea930000SAlex Sierra 					gmc_v10_0_flush_gpu_tlb(adev, vmid,
460fa34edbeSFelix Kuehling 							i, flush_type);
461ea930000SAlex Sierra 			} else {
462ea930000SAlex Sierra 				gmc_v10_0_flush_gpu_tlb(adev, vmid,
463f4caf584SHawking Zhang 						AMDGPU_GFXHUB(0), flush_type);
464ea930000SAlex Sierra 			}
465b3e73cbfSGraham Sider 			if (!adev->enable_mes)
466ea930000SAlex Sierra 				break;
467ea930000SAlex Sierra 		}
468ea930000SAlex Sierra 	}
469ea930000SAlex Sierra 
470ea930000SAlex Sierra 	return 0;
471ea930000SAlex Sierra }
472ea930000SAlex Sierra 
gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring * ring,unsigned int vmid,uint64_t pd_addr)473f9df67e9SHawking Zhang static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
4748612a435SSrinivasan Shanmugam 					     unsigned int vmid, uint64_t pd_addr)
475f9df67e9SHawking Zhang {
4760530553bSLe Ma 	bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(ring->adev, ring->vm_hub);
4770530553bSLe Ma 	struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
478caa9f483SHuang Rui 	uint32_t req = hub->vmhub_funcs->get_invalidate_req(vmid, 0);
4798612a435SSrinivasan Shanmugam 	unsigned int eng = ring->vm_inv_eng;
480f9df67e9SHawking Zhang 
481f920d1bbSchangzhu 	/*
482f920d1bbSchangzhu 	 * It may lose gpuvm invalidate acknowldege state across power-gating
483f920d1bbSchangzhu 	 * off cycle, add semaphore acquire before invalidation and semaphore
484f920d1bbSchangzhu 	 * release after invalidation to avoid entering power gated state
485f920d1bbSchangzhu 	 * to WA the Issue
486f920d1bbSchangzhu 	 */
487f920d1bbSchangzhu 
488f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
489f271fe18Schangzhu 	if (use_semaphore)
490f920d1bbSchangzhu 		/* a read return value of 1 means semaphore acuqire */
491f920d1bbSchangzhu 		amdgpu_ring_emit_reg_wait(ring,
492af6c5c4fSHuang Rui 					  hub->vm_inv_eng0_sem +
493af6c5c4fSHuang Rui 					  hub->eng_distance * eng, 0x1, 0x1);
494f920d1bbSchangzhu 
495af6c5c4fSHuang Rui 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 +
496af6c5c4fSHuang Rui 			      (hub->ctx_addr_distance * vmid),
497f9df67e9SHawking Zhang 			      lower_32_bits(pd_addr));
498f9df67e9SHawking Zhang 
499af6c5c4fSHuang Rui 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_hi32 +
500af6c5c4fSHuang Rui 			      (hub->ctx_addr_distance * vmid),
501f9df67e9SHawking Zhang 			      upper_32_bits(pd_addr));
502f9df67e9SHawking Zhang 
503af6c5c4fSHuang Rui 	amdgpu_ring_emit_reg_write_reg_wait(ring, hub->vm_inv_eng0_req +
504af6c5c4fSHuang Rui 					    hub->eng_distance * eng,
505af6c5c4fSHuang Rui 					    hub->vm_inv_eng0_ack +
506af6c5c4fSHuang Rui 					    hub->eng_distance * eng,
507589b64a7Schangzhu 					    req, 1 << vmid);
508f9df67e9SHawking Zhang 
509f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
510f271fe18Schangzhu 	if (use_semaphore)
511f920d1bbSchangzhu 		/*
512f920d1bbSchangzhu 		 * add semaphore release after invalidation,
513f920d1bbSchangzhu 		 * write with 0 means semaphore release
514f920d1bbSchangzhu 		 */
515af6c5c4fSHuang Rui 		amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem +
516af6c5c4fSHuang Rui 				      hub->eng_distance * eng, 0);
517f920d1bbSchangzhu 
518f9df67e9SHawking Zhang 	return pd_addr;
519f9df67e9SHawking Zhang }
520f9df67e9SHawking Zhang 
gmc_v10_0_emit_pasid_mapping(struct amdgpu_ring * ring,unsigned int vmid,unsigned int pasid)5218612a435SSrinivasan Shanmugam static void gmc_v10_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned int vmid,
5228612a435SSrinivasan Shanmugam 					 unsigned int pasid)
523f9df67e9SHawking Zhang {
524f9df67e9SHawking Zhang 	struct amdgpu_device *adev = ring->adev;
525f9df67e9SHawking Zhang 	uint32_t reg;
526f9df67e9SHawking Zhang 
52756443402SJack Xiao 	/* MES fw manages IH_VMID_x_LUT updating */
52856443402SJack Xiao 	if (ring->is_mes_queue)
52956443402SJack Xiao 		return;
53056443402SJack Xiao 
531f4caf584SHawking Zhang 	if (ring->vm_hub == AMDGPU_GFXHUB(0))
532f9df67e9SHawking Zhang 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid;
533f9df67e9SHawking Zhang 	else
534f9df67e9SHawking Zhang 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT_MM) + vmid;
535f9df67e9SHawking Zhang 
536f9df67e9SHawking Zhang 	amdgpu_ring_emit_wreg(ring, reg, pasid);
537f9df67e9SHawking Zhang }
538f9df67e9SHawking Zhang 
539f9df67e9SHawking Zhang /*
540f9df67e9SHawking Zhang  * PTE format on NAVI 10:
541f9df67e9SHawking Zhang  * 63:59 reserved
5424005809bSLikun Gao  * 58 reserved and for sienna_cichlid is used for MALL noalloc
5434005809bSLikun Gao  * 57 reserved
544f9df67e9SHawking Zhang  * 56 F
545f9df67e9SHawking Zhang  * 55 L
546f9df67e9SHawking Zhang  * 54 reserved
547f9df67e9SHawking Zhang  * 53:52 SW
548f9df67e9SHawking Zhang  * 51 T
549f9df67e9SHawking Zhang  * 50:48 mtype
550f9df67e9SHawking Zhang  * 47:12 4k physical page base address
551f9df67e9SHawking Zhang  * 11:7 fragment
552f9df67e9SHawking Zhang  * 6 write
553f9df67e9SHawking Zhang  * 5 read
554f9df67e9SHawking Zhang  * 4 exe
555f9df67e9SHawking Zhang  * 3 Z
556f9df67e9SHawking Zhang  * 2 snooped
557f9df67e9SHawking Zhang  * 1 system
558f9df67e9SHawking Zhang  * 0 valid
559f9df67e9SHawking Zhang  *
560f9df67e9SHawking Zhang  * PDE format on NAVI 10:
561f9df67e9SHawking Zhang  * 63:59 block fragment size
562f9df67e9SHawking Zhang  * 58:55 reserved
563f9df67e9SHawking Zhang  * 54 P
564f9df67e9SHawking Zhang  * 53:48 reserved
565f9df67e9SHawking Zhang  * 47:6 physical base address of PD or PTE
566f9df67e9SHawking Zhang  * 5:3 reserved
567f9df67e9SHawking Zhang  * 2 C
568f9df67e9SHawking Zhang  * 1 system
569f9df67e9SHawking Zhang  * 0 valid
570f9df67e9SHawking Zhang  */
57171776b6dSChristian König 
gmc_v10_0_map_mtype(struct amdgpu_device * adev,uint32_t flags)57271776b6dSChristian König static uint64_t gmc_v10_0_map_mtype(struct amdgpu_device *adev, uint32_t flags)
573f9df67e9SHawking Zhang {
57471776b6dSChristian König 	switch (flags) {
575f9df67e9SHawking Zhang 	case AMDGPU_VM_MTYPE_DEFAULT:
57671776b6dSChristian König 		return AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
577f9df67e9SHawking Zhang 	case AMDGPU_VM_MTYPE_NC:
57871776b6dSChristian König 		return AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
579f9df67e9SHawking Zhang 	case AMDGPU_VM_MTYPE_WC:
58071776b6dSChristian König 		return AMDGPU_PTE_MTYPE_NV10(MTYPE_WC);
581f9df67e9SHawking Zhang 	case AMDGPU_VM_MTYPE_CC:
58271776b6dSChristian König 		return AMDGPU_PTE_MTYPE_NV10(MTYPE_CC);
583f9df67e9SHawking Zhang 	case AMDGPU_VM_MTYPE_UC:
58471776b6dSChristian König 		return AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
585f9df67e9SHawking Zhang 	default:
58671776b6dSChristian König 		return AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
587f9df67e9SHawking Zhang 	}
588f9df67e9SHawking Zhang }
589f9df67e9SHawking Zhang 
gmc_v10_0_get_vm_pde(struct amdgpu_device * adev,int level,uint64_t * addr,uint64_t * flags)590f9df67e9SHawking Zhang static void gmc_v10_0_get_vm_pde(struct amdgpu_device *adev, int level,
591f9df67e9SHawking Zhang 				 uint64_t *addr, uint64_t *flags)
592f9df67e9SHawking Zhang {
593f9df67e9SHawking Zhang 	if (!(*flags & AMDGPU_PDE_PTE) && !(*flags & AMDGPU_PTE_SYSTEM))
5940ca565abSOak Zeng 		*addr = amdgpu_gmc_vram_mc2pa(adev, *addr);
595f9df67e9SHawking Zhang 	BUG_ON(*addr & 0xFFFF00000000003FULL);
596f9df67e9SHawking Zhang 
597f9df67e9SHawking Zhang 	if (!adev->gmc.translate_further)
598f9df67e9SHawking Zhang 		return;
599f9df67e9SHawking Zhang 
600f9df67e9SHawking Zhang 	if (level == AMDGPU_VM_PDB1) {
601f9df67e9SHawking Zhang 		/* Set the block fragment size */
602f9df67e9SHawking Zhang 		if (!(*flags & AMDGPU_PDE_PTE))
603f9df67e9SHawking Zhang 			*flags |= AMDGPU_PDE_BFS(0x9);
604f9df67e9SHawking Zhang 
605f9df67e9SHawking Zhang 	} else if (level == AMDGPU_VM_PDB0) {
606f9df67e9SHawking Zhang 		if (*flags & AMDGPU_PDE_PTE)
607f9df67e9SHawking Zhang 			*flags &= ~AMDGPU_PDE_PTE;
608f9df67e9SHawking Zhang 		else
609f9df67e9SHawking Zhang 			*flags |= AMDGPU_PTE_TF;
610f9df67e9SHawking Zhang 	}
611f9df67e9SHawking Zhang }
612f9df67e9SHawking Zhang 
gmc_v10_0_get_vm_pte(struct amdgpu_device * adev,struct amdgpu_bo_va_mapping * mapping,uint64_t * flags)613cbfae36cSChristian König static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
614cbfae36cSChristian König 				 struct amdgpu_bo_va_mapping *mapping,
615cbfae36cSChristian König 				 uint64_t *flags)
616cbfae36cSChristian König {
617d1a372afSFelix Kuehling 	struct amdgpu_bo *bo = mapping->bo_va->base.bo;
618d1a372afSFelix Kuehling 
619cbfae36cSChristian König 	*flags &= ~AMDGPU_PTE_EXECUTABLE;
620cbfae36cSChristian König 	*flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
621cbfae36cSChristian König 
622cbfae36cSChristian König 	*flags &= ~AMDGPU_PTE_MTYPE_NV10_MASK;
623cbfae36cSChristian König 	*flags |= (mapping->flags & AMDGPU_PTE_MTYPE_NV10_MASK);
624cbfae36cSChristian König 
625b6c65a2cSChristian König 	*flags &= ~AMDGPU_PTE_NOALLOC;
626b6c65a2cSChristian König 	*flags |= (mapping->flags & AMDGPU_PTE_NOALLOC);
627b6c65a2cSChristian König 
628cbfae36cSChristian König 	if (mapping->flags & AMDGPU_PTE_PRT) {
629cbfae36cSChristian König 		*flags |= AMDGPU_PTE_PRT;
630cbfae36cSChristian König 		*flags |= AMDGPU_PTE_SNOOPED;
631cbfae36cSChristian König 		*flags |= AMDGPU_PTE_LOG;
632cbfae36cSChristian König 		*flags |= AMDGPU_PTE_SYSTEM;
633cbfae36cSChristian König 		*flags &= ~AMDGPU_PTE_VALID;
634cbfae36cSChristian König 	}
635d1a372afSFelix Kuehling 
636d1a372afSFelix Kuehling 	if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
637d1a372afSFelix Kuehling 			       AMDGPU_GEM_CREATE_UNCACHED))
638d1a372afSFelix Kuehling 		*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
639d1a372afSFelix Kuehling 			 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
640cbfae36cSChristian König }
641cbfae36cSChristian König 
gmc_v10_0_get_vbios_fb_size(struct amdgpu_device * adev)6428612a435SSrinivasan Shanmugam static unsigned int gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev)
6437348c20aSAlex Deucher {
6447348c20aSAlex Deucher 	u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL);
6458612a435SSrinivasan Shanmugam 	unsigned int size;
6467348c20aSAlex Deucher 
6477348c20aSAlex Deucher 	if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) {
6487348c20aSAlex Deucher 		size = AMDGPU_VBIOS_VGA_ALLOCATION;
6497348c20aSAlex Deucher 	} else {
6507348c20aSAlex Deucher 		u32 viewport;
6517348c20aSAlex Deucher 		u32 pitch;
6527348c20aSAlex Deucher 
6537348c20aSAlex Deucher 		viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION);
6547348c20aSAlex Deucher 		pitch = RREG32_SOC15(DCE, 0, mmHUBPREQ0_DCSURF_SURFACE_PITCH);
6557348c20aSAlex Deucher 		size = (REG_GET_FIELD(viewport,
6567348c20aSAlex Deucher 					HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) *
6577348c20aSAlex Deucher 				REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) *
6587348c20aSAlex Deucher 				4);
6597348c20aSAlex Deucher 	}
6607348c20aSAlex Deucher 
6617348c20aSAlex Deucher 	return size;
6627348c20aSAlex Deucher }
6637348c20aSAlex Deucher 
664f9df67e9SHawking Zhang static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = {
665f9df67e9SHawking Zhang 	.flush_gpu_tlb = gmc_v10_0_flush_gpu_tlb,
666ea930000SAlex Sierra 	.flush_gpu_tlb_pasid = gmc_v10_0_flush_gpu_tlb_pasid,
667f9df67e9SHawking Zhang 	.emit_flush_gpu_tlb = gmc_v10_0_emit_flush_gpu_tlb,
668f9df67e9SHawking Zhang 	.emit_pasid_mapping = gmc_v10_0_emit_pasid_mapping,
66971776b6dSChristian König 	.map_mtype = gmc_v10_0_map_mtype,
670cbfae36cSChristian König 	.get_vm_pde = gmc_v10_0_get_vm_pde,
6717348c20aSAlex Deucher 	.get_vm_pte = gmc_v10_0_get_vm_pte,
6727348c20aSAlex Deucher 	.get_vbios_fb_size = gmc_v10_0_get_vbios_fb_size,
673f9df67e9SHawking Zhang };
674f9df67e9SHawking Zhang 
gmc_v10_0_set_gmc_funcs(struct amdgpu_device * adev)675f9df67e9SHawking Zhang static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev)
676f9df67e9SHawking Zhang {
677f9df67e9SHawking Zhang 	if (adev->gmc.gmc_funcs == NULL)
678f9df67e9SHawking Zhang 		adev->gmc.gmc_funcs = &gmc_v10_0_gmc_funcs;
679f9df67e9SHawking Zhang }
680f9df67e9SHawking Zhang 
gmc_v10_0_set_umc_funcs(struct amdgpu_device * adev)68101eee24fSJohn Clements static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev)
68201eee24fSJohn Clements {
6831d789535SAlex Deucher 	switch (adev->ip_versions[UMC_HWIP][0]) {
6845db9d065SAlex Deucher 	case IP_VERSION(8, 7, 0):
68501eee24fSJohn Clements 		adev->umc.max_ras_err_cnt_per_query = UMC_V8_7_TOTAL_CHANNEL_NUM;
68601eee24fSJohn Clements 		adev->umc.channel_inst_num = UMC_V8_7_CHANNEL_INSTANCE_NUM;
68701eee24fSJohn Clements 		adev->umc.umc_inst_num = UMC_V8_7_UMC_INSTANCE_NUM;
68801eee24fSJohn Clements 		adev->umc.channel_offs = UMC_V8_7_PER_CHANNEL_OFFSET_SIENNA;
689e69c7857STao Zhou 		adev->umc.retire_unit = 1;
69001eee24fSJohn Clements 		adev->umc.channel_idx_tbl = &umc_v8_7_channel_idx_tbl[0][0];
691efe17d5aSyipechai 		adev->umc.ras = &umc_v8_7_ras;
69201eee24fSJohn Clements 		break;
69301eee24fSJohn Clements 	default:
69401eee24fSJohn Clements 		break;
69501eee24fSJohn Clements 	}
696efe17d5aSyipechai }
6979fb1506eSOak Zeng 
gmc_v10_0_set_mmhub_funcs(struct amdgpu_device * adev)6989fb1506eSOak Zeng static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev)
6999fb1506eSOak Zeng {
7001d789535SAlex Deucher 	switch (adev->ip_versions[MMHUB_HWIP][0]) {
7015db9d065SAlex Deucher 	case IP_VERSION(2, 3, 0):
7025db9d065SAlex Deucher 	case IP_VERSION(2, 4, 0):
703a142606dSYifan Zhang 	case IP_VERSION(2, 4, 1):
7044d8d75a4SHuang Rui 		adev->mmhub.funcs = &mmhub_v2_3_funcs;
7054d8d75a4SHuang Rui 		break;
7064d8d75a4SHuang Rui 	default:
7079fb1506eSOak Zeng 		adev->mmhub.funcs = &mmhub_v2_0_funcs;
7084d8d75a4SHuang Rui 		break;
7094d8d75a4SHuang Rui 	}
7109fb1506eSOak Zeng }
7119fb1506eSOak Zeng 
gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device * adev)7128ffff9b4SOak Zeng static void gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device *adev)
7138ffff9b4SOak Zeng {
7141d789535SAlex Deucher 	switch (adev->ip_versions[GC_HWIP][0]) {
7155db9d065SAlex Deucher 	case IP_VERSION(10, 3, 0):
7165db9d065SAlex Deucher 	case IP_VERSION(10, 3, 2):
7175db9d065SAlex Deucher 	case IP_VERSION(10, 3, 1):
7185db9d065SAlex Deucher 	case IP_VERSION(10, 3, 4):
7195db9d065SAlex Deucher 	case IP_VERSION(10, 3, 5):
720a142606dSYifan Zhang 	case IP_VERSION(10, 3, 6):
7215db9d065SAlex Deucher 	case IP_VERSION(10, 3, 3):
72297437f47SPrike Liang 	case IP_VERSION(10, 3, 7):
7238ffff9b4SOak Zeng 		adev->gfxhub.funcs = &gfxhub_v2_1_funcs;
7248ffff9b4SOak Zeng 		break;
7258ffff9b4SOak Zeng 	default:
7268ffff9b4SOak Zeng 		adev->gfxhub.funcs = &gfxhub_v2_0_funcs;
7278ffff9b4SOak Zeng 		break;
7288ffff9b4SOak Zeng 	}
7298ffff9b4SOak Zeng }
7308ffff9b4SOak Zeng 
7318ffff9b4SOak Zeng 
gmc_v10_0_early_init(void * handle)732f9df67e9SHawking Zhang static int gmc_v10_0_early_init(void *handle)
733f9df67e9SHawking Zhang {
734f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
735f9df67e9SHawking Zhang 
7369fb1506eSOak Zeng 	gmc_v10_0_set_mmhub_funcs(adev);
7378ffff9b4SOak Zeng 	gmc_v10_0_set_gfxhub_funcs(adev);
738f9df67e9SHawking Zhang 	gmc_v10_0_set_gmc_funcs(adev);
739f9df67e9SHawking Zhang 	gmc_v10_0_set_irq_funcs(adev);
74001eee24fSJohn Clements 	gmc_v10_0_set_umc_funcs(adev);
741f9df67e9SHawking Zhang 
742f9df67e9SHawking Zhang 	adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
743f9df67e9SHawking Zhang 	adev->gmc.shared_aperture_end =
744f9df67e9SHawking Zhang 		adev->gmc.shared_aperture_start + (4ULL << 30) - 1;
745f9df67e9SHawking Zhang 	adev->gmc.private_aperture_start = 0x1000000000000000ULL;
746f9df67e9SHawking Zhang 	adev->gmc.private_aperture_end =
747f9df67e9SHawking Zhang 		adev->gmc.private_aperture_start + (4ULL << 30) - 1;
748e77673d1SMukul Joshi 	adev->gmc.noretry_flags = AMDGPU_VM_NORETRY_FLAGS_TF;
749f9df67e9SHawking Zhang 
750f9df67e9SHawking Zhang 	return 0;
751f9df67e9SHawking Zhang }
752f9df67e9SHawking Zhang 
gmc_v10_0_late_init(void * handle)753f9df67e9SHawking Zhang static int gmc_v10_0_late_init(void *handle)
754f9df67e9SHawking Zhang {
755f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
7565677c520SAlex Deucher 	int r;
757f9df67e9SHawking Zhang 
7585677c520SAlex Deucher 	r = amdgpu_gmc_allocate_vm_inv_eng(adev);
7595677c520SAlex Deucher 	if (r)
7605677c520SAlex Deucher 		return r;
761f9df67e9SHawking Zhang 
7620ad7a64dSJohn Clements 	r = amdgpu_gmc_ras_late_init(adev);
7630ad7a64dSJohn Clements 	if (r)
7640ad7a64dSJohn Clements 		return r;
7650ad7a64dSJohn Clements 
766f9df67e9SHawking Zhang 	return amdgpu_irq_get(adev, &adev->gmc.vm_fault, 0);
767f9df67e9SHawking Zhang }
768f9df67e9SHawking Zhang 
gmc_v10_0_vram_gtt_location(struct amdgpu_device * adev,struct amdgpu_gmc * mc)769f9df67e9SHawking Zhang static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev,
770f9df67e9SHawking Zhang 					struct amdgpu_gmc *mc)
771f9df67e9SHawking Zhang {
772f9df67e9SHawking Zhang 	u64 base = 0;
773f9df67e9SHawking Zhang 
7748ffff9b4SOak Zeng 	base = adev->gfxhub.funcs->get_fb_location(adev);
775f9df67e9SHawking Zhang 
776fdb8483bSJohn Clements 	/* add the xgmi offset of the physical node */
777fdb8483bSJohn Clements 	base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
778fdb8483bSJohn Clements 
779f9df67e9SHawking Zhang 	amdgpu_gmc_vram_location(adev, &adev->gmc, base);
780f9df67e9SHawking Zhang 	amdgpu_gmc_gart_location(adev, mc);
78199698b51SAlex Deucher 	amdgpu_gmc_agp_location(adev, mc);
782f9df67e9SHawking Zhang 
783f9df67e9SHawking Zhang 	/* base offset of vram pages */
7848ffff9b4SOak Zeng 	adev->vm_manager.vram_base_offset = adev->gfxhub.funcs->get_mc_fb_offset(adev);
785fdb8483bSJohn Clements 
786fdb8483bSJohn Clements 	/* add the xgmi offset of the physical node */
787fdb8483bSJohn Clements 	adev->vm_manager.vram_base_offset +=
788fdb8483bSJohn Clements 		adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
789f9df67e9SHawking Zhang }
790f9df67e9SHawking Zhang 
791f9df67e9SHawking Zhang /**
792f9df67e9SHawking Zhang  * gmc_v10_0_mc_init - initialize the memory controller driver params
793f9df67e9SHawking Zhang  *
794f9df67e9SHawking Zhang  * @adev: amdgpu_device pointer
795f9df67e9SHawking Zhang  *
796f9df67e9SHawking Zhang  * Look up the amount of vram, vram width, and decide how to place
797f9df67e9SHawking Zhang  * vram and gart within the GPU's physical address space.
798f9df67e9SHawking Zhang  * Returns 0 for success.
799f9df67e9SHawking Zhang  */
gmc_v10_0_mc_init(struct amdgpu_device * adev)800f9df67e9SHawking Zhang static int gmc_v10_0_mc_init(struct amdgpu_device *adev)
801f9df67e9SHawking Zhang {
80278b7dfd9SAlan Swanson 	int r;
803f9df67e9SHawking Zhang 
804f9df67e9SHawking Zhang 	/* size in MB on si */
805f9df67e9SHawking Zhang 	adev->gmc.mc_vram_size =
806bebc0762SHawking Zhang 		adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
807f9df67e9SHawking Zhang 	adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
80878b7dfd9SAlan Swanson 
80978b7dfd9SAlan Swanson 	if (!(adev->flags & AMD_IS_APU)) {
81078b7dfd9SAlan Swanson 		r = amdgpu_device_resize_fb_bar(adev);
81178b7dfd9SAlan Swanson 		if (r)
81278b7dfd9SAlan Swanson 			return r;
81378b7dfd9SAlan Swanson 	}
81478b7dfd9SAlan Swanson 	adev->gmc.aper_base = pci_resource_start(adev->pdev, 0);
81578b7dfd9SAlan Swanson 	adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
816f9df67e9SHawking Zhang 
8176405e627SHuang Rui #ifdef CONFIG_X86_64
818b818a5d3SAlex Deucher 	if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) {
8196405e627SHuang Rui 		adev->gmc.aper_base = adev->gfxhub.funcs->get_mc_fb_offset(adev);
8206405e627SHuang Rui 		adev->gmc.aper_size = adev->gmc.real_vram_size;
8216405e627SHuang Rui 	}
8226405e627SHuang Rui #endif
8236405e627SHuang Rui 
82478b7dfd9SAlan Swanson 	adev->gmc.visible_vram_size = adev->gmc.aper_size;
825f9df67e9SHawking Zhang 
826f9df67e9SHawking Zhang 	/* set the gart size */
82788c775bbSAlex Deucher 	if (amdgpu_gart_size == -1) {
82888c775bbSAlex Deucher 		switch (adev->ip_versions[GC_HWIP][0]) {
82988c775bbSAlex Deucher 		default:
830f9df67e9SHawking Zhang 			adev->gmc.gart_size = 512ULL << 20;
83188c775bbSAlex Deucher 			break;
83288c775bbSAlex Deucher 		case IP_VERSION(10, 3, 1):   /* DCE SG support */
83388c775bbSAlex Deucher 		case IP_VERSION(10, 3, 3):   /* DCE SG support */
83488c775bbSAlex Deucher 		case IP_VERSION(10, 3, 6):   /* DCE SG support */
83588c775bbSAlex Deucher 		case IP_VERSION(10, 3, 7):   /* DCE SG support */
83688c775bbSAlex Deucher 			adev->gmc.gart_size = 1024ULL << 20;
83788c775bbSAlex Deucher 			break;
83888c775bbSAlex Deucher 		}
83988c775bbSAlex Deucher 	} else {
840f9df67e9SHawking Zhang 		adev->gmc.gart_size = (u64)amdgpu_gart_size << 20;
84188c775bbSAlex Deucher 	}
842f9df67e9SHawking Zhang 
843f9df67e9SHawking Zhang 	gmc_v10_0_vram_gtt_location(adev, &adev->gmc);
844f9df67e9SHawking Zhang 
845f9df67e9SHawking Zhang 	return 0;
846f9df67e9SHawking Zhang }
847f9df67e9SHawking Zhang 
gmc_v10_0_gart_init(struct amdgpu_device * adev)848f9df67e9SHawking Zhang static int gmc_v10_0_gart_init(struct amdgpu_device *adev)
849f9df67e9SHawking Zhang {
850f9df67e9SHawking Zhang 	int r;
851f9df67e9SHawking Zhang 
852f9df67e9SHawking Zhang 	if (adev->gart.bo) {
853f9df67e9SHawking Zhang 		WARN(1, "NAVI10 PCIE GART already initialized\n");
854f9df67e9SHawking Zhang 		return 0;
855f9df67e9SHawking Zhang 	}
856f9df67e9SHawking Zhang 
857f9df67e9SHawking Zhang 	/* Initialize common gart structure */
858f9df67e9SHawking Zhang 	r = amdgpu_gart_init(adev);
859f9df67e9SHawking Zhang 	if (r)
860f9df67e9SHawking Zhang 		return r;
861f9df67e9SHawking Zhang 
862f9df67e9SHawking Zhang 	adev->gart.table_size = adev->gart.num_gpu_pages * 8;
863f9df67e9SHawking Zhang 	adev->gart.gart_pte_flags = AMDGPU_PTE_MTYPE_NV10(MTYPE_UC) |
864f9df67e9SHawking Zhang 				 AMDGPU_PTE_EXECUTABLE;
865f9df67e9SHawking Zhang 
866f9df67e9SHawking Zhang 	return amdgpu_gart_table_vram_alloc(adev);
867f9df67e9SHawking Zhang }
868f9df67e9SHawking Zhang 
gmc_v10_0_sw_init(void * handle)869f9df67e9SHawking Zhang static int gmc_v10_0_sw_init(void *handle)
870f9df67e9SHawking Zhang {
871ad02e08eSOri Messinger 	int r, vram_width = 0, vram_type = 0, vram_vendor = 0;
872f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
873f9df67e9SHawking Zhang 
8748ffff9b4SOak Zeng 	adev->gfxhub.funcs->init(adev);
8750b3df16bSLikun Gao 
8769fb1506eSOak Zeng 	adev->mmhub.funcs->init(adev);
877f9df67e9SHawking Zhang 
878f9df67e9SHawking Zhang 	spin_lock_init(&adev->gmc.invalidate_lock);
879f9df67e9SHawking Zhang 
8806405e627SHuang Rui 	if ((adev->flags & AMD_IS_APU) && amdgpu_emu_mode == 1) {
8816405e627SHuang Rui 		adev->gmc.vram_type = AMDGPU_VRAM_TYPE_DDR4;
8826405e627SHuang Rui 		adev->gmc.vram_width = 64;
8836405e627SHuang Rui 	} else if (amdgpu_emu_mode == 1) {
8840b3df16bSLikun Gao 		adev->gmc.vram_type = AMDGPU_VRAM_TYPE_GDDR6;
8850b3df16bSLikun Gao 		adev->gmc.vram_width = 1 * 128; /* numchan * chansize */
8860b3df16bSLikun Gao 	} else {
887ad02e08eSOri Messinger 		r = amdgpu_atomfirmware_get_vram_info(adev,
888ad02e08eSOri Messinger 				&vram_width, &vram_type, &vram_vendor);
889631cdbd2SAlex Deucher 		adev->gmc.vram_width = vram_width;
890631cdbd2SAlex Deucher 
891631cdbd2SAlex Deucher 		adev->gmc.vram_type = vram_type;
892ad02e08eSOri Messinger 		adev->gmc.vram_vendor = vram_vendor;
8930b3df16bSLikun Gao 	}
8940b3df16bSLikun Gao 
8951d789535SAlex Deucher 	switch (adev->ip_versions[GC_HWIP][0]) {
896053d35deSAlex Deucher 	case IP_VERSION(10, 3, 0):
897053d35deSAlex Deucher 		adev->gmc.mall_size = 128 * 1024 * 1024;
898053d35deSAlex Deucher 		break;
899053d35deSAlex Deucher 	case IP_VERSION(10, 3, 2):
900053d35deSAlex Deucher 		adev->gmc.mall_size = 96 * 1024 * 1024;
901053d35deSAlex Deucher 		break;
902053d35deSAlex Deucher 	case IP_VERSION(10, 3, 4):
903053d35deSAlex Deucher 		adev->gmc.mall_size = 32 * 1024 * 1024;
904053d35deSAlex Deucher 		break;
905053d35deSAlex Deucher 	case IP_VERSION(10, 3, 5):
906053d35deSAlex Deucher 		adev->gmc.mall_size = 16 * 1024 * 1024;
907053d35deSAlex Deucher 		break;
908053d35deSAlex Deucher 	default:
909053d35deSAlex Deucher 		adev->gmc.mall_size = 0;
910053d35deSAlex Deucher 		break;
911053d35deSAlex Deucher 	}
912053d35deSAlex Deucher 
913053d35deSAlex Deucher 	switch (adev->ip_versions[GC_HWIP][0]) {
9145db9d065SAlex Deucher 	case IP_VERSION(10, 1, 10):
9155db9d065SAlex Deucher 	case IP_VERSION(10, 1, 1):
9165db9d065SAlex Deucher 	case IP_VERSION(10, 1, 2):
9175db9d065SAlex Deucher 	case IP_VERSION(10, 1, 3):
918f9ed188dSLang Yu 	case IP_VERSION(10, 1, 4):
9195db9d065SAlex Deucher 	case IP_VERSION(10, 3, 0):
9205db9d065SAlex Deucher 	case IP_VERSION(10, 3, 2):
9215db9d065SAlex Deucher 	case IP_VERSION(10, 3, 1):
9225db9d065SAlex Deucher 	case IP_VERSION(10, 3, 4):
9235db9d065SAlex Deucher 	case IP_VERSION(10, 3, 5):
924a142606dSYifan Zhang 	case IP_VERSION(10, 3, 6):
9255db9d065SAlex Deucher 	case IP_VERSION(10, 3, 3):
92697437f47SPrike Liang 	case IP_VERSION(10, 3, 7):
927d9426c3dSLe Ma 		set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
928d9426c3dSLe Ma 		set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
929f9df67e9SHawking Zhang 		/*
930f9df67e9SHawking Zhang 		 * To fulfill 4-level page support,
9314a0e815fSXiaojie Yuan 		 * vm size is 256TB (48bit), maximum size of Navi10/Navi14/Navi12,
932f9df67e9SHawking Zhang 		 * block size 512 (9bit)
933f9df67e9SHawking Zhang 		 */
934f9df67e9SHawking Zhang 		amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
935f9df67e9SHawking Zhang 		break;
936f9df67e9SHawking Zhang 	default:
937f9df67e9SHawking Zhang 		break;
938f9df67e9SHawking Zhang 	}
939f9df67e9SHawking Zhang 
940f9df67e9SHawking Zhang 	/* This interrupt is VMC page fault.*/
941f9df67e9SHawking Zhang 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC,
942f9df67e9SHawking Zhang 			      VMC_1_0__SRCID__VM_FAULT,
943f9df67e9SHawking Zhang 			      &adev->gmc.vm_fault);
9445021e9a8SNirmoy Das 
9455021e9a8SNirmoy Das 	if (r)
9465021e9a8SNirmoy Das 		return r;
9475021e9a8SNirmoy Das 
948f9df67e9SHawking Zhang 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_UTCL2,
949f9df67e9SHawking Zhang 			      UTCL2_1_0__SRCID__FAULT,
950f9df67e9SHawking Zhang 			      &adev->gmc.vm_fault);
951f9df67e9SHawking Zhang 	if (r)
952f9df67e9SHawking Zhang 		return r;
953f9df67e9SHawking Zhang 
95401eee24fSJohn Clements 	if (!amdgpu_sriov_vf(adev)) {
95501eee24fSJohn Clements 		/* interrupt sent to DF. */
95601eee24fSJohn Clements 		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DF, 0,
95701eee24fSJohn Clements 				      &adev->gmc.ecc_irq);
95801eee24fSJohn Clements 		if (r)
95901eee24fSJohn Clements 			return r;
96001eee24fSJohn Clements 	}
96101eee24fSJohn Clements 
962f9df67e9SHawking Zhang 	/*
963f9df67e9SHawking Zhang 	 * Set the internal MC address mask This is the max address of the GPU's
964f9df67e9SHawking Zhang 	 * internal address space.
965f9df67e9SHawking Zhang 	 */
966f9df67e9SHawking Zhang 	adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
967f9df67e9SHawking Zhang 
968244511f3SChristoph Hellwig 	r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
969f9df67e9SHawking Zhang 	if (r) {
970e2710187SSrinivasan Shanmugam 		dev_warn(adev->dev, "amdgpu: No suitable DMA available.\n");
971244511f3SChristoph Hellwig 		return r;
972f9df67e9SHawking Zhang 	}
973f9df67e9SHawking Zhang 
9743616d49dSAaron Liu 	adev->need_swiotlb = drm_need_swiotlb(44);
9753616d49dSAaron Liu 
976f9df67e9SHawking Zhang 	r = gmc_v10_0_mc_init(adev);
977f9df67e9SHawking Zhang 	if (r)
978f9df67e9SHawking Zhang 		return r;
979f9df67e9SHawking Zhang 
9807348c20aSAlex Deucher 	amdgpu_gmc_get_vbios_allocations(adev);
981f9df67e9SHawking Zhang 
982f9df67e9SHawking Zhang 	/* Memory manager */
983f9df67e9SHawking Zhang 	r = amdgpu_bo_init(adev);
984f9df67e9SHawking Zhang 	if (r)
985f9df67e9SHawking Zhang 		return r;
986f9df67e9SHawking Zhang 
987f9df67e9SHawking Zhang 	r = gmc_v10_0_gart_init(adev);
988f9df67e9SHawking Zhang 	if (r)
989f9df67e9SHawking Zhang 		return r;
990f9df67e9SHawking Zhang 
991f9df67e9SHawking Zhang 	/*
992f9df67e9SHawking Zhang 	 * number of VMs
993f9df67e9SHawking Zhang 	 * VMID 0 is reserved for System
994f9df67e9SHawking Zhang 	 * amdgpu graphics/compute will use VMIDs 1-7
995f9df67e9SHawking Zhang 	 * amdkfd will use VMIDs 8-15
996f9df67e9SHawking Zhang 	 */
99740111ec2SFelix Kuehling 	adev->vm_manager.first_kfd_vmid = 8;
998f9df67e9SHawking Zhang 
999f9df67e9SHawking Zhang 	amdgpu_vm_manager_init(adev);
1000f9df67e9SHawking Zhang 
1001a6dcf9a7SHawking Zhang 	r = amdgpu_gmc_ras_sw_init(adev);
1002a6dcf9a7SHawking Zhang 	if (r)
1003a6dcf9a7SHawking Zhang 		return r;
1004a6dcf9a7SHawking Zhang 
1005f9df67e9SHawking Zhang 	return 0;
1006f9df67e9SHawking Zhang }
1007f9df67e9SHawking Zhang 
1008f9df67e9SHawking Zhang /**
10092cce318cSLee Jones  * gmc_v10_0_gart_fini - vm fini callback
1010f9df67e9SHawking Zhang  *
1011f9df67e9SHawking Zhang  * @adev: amdgpu_device pointer
1012f9df67e9SHawking Zhang  *
1013f9df67e9SHawking Zhang  * Tears down the driver GART/VM setup (CIK).
1014f9df67e9SHawking Zhang  */
gmc_v10_0_gart_fini(struct amdgpu_device * adev)1015f9df67e9SHawking Zhang static void gmc_v10_0_gart_fini(struct amdgpu_device *adev)
1016f9df67e9SHawking Zhang {
1017f9df67e9SHawking Zhang 	amdgpu_gart_table_vram_free(adev);
1018f9df67e9SHawking Zhang }
1019f9df67e9SHawking Zhang 
gmc_v10_0_sw_fini(void * handle)1020f9df67e9SHawking Zhang static int gmc_v10_0_sw_fini(void *handle)
1021f9df67e9SHawking Zhang {
1022f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1023f9df67e9SHawking Zhang 
1024f9df67e9SHawking Zhang 	amdgpu_vm_manager_fini(adev);
1025f9df67e9SHawking Zhang 	gmc_v10_0_gart_fini(adev);
1026f9df67e9SHawking Zhang 	amdgpu_gem_force_release(adev);
1027f9df67e9SHawking Zhang 	amdgpu_bo_fini(adev);
1028f9df67e9SHawking Zhang 
1029f9df67e9SHawking Zhang 	return 0;
1030f9df67e9SHawking Zhang }
1031f9df67e9SHawking Zhang 
gmc_v10_0_init_golden_registers(struct amdgpu_device * adev)1032f9df67e9SHawking Zhang static void gmc_v10_0_init_golden_registers(struct amdgpu_device *adev)
1033f9df67e9SHawking Zhang {
1034f9df67e9SHawking Zhang }
1035f9df67e9SHawking Zhang 
1036f9df67e9SHawking Zhang /**
1037f9df67e9SHawking Zhang  * gmc_v10_0_gart_enable - gart enable
1038f9df67e9SHawking Zhang  *
1039f9df67e9SHawking Zhang  * @adev: amdgpu_device pointer
1040f9df67e9SHawking Zhang  */
gmc_v10_0_gart_enable(struct amdgpu_device * adev)1041f9df67e9SHawking Zhang static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)
1042f9df67e9SHawking Zhang {
1043f9df67e9SHawking Zhang 	int r;
1044f9df67e9SHawking Zhang 	bool value;
1045f9df67e9SHawking Zhang 
1046f9df67e9SHawking Zhang 	if (adev->gart.bo == NULL) {
1047f9df67e9SHawking Zhang 		dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
1048f9df67e9SHawking Zhang 		return -EINVAL;
1049f9df67e9SHawking Zhang 	}
1050f9df67e9SHawking Zhang 
10511b08dfb8SChristian König 	amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
1052d5d29009SAlex Deucher 
1053d5d29009SAlex Deucher 	if (!adev->in_s0ix) {
10548ffff9b4SOak Zeng 		r = adev->gfxhub.funcs->gart_enable(adev);
1055f9df67e9SHawking Zhang 		if (r)
1056f9df67e9SHawking Zhang 			return r;
1057d5d29009SAlex Deucher 	}
1058f9df67e9SHawking Zhang 
10599fb1506eSOak Zeng 	r = adev->mmhub.funcs->gart_enable(adev);
1060f9df67e9SHawking Zhang 	if (r)
1061f9df67e9SHawking Zhang 		return r;
1062f9df67e9SHawking Zhang 
1063bf087285SLikun Gao 	adev->hdp.funcs->init_registers(adev);
1064f9df67e9SHawking Zhang 
1065f9df67e9SHawking Zhang 	/* Flush HDP after it is initialized */
1066bf087285SLikun Gao 	adev->hdp.funcs->flush_hdp(adev, NULL);
1067f9df67e9SHawking Zhang 
1068f9df67e9SHawking Zhang 	value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?
1069f9df67e9SHawking Zhang 		false : true;
1070f9df67e9SHawking Zhang 
1071d5d29009SAlex Deucher 	if (!adev->in_s0ix)
10728ffff9b4SOak Zeng 		adev->gfxhub.funcs->set_fault_enable_default(adev, value);
10739fb1506eSOak Zeng 	adev->mmhub.funcs->set_fault_enable_default(adev, value);
1074f4caf584SHawking Zhang 	gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB0(0), 0);
1075d5d29009SAlex Deucher 	if (!adev->in_s0ix)
1076f4caf584SHawking Zhang 		gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
1077f9df67e9SHawking Zhang 
1078f9df67e9SHawking Zhang 	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
10798612a435SSrinivasan Shanmugam 		 (unsigned int)(adev->gmc.gart_size >> 20),
1080f9df67e9SHawking Zhang 		 (unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
1081f9df67e9SHawking Zhang 
1082f9df67e9SHawking Zhang 	return 0;
1083f9df67e9SHawking Zhang }
1084f9df67e9SHawking Zhang 
gmc_v10_0_hw_init(void * handle)1085f9df67e9SHawking Zhang static int gmc_v10_0_hw_init(void *handle)
1086f9df67e9SHawking Zhang {
1087f9df67e9SHawking Zhang 	int r;
1088f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1089f9df67e9SHawking Zhang 
1090f9df67e9SHawking Zhang 	/* The sequence of these two function calls matters.*/
1091f9df67e9SHawking Zhang 	gmc_v10_0_init_golden_registers(adev);
1092f9df67e9SHawking Zhang 
1093b3accd6fSXiaomeng Hou 	/*
1094b3accd6fSXiaomeng Hou 	 * harvestable groups in gc_utcl2 need to be programmed before any GFX block
1095b3accd6fSXiaomeng Hou 	 * register setup within GMC, or else system hang when harvesting SA.
1096b3accd6fSXiaomeng Hou 	 */
1097d5d29009SAlex Deucher 	if (!adev->in_s0ix && adev->gfxhub.funcs && adev->gfxhub.funcs->utcl2_harvest)
1098b3accd6fSXiaomeng Hou 		adev->gfxhub.funcs->utcl2_harvest(adev);
1099b3accd6fSXiaomeng Hou 
1100f9df67e9SHawking Zhang 	r = gmc_v10_0_gart_enable(adev);
1101f9df67e9SHawking Zhang 	if (r)
1102f9df67e9SHawking Zhang 		return r;
1103f9df67e9SHawking Zhang 
1104479e3b02SXiaojian Du 	if (amdgpu_emu_mode == 1) {
1105479e3b02SXiaojian Du 		r = amdgpu_gmc_vram_checking(adev);
1106479e3b02SXiaojian Du 		if (r)
1107479e3b02SXiaojian Du 			return r;
1108479e3b02SXiaojian Du 	}
1109479e3b02SXiaojian Du 
111001eee24fSJohn Clements 	if (adev->umc.funcs && adev->umc.funcs->init_registers)
111101eee24fSJohn Clements 		adev->umc.funcs->init_registers(adev);
111201eee24fSJohn Clements 
1113f9df67e9SHawking Zhang 	return 0;
1114f9df67e9SHawking Zhang }
1115f9df67e9SHawking Zhang 
1116f9df67e9SHawking Zhang /**
1117f9df67e9SHawking Zhang  * gmc_v10_0_gart_disable - gart disable
1118f9df67e9SHawking Zhang  *
1119f9df67e9SHawking Zhang  * @adev: amdgpu_device pointer
1120f9df67e9SHawking Zhang  *
1121f9df67e9SHawking Zhang  * This disables all VM page table.
1122f9df67e9SHawking Zhang  */
gmc_v10_0_gart_disable(struct amdgpu_device * adev)1123f9df67e9SHawking Zhang static void gmc_v10_0_gart_disable(struct amdgpu_device *adev)
1124f9df67e9SHawking Zhang {
1125d5d29009SAlex Deucher 	if (!adev->in_s0ix)
11268ffff9b4SOak Zeng 		adev->gfxhub.funcs->gart_disable(adev);
11279fb1506eSOak Zeng 	adev->mmhub.funcs->gart_disable(adev);
1128f9df67e9SHawking Zhang }
1129f9df67e9SHawking Zhang 
gmc_v10_0_hw_fini(void * handle)1130f9df67e9SHawking Zhang static int gmc_v10_0_hw_fini(void *handle)
1131f9df67e9SHawking Zhang {
1132f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1133f9df67e9SHawking Zhang 
113471cf9e72SLeslie Shi 	gmc_v10_0_gart_disable(adev);
113571cf9e72SLeslie Shi 
1136f9df67e9SHawking Zhang 	if (amdgpu_sriov_vf(adev)) {
1137f9df67e9SHawking Zhang 		/* full access mode, so don't touch any GMC register */
1138f9df67e9SHawking Zhang 		DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
1139f9df67e9SHawking Zhang 		return 0;
1140f9df67e9SHawking Zhang 	}
1141f9df67e9SHawking Zhang 
1142f9df67e9SHawking Zhang 	amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
1143f9df67e9SHawking Zhang 
1144*0a8fc4e0SStanley.Yang 	if (adev->gmc.ecc_irq.funcs &&
1145*0a8fc4e0SStanley.Yang 		amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC))
1146*0a8fc4e0SStanley.Yang 		amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
1147*0a8fc4e0SStanley.Yang 
1148f9df67e9SHawking Zhang 	return 0;
1149f9df67e9SHawking Zhang }
1150f9df67e9SHawking Zhang 
gmc_v10_0_suspend(void * handle)1151f9df67e9SHawking Zhang static int gmc_v10_0_suspend(void *handle)
1152f9df67e9SHawking Zhang {
1153f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1154f9df67e9SHawking Zhang 
1155f9df67e9SHawking Zhang 	gmc_v10_0_hw_fini(adev);
1156f9df67e9SHawking Zhang 
1157f9df67e9SHawking Zhang 	return 0;
1158f9df67e9SHawking Zhang }
1159f9df67e9SHawking Zhang 
gmc_v10_0_resume(void * handle)1160f9df67e9SHawking Zhang static int gmc_v10_0_resume(void *handle)
1161f9df67e9SHawking Zhang {
1162f9df67e9SHawking Zhang 	int r;
1163f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1164f9df67e9SHawking Zhang 
1165f9df67e9SHawking Zhang 	r = gmc_v10_0_hw_init(adev);
1166f9df67e9SHawking Zhang 	if (r)
1167f9df67e9SHawking Zhang 		return r;
1168f9df67e9SHawking Zhang 
1169f9df67e9SHawking Zhang 	amdgpu_vmid_reset_all(adev);
1170f9df67e9SHawking Zhang 
1171f9df67e9SHawking Zhang 	return 0;
1172f9df67e9SHawking Zhang }
1173f9df67e9SHawking Zhang 
gmc_v10_0_is_idle(void * handle)1174f9df67e9SHawking Zhang static bool gmc_v10_0_is_idle(void *handle)
1175f9df67e9SHawking Zhang {
1176f9df67e9SHawking Zhang 	/* MC is always ready in GMC v10.*/
1177f9df67e9SHawking Zhang 	return true;
1178f9df67e9SHawking Zhang }
1179f9df67e9SHawking Zhang 
gmc_v10_0_wait_for_idle(void * handle)1180f9df67e9SHawking Zhang static int gmc_v10_0_wait_for_idle(void *handle)
1181f9df67e9SHawking Zhang {
1182f9df67e9SHawking Zhang 	/* There is no need to wait for MC idle in GMC v10.*/
1183f9df67e9SHawking Zhang 	return 0;
1184f9df67e9SHawking Zhang }
1185f9df67e9SHawking Zhang 
gmc_v10_0_soft_reset(void * handle)1186f9df67e9SHawking Zhang static int gmc_v10_0_soft_reset(void *handle)
1187f9df67e9SHawking Zhang {
1188f9df67e9SHawking Zhang 	return 0;
1189f9df67e9SHawking Zhang }
1190f9df67e9SHawking Zhang 
gmc_v10_0_set_clockgating_state(void * handle,enum amd_clockgating_state state)1191f9df67e9SHawking Zhang static int gmc_v10_0_set_clockgating_state(void *handle,
1192f9df67e9SHawking Zhang 					   enum amd_clockgating_state state)
1193f9df67e9SHawking Zhang {
1194f9df67e9SHawking Zhang 	int r;
1195f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1196f9df67e9SHawking Zhang 
11973bbeaa30SPrike Liang 	/*
11983bbeaa30SPrike Liang 	 * The issue mmhub can't disconnect from DF with MMHUB clock gating being disabled
11993bbeaa30SPrike Liang 	 * is a new problem observed at DF 3.0.3, however with the same suspend sequence not
12003bbeaa30SPrike Liang 	 * seen any issue on the DF 3.0.2 series platform.
12013bbeaa30SPrike Liang 	 */
12023bbeaa30SPrike Liang 	if (adev->in_s0ix && adev->ip_versions[DF_HWIP][0] > IP_VERSION(3, 0, 2)) {
12033bbeaa30SPrike Liang 		dev_dbg(adev->dev, "keep mmhub clock gating being enabled for s0ix\n");
12043bbeaa30SPrike Liang 		return 0;
12053bbeaa30SPrike Liang 	}
12063bbeaa30SPrike Liang 
12079fb1506eSOak Zeng 	r = adev->mmhub.funcs->set_clockgating(adev, state);
1208f9df67e9SHawking Zhang 	if (r)
1209f9df67e9SHawking Zhang 		return r;
1210f9df67e9SHawking Zhang 
12111d789535SAlex Deucher 	if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0))
1212920a4cd3SLikun Gao 		return athub_v2_1_set_clockgating(adev, state);
1213920a4cd3SLikun Gao 	else
1214f9df67e9SHawking Zhang 		return athub_v2_0_set_clockgating(adev, state);
1215f9df67e9SHawking Zhang }
1216f9df67e9SHawking Zhang 
gmc_v10_0_get_clockgating_state(void * handle,u64 * flags)121725faeddcSEvan Quan static void gmc_v10_0_get_clockgating_state(void *handle, u64 *flags)
1218f9df67e9SHawking Zhang {
1219f9df67e9SHawking Zhang 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1220f9df67e9SHawking Zhang 
1221f9ed188dSLang Yu 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 3) ||
1222f9ed188dSLang Yu 	    adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 4))
1223d2895ec4SLang Yu 		return;
1224d2895ec4SLang Yu 
12259fb1506eSOak Zeng 	adev->mmhub.funcs->get_clockgating(adev, flags);
1226f9df67e9SHawking Zhang 
12271d789535SAlex Deucher 	if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0))
1228920a4cd3SLikun Gao 		athub_v2_1_get_clockgating(adev, flags);
1229920a4cd3SLikun Gao 	else
1230f9df67e9SHawking Zhang 		athub_v2_0_get_clockgating(adev, flags);
1231f9df67e9SHawking Zhang }
1232f9df67e9SHawking Zhang 
gmc_v10_0_set_powergating_state(void * handle,enum amd_powergating_state state)1233f9df67e9SHawking Zhang static int gmc_v10_0_set_powergating_state(void *handle,
1234f9df67e9SHawking Zhang 					   enum amd_powergating_state state)
1235f9df67e9SHawking Zhang {
1236f9df67e9SHawking Zhang 	return 0;
1237f9df67e9SHawking Zhang }
1238f9df67e9SHawking Zhang 
1239f9df67e9SHawking Zhang const struct amd_ip_funcs gmc_v10_0_ip_funcs = {
1240f9df67e9SHawking Zhang 	.name = "gmc_v10_0",
1241f9df67e9SHawking Zhang 	.early_init = gmc_v10_0_early_init,
1242f9df67e9SHawking Zhang 	.late_init = gmc_v10_0_late_init,
1243f9df67e9SHawking Zhang 	.sw_init = gmc_v10_0_sw_init,
1244f9df67e9SHawking Zhang 	.sw_fini = gmc_v10_0_sw_fini,
1245f9df67e9SHawking Zhang 	.hw_init = gmc_v10_0_hw_init,
1246f9df67e9SHawking Zhang 	.hw_fini = gmc_v10_0_hw_fini,
1247f9df67e9SHawking Zhang 	.suspend = gmc_v10_0_suspend,
1248f9df67e9SHawking Zhang 	.resume = gmc_v10_0_resume,
1249f9df67e9SHawking Zhang 	.is_idle = gmc_v10_0_is_idle,
1250f9df67e9SHawking Zhang 	.wait_for_idle = gmc_v10_0_wait_for_idle,
1251f9df67e9SHawking Zhang 	.soft_reset = gmc_v10_0_soft_reset,
1252f9df67e9SHawking Zhang 	.set_clockgating_state = gmc_v10_0_set_clockgating_state,
1253f9df67e9SHawking Zhang 	.set_powergating_state = gmc_v10_0_set_powergating_state,
1254f9df67e9SHawking Zhang 	.get_clockgating_state = gmc_v10_0_get_clockgating_state,
1255f9df67e9SHawking Zhang };
1256f9df67e9SHawking Zhang 
12578612a435SSrinivasan Shanmugam const struct amdgpu_ip_block_version gmc_v10_0_ip_block = {
1258f9df67e9SHawking Zhang 	.type = AMD_IP_BLOCK_TYPE_GMC,
1259f9df67e9SHawking Zhang 	.major = 10,
1260f9df67e9SHawking Zhang 	.minor = 0,
1261f9df67e9SHawking Zhang 	.rev = 0,
1262f9df67e9SHawking Zhang 	.funcs = &gmc_v10_0_ip_funcs,
1263f9df67e9SHawking Zhang };
1264