History

Merge tag 'drm-fixes-2023-01-13' of git://anongit.freedesktop.org/drm/drm

Pull drm fixes from Dave Airlie: "There is a bit of a post-holiday build up here I expect, small fixes across the board, amdgpu and msm being the main leaders, with others having a few. One code removal patch for nouveau: buddy: - benchmark regression fix for top-down buddy allocation panel: - add Lenovo panel orientation quirk ttm: - fix kernel oops regression amdgpu: - fix missing fence references - fix missing pipeline sync fencing - SMU13 fan speed fix - SMU13 fix power cap handling - SMU13 BACO fix - Fix a possible segfault in bo validation error case - Delay removal of firmware framebuffer - Fix error when unloading amdkfd: - SVM fix when clearing vram - GC11 fix for multi-GPU i915: - Reserve enough fence slot for i915_vma_unbind_vsync - Fix potential use after free - Reset engines twice in case of reset failure - Use multi-cast registers for SVG Unit registers msm: - display: - doc warning fixes - dt attribs cleanups - memory leak fix - error handing in hdmi probe fix - dp_aux_isr incorrect signalling fix - shutdown path fix - accel: - a5xx: fix quirks to be a bitmask - a6xx: fix gx halt to avoid 1s hang - kexec shutdown fix - fix potential double free vmwgfx: - drop rcu usage to make code more robust virtio: - fix use-after-free in gem handle code nouveau: - drop unused nouveau_fbcon.c" * tag 'drm-fixes-2023-01-13' of git://anongit.freedesktop.org/drm/drm: (35 commits) drm: Optimize drm buddy top-down allocation method drm/ttm: Fix a regression causing kernel oops'es drm/i915/gt: Cover rest of SVG unit MCR registers drm/nouveau: Remove file nouveau_fbcon.c drm/amdkfd: Fix NULL pointer error for GC 11.0.1 on mGPU drm/amd/pm/smu13: BACO is supported when it's in BACO state drm/amdkfd: Add sync after creating vram bo drm/i915/gt: Reset twice drm/amdgpu: fix pipeline sync v2 drm/vmwgfx: Remove rcu locks from user resources drm/virtio: Fix GEM handle creation UAF drm/amdgpu: Fixed bug on error when unloading amdgpu drm/amd: Delay removal of the firmware framebuffer drm/amdgpu: Fix potential NULL dereference drm/i915: Fix potential context UAFs drm/i915: Reserve enough fence slot for i915_vma_unbind_async drm: Add orientation quirk for Lenovo ideapad D330-10IGL drm/msm/a6xx: Avoid gx gbit halt during rpm suspend drm/msm/adreno: Make adreno quirks not overwrite each other drm/msm: another fix for the headless Adreno GPU ...

Linus Torvalds committed 3 years ago

Commit ff5ebaf2 parents d45b832 e695bc743 files · +332 −950Browse files

Unified · Split

