linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 01/23] drm/qxl: drop ttm_mem_reg arg from qxl_hw_surface_alloc()
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
@ 2019-01-18 12:19 ` Gerd Hoffmann
  2019-01-25 15:44   ` Noralf Trønnes
  2019-01-18 12:19 ` [PATCH v3 02/23] drm/qxl: drop unused qxl_fb_virtual_address Gerd Hoffmann
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Not used, is always NULL.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h    |  3 +--
 drivers/gpu/drm/qxl/qxl_cmd.c    | 14 ++------------
 drivers/gpu/drm/qxl/qxl_object.c |  2 +-
 3 files changed, 4 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 13a0254b59..38c5a8b1df 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -497,8 +497,7 @@ int qxl_surface_id_alloc(struct qxl_device *qdev,
 void qxl_surface_id_dealloc(struct qxl_device *qdev,
 			    uint32_t surface_id);
 int qxl_hw_surface_alloc(struct qxl_device *qdev,
-			 struct qxl_bo *surf,
-			 struct ttm_mem_reg *mem);
+			 struct qxl_bo *surf);
 int qxl_hw_surface_dealloc(struct qxl_device *qdev,
 			   struct qxl_bo *surf);
 
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 2e100f6442..5ba831c78c 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -460,8 +460,7 @@ void qxl_surface_id_dealloc(struct qxl_device *qdev,
 }
 
 int qxl_hw_surface_alloc(struct qxl_device *qdev,
-			 struct qxl_bo *surf,
-			 struct ttm_mem_reg *new_mem)
+			 struct qxl_bo *surf)
 {
 	struct qxl_surface_cmd *cmd;
 	struct qxl_release *release;
@@ -487,16 +486,7 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
 	cmd->u.surface_create.width = surf->surf.width;
 	cmd->u.surface_create.height = surf->surf.height;
 	cmd->u.surface_create.stride = surf->surf.stride;
-	if (new_mem) {
-		int slot_id = surf->type == QXL_GEM_DOMAIN_VRAM ? qdev->main_mem_slot : qdev->surfaces_mem_slot;
-		struct qxl_memslot *slot = &(qdev->mem_slots[slot_id]);
-
-		/* TODO - need to hold one of the locks to read tbo.offset */
-		cmd->u.surface_create.data = slot->high_bits;
-
-		cmd->u.surface_create.data |= (new_mem->start << PAGE_SHIFT) + surf->tbo.bdev->man[new_mem->mem_type].gpu_offset;
-	} else
-		cmd->u.surface_create.data = qxl_bo_physical_address(qdev, surf, 0);
+	cmd->u.surface_create.data = qxl_bo_physical_address(qdev, surf, 0);
 	cmd->surface_id = surf->surface_id;
 	qxl_release_unmap(qdev, release, &cmd->release_info);
 
diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c
index 91f3bbc73e..34eff8b21e 100644
--- a/drivers/gpu/drm/qxl/qxl_object.c
+++ b/drivers/gpu/drm/qxl/qxl_object.c
@@ -332,7 +332,7 @@ int qxl_bo_check_id(struct qxl_device *qdev, struct qxl_bo *bo)
 		if (ret)
 			return ret;
 
-		ret = qxl_hw_surface_alloc(qdev, bo, NULL);
+		ret = qxl_hw_surface_alloc(qdev, bo);
 		if (ret)
 			return ret;
 	}
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 02/23] drm/qxl: drop unused qxl_fb_virtual_address
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
  2019-01-18 12:19 ` [PATCH v3 01/23] drm/qxl: drop ttm_mem_reg arg from qxl_hw_surface_alloc() Gerd Hoffmann
@ 2019-01-18 12:19 ` Gerd Hoffmann
  2019-01-25 15:44   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 03/23] drm/qxl: simplify slot management Gerd Hoffmann
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 38c5a8b1df..7eabf4a9ed 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -308,13 +308,6 @@ void qxl_ring_free(struct qxl_ring *ring);
 void qxl_ring_init_hdr(struct qxl_ring *ring);
 int qxl_check_idle(struct qxl_ring *ring);
 
-static inline void *
-qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical)
-{
-	DRM_DEBUG_DRIVER("not implemented (%lu)\n", physical);
-	return 0;
-}
-
 static inline uint64_t
 qxl_bo_physical_address(struct qxl_device *qdev, struct qxl_bo *bo,
 			unsigned long offset)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 03/23] drm/qxl: simplify slot management
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
  2019-01-18 12:19 ` [PATCH v3 01/23] drm/qxl: drop ttm_mem_reg arg from qxl_hw_surface_alloc() Gerd Hoffmann
  2019-01-18 12:19 ` [PATCH v3 02/23] drm/qxl: drop unused qxl_fb_virtual_address Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 15:52   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 04/23] drm/qxl: change the way slot is detected Gerd Hoffmann
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Drop pointless indirection, remove the mem_slots array and index
variables, drop dynamic allocation.  Store memslots in qxl_device
instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h | 15 +++++----
 drivers/gpu/drm/qxl/qxl_kms.c | 72 +++++++++++++++++--------------------------
 2 files changed, 36 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 7eabf4a9ed..f9dddfe7d9 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -130,9 +130,11 @@ struct qxl_mman {
 };
 
 struct qxl_memslot {
+	int             index;
+	const char      *name;
 	uint8_t		generation;
 	uint64_t	start_phys_addr;
-	uint64_t	end_phys_addr;
+	uint64_t	size;
 	uint64_t	high_bits;
 };
 
@@ -228,11 +230,8 @@ struct qxl_device {
 
 	unsigned int primary_created:1;
 
-	struct qxl_memslot	*mem_slots;
-	uint8_t		n_mem_slots;
-
-	uint8_t		main_mem_slot;
-	uint8_t		surfaces_mem_slot;
+	struct qxl_memslot main_slot;
+	struct qxl_memslot surfaces_slot;
 	uint8_t		slot_id_bits;
 	uint8_t		slot_gen_bits;
 	uint64_t	va_slot_mask;
@@ -312,8 +311,8 @@ static inline uint64_t
 qxl_bo_physical_address(struct qxl_device *qdev, struct qxl_bo *bo,
 			unsigned long offset)
 {
-	int slot_id = bo->type == QXL_GEM_DOMAIN_VRAM ? qdev->main_mem_slot : qdev->surfaces_mem_slot;
-	struct qxl_memslot *slot = &(qdev->mem_slots[slot_id]);
+	struct qxl_memslot *slot = bo->type == QXL_GEM_DOMAIN_VRAM
+		? &qdev->main_slot : &qdev->surfaces_slot;
 
 	/* TODO - need to hold one of the locks to read tbo.offset */
 	return slot->high_bits | (bo->tbo.offset + offset);
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index 15238a413f..a9288100ae 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -53,40 +53,46 @@ static bool qxl_check_device(struct qxl_device *qdev)
 	return true;
 }
 
-static void setup_hw_slot(struct qxl_device *qdev, int slot_index,
-			  struct qxl_memslot *slot)
+static void setup_hw_slot(struct qxl_device *qdev, struct qxl_memslot *slot)
 {
 	qdev->ram_header->mem_slot.mem_start = slot->start_phys_addr;
-	qdev->ram_header->mem_slot.mem_end = slot->end_phys_addr;
-	qxl_io_memslot_add(qdev, slot_index);
+	qdev->ram_header->mem_slot.mem_end = slot->start_phys_addr + slot->size;
+	qxl_io_memslot_add(qdev, qdev->rom->slots_start + slot->index);
 }
 
-static uint8_t setup_slot(struct qxl_device *qdev, uint8_t slot_index_offset,
-	unsigned long start_phys_addr, unsigned long end_phys_addr)
+static void setup_slot(struct qxl_device *qdev,
+		       struct qxl_memslot *slot,
+		       unsigned int slot_index,
+		       const char *slot_name,
+		       unsigned long start_phys_addr,
+		       unsigned long size)
 {
 	uint64_t high_bits;
-	struct qxl_memslot *slot;
-	uint8_t slot_index;
 
-	slot_index = qdev->rom->slots_start + slot_index_offset;
-	slot = &qdev->mem_slots[slot_index];
+	slot->index = slot_index;
+	slot->name = slot_name;
 	slot->start_phys_addr = start_phys_addr;
-	slot->end_phys_addr = end_phys_addr;
+	slot->size = size;
 
-	setup_hw_slot(qdev, slot_index, slot);
+	setup_hw_slot(qdev, slot);
 
 	slot->generation = qdev->rom->slot_generation;
-	high_bits = slot_index << qdev->slot_gen_bits;
+	high_bits = (qdev->rom->slots_start + slot->index)
+		<< qdev->slot_gen_bits;
 	high_bits |= slot->generation;
 	high_bits <<= (64 - (qdev->slot_gen_bits + qdev->slot_id_bits));
 	slot->high_bits = high_bits;
-	return slot_index;
+
+	DRM_INFO("slot %d (%s): base 0x%08lx, size 0x%08lx\n",
+		 slot->index, slot->name,
+		 (unsigned long)slot->start_phys_addr,
+		 (unsigned long)slot->size);
 }
 
 void qxl_reinit_memslots(struct qxl_device *qdev)
 {
-	setup_hw_slot(qdev, qdev->main_mem_slot, &qdev->mem_slots[qdev->main_mem_slot]);
-	setup_hw_slot(qdev, qdev->surfaces_mem_slot, &qdev->mem_slots[qdev->surfaces_mem_slot]);
+	setup_hw_slot(qdev, &qdev->main_slot);
+	setup_hw_slot(qdev, &qdev->surfaces_slot);
 }
 
 static void qxl_gc_work(struct work_struct *work)
@@ -231,22 +237,11 @@ int qxl_device_init(struct qxl_device *qdev,
 	}
 	/* TODO - slot initialization should happen on reset. where is our
 	 * reset handler? */
-	qdev->n_mem_slots = qdev->rom->slots_end;
 	qdev->slot_gen_bits = qdev->rom->slot_gen_bits;
 	qdev->slot_id_bits = qdev->rom->slot_id_bits;
 	qdev->va_slot_mask =
 		(~(uint64_t)0) >> (qdev->slot_id_bits + qdev->slot_gen_bits);
 
-	qdev->mem_slots =
-		kmalloc_array(qdev->n_mem_slots, sizeof(struct qxl_memslot),
-			      GFP_KERNEL);
-
-	if (!qdev->mem_slots) {
-		DRM_ERROR("Unable to alloc mem slots\n");
-		r = -ENOMEM;
-		goto release_ring_free;
-	}
-
 	idr_init(&qdev->release_idr);
 	spin_lock_init(&qdev->release_idr_lock);
 	spin_lock_init(&qdev->release_lock);
@@ -264,33 +259,24 @@ int qxl_device_init(struct qxl_device *qdev,
 	r = qxl_irq_init(qdev);
 	if (r) {
 		DRM_ERROR("Unable to init qxl irq\n");
-		goto mem_slots_free;
+		goto release_ring_free;
 	}
 
 	/*
 	 * Note that virtual is surface0. We rely on the single ioremap done
 	 * before.
 	 */
-	qdev->main_mem_slot = setup_slot(qdev, 0,
-		(unsigned long)qdev->vram_base,
-		(unsigned long)qdev->vram_base + qdev->rom->ram_header_offset);
-	qdev->surfaces_mem_slot = setup_slot(qdev, 1,
-		(unsigned long)qdev->surfaceram_base,
-		(unsigned long)qdev->surfaceram_base + qdev->surfaceram_size);
-	DRM_INFO("main mem slot %d [%lx,%x]\n",
-		 qdev->main_mem_slot,
-		 (unsigned long)qdev->vram_base, qdev->rom->ram_header_offset);
-	DRM_INFO("surface mem slot %d [%lx,%lx]\n",
-		 qdev->surfaces_mem_slot,
-		 (unsigned long)qdev->surfaceram_base,
-		 (unsigned long)qdev->surfaceram_size);
+	setup_slot(qdev, &qdev->main_slot, 0, "main",
+		   (unsigned long)qdev->vram_base,
+		   (unsigned long)qdev->rom->ram_header_offset);
+	setup_slot(qdev, &qdev->surfaces_slot, 1, "surfaces",
+		   (unsigned long)qdev->surfaceram_base,
+		   (unsigned long)qdev->surfaceram_size);
 
 	INIT_WORK(&qdev->gc_work, qxl_gc_work);
 
 	return 0;
 
-mem_slots_free:
-	kfree(qdev->mem_slots);
 release_ring_free:
 	qxl_ring_free(qdev->release_ring);
 cursor_ring_free:
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 04/23] drm/qxl: change the way slot is detected
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (2 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 03/23] drm/qxl: simplify slot management Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 15:52   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 05/23] drm/qxl: drop unused fields from struct qxl_device Gerd Hoffmann
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Frediano Ziglio, Gerd Hoffmann, Dave Airlie, David Airlie,
	Daniel Vetter, open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

From: Frediano Ziglio <fziglio@redhat.com>

Instead of relaying on surface type use the actual placement.
This allow to have different placement for a single type of
surface.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>

[ kraxel: rebased, adapted to upstream changes ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index f9dddfe7d9..d015d4fff1 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -311,7 +311,8 @@ static inline uint64_t
 qxl_bo_physical_address(struct qxl_device *qdev, struct qxl_bo *bo,
 			unsigned long offset)
 {
-	struct qxl_memslot *slot = bo->type == QXL_GEM_DOMAIN_VRAM
+	struct qxl_memslot *slot =
+		(bo->tbo.mem.mem_type == TTM_PL_VRAM)
 		? &qdev->main_slot : &qdev->surfaces_slot;
 
 	/* TODO - need to hold one of the locks to read tbo.offset */
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 05/23] drm/qxl: drop unused fields from struct qxl_device
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (3 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 04/23] drm/qxl: change the way slot is detected Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 15:53   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 06/23] drm/qxl: use separate offset spaces for the two slots / ttm memory types Gerd Hoffmann
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

slot_id_bits and slot_gen_bits can be read directly from qxlrom instead.
va_slot_mask is never used anywhere.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h |  3 ---
 drivers/gpu/drm/qxl/qxl_kms.c | 10 ++--------
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index d015d4fff1..3ebe66abf2 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -232,9 +232,6 @@ struct qxl_device {
 
 	struct qxl_memslot main_slot;
 	struct qxl_memslot surfaces_slot;
-	uint8_t		slot_id_bits;
-	uint8_t		slot_gen_bits;
-	uint64_t	va_slot_mask;
 
 	spinlock_t	release_lock;
 	struct idr	release_idr;
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index a9288100ae..3c1753667d 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -78,9 +78,9 @@ static void setup_slot(struct qxl_device *qdev,
 
 	slot->generation = qdev->rom->slot_generation;
 	high_bits = (qdev->rom->slots_start + slot->index)
-		<< qdev->slot_gen_bits;
+		<< qdev->rom->slot_gen_bits;
 	high_bits |= slot->generation;
-	high_bits <<= (64 - (qdev->slot_gen_bits + qdev->slot_id_bits));
+	high_bits <<= (64 - (qdev->rom->slot_gen_bits + qdev->rom->slot_id_bits));
 	slot->high_bits = high_bits;
 
 	DRM_INFO("slot %d (%s): base 0x%08lx, size 0x%08lx\n",
@@ -235,12 +235,6 @@ int qxl_device_init(struct qxl_device *qdev,
 		r = -ENOMEM;
 		goto cursor_ring_free;
 	}
-	/* TODO - slot initialization should happen on reset. where is our
-	 * reset handler? */
-	qdev->slot_gen_bits = qdev->rom->slot_gen_bits;
-	qdev->slot_id_bits = qdev->rom->slot_id_bits;
-	qdev->va_slot_mask =
-		(~(uint64_t)0) >> (qdev->slot_id_bits + qdev->slot_gen_bits);
 
 	idr_init(&qdev->release_idr);
 	spin_lock_init(&qdev->release_idr_lock);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 06/23] drm/qxl: use separate offset spaces for the two slots / ttm memory types.
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (4 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 05/23] drm/qxl: drop unused fields from struct qxl_device Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 15:57   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 07/23] drm/qxl: allow both PRIV and VRAM placement for QXL_GEM_DOMAIN_SURFACE Gerd Hoffmann
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Without that ttm offsets are not unique, they can refer to objects
in both VRAM and PRIV memory (aka main and surfaces slot).

One of those "why things didn't blow up without this" moments.
Probably offset conflicts are rare enough by pure luck.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h |  5 ++++-
 drivers/gpu/drm/qxl/qxl_kms.c |  5 +++--
 drivers/gpu/drm/qxl/qxl_ttm.c | 10 +++++++++-
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 3ebe66abf2..27e0a3fc08 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -136,6 +136,7 @@ struct qxl_memslot {
 	uint64_t	start_phys_addr;
 	uint64_t	size;
 	uint64_t	high_bits;
+	uint64_t        gpu_offset;
 };
 
 enum {
@@ -312,8 +313,10 @@ qxl_bo_physical_address(struct qxl_device *qdev, struct qxl_bo *bo,
 		(bo->tbo.mem.mem_type == TTM_PL_VRAM)
 		? &qdev->main_slot : &qdev->surfaces_slot;
 
+	WARN_ON_ONCE((bo->tbo.offset & slot->gpu_offset) != slot->gpu_offset);
+
 	/* TODO - need to hold one of the locks to read tbo.offset */
-	return slot->high_bits | (bo->tbo.offset + offset);
+	return slot->high_bits | (bo->tbo.offset - slot->gpu_offset + offset);
 }
 
 /* qxl_fb.c */
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index 3c1753667d..82c764623f 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -83,10 +83,11 @@ static void setup_slot(struct qxl_device *qdev,
 	high_bits <<= (64 - (qdev->rom->slot_gen_bits + qdev->rom->slot_id_bits));
 	slot->high_bits = high_bits;
 
-	DRM_INFO("slot %d (%s): base 0x%08lx, size 0x%08lx\n",
+	DRM_INFO("slot %d (%s): base 0x%08lx, size 0x%08lx, gpu_offset 0x%lx\n",
 		 slot->index, slot->name,
 		 (unsigned long)slot->start_phys_addr,
-		 (unsigned long)slot->size);
+		 (unsigned long)slot->size,
+		 (unsigned long)slot->gpu_offset);
 }
 
 void qxl_reinit_memslots(struct qxl_device *qdev)
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index 886f61e94f..36ea993aac 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -100,6 +100,11 @@ static int qxl_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
 static int qxl_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
 			     struct ttm_mem_type_manager *man)
 {
+	struct qxl_device *qdev = qxl_get_qdev(bdev);
+	unsigned int gpu_offset_shift =
+		64 - (qdev->rom->slot_gen_bits + qdev->rom->slot_id_bits + 8);
+	struct qxl_memslot *slot;
+
 	switch (type) {
 	case TTM_PL_SYSTEM:
 		/* System memory */
@@ -110,8 +115,11 @@ static int qxl_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
 	case TTM_PL_VRAM:
 	case TTM_PL_PRIV:
 		/* "On-card" video ram */
+		slot = (type == TTM_PL_VRAM) ?
+			&qdev->main_slot : &qdev->surfaces_slot;
+		slot->gpu_offset = (uint64_t)type << gpu_offset_shift;
 		man->func = &ttm_bo_manager_func;
-		man->gpu_offset = 0;
+		man->gpu_offset = slot->gpu_offset;
 		man->flags = TTM_MEMTYPE_FLAG_FIXED |
 			     TTM_MEMTYPE_FLAG_MAPPABLE;
 		man->available_caching = TTM_PL_MASK_CACHING;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 07/23] drm/qxl: allow both PRIV and VRAM placement for QXL_GEM_DOMAIN_SURFACE
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (5 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 06/23] drm/qxl: use separate offset spaces for the two slots / ttm memory types Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 15:58   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 08/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for shadow bo Gerd Hoffmann
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

qxl surfaces (used for framebuffers and gem objects) can live in both
VRAM and PRIV ttm domains.  Update placement setup to include both.
Put PRIV first in the list so it is preferred, so VRAM will have more
room for objects which must be allocated there.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_object.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c
index 34eff8b21e..024c8dd317 100644
--- a/drivers/gpu/drm/qxl/qxl_object.c
+++ b/drivers/gpu/drm/qxl/qxl_object.c
@@ -60,8 +60,10 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain, bool pinned)
 	qbo->placement.busy_placement = qbo->placements;
 	if (domain == QXL_GEM_DOMAIN_VRAM)
 		qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM | pflag;
-	if (domain == QXL_GEM_DOMAIN_SURFACE)
+	if (domain == QXL_GEM_DOMAIN_SURFACE) {
 		qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_PRIV | pflag;
+		qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM | pflag;
+	}
 	if (domain == QXL_GEM_DOMAIN_CPU)
 		qbo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM | pflag;
 	if (!c)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 08/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for shadow bo.
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (6 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 07/23] drm/qxl: allow both PRIV and VRAM placement for QXL_GEM_DOMAIN_SURFACE Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 15:58   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 09/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for dumb gem objects Gerd Hoffmann
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

The shadow bo is used as qxl surface, so allocate it as
QXL_GEM_DOMAIN_SURFACE.  Should usually be allocated in
PRIV ttm domain then, so this reduces VRAM memory pressure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 1f8fddcc34..86bfc19bea 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -758,7 +758,7 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
 			user_bo->shadow = old_bo->shadow;
 		} else {
 			qxl_bo_create(qdev, user_bo->gem_base.size,
-				      true, true, QXL_GEM_DOMAIN_VRAM, NULL,
+				      true, true, QXL_GEM_DOMAIN_SURFACE, NULL,
 				      &user_bo->shadow);
 		}
 	}
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 09/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for dumb gem objects
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (7 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 08/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for shadow bo Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 15:59   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place Gerd Hoffmann
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

dumb buffers are used as qxl surfaces, so allocate them as
QXL_GEM_DOMAIN_SURFACE.  Should usually be allocated in
PRIV ttm domain then, so this reduces VRAM memory pressure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_dumb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
index e3765739c3..272d19b677 100644
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
@@ -59,7 +59,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
 	surf.stride = pitch;
 	surf.format = format;
 	r = qxl_gem_object_create_with_handle(qdev, file_priv,
-					      QXL_GEM_DOMAIN_VRAM,
+					      QXL_GEM_DOMAIN_SURFACE,
 					      args->size, &surf, &qobj,
 					      &handle);
 	if (r)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (8 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 09/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for dumb gem objects Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 16:09   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 11/23] drm/qxl: drop unused offset parameter from qxl_io_create_primary() Gerd Hoffmann
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

The cursor must be set again after creating the primary surface.
Also drop the error message.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_display.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 86bfc19bea..1b700ef503 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -533,7 +533,6 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
 	    .x2 = plane->state->fb->width,
 	    .y2 = plane->state->fb->height
 	};
-	int ret;
 	bool same_shadow = false;
 
 	if (old_state->fb) {
@@ -554,16 +553,13 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
 		if (!same_shadow)
 			qxl_io_destroy_primary(qdev);
 		bo_old->is_primary = false;
-
-		ret = qxl_primary_apply_cursor(plane);
-		if (ret)
-			DRM_ERROR(
-			"could not set cursor after creating primary");
 	}
 
 	if (!bo->is_primary) {
-		if (!same_shadow)
+		if (!same_shadow) {
 			qxl_io_create_primary(qdev, 0, bo);
+			qxl_primary_apply_cursor(plane);
+		}
 		bo->is_primary = true;
 	}
 
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 11/23] drm/qxl: drop unused offset parameter from qxl_io_create_primary()
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (9 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 16:10   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 12/23] drm/qxl: track primary bo Gerd Hoffmann
                   ` (11 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h     | 1 -
 drivers/gpu/drm/qxl/qxl_cmd.c     | 7 +++----
 drivers/gpu/drm/qxl/qxl_display.c | 2 +-
 3 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 27e0a3fc08..cb767aaef6 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -385,7 +385,6 @@ void qxl_update_screen(struct qxl_device *qxl);
 /* qxl io operations (qxl_cmd.c) */
 
 void qxl_io_create_primary(struct qxl_device *qdev,
-			   unsigned int offset,
 			   struct qxl_bo *bo);
 void qxl_io_destroy_primary(struct qxl_device *qdev);
 void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id);
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 5ba831c78c..bc13539249 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -377,8 +377,7 @@ void qxl_io_destroy_primary(struct qxl_device *qdev)
 	qdev->primary_created = false;
 }
 
