This patchset add the necessary infrastructure needed later for CRC support.
1. add functions to map buffers to kernel address space. 2. map/unmap buffers in the prepare/cleanup_fb hooks. 3. clip plane coordinates. 4. subclass CRTC state.
changes in v4: - drop patch 5 "drm/vkms: Implement CRC debugfs API" from this patchset since it needs further work.
Haneen Mohammed (4): drm/vkms: Add functions to map/unmap GEM backing storage drm/vkms: map/unmap buffers in [prepare/cleanup]_fb hooks drm/vkms: Add atomic_helper_check_plane_state drm/vkms: subclass CRTC state
drivers/gpu/drm/vkms/vkms_crtc.c | 53 +++++++++++++++++++-- drivers/gpu/drm/vkms/vkms_drv.h | 20 ++++++++ drivers/gpu/drm/vkms/vkms_gem.c | 79 ++++++++++++++++++++++++++++++- drivers/gpu/drm/vkms/vkms_plane.c | 63 ++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 4 deletions(-)
This patch add the necessary functions to map/unmap GEM backing memory to the kernel's virtual address space.
Signed-off-by: Haneen Mohammed hamohammed.sa@gmail.com --- Changes in v2: - add vkms_gem_vunmap - use vmap_count to guard against multiple prepare_fb calls on the same fb Changes in v3: - change vkms_gem_vmap to retrun int - cleanup if vmap failed - increment vmap_count after successful vmap Changes in v4: - add err_vmap label - use out label instead of fail and remove 2 redundant lines
drivers/gpu/drm/vkms/vkms_drv.h | 9 ++++ drivers/gpu/drm/vkms/vkms_gem.c | 79 ++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 07be29f2dc44..47048f707566 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -39,6 +39,8 @@ struct vkms_gem_object { struct drm_gem_object gem; struct mutex pages_lock; /* Page lock used in page fault handler */ struct page **pages; + unsigned int vmap_count; + void *vaddr; };
#define drm_crtc_to_vkms_output(target) \ @@ -47,6 +49,9 @@ struct vkms_gem_object { #define drm_device_to_vkms_device(target) \ container_of(target, struct vkms_device, drm)
+#define drm_gem_to_vkms_gem(target)\ + container_of(target, struct vkms_gem_object, gem) + /* CRTC */ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor); @@ -75,4 +80,8 @@ int vkms_dumb_map(struct drm_file *file, struct drm_device *dev,
void vkms_gem_free_object(struct drm_gem_object *obj);
+int vkms_gem_vmap(struct drm_gem_object *obj); + +void vkms_gem_vunmap(struct drm_gem_object *obj); + #endif /* _VKMS_DRV_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c index c7e38368602b..a52e88338c05 100644 --- a/drivers/gpu/drm/vkms/vkms_gem.c +++ b/drivers/gpu/drm/vkms/vkms_gem.c @@ -37,7 +37,9 @@ void vkms_gem_free_object(struct drm_gem_object *obj) struct vkms_gem_object *gem = container_of(obj, struct vkms_gem_object, gem);
- kvfree(gem->pages); + WARN_ON(gem->pages); + WARN_ON(gem->vaddr); + mutex_destroy(&gem->pages_lock); drm_gem_object_release(obj); kfree(gem); @@ -177,3 +179,78 @@ int vkms_dumb_map(struct drm_file *file, struct drm_device *dev,
return ret; } + +static struct page **_get_pages(struct vkms_gem_object *vkms_obj) +{ + struct drm_gem_object *gem_obj = &vkms_obj->gem; + + if (!vkms_obj->pages) { + struct page **pages = drm_gem_get_pages(gem_obj); + + if (IS_ERR(pages)) + return pages; + + if (cmpxchg(&vkms_obj->pages, NULL, pages)) + drm_gem_put_pages(gem_obj, pages, false, true); + } + + return vkms_obj->pages; +} + +void vkms_gem_vunmap(struct drm_gem_object *obj) +{ + struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(obj); + + mutex_lock(&vkms_obj->pages_lock); + if (vkms_obj->vmap_count < 1) { + WARN_ON(vkms_obj->vaddr); + WARN_ON(vkms_obj->pages); + mutex_unlock(&vkms_obj->pages_lock); + return; + } + + vkms_obj->vmap_count--; + + if (vkms_obj->vmap_count == 0) { + vunmap(vkms_obj->vaddr); + vkms_obj->vaddr = NULL; + drm_gem_put_pages(obj, vkms_obj->pages, false, true); + vkms_obj->pages = NULL; + } + + mutex_unlock(&vkms_obj->pages_lock); +} + +int vkms_gem_vmap(struct drm_gem_object *obj) +{ + struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(obj); + int ret = 0; + + mutex_lock(&vkms_obj->pages_lock); + + if (!vkms_obj->vaddr) { + unsigned int n_pages = obj->size >> PAGE_SHIFT; + struct page **pages = _get_pages(vkms_obj); + + if (IS_ERR(pages)) { + ret = PTR_ERR(pages); + goto out; + } + + vkms_obj->vaddr = vmap(pages, n_pages, VM_MAP, PAGE_KERNEL); + if (!vkms_obj->vaddr) + goto err_vmap; + + vkms_obj->vmap_count++; + } + + goto out; + +err_vmap: + ret = -ENOMEM; + drm_gem_put_pages(obj, vkms_obj->pages, false, true); + vkms_obj->pages = NULL; +out: + mutex_unlock(&vkms_obj->pages_lock); + return ret; +}
This patch map/unmap GEM backing memory to kernel address space in prepare/cleanup_fb respectively and cache the virtual address for later use.
Signed-off-by: Haneen Mohammed hamohammed.sa@gmail.com --- Changes in v2: - use vkms_gem_vunmap Changes in v3: - return error number instead of vkms_obj->vaddr Changes in v4: - print return value from vkms_gem_vmap
drivers/gpu/drm/vkms/vkms_plane.c | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 9f75b1e2c1c4..5611e7cf5fc9 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -9,6 +9,7 @@ #include "vkms_drv.h" #include <drm/drm_plane_helper.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_gem_framebuffer_helper.h>
static const struct drm_plane_funcs vkms_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, @@ -24,8 +25,41 @@ static void vkms_primary_plane_update(struct drm_plane *plane, { }
+static int vkms_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_gem_object *gem_obj; + struct vkms_gem_object *vkms_obj; + int ret; + + if (!state->fb) + return 0; + + gem_obj = drm_gem_fb_get_obj(state->fb, 0); + vkms_obj = drm_gem_to_vkms_gem(gem_obj); + ret = vkms_gem_vmap(gem_obj); + if (ret) + DRM_ERROR("vmap failed: %d\n", ret); + + return drm_gem_fb_prepare_fb(plane, state); +} + +static void vkms_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_gem_object *gem_obj; + + if (!old_state->fb) + return; + + gem_obj = drm_gem_fb_get_obj(old_state->fb, 0); + vkms_gem_vunmap(gem_obj); +} + static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = { .atomic_update = vkms_primary_plane_update, + .prepare_fb = vkms_prepare_fb, + .cleanup_fb = vkms_cleanup_fb, };
struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev)
Call atomic_helper_check_plane_state to clip plane coordinates.
Signed-off-by: Haneen Mohammed hamohammed.sa@gmail.com Reviewed-by: Sean Paul seanpaul@chromium.org --- Changes in v2: - check for plane_state->visible since we can't handle a disabled primary plane yet.
drivers/gpu/drm/vkms/vkms_plane.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 5611e7cf5fc9..8191940844e5 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -8,6 +8,7 @@
#include "vkms_drv.h" #include <drm/drm_plane_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
@@ -25,6 +26,33 @@ static void vkms_primary_plane_update(struct drm_plane *plane, { }
+static int vkms_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_crtc_state *crtc_state; + int ret; + + if (!state->fb | !state->crtc) + return 0; + + crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + ret = drm_atomic_helper_check_plane_state(state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); + if (ret != 0) + return ret; + + /* for now primary plane must be visible and full screen */ + if (!state->visible) + return -EINVAL; + + return 0; +} + static int vkms_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) { @@ -58,6 +86,7 @@ static void vkms_cleanup_fb(struct drm_plane *plane,
static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = { .atomic_update = vkms_primary_plane_update, + .atomic_check = vkms_plane_atomic_check, .prepare_fb = vkms_prepare_fb, .cleanup_fb = vkms_cleanup_fb, };
Subclass CRTC state struct to enable storing driver's private state. This patch only adds the base drm_crtc_state struct and the atomic functions that handle it.
Signed-off-by: Haneen Mohammed hamohammed.sa@gmail.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Reviewed-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/vkms/vkms_crtc.c | 53 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/vkms/vkms_drv.h | 11 +++++++ 2 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 875fca662ac0..26babb85ca77 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -64,13 +64,60 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, return true; }
+static void vkms_atomic_crtc_reset(struct drm_crtc *crtc) +{ + struct vkms_crtc_state *vkms_state = NULL; + + if (crtc->state) { + vkms_state = to_vkms_crtc_state(crtc->state); + __drm_atomic_helper_crtc_destroy_state(crtc->state); + kfree(vkms_state); + crtc->state = NULL; + } + + vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL); + if (!vkms_state) + return; + + crtc->state = &vkms_state->base; + crtc->state->crtc = crtc; +} + +static struct drm_crtc_state * +vkms_atomic_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct vkms_crtc_state *vkms_state; + + if (WARN_ON(!crtc->state)) + return NULL; + + vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL); + if (!vkms_state) + return NULL; + + __drm_atomic_helper_crtc_duplicate_state(crtc, &vkms_state->base); + + return &vkms_state->base; +} + +static void vkms_atomic_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct vkms_crtc_state *vkms_state; + + vkms_state = to_vkms_crtc_state(state); + + __drm_atomic_helper_crtc_destroy_state(state); + kfree(vkms_state); +} + static const struct drm_crtc_funcs vkms_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = drm_crtc_cleanup, .page_flip = drm_atomic_helper_page_flip, - .reset = drm_atomic_helper_crtc_reset, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .reset = vkms_atomic_crtc_reset, + .atomic_duplicate_state = vkms_atomic_crtc_duplicate_state, + .atomic_destroy_state = vkms_atomic_crtc_destroy_state, .enable_vblank = vkms_enable_vblank, .disable_vblank = vkms_disable_vblank, }; diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 47048f707566..75e52d61e65d 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -20,6 +20,14 @@ static const u32 vkms_formats[] = { DRM_FORMAT_XRGB8888, };
+/** + * vkms_crtc_state - Driver specific CRTC state + * @base: base CRTC state + */ +struct vkms_crtc_state { + struct drm_crtc_state base; +}; + struct vkms_output { struct drm_crtc crtc; struct drm_encoder encoder; @@ -52,6 +60,9 @@ struct vkms_gem_object { #define drm_gem_to_vkms_gem(target)\ container_of(target, struct vkms_gem_object, gem)
+#define to_vkms_crtc_state(target)\ + container_of(target, struct vkms_crtc_state, base) + /* CRTC */ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor);
On Tue, Jul 24, 2018 at 07:25:38PM +0300, Haneen Mohammed wrote:
This patchset add the necessary infrastructure needed later for CRC support.
- add functions to map buffers to kernel address space.
- map/unmap buffers in the prepare/cleanup_fb hooks.
- clip plane coordinates.
- subclass CRTC state.
Applied the set to drm-misc-next
Thanks!
Sean
changes in v4:
- drop patch 5 "drm/vkms: Implement CRC debugfs API" from this patchset
since it needs further work.
Haneen Mohammed (4): drm/vkms: Add functions to map/unmap GEM backing storage drm/vkms: map/unmap buffers in [prepare/cleanup]_fb hooks drm/vkms: Add atomic_helper_check_plane_state drm/vkms: subclass CRTC state
drivers/gpu/drm/vkms/vkms_crtc.c | 53 +++++++++++++++++++-- drivers/gpu/drm/vkms/vkms_drv.h | 20 ++++++++ drivers/gpu/drm/vkms/vkms_gem.c | 79 ++++++++++++++++++++++++++++++- drivers/gpu/drm/vkms/vkms_plane.c | 63 ++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 4 deletions(-)
-- 2.17.1
dri-devel@lists.freedesktop.org