Skip to content

Commit

Permalink
drm/virtio: Ensure framebuffers for dGPU residing in local memory
Browse files Browse the repository at this point in the history
Leverage shared field in dmabuf attachment to obtained information about
the imported buffers. In atomic check, we must return an error when the
user space is trying to present a framebuffer in system memory on dGPU
backing display.

Tracked-On: OAM-129610
Signed-off-by: Weifeng Liu <weifeng.liu@intel.com>
  • Loading branch information
phreer committed Feb 19, 2025
1 parent b1bd502 commit f005c23
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
6 changes: 5 additions & 1 deletion drivers/gpu/drm/virtio/virtgpu_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
#include <linux/moduleparam.h>

Expand Down Expand Up @@ -114,8 +115,11 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
kfree(vram);
}

if (bo->prime)
if (bo->prime) {
kfree(bo->ents);
if (bo->base.base.import_attach->shared)
kfree(bo->base.base.import_attach->shared);
}

virtio_gpu_object_del_restore_list(vgdev, bo);
}
Expand Down
39 changes: 39 additions & 0 deletions drivers/gpu/drm/virtio/virtgpu_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <linux/dma-buf.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
Expand Down Expand Up @@ -244,6 +246,7 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
plane);
struct drm_device *dev = plane->dev;
struct virtio_gpu_device *vgdev = dev->dev_private;
struct virtio_gpu_dmabuf_attach_shared *shared = NULL;
bool is_cursor = 1;
struct virtio_gpu_output *output = NULL;
output = drm_crtc_to_virtio_gpu_output(new_plane_state->crtc);
Expand All @@ -264,6 +267,42 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);

/* Ensure lmem objects from i915_ag are attached to dGPU backing CRTC */
if (vgdev->output_cap_mask & (1lu << drm_crtc_index(new_plane_state->crtc))) {
for (int i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) {
struct drm_gem_object *obj = new_plane_state->fb->obj[i];
if (!obj)
break;

if (!obj->import_attach)
return -EINVAL;

if (obj->import_attach->dmabuf->exporter_type_id
!= DMA_BUF_DRIVER_TYPE_ID_I915_BACKPORTS) {
drm_dbg(vgdev->ddev, "cannot use non-i915_ag "
"buffer for crtc %u, driver name %s\n",
drm_crtc_index(new_plane_state->crtc),
obj->dev->driver->name);
return -EINVAL;
}

shared = obj->import_attach->shared;
if (!shared) {
drm_dbg(vgdev->ddev, "unsupported i915_ag dmabuf attachment\n");
return -EINVAL;
}
if (shared->version != VIRTIO_GPU_DMABUF_ATTACH_SHARED_CURRENT_VERSION) {
drm_dbg(vgdev->ddev, "unsupported i915_ag dmabuf attachment "
"version %u\n", shared->version);
return -EINVAL;
}
if (!(shared->shared.v1.flags & VIRTIO_GPU_DMABUF_ATTACH_SHARED_FLAG_LMEM)) {
drm_dbg(vgdev->ddev, "not local memory from i915_ag\n");
return -EINVAL;
}
}
}

if(vgdev->has_scaling && (new_plane_state->fb->format->format != DRM_FORMAT_C8)) {
min_scale = 1;
max_scale = 0x30000-1;
Expand Down
22 changes: 18 additions & 4 deletions drivers/gpu/drm/virtio/virtgpu_prime.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev,
struct sg_table *sgt;
struct device *attach_dev = dev->dev;
struct virtio_gpu_device *vgdev = dev->dev_private;
struct virtio_gpu_dmabuf_attach_shared *shared = NULL;
int ret;
bool p2p = false;

Expand Down Expand Up @@ -180,10 +181,19 @@ struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev,
}
spin_unlock(&dma_buf->name_lock);

attach = ____dma_buf_dynamic_attach(dma_buf, attach_dev, NULL, NULL,
p2p);
if (IS_ERR(attach))
return ERR_CAST(attach);
if (dma_buf->exporter_type_id == DMA_BUF_DRIVER_TYPE_ID_I915_BACKPORTS) {
shared = kmalloc(sizeof(*shared), GFP_KERNEL);
if (!shared)
return ERR_PTR(-ENOMEM);
}

attach = ____dma_buf_dynamic_attach(dma_buf, attach_dev,
DMA_BUF_DRIVER_TYPE_ID_VIRTIO_GPU,
shared, NULL, NULL, p2p);
if (IS_ERR(attach)) {
ret = PTR_ERR(attach);
goto fail_shared;
}

get_dma_buf(dma_buf);

Expand All @@ -210,6 +220,10 @@ struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev,
dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);

fail_shared:
if (shared)
kfree(shared);

return ERR_PTR(ret);
}

Expand Down

0 comments on commit f005c23

Please sign in to comment.