-void qxl_io_create_primary(struct qxl_device *qdev,
-			   unsigned int offset, struct qxl_bo *bo)
+void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo)
 {
 	struct qxl_surface_create *create;
 
@@ -389,9 +388,9 @@ void qxl_io_create_primary(struct qxl_device *qdev,
 	create->height = bo->surf.height;
 	create->stride = bo->surf.stride;
 	if (bo->shadow) {
-		create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset);
+		create->mem = qxl_bo_physical_address(qdev, bo->shadow, 0);
 	} else {
-		create->mem = qxl_bo_physical_address(qdev, bo, offset);
+		create->mem = qxl_bo_physical_address(qdev, bo, 0);
 	}
 
 	DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 1b700ef503..21165ab514 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -557,7 +557,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
 
 	if (!bo->is_primary) {
 		if (!same_shadow) {
-			qxl_io_create_primary(qdev, 0, bo);
+			qxl_io_create_primary(qdev, bo);
 			qxl_primary_apply_cursor(plane);
 		}
 		bo->is_primary = true;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 12/23] drm/qxl: track primary bo
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (10 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 11/23] drm/qxl: drop unused offset parameter from qxl_io_create_primary() Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 16:11   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 13/23] drm/qxl: use shadow bo directly Gerd Hoffmann
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Track which bo is used as primary surface.  With that in place we don't
need the primary_created flag any more, we can just check the primary bo
pointer instead.

Also verify we don't already have a primary surface in
qxl_io_create_primary().

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h     | 2 +-
 drivers/gpu/drm/qxl/qxl_cmd.c     | 7 +++++--
 drivers/gpu/drm/qxl/qxl_display.c | 2 +-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index cb767aaef6..150b1a4f66 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -229,7 +229,7 @@ struct qxl_device {
 
 	struct qxl_ram_header *ram_header;
 
-	unsigned int primary_created:1;
+	struct qxl_bo *primary_bo;
 
 	struct qxl_memslot main_slot;
 	struct qxl_memslot surfaces_slot;
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index bc13539249..8e64127259 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -374,13 +374,16 @@ void qxl_io_flush_surfaces(struct qxl_device *qdev)
 void qxl_io_destroy_primary(struct qxl_device *qdev)
 {
 	wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC);
-	qdev->primary_created = false;
+	qdev->primary_bo = NULL;
 }
 
 void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo)
 {
 	struct qxl_surface_create *create;
 
+	if (WARN_ON(qdev->primary_bo))
+		return;
+
 	DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header);
 	create = &qdev->ram_header->create_surface;
 	create->format = bo->surf.format;
@@ -399,7 +402,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo)
 	create->type = QXL_SURF_TYPE_PRIMARY;
 
 	wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC);
-	qdev->primary_created = true;
+	qdev->primary_bo = bo;
 }
 
 void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 21165ab514..d3215eac9b 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -302,7 +302,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
 	struct qxl_head head;
 	int oldcount, i = qcrtc->index;
 
-	if (!qdev->primary_created) {
+	if (!qdev->primary_bo) {
 		DRM_DEBUG_KMS("no primary surface, skip (%s)\n", reason);
 		return;
 	}
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 13/23] drm/qxl: use shadow bo directly
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (11 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 12/23] drm/qxl: track primary bo Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 16:59   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 14/23] drm/qxl: cover all crtcs in shadow bo Gerd Hoffmann
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Pass the shadow bo to qxl_io_create_primary() instead of expecting
qxl_io_create_primary to check bo->shadow.  Set is_primary flag on the
shadow bo.  Move the is_primary tracking into qxl_io_create_primary()
and qxl_io_destroy_primary() functions.

That simplifies primary surface tracking and the workflow in
qxl_primary_atomic_update().

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

qxl_io_create/destroy_primary: primary_bo tracking [fixup]
---
 drivers/gpu/drm/qxl/qxl_cmd.c     | 10 +++++-----
 drivers/gpu/drm/qxl/qxl_display.c | 33 +++++++++++----------------------
 2 files changed, 16 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 8e64127259..0a2e51af12 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -374,6 +374,8 @@ void qxl_io_flush_surfaces(struct qxl_device *qdev)
 void qxl_io_destroy_primary(struct qxl_device *qdev)
 {
 	wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC);
+	qdev->primary_bo->is_primary = false;
+	drm_gem_object_put_unlocked(&qdev->primary_bo->gem_base);
 	qdev->primary_bo = NULL;
 }
 
@@ -390,11 +392,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo)
 	create->width = bo->surf.width;
 	create->height = bo->surf.height;
 	create->stride = bo->surf.stride;
-	if (bo->shadow) {
-		create->mem = qxl_bo_physical_address(qdev, bo->shadow, 0);
-	} else {
-		create->mem = qxl_bo_physical_address(qdev, bo, 0);
-	}
+	create->mem = qxl_bo_physical_address(qdev, bo, 0);
 
 	DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
 
@@ -403,6 +401,8 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo)
 
 	wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC);
 	qdev->primary_bo = bo;
+	qdev->primary_bo->is_primary = true;
+	drm_gem_object_get(&qdev->primary_bo->gem_base);
 }
 
 void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index d3215eac9b..ff13bc6a4a 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -401,13 +401,15 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
 	struct qxl_device *qdev = fb->dev->dev_private;
 	struct drm_clip_rect norect;
 	struct qxl_bo *qobj;
+	bool is_primary;
 	int inc = 1;
 
 	drm_modeset_lock_all(fb->dev);
 
 	qobj = gem_to_qxl_bo(fb->obj[0]);
 	/* if we aren't primary surface ignore this */
-	if (!qobj->is_primary) {
+	is_primary = qobj->shadow ? qobj->shadow->is_primary : qobj->is_primary;
+	if (!is_primary) {
 		drm_modeset_unlock_all(fb->dev);
 		return 0;
 	}
@@ -526,14 +528,13 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
 {
 	struct qxl_device *qdev = plane->dev->dev_private;
 	struct qxl_bo *bo = gem_to_qxl_bo(plane->state->fb->obj[0]);
-	struct qxl_bo *bo_old;
+	struct qxl_bo *bo_old, *primary;
 	struct drm_clip_rect norect = {
 	    .x1 = 0,
 	    .y1 = 0,
 	    .x2 = plane->state->fb->width,
 	    .y2 = plane->state->fb->height
 	};
-	bool same_shadow = false;
 
 	if (old_state->fb) {
 		bo_old = gem_to_qxl_bo(old_state->fb->obj[0]);
@@ -541,26 +542,13 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
 		bo_old = NULL;
 	}
 
-	if (bo == bo_old)
-		return;
+	primary = bo->shadow ? bo->shadow : bo;
 
-	if (bo_old && bo_old->shadow && bo->shadow &&
-	    bo_old->shadow == bo->shadow) {
-		same_shadow = true;
-	}
-
-	if (bo_old && bo_old->is_primary) {
-		if (!same_shadow)
+	if (!primary->is_primary) {
+		if (qdev->primary_bo)
 			qxl_io_destroy_primary(qdev);
-		bo_old->is_primary = false;
-	}
-
-	if (!bo->is_primary) {
-		if (!same_shadow) {
-			qxl_io_create_primary(qdev, bo);
-			qxl_primary_apply_cursor(plane);
-		}
-		bo->is_primary = true;
+		qxl_io_create_primary(qdev, primary);
+		qxl_primary_apply_cursor(plane);
 	}
 
 	qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1);
@@ -756,6 +744,7 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
 			qxl_bo_create(qdev, user_bo->gem_base.size,
 				      true, true, QXL_GEM_DOMAIN_SURFACE, NULL,
 				      &user_bo->shadow);
+			user_bo->shadow->surf = user_bo->surf;
 		}
 	}
 
@@ -784,7 +773,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
 	user_bo = gem_to_qxl_bo(obj);
 	qxl_bo_unpin(user_bo);
 
-	if (user_bo->shadow && !user_bo->is_primary) {
+	if (user_bo->shadow && !user_bo->shadow->is_primary) {
 		drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
 		user_bo->shadow = NULL;
 	}
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 14/23] drm/qxl: cover all crtcs in shadow bo.
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (12 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 13/23] drm/qxl: use shadow bo directly Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:08   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 15/23] drm/qxl: use qxl_num_crtc directly Gerd Hoffmann
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

The qxl device supports only a single active framebuffer ("primary
surface" in spice terminology).  In multihead configurations are handled
by defining rectangles within the primary surface for each head/crtc.

Userspace which uses the qxl ioctl interface (xorg qxl driver) is aware
of this limitation and will setup framebuffers and crtcs accordingly.

Userspace which uses dumb framebuffers (xorg modesetting driver,
wayland) is not aware of this limitation and tries to use two
framebuffers (one for each crtc) instead.

The qxl kms driver already has the dumb bo separated from the primary
surface, by using a (shared) shadow bo as primary surface.  This is
needed to support pageflips without having to re-create the primary
surface.  The qxl driver will blit from the dumb bo to the shadow bo
instead.

So we can extend the shadow logic:  Maintain a global shadow bo (aka
primary surface), make it big enough that dumb bo's for all crtcs fit in
side-by-side.  Adjust the pageflip blits to place the heads next to each
other in the shadow.

With this patch in place multihead qxl works with wayland.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h     |   5 +-
 drivers/gpu/drm/qxl/qxl_display.c | 119 +++++++++++++++++++++++++++++---------
 drivers/gpu/drm/qxl/qxl_draw.c    |   9 ++-
 3 files changed, 104 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 150b1a4f66..43c6df9cf9 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -230,6 +230,8 @@ struct qxl_device {
 	struct qxl_ram_header *ram_header;
 
 	struct qxl_bo *primary_bo;
+	struct qxl_bo *dumb_shadow_bo;
+	struct qxl_head *dumb_heads;
 
 	struct qxl_memslot main_slot;
 	struct qxl_memslot surfaces_slot;
@@ -437,7 +439,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
 		       struct qxl_bo *bo,
 		       unsigned int flags, unsigned int color,
 		       struct drm_clip_rect *clips,
-		       unsigned int num_clips, int inc);
+		       unsigned int num_clips, int inc,
+		       uint32_t dumb_shadow_offset);
 
 void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec);
 
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index ff13bc6a4a..d9de43e5fd 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -323,6 +323,8 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
 		head.y = crtc->y;
 		if (qdev->monitors_config->count < i + 1)
 			qdev->monitors_config->count = i + 1;
