drm/amdgpu: Use atomic function to disable crtcs with dc enabled
[linux-2.6-block.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_device.c
index 00a50cc5ec9a31a77b7476020e5f47089c83c5de..cdf7a6cde60330773db452cd7f2a621e2c328ac4 100644 (file)
@@ -87,6 +87,16 @@ static const char *amdgpu_asic_name[] = {
        "LAST",
 };
 
+static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
+
+/**
+ * amdgpu_device_is_px - Is the device is a dGPU with HG/PX power control
+ *
+ * @dev: drm_device pointer
+ *
+ * Returns true if the device is a dGPU with HG/PX power control,
+ * otherwise return false.
+ */
 bool amdgpu_device_is_px(struct drm_device *dev)
 {
        struct amdgpu_device *adev = dev->dev_private;
@@ -99,6 +109,15 @@ bool amdgpu_device_is_px(struct drm_device *dev)
 /*
  * MMIO register access helper functions.
  */
+/**
+ * amdgpu_mm_rreg - read a memory mapped IO register
+ *
+ * @adev: amdgpu_device pointer
+ * @reg: dword aligned register offset
+ * @acc_flags: access flags which require special behavior
+ *
+ * Returns the 32 bit value from the offset specified.
+ */
 uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
                        uint32_t acc_flags)
 {
@@ -121,6 +140,58 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
        return ret;
 }
 
+/*
+ * MMIO register read with bytes helper functions
+ * @offset:bytes offset from MMIO start
+ *
+*/
+
+/**
+ * amdgpu_mm_rreg8 - read a memory mapped IO register
+ *
+ * @adev: amdgpu_device pointer
+ * @offset: byte aligned register offset
+ *
+ * Returns the 8 bit value from the offset specified.
+ */
+uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) {
+       if (offset < adev->rmmio_size)
+               return (readb(adev->rmmio + offset));
+       BUG();
+}
+
+/*
+ * MMIO register write with bytes helper functions
+ * @offset:bytes offset from MMIO start
+ * @value: the value want to be written to the register
+ *
+*/
+/**
+ * amdgpu_mm_wreg8 - read a memory mapped IO register
+ *
+ * @adev: amdgpu_device pointer
+ * @offset: byte aligned register offset
+ * @value: 8 bit value to write
+ *
+ * Writes the value specified to the offset specified.
+ */
+void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) {
+       if (offset < adev->rmmio_size)
+               writeb(value, adev->rmmio + offset);
+       else
+               BUG();
+}
+
+/**
+ * amdgpu_mm_wreg - write to a memory mapped IO register
+ *
+ * @adev: amdgpu_device pointer
+ * @reg: dword aligned register offset
+ * @v: 32 bit value to write to the register
+ * @acc_flags: access flags which require special behavior
+ *
+ * Writes the value specified to the offset specified.
+ */
 void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
                    uint32_t acc_flags)
 {
@@ -149,6 +220,14 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
        }
 }
 
+/**
+ * amdgpu_io_rreg - read an IO register
+ *
+ * @adev: amdgpu_device pointer
+ * @reg: dword aligned register offset
+ *
+ * Returns the 32 bit value from the offset specified.
+ */
 u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg)
 {
        if ((reg * 4) < adev->rio_mem_size)
@@ -159,6 +238,15 @@ u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg)
        }
 }
 
+/**
+ * amdgpu_io_wreg - write to an IO register
+ *
+ * @adev: amdgpu_device pointer
+ * @reg: dword aligned register offset
+ * @v: 32 bit value to write to the register
+ *
+ * Writes the value specified to the offset specified.
+ */
 void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
 {
        if (adev->asic_type >= CHIP_VEGA10 && reg == 0) {
@@ -327,6 +415,14 @@ static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev,
        BUG();
 }
 
+/**
+ * amdgpu_device_vram_scratch_init - allocate the VRAM scratch page
+ *
+ * @adev: amdgpu device pointer
+ *
+ * Allocates a scratch page of VRAM for use by various things in the
+ * driver.
+ */
 static int amdgpu_device_vram_scratch_init(struct amdgpu_device *adev)
 {
        return amdgpu_bo_create_kernel(adev, AMDGPU_GPU_PAGE_SIZE,
@@ -336,6 +432,13 @@ static int amdgpu_device_vram_scratch_init(struct amdgpu_device *adev)
                                       (void **)&adev->vram_scratch.ptr);
 }
 
+/**
+ * amdgpu_device_vram_scratch_fini - Free the VRAM scratch page
+ *
+ * @adev: amdgpu device pointer
+ *
+ * Frees the VRAM scratch page.
+ */
 static void amdgpu_device_vram_scratch_fini(struct amdgpu_device *adev)
 {
        amdgpu_bo_free_kernel(&adev->vram_scratch.robj, NULL, NULL);
@@ -377,6 +480,14 @@ void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
        }
 }
 
+/**
+ * amdgpu_device_pci_config_reset - reset the GPU
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Resets the GPU using the pci config reset sequence.
+ * Only applicable to asics prior to vega10.
+ */
 void amdgpu_device_pci_config_reset(struct amdgpu_device *adev)
 {
        pci_write_config_dword(adev->pdev, 0x7c, AMDGPU_ASIC_RESET_DATA);
@@ -492,7 +603,7 @@ static int amdgpu_device_wb_init(struct amdgpu_device *adev)
                memset(&adev->wb.used, 0, sizeof(adev->wb.used));
 
                /* clear wb memory */
-               memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t));
+               memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);
        }
 
        return 0;
