Merge tag 'drm-for-v4.15-amd-dc' of git://people.freedesktop.org/~airlied/linux
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_device.c
index f5543758667f47c3bca7987cba1e5014bb9945b7..2d792cdc094cd60e86542c0ed5380c3590198fc2 100644 (file)
@@ -110,10 +110,8 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
 {
        uint32_t ret;
 
-       if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) {
-               BUG_ON(in_interrupt());
+       if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev))
                return amdgpu_virt_kiq_rreg(adev, reg);
-       }
 
        if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX))
                ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
@@ -138,10 +136,8 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
                adev->last_mm_index = v;
        }
 
-       if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) {
-               BUG_ON(in_interrupt());
+       if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev))
                return amdgpu_virt_kiq_wreg(adev, reg, v);
-       }
 
        if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX))
                writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
@@ -551,7 +547,7 @@ int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb)
 
        if (offset < adev->wb.num_wb) {
                __set_bit(offset, adev->wb.used);
-               *wb = offset * 8; /* convert to dw offset */
+               *wb = offset << 3; /* convert to dw offset */
                return 0;
        } else {
                return -EINVAL;
@@ -569,7 +565,7 @@ int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb)
 void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb)
 {
        if (wb < adev->wb.num_wb)
-               __clear_bit(wb, adev->wb.used);
+               __clear_bit(wb >> 3, adev->wb.used);
 }
 
 /**
@@ -659,42 +655,96 @@ void amdgpu_gart_location(struct amdgpu_device *adev, struct amdgpu_mc *mc)
 }
 
 /*
- * GPU helpers function.
+ * Firmware Reservation functions
  */
 /**
- * amdgpu_need_post - check if the hw need post or not
+ * amdgpu_fw_reserve_vram_fini - free fw reserved vram
  *
  * @adev: amdgpu_device pointer
  *
- * Check if the asic has been initialized (all asics) at driver startup
- * or post is needed if  hw reset is performed.
- * Returns true if need or false if not.
+ * free fw reserved vram if it has been reserved.
  */
-bool amdgpu_need_post(struct amdgpu_device *adev)
+void amdgpu_fw_reserve_vram_fini(struct amdgpu_device *adev)
 {
-       uint32_t reg;
+       amdgpu_bo_free_kernel(&adev->fw_vram_usage.reserved_bo,
+               NULL, &adev->fw_vram_usage.va);
+}
 
-       if (adev->has_hw_reset) {
-               adev->has_hw_reset = false;
-               return true;
-       }
+/**
+ * amdgpu_fw_reserve_vram_init - create bo vram reservation from fw
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * create bo vram reservation from fw.
+ */
+int amdgpu_fw_reserve_vram_init(struct amdgpu_device *adev)
+{
+       int r = 0;
+       u64 gpu_addr;
+       u64 vram_size = adev->mc.visible_vram_size;
 
-       /* bios scratch used on CIK+ */
-       if (adev->asic_type >= CHIP_BONAIRE)
-               return amdgpu_atombios_scratch_need_asic_init(adev);
+       adev->fw_vram_usage.va = NULL;
+       adev->fw_vram_usage.reserved_bo = NULL;
 
-       /* check MEM_SIZE for older asics */
-       reg = amdgpu_asic_get_config_memsize(adev);
+       if (adev->fw_vram_usage.size > 0 &&
+               adev->fw_vram_usage.size <= vram_size) {
 
-       if ((reg != 0) && (reg != 0xffffffff))
-               return false;
+               r = amdgpu_bo_create(adev, adev->fw_vram_usage.size,
+                       PAGE_SIZE, true, 0,
+                       AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+                       AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, 0,
+                       &adev->fw_vram_usage.reserved_bo);
+               if (r)
+                       goto error_create;
 
-       return true;
+               r = amdgpu_bo_reserve(adev->fw_vram_usage.reserved_bo, false);
+               if (r)
+                       goto error_reserve;
+               r = amdgpu_bo_pin_restricted(adev->fw_vram_usage.reserved_bo,
+                       AMDGPU_GEM_DOMAIN_VRAM,
+                       adev->fw_vram_usage.start_offset,
+                       (adev->fw_vram_usage.start_offset +
+                       adev->fw_vram_usage.size), &gpu_addr);
+               if (r)
+                       goto error_pin;
+               r = amdgpu_bo_kmap(adev->fw_vram_usage.reserved_bo,
+                       &adev->fw_vram_usage.va);
+               if (r)
+                       goto error_kmap;
 
+               amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo);
+       }
+       return r;
+
+error_kmap:
+       amdgpu_bo_unpin(adev->fw_vram_usage.reserved_bo);
+error_pin:
+       amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo);
+error_reserve:
+       amdgpu_bo_unref(&adev->fw_vram_usage.reserved_bo);
+error_create:
+       adev->fw_vram_usage.va = NULL;
+       adev->fw_vram_usage.reserved_bo = NULL;
+       return r;
 }
 
-static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
+
+/*
+ * GPU helpers function.
+ */
+/**
+ * amdgpu_need_post - check if the hw need post or not
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Check if the asic has been initialized (all asics) at driver startup
+ * or post is needed if  hw reset is performed.
+ * Returns true if need or false if not.
+ */
+bool amdgpu_need_post(struct amdgpu_device *adev)
 {
+       uint32_t reg;
+
        if (amdgpu_sriov_vf(adev))
                return false;
 
@@ -717,7 +767,23 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
                                return true;
                }
        }
