]> Git Repo - linux.git/blobdiff - drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
Merge tag '5.15-rc-ksmbd-part2' of git://git.samba.org/ksmbd
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_device.c
index f944ed858f3e7f02c003c476eff136da705d89e1..41c6b3aacd37921ab5c392ee84240561fb2624bb 100644 (file)
@@ -116,6 +116,7 @@ const char *amdgpu_asic_name[] = {
        "RENOIR",
        "ALDEBARAN",
        "NAVI10",
+       "CYAN_SKILLFISH",
        "NAVI14",
        "NAVI12",
        "SIENNA_CICHLID",
@@ -287,7 +288,7 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
  */
 
 /**
- * amdgpu_device_vram_access - read/write a buffer in vram
+ * amdgpu_device_mm_access - access vram by MM_INDEX/MM_DATA
  *
  * @adev: amdgpu_device pointer
  * @pos: offset of the buffer in vram
@@ -295,22 +296,65 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
  * @size: read/write size, sizeof(@buf) must > @size
  * @write: true - write to vram, otherwise - read from vram
  */
-void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
-                              uint32_t *buf, size_t size, bool write)
+void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
+                            void *buf, size_t size, bool write)
 {
        unsigned long flags;
-       uint32_t hi = ~0;
+       uint32_t hi = ~0, tmp = 0;
+       uint32_t *data = buf;
        uint64_t last;
        int idx;
 
        if (!drm_dev_enter(&adev->ddev, &idx))
                return;
 
+       BUG_ON(!IS_ALIGNED(pos, 4) || !IS_ALIGNED(size, 4));
+
+       spin_lock_irqsave(&adev->mmio_idx_lock, flags);
+       for (last = pos + size; pos < last; pos += 4) {
+               tmp = pos >> 31;
+
+               WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
+               if (tmp != hi) {
+                       WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
+                       hi = tmp;
+               }
+               if (write)
+                       WREG32_NO_KIQ(mmMM_DATA, *data++);
+               else
+                       *data++ = RREG32_NO_KIQ(mmMM_DATA);
+       }
+
+       spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
+       drm_dev_exit(idx);
+}
+
+/**
+ * amdgpu_device_vram_access - access vram by vram aperature
+ *
+ * @adev: amdgpu_device pointer
+ * @pos: offset of the buffer in vram
+ * @buf: virtual address of the buffer in system memory
+ * @size: read/write size, sizeof(@buf) must > @size
+ * @write: true - write to vram, otherwise - read from vram
+ *
+ * The return value means how many bytes have been transferred.
+ */
+size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
+                                void *buf, size_t size, bool write)
+{
 #ifdef CONFIG_64BIT
+       void __iomem *addr;
+       size_t count = 0;
+       uint64_t last;
+
+       if (!adev->mman.aper_base_kaddr)
+               return 0;
+
        last = min(pos + size, adev->gmc.visible_vram_size);
        if (last > pos) {
-               void __iomem *addr = adev->mman.aper_base_kaddr + pos;
-               size_t count = last - pos;
+               addr = adev->mman.aper_base_kaddr + pos;
+               count = last - pos;
 
                if (write) {
                        memcpy_toio(addr, buf, count);
@@ -322,35 +366,37 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
                        memcpy_fromio(buf, addr, count);
                }
 
-               if (count == size)
-                       goto exit;
-
-               pos += count;
-               buf += count / 4;
-               size -= count;
        }
+
+       return count;
+#else
+       return 0;
 #endif
+}
 