@@ -530,12 +641,14 @@ int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
  */
 void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
 {
+       wb >>= 3;
        if (wb < adev->wb.num_wb)
-               __clear_bit(wb >> 3, adev->wb.used);
+               __clear_bit(wb, adev->wb.used);
 }
 
 /**
  * amdgpu_device_vram_location - try to find VRAM location
+ *
  * @adev: amdgpu device structure holding all necessary informations
  * @mc: memory controller structure holding memory informations
  * @base: base address at which to put VRAM
@@ -544,7 +657,7 @@ void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
  * as parameter.
  */
 void amdgpu_device_vram_location(struct amdgpu_device *adev,
-                                struct amdgpu_mc *mc, u64 base)
+                                struct amdgpu_gmc *mc, u64 base)
 {
        uint64_t limit = (uint64_t)amdgpu_vram_limit << 20;
 
@@ -559,6 +672,7 @@ void amdgpu_device_vram_location(struct amdgpu_device *adev,
 
 /**
  * amdgpu_device_gart_location - try to find GTT location
+ *
  * @adev: amdgpu device structure holding all necessary informations
  * @mc: memory controller structure holding memory informations
  *
@@ -570,11 +684,11 @@ void amdgpu_device_vram_location(struct amdgpu_device *adev,
  * FIXME: when reducing GTT size align new size on power of 2.
  */
 void amdgpu_device_gart_location(struct amdgpu_device *adev,
-                                struct amdgpu_mc *mc)
+                                struct amdgpu_gmc *mc)
 {
        u64 size_af, size_bf;
 
-       size_af = adev->mc.mc_mask - mc->vram_end;
+       size_af = adev->gmc.mc_mask - mc->vram_end;
        size_bf = mc->vram_start;
        if (size_bf > size_af) {
                if (mc->gart_size > size_bf) {
@@ -608,7 +722,7 @@ void amdgpu_device_gart_location(struct amdgpu_device *adev,
  */
 int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
 {
-       u64 space_needed = roundup_pow_of_two(adev->mc.real_vram_size);
+       u64 space_needed = roundup_pow_of_two(adev->gmc.real_vram_size);
        u32 rbar_size = order_base_2(((space_needed >> 20) | 1)) - 1;
        struct pci_bus *root;
        struct resource *res;
@@ -745,6 +859,16 @@ static unsigned int amdgpu_device_vga_set_decode(void *cookie, bool state)
                return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
+/**
+ * amdgpu_device_check_block_size - validate the vm block size
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Validates the vm block size specified via module parameter.
+ * The vm block size defines number of bits in page table versus page directory,
+ * a page is 4KB so we have 12 bits offset, minimum 9 bits in the
+ * page table and the remaining bits are in the page directory.
+ */
 static void amdgpu_device_check_block_size(struct amdgpu_device *adev)
 {
        /* defines number of bits in page table versus page directory,
@@ -760,6 +884,14 @@ static void amdgpu_device_check_block_size(struct amdgpu_device *adev)
        }
 }
 
+/**
+ * amdgpu_device_check_vm_size - validate the vm size
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Validates the vm size in GB specified via module parameter.
+ * The VM size is the size of the GPU virtual memory space in GB.
+ */
 static void amdgpu_device_check_vm_size(struct amdgpu_device *adev)
 {
        /* no need to check the default value */
@@ -829,6 +961,8 @@ static void amdgpu_device_check_arguments(struct amdgpu_device *adev)
                dev_warn(adev->dev, "lockup_timeout msut be > 0, adjusting to 10000\n");
                amdgpu_lockup_timeout = 10000;
        }
+
+       adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
 }
 
 /**
@@ -892,6 +1026,17 @@ static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = {
        .can_switch = amdgpu_switcheroo_can_switch,
 };
 
+/**
+ * amdgpu_device_ip_set_clockgating_state - set the CG state
+ *
+ * @adev: amdgpu_device pointer
+ * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
+ * @state: clockgating state (gate or ungate)
+ *
+ * Sets the requested clockgating state for all instances of
+ * the hardware IP specified.
+ * Returns the error code from the last instance.
+ */
 int amdgpu_device_ip_set_clockgating_state(struct amdgpu_device *adev,
                                           enum amd_ip_block_type block_type,
                                           enum amd_clockgating_state state)
@@ -914,6 +1059,17 @@ int amdgpu_device_ip_set_clockgating_state(struct amdgpu_device *adev,
        return r;
 }
 
+/**
+ * amdgpu_device_ip_set_powergating_state - set the PG state
+ *
+ * @adev: amdgpu_device pointer
+ * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
+ * @state: powergating state (gate or ungate)
+ *
+ * Sets the requested powergating state for all instances of
+ * the hardware IP specified.
+ * Returns the error code from the last instance.
+ */
 int amdgpu_device_ip_set_powergating_state(struct amdgpu_device *adev,
                                           enum amd_ip_block_type block_type,
                                           enum amd_powergating_state state)
@@ -936,6 +1092,17 @@ int amdgpu_device_ip_set_powergating_state(struct amdgpu_device *adev,
        return r;
 }
 
+/**
+ * amdgpu_device_ip_get_clockgating_state - get the CG state
+ *
+ * @adev: amdgpu_device pointer
+ * @flags: clockgating feature flags
+ *
+ * Walks the list of IPs on the device and updates the clockgating
+ * flags for each IP.
+ * Updates @flags with the feature flags for each hardware IP where
+ * clockgating is enabled.
+ */
 void amdgpu_device_ip_get_clockgating_state(struct amdgpu_device *adev,
                                            u32 *flags)
 {
@@ -949,6 +1116,15 @@ void amdgpu_device_ip_get_clockgating_state(struct amdgpu_device *adev,
        }
 }
 
+/**
+ * amdgpu_device_ip_wait_for_idle - wait for idle
+ *
+ * @adev: amdgpu_device pointer
+ * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
+ *
+ * Waits for the request hardware IP to be idle.
+ * Returns 0 for success or a negative error code on failure.
+ */
 int amdgpu_device_ip_wait_for_idle(struct amdgpu_device *adev,
                                   enum amd_ip_block_type block_type)
 {
@@ -968,6 +1144,15 @@ int amdgpu_device_ip_wait_for_idle(struct amdgpu_device *adev,
 
 }
 
+/**
+ * amdgpu_device_ip_is_idle - is the hardware IP idle
+ *
+ * @adev: amdgpu_device pointer
+ * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
+ *
+ * Check if the hardware IP is idle or not.
+ * Returns true if it the IP is idle, false if not.
+ */
 bool amdgpu_device_ip_is_idle(struct amdgpu_device *adev,
                              enum amd_ip_block_type block_type)
 {
@@ -983,6 +1168,15 @@ bool amdgpu_device_ip_is_idle(struct amdgpu_device *adev,
 
 }
 
+/**
+ * amdgpu_device_ip_get_ip_block - get a hw IP pointer
+ *
+ * @adev: amdgpu_device pointer
+ * @block_type: Type of hardware IP (SMU, GFX, UVD, etc.)
+ *
+ * Returns a pointer to the hardware IP block structure
+ * if it exists for the asic, otherwise NULL.
+ */
 struct amdgpu_ip_block *
 amdgpu_device_ip_get_ip_block(struct amdgpu_device *adev,
                              enum amd_ip_block_type type)
@@ -1036,7 +1230,7 @@ int amdgpu_device_ip_block_add(struct amdgpu_device *adev,
        if (!ip_block_version)
                return -EINVAL;
 
-       DRM_DEBUG("add ip block number %d <%s>\n", adev->num_ip_blocks,
+       DRM_INFO("add ip block number %d <%s>\n", adev->num_ip_blocks,
                  ip_block_version->funcs->name);
 
        adev->ip_blocks[adev->num_ip_blocks++].version = ip_block_version;
@@ -1044,6 +1238,18 @@ int amdgpu_device_ip_block_add(struct amdgpu_device *adev,
        return 0;
 }
 
+/**
+ * amdgpu_device_enable_virtual_display - enable virtual display feature
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Enabled the virtual display feature if the user has enabled it via
+ * the module parameter virtual_display.  This feature provides a virtual
+ * display hardware on headless boards or in virtualized environments.
+ * This function parses and validates the configuration string specified by
+ * the user and configues the virtual display configuration (number of
+ * virtual connectors, crtcs, etc.) specified.
+ */
 static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
 {
        adev->enable_virtual_display = false;
@@ -1089,6 +1295,16 @@ static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
        }
 }
 
+/**
+ * amdgpu_device_parse_gpu_info_fw - parse gpu info firmware
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Parses the asic configuration parameters specified in the gpu info
+ * firmware and makes them availale to the driver for use in configuring
+ * the asic.
+ * Returns 0 on success, -EINVAL on failure.
+ */
 static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
 {
        const char *chip_name;
@@ -1187,6 +1403,16 @@ out:
        return err;
 }
 
+/**
+ * amdgpu_device_ip_early_init - run early init for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Early initialization pass for hardware IPs.  The hardware IPs that make
+ * up each asic are discovered each IP's early_init callback is run.  This
+ * is the first stage in initializing the asic.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
 {
        int i, r;
@@ -1296,6 +1522,17 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_init - run init for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Main initialization pass for hardware IPs.  The list of all the hardware
+ * IPs that make up the asic is walked and the sw_init and hw_init callbacks
+ * are run.  sw_init initializes the software state associated with each IP
+ * and hw_init initializes the hardware associated with each IP.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_init(struct amdgpu_device *adev)
 {
        int i, r;
@@ -1310,6 +1547,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                        return r;
                }
                adev->ip_blocks[i].status.sw = true;
+
                /* need to do gmc hw init early so we can allocate gpu mem */
                if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
                        r = amdgpu_device_vram_scratch_init(adev);
@@ -1343,8 +1581,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_blocks[i].status.sw)
                        continue;
-               /* gmc hw init is done early */
-               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC)
+               if (adev->ip_blocks[i].status.hw)
                        continue;
                r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
                if (r) {
@@ -1363,27 +1600,61 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_fill_reset_magic - writes reset magic to gart pointer
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Writes a reset magic value to the gart pointer in VRAM.  The driver calls
+ * this function before a GPU reset.  If the value is retained after a
+ * GPU reset, VRAM has not been lost.  Some GPU resets may destry VRAM contents.
+ */
 static void amdgpu_device_fill_reset_magic(struct amdgpu_device *adev)
 {
        memcpy(adev->reset_magic, adev->gart.ptr, AMDGPU_RESET_MAGIC_NUM);
 }
 
+/**
+ * amdgpu_device_check_vram_lost - check if vram is valid
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Checks the reset magic value written to the gart pointer in VRAM.
+ * The driver calls this after a GPU reset to see if the contents of
+ * VRAM is lost or now.
+ * returns true if vram is lost, false if not.
+ */
 static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev)
 {
        return !!memcmp(adev->gart.ptr, adev->reset_magic,
                        AMDGPU_RESET_MAGIC_NUM);
 }
 
+/**
+ * amdgpu_device_ip_late_set_cg_state - late init for clockgating
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Late initialization pass enabling clockgating for hardware IPs.
+ * The list of all the hardware IPs that make up the asic is walked and the
+ * set_clockgating_state callbacks are run.  This stage is run late
+ * in the init process.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_late_set_cg_state(struct amdgpu_device *adev)
 {
        int i = 0, r;
 
+       if (amdgpu_emu_mode == 1)
+               return 0;
+
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_blocks[i].status.valid)
                        continue;
                /* skip CG for VCE/UVD, it's handled specially */
                if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
-                   adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) {
+                   adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
+                   adev->ip_blocks[i].version->funcs->set_clockgating_state) {
                        /* enable clockgating to save power */
                        r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
                                                                                     AMD_CG_STATE_GATE);
@@ -1397,6 +1668,18 @@ static int amdgpu_device_ip_late_set_cg_state(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_late_init - run late init for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Late initialization pass for hardware IPs.  The list of all the hardware
+ * IPs that make up the asic is walked and the late_init callbacks are run.
+ * late_init covers any special initialization that an IP requires
+ * after all of the have been initialized or something that needs to happen
+ * late in the init process.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
 {
        int i = 0, r;
@@ -1423,6 +1706,17 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_fini - run fini for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Main teardown pass for hardware IPs.  The list of all the hardware
+ * IPs that make up the asic is walked and the hw_fini and sw_fini callbacks
+ * are run.  hw_fini tears down the hardware associated with each IP
+ * and sw_fini tears down any software state associated with each IP.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
 {
        int i, r;
@@ -1432,7 +1726,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_blocks[i].status.hw)
                        continue;
-               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
+               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC &&
+                       adev->ip_blocks[i].version->funcs->set_clockgating_state) {
                        /* ungate blocks before hw fini so that we can shutdown the blocks safely */
                        r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
                                                                                     AMD_CG_STATE_UNGATE);
@@ -1455,11 +1750,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_blocks[i].status.hw)
                        continue;
-               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
-                       amdgpu_free_static_csa(adev);
-                       amdgpu_device_wb_fini(adev);
-                       amdgpu_device_vram_scratch_fini(adev);
-               }
 
                if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
                        adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) {
@@ -1483,9 +1773,19 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
                adev->ip_blocks[i].status.hw = false;
        }
 
+       /* disable all interrupts */
+       amdgpu_irq_disable_all(adev);
+
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_blocks[i].status.sw)
                        continue;
+
+               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
+                       amdgpu_free_static_csa(adev);
+                       amdgpu_device_wb_fini(adev);
+                       amdgpu_device_vram_scratch_fini(adev);
+               }
+
                r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev);
                /* XXX handle errors */
                if (r) {
@@ -1511,6 +1811,15 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_late_init_func_handler - work handler for clockgating
+ *
+ * @work: work_struct
+ *
+ * Work handler for amdgpu_device_ip_late_set_cg_state.  We put the
+ * clockgating setup into a worker thread to speed up driver init and
+ * resume from suspend.
+ */
 static void amdgpu_device_ip_late_init_func_handler(struct work_struct *work)
 {
        struct amdgpu_device *adev =
@@ -1518,6 +1827,17 @@ static void amdgpu_device_ip_late_init_func_handler(struct work_struct *work)
        amdgpu_device_ip_late_set_cg_state(adev);
 }
 
+/**
+ * amdgpu_device_ip_suspend - run suspend for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Main suspend function for hardware IPs.  The list of all the hardware
+ * IPs that make up the asic is walked, clockgating is disabled and the
+ * suspend callbacks are run.  suspend puts the hardware and software state
+ * in each IP into a state suitable for suspend.
+ * Returns 0 on success, negative error code on failure.
+ */
 int amdgpu_device_ip_suspend(struct amdgpu_device *adev)
 {
        int i, r;
@@ -1536,7 +1856,8 @@ int amdgpu_device_ip_suspend(struct amdgpu_device *adev)
                if (!adev->ip_blocks[i].status.valid)
                        continue;
                /* ungate blocks so that suspend can properly shut them down */
-               if (i != AMD_IP_BLOCK_TYPE_SMC) {
+               if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_SMC &&
+                       adev->ip_blocks[i].version->funcs->set_clockgating_state) {
                        r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
                                                                                     AMD_CG_STATE_UNGATE);
                        if (r) {
@@ -1582,6 +1903,8 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
 
                        r = block->version->funcs->hw_init(adev);
                        DRM_INFO("RE-INIT: %s %s\n", block->version->funcs->name, r?"failed":"successed");
+                       if (r)
+                               return r;
                }
        }
 
@@ -1615,12 +1938,26 @@ static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
 
                        r = block->version->funcs->hw_init(adev);
                        DRM_INFO("RE-INIT: %s %s\n", block->version->funcs->name, r?"failed":"successed");
+                       if (r)
+                               return r;
                }
        }
 
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_resume_phase1 - run resume for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * First resume function for hardware IPs.  The list of all the hardware
+ * IPs that make up the asic is walked and the resume callbacks are run for
+ * COMMON, GMC, and IH.  resume puts the hardware into a functional state
+ * after a suspend and updates the software state as necessary.  This
+ * function is also used for restoring the GPU after a GPU reset.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
 {
        int i, r;
@@ -1629,9 +1966,8 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
                if (!adev->ip_blocks[i].status.valid)
                        continue;
                if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
-                               adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
-                               adev->ip_blocks[i].version->type ==
-                               AMD_IP_BLOCK_TYPE_IH) {
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
                        r = adev->ip_blocks[i].version->funcs->resume(adev);
                        if (r) {
                                DRM_ERROR("resume of IP block <%s> failed %d\n",
@@ -1644,6 +1980,19 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_resume_phase2 - run resume for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * First resume function for hardware IPs.  The list of all the hardware
+ * IPs that make up the asic is walked and the resume callbacks are run for
+ * all blocks except COMMON, GMC, and IH.  resume puts the hardware into a
+ * functional state after a suspend and updates the software state as
+ * necessary.  This function is also used for restoring the GPU after a GPU
+ * reset.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
 {
        int i, r;
@@ -1652,8 +2001,8 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
                if (!adev->ip_blocks[i].status.valid)
                        continue;
                if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
-                               adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
-                               adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH )
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH)
                        continue;
                r = adev->ip_blocks[i].version->funcs->resume(adev);
                if (r) {
@@ -1666,6 +2015,18 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_resume - run resume for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Main resume function for hardware IPs.  The hardware IPs
+ * are split into two resume functions because they are
+ * are also used in in recovering from a GPU reset and some additional
+ * steps need to be take between them.  In this case (S3/S4) they are
+ * run sequentially.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
 {
        int r;
@@ -1678,6 +2039,13 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
        return r;
 }
 
+/**
+ * amdgpu_device_detect_sriov_bios - determine if the board supports SR-IOV
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Query the VBIOS data tables to determine if the board supports SR-IOV.
+ */
 static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
 {
        if (amdgpu_sriov_vf(adev)) {
@@ -1694,6 +2062,14 @@ static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
        }
 }
 
+/**
+ * amdgpu_device_asic_has_dc_support - determine if DC supports the asic
+ *
+ * @asic_type: AMD asic type
+ *
+ * Check if there is DC (new modesetting infrastructre) support for an asic.
+ * returns true if DC has support, false if not.
+ */
 bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
 {
        switch (asic_type) {
@@ -1701,6 +2077,8 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
        case CHIP_BONAIRE:
        case CHIP_HAWAII:
        case CHIP_KAVERI:
+       case CHIP_KABINI:
+       case CHIP_MULLINS:
        case CHIP_CARRIZO:
        case CHIP_STONEY:
        case CHIP_POLARIS11:
@@ -1711,9 +2089,6 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
 #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA)
                return amdgpu_dc != 0;
 #endif
-       case CHIP_KABINI:
-       case CHIP_MULLINS:
-               return amdgpu_dc > 0;
        case CHIP_VEGA10:
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case CHIP_RAVEN:
@@ -1768,14 +2143,16 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        adev->flags = flags;
        adev->asic_type = flags & AMD_ASIC_MASK;
        adev->usec_timeout = AMDGPU_MAX_USEC_TIMEOUT;
-       adev->mc.gart_size = 512 * 1024 * 1024;
+       if (amdgpu_emu_mode == 1)
+               adev->usec_timeout *= 2;
+       adev->gmc.gart_size = 512 * 1024 * 1024;
        adev->accel_working = false;
        adev->num_rings = 0;
        adev->mman.buffer_funcs = NULL;
        adev->mman.buffer_funcs_ring = NULL;
        adev->vm_manager.vm_pte_funcs = NULL;
        adev->vm_manager.vm_pte_num_rings = 0;
-       adev->gart.gart_funcs = NULL;
+       adev->gmc.gmc_funcs = NULL;
        adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS);
        bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
 
@@ -1864,6 +2241,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        if (adev->rio_mem == NULL)
                DRM_INFO("PCI I/O BAR is not found.\n");
 
+       amdgpu_device_get_pcie_info(adev);
+
        /* early init functions */
        r = amdgpu_device_ip_early_init(adev);
        if (r)
@@ -1882,6 +2261,12 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        if (runtime)
                vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
 
+       if (amdgpu_emu_mode == 1) {
+               /* post the asic on emulation mode */
+               emu_soc_asic_init(adev);
+               goto fence_driver_init;
+       }
+
        /* Read BIOS */
        if (!amdgpu_get_bios(adev)) {
                r = -EINVAL;
@@ -1934,6 +2319,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
                        amdgpu_atombios_i2c_init(adev);
        }
 
+fence_driver_init:
        /* Fence driver */
        r = amdgpu_fence_driver_init(adev);
        if (r) {
@@ -2060,11 +2446,15 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
 
        DRM_INFO("amdgpu: finishing device.\n");
        adev->shutdown = true;
-       if (adev->mode_info.mode_config_initialized)
-               drm_crtc_force_disable_all(adev->ddev);
-
+       if (adev->mode_info.mode_config_initialized){
+               if (!amdgpu_device_has_dc_support(adev))
+                       drm_crtc_force_disable_all(adev->ddev);
+               else
+                       drm_atomic_helper_shutdown(adev->ddev);
+       }
        amdgpu_ib_pool_fini(adev);
        amdgpu_fence_driver_fini(adev);
+       amdgpu_pm_sysfs_fini(adev);
        amdgpu_fbdev_fini(adev);
        r = amdgpu_device_ip_fini(adev);
        if (adev->firmware.gpu_info_fw) {
@@ -2076,7 +2466,10 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
        /* free i2c buses */
        if (!amdgpu_device_has_dc_support(adev))
                amdgpu_i2c_fini(adev);
-       amdgpu_atombios_fini(adev);
+
+       if (amdgpu_emu_mode != 1)
+               amdgpu_atombios_fini(adev);
+
        kfree(adev->bios);
        adev->bios = NULL;
        if (!pci_is_thunderbolt_attached(adev->pdev))
@@ -2090,7 +2483,6 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
        iounmap(adev->rmmio);
        adev->rmmio = NULL;
        amdgpu_device_doorbell_fini(adev);
-       amdgpu_pm_sysfs_fini(adev);
        amdgpu_debugfs_regs_cleanup(adev);
 }
 
@@ -2284,14 +2676,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
                                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
                        }
                        drm_modeset_unlock_all(dev);
-               } else {
-                       /*
-                        * There is no equivalent atomic helper to turn on
-                        * display, so we defined our own function for this,
-                        * once suspend resume is supported by the atomic
-                        * framework this will be reworked
-                        */
-                       amdgpu_dm_display_resume(adev);
                }
        }
 
@@ -2327,6 +2711,16 @@ unlock:
        return r;
 }
 
+/**
+ * amdgpu_device_ip_check_soft_reset - did soft reset succeed
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * The list of all the hardware IPs that make up the asic is walked and
+ * the check_soft_reset callbacks are run.  check_soft_reset determines
+ * if the asic is still hung or not.
+ * Returns true if any of the IPs are still in a hung state, false if not.
+ */
 static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev)
 {
        int i;
@@ -2349,6 +2743,17 @@ static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev)
        return asic_hang;
 }
 