43 files
  1. Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +1 −3
  2. Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml +0 −1
  3. Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml +0 −1
  4. Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml +4 −0
  5. Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml +1 −1
  6. Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml +1 −1
  7. drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +1 −1
  8. drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +34 −17
  9. drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +8 −0
  10. drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +0 −6
  11. drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +3 −2
  12. drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +3 −1
  13. drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +1 −1
  14. drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +1 −1
  15. drivers/gpu/drm/amd/amdkfd/kfd_svm.c +9 −0
  16. drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +6 −2
  17. drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +1 −0
  18. drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +1 −0
  19. drivers/gpu/drm/drm_buddy.c +54 −27
  20. drivers/gpu/drm/drm_panel_orientation_quirks.c +6 −0
  21. drivers/gpu/drm/i915/gem/i915_gem_context.c +18 −6
  22. drivers/gpu/drm/i915/gt/intel_gt_regs.h +2 −2
  23. drivers/gpu/drm/i915/gt/intel_reset.c +28 −6
  24. drivers/gpu/drm/i915/gt/intel_workarounds.c +2 −2
  25. drivers/gpu/drm/i915/i915_vma.c +1 −1
  26. drivers/gpu/drm/msm/adreno/a6xx_gmu.c +9 −6
  27. drivers/gpu/drm/msm/adreno/a6xx_gpu.c +7 −0
  28. drivers/gpu/drm/msm/adreno/a6xx_gpu.h +1 −0
  29. drivers/gpu/drm/msm/adreno/adreno_gpu.h +4 −6
  30. drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +1 −2
  31. drivers/gpu/drm/msm/dp/dp_aux.c +4 −0
  32. drivers/gpu/drm/msm/hdmi/hdmi.c +10 −2
  33. drivers/gpu/drm/msm/msm_drv.c +1 −1
  34. drivers/gpu/drm/msm/msm_mdss.c +4 −2
  35. drivers/gpu/drm/nouveau/nouveau_fbcon.c +0 −613
  36. drivers/gpu/drm/ttm/ttm_bo_util.c +1 −1
  37. drivers/gpu/drm/virtio/virtgpu_ioctl.c +17 −2
  38. drivers/gpu/drm/vmwgfx/ttm_object.c +4 −37
  39. drivers/gpu/drm/vmwgfx/ttm_object.h +0 −14
  40. drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +0 −38
  41. drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +1 −17
  42. drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +82 −94
  43. drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +0 −33
Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml+1−3
@@ -32,7 +32,7 @@ properties: · 31 unmodified lines
32 - description: Display byte clock32 - description: Display byte clock
33 - description: Display byte interface clock33 - description: Display byte interface clock
34 - description: Display pixel clock34 - description: Display pixel clock
35 - description: Display escape clock35 - description: Display core clock
36 - description: Display AHB clock36 - description: Display AHB clock
37 - description: Display AXI clock37 - description: Display AXI clock
38 38
@@ -137,8 +137,6 @@ required: · 98 unmodified lines
137 - phys137 - phys
138 - assigned-clocks138 - assigned-clocks
139 - assigned-clock-parents139 - assigned-clock-parents
140 - power-domains
141 - operating-points-v2
142 - ports140 - ports
143 141
144additionalProperties: false142additionalProperties: false
Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml+0−1
@@ -69,7 +69,6 @@ required: · 68 unmodified lines
69 - compatible69 - compatible
70 - reg70 - reg
71 - reg-names71 - reg-names
72 - vdds-supply
73 72
74unevaluatedProperties: false73unevaluatedProperties: false
75 74
Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml+0−1
@@ -39,7 +39,6 @@ required: · 38 unmodified lines
39 - compatible39 - compatible
40 - reg40 - reg
41 - reg-names41 - reg-names
42 - vcca-supply
43 42
44unevaluatedProperties: false43unevaluatedProperties: false
45 44
Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml+4−0
@@ -34,6 +34,10 @@ properties: · 33 unmodified lines
34 vddio-supply:34 vddio-supply:
35 description: Phandle to vdd-io regulator device node.35 description: Phandle to vdd-io regulator device node.
36 36
37 qcom,dsi-phy-regulator-ldo-mode:
38 type: boolean
39 description: Indicates if the LDO mode PHY regulator is wanted.
40
37required:41required:
38 - compatible42 - compatible
39 - reg43 - reg
Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml+1−1
@@ -72,7 +72,7 @@ examples: · 71 unmodified lines
72 #include <dt-bindings/interconnect/qcom,qcm2290.h>72 #include <dt-bindings/interconnect/qcom,qcm2290.h>
73 #include <dt-bindings/power/qcom-rpmpd.h>73 #include <dt-bindings/power/qcom-rpmpd.h>
74 74
75 mdss@5e00000 {75 display-subsystem@5e00000 {
76 #address-cells = <1>;76 #address-cells = <1>;
77 #size-cells = <1>;77 #size-cells = <1>;
78 compatible = "qcom,qcm2290-mdss";78 compatible = "qcom,qcm2290-mdss";
Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml+1−1
@@ -62,7 +62,7 @@ examples: · 61 unmodified lines
62 #include <dt-bindings/interrupt-controller/arm-gic.h>62 #include <dt-bindings/interrupt-controller/arm-gic.h>
63 #include <dt-bindings/power/qcom-rpmpd.h>63 #include <dt-bindings/power/qcom-rpmpd.h>
64 64
65 mdss@5e00000 {65 display-subsystem@5e00000 {
66 #address-cells = <1>;66 #address-cells = <1>;
67 #size-cells = <1>;67 #size-cells = <1>;
68 compatible = "qcom,sm6115-mdss";68 compatible = "qcom,sm6115-mdss";
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c+1−1
@@ -2099,7 +2099,7 @@ int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device *adev, struct amdgpu_b · 2098 unmodified lines
2099 }2099 }
2100 2100
2101 amdgpu_amdkfd_remove_eviction_fence(2101 amdgpu_amdkfd_remove_eviction_fence(
2102 bo, bo->kfd_bo->process_info->eviction_fence);2102 bo, bo->vm_bo->vm->process_info->eviction_fence);
2103 2103
2104 amdgpu_bo_unreserve(bo);2104 amdgpu_bo_unreserve(bo);
2105 2105
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c+34−17
@@ -61,6 +61,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, · 60 unmodified lines
61 amdgpu_ctx_put(p->ctx);61 amdgpu_ctx_put(p->ctx);
62 return -ECANCELED;62 return -ECANCELED;
63 }63 }
64
65 amdgpu_sync_create(&p->sync);
64 return 0;66 return 0;
65}67}
66 68
@@ -452,18 +454,6 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p, · 385 unmodified lines
452 }454 }
453 455
454 r = amdgpu_sync_fence(&p->sync, fence);456 r = amdgpu_sync_fence(&p->sync, fence);
455 if (r)
456 goto error;
457
458 /*
459 * When we have an explicit dependency it might be necessary to insert a
460 * pipeline sync to make sure that all caches etc are flushed and the
461 * next job actually sees the results from the previous one.
462 */
463 if (fence->context == p->gang_leader->base.entity->fence_context)
464 r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
465
466error:
467 dma_fence_put(fence);457 dma_fence_put(fence);
468 return r;458 return r;
469}459}
@@ -1188,10 +1178,19 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 718 unmodified lines
1188static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)1178static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
1189{1179{
1190 struct amdgpu_fpriv *fpriv = p->filp->driver_priv;1180 struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
1181 struct drm_gpu_scheduler *sched;
1191 struct amdgpu_bo_list_entry *e;1182 struct amdgpu_bo_list_entry *e;
1183 struct dma_fence *fence;
1192 unsigned int i;1184 unsigned int i;
1193 int r;1185 int r;
1194 1186
1187 r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
1188 if (r) {
1189 if (r != -ERESTARTSYS)
1190 DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
1191 return r;
1192 }
1193
1195 list_for_each_entry(e, &p->validated, tv.head) {1194 list_for_each_entry(e, &p->validated, tv.head) {
1196 struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);1195 struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);
1197 struct dma_resv *resv = bo->tbo.base.resv;1196 struct dma_resv *resv = bo->tbo.base.resv;
@@ -1211,10 +1210,24 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) · 13 unmodified lines
1211 return r;1210 return r;
1212 }1211 }
1213 1212
1214 r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);1213 sched = p->gang_leader->base.entity->rq->sched;
1215 if (r && r != -ERESTARTSYS)1214 while ((fence = amdgpu_sync_get_fence(&p->sync))) {
1216 DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");1215 struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
1217 return r;1216
1217 /*
1218 * When we have an dependency it might be necessary to insert a
1219 * pipeline sync to make sure that all caches etc are flushed and the
1220 * next job actually sees the results from the previous one
1221 * before we start executing on the same scheduler ring.
1222 */
1223 if (!s_fence || s_fence->sched != sched)
1224 continue;
1225
1226 r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
1227 if (r)
1228 return r;
1229 }
1230 return 0;
1218}1231}
1219 1232
1220static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)1233static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
@@ -1254,9 +1267,12 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, · 33 unmodified lines
1254 continue;1267 continue;
1255 1268
1256 fence = &p->jobs[i]->base.s_fence->scheduled;1269 fence = &p->jobs[i]->base.s_fence->scheduled;
1270 dma_fence_get(fence);
1257 r = drm_sched_job_add_dependency(&leader->base, fence);1271 r = drm_sched_job_add_dependency(&leader->base, fence);
1258 if (r)1272 if (r) {
1273 dma_fence_put(fence);
1259 goto error_cleanup;1274 goto error_cleanup;
1275 }
1260 }1276 }
1261 1277
1262 if (p->gang_size > 1) {1278 if (p->gang_size > 1) {
@@ -1344,6 +1360,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser) · 81 unmodified lines
1344{1360{
1345 unsigned i;1361 unsigned i;
1346 1362
1363 amdgpu_sync_free(&parser->sync);
1347 for (i = 0; i < parser->num_post_deps; i++) {1364 for (i = 0; i < parser->num_post_deps; i++) {
1348 drm_syncobj_put(parser->post_deps[i].syncobj);1365 drm_syncobj_put(parser->post_deps[i].syncobj);
1349 kfree(parser->post_deps[i].chain);1366 kfree(parser->post_deps[i].chain);
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c+8−0
@@ -36,6 +36,7 @@ · 35 unmodified lines
36#include <generated/utsrelease.h>36#include <generated/utsrelease.h>
37#include <linux/pci-p2pdma.h>37#include <linux/pci-p2pdma.h>
38 38
39#include <drm/drm_aperture.h>
39#include <drm/drm_atomic_helper.h>40#include <drm/drm_atomic_helper.h>
40#include <drm/drm_fb_helper.h>41#include <drm/drm_fb_helper.h>
41#include <drm/drm_probe_helper.h>42#include <drm/drm_probe_helper.h>
@@ -90,6 +91,8 @@ MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin"); · 48 unmodified lines
90#define AMDGPU_MAX_RETRY_LIMIT 291#define AMDGPU_MAX_RETRY_LIMIT 2
91#define AMDGPU_RETRY_SRIOV_RESET(r) ((r) == -EBUSY || (r) == -ETIMEDOUT || (r) == -EINVAL)92#define AMDGPU_RETRY_SRIOV_RESET(r) ((r) == -EBUSY || (r) == -ETIMEDOUT || (r) == -EINVAL)
92 93
94static const struct drm_driver amdgpu_kms_driver;
95
93const char *amdgpu_asic_name[] = {96const char *amdgpu_asic_name[] = {
94 "TAHITI",97 "TAHITI",
95 "PITCAIRN",98 "PITCAIRN",
@@ -3687,6 +3690,11 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 3591 unmodified lines
3687 if (r)3690 if (r)
3688 return r;3691 return r;
3689 3692
3693 /* Get rid of things like offb */
3694 r = drm_aperture_remove_conflicting_pci_framebuffers(adev->pdev, &amdgpu_kms_driver);
3695 if (r)
3696 return r;
3697
3690 /* Enable TMZ based on IP_VERSION */3698 /* Enable TMZ based on IP_VERSION */
3691 amdgpu_gmc_tmz_set(adev);3699 amdgpu_gmc_tmz_set(adev);
3692 3700
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c+0−6
@@ -23,7 +23,6 @@ · 22 unmodified lines
23 */23 */
24 24
25#include <drm/amdgpu_drm.h>25#include <drm/amdgpu_drm.h>
26#include <drm/drm_aperture.h>
27#include <drm/drm_drv.h>26#include <drm/drm_drv.h>
28#include <drm/drm_fbdev_generic.h>27#include <drm/drm_fbdev_generic.h>
29#include <drm/drm_gem.h>28#include <drm/drm_gem.h>
@@ -2122,11 +2121,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, · 2092 unmodified lines
2122 }2121 }
2123#endif2122#endif
2124 2123
2125 /* Get rid of things like offb */
2126 ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver);
2127 if (ret)
2128 return ret;
2129
2130 adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev);2124 adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev);
2131 if (IS_ERR(adev))2125 if (IS_ERR(adev))
2132 return PTR_ERR(adev);2126 return PTR_ERR(adev);
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c+3−2
@@ -470,8 +470,9 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev, · 469 unmodified lines
470 return true;470 return true;
471 471
472fail:472fail:
473 DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,473 if (man)
474 man->size);474 DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
475 man->size);
475 return false;476 return false;
476}477}
477 478
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c+3−1
@@ -391,8 +391,10 @@ int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job) · 390 unmodified lines
391 391
392 dma_fence_get(f);392 dma_fence_get(f);
393 r = drm_sched_job_add_dependency(&job->base, f);393 r = drm_sched_job_add_dependency(&job->base, f);
394 if (r)394 if (r) {
395 dma_fence_put(f);
395 return r;396 return r;
397 }
396 }398 }
397 return 0;399 return 0;
398}400}
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c+1−1
@@ -882,7 +882,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) · 881 unmodified lines
882 kfree(rsv);882 kfree(rsv);
883 883
884 list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) {884 list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) {
885 drm_buddy_free_list(&mgr->mm, &rsv->blocks);885 drm_buddy_free_list(&mgr->mm, &rsv->allocated);
886 kfree(rsv);886 kfree(rsv);
887 }887 }
888 drm_buddy_fini(&mgr->mm);888 drm_buddy_fini(&mgr->mm);
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c+1−1
@@ -200,7 +200,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q, · 199 unmodified lines
200 queue_input.wptr_addr = (uint64_t)q->properties.write_ptr;200 queue_input.wptr_addr = (uint64_t)q->properties.write_ptr;
201 201
202 if (q->wptr_bo) {202 if (q->wptr_bo) {
203 wptr_addr_off = (uint64_t)q->properties.write_ptr - (uint64_t)q->wptr_bo->kfd_bo->va;203 wptr_addr_off = (uint64_t)q->properties.write_ptr & (PAGE_SIZE - 1);
204 queue_input.wptr_mc_addr = ((uint64_t)q->wptr_bo->tbo.resource->start << PAGE_SHIFT) + wptr_addr_off;204 queue_input.wptr_mc_addr = ((uint64_t)q->wptr_bo->tbo.resource->start << PAGE_SHIFT) + wptr_addr_off;
205 }205 }
206 206
drivers/gpu/drm/amd/amdkfd/kfd_svm.c+9−0
@@ -570,6 +570,15 @@ svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange, · 569 unmodified lines
570 goto reserve_bo_failed;570 goto reserve_bo_failed;
571 }571 }
572 572
573 if (clear) {
574 r = amdgpu_bo_sync_wait(bo, AMDGPU_FENCE_OWNER_KFD, false);
575 if (r) {
576 pr_debug("failed %d to sync bo\n", r);
577 amdgpu_bo_unreserve(bo);
578 goto reserve_bo_failed;
579 }
580 }
581
573 r = dma_resv_reserve_fences(bo->tbo.base.resv, 1);582 r = dma_resv_reserve_fences(bo->tbo.base.resv, 1);
574 if (r) {583 if (r) {
575 pr_debug("failed %d to reserve bo\n", r);584 pr_debug("failed %d to reserve bo\n", r);
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c+6−2
@@ -1261,7 +1261,8 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu, · 1260 unmodified lines
1261 uint32_t speed)1261 uint32_t speed)
1262{1262{
1263 struct amdgpu_device *adev = smu->adev;1263 struct amdgpu_device *adev = smu->adev;
1264 uint32_t tach_period, crystal_clock_freq;1264 uint32_t crystal_clock_freq = 2500;
1265 uint32_t tach_period;
1265 int ret;1266 int ret;
1266 1267
1267 if (!speed)1268 if (!speed)
@@ -1271,7 +1272,6 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu, · 3 unmodified lines
1271 if (ret)1272 if (ret)
1272 return ret;1273 return ret;
1273 1274
1274 crystal_clock_freq = amdgpu_asic_get_xclk(adev);
1275 tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);1275 tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
1276 WREG32_SOC15(THM, 0, regCG_TACH_CTRL,1276 WREG32_SOC15(THM, 0, regCG_TACH_CTRL,
1277 REG_SET_FIELD(RREG32_SOC15(THM, 0, regCG_TACH_CTRL),1277 REG_SET_FIELD(RREG32_SOC15(THM, 0, regCG_TACH_CTRL),
@@ -2298,6 +2298,10 @@ bool smu_v13_0_baco_is_support(struct smu_context *smu) · 1020 unmodified lines
2298 !smu_baco->platform_support)2298 !smu_baco->platform_support)
2299 return false;2299 return false;
2300 2300
2301 /* return true if ASIC is in BACO state already */
2302 if (smu_v13_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER)
2303 return true;
2304
2301 if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) &&2305 if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) &&
2302 !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT))2306 !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT))
2303 return false;2307 return false;
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c+1−0
@@ -213,6 +213,7 @@ static struct cmn2asic_mapping smu_v13_0_0_feature_mask_map[SMU_FEATURE_COUNT] = · 212 unmodified lines
213 FEA_MAP(SOC_PCC),213 FEA_MAP(SOC_PCC),
214 [SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},214 [SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
215 [SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},215 [SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
216 [SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT},
216};217};
217 218
218static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {219static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c+1−0
@@ -192,6 +192,7 @@ static struct cmn2asic_mapping smu_v13_0_7_feature_mask_map[SMU_FEATURE_COUNT] = · 191 unmodified lines
192 FEA_MAP(SOC_PCC),192 FEA_MAP(SOC_PCC),
193 [SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},193 [SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
194 [SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},194 [SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
195 [SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT},
195};196};
196 197
197static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {198static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
drivers/gpu/drm/drm_buddy.c+54−27
@@ -38,6 +38,25 @@ static void drm_block_free(struct drm_buddy *mm, · 37 unmodified lines
38 kmem_cache_free(slab_blocks, block);38 kmem_cache_free(slab_blocks, block);
39}39}
40 40
41static void list_insert_sorted(struct drm_buddy *mm,
42 struct drm_buddy_block *block)
43{
44 struct drm_buddy_block *node;
45 struct list_head *head;
46
47 head = &mm->free_list[drm_buddy_block_order(block)];
48 if (list_empty(head)) {
49 list_add(&block->link, head);
50 return;
51 }
52
53 list_for_each_entry(node, head, link)
54 if (drm_buddy_block_offset(block) < drm_buddy_block_offset(node))
55 break;
56
57 __list_add(&block->link, node->link.prev, &node->link);
58}
59
41static void mark_allocated(struct drm_buddy_block *block)60static void mark_allocated(struct drm_buddy_block *block)
42{61{
43 block->header &= ~DRM_BUDDY_HEADER_STATE;62 block->header &= ~DRM_BUDDY_HEADER_STATE;
@@ -52,8 +71,7 @@ static void mark_free(struct drm_buddy *mm, · 8 unmodified lines
52 block->header &= ~DRM_BUDDY_HEADER_STATE;71 block->header &= ~DRM_BUDDY_HEADER_STATE;
53 block->header |= DRM_BUDDY_FREE;72 block->header |= DRM_BUDDY_FREE;
54 73
55 list_add(&block->link,74 list_insert_sorted(mm, block);
56 &mm->free_list[drm_buddy_block_order(block)]);
57}75}
58 76
59static void mark_split(struct drm_buddy_block *block)77static void mark_split(struct drm_buddy_block *block)
@@ -387,20 +405,26 @@ err_undo: · 327 unmodified lines
387}405}
388 406
389static struct drm_buddy_block *407static struct drm_buddy_block *
390get_maxblock(struct list_head *head)408get_maxblock(struct drm_buddy *mm, unsigned int order)
391{409{
392 struct drm_buddy_block *max_block = NULL, *node;410 struct drm_buddy_block *max_block = NULL, *node;
411 unsigned int i;
393 412
394 max_block = list_first_entry_or_null(head,413 for (i = order; i <= mm->max_order; ++i) {
395 struct drm_buddy_block,414 if (!list_empty(&mm->free_list[i])) {
396 link);415 node = list_last_entry(&mm->free_list[i],
397 if (!max_block)416 struct drm_buddy_block,
398 return NULL;417 link);
418 if (!max_block) {
419 max_block = node;
420 continue;
421 }
399 422
400 list_for_each_entry(node, head, link) {423 if (drm_buddy_block_offset(node) >
401 if (drm_buddy_block_offset(node) >424 drm_buddy_block_offset(max_block)) {
402 drm_buddy_block_offset(max_block))425 max_block = node;
403 max_block = node;426 }
427 }
404 }428 }
405 429
406 return max_block;430 return max_block;
@@ -412,20 +436,23 @@ alloc_from_freelist(struct drm_buddy *mm, · 5 unmodified lines
412 unsigned long flags)436 unsigned long flags)
413{437{
414 struct drm_buddy_block *block = NULL;438 struct drm_buddy_block *block = NULL;
415 unsigned int i;439 unsigned int tmp;
416 int err;440 int err;
417 441
418 for (i = order; i <= mm->max_order; ++i) {442 if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
419 if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {443 block = get_maxblock(mm, order);
420 block = get_maxblock(&mm->free_list[i]);444 if (block)
421 if (block)445 /* Store the obtained block order */
422 break;446 tmp = drm_buddy_block_order(block);
423 } else {447 } else {
424 block = list_first_entry_or_null(&mm->free_list[i],448 for (tmp = order; tmp <= mm->max_order; ++tmp) {
425 struct drm_buddy_block,449 if (!list_empty(&mm->free_list[tmp])) {
426 link);450 block = list_last_entry(&mm->free_list[tmp],
427 if (block)451 struct drm_buddy_block,
428 break;452 link);
453 if (block)
454 break;
455 }
429 }456 }
430 }457 }
431 458
@@ -434,18 +461,18 @@ alloc_from_freelist(struct drm_buddy *mm, · 2 unmodified lines
434 461
435 BUG_ON(!drm_buddy_block_is_free(block));462 BUG_ON(!drm_buddy_block_is_free(block));
436 463
437 while (i != order) {464 while (tmp != order) {
438 err = split_block(mm, block);465 err = split_block(mm, block);
439 if (unlikely(err))466 if (unlikely(err))
440 goto err_undo;467 goto err_undo;
441 468
442 block = block->right;469 block = block->right;
443 i--;470 tmp--;
444 }471 }
445 return block;472 return block;
446 473
447err_undo:474err_undo:
448 if (i != order)475 if (tmp != order)
449 __drm_buddy_free(mm, block);476 __drm_buddy_free(mm, block);
450 return ERR_PTR(err);477 return ERR_PTR(err);
451}478}
drivers/gpu/drm/drm_panel_orientation_quirks.c+6−0
@@ -304,6 +304,12 @@ static const struct dmi_system_id orientation_data[] = { · 303 unmodified lines
304 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),304 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
305 },305 },
306 .driver_data = (void *)&lcd1200x1920_rightside_up,306 .driver_data = (void *)&lcd1200x1920_rightside_up,
307 }, { /* Lenovo Ideapad D330-10IGL (HD) */
308 .matches = {
309 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
310 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"),
311 },
312 .driver_data = (void *)&lcd800x1280_rightside_up,
307 }, { /* Lenovo Yoga Book X90F / X91F / X91L */313 }, { /* Lenovo Yoga Book X90F / X91F / X91L */
308 .matches = {314 .matches = {
309 /* Non exact match to match all versions */315 /* Non exact match to match all versions */
drivers/gpu/drm/i915/gem/i915_gem_context.c+18−6
@@ -1688,6 +1688,10 @@ void i915_gem_init__contexts(struct drm_i915_private *i915) · 1687 unmodified lines
1688 init_contexts(&i915->gem.contexts);1688 init_contexts(&i915->gem.contexts);
1689}1689}
1690 1690
1691/*
1692 * Note that this implicitly consumes the ctx reference, by placing
1693 * the ctx in the context_xa.
1694 */
1691static void gem_context_register(struct i915_gem_context *ctx,1695static void gem_context_register(struct i915_gem_context *ctx,
1692 struct drm_i915_file_private *fpriv,1696 struct drm_i915_file_private *fpriv,
1693 u32 id)1697 u32 id)
@@ -1703,10 +1707,6 @@ static void gem_context_register(struct i915_gem_context *ctx, · 9 unmodified lines
1703 snprintf(ctx->name, sizeof(ctx->name), "%s[%d]",1707 snprintf(ctx->name, sizeof(ctx->name), "%s[%d]",
1704 current->comm, pid_nr(ctx->pid));1708 current->comm, pid_nr(ctx->pid));
1705 1709
1706 /* And finally expose ourselves to userspace via the idr */
1707 old = xa_store(&fpriv->context_xa, id, ctx, GFP_KERNEL);
1708 WARN_ON(old);
1709
1710 spin_lock(&ctx->client->ctx_lock);1710 spin_lock(&ctx->client->ctx_lock);
1711 list_add_tail_rcu(&ctx->client_link, &ctx->client->ctx_list);1711 list_add_tail_rcu(&ctx->client_link, &ctx->client->ctx_list);
1712 spin_unlock(&ctx->client->ctx_lock);1712 spin_unlock(&ctx->client->ctx_lock);
@@ -1714,6 +1714,10 @@ static void gem_context_register(struct i915_gem_context *ctx, · 1 unmodified line
1714 spin_lock(&i915->gem.contexts.lock);1714 spin_lock(&i915->gem.contexts.lock);
1715 list_add_tail(&ctx->link, &i915->gem.contexts.list);1715 list_add_tail(&ctx->link, &i915->gem.contexts.list);
1716 spin_unlock(&i915->gem.contexts.lock);1716 spin_unlock(&i915->gem.contexts.lock);
1717
1718 /* And finally expose ourselves to userspace via the idr */
1719 old = xa_store(&fpriv->context_xa, id, ctx, GFP_KERNEL);
1720 WARN_ON(old);
1717}1721}
1718 1722
1719int i915_gem_context_open(struct drm_i915_private *i915,1723int i915_gem_context_open(struct drm_i915_private *i915,
@@ -2199,14 +2203,22 @@ finalize_create_context_locked(struct drm_i915_file_private *file_priv, · 479 unmodified lines
2199 if (IS_ERR(ctx))2203 if (IS_ERR(ctx))
2200 return ctx;2204 return ctx;
2201 2205
2206 /*
2207 * One for the xarray and one for the caller. We need to grab
2208 * the reference *prior* to making the ctx visble to userspace
2209 * in gem_context_register(), as at any point after that
2210 * userspace can try to race us with another thread destroying
2211 * the context under our feet.
2212 */
2213 i915_gem_context_get(ctx);
2214
2202 gem_context_register(ctx, file_priv, id);2215 gem_context_register(ctx, file_priv, id);
2203 2216
2204 old = xa_erase(&file_priv->proto_context_xa, id);2217 old = xa_erase(&file_priv->proto_context_xa, id);
2205 GEM_BUG_ON(old != pc);2218 GEM_BUG_ON(old != pc);
2206 proto_context_close(file_priv->dev_priv, pc);2219 proto_context_close(file_priv->dev_priv, pc);
2207 2220
2208 /* One for the xarray and one for the caller */2221 return ctx;
2209 return i915_gem_context_get(ctx);
2210}2222}
2211 2223
2212struct i915_gem_context *2224struct i915_gem_context *
drivers/gpu/drm/i915/gt/intel_gt_regs.h+2−2
@@ -406,10 +406,10 @@ · 405 unmodified lines
406#define GEN9_WM_CHICKEN3 _MMIO(0x5588)406#define GEN9_WM_CHICKEN3 _MMIO(0x5588)
407#define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9)407#define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9)
408 408
409#define CHICKEN_RASTER_1 _MMIO(0x6204)409#define CHICKEN_RASTER_1 MCR_REG(0x6204)
410#define DIS_SF_ROUND_NEAREST_EVEN REG_BIT(8)410#define DIS_SF_ROUND_NEAREST_EVEN REG_BIT(8)
411 411
412#define CHICKEN_RASTER_2 _MMIO(0x6208)412#define CHICKEN_RASTER_2 MCR_REG(0x6208)
413#define TBIMR_FAST_CLIP REG_BIT(5)413#define TBIMR_FAST_CLIP REG_BIT(5)
414 414
415#define VFLSKPD MCR_REG(0x62a8)415#define VFLSKPD MCR_REG(0x62a8)
drivers/gpu/drm/i915/gt/intel_reset.c+28−6
@@ -278,6 +278,7 @@ out: · 277 unmodified lines
278static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask)278static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask)
279{279{
280 struct intel_uncore *uncore = gt->uncore;280 struct intel_uncore *uncore = gt->uncore;
281 int loops = 2;
281 int err;282 int err;
282 283
283 /*284 /*
@@ -285,18 +286,39 @@ static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask) · 1 unmodified line
285 * for fifo space for the write or forcewake the chip for286 * for fifo space for the write or forcewake the chip for
286 * the read287 * the read
287 */288 */
288 intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask);289 do {
290 intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask);
289 291
290 /* Wait for the device to ack the reset requests */292 /*
291 err = __intel_wait_for_register_fw(uncore,293 * Wait for the device to ack the reset requests.
292 GEN6_GDRST, hw_domain_mask, 0,294 *
293 500, 0,295 * On some platforms, e.g. Jasperlake, we see that the
294 NULL);296 * engine register state is not cleared until shortly after
297 * GDRST reports completion, causing a failure as we try
298 * to immediately resume while the internal state is still
299 * in flux. If we immediately repeat the reset, the second
300 * reset appears to serialise with the first, and since
301 * it is a no-op, the registers should retain their reset
302 * value. However, there is still a concern that upon
303 * leaving the second reset, the internal engine state
304 * is still in flux and not ready for resuming.
305 */
306 err = __intel_wait_for_register_fw(uncore, GEN6_GDRST,
307 hw_domain_mask, 0,
308 2000, 0,
309 NULL);
310 } while (err == 0 && --loops);
295 if (err)311 if (err)
296 GT_TRACE(gt,312 GT_TRACE(gt,
297 "Wait for 0x%08x engines reset failed\n",313 "Wait for 0x%08x engines reset failed\n",
298 hw_domain_mask);314 hw_domain_mask);
299 315
316 /*
317 * As we have observed that the engine state is still volatile
318 * after GDRST is acked, impose a small delay to let everything settle.
319 */
320 udelay(50);
321
300 return err;322 return err;
301}323}
302 324
drivers/gpu/drm/i915/gt/intel_workarounds.c+2−2
@@ -645,7 +645,7 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, · 644 unmodified lines
645static void dg2_ctx_gt_tuning_init(struct intel_engine_cs *engine,645static void dg2_ctx_gt_tuning_init(struct intel_engine_cs *engine,
646 struct i915_wa_list *wal)646 struct i915_wa_list *wal)
647{647{
648 wa_masked_en(wal, CHICKEN_RASTER_2, TBIMR_FAST_CLIP);648 wa_mcr_masked_en(wal, CHICKEN_RASTER_2, TBIMR_FAST_CLIP);
649 wa_mcr_write_clr_set(wal, XEHP_L3SQCREG5, L3_PWM_TIMER_INIT_VAL_MASK,649 wa_mcr_write_clr_set(wal, XEHP_L3SQCREG5, L3_PWM_TIMER_INIT_VAL_MASK,
650 REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f));650 REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f));
651 wa_mcr_add(wal,651 wa_mcr_add(wal,
@@ -775,7 +775,7 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine, · 123 unmodified lines
775 wa_masked_field_set(wal, VF_PREEMPTION, PREEMPTION_VERTEX_COUNT, 0x4000);775 wa_masked_field_set(wal, VF_PREEMPTION, PREEMPTION_VERTEX_COUNT, 0x4000);
776 776
777 /* Wa_15010599737:dg2 */777 /* Wa_15010599737:dg2 */
778 wa_masked_en(wal, CHICKEN_RASTER_1, DIS_SF_ROUND_NEAREST_EVEN);778 wa_mcr_masked_en(wal, CHICKEN_RASTER_1, DIS_SF_ROUND_NEAREST_EVEN);
779}779}
780 780
781static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine,781static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine,
drivers/gpu/drm/i915/i915_vma.c+1−1
@@ -2116,7 +2116,7 @@ int i915_vma_unbind_async(struct i915_vma *vma, bool trylock_vm) · 2115 unmodified lines
2116 if (!obj->mm.rsgt)2116 if (!obj->mm.rsgt)
2117 return -EBUSY;2117 return -EBUSY;
2118 2118
2119 err = dma_resv_reserve_fences(obj->base.resv, 1);2119 err = dma_resv_reserve_fences(obj->base.resv, 2);
2120 if (err)2120 if (err)
2121 return -EBUSY;2121 return -EBUSY;
2122 2122
drivers/gpu/drm/msm/adreno/a6xx_gmu.c+9−6
@@ -876,7 +876,8 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) · 875 unmodified lines
876#define GBIF_CLIENT_HALT_MASK BIT(0)876#define GBIF_CLIENT_HALT_MASK BIT(0)
877#define GBIF_ARB_HALT_MASK BIT(1)877#define GBIF_ARB_HALT_MASK BIT(1)
878 878
879static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)879static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu,
880 bool gx_off)
880{881{
881 struct msm_gpu *gpu = &adreno_gpu->base;882 struct msm_gpu *gpu = &adreno_gpu->base;
882 883
@@ -889,9 +890,11 @@ static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu) · 6 unmodified lines
889 return;890 return;
890 }891 }
891 892
892 /* Halt the gx side of GBIF */893 if (gx_off) {
893 gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1);894 /* Halt the gx side of GBIF */
894 spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1);895 gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1);
896 spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1);
897 }
895 898
896 /* Halt new client requests on GBIF */899 /* Halt new client requests on GBIF */
897 gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);900 gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
@@ -929,7 +932,7 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) · 31 unmodified lines
929 /* Halt the gmu cm3 core */932 /* Halt the gmu cm3 core */
930 gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);933 gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
931 934
932 a6xx_bus_clear_pending_transactions(adreno_gpu);935 a6xx_bus_clear_pending_transactions(adreno_gpu, true);
933 936
934 /* Reset GPU core blocks */937 /* Reset GPU core blocks */
935 gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1);938 gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1);
@@ -1083,7 +1086,7 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) · 147 unmodified lines
1083 return;1086 return;
1084 }1087 }
1085 1088
1086 a6xx_bus_clear_pending_transactions(adreno_gpu);1089 a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung);
1087 1090
1088 /* tell the GMU we want to slumber */1091 /* tell the GMU we want to slumber */
1089 ret = a6xx_gmu_notify_slumber(gmu);1092 ret = a6xx_gmu_notify_slumber(gmu);
drivers/gpu/drm/msm/adreno/a6xx_gpu.c+7−0
@@ -1270,6 +1270,12 @@ static void a6xx_recover(struct msm_gpu *gpu) · 1269 unmodified lines
1270 if (hang_debug)1270 if (hang_debug)
1271 a6xx_dump(gpu);1271 a6xx_dump(gpu);
1272 1272
1273 /*
1274 * To handle recovery specific sequences during the rpm suspend we are
1275 * about to trigger
1276 */
1277 a6xx_gpu->hung = true;
1278
1273 /* Halt SQE first */1279 /* Halt SQE first */
1274 gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);1280 gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
1275 1281
@@ -1312,6 +1318,7 @@ static void a6xx_recover(struct msm_gpu *gpu) · 36 unmodified lines
1312 mutex_unlock(&gpu->active_lock);1318 mutex_unlock(&gpu->active_lock);
1313 1319
1314 msm_gpu_hw_init(gpu);1320 msm_gpu_hw_init(gpu);
1321 a6xx_gpu->hung = false;
1315}1322}
1316 1323
1317static const char *a6xx_uche_fault_block(struct msm_gpu *gpu, u32 mid)1324static const char *a6xx_uche_fault_block(struct msm_gpu *gpu, u32 mid)
drivers/gpu/drm/msm/adreno/a6xx_gpu.h+1−0
@@ -32,6 +32,7 @@ struct a6xx_gpu { · 31 unmodified lines
32 void *llc_slice;32 void *llc_slice;
33 void *htw_llc_slice;33 void *htw_llc_slice;
34 bool have_mmu500;34 bool have_mmu500;
35 bool hung;
35};36};
36 37
37#define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base)38#define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base)
drivers/gpu/drm/msm/adreno/adreno_gpu.h+4−6
@@ -29,11 +29,9 @@ enum { · 28 unmodified lines
29 ADRENO_FW_MAX,29 ADRENO_FW_MAX,
30};30};
31 31
32enum adreno_quirks {32#define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0)
33 ADRENO_QUIRK_TWO_PASS_USE_WFI = 1,33#define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1)
34 ADRENO_QUIRK_FAULT_DETECT_MASK = 2,34#define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2)
35 ADRENO_QUIRK_LMLOADKILL_DISABLE = 3,
36};
37 35
38struct adreno_rev {36struct adreno_rev {
39 uint8_t core;37 uint8_t core;
@@ -65,7 +63,7 @@ struct adreno_info { · 25 unmodified lines
65 const char *name;63 const char *name;
66 const char *fw[ADRENO_FW_MAX];64 const char *fw[ADRENO_FW_MAX];
67 uint32_t gmem;65 uint32_t gmem;
68 enum adreno_quirks quirks;66 u64 quirks;
69 struct msm_gpu *(*init)(struct drm_device *dev);67 struct msm_gpu *(*init)(struct drm_device *dev);
70 const char *zapfw;68 const char *zapfw;
71 u32 inactive_period;69 u32 inactive_period;
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c+1−2
@@ -132,7 +132,6 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc) · 131 unmodified lines
132 * dpu_encoder_phys_wb_setup_fb - setup output framebuffer132 * dpu_encoder_phys_wb_setup_fb - setup output framebuffer
133 * @phys_enc: Pointer to physical encoder133 * @phys_enc: Pointer to physical encoder
134 * @fb: Pointer to output framebuffer134 * @fb: Pointer to output framebuffer
135 * @wb_roi: Pointer to output region of interest
136 */135 */
137static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,136static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
138 struct drm_framebuffer *fb)137 struct drm_framebuffer *fb)
@@ -692,7 +691,7 @@ static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops) · 553 unmodified lines
692 691
693/**692/**
694 * dpu_encoder_phys_wb_init - initialize writeback encoder693 * dpu_encoder_phys_wb_init - initialize writeback encoder
695 * @init: Pointer to init info structure with initialization params694 * @p: Pointer to init info structure with initialization params
696 */695 */
697struct dpu_encoder_phys *dpu_encoder_phys_wb_init(696struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
698 struct dpu_enc_phys_init_params *p)697 struct dpu_enc_phys_init_params *p)
drivers/gpu/drm/msm/dp/dp_aux.c+4−0
@@ -423,6 +423,10 @@ void dp_aux_isr(struct drm_dp_aux *dp_aux) · 422 unmodified lines
423 423
424 isr = dp_catalog_aux_get_irq(aux->catalog);424 isr = dp_catalog_aux_get_irq(aux->catalog);
425 425
426 /* no interrupts pending, return immediately */
427 if (!isr)
428 return;
429
426 if (!aux->cmd_busy)430 if (!aux->cmd_busy)
427 return;431 return;
428 432
drivers/gpu/drm/msm/hdmi/hdmi.c+10−2
@@ -532,11 +532,19 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) · 531 unmodified lines
532 532
533 ret = devm_pm_runtime_enable(&pdev->dev);533 ret = devm_pm_runtime_enable(&pdev->dev);
534 if (ret)534 if (ret)
535 return ret;535 goto err_put_phy;
536 536
537 platform_set_drvdata(pdev, hdmi);537 platform_set_drvdata(pdev, hdmi);
538 538
539 return component_add(&pdev->dev, &msm_hdmi_ops);539 ret = component_add(&pdev->dev, &msm_hdmi_ops);
540 if (ret)
541 goto err_put_phy;
542
543 return 0;
544
545err_put_phy:
546 msm_hdmi_put_phy(hdmi);
547 return ret;
540}548}
541 549
542static int msm_hdmi_dev_remove(struct platform_device *pdev)550static int msm_hdmi_dev_remove(struct platform_device *pdev)
drivers/gpu/drm/msm/msm_drv.c+1−1
@@ -1278,7 +1278,7 @@ void msm_drv_shutdown(struct platform_device *pdev) · 1277 unmodified lines
1278 * msm_drm_init, drm_dev->registered is used as an indicator that the1278 * msm_drm_init, drm_dev->registered is used as an indicator that the
1279 * shutdown will be successful.1279 * shutdown will be successful.
1280 */1280 */
1281 if (drm && drm->registered)1281 if (drm && drm->registered && priv->kms)
1282 drm_atomic_helper_shutdown(drm);1282 drm_atomic_helper_shutdown(drm);
1283}1283}
1284 1284
drivers/gpu/drm/msm/msm_mdss.c+4−2
@@ -47,15 +47,17 @@ struct msm_mdss { · 46 unmodified lines
47static int msm_mdss_parse_data_bus_icc_path(struct device *dev,47static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
48 struct msm_mdss *msm_mdss)48 struct msm_mdss *msm_mdss)
49{49{
50 struct icc_path *path0 = of_icc_get(dev, "mdp0-mem");50 struct icc_path *path0;
51 struct icc_path *path1 = of_icc_get(dev, "mdp1-mem");51 struct icc_path *path1;
52 52
53 path0 = of_icc_get(dev, "mdp0-mem");
53 if (IS_ERR_OR_NULL(path0))54 if (IS_ERR_OR_NULL(path0))
54 return PTR_ERR_OR_ZERO(path0);55 return PTR_ERR_OR_ZERO(path0);
55 56
56 msm_mdss->path[0] = path0;57 msm_mdss->path[0] = path0;
57 msm_mdss->num_paths = 1;58 msm_mdss->num_paths = 1;
58 59
60 path1 = of_icc_get(dev, "mdp1-mem");
59 if (!IS_ERR_OR_NULL(path1)) {61 if (!IS_ERR_OR_NULL(path1)) {
60 msm_mdss->path[1] = path1;62 msm_mdss->path[1] = path1;
61 msm_mdss->num_paths++;63 msm_mdss->num_paths++;
drivers/gpu/drm/nouveau/nouveau_fbcon.c+0−613
@@ -1,613 +0,0 @@
1/*
2 * Copyright © 2007 David Airlie
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * David Airlie
25 */
26
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/errno.h>
30#include <linux/string.h>
31#include <linux/mm.h>
32#include <linux/tty.h>
33#include <linux/sysrq.h>
34#include <linux/delay.h>
35#include <linux/init.h>
36#include <linux/screen_info.h>
37#include <linux/vga_switcheroo.h>
38#include <linux/console.h>
39
40#include <drm/drm_crtc.h>
41#include <drm/drm_crtc_helper.h>
42#include <drm/drm_probe_helper.h>
43#include <drm/drm_fb_helper.h>
44#include <drm/drm_fourcc.h>
45#include <drm/drm_atomic.h>
46
47#include "nouveau_drv.h"
48#include "nouveau_gem.h"
49#include "nouveau_bo.h"
50#include "nouveau_fbcon.h"
51#include "nouveau_chan.h"
52#include "nouveau_vmm.h"
53
54#include "nouveau_crtc.h"
55
56MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
57int nouveau_nofbaccel = 0;
58module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
59
60MODULE_PARM_DESC(fbcon_bpp, "fbcon bits-per-pixel (default: auto)");
61static int nouveau_fbcon_bpp;
62module_param_named(fbcon_bpp, nouveau_fbcon_bpp, int, 0400);
63
64static void
65nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
66{
67 struct nouveau_fbdev *fbcon = info->par;
68 struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
69 struct nvif_device *device = &drm->client.device;
70 int ret;
71
72 if (info->state != FBINFO_STATE_RUNNING)
73 return;
74
75 ret = -ENODEV;
76 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
77 mutex_trylock(&drm->client.mutex)) {
78 if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
79 ret = nv04_fbcon_fillrect(info, rect);
80 else
81 if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
82 ret = nv50_fbcon_fillrect(info, rect);
83 else
84 ret = nvc0_fbcon_fillrect(info, rect);
85 mutex_unlock(&drm->client.mutex);
86 }
87
88 if (ret == 0)
89 return;
90
91 if (ret != -ENODEV)
92 nouveau_fbcon_gpu_lockup(info);
93 drm_fb_helper_cfb_fillrect(info, rect);
94}
95
96static void
97nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
98{
99 struct nouveau_fbdev *fbcon = info->par;
100 struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
101 struct nvif_device *device = &drm->client.device;
102 int ret;
103
104 if (info->state != FBINFO_STATE_RUNNING)
105 return;
106
107 ret = -ENODEV;
108 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
109 mutex_trylock(&drm->client.mutex)) {
110 if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
111 ret = nv04_fbcon_copyarea(info, image);
112 else
113 if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
114 ret = nv50_fbcon_copyarea(info, image);
115 else
116 ret = nvc0_fbcon_copyarea(info, image);
117 mutex_unlock(&drm->client.mutex);
118 }
119
120 if (ret == 0)
121 return;
122
123 if (ret != -ENODEV)
124 nouveau_fbcon_gpu_lockup(info);
125 drm_fb_helper_cfb_copyarea(info, image);
126}
127
128static void
129nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
130{
131 struct nouveau_fbdev *fbcon = info->par;
132 struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
133 struct nvif_device *device = &drm->client.device;
134 int ret;
135
136 if (info->state != FBINFO_STATE_RUNNING)
137 return;
138
139 ret = -ENODEV;
140 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
141 mutex_trylock(&drm->client.mutex)) {
142 if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
143 ret = nv04_fbcon_imageblit(info, image);
144 else
145 if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
146 ret = nv50_fbcon_imageblit(info, image);
147 else
148 ret = nvc0_fbcon_imageblit(info, image);
149 mutex_unlock(&drm->client.mutex);
150 }
151
152 if (ret == 0)
153 return;
154
155 if (ret != -ENODEV)
156 nouveau_fbcon_gpu_lockup(info);
157 drm_fb_helper_cfb_imageblit(info, image);
158}
159
160static int
161nouveau_fbcon_sync(struct fb_info *info)
162{
163 struct nouveau_fbdev *fbcon = info->par;
164 struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
165 struct nouveau_channel *chan = drm->channel;
166 int ret;
167
168 if (!chan || !chan->accel_done || in_interrupt() ||
169 info->state != FBINFO_STATE_RUNNING ||
170 info->flags & FBINFO_HWACCEL_DISABLED)
171 return 0;
172
173 if (!mutex_trylock(&drm->client.mutex))
174 return 0;
175
176 ret = nouveau_channel_idle(chan);
177 mutex_unlock(&drm->client.mutex);
178 if (ret) {
179 nouveau_fbcon_gpu_lockup(info);
180 return 0;
181 }
182
183 chan->accel_done = false;
184 return 0;
185}
186
187static int
188nouveau_fbcon_open(struct fb_info *info, int user)
189{
190 struct nouveau_fbdev *fbcon = info->par;
191 struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
192 int ret = pm_runtime_get_sync(drm->dev->dev);
193 if (ret < 0 && ret != -EACCES) {
194 pm_runtime_put(drm->dev->dev);
195 return ret;
196 }
197 return 0;
198}
199
200static int
201nouveau_fbcon_release(struct fb_info *info, int user)
202{
203 struct nouveau_fbdev *fbcon = info->par;
204 struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
205 pm_runtime_put(drm->dev->dev);
206 return 0;
207}
208
209static const struct fb_ops nouveau_fbcon_ops = {
210 .owner = THIS_MODULE,
211 DRM_FB_HELPER_DEFAULT_OPS,
212 .fb_open = nouveau_fbcon_open,
213 .fb_release = nouveau_fbcon_release,
214 .fb_fillrect = nouveau_fbcon_fillrect,
215 .fb_copyarea = nouveau_fbcon_copyarea,
216 .fb_imageblit = nouveau_fbcon_imageblit,
217 .fb_sync = nouveau_fbcon_sync,
218};
219
220static const struct fb_ops nouveau_fbcon_sw_ops = {
221 .owner = THIS_MODULE,
222 DRM_FB_HELPER_DEFAULT_OPS,
223 .fb_open = nouveau_fbcon_open,
224 .fb_release = nouveau_fbcon_release,
225 .fb_fillrect = drm_fb_helper_cfb_fillrect,
226 .fb_copyarea = drm_fb_helper_cfb_copyarea,
227 .fb_imageblit = drm_fb_helper_cfb_imageblit,
228};
229
230void
231nouveau_fbcon_accel_save_disable(struct drm_device *dev)
232{
233 struct nouveau_drm *drm = nouveau_drm(dev);
234 if (drm->fbcon && drm->fbcon->helper.info) {
235 drm->fbcon->saved_flags = drm->fbcon->helper.info->flags;
236 drm->fbcon->helper.info->flags |= FBINFO_HWACCEL_DISABLED;
237 }
238}
239
240void
241nouveau_fbcon_accel_restore(struct drm_device *dev)
242{
243 struct nouveau_drm *drm = nouveau_drm(dev);
244 if (drm->fbcon && drm->fbcon->helper.info)
245 drm->fbcon->helper.info->flags = drm->fbcon->saved_flags;
246}
247
248static void
249nouveau_fbcon_accel_fini(struct drm_device *dev)
250{
251 struct nouveau_drm *drm = nouveau_drm(dev);
252 struct nouveau_fbdev *fbcon = drm->fbcon;
253 if (fbcon && drm->channel) {
254 console_lock();
255 if (fbcon->helper.info)
256 fbcon->helper.info->flags |= FBINFO_HWACCEL_DISABLED;
257 console_unlock();
258 nouveau_channel_idle(drm->channel);
259 nvif_object_dtor(&fbcon->twod);
260 nvif_object_dtor(&fbcon->blit);
261 nvif_object_dtor(&fbcon->gdi);
262 nvif_object_dtor(&fbcon->patt);
263 nvif_object_dtor(&fbcon->rop);
264 nvif_object_dtor(&fbcon->clip);
265 nvif_object_dtor(&fbcon->surf2d);
266 }
267}
268
269static void
270nouveau_fbcon_accel_init(struct drm_device *dev)
271{
272 struct nouveau_drm *drm = nouveau_drm(dev);
273 struct nouveau_fbdev *fbcon = drm->fbcon;
274 struct fb_info *info = fbcon->helper.info;
275 int ret;
276
277 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA)
278 ret = nv04_fbcon_accel_init(info);
279 else
280 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
281 ret = nv50_fbcon_accel_init(info);
282 else
283 ret = nvc0_fbcon_accel_init(info);
284
285 if (ret == 0)
286 info->fbops = &nouveau_fbcon_ops;
287}
288
289static void
290nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon)
291{
292 struct fb_info *info = fbcon->helper.info;
293 struct fb_fillrect rect;
294
295 /* Clear the entire fbcon. The drm will program every connector
296 * with it's preferred mode. If the sizes differ, one display will
297 * quite likely have garbage around the console.
298 */
299 rect.dx = rect.dy = 0;
300 rect.width = info->var.xres_virtual;
301 rect.height = info->var.yres_virtual;
302 rect.color = 0;
303 rect.rop = ROP_COPY;
304 info->fbops->fb_fillrect(info, &rect);
305}
306
307static int
308nouveau_fbcon_create(struct drm_fb_helper *helper,
309 struct drm_fb_helper_surface_size *sizes)
310{
311 struct nouveau_fbdev *fbcon =
312 container_of(helper, struct nouveau_fbdev, helper);
313 struct drm_device *dev = fbcon->helper.dev;
314 struct nouveau_drm *drm = nouveau_drm(dev);
315 struct nvif_device *device = &drm->client.device;
316 struct fb_info *info;
317 struct drm_framebuffer *fb;
318 struct nouveau_channel *chan;
319 struct nouveau_bo *nvbo;
320 struct drm_mode_fb_cmd2 mode_cmd = {};
321 int ret;
322
323 mode_cmd.width = sizes->surface_width;
324 mode_cmd.height = sizes->surface_height;
325
326 mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
327 mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
328
329 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
330 sizes->surface_depth);
331
332 ret = nouveau_gem_new(&drm->client, mode_cmd.pitches[0] *
333 mode_cmd.height, 0, NOUVEAU_GEM_DOMAIN_VRAM,
334 0, 0x0000, &nvbo);
335 if (ret) {
336 NV_ERROR(drm, "failed to allocate framebuffer\n");
337 goto out;
338 }
339
340 ret = nouveau_framebuffer_new(dev, &mode_cmd, &nvbo->bo.base, &fb);
341 if (ret)
342 goto out_unref;
343
344 ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false);
345 if (ret) {
346 NV_ERROR(drm, "failed to pin fb: %d\n", ret);
347 goto out_unref;
348 }
349
350 ret = nouveau_bo_map(nvbo);
351 if (ret) {
352 NV_ERROR(drm, "failed to map fb: %d\n", ret);
353 goto out_unpin;
354 }
355
356 chan = nouveau_nofbaccel ? NULL : drm->channel;
357 if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
358 ret = nouveau_vma_new(nvbo, chan->vmm, &fbcon->vma);
359 if (ret) {
360 NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
361 chan = NULL;
362 }
363 }
364
365 info = drm_fb_helper_alloc_info(helper);
366 if (IS_ERR(info)) {
367 ret = PTR_ERR(info);
368 goto out_unlock;
369 }
370
371 /* setup helper */
372 fbcon->helper.fb = fb;
373
374 if (!chan)
375 info->flags = FBINFO_HWACCEL_DISABLED;
376 else
377 info->flags = FBINFO_HWACCEL_COPYAREA |
378 FBINFO_HWACCEL_FILLRECT |
379 FBINFO_HWACCEL_IMAGEBLIT;
380 info->fbops = &nouveau_fbcon_sw_ops;
381 info->fix.smem_start = nvbo->bo.resource->bus.offset;
382 info->fix.smem_len = nvbo->bo.base.size;
383
384 info->screen_base = nvbo_kmap_obj_iovirtual(nvbo);
385 info->screen_size = nvbo->bo.base.size;
386
387 drm_fb_helper_fill_info(info, &fbcon->helper, sizes);
388
389 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
390
391 if (chan)
392 nouveau_fbcon_accel_init(dev);
393 nouveau_fbcon_zfill(dev, fbcon);
394
395 /* To allow resizeing without swapping buffers */
396 NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n",
397 fb->width, fb->height, nvbo->offset, nvbo);
398
399 if (dev_is_pci(dev->dev))
400 vga_switcheroo_client_fb_set(to_pci_dev(dev->dev), info);
401
402 return 0;
403
404out_unlock:
405 if (chan)
406 nouveau_vma_del(&fbcon->vma);
407 nouveau_bo_unmap(nvbo);
408out_unpin:
409 nouveau_bo_unpin(nvbo);
410out_unref:
411 nouveau_bo_ref(NULL, &nvbo);
412out:
413 return ret;
414}
415
416static int
417nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
418{
419 struct drm_framebuffer *fb = fbcon->helper.fb;
420 struct nouveau_bo *nvbo;
421
422 drm_fb_helper_unregister_info(&fbcon->helper);
423 drm_fb_helper_fini(&fbcon->helper);
424
425 if (fb && fb->obj[0]) {
426 nvbo = nouveau_gem_object(fb->obj[0]);
427 nouveau_vma_del(&fbcon->vma);
428 nouveau_bo_unmap(nvbo);
429 nouveau_bo_unpin(nvbo);
430 drm_framebuffer_put(fb);
431 }
432
433 return 0;
434}
435
436void nouveau_fbcon_gpu_lockup(struct fb_info *info)
437{
438 struct nouveau_fbdev *fbcon = info->par;
439 struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
440
441 NV_ERROR(drm, "GPU lockup - switching to software fbcon\n");
442 info->flags |= FBINFO_HWACCEL_DISABLED;
443}
444
445static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
446 .fb_probe = nouveau_fbcon_create,
447};
448
449static void
450nouveau_fbcon_set_suspend_work(struct work_struct *work)
451{
452 struct nouveau_drm *drm = container_of(work, typeof(*drm), fbcon_work);
453 int state = READ_ONCE(drm->fbcon_new_state);
454
455 if (state == FBINFO_STATE_RUNNING)
456 pm_runtime_get_sync(drm->dev->dev);
457
458 console_lock();
459 if (state == FBINFO_STATE_RUNNING)
460 nouveau_fbcon_accel_restore(drm->dev);
461 drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
462 if (state != FBINFO_STATE_RUNNING)
463 nouveau_fbcon_accel_save_disable(drm->dev);
464 console_unlock();
465
466 if (state == FBINFO_STATE_RUNNING) {
467 nouveau_fbcon_hotplug_resume(drm->fbcon);
468 pm_runtime_mark_last_busy(drm->dev->dev);
469 pm_runtime_put_autosuspend(drm->dev->dev);
470 }
471}
472
473void
474nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
475{
476 struct nouveau_drm *drm = nouveau_drm(dev);
477
478 if (!drm->fbcon)
479 return;
480
481 drm->fbcon_new_state = state;
482 /* Since runtime resume can happen as a result of a sysfs operation,
483 * it's possible we already have the console locked. So handle fbcon
484 * init/deinit from a seperate work thread
485 */
486 schedule_work(&drm->fbcon_work);
487}
488
489void
490nouveau_fbcon_output_poll_changed(struct drm_device *dev)
491{
492 struct nouveau_drm *drm = nouveau_drm(dev);
493 struct nouveau_fbdev *fbcon = drm->fbcon;
494 int ret;
495
496 if (!fbcon)
497 return;
498
499 mutex_lock(&fbcon->hotplug_lock);
500
501 ret = pm_runtime_get(dev->dev);
502 if (ret == 1 || ret == -EACCES) {
503 drm_fb_helper_hotplug_event(&fbcon->helper);
504
505 pm_runtime_mark_last_busy(dev->dev);
506 pm_runtime_put_autosuspend(dev->dev);
507 } else if (ret == 0) {
508 /* If the GPU was already in the process of suspending before
509 * this event happened, then we can't block here as we'll
510 * deadlock the runtime pmops since they wait for us to
511 * finish. So, just defer this event for when we runtime
512 * resume again. It will be handled by fbcon_work.
513 */
514 NV_DEBUG(drm, "fbcon HPD event deferred until runtime resume\n");
515 fbcon->hotplug_waiting = true;
516 pm_runtime_put_noidle(drm->dev->dev);
517 } else {
518 DRM_WARN("fbcon HPD event lost due to RPM failure: %d\n",
519 ret);
520 }
521
522 mutex_unlock(&fbcon->hotplug_lock);
523}
524
525void
526nouveau_fbcon_hotplug_resume(struct nouveau_fbdev *fbcon)
527{
528 struct nouveau_drm *drm;
529
530 if (!fbcon)
531 return;
532 drm = nouveau_drm(fbcon->helper.dev);
533
534 mutex_lock(&fbcon->hotplug_lock);
535 if (fbcon->hotplug_waiting) {
536 fbcon->hotplug_waiting = false;
537
538 NV_DEBUG(drm, "Handling deferred fbcon HPD events\n");
539 drm_fb_helper_hotplug_event(&fbcon->helper);
540 }
541 mutex_unlock(&fbcon->hotplug_lock);
542}
543
544int
545nouveau_fbcon_init(struct drm_device *dev)
546{
547 struct nouveau_drm *drm = nouveau_drm(dev);
548 struct nouveau_fbdev *fbcon;
549 int preferred_bpp = nouveau_fbcon_bpp;
550 int ret;
551
552 if (!dev->mode_config.num_crtc ||
553 (to_pci_dev(dev->dev)->class >> 8) != PCI_CLASS_DISPLAY_VGA)
554 return 0;
555
556 fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
557 if (!fbcon)
558 return -ENOMEM;
559
560 drm->fbcon = fbcon;
561 INIT_WORK(&drm->fbcon_work, nouveau_fbcon_set_suspend_work);
562 mutex_init(&fbcon->hotplug_lock);
563
564 drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
565
566 ret = drm_fb_helper_init(dev, &fbcon->helper);
567 if (ret)
568 goto free;
569
570 if (preferred_bpp != 8 && preferred_bpp != 16 && preferred_bpp != 32) {
571 if (drm->client.device.info.ram_size <= 32 * 1024 * 1024)
572 preferred_bpp = 8;
573 else
574 if (drm->client.device.info.ram_size <= 64 * 1024 * 1024)
575 preferred_bpp = 16;
576 else
577 preferred_bpp = 32;
578 }
579
580 /* disable all the possible outputs/crtcs before entering KMS mode */
581 if (!drm_drv_uses_atomic_modeset(dev))
582 drm_helper_disable_unused_functions(dev);
583
584 ret = drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp);
585 if (ret)
586 goto fini;
587
588 if (fbcon->helper.info)
589 fbcon->helper.info->pixmap.buf_align = 4;
590 return 0;
591
592fini:
593 drm_fb_helper_fini(&fbcon->helper);
594free:
595 kfree(fbcon);
596 drm->fbcon = NULL;
597 return ret;
598}
599
600void
601nouveau_fbcon_fini(struct drm_device *dev)
602{
603 struct nouveau_drm *drm = nouveau_drm(dev);
604
605 if (!drm->fbcon)
606 return;
607
608 drm_kms_helper_poll_fini(dev);
609 nouveau_fbcon_accel_fini(dev);
610 nouveau_fbcon_destroy(dev, drm->fbcon);
611 kfree(drm->fbcon);
612 drm->fbcon = NULL;
613}
drivers/gpu/drm/ttm/ttm_bo_util.c+1−1
@@ -173,7 +173,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, · 172 unmodified lines
173 173
174 clear = src_iter->ops->maps_tt && (!ttm || !ttm_tt_is_populated(ttm));174 clear = src_iter->ops->maps_tt && (!ttm || !ttm_tt_is_populated(ttm));
175 if (!(clear && ttm && !(ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC)))175 if (!(clear && ttm && !(ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC)))
176 ttm_move_memcpy(clear, ttm->num_pages, dst_iter, src_iter);176 ttm_move_memcpy(clear, PFN_UP(dst_mem->size), dst_iter, src_iter);
177 177
178 if (!src_iter->ops->maps_tt)178 if (!src_iter->ops->maps_tt)
179 ttm_kmap_iter_linear_io_fini(&_src_iter.io, bdev, src_mem);179 ttm_kmap_iter_linear_io_fini(&_src_iter.io, bdev, src_mem);
drivers/gpu/drm/virtio/virtgpu_ioctl.c+17−2
@@ -358,10 +358,18 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, · 357 unmodified lines
358 drm_gem_object_release(obj);358 drm_gem_object_release(obj);
359 return ret;359 return ret;
360 }360 }
361 drm_gem_object_put(obj);
362 361
363 rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */362 rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */
364 rc->bo_handle = handle;363 rc->bo_handle = handle;
364
365 /*
366 * The handle owns the reference now. But we must drop our
367 * remaining reference *after* we no longer need to dereference
368 * the obj. Otherwise userspace could guess the handle and
369 * race closing it from another thread.
370 */
371 drm_gem_object_put(obj);
372
365 return 0;373 return 0;
366}374}
367 375
@@ -723,11 +731,18 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, · 355 unmodified lines
723 drm_gem_object_release(obj);731 drm_gem_object_release(obj);
724 return ret;732 return ret;
725 }733 }
726 drm_gem_object_put(obj);
727 734
728 rc_blob->res_handle = bo->hw_res_handle;735 rc_blob->res_handle = bo->hw_res_handle;
729 rc_blob->bo_handle = handle;736 rc_blob->bo_handle = handle;
730 737
738 /*
739 * The handle owns the reference now. But we must drop our
740 * remaining reference *after* we no longer need to dereference
741 * the obj. Otherwise userspace could guess the handle and
742 * race closing it from another thread.
743 */
744 drm_gem_object_put(obj);
745
731 return 0;746 return 0;
732}747}
733 748
drivers/gpu/drm/vmwgfx/ttm_object.c+4−37
@@ -254,40 +254,6 @@ void ttm_base_object_unref(struct ttm_base_object **p_base) · 253 unmodified lines
254 kref_put(&base->refcount, ttm_release_base);254 kref_put(&base->refcount, ttm_release_base);
255}255}
256 256
257/**
258 * ttm_base_object_noref_lookup - look up a base object without reference
259 * @tfile: The struct ttm_object_file the object is registered with.
260 * @key: The object handle.
261 *
262 * This function looks up a ttm base object and returns a pointer to it
263 * without refcounting the pointer. The returned pointer is only valid
264 * until ttm_base_object_noref_release() is called, and the object
265 * pointed to by the returned pointer may be doomed. Any persistent usage
266 * of the object requires a refcount to be taken using kref_get_unless_zero().
267 * Iff this function returns successfully it needs to be paired with
268 * ttm_base_object_noref_release() and no sleeping- or scheduling functions
269 * may be called inbetween these function callse.
270 *
271 * Return: A pointer to the object if successful or NULL otherwise.
272 */
273struct ttm_base_object *
274ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
275{
276 struct vmwgfx_hash_item *hash;
277 int ret;
278
279 rcu_read_lock();
280 ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
281 if (ret) {
282 rcu_read_unlock();
283 return NULL;
284 }
285
286 __release(RCU);
287 return hlist_entry(hash, struct ttm_ref_object, hash)->obj;
288}
289EXPORT_SYMBOL(ttm_base_object_noref_lookup);
290
291struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,257struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
292 uint64_t key)258 uint64_t key)
293{259{
@@ -295,15 +261,16 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, · 1 unmodified line
295 struct vmwgfx_hash_item *hash;261 struct vmwgfx_hash_item *hash;
296 int ret;262 int ret;
297 263
298 rcu_read_lock();264 spin_lock(&tfile->lock);
299 ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);265 ret = ttm_tfile_find_ref(tfile, key, &hash);
300 266
301 if (likely(ret == 0)) {267 if (likely(ret == 0)) {
302 base = hlist_entry(hash, struct ttm_ref_object, hash)->obj;268 base = hlist_entry(hash, struct ttm_ref_object, hash)->obj;
303 if (!kref_get_unless_zero(&base->refcount))269 if (!kref_get_unless_zero(&base->refcount))
304 base = NULL;270 base = NULL;
305 }271 }
306 rcu_read_unlock();272 spin_unlock(&tfile->lock);
273
307 274
308 return base;275 return base;
309}276}
drivers/gpu/drm/vmwgfx/ttm_object.h+0−14
@@ -307,18 +307,4 @@ extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile, · 306 unmodified lines
307#define ttm_prime_object_kfree(__obj, __prime) \307#define ttm_prime_object_kfree(__obj, __prime) \
308 kfree_rcu(__obj, __prime.base.rhead)308 kfree_rcu(__obj, __prime.base.rhead)
309 309
310struct ttm_base_object *
311ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key);
312
313/**
314 * ttm_base_object_noref_release - release a base object pointer looked up
315 * without reference
316 *
317 * Releases a base object pointer looked up with ttm_base_object_noref_lookup().
318 */
319static inline void ttm_base_object_noref_release(void)
320{
321 __acquire(RCU);
322 rcu_read_unlock();
323}
324#endif310#endif
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c+0−38
@@ -715,44 +715,6 @@ int vmw_user_bo_lookup(struct drm_file *filp, · 714 unmodified lines
715 return 0;715 return 0;
716}716}
717 717
718/**
719 * vmw_user_bo_noref_lookup - Look up a vmw user buffer object without reference
720 * @filp: The TTM object file the handle is registered with.
721 * @handle: The user buffer object handle.
722 *
723 * This function looks up a struct vmw_bo and returns a pointer to the
724 * struct vmw_buffer_object it derives from without refcounting the pointer.
725 * The returned pointer is only valid until vmw_user_bo_noref_release() is
726 * called, and the object pointed to by the returned pointer may be doomed.
727 * Any persistent usage of the object requires a refcount to be taken using
728 * ttm_bo_reference_unless_doomed(). Iff this function returns successfully it
729 * needs to be paired with vmw_user_bo_noref_release() and no sleeping-
730 * or scheduling functions may be called in between these function calls.
731 *
732 * Return: A struct vmw_buffer_object pointer if successful or negative
733 * error pointer on failure.
734 */
735struct vmw_buffer_object *
736vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle)
737{
738 struct vmw_buffer_object *vmw_bo;
739 struct ttm_buffer_object *bo;
740 struct drm_gem_object *gobj = drm_gem_object_lookup(filp, handle);
741
742 if (!gobj) {
743 DRM_ERROR("Invalid buffer object handle 0x%08lx.\n",
744 (unsigned long)handle);
745 return ERR_PTR(-ESRCH);
746 }
747 vmw_bo = gem_to_vmw_bo(gobj);
748 bo = ttm_bo_get_unless_zero(&vmw_bo->base);
749 vmw_bo = vmw_buffer_object(bo);
750 drm_gem_object_put(gobj);
751
752 return vmw_bo;
753}
754
755
756/**718/**
757 * vmw_bo_fence_single - Utility function to fence a single TTM buffer719 * vmw_bo_fence_single - Utility function to fence a single TTM buffer
758 * object without unreserving it.720 * object without unreserving it.
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h+1−17
@@ -830,12 +830,7 @@ extern int vmw_user_resource_lookup_handle( · 829 unmodified lines
830 uint32_t handle,830 uint32_t handle,
831 const struct vmw_user_resource_conv *converter,831 const struct vmw_user_resource_conv *converter,
832 struct vmw_resource **p_res);832 struct vmw_resource **p_res);
833extern struct vmw_resource *833
834vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
835 struct ttm_object_file *tfile,
836 uint32_t handle,
837 const struct vmw_user_resource_conv *
838 converter);
839extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,834extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
840 struct drm_file *file_priv);835 struct drm_file *file_priv);
841extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,836extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -874,15 +869,6 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res) · 32 unmodified lines
874 return !RB_EMPTY_NODE(&res->mob_node);869 return !RB_EMPTY_NODE(&res->mob_node);
875}870}
876 871
877/**
878 * vmw_user_resource_noref_release - release a user resource pointer looked up
879 * without reference
880 */
881static inline void vmw_user_resource_noref_release(void)
882{
883 ttm_base_object_noref_release();
884}
885
886/**872/**
887 * Buffer object helper functions - vmwgfx_bo.c873 * Buffer object helper functions - vmwgfx_bo.c
888 */874 */
@@ -934,8 +920,6 @@ extern void vmw_bo_unmap(struct vmw_buffer_object *vbo); · 45 unmodified lines
934extern void vmw_bo_move_notify(struct ttm_buffer_object *bo,920extern void vmw_bo_move_notify(struct ttm_buffer_object *bo,
935 struct ttm_resource *mem);921 struct ttm_resource *mem);
936extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo);922extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo);
937extern struct vmw_buffer_object *
938vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle);
939 923
940/**924/**
941 * vmw_bo_adjust_prio - Adjust the buffer object eviction priority925 * vmw_bo_adjust_prio - Adjust the buffer object eviction priority
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c+82−94
@@ -290,20 +290,26 @@ static void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache, · 289 unmodified lines
290 rcache->valid_handle = 0;290 rcache->valid_handle = 0;
291}291}
292 292
293enum vmw_val_add_flags {
294 vmw_val_add_flag_none = 0,
295 vmw_val_add_flag_noctx = 1 << 0,
296};
297
293/**298/**
294 * vmw_execbuf_res_noref_val_add - Add a resource described by an unreferenced299 * vmw_execbuf_res_val_add - Add a resource to the validation list.
295 * rcu-protected pointer to the validation list.
296 *300 *
297 * @sw_context: Pointer to the software context.301 * @sw_context: Pointer to the software context.
298 * @res: Unreferenced rcu-protected pointer to the resource.302 * @res: Unreferenced rcu-protected pointer to the resource.
299 * @dirty: Whether to change dirty status.303 * @dirty: Whether to change dirty status.
304 * @flags: specifies whether to use the context or not
300 *305 *
301 * Returns: 0 on success. Negative error code on failure. Typical error codes306 * Returns: 0 on success. Negative error code on failure. Typical error codes
302 * are %-EINVAL on inconsistency and %-ESRCH if the resource was doomed.307 * are %-EINVAL on inconsistency and %-ESRCH if the resource was doomed.
303 */308 */
304static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context,309static int vmw_execbuf_res_val_add(struct vmw_sw_context *sw_context,
305 struct vmw_resource *res,310 struct vmw_resource *res,
306 u32 dirty)311 u32 dirty,
312 u32 flags)
307{313{
308 struct vmw_private *dev_priv = res->dev_priv;314 struct vmw_private *dev_priv = res->dev_priv;
309 int ret;315 int ret;
@@ -318,24 +324,30 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, · 8 unmodified lines
318 if (dirty)324 if (dirty)
319 vmw_validation_res_set_dirty(sw_context->ctx,325 vmw_validation_res_set_dirty(sw_context->ctx,
320 rcache->private, dirty);326 rcache->private, dirty);
321 vmw_user_resource_noref_release();
322 return 0;327 return 0;
323 }328 }
324 329
325 priv_size = vmw_execbuf_res_size(dev_priv, res_type);330 if ((flags & vmw_val_add_flag_noctx) != 0) {
326 ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size,331 ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty,
327 dirty, (void **)&ctx_info,332 (void **)&ctx_info, NULL);
328 &first_usage);333 if (ret)
329 vmw_user_resource_noref_release();334 return ret;
330 if (ret)
331 return ret;
332 335
333 if (priv_size && first_usage) {336 } else {
334 ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res,337 priv_size = vmw_execbuf_res_size(dev_priv, res_type);
335 ctx_info);338 ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size,
336 if (ret) {339 dirty, (void **)&ctx_info,
337 VMW_DEBUG_USER("Failed first usage context setup.\n");340 &first_usage);
341 if (ret)
338 return ret;342 return ret;
343
344 if (priv_size && first_usage) {
345 ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res,
346 ctx_info);
347 if (ret) {
348 VMW_DEBUG_USER("Failed first usage context setup.\n");
349 return ret;
350 }
339 }351 }
340 }352 }
341 353
@@ -343,43 +355,6 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context, · 1 unmodified line
343 return 0;355 return 0;
344}356}
345 357
346/**
347 * vmw_execbuf_res_noctx_val_add - Add a non-context resource to the resource
348 * validation list if it's not already on it
349 *
350 * @sw_context: Pointer to the software context.
351 * @res: Pointer to the resource.
352 * @dirty: Whether to change dirty status.
353 *
354 * Returns: Zero on success. Negative error code on failure.
355 */
356static int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context,
357 struct vmw_resource *res,
358 u32 dirty)
359{
360 struct vmw_res_cache_entry *rcache;
361 enum vmw_res_type res_type = vmw_res_type(res);
362 void *ptr;
363 int ret;
364
365 rcache = &sw_context->res_cache[res_type];
366 if (likely(rcache->valid && rcache->res == res)) {
367 if (dirty)
368 vmw_validation_res_set_dirty(sw_context->ctx,
369 rcache->private, dirty);
370 return 0;
371 }
372
373 ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty,
374 &ptr, NULL);
375 if (ret)
376 return ret;
377
378 vmw_execbuf_rcache_update(rcache, res, ptr);
379
380 return 0;
381}
382
383/**358/**
384 * vmw_view_res_val_add - Add a view and the surface it's pointing to to the359 * vmw_view_res_val_add - Add a view and the surface it's pointing to to the
385 * validation list360 * validation list
@@ -398,13 +373,13 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context, · 12 unmodified lines
398 * First add the resource the view is pointing to, otherwise it may be373 * First add the resource the view is pointing to, otherwise it may be
399 * swapped out when the view is validated.374 * swapped out when the view is validated.
400 */375 */
401 ret = vmw_execbuf_res_noctx_val_add(sw_context, vmw_view_srf(view),376 ret = vmw_execbuf_res_val_add(sw_context, vmw_view_srf(view),
402 vmw_view_dirtying(view));377 vmw_view_dirtying(view), vmw_val_add_flag_noctx);
403 if (ret)378 if (ret)
404 return ret;379 return ret;
405 380
406 return vmw_execbuf_res_noctx_val_add(sw_context, view,381 return vmw_execbuf_res_val_add(sw_context, view, VMW_RES_DIRTY_NONE,
407 VMW_RES_DIRTY_NONE);382 vmw_val_add_flag_noctx);
408}383}
409 384
410/**385/**
@@ -475,8 +450,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, · 64 unmodified lines
475 if (IS_ERR(res))450 if (IS_ERR(res))
476 continue;451 continue;
477 452
478 ret = vmw_execbuf_res_noctx_val_add(sw_context, res,453 ret = vmw_execbuf_res_val_add(sw_context, res,
479 VMW_RES_DIRTY_SET);454 VMW_RES_DIRTY_SET,
455 vmw_val_add_flag_noctx);
480 if (unlikely(ret != 0))456 if (unlikely(ret != 0))
481 return ret;457 return ret;
482 }458 }
@@ -490,9 +466,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, · 7 unmodified lines
490 if (vmw_res_type(entry->res) == vmw_res_view)466 if (vmw_res_type(entry->res) == vmw_res_view)
491 ret = vmw_view_res_val_add(sw_context, entry->res);467 ret = vmw_view_res_val_add(sw_context, entry->res);
492 else468 else
493 ret = vmw_execbuf_res_noctx_val_add469 ret = vmw_execbuf_res_val_add(sw_context, entry->res,
494 (sw_context, entry->res,470 vmw_binding_dirtying(entry->bt),
495 vmw_binding_dirtying(entry->bt));471 vmw_val_add_flag_noctx);
496 if (unlikely(ret != 0))472 if (unlikely(ret != 0))
497 break;473 break;
498 }474 }
@@ -658,7 +634,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, · 159 unmodified lines
658{634{
659 struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type];635 struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type];
660 struct vmw_resource *res;636 struct vmw_resource *res;
661 int ret;637 int ret = 0;
638 bool needs_unref = false;
662 639
663 if (p_res)640 if (p_res)
664 *p_res = NULL;641 *p_res = NULL;
@@ -683,17 +660,18 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, · 18 unmodified lines
683 if (ret)660 if (ret)
684 return ret;661 return ret;
685 662
686 res = vmw_user_resource_noref_lookup_handle663 ret = vmw_user_resource_lookup_handle
687 (dev_priv, sw_context->fp->tfile, *id_loc, converter);664 (dev_priv, sw_context->fp->tfile, *id_loc, converter, &res);
688 if (IS_ERR(res)) {665 if (ret != 0) {
689 VMW_DEBUG_USER("Could not find/use resource 0x%08x.\n",666 VMW_DEBUG_USER("Could not find/use resource 0x%08x.\n",
690 (unsigned int) *id_loc);667 (unsigned int) *id_loc);
691 return PTR_ERR(res);668 return ret;
692 }669 }
670 needs_unref = true;
693 671
694 ret = vmw_execbuf_res_noref_val_add(sw_context, res, dirty);672 ret = vmw_execbuf_res_val_add(sw_context, res, dirty, vmw_val_add_flag_none);
695 if (unlikely(ret != 0))673 if (unlikely(ret != 0))
696 return ret;674 goto res_check_done;
697 675
698 if (rcache->valid && rcache->res == res) {676 if (rcache->valid && rcache->res == res) {
699 rcache->valid_handle = true;677 rcache->valid_handle = true;
@@ -708,7 +686,11 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, · 8 unmodified lines
708 if (p_res)686 if (p_res)
709 *p_res = res;687 *p_res = res;
710 688
711 return 0;689res_check_done:
690 if (needs_unref)
691 vmw_resource_unreference(&res);
692
693 return ret;
712}694}
713 695
714/**696/**
@@ -1171,9 +1153,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 456 unmodified lines
1171 int ret;1153 int ret;
1172 1154
1173 vmw_validation_preload_bo(sw_context->ctx);1155 vmw_validation_preload_bo(sw_context->ctx);
1174 vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle);1156 ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
1175 if (IS_ERR(vmw_bo)) {1157 if (ret != 0) {
1176 VMW_DEBUG_USER("Could not find or use MOB buffer.\n");1158 drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");
1177 return PTR_ERR(vmw_bo);1159 return PTR_ERR(vmw_bo);
1178 }1160 }
1179 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false);1161 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false);
@@ -1225,9 +1207,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 45 unmodified lines
1225 int ret;1207 int ret;
1226 1208
1227 vmw_validation_preload_bo(sw_context->ctx);1209 vmw_validation_preload_bo(sw_context->ctx);
1228 vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle);1210 ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
1229 if (IS_ERR(vmw_bo)) {1211 if (ret != 0) {
1230 VMW_DEBUG_USER("Could not find or use GMR region.\n");1212 drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");
1231 return PTR_ERR(vmw_bo);1213 return PTR_ERR(vmw_bo);
1232 }1214 }
1233 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false);1215 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false);
@@ -2025,8 +2007,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, · 791 unmodified lines
2025 res = vmw_shader_lookup(vmw_context_res_man(ctx),2007 res = vmw_shader_lookup(vmw_context_res_man(ctx),
2026 cmd->body.shid, cmd->body.type);2008 cmd->body.shid, cmd->body.type);
2027 if (!IS_ERR(res)) {2009 if (!IS_ERR(res)) {
2028 ret = vmw_execbuf_res_noctx_val_add(sw_context, res,2010 ret = vmw_execbuf_res_val_add(sw_context, res,
2029 VMW_RES_DIRTY_NONE);2011 VMW_RES_DIRTY_NONE,
2012 vmw_val_add_flag_noctx);
2030 if (unlikely(ret != 0))2013 if (unlikely(ret != 0))
2031 return ret;2014 return ret;
2032 2015
@@ -2273,8 +2256,9 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, · 240 unmodified lines
2273 return PTR_ERR(res);2256 return PTR_ERR(res);
2274 }2257 }
2275 2258
2276 ret = vmw_execbuf_res_noctx_val_add(sw_context, res,2259 ret = vmw_execbuf_res_val_add(sw_context, res,
2277 VMW_RES_DIRTY_NONE);2260 VMW_RES_DIRTY_NONE,
2261 vmw_val_add_flag_noctx);
2278 if (ret)2262 if (ret)
2279 return ret;2263 return ret;
2280 }2264 }
@@ -2777,8 +2761,8 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv, · 496 unmodified lines
2777 return PTR_ERR(res);2761 return PTR_ERR(res);
2778 }2762 }
2779 2763
2780 ret = vmw_execbuf_res_noctx_val_add(sw_context, res,2764 ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE,
2781 VMW_RES_DIRTY_NONE);2765 vmw_val_add_flag_noctx);
2782 if (ret) {2766 if (ret) {
2783 VMW_DEBUG_USER("Error creating resource validation node.\n");2767 VMW_DEBUG_USER("Error creating resource validation node.\n");
2784 return ret;2768 return ret;
@@ -3098,8 +3082,8 @@ static int vmw_cmd_dx_bind_streamoutput(struct vmw_private *dev_priv, · 313 unmodified lines
3098 3082
3099 vmw_dx_streamoutput_set_size(res, cmd->body.sizeInBytes);3083 vmw_dx_streamoutput_set_size(res, cmd->body.sizeInBytes);
3100 3084
3101 ret = vmw_execbuf_res_noctx_val_add(sw_context, res,3085 ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE,
3102 VMW_RES_DIRTY_NONE);3086 vmw_val_add_flag_noctx);
3103 if (ret) {3087 if (ret) {
3104 DRM_ERROR("Error creating resource validation node.\n");3088 DRM_ERROR("Error creating resource validation node.\n");
3105 return ret;3089 return ret;
@@ -3148,8 +3132,8 @@ static int vmw_cmd_dx_set_streamoutput(struct vmw_private *dev_priv, · 42 unmodified lines
3148 return 0;3132 return 0;
3149 }3133 }
3150 3134
3151 ret = vmw_execbuf_res_noctx_val_add(sw_context, res,3135 ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE,
3152 VMW_RES_DIRTY_NONE);3136 vmw_val_add_flag_noctx);
3153 if (ret) {3137 if (ret) {
3154 DRM_ERROR("Error creating resource validation node.\n");3138 DRM_ERROR("Error creating resource validation node.\n");
3155 return ret;3139 return ret;
@@ -4066,22 +4050,26 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv, · 910 unmodified lines
4066 if (ret)4050 if (ret)
4067 return ret;4051 return ret;
4068 4052
4069 res = vmw_user_resource_noref_lookup_handle4053 ret = vmw_user_resource_lookup_handle
4070 (dev_priv, sw_context->fp->tfile, handle,4054 (dev_priv, sw_context->fp->tfile, handle,
4071 user_context_converter);4055 user_context_converter, &res);
4072 if (IS_ERR(res)) {4056 if (ret != 0) {
4073 VMW_DEBUG_USER("Could not find or user DX context 0x%08x.\n",4057 VMW_DEBUG_USER("Could not find or user DX context 0x%08x.\n",
4074 (unsigned int) handle);4058 (unsigned int) handle);
4075 return PTR_ERR(res);4059 return ret;
4076 }4060 }
4077 4061
4078 ret = vmw_execbuf_res_noref_val_add(sw_context, res, VMW_RES_DIRTY_SET);4062 ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_SET,
4079 if (unlikely(ret != 0))4063 vmw_val_add_flag_none);
4064 if (unlikely(ret != 0)) {
4065 vmw_resource_unreference(&res);
4080 return ret;4066 return ret;
4067 }
4081 4068
4082 sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res);4069 sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res);
4083 sw_context->man = vmw_context_res_man(res);4070 sw_context->man = vmw_context_res_man(res);
4084 4071
4072 vmw_resource_unreference(&res);
4085 return 0;4073 return 0;
4086}4074}
4087 4075
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c+0−33
@@ -281,39 +281,6 @@ out_bad_resource: · 280 unmodified lines
281 return ret;281 return ret;
282}282}
283 283
284/**
285 * vmw_user_resource_noref_lookup_handle - lookup a struct resource from a
286 * TTM user-space handle and perform basic type checks
287 *
288 * @dev_priv: Pointer to a device private struct
289 * @tfile: Pointer to a struct ttm_object_file identifying the caller
290 * @handle: The TTM user-space handle
291 * @converter: Pointer to an object describing the resource type
292 *
293 * If the handle can't be found or is associated with an incorrect resource
294 * type, -EINVAL will be returned.
295 */
296struct vmw_resource *
297vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
298 struct ttm_object_file *tfile,
299 uint32_t handle,
300 const struct vmw_user_resource_conv
301 *converter)
302{
303 struct ttm_base_object *base;
304
305 base = ttm_base_object_noref_lookup(tfile, handle);
306 if (!base)
307 return ERR_PTR(-ESRCH);
308
309 if (unlikely(ttm_base_object_type(base) != converter->object_type)) {
310 ttm_base_object_noref_release();
311 return ERR_PTR(-EINVAL);
312 }
313
314 return converter->base_obj_to_res(base);
315}
316
317/*284/*
318 * Helper function that looks either a surface or bo.285 * Helper function that looks either a surface or bo.
319 *286 *