Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-fixes-2024-10-11' of https://gitlab.freedesktop.org/drm/kernel

Pull drm fixes from Dave Airlie:
"Weekly fixes haul for drm, lots of small fixes all over, amdgpu, xe
lead the way, some minor nouveau and radeon fixes, and then a bunch of
misc all over.

Nothing too scary or out of the unusual.

sched:
- Avoid leaking lockdep map

fbdev-dma:
- Only clean up deferred I/O if instanciated

amdgpu:
- Fix invalid UBSAN warnings
- Fix artifacts in MPO transitions
- Hibernation fix

amdkfd:
- Fix an eviction fence leak

radeon:
- Add late register for connectors
- Always set GEM function pointers

i915:
- HDCP refcount fix

nouveau:
- dmem: Fix privileged error in copy engine channel; Fix possible
data leak in migrate_to_ram()
- gsp: Fix coding style

v3d:
- Stop active perfmon before destroying it

vc4:
- Stop active perfmon before destroying it

xe:
- Drop GuC submit_wq pool
- Fix error checking with xa_store()
- Fix missing freq restore on GSC load error
- Fix wedged_mode file permission
- Fix use-after-free in ct communication"

* tag 'drm-fixes-2024-10-11' of https://gitlab.freedesktop.org/drm/kernel:
drm/fbdev-dma: Only cleanup deferred I/O if necessary
drm/xe: Make wedged_mode debugfs writable
drm/xe: Restore GT freq on GSC load error
drm/xe/guc_submit: fix xa_store() error checking
drm/xe/ct: fix xa_store() error checking
drm/xe/ct: prevent UAF in send_recv()
drm/radeon: always set GEM function pointer
nouveau/dmem: Fix vulnerability in migrate_to_ram upon copy error
nouveau/dmem: Fix privileged error in copy engine channel
drm/amd/display: fix hibernate entry for DCN35+
drm/amd/display: Clear update flags after update has been applied
drm/amdgpu: partially revert powerplay `__counted_by` changes
drm/radeon: add late_register for connector
drm/amdkfd: Fix an eviction fence leak
drm/vc4: Stop the active perfmon before being destroyed
drm/v3d: Stop the active perfmon before being destroyed
drm/i915/hdcp: fix connector refcounting
drm/nouveau/gsp: remove extraneous ; after mutex
drm/xe: Drop GuC submit_wq pool
drm/sched: Use drm sched lockdep map for submit_wq

