drm/amdgpu: set ip specific ras interface pointer to NULL after free it
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / gmc_v9_0.c
index 73f3b79..ba14955 100644 (file)
 
 #include "gfxhub_v1_0.h"
 #include "mmhub_v1_0.h"
+#include "athub_v1_0.h"
 #include "gfxhub_v1_1.h"
+#include "mmhub_v9_4.h"
+#include "umc_v6_1.h"
 
 #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
 
@@ -241,18 +244,32 @@ static int gmc_v9_0_ecc_interrupt_state(struct amdgpu_device *adev,
 }
 
 static int gmc_v9_0_process_ras_data_cb(struct amdgpu_device *adev,
+               struct ras_err_data *err_data,
                struct amdgpu_iv_entry *entry)
 {
-       kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
-       amdgpu_ras_reset_gpu(adev, 0);
-       return AMDGPU_RAS_UE;
+       if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) {
+               kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
+               if (adev->umc.funcs->query_ras_error_count)
+                       adev->umc.funcs->query_ras_error_count(adev, err_data);
+               /* umc query_ras_error_address is also responsible for clearing
+                * error status
+                */
+               if (adev->umc.funcs->query_ras_error_address)
+                       adev->umc.funcs->query_ras_error_address(adev, err_data);
+
+               /* only uncorrectable error needs gpu reset */
+               if (err_data->ue_count)
+                       amdgpu_ras_reset_gpu(adev, 0);
+       }
+
+       return AMDGPU_RAS_SUCCESS;
 }
 
 static int gmc_v9_0_process_ecc_irq(struct amdgpu_device *adev,
                struct amdgpu_irq_src *source,
                struct amdgpu_iv_entry *entry)
 {
-       struct ras_common_if *ras_if = adev->gmc.ras_if;
+       struct ras_common_if *ras_if = adev->gmc.umc_ras_if;
        struct ras_dispatch_if ih_data = {
                .entry = entry,
        };
@@ -284,7 +301,7 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
 
        switch (state) {
        case AMDGPU_IRQ_STATE_DISABLE:
-               for (j = 0; j < AMDGPU_MAX_VMHUBS; j++) {
+               for (j = 0; j < adev->num_vmhubs; j++) {
                        hub = &adev->vmhub[j];
                        for (i = 0; i < 16; i++) {
                                reg = hub->vm_context0_cntl + i;
@@ -295,7 +312,7 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
                }
                break;
        case AMDGPU_IRQ_STATE_ENABLE:
-               for (j = 0; j < AMDGPU_MAX_VMHUBS; j++) {
+               for (j = 0; j < adev->num_vmhubs; j++) {
                        hub = &adev->vmhub[j];
                        for (i = 0; i < 16; i++) {
                                reg = hub->vm_context0_cntl + i;
@@ -315,10 +332,11 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
                                struct amdgpu_irq_src *source,
                                struct amdgpu_iv_entry *entry)
 {
-       struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src];
+       struct amdgpu_vmhub *hub;
        bool retry_fault = !!(entry->src_data[1] & 0x80);
        uint32_t status = 0;
        u64 addr;
+       char hub_name[10];
 
        addr = (u64)entry->src_data[0] << 12;
        addr |= ((u64)entry->src_data[1] & 0xf) << 44;
@@ -327,8 +345,27 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
                                                    entry->timestamp))
                return 1; /* This also prevents sending it to KFD */
 
+       if (entry->client_id == SOC15_IH_CLIENTID_VMC) {
+               snprintf(hub_name, sizeof(hub_name), "mmhub0");
+               hub = &adev->vmhub[AMDGPU_MMHUB_0];
+       } else if (entry->client_id == SOC15_IH_CLIENTID_VMC1) {
+               snprintf(hub_name, sizeof(hub_name), "mmhub1");
+               hub = &adev->vmhub[AMDGPU_MMHUB_1];
+       } else {
+               snprintf(hub_name, sizeof(hub_name), "gfxhub0");
+               hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+       }
+
        /* If it's the first fault for this address, process it normally */
        if (!amdgpu_sriov_vf(adev)) {
+               /*
+                * Issue a dummy read to wait for the status register to
+                * be updated to avoid reading an incorrect value due to
+                * the new fast GRBM interface.
+                */
+               if (entry->vmid_src == AMDGPU_GFXHUB_0)
+                       RREG32(hub->vm_l2_pro_fault_status);
+
                status = RREG32(hub->vm_l2_pro_fault_status);
                WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
        }
@@ -342,17 +379,33 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
                dev_err(adev->dev,
                        "[%s] %s page fault (src_id:%u ring:%u vmid:%u "
                        "pasid:%u, for process %s pid %d thread %s pid %d)\n",
-                       entry->vmid_src ? "mmhub" : "gfxhub",
-                       retry_fault ? "retry" : "no-retry",
+                       hub_name, retry_fault ? "retry" : "no-retry",
                        entry->src_id, entry->ring_id, entry->vmid,
                        entry->pasid, task_info.process_name, task_info.tgid,
                        task_info.task_name, task_info.pid);
-               dev_err(adev->dev, "  in page starting at address 0x%016llx from %d\n",
+               dev_err(adev->dev, "  in page starting at address 0x%016llx from client %d\n",
                        addr, entry->client_id);
-               if (!amdgpu_sriov_vf(adev))
+               if (!amdgpu_sriov_vf(adev)) {
                        dev_err(adev->dev,
                                "VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
                                status);
+                       dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
+                               REG_GET_FIELD(status,
+                               VM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS));
+                       dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n",
+                               REG_GET_FIELD(status,
+                               VM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR));
+                       dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n",
+                               REG_GET_FIELD(status,
+                               VM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS));
+                       dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n",
+                               REG_GET_FIELD(status,
+                               VM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR));
+                       dev_err(adev->dev, "\t RW: 0x%lx\n",
+                               REG_GET_FIELD(status,
+                               VM_L2_PROTECTION_FAULT_STATUS, RW));
+
+               }
        }
 
        return 0;
