mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 07:01:32 +00:00
Merge branch 'vmwgfx-fixes-4.12' of git://people.freedesktop.org/~thomash/linux into drm-fixes
A bunch of fixes for vmwgfx 4.12 regressions and older stuff. In the latter case either trivial, cc'd stable or requiring backports for stable. * 'vmwgfx-fixes-4.12' of git://people.freedesktop.org/~thomash/linux: drm/vmwgfx: Bump driver minor and date drm/vmwgfx: Remove unused legacy cursor functions drm/vmwgfx: fix spelling mistake "exeeds" -> "exceeds" drm/vmwgfx: Fix large topology crash drm/vmwgfx: Make sure to update STDU when FB is updated drm/vmwgfx: Make sure backup_handle is always valid drm/vmwgfx: Handle vmalloc() failure in vmw_local_fifo_reserve() drm/vmwgfx: Don't create proxy surface for cursor drm/vmwgfx: limit the number of mip levels in vmw_gb_surface_define_ioctl()
This commit is contained in:
commit
6e88007e22
@ -41,9 +41,9 @@
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
#include "vmwgfx_fence.h"
|
||||
|
||||
#define VMWGFX_DRIVER_DATE "20170221"
|
||||
#define VMWGFX_DRIVER_DATE "20170607"
|
||||
#define VMWGFX_DRIVER_MAJOR 2
|
||||
#define VMWGFX_DRIVER_MINOR 12
|
||||
#define VMWGFX_DRIVER_MINOR 13
|
||||
#define VMWGFX_DRIVER_PATCHLEVEL 0
|
||||
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
|
||||
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
|
||||
|
@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
|
||||
return fifo_state->static_buffer;
|
||||
else {
|
||||
fifo_state->dynamic_buffer = vmalloc(bytes);
|
||||
if (!fifo_state->dynamic_buffer)
|
||||
goto out_err;
|
||||
return fifo_state->dynamic_buffer;
|
||||
}
|
||||
}
|
||||
|
@ -274,108 +274,6 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* vmw_du_cursor_plane_update() - Update cursor image and location
|
||||
*
|
||||
* @plane: plane object to update
|
||||
* @crtc: owning CRTC of @plane
|
||||
* @fb: framebuffer to flip onto plane
|
||||
* @crtc_x: x offset of plane on crtc
|
||||
* @crtc_y: y offset of plane on crtc
|
||||
* @crtc_w: width of plane rectangle on crtc
|
||||
* @crtc_h: height of plane rectangle on crtc
|
||||
* @src_x: Not used
|
||||
* @src_y: Not used
|
||||
* @src_w: Not used
|
||||
* @src_h: Not used
|
||||
*
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
int vmw_du_cursor_plane_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w,
|
||||
unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
{
|
||||
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
|
||||
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
|
||||
struct vmw_surface *surface = NULL;
|
||||
struct vmw_dma_buffer *dmabuf = NULL;
|
||||
s32 hotspot_x, hotspot_y;
|
||||
int ret;
|
||||
|
||||
hotspot_x = du->hotspot_x + fb->hot_x;
|
||||
hotspot_y = du->hotspot_y + fb->hot_y;
|
||||
|
||||
/* A lot of the code assumes this */
|
||||
if (crtc_w != 64 || crtc_h != 64) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vmw_framebuffer_to_vfb(fb)->dmabuf)
|
||||
dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
|
||||
else
|
||||
surface = vmw_framebuffer_to_vfbs(fb)->surface;
|
||||
|
||||
if (surface && !surface->snooper.image) {
|
||||
DRM_ERROR("surface not suitable for cursor\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* setup new image */
|
||||
ret = 0;
|
||||
if (surface) {
|
||||
/* vmw_user_surface_lookup takes one reference */
|
||||
du->cursor_surface = surface;
|
||||
|
||||
du->cursor_age = du->cursor_surface->snooper.age;
|
||||
|
||||
ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
|
||||
64, 64, hotspot_x, hotspot_y);
|
||||
} else if (dmabuf) {
|
||||
/* vmw_user_surface_lookup takes one reference */
|
||||
du->cursor_dmabuf = dmabuf;
|
||||
|
||||
ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h,
|
||||
hotspot_x, hotspot_y);
|
||||
} else {
|
||||
vmw_cursor_update_position(dev_priv, false, 0, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
du->cursor_x = crtc_x + du->set_gui_x;
|
||||
du->cursor_y = crtc_y + du->set_gui_y;
|
||||
|
||||
vmw_cursor_update_position(dev_priv, true,
|
||||
du->cursor_x + hotspot_x,
|
||||
du->cursor_y + hotspot_y);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int vmw_du_cursor_plane_disable(struct drm_plane *plane)
|
||||
{
|
||||
if (plane->fb) {
|
||||
drm_framebuffer_unreference(plane->fb);
|
||||
plane->fb = NULL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
|
||||
@ -472,18 +370,6 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
|
||||
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
|
||||
|
||||
drm_atomic_set_fb_for_plane(plane->state, NULL);
|
||||
vmw_cursor_update_position(dev_priv, false, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
@ -1498,6 +1384,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
|
||||
*/
|
||||
if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height) &&
|
||||
dmabuf && only_2d &&
|
||||
mode_cmd->width > 64 && /* Don't create a proxy for cursor */
|
||||
dev_priv->active_display_unit == vmw_du_screen_target) {
|
||||
ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd,
|
||||
dmabuf, &surface);
|
||||
|
@ -256,10 +256,6 @@ int vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
|
||||
u16 *r, u16 *g, u16 *b,
|
||||
uint32_t size,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
|
||||
uint32_t handle, uint32_t width, uint32_t height,
|
||||
int32_t hot_x, int32_t hot_y);
|
||||
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
|
||||
int vmw_du_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
@ -339,15 +335,6 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
|
||||
/* Universal Plane Helpers */
|
||||
void vmw_du_primary_plane_destroy(struct drm_plane *plane);
|
||||
void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
|
||||
int vmw_du_cursor_plane_disable(struct drm_plane *plane);
|
||||
int vmw_du_cursor_plane_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w,
|
||||
unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
|
||||
/* Atomic Helpers */
|
||||
int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
|
||||
@ -356,8 +343,6 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state);
|
||||
void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state);
|
||||
int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state);
|
||||
void vmw_du_plane_cleanup_fb(struct drm_plane *plane,
|
||||
|
@ -56,6 +56,8 @@ enum stdu_content_type {
|
||||
* @right: Right side of bounding box.
|
||||
* @top: Top side of bounding box.
|
||||
* @bottom: Bottom side of bounding box.
|
||||
* @fb_left: Left side of the framebuffer/content bounding box
|
||||
* @fb_top: Top of the framebuffer/content bounding box
|
||||
* @buf: DMA buffer when DMA-ing between buffer and screen targets.
|
||||
* @sid: Surface ID when copying between surface and screen targets.
|
||||
*/
|
||||
@ -63,6 +65,7 @@ struct vmw_stdu_dirty {
|
||||
struct vmw_kms_dirty base;
|
||||
SVGA3dTransferType transfer;
|
||||
s32 left, right, top, bottom;
|
||||
s32 fb_left, fb_top;
|
||||
u32 pitch;
|
||||
union {
|
||||
struct vmw_dma_buffer *buf;
|
||||
@ -647,7 +650,7 @@ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
|
||||
*
|
||||
* @dirty: The closure structure.
|
||||
*
|
||||
* This function calculates the bounding box for all the incoming clips
|
||||
* This function calculates the bounding box for all the incoming clips.
|
||||
*/
|
||||
static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
|
||||
{
|
||||
@ -656,11 +659,19 @@ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
|
||||
|
||||
dirty->num_hits = 1;
|
||||
|
||||
/* Calculate bounding box */
|
||||
/* Calculate destination bounding box */
|
||||
ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
|
||||
ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
|
||||
ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
|
||||
ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
|
||||
|
||||
/*
|
||||
* Calculate content bounding box. We only need the top-left
|
||||
* coordinate because width and height will be the same as the
|
||||
* destination bounding box above
|
||||
*/
|
||||
ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x);
|
||||
ddirty->fb_top = min_t(s32, ddirty->fb_top, dirty->fb_y);
|
||||
}
|
||||
|
||||
|
||||
@ -697,11 +708,11 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
|
||||
/* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */
|
||||
src_pitch = stdu->display_srf->base_size.width * stdu->cpp;
|
||||
src = ttm_kmap_obj_virtual(&stdu->host_map, ¬_used);
|
||||
src += dirty->unit_y1 * src_pitch + dirty->unit_x1 * stdu->cpp;
|
||||
src += ddirty->top * src_pitch + ddirty->left * stdu->cpp;
|
||||
|
||||
dst_pitch = ddirty->pitch;
|
||||
dst = ttm_kmap_obj_virtual(&stdu->guest_map, ¬_used);
|
||||
dst += dirty->fb_y * dst_pitch + dirty->fb_x * stdu->cpp;
|
||||
dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp;
|
||||
|
||||
|
||||
/* Figure out the real direction */
|
||||
@ -760,7 +771,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
|
||||
}
|
||||
|
||||
out_cleanup:
|
||||
ddirty->left = ddirty->top = S32_MAX;
|
||||
ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
|
||||
ddirty->right = ddirty->bottom = S32_MIN;
|
||||
}
|
||||
|
||||
@ -812,6 +823,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
|
||||
SVGA3D_READ_HOST_VRAM;
|
||||
ddirty.left = ddirty.top = S32_MAX;
|
||||
ddirty.right = ddirty.bottom = S32_MIN;
|
||||
ddirty.fb_left = ddirty.fb_top = S32_MAX;
|
||||
ddirty.pitch = vfb->base.pitches[0];
|
||||
ddirty.buf = buf;
|
||||
ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit;
|
||||
@ -1355,6 +1367,11 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
|
||||
DRM_ERROR("Failed to bind surface to STDU.\n");
|
||||
else
|
||||
crtc->primary->fb = plane->state->fb;
|
||||
|
||||
ret = vmw_stdu_update_st(dev_priv, stdu);
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to update STDU.\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1274,11 +1274,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
|
||||
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
|
||||
int ret;
|
||||
uint32_t size;
|
||||
uint32_t backup_handle;
|
||||
uint32_t backup_handle = 0;
|
||||
|
||||
if (req->multisample_count != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(vmw_user_surface_size == 0))
|
||||
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
|
||||
128;
|
||||
@ -1314,12 +1317,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
|
||||
ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
|
||||
&res->backup,
|
||||
&user_srf->backup_base);
|
||||
if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE <
|
||||
res->backup_size) {
|
||||
DRM_ERROR("Surface backup buffer is too small.\n");
|
||||
vmw_dmabuf_unreference(&res->backup);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
if (ret == 0) {
|
||||
if (res->backup->base.num_pages * PAGE_SIZE <
|
||||
res->backup_size) {
|
||||
DRM_ERROR("Surface backup buffer is too small.\n");
|
||||
vmw_dmabuf_unreference(&res->backup);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
} else {
|
||||
backup_handle = req->buffer_handle;
|
||||
}
|
||||
}
|
||||
} else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
|
||||
ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
|
||||
@ -1491,7 +1498,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
|
||||
dev_priv->stdu_max_height);
|
||||
|
||||
if (size.width > max_width || size.height > max_height) {
|
||||
DRM_ERROR("%ux%u\n, exeeds max surface size %ux%u",
|
||||
DRM_ERROR("%ux%u\n, exceeds max surface size %ux%u",
|
||||
size.width, size.height,
|
||||
max_width, max_height);
|
||||
return -EINVAL;
|
||||
|
Loading…
Reference in New Issue
Block a user