diff options
author | Joonas Lahtinen <joonas.lahtinen@linux.intel.com> | 2017-12-07 06:35:32 -0500 |
---|---|---|
committer | Joonas Lahtinen <joonas.lahtinen@linux.intel.com> | 2017-12-07 06:35:33 -0500 |
commit | d85936ab62f902ab84be7a021aa013d4b5dfe292 (patch) | |
tree | 93e198d5800836cbbb28cb61702a7c967df1645c | |
parent | 7a8b70535037a7d8503d12c1a5abbbc8aa5d709a (diff) | |
parent | 11474e9091cf2002e948647fd9f63a7f027e488a (diff) |
Merge tag 'gvt-fixes-2017-12-06' of https://github.com/intel/gvt-linux into drm-intel-fixes
gvt-fixes-2017-12-06
- Fix invalid hw reg read value for vGPU (Xiong)
- Fix qemu warning on PCI ROM bar missing (Changbin)
- Workaround preemption regression (Zhenyu)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171206075105.wlh2ojubjczlstox@zhen-hp.sh.intel.com
-rw-r--r-- | drivers/gpu/drm/i915/gvt/cfg_space.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/gvt/handlers.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/gvt/mmio.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/gvt/scheduler.c | 22 |
4 files changed, 81 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index ab19545d59a1..4ce2e6bd0680 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c | |||
@@ -208,6 +208,20 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu, | |||
208 | return 0; | 208 | return 0; |
209 | } | 209 | } |
210 | 210 | ||
211 | static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu, | ||
212 | unsigned int offset, void *p_data, unsigned int bytes) | ||
213 | { | ||
214 | u32 *pval = (u32 *)(vgpu_cfg_space(vgpu) + offset); | ||
215 | u32 new = *(u32 *)(p_data); | ||
216 | |||
217 | if ((new & PCI_ROM_ADDRESS_MASK) == PCI_ROM_ADDRESS_MASK) | ||
218 | /* We don't have rom, return size of 0. */ | ||
219 | *pval = 0; | ||
220 | else | ||
221 | vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); | ||
222 | return 0; | ||
223 | } | ||
224 | |||
211 | static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, | 225 | static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, |
212 | void *p_data, unsigned int bytes) | 226 | void *p_data, unsigned int bytes) |
213 | { | 227 | { |
@@ -300,6 +314,11 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, | |||
300 | } | 314 | } |
301 | 315 | ||
302 | switch (rounddown(offset, 4)) { | 316 | switch (rounddown(offset, 4)) { |
317 | case PCI_ROM_ADDRESS: | ||
318 | if (WARN_ON(!IS_ALIGNED(offset, 4))) | ||
319 | return -EINVAL; | ||
320 | return emulate_pci_rom_bar_write(vgpu, offset, p_data, bytes); | ||
321 | |||
303 | case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5: | 322 | case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5: |
304 | if (WARN_ON(!IS_ALIGNED(offset, 4))) | 323 | if (WARN_ON(!IS_ALIGNED(offset, 4))) |
305 | return -EINVAL; | 324 | return -EINVAL; |
@@ -375,6 +394,8 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, | |||
375 | pci_resource_len(gvt->dev_priv->drm.pdev, 0); | 394 | pci_resource_len(gvt->dev_priv->drm.pdev, 0); |
376 | vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size = | 395 | vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size = |
377 | pci_resource_len(gvt->dev_priv->drm.pdev, 2); | 396 | pci_resource_len(gvt->dev_priv->drm.pdev, 2); |
397 | |||
398 | memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4); | ||
378 | } | 399 | } |
379 | 400 | ||
380 | /** | 401 | /** |
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 44cd5ff5e97d..1f840f6b81bb 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c | |||
@@ -137,17 +137,26 @@ static int new_mmio_info(struct intel_gvt *gvt, | |||
137 | return 0; | 137 | return 0; |
138 | } | 138 | } |
139 | 139 | ||
140 | static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg) | 140 | /** |
141 | * intel_gvt_render_mmio_to_ring_id - convert a mmio offset into ring id | ||
142 | * @gvt: a GVT device | ||
143 | * @offset: register offset | ||
144 | * | ||
145 | * Returns: | ||
146 | * Ring ID on success, negative error code if failed. | ||
147 | */ | ||
148 | int intel_gvt_render_mmio_to_ring_id(struct intel_gvt *gvt, | ||
149 | unsigned int offset) | ||
141 | { | 150 | { |
142 | enum intel_engine_id id; | 151 | enum intel_engine_id id; |
143 | struct intel_engine_cs *engine; | 152 | struct intel_engine_cs *engine; |
144 | 153 | ||
145 | reg &= ~GENMASK(11, 0); | 154 | offset &= ~GENMASK(11, 0); |
146 | for_each_engine(engine, gvt->dev_priv, id) { | 155 | for_each_engine(engine, gvt->dev_priv, id) { |
147 | if (engine->mmio_base == reg) | 156 | if (engine->mmio_base == offset) |
148 | return id; | 157 | return id; |
149 | } | 158 | } |
150 | return -1; | 159 | return -ENODEV; |
151 | } | 160 | } |
152 | 161 | ||
153 | #define offset_to_fence_num(offset) \ | 162 | #define offset_to_fence_num(offset) \ |
@@ -1398,18 +1407,36 @@ static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset, | |||
1398 | static int mmio_read_from_hw(struct intel_vgpu *vgpu, | 1407 | static int mmio_read_from_hw(struct intel_vgpu *vgpu, |
1399 | unsigned int offset, void *p_data, unsigned int bytes) | 1408 | unsigned int offset, void *p_data, unsigned int bytes) |
1400 | { | 1409 | { |
1401 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | 1410 | struct intel_gvt *gvt = vgpu->gvt; |
1411 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
1412 | int ring_id; | ||
1413 | u32 ring_base; | ||
1414 | |||
1415 | ring_id = intel_gvt_render_mmio_to_ring_id(gvt, offset); | ||
1416 | /** | ||
1417 | * Read HW reg in following case | ||
1418 | * a. the offset isn't a ring mmio | ||
1419 | * b. the offset's ring is running on hw. | ||
1420 | * c. the offset is ring time stamp mmio | ||
1421 | */ | ||
1422 | if (ring_id >= 0) | ||
1423 | ring_base = dev_priv->engine[ring_id]->mmio_base; | ||
1424 | |||
1425 | if (ring_id < 0 || vgpu == gvt->scheduler.engine_owner[ring_id] || | ||
1426 | offset == i915_mmio_reg_offset(RING_TIMESTAMP(ring_base)) || | ||
1427 | offset == i915_mmio_reg_offset(RING_TIMESTAMP_UDW(ring_base))) { | ||
1428 | mmio_hw_access_pre(dev_priv); | ||
1429 | vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset)); | ||
1430 | mmio_hw_access_post(dev_priv); | ||
1431 | } | ||
1402 | 1432 | ||
1403 | mmio_hw_access_pre(dev_priv); | ||
1404 | vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset)); | ||
1405 | mmio_hw_access_post(dev_priv); | ||
1406 | return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); | 1433 | return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); |
1407 | } | 1434 | } |
1408 | 1435 | ||
1409 | static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | 1436 | static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, |
1410 | void *p_data, unsigned int bytes) | 1437 | void *p_data, unsigned int bytes) |
1411 | { | 1438 | { |
1412 | int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); | 1439 | int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset); |
1413 | struct intel_vgpu_execlist *execlist; | 1440 | struct intel_vgpu_execlist *execlist; |
1414 | u32 data = *(u32 *)p_data; | 1441 | u32 data = *(u32 *)p_data; |
1415 | int ret = 0; | 1442 | int ret = 0; |
@@ -1436,7 +1463,7 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | |||
1436 | void *p_data, unsigned int bytes) | 1463 | void *p_data, unsigned int bytes) |
1437 | { | 1464 | { |
1438 | u32 data = *(u32 *)p_data; | 1465 | u32 data = *(u32 *)p_data; |
1439 | int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); | 1466 | int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset); |
1440 | bool enable_execlist; | 1467 | bool enable_execlist; |
1441 | 1468 | ||
1442 | write_vreg(vgpu, offset, p_data, bytes); | 1469 | write_vreg(vgpu, offset, p_data, bytes); |
diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index 32cd64ddad26..dbc04ad2c7a1 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h | |||
@@ -65,6 +65,8 @@ struct intel_gvt_mmio_info { | |||
65 | struct hlist_node node; | 65 | struct hlist_node node; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | int intel_gvt_render_mmio_to_ring_id(struct intel_gvt *gvt, | ||
69 | unsigned int reg); | ||
68 | unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt); | 70 | unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt); |
69 | bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device); | 71 | bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device); |
70 | 72 | ||
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 3ac1dc97a7a0..69f8f0d155b9 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c | |||
@@ -131,6 +131,20 @@ static inline bool is_gvt_request(struct drm_i915_gem_request *req) | |||
131 | return i915_gem_context_force_single_submission(req->ctx); | 131 | return i915_gem_context_force_single_submission(req->ctx); |
132 | } | 132 | } |
133 | 133 | ||
134 | static void save_ring_hw_state(struct intel_vgpu *vgpu, int ring_id) | ||
135 | { | ||
136 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
137 | u32 ring_base = dev_priv->engine[ring_id]->mmio_base; | ||
138 | i915_reg_t reg; | ||
139 | |||
140 | reg = RING_INSTDONE(ring_base); | ||
141 | vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) = I915_READ_FW(reg); | ||
142 | reg = RING_ACTHD(ring_base); | ||
143 | vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) = I915_READ_FW(reg); | ||
144 | reg = RING_ACTHD_UDW(ring_base); | ||
145 | vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) = I915_READ_FW(reg); | ||
146 | } | ||
147 | |||
134 | static int shadow_context_status_change(struct notifier_block *nb, | 148 | static int shadow_context_status_change(struct notifier_block *nb, |
135 | unsigned long action, void *data) | 149 | unsigned long action, void *data) |
136 | { | 150 | { |
@@ -175,9 +189,12 @@ static int shadow_context_status_change(struct notifier_block *nb, | |||
175 | atomic_set(&workload->shadow_ctx_active, 1); | 189 | atomic_set(&workload->shadow_ctx_active, 1); |
176 | break; | 190 | break; |
177 | case INTEL_CONTEXT_SCHEDULE_OUT: | 191 | case INTEL_CONTEXT_SCHEDULE_OUT: |
178 | case INTEL_CONTEXT_SCHEDULE_PREEMPTED: | 192 | save_ring_hw_state(workload->vgpu, ring_id); |
179 | atomic_set(&workload->shadow_ctx_active, 0); | 193 | atomic_set(&workload->shadow_ctx_active, 0); |
180 | break; | 194 | break; |
195 | case INTEL_CONTEXT_SCHEDULE_PREEMPTED: | ||
196 | save_ring_hw_state(workload->vgpu, ring_id); | ||
197 | break; | ||
181 | default: | 198 | default: |
182 | WARN_ON(1); | 199 | WARN_ON(1); |
183 | return NOTIFY_OK; | 200 | return NOTIFY_OK; |
@@ -740,6 +757,9 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu) | |||
740 | if (IS_ERR(vgpu->shadow_ctx)) | 757 | if (IS_ERR(vgpu->shadow_ctx)) |
741 | return PTR_ERR(vgpu->shadow_ctx); | 758 | return PTR_ERR(vgpu->shadow_ctx); |
742 | 759 | ||
760 | if (INTEL_INFO(vgpu->gvt->dev_priv)->has_logical_ring_preemption) | ||
761 | vgpu->shadow_ctx->priority = INT_MAX; | ||
762 | |||
743 | vgpu->shadow_ctx->engine[RCS].initialised = true; | 763 | vgpu->shadow_ctx->engine[RCS].initialised = true; |
744 | 764 | ||
745 | bitmap_zero(vgpu->shadow_ctx_desc_updated, I915_NUM_ENGINES); | 765 | bitmap_zero(vgpu->shadow_ctx_desc_updated, I915_NUM_ENGINES); |