-       return amdgpu_need_post(adev);
+
+       if (adev->has_hw_reset) {
+               adev->has_hw_reset = false;
+               return true;
+       }
+
+       /* bios scratch used on CIK+ */
+       if (adev->asic_type >= CHIP_BONAIRE)
+               return amdgpu_atombios_scratch_need_asic_init(adev);
+
+       /* check MEM_SIZE for older asics */
+       reg = amdgpu_asic_get_config_memsize(adev);
+
+       if ((reg != 0) && (reg != 0xffffffff))
+               return false;
+
+       return true;
 }
 
 /**
@@ -1605,7 +1671,6 @@ static int amdgpu_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_vram_scratch_init(adev);
@@ -1636,11 +1701,6 @@ static int amdgpu_init(struct amdgpu_device *adev)
                }
        }
 
-       mutex_lock(&adev->firmware.mutex);
-       if (amdgpu_ucode_init_bo(adev))
-               adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT;
-       mutex_unlock(&adev->firmware.mutex);
-
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_blocks[i].status.sw)
                        continue;
@@ -1776,8 +1836,6 @@ static int amdgpu_fini(struct amdgpu_device *adev)
 
                adev->ip_blocks[i].status.hw = false;
        }
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_DIRECT)
-               amdgpu_ucode_fini_bo(adev);
 
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_blocks[i].status.sw)
@@ -1889,6 +1947,7 @@ static int amdgpu_sriov_reinit_late(struct amdgpu_device *adev)
 
        static enum amd_ip_block_type ip_order[] = {
                AMD_IP_BLOCK_TYPE_SMC,
+               AMD_IP_BLOCK_TYPE_PSP,
                AMD_IP_BLOCK_TYPE_DCE,
                AMD_IP_BLOCK_TYPE_GFX,
                AMD_IP_BLOCK_TYPE_SDMA,
@@ -1974,12 +2033,17 @@ static int amdgpu_resume(struct amdgpu_device *adev)
 
 static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
 {
-       if (adev->is_atom_fw) {
-               if (amdgpu_atomfirmware_gpu_supports_virtualization(adev))
-                       adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
-       } else {
-               if (amdgpu_atombios_has_gpu_virtualization_table(adev))
-                       adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
+       if (amdgpu_sriov_vf(adev)) {
+               if (adev->is_atom_fw) {
+                       if (amdgpu_atomfirmware_gpu_supports_virtualization(adev))
+                               adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
+               } else {
+                       if (amdgpu_atombios_has_gpu_virtualization_table(adev))
+                               adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
+               }
+
+               if (!(adev->virt.caps & AMDGPU_SRIOV_CAPS_SRIOV_VBIOS))
+                       amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_NO_VBIOS, 0, 0);
        }
 }
 
@@ -2066,6 +2130,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        adev->vm_manager.vm_pte_num_rings = 0;
        adev->gart.gart_funcs = NULL;
        adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS);
+       bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
 
        adev->smc_rreg = &amdgpu_invalid_rreg;
        adev->smc_wreg = &amdgpu_invalid_wreg;
@@ -2093,6 +2158,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        mutex_init(&adev->pm.mutex);
        mutex_init(&adev->gfx.gpu_clock_mutex);
        mutex_init(&adev->srbm_mutex);
+       mutex_init(&adev->gfx.pipe_reserve_mutex);
        mutex_init(&adev->grbm_idx_mutex);
        mutex_init(&adev->mn_lock);
        mutex_init(&adev->virt.vf_errors.lock);
@@ -2189,10 +2255,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        amdgpu_device_detect_sriov_bios(adev);
 
        /* Post card if necessary */
-       if (amdgpu_vpost_needed(adev)) {
+       if (amdgpu_need_post(adev)) {
                if (!adev->bios) {
                        dev_err(adev->dev, "no vBIOS found\n");
-                       amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_NO_VBIOS, 0, 0);
                        r = -EINVAL;
                        goto failed;
                }
@@ -2200,7 +2265,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
                r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
                if (r) {
                        dev_err(adev->dev, "gpu post error!\n");
-                       amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_GPU_POST_ERROR, 0, 0);
                        goto failed;
                }
        } else {
@@ -2270,6 +2334,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        if (r)
                DRM_ERROR("ib ring test failed (%d).\n", r);
 
+       if (amdgpu_sriov_vf(adev))
+               amdgpu_virt_init_data_exchange(adev);
+
        amdgpu_fbdev_init(adev);
 
        r = amdgpu_pm_sysfs_init(adev);
@@ -2347,6 +2414,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
        /* evict vram memory */
        amdgpu_bo_evict_vram(adev);
        amdgpu_ib_pool_fini(adev);
+       amdgpu_fw_reserve_vram_fini(adev);
        amdgpu_fence_driver_fini(adev);
        amdgpu_fbdev_fini(adev);
        r = amdgpu_fini(adev);
@@ -2617,6 +2685,9 @@ static bool amdgpu_check_soft_reset(struct amdgpu_device *adev)
        int i;
        bool asic_hang = false;
 
+       if (amdgpu_sriov_vf(adev))
+               return true;
+
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_blocks[i].status.valid)
                        continue;
@@ -3020,7 +3091,6 @@ out:
                }
        } else {
                dev_err(adev->dev, "asic resume failed (%d).\n", r);
-               amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ASIC_RESUME_FAIL, 0, r);
                for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
                        if (adev->rings[i] && adev->rings[i]->sched.thread) {
                                kthread_unpark(adev->rings[i]->sched.thread);
@@ -3038,7 +3108,6 @@ out:
        if (r) {
                /* bad news, how to tell it to userspace ? */
                dev_info(adev->dev, "GPU reset failed\n");
-               amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r);
        }
        else {
                dev_info(adev->dev, "GPU reset successed!\n");