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