aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2017-12-12 08:45:50 -0500
committerMichael S. Tsirkin <mst@redhat.com>2017-12-14 14:01:40 -0500
commitc2e90800aef22e7ea14ea7560ba99993f11d3616 (patch)
tree3fbd339394fe73cde6ae383d8c12184484911d52 /drivers/virtio
parent5790eabc6e7c3ce2d6ca2e3bbf4de467ce2b64b3 (diff)
virtio_mmio: fix devm cleanup
Recent rework of the virtio_mmio probe/remove paths balanced a devm_ioremap() with an iounmap() rather than its devm variant. This ends up corrupting the devm datastructures, and results in the following boot-time splat on arm64 under QEMU 2.9.0: [ 3.450397] ------------[ cut here ]------------ [ 3.453822] Trying to vfree() nonexistent vm area (00000000c05b4844) [ 3.460534] WARNING: CPU: 1 PID: 1 at mm/vmalloc.c:1525 __vunmap+0x1b8/0x220 [ 3.475898] Kernel panic - not syncing: panic_on_warn set ... [ 3.475898] [ 3.493933] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.15.0-rc3 #1 [ 3.513109] Hardware name: linux,dummy-virt (DT) [ 3.525382] Call trace: [ 3.531683] dump_backtrace+0x0/0x368 [ 3.543921] show_stack+0x20/0x30 [ 3.547767] dump_stack+0x108/0x164 [ 3.559584] panic+0x25c/0x51c [ 3.569184] __warn+0x29c/0x31c [ 3.576023] report_bug+0x1d4/0x290 [ 3.586069] bug_handler.part.2+0x40/0x100 [ 3.597820] bug_handler+0x4c/0x88 [ 3.608400] brk_handler+0x11c/0x218 [ 3.613430] do_debug_exception+0xe8/0x318 [ 3.627370] el1_dbg+0x18/0x78 [ 3.634037] __vunmap+0x1b8/0x220 [ 3.648747] vunmap+0x6c/0xc0 [ 3.653864] __iounmap+0x44/0x58 [ 3.659771] devm_ioremap_release+0x34/0x68 [ 3.672983] release_nodes+0x404/0x880 [ 3.683543] devres_release_all+0x6c/0xe8 [ 3.695692] driver_probe_device+0x250/0x828 [ 3.706187] __driver_attach+0x190/0x210 [ 3.717645] bus_for_each_dev+0x14c/0x1f0 [ 3.728633] driver_attach+0x48/0x78 [ 3.740249] bus_add_driver+0x26c/0x5b8 [ 3.752248] driver_register+0x16c/0x398 [ 3.757211] __platform_driver_register+0xd8/0x128 [ 3.770860] virtio_mmio_init+0x1c/0x24 [ 3.782671] do_one_initcall+0xe0/0x398 [ 3.791890] kernel_init_freeable+0x594/0x660 [ 3.798514] kernel_init+0x18/0x190 [ 3.810220] ret_from_fork+0x10/0x18 To fix this, we can simply rip out the explicit cleanup that the devm infrastructure will do for us when our probe function returns an error code, or when our remove function returns. We only need to ensure that we call put_device() if a call to register_virtio_device() fails in the probe path. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Fixes: 7eb781b1bbb7136f ("virtio_mmio: add cleanup for virtio_mmio_probe") Fixes: 25f32223bce5c580 ("virtio_mmio: add cleanup for virtio_mmio_remove") Cc: Cornelia Huck <cohuck@redhat.com> Cc: Michael S. Tsirkin <mst@redhat.com> Cc: weiping zhang <zhangweiping@didichuxing.com> Cc: virtualization@lists.linux-foundation.org Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Diffstat (limited to 'drivers/virtio')
-rw-r--r--drivers/virtio/virtio_mmio.c43
1 files changed, 9 insertions, 34 deletions
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index a9192fe4f345..c92131edfaba 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -522,10 +522,8 @@ static int virtio_mmio_probe(struct platform_device *pdev)
522 return -EBUSY; 522 return -EBUSY;
523 523
524 vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL); 524 vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
525 if (!vm_dev) { 525 if (!vm_dev)
526 rc = -ENOMEM; 526 return -ENOMEM;
527 goto free_mem;
528 }
529 527
530 vm_dev->vdev.dev.parent = &pdev->dev; 528 vm_dev->vdev.dev.parent = &pdev->dev;
531 vm_dev->vdev.dev.release = virtio_mmio_release_dev; 529 vm_dev->vdev.dev.release = virtio_mmio_release_dev;
@@ -535,17 +533,14 @@ static int virtio_mmio_probe(struct platform_device *pdev)
535 spin_lock_init(&vm_dev->lock); 533 spin_lock_init(&vm_dev->lock);
536 534
537 vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); 535 vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
538 if (vm_dev->base == NULL) { 536 if (vm_dev->base == NULL)
539 rc = -EFAULT; 537 return -EFAULT;
540 goto free_vmdev;
541 }
542 538
543 /* Check magic value */ 539 /* Check magic value */
544 magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); 540 magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
545 if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { 541 if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
546 dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); 542 dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic);
547 rc = -ENODEV; 543 return -ENODEV;
548 goto unmap;
549 } 544 }
550 545
551 /* Check device version */ 546 /* Check device version */
@@ -553,8 +548,7 @@ static int virtio_mmio_probe(struct platform_device *pdev)
553 if (vm_dev->version < 1 || vm_dev->version > 2) { 548 if (vm_dev->version < 1 || vm_dev->version > 2) {
554 dev_err(&pdev->dev, "Version %ld not supported!\n", 549 dev_err(&pdev->dev, "Version %ld not supported!\n",
555 vm_dev->version); 550 vm_dev->version);
556 rc = -ENXIO; 551 return -ENXIO;
557 goto unmap;
558 } 552 }
559 553
560 vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); 554 vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
@@ -563,8 +557,7 @@ static int virtio_mmio_probe(struct platform_device *pdev)
563 * virtio-mmio device with an ID 0 is a (dummy) placeholder 557 * virtio-mmio device with an ID 0 is a (dummy) placeholder
564 * with no function. End probing now with no error reported. 558 * with no function. End probing now with no error reported.
565 */ 559 */
566 rc = -ENODEV; 560 return -ENODEV;
567 goto unmap;
568 } 561 }
569 vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); 562 vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
570 563
@@ -590,33 +583,15 @@ static int virtio_mmio_probe(struct platform_device *pdev)
590 platform_set_drvdata(pdev, vm_dev); 583 platform_set_drvdata(pdev, vm_dev);
591 584
592 rc = register_virtio_device(&vm_dev->vdev); 585 rc = register_virtio_device(&vm_dev->vdev);
593 if (rc) { 586 if (rc)
594 iounmap(vm_dev->base);
595 devm_release_mem_region(&pdev->dev, mem->start,
596 resource_size(mem));
597 put_device(&vm_dev->vdev.dev); 587 put_device(&vm_dev->vdev.dev);
598 } 588
599 return rc;
600unmap:
601 iounmap(vm_dev->base);
602free_mem:
603 devm_release_mem_region(&pdev->dev, mem->start,
604 resource_size(mem));
605free_vmdev:
606 devm_kfree(&pdev->dev, vm_dev);
607 return rc; 589 return rc;
608} 590}
609 591
610static int virtio_mmio_remove(struct platform_device *pdev) 592static int virtio_mmio_remove(struct platform_device *pdev)
611{ 593{
612 struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev); 594 struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev);
613 struct resource *mem;
614
615 iounmap(vm_dev->base);
616 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
617 if (mem)
618 devm_release_mem_region(&pdev->dev, mem->start,
619 resource_size(mem));
620 unregister_virtio_device(&vm_dev->vdev); 595 unregister_virtio_device(&vm_dev->vdev);
621 596
622 return 0; 597 return 0;