+		if (qdev->primary_bo == qdev->dumb_shadow_bo)
+			head.x += qdev->dumb_heads[i].x;
 	} else if (i > 0) {
 		head.width = 0;
 		head.height = 0;
@@ -426,7 +428,7 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
 	}
 
 	qxl_draw_dirty_fb(qdev, fb, qobj, flags, color,
-			  clips, num_clips, inc);
+			  clips, num_clips, inc, 0);
 
 	drm_modeset_unlock_all(fb->dev);
 
@@ -535,6 +537,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
 	    .x2 = plane->state->fb->width,
 	    .y2 = plane->state->fb->height
 	};
+	uint32_t dumb_shadow_offset = 0;
 
 	if (old_state->fb) {
 		bo_old = gem_to_qxl_bo(old_state->fb->obj[0]);
@@ -551,7 +554,12 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
 		qxl_primary_apply_cursor(plane);
 	}
 
-	qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1);
+	if (bo->is_dumb)
+		dumb_shadow_offset =
+			qdev->dumb_heads[plane->state->crtc->index].x;
+
+	qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1,
+			  dumb_shadow_offset);
 }
 
 static void qxl_primary_atomic_disable(struct drm_plane *plane,
@@ -707,12 +715,68 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
 	qxl_release_fence_buffer_objects(release);
 }
 
+static void qxl_update_dumb_head(struct qxl_device *qdev,
+				 int index, struct qxl_bo *bo)
+{
+	uint32_t width, height;
+
+	if (index >= qdev->monitors_config->max_allowed)
+		return;
+
+	if (bo && bo->is_dumb) {
+		width = bo->surf.width;
+		height = bo->surf.height;
+	} else {
+		width = 0;
+		height = 0;
+	}
+
+	if (qdev->dumb_heads[index].width == width &&
+	    qdev->dumb_heads[index].height == height)
+		return;
+
+	DRM_DEBUG("#%d: %dx%d -> %dx%d\n", index,
+		  qdev->dumb_heads[index].width,
+		  qdev->dumb_heads[index].height,
+		  width, height);
+	qdev->dumb_heads[index].width = width;
+	qdev->dumb_heads[index].height = height;
+}
+
+static void qxl_calc_dumb_shadow(struct qxl_device *qdev,
+				 struct qxl_surface *surf)
+{
+	struct qxl_head *head;
+	int i;
+
+	memset(surf, 0, sizeof(*surf));
+	for (i = 0; i < qdev->monitors_config->max_allowed; i++) {
+		head = qdev->dumb_heads + i;
+		head->x = surf->width;
+		surf->width += head->width;
+		if (surf->height < head->height)
+			surf->height = head->height;
+	}
+	if (surf->width < 64)
+		surf->width = 64;
+	if (surf->height < 64)
+		surf->height = 64;
+	surf->format = SPICE_SURFACE_FMT_32_xRGB;
+	surf->stride = surf->width * 4;
+
+	if (!qdev->dumb_shadow_bo ||
+	    qdev->dumb_shadow_bo->surf.width != surf->width ||
+	    qdev->dumb_shadow_bo->surf.height != surf->height)
+		DRM_DEBUG("%dx%d\n", surf->width, surf->height);
+}
+
 static int qxl_plane_prepare_fb(struct drm_plane *plane,
 				struct drm_plane_state *new_state)
 {
 	struct qxl_device *qdev = plane->dev->dev_private;
 	struct drm_gem_object *obj;
-	struct qxl_bo *user_bo, *old_bo = NULL;
+	struct qxl_bo *user_bo;
+	struct qxl_surface surf;
 	int ret;
 
 	if (!new_state->fb)
@@ -722,29 +786,30 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
 	user_bo = gem_to_qxl_bo(obj);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
-	    user_bo->is_dumb && !user_bo->shadow) {
-		if (plane->state->fb) {
-			obj = plane->state->fb->obj[0];
-			old_bo = gem_to_qxl_bo(obj);
+	    user_bo->is_dumb) {
+		qxl_update_dumb_head(qdev, new_state->crtc->index,
+				     user_bo);
+		qxl_calc_dumb_shadow(qdev, &surf);
+		if (!qdev->dumb_shadow_bo ||
+		    qdev->dumb_shadow_bo->surf.width  != surf.width ||
+		    qdev->dumb_shadow_bo->surf.height != surf.height) {
+			if (qdev->dumb_shadow_bo) {
+				drm_gem_object_put_unlocked
+					(&qdev->dumb_shadow_bo->gem_base);
+				qdev->dumb_shadow_bo = NULL;
+			}
+			qxl_bo_create(qdev, surf.height * surf.stride,
+				      true, true, QXL_GEM_DOMAIN_SURFACE, &surf,
+				      &qdev->dumb_shadow_bo);
 		}
-		if (old_bo && old_bo->shadow &&
-		    user_bo->gem_base.size == old_bo->gem_base.size &&
-		    plane->state->crtc     == new_state->crtc &&
-		    plane->state->crtc_w   == new_state->crtc_w &&
-		    plane->state->crtc_h   == new_state->crtc_h &&
-		    plane->state->src_x    == new_state->src_x &&
-		    plane->state->src_y    == new_state->src_y &&
-		    plane->state->src_w    == new_state->src_w &&
-		    plane->state->src_h    == new_state->src_h &&
-		    plane->state->rotation == new_state->rotation &&
-		    plane->state->zpos     == new_state->zpos) {
-			drm_gem_object_get(&old_bo->shadow->gem_base);
-			user_bo->shadow = old_bo->shadow;
-		} else {
-			qxl_bo_create(qdev, user_bo->gem_base.size,
-				      true, true, QXL_GEM_DOMAIN_SURFACE, NULL,
-				      &user_bo->shadow);
-			user_bo->shadow->surf = user_bo->surf;
+		if (user_bo->shadow != qdev->dumb_shadow_bo) {
+			if (user_bo->shadow) {
+				drm_gem_object_put_unlocked
+					(&user_bo->shadow->gem_base);
+				user_bo->shadow = NULL;
+			}
+			drm_gem_object_get(&qdev->dumb_shadow_bo->gem_base);
+			user_bo->shadow = qdev->dumb_shadow_bo;
 		}
 	}
 
@@ -773,7 +838,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
 	user_bo = gem_to_qxl_bo(obj);
 	qxl_bo_unpin(user_bo);
 
-	if (user_bo->shadow && !user_bo->shadow->is_primary) {
+	if (old_state->fb != plane->state->fb && user_bo->shadow) {
 		drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
 		user_bo->shadow = NULL;
 	}
@@ -1106,6 +1171,8 @@ int qxl_create_monitors_object(struct qxl_device *qdev)
 
 	memset(qdev->monitors_config, 0, monitors_config_size);
 	qdev->monitors_config->max_allowed = max_allowed;
+
+	qdev->dumb_heads = kcalloc(max_allowed, sizeof(qdev->dumb_heads[0]), GFP_KERNEL);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c
index c408bb83c7..5313ad21c1 100644
--- a/drivers/gpu/drm/qxl/qxl_draw.c
+++ b/drivers/gpu/drm/qxl/qxl_draw.c
@@ -267,7 +267,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
 		       struct qxl_bo *bo,
 		       unsigned int flags, unsigned int color,
 		       struct drm_clip_rect *clips,
-		       unsigned int num_clips, int inc)
+		       unsigned int num_clips, int inc,
+		       uint32_t dumb_shadow_offset)
 {
 	/*
 	 * TODO: if flags & DRM_MODE_FB_DIRTY_ANNOTATE_FILL then we should
@@ -295,6 +296,9 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
 	if (ret)
 		return;
 
+	clips->x1 += dumb_shadow_offset;
+	clips->x2 += dumb_shadow_offset;
+
 	left = clips->x1;
 	right = clips->x2;
 	top = clips->y1;
@@ -342,7 +346,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
 		goto out_release_backoff;
 
 	ret = qxl_image_init(qdev, release, dimage, surface_base,
-			     left, top, width, height, depth, stride);
+			     left - dumb_shadow_offset,
+			     top, width, height, depth, stride);
 	qxl_bo_kunmap(bo);
 	if (ret)
 		goto out_release_backoff;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 15/23] drm/qxl: use qxl_num_crtc directly
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (13 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 14/23] drm/qxl: cover all crtcs in shadow bo Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:12   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 16/23] drm/qxl: implement prime kmap/kunmap Gerd Hoffmann
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

qdev->monitors_config->max_allowed is effectively set by the
qxl.num_heads module parameter, stored in the qxl_num_crtc variable.
Lets get rid of the indirection and use the variable qxl_num_crtc
directly.  The kernel doesn't need to dereference pointers each time it
needs the value, and when reading the code you don't have to trace where
and why qdev->monitors_config->max_allowed is set.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_display.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index d9de43e5fd..ef832f98ab 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -80,10 +80,10 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
 		DRM_DEBUG_KMS("no client monitors configured\n");
 		return status;
 	}
-	if (num_monitors > qdev->monitors_config->max_allowed) {
+	if (num_monitors > qxl_num_crtc) {
 		DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n",
-			      qdev->monitors_config->max_allowed, num_monitors);
-		num_monitors = qdev->monitors_config->max_allowed;
+			      qxl_num_crtc, num_monitors);
+		num_monitors = qxl_num_crtc;
 	} else {
 		num_monitors = qdev->rom->client_monitors_config.count;
 	}
@@ -96,8 +96,7 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
 		return status;
 	}
 	/* we copy max from the client but it isn't used */
-	qdev->client_monitors_config->max_allowed =
-				qdev->monitors_config->max_allowed;
+	qdev->client_monitors_config->max_allowed = qxl_num_crtc;
 	for (i = 0 ; i < qdev->client_monitors_config->count ; ++i) {
 		struct qxl_urect *c_rect =
 			&qdev->rom->client_monitors_config.heads[i];
@@ -204,7 +203,7 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
 
 	if (!qdev->monitors_config)
 		return 0;
-	if (h >= qdev->monitors_config->max_allowed)
+	if (h >= qxl_num_crtc)
 		return 0;
 	if (!qdev->client_monitors_config)
 		return 0;
@@ -307,8 +306,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
 		return;
 	}
 
-	if (!qdev->monitors_config ||
-	    qdev->monitors_config->max_allowed <= i)
+	if (!qdev->monitors_config || qxl_num_crtc <= i)
 		return;
 
 	head.id = i;
@@ -350,9 +348,10 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
 	if (oldcount != qdev->monitors_config->count)
 		DRM_DEBUG_KMS("active heads %d -> %d (%d total)\n",
 			      oldcount, qdev->monitors_config->count,
-			      qdev->monitors_config->max_allowed);
+			      qxl_num_crtc);
 
 	qdev->monitors_config->heads[i] = head;
+	qdev->monitors_config->max_allowed = qxl_num_crtc;
 	qxl_send_monitors_config(qdev);
 }
 
@@ -1146,9 +1145,8 @@ int qxl_create_monitors_object(struct qxl_device *qdev)
 {
 	int ret;
 	struct drm_gem_object *gobj;
-	int max_allowed = qxl_num_crtc;
 	int monitors_config_size = sizeof(struct qxl_monitors_config) +
-		max_allowed * sizeof(struct qxl_head);
+		qxl_num_crtc * sizeof(struct qxl_head);
 
 	ret = qxl_gem_object_create(qdev, monitors_config_size, 0,
 				    QXL_GEM_DOMAIN_VRAM,
@@ -1170,9 +1168,8 @@ int qxl_create_monitors_object(struct qxl_device *qdev)
 		qxl_bo_physical_address(qdev, qdev->monitors_config_bo, 0);
 
 	memset(qdev->monitors_config, 0, monitors_config_size);
-	qdev->monitors_config->max_allowed = max_allowed;
-
-	qdev->dumb_heads = kcalloc(max_allowed, sizeof(qdev->dumb_heads[0]), GFP_KERNEL);
+	qdev->dumb_heads = kcalloc(qxl_num_crtc, sizeof(qdev->dumb_heads[0]),
+				   GFP_KERNEL);
 	return 0;
 }
 
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 16/23] drm/qxl: implement prime kmap/kunmap
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (14 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 15/23] drm/qxl: use qxl_num_crtc directly Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:19   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 17/23] drm/qxl: use generic fbdev emulation Gerd Hoffmann
                   ` (6 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Generic fbdev emulation needs this.  Also: We must keep track of the
number of mappings now, so we don't unmap early in case two users want a
kmap of the same bo.  Add a sanity check to destroy callback to make
sure kmap/kunmap is balanced.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h    |  1 +
 drivers/gpu/drm/qxl/qxl_object.c |  6 ++++++
 drivers/gpu/drm/qxl/qxl_prime.c  | 17 +++++++++++++----
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 43c6df9cf9..8c3af1cdbe 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -84,6 +84,7 @@ struct qxl_bo {
 	struct ttm_bo_kmap_obj		kmap;
 	unsigned int pin_count;
 	void				*kptr;
+	unsigned int                    map_count;
 	int                             type;
 
 	/* Constant after initialization */
diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c
index 024c8dd317..4928fa6029 100644
--- a/drivers/gpu/drm/qxl/qxl_object.c
+++ b/drivers/gpu/drm/qxl/qxl_object.c
@@ -36,6 +36,7 @@ static void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo)
 	qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
 
 	qxl_surface_evict(qdev, bo, false);
+	WARN_ON_ONCE(bo->map_count > 0);
 	mutex_lock(&qdev->gem.mutex);
 	list_del_init(&bo->list);
 	mutex_unlock(&qdev->gem.mutex);
@@ -131,6 +132,7 @@ int qxl_bo_kmap(struct qxl_bo *bo, void **ptr)
 	if (bo->kptr) {
 		if (ptr)
 			*ptr = bo->kptr;
+		bo->map_count++;
 		return 0;
 	}
 	r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
@@ -139,6 +141,7 @@ int qxl_bo_kmap(struct qxl_bo *bo, void **ptr)
 	bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
 	if (ptr)
 		*ptr = bo->kptr;
+	bo->map_count = 1;
 	return 0;
 }
 
@@ -180,6 +183,9 @@ void qxl_bo_kunmap(struct qxl_bo *bo)
 {
 	if (bo->kptr == NULL)
 		return;
+	bo->map_count--;
+	if (bo->map_count > 0)
+		return;
 	bo->kptr = NULL;
 	ttm_bo_kunmap(&bo->kmap);
 }
diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c
index a55dece118..708378844c 100644
--- a/drivers/gpu/drm/qxl/qxl_prime.c
+++ b/drivers/gpu/drm/qxl/qxl_prime.c
@@ -22,7 +22,7 @@
  * Authors: Andreas Pokorny
  */
 
-#include "qxl_drv.h"
+#include "qxl_object.h"
 
 /* Empty Implementations as there should not be any other driver for a virtual
  * device that might share buffers with qxl */
@@ -54,13 +54,22 @@ struct drm_gem_object *qxl_gem_prime_import_sg_table(
 
 void *qxl_gem_prime_vmap(struct drm_gem_object *obj)
 {
-	WARN_ONCE(1, "not implemented");
-	return ERR_PTR(-ENOSYS);
+	struct qxl_bo *bo = gem_to_qxl_bo(obj);
+	void *ptr;
+	int ret;
+
+	ret = qxl_bo_kmap(bo, &ptr);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	return ptr;
 }
 
 void qxl_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
 {
-	WARN_ONCE(1, "not implemented");
+	struct qxl_bo *bo = gem_to_qxl_bo(obj);
+
+	qxl_bo_kunmap(bo);
 }
 
 int qxl_gem_prime_mmap(struct drm_gem_object *obj,
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 17/23] drm/qxl: use generic fbdev emulation
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (15 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 16/23] drm/qxl: implement prime kmap/kunmap Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:25   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code Gerd Hoffmann
                   ` (5 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Switch qxl over to the new generic fbdev emulation.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_display.c | 7 -------
 drivers/gpu/drm/qxl/qxl_drv.c     | 2 ++
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index ef832f98ab..9c751f01e3 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -1221,18 +1221,11 @@ int qxl_modeset_init(struct qxl_device *qdev)
 	qxl_display_read_client_monitors_config(qdev);
 
 	drm_mode_config_reset(&qdev->ddev);
-
-	/* primary surface must be created by this point, to allow
-	 * issuing command queue commands and having them read by
-	 * spice server. */
-	qxl_fbdev_init(qdev);
 	return 0;
 }
 
 void qxl_modeset_fini(struct qxl_device *qdev)
 {
-	qxl_fbdev_fini(qdev);
-
 	qxl_destroy_monitors_object(qdev);
 	drm_mode_config_cleanup(&qdev->ddev);
 }
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 13c8a662f9..3fce7d16df 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -93,6 +93,8 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (ret)
 		goto modeset_cleanup;
 
