diff options
author | Gabriel Krisman Bertazi <krisman@collabora.co.uk> | 2017-02-27 17:43:16 -0300 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2017-02-28 17:26:08 +0100 |
commit | 715a11fabbe6aa01daefc7bef34a08f4933237ce (patch) | |
tree | 339d67c1dc7aa4ad326bc67519314748482619f9 /drivers/gpu/drm/qxl/qxl_object.c | |
parent | aa5b62bac05d4b2bf7e5b3a006fa87625ee7beec (diff) | |
download | linux-715a11fabbe6aa01daefc7bef34a08f4933237ce.tar.gz |
drm: qxl: Consolidate bo reservation when pinning
Every attempt to pin/unpin objects in memory requires
qxl_bo_reserve/unreserve calls around the pinning operation to protect
the object from concurrent access, which causes that call sequence to be
reproduced every place where pinning is needed. In some cases, that
sequence was not executed correctly, resulting in potential unprotected
pinning operations.
This commit encapsulates the reservation inside a new wrapper to make
sure it is always handled properly. In cases where reservation must be
done beforehand, for some reason, one can use the unprotected version
__qxl_bo_pin/unpin.
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170227204328.18761-3-krisman@collabora.co.uk
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/qxl/qxl_object.c')
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_object.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index dbc13510a1f8..9a7eef7dd604 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -221,7 +221,7 @@ struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo) return bo; } -int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) +int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) { struct drm_device *ddev = bo->gem_base.dev; int r; @@ -244,7 +244,7 @@ int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) return r; } -int qxl_bo_unpin(struct qxl_bo *bo) +int __qxl_bo_unpin(struct qxl_bo *bo) { struct drm_device *ddev = bo->gem_base.dev; int r, i; @@ -264,6 +264,43 @@ int qxl_bo_unpin(struct qxl_bo *bo) return r; } + +/* + * Reserve the BO before pinning the object. If the BO was reserved + * beforehand, use the internal version directly __qxl_bo_pin. + * + */ +int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) +{ + int r; + + r = qxl_bo_reserve(bo, false); + if (r) + return r; + + r = __qxl_bo_pin(bo, bo->type, NULL); + qxl_bo_unreserve(bo); + return r; +} + +/* + * Reserve the BO before pinning the object. If the BO was reserved + * beforehand, use the internal version directly __qxl_bo_unpin. + * + */ +int qxl_bo_unpin(struct qxl_bo *bo) +{ + int r; + + r = qxl_bo_reserve(bo, false); + if (r) + return r; + + r = __qxl_bo_unpin(bo); + qxl_bo_unreserve(bo); + return r; +} + void qxl_bo_force_delete(struct qxl_device *qdev) { struct qxl_bo *bo, *n; |