/** * Allocate the backing store for the buffer. */ static int vmw_sou_backing_alloc(struct vmw_private *dev_priv, struct vmw_screen_object_unit *sou, unsigned long size) { int ret; if (sou->buffer_size == size) return 0; if (sou->buffer) vmw_sou_backing_free(dev_priv, sou); sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL); if (unlikely(sou->buffer == NULL)) return -ENOMEM; /* After we have alloced the backing store might not be able to * resume the overlays, this is preferred to failing to alloc. */ vmw_overlay_pause_all(dev_priv); ret = vmw_dmabuf_init(dev_priv, sou->buffer, size, &vmw_vram_ne_placement, false, &vmw_dmabuf_bo_free); vmw_overlay_resume_all(dev_priv); if (unlikely(ret != 0)) sou->buffer = NULL; /* vmw_dmabuf_init frees on error */ else sou->buffer_size = size; return ret; }
/** * vmw_sou_primary_plane_prepare_fb - allocate backing buffer * * @plane: display plane * @new_state: info on the new plane state, including the FB * * The SOU backing buffer is our equivalent of the display plane. * * Returns 0 on success */ static int vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { struct drm_framebuffer *new_fb = new_state->fb; struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc; struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); struct vmw_private *dev_priv; size_t size; int ret; if (!new_fb) { vmw_dmabuf_unreference(&vps->dmabuf); vps->dmabuf_size = 0; return 0; } size = new_state->crtc_w * new_state->crtc_h * 4; if (vps->dmabuf) { if (vps->dmabuf_size == size) return 0; vmw_dmabuf_unreference(&vps->dmabuf); vps->dmabuf_size = 0; } vps->dmabuf = kzalloc(sizeof(*vps->dmabuf), GFP_KERNEL); if (!vps->dmabuf) return -ENOMEM; dev_priv = vmw_priv(crtc->dev); vmw_svga_enable(dev_priv); /* After we have alloced the backing store might not be able to * resume the overlays, this is preferred to failing to alloc. */ vmw_overlay_pause_all(dev_priv); ret = vmw_dmabuf_init(dev_priv, vps->dmabuf, size, &vmw_vram_ne_placement, false, &vmw_dmabuf_bo_free); vmw_overlay_resume_all(dev_priv); if (ret != 0) vps->dmabuf = NULL; /* vmw_dmabuf_init frees on error */ else vps->dmabuf_size = size; return ret; }
/** * vmw_sou_primary_plane_prepare_fb - allocate backing buffer * * @plane: display plane * @new_state: info on the new plane state, including the FB * * The SOU backing buffer is our equivalent of the display plane. * * Returns 0 on success */ static int vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { struct drm_framebuffer *new_fb = new_state->fb; struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc; struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); struct vmw_private *dev_priv; size_t size; int ret; if (!new_fb) { vmw_bo_unreference(&vps->bo); vps->bo_size = 0; return 0; } size = new_state->crtc_w * new_state->crtc_h * 4; dev_priv = vmw_priv(crtc->dev); if (vps->bo) { if (vps->bo_size == size) { /* * Note that this might temporarily up the pin-count * to 2, until cleanup_fb() is called. */ return vmw_bo_pin_in_vram(dev_priv, vps->bo, true); } vmw_bo_unreference(&vps->bo); vps->bo_size = 0; } vps->bo = kzalloc(sizeof(*vps->bo), GFP_KERNEL); if (!vps->bo) return -ENOMEM; vmw_svga_enable(dev_priv); /* After we have alloced the backing store might not be able to * resume the overlays, this is preferred to failing to alloc. */ vmw_overlay_pause_all(dev_priv); ret = vmw_bo_init(dev_priv, vps->bo, size, &vmw_vram_ne_placement, false, &vmw_bo_bo_free); vmw_overlay_resume_all(dev_priv); if (ret) { vps->bo = NULL; /* vmw_bo_init frees on error */ return ret; } vps->bo_size = size; /* * TTM already thinks the buffer is pinned, but make sure the * pin_count is upped. */ return vmw_bo_pin_in_vram(dev_priv, vps->bo, true); }