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.

accel/qaic: Synchronize access to DBC request queue head & tail pointer

Two threads of the same process can potential read and write parallelly to
head and tail pointers of the same DBC request queue. This could lead to a
race condition and corrupt the DBC request queue.

Fixes: ff13be830333 ("accel/qaic: Add datapath")
Signed-off-by: Pranjal Ramajor Asha Kanojiya <quic_pkanojiy@quicinc.com>
Signed-off-by: Youssef Samir <youssef.abdulrahman@oss.qualcomm.com>
Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Reviewed-by: Carl Vanderlip <carl.vanderlip@oss.qualcomm.com>
[jhugo: Add fixes tag]
Signed-off-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20251007061837.206132-1-youssef.abdulrahman@oss.qualcomm.com

authored by

Pranjal Ramajor Asha Kanojiya and committed by
Jeff Hugo
52e59f77 11f08c30

+15 -2
+2
drivers/accel/qaic/qaic.h
··· 97 97 * response queue's head and tail pointer of this DBC. 98 98 */ 99 99 void __iomem *dbc_base; 100 + /* Synchronizes access to Request queue's head and tail pointer */ 101 + struct mutex req_lock; 100 102 /* Head of list where each node is a memory handle queued in request queue */ 101 103 struct list_head xfer_list; 102 104 /* Synchronizes DBC readers during cleanup */
+10 -2
drivers/accel/qaic/qaic_data.c
··· 1356 1356 goto release_ch_rcu; 1357 1357 } 1358 1358 1359 + ret = mutex_lock_interruptible(&dbc->req_lock); 1360 + if (ret) 1361 + goto release_ch_rcu; 1362 + 1359 1363 head = readl(dbc->dbc_base + REQHP_OFF); 1360 1364 tail = readl(dbc->dbc_base + REQTP_OFF); 1361 1365 1362 1366 if (head == U32_MAX || tail == U32_MAX) { 1363 1367 /* PCI link error */ 1364 1368 ret = -ENODEV; 1365 - goto release_ch_rcu; 1369 + goto unlock_req_lock; 1366 1370 } 1367 1371 1368 1372 queue_level = head <= tail ? tail - head : dbc->nelem - (head - tail); ··· 1374 1370 ret = send_bo_list_to_device(qdev, file_priv, exec, args->hdr.count, is_partial, dbc, 1375 1371 head, &tail); 1376 1372 if (ret) 1377 - goto release_ch_rcu; 1373 + goto unlock_req_lock; 1378 1374 1379 1375 /* Finalize commit to hardware */ 1380 1376 submit_ts = ktime_get_ns(); 1381 1377 writel(tail, dbc->dbc_base + REQTP_OFF); 1378 + mutex_unlock(&dbc->req_lock); 1382 1379 1383 1380 update_profiling_data(file_priv, exec, args->hdr.count, is_partial, received_ts, 1384 1381 submit_ts, queue_level); ··· 1387 1382 if (datapath_polling) 1388 1383 schedule_work(&dbc->poll_work); 1389 1384 1385 + unlock_req_lock: 1386 + if (ret) 1387 + mutex_unlock(&dbc->req_lock); 1390 1388 release_ch_rcu: 1391 1389 srcu_read_unlock(&dbc->ch_lock, rcu_id); 1392 1390 unlock_dev_srcu:
+3
drivers/accel/qaic/qaic_drv.c
··· 454 454 return NULL; 455 455 init_waitqueue_head(&qdev->dbc[i].dbc_release); 456 456 INIT_LIST_HEAD(&qdev->dbc[i].bo_lists); 457 + ret = drmm_mutex_init(drm, &qdev->dbc[i].req_lock); 458 + if (ret) 459 + return NULL; 457 460 } 458 461 459 462 return qdev;