@@ -413,44 +466,53 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
  *
  * Flush the TLB for the requested page table using certain type.
  */
-static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev,
-                               uint32_t vmid, uint32_t flush_type)
+static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
+                                       uint32_t vmhub, uint32_t flush_type)
 {
        const unsigned eng = 17;
-       unsigned i, j;
+       u32 j, tmp;
+       struct amdgpu_vmhub *hub;
 
-       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
-               struct amdgpu_vmhub *hub = &adev->vmhub[i];
-               u32 tmp = gmc_v9_0_get_invalidate_req(vmid, flush_type);
+       BUG_ON(vmhub >= adev->num_vmhubs);
 
-               /* This is necessary for a HW workaround under SRIOV as well
-                * as GFXOFF under bare metal
-                */
-               if (adev->gfx.kiq.ring.sched.ready &&
-                   (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
-                   !adev->in_gpu_reset) {
-                       uint32_t req = hub->vm_inv_eng0_req + eng;
-                       uint32_t ack = hub->vm_inv_eng0_ack + eng;
-
-                       amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, tmp,
-                                                          1 << vmid);
-                       continue;
-               }
+       hub = &adev->vmhub[vmhub];
+       tmp = gmc_v9_0_get_invalidate_req(vmid, flush_type);
 
-               spin_lock(&adev->gmc.invalidate_lock);
-               WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
-               for (j = 0; j < adev->usec_timeout; j++) {
-                       tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_ack + eng);
-                       if (tmp & (1 << vmid))
-                               break;
-                       udelay(1);
-               }
-               spin_unlock(&adev->gmc.invalidate_lock);
-               if (j < adev->usec_timeout)
-                       continue;
+       /* This is necessary for a HW workaround under SRIOV as well
+        * as GFXOFF under bare metal
+        */
+       if (adev->gfx.kiq.ring.sched.ready &&
+                       (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
+                       !adev->in_gpu_reset) {
+               uint32_t req = hub->vm_inv_eng0_req + eng;
+               uint32_t ack = hub->vm_inv_eng0_ack + eng;
+
+               amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, tmp,
+                               1 << vmid);
+               return;
+       }
+
+       spin_lock(&adev->gmc.invalidate_lock);
+       WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
 