+	drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "qxl");
+	drm_fbdev_generic_setup(&qdev->ddev, 32);
 	return 0;
 
 modeset_cleanup:
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (16 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 17/23] drm/qxl: use generic fbdev emulation Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:25   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 19/23] drm/qxl: implement qxl_gem_prime_(un)pin Gerd Hoffmann
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list, open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU

Lovely diffstat, thanks to the new generic fbdev emulation.

 drm/qxl/Makefile   |    2
 drm/qxl/qxl_draw.c |  232 ----------------------------------------
 drm/qxl/qxl_drv.h  |   21 ---
 drm/qxl/qxl_fb.c   |  300 -----------------------------------------------------

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_drv.h  |  21 ---
 drivers/gpu/drm/qxl/qxl_draw.c | 232 -------------------------------
 drivers/gpu/drm/qxl/qxl_fb.c   | 300 -----------------------------------------
 drivers/gpu/drm/qxl/Makefile   |   2 +-
 4 files changed, 1 insertion(+), 554 deletions(-)
 delete mode 100644 drivers/gpu/drm/qxl/qxl_fb.c

diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 8c3af1cdbe..4a0331b3ff 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -220,8 +220,6 @@ struct qxl_device {
 	struct qxl_mman		mman;
 	struct qxl_gem		gem;
 
-	struct drm_fb_helper	fb_helper;
-
 	void *ram_physical;
 
 	struct qxl_ring *release_ring;
@@ -322,12 +320,6 @@ qxl_bo_physical_address(struct qxl_device *qdev, struct qxl_bo *bo,
 	return slot->high_bits | (bo->tbo.offset - slot->gpu_offset + offset);
 }
 
-/* qxl_fb.c */
-#define QXLFB_CONN_LIMIT 1
-
-int qxl_fbdev_init(struct qxl_device *qdev);
-void qxl_fbdev_fini(struct qxl_device *qdev);
-
 /* qxl_display.c */
 void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
 int qxl_create_monitors_object(struct qxl_device *qdev);
@@ -432,9 +424,6 @@ int qxl_alloc_bo_reserved(struct qxl_device *qdev,
 			  struct qxl_bo **_bo);
 /* qxl drawing commands */
 
-void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image,
-			int stride /* filled in if 0 */);
-
 void qxl_draw_dirty_fb(struct qxl_device *qdev,
 		       struct drm_framebuffer *fb,
 		       struct qxl_bo *bo,
@@ -443,13 +432,6 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
 		       unsigned int num_clips, int inc,
 		       uint32_t dumb_shadow_offset);
 
-void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec);
-
-void qxl_draw_copyarea(struct qxl_device *qdev,
-		       u32 width, u32 height,
-		       u32 sx, u32 sy,
-		       u32 dx, u32 dy);
-
 void qxl_release_free(struct qxl_device *qdev,
 		      struct qxl_release *release);
 
@@ -481,9 +463,6 @@ int qxl_gem_prime_mmap(struct drm_gem_object *obj,
 int qxl_irq_init(struct qxl_device *qdev);
 irqreturn_t qxl_irq_handler(int irq, void *arg);
 
-/* qxl_fb.c */
-bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj);
-
 int qxl_debugfs_add_files(struct qxl_device *qdev,
 			  struct drm_info_list *files,
 			  unsigned int nfiles);
diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c
index 5313ad21c1..97c3f1a95a 100644
--- a/drivers/gpu/drm/qxl/qxl_draw.c
+++ b/drivers/gpu/drm/qxl/qxl_draw.c
@@ -109,152 +109,6 @@ make_drawable(struct qxl_device *qdev, int surface, uint8_t type,
 	return 0;
 }
 
-static int alloc_palette_object(struct qxl_device *qdev,
-				struct qxl_release *release,
-				struct qxl_bo **palette_bo)
-{
-	return qxl_alloc_bo_reserved(qdev, release,
-				     sizeof(struct qxl_palette) + sizeof(uint32_t) * 2,
-				     palette_bo);
-}
-
-static int qxl_palette_create_1bit(struct qxl_bo *palette_bo,
-				   struct qxl_release *release,
-				   const struct qxl_fb_image *qxl_fb_image)
-{
-	const struct fb_image *fb_image = &qxl_fb_image->fb_image;
-	uint32_t visual = qxl_fb_image->visual;
-	const uint32_t *pseudo_palette = qxl_fb_image->pseudo_palette;
-	struct qxl_palette *pal;
-	int ret;
-	uint32_t fgcolor, bgcolor;
-	static uint64_t unique; /* we make no attempt to actually set this
-				 * correctly globaly, since that would require
-				 * tracking all of our palettes. */
-	ret = qxl_bo_kmap(palette_bo, (void **)&pal);
-	if (ret)
-		return ret;
-	pal->num_ents = 2;
-	pal->unique = unique++;
-	if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) {
-		/* NB: this is the only used branch currently. */
-		fgcolor = pseudo_palette[fb_image->fg_color];
-		bgcolor = pseudo_palette[fb_image->bg_color];
-	} else {
-		fgcolor = fb_image->fg_color;
-		bgcolor = fb_image->bg_color;
-	}
-	pal->ents[0] = bgcolor;
-	pal->ents[1] = fgcolor;
-	qxl_bo_kunmap(palette_bo);
-	return 0;
-}
-
-void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image,
-			int stride /* filled in if 0 */)
-{
-	struct qxl_device *qdev = qxl_fb_image->qdev;
-	struct qxl_drawable *drawable;
-	struct qxl_rect rect;
-	const struct fb_image *fb_image = &qxl_fb_image->fb_image;
-	int x = fb_image->dx;
-	int y = fb_image->dy;
-	int width = fb_image->width;
-	int height = fb_image->height;
-	const char *src = fb_image->data;
-	int depth = fb_image->depth;
-	struct qxl_release *release;
-	struct qxl_image *image;
-	int ret;
-	struct qxl_drm_image *dimage;
-	struct qxl_bo *palette_bo = NULL;
-
-	if (stride == 0)
-		stride = depth * width / 8;
-
-	ret = alloc_drawable(qdev, &release);
-	if (ret)
-		return;
-
-	ret = qxl_image_alloc_objects(qdev, release,
-				      &dimage,
-				      height, stride);
-	if (ret)
-		goto out_free_drawable;
-
-	if (depth == 1) {
-		ret = alloc_palette_object(qdev, release, &palette_bo);
-		if (ret)
-			goto out_free_image;
-	}
-
-	/* do a reservation run over all the objects we just allocated */
-	ret = qxl_release_reserve_list(release, true);
-	if (ret)
-		goto out_free_palette;
-
-	rect.left = x;
-	rect.right = x + width;
-	rect.top = y;
-	rect.bottom = y + height;
-
-	ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &rect, release);
-	if (ret) {
-		qxl_release_backoff_reserve_list(release);
-		goto out_free_palette;
-	}
-
-	ret = qxl_image_init(qdev, release, dimage,
-			     (const uint8_t *)src, 0, 0,
-			     width, height, depth, stride);
-	if (ret) {
-		qxl_release_backoff_reserve_list(release);
-		qxl_release_free(qdev, release);
-		return;
-	}
-
-	if (depth == 1) {
-		void *ptr;
-
-		ret = qxl_palette_create_1bit(palette_bo, release, qxl_fb_image);
-
-		ptr = qxl_bo_kmap_atomic_page(qdev, dimage->bo, 0);
-		image = ptr;
-		image->u.bitmap.palette =
-			qxl_bo_physical_address(qdev, palette_bo, 0);
-		qxl_bo_kunmap_atomic_page(qdev, dimage->bo, ptr);
-	}
-
-	drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
-
-	drawable->u.copy.src_area.top = 0;
-	drawable->u.copy.src_area.bottom = height;
-	drawable->u.copy.src_area.left = 0;
-	drawable->u.copy.src_area.right = width;
-
-	drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
-	drawable->u.copy.scale_mode = 0;
-	drawable->u.copy.mask.flags = 0;
-	drawable->u.copy.mask.pos.x = 0;
-	drawable->u.copy.mask.pos.y = 0;
-	drawable->u.copy.mask.bitmap = 0;
-
-	drawable->u.copy.src_bitmap =
-		qxl_bo_physical_address(qdev, dimage->bo, 0);
-	qxl_release_unmap(qdev, release, &drawable->release_info);
-
-	qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
-	qxl_release_fence_buffer_objects(release);
-
-out_free_palette:
-	qxl_bo_unref(&palette_bo);
-out_free_image:
-	qxl_image_free_objects(qdev, dimage);
-out_free_drawable:
-	if (ret)
-		free_drawable(qdev, release);
-}
-
 /* push a draw command using the given clipping rectangles as
  * the sources from the shadow framebuffer.
  *
@@ -402,89 +256,3 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
 		free_drawable(qdev, release);
 
 }
-
-void qxl_draw_copyarea(struct qxl_device *qdev,
-		       u32 width, u32 height,
-		       u32 sx, u32 sy,
-		       u32 dx, u32 dy)
-{
-	struct qxl_drawable *drawable;
-	struct qxl_rect rect;
-	struct qxl_release *release;
-	int ret;
-
-	ret = alloc_drawable(qdev, &release);
-	if (ret)
-		return;
-
-	/* do a reservation run over all the objects we just allocated */
-	ret = qxl_release_reserve_list(release, true);
-	if (ret)
-		goto out_free_release;
-
-	rect.left = dx;
-	rect.top = dy;
-	rect.right = dx + width;
-	rect.bottom = dy + height;
-	ret = make_drawable(qdev, 0, QXL_COPY_BITS, &rect, release);
-	if (ret) {
-		qxl_release_backoff_reserve_list(release);
-		goto out_free_release;
-	}
-
-	drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
-	drawable->u.copy_bits.src_pos.x = sx;
-	drawable->u.copy_bits.src_pos.y = sy;
-	qxl_release_unmap(qdev, release, &drawable->release_info);
-
-	qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
-	qxl_release_fence_buffer_objects(release);
-
-out_free_release:
-	if (ret)
-		free_drawable(qdev, release);
-}
-
-void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec)
-{
-	struct qxl_device *qdev = qxl_draw_fill_rec->qdev;
-	struct qxl_rect rect = qxl_draw_fill_rec->rect;
-	uint32_t color = qxl_draw_fill_rec->color;
-	uint16_t rop = qxl_draw_fill_rec->rop;
-	struct qxl_drawable *drawable;
-	struct qxl_release *release;
-	int ret;
-
-	ret = alloc_drawable(qdev, &release);
-	if (ret)
-		return;
-
-	/* do a reservation run over all the objects we just allocated */
-	ret = qxl_release_reserve_list(release, true);
-	if (ret)
-		goto out_free_release;
-
-	ret = make_drawable(qdev, 0, QXL_DRAW_FILL, &rect, release);
-	if (ret) {
-		qxl_release_backoff_reserve_list(release);
-		goto out_free_release;
-	}
-
-	drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
-	drawable->u.fill.brush.type = SPICE_BRUSH_TYPE_SOLID;
-	drawable->u.fill.brush.u.color = color;
-	drawable->u.fill.rop_descriptor = rop;
-	drawable->u.fill.mask.flags = 0;
-	drawable->u.fill.mask.pos.x = 0;
-	drawable->u.fill.mask.pos.y = 0;
-	drawable->u.fill.mask.bitmap = 0;
-
-	qxl_release_unmap(qdev, release, &drawable->release_info);
-
-	qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
-	qxl_release_fence_buffer_objects(release);
-
-out_free_release:
-	if (ret)
-		free_drawable(qdev, release);
-}
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
deleted file mode 100644
index a819d24225..0000000000
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright © 2013 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *     David Airlie
- */
-#include <linux/module.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-
-#include "qxl_drv.h"
-
-#include "qxl_object.h"
-
-static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image,
-			      struct qxl_device *qdev, struct fb_info *info,
-			      const struct fb_image *image)
-{
-	qxl_fb_image->qdev = qdev;
-	if (info) {
-		qxl_fb_image->visual = info->fix.visual;
-		if (qxl_fb_image->visual == FB_VISUAL_TRUECOLOR ||
-		    qxl_fb_image->visual == FB_VISUAL_DIRECTCOLOR)
-			memcpy(&qxl_fb_image->pseudo_palette,
-			       info->pseudo_palette,
-			       sizeof(qxl_fb_image->pseudo_palette));
-	} else {
-		 /* fallback */
-		if (image->depth == 1)
-			qxl_fb_image->visual = FB_VISUAL_MONO10;
-		else
-			qxl_fb_image->visual = FB_VISUAL_DIRECTCOLOR;
-	}
-	if (image) {
-		memcpy(&qxl_fb_image->fb_image, image,
-		       sizeof(qxl_fb_image->fb_image));
-	}
-}
-
-static struct fb_ops qxlfb_ops = {
-	.owner = THIS_MODULE,
-	DRM_FB_HELPER_DEFAULT_OPS,
-	.fb_fillrect = drm_fb_helper_sys_fillrect,
-	.fb_copyarea = drm_fb_helper_sys_copyarea,
-	.fb_imageblit = drm_fb_helper_sys_imageblit,
-};
-
-static void qxlfb_destroy_pinned_object(struct drm_gem_object *gobj)
-{
-	struct qxl_bo *qbo = gem_to_qxl_bo(gobj);
-
-	qxl_bo_kunmap(qbo);
-	qxl_bo_unpin(qbo);
-
-	drm_gem_object_put_unlocked(gobj);
-}
-
-static int qxlfb_create_pinned_object(struct qxl_device *qdev,
-				      const struct drm_mode_fb_cmd2 *mode_cmd,
-				      struct drm_gem_object **gobj_p)
-{
-	struct drm_gem_object *gobj = NULL;
-	struct qxl_bo *qbo = NULL;
-	int ret;
-	int aligned_size, size;
-	int height = mode_cmd->height;
-
-	size = mode_cmd->pitches[0] * height;
-	aligned_size = ALIGN(size, PAGE_SIZE);
-	/* TODO: unallocate and reallocate surface0 for real. Hack to just
-	 * have a large enough surface0 for 1024x768 Xorg 32bpp mode */
-	ret = qxl_gem_object_create(qdev, aligned_size, 0,
-				    QXL_GEM_DOMAIN_SURFACE,
-				    false, /* is discardable */
-				    false, /* is kernel (false means device) */
-				    NULL,
-				    &gobj);
-	if (ret) {
-		pr_err("failed to allocate framebuffer (%d)\n",
-		       aligned_size);
-		return -ENOMEM;
-	}
-	qbo = gem_to_qxl_bo(gobj);
-
-	qbo->surf.width = mode_cmd->width;
-	qbo->surf.height = mode_cmd->height;
-	qbo->surf.stride = mode_cmd->pitches[0];
-	qbo->surf.format = SPICE_SURFACE_FMT_32_xRGB;
-
-	ret = qxl_bo_pin(qbo);
-	if (ret) {
-		goto out_unref;
-	}
-	ret = qxl_bo_kmap(qbo, NULL);
-
-	if (ret)
-		goto out_unref;
-
-	*gobj_p = gobj;
-	return 0;
-out_unref:
-	qxlfb_destroy_pinned_object(gobj);
-	*gobj_p = NULL;
-	return ret;
-}
-
-/*
- * FIXME
- * It should not be necessary to have a special dirty() callback for fbdev.
- */
-static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb,
-				   struct drm_file *file_priv,
-				   unsigned int flags, unsigned int color,
-				   struct drm_clip_rect *clips,
-				   unsigned int num_clips)
-{
-	struct qxl_device *qdev = fb->dev->dev_private;
-	struct fb_info *info = qdev->fb_helper.fbdev;
-	struct qxl_fb_image qxl_fb_image;
-	struct fb_image *image = &qxl_fb_image.fb_image;
-
-	/* TODO: hard coding 32 bpp */
-	int stride = fb->pitches[0];
-
-	/*
-	 * we are using a shadow draw buffer, at qdev->surface0_shadow
-	 */
-	image->dx = clips->x1;
-	image->dy = clips->y1;
-	image->width = clips->x2 - clips->x1;
-	image->height = clips->y2 - clips->y1;
-	image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized
-					 warnings */
-	image->bg_color = 0;
-	image->depth = 32;	     /* TODO: take from somewhere? */
-	image->cmap.start = 0;
-	image->cmap.len = 0;
-	image->cmap.red = NULL;
-	image->cmap.green = NULL;
-	image->cmap.blue = NULL;
-	image->cmap.transp = NULL;
-	image->data = info->screen_base + (clips->x1 * 4) + (stride * clips->y1);
-
-	qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
-	qxl_draw_opaque_fb(&qxl_fb_image, stride);
-
-	return 0;
-}
-
-static const struct drm_framebuffer_funcs qxlfb_fb_funcs = {
-	.destroy = drm_gem_fb_destroy,
-	.create_handle = drm_gem_fb_create_handle,
-	.dirty = qxlfb_framebuffer_dirty,
-};
-
-static int qxlfb_create(struct drm_fb_helper *helper,
-			struct drm_fb_helper_surface_size *sizes)
-{
-	struct qxl_device *qdev =
-		container_of(helper, struct qxl_device, fb_helper);
-	struct fb_info *info;
-	struct drm_framebuffer *fb = NULL;
-	struct drm_mode_fb_cmd2 mode_cmd;
-	struct drm_gem_object *gobj = NULL;
-	struct qxl_bo *qbo = NULL;
-	int ret;
-	int bpp = sizes->surface_bpp;
-	int depth = sizes->surface_depth;
-	void *shadow;
-
-	mode_cmd.width = sizes->surface_width;
-	mode_cmd.height = sizes->surface_height;
-
-	mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 1) / 8), 64);
-	mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
-
-	ret = qxlfb_create_pinned_object(qdev, &mode_cmd, &gobj);
-	if (ret < 0)
-		return ret;
-
-	qbo = gem_to_qxl_bo(gobj);
-	DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width,
-			 mode_cmd.height, mode_cmd.pitches[0]);
-
-	shadow = vmalloc(array_size(mode_cmd.pitches[0], mode_cmd.height));
-	/* TODO: what's the usual response to memory allocation errors? */
-	BUG_ON(!shadow);
-	DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
-			 qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo),
-			 qbo->kptr, shadow);
-
-	info = drm_fb_helper_alloc_fbi(helper);
-	if (IS_ERR(info)) {
-		ret = PTR_ERR(info);
-		goto out_unref;
-	}
-
-	info->par = helper;
-
-	fb = drm_gem_fbdev_fb_create(&qdev->ddev, sizes, 64, gobj,
-				     &qxlfb_fb_funcs);
-	if (IS_ERR(fb)) {
-		DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb));
-		ret = PTR_ERR(fb);
-		goto out_unref;
-	}
-
-	/* setup helper with fb data */
-	qdev->fb_helper.fb = fb;
-
-	strcpy(info->fix.id, "qxldrmfb");
-
-	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
-
-	info->fbops = &qxlfb_ops;
-
-	/*
-	 * TODO: using gobj->size in various places in this function. Not sure
-	 * what the difference between the different sizes is.
-	 */
-	info->fix.smem_start = qdev->vram_base; /* TODO - correct? */
-	info->fix.smem_len = gobj->size;
-	info->screen_base = shadow;
-	info->screen_size = gobj->size;
-
-	drm_fb_helper_fill_var(info, &qdev->fb_helper, sizes->fb_width,
-			       sizes->fb_height);
-
-	/* setup aperture base/size for vesafb takeover */
-	info->apertures->ranges[0].base = qdev->ddev.mode_config.fb_base;
-	info->apertures->ranges[0].size = qdev->vram_size;
-
-	info->fix.mmio_start = 0;
-	info->fix.mmio_len = 0;
-
-	if (info->screen_base == NULL) {
-		ret = -ENOSPC;
-		goto out_unref;
-	}
-
-	/* XXX error handling. */
-	drm_fb_helper_defio_init(helper);
-
-	DRM_INFO("fb mappable at 0x%lX, size %lu\n",  info->fix.smem_start, (unsigned long)info->screen_size);
-	DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n",
-		 fb->format->depth, fb->pitches[0], fb->width, fb->height);
-	return 0;
-
-out_unref:
-	if (qbo) {
-		qxl_bo_kunmap(qbo);
-		qxl_bo_unpin(qbo);
-	}
-	drm_gem_object_put_unlocked(gobj);
-	return ret;
-}
-
-static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
-	.fb_probe = qxlfb_create,
-};
-
-int qxl_fbdev_init(struct qxl_device *qdev)
-{
-	return drm_fb_helper_fbdev_setup(&qdev->ddev, &qdev->fb_helper,
-					 &qxl_fb_helper_funcs, 32,
-					 QXLFB_CONN_LIMIT);
-}
-
-void qxl_fbdev_fini(struct qxl_device *qdev)
-{
-	struct fb_info *fbi = qdev->fb_helper.fbdev;
-	void *shadow = fbi ? fbi->screen_buffer : NULL;
-
-	drm_fb_helper_fbdev_teardown(&qdev->ddev);
-	vfree(shadow);
-}
diff --git a/drivers/gpu/drm/qxl/Makefile b/drivers/gpu/drm/qxl/Makefile
index 33a7d0c434..fc59d42b31 100644
--- a/drivers/gpu/drm/qxl/Makefile
+++ b/drivers/gpu/drm/qxl/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-qxl-y := qxl_drv.o qxl_kms.o qxl_display.o qxl_ttm.o qxl_fb.o qxl_object.o qxl_gem.o qxl_cmd.o qxl_image.o qxl_draw.o qxl_debugfs.o qxl_irq.o qxl_dumb.o qxl_ioctl.o qxl_release.o qxl_prime.o
+qxl-y := qxl_drv.o qxl_kms.o qxl_display.o qxl_ttm.o qxl_object.o qxl_gem.o qxl_cmd.o qxl_image.o qxl_draw.o qxl_debugfs.o qxl_irq.o qxl_dumb.o qxl_ioctl.o qxl_release.o qxl_prime.o
 
 obj-$(CONFIG_DRM_QXL)+= qxl.o
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 19/23] drm/qxl: implement qxl_gem_prime_(un)pin
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (17 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:26   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 20/23] drm/qxl: add mode/framebuffer check functions Gerd Hoffmann
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_prime.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c
index 708378844c..22e1faf047 100644
--- a/drivers/gpu/drm/qxl/qxl_prime.c
+++ b/drivers/gpu/drm/qxl/qxl_prime.c
@@ -22,6 +22,7 @@
  * Authors: Andreas Pokorny
  */
 