+149 -158
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
··· 1439 1439 list_add_tail(&vm->vm_list_node, 1440 1440 &(vm->process_info->vm_list_head)); 1441 1441 vm->process_info->n_vms++; 1442 - 1443 - *ef = dma_fence_get(&vm->process_info->eviction_fence->base); 1442 + if (ef) 1443 + *ef = dma_fence_get(&vm->process_info->eviction_fence->base); 1444 1444 mutex_unlock(&vm->process_info->lock); 1445 1445 1446 1446 return 0;
+5 -2
drivers/gpu/drm/amd/amdkfd/kfd_process.c
··· 1702 1702 1703 1703 ret = amdgpu_amdkfd_gpuvm_acquire_process_vm(dev->adev, avm, 1704 1704 &p->kgd_process_info, 1705 - &ef); 1705 + p->ef ? NULL : &ef); 1706 1706 if (ret) { 1707 1707 dev_err(dev->adev->dev, "Failed to create process VM object\n"); 1708 1708 return ret; 1709 1709 } 1710 - RCU_INIT_POINTER(p->ef, ef); 1710 + 1711 + if (!p->ef) 1712 + RCU_INIT_POINTER(p->ef, ef); 1713 + 1711 1714 pdd->drm_priv = drm_file->private_data; 1712 1715 1713 1716 ret = kfd_process_device_reserve_ib_mem(pdd);
+4 -3
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 2972 2972 2973 2973 hpd_rx_irq_work_suspend(dm); 2974 2974 2975 - if (adev->dm.dc->caps.ips_support) 2976 - dc_allow_idle_optimizations(adev->dm.dc, true); 2977 - 2978 2975 dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); 2976 + 2977 + if (dm->dc->caps.ips_support && adev->in_s0ix) 2978 + dc_allow_idle_optimizations(dm->dc, true); 2979 + 2979 2980 dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3); 2980 2981 2981 2982 return 0;
+34 -11
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 5065 5065 return true; 5066 5066 } 5067 5067 5068 + static void clear_update_flags(struct dc_surface_update *srf_updates, 5069 + int surface_count, struct dc_stream_state *stream) 5070 + { 5071 + int i; 5072 + 5073 + if (stream) 5074 + stream->update_flags.raw = 0; 5075 + 5076 + for (i = 0; i < surface_count; i++) 5077 + if (srf_updates[i].surface) 5078 + srf_updates[i].surface->update_flags.raw = 0; 5079 + } 5080 + 5068 5081 bool dc_update_planes_and_stream(struct dc *dc, 5069 5082 struct dc_surface_update *srf_updates, int surface_count, 5070 5083 struct dc_stream_state *stream, 5071 5084 struct dc_stream_update *stream_update) 5072 5085 { 5086 + bool ret = false; 5087 + 5073 5088 dc_exit_ips_for_hw_access(dc); 5074 5089 /* 5075 5090 * update planes and stream version 3 separates FULL and FAST updates ··· 5101 5086 * features as they are now transparent to the new sequence. 5102 5087 */ 5103 5088 if (dc->ctx->dce_version >= DCN_VERSION_4_01) 5104 - return update_planes_and_stream_v3(dc, srf_updates, 5089 + ret = update_planes_and_stream_v3(dc, srf_updates, 5105 5090 surface_count, stream, stream_update); 5106 - return update_planes_and_stream_v2(dc, srf_updates, 5091 + else 5092 + ret = update_planes_and_stream_v2(dc, srf_updates, 5107 5093 surface_count, stream, stream_update); 5094 + 5095 + if (ret) 5096 + clear_update_flags(srf_updates, surface_count, stream); 5097 + 5098 + return ret; 5108 5099 } 5109 5100 5110 5101 void dc_commit_updates_for_stream(struct dc *dc, ··· 5120 5099 struct dc_stream_update *stream_update, 5121 5100 struct dc_state *state) 5122 5101 { 5102 + bool ret = false; 5103 + 5123 5104 dc_exit_ips_for_hw_access(dc); 5124 5105 /* TODO: Since change commit sequence can have a huge impact, 5125 5106 * we decided to only enable it for DCN3x. However, as soon as ··· 5129 5106 * the new sequence for all ASICs. 5130 5107 */ 5131 5108 if (dc->ctx->dce_version >= DCN_VERSION_4_01) { 5132 - update_planes_and_stream_v3(dc, srf_updates, surface_count, 5109 + ret = update_planes_and_stream_v3(dc, srf_updates, surface_count, 5133 5110 stream, stream_update); 5134 - return; 5135 - } 5136 - if (dc->ctx->dce_version >= DCN_VERSION_3_2) { 5137 - update_planes_and_stream_v2(dc, srf_updates, surface_count, 5111 + } else if (dc->ctx->dce_version >= DCN_VERSION_3_2) { 5112 + ret = update_planes_and_stream_v2(dc, srf_updates, surface_count, 5138 5113 stream, stream_update); 5139 - return; 5140 - } 5141 - update_planes_and_stream_v1(dc, srf_updates, surface_count, stream, 5142 - stream_update, state); 5114 + } else 5115 + ret = update_planes_and_stream_v1(dc, srf_updates, surface_count, stream, 5116 + stream_update, state); 5117 + 5118 + if (ret) 5119 + clear_update_flags(srf_updates, surface_count, stream); 5143 5120 } 5144 5121 5145 5122 uint8_t dc_get_current_stream_count(struct dc *dc)
+13 -13
drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
··· 60 60 61 61 struct vi_dpm_table { 62 62 uint32_t count; 63 - struct vi_dpm_level dpm_level[] __counted_by(count); 63 + struct vi_dpm_level dpm_level[]; 64 64 }; 65 65 66 66 #define PCIE_PERF_REQ_REMOVE_REGISTRY 0 ··· 91 91 92 92 struct phm_clock_array { 93 93 uint32_t count; 94 - uint32_t values[] __counted_by(count); 94 + uint32_t values[]; 95 95 }; 96 96 97 97 struct phm_clock_voltage_dependency_record { ··· 123 123 124 124 struct phm_clock_voltage_dependency_table { 125 125 uint32_t count; 126 - struct phm_clock_voltage_dependency_record entries[] __counted_by(count); 126 + struct phm_clock_voltage_dependency_record entries[]; 127 127 }; 128 128 129 129 struct phm_phase_shedding_limits_record { ··· 140 140 141 141 struct phm_uvd_clock_voltage_dependency_table { 142 142 uint8_t count; 143 - struct phm_uvd_clock_voltage_dependency_record entries[] __counted_by(count); 143 + struct phm_uvd_clock_voltage_dependency_record entries[]; 144 144 }; 145 145 146 146 struct phm_acp_clock_voltage_dependency_record { ··· 150 150 151 151 struct phm_acp_clock_voltage_dependency_table { 152 152 uint32_t count; 153 - struct phm_acp_clock_voltage_dependency_record entries[] __counted_by(count); 153 + struct phm_acp_clock_voltage_dependency_record entries[]; 154 154 }; 155 155 156 156 struct phm_vce_clock_voltage_dependency_record { ··· 161 161 162 162 struct phm_phase_shedding_limits_table { 163 163 uint32_t count; 164 - struct phm_phase_shedding_limits_record entries[] __counted_by(count); 164 + struct phm_phase_shedding_limits_record entries[]; 165 165 }; 166 166 167 167 struct phm_vceclock_voltage_dependency_table { 168 168 uint8_t count; 169 - struct phm_vceclock_voltage_dependency_record entries[] __counted_by(count); 169 + struct phm_vceclock_voltage_dependency_record entries[]; 170 170 }; 171 171 172 172 struct phm_uvdclock_voltage_dependency_table { 173 173 uint8_t count; 174 - struct phm_uvdclock_voltage_dependency_record entries[] __counted_by(count); 174 + struct phm_uvdclock_voltage_dependency_record entries[]; 175 175 }; 176 176 177 177 struct phm_samuclock_voltage_dependency_table { 178 178 uint8_t count; 179 - struct phm_samuclock_voltage_dependency_record entries[] __counted_by(count); 179 + struct phm_samuclock_voltage_dependency_record entries[]; 180 180 }; 181 181 182 182 struct phm_acpclock_voltage_dependency_table { 183 183 uint32_t count; 184 - struct phm_acpclock_voltage_dependency_record entries[] __counted_by(count); 184 + struct phm_acpclock_voltage_dependency_record entries[]; 185 185 }; 186 186 187 187 struct phm_vce_clock_voltage_dependency_table { 188 188 uint8_t count; 189 - struct phm_vce_clock_voltage_dependency_record entries[] __counted_by(count); 189 + struct phm_vce_clock_voltage_dependency_record entries[]; 190 190 }; 191 191 192 192 ··· 393 393 394 394 struct phm_cac_leakage_table { 395 395 uint32_t count; 396 - union phm_cac_leakage_record entries[] __counted_by(count); 396 + union phm_cac_leakage_record entries[]; 397 397 }; 398 398 399 399 struct phm_samu_clock_voltage_dependency_record { ··· 404 404 405 405 struct phm_samu_clock_voltage_dependency_table { 406 406 uint8_t count; 407 - struct phm_samu_clock_voltage_dependency_record entries[] __counted_by(count); 407 + struct phm_samu_clock_voltage_dependency_record entries[]; 408 408 }; 409 409 410 410 struct phm_cac_tdp_table {
+2 -1
drivers/gpu/drm/drm_fbdev_dma.c
··· 50 50 if (!fb_helper->dev) 51 51 return; 52 52 53 - fb_deferred_io_cleanup(info); 53 + if (info->fbdefio) 54 + fb_deferred_io_cleanup(info); 54 55 drm_fb_helper_fini(fb_helper); 55 56 56 57 drm_client_buffer_vunmap(fb_helper->buffer);
+7 -3
drivers/gpu/drm/i915/display/intel_hdcp.c
··· 1094 1094 hdcp->value = value; 1095 1095 if (update_property) { 1096 1096 drm_connector_get(&connector->base); 1097 - queue_work(i915->unordered_wq, &hdcp->prop_work); 1097 + if (!queue_work(i915->unordered_wq, &hdcp->prop_work)) 1098 + drm_connector_put(&connector->base); 1098 1099 } 1099 1100 } 1100 1101 ··· 2525 2524 mutex_lock(&hdcp->mutex); 2526 2525 hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; 2527 2526 drm_connector_get(&connector->base); 2528 - queue_work(i915->unordered_wq, &hdcp->prop_work); 2527 + if (!queue_work(i915->unordered_wq, &hdcp->prop_work)) 2528 + drm_connector_put(&connector->base); 2529 2529 mutex_unlock(&hdcp->mutex); 2530 2530 } 2531 2531 ··· 2543 2541 */ 2544 2542 if (!desired_and_not_enabled && !content_protection_type_changed) { 2545 2543 drm_connector_get(&connector->base); 2546 - queue_work(i915->unordered_wq, &hdcp->prop_work); 2544 + if (!queue_work(i915->unordered_wq, &hdcp->prop_work)) 2545 + drm_connector_put(&connector->base); 2546 + 2547 2547 } 2548 2548 } 2549 2549
+1 -1
drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
··· 210 210 } *rm; 211 211 212 212 struct { 213 - struct mutex mutex;; 213 + struct mutex mutex; 214 214 struct idr idr; 215 215 } client_id; 216 216
+1 -1
drivers/gpu/drm/nouveau/nouveau_dmem.c
··· 193 193 if (!spage || !(src & MIGRATE_PFN_MIGRATE)) 194 194 goto done; 195 195 196 - dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address); 196 + dpage = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vmf->vma, vmf->address); 197 197 if (!dpage) 198 198 goto done; 199 199
+1 -1
drivers/gpu/drm/nouveau/nouveau_drm.c
··· 331 331 return; 332 332 } 333 333 334 - ret = nouveau_channel_new(&drm->client, false, runm, NvDmaFB, NvDmaTT, &drm->cechan); 334 + ret = nouveau_channel_new(&drm->client, true, runm, NvDmaFB, NvDmaTT, &drm->cechan); 335 335 if (ret) 336 336 NV_ERROR(drm, "failed to create ce channel, %d\n", ret); 337 337 }
+2 -7
drivers/gpu/drm/radeon/atombios_dp.c
··· 228 228 { 229 229 struct drm_device *dev = radeon_connector->base.dev; 230 230 struct radeon_device *rdev = dev->dev_private; 231 - int ret; 232 231 233 232 radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd; 234 - radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; 235 233 radeon_connector->ddc_bus->aux.drm_dev = radeon_connector->base.dev; 236 234 if (ASIC_IS_DCE5(rdev)) { 237 235 if (radeon_auxch) ··· 240 242 radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom; 241 243 } 242 244 243 - ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux); 244 - if (!ret) 245 - radeon_connector->ddc_bus->has_aux = true; 246 - 247 - WARN(ret, "drm_dp_aux_register() failed with error %d\n", ret); 245 + drm_dp_aux_init(&radeon_connector->ddc_bus->aux); 246 + radeon_connector->ddc_bus->has_aux = true; 248 247 } 249 248 250 249 /***** general DP utility functions *****/
+17
drivers/gpu/drm/radeon/radeon_connectors.c
··· 1786 1786 return MODE_OK; 1787 1787 } 1788 1788 1789 + static int 1790 + radeon_connector_late_register(struct drm_connector *connector) 1791 + { 1792 + struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1793 + int r = 0; 1794 + 1795 + if (radeon_connector->ddc_bus->has_aux) { 1796 + radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; 1797 + r = drm_dp_aux_register(&radeon_connector->ddc_bus->aux); 1798 + } 1799 + 1800 + return r; 1801 + } 1802 + 1789 1803 static const struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = { 1790 1804 .get_modes = radeon_dp_get_modes, 1791 1805 .mode_valid = radeon_dp_mode_valid, ··· 1814 1800 .early_unregister = radeon_connector_unregister, 1815 1801 .destroy = radeon_connector_destroy, 1816 1802 .force = radeon_dvi_force, 1803 + .late_register = radeon_connector_late_register, 1817 1804 }; 1818 1805 1819 1806 static const struct drm_connector_funcs radeon_edp_connector_funcs = { ··· 1825 1810 .early_unregister = radeon_connector_unregister, 1826 1811 .destroy = radeon_connector_destroy, 1827 1812 .force = radeon_dvi_force, 1813 + .late_register = radeon_connector_late_register, 1828 1814 }; 1829 1815 1830 1816 static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { ··· 1836 1820 .early_unregister = radeon_connector_unregister, 1837 1821 .destroy = radeon_connector_destroy, 1838 1822 .force = radeon_dvi_force, 1823 + .late_register = radeon_connector_late_register, 1839 1824 }; 1840 1825 1841 1826 void
-3
drivers/gpu/drm/radeon/radeon_gem.c
··· 44 44 int radeon_gem_prime_pin(struct drm_gem_object *obj); 45 45 void radeon_gem_prime_unpin(struct drm_gem_object *obj); 46 46 47 - const struct drm_gem_object_funcs radeon_gem_object_funcs; 48 - 49 47 static vm_fault_t radeon_gem_fault(struct vm_fault *vmf) 50 48 { 51 49 struct ttm_buffer_object *bo = vmf->vma->vm_private_data; ··· 130 132 return r; 131 133 } 132 134 *obj = &robj->tbo.base; 133 - (*obj)->funcs = &radeon_gem_object_funcs; 134 135 robj->pid = task_pid_nr(current); 135 136 136 137 mutex_lock(&rdev->gem.mutex);
+1
drivers/gpu/drm/radeon/radeon_object.c
··· 151 151 if (bo == NULL) 152 152 return -ENOMEM; 153 153 drm_gem_private_object_init(rdev_to_drm(rdev), &bo->tbo.base, size); 154 + bo->tbo.base.funcs = &radeon_gem_object_funcs; 154 155 bo->rdev = rdev; 155 156 bo->surface_reg = -1; 156 157 INIT_LIST_HEAD(&bo->list);
+11
drivers/gpu/drm/scheduler/sched_main.c
··· 87 87 #define CREATE_TRACE_POINTS 88 88 #include "gpu_scheduler_trace.h" 89 89 90 + #ifdef CONFIG_LOCKDEP 91 + static struct lockdep_map drm_sched_lockdep_map = { 92 + .name = "drm_sched_lockdep_map" 93 + }; 94 + #endif 95 + 90 96 #define to_drm_sched_job(sched_job) \ 91 97 container_of((sched_job), struct drm_sched_job, queue_node) 92 98 ··· 1275 1269 sched->submit_wq = submit_wq; 1276 1270 sched->own_submit_wq = false; 1277 1271 } else { 1272 + #ifdef CONFIG_LOCKDEP 1273 + sched->submit_wq = alloc_ordered_workqueue_lockdep_map(name, 0, 1274 + &drm_sched_lockdep_map); 1275 + #else 1278 1276 sched->submit_wq = alloc_ordered_workqueue(name, 0); 1277 + #endif 1279 1278 if (!sched->submit_wq) 1280 1279 return -ENOMEM; 1281 1280
+8 -1
drivers/gpu/drm/v3d/v3d_perfmon.c
··· 306 306 static int v3d_perfmon_idr_del(int id, void *elem, void *data) 307 307 { 308 308 struct v3d_perfmon *perfmon = elem; 309 + struct v3d_dev *v3d = (struct v3d_dev *)data; 310 + 311 + /* If the active perfmon is being destroyed, stop it first */ 312 + if (perfmon == v3d->active_perfmon) 313 + v3d_perfmon_stop(v3d, perfmon, false); 309 314 310 315 v3d_perfmon_put(perfmon); 311 316 ··· 319 314 320 315 void v3d_perfmon_close_file(struct v3d_file_priv *v3d_priv) 321 316 { 317 + struct v3d_dev *v3d = v3d_priv->v3d; 318 + 322 319 mutex_lock(&v3d_priv->perfmon.lock); 323 - idr_for_each(&v3d_priv->perfmon.idr, v3d_perfmon_idr_del, NULL); 320 + idr_for_each(&v3d_priv->perfmon.idr, v3d_perfmon_idr_del, v3d); 324 321 idr_destroy(&v3d_priv->perfmon.idr); 325 322 mutex_unlock(&v3d_priv->perfmon.lock); 326 323 mutex_destroy(&v3d_priv->perfmon.lock);
+6 -1
drivers/gpu/drm/vc4/vc4_perfmon.c
··· 116 116 static int vc4_perfmon_idr_del(int id, void *elem, void *data) 117 117 { 118 118 struct vc4_perfmon *perfmon = elem; 119 + struct vc4_dev *vc4 = (struct vc4_dev *)data; 120 + 121 + /* If the active perfmon is being destroyed, stop it first */ 122 + if (perfmon == vc4->active_perfmon) 123 + vc4_perfmon_stop(vc4, perfmon, false); 119 124 120 125 vc4_perfmon_put(perfmon); 121 126 ··· 135 130 return; 136 131 137 132 mutex_lock(&vc4file->perfmon.lock); 138 - idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, NULL); 133 + idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, vc4); 139 134 idr_destroy(&vc4file->perfmon.idr); 140 135 mutex_unlock(&vc4file->perfmon.lock); 141 136 mutex_destroy(&vc4file->perfmon.lock);
+1 -1
drivers/gpu/drm/xe/xe_debugfs.c
··· 187 187 debugfs_create_file("forcewake_all", 0400, root, xe, 188 188 &forcewake_all_fops); 189 189 190 - debugfs_create_file("wedged_mode", 0400, root, xe, 190 + debugfs_create_file("wedged_mode", 0600, root, xe, 191 191 &wedged_mode_fops); 192 192 193 193 for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
+3 -1
drivers/gpu/drm/xe/xe_gt.c
··· 874 874 int ret = 0; 875 875 876 876 if ((!xe_uc_fw_is_available(&gt->uc.gsc.fw) || 877 - xe_uc_fw_is_loaded(&gt->uc.gsc.fw)) && XE_WA(gt, 22019338487)) 877 + xe_uc_fw_is_loaded(&gt->uc.gsc.fw) || 878 + xe_uc_fw_is_in_error_state(&gt->uc.gsc.fw)) && 879 + XE_WA(gt, 22019338487)) 878 880 ret = xe_guc_pc_restore_stashed_freq(&gt->uc.guc.pc); 879 881 880 882 return ret;
+26 -18
drivers/gpu/drm/xe/xe_guc_ct.c
··· 667 667 num_g2h = 1; 668 668 669 669 if (g2h_fence_needs_alloc(g2h_fence)) { 670 - void *ptr; 671 - 672 670 g2h_fence->seqno = next_ct_seqno(ct, true); 673 - ptr = xa_store(&ct->fence_lookup, 674 - g2h_fence->seqno, 675 - g2h_fence, GFP_ATOMIC); 676 - if (IS_ERR(ptr)) { 677 - ret = PTR_ERR(ptr); 671 + ret = xa_err(xa_store(&ct->fence_lookup, 672 + g2h_fence->seqno, g2h_fence, 673 + GFP_ATOMIC)); 674 + if (ret) 678 675 goto out; 679 - } 680 676 } 681 677 682 678 seqno = g2h_fence->seqno; ··· 875 879 retry_same_fence: 876 880 ret = guc_ct_send(ct, action, len, 0, 0, &g2h_fence); 877 881 if (unlikely(ret == -ENOMEM)) { 878 - void *ptr; 879 - 880 882 /* Retry allocation /w GFP_KERNEL */ 881 - ptr = xa_store(&ct->fence_lookup, 882 - g2h_fence.seqno, 883 - &g2h_fence, GFP_KERNEL); 884 - if (IS_ERR(ptr)) 885 - return PTR_ERR(ptr); 883 + ret = xa_err(xa_store(&ct->fence_lookup, g2h_fence.seqno, 884 + &g2h_fence, GFP_KERNEL)); 885 + if (ret) 886 + return ret; 886 887 887 888 goto retry_same_fence; 888 889 } else if (unlikely(ret)) { ··· 896 903 } 897 904 898 905 ret = wait_event_timeout(ct->g2h_fence_wq, g2h_fence.done, HZ); 906 + 907 + /* 908 + * Ensure we serialize with completion side to prevent UAF with fence going out of scope on 909 + * the stack, since we have no clue if it will fire after the timeout before we can erase 910 + * from the xa. Also we have some dependent loads and stores below for which we need the 911 + * correct ordering, and we lack the needed barriers. 912 + */ 913 + mutex_lock(&ct->lock); 899 914 if (!ret) { 900 - xe_gt_err(gt, "Timed out wait for G2H, fence %u, action %04x", 901 - g2h_fence.seqno, action[0]); 915 + xe_gt_err(gt, "Timed out wait for G2H, fence %u, action %04x, done %s", 916 + g2h_fence.seqno, action[0], str_yes_no(g2h_fence.done)); 902 917 xa_erase_irq(&ct->fence_lookup, g2h_fence.seqno); 918 + mutex_unlock(&ct->lock); 903 919 return -ETIME; 904 920 } 905 921 906 922 if (g2h_fence.retry) { 907 923 xe_gt_dbg(gt, "H2G action %#x retrying: reason %#x\n", 908 924 action[0], g2h_fence.reason); 925 + mutex_unlock(&ct->lock); 909 926 goto retry; 910 927 } 911 928 if (g2h_fence.fail) { ··· 924 921 ret = -EIO; 925 922 } 926 923 927 - return ret > 0 ? response_buffer ? g2h_fence.response_len : g2h_fence.response_data : ret; 924 + if (ret > 0) 925 + ret = response_buffer ? g2h_fence.response_len : g2h_fence.response_data; 926 + 927 + mutex_unlock(&ct->lock); 928 + 929 + return ret; 928 930 } 929 931 930 932 /**
+4 -81
drivers/gpu/drm/xe/xe_guc_submit.c
··· 224 224 EXEC_QUEUE_STATE_BANNED)); 225 225 } 226 226 227 - #ifdef CONFIG_PROVE_LOCKING 228 - static int alloc_submit_wq(struct xe_guc *guc) 229 - { 230 - int i; 231 - 232 - for (i = 0; i < NUM_SUBMIT_WQ; ++i) { 233 - guc->submission_state.submit_wq_pool[i] = 234 - alloc_ordered_workqueue("submit_wq", 0); 235 - if (!guc->submission_state.submit_wq_pool[i]) 236 - goto err_free; 237 - } 238 - 239 - return 0; 240 - 241 - err_free: 242 - while (i) 243 - destroy_workqueue(guc->submission_state.submit_wq_pool[--i]); 244 - 245 - return -ENOMEM; 246 - } 247 - 248 - static void free_submit_wq(struct xe_guc *guc) 249 - { 250 - int i; 251 - 252 - for (i = 0; i < NUM_SUBMIT_WQ; ++i) 253 - destroy_workqueue(guc->submission_state.submit_wq_pool[i]); 254 - } 255 - 256 - static struct workqueue_struct *get_submit_wq(struct xe_guc *guc) 257 - { 258 - int idx = guc->submission_state.submit_wq_idx++ % NUM_SUBMIT_WQ; 259 - 260 - return guc->submission_state.submit_wq_pool[idx]; 261 - } 262 - #else 263 - static int alloc_submit_wq(struct xe_guc *guc) 264 - { 265 - return 0; 266 - } 267 - 268 - static void free_submit_wq(struct xe_guc *guc) 269 - { 270 - 271 - } 272 - 273 - static struct workqueue_struct *get_submit_wq(struct xe_guc *guc) 274 - { 275 - return NULL; 276 - } 277 - #endif 278 - 279 - static void xe_guc_submit_fini(struct xe_guc *guc) 280 - { 281 - struct xe_device *xe = guc_to_xe(guc); 282 - struct xe_gt *gt = guc_to_gt(guc); 283 - int ret; 284 - 285 - ret = wait_event_timeout(guc->submission_state.fini_wq, 286 - xa_empty(&guc->submission_state.exec_queue_lookup), 287 - HZ * 5); 288 - 289 - drain_workqueue(xe->destroy_wq); 290 - 291 - xe_gt_assert(gt, ret); 292 - } 293 - 294 227 static void guc_submit_fini(struct drm_device *drm, void *arg) 295 228 { 296 229 struct xe_guc *guc = arg; 297 230 298 - xe_guc_submit_fini(guc); 299 231 xa_destroy(&guc->submission_state.exec_queue_lookup); 300 - free_submit_wq(guc); 301 232 } 302 233 303 234 static void guc_submit_wedged_fini(void *arg) ··· 290 359 if (err) 291 360 return err; 292 361 293 - err = alloc_submit_wq(guc); 294 - if (err) 295 - return err; 296 - 297 362 gt->exec_queue_ops = &guc_exec_queue_ops; 298 363 299 364 xa_init(&guc->submission_state.exec_queue_lookup); ··· 320 393 static int alloc_guc_id(struct xe_guc *guc, struct xe_exec_queue *q) 321 394 { 322 395 int ret; 323 - void *ptr; 324 396 int i; 325 397 326 398 /* ··· 339 413 q->guc->id = ret; 340 414 341 415 for (i = 0; i < q->width; ++i) { 342 - ptr = xa_store(&guc->submission_state.exec_queue_lookup, 343 - q->guc->id + i, q, GFP_NOWAIT); 344 - if (IS_ERR(ptr)) { 345 - ret = PTR_ERR(ptr); 416 + ret = xa_err(xa_store(&guc->submission_state.exec_queue_lookup, 417 + q->guc->id + i, q, GFP_NOWAIT)); 418 + if (ret) 346 419 goto err_release; 347 - } 348 420 } 349 421 350 422 return 0; ··· 1406 1482 timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT : 1407 1483 msecs_to_jiffies(q->sched_props.job_timeout_ms); 1408 1484 err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops, 1409 - get_submit_wq(guc), 1410 - q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, 64, 1485 + NULL, q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, 64, 1411 1486 timeout, guc_to_gt(guc)->ordered_wq, NULL, 1412 1487 q->name, gt_to_xe(q->gt)->drm.dev); 1413 1488 if (err)
-7
drivers/gpu/drm/xe/xe_guc_types.h
··· 72 72 atomic_t stopped; 73 73 /** @submission_state.lock: protects submission state */ 74 74 struct mutex lock; 75 - #ifdef CONFIG_PROVE_LOCKING 76 - #define NUM_SUBMIT_WQ 256 77 - /** @submission_state.submit_wq_pool: submission ordered workqueues pool */ 78 - struct workqueue_struct *submit_wq_pool[NUM_SUBMIT_WQ]; 79 - /** @submission_state.submit_wq_idx: submission ordered workqueue index */ 80 - int submit_wq_idx; 81 - #endif 82 75 /** @submission_state.enabled: submission is enabled */ 83 76 bool enabled; 84 77 /** @submission_state.fini_wq: submit fini wait queue */