-               DRM_ERROR("Timeout waiting for VM flush ACK!\n");
+       /*
+        * Issue a dummy read to wait for the ACK register to be cleared
+        * to avoid a false ACK due to the new fast GRBM interface.
+        */
+       if (vmhub == AMDGPU_GFXHUB_0)
+               RREG32_NO_KIQ(hub->vm_inv_eng0_req + eng);
+
+       for (j = 0; j < adev->usec_timeout; j++) {
+               tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_ack + eng);
+               if (tmp & (1 << vmid))
+                       break;
+               udelay(1);
        }
+       spin_unlock(&adev->gmc.invalidate_lock);
+       if (j < adev->usec_timeout)
+               return;
+
+       DRM_ERROR("Timeout waiting for VM flush ACK!\n");
 }
 
 static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
@@ -480,7 +542,11 @@ static void gmc_v9_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid,
        struct amdgpu_device *adev = ring->adev;
        uint32_t reg;
 
-       if (ring->funcs->vmhub == AMDGPU_GFXHUB)
+       /* Do nothing because there's no lut register for mmhub1. */
+       if (ring->funcs->vmhub == AMDGPU_MMHUB_1)
+               return;
+
+       if (ring->funcs->vmhub == AMDGPU_GFXHUB_0)
                reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid;
        else
                reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT_MM) + vmid;
@@ -543,6 +609,9 @@ static uint64_t gmc_v9_0_get_vm_pte_flags(struct amdgpu_device *adev,
        case AMDGPU_VM_MTYPE_WC:
                pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_WC);
                break;
+       case AMDGPU_VM_MTYPE_RW:
+               pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_RW);
+               break;
        case AMDGPU_VM_MTYPE_CC:
                pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_CC);
                break;
@@ -597,12 +666,41 @@ static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev)
        adev->gmc.gmc_funcs = &gmc_v9_0_gmc_funcs;
 }
 
+static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
+{
+       switch (adev->asic_type) {
+       case CHIP_VEGA20:
+               adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
+               adev->umc.channel_inst_num = UMC_V6_1_CHANNEL_INSTANCE_NUM;
+               adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
+               adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET;
+               adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
+               adev->umc.funcs = &umc_v6_1_funcs;
+               break;
+       default:
+               break;
+       }
+}
+
+static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
+{
+       switch (adev->asic_type) {
+       case CHIP_VEGA20:
+               adev->mmhub_funcs = &mmhub_v1_0_funcs;
+               break;
+       default:
+               break;
+       }
+}
+
 static int gmc_v9_0_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        gmc_v9_0_set_gmc_funcs(adev);
        gmc_v9_0_set_irq_funcs(adev);
+       gmc_v9_0_set_umc_funcs(adev);
+       gmc_v9_0_set_mmhub_funcs(adev);
 
        adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
        adev->gmc.shared_aperture_end =
