diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2017-03-03 12:00:09 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2017-03-06 15:24:48 -0500 |
commit | d85fc67dd11e9a32966140677d4d6429ca540b25 (patch) | |
tree | faf40259eb99fc42941b828a7870fbff6f012146 /drivers/ata | |
parent | c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201 (diff) |
libata: transport: Remove circular dependency at free time
Without this patch, failed probe would not free resources like irq.
ata port tdev object currently hold a reference to the ata port
object. Therefore the ata port object release function will not get
called until the ata_tport_release is called. But that would never
happen, releasing the last reference of ata port dev is done by
scsi_host_release, which is called by ata_host_release when the ata
port object is released.
The ata device objects actually do not need to explicitly hold a
reference to their real counterpart, given the transport objects are
the children of these objects and device_add() is call for each child.
We know the parent will not be deleted until we call the child's
device_del().
Reported-by: Matthew Whitehead <tedheadster@gmail.com>
Tested-by: Matthew Whitehead <tedheadster@gmail.com>
Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-transport.c | 9 |
1 files changed, 3 insertions, 6 deletions
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 46698232e6bf..19e6e539a061 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c | |||
@@ -224,7 +224,6 @@ static DECLARE_TRANSPORT_CLASS(ata_port_class, | |||
224 | 224 | ||
225 | static void ata_tport_release(struct device *dev) | 225 | static void ata_tport_release(struct device *dev) |
226 | { | 226 | { |
227 | put_device(dev->parent); | ||
228 | } | 227 | } |
229 | 228 | ||
230 | /** | 229 | /** |
@@ -284,7 +283,7 @@ int ata_tport_add(struct device *parent, | |||
284 | device_initialize(dev); | 283 | device_initialize(dev); |
285 | dev->type = &ata_port_type; | 284 | dev->type = &ata_port_type; |
286 | 285 | ||
287 | dev->parent = get_device(parent); | 286 | dev->parent = parent; |
288 | dev->release = ata_tport_release; | 287 | dev->release = ata_tport_release; |
289 | dev_set_name(dev, "ata%d", ap->print_id); | 288 | dev_set_name(dev, "ata%d", ap->print_id); |
290 | transport_setup_device(dev); | 289 | transport_setup_device(dev); |
@@ -348,7 +347,6 @@ static DECLARE_TRANSPORT_CLASS(ata_link_class, | |||
348 | 347 | ||
349 | static void ata_tlink_release(struct device *dev) | 348 | static void ata_tlink_release(struct device *dev) |
350 | { | 349 | { |
351 | put_device(dev->parent); | ||
352 | } | 350 | } |
353 | 351 | ||
354 | /** | 352 | /** |
@@ -410,7 +408,7 @@ int ata_tlink_add(struct ata_link *link) | |||
410 | int error; | 408 | int error; |
411 | 409 | ||
412 | device_initialize(dev); | 410 | device_initialize(dev); |
413 | dev->parent = get_device(&ap->tdev); | 411 | dev->parent = &ap->tdev; |
414 | dev->release = ata_tlink_release; | 412 | dev->release = ata_tlink_release; |
415 | if (ata_is_host_link(link)) | 413 | if (ata_is_host_link(link)) |
416 | dev_set_name(dev, "link%d", ap->print_id); | 414 | dev_set_name(dev, "link%d", ap->print_id); |
@@ -589,7 +587,6 @@ static DECLARE_TRANSPORT_CLASS(ata_dev_class, | |||
589 | 587 | ||
590 | static void ata_tdev_release(struct device *dev) | 588 | static void ata_tdev_release(struct device *dev) |
591 | { | 589 | { |
592 | put_device(dev->parent); | ||
593 | } | 590 | } |
594 | 591 | ||
595 | /** | 592 | /** |
@@ -662,7 +659,7 @@ static int ata_tdev_add(struct ata_device *ata_dev) | |||
662 | int error; | 659 | int error; |
663 | 660 | ||
664 | device_initialize(dev); | 661 | device_initialize(dev); |
665 | dev->parent = get_device(&link->tdev); | 662 | dev->parent = &link->tdev; |
666 | dev->release = ata_tdev_release; | 663 | dev->release = ata_tdev_release; |
667 | if (ata_is_host_link(link)) | 664 | if (ata_is_host_link(link)) |
668 | dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno); | 665 | dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno); |