drm/amdgpu:changes of virtualization cases probe (v3)
authorMonk Liu <Monk.Liu@amd.com>
Thu, 31 Mar 2016 05:26:59 +0000 (13:26 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 19 Sep 2016 18:45:52 +0000 (14:45 -0400)
1,Changes on virtualization detections
2,Don't load smu & mc firmware if using sr-iov bios
3,skip vPost for sriov & force vPost if dev pass-through

v2: agd: squash in Rays's fix for the missed SI case
v3: agd: squash in additional fixes for CIK, SI, cleanup

Signed-off-by: Monk Liu <Monk.Liu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/fiji_smc.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/iceland_smc.c
drivers/gpu/drm/amd/amdgpu/si.c
drivers/gpu/drm/amd/amdgpu/tonga_smc.c
drivers/gpu/drm/amd/amdgpu/vi.c

index ee45d9f..fb8d603 100644 (file)
@@ -1827,6 +1827,7 @@ struct amdgpu_asic_funcs {
        bool (*read_disabled_bios)(struct amdgpu_device *adev);
        bool (*read_bios_from_rom)(struct amdgpu_device *adev,
                                   u8 *bios, u32 length_bytes);
+       void (*detect_hw_virtualization) (struct amdgpu_device *adev);
        int (*read_register)(struct amdgpu_device *adev, u32 se_num,
                             u32 sh_num, u32 reg_offset, u32 *value);
        void (*set_vga_state)(struct amdgpu_device *adev, bool state);
@@ -1836,8 +1837,6 @@ struct amdgpu_asic_funcs {
        /* MM block clocks */
        int (*set_uvd_clocks)(struct amdgpu_device *adev, u32 vclk, u32 dclk);
        int (*set_vce_clocks)(struct amdgpu_device *adev, u32 evclk, u32 ecclk);
-       /* query virtual capabilities */
-       u32 (*get_virtual_caps)(struct amdgpu_device *adev);
        /* static power management */
        int (*get_pcie_lanes)(struct amdgpu_device *adev);
        void (*set_pcie_lanes)(struct amdgpu_device *adev, int lanes);
@@ -1934,15 +1933,36 @@ struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev);
 void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);
 
 
+#define AMDGPU_SRIOV_CAPS_SRIOV_VBIOS  (1 << 0) /* vBIOS is sr-iov ready */
+#define AMDGPU_SRIOV_CAPS_ENABLE_IOV   (1 << 1) /* sr-iov is enabled on this GPU */
+#define AMDGPU_SRIOV_CAPS_IS_VF        (1 << 2) /* this GPU is a virtual function */
+#define AMDGPU_PASSTHROUGH_MODE        (1 << 3) /* thw whole GPU is pass through for VM */
 /* GPU virtualization */
-#define AMDGPU_VIRT_CAPS_SRIOV_EN       (1 << 0)
-#define AMDGPU_VIRT_CAPS_IS_VF          (1 << 1)
 struct amdgpu_virtualization {
-       bool supports_sr_iov;
-       bool is_virtual;
-       u32 caps;
+       uint32_t virtual_caps;
 };
 
+#define amdgpu_sriov_enabled(adev) \
+((adev)->virtualization.virtual_caps & AMDGPU_SRIOV_CAPS_ENABLE_IOV)
+
+#define amdgpu_sriov_vf(adev) \
+((adev)->virtualization.virtual_caps & AMDGPU_SRIOV_CAPS_IS_VF)
+
+#define amdgpu_sriov_bios(adev) \
+((adev)->virtualization.virtual_caps & AMDGPU_SRIOV_CAPS_SRIOV_VBIOS)
+
+#define amdgpu_passthrough(adev) \
+((adev)->virtualization.virtual_caps & AMDGPU_PASSTHROUGH_MODE)
+
+static inline bool is_virtual_machine(void)
+{
+#ifdef CONFIG_X86
+       return boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#else
+       return false;
+#endif
+}
+
 /*
  * Core structure, functions and helpers.
  */
@@ -2260,12 +2280,12 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
 #define amdgpu_asic_get_xclk(adev) (adev)->asic_funcs->get_xclk((adev))
 #define amdgpu_asic_set_uvd_clocks(adev, v, d) (adev)->asic_funcs->set_uvd_clocks((adev), (v), (d))
 #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec))
-#define amdgpu_asic_get_virtual_caps(adev) ((adev)->asic_funcs->get_virtual_caps((adev)))
 #define amdgpu_get_pcie_lanes(adev) (adev)->asic_funcs->get_pcie_lanes((adev))
 #define amdgpu_set_pcie_lanes(adev, l) (adev)->asic_funcs->set_pcie_lanes((adev), (l))
 #define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev))
 #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev))
 #define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l))
+#define amdgpu_asic_detect_hw_virtualization(adev) (adev)->asic_funcs->detect_hw_virtualization((adev))
 #define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v)))
 #define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid))
 #define amdgpu_gart_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gart.gart_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags))
index d97efc1..4acc92b 100644 (file)
@@ -110,7 +110,7 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
                    bool always_indirect)
 {
        trace_amdgpu_mm_wreg(adev->pdev->device, reg, v);
-       
+
        if ((reg * 4) < adev->rmmio_size && !always_indirect)
                writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
        else {
@@ -1485,13 +1485,10 @@ static int amdgpu_resume(struct amdgpu_device *adev)
        return 0;
 }
 
-static bool amdgpu_device_is_virtual(void)
+static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
 {
-#ifdef CONFIG_X86
-       return boot_cpu_has(X86_FEATURE_HYPERVISOR);
-#else
-       return false;
-#endif
+       if (amdgpu_atombios_has_gpu_virtualization_table(adev))
+               adev->virtualization.virtual_caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
 }
 
 /**
@@ -1648,25 +1645,25 @@ int amdgpu_device_init(struct amdgpu_device *adev,
                goto failed;
        }
 
-       /* See if the asic supports SR-IOV */
-       adev->virtualization.supports_sr_iov =
-               amdgpu_atombios_has_gpu_virtualization_table(adev);
-
-       /* Check if we are executing in a virtualized environment */
-       adev->virtualization.is_virtual = amdgpu_device_is_virtual();
-       adev->virtualization.caps = amdgpu_asic_get_virtual_caps(adev);
+       /* detect if we are with an SRIOV vbios */
+       amdgpu_device_detect_sriov_bios(adev);
 
        /* Post card if necessary */
-       if (!amdgpu_card_posted(adev) ||
-           (adev->virtualization.is_virtual &&
-            !(adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN))) {
+       if (!amdgpu_sriov_vf(adev) &&
+               (!amdgpu_card_posted(adev) || amdgpu_passthrough(adev))) {
                if (!adev->bios) {
                        dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n");
                        r = -EINVAL;
                        goto failed;
                }
                DRM_INFO("GPU not posted. posting now...\n");
-               amdgpu_atom_asic_init(adev->mode_info.atom_context);
+               r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
+               if (r) {
+                       dev_err(adev->dev, "gpu post error!\n");
+                       goto failed;
+               }
+       } else {
+               DRM_INFO("GPU post is not needed\n");
        }
 
        /* Initialize clocks */
index c96ae10..0c5f36d 100644 (file)
@@ -485,7 +485,7 @@ amdgpu_pci_shutdown(struct pci_dev *pdev)
        /* if we are running in a VM, make sure the device
         * torn down properly on reboot/shutdown
         */
-       if (adev->virtualization.is_virtual)
+       if (amdgpu_passthrough(adev))
                amdgpu_pci_remove(pdev);
 }
 
index 825de80..a845b6a 100644 (file)
@@ -963,12 +963,6 @@ static bool cik_read_bios_from_rom(struct amdgpu_device *adev,
        return true;
 }
 
-static u32 cik_get_virtual_caps(struct amdgpu_device *adev)
-{
-       /* CIK does not support SR-IOV */
-       return 0;
-}
-
 static const struct amdgpu_allowed_register_entry cik_allowed_read_registers[] = {
        {mmGRBM_STATUS, false},
        {mmGB_ADDR_CONFIG, false},
@@ -1641,6 +1635,12 @@ static uint32_t cik_get_rev_id(struct amdgpu_device *adev)
                >> CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT;
 }
 
+static void cik_detect_hw_virtualization(struct amdgpu_device *adev)
+{
+       if (is_virtual_machine()) /* passthrough mode */
+               adev->virtualization.virtual_caps |= AMDGPU_PASSTHROUGH_MODE;
+}
+
 static const struct amdgpu_ip_block_version bonaire_ip_blocks[] =
 {
        /* ORDER MATTERS! */
@@ -2384,13 +2384,13 @@ static const struct amdgpu_asic_funcs cik_asic_funcs =
 {
        .read_disabled_bios = &cik_read_disabled_bios,
        .read_bios_from_rom = &cik_read_bios_from_rom,
+       .detect_hw_virtualization = cik_detect_hw_virtualization,
        .read_register = &cik_read_register,
        .reset = &cik_asic_reset,
        .set_vga_state = &cik_vga_set_state,
        .get_xclk = &cik_get_xclk,
        .set_uvd_clocks = &cik_set_uvd_clocks,
        .set_vce_clocks = &cik_set_vce_clocks,
-       .get_virtual_caps = &cik_get_virtual_caps,
 };
 
 static int cik_common_early_init(void *handle)
index b3e19ba..8cfb0a3 100644 (file)
@@ -275,7 +275,7 @@ static int fiji_smu_upload_firmware_image(struct amdgpu_device *adev)
        /* Skip SMC ucode loading on SR-IOV capable boards.
         * vbios does this for us in asic_init in that case.
         */
-       if (adev->virtualization.supports_sr_iov)
+       if (amdgpu_sriov_bios(adev))
                return 0;
 
        hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
index 8e7127f..6ec8e01 100644 (file)
@@ -261,8 +261,10 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
 
        /* Skip MC ucode loading on SR-IOV capable boards.
         * vbios does this for us in asic_init in that case.
+        * Skip MC ucode loading on VF, because hypervisor will do that
+        * for this adaptor.
         */
-       if (adev->virtualization.supports_sr_iov)
+       if (amdgpu_sriov_bios(adev))
                return 0;
 
        hdr = (const struct mc_firmware_header_v1_0 *)adev->mc.fw->data;
index ef7c27d..c6e004a 100644 (file)
@@ -282,7 +282,7 @@ static int iceland_smu_upload_firmware_image(struct amdgpu_device *adev)
        /* Skip SMC ucode loading on SR-IOV capable boards.
         * vbios does this for us in asic_init in that case.
         */
-       if (adev->virtualization.supports_sr_iov)
+       if (amdgpu_sriov_bios(adev))
                return 0;
 
        hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
index fee76b8..dc9511c 100644 (file)
@@ -952,12 +952,6 @@ static void si_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
        spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
 }
 
-static u32 si_get_virtual_caps(struct amdgpu_device *adev)
-{
-       /* SI does not support SR-IOV */
-       return 0;
-}
-
 static struct amdgpu_allowed_register_entry si_allowed_read_registers[] = {
        {GRBM_STATUS, false},
        {GB_ADDR_CONFIG, false},
@@ -1124,16 +1118,22 @@ static int si_set_uvd_clocks(struct amdgpu_device *adev, u32 vclk, u32 dclk)
        return 0;
 }
 
+static void si_detect_hw_virtualization(struct amdgpu_device *adev)
+{
+       if (is_virtual_machine()) /* passthrough mode */
+               adev->virtualization.virtual_caps |= AMDGPU_PASSTHROUGH_MODE;
+}
+
 static const struct amdgpu_asic_funcs si_asic_funcs =
 {
        .read_disabled_bios = &si_read_disabled_bios,
+       .detect_hw_virtualization = si_detect_hw_virtualization,
        .read_register = &si_read_register,
        .reset = &si_asic_reset,
        .set_vga_state = &si_vga_set_state,
        .get_xclk = &si_get_xclk,
        .set_uvd_clocks = &si_set_uvd_clocks,
        .set_vce_clocks = NULL,
-       .get_virtual_caps = &si_get_virtual_caps,
 };
 
 static uint32_t si_get_rev_id(struct amdgpu_device *adev)
index 940de18..1e71e81 100644 (file)
@@ -275,7 +275,7 @@ static int tonga_smu_upload_firmware_image(struct amdgpu_device *adev)
        /* Skip SMC ucode loading on SR-IOV capable boards.
         * vbios does this for us in asic_init in that case.
         */
-       if (adev->virtualization.supports_sr_iov)
+       if (amdgpu_sriov_bios(adev))
                return 0;
 
        hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
index b688e2f..a8154d0 100644 (file)
@@ -445,18 +445,21 @@ static bool vi_read_bios_from_rom(struct amdgpu_device *adev,
        return true;
 }
 
-static u32 vi_get_virtual_caps(struct amdgpu_device *adev)
+static void vi_detect_hw_virtualization(struct amdgpu_device *adev)
 {
-       u32 caps = 0;
-       u32 reg = RREG32(mmBIF_IOV_FUNC_IDENTIFIER);
+       uint32_t reg = RREG32(mmBIF_IOV_FUNC_IDENTIFIER);
+       /* bit0: 0 means pf and 1 means vf */
+       /* bit31: 0 means disable IOV and 1 means enable */
+       if (reg & 1)
+               adev->virtualization.virtual_caps |= AMDGPU_SRIOV_CAPS_IS_VF;
 
-       if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, IOV_ENABLE))
-               caps |= AMDGPU_VIRT_CAPS_SRIOV_EN;
+       if (reg & 0x80000000)
+               adev->virtualization.virtual_caps |= AMDGPU_SRIOV_CAPS_ENABLE_IOV;
 