+#include "qxl_drv.h"
 #include "qxl_object.h"
 
 /* Empty Implementations as there should not be any other driver for a virtual
@@ -29,13 +30,16 @@
 
 int qxl_gem_prime_pin(struct drm_gem_object *obj)
 {
-	WARN_ONCE(1, "not implemented");
-	return -ENOSYS;
+	struct qxl_bo *bo = gem_to_qxl_bo(obj);
+
+	return qxl_bo_pin(bo);
 }
 
 void qxl_gem_prime_unpin(struct drm_gem_object *obj)
 {
-	WARN_ONCE(1, "not implemented");
+	struct qxl_bo *bo = gem_to_qxl_bo(obj);
+
+	qxl_bo_unpin(bo);
 }
 
 struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 20/23] drm/qxl: add mode/framebuffer check functions
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (18 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 19/23] drm/qxl: implement qxl_gem_prime_(un)pin Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:30   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 21/23] drm/qxl: add qxl_add_mode helper function Gerd Hoffmann
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Add a helper functions to check video modes.  Also add a helper to check
framebuffer buffer objects, using the former for consistency.  That way
we should not fail in qxl_primary_atomic_check() because video modes
which are too big will not be added to the mode list in the first place.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_display.c | 44 +++++++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 9c751f01e3..fed2ea018d 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -190,6 +190,28 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
 	}
 }
 
+static int qxl_check_mode(struct qxl_device *qdev,
+			  unsigned int width,
+			  unsigned int height)
+{
+	unsigned int stride;
+	unsigned int size;
+
+	if (check_mul_overflow(width, 4u, &stride))
+		return -EINVAL;
+	if (check_mul_overflow(stride, height, &size))
+		return -EINVAL;
+	if (size > qdev->vram_size)
+		return -ENOMEM;
+	return 0;
+}
+
+static int qxl_check_framebuffer(struct qxl_device *qdev,
+				 struct qxl_bo *bo)
+{
+	return qxl_check_mode(qdev, bo->surf.width, bo->surf.height);
+}
+
 static int qxl_add_monitors_config_modes(struct drm_connector *connector,
                                          unsigned *pwidth,
                                          unsigned *pheight)
@@ -469,12 +491,7 @@ static int qxl_primary_atomic_check(struct drm_plane *plane,
 
 	bo = gem_to_qxl_bo(state->fb->obj[0]);
 
-	if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
-		DRM_ERROR("Mode doesn't fit in vram size (vgamem)");
-		return -EINVAL;
-	}
-
-	return 0;
+	return qxl_check_framebuffer(qdev, bo);
 }
 
 static int qxl_primary_apply_cursor(struct drm_plane *plane)
@@ -990,20 +1007,11 @@ static enum drm_mode_status qxl_conn_mode_valid(struct drm_connector *connector,
 {
 	struct drm_device *ddev = connector->dev;
 	struct qxl_device *qdev = ddev->dev_private;
-	int i;
 
-	/* TODO: is this called for user defined modes? (xrandr --add-mode)
-	 * TODO: check that the mode fits in the framebuffer */
+	if (qxl_check_mode(qdev, mode->hdisplay, mode->vdisplay) != 0)
+		return MODE_BAD;
 
-	if (qdev->monitors_config_width == mode->hdisplay &&
-	    qdev->monitors_config_height == mode->vdisplay)
-		return MODE_OK;
-
-	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
-		if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay)
-			return MODE_OK;
-	}
-	return MODE_BAD;
+	return MODE_OK;
 }
 
 static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 21/23] drm/qxl: add qxl_add_mode helper function
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (19 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 20/23] drm/qxl: add mode/framebuffer check functions Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:34   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 22/23] drm/qxl: use kernel mode db Gerd Hoffmann
  2019-01-18 12:20 ` [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create() Gerd Hoffmann
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Add a helper function to add custom video modes to a connector.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_display.c | 84 +++++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index fed2ea018d..926fcb49b2 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -212,15 +212,36 @@ static int qxl_check_framebuffer(struct qxl_device *qdev,
 	return qxl_check_mode(qdev, bo->surf.width, bo->surf.height);
 }
 
-static int qxl_add_monitors_config_modes(struct drm_connector *connector,
-                                         unsigned *pwidth,
-                                         unsigned *pheight)
+static int qxl_add_mode(struct drm_connector *connector,
+			unsigned int width,
+			unsigned int height,
+			bool preferred)
+{
+	struct drm_device *dev = connector->dev;
+	struct qxl_device *qdev = dev->dev_private;
+	struct drm_display_mode *mode = NULL;
+	int rc;
+
+	rc = qxl_check_mode(qdev, width, height);
+	if (rc != 0)
+		return 0;
+
+	mode = drm_cvt_mode(dev, width, height, 60, false, false, false);
+	if (preferred)
+		mode->type |= DRM_MODE_TYPE_PREFERRED;
+	mode->hdisplay = width;
+	mode->vdisplay = height;
+	drm_mode_set_name(mode);
+	drm_mode_probed_add(connector, mode);
+	return 1;
+}
+
+static int qxl_add_monitors_config_modes(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct qxl_device *qdev = dev->dev_private;
 	struct qxl_output *output = drm_connector_to_qxl_output(connector);
 	int h = output->index;
-	struct drm_display_mode *mode = NULL;
 	struct qxl_head *head;
 
 	if (!qdev->monitors_config)
@@ -235,19 +256,7 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
 	head = &qdev->client_monitors_config->heads[h];
 	DRM_DEBUG_KMS("head %d is %dx%d\n", h, head->width, head->height);
 
-	mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
-			    false);
-	mode->type |= DRM_MODE_TYPE_PREFERRED;
-	mode->hdisplay = head->width;
-	mode->vdisplay = head->height;
-	drm_mode_set_name(mode);
-	*pwidth = head->width;
-	*pheight = head->height;
-	drm_mode_probed_add(connector, mode);
-	/* remember the last custom size for mode validation */
-	qdev->monitors_config_width = mode->hdisplay;
-	qdev->monitors_config_height = mode->vdisplay;
-	return 1;
+	return qxl_add_mode(connector, head->width, head->height, true);
 }
 
 static struct mode_size {
@@ -273,22 +282,16 @@ static struct mode_size {
 	{1920, 1200}
 };
 
-static int qxl_add_common_modes(struct drm_connector *connector,
-                                unsigned int pwidth,
-                                unsigned int pheight)
+static int qxl_add_common_modes(struct drm_connector *connector)
 {
-	struct drm_device *dev = connector->dev;
-	struct drm_display_mode *mode = NULL;
-	int i;
+	int i, ret = 0;
 
-	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
-		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
-				    60, false, false, false);
-		if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
-			mode->type |= DRM_MODE_TYPE_PREFERRED;
-		drm_mode_probed_add(connector, mode);
-	}
-	return i - 1;
+	for (i = 0; i < ARRAY_SIZE(common_modes); i++)
+		ret += qxl_add_mode(connector,
+				    common_modes[i].w,
+				    common_modes[i].h,
+				    false);
+	return ret;
 }
 
 static void qxl_send_monitors_config(struct qxl_device *qdev)
@@ -991,14 +994,25 @@ static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
 
 static int qxl_conn_get_modes(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
+	struct qxl_device *qdev = dev->dev_private;
+	struct qxl_output *output = drm_connector_to_qxl_output(connector);
 	unsigned int pwidth = 1024;
 	unsigned int pheight = 768;
 	int ret = 0;
 
-	ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
-	if (ret < 0)
-		return ret;
-	ret += qxl_add_common_modes(connector, pwidth, pheight);
+	if (qdev->client_monitors_config) {
+		struct qxl_head *head;
+		head = &qdev->client_monitors_config->heads[output->index];
+		if (head->width)
+			pwidth = head->width;
+		if (head->height)
+			pheight = head->height;
+	}
+
+	ret += qxl_add_common_modes(connector);
+	ret += qxl_add_monitors_config_modes(connector);
+	drm_set_preferred_mode(connector, pwidth, pheight);
 	return ret;
 }
 
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 22/23] drm/qxl: use kernel mode db
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (20 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 21/23] drm/qxl: add qxl_add_mode helper function Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-25 17:35   ` Noralf Trønnes
  2019-01-18 12:20 ` [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create() Gerd Hoffmann
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Add all standard modes from the kernel's video mode data base.
Keep a few non-standard modes in the qxl mode list.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_display.c | 27 +++++++--------------------
 1 file changed, 7 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 926fcb49b2..df768b0c83 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -262,34 +262,20 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector)
 static struct mode_size {
 	int w;
 	int h;
-} common_modes[] = {
-	{ 640,  480},
+} extra_modes[] = {
 	{ 720,  480},
-	{ 800,  600},
-	{ 848,  480},
-	{1024,  768},
 	{1152,  768},
-	{1280,  720},
-	{1280,  800},
 	{1280,  854},
-	{1280,  960},
-	{1280, 1024},
-	{1440,  900},
-	{1400, 1050},
-	{1680, 1050},
-	{1600, 1200},
-	{1920, 1080},
-	{1920, 1200}
 };
 
-static int qxl_add_common_modes(struct drm_connector *connector)
+static int qxl_add_extra_modes(struct drm_connector *connector)
 {
 	int i, ret = 0;
 
-	for (i = 0; i < ARRAY_SIZE(common_modes); i++)
+	for (i = 0; i < ARRAY_SIZE(extra_modes); i++)
 		ret += qxl_add_mode(connector,
-				    common_modes[i].w,
-				    common_modes[i].h,
+				    extra_modes[i].w,
+				    extra_modes[i].h,
 				    false);
 	return ret;
 }
@@ -1010,7 +996,8 @@ static int qxl_conn_get_modes(struct drm_connector *connector)
 			pheight = head->height;
 	}
 
-	ret += qxl_add_common_modes(connector);
+	ret += drm_add_modes_noedid(connector, 8192, 8192);
+	ret += qxl_add_extra_modes(connector);
 	ret += qxl_add_monitors_config_modes(connector);
 	drm_set_preferred_mode(connector, pwidth, pheight);
 	return ret;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create()
       [not found] <20190118122020.27596-1-kraxel@redhat.com>
                   ` (21 preceding siblings ...)
  2019-01-18 12:20 ` [PATCH v3 22/23] drm/qxl: use kernel mode db Gerd Hoffmann
@ 2019-01-18 12:20 ` Gerd Hoffmann
  2019-01-18 15:49   ` Daniel Vetter
  22 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-18 12:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Gerd Hoffmann, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/qxl/qxl_dumb.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
index 272d19b677..bed6d06ee4 100644
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
@@ -37,11 +37,13 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
 	uint32_t handle;
 	int r;
 	struct qxl_surface surf;
-	uint32_t pitch, format;
+	uint32_t pitch, size, format;
 
-	pitch = args->width * ((args->bpp + 1) / 8);
-	args->size = pitch * args->height;
-	args->size = ALIGN(args->size, PAGE_SIZE);
+	if (check_mul_overflow(args->width, ((args->bpp + 1) / 8), &pitch))
+		return -EINVAL;
+	if (check_mul_overflow(pitch, args->height, &size))
+		return -EINVAL;
+	args->size = ALIGN(size, PAGE_SIZE);
 
 	switch (args->bpp) {
 	case 16:
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create()
  2019-01-18 12:20 ` [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create() Gerd Hoffmann
@ 2019-01-18 15:49   ` Daniel Vetter
  2019-01-18 16:32     ` Ville Syrjälä
  0 siblings, 1 reply; 55+ messages in thread
From: Daniel Vetter @ 2019-01-18 15:49 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: dri-devel, Dave Airlie, David Airlie, Daniel Vetter,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

On Fri, Jan 18, 2019 at 01:20:20PM +0100, Gerd Hoffmann wrote:
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

We already do all reasonable overflow checks in drm_mode_create_dumb(). If
you don't trust them I think would be better time spent typing an igt to
test this than adding redundant check in all drivers.

You're also missing one check for bpp underflows :-)
-Daniel

> ---
>  drivers/gpu/drm/qxl/qxl_dumb.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
> index 272d19b677..bed6d06ee4 100644
> --- a/drivers/gpu/drm/qxl/qxl_dumb.c
> +++ b/drivers/gpu/drm/qxl/qxl_dumb.c
> @@ -37,11 +37,13 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
>  	uint32_t handle;
>  	int r;
>  	struct qxl_surface surf;
> -	uint32_t pitch, format;
> +	uint32_t pitch, size, format;
>  
> -	pitch = args->width * ((args->bpp + 1) / 8);
> -	args->size = pitch * args->height;
> -	args->size = ALIGN(args->size, PAGE_SIZE);
> +	if (check_mul_overflow(args->width, ((args->bpp + 1) / 8), &pitch))
> +		return -EINVAL;
> +	if (check_mul_overflow(pitch, args->height, &size))
> +		return -EINVAL;
> +	args->size = ALIGN(size, PAGE_SIZE);
>  
>  	switch (args->bpp) {
>  	case 16:
> -- 
> 2.9.3
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create()
  2019-01-18 15:49   ` Daniel Vetter
@ 2019-01-18 16:32     ` Ville Syrjälä
  2019-01-18 17:15       ` Daniel Vetter
  0 siblings, 1 reply; 55+ messages in thread
From: Ville Syrjälä @ 2019-01-18 16:32 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel, Dave Airlie, David Airlie,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

On Fri, Jan 18, 2019 at 04:49:44PM +0100, Daniel Vetter wrote:
> On Fri, Jan 18, 2019 at 01:20:20PM +0100, Gerd Hoffmann wrote:
> > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> 
> We already do all reasonable overflow checks in drm_mode_create_dumb(). If
> you don't trust them I think would be better time spent typing an igt to
> test this than adding redundant check in all drivers.
> 
> You're also missing one check for bpp underflows :-)

BTW I just noticed that we don't seem to validating 
create_dumb->flags at all. Someone should probably add some
checks for that, or mark it as deprecated in case we already
lost the battle with userspace stack garbage.

> -Daniel
> 
> > ---
> >  drivers/gpu/drm/qxl/qxl_dumb.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
> > index 272d19b677..bed6d06ee4 100644
> > --- a/drivers/gpu/drm/qxl/qxl_dumb.c
> > +++ b/drivers/gpu/drm/qxl/qxl_dumb.c
> > @@ -37,11 +37,13 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
> >  	uint32_t handle;
> >  	int r;
> >  	struct qxl_surface surf;
> > -	uint32_t pitch, format;
> > +	uint32_t pitch, size, format;
> >  
> > -	pitch = args->width * ((args->bpp + 1) / 8);
> > -	args->size = pitch * args->height;
> > -	args->size = ALIGN(args->size, PAGE_SIZE);
> > +	if (check_mul_overflow(args->width, ((args->bpp + 1) / 8), &pitch))
> > +		return -EINVAL;
> > +	if (check_mul_overflow(pitch, args->height, &size))
> > +		return -EINVAL;
> > +	args->size = ALIGN(size, PAGE_SIZE);
> >  
> >  	switch (args->bpp) {
> >  	case 16:
> > -- 
> > 2.9.3
> > 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create()
  2019-01-18 16:32     ` Ville Syrjälä
@ 2019-01-18 17:15       ` Daniel Vetter
  0 siblings, 0 replies; 55+ messages in thread
From: Daniel Vetter @ 2019-01-18 17:15 UTC (permalink / raw)
  To: Ville Syrjälä
  Cc: Gerd Hoffmann, dri-devel, Dave Airlie, David Airlie,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, open list

On Fri, Jan 18, 2019 at 5:32 PM Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
>
> On Fri, Jan 18, 2019 at 04:49:44PM +0100, Daniel Vetter wrote:
> > On Fri, Jan 18, 2019 at 01:20:20PM +0100, Gerd Hoffmann wrote:
> > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> >
> > We already do all reasonable overflow checks in drm_mode_create_dumb(). If
> > you don't trust them I think would be better time spent typing an igt to
> > test this than adding redundant check in all drivers.
> >
> > You're also missing one check for bpp underflows :-)
>
> BTW I just noticed that we don't seem to validating
> create_dumb->flags at all. Someone should probably add some
> checks for that, or mark it as deprecated in case we already
> lost the battle with userspace stack garbage.

Given that every kms client/compositor under the sun uses this (or
well, all the generic ones at least) I think we can safely assume to
have lost that battle :-/
-Daniel

>
> > -Daniel
> >
> > > ---
> > >  drivers/gpu/drm/qxl/qxl_dumb.c | 10 ++++++----
> > >  1 file changed, 6 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
> > > index 272d19b677..bed6d06ee4 100644
> > > --- a/drivers/gpu/drm/qxl/qxl_dumb.c
> > > +++ b/drivers/gpu/drm/qxl/qxl_dumb.c
> > > @@ -37,11 +37,13 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
> > >     uint32_t handle;
> > >     int r;
> > >     struct qxl_surface surf;
> > > -   uint32_t pitch, format;
> > > +   uint32_t pitch, size, format;
> > >
> > > -   pitch = args->width * ((args->bpp + 1) / 8);
> > > -   args->size = pitch * args->height;
> > > -   args->size = ALIGN(args->size, PAGE_SIZE);
> > > +   if (check_mul_overflow(args->width, ((args->bpp + 1) / 8), &pitch))
> > > +           return -EINVAL;
> > > +   if (check_mul_overflow(pitch, args->height, &size))
> > > +           return -EINVAL;
> > > +   args->size = ALIGN(size, PAGE_SIZE);
> > >
> > >     switch (args->bpp) {
> > >     case 16:
> > > --
> > > 2.9.3
> > >
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
> --
> Ville Syrjälä
> Intel
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 01/23] drm/qxl: drop ttm_mem_reg arg from qxl_hw_surface_alloc()
  2019-01-18 12:19 ` [PATCH v3 01/23] drm/qxl: drop ttm_mem_reg arg from qxl_hw_surface_alloc() Gerd Hoffmann
@ 2019-01-25 15:44   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:44 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.19, skrev Gerd Hoffmann:
> Not used, is always NULL.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 02/23] drm/qxl: drop unused qxl_fb_virtual_address
  2019-01-18 12:19 ` [PATCH v3 02/23] drm/qxl: drop unused qxl_fb_virtual_address Gerd Hoffmann
@ 2019-01-25 15:44   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:44 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.19, skrev Gerd Hoffmann:
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 03/23] drm/qxl: simplify slot management
  2019-01-18 12:20 ` [PATCH v3 03/23] drm/qxl: simplify slot management Gerd Hoffmann
@ 2019-01-25 15:52   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:52 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Drop pointless indirection, remove the mem_slots array and index
> variables, drop dynamic allocation.  Store memslots in qxl_device
> instead.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Looks sane:

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 04/23] drm/qxl: change the way slot is detected
  2019-01-18 12:20 ` [PATCH v3 04/23] drm/qxl: change the way slot is detected Gerd Hoffmann
@ 2019-01-25 15:52   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:52 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie,
	Frediano Ziglio



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> From: Frediano Ziglio <fziglio@redhat.com>
> 
> Instead of relaying on surface type use the actual placement.
> This allow to have different placement for a single type of
> surface.
> 
> Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
> 
> [ kraxel: rebased, adapted to upstream changes ]
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 05/23] drm/qxl: drop unused fields from struct qxl_device
  2019-01-18 12:20 ` [PATCH v3 05/23] drm/qxl: drop unused fields from struct qxl_device Gerd Hoffmann
@ 2019-01-25 15:53   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:53 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> slot_id_bits and slot_gen_bits can be read directly from qxlrom instead.
> va_slot_mask is never used anywhere.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 06/23] drm/qxl: use separate offset spaces for the two slots / ttm memory types.
  2019-01-18 12:20 ` [PATCH v3 06/23] drm/qxl: use separate offset spaces for the two slots / ttm memory types Gerd Hoffmann
@ 2019-01-25 15:57   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:57 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Without that ttm offsets are not unique, they can refer to objects
> in both VRAM and PRIV memory (aka main and surfaces slot).
> 
> One of those "why things didn't blow up without this" moments.
> Probably offset conflicts are rare enough by pure luck.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 07/23] drm/qxl: allow both PRIV and VRAM placement for QXL_GEM_DOMAIN_SURFACE
  2019-01-18 12:20 ` [PATCH v3 07/23] drm/qxl: allow both PRIV and VRAM placement for QXL_GEM_DOMAIN_SURFACE Gerd Hoffmann
@ 2019-01-25 15:58   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:58 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> qxl surfaces (used for framebuffers and gem objects) can live in both
> VRAM and PRIV ttm domains.  Update placement setup to include both.
> Put PRIV first in the list so it is preferred, so VRAM will have more
> room for objects which must be allocated there.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 08/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for shadow bo.
  2019-01-18 12:20 ` [PATCH v3 08/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for shadow bo Gerd Hoffmann
@ 2019-01-25 15:58   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:58 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> The shadow bo is used as qxl surface, so allocate it as
> QXL_GEM_DOMAIN_SURFACE.  Should usually be allocated in
> PRIV ttm domain then, so this reduces VRAM memory pressure.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 09/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for dumb gem objects
  2019-01-18 12:20 ` [PATCH v3 09/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for dumb gem objects Gerd Hoffmann
@ 2019-01-25 15:59   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 15:59 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> dumb buffers are used as qxl surfaces, so allocate them as
> QXL_GEM_DOMAIN_SURFACE.  Should usually be allocated in
> PRIV ttm domain then, so this reduces VRAM memory pressure.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place
  2019-01-18 12:20 ` [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place Gerd Hoffmann
@ 2019-01-25 16:09   ` Noralf Trønnes
  2019-01-28  8:10     ` Gerd Hoffmann
  0 siblings, 1 reply; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 16:09 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> The cursor must be set again after creating the primary surface.
> Also drop the error message.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  drivers/gpu/drm/qxl/qxl_display.c | 10 +++-------
>  1 file changed, 3 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index 86bfc19bea..1b700ef503 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -533,7 +533,6 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
>  	    .x2 = plane->state->fb->width,
>  	    .y2 = plane->state->fb->height
>  	};
> -	int ret;
>  	bool same_shadow = false;
>  
>  	if (old_state->fb) {
> @@ -554,16 +553,13 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
>  		if (!same_shadow)
>  			qxl_io_destroy_primary(qdev);
>  		bo_old->is_primary = false;
> -
> -		ret = qxl_primary_apply_cursor(plane);
> -		if (ret)
> -			DRM_ERROR(
> -			"could not set cursor after creating primary");
>  	}
>  
>  	if (!bo->is_primary) {
> -		if (!same_shadow)
> +		if (!same_shadow) {
>  			qxl_io_create_primary(qdev, 0, bo);
> +			qxl_primary_apply_cursor(plane);
> +		}
>  		bo->is_primary = true;
>  	}
>  
> 

I don't see how the commit message matches what you're doing. It gives
the impression that it must be applied under yet another condition, but
the condition for applying the cursor is changed from bo_old->is_primary
to !bo->is_primary.
It probably makes sense to someone that knows the driver.

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 11/23] drm/qxl: drop unused offset parameter from qxl_io_create_primary()
  2019-01-18 12:20 ` [PATCH v3 11/23] drm/qxl: drop unused offset parameter from qxl_io_create_primary() Gerd Hoffmann
@ 2019-01-25 16:10   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 16:10 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 12/23] drm/qxl: track primary bo
  2019-01-18 12:20 ` [PATCH v3 12/23] drm/qxl: track primary bo Gerd Hoffmann
@ 2019-01-25 16:11   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 16:11 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Track which bo is used as primary surface.  With that in place we don't
> need the primary_created flag any more, we can just check the primary bo
> pointer instead.
> 
> Also verify we don't already have a primary surface in
> qxl_io_create_primary().
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 13/23] drm/qxl: use shadow bo directly
  2019-01-18 12:20 ` [PATCH v3 13/23] drm/qxl: use shadow bo directly Gerd Hoffmann
@ 2019-01-25 16:59   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 16:59 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Pass the shadow bo to qxl_io_create_primary() instead of expecting
> qxl_io_create_primary to check bo->shadow.  Set is_primary flag on the
> shadow bo.  Move the is_primary tracking into qxl_io_create_primary()
> and qxl_io_destroy_primary() functions.
> 
> That simplifies primary surface tracking and the workflow in
> qxl_primary_atomic_update().
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> 
> qxl_io_create/destroy_primary: primary_bo tracking [fixup]
> ---

