[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20170920044542.7571-30-alexander.levin@verizon.com>
Date: Wed, 20 Sep 2017 04:45:57 +0000
From: "Levin, Alexander (Sasha Levin)" <alexander.levin@...izon.com>
To: "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"stable@...r.kernel.org" <stable@...r.kernel.org>
Cc: Gwendal Grignou <gwendal@...omium.org>, Tejun Heo <tj@...nel.org>,
"Levin, Alexander (Sasha Levin)" <alexander.levin@...izon.com>
Subject: [PATCH review for 3.18 30/30] libata: transport: Remove circular
dependency at free time
From: Gwendal Grignou <gwendal@...omium.org>
[ Upstream commit d85fc67dd11e9a32966140677d4d6429ca540b25 ]
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@...il.com>
Tested-by: Matthew Whitehead <tedheadster@...il.com>
Suggested-by: Tejun Heo <tj@...nel.org>
Signed-off-by: Gwendal Grignou <gwendal@...omium.org>
Signed-off-by: Tejun Heo <tj@...nel.org>
Signed-off-by: Sasha Levin <alexander.levin@...izon.com>
---
drivers/ata/libata-transport.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
index fd29b7224082..43d4fbb377da 100644
--- a/drivers/ata/libata-transport.c
+++ b/drivers/ata/libata-transport.c
@@ -223,7 +223,6 @@ static DECLARE_TRANSPORT_CLASS(ata_port_class,
static void ata_tport_release(struct device *dev)
{
- put_device(dev->parent);
}
/**
@@ -283,7 +282,7 @@ int ata_tport_add(struct device *parent,
device_initialize(dev);
dev->type = &ata_port_type;
- dev->parent = get_device(parent);
+ dev->parent = parent;
dev->release = ata_tport_release;
dev_set_name(dev, "ata%d", ap->print_id);
transport_setup_device(dev);
@@ -347,7 +346,6 @@ static DECLARE_TRANSPORT_CLASS(ata_link_class,
static void ata_tlink_release(struct device *dev)
{
- put_device(dev->parent);
}
/**
@@ -409,7 +407,7 @@ int ata_tlink_add(struct ata_link *link)
int error;
device_initialize(dev);
- dev->parent = get_device(&ap->tdev);
+ dev->parent = &ap->tdev;
dev->release = ata_tlink_release;
if (ata_is_host_link(link))
dev_set_name(dev, "link%d", ap->print_id);
@@ -587,7 +585,6 @@ static DECLARE_TRANSPORT_CLASS(ata_dev_class,
static void ata_tdev_release(struct device *dev)
{
- put_device(dev->parent);
}
/**
@@ -660,7 +657,7 @@ static int ata_tdev_add(struct ata_device *ata_dev)
int error;
device_initialize(dev);
- dev->parent = get_device(&link->tdev);
+ dev->parent = &link->tdev;
dev->release = ata_tdev_release;
if (ata_is_host_link(link))
dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno);
--
2.11.0
Powered by blists - more mailing lists