Skip to content

Commit 52e59f7

Browse files
Pranjal Ramajor Asha KanojiyaJeff Hugo
authored andcommitted
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: ff13be8 ("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
1 parent 11f08c3 commit 52e59f7

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

drivers/accel/qaic/qaic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ struct dma_bridge_chan {
9797
* response queue's head and tail pointer of this DBC.
9898
*/
9999
void __iomem *dbc_base;
100+
/* Synchronizes access to Request queue's head and tail pointer */
101+
struct mutex req_lock;
100102
/* Head of list where each node is a memory handle queued in request queue */
101103
struct list_head xfer_list;
102104
/* Synchronizes DBC readers during cleanup */

drivers/accel/qaic/qaic_data.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,32 +1356,40 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr
13561356
goto release_ch_rcu;
13571357
}
13581358

1359+
ret = mutex_lock_interruptible(&dbc->req_lock);
1360+
if (ret)
1361+
goto release_ch_rcu;
1362+
13591363
head = readl(dbc->dbc_base + REQHP_OFF);
13601364
tail = readl(dbc->dbc_base + REQTP_OFF);
13611365

13621366
if (head == U32_MAX || tail == U32_MAX) {
13631367
/* PCI link error */
13641368
ret = -ENODEV;
1365-
goto release_ch_rcu;
1369+
goto unlock_req_lock;
13661370
}
13671371

13681372
queue_level = head <= tail ? tail - head : dbc->nelem - (head - tail);
13691373

13701374
ret = send_bo_list_to_device(qdev, file_priv, exec, args->hdr.count, is_partial, dbc,
13711375
head, &tail);
13721376
if (ret)
1373-
goto release_ch_rcu;
1377+
goto unlock_req_lock;
13741378

13751379
/* Finalize commit to hardware */
13761380
submit_ts = ktime_get_ns();
13771381
writel(tail, dbc->dbc_base + REQTP_OFF);
1382+
mutex_unlock(&dbc->req_lock);
13781383

13791384
update_profiling_data(file_priv, exec, args->hdr.count, is_partial, received_ts,
13801385
submit_ts, queue_level);
13811386

13821387
if (datapath_polling)
13831388
schedule_work(&dbc->poll_work);
13841389

1390+
unlock_req_lock:
1391+
if (ret)
1392+
mutex_unlock(&dbc->req_lock);
13851393
release_ch_rcu:
13861394
srcu_read_unlock(&dbc->ch_lock, rcu_id);
13871395
unlock_dev_srcu:

drivers/accel/qaic/qaic_drv.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,9 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev,
454454
return NULL;
455455
init_waitqueue_head(&qdev->dbc[i].dbc_release);
456456
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;
457460
}
458461

459462
return qdev;

0 commit comments

Comments
 (0)