@@ -629,6 +727,8 @@ static bool gmc_v9_0_keep_stolen_memory(struct amdgpu_device *adev)
        switch (adev->asic_type) {
        case CHIP_VEGA10:
        case CHIP_RAVEN:
+       case CHIP_ARCTURUS:
+       case CHIP_RENOIR:
                return true;
        case CHIP_VEGA12:
        case CHIP_VEGA20:
@@ -641,7 +741,8 @@ static int gmc_v9_0_allocate_vm_inv_eng(struct amdgpu_device *adev)
 {
        struct amdgpu_ring *ring;
        unsigned vm_inv_engs[AMDGPU_MAX_VMHUBS] =
-               {GFXHUB_FREE_VM_INV_ENGS_BITMAP, MMHUB_FREE_VM_INV_ENGS_BITMAP};
+               {GFXHUB_FREE_VM_INV_ENGS_BITMAP, MMHUB_FREE_VM_INV_ENGS_BITMAP,
+               GFXHUB_FREE_VM_INV_ENGS_BITMAP};
        unsigned i;
        unsigned vmhub, inv_eng;
 
@@ -668,96 +769,56 @@ static int gmc_v9_0_allocate_vm_inv_eng(struct amdgpu_device *adev)
 
 static int gmc_v9_0_ecc_late_init(void *handle)
 {
+       int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ras_common_if **ras_if = &adev->gmc.ras_if;
-       struct ras_ih_if ih_info = {
-               .cb = gmc_v9_0_process_ras_data_cb,
-       };
-       struct ras_fs_if fs_info = {
+       struct ras_fs_if umc_fs_info = {
                .sysfs_name = "umc_err_count",
                .debugfs_name = "umc_err_inject",
        };
-       struct ras_common_if ras_block = {
-               .block = AMDGPU_RAS_BLOCK__UMC,
-               .type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
-               .sub_block_index = 0,
-               .name = "umc",
+       struct ras_ih_if umc_ih_info = {
+               .cb = gmc_v9_0_process_ras_data_cb,
        };
-       int r;
-
-       if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC)) {
-               amdgpu_ras_feature_enable_on_boot(adev, &ras_block, 0);
-               return 0;
-       }
-       /* handle resume path. */
-       if (*ras_if) {
-               /* resend ras TA enable cmd during resume.
-                * prepare to handle failure.
-                */
-               ih_info.head = **ras_if;
-               r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-               if (r) {
-                       if (r == -EAGAIN) {
-                               /* request a gpu reset. will run again. */
-                               amdgpu_ras_request_reset_on_boot(adev,
-                                               AMDGPU_RAS_BLOCK__UMC);
-                               return 0;
-                       }
-                       /* fail to enable ras, cleanup all. */
-                       goto irq;
-               }
-               /* enable successfully. continue. */
-               goto resume;
-       }
-
-       *ras_if = kmalloc(sizeof(**ras_if), GFP_KERNEL);
-       if (!*ras_if)
-               return -ENOMEM;
-
-       **ras_if = ras_block;
 
-       r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-       if (r) {
-               if (r == -EAGAIN) {
-                       amdgpu_ras_request_reset_on_boot(adev,
-                                       AMDGPU_RAS_BLOCK__UMC);
-                       r = 0;
-               }
-               goto feature;
+       if (!adev->gmc.umc_ras_if) {
+               adev->gmc.umc_ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+               if (!adev->gmc.umc_ras_if)
+                       return -ENOMEM;
+               adev->gmc.umc_ras_if->block = AMDGPU_RAS_BLOCK__UMC;
+               adev->gmc.umc_ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+               adev->gmc.umc_ras_if->sub_block_index = 0;
+               strcpy(adev->gmc.umc_ras_if->name, "umc");
        }
+       umc_ih_info.head = umc_fs_info.head = *adev->gmc.umc_ras_if;
 
-       ih_info.head = **ras_if;
-       fs_info.head = **ras_if;
-
-       r = amdgpu_ras_interrupt_add_handler(adev, &ih_info);
+       r = amdgpu_ras_late_init(adev, adev->gmc.umc_ras_if,
+                                &umc_fs_info, &umc_ih_info);
        if (r)
-               goto interrupt;
-
-       amdgpu_ras_debugfs_create(adev, &fs_info);
+               goto free;
 
-       r = amdgpu_ras_sysfs_create(adev, &fs_info);
-       if (r)
-               goto sysfs;
-resume:
-       r = amdgpu_irq_get(adev, &adev->gmc.ecc_irq, 0);
-       if (r)
-               goto irq;
+       if (amdgpu_ras_is_supported(adev, adev->gmc.umc_ras_if->block)) {
+               r = amdgpu_irq_get(adev, &adev->gmc.ecc_irq, 0);
+               if (r)
+                       goto umc_late_fini;
+       } else {
+               /* free umc ras_if if umc ras is not supported */
+               r = 0;
+               goto free;
+       }
 
+       if (adev->mmhub_funcs && adev->mmhub_funcs->ras_late_init) {
+               r = adev->mmhub_funcs->ras_late_init(adev);
+               if (r)
+                       return r;
+       }
        return 0;
-irq:
-       amdgpu_ras_sysfs_remove(adev, *ras_if);
-sysfs:
-       amdgpu_ras_debugfs_remove(adev, *ras_if);
-       amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
-interrupt:
-       amdgpu_ras_feature_enable(adev, *ras_if, 0);
-feature:
-       kfree(*ras_if);
-       *ras_if = NULL;
+umc_late_fini:
+       amdgpu_ras_late_fini(adev, adev->gmc.umc_ras_if, &umc_ih_info);
+free:
+       kfree(adev->gmc.umc_ras_if);
+       adev->gmc.umc_ras_if = NULL;
        return r;
 }
 
-
 static int gmc_v9_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -806,14 +867,17 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev,
                                        struct amdgpu_gmc *mc)
 {
        u64 base = 0;
-       if (!amdgpu_sriov_vf(adev))
+
+       if (adev->asic_type == CHIP_ARCTURUS)
+               base = mmhub_v9_4_get_fb_location(adev);
+       else if (!amdgpu_sriov_vf(adev))
                base = mmhub_v1_0_get_fb_location(adev);
+
        /* add the xgmi offset of the physical node */
        base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
        amdgpu_gmc_vram_location(adev, mc, base);
        amdgpu_gmc_gart_location(adev, mc);
-       if (!amdgpu_sriov_vf(adev))
-               amdgpu_gmc_agp_location(adev, mc);
+       amdgpu_gmc_agp_location(adev, mc);
        /* base offset of vram pages */
        adev->vm_manager.vram_base_offset = gfxhub_v1_0_get_mc_fb_offset(adev);
 
@@ -859,7 +923,7 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
 
        /* size in MB on si */
        adev->gmc.mc_vram_size =
-               adev->nbio_funcs->get_memsize(adev) * 1024ULL * 1024ULL;
+               adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
        adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
 
        if (!(adev->flags & AMD_IS_APU)) {
@@ -887,10 +951,12 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
                case CHIP_VEGA10:  /* all engines support GPUVM */
                case CHIP_VEGA12:  /* all engines support GPUVM */
                case CHIP_VEGA20:
+               case CHIP_ARCTURUS:
                default:
                        adev->gmc.gart_size = 512ULL << 20;
                        break;
                case CHIP_RAVEN:   /* DCE SG support */
+               case CHIP_RENOIR:
                        adev->gmc.gart_size = 1024ULL << 20;
                        break;
                }
@@ -923,7 +989,7 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev)
 
 static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
 {
-       u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL);
+       u32 d1vga_control;
        unsigned size;
 
        /*
@@ -933,6 +999,7 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
        if (gmc_v9_0_keep_stolen_memory(adev))
                return 9 * 1024 * 1024;
 
+       d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL);
        if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) {
                size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */
        } else {
@@ -940,6 +1007,7 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
 
                switch (adev->asic_type) {
                case CHIP_RAVEN:
+               case CHIP_RENOIR:
                        viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION);
                        size = (REG_GET_FIELD(viewport,
                                              HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) *
@@ -968,17 +1036,21 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
 static int gmc_v9_0_sw_init(void *handle)
 {
        int r;
-       int dma_bits;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        gfxhub_v1_0_init(adev);
-       mmhub_v1_0_init(adev);
+       if (adev->asic_type == CHIP_ARCTURUS)
+               mmhub_v9_4_init(adev);
+       else
+               mmhub_v1_0_init(adev);
 
        spin_lock_init(&adev->gmc.invalidate_lock);
 
        adev->gmc.vram_type = amdgpu_atomfirmware_get_vram_type(adev);
        switch (adev->asic_type) {
        case CHIP_RAVEN:
+               adev->num_vmhubs = 2;
+
                if (adev->rev_id == 0x0 || adev->rev_id == 0x1) {
                        amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
                } else {
@@ -991,6 +1063,10 @@ static int gmc_v9_0_sw_init(void *handle)
        case CHIP_VEGA10:
        case CHIP_VEGA12:
        case CHIP_VEGA20:
+       case CHIP_RENOIR:
+               adev->num_vmhubs = 2;
+
+
                /*
                 * To fulfill 4-level page support,
                 * vm size is 256TB (48bit), maximum size of Vega10,
@@ -1002,6 +1078,12 @@ static int gmc_v9_0_sw_init(void *handle)
                else
                        amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
                break;
+       case CHIP_ARCTURUS:
+               adev->num_vmhubs = 3;
+
+               /* Keep the vm size same with Vega20 */
+               amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
+               break;
        default:
                break;
        }
@@ -1012,6 +1094,13 @@ static int gmc_v9_0_sw_init(void *handle)
        if (r)
                return r;
 
+       if (adev->asic_type == CHIP_ARCTURUS) {
+               r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC1, VMC_1_0__SRCID__VM_FAULT,
+                                       &adev->gmc.vm_fault);
+               if (r)
+                       return r;
+       }
+
        r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_UTCL2, UTCL2_1_0__SRCID__FAULT,
                                &adev->gmc.vm_fault);
 
@@ -1030,25 +1119,12 @@ static int gmc_v9_0_sw_init(void *handle)
         */
        adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
 
-       /* set DMA mask + need_dma32 flags.
-        * PCIE - can handle 44-bits.
-        * IGP - can handle 44-bits
-        * PCI - dma32 for legacy pci gart, 44 bits on vega10
-        */
-       adev->need_dma32 = false;
-       dma_bits = adev->need_dma32 ? 32 : 44;
-       r = pci_set_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits));
+       r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
        if (r) {
-               adev->need_dma32 = true;
-               dma_bits = 32;
                printk(KERN_WARNING "amdgpu: No suitable DMA available.\n");
+               return r;
        }
-       r = pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits));
-       if (r) {
-               pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32));
-               printk(KERN_WARNING "amdgpu: No coherent DMA available.\n");
-       }
-       adev->need_swiotlb = drm_need_swiotlb(dma_bits);
+       adev->need_swiotlb = drm_need_swiotlb(44);
 
        if (adev->gmc.xgmi.supported) {
                r = gfxhub_v1_1_get_xgmi_info(adev);
@@ -1077,8 +1153,9 @@ static int gmc_v9_0_sw_init(void *handle)
         * amdgpu graphics/compute will use VMIDs 1-7
         * amdkfd will use VMIDs 8-15
         */
-       adev->vm_manager.id_mgr[AMDGPU_GFXHUB].num_ids = AMDGPU_NUM_OF_VMIDS;
-       adev->vm_manager.id_mgr[AMDGPU_MMHUB].num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[AMDGPU_GFXHUB_0].num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[AMDGPU_MMHUB_0].num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[AMDGPU_MMHUB_1].num_ids = AMDGPU_NUM_OF_VMIDS;
 
        amdgpu_vm_manager_init(adev);
 
@@ -1088,28 +1165,40 @@ static int gmc_v9_0_sw_init(void *handle)
 static int gmc_v9_0_sw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       void *stolen_vga_buf;
 
        if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC) &&