-       spin_lock_irqsave(&adev->mmio_idx_lock, flags);
-       for (last = pos + size; pos < last; pos += 4) {
-               uint32_t tmp = pos >> 31;
+/**
+ * amdgpu_device_vram_access - read/write a buffer in vram
+ *
+ * @adev: amdgpu_device pointer
+ * @pos: offset of the buffer in vram
+ * @buf: virtual address of the buffer in system memory
+ * @size: read/write size, sizeof(@buf) must > @size
+ * @write: true - write to vram, otherwise - read from vram
+ */
+void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
+                              void *buf, size_t size, bool write)
+{
+       size_t count;
 
-               WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
-               if (tmp != hi) {
-                       WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
-                       hi = tmp;
-               }
-               if (write)
-                       WREG32_NO_KIQ(mmMM_DATA, *buf++);
-               else
-                       *buf++ = RREG32_NO_KIQ(mmMM_DATA);
+       /* try to using vram apreature to access vram first */
+       count = amdgpu_device_aper_access(adev, pos, buf, size, write);
+       size -= count;
+       if (size) {
+               /* using MM to access rest vram */
+               pos += count;
+               buf += count;
+               amdgpu_device_mm_access(adev, pos, buf, size, write);
        }
-       spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
-
-#ifdef CONFIG_64BIT
-exit:
-#endif
-       drm_dev_exit(idx);
 }
 
 /*
@@ -518,7 +564,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
            adev->gfx.rlc.funcs &&
            adev->gfx.rlc.funcs->is_rlcg_access_range) {
                if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg))
-                       return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v, 0, 0);
+                       return adev->gfx.rlc.funcs->sriov_wreg(adev, reg, v, 0, 0);
        } else {
                writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
        }
@@ -1266,15 +1312,16 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
 /**
  * amdgpu_device_vga_set_decode - enable/disable vga decode
  *
- * @cookie: amdgpu_device pointer
+ * @pdev: PCI device pointer
  * @state: enable/disable vga decode
  *
  * Enable/disable vga decode (all asics).
  * Returns VGA resource flags.
  */
-static unsigned int amdgpu_device_vga_set_decode(void *cookie, bool state)
+static unsigned int amdgpu_device_vga_set_decode(struct pci_dev *pdev,
+               bool state)
 {
-       struct amdgpu_device *adev = cookie;
+       struct amdgpu_device *adev = drm_to_adev(pci_get_drvdata(pdev));
        amdgpu_asic_set_vga_state(adev, state);
        if (state)
                return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
@@ -1394,6 +1441,10 @@ static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev)
                break;
        case CHIP_YELLOW_CARP:
                break;
+       case CHIP_CYAN_SKILLFISH:
+               if (adev->pdev->device == 0x13FE)
+                       adev->apu_flags |= AMD_APU_IS_CYAN_SKILLFISH2;
+               break;
        default:
                return -EINVAL;
        }
@@ -2100,6 +2151,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
        case  CHIP_BEIGE_GOBY:
        case CHIP_VANGOGH:
        case CHIP_YELLOW_CARP:
+       case CHIP_CYAN_SKILLFISH:
                if (adev->asic_type == CHIP_VANGOGH)
                        adev->family = AMDGPU_FAMILY_VGH;
                else if (adev->asic_type == CHIP_YELLOW_CARP)
@@ -3594,9 +3646,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 
 fence_driver_init:
        /* Fence driver */
-       r = amdgpu_fence_driver_init(adev);
+       r = amdgpu_fence_driver_sw_init(adev);
        if (r) {
-               dev_err(adev->dev, "amdgpu_fence_driver_init failed\n");
+               dev_err(adev->dev, "amdgpu_fence_driver_sw_init failed\n");
                amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0);
                goto failed;
        }
@@ -3623,6 +3675,8 @@ fence_driver_init:
                goto release_ras_con;
        }
 
