diff options
Diffstat (limited to 'drivers/gpu/drm/qxl/qxl_kms.c')
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_kms.c | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 771250aed78d..e25c589d5f50 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -102,8 +102,10 @@ int qxl_device_init(struct qxl_device *qdev, int r, sb; r = drm_dev_init(&qdev->ddev, drv, &pdev->dev); - if (r) - return r; + if (r) { + pr_err("Unable to init drm dev"); + goto error; + } qdev->ddev.pdev = pdev; pci_set_drvdata(pdev, &qdev->ddev); @@ -121,6 +123,11 @@ int qxl_device_init(struct qxl_device *qdev, qdev->io_base = pci_resource_start(pdev, 3); qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0)); + if (!qdev->vram_mapping) { + pr_err("Unable to create vram_mapping"); + r = -ENOMEM; + goto error; + } if (pci_resource_len(pdev, 4) > 0) { /* 64bit surface bar present */ @@ -139,6 +146,11 @@ int qxl_device_init(struct qxl_device *qdev, qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size); + if (!qdev->surface_mapping) { + pr_err("Unable to create surface_mapping"); + r = -ENOMEM; + goto vram_mapping_free; + } } DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk, %s)\n", @@ -155,20 +167,29 @@ int qxl_device_init(struct qxl_device *qdev, qdev->rom = ioremap(qdev->rom_base, qdev->rom_size); if (!qdev->rom) { pr_err("Unable to ioremap ROM\n"); - return -ENOMEM; + r = -ENOMEM; + goto surface_mapping_free; } - qxl_check_device(qdev); + if (!qxl_check_device(qdev)) { + r = -ENODEV; + goto surface_mapping_free; + } r = qxl_bo_init(qdev); if (r) { DRM_ERROR("bo init failed %d\n", r); - return r; + goto rom_unmap; } qdev->ram_header = ioremap(qdev->vram_base + qdev->rom->ram_header_offset, sizeof(*qdev->ram_header)); + if (!qdev->ram_header) { + DRM_ERROR("Unable to ioremap RAM header\n"); + r = -ENOMEM; + goto bo_fini; + } qdev->command_ring = qxl_ring_create(&(qdev->ram_header->cmd_ring_hdr), sizeof(struct qxl_command), @@ -176,6 +197,11 @@ int qxl_device_init(struct qxl_device *qdev, qdev->io_base + QXL_IO_NOTIFY_CMD, false, &qdev->display_event); + if (!qdev->command_ring) { + DRM_ERROR("Unable to create command ring\n"); + r = -ENOMEM; + goto ram_header_unmap; + } qdev->cursor_ring = qxl_ring_create( &(qdev->ram_header->cursor_ring_hdr), @@ -185,12 +211,23 @@ int qxl_device_init(struct qxl_device *qdev, false, &qdev->cursor_event); + if (!qdev->cursor_ring) { + DRM_ERROR("Unable to create cursor ring\n"); + r = -ENOMEM; + goto command_ring_free; + } + qdev->release_ring = qxl_ring_create( &(qdev->ram_header->release_ring_hdr), sizeof(uint64_t), QXL_RELEASE_RING_SIZE, 0, true, NULL); + if (!qdev->release_ring) { + DRM_ERROR("Unable to create release ring\n"); + r = -ENOMEM; + goto cursor_ring_free; + } /* TODO - slot initialization should happen on reset. where is our * reset handler? */ qdev->n_mem_slots = qdev->rom->slots_end; @@ -203,6 +240,12 @@ int qxl_device_init(struct qxl_device *qdev, 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); @@ -218,8 +261,10 @@ int qxl_device_init(struct qxl_device *qdev, /* must initialize irq before first async io - slot creation */ r = qxl_irq_init(qdev); - if (r) - return r; + if (r) { + DRM_ERROR("Unable to init qxl irq\n"); + goto mem_slots_free; + } /* * Note that virtual is surface0. We rely on the single ioremap done @@ -243,6 +288,27 @@ int qxl_device_init(struct qxl_device *qdev, 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: + qxl_ring_free(qdev->cursor_ring); +command_ring_free: + qxl_ring_free(qdev->command_ring); +ram_header_unmap: + iounmap(qdev->ram_header); +bo_fini: + qxl_bo_fini(qdev); +rom_unmap: + iounmap(qdev->rom); +surface_mapping_free: + io_mapping_free(qdev->surface_mapping); +vram_mapping_free: + io_mapping_free(qdev->vram_mapping); +error: + return r; } void qxl_device_fini(struct qxl_device *qdev) |