Pull drm fixes from Dave Airlie: "Bit of an uptick in patch count this week, though it's all relatively small overall. I suspect msm has been queuing up a few fixes to skew it here. Otherwise amdgpu has a scattered bunch of small fixes, and then some vc4, i915. virtio-gpu changes an rc1 introduced uAPI mistake, and makes it operate more like other drivers. This should be fine as no userspace relies on the behaviour yet. Summary: dma-buf: - memory leak fix msm: - kasan found memory overwrite - mmap flags - fencing error bug - ioctl NULL ptr - uninit var - devfreqless devices fix - dsi lanes fix - dp: avoid unpowered aux xfers amdgpu: - IP discovery based enumeration fixes - vkms fixes - DSC fixes for DP MST - Audio fix for hotplug with tiled displays - Misc display fixes - DP tunneling fix - DP fix - Aldebaran fix amdkfd: - Locking fix - Static checker fix - Fix double free i915: - backlight regression - Intel HDR backlight detection fix - revert TGL workaround that caused hangs virtio-gpu: - switch back to drm_poll vc4: - memory leak - error check fix - HVS modesetting fixes" * tag 'drm-fixes-2021-12-03-1' of git://anongit.freedesktop.org/drm/drm: (41 commits) Revert "drm/i915: Implement Wa_1508744258" drm/amdkfd: process_info lock not needed for svm drm/amdgpu: adjust the kfd reset sequence in reset sriov function drm/amd/display: add connector type check for CRC source set drm/amdkfd: fix double free mem structure drm/amdkfd: set "r = 0" explicitly before goto drm/amd/display: Add work around for tunneled MST. drm/amd/display: Fix for the no Audio bug with Tiled Displays drm/amd/display: Clear DPCD lane settings after repeater training drm/amd/display: Allow DSC on supported MST branch devices drm/amdgpu: Don't halt RLC on GFX suspend drm/amdgpu: fix the missed handling for SDMA2 and SDMA3 drm/amdgpu: check atomic flag to differeniate with legacy path drm/amdgpu: cancel the correct hrtimer on exit drm/amdgpu/sriov/vcn: add new vcn ip revision check case for SIENNA_CICHLID drm/i915/dp: Perform 30ms delay after source OUI write dma-buf: system_heap: Use 'for_each_sgtable_sg' in pages free flow drm/i915: Add support for panels with VESA backlights with PWM enable/disable drm/vc4: kms: Fix previous HVS commit wait drm/vc4: kms: Don't duplicate pending commit ...
Unified · Split
| @@ -290,7 +290,7 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf) · 289 unmodified lines | ||
| 290 | 290 | int i; |
| 291 | 291 | |
| 292 | 292 | table = &buffer->sg_table; |
| 293 | − for_each_sg(table->sgl, sg, table->nents, i) { | |
| 293 | + for_each_sgtable_sg(table, sg, i) { | |
| 294 | 294 | struct page *page = sg_page(sg); |
| 295 | 295 | |
| 296 | 296 | __free_pages(page, compound_order(page)); |
| @@ -1396,7 +1396,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 1395 unmodified lines | ||
| 1396 | 1396 | struct sg_table *sg = NULL; |
| 1397 | 1397 | uint64_t user_addr = 0; |
| 1398 | 1398 | struct amdgpu_bo *bo; |
| 1399 | − struct drm_gem_object *gobj; | |
| 1399 | + struct drm_gem_object *gobj = NULL; | |
| 1400 | 1400 | u32 domain, alloc_domain; |
| 1401 | 1401 | u64 alloc_flags; |
| 1402 | 1402 | int ret; |
| @@ -1506,14 +1506,16 @@ allocate_init_user_pages_failed: · 103 unmodified lines | ||
| 1506 | 1506 | remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info); |
| 1507 | 1507 | drm_vma_node_revoke(&gobj->vma_node, drm_priv); |
| 1508 | 1508 | err_node_allow: |
| 1509 | − drm_gem_object_put(gobj); | |
| 1510 | 1509 | /* Don't unreserve system mem limit twice */ |
| 1511 | 1510 | goto err_reserve_limit; |
| 1512 | 1511 | err_bo_create: |
| 1513 | 1512 | unreserve_mem_limit(adev, size, alloc_domain, !!sg); |
| 1514 | 1513 | err_reserve_limit: |
| 1515 | 1514 | mutex_destroy(&(*mem)->lock); |
| 1516 | − kfree(*mem); | |
| 1515 | + if (gobj) | |
| 1516 | + drm_gem_object_put(gobj); | |
| 1517 | + else | |
| 1518 | + kfree(*mem); | |
| 1517 | 1519 | err: |
| 1518 | 1520 | if (sg) { |
| 1519 | 1521 | sg_free_table(sg); |
| @@ -3833,7 +3833,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) · 3832 unmodified lines | ||
| 3833 | 3833 | /* disable all interrupts */ |
| 3834 | 3834 | amdgpu_irq_disable_all(adev); |
| 3835 | 3835 | if (adev->mode_info.mode_config_initialized){ |
| 3836 | − if (!amdgpu_device_has_dc_support(adev)) | |
| 3836 | + if (!drm_drv_uses_atomic_modeset(adev_to_drm(adev))) | |
| 3837 | 3837 | drm_helper_force_disable_all(adev_to_drm(adev)); |
| 3838 | 3838 | else |
| 3839 | 3839 | drm_atomic_helper_shutdown(adev_to_drm(adev)); |
| @@ -4289,6 +4289,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, · 449 unmodified lines | ||
| 4289 | 4289 | { |
| 4290 | 4290 | int r; |
| 4291 | 4291 | |
| 4292 | + amdgpu_amdkfd_pre_reset(adev); | |
| 4293 | + | |
| 4292 | 4294 | if (from_hypervisor) |
| 4293 | 4295 | r = amdgpu_virt_request_full_gpu(adev, true); |
| 4294 | 4296 | else |
| @@ -4316,6 +4318,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, · 21 unmodified lines | ||
| 4316 | 4318 | |
| 4317 | 4319 | amdgpu_irq_gpu_reset_resume_helper(adev); |
| 4318 | 4320 | r = amdgpu_ib_ring_tests(adev); |
| 4321 | + amdgpu_amdkfd_post_reset(adev); | |
| 4319 | 4322 | |
| 4320 | 4323 | error: |
| 4321 | 4324 | if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) { |
| @@ -5030,7 +5033,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 708 unmodified lines | ||
| 5030 | 5033 | |
| 5031 | 5034 | cancel_delayed_work_sync(&tmp_adev->delayed_init_work); |
| 5032 | 5035 | |
| 5033 | − amdgpu_amdkfd_pre_reset(tmp_adev); | |
| 5036 | + if (!amdgpu_sriov_vf(tmp_adev)) | |
| 5037 | + amdgpu_amdkfd_pre_reset(tmp_adev); | |
| 5034 | 5038 | |
| 5035 | 5039 | /* |
| 5036 | 5040 | * Mark these ASICs to be reseted as untracked first |
| @@ -5129,7 +5133,7 @@ skip_hw_reset: · 92 unmodified lines | ||
| 5129 | 5133 | drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); |
| 5130 | 5134 | } |
| 5131 | 5135 | |
| 5132 | − if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) { | |
| 5136 | + if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) { | |
| 5133 | 5137 | drm_helper_resume_force_mode(adev_to_drm(tmp_adev)); |
| 5134 | 5138 | } |
| 5135 | 5139 | |
| @@ -5148,9 +5152,9 @@ skip_hw_reset: · 12 unmodified lines | ||
| 5148 | 5152 | |
| 5149 | 5153 | skip_sched_resume: |
| 5150 | 5154 | list_for_each_entry(tmp_adev, device_list_handle, reset_list) { |
| 5151 | − /* unlock kfd */ | |
| 5152 | − if (!need_emergency_restart) | |
| 5153 | − amdgpu_amdkfd_post_reset(tmp_adev); | |
| 5155 | + /* unlock kfd: SRIOV would do it separately */ | |
| 5156 | + if (!need_emergency_restart && !amdgpu_sriov_vf(tmp_adev)) | |
| 5157 | + amdgpu_amdkfd_post_reset(tmp_adev); | |
| 5154 | 5158 | |
| 5155 | 5159 | /* kfd_post_reset will do nothing if kfd device is not initialized, |
| 5156 | 5160 | * need to bring up kfd here if it's not be initialized before |
| @@ -157,6 +157,8 @@ static int hw_id_map[MAX_HWIP] = { · 156 unmodified lines | ||
| 157 | 157 | [HDP_HWIP] = HDP_HWID, |
| 158 | 158 | [SDMA0_HWIP] = SDMA0_HWID, |
| 159 | 159 | [SDMA1_HWIP] = SDMA1_HWID, |
| 160 | + [SDMA2_HWIP] = SDMA2_HWID, | |
| 161 | + [SDMA3_HWIP] = SDMA3_HWID, | |
| 160 | 162 | [MMHUB_HWIP] = MMHUB_HWID, |
| 161 | 163 | [ATHUB_HWIP] = ATHUB_HWID, |
| 162 | 164 | [NBIO_HWIP] = NBIF_HWID, |
| @@ -918,6 +920,7 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev) · 755 unmodified lines | ||
| 918 | 920 | case IP_VERSION(3, 0, 64): |
| 919 | 921 | case IP_VERSION(3, 1, 1): |
| 920 | 922 | case IP_VERSION(3, 0, 2): |
| 923 | + case IP_VERSION(3, 0, 192): | |
| 921 | 924 | amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block); |
| 922 | 925 | if (!amdgpu_sriov_vf(adev)) |
| 923 | 926 | amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block); |
| @@ -135,6 +135,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) · 134 unmodified lines | ||
| 135 | 135 | break; |
| 136 | 136 | case IP_VERSION(3, 0, 0): |
| 137 | 137 | case IP_VERSION(3, 0, 64): |
| 138 | + case IP_VERSION(3, 0, 192): | |
| 138 | 139 | if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0)) |
| 139 | 140 | fw_name = FIRMWARE_SIENNA_CICHLID; |
| 140 | 141 | else |
| @@ -504,8 +504,8 @@ static int amdgpu_vkms_sw_fini(void *handle) · 503 unmodified lines | ||
| 504 | 504 | int i = 0; |
| 505 | 505 | |
| 506 | 506 | for (i = 0; i < adev->mode_info.num_crtc; i++) |
| 507 | − if (adev->mode_info.crtcs[i]) | |
| 508 | − hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); | |
| 507 | + if (adev->amdgpu_vkms_output[i].vblank_hrtimer.function) | |
| 508 | + hrtimer_cancel(&adev->amdgpu_vkms_output[i].vblank_hrtimer); | |
| 509 | 509 | |
| 510 | 510 | kfree(adev->mode_info.bios_hardcoded_edid); |
| 511 | 511 | kfree(adev->amdgpu_vkms_output); |
| @@ -4060,9 +4060,10 @@ static int gfx_v9_0_hw_fini(void *handle) · 4059 unmodified lines | ||
| 4060 | 4060 | |
| 4061 | 4061 | gfx_v9_0_cp_enable(adev, false); |
| 4062 | 4062 | |
| 4063 | − /* Skip suspend with A+A reset */ | |
| 4064 | − if (adev->gmc.xgmi.connected_to_cpu && amdgpu_in_reset(adev)) { | |
| 4065 | − dev_dbg(adev->dev, "Device in reset. Skipping RLC halt\n"); | |
| 4063 | + /* Skip stopping RLC with A+A reset or when RLC controls GFX clock */ | |
| 4064 | + if ((adev->gmc.xgmi.connected_to_cpu && amdgpu_in_reset(adev)) || | |
| 4065 | + (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2))) { | |
| 4066 | + dev_dbg(adev->dev, "Skipping RLC halt\n"); | |
| 4066 | 4067 | return 0; |
| 4067 | 4068 | } |
| 4068 | 4069 | |
| @@ -183,6 +183,7 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode, · 182 unmodified lines | ||
| 183 | 183 | switch (adev->ip_versions[UVD_HWIP][0]) { |
| 184 | 184 | case IP_VERSION(3, 0, 0): |
| 185 | 185 | case IP_VERSION(3, 0, 64): |
| 186 | + case IP_VERSION(3, 0, 192): | |
| 186 | 187 | if (amdgpu_sriov_vf(adev)) { |
| 187 | 188 | if (encode) |
| 188 | 189 | *codecs = &sriov_sc_video_codecs_encode; |
| @@ -1574,7 +1574,6 @@ retry_flush_work: · 1573 unmodified lines | ||
| 1574 | 1574 | static void svm_range_restore_work(struct work_struct *work) |
| 1575 | 1575 | { |
| 1576 | 1576 | struct delayed_work *dwork = to_delayed_work(work); |
| 1577 | − struct amdkfd_process_info *process_info; | |
| 1578 | 1577 | struct svm_range_list *svms; |
| 1579 | 1578 | struct svm_range *prange; |
| 1580 | 1579 | struct kfd_process *p; |
| @@ -1594,12 +1593,10 @@ static void svm_range_restore_work(struct work_struct *work) · 13 unmodified lines | ||
| 1594 | 1593 | * the lifetime of this thread, kfd_process and mm will be valid. |
| 1595 | 1594 | */ |
| 1596 | 1595 | p = container_of(svms, struct kfd_process, svms); |
| 1597 | − process_info = p->kgd_process_info; | |
| 1598 | 1596 | mm = p->mm; |
| 1599 | 1597 | if (!mm) |
| 1600 | 1598 | return; |
| 1601 | 1599 | |
| 1602 | − mutex_lock(&process_info->lock); | |
| 1603 | 1600 | svm_range_list_lock_and_flush_work(svms, mm); |
| 1604 | 1601 | mutex_lock(&svms->lock); |
| 1605 | 1602 | |
| @@ -1652,7 +1649,6 @@ static void svm_range_restore_work(struct work_struct *work) · 46 unmodified lines | ||
| 1652 | 1649 | out_reschedule: |
| 1653 | 1650 | mutex_unlock(&svms->lock); |
| 1654 | 1651 | mmap_write_unlock(mm); |
| 1655 | − mutex_unlock(&process_info->lock); | |
| 1656 | 1652 | |
| 1657 | 1653 | /* If validation failed, reschedule another attempt */ |
| 1658 | 1654 | if (evicted_ranges) { |
| @@ -2614,6 +2610,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, · 955 unmodified lines | ||
| 2614 | 2610 | |
| 2615 | 2611 | if (atomic_read(&svms->drain_pagefaults)) { |
| 2616 | 2612 | pr_debug("draining retry fault, drop fault 0x%llx\n", addr); |
| 2613 | + r = 0; | |
| 2617 | 2614 | goto out; |
| 2618 | 2615 | } |
| 2619 | 2616 | |
| @@ -2623,6 +2620,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, · 3 unmodified lines | ||
| 2623 | 2620 | mm = get_task_mm(p->lead_thread); |
| 2624 | 2621 | if (!mm) { |
| 2625 | 2622 | pr_debug("svms 0x%p failed to get mm\n", svms); |
| 2623 | + r = 0; | |
| 2626 | 2624 | goto out; |
| 2627 | 2625 | } |
| 2628 | 2626 | |
| @@ -2660,6 +2658,7 @@ retry_write_locked: · 31 unmodified lines | ||
| 2660 | 2658 | |
| 2661 | 2659 | if (svm_range_skip_recover(prange)) { |
| 2662 | 2660 | amdgpu_gmc_filter_faults_remove(adev, addr, pasid); |
| 2661 | + r = 0; | |
| 2663 | 2662 | goto out_unlock_range; |
| 2664 | 2663 | } |
| 2665 | 2664 | |
| @@ -2668,6 +2667,7 @@ retry_write_locked: · 2 unmodified lines | ||
| 2668 | 2667 | if (timestamp < AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING) { |
| 2669 | 2668 | pr_debug("svms 0x%p [0x%lx %lx] already restored\n", |
| 2670 | 2669 | svms, prange->start, prange->last); |
| 2670 | + r = 0; | |
| 2671 | 2671 | goto out_unlock_range; |
| 2672 | 2672 | } |
| 2673 | 2673 | |
| @@ -3177,7 +3177,6 @@ static int · 503 unmodified lines | ||
| 3177 | 3177 | svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, |
| 3178 | 3178 | uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) |
| 3179 | 3179 | { |
| 3180 | − struct amdkfd_process_info *process_info = p->kgd_process_info; | |
| 3181 | 3180 | struct mm_struct *mm = current->mm; |
| 3182 | 3181 | struct list_head update_list; |
| 3183 | 3182 | struct list_head insert_list; |
| @@ -3196,8 +3195,6 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 12 unmodified lines | ||
| 3196 | 3195 | |
| 3197 | 3196 | svms = &p->svms; |
| 3198 | 3197 | |
| 3199 | − mutex_lock(&process_info->lock); | |
| 3200 | − | |
| 3201 | 3198 | svm_range_list_lock_and_flush_work(svms, mm); |
| 3202 | 3199 | |
| 3203 | 3200 | r = svm_range_is_valid(p, start, size); |
| @@ -3273,8 +3270,6 @@ out_unlock_range: · 69 unmodified lines | ||
| 3273 | 3270 | mutex_unlock(&svms->lock); |
| 3274 | 3271 | mmap_read_unlock(mm); |
| 3275 | 3272 | out: |
| 3276 | − mutex_unlock(&process_info->lock); | |
| 3277 | − | |
| 3278 | 3273 | pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] done, r=%d\n", p->pasid, |
| 3279 | 3274 | &p->svms, start, start + size - 1, r); |
| 3280 | 3275 | |
| @@ -314,6 +314,14 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) · 313 unmodified lines | ||
| 314 | 314 | ret = -EINVAL; |
| 315 | 315 | goto cleanup; |
| 316 | 316 | } |
| 317 | + | |
| 318 | + if ((aconn->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) && | |
| 319 | + (aconn->base.connector_type != DRM_MODE_CONNECTOR_eDP)) { | |
| 320 | + DRM_DEBUG_DRIVER("No DP connector available for CRC source\n"); | |
| 321 | + ret = -EINVAL; | |
| 322 | + goto cleanup; | |
| 323 | + } | |
| 324 | + | |
| 317 | 325 | } |
| 318 | 326 | |
| 319 | 327 | #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) |
| @@ -36,6 +36,8 @@ · 35 unmodified lines | ||
| 36 | 36 | #include "dm_helpers.h" |
| 37 | 37 | |
| 38 | 38 | #include "dc_link_ddc.h" |
| 39 | +#include "ddc_service_types.h" | |
| 40 | +#include "dpcd_defs.h" | |
| 39 | 41 | |
| 40 | 42 | #include "i2caux_interface.h" |
| 41 | 43 | #include "dmub_cmd.h" |
| @@ -157,6 +159,16 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { · 115 unmodified lines | ||
| 157 | 159 | }; |
| 158 | 160 | |
| 159 | 161 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 162 | +static bool needs_dsc_aux_workaround(struct dc_link *link) | |
| 163 | +{ | |
| 164 | + if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && | |
| 165 | + (link->dpcd_caps.dpcd_rev.raw == DPCD_REV_14 || link->dpcd_caps.dpcd_rev.raw == DPCD_REV_12) && | |
| 166 | + link->dpcd_caps.sink_count.bits.SINK_COUNT >= 2) | |
| 167 | + return true; | |
| 168 | + | |
| 169 | + return false; | |
| 170 | +} | |
| 171 | + | |
| 160 | 172 | static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector) |
| 161 | 173 | { |
| 162 | 174 | struct dc_sink *dc_sink = aconnector->dc_sink; |
| @@ -166,7 +178,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto · 3 unmodified lines | ||
| 166 | 178 | u8 *dsc_branch_dec_caps = NULL; |
| 167 | 179 | |
| 168 | 180 | aconnector->dsc_aux = drm_dp_mst_dsc_aux_for_port(port); |
| 169 | −#if defined(CONFIG_HP_HOOK_WORKAROUND) | |
| 181 | + | |
| 170 | 182 | /* |
| 171 | 183 | * drm_dp_mst_dsc_aux_for_port() will return NULL for certain configs |
| 172 | 184 | * because it only check the dsc/fec caps of the "port variable" and not the dock |
| @@ -176,10 +188,10 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto · 3 unmodified lines | ||
| 176 | 188 | * Workaround: explicitly check the use case above and use the mst dock's aux as dsc_aux |
| 177 | 189 | * |
| 178 | 190 | */ |
| 179 | − | |
| 180 | − if (!aconnector->dsc_aux && !port->parent->port_parent) | |
| 191 | + if (!aconnector->dsc_aux && !port->parent->port_parent && | |
| 192 | + needs_dsc_aux_workaround(aconnector->dc_link)) | |
| 181 | 193 | aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; |
| 182 | −#endif | |
| 194 | + | |
| 183 | 195 | if (!aconnector->dsc_aux) |
| 184 | 196 | return false; |
| 185 | 197 | |
| @@ -758,6 +758,18 @@ static bool detect_dp(struct dc_link *link, · 757 unmodified lines | ||
| 758 | 758 | dal_ddc_service_set_transaction_type(link->ddc, |
| 759 | 759 | sink_caps->transaction_type); |
| 760 | 760 | |
| 761 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 762 | + /* Apply work around for tunneled MST on certain USB4 docks. Always use DSC if dock | |
| 763 | + * reports DSC support. | |
| 764 | + */ | |
| 765 | + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && | |
| 766 | + link->type == dc_connection_mst_branch && | |
| 767 | + link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && | |
| 768 | + link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && | |
| 769 | + !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around) | |
| 770 | + link->wa_flags.dpia_mst_dsc_always_on = true; | |
| 771 | +#endif | |
| 772 | + | |
| 761 | 773 | #if defined(CONFIG_DRM_AMD_DC_HDCP) |
| 762 | 774 | /* In case of fallback to SST when topology discovery below fails |
| 763 | 775 | * HDCP caps will be querried again later by the upper layer (caller |
| @@ -1203,6 +1215,10 @@ static bool dc_link_detect_helper(struct dc_link *link, · 439 unmodified lines | ||
| 1203 | 1215 | LINK_INFO("link=%d, mst branch is now Disconnected\n", |
| 1204 | 1216 | link->link_index); |
| 1205 | 1217 | |
| 1218 | + /* Disable work around which keeps DSC on for tunneled MST on certain USB4 docks. */ | |
| 1219 | + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) | |
| 1220 | + link->wa_flags.dpia_mst_dsc_always_on = false; | |
| 1221 | + | |
| 1206 | 1222 | dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); |
| 1207 | 1223 | |
| 1208 | 1224 | link->mst_stream_alloc_table.stream_count = 0; |
| @@ -2138,7 +2138,7 @@ static enum link_training_result dp_perform_8b_10b_link_training( · 2137 unmodified lines | ||
| 2138 | 2138 | } |
| 2139 | 2139 | |
| 2140 | 2140 | for (lane = 0; lane < (uint8_t)lt_settings->link_settings.lane_count; lane++) |
| 2141 | − lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET = VOLTAGE_SWING_LEVEL0; | |
| 2141 | + lt_settings->dpcd_lane_settings[lane].raw = 0; | |
| 2142 | 2142 | } |
| 2143 | 2143 | |
| 2144 | 2144 | if (status == LINK_TRAINING_SUCCESS) { |
| @@ -1664,6 +1664,10 @@ bool dc_is_stream_unchanged( · 1663 unmodified lines | ||
| 1664 | 1664 | if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) |
| 1665 | 1665 | return false; |
| 1666 | 1666 | |
| 1667 | + // Only Have Audio left to check whether it is same or not. This is a corner case for Tiled sinks | |
| 1668 | + if (old_stream->audio_info.mode_count != stream->audio_info.mode_count) | |
| 1669 | + return false; | |
| 1670 | + | |
| 1667 | 1671 | return true; |
| 1668 | 1672 | } |
| 1669 | 1673 | |
| @@ -2252,16 +2256,6 @@ enum dc_status dc_validate_global_state( · 582 unmodified lines | ||
| 2252 | 2256 | |
| 2253 | 2257 | if (!new_ctx) |
| 2254 | 2258 | return DC_ERROR_UNEXPECTED; |
| 2255 | −#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 2256 | − | |
| 2257 | − /* | |
| 2258 | − * Update link encoder to stream assignment. | |
| 2259 | − * TODO: Split out reason allocation from validation. | |
| 2260 | − */ | |
| 2261 | − if (dc->res_pool->funcs->link_encs_assign && fast_validate == false) | |
| 2262 | − dc->res_pool->funcs->link_encs_assign( | |
| 2263 | − dc, new_ctx, new_ctx->streams, new_ctx->stream_count); | |
| 2264 | −#endif | |
| 2265 | 2259 | |
| 2266 | 2260 | if (dc->res_pool->funcs->validate_global) { |
| 2267 | 2261 | result = dc->res_pool->funcs->validate_global(dc, new_ctx); |
| @@ -2313,6 +2307,16 @@ enum dc_status dc_validate_global_state( · 45 unmodified lines | ||
| 2313 | 2307 | if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) |
| 2314 | 2308 | result = DC_FAIL_BANDWIDTH_VALIDATE; |
| 2315 | 2309 | |
| 2310 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 2311 | + /* | |
| 2312 | + * Only update link encoder to stream assignment after bandwidth validation passed. | |
| 2313 | + * TODO: Split out assignment and validation. | |
| 2314 | + */ | |
| 2315 | + if (result == DC_OK && dc->res_pool->funcs->link_encs_assign && fast_validate == false) | |
| 2316 | + dc->res_pool->funcs->link_encs_assign( | |
| 2317 | + dc, new_ctx, new_ctx->streams, new_ctx->stream_count); | |
| 2318 | +#endif | |
| 2319 | + | |
| 2316 | 2320 | return result; |
| 2317 | 2321 | } |
| 2318 | 2322 | |
| @@ -508,7 +508,8 @@ union dpia_debug_options { · 507 unmodified lines | ||
| 508 | 508 | uint32_t disable_dpia:1; |
| 509 | 509 | uint32_t force_non_lttpr:1; |
| 510 | 510 | uint32_t extend_aux_rd_interval:1; |
| 511 | − uint32_t reserved:29; | |
| 511 | + uint32_t disable_mst_dsc_work_around:1; | |
| 512 | + uint32_t reserved:28; | |
| 512 | 513 | } bits; |
| 513 | 514 | uint32_t raw; |
| 514 | 515 | }; |
| @@ -191,6 +191,8 @@ struct dc_link { · 190 unmodified lines | ||
| 191 | 191 | bool dp_skip_DID2; |
| 192 | 192 | bool dp_skip_reset_segment; |
| 193 | 193 | bool dp_mot_reset_segment; |
| 194 | + /* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */ | |
| 195 | + bool dpia_mst_dsc_always_on; | |
| 194 | 196 | } wa_flags; |
| 195 | 197 | struct link_mst_stream_allocation_table mst_stream_alloc_table; |
| 196 | 198 | |
| @@ -1468,7 +1468,7 @@ static int smu_disable_dpms(struct smu_context *smu) · 1467 unmodified lines | ||
| 1468 | 1468 | dev_err(adev->dev, "Failed to disable smu features.\n"); |
| 1469 | 1469 | } |
| 1470 | 1470 | |
| 1471 | − if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0) && | |
| 1471 | + if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) && | |
| 1472 | 1472 | adev->gfx.rlc.funcs->stop) |
| 1473 | 1473 | adev->gfx.rlc.funcs->stop(adev); |
| 1474 | 1474 | |
| @@ -1640,6 +1640,9 @@ struct intel_dp { · 1639 unmodified lines | ||
| 1640 | 1640 | struct intel_dp_pcon_frl frl; |
| 1641 | 1641 | |
| 1642 | 1642 | struct intel_psr psr; |
| 1643 | + | |
| 1644 | + /* When we last wrote the OUI for eDP */ | |
| 1645 | + unsigned long last_oui_write; | |
| 1643 | 1646 | }; |
| 1644 | 1647 | |
| 1645 | 1648 | enum lspcon_vendor { |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/i2c.h> |
| 30 | 30 | #include <linux/notifier.h> |
| 31 | 31 | #include <linux/slab.h> |
| 32 | +#include <linux/timekeeping.h> | |
| 32 | 33 | #include <linux/types.h> |
| 33 | 34 | |
| 34 | 35 | #include <asm/byteorder.h> |
| @@ -1955,6 +1956,16 @@ intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful) · 1920 unmodified lines | ||
| 1955 | 1956 | |
| 1956 | 1957 | if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) |
| 1957 | 1958 | drm_err(&i915->drm, "Failed to write source OUI\n"); |
| 1959 | + | |
| 1960 | + intel_dp->last_oui_write = jiffies; | |
| 1961 | +} | |
| 1962 | + | |
| 1963 | +void intel_dp_wait_source_oui(struct intel_dp *intel_dp) | |
| 1964 | +{ | |
| 1965 | + struct drm_i915_private *i915 = dp_to_i915(intel_dp); | |
| 1966 | + | |
| 1967 | + drm_dbg_kms(&i915->drm, "Performing OUI wait\n"); | |
| 1968 | + wait_remaining_ms_from_jiffies(intel_dp->last_oui_write, 30); | |
| 1958 | 1969 | } |
| 1959 | 1970 | |
| 1960 | 1971 | /* If the device supports it, try to set the power state appropriately */ |
| @@ -119,4 +119,6 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp, · 118 unmodified lines | ||
| 119 | 119 | const struct intel_crtc_state *crtc_state); |
| 120 | 120 | void intel_dp_phy_test(struct intel_encoder *encoder); |
| 121 | 121 | |
| 122 | +void intel_dp_wait_source_oui(struct intel_dp *intel_dp); | |
| 123 | + | |
| 122 | 124 | #endif /* __INTEL_DP_H__ */ |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | #include "intel_backlight.h" |
| 38 | 38 | #include "intel_display_types.h" |
| 39 | +#include "intel_dp.h" | |
| 39 | 40 | #include "intel_dp_aux_backlight.h" |
| 40 | 41 | |
| 41 | 42 | /* TODO: |
| @@ -106,6 +107,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) · 64 unmodified lines | ||
| 106 | 107 | int ret; |
| 107 | 108 | u8 tcon_cap[4]; |
| 108 | 109 | |
| 110 | + intel_dp_wait_source_oui(intel_dp); | |
| 111 | + | |
| 109 | 112 | ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); |
| 110 | 113 | if (ret != sizeof(tcon_cap)) |
| 111 | 114 | return false; |
| @@ -204,6 +207,8 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, · 92 unmodified lines | ||
| 204 | 207 | int ret; |
| 205 | 208 | u8 old_ctrl, ctrl; |
| 206 | 209 | |
| 210 | + intel_dp_wait_source_oui(intel_dp); | |
| 211 | + | |
| 207 | 212 | ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); |
| 208 | 213 | if (ret != 1) { |
| 209 | 214 | drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret); |
| @@ -293,6 +298,13 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state, · 83 unmodified lines | ||
| 293 | 298 | struct intel_panel *panel = &connector->panel; |
| 294 | 299 | struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
| 295 | 300 | |
| 301 | + if (!panel->backlight.edp.vesa.info.aux_enable) { | |
| 302 | + u32 pwm_level = intel_backlight_invert_pwm_level(connector, | |
| 303 | + panel->backlight.pwm_level_max); | |
| 304 | + | |
| 305 | + panel->backlight.pwm_funcs->enable(crtc_state, conn_state, pwm_level); | |
| 306 | + } | |
| 307 | + | |
| 296 | 308 | drm_edp_backlight_enable(&intel_dp->aux, &panel->backlight.edp.vesa.info, level); |
| 297 | 309 | } |
| 298 | 310 | |
| @@ -304,6 +316,10 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state · 5 unmodified lines | ||
| 304 | 316 | struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
| 305 | 317 | |
| 306 | 318 | drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info); |
| 319 | + | |
| 320 | + if (!panel->backlight.edp.vesa.info.aux_enable) | |
| 321 | + panel->backlight.pwm_funcs->disable(old_conn_state, | |
| 322 | + intel_backlight_invert_pwm_level(connector, 0)); | |
| 307 | 323 | } |
| 308 | 324 | |
| 309 | 325 | static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe) |
| @@ -321,6 +337,15 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, · 11 unmodified lines | ||
| 321 | 337 | if (ret < 0) |
| 322 | 338 | return ret; |
| 323 | 339 | |
| 340 | + if (!panel->backlight.edp.vesa.info.aux_enable) { | |
| 341 | + ret = panel->backlight.pwm_funcs->setup(connector, pipe); | |
| 342 | + if (ret < 0) { | |
| 343 | + drm_err(&i915->drm, | |
| 344 | + "Failed to setup PWM backlight controls for eDP backlight: %d\n", | |
| 345 | + ret); | |
| 346 | + return ret; | |
| 347 | + } | |
| 348 | + } | |
| 324 | 349 | panel->backlight.max = panel->backlight.edp.vesa.info.max; |
| 325 | 350 | panel->backlight.min = 0; |
| 326 | 351 | if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { |
| @@ -340,12 +365,7 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector) · 13 unmodified lines | ||
| 340 | 365 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
| 341 | 366 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
| 342 | 367 | |
| 343 | − /* TODO: We currently only support AUX only backlight configurations, not backlights which | |
| 344 | − * require a mix of PWM and AUX controls to work. In the mean time, these machines typically | |
| 345 | − * work just fine using normal PWM controls anyway. | |
| 346 | − */ | |
| 347 | − if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && | |
| 348 | − drm_edp_backlight_supported(intel_dp->edp_dpcd)) { | |
| 368 | + if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) { | |
| 349 | 369 | drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n"); |
| 350 | 370 | return true; |
| 351 | 371 | } |
| @@ -621,13 +621,6 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, · 620 unmodified lines | ||
| 621 | 621 | FF_MODE2_GS_TIMER_MASK, |
| 622 | 622 | FF_MODE2_GS_TIMER_224, |
| 623 | 623 | 0, false); |
| 624 | − | |
| 625 | − /* | |
| 626 | − * Wa_14012131227:dg1 | |
| 627 | − * Wa_1508744258:tgl,rkl,dg1,adl-s,adl-p | |
| 628 | − */ | |
| 629 | − wa_masked_en(wal, GEN7_COMMON_SLICE_CHICKEN1, | |
| 630 | − GEN9_RHWO_OPTIMIZATION_DISABLE); | |
| 631 | 624 | } |
| 632 | 625 | |
| 633 | 626 | static void dg1_ctx_workarounds_init(struct intel_engine_cs *engine, |
| @@ -4,8 +4,8 @@ config DRM_MSM · 3 unmodified lines | ||
| 4 | 4 | tristate "MSM DRM" |
| 5 | 5 | depends on DRM |
| 6 | 6 | depends on ARCH_QCOM || SOC_IMX5 || COMPILE_TEST |
| 7 | + depends on COMMON_CLK | |
| 7 | 8 | depends on IOMMU_SUPPORT |
| 8 | − depends on (OF && COMMON_CLK) || COMPILE_TEST | |
| 9 | 9 | depends on QCOM_OCMEM || QCOM_OCMEM=n |
| 10 | 10 | depends on QCOM_LLCC || QCOM_LLCC=n |
| 11 | 11 | depends on QCOM_COMMAND_DB || QCOM_COMMAND_DB=n |
| @@ -23,8 +23,10 @@ msm-y := \ · 22 unmodified lines | ||
| 23 | 23 | hdmi/hdmi_i2c.o \ |
| 24 | 24 | hdmi/hdmi_phy.o \ |
| 25 | 25 | hdmi/hdmi_phy_8960.o \ |
| 26 | + hdmi/hdmi_phy_8996.o \ | |
| 26 | 27 | hdmi/hdmi_phy_8x60.o \ |
| 27 | 28 | hdmi/hdmi_phy_8x74.o \ |
| 29 | + hdmi/hdmi_pll_8960.o \ | |
| 28 | 30 | edp/edp.o \ |
| 29 | 31 | edp/edp_aux.o \ |
| 30 | 32 | edp/edp_bridge.o \ |
| @@ -37,6 +39,7 @@ msm-y := \ · 6 unmodified lines | ||
| 37 | 39 | disp/mdp4/mdp4_dtv_encoder.o \ |
| 38 | 40 | disp/mdp4/mdp4_lcdc_encoder.o \ |
| 39 | 41 | disp/mdp4/mdp4_lvds_connector.o \ |
| 42 | + disp/mdp4/mdp4_lvds_pll.o \ | |
| 40 | 43 | disp/mdp4/mdp4_irq.o \ |
| 41 | 44 | disp/mdp4/mdp4_kms.o \ |
| 42 | 45 | disp/mdp4/mdp4_plane.o \ |
| @@ -116,9 +119,6 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ · 73 unmodified lines | ||
| 116 | 119 | dp/dp_audio.o |
| 117 | 120 | |
| 118 | 121 | msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o |
| 119 | −msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o | |
| 120 | −msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o | |
| 121 | −msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_phy_8996.o | |
| 122 | 122 | |
| 123 | 123 | msm-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o |
| 124 | 124 | |
| @@ -1424,17 +1424,24 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) · 1423 unmodified lines | ||
| 1424 | 1424 | { |
| 1425 | 1425 | struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; |
| 1426 | 1426 | struct msm_gpu *gpu = &adreno_gpu->base; |
| 1427 | − u32 gpu_scid, cntl1_regval = 0; | |
| 1427 | + u32 cntl1_regval = 0; | |
| 1428 | 1428 | |
| 1429 | 1429 | if (IS_ERR(a6xx_gpu->llc_mmio)) |
| 1430 | 1430 | return; |
| 1431 | 1431 | |
| 1432 | 1432 | if (!llcc_slice_activate(a6xx_gpu->llc_slice)) { |
| 1433 | − gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); | |
| 1433 | + u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); | |
| 1434 | 1434 | |
| 1435 | 1435 | gpu_scid &= 0x1f; |
| 1436 | 1436 | cntl1_regval = (gpu_scid << 0) | (gpu_scid << 5) | (gpu_scid << 10) | |
| 1437 | 1437 | (gpu_scid << 15) | (gpu_scid << 20); |
| 1438 | + | |
| 1439 | + /* On A660, the SCID programming for UCHE traffic is done in | |
| 1440 | + * A6XX_GBIF_SCACHE_CNTL0[14:10] | |
| 1441 | + */ | |
| 1442 | + if (adreno_is_a660_family(adreno_gpu)) | |
| 1443 | + gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | | |
| 1444 | + (1 << 8), (gpu_scid << 10) | (1 << 8)); | |
| 1438 | 1445 | } |
| 1439 | 1446 | |
| 1440 | 1447 | /* |
| @@ -1471,13 +1478,6 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) · 30 unmodified lines | ||
| 1471 | 1478 | } |
| 1472 | 1479 | |
| 1473 | 1480 | gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0), cntl1_regval); |
| 1474 | − | |
| 1475 | − /* On A660, the SCID programming for UCHE traffic is done in | |
| 1476 | − * A6XX_GBIF_SCACHE_CNTL0[14:10] | |
| 1477 | − */ | |
| 1478 | − if (adreno_is_a660_family(adreno_gpu)) | |
| 1479 | − gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | | |
| 1480 | − (1 << 8), (gpu_scid << 10) | (1 << 8)); | |
| 1481 | 1481 | } |
| 1482 | 1482 | |
| 1483 | 1483 | static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu) |
| @@ -1640,7 +1640,7 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) · 156 unmodified lines | ||
| 1640 | 1640 | return (unsigned long)busy_time; |
| 1641 | 1641 | } |
| 1642 | 1642 | |
| 1643 | −void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) | |
| 1643 | +static void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) | |
| 1644 | 1644 | { |
| 1645 | 1645 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
| 1646 | 1646 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); |
| @@ -777,12 +777,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, · 776 unmodified lines | ||
| 777 | 777 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); |
| 778 | 778 | |
| 779 | 779 | a6xx_state->gmu_registers = state_kcalloc(a6xx_state, |
| 780 | − 2, sizeof(*a6xx_state->gmu_registers)); | |
| 780 | + 3, sizeof(*a6xx_state->gmu_registers)); | |
| 781 | 781 | |
| 782 | 782 | if (!a6xx_state->gmu_registers) |
| 783 | 783 | return; |
| 784 | 784 | |
| 785 | − a6xx_state->nr_gmu_registers = 2; | |
| 785 | + a6xx_state->nr_gmu_registers = 3; | |
| 786 | 786 | |
| 787 | 787 | /* Get the CX GMU registers from AHB */ |
| 788 | 788 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0], |
| @@ -33,6 +33,7 @@ struct dp_aux_private { · 32 unmodified lines | ||
| 33 | 33 | bool read; |
| 34 | 34 | bool no_send_addr; |
| 35 | 35 | bool no_send_stop; |
| 36 | + bool initted; | |
| 36 | 37 | u32 offset; |
| 37 | 38 | u32 segment; |
| 38 | 39 | |
| @@ -331,6 +332,10 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, · 292 unmodified lines | ||
| 331 | 332 | } |
| 332 | 333 | |
| 333 | 334 | mutex_lock(&aux->mutex); |
| 335 | + if (!aux->initted) { | |
| 336 | + ret = -EIO; | |
| 337 | + goto exit; | |
| 338 | + } | |
| 334 | 339 | |
| 335 | 340 | dp_aux_update_offset_and_segment(aux, msg); |
| 336 | 341 | dp_aux_transfer_helper(aux, msg, true); |
| @@ -380,6 +385,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, · 43 unmodified lines | ||
| 380 | 385 | } |
| 381 | 386 | |
| 382 | 387 | aux->cmd_busy = false; |
| 388 | + | |
| 389 | +exit: | |
| 383 | 390 | mutex_unlock(&aux->mutex); |
| 384 | 391 | |
| 385 | 392 | return ret; |
| @@ -431,8 +438,13 @@ void dp_aux_init(struct drm_dp_aux *dp_aux) · 45 unmodified lines | ||
| 431 | 438 | |
| 432 | 439 | aux = container_of(dp_aux, struct dp_aux_private, dp_aux); |
| 433 | 440 | |
| 441 | + mutex_lock(&aux->mutex); | |
| 442 | + | |
| 434 | 443 | dp_catalog_aux_enable(aux->catalog, true); |
| 435 | 444 | aux->retry_cnt = 0; |
| 445 | + aux->initted = true; | |
| 446 | + | |
| 447 | + mutex_unlock(&aux->mutex); | |
| 436 | 448 | } |
| 437 | 449 | |
| 438 | 450 | void dp_aux_deinit(struct drm_dp_aux *dp_aux) |
| @@ -441,7 +453,12 @@ void dp_aux_deinit(struct drm_dp_aux *dp_aux) · 2 unmodified lines | ||
| 441 | 453 | |
| 442 | 454 | aux = container_of(dp_aux, struct dp_aux_private, dp_aux); |
| 443 | 455 | |
| 456 | + mutex_lock(&aux->mutex); | |
| 457 | + | |
| 458 | + aux->initted = false; | |
| 444 | 459 | dp_catalog_aux_enable(aux->catalog, false); |
| 460 | + | |
| 461 | + mutex_unlock(&aux->mutex); | |
| 445 | 462 | } |
| 446 | 463 | |
| 447 | 464 | int dp_aux_register(struct drm_dp_aux *dp_aux) |
| @@ -1658,6 +1658,8 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host, · 1657 unmodified lines | ||
| 1658 | 1658 | if (!prop) { |
| 1659 | 1659 | DRM_DEV_DEBUG(dev, |
| 1660 | 1660 | "failed to find data lane mapping, using default\n"); |
| 1661 | + /* Set the number of date lanes to 4 by default. */ | |
| 1662 | + msm_host->num_data_lanes = 4; | |
| 1661 | 1663 | return 0; |
| 1662 | 1664 | } |
| 1663 | 1665 | |
| @@ -77,6 +77,7 @@ static int msm_gpu_open(struct inode *inode, struct file *file) · 76 unmodified lines | ||
| 77 | 77 | goto free_priv; |
| 78 | 78 | |
| 79 | 79 | pm_runtime_get_sync(&gpu->pdev->dev); |
| 80 | + msm_gpu_hw_init(gpu); | |
| 80 | 81 | show_priv->state = gpu->funcs->gpu_state_get(gpu); |
| 81 | 82 | pm_runtime_put_sync(&gpu->pdev->dev); |
| 82 | 83 | |
| @@ -967,29 +967,18 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, · 966 unmodified lines | ||
| 967 | 967 | return ret; |
| 968 | 968 | } |
| 969 | 969 | |
| 970 | −static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, | |
| 971 | − struct drm_file *file) | |
| 970 | +static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, | |
| 971 | + ktime_t timeout) | |
| 972 | 972 | { |
| 973 | − struct msm_drm_private *priv = dev->dev_private; | |
| 974 | − struct drm_msm_wait_fence *args = data; | |
| 975 | − ktime_t timeout = to_ktime(args->timeout); | |
| 976 | − struct msm_gpu_submitqueue *queue; | |
| 977 | − struct msm_gpu *gpu = priv->gpu; | |
| 978 | 973 | struct dma_fence *fence; |
| 979 | 974 | int ret; |
| 980 | 975 | |
| 981 | − if (args->pad) { | |
| 982 | − DRM_ERROR("invalid pad: %08x\n", args->pad); | |
| 976 | + if (fence_id > queue->last_fence) { | |
| 977 | + DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of %u)\n", | |
| 978 | + fence_id, queue->last_fence); | |
| 983 | 979 | return -EINVAL; |
| 984 | 980 | } |
| 985 | 981 | |
| 986 | − if (!gpu) | |
| 987 | − return 0; | |
| 988 | − | |
| 989 | − queue = msm_submitqueue_get(file->driver_priv, args->queueid); | |
| 990 | − if (!queue) | |
| 991 | − return -ENOENT; | |
| 992 | − | |
| 993 | 982 | /* |
| 994 | 983 | * Map submitqueue scoped "seqno" (which is actually an idr key) |
| 995 | 984 | * back to underlying dma-fence |
| @@ -1001,7 +990,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, · 5 unmodified lines | ||
| 1001 | 990 | ret = mutex_lock_interruptible(&queue->lock); |
| 1002 | 991 | if (ret) |
| 1003 | 992 | return ret; |
| 1004 | − fence = idr_find(&queue->fence_idr, args->fence); | |
| 993 | + fence = idr_find(&queue->fence_idr, fence_id); | |
| 1005 | 994 | if (fence) |
| 1006 | 995 | fence = dma_fence_get_rcu(fence); |
| 1007 | 996 | mutex_unlock(&queue->lock); |
| @@ -1017,6 +1006,32 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, · 9 unmodified lines | ||
| 1017 | 1006 | } |
| 1018 | 1007 | |
| 1019 | 1008 | dma_fence_put(fence); |
| 1009 | + | |
| 1010 | + return ret; | |
| 1011 | +} | |
| 1012 | + | |
| 1013 | +static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, | |
| 1014 | + struct drm_file *file) | |
| 1015 | +{ | |
| 1016 | + struct msm_drm_private *priv = dev->dev_private; | |
| 1017 | + struct drm_msm_wait_fence *args = data; | |
| 1018 | + struct msm_gpu_submitqueue *queue; | |
| 1019 | + int ret; | |
| 1020 | + | |
| 1021 | + if (args->pad) { | |
| 1022 | + DRM_ERROR("invalid pad: %08x\n", args->pad); | |
| 1023 | + return -EINVAL; | |
| 1024 | + } | |
| 1025 | + | |
| 1026 | + if (!priv->gpu) | |
| 1027 | + return 0; | |
| 1028 | + | |
| 1029 | + queue = msm_submitqueue_get(file->driver_priv, args->queueid); | |
| 1030 | + if (!queue) | |
| 1031 | + return -ENOENT; | |
| 1032 | + | |
| 1033 | + ret = wait_fence(queue, args->fence, to_ktime(args->timeout)); | |
| 1034 | + | |
| 1020 | 1035 | msm_submitqueue_put(queue); |
| 1021 | 1036 | |
| 1022 | 1037 | return ret; |
| @@ -1056,8 +1056,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct · 1055 unmodified lines | ||
| 1056 | 1056 | { |
| 1057 | 1057 | struct msm_gem_object *msm_obj = to_msm_bo(obj); |
| 1058 | 1058 | |
| 1059 | − vma->vm_flags &= ~VM_PFNMAP; | |
| 1060 | − vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND; | |
| 1059 | + vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP; | |
| 1061 | 1060 | vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags)); |
| 1062 | 1061 | |
| 1063 | 1062 | return 0; |
| @@ -1121,7 +1120,7 @@ static int msm_gem_new_impl(struct drm_device *dev, · 57 unmodified lines | ||
| 1121 | 1120 | break; |
| 1122 | 1121 | fallthrough; |
| 1123 | 1122 | default: |
| 1124 | − DRM_DEV_ERROR(dev->dev, "invalid cache flag: %x\n", | |
| 1123 | + DRM_DEV_DEBUG(dev->dev, "invalid cache flag: %x\n", | |
| 1125 | 1124 | (flags & MSM_BO_CACHE_MASK)); |
| 1126 | 1125 | return -EINVAL; |
| 1127 | 1126 | } |
| @@ -772,6 +772,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 771 unmodified lines | ||
| 772 | 772 | args->nr_cmds); |
| 773 | 773 | if (IS_ERR(submit)) { |
| 774 | 774 | ret = PTR_ERR(submit); |
| 775 | + submit = NULL; | |
| 775 | 776 | goto out_unlock; |
| 776 | 777 | } |
| 777 | 778 | |
| @@ -904,6 +905,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 126 unmodified lines | ||
| 904 | 905 | drm_sched_entity_push_job(&submit->base); |
| 905 | 906 | |
| 906 | 907 | args->fence = submit->fence_id; |
| 908 | + queue->last_fence = submit->fence_id; | |
| 907 | 909 | |
| 908 | 910 | msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs); |
| 909 | 911 | msm_process_post_deps(post_deps, args->nr_out_syncobjs, |
| @@ -359,6 +359,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, · 358 unmodified lines | ||
| 359 | 359 | * @ring_nr: the ringbuffer used by this submitqueue, which is determined |
| 360 | 360 | * by the submitqueue's priority |
| 361 | 361 | * @faults: the number of GPU hangs associated with this submitqueue |
| 362 | + * @last_fence: the sequence number of the last allocated fence (for error | |
| 363 | + * checking) | |
| 362 | 364 | * @ctx: the per-drm_file context associated with the submitqueue (ie. |
| 363 | 365 | * which set of pgtables do submits jobs associated with the |
| 364 | 366 | * submitqueue use) |
| @@ -374,6 +376,7 @@ struct msm_gpu_submitqueue { · 9 unmodified lines | ||
| 374 | 376 | u32 flags; |
| 375 | 377 | u32 ring_nr; |
| 376 | 378 | int faults; |
| 379 | + uint32_t last_fence; | |
| 377 | 380 | struct msm_file_private *ctx; |
| 378 | 381 | struct list_head node; |
| 379 | 382 | struct idr fence_idr; |
| @@ -20,6 +20,10 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, · 19 unmodified lines | ||
| 20 | 20 | struct msm_gpu *gpu = dev_to_gpu(dev); |
| 21 | 21 | struct dev_pm_opp *opp; |
| 22 | 22 | |
| 23 | + /* | |
| 24 | + * Note that devfreq_recommended_opp() can modify the freq | |
| 25 | + * to something that actually is in the opp table: | |
| 26 | + */ | |
| 23 | 27 | opp = devfreq_recommended_opp(dev, freq, flags); |
| 24 | 28 | |
| 25 | 29 | /* |
| @@ -28,6 +32,7 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, · 2 unmodified lines | ||
| 28 | 32 | */ |
| 29 | 33 | if (gpu->devfreq.idle_freq) { |
| 30 | 34 | gpu->devfreq.idle_freq = *freq; |
| 35 | + dev_pm_opp_put(opp); | |
| 31 | 36 | return 0; |
| 32 | 37 | } |
| 33 | 38 | |
| @@ -203,9 +208,6 @@ static void msm_devfreq_idle_work(struct kthread_work *work) · 169 unmodified lines | ||
| 203 | 208 | struct msm_gpu *gpu = container_of(df, struct msm_gpu, devfreq); |
| 204 | 209 | unsigned long idle_freq, target_freq = 0; |
| 205 | 210 | |
| 206 | − if (!df->devfreq) | |
| 207 | − return; | |
| 208 | − | |
| 209 | 211 | /* |
| 210 | 212 | * Hold devfreq lock to synchronize with get_dev_status()/ |
| 211 | 213 | * target() callbacks |
| @@ -227,6 +229,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu) · 15 unmodified lines | ||
| 227 | 229 | { |
| 228 | 230 | struct msm_gpu_devfreq *df = &gpu->devfreq; |
| 229 | 231 | |
| 232 | + if (!df->devfreq) | |
| 233 | + return; | |
| 234 | + | |
| 230 | 235 | msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1), |
| 231 | − HRTIMER_MODE_ABS); | |
| 236 | + HRTIMER_MODE_REL); | |
| 232 | 237 | } |
| @@ -337,10 +337,10 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) · 336 unmodified lines | ||
| 337 | 337 | struct drm_device *dev = state->dev; |
| 338 | 338 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
| 339 | 339 | struct vc4_hvs *hvs = vc4->hvs; |
| 340 | − struct drm_crtc_state *old_crtc_state; | |
| 341 | 340 | struct drm_crtc_state *new_crtc_state; |
| 342 | 341 | struct drm_crtc *crtc; |
| 343 | 342 | struct vc4_hvs_state *old_hvs_state; |
| 343 | + unsigned int channel; | |
| 344 | 344 | int i; |
| 345 | 345 | |
| 346 | 346 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
| @@ -353,30 +353,32 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) · 6 unmodified lines | ||
| 353 | 353 | vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); |
| 354 | 354 | } |
| 355 | 355 | |
| 356 | − if (vc4->hvs->hvs5) | |
| 357 | − clk_set_min_rate(hvs->core_clk, 500000000); | |
| 358 | − | |
| 359 | 356 | old_hvs_state = vc4_hvs_get_old_global_state(state); |
| 360 | − if (!old_hvs_state) | |
| 357 | + if (IS_ERR(old_hvs_state)) | |
| 361 | 358 | return; |
| 362 | 359 | |
| 363 | − for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { | |
| 364 | − struct vc4_crtc_state *vc4_crtc_state = | |
| 365 | − to_vc4_crtc_state(old_crtc_state); | |
| 366 | − unsigned int channel = vc4_crtc_state->assigned_channel; | |
| 360 | + for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) { | |
| 361 | + struct drm_crtc_commit *commit; | |
| 367 | 362 | int ret; |
| 368 | 363 | |
| 369 | − if (channel == VC4_HVS_CHANNEL_DISABLED) | |
| 364 | + if (!old_hvs_state->fifo_state[channel].in_use) | |
| 370 | 365 | continue; |
| 371 | 366 | |
| 372 | − if (!old_hvs_state->fifo_state[channel].in_use) | |
| 367 | + commit = old_hvs_state->fifo_state[channel].pending_commit; | |
| 368 | + if (!commit) | |
| 373 | 369 | continue; |
| 374 | 370 | |
| 375 | − ret = drm_crtc_commit_wait(old_hvs_state->fifo_state[channel].pending_commit); | |
| 371 | + ret = drm_crtc_commit_wait(commit); | |
| 376 | 372 | if (ret) |
| 377 | 373 | drm_err(dev, "Timed out waiting for commit\n"); |
| 374 | + | |
| 375 | + drm_crtc_commit_put(commit); | |
| 376 | + old_hvs_state->fifo_state[channel].pending_commit = NULL; | |
| 378 | 377 | } |
| 379 | 378 | |
| 379 | + if (vc4->hvs->hvs5) | |
| 380 | + clk_set_min_rate(hvs->core_clk, 500000000); | |
| 381 | + | |
| 380 | 382 | drm_atomic_helper_commit_modeset_disables(dev, state); |
| 381 | 383 | |
| 382 | 384 | vc4_ctm_commit(vc4, state); |
| @@ -410,8 +412,8 @@ static int vc4_atomic_commit_setup(struct drm_atomic_state *state) · 27 unmodified lines | ||
| 410 | 412 | unsigned int i; |
| 411 | 413 | |
| 412 | 414 | hvs_state = vc4_hvs_get_new_global_state(state); |
| 413 | − if (!hvs_state) | |
| 414 | − return -EINVAL; | |
| 415 | + if (WARN_ON(IS_ERR(hvs_state))) | |
| 416 | + return PTR_ERR(hvs_state); | |
| 415 | 417 | |
| 416 | 418 | for_each_new_crtc_in_state(state, crtc, crtc_state, i) { |
| 417 | 419 | struct vc4_crtc_state *vc4_crtc_state = |
| @@ -668,12 +670,6 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) · 250 unmodified lines | ||
| 668 | 670 | |
| 669 | 671 | for (i = 0; i < HVS_NUM_CHANNELS; i++) { |
| 670 | 672 | state->fifo_state[i].in_use = old_state->fifo_state[i].in_use; |
| 671 | − | |
| 672 | − if (!old_state->fifo_state[i].pending_commit) | |
| 673 | − continue; | |
| 674 | − | |
| 675 | − state->fifo_state[i].pending_commit = | |
| 676 | − drm_crtc_commit_get(old_state->fifo_state[i].pending_commit); | |
| 677 | 673 | } |
| 678 | 674 | |
| 679 | 675 | return &state->base; |
| @@ -762,8 +758,8 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, · 82 unmodified lines | ||
| 762 | 758 | unsigned int i; |
| 763 | 759 | |
| 764 | 760 | hvs_new_state = vc4_hvs_get_global_state(state); |
| 765 | − if (!hvs_new_state) | |
| 766 | − return -EINVAL; | |
| 761 | + if (IS_ERR(hvs_new_state)) | |
| 762 | + return PTR_ERR(hvs_new_state); | |
| 767 | 763 | |
| 768 | 764 | for (i = 0; i < ARRAY_SIZE(hvs_new_state->fifo_state); i++) |
| 769 | 765 | if (!hvs_new_state->fifo_state[i].in_use) |
| @@ -157,36 +157,6 @@ static void virtio_gpu_config_changed(struct virtio_device *vdev) · 156 unmodified lines | ||
| 157 | 157 | schedule_work(&vgdev->config_changed_work); |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | −static __poll_t virtio_gpu_poll(struct file *filp, | |
| 161 | − struct poll_table_struct *wait) | |
| 162 | −{ | |
| 163 | − struct drm_file *drm_file = filp->private_data; | |
| 164 | − struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv; | |
| 165 | − struct drm_device *dev = drm_file->minor->dev; | |
| 166 | − struct virtio_gpu_device *vgdev = dev->dev_private; | |
| 167 | − struct drm_pending_event *e = NULL; | |
| 168 | − __poll_t mask = 0; | |
| 169 | − | |
| 170 | − if (!vgdev->has_virgl_3d || !vfpriv || !vfpriv->ring_idx_mask) | |
| 171 | − return drm_poll(filp, wait); | |
| 172 | − | |
| 173 | − poll_wait(filp, &drm_file->event_wait, wait); | |
| 174 | − | |
| 175 | − if (!list_empty(&drm_file->event_list)) { | |
| 176 | − spin_lock_irq(&dev->event_lock); | |
| 177 | − e = list_first_entry(&drm_file->event_list, | |
| 178 | − struct drm_pending_event, link); | |
| 179 | − drm_file->event_space += e->event->length; | |
| 180 | − list_del(&e->link); | |
| 181 | − spin_unlock_irq(&dev->event_lock); | |
| 182 | − | |
| 183 | − kfree(e); | |
| 184 | − mask |= EPOLLIN | EPOLLRDNORM; | |
| 185 | − } | |
| 186 | − | |
| 187 | − return mask; | |
| 188 | −} | |
| 189 | − | |
| 190 | 160 | static struct virtio_device_id id_table[] = { |
| 191 | 161 | { VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID }, |
| 192 | 162 | { 0 }, |
| @@ -226,17 +196,7 @@ MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>"); · 33 unmodified lines | ||
| 226 | 196 | MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>"); |
| 227 | 197 | MODULE_AUTHOR("Alon Levy"); |
| 228 | 198 | |
| 229 | −static const struct file_operations virtio_gpu_driver_fops = { | |
| 230 | − .owner = THIS_MODULE, | |
| 231 | − .open = drm_open, | |
| 232 | − .release = drm_release, | |
| 233 | − .unlocked_ioctl = drm_ioctl, | |
| 234 | − .compat_ioctl = drm_compat_ioctl, | |
| 235 | − .poll = virtio_gpu_poll, | |
| 236 | − .read = drm_read, | |
| 237 | − .llseek = noop_llseek, | |
| 238 | − .mmap = drm_gem_mmap | |
| 239 | −}; | |
| 199 | +DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops); | |
| 240 | 200 | |
| 241 | 201 | static const struct drm_driver driver = { |
| 242 | 202 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC, |
| @@ -138,7 +138,6 @@ struct virtio_gpu_fence_driver { · 137 unmodified lines | ||
| 138 | 138 | spinlock_t lock; |
| 139 | 139 | }; |
| 140 | 140 | |
| 141 | −#define VIRTGPU_EVENT_FENCE_SIGNALED_INTERNAL 0x10000000 | |
| 142 | 141 | struct virtio_gpu_fence_event { |
| 143 | 142 | struct drm_pending_event base; |
| 144 | 143 | struct drm_event event; |
| @@ -54,7 +54,7 @@ static int virtio_gpu_fence_event_create(struct drm_device *dev, · 53 unmodified lines | ||
| 54 | 54 | if (!e) |
| 55 | 55 | return -ENOMEM; |
| 56 | 56 | |
| 57 | − e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED_INTERNAL; | |
| 57 | + e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED; | |
| 58 | 58 | e->event.length = sizeof(e->event); |
| 59 | 59 | |
| 60 | 60 | ret = drm_event_reserve_init(dev, file, &e->base, &e->event); |
| @@ -196,6 +196,13 @@ struct drm_virtgpu_context_init { · 195 unmodified lines | ||
| 196 | 196 | __u64 ctx_set_params; |
| 197 | 197 | }; |
| 198 | 198 | |
| 199 | +/* | |
| 200 | + * Event code that's given when VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK is in | |
| 201 | + * effect. The event size is sizeof(drm_event), since there is no additional | |
| 202 | + * payload. | |
| 203 | + */ | |
| 204 | +#define VIRTGPU_EVENT_FENCE_SIGNALED 0x90000000 | |
| 205 | + | |
| 199 | 206 | #define DRM_IOCTL_VIRTGPU_MAP \ |
| 200 | 207 | DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) |
| 201 | 208 | |