diff options
author | weiping zhang <zhangweiping@didichuxing.com> | 2017-12-21 07:40:43 -0500 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2018-02-01 09:26:45 -0500 |
commit | 0063e8bbd2b62d13645d416625478c2199fdee0f (patch) | |
tree | f913958c384c5faaf936626b6764c7e68a971122 | |
parent | 33635bd976fb4c3ccf0cfbb81a8d29bb87760607 (diff) |
virtio_vop: don't kfree device on register failure
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 vdev until vdev->vdev.dev.release be called.
Signed-off-by: weiping zhang <zhangweiping@didichuxing.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r-- | drivers/misc/mic/vop/vop_main.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c index a341938c7e2c..3633202e18f4 100644 --- a/drivers/misc/mic/vop/vop_main.c +++ b/drivers/misc/mic/vop/vop_main.c | |||
@@ -452,10 +452,12 @@ static irqreturn_t vop_virtio_intr_handler(int irq, void *data) | |||
452 | 452 | ||
453 | static void vop_virtio_release_dev(struct device *_d) | 453 | static void vop_virtio_release_dev(struct device *_d) |
454 | { | 454 | { |
455 | /* | 455 | struct virtio_device *vdev = |
456 | * No need for a release method similar to virtio PCI. | 456 | container_of(_d, struct virtio_device, dev); |
457 | * Provide an empty one to avoid getting a warning from core. | 457 | struct _vop_vdev *vop_vdev = |
458 | */ | 458 | container_of(vdev, struct _vop_vdev, vdev); |
459 | |||
460 | kfree(vop_vdev); | ||
459 | } | 461 | } |
460 | 462 | ||
461 | /* | 463 | /* |
@@ -466,7 +468,7 @@ static int _vop_add_device(struct mic_device_desc __iomem *d, | |||
466 | unsigned int offset, struct vop_device *vpdev, | 468 | unsigned int offset, struct vop_device *vpdev, |
467 | int dnode) | 469 | int dnode) |
468 | { | 470 | { |
469 | struct _vop_vdev *vdev; | 471 | struct _vop_vdev *vdev, *reg_dev = NULL; |
470 | int ret; | 472 | int ret; |
471 | u8 type = ioread8(&d->type); | 473 | u8 type = ioread8(&d->type); |
472 | 474 | ||
@@ -497,6 +499,7 @@ static int _vop_add_device(struct mic_device_desc __iomem *d, | |||
497 | vdev->c2h_vdev_db = ioread8(&vdev->dc->c2h_vdev_db); | 499 | vdev->c2h_vdev_db = ioread8(&vdev->dc->c2h_vdev_db); |
498 | 500 | ||
499 | ret = register_virtio_device(&vdev->vdev); | 501 | ret = register_virtio_device(&vdev->vdev); |
502 | reg_dev = vdev; | ||
500 | if (ret) { | 503 | if (ret) { |
501 | dev_err(_vop_dev(vdev), | 504 | dev_err(_vop_dev(vdev), |
502 | "Failed to register vop device %u type %u\n", | 505 | "Failed to register vop device %u type %u\n", |
@@ -512,7 +515,10 @@ static int _vop_add_device(struct mic_device_desc __iomem *d, | |||
512 | free_irq: | 515 | free_irq: |
513 | vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev); | 516 | vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev); |
514 | kfree: | 517 | kfree: |
515 | kfree(vdev); | 518 | if (reg_dev) |
519 | put_device(&vdev->vdev.dev); | ||
520 | else | ||
521 | kfree(vdev); | ||
516 | return ret; | 522 | return ret; |
517 | } | 523 | } |
518 | 524 | ||
@@ -568,7 +574,7 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d, | |||
568 | iowrite8(-1, &dc->h2c_vdev_db); | 574 | iowrite8(-1, &dc->h2c_vdev_db); |
569 | if (status & VIRTIO_CONFIG_S_DRIVER_OK) | 575 | if (status & VIRTIO_CONFIG_S_DRIVER_OK) |
570 | wait_for_completion(&vdev->reset_done); | 576 | wait_for_completion(&vdev->reset_done); |
571 | kfree(vdev); | 577 | put_device(&vdev->vdev.dev); |
572 | iowrite8(1, &dc->guest_ack); | 578 | iowrite8(1, &dc->guest_ack); |
573 | dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n", | 579 | dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n", |
574 | __func__, __LINE__, ioread8(&dc->guest_ack)); | 580 | __func__, __LINE__, ioread8(&dc->guest_ack)); |