summaryrefslogtreecommitdiff
path: root/drivers/accel
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2026-06-30 10:16:00 +0200
committerThomas Zimmermann <tzimmermann@suse.de>2026-06-30 10:16:00 +0200
commit827b9aabd3ea3e96d5e48abed9f44dbd1e550d4e (patch)
tree845a97a83f20fe0585840a66d9eed8fcf1286772 /drivers/accel
parent3b3bce4a692ac60d9f4a341e6b597dd1fd0a28f9 (diff)
parentdc59e4fea9d83f03bad6bddf3fa2e52491777482 (diff)
downloadlinux-next-827b9aabd3ea3e96d5e48abed9f44dbd1e550d4e.tar.gz
linux-next-827b9aabd3ea3e96d5e48abed9f44dbd1e550d4e.zip
Merge drm/drm-next into drm-misc-next
Backmerging to get drm-misc-next to v7.2-rc1. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Diffstat (limited to 'drivers/accel')
-rw-r--r--drivers/accel/amdxdna/aie2_ctx.c19
-rw-r--r--drivers/accel/amdxdna/aie2_pci.c5
-rw-r--r--drivers/accel/amdxdna/amdxdna_gem.c7
-rw-r--r--drivers/accel/amdxdna/amdxdna_pci_drv.c9
-rw-r--r--drivers/accel/ethosu/ethosu_gem.c35
-rw-r--r--drivers/accel/ivpu/ivpu_debugfs.c2
-rw-r--r--drivers/accel/ivpu/ivpu_fw.c16
-rw-r--r--drivers/accel/ivpu/ivpu_fw_log.c5
-rw-r--r--drivers/accel/ivpu/ivpu_ipc.c2
-rw-r--r--drivers/accel/ivpu/ivpu_job.c10
-rw-r--r--drivers/accel/ivpu/ivpu_ms.c7
-rw-r--r--drivers/accel/rocket/rocket_gem.c17
12 files changed, 101 insertions, 33 deletions
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index 658a5fb1fda6..e9fbd8c14364 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -305,17 +305,13 @@ aie2_sched_drvcmd_resp_handler(void *handle, void __iomem *data, size_t size)
struct amdxdna_sched_job *job = handle;
int ret = 0;
- if (unlikely(!data))
- goto out;
-
- if (unlikely(size != sizeof(u32))) {
+ if (unlikely(!data || size != sizeof(u32))) {
+ job->drv_cmd->result = U32_MAX;
ret = -EINVAL;
- goto out;
+ } else {
+ job->drv_cmd->result = readl(data);
}
- job->drv_cmd->result = readl(data);
-
-out:
aie2_sched_notify(job);
return ret;
}
@@ -437,8 +433,9 @@ static void aie2_sched_job_free(struct drm_sched_job *sched_job)
struct amdxdna_sched_job *job = drm_job_to_xdna_job(sched_job);
struct amdxdna_hwctx *hwctx = job->hwctx;
+ /* job->drv_cmd could be freed, so use DEFAULT_IO */
trace_xdna_job(sched_job, hwctx->name, "job free",
- job->seq, job->drv_cmd ? job->drv_cmd->opcode : DEFAULT_IO);
+ job->seq, DEFAULT_IO);
if (!job->job_done)
up(&hwctx->priv->job_sem);
@@ -939,6 +936,7 @@ static int aie2_hwctx_cfg_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl,
aie2_cmd_wait(hwctx, seq);
if (cmd.result) {
XDNA_ERR(xdna, "Response failure 0x%x", cmd.result);
+ ret = -EINVAL;
goto put_obj;
}
@@ -1045,6 +1043,7 @@ again:
if (ret == -EBUSY) {
amdxdna_umap_put(mapp);
+ mmput(mm);
goto again;
}
@@ -1055,11 +1054,13 @@ again:
if (mmu_interval_read_retry(&mapp->notifier, mapp->range.notifier_seq)) {
up_write(&xdna->notifier_lock);
amdxdna_umap_put(mapp);
+ mmput(mm);
goto again;
}
mapp->invalid = false;
up_write(&xdna->notifier_lock);
amdxdna_umap_put(mapp);
+ mmput(mm);
goto again;
put_mm:
diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c
index c4d345d4c76b..22f66c7f534d 100644
--- a/drivers/accel/amdxdna/aie2_pci.c
+++ b/drivers/accel/amdxdna/aie2_pci.c
@@ -490,6 +490,11 @@ static int aie2_init(struct amdxdna_dev *xdna)
return -EINVAL;
}
+ if (!xdna->group) {
+ XDNA_ERR(xdna, "Running without IOMMU not supported");
+ return -EINVAL;
+ }
+
ndev = drmm_kzalloc(&xdna->ddev, sizeof(*ndev), GFP_KERNEL);
if (!ndev)
return -ENOMEM;
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index 77e5fad08ae5..1f190b319bb6 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -349,8 +349,11 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
u32 nr_pages;
int ret;
- if (!amdxdna_pasid_on(abo->client))
+ if (!amdxdna_pasid_on(abo->client)) {
+ /* Need to set uva for heap uva validation */
+ abo->mem.uva = addr;
return 0;
+ }
mapp = kzalloc_obj(*mapp);
if (!mapp)
@@ -1303,7 +1306,7 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
args->handle, args->offset, args->size);
if (args->direction == SYNC_DIRECT_FROM_DEVICE)
- ret = amdxdna_hwctx_sync_debug_bo(abo->client, args->handle);
+ ret = amdxdna_hwctx_sync_debug_bo(client, args->handle);
put_obj:
drm_gem_object_put(gobj);
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index c677293c1ae7..65489bb3f2b0 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -87,6 +87,7 @@ static int amdxdna_sva_init(struct amdxdna_client *client)
client->pasid = iommu_sva_get_pasid(client->sva);
if (client->pasid == IOMMU_PASID_INVALID) {
iommu_sva_unbind_device(client->sva);
+ client->sva = NULL;
XDNA_ERR(xdna, "SVA get pasid failed");
return -ENODEV;
}
@@ -120,8 +121,14 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
if (!amdxdna_iova_on(xdna)) {
/* No need to fail open since user may use pa + carveout later. */
- if (amdxdna_sva_init(client))
+ if (amdxdna_sva_init(client)) {
XDNA_WARN(xdna, "PASID not available for pid %d", client->pid);
+ if (!amdxdna_use_carveout(xdna)) {
+ XDNA_ERR(xdna, "PASID unavailable and carveout not configured");
+ kfree(client);
+ return -EINVAL;
+ }
+ }
}
mmgrab(client->mm);
init_srcu_struct(&client->hwctx_srcu);
diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c
index 7994e7073903..3401883e207f 100644
--- a/drivers/accel/ethosu/ethosu_gem.c
+++ b/drivers/accel/ethosu/ethosu_gem.c
@@ -2,6 +2,7 @@
/* Copyright 2025 Arm, Ltd. */
#include <linux/err.h>
+#include <linux/overflow.h>
#include <linux/slab.h>
#include <drm/ethosu_accel.h>
@@ -163,17 +164,30 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
s8 mode = dma_st->mode;
u64 len = dma->len;
+ if (len == U64_MAX)
+ return U64_MAX;
+
if (mode >= 1) {
+ if (dma->stride[0] < 0 && (u64)(-dma->stride[0]) > len)
+ return U64_MAX;
len += dma->stride[0];
- len *= dma_st->size0;
+ if (check_mul_overflow(len, (u64)dma_st->size0, &len))
+ return U64_MAX;
}
if (mode == 2) {
+ if (dma->stride[1] < 0 && (u64)(-dma->stride[1]) > len)
+ return U64_MAX;
len += dma->stride[1];
- len *= dma_st->size1;
+ if (check_mul_overflow(len, (u64)dma_st->size1, &len))
+ return U64_MAX;
+ }
+ if (dma->region >= 0) {
+ u64 end;
+
+ if (check_add_overflow(len, dma->offset, &end))
+ return U64_MAX;
+ info->region_size[dma->region] = max(info->region_size[dma->region], end);
}
- if (dma->region >= 0)
- info->region_size[dma->region] = max(info->region_size[dma->region],
- len + dma->offset);
return len;
}
@@ -387,6 +401,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
return -EFAULT;
i++;
+ if (i >= size / 4)
+ return -EINVAL;
bocmds[i] = cmds[1];
addr = cmd_to_addr(cmds);
}
@@ -395,6 +411,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
case NPU_OP_DMA_START:
srclen = dma_length(info, &st.dma, &st.dma.src);
dstlen = dma_length(info, &st.dma, &st.dma.dst);
+ if (srclen == U64_MAX || dstlen == U64_MAX)
+ return -EINVAL;
if (st.dma.dst.region >= 0)
info->output_region[st.dma.dst.region] = true;
@@ -431,8 +449,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
return ret;
break;
case NPU_OP_RESIZE: // U85 only
- WARN_ON(1); // TODO
- break;
+ return -EINVAL;
case NPU_SET_KERNEL_WIDTH_M1:
st.ifm.width = param;
break;
@@ -464,7 +481,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
st.ifm.broadcast = param;
break;
case NPU_SET_IFM_REGION:
- st.ifm.region = param & 0x7f;
+ st.ifm.region = param & 0x7;
break;
case NPU_SET_IFM_WIDTH0_M1:
st.ifm.width0 = param;
@@ -599,7 +616,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
if (ethosu_is_u65(edev))
st.scale[1].length = cmds[1];
else
- st.weight[1].length = cmds[1];
+ st.weight[2].length = cmds[1];
break;
case NPU_SET_WEIGHT3_BASE:
st.weight[3].base = addr;
diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c
index 189dbe94cf14..dc20bc73c6ed 100644
--- a/drivers/accel/ivpu/ivpu_debugfs.c
+++ b/drivers/accel/ivpu/ivpu_debugfs.c
@@ -450,7 +450,7 @@ priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t
u32 band;
int ret;
- if (size >= sizeof(buf))
+ if (*pos != 0 || size >= sizeof(buf))
return -EINVAL;
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, pos, user_buf, size);
diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c
index 7db199e04f7c..5a8f7dfb54e6 100644
--- a/drivers/accel/ivpu/ivpu_fw.c
+++ b/drivers/accel/ivpu/ivpu_fw.c
@@ -259,6 +259,22 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
return -EINVAL;
}
+ if (!PAGE_ALIGNED(runtime_addr)) {
+ ivpu_err(vdev, "Runtime address 0x%llx not page aligned\n", runtime_addr);
+ return -EINVAL;
+ }
+
+ if (!PAGE_ALIGNED(runtime_size)) {
+ ivpu_err(vdev, "Runtime size %llu not page aligned\n", runtime_size);
+ return -EINVAL;
+ }
+
+ if (runtime_size < image_size) {
+ ivpu_err(vdev, "Runtime size too small: %llu, image size: %llu\n",
+ runtime_size, image_size);
+ return -EINVAL;
+ }
+
if (!ivpu_is_within_range(image_load_addr, image_size, &vdev->hw->ranges.runtime)) {
ivpu_err(vdev, "Invalid firmware load address: 0x%llx and size %llu\n",
image_load_addr, image_size);
diff --git a/drivers/accel/ivpu/ivpu_fw_log.c b/drivers/accel/ivpu/ivpu_fw_log.c
index 337c906b0210..275baf844b56 100644
--- a/drivers/accel/ivpu/ivpu_fw_log.c
+++ b/drivers/accel/ivpu/ivpu_fw_log.c
@@ -98,6 +98,11 @@ static void fw_log_print_buffer(struct vpu_tracing_buffer_header *log, const cha
u32 log_start = only_new_msgs ? READ_ONCE(log->read_index) : 0;
u32 log_end = READ_ONCE(log->write_index);
+ if (log_start >= data_size)
+ log_start = 0;
+ if (log_end > data_size)
+ log_end = data_size;
+
if (log->wrap_count == log->read_wrap_count) {
if (log_end <= log_start) {
drm_printf(p, "==== %s \"%s\" log empty ====\n", prefix, log->name);
diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c
index c5f11be86c8c..62607ec8ca8f 100644
--- a/drivers/accel/ivpu/ivpu_ipc.c
+++ b/drivers/accel/ivpu/ivpu_ipc.c
@@ -280,7 +280,7 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
if (ipc_buf)
memcpy(ipc_buf, rx_msg->ipc_hdr, sizeof(*ipc_buf));
if (rx_msg->jsm_msg) {
- u32 size = min_t(int, rx_msg->ipc_hdr->data_size, sizeof(*jsm_msg));
+ u32 size = min(rx_msg->ipc_hdr->data_size, sizeof(*jsm_msg));
if (rx_msg->jsm_msg->result != VPU_JSM_STATUS_SUCCESS) {
ivpu_err(vdev, "IPC resp result error: %d\n", rx_msg->jsm_msg->result);
diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c
index 7320c9776283..ebb2c865b09a 100644
--- a/drivers/accel/ivpu/ivpu_job.c
+++ b/drivers/accel/ivpu/ivpu_job.c
@@ -208,9 +208,9 @@ static int ivpu_hws_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq
ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->id,
priority);
if (ret)
- return ret;
+ ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id);
- return 0;
+ return ret;
}
static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
@@ -281,10 +281,10 @@ static int ivpu_cmdq_register(struct ivpu_file_priv *file_priv, struct ivpu_cmdq
}
ret = ivpu_register_db(file_priv, cmdq);
- if (ret)
- return ret;
+ if (ret && vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW)
+ ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id);
- return 0;
+ return ret;
}
static int ivpu_cmdq_unregister(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c
index be43851f5f32..cd176e77b9a0 100644
--- a/drivers/accel/ivpu/ivpu_ms.c
+++ b/drivers/accel/ivpu/ivpu_ms.c
@@ -291,6 +291,13 @@ int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *
if (ret)
goto unlock;
+ if (info_size > ivpu_bo_size(bo)) {
+ ivpu_warn_ratelimited(vdev, "MS info overflow: %#llx > %#zx\n",
+ info_size, ivpu_bo_size(bo));
+ ret = -EOVERFLOW;
+ goto unlock;
+ }
+
if (args->buffer_size < info_size) {
ret = -ENOSPC;
goto unlock;
diff --git a/drivers/accel/rocket/rocket_gem.c b/drivers/accel/rocket/rocket_gem.c
index c8084719208a..a5fffa51ff35 100644
--- a/drivers/accel/rocket/rocket_gem.c
+++ b/drivers/accel/rocket/rocket_gem.c
@@ -79,11 +79,6 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
rkt_obj->size = args->size;
rkt_obj->offset = 0;
- ret = drm_gem_handle_create(file, gem_obj, &args->handle);
- drm_gem_object_put(gem_obj);
- if (ret)
- goto err;
-
sgt = drm_gem_shmem_get_pages_sgt(shmem_obj);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
@@ -95,6 +90,8 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
rkt_obj->size, PAGE_SIZE,
0, 0);
mutex_unlock(&rocket_priv->mm_lock);
+ if (ret)
+ goto err;
ret = iommu_map_sgtable(rocket_priv->domain->domain,
rkt_obj->mm.start,
@@ -112,8 +109,18 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
args->dma_address = rkt_obj->mm.start;
+ ret = drm_gem_handle_create(file, gem_obj, &args->handle);
+ if (ret)
+ goto err_unmap;
+
+ drm_gem_object_put(gem_obj);
+
return 0;
+err_unmap:
+ iommu_unmap(rocket_priv->domain->domain,
+ rkt_obj->mm.start, rkt_obj->size);
+
err_remove_node:
mutex_lock(&rocket_priv->mm_lock);
drm_mm_remove_node(&rkt_obj->mm);