drm/i915/gvt: Set initial PORT_CLK_SEL vreg for BDW
authorXiong Zhang <xiong.y.zhang@intel.com>
Tue, 20 Jun 2017 03:37:22 +0000 (11:37 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Tue, 27 Jun 2017 09:29:19 +0000 (17:29 +0800)
On BDW, when host physical screen and guest virtual screen aren't on
the same DDI port, guest i915 driver prints the following error and
stop running.
[    6.775873] BUG: unable to handle kernel NULL pointer dereference
at 0000000000000068
[    6.775928] IP: intel_ddi_clock_get+0x81/0x430 [i915]
[    6.776206] Call Trace:
[    6.776233]  ? vgpu_read32+0x4f/0x100 [i915]
[    6.776264]  intel_ddi_get_config+0x11c/0x230 [i915]
[    6.776298]  intel_modeset_setup_hw_state+0x313/0xd40 [i915]
[    6.776334]  intel_modeset_init+0xe49/0x18d0 [i915]
[    6.776368]  ? vgpu_write32+0x53/0x100 [i915]
[    6.776731]  ? intel_i2c_reset+0x42/0x50 [i915]
[    6.777085]  ? intel_setup_gmbus+0x32a/0x350 [i915]
[    6.777427]  i915_driver_load+0xabc/0x14d0 [i915]
[    6.777768]  i915_pci_probe+0x4f/0x70 [i915]

The null pointer is guest intel_crtc_state->shared_dpll which is
setted in haswell_get_ddi_pll(). When guest and host screen are
on different DDI port, host driver won't set PORT_CLK_SET(guest_port),
so haswell_get_ddi_pll() will return null and don't set
pipe_config->shared_dpll, once the following program refernce this
structure, it will print the above error.

This patch set the initial val of guest PORT_CLK_SEL(guest_port) to
LCPLL_810. And guest i915 driver will reset this value according to
guest screen mode.

Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/display.c

index e0261fcc5b504ef6d91766bc40b999a5a9d058bc..818e94907c3b3b070a4b72d58b35e53b99eb5d82 100644 (file)
@@ -197,6 +197,12 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                        (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
                        (PORT_B << TRANS_DDI_PORT_SHIFT) |
                        TRANS_DDI_FUNC_ENABLE);
+               if (IS_BROADWELL(dev_priv)) {
+                       vgpu_vreg(vgpu, PORT_CLK_SEL(PORT_B)) &=
+                               ~PORT_CLK_SEL_MASK;
+                       vgpu_vreg(vgpu, PORT_CLK_SEL(PORT_B)) |=
+                               PORT_CLK_SEL_LCPLL_810;
+               }
                vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_B)) |= DDI_BUF_CTL_ENABLE;
                vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_B)) &= ~DDI_BUF_IS_IDLE;
                vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT;
@@ -211,6 +217,12 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                        (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
                        (PORT_C << TRANS_DDI_PORT_SHIFT) |
                        TRANS_DDI_FUNC_ENABLE);
+               if (IS_BROADWELL(dev_priv)) {
+                       vgpu_vreg(vgpu, PORT_CLK_SEL(PORT_C)) &=
+                               ~PORT_CLK_SEL_MASK;
+                       vgpu_vreg(vgpu, PORT_CLK_SEL(PORT_C)) |=
+                               PORT_CLK_SEL_LCPLL_810;
+               }
                vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_C)) |= DDI_BUF_CTL_ENABLE;
                vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_C)) &= ~DDI_BUF_IS_IDLE;
                vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED;
@@ -225,6 +237,12 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                        (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
                        (PORT_D << TRANS_DDI_PORT_SHIFT) |
                        TRANS_DDI_FUNC_ENABLE);
+               if (IS_BROADWELL(dev_priv)) {
+                       vgpu_vreg(vgpu, PORT_CLK_SEL(PORT_D)) &=
+                               ~PORT_CLK_SEL_MASK;
+                       vgpu_vreg(vgpu, PORT_CLK_SEL(PORT_D)) |=
+                               PORT_CLK_SEL_LCPLL_810;
+               }
                vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_D)) |= DDI_BUF_CTL_ENABLE;
                vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_D)) &= ~DDI_BUF_IS_IDLE;
                vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED;