summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-08-20 13:06:30 +0100
committerMark Brown <broonie@kernel.org>2026-08-20 13:06:30 +0100
commite81baba2a45004b00219bf9da5828c2b814e97ed (patch)
treea474ed0c095034e088a99ba2728581ee41168694
parent7bf34f54b914e110c10edba3d3289b617adde5cc (diff)
parentdc14753664240cedf669623b27ae9922b0618b25 (diff)
downloadlinux-next-pending-fixes.tar.gz
linux-next-pending-fixes.zip
Merge branch 'for-linux-next-fixes' of https://gitlab.freedesktop.org/drm/misc/kernel.gitpending-fixes
-rw-r--r--drivers/accel/amdxdna/amdxdna_gem.c3
-rw-r--r--drivers/accel/qaic/qaic_control.c46
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c9
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h21
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_object.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c21
7 files changed, 74 insertions, 29 deletions
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index 1c63eff0a4a8..2a16de96e6a4 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -1247,6 +1247,9 @@ static int amdxdna_flush_bo(struct amdxdna_gem_obj *abo, u64 offset, u64 size)
return -EINVAL;
size = min(abo->mem.size, end) - offset;
+ if (!size)
+ return 0;
+
if (is_import_bo(abo))
drm_clflush_sg(abo->base.sgt);
else if (amdxdna_gem_vmap(abo))
diff --git a/drivers/accel/qaic/qaic_control.c b/drivers/accel/qaic/qaic_control.c
index 50bf3340e49c..2ccc55486aac 100644
--- a/drivers/accel/qaic/qaic_control.c
+++ b/drivers/accel/qaic/qaic_control.c
@@ -963,11 +963,13 @@ static int decode_status(struct qaic_device *qdev, void *trans, struct manage_ms
static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
struct wire_msg *msg, struct ioctl_resources *resources,
- struct qaic_user *usr)
+ struct qaic_user *usr, bool orphaned_deactivate)
{
+ u32 msg_hdr_count = le32_to_cpu(msg->hdr.count);
u32 msg_hdr_len = le32_to_cpu(msg->hdr.len);
struct wire_trans_hdr *trans_hdr;
u32 msg_len = 0;
+ int trans_type;
int ret;
int i;
@@ -975,10 +977,12 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
return -EINVAL;
- user_msg->len = 0;
- user_msg->count = le32_to_cpu(msg->hdr.count);
+ if (user_msg) {
+ user_msg->len = 0;
+ user_msg->count = msg_hdr_count;
+ }
- for (i = 0; i < user_msg->count; ++i) {
+ for (i = 0; i < msg_hdr_count; ++i) {
u32 hdr_len;
if (msg_len > msg_hdr_len - sizeof(*trans_hdr))
@@ -990,7 +994,20 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
size_add(msg_len, hdr_len) > msg_hdr_len)
return -EINVAL;
- switch (le32_to_cpu(trans_hdr->type)) {
+ trans_type = le32_to_cpu(trans_hdr->type);
+ /*
+ * orphaned_deactivate is the case where a deactivate response
+ * is received from the device after the user owning the DBC,
+ * and the message requesting deactivation, has gone away.
+ * In this case, only process QAIC_TRANS_DEACTIVATE_FROM_DEV
+ * transaction and skip the others.
+ */
+ if (orphaned_deactivate && trans_type != QAIC_TRANS_DEACTIVATE_FROM_DEV) {
+ msg_len += hdr_len;
+ continue;
+ }
+
+ switch (trans_type) {
case QAIC_TRANS_PASSTHROUGH_FROM_DEV:
ret = decode_passthrough(qdev, trans_hdr, user_msg, &msg_len);
break;
@@ -1281,7 +1298,7 @@ dma_xfer_continue:
goto dma_cont_failed;
}
- ret = decode_message(qdev, user_msg, rsp, &resources, usr);
+ ret = decode_message(qdev, user_msg, rsp, &resources, usr, false);
dma_cont_failed:
free_dbc_buf(qdev, &resources);
@@ -1446,22 +1463,7 @@ static void resp_worker(struct work_struct *work)
* response to the QAIC_TRANS_TERMINATE_TO_DEV transaction,
* otherwise, the user can issue an soc_reset to the device.
*/
- u32 msg_count = le32_to_cpu(msg->hdr.count);
- u32 msg_len = le32_to_cpu(msg->hdr.len);
- u32 len = 0;
- int j;
-
- for (j = 0; j < msg_count && len < msg_len; ++j) {
- struct wire_trans_hdr *trans_hdr;
-
- trans_hdr = (struct wire_trans_hdr *)(msg->data + len);
- if (le32_to_cpu(trans_hdr->type) == QAIC_TRANS_DEACTIVATE_FROM_DEV) {
- if (decode_deactivate(qdev, trans_hdr, &len, NULL))
- len += le32_to_cpu(trans_hdr->len);
- } else {
- len += le32_to_cpu(trans_hdr->len);
- }
- }
+ decode_message(qdev, NULL, msg, NULL, NULL, true);
/* request must have timed out, drop packet */
kfree(msg);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index 44ffffec550f..a1a875a0c706 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -344,7 +344,7 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
if (ret) {
kfree(virtio_gpu_fb);
drm_gem_object_put(obj);
- return NULL;
+ return ERR_PTR(ret);
}
return &virtio_gpu_fb->base;
@@ -378,8 +378,11 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
vgdev->ddev->mode_config.fb_modifiers_not_supported = true;
- for (i = 0 ; i < vgdev->num_scanouts; ++i)
- vgdev_output_init(vgdev, i);
+ for (i = 0; i < vgdev->num_scanouts; ++i) {
+ ret = vgdev_output_init(vgdev, i);
+ if (ret)
+ return ret;
+ }
ret = drm_vblank_init(vgdev->ddev, vgdev->num_scanouts);
if (ret)
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 7449907754a4..626aadf680bd 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -43,6 +43,8 @@
#include <drm/drm_probe_helper.h>
#include <drm/virtgpu_drm.h>
+#include <xen/xen.h>
+
#define DRIVER_NAME "virtio_gpu"
#define DRIVER_DESC "virtio GPU"
@@ -60,6 +62,24 @@
/* See virtio_gpu_ctx_create. One additional character for NULL terminator. */
#define DEBUG_NAME_MAX_LEN 65
+/*
+ * Whether the host must be told about resource backing pages by DMA address
+ * rather than guest-physical address.
+ *
+ * This mirrors vring_use_map_api() in drivers/virtio/virtio_ring.c, including
+ * its xen_domain() case.
+ */
+static inline bool virtio_gpu_use_dma_api(const struct virtio_device *vdev)
+{
+ if (!virtio_has_dma_quirk(vdev))
+ return true;
+
+ if (xen_domain())
+ return true;
+
+ return false;
+}
+
struct virtio_gpu_object_params {
unsigned long size;
bool dumb;
@@ -332,6 +352,7 @@ void virtio_gpu_array_put_free_work(struct work_struct *work);
/* virtgpu_vq.c */
int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev);
void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev);
+void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev);
void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev,
struct virtio_gpu_object *bo,
struct virtio_gpu_object_params *params,
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index b4329f28e976..e5a6ae679f36 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -298,6 +298,7 @@ void virtio_gpu_deinit(struct drm_device *dev)
flush_work(&vgdev->cursorq.dequeue_work);
flush_work(&vgdev->config_changed_work);
virtio_reset_device(vgdev->vdev);
+ virtio_gpu_reclaim_vbufs(vgdev);
vgdev->vdev->config->del_vqs(vgdev->vdev);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index ec9efacc6919..1527c62be88b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -163,7 +163,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
struct virtio_gpu_mem_entry **ents,
unsigned int *nents)
{
- bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+ bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
struct scatterlist *sg;
struct sg_table *pages;
int si;
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index e5e1af8b8e8a..5e9b7b192db0 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -208,6 +208,21 @@ static void free_vbuf(struct virtio_gpu_device *vgdev,
kmem_cache_free(vgdev->vbufs, vbuf);
}
+void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev)
+{
+ struct virtio_gpu_vbuffer *vbuf;
+
+ while ((vbuf = virtqueue_detach_unused_buf(vgdev->ctrlq.vq))) {
+ if (vbuf->objs)
+ virtio_gpu_array_put_free(vbuf->objs);
+ if (vbuf->resp_cb_data)
+ virtio_gpu_cleanup_object(vbuf->resp_cb_data);
+ free_vbuf(vgdev, vbuf);
+ }
+ while ((vbuf = virtqueue_detach_unused_buf(vgdev->cursorq.vq)))
+ free_vbuf(vgdev, vbuf);
+}
+
static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list)
{
struct virtio_gpu_vbuffer *vbuf;
@@ -724,7 +739,7 @@ int virtio_gpu_panic_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
struct virtio_gpu_transfer_to_host_2d *cmd_p;
struct virtio_gpu_vbuffer *vbuf;
- bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+ bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
if (virtio_gpu_is_shmem(bo) && use_dma_api)
dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
@@ -755,7 +770,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
struct virtio_gpu_transfer_to_host_2d *cmd_p;
struct virtio_gpu_vbuffer *vbuf;
- bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+ bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
if (virtio_gpu_is_shmem(bo) && use_dma_api)
dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
@@ -1188,7 +1203,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
struct virtio_gpu_transfer_host_3d *cmd_p;
struct virtio_gpu_vbuffer *vbuf;
- bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+ bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
if (virtio_gpu_is_shmem(bo) && use_dma_api)
dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,