+/**
+ * amdgpu_device_ip_pre_soft_reset - prepare for soft reset
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * The list of all the hardware IPs that make up the asic is walked and the
+ * pre_soft_reset callbacks are run if the block is hung.  pre_soft_reset
+ * handles any IP specific hardware or software state changes that are
+ * necessary for a soft reset to succeed.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_pre_soft_reset(struct amdgpu_device *adev)
 {
        int i, r = 0;
@@ -2367,6 +2772,15 @@ static int amdgpu_device_ip_pre_soft_reset(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_need_full_reset - check if a full asic reset is needed
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Some hardware IPs cannot be soft reset.  If they are hung, a full gpu
+ * reset is necessary to recover.
+ * Returns true if a full asic reset is required, false if not.
+ */
 static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev)
 {
        int i;
@@ -2388,6 +2802,17 @@ static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev)
        return false;
 }
 
+/**
+ * amdgpu_device_ip_soft_reset - do a soft reset
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * The list of all the hardware IPs that make up the asic is walked and the
+ * soft_reset callbacks are run if the block is hung.  soft_reset handles any
+ * IP specific hardware or software state changes that are necessary to soft
+ * reset the IP.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_soft_reset(struct amdgpu_device *adev)
 {
        int i, r = 0;
@@ -2406,6 +2831,17 @@ static int amdgpu_device_ip_soft_reset(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_ip_post_soft_reset - clean up from soft reset
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * The list of all the hardware IPs that make up the asic is walked and the
+ * post_soft_reset callbacks are run if the asic was hung.  post_soft_reset
+ * handles any IP specific hardware or software state changes that are
+ * necessary after the IP has been soft reset.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_ip_post_soft_reset(struct amdgpu_device *adev)
 {
        int i, r = 0;
@@ -2423,6 +2859,19 @@ static int amdgpu_device_ip_post_soft_reset(struct amdgpu_device *adev)
        return 0;
 }
 
+/**
+ * amdgpu_device_recover_vram_from_shadow - restore shadowed VRAM buffers
+ *
+ * @adev: amdgpu_device pointer
+ * @ring: amdgpu_ring for the engine handling the buffer operations
+ * @bo: amdgpu_bo buffer whose shadow is being restored
+ * @fence: dma_fence associated with the operation
+ *
+ * Restores the VRAM buffer contents from the shadow in GTT.  Used to
+ * restore things like GPUVM page tables after a GPU reset where
+ * the contents of VRAM might be lost.
+ * Returns 0 on success, negative error code on failure.
+ */
 static int amdgpu_device_recover_vram_from_shadow(struct amdgpu_device *adev,
                                                  struct amdgpu_ring *ring,
                                                  struct amdgpu_bo *bo,
@@ -2458,17 +2907,81 @@ err:
        return r;
 }
 