-       if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, FUNC_IDENTIFIER))
-               caps |= AMDGPU_VIRT_CAPS_IS_VF;
-
-       return caps;
+       if (reg == 0) {
+               if (is_virtual_machine()) /* passthrough mode exclus sr-iov mode */
+                       adev->virtualization.virtual_caps |= AMDGPU_PASSTHROUGH_MODE;
+       }
 }
 
 static const struct amdgpu_allowed_register_entry tonga_allowed_read_registers[] = {
@@ -1521,13 +1524,13 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =
 {
        .read_disabled_bios = &vi_read_disabled_bios,
        .read_bios_from_rom = &vi_read_bios_from_rom,
+       .detect_hw_virtualization = vi_detect_hw_virtualization,
        .read_register = &vi_read_register,
        .reset = &vi_asic_reset,
        .set_vga_state = &vi_vga_set_state,
        .get_xclk = &vi_get_xclk,
        .set_uvd_clocks = &vi_set_uvd_clocks,
        .set_vce_clocks = &vi_set_vce_clocks,
-       .get_virtual_caps = &vi_get_virtual_caps,
 };
 
 static int vi_common_early_init(void *handle)
@@ -1657,6 +1660,10 @@ static int vi_common_early_init(void *handle)
                return -EINVAL;
        }
 
+       /* in early init stage, vbios code won't work */
+       if (adev->asic_funcs->detect_hw_virtualization)
+               amdgpu_asic_detect_hw_virtualization(adev);
+
        if (amdgpu_smc_load_fw && smc_enabled)
                adev->firmware.smu_load = true;