-                       adev->gmc.ras_if) {
-               struct ras_common_if *ras_if = adev->gmc.ras_if;
+                       adev->gmc.umc_ras_if) {
+               struct ras_common_if *ras_if = adev->gmc.umc_ras_if;
                struct ras_ih_if ih_info = {
                        .head = *ras_if,
                };
 
-               /*remove fs first*/
+               /* remove fs first */
                amdgpu_ras_debugfs_remove(adev, ras_if);
                amdgpu_ras_sysfs_remove(adev, ras_if);
-               /*remove the IH*/
+               /* remove the IH */
                amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
                amdgpu_ras_feature_enable(adev, ras_if, 0);
                kfree(ras_if);
        }
 
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB) &&
+                       adev->gmc.mmhub_ras_if) {
+               struct ras_common_if *ras_if = adev->gmc.mmhub_ras_if;
+
+               /* remove fs and disable ras feature */
+               amdgpu_ras_debugfs_remove(adev, ras_if);
+               amdgpu_ras_sysfs_remove(adev, ras_if);
+               amdgpu_ras_feature_enable(adev, ras_if, 0);
+               kfree(ras_if);
+       }
+
        amdgpu_gem_force_release(adev);
        amdgpu_vm_manager_fini(adev);
 
        if (gmc_v9_0_keep_stolen_memory(adev))
