summaryrefslogtreecommitdiff
path: root/drivers/accel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-07-03 15:42:20 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-07-03 15:42:20 -1000
commitdac0b8c58757eba9deb0fdd32d37a85bbb06006d (patch)
tree03cdd6031497bce9cf63e4e60b408ca1ae1c12c7 /drivers/accel
parente6174e9b38e766cdfcfed41ffd8be35c504a9963 (diff)
parentacd7c71ba8d83808fa8d704196f3d53f7d58cf50 (diff)
downloadlinux-next-dac0b8c58757eba9deb0fdd32d37a85bbb06006d.tar.gz
linux-next-dac0b8c58757eba9deb0fdd32d37a85bbb06006d.zip
Merge tag 'drm-fixes-2026-07-04' of https://gitlab.freedesktop.org/drm/kernel
Pull drm fixes from Dave Airlie: "Weekly fixes for drm. This is large for rc2 but it's just a lot of small fixes across a bunch of drivers, xe, amdgpu as usual, plus some sashiko-inspired fixes for panthor, and some dma-fence updates. core: - kernel doc fix - include types.h in drm_ras.h dma-fence: - fix NULL ptr dereference - use correct callback - make dma_fence_dedup_array more robust dp: - handle torn down topology gracefully - fix kernel doc i915: - Input validation fixes for BIOS and EDID - Fix HDCP code buffer overflow and seq_num_v monotonic increase check - Fix near-NULL deref in i915_active during GFP_ATOMIC exhaustion xe: - Wedge from the timeout handler only after releasing the queue - Fix a NULL pointer dereference - Remove redundant exec_queue_suspended - RTP / OA whitelist fixes - Return error on non-migratable faults requiring devmem - Skip FORCE_WC and vm_bound check for external dma-bufs - Hold notifier lock for write on inject test path - Drop bogus static from finish in force_invalidate - Fix double-free of managed BO in error path - Don't attempt to process FAST_REQ or EVENT relays - Fix NPD in bo_meminfo - Prevent invalid cursor access for purged BOs - Fix offset alignment for MERT WHITELST_OA_MERT_MMIO_TRG amdgpu: - Soc24 aborted suspend fix - Drop unecessary BUG() and BUG_ON() from error paths - SCPM fix - Power reporting fix - DCE HDR fix - UVD boundary checks - VCN boundary checks - VCE boundary checks - DCN 4.2 fixes - Large stack allocation fixes - Fix aperture mapping leak - UserQ fixes - Ignore_damage_clips fix - ACP fixes - DC boundary checks - GPUVM fixes - JPEG idle check fixes - Userptr fix - GC 11.7 updates - Non-4K page fix - SMU 13 fixes - DP alt mode fix amdkfd: - Boundary checks - CRIU fixes amdxdna: - fix device removal issues - fix use after free in debug BO imagination: - fix double call to scheduler fini - fix ioctl return values - fix user array stride virtio: - handle EDIDs better panthor: - irq safe fence lock fix - reset work fix - fix invalid pointer - fix iomem access in suspended state - sched resume fix - unplug suspend fix - drop needless check - eviction leak fix - bail on group start/resume fix - keep irqs masked malidp: - use clock bulk API komeda: - clock prepare fixes" * tag 'drm-fixes-2026-07-04' of https://gitlab.freedesktop.org/drm/kernel: (105 commits) drm/xe/oa: Fix offset alignment for MERT WHITELIST_OA_MERT_MMIO_TRG drm/xe/pt: prevent invalid cursor access for purged BOs drm/xe: fix NPD in bo_meminfo() drm/xe/pf: Don't attempt to process FAST_REQ or EVENT relays drm/xe/hw_engine: Fix double-free of managed BO in error path drm/xe/userptr: Drop bogus static from finish in force_invalidate drm/xe/userptr: Hold notifier_lock for write on inject test path drm/xe/display: skip FORCE_WC and vm_bound check for external dma-bufs drm/xe: Return error on non-migratable faults requiring devmem drm/xe/rtp: Ensure locking/ref counting for OA whitelists drm/xe/oa: (De-)whitelist OA registers on OA stream open/release drm/xe/rtp: (De-)whitelist OA registers for all hwe's for a gt drm/xe/rtp: Toggle 'deny' bit to (de-)whitelist OA regs drm/xe/rtp: Save OA nonpriv registers to register save/restore lists drm/xe/rtp: Generalize whitelist_apply_to_hwe drm/xe/rtp: Keep track of non-OA nonpriv slots drm/xe/rtp: Maintain OA whitelists separately drm/xe/rtp: Fix build error with clang < 21 and non-const initializers drm/imagination: Fix user array stride in pvr_set_uobj_array() drm/imagination: Fix returned size for DRM_IOCTL_PVR_DEV_QUERY ...
Diffstat (limited to 'drivers/accel')
-rw-r--r--drivers/accel/amdxdna/aie2_ctx.c68
-rw-r--r--drivers/accel/amdxdna/amdxdna_ctx.h1
-rw-r--r--drivers/accel/amdxdna/amdxdna_iommu.c43
-rw-r--r--drivers/accel/amdxdna/amdxdna_pci_drv.c38
-rw-r--r--drivers/accel/amdxdna/amdxdna_pci_drv.h1
5 files changed, 98 insertions, 53 deletions
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index e9fbd8c14364..54486960cbf5 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -59,6 +59,18 @@ static bool aie2_tdr_detect(struct amdxdna_dev *xdna)
return false;
}
+static void aie2_cmd_release(struct kref *ref)
+{
+ struct amdxdna_drv_cmd *drv_cmd = container_of(ref, struct amdxdna_drv_cmd, refcnt);
+
+ kfree(drv_cmd);
+}
+
+static void aie2_cmd_put(struct amdxdna_drv_cmd *drv_cmd)
+{
+ kref_put(&drv_cmd->refcnt, aie2_cmd_release);
+}
+
static void aie2_job_release(struct kref *ref)
{
struct amdxdna_sched_job *job;
@@ -70,6 +82,8 @@ static void aie2_job_release(struct kref *ref)
wake_up(&job->hwctx->priv->job_free_wq);
if (job->out_fence)
dma_fence_put(job->out_fence);
+ if (job->drv_cmd)
+ aie2_cmd_put(job->drv_cmd);
kfree(job->aie2_job_health);
kfree(job);
}
@@ -901,7 +915,7 @@ static int aie2_hwctx_cfg_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl,
{
struct amdxdna_client *client = hwctx->client;
struct amdxdna_dev *xdna = client->xdna;
- struct amdxdna_drv_cmd cmd = { 0 };
+ struct amdxdna_drv_cmd *cmd;
struct amdxdna_gem_obj *abo;
u64 seq;
int ret;
@@ -912,32 +926,39 @@ static int aie2_hwctx_cfg_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl,
return -EINVAL;
}
+ cmd = kzalloc_obj(*cmd);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto put_obj;
+ }
+ kref_init(&cmd->refcnt);
+
if (attach) {
if (abo->assigned_hwctx != AMDXDNA_INVALID_CTX_HANDLE) {
ret = -EBUSY;
- goto put_obj;
+ goto put_cmd;
}
- cmd.opcode = ATTACH_DEBUG_BO;
+ cmd->opcode = ATTACH_DEBUG_BO;
} else {
if (abo->assigned_hwctx != hwctx->id) {
ret = -EINVAL;
- goto put_obj;
+ goto put_cmd;
}
- cmd.opcode = DETACH_DEBUG_BO;
+ cmd->opcode = DETACH_DEBUG_BO;
}
- ret = amdxdna_cmd_submit(client, &cmd, AMDXDNA_INVALID_BO_HANDLE,
+ ret = amdxdna_cmd_submit(client, cmd, AMDXDNA_INVALID_BO_HANDLE,
&bo_hdl, 1, hwctx->id, &seq);
if (ret) {
XDNA_ERR(xdna, "Submit command failed");
- goto put_obj;
+ goto put_cmd;
}
aie2_cmd_wait(hwctx, seq);
- if (cmd.result) {
- XDNA_ERR(xdna, "Response failure 0x%x", cmd.result);
+ if (cmd->result) {
+ XDNA_ERR(xdna, "Response failure 0x%x", cmd->result);
ret = -EINVAL;
- goto put_obj;
+ goto put_cmd;
}
if (attach)
@@ -947,6 +968,8 @@ static int aie2_hwctx_cfg_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl,
XDNA_DBG(xdna, "Config debug BO %d to %s", bo_hdl, hwctx->name);
+put_cmd:
+ aie2_cmd_put(cmd);
put_obj:
amdxdna_gem_put_obj(abo);
return ret;
@@ -974,25 +997,32 @@ int aie2_hwctx_sync_debug_bo(struct amdxdna_hwctx *hwctx, u32 debug_bo_hdl)
{
struct amdxdna_client *client = hwctx->client;
struct amdxdna_dev *xdna = client->xdna;
- struct amdxdna_drv_cmd cmd = { 0 };
+ struct amdxdna_drv_cmd *cmd;
u64 seq;
int ret;
- cmd.opcode = SYNC_DEBUG_BO;
- ret = amdxdna_cmd_submit(client, &cmd, AMDXDNA_INVALID_BO_HANDLE,
+ cmd = kzalloc_obj(*cmd);
+ if (!cmd)
+ return -ENOMEM;
+ kref_init(&cmd->refcnt);
+
+ cmd->opcode = SYNC_DEBUG_BO;
+ ret = amdxdna_cmd_submit(client, cmd, AMDXDNA_INVALID_BO_HANDLE,
&debug_bo_hdl, 1, hwctx->id, &seq);
if (ret) {
XDNA_ERR(xdna, "Submit command failed");
- return ret;
+ goto put_cmd;
}
aie2_cmd_wait(hwctx, seq);
- if (cmd.result) {
- XDNA_ERR(xdna, "Response failure 0x%x", cmd.result);
- return -EINVAL;
+ if (cmd->result) {
+ XDNA_ERR(xdna, "Response failure 0x%x", cmd->result);
+ ret = -EINVAL;
}
- return 0;
+put_cmd:
+ aie2_cmd_put(cmd);
+ return ret;
}
static int aie2_populate_range(struct amdxdna_gem_obj *abo)
@@ -1142,6 +1172,8 @@ retry:
dma_resv_add_fence(job->bos[i]->resv, job->out_fence, DMA_RESV_USAGE_WRITE);
job->seq = hwctx->priv->seq++;
kref_get(&job->refcnt);
+ if (job->drv_cmd)
+ kref_get(&job->drv_cmd->refcnt);
drm_sched_entity_push_job(&job->base);
*seq = job->seq;
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h b/drivers/accel/amdxdna/amdxdna_ctx.h
index aaae16430466..b6bef3af7dab 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.h
+++ b/drivers/accel/amdxdna/amdxdna_ctx.h
@@ -132,6 +132,7 @@ enum amdxdna_job_opcode {
struct amdxdna_drv_cmd {
enum amdxdna_job_opcode opcode;
u32 result;
+ struct kref refcnt;
};
struct app_health_report;
diff --git a/drivers/accel/amdxdna/amdxdna_iommu.c b/drivers/accel/amdxdna/amdxdna_iommu.c
index eff00131d0f8..4f245b969eef 100644
--- a/drivers/accel/amdxdna/amdxdna_iommu.c
+++ b/drivers/accel/amdxdna/amdxdna_iommu.c
@@ -4,6 +4,7 @@
*/
#include <drm/amdxdna_accel.h>
+#include <drm/drm_managed.h>
#include <linux/iommu.h>
#include <linux/iova.h>
@@ -153,10 +154,30 @@ void amdxdna_iommu_free(struct amdxdna_dev *xdna, size_t size,
free_pages((unsigned long)cpu_addr, get_order(size));
}
+static void amdxdna_cleanup_force_iova(struct drm_device *dev, void *res)
+{
+ struct amdxdna_dev *xdna = to_xdna_dev(dev);
+
+ if (xdna->domain) {
+ iommu_detach_group(xdna->domain, xdna->group);
+ put_iova_domain(&xdna->iovad);
+ iova_cache_put();
+ iommu_domain_free(xdna->domain);
+ }
+
+ iommu_group_put(xdna->group);
+}
+
+void amdxdna_iommu_fini(struct amdxdna_dev *xdna)
+{
+ if (xdna->group && !xdna->domain)
+ iommu_group_put(xdna->group);
+}
+
int amdxdna_iommu_init(struct amdxdna_dev *xdna)
{
unsigned long order;
- int ret;
+ int ret = 0;
xdna->group = iommu_group_get(xdna->ddev.dev);
if (!xdna->group || !force_iova)
@@ -182,8 +203,14 @@ int amdxdna_iommu_init(struct amdxdna_dev *xdna)
if (ret)
goto put_iova;
+ ret = drmm_add_action(&xdna->ddev, amdxdna_cleanup_force_iova, NULL);
+ if (ret)
+ goto detach_group;
+
return 0;
+detach_group:
+ iommu_detach_group(xdna->domain, xdna->group);
put_iova:
put_iova_domain(&xdna->iovad);
iova_cache_put();
@@ -191,20 +218,8 @@ free_domain:
iommu_domain_free(xdna->domain);
put_group:
iommu_group_put(xdna->group);
+ xdna->group = NULL;
xdna->domain = NULL;
return ret;
}
-
-void amdxdna_iommu_fini(struct amdxdna_dev *xdna)
-{
- if (xdna->domain) {
- iommu_detach_group(xdna->domain, xdna->group);
- put_iova_domain(&xdna->iovad);
- iova_cache_put();
- iommu_domain_free(xdna->domain);
- }
-
- if (xdna->group)
- iommu_group_put(xdna->group);
-}
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index 65489bb3f2b0..e94d8290a807 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -138,9 +138,11 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
xdna->dev_info->dev_heap_max_size);
mutex_init(&client->mm_lock);
+ mutex_lock(&xdna->client_lock);
mutex_lock(&xdna->dev_lock);
list_add_tail(&client->node, &xdna->client_list);
mutex_unlock(&xdna->dev_lock);
+ mutex_unlock(&xdna->client_lock);
filp->driver_priv = client;
client->filp = filp;
@@ -174,18 +176,14 @@ static void amdxdna_drm_close(struct drm_device *ddev, struct drm_file *filp)
{
struct amdxdna_client *client = filp->driver_priv;
struct amdxdna_dev *xdna = to_xdna_dev(ddev);
- int idx;
XDNA_DBG(xdna, "closing pid %d", client->pid);
- if (!drm_dev_enter(&xdna->ddev, &idx))
- return;
-
+ mutex_lock(&xdna->client_lock);
mutex_lock(&xdna->dev_lock);
amdxdna_client_cleanup(client);
mutex_unlock(&xdna->dev_lock);
-
- drm_dev_exit(idx);
+ mutex_unlock(&xdna->client_lock);
}
static int amdxdna_drm_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
@@ -371,6 +369,10 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!xdna->dev_info)
return -ENODEV;
+ ret = drmm_mutex_init(ddev, &xdna->client_lock);
+ if (ret)
+ return ret;
+
drmm_mutex_init(ddev, &xdna->dev_lock);
init_rwsem(&xdna->notifier_lock);
INIT_LIST_HEAD(&xdna->client_list);
@@ -390,9 +392,9 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
return ret;
- xdna->notifier_wq = alloc_ordered_workqueue("notifier_wq", WQ_MEM_RECLAIM);
- if (!xdna->notifier_wq) {
- ret = -ENOMEM;
+ xdna->notifier_wq = drmm_alloc_ordered_workqueue(ddev, "notifier_wq", WQ_MEM_RECLAIM);
+ if (IS_ERR(xdna->notifier_wq)) {
+ ret = PTR_ERR(xdna->notifier_wq);
goto iommu_fini;
}
@@ -401,7 +403,7 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_unlock(&xdna->dev_lock);
if (ret) {
XDNA_ERR(xdna, "Hardware init failed, ret %d", ret);
- goto destroy_notifier_wq;
+ goto iommu_fini;
}
ret = amdxdna_sysfs_init(xdna);
@@ -425,8 +427,6 @@ failed_dev_fini:
mutex_lock(&xdna->dev_lock);
xdna->dev_info->ops->fini(xdna);
mutex_unlock(&xdna->dev_lock);
-destroy_notifier_wq:
- destroy_workqueue(xdna->notifier_wq);
iommu_fini:
amdxdna_iommu_fini(xdna);
return ret;
@@ -437,23 +437,19 @@ static void amdxdna_remove(struct pci_dev *pdev)
struct amdxdna_dev *xdna = pci_get_drvdata(pdev);
struct amdxdna_client *client;
- destroy_workqueue(xdna->notifier_wq);
-
drm_dev_unplug(&xdna->ddev);
amdxdna_sysfs_fini(xdna);
+ mutex_lock(&xdna->client_lock);
mutex_lock(&xdna->dev_lock);
- client = list_first_entry_or_null(&xdna->client_list,
- struct amdxdna_client, node);
- while (client) {
- amdxdna_client_cleanup(client);
-
- client = list_first_entry_or_null(&xdna->client_list,
- struct amdxdna_client, node);
+ list_for_each_entry(client, &xdna->client_list, node) {
+ amdxdna_hwctx_remove_all(client);
+ amdxdna_sva_fini(client);
}
xdna->dev_info->ops->fini(xdna);
mutex_unlock(&xdna->dev_lock);
+ mutex_unlock(&xdna->client_lock);
amdxdna_iommu_fini(xdna);
}
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.h b/drivers/accel/amdxdna/amdxdna_pci_drv.h
index 34271c14d359..a997d27a504d 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.h
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.h
@@ -120,6 +120,7 @@ struct amdxdna_dev {
struct mutex dev_lock; /* per device lock */
struct list_head client_list;
+ struct mutex client_lock; /* client_list */
struct amdxdna_fw_ver fw_ver;
struct rw_semaphore notifier_lock; /* for mmu notifier*/
struct workqueue_struct *notifier_wq;