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: ff13be8303
("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
This commit is contained in:
parent
11f08c30a3
commit
52e59f7740
|
@ -97,6 +97,8 @@ struct dma_bridge_chan {
|
|||
* response queue's head and tail pointer of this DBC.
|
||||
*/
|
||||
void __iomem *dbc_base;
|
||||
/* Synchronizes access to Request queue's head and tail pointer */
|
||||
struct mutex req_lock;
|
||||
/* Head of list where each node is a memory handle queued in request queue */
|
||||
struct list_head xfer_list;
|
||||
/* Synchronizes DBC readers during cleanup */
|
||||
|
|
|
@ -1356,13 +1356,17 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr
|
|||
goto release_ch_rcu;
|
||||
}
|
||||
|
||||
ret = mutex_lock_interruptible(&dbc->req_lock);
|
||||
if (ret)
|
||||
goto release_ch_rcu;
|
||||
|
||||
head = readl(dbc->dbc_base + REQHP_OFF);
|
||||
tail = readl(dbc->dbc_base + REQTP_OFF);
|
||||
|
||||
if (head == U32_MAX || tail == U32_MAX) {
|
||||
/* PCI link error */
|
||||
ret = -ENODEV;
|
||||
goto release_ch_rcu;
|
||||
goto unlock_req_lock;
|
||||
}
|
||||
|
||||
queue_level = head <= tail ? tail - head : dbc->nelem - (head - tail);
|
||||
|
@ -1370,11 +1374,12 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr
|
|||
ret = send_bo_list_to_device(qdev, file_priv, exec, args->hdr.count, is_partial, dbc,
|
||||
head, &tail);
|
||||
if (ret)
|
||||
goto release_ch_rcu;
|
||||
goto unlock_req_lock;
|
||||
|
||||
/* Finalize commit to hardware */
|
||||
submit_ts = ktime_get_ns();
|
||||
writel(tail, dbc->dbc_base + REQTP_OFF);
|
||||
mutex_unlock(&dbc->req_lock);
|
||||
|
||||
update_profiling_data(file_priv, exec, args->hdr.count, is_partial, received_ts,
|
||||
submit_ts, queue_level);
|
||||
|
@ -1382,6 +1387,9 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr
|
|||
if (datapath_polling)
|
||||
schedule_work(&dbc->poll_work);
|
||||
|
||||
unlock_req_lock:
|
||||
if (ret)
|
||||
mutex_unlock(&dbc->req_lock);
|
||||
release_ch_rcu:
|
||||
srcu_read_unlock(&dbc->ch_lock, rcu_id);
|
||||
unlock_dev_srcu:
|
||||
|
|
|
@ -454,6 +454,9 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev,
|
|||
return NULL;
|
||||
init_waitqueue_head(&qdev->dbc[i].dbc_release);
|
||||
INIT_LIST_HEAD(&qdev->dbc[i].bo_lists);
|
||||
ret = drmm_mutex_init(drm, &qdev->dbc[i].req_lock);
|
||||
if (ret)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return qdev;
|
||||
|
|
Loading…
Reference in New Issue