-               amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, NULL);
+               amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf);
 
        amdgpu_gart_table_vram_free(adev);
        amdgpu_bo_fini(adev);
@@ -1123,7 +1212,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
 
        switch (adev->asic_type) {
        case CHIP_VEGA10:
-               if (amdgpu_virt_support_skip_setting(adev))
+               if (amdgpu_sriov_vf(adev))
                        break;
                /* fall through */
        case CHIP_VEGA20:
@@ -1137,6 +1226,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
        case CHIP_VEGA12:
                break;
        case CHIP_RAVEN:
+               /* TODO for renoir */
                soc15_program_register_sequence(adev,
                                                golden_settings_athub_1_0_0,
                                                ARRAY_SIZE(golden_settings_athub_1_0_0));
@@ -1153,7 +1243,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
  */
 static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
 {
-       int r;
+       int r, i;
        bool value;
        u32 tmp;
 
@@ -1171,6 +1261,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
 
        switch (adev->asic_type) {
        case CHIP_RAVEN:
+               /* TODO for renoir */
                mmhub_v1_0_update_power_gating(adev, true);
                break;
        default:
@@ -1181,7 +1272,10 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
        if (r)
                return r;
 
-       r = mmhub_v1_0_gart_enable(adev);
+       if (adev->asic_type == CHIP_ARCTURUS)
+               r = mmhub_v9_4_gart_enable(adev);
+       else
+               r = mmhub_v1_0_gart_enable(adev);
        if (r)
                return r;
 
@@ -1194,7 +1288,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
        WREG32_SOC15(HDP, 0, mmHDP_NONSURFACE_BASE_HI, (adev->gmc.vram_start >> 40));
 
        /* After HDP is initialized, flush HDP.*/
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
                value = false;
@@ -1202,8 +1296,13 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
                value = true;
 
        gfxhub_v1_0_set_fault_enable_default(adev, value);
-       mmhub_v1_0_set_fault_enable_default(adev, value);
-       gmc_v9_0_flush_gpu_tlb(adev, 0, 0);
+       if (adev->asic_type == CHIP_ARCTURUS)
+               mmhub_v9_4_set_fault_enable_default(adev, value);
+       else
+               mmhub_v1_0_set_fault_enable_default(adev, value);
+
+       for (i = 0; i < adev->num_vmhubs; ++i)
+               gmc_v9_0_flush_gpu_tlb(adev, 0, i, 0);
 
        DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
                 (unsigned)(adev->gmc.gart_size >> 20),
@@ -1243,7 +1342,10 @@ static int gmc_v9_0_hw_init(void *handle)
 static void gmc_v9_0_gart_disable(struct amdgpu_device *adev)
 {
        gfxhub_v1_0_gart_disable(adev);
-       mmhub_v1_0_gart_disable(adev);
+       if (adev->asic_type == CHIP_ARCTURUS)
+               mmhub_v9_4_gart_disable(adev);
+       else
+               mmhub_v1_0_gart_disable(adev);
        amdgpu_gart_table_vram_unpin(adev);
 }
 
@@ -1308,14 +1410,26 @@ static int gmc_v9_0_set_clockgating_state(void *handle,
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       return mmhub_v1_0_set_clockgating(adev, state);
+       if (adev->asic_type == CHIP_ARCTURUS)
+               mmhub_v9_4_set_clockgating(adev, state);
+       else
+               mmhub_v1_0_set_clockgating(adev, state);
+
+       athub_v1_0_set_clockgating(adev, state);
+
+       return 0;
 }
 
 static void gmc_v9_0_get_clockgating_state(void *handle, u32 *flags)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       mmhub_v1_0_get_clockgating(adev, flags);
+       if (adev->asic_type == CHIP_ARCTURUS)
+               mmhub_v9_4_get_clockgating(adev, flags);
+       else
+               mmhub_v1_0_get_clockgating(adev, flags);
+
+       athub_v1_0_get_clockgating(adev, flags);
 }
 
 static int gmc_v9_0_set_powergating_state(void *handle,