-/*
+/**
+ * amdgpu_device_handle_vram_lost - Handle the loss of VRAM contents
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Restores the contents of VRAM buffers from the shadows in GTT.  Used to
+ * restore things like GPUVM page tables after a GPU reset where
+ * the contents of VRAM might be lost.
+ * Returns 0 on success, 1 on failure.
+ */
+static int amdgpu_device_handle_vram_lost(struct amdgpu_device *adev)
+{
+       struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
+       struct amdgpu_bo *bo, *tmp;
+       struct dma_fence *fence = NULL, *next = NULL;
+       long r = 1;
+       int i = 0;
+       long tmo;
+
+       if (amdgpu_sriov_runtime(adev))
+               tmo = msecs_to_jiffies(amdgpu_lockup_timeout);
+       else
+               tmo = msecs_to_jiffies(100);
+
+       DRM_INFO("recover vram bo from shadow start\n");
+       mutex_lock(&adev->shadow_list_lock);
+       list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
+               next = NULL;
+               amdgpu_device_recover_vram_from_shadow(adev, ring, bo, &next);
+               if (fence) {
+                       r = dma_fence_wait_timeout(fence, false, tmo);
+                       if (r == 0)
+                               pr_err("wait fence %p[%d] timeout\n", fence, i);
+                       else if (r < 0)
+                               pr_err("wait fence %p[%d] interrupted\n", fence, i);
+                       if (r < 1) {
+                               dma_fence_put(fence);
+                               fence = next;
+                               break;
+                       }
+                       i++;
+               }
+
+               dma_fence_put(fence);
+               fence = next;
+       }
+       mutex_unlock(&adev->shadow_list_lock);
+
+       if (fence) {
+               r = dma_fence_wait_timeout(fence, false, tmo);
+               if (r == 0)
+                       pr_err("wait fence %p[%d] timeout\n", fence, i);
+               else if (r < 0)
+                       pr_err("wait fence %p[%d] interrupted\n", fence, i);
+
+       }
+       dma_fence_put(fence);
+
+       if (r > 0)
+               DRM_INFO("recover vram bo from shadow done\n");
+       else
+               DRM_ERROR("recover vram bo from shadow failed\n");
+
+       return (r > 0) ? 0 : 1;
+}
+
+/**
  * amdgpu_device_reset - reset ASIC/GPU for bare-metal or passthrough
  *
  * @adev: amdgpu device pointer
- * @reset_flags: output param tells caller the reset result
  *
  * attempt to do soft-reset or full-reset and reinitialize Asic
  * return 0 means successed otherwise failed
-*/
-static int amdgpu_device_reset(struct amdgpu_device *adev,
-                              uint64_t* reset_flags)
+ */
+static int amdgpu_device_reset(struct amdgpu_device *adev)
 {
        bool need_full_reset, vram_lost = 0;
        int r;
@@ -2483,7 +2996,6 @@ static int amdgpu_device_reset(struct amdgpu_device *adev,
                        DRM_INFO("soft reset failed, will fallback to full reset!\n");
                        need_full_reset = true;
                }
-
        }
 
        if (need_full_reset) {
@@ -2532,28 +3044,21 @@ out:
                }
        }
 
