From edd38a1e598dd970f61f9c8d8649e65089a4fdbc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:19:58 +0100 Subject: drm/qxl: drop ttm_mem_reg arg from qxl_hw_surface_alloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not used, is always NULL. Signed-off-by: Gerd Hoffmann Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-2-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_drv.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 13a0254b59a1..38c5a8b1dfc1 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); -- cgit v1.2.3-59-g8ed1b From d934ef6b98bcdc77242b66f4fa0ea0c3330ae3b6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:19:59 +0100 Subject: drm/qxl: drop unused qxl_fb_virtual_address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gerd Hoffmann Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-3-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_drv.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 38c5a8b1dfc1..7eabf4a9ed14 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) -- cgit v1.2.3-59-g8ed1b From 2ec6bd67b76ea0afc97eaa22f369738f1a7ad7f3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:00 +0100 Subject: drm/qxl: simplify slot management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-4-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(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 7eabf4a9ed14..f9dddfe7d988 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 85e13afa1808..ec0e83f395e9 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: -- cgit v1.2.3-59-g8ed1b From a8dc42142a0ebbb5fade13f3e48d89399499d297 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Fri, 18 Jan 2019 13:20:01 +0100 Subject: drm/qxl: change the way slot is detected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Signed-off-by: Gerd Hoffmann Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-5-kraxel@redhat.com [ kraxel: rebased, adapted to upstream changes ] Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/qxl/qxl_drv.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index f9dddfe7d988..d015d4fff158 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 */ -- cgit v1.2.3-59-g8ed1b From 3ebe3ddf37c84acfb1dfbe471482cb4bbdb0f7c0 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:02 +0100 Subject: drm/qxl: drop unused fields from struct qxl_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-6-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(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index d015d4fff158..3ebe66abf259 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 ec0e83f395e9..9936b3111bb2 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); -- cgit v1.2.3-59-g8ed1b From 96e8f153964aa0cc0ebb21576974a723f2b03cd5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:03 +0100 Subject: drm/qxl: use separate offset spaces for the two slots / ttm memory types. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-7-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(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 3ebe66abf259..27e0a3fc08e6 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 9936b3111bb2..bee61fa2c9bc 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 886f61e94f24..36ea993aac07 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; -- cgit v1.2.3-59-g8ed1b From fb7ebc0119ed0b24e261b06bacca6a4eb766443c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:08 +0100 Subject: drm/qxl: drop unused offset parameter from qxl_io_create_primary() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gerd Hoffmann Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-12-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_cmd.c | 7 +++---- drivers/gpu/drm/qxl/qxl_display.c | 2 +- drivers/gpu/drm/qxl/qxl_drv.h | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 5ba831c78cfe..bc13539249fc 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 6180b4a714b6..8153e9e478d3 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; diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 27e0a3fc08e6..cb767aaef630 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); -- cgit v1.2.3-59-g8ed1b From 166205444b90f49382e26cc4ed0f9abc6b6a81f8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:09 +0100 Subject: drm/qxl: track primary bo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-13-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_cmd.c | 7 +++++-- drivers/gpu/drm/qxl/qxl_display.c | 2 +- drivers/gpu/drm/qxl/qxl_drv.h | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index bc13539249fc..8e6412725946 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 8153e9e478d3..a0db90788824 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; } diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index cb767aaef630..150b1a4f667a 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; -- cgit v1.2.3-59-g8ed1b From 90adda2ce898c7a76d1a55d4650ade8cc957e54f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:11 +0100 Subject: drm/qxl: cover all crtcs in shadow bo. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-15-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_display.c | 123 ++++++++++++++++++++++++++++++-------- drivers/gpu/drm/qxl/qxl_draw.c | 9 ++- drivers/gpu/drm/qxl/qxl_drv.h | 5 +- 3 files changed, 108 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 455b1b595a09..3f2e253f7244 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,12 @@ 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); + if (!qdev->dumb_heads) { + qxl_destroy_monitors_object(qdev); + return -ENOMEM; + } return 0; } diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index c408bb83c7a9..5313ad21c1bb 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; diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 150b1a4f667a..43c6df9cf98e 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); -- cgit v1.2.3-59-g8ed1b From 9b369116fd0ecd3e4fb3d82f8d61859d9607f9b3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:13 +0100 Subject: drm/qxl: implement prime kmap/kunmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-17-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(-) (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 43c6df9cf98e..8c3af1cdbe9b 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 024c8dd3174c..4928fa602944 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 a55dece118b2..708378844c02 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, -- cgit v1.2.3-59-g8ed1b From 13aff184ed9f651f80e7dc8be1e1b457a5d38134 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Jan 2019 13:20:15 +0100 Subject: drm/qxl: remove dead qxl fbdev emulation code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Noralf Trønnes Link: http://patchwork.freedesktop.org/patch/msgid/20190118122020.27596-19-kraxel@redhat.com --- drivers/gpu/drm/qxl/Makefile | 2 +- drivers/gpu/drm/qxl/qxl_draw.c | 232 ------------------------------- drivers/gpu/drm/qxl/qxl_drv.h | 21 --- drivers/gpu/drm/qxl/qxl_fb.c | 300 ----------------------------------------- 4 files changed, 1 insertion(+), 554 deletions(-) delete mode 100644 drivers/gpu/drm/qxl/qxl_fb.c (limited to 'drivers/gpu/drm/qxl/qxl_drv.h') diff --git a/drivers/gpu/drm/qxl/Makefile b/drivers/gpu/drm/qxl/Makefile index 33a7d0c434b7..fc59d42b31af 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 diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index 5313ad21c1bb..97c3f1a95a32 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 @@ out_free_drawable: 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_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 8c3af1cdbe9b..4a0331b3ff7d 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_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c deleted file mode 100644 index d028471597ef..000000000000 --- 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 - -#include -#include -#include -#include -#include -#include - -#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); -} -- cgit v1.2.3-59-g8ed1b