I'm unable to follow the logic, but I didn't spot anything suspicious
looking.

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 14/23] drm/qxl: cover all crtcs in shadow bo.
  2019-01-18 12:20 ` [PATCH v3 14/23] drm/qxl: cover all crtcs in shadow bo Gerd Hoffmann
@ 2019-01-25 17:08   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:08 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> The qxl device supports only a single active framebuffer ("primary
> surface" in spice terminology).  In multihead configurations are handled
> by defining rectangles within the primary surface for each head/crtc.
> 
> Userspace which uses the qxl ioctl interface (xorg qxl driver) is aware
> of this limitation and will setup framebuffers and crtcs accordingly.
> 
> Userspace which uses dumb framebuffers (xorg modesetting driver,
> wayland) is not aware of this limitation and tries to use two
> framebuffers (one for each crtc) instead.
> 
> The qxl kms driver already has the dumb bo separated from the primary
> surface, by using a (shared) shadow bo as primary surface.  This is
> needed to support pageflips without having to re-create the primary
> surface.  The qxl driver will blit from the dumb bo to the shadow bo
> instead.
> 
> So we can extend the shadow logic:  Maintain a global shadow bo (aka
> primary surface), make it big enough that dumb bo's for all crtcs fit in
> side-by-side.  Adjust the pageflip blits to place the heads next to each
> other in the shadow.
> 
> With this patch in place multihead qxl works with wayland.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  drivers/gpu/drm/qxl/qxl_drv.h     |   5 +-
>  drivers/gpu/drm/qxl/qxl_display.c | 119 +++++++++++++++++++++++++++++---------
>  drivers/gpu/drm/qxl/qxl_draw.c    |   9 ++-
>  3 files changed, 104 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> index 150b1a4f66..43c6df9cf9 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.h
> +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> @@ -230,6 +230,8 @@ struct qxl_device {
>  	struct qxl_ram_header *ram_header;
>  
>  	struct qxl_bo *primary_bo;
> +	struct qxl_bo *dumb_shadow_bo;
> +	struct qxl_head *dumb_heads;
>  
>  	struct qxl_memslot main_slot;
>  	struct qxl_memslot surfaces_slot;
> @@ -437,7 +439,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
>  		       struct qxl_bo *bo,
>  		       unsigned int flags, unsigned int color,
>  		       struct drm_clip_rect *clips,
> -		       unsigned int num_clips, int inc);
> +		       unsigned int num_clips, int inc,
> +		       uint32_t dumb_shadow_offset);
>  
>  void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec);
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index ff13bc6a4a..d9de43e5fd 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -323,6 +323,8 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
>  		head.y = crtc->y;
>  		if (qdev->monitors_config->count < i + 1)
>  			qdev->monitors_config->count = i + 1;
> +		if (qdev->primary_bo == qdev->dumb_shadow_bo)
> +			head.x += qdev->dumb_heads[i].x;
>  	} else if (i > 0) {
>  		head.width = 0;
>  		head.height = 0;
> @@ -426,7 +428,7 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
>  	}
>  
>  	qxl_draw_dirty_fb(qdev, fb, qobj, flags, color,
> -			  clips, num_clips, inc);
> +			  clips, num_clips, inc, 0);
>  
>  	drm_modeset_unlock_all(fb->dev);
>  
> @@ -535,6 +537,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
>  	    .x2 = plane->state->fb->width,
>  	    .y2 = plane->state->fb->height
>  	};
> +	uint32_t dumb_shadow_offset = 0;
>  
>  	if (old_state->fb) {
>  		bo_old = gem_to_qxl_bo(old_state->fb->obj[0]);
> @@ -551,7 +554,12 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
>  		qxl_primary_apply_cursor(plane);
>  	}
>  
> -	qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1);
> +	if (bo->is_dumb)
> +		dumb_shadow_offset =
> +			qdev->dumb_heads[plane->state->crtc->index].x;
> +
> +	qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1,
> +			  dumb_shadow_offset);
>  }
>  
>  static void qxl_primary_atomic_disable(struct drm_plane *plane,
> @@ -707,12 +715,68 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
>  	qxl_release_fence_buffer_objects(release);
>  }
>  
> +static void qxl_update_dumb_head(struct qxl_device *qdev,
> +				 int index, struct qxl_bo *bo)
> +{
> +	uint32_t width, height;
> +
> +	if (index >= qdev->monitors_config->max_allowed)
> +		return;
> +
> +	if (bo && bo->is_dumb) {
> +		width = bo->surf.width;
> +		height = bo->surf.height;
> +	} else {
> +		width = 0;
> +		height = 0;
> +	}
> +
> +	if (qdev->dumb_heads[index].width == width &&
> +	    qdev->dumb_heads[index].height == height)
> +		return;
> +
> +	DRM_DEBUG("#%d: %dx%d -> %dx%d\n", index,
> +		  qdev->dumb_heads[index].width,
> +		  qdev->dumb_heads[index].height,
> +		  width, height);
> +	qdev->dumb_heads[index].width = width;
> +	qdev->dumb_heads[index].height = height;
> +}
> +
> +static void qxl_calc_dumb_shadow(struct qxl_device *qdev,
> +				 struct qxl_surface *surf)
> +{
> +	struct qxl_head *head;
> +	int i;
> +
> +	memset(surf, 0, sizeof(*surf));
> +	for (i = 0; i < qdev->monitors_config->max_allowed; i++) {
> +		head = qdev->dumb_heads + i;
> +		head->x = surf->width;
> +		surf->width += head->width;
> +		if (surf->height < head->height)
> +			surf->height = head->height;
> +	}
> +	if (surf->width < 64)
> +		surf->width = 64;
> +	if (surf->height < 64)
> +		surf->height = 64;
> +	surf->format = SPICE_SURFACE_FMT_32_xRGB;
> +	surf->stride = surf->width * 4;
> +
> +	if (!qdev->dumb_shadow_bo ||
> +	    qdev->dumb_shadow_bo->surf.width != surf->width ||
> +	    qdev->dumb_shadow_bo->surf.height != surf->height)
> +		DRM_DEBUG("%dx%d\n", surf->width, surf->height);
> +}
> +
>  static int qxl_plane_prepare_fb(struct drm_plane *plane,
>  				struct drm_plane_state *new_state)
>  {
>  	struct qxl_device *qdev = plane->dev->dev_private;
>  	struct drm_gem_object *obj;
> -	struct qxl_bo *user_bo, *old_bo = NULL;
> +	struct qxl_bo *user_bo;
> +	struct qxl_surface surf;
>  	int ret;
>  
>  	if (!new_state->fb)
> @@ -722,29 +786,30 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
>  	user_bo = gem_to_qxl_bo(obj);
>  
>  	if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
> -	    user_bo->is_dumb && !user_bo->shadow) {
> -		if (plane->state->fb) {
> -			obj = plane->state->fb->obj[0];
> -			old_bo = gem_to_qxl_bo(obj);
> +	    user_bo->is_dumb) {
> +		qxl_update_dumb_head(qdev, new_state->crtc->index,
> +				     user_bo);
> +		qxl_calc_dumb_shadow(qdev, &surf);
> +		if (!qdev->dumb_shadow_bo ||
> +		    qdev->dumb_shadow_bo->surf.width  != surf.width ||
> +		    qdev->dumb_shadow_bo->surf.height != surf.height) {
> +			if (qdev->dumb_shadow_bo) {
> +				drm_gem_object_put_unlocked
> +					(&qdev->dumb_shadow_bo->gem_base);
> +				qdev->dumb_shadow_bo = NULL;
> +			}
> +			qxl_bo_create(qdev, surf.height * surf.stride,
> +				      true, true, QXL_GEM_DOMAIN_SURFACE, &surf,
> +				      &qdev->dumb_shadow_bo);
>  		}
> -		if (old_bo && old_bo->shadow &&
> -		    user_bo->gem_base.size == old_bo->gem_base.size &&
> -		    plane->state->crtc     == new_state->crtc &&
> -		    plane->state->crtc_w   == new_state->crtc_w &&
> -		    plane->state->crtc_h   == new_state->crtc_h &&
> -		    plane->state->src_x    == new_state->src_x &&
> -		    plane->state->src_y    == new_state->src_y &&
> -		    plane->state->src_w    == new_state->src_w &&
> -		    plane->state->src_h    == new_state->src_h &&
> -		    plane->state->rotation == new_state->rotation &&
> -		    plane->state->zpos     == new_state->zpos) {
> -			drm_gem_object_get(&old_bo->shadow->gem_base);
> -			user_bo->shadow = old_bo->shadow;
> -		} else {
> -			qxl_bo_create(qdev, user_bo->gem_base.size,
> -				      true, true, QXL_GEM_DOMAIN_SURFACE, NULL,
> -				      &user_bo->shadow);
> -			user_bo->shadow->surf = user_bo->surf;
> +		if (user_bo->shadow != qdev->dumb_shadow_bo) {
> +			if (user_bo->shadow) {
> +				drm_gem_object_put_unlocked
> +					(&user_bo->shadow->gem_base);
> +				user_bo->shadow = NULL;
> +			}
> +			drm_gem_object_get(&qdev->dumb_shadow_bo->gem_base);
> +			user_bo->shadow = qdev->dumb_shadow_bo;
>  		}
>  	}
>  
> @@ -773,7 +838,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
>  	user_bo = gem_to_qxl_bo(obj);
>  	qxl_bo_unpin(user_bo);
>  
> -	if (user_bo->shadow && !user_bo->shadow->is_primary) {
> +	if (old_state->fb != plane->state->fb && user_bo->shadow) {
>  		drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
>  		user_bo->shadow = NULL;
>  	}
> @@ -1106,6 +1171,8 @@ int qxl_create_monitors_object(struct qxl_device *qdev)
>  
>  	memset(qdev->monitors_config, 0, monitors_config_size);
>  	qdev->monitors_config->max_allowed = max_allowed;
> +
> +	qdev->dumb_heads = kcalloc(max_allowed, sizeof(qdev->dumb_heads[0]), GFP_KERNEL);

Needs an allocation failure check. With that:

Acked-by: Noralf Trønnes <noralf@tronnes.org>


>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c
> index c408bb83c7..5313ad21c1 100644
> --- a/drivers/gpu/drm/qxl/qxl_draw.c
> +++ b/drivers/gpu/drm/qxl/qxl_draw.c
> @@ -267,7 +267,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
>  		       struct qxl_bo *bo,
>  		       unsigned int flags, unsigned int color,
>  		       struct drm_clip_rect *clips,
> -		       unsigned int num_clips, int inc)
> +		       unsigned int num_clips, int inc,
> +		       uint32_t dumb_shadow_offset)
>  {
>  	/*
>  	 * TODO: if flags & DRM_MODE_FB_DIRTY_ANNOTATE_FILL then we should
> @@ -295,6 +296,9 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
>  	if (ret)
>  		return;
>  
> +	clips->x1 += dumb_shadow_offset;
> +	clips->x2 += dumb_shadow_offset;
> +
>  	left = clips->x1;
>  	right = clips->x2;
>  	top = clips->y1;
> @@ -342,7 +346,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
>  		goto out_release_backoff;
>  
>  	ret = qxl_image_init(qdev, release, dimage, surface_base,
> -			     left, top, width, height, depth, stride);
> +			     left - dumb_shadow_offset,
> +			     top, width, height, depth, stride);
>  	qxl_bo_kunmap(bo);
>  	if (ret)
>  		goto out_release_backoff;
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 15/23] drm/qxl: use qxl_num_crtc directly
  2019-01-18 12:20 ` [PATCH v3 15/23] drm/qxl: use qxl_num_crtc directly Gerd Hoffmann
@ 2019-01-25 17:12   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:12 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> qdev->monitors_config->max_allowed is effectively set by the
> qxl.num_heads module parameter, stored in the qxl_num_crtc variable.
> Lets get rid of the indirection and use the variable qxl_num_crtc
> directly.  The kernel doesn't need to dereference pointers each time it
> needs the value, and when reading the code you don't have to trace where
> and why qdev->monitors_config->max_allowed is set.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 16/23] drm/qxl: implement prime kmap/kunmap
  2019-01-18 12:20 ` [PATCH v3 16/23] drm/qxl: implement prime kmap/kunmap Gerd Hoffmann
@ 2019-01-25 17:19   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:19 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Generic fbdev emulation needs this.  Also: We must keep track of the
> number of mappings now, so we don't unmap early in case two users want a
> kmap of the same bo.  Add a sanity check to destroy callback to make
> sure kmap/kunmap is balanced.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Just a note: You catch the one-to-many kmap type of unbalance, but not
the one-too-many kunmap situation.

Acked-by: Noralf Trønnes <noralf@tronnes.org>


>  drivers/gpu/drm/qxl/qxl_drv.h    |  1 +
>  drivers/gpu/drm/qxl/qxl_object.c |  6 ++++++
>  drivers/gpu/drm/qxl/qxl_prime.c  | 17 +++++++++++++----
>  3 files changed, 20 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> index 43c6df9cf9..8c3af1cdbe 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.h
> +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> @@ -84,6 +84,7 @@ struct qxl_bo {
>  	struct ttm_bo_kmap_obj		kmap;
>  	unsigned int pin_count;
>  	void				*kptr;
> +	unsigned int                    map_count;
>  	int                             type;
>  
>  	/* Constant after initialization */
> diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c
> index 024c8dd317..4928fa6029 100644
> --- a/drivers/gpu/drm/qxl/qxl_object.c
> +++ b/drivers/gpu/drm/qxl/qxl_object.c
> @@ -36,6 +36,7 @@ static void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo)
>  	qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
>  
>  	qxl_surface_evict(qdev, bo, false);
> +	WARN_ON_ONCE(bo->map_count > 0);
>  	mutex_lock(&qdev->gem.mutex);
>  	list_del_init(&bo->list);
>  	mutex_unlock(&qdev->gem.mutex);
> @@ -131,6 +132,7 @@ int qxl_bo_kmap(struct qxl_bo *bo, void **ptr)
>  	if (bo->kptr) {
>  		if (ptr)
>  			*ptr = bo->kptr;
> +		bo->map_count++;
>  		return 0;
>  	}
>  	r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
> @@ -139,6 +141,7 @@ int qxl_bo_kmap(struct qxl_bo *bo, void **ptr)
>  	bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
>  	if (ptr)
>  		*ptr = bo->kptr;
> +	bo->map_count = 1;
>  	return 0;
>  }
>  
> @@ -180,6 +183,9 @@ void qxl_bo_kunmap(struct qxl_bo *bo)
>  {
>  	if (bo->kptr == NULL)
>  		return;
> +	bo->map_count--;
> +	if (bo->map_count > 0)
> +		return;
>  	bo->kptr = NULL;
>  	ttm_bo_kunmap(&bo->kmap);
>  }
> diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c
> index a55dece118..708378844c 100644
> --- a/drivers/gpu/drm/qxl/qxl_prime.c
> +++ b/drivers/gpu/drm/qxl/qxl_prime.c
> @@ -22,7 +22,7 @@
>   * Authors: Andreas Pokorny
>   */
>  
> -#include "qxl_drv.h"
> +#include "qxl_object.h"
>  
>  /* Empty Implementations as there should not be any other driver for a virtual
>   * device that might share buffers with qxl */
> @@ -54,13 +54,22 @@ struct drm_gem_object *qxl_gem_prime_import_sg_table(
>  
>  void *qxl_gem_prime_vmap(struct drm_gem_object *obj)
>  {
> -	WARN_ONCE(1, "not implemented");
> -	return ERR_PTR(-ENOSYS);
> +	struct qxl_bo *bo = gem_to_qxl_bo(obj);
> +	void *ptr;
> +	int ret;
> +
> +	ret = qxl_bo_kmap(bo, &ptr);
> +	if (ret < 0)
> +		return ERR_PTR(ret);
> +
> +	return ptr;
>  }
>  
>  void qxl_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
>  {
> -	WARN_ONCE(1, "not implemented");
> +	struct qxl_bo *bo = gem_to_qxl_bo(obj);
> +
> +	qxl_bo_kunmap(bo);
>  }
>  
>  int qxl_gem_prime_mmap(struct drm_gem_object *obj,
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 17/23] drm/qxl: use generic fbdev emulation
  2019-01-18 12:20 ` [PATCH v3 17/23] drm/qxl: use generic fbdev emulation Gerd Hoffmann
@ 2019-01-25 17:25   ` Noralf Trønnes
  2019-01-28  8:59     ` Gerd Hoffmann
  0 siblings, 1 reply; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:25 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Switch qxl over to the new generic fbdev emulation.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  drivers/gpu/drm/qxl/qxl_display.c | 7 -------
>  drivers/gpu/drm/qxl/qxl_drv.c     | 2 ++
>  2 files changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index ef832f98ab..9c751f01e3 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -1221,18 +1221,11 @@ int qxl_modeset_init(struct qxl_device *qdev)
>  	qxl_display_read_client_monitors_config(qdev);
>  
>  	drm_mode_config_reset(&qdev->ddev);
> -
> -	/* primary surface must be created by this point, to allow
> -	 * issuing command queue commands and having them read by
> -	 * spice server. */
> -	qxl_fbdev_init(qdev);
>  	return 0;
>  }
>  
>  void qxl_modeset_fini(struct qxl_device *qdev)
>  {
> -	qxl_fbdev_fini(qdev);
> -
>  	qxl_destroy_monitors_object(qdev);
>  	drm_mode_config_cleanup(&qdev->ddev);
>  }
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
> index 13c8a662f9..3fce7d16df 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.c
> +++ b/drivers/gpu/drm/qxl/qxl_drv.c
> @@ -93,6 +93,8 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	if (ret)
>  		goto modeset_cleanup;
>  
> +	drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "qxl");

I couldn't find that this was part of old fbdev code, so it would be
nice to mention it in the commit message.

Acked-by: Noralf Trønnes <noralf@tronnes.org>


> +	drm_fbdev_generic_setup(&qdev->ddev, 32);
>  	return 0;
>  
>  modeset_cleanup:
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code
  2019-01-18 12:20 ` [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code Gerd Hoffmann
@ 2019-01-25 17:25   ` Noralf Trønnes
  2019-01-25 18:10     ` Sam Ravnborg
  0 siblings, 1 reply; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:25 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Lovely diffstat, thanks to the new generic fbdev emulation.
> 
>  drm/qxl/Makefile   |    2
>  drm/qxl/qxl_draw.c |  232 ----------------------------------------
>  drm/qxl/qxl_drv.h  |   21 ---
>  drm/qxl/qxl_fb.c   |  300 -----------------------------------------------------
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  drivers/gpu/drm/qxl/qxl_drv.h  |  21 ---
>  drivers/gpu/drm/qxl/qxl_draw.c | 232 -------------------------------
>  drivers/gpu/drm/qxl/qxl_fb.c   | 300 -----------------------------------------
>  drivers/gpu/drm/qxl/Makefile   |   2 +-
>  4 files changed, 1 insertion(+), 554 deletions(-)
>  delete mode 100644 drivers/gpu/drm/qxl/qxl_fb.c
> 

Nice!

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 19/23] drm/qxl: implement qxl_gem_prime_(un)pin
  2019-01-18 12:20 ` [PATCH v3 19/23] drm/qxl: implement qxl_gem_prime_(un)pin Gerd Hoffmann
@ 2019-01-25 17:26   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:26 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 20/23] drm/qxl: add mode/framebuffer check functions
  2019-01-18 12:20 ` [PATCH v3 20/23] drm/qxl: add mode/framebuffer check functions Gerd Hoffmann
@ 2019-01-25 17:30   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:30 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Add a helper functions to check video modes.  Also add a helper to check
> framebuffer buffer objects, using the former for consistency.  That way
> we should not fail in qxl_primary_atomic_check() because video modes
> which are too big will not be added to the mode list in the first place.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 21/23] drm/qxl: add qxl_add_mode helper function
  2019-01-18 12:20 ` [PATCH v3 21/23] drm/qxl: add qxl_add_mode helper function Gerd Hoffmann
@ 2019-01-25 17:34   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:34 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Add a helper function to add custom video modes to a connector.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 22/23] drm/qxl: use kernel mode db
  2019-01-18 12:20 ` [PATCH v3 22/23] drm/qxl: use kernel mode db Gerd Hoffmann
@ 2019-01-25 17:35   ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 17:35 UTC (permalink / raw)
  To: Gerd Hoffmann, dri-devel
  Cc: David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> Add all standard modes from the kernel's video mode data base.
> Keep a few non-standard modes in the qxl mode list.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code
  2019-01-25 17:25   ` Noralf Trønnes