-       if (reset_flags) {
-               if (vram_lost)
-                       (*reset_flags) |= AMDGPU_RESET_INFO_VRAM_LOST;
-
-               if (need_full_reset)
-                       (*reset_flags) |= AMDGPU_RESET_INFO_FULLRESET;
-       }
+       if (!r && ((need_full_reset && !(adev->flags & AMD_IS_APU)) || vram_lost))
+               r = amdgpu_device_handle_vram_lost(adev);
 
        return r;
 }
 
-/*
+/**
  * amdgpu_device_reset_sriov - reset ASIC for SR-IOV vf
  *
  * @adev: amdgpu device pointer
- * @reset_flags: output param tells caller the reset result
  *
  * do VF FLR and reinitialize Asic
  * return 0 means successed otherwise failed
-*/
+ */
 static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
-                                    uint64_t *reset_flags,
                                     bool from_hypervisor)
 {
        int r;
@@ -2575,28 +3080,20 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
 
        /* now we are okay to resume SMC/CP/SDMA */
        r = amdgpu_device_ip_reinit_late_sriov(adev);
+       amdgpu_virt_release_full_gpu(adev, true);
        if (r)
                goto error;
 
        amdgpu_irq_gpu_reset_resume_helper(adev);
        r = amdgpu_ib_ring_tests(adev);
-       if (r)
-               dev_err(adev->dev, "[GPU_RESET] ib ring test failed (%d).\n", r);
 
-error:
-       /* release full control of GPU after ib test */
-       amdgpu_virt_release_full_gpu(adev, true);
-
-       if (reset_flags) {
-               if (adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
-                       (*reset_flags) |= AMDGPU_RESET_INFO_VRAM_LOST;
-                       atomic_inc(&adev->vram_lost_counter);
-               }
-
-               /* VF FLR or hotlink reset is always full-reset */
-               (*reset_flags) |= AMDGPU_RESET_INFO_FULLRESET;
+       if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
+               atomic_inc(&adev->vram_lost_counter);
+               r = amdgpu_device_handle_vram_lost(adev);
        }
 
+error:
+
        return r;
 }
 
