diff options
author | weiping zhang <zhangweiping@didichuxing.com> | 2017-12-06 08:59:16 -0500 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2017-12-07 11:30:50 -0500 |
commit | 7eb781b1bbb7136fe78fb8c28c1c223c61fa32b5 (patch) | |
tree | 38ef83887dd988fe7ea05a07d0f3ec1ac8461c26 | |
parent | d9e427f6ab8142d6868eb719e6a7851aafea56b6 (diff) |
virtio_mmio: add cleanup for virtio_mmio_probe
As mentioned at drivers/base/core.c:
/*
* NOTE: _Never_ directly free @dev after calling this function, even
* if it returned an error! Always use put_device() to give up the
* reference initialized in this function instead.
*/
so we don't free vm_dev until vm_dev.dev.release be called.
Signed-off-by: weiping zhang <zhangweiping@didichuxing.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
-rw-r--r-- | drivers/virtio/virtio_mmio.c | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 74dc7170fd35..ec401042a5d1 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c | |||
@@ -493,7 +493,16 @@ static const struct virtio_config_ops virtio_mmio_config_ops = { | |||
493 | }; | 493 | }; |
494 | 494 | ||
495 | 495 | ||
496 | static void virtio_mmio_release_dev_empty(struct device *_d) {} | 496 | static void virtio_mmio_release_dev(struct device *_d) |
497 | { | ||
498 | struct virtio_device *vdev = | ||
499 | container_of(_d, struct virtio_device, dev); | ||
500 | struct virtio_mmio_device *vm_dev = | ||
501 | container_of(vdev, struct virtio_mmio_device, vdev); | ||
502 | struct platform_device *pdev = vm_dev->pdev; | ||
503 | |||
504 | devm_kfree(&pdev->dev, vm_dev); | ||
505 | } | ||
497 | 506 | ||
498 | /* Platform device */ | 507 | /* Platform device */ |
499 | 508 | ||
@@ -513,25 +522,30 @@ static int virtio_mmio_probe(struct platform_device *pdev) | |||
513 | return -EBUSY; | 522 | return -EBUSY; |
514 | 523 | ||
515 | vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL); | 524 | vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL); |
516 | if (!vm_dev) | 525 | if (!vm_dev) { |
517 | return -ENOMEM; | 526 | rc = -ENOMEM; |
527 | goto free_mem; | ||
528 | } | ||
518 | 529 | ||
519 | vm_dev->vdev.dev.parent = &pdev->dev; | 530 | vm_dev->vdev.dev.parent = &pdev->dev; |
520 | vm_dev->vdev.dev.release = virtio_mmio_release_dev_empty; | 531 | vm_dev->vdev.dev.release = virtio_mmio_release_dev; |
521 | vm_dev->vdev.config = &virtio_mmio_config_ops; | 532 | vm_dev->vdev.config = &virtio_mmio_config_ops; |
522 | vm_dev->pdev = pdev; | 533 | vm_dev->pdev = pdev; |
523 | INIT_LIST_HEAD(&vm_dev->virtqueues); | 534 | INIT_LIST_HEAD(&vm_dev->virtqueues); |
524 | spin_lock_init(&vm_dev->lock); | 535 | spin_lock_init(&vm_dev->lock); |
525 | 536 | ||
526 | vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | 537 | vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); |
527 | if (vm_dev->base == NULL) | 538 | if (vm_dev->base == NULL) { |
528 | return -EFAULT; | 539 | rc = -EFAULT; |
540 | goto free_vmdev; | ||
541 | } | ||
529 | 542 | ||
530 | /* Check magic value */ | 543 | /* Check magic value */ |
531 | magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); | 544 | magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); |
532 | if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { | 545 | if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { |
533 | dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); | 546 | dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); |
534 | return -ENODEV; | 547 | rc = -ENODEV; |
548 | goto unmap; | ||
535 | } | 549 | } |
536 | 550 | ||
537 | /* Check device version */ | 551 | /* Check device version */ |
@@ -539,7 +553,8 @@ static int virtio_mmio_probe(struct platform_device *pdev) | |||
539 | if (vm_dev->version < 1 || vm_dev->version > 2) { | 553 | if (vm_dev->version < 1 || vm_dev->version > 2) { |
540 | dev_err(&pdev->dev, "Version %ld not supported!\n", | 554 | dev_err(&pdev->dev, "Version %ld not supported!\n", |
541 | vm_dev->version); | 555 | vm_dev->version); |
542 | return -ENXIO; | 556 | rc = -ENXIO; |
557 | goto unmap; | ||
543 | } | 558 | } |
544 | 559 | ||
545 | vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); | 560 | vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); |
@@ -548,7 +563,8 @@ static int virtio_mmio_probe(struct platform_device *pdev) | |||
548 | * virtio-mmio device with an ID 0 is a (dummy) placeholder | 563 | * virtio-mmio device with an ID 0 is a (dummy) placeholder |
549 | * with no function. End probing now with no error reported. | 564 | * with no function. End probing now with no error reported. |
550 | */ | 565 | */ |
551 | return -ENODEV; | 566 | rc = -ENODEV; |
567 | goto unmap; | ||
552 | } | 568 | } |
553 | vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); | 569 | vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); |
554 | 570 | ||
@@ -573,7 +589,22 @@ static int virtio_mmio_probe(struct platform_device *pdev) | |||
573 | 589 | ||
574 | platform_set_drvdata(pdev, vm_dev); | 590 | platform_set_drvdata(pdev, vm_dev); |
575 | 591 | ||
576 | return register_virtio_device(&vm_dev->vdev); | 592 | rc = register_virtio_device(&vm_dev->vdev); |
593 | 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); | ||
598 | } | ||
599 | return rc; | ||
600 | unmap: | ||
601 | iounmap(vm_dev->base); | ||
602 | free_mem: | ||
603 | devm_release_mem_region(&pdev->dev, mem->start, | ||
604 | resource_size(mem)); | ||
605 | free_vmdev: | ||
606 | devm_kfree(&pdev->dev, vm_dev); | ||
607 | return rc; | ||
577 | } | 608 | } |
578 | 609 | ||
579 | static int virtio_mmio_remove(struct platform_device *pdev) | 610 | static int virtio_mmio_remove(struct platform_device *pdev) |