@ 2019-01-25 18:10     ` Sam Ravnborg
  2019-01-25 18:44       ` Noralf Trønnes
  0 siblings, 1 reply; 55+ messages in thread
From: Sam Ravnborg @ 2019-01-25 18:10 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: Gerd Hoffmann, dri-devel, David Airlie,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU

Hi Noralf.

> > Lovely diffstat, thanks to the new generic fbdev emulation.
> > 
> >  drm/qxl/Makefile   |    2
> >  drm/qxl/qxl_draw.c |  232 ----------------------------------------
> >  drm/qxl/qxl_drv.h  |   21 ---
> >  drm/qxl/qxl_fb.c   |  300 -----------------------------------------------------
> > 
> > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> > ---
> >  drivers/gpu/drm/qxl/qxl_drv.h  |  21 ---
> >  drivers/gpu/drm/qxl/qxl_draw.c | 232 -------------------------------
> >  drivers/gpu/drm/qxl/qxl_fb.c   | 300 -----------------------------------------
> >  drivers/gpu/drm/qxl/Makefile   |   2 +-
> >  4 files changed, 1 insertion(+), 554 deletions(-)
> >  delete mode 100644 drivers/gpu/drm/qxl/qxl_fb.c
> > 
> 
> Nice!
> 
> Acked-by: Noralf Trønnes <noralf@tronnes.org>
It must be a very satisfying experience to see such benefits
of the many hours of works you have put into the genric
fbdev emulation code.
Well done, and indeed a nice patch from Gerd.

	Sam

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code
  2019-01-25 18:10     ` Sam Ravnborg
@ 2019-01-25 18:44       ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-25 18:44 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Gerd Hoffmann, dri-devel, David Airlie,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU



Den 25.01.2019 19.10, skrev Sam Ravnborg:
> Hi Noralf.
> 
>>> Lovely diffstat, thanks to the new generic fbdev emulation.
>>>
>>>  drm/qxl/Makefile   |    2
>>>  drm/qxl/qxl_draw.c |  232 ----------------------------------------
>>>  drm/qxl/qxl_drv.h  |   21 ---
>>>  drm/qxl/qxl_fb.c   |  300 -----------------------------------------------------
>>>
>>> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>>> ---
>>>  drivers/gpu/drm/qxl/qxl_drv.h  |  21 ---
>>>  drivers/gpu/drm/qxl/qxl_draw.c | 232 -------------------------------
>>>  drivers/gpu/drm/qxl/qxl_fb.c   | 300 -----------------------------------------
>>>  drivers/gpu/drm/qxl/Makefile   |   2 +-
>>>  4 files changed, 1 insertion(+), 554 deletions(-)
>>>  delete mode 100644 drivers/gpu/drm/qxl/qxl_fb.c
>>>
>>
>> Nice!
>>
>> Acked-by: Noralf Trønnes <noralf@tronnes.org>
> It must be a very satisfying experience to see such benefits
> of the many hours of works you have put into the genric
> fbdev emulation code.

Indeed and having more users of the code increases the chance of
detecting any bugs lurking underneath the surface.

> Well done, and indeed a nice patch from Gerd.
> 
> 	Sam
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place
  2019-01-25 16:09   ` Noralf Trønnes
@ 2019-01-28  8:10     ` Gerd Hoffmann
  2019-01-28 10:38       ` Noralf Trønnes
  0 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-28  8:10 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: dri-devel, David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie

> > The cursor must be set again after creating the primary surface.
> > Also drop the error message.

> >  	if (!bo->is_primary) {
> > -		if (!same_shadow)
> > +		if (!same_shadow) {
> >  			qxl_io_create_primary(qdev, 0, bo);
> > +			qxl_primary_apply_cursor(plane);
> > +		}
> >  		bo->is_primary = true;
> >  	}
> >  
> > 
> 
> I don't see how the commit message matches what you're doing. It gives
> the impression that it must be applied under yet another condition, but
> the condition for applying the cursor is changed from bo_old->is_primary
> to !bo->is_primary.

The qxl device ties the cursor to the primary surface.  Therefore
calling qxl_io_destroy_primary() and qxl_io_create_primary() to switch
the framebuffer causes the cursor information being lost and the driver
must re-apply it.

The correct call order to do that is qxl_io_destroy_primary() +
qxl_io_create_primary() + qxl_primary_apply_cursor().

The old code did qxl_io_destroy_primary() + qxl_primary_apply_cursor() +
qxl_io_create_primary().  Due to qxl_primary_apply_cursor request being
queued in a ringbuffer and qxl_io_create_primary() trapping to the
hypervisor instantly there is a high chance that qxl_io_create_primary()
is processed first even with the wrong call order.  But it's racy and
thus not reliable.

> It probably makes sense to someone that knows the driver.

If the above explains things better to you I should probably replace the
commit message with that.

> Acked-by: Noralf Trønnes <noralf@tronnes.org>

thanks,
  Gerd


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 17/23] drm/qxl: use generic fbdev emulation
  2019-01-25 17:25   ` Noralf Trønnes
@ 2019-01-28  8:59     ` Gerd Hoffmann
  2019-01-28 10:39       ` Noralf Trønnes
  0 siblings, 1 reply; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-28  8:59 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: dri-devel, David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie

On Fri, Jan 25, 2019 at 06:25:27PM +0100, Noralf Trønnes wrote:
> 
> 
> Den 18.01.2019 13.20, skrev Gerd Hoffmann:
> > Switch qxl over to the new generic fbdev emulation.
> > 
> > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> > ---
> >  drivers/gpu/drm/qxl/qxl_display.c | 7 -------
> >  drivers/gpu/drm/qxl/qxl_drv.c     | 2 ++
> >  2 files changed, 2 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> > index ef832f98ab..9c751f01e3 100644
> > --- a/drivers/gpu/drm/qxl/qxl_display.c
> > +++ b/drivers/gpu/drm/qxl/qxl_display.c
> > @@ -1221,18 +1221,11 @@ int qxl_modeset_init(struct qxl_device *qdev)
> >  	qxl_display_read_client_monitors_config(qdev);
> >  
> >  	drm_mode_config_reset(&qdev->ddev);
> > -
> > -	/* primary surface must be created by this point, to allow
> > -	 * issuing command queue commands and having them read by
> > -	 * spice server. */
> > -	qxl_fbdev_init(qdev);
> >  	return 0;
> >  }
> >  
> >  void qxl_modeset_fini(struct qxl_device *qdev)
> >  {
> > -	qxl_fbdev_fini(qdev);
> > -
> >  	qxl_destroy_monitors_object(qdev);
> >  	drm_mode_config_cleanup(&qdev->ddev);
> >  }
> > diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
> > index 13c8a662f9..3fce7d16df 100644
> > --- a/drivers/gpu/drm/qxl/qxl_drv.c
> > +++ b/drivers/gpu/drm/qxl/qxl_drv.c
> > @@ -93,6 +93,8 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> >  	if (ret)
> >  		goto modeset_cleanup;
> >  
> > +	drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "qxl");
> 
> I couldn't find that this was part of old fbdev code, so it would be
> nice to mention it in the commit message.

It actually is, but a bit hidden because it doesn't use a helper you can
easily grep for.  Instead sets fb_info->apertures->ranges[0] in
qxlfb_create(), which has the same effect.

cheers,
  Gerd


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place
  2019-01-28  8:10     ` Gerd Hoffmann
@ 2019-01-28 10:38       ` Noralf Trønnes
  2019-01-28 11:40         ` Gerd Hoffmann
  0 siblings, 1 reply; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-28 10:38 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: dri-devel, David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 28.01.2019 09.10, skrev Gerd Hoffmann:
>>> The cursor must be set again after creating the primary surface.
>>> Also drop the error message.
> 
>>>  	if (!bo->is_primary) {
>>> -		if (!same_shadow)
>>> +		if (!same_shadow) {
>>>  			qxl_io_create_primary(qdev, 0, bo);
>>> +			qxl_primary_apply_cursor(plane);
>>> +		}
>>>  		bo->is_primary = true;
>>>  	}
>>>  
>>>
>>
>> I don't see how the commit message matches what you're doing. It gives
>> the impression that it must be applied under yet another condition, but
>> the condition for applying the cursor is changed from bo_old->is_primary
>> to !bo->is_primary.
> 
> The qxl device ties the cursor to the primary surface.  Therefore
> calling qxl_io_destroy_primary() and qxl_io_create_primary() to switch
> the framebuffer causes the cursor information being lost and the driver
> must re-apply it.
> 
> The correct call order to do that is qxl_io_destroy_primary() +
> qxl_io_create_primary() + qxl_primary_apply_cursor().
> 
> The old code did qxl_io_destroy_primary() + qxl_primary_apply_cursor() +
> qxl_io_create_primary().  Due to qxl_primary_apply_cursor request being
> queued in a ringbuffer and qxl_io_create_primary() trapping to the
> hypervisor instantly there is a high chance that qxl_io_create_primary()
> is processed first even with the wrong call order.  But it's racy and
> thus not reliable.
> 
>> It probably makes sense to someone that knows the driver.
> 
> If the above explains things better to you I should probably replace the
> commit message with that.
> 

This is actually my first review of a driver that I'm not familiar with.
I'm not quite sure how much in depth understanding that is required to
put my ack on it. Going further into the patchset I realised that
there's no way that I can verify the logic without being intimate with
the driver. So I have tried to verify things from a kms point of view.

I liked your expanded explanation better.

Noralf.

>> Acked-by: Noralf Trønnes <noralf@tronnes.org>
> 
> thanks,
>   Gerd
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 17/23] drm/qxl: use generic fbdev emulation
  2019-01-28  8:59     ` Gerd Hoffmann
@ 2019-01-28 10:39       ` Noralf Trønnes
  0 siblings, 0 replies; 55+ messages in thread
From: Noralf Trønnes @ 2019-01-28 10:39 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: dri-devel, David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie



Den 28.01.2019 09.59, skrev Gerd Hoffmann:
> On Fri, Jan 25, 2019 at 06:25:27PM +0100, Noralf Trønnes wrote:
>>
>>
>> Den 18.01.2019 13.20, skrev Gerd Hoffmann:
>>> Switch qxl over to the new generic fbdev emulation.
>>>
>>> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>>> ---
>>>  drivers/gpu/drm/qxl/qxl_display.c | 7 -------
>>>  drivers/gpu/drm/qxl/qxl_drv.c     | 2 ++
>>>  2 files changed, 2 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
>>> index ef832f98ab..9c751f01e3 100644
>>> --- a/drivers/gpu/drm/qxl/qxl_display.c
>>> +++ b/drivers/gpu/drm/qxl/qxl_display.c
>>> @@ -1221,18 +1221,11 @@ int qxl_modeset_init(struct qxl_device *qdev)
>>>  	qxl_display_read_client_monitors_config(qdev);
>>>  
>>>  	drm_mode_config_reset(&qdev->ddev);
>>> -
>>> -	/* primary surface must be created by this point, to allow
>>> -	 * issuing command queue commands and having them read by
>>> -	 * spice server. */
>>> -	qxl_fbdev_init(qdev);
>>>  	return 0;
>>>  }
>>>  
>>>  void qxl_modeset_fini(struct qxl_device *qdev)
>>>  {
>>> -	qxl_fbdev_fini(qdev);
>>> -
>>>  	qxl_destroy_monitors_object(qdev);
>>>  	drm_mode_config_cleanup(&qdev->ddev);
>>>  }
>>> diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
>>> index 13c8a662f9..3fce7d16df 100644
>>> --- a/drivers/gpu/drm/qxl/qxl_drv.c
>>> +++ b/drivers/gpu/drm/qxl/qxl_drv.c
>>> @@ -93,6 +93,8 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>>>  	if (ret)
>>>  		goto modeset_cleanup;
>>>  
>>> +	drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "qxl");
>>
>> I couldn't find that this was part of old fbdev code, so it would be
>> nice to mention it in the commit message.
> 
> It actually is, but a bit hidden because it doesn't use a helper you can
> easily grep for.  Instead sets fb_info->apertures->ranges[0] in
> qxlfb_create(), which has the same effect.
> 

Indeed,

Acked-by: Noralf Trønnes <noralf@tronnes.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place
  2019-01-28 10:38       ` Noralf Trønnes
@ 2019-01-28 11:40         ` Gerd Hoffmann
  0 siblings, 0 replies; 55+ messages in thread
From: Gerd Hoffmann @ 2019-01-28 11:40 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: dri-devel, David Airlie, open list,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU,
	open list:DRM DRIVER FOR QXL VIRTUAL GPU, Dave Airlie

  Hi,

> > If the above explains things better to you I should probably replace the
> > commit message with that.
> 
> This is actually my first review of a driver that I'm not familiar with.
> I'm not quite sure how much in depth understanding that is required to
> put my ack on it.

Usually I try to show that by picking either Reviewed-by (I'm confident
the changes are fine) or Acked-by (Changes look sane, but I don't know
the code base and/or hardware good enough to be sure).

> Going further into the patchset I realised that
> there's no way that I can verify the logic without being intimate with
> the driver.

Yep.  Same for me when looking at patches for other drivers.  I think
this is one reason why it isn't that easy to get patches for drivers
reviewed where effectively only a single maintainer/developer is working
on.

> I liked your expanded explanation better.

Updated the commit message.

cheers,
  Gerd


^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2019-01-28 11:40 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20190118122020.27596-1-kraxel@redhat.com>
2019-01-18 12:19 ` [PATCH v3 01/23] drm/qxl: drop ttm_mem_reg arg from qxl_hw_surface_alloc() Gerd Hoffmann
2019-01-25 15:44   ` Noralf Trønnes
2019-01-18 12:19 ` [PATCH v3 02/23] drm/qxl: drop unused qxl_fb_virtual_address Gerd Hoffmann
2019-01-25 15:44   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 03/23] drm/qxl: simplify slot management Gerd Hoffmann
2019-01-25 15:52   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 04/23] drm/qxl: change the way slot is detected Gerd Hoffmann
2019-01-25 15:52   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 05/23] drm/qxl: drop unused fields from struct qxl_device Gerd Hoffmann
2019-01-25 15:53   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 06/23] drm/qxl: use separate offset spaces for the two slots / ttm memory types Gerd Hoffmann
2019-01-25 15:57   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 07/23] drm/qxl: allow both PRIV and VRAM placement for QXL_GEM_DOMAIN_SURFACE Gerd Hoffmann
2019-01-25 15:58   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 08/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for shadow bo Gerd Hoffmann
2019-01-25 15:58   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 09/23] drm/qxl: use QXL_GEM_DOMAIN_SURFACE for dumb gem objects Gerd Hoffmann
2019-01-25 15:59   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 10/23] drm/qxl: move qxl_primary_apply_cursor to correct place Gerd Hoffmann
2019-01-25 16:09   ` Noralf Trønnes
2019-01-28  8:10     ` Gerd Hoffmann
2019-01-28 10:38       ` Noralf Trønnes
2019-01-28 11:40         ` Gerd Hoffmann
2019-01-18 12:20 ` [PATCH v3 11/23] drm/qxl: drop unused offset parameter from qxl_io_create_primary() Gerd Hoffmann
2019-01-25 16:10   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 12/23] drm/qxl: track primary bo Gerd Hoffmann
2019-01-25 16:11   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 13/23] drm/qxl: use shadow bo directly Gerd Hoffmann
2019-01-25 16:59   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 14/23] drm/qxl: cover all crtcs in shadow bo Gerd Hoffmann
2019-01-25 17:08   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 15/23] drm/qxl: use qxl_num_crtc directly Gerd Hoffmann
2019-01-25 17:12   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 16/23] drm/qxl: implement prime kmap/kunmap Gerd Hoffmann
2019-01-25 17:19   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 17/23] drm/qxl: use generic fbdev emulation Gerd Hoffmann
2019-01-25 17:25   ` Noralf Trønnes
2019-01-28  8:59     ` Gerd Hoffmann
2019-01-28 10:39       ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 18/23] drm/qxl: remove dead qxl fbdev emulation code Gerd Hoffmann
2019-01-25 17:25   ` Noralf Trønnes
2019-01-25 18:10     ` Sam Ravnborg
2019-01-25 18:44       ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 19/23] drm/qxl: implement qxl_gem_prime_(un)pin Gerd Hoffmann
2019-01-25 17:26   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 20/23] drm/qxl: add mode/framebuffer check functions Gerd Hoffmann
2019-01-25 17:30   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 21/23] drm/qxl: add qxl_add_mode helper function Gerd Hoffmann
2019-01-25 17:34   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 22/23] drm/qxl: use kernel mode db Gerd Hoffmann
2019-01-25 17:35   ` Noralf Trønnes
2019-01-18 12:20 ` [PATCH v3 23/23] drm/qxl: add overflow checks to qxl_mode_dumb_create() Gerd Hoffmann
2019-01-18 15:49   ` Daniel Vetter
2019-01-18 16:32     ` Ville Syrjälä
2019-01-18 17:15       ` Daniel Vetter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).