+       amdgpu_fence_driver_hw_init(adev);
+
        dev_info(adev->dev,
                "SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n",
                        adev->gfx.config.max_shader_engines,
@@ -3714,7 +3768,7 @@ fence_driver_init:
        /* this will fail for cards that aren't VGA class devices, just
         * ignore it */
        if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
-               vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode);
+               vga_client_register(adev->pdev, amdgpu_device_vga_set_decode);
 
        if (amdgpu_device_supports_px(ddev)) {
                px = true;
@@ -3771,7 +3825,10 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
 {
        dev_info(adev->dev, "amdgpu: finishing device.\n");
        flush_delayed_work(&adev->delayed_init_work);
-       ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
+       if (adev->mman.initialized) {
+               flush_delayed_work(&adev->mman.bdev.wq);
+               ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
+       }
        adev->shutdown = true;
 
        /* make sure IB test finished before entering exclusive mode
@@ -3790,7 +3847,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
                else
                        drm_atomic_helper_shutdown(adev_to_drm(adev));
        }
-       amdgpu_fence_driver_fini_hw(adev);
+       amdgpu_fence_driver_hw_fini(adev);
 
        if (adev->pm_sysfs_en)
                amdgpu_pm_sysfs_fini(adev);
@@ -3812,7 +3869,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
 void amdgpu_device_fini_sw(struct amdgpu_device *adev)
 {
        amdgpu_device_ip_fini(adev);
-       amdgpu_fence_driver_fini_sw(adev);
+       amdgpu_fence_driver_sw_fini(adev);
        release_firmware(adev->firmware.gpu_info_fw);
        adev->firmware.gpu_info_fw = NULL;
        adev->accel_working = false;
@@ -3833,7 +3890,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
                vga_switcheroo_fini_domain_pm_ops(adev->dev);
        }
        if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
-               vga_client_register(adev->pdev, NULL, NULL, NULL);
+               vga_client_unregister(adev->pdev);
 
        if (IS_ENABLED(CONFIG_PERF_EVENTS))
                amdgpu_pmu_fini(adev);
@@ -3887,7 +3944,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
        /* evict vram memory */
        amdgpu_bo_evict_vram(adev);
 
-       amdgpu_fence_driver_suspend(adev);
+       amdgpu_fence_driver_hw_fini(adev);
 
        amdgpu_device_ip_suspend_phase2(adev);
        /* evict remaining vram memory
@@ -3932,8 +3989,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
                dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
                return r;
        }
-       amdgpu_fence_driver_resume(adev);
-
+       amdgpu_fence_driver_hw_init(adev);
 
        r = amdgpu_device_ip_late_init(adev);
        if (r)
@@ -4394,7 +4450,7 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev)
 int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
                                 struct amdgpu_reset_context *reset_context)
 {
-       int i, r = 0;
+       int i, j, r = 0;
        struct amdgpu_job *job = NULL;
        bool need_full_reset =
                test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
@@ -4418,11 +4474,22 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
                if (!ring || !ring->sched.thread)
                        continue;
 
+               /*clear job fence from fence drv to avoid force_completion
+                *leave NULL and vm flush fence in fence drv */
+               for (j = 0; j <= ring->fence_drv.num_fences_mask; j++) {
+                       struct dma_fence *old, **ptr;
+
+                       ptr = &ring->fence_drv.fences[j];
+                       old = rcu_dereference_protected(*ptr, 1);
+                       if (old && test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &old->flags)) {
+                               RCU_INIT_POINTER(*ptr, NULL);
+                       }
+               }
                /* after all hw jobs are reset, hw fence is meaningless, so force_completion */
                amdgpu_fence_driver_force_completion(ring);
        }
 
-       if(job)
+       if (job && job->vm)
                drm_sched_increase_karma(&job->base);
 
        r = amdgpu_reset_prepare_hwcontext(adev, reset_context);
@@ -4886,7 +4953,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                        DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
                                job ? job->base.id : -1, hive->hive_id);
                        amdgpu_put_xgmi_hive(hive);
-                       if (job)
+                       if (job && job->vm)
                                drm_sched_increase_karma(&job->base);
                        return 0;
                }
@@ -4910,7 +4977,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                                        job ? job->base.id : -1);
 
                /* even we skipped this reset, still need to set the job to guilty */
-               if (job)
+               if (job && job->vm)
                        drm_sched_increase_karma(&job->base);
                goto skip_recovery;
        }
@@ -5277,6 +5344,10 @@ int amdgpu_device_baco_exit(struct drm_device *dev)
            adev->nbio.funcs->enable_doorbell_interrupt)
                adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
 
+       if (amdgpu_passthrough(adev) &&
+           adev->nbio.funcs->clear_doorbell_interrupt)
+               adev->nbio.funcs->clear_doorbell_interrupt(adev);
+
        return 0;
 }
 
This page took 0.046034 seconds and 4 git commands to generate.