Merge tag 'drm-qemu-20160921' of git://git.kraxel.org/linux into drm-next
authorDave Airlie <airlied@redhat.com>
Wed, 28 Sep 2016 03:23:07 +0000 (13:23 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 28 Sep 2016 03:23:07 +0000 (13:23 +1000)
bugfixes for qemu (bochs, qxl and virtio-gpu) drm drivers

* tag 'drm-qemu-20160921' of git://git.kraxel.org/linux:
  drm/virtio: add real fence context and seqno
  drm/virtio: drop virtio_gpu_execbuffer_ioctl() wrapping
  virtio-gpu: avoid possible NULL pointer dereference
  drm/qxl: reapply cursor after SetCrtc calls
  bochs: ignore device if there isn't enougth memory

drivers/gpu/drm/bochs/bochs_drv.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_fence.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/virtio/virtgpu_plane.c

index 277654a..534227d 100644 (file)
@@ -163,8 +163,15 @@ static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
 static int bochs_pci_probe(struct pci_dev *pdev,
                           const struct pci_device_id *ent)
 {
+       unsigned long fbsize;
        int ret;
 
+       fbsize = pci_resource_len(pdev, 0);
+       if (fbsize < 4 * 1024 * 1024) {
+               DRM_ERROR("less than 4 MB video memory, ignoring device\n");
+               return -ENOMEM;
+       }
+
        ret = bochs_kick_out_firmware_fb(pdev);
        if (ret)
                return ret;
index 3aef127..a61c0d4 100644 (file)
@@ -211,6 +211,7 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc)
        struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
 
        drm_crtc_cleanup(crtc);
+       qxl_bo_unref(&qxl_crtc->cursor_bo);
        kfree(qxl_crtc);
 }
 
@@ -296,6 +297,52 @@ qxl_hide_cursor(struct qxl_device *qdev)
        return 0;
 }
 
+static int qxl_crtc_apply_cursor(struct drm_crtc *crtc)
+{
+       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct qxl_device *qdev = dev->dev_private;
+       struct qxl_cursor_cmd *cmd;
+       struct qxl_release *release;
+       int ret = 0;
+
+       if (!qcrtc->cursor_bo)
+               return 0;
+
+       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
+                                        QXL_RELEASE_CURSOR_CMD,
+                                        &release, NULL);
+       if (ret)
+               return ret;
+
+       ret = qxl_release_list_add(release, qcrtc->cursor_bo);
+       if (ret)
+               goto out_free_release;
+
+       ret = qxl_release_reserve_list(release, false);
+       if (ret)
+               goto out_free_release;
+
+       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
+       cmd->type = QXL_CURSOR_SET;
+       cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
+       cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
+
+       cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0);
+
+       cmd->u.set.visible = 1;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
+
+       return ret;
+
+out_free_release:
+       qxl_release_free(qdev, release);
+       return ret;
+}
+
 static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
                                struct drm_file *file_priv,
                                uint32_t handle,
@@ -400,7 +447,8 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
        }
        drm_gem_object_unreference_unlocked(obj);
 
-       qxl_bo_unref(&cursor_bo);
+       qxl_bo_unref (&qcrtc->cursor_bo);
+       qcrtc->cursor_bo = cursor_bo;
 
        return ret;
 
@@ -655,6 +703,12 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
                           bo->surf.stride, bo->surf.format);
                qxl_io_create_primary(qdev, 0, bo);
                bo->is_primary = true;
+
+               ret = qxl_crtc_apply_cursor(crtc);
+               if (ret) {
+                       DRM_ERROR("could not set cursor after modeset");
+                       ret = 0;
+               }
        }
 
        if (bo->is_primary) {
index 8e633ca..5f3e5ad 100644 (file)
@@ -137,6 +137,7 @@ struct qxl_crtc {
        int cur_y;
        int hot_spot_x;
        int hot_spot_y;
+       struct qxl_bo *cursor_bo;
 };
 
 struct qxl_output {
index b18ef31..06ad923 100644 (file)
@@ -75,6 +75,7 @@ typedef void (*virtio_gpu_resp_cb)(struct virtio_gpu_device *vgdev,
 struct virtio_gpu_fence_driver {
        atomic64_t       last_seq;
        uint64_t         sync_seq;
+       uint64_t         context;
        struct list_head fences;
        spinlock_t       lock;
 };
index cf44187..f3f70fa 100644 (file)
@@ -89,7 +89,7 @@ int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
        (*fence)->drv = drv;
        (*fence)->seq = ++drv->sync_seq;
        fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock,
-                  0, (*fence)->seq);
+                  drv->context, (*fence)->seq);
        fence_get(&(*fence)->f);
        list_add_tail(&(*fence)->node, &drv->fences);
        spin_unlock_irqrestore(&drv->lock, irq_flags);
index 512e7cd..818478b 100644 (file)
@@ -89,10 +89,16 @@ static void virtio_gpu_unref_list(struct list_head *head)
        }
 }
 
-static int virtio_gpu_execbuffer(struct drm_device *dev,
-                                struct drm_virtgpu_execbuffer *exbuf,
+/*
+ * Usage of execbuffer:
+ * Relocations need to take into account the full VIRTIO_GPUDrawable size.
+ * However, the command as passed from user space must *not* contain the initial
+ * VIRTIO_GPUReleaseInfo struct (first XXX bytes)
+ */
+static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
                                 struct drm_file *drm_file)
 {
+       struct drm_virtgpu_execbuffer *exbuf = data;
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv;
        struct drm_gem_object *gobj;
@@ -177,20 +183,6 @@ out_free:
        return ret;
 }
 
-/*
- * Usage of execbuffer:
- * Relocations need to take into account the full VIRTIO_GPUDrawable size.
- * However, the command as passed from user space must *not* contain the initial
- * VIRTIO_GPUReleaseInfo struct (first XXX bytes)
- */
-static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
-                                      struct drm_file *file_priv)
-{
-       struct drm_virtgpu_execbuffer *execbuffer = data;
-       return virtio_gpu_execbuffer(dev, execbuffer, file_priv);
-}
-
-
 static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
                                     struct drm_file *file_priv)
 {
index 4150873..036b0fb 100644 (file)
@@ -159,6 +159,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
        virtio_gpu_init_vq(&vgdev->ctrlq, virtio_gpu_dequeue_ctrl_func);
        virtio_gpu_init_vq(&vgdev->cursorq, virtio_gpu_dequeue_cursor_func);
 
+       vgdev->fence_drv.context = fence_context_alloc(1);
        spin_lock_init(&vgdev->fence_drv.lock);
        INIT_LIST_HEAD(&vgdev->fence_drv.fences);
        INIT_LIST_HEAD(&vgdev->cap_cache);
index 925ca25..ba28c0f 100644 (file)
@@ -76,7 +76,8 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
                output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
        if (old_state->crtc)
                output = drm_crtc_to_virtio_gpu_output(old_state->crtc);
-       WARN_ON(!output);
+       if (WARN_ON(!output))
+               return;
 
        if (plane->state->fb) {
                vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
@@ -129,7 +130,8 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
                output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
        if (old_state->crtc)
                output = drm_crtc_to_virtio_gpu_output(old_state->crtc);
-       WARN_ON(!output);
+       if (WARN_ON(!output))
+               return;
 
        if (plane->state->fb) {
                vgfb = to_virtio_gpu_framebuffer(plane->state->fb);