@@ -2614,7 +3111,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                              struct amdgpu_job *job, bool force)
 {
        struct drm_atomic_state *state = NULL;
-       uint64_t reset_flags = 0;
        int i, r, resched;
 
        if (!force && !amdgpu_device_ip_check_soft_reset(adev)) {
@@ -2636,22 +3132,23 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
+
        /* store modesetting */
        if (amdgpu_device_has_dc_support(adev))
                state = drm_atomic_helper_suspend(adev->ddev);
 
-       /* block scheduler */
+       /* block all schedulers and reset given job's ring */
        for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
                struct amdgpu_ring *ring = adev->rings[i];
 
                if (!ring || !ring->sched.thread)
                        continue;
 
-               /* only focus on the ring hit timeout if &job not NULL */
+               kthread_park(ring->sched.thread);
+
                if (job && job->ring->idx != i)
                        continue;
 
-               kthread_park(ring->sched.thread);
                drm_sched_hw_job_reset(&ring->sched, &job->base);
 
                /* after all hw jobs are reset, hw fence is meaningless, so force_completion */
@@ -2659,74 +3156,29 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
        }
 
        if (amdgpu_sriov_vf(adev))
-               r = amdgpu_device_reset_sriov(adev, &reset_flags, job ? false : true);
+               r = amdgpu_device_reset_sriov(adev, job ? false : true);
        else
-               r = amdgpu_device_reset(adev, &reset_flags);
-
-       if (!r) {
-               if (((reset_flags & AMDGPU_RESET_INFO_FULLRESET) && !(adev->flags & AMD_IS_APU)) ||
-                       (reset_flags & AMDGPU_RESET_INFO_VRAM_LOST)) {
-                       struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
-                       struct amdgpu_bo *bo, *tmp;
-                       struct dma_fence *fence = NULL, *next = NULL;
-
-                       DRM_INFO("recover vram bo from shadow\n");
-                       mutex_lock(&adev->shadow_list_lock);
-                       list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
-                               next = NULL;
-                               amdgpu_device_recover_vram_from_shadow(adev, ring, bo, &next);
-                               if (fence) {
-                                       r = dma_fence_wait(fence, false);
-                                       if (r) {
-                                               WARN(r, "recovery from shadow isn't completed\n");
-                                               break;
-                                       }
-                               }
-
-                               dma_fence_put(fence);
-                               fence = next;
-                       }
-                       mutex_unlock(&adev->shadow_list_lock);
-                       if (fence) {
-                               r = dma_fence_wait(fence, false);
-                               if (r)
-                                       WARN(r, "recovery from shadow isn't completed\n");
-                       }
-                       dma_fence_put(fence);
-               }
+               r = amdgpu_device_reset(adev);
 
-               for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-                       struct amdgpu_ring *ring = adev->rings[i];
-
-                       if (!ring || !ring->sched.thread)
-                               continue;
+       for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
+               struct amdgpu_ring *ring = adev->rings[i];
 
-                       /* only focus on the ring hit timeout if &job not NULL */
-                       if (job && job->ring->idx != i)
-                               continue;
+               if (!ring || !ring->sched.thread)
+                       continue;
 
+               /* only need recovery sched of the given job's ring
+                * or all rings (in the case @job is NULL)
+                * after above amdgpu_reset accomplished
+                */
+               if ((!job || job->ring->idx == i) && !r)
                        drm_sched_job_recovery(&ring->sched);
-                       kthread_unpark(ring->sched.thread);
-               }
-       } else {
-               for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-                       struct amdgpu_ring *ring = adev->rings[i];
 
-                       if (!ring || !ring->sched.thread)
-                               continue;
-
-                       /* only focus on the ring hit timeout if &job not NULL */
-                       if (job && job->ring->idx != i)
-                               continue;
-
-                       kthread_unpark(adev->rings[i]->sched.thread);
-               }
+               kthread_unpark(ring->sched.thread);
        }
 
        if (amdgpu_device_has_dc_support(adev)) {
                if (drm_atomic_helper_resume(adev->ddev, state))
                        dev_info(adev->dev, "drm resume failed:%d\n", r);
-               amdgpu_dm_display_resume(adev);
        } else {
                drm_helper_resume_force_mode(adev->ddev);
        }
@@ -2747,7 +3199,16 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
        return r;
 }
 
-void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
+/**
+ * amdgpu_device_get_pcie_info - fence pcie info about the PCIE slot
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Fetchs and stores in the driver the PCIE capabilities (gen speed
+ * and lanes) of the slot the device is in. Handles APUs and
+ * virtualized environments where PCIE config space may not be available.
+ */
+static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
 {
        u32 mask;
        int ret;