|
@@ -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)
|