diff mbox

[3/3] ata: prevent double resume of ata platform device on init

Message ID 20180716224103.7912-4-0v3rdr0n3@gmail.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

0v3rdr0n3@gmail.com July 16, 2018, 10:41 p.m. UTC
From: Samuel Morris <samorris@lexmark.com>

This prevents the first resume of the ahci_platform device, while still
allowing parent devices to be resumed.

Signed-off-by: Samuel Morris <samorris@lexmark.com>
---
 drivers/ata/ahci.h             |  1 +
 drivers/ata/libahci_platform.c | 19 +++++++++++++------
 2 files changed, 14 insertions(+), 6 deletions(-)

Comments

Samuel Morris July 18, 2018, 5:54 p.m. UTC | #1
Adding Hans de Goede...

On Mon, Jul 16, 2018 at 10:41 PM, Sam Morris <0v3rdr0n3@gmail.com> wrote:
> From: Samuel Morris <samorris@lexmark.com>
>
> This prevents the first resume of the ahci_platform device, while still
> allowing parent devices to be resumed.
>
> Signed-off-by: Samuel Morris <samorris@lexmark.com>
> ---
>  drivers/ata/ahci.h             |  1 +
>  drivers/ata/libahci_platform.c | 19 +++++++++++++------
>  2 files changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index 1609ebab4e23..8ec39f69fae4 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -349,6 +349,7 @@ struct ahci_host_priv {
>         u32                     em_buf_sz;      /* EM buffer size in byte */
>         u32                     em_msg_type;    /* EM message type */
>         bool                    got_runtime_pm; /* Did we do pm_runtime_get? */
> +       bool                    initialized;
>         struct clk              *clks[AHCI_MAX_CLKS]; /* Optional */
>         struct regulator        **target_pwrs;  /* Optional */
>         /*
> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> index feee2e11fb33..baad85adf90c 100644
> --- a/drivers/ata/libahci_platform.c
> +++ b/drivers/ata/libahci_platform.c
> @@ -476,11 +476,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
>                         goto err_out;
>         }
>
> -       pm_runtime_set_active(dev);
> -       pm_runtime_enable(dev);
> -       pm_runtime_forbid(dev);
> -       hpriv->got_runtime_pm = true;
> -
>         devres_remove_group(dev, NULL);
>         return hpriv;
>
> @@ -594,7 +589,16 @@ int ahci_platform_init_host(struct platform_device *pdev,
>         ahci_init_controller(host);
>         ahci_print_info(host, "platform");
>
> -       return ahci_host_activate(host, sht);
> +       rc = ahci_host_activate(host, sht);
> +       if (rc)
> +               return rc;
> +
> +       pm_runtime_enable(dev);
> +       pm_runtime_forbid(dev);
> +       hpriv->got_runtime_pm = true;
> +       hpriv->initialized = true;
> +
> +       return 0;
>  }
>  EXPORT_SYMBOL_GPL(ahci_platform_init_host);
>
> @@ -760,6 +764,9 @@ static int _ahci_platform_resume(struct device *dev)
>         struct ahci_host_priv *hpriv = host->private_data;
>         int rc;
>
> +       if (!hpriv->initialized)
> +               return 0;
> +
>         rc = ahci_platform_enable_resources(hpriv);
>         if (rc)
>                 return rc;
> --
> 2.17.0
>
Hans de Goede July 19, 2018, 12:51 p.m. UTC | #2
Hi,

On 18-07-18 19:54, Samuel Morris wrote:
> Adding Hans de Goede...

Thanks, patch 2/3 looks good to me.

I've some remarks inline in this one, note I'm not
an expert on runtime pm support, it might be good if
someone more knowledgeable on this subject replies.


> On Mon, Jul 16, 2018 at 10:41 PM, Sam Morris <0v3rdr0n3@gmail.com> wrote:
>> From: Samuel Morris <samorris@lexmark.com>
>>
>> This prevents the first resume of the ahci_platform device, while still
>> allowing parent devices to be resumed.
>>
>> Signed-off-by: Samuel Morris <samorris@lexmark.com>
>> ---
>>   drivers/ata/ahci.h             |  1 +
>>   drivers/ata/libahci_platform.c | 19 +++++++++++++------
>>   2 files changed, 14 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
>> index 1609ebab4e23..8ec39f69fae4 100644
>> --- a/drivers/ata/ahci.h
>> +++ b/drivers/ata/ahci.h
>> @@ -349,6 +349,7 @@ struct ahci_host_priv {
>>          u32                     em_buf_sz;      /* EM buffer size in byte */
>>          u32                     em_msg_type;    /* EM message type */
>>          bool                    got_runtime_pm; /* Did we do pm_runtime_get? */
>> +       bool                    initialized;
>>          struct clk              *clks[AHCI_MAX_CLKS]; /* Optional */
>>          struct regulator        **target_pwrs;  /* Optional */
>>          /*
>> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
>> index feee2e11fb33..baad85adf90c 100644
>> --- a/drivers/ata/libahci_platform.c
>> +++ b/drivers/ata/libahci_platform.c
>> @@ -476,11 +476,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
>>                          goto err_out;
>>          }
>>
>> -       pm_runtime_set_active(dev);

The set_active before enable you are removing here should already avoid
resume being called on init and thus enable_resources being called
twice (which I assume is the problem, resume should never be called
twice itself).

>> -       pm_runtime_enable(dev);
>> -       pm_runtime_forbid(dev);
>> -       hpriv->got_runtime_pm = true;
>> -
>>          devres_remove_group(dev, NULL);
>>          return hpriv;
>>
>> @@ -594,7 +589,16 @@ int ahci_platform_init_host(struct platform_device *pdev,
>>          ahci_init_controller(host);
>>          ahci_print_info(host, "platform");
>>
>> -       return ahci_host_activate(host, sht);
>> +       rc = ahci_host_activate(host, sht);
>> +       if (rc)
>> +               return rc;
>> +
>> +       pm_runtime_enable(dev);
>> +       pm_runtime_forbid(dev);
>> +       hpriv->got_runtime_pm = true;
>> +       hpriv->initialized = true;
>> +
>> +       return 0;
>>   }
>>   EXPORT_SYMBOL_GPL(ahci_platform_init_host);
>>

Hmm, moving thus from get_resources to platform_init_host while keeping
the counter parts in put_resources makes get_resources and
put_resources asymmetrical. As such I'm not a fan of this change.

Regards,

Hans



>> @@ -760,6 +764,9 @@ static int _ahci_platform_resume(struct device *dev)
>>          struct ahci_host_priv *hpriv = host->private_data;
>>          int rc;
>>
>> +       if (!hpriv->initialized)
>> +               return 0;
>> +
>>          rc = ahci_platform_enable_resources(hpriv);
>>          if (rc)
>>                  return rc;
>> --
>> 2.17.0
>>
Samuel Morris July 19, 2018, 5:43 p.m. UTC | #3
On Thu, Jul 19, 2018 at 12:51 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-07-18 19:54, Samuel Morris wrote:
>>
>> Adding Hans de Goede...
>
>
> Thanks, patch 2/3 looks good to me.
>
> I've some remarks inline in this one, note I'm not
> an expert on runtime pm support, it might be good if
> someone more knowledgeable on this subject replies.
>
>
>
>> On Mon, Jul 16, 2018 at 10:41 PM, Sam Morris <0v3rdr0n3@gmail.com> wrote:
>>>
>>> From: Samuel Morris <samorris@lexmark.com>
>>>
>>> This prevents the first resume of the ahci_platform device, while still
>>> allowing parent devices to be resumed.
>>>
>>> Signed-off-by: Samuel Morris <samorris@lexmark.com>
>>> ---
>>>   drivers/ata/ahci.h             |  1 +
>>>   drivers/ata/libahci_platform.c | 19 +++++++++++++------
>>>   2 files changed, 14 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
>>> index 1609ebab4e23..8ec39f69fae4 100644
>>> --- a/drivers/ata/ahci.h
>>> +++ b/drivers/ata/ahci.h
>>> @@ -349,6 +349,7 @@ struct ahci_host_priv {
>>>          u32                     em_buf_sz;      /* EM buffer size in
>>> byte */
>>>          u32                     em_msg_type;    /* EM message type */
>>>          bool                    got_runtime_pm; /* Did we do
>>> pm_runtime_get? */
>>> +       bool                    initialized;
>>>          struct clk              *clks[AHCI_MAX_CLKS]; /* Optional */
>>>          struct regulator        **target_pwrs;  /* Optional */
>>>          /*
>>> diff --git a/drivers/ata/libahci_platform.c
>>> b/drivers/ata/libahci_platform.c
>>> index feee2e11fb33..baad85adf90c 100644
>>> --- a/drivers/ata/libahci_platform.c
>>> +++ b/drivers/ata/libahci_platform.c
>>> @@ -476,11 +476,6 @@ struct ahci_host_priv
>>> *ahci_platform_get_resources(struct platform_device *pdev)
>>>                          goto err_out;
>>>          }
>>>
>>> -       pm_runtime_set_active(dev);
>
>
> The set_active before enable you are removing here should already avoid
> resume being called on init and thus enable_resources being called
> twice (which I assume is the problem, resume should never be called
> twice itself).
>
>>> -       pm_runtime_enable(dev);
>>> -       pm_runtime_forbid(dev);
>>> -       hpriv->got_runtime_pm = true;
>>> -
>>>          devres_remove_group(dev, NULL);
>>>          return hpriv;
>>>
>>> @@ -594,7 +589,16 @@ int ahci_platform_init_host(struct platform_device
>>> *pdev,
>>>          ahci_init_controller(host);
>>>          ahci_print_info(host, "platform");
>>>
>>> -       return ahci_host_activate(host, sht);
>>> +       rc = ahci_host_activate(host, sht);
>>> +       if (rc)
>>> +               return rc;
>>> +
>>> +       pm_runtime_enable(dev);
>>> +       pm_runtime_forbid(dev);
>>> +       hpriv->got_runtime_pm = true;
>>> +       hpriv->initialized = true;
>>> +
>>> +       return 0;
>>>   }
>>>   EXPORT_SYMBOL_GPL(ahci_platform_init_host);
>>>
>
> Hmm, moving thus from get_resources to platform_init_host while keeping
> the counter parts in put_resources makes get_resources and
> put_resources asymmetrical. As such I'm not a fan of this change.

I don't much like the ordering either, but if runtime_resume is
called, then it needs the platform data, which is not set until
ahci_platform_get_resources returns, naturally. This wouldn't be a
problem if we didn't need to resume the parent devices for these OMAP
devices, but again, I'm just guessing that's what caused the
beagleboard issue, and making sure we do exactly the same operations
on probe as before is my way of sidestepping that problem for now. A
better solution if I'm right perhaps would be to move or copy whatever
resume operations are necessary for those parent devices to their
probe, rather than relying on runtime_pm to initialize the device.
Then, to make sure the parent module loads before ahci_platform, I
typically use modprobe.d, or just build both dependent drivers into
the kernel. Or, at runtime, if you can keep track of that dependency,
you could just defer until it's ready, like the regulator subsystem.

As is though, it might be best to move the runtime_put out of
put_resources and into a new remove callback.

>
> Regards,
>
> Hans
>
>
>
>
>>> @@ -760,6 +764,9 @@ static int _ahci_platform_resume(struct device *dev)
>>>          struct ahci_host_priv *hpriv = host->private_data;
>>>          int rc;
>>>
>>> +       if (!hpriv->initialized)
>>> +               return 0;
>>> +
>>>          rc = ahci_platform_enable_resources(hpriv);
>>>          if (rc)
>>>                  return rc;
>>> --
>>> 2.17.0
>>>
>
Roger Quadros July 23, 2018, 12:31 p.m. UTC | #4
+Tero/Tony,

On 19/07/18 20:43, Samuel Morris wrote:
> On Thu, Jul 19, 2018 at 12:51 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>> On 18-07-18 19:54, Samuel Morris wrote:
>>>
>>> Adding Hans de Goede...
>>
>>
>> Thanks, patch 2/3 looks good to me.
>>
>> I've some remarks inline in this one, note I'm not
>> an expert on runtime pm support, it might be good if
>> someone more knowledgeable on this subject replies.
>>
>>
>>
>>> On Mon, Jul 16, 2018 at 10:41 PM, Sam Morris <0v3rdr0n3@gmail.com> wrote:
>>>>
>>>> From: Samuel Morris <samorris@lexmark.com>
>>>>
>>>> This prevents the first resume of the ahci_platform device, while still
>>>> allowing parent devices to be resumed.
>>>>
>>>> Signed-off-by: Samuel Morris <samorris@lexmark.com>
>>>> ---
>>>>   drivers/ata/ahci.h             |  1 +
>>>>   drivers/ata/libahci_platform.c | 19 +++++++++++++------
>>>>   2 files changed, 14 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
>>>> index 1609ebab4e23..8ec39f69fae4 100644
>>>> --- a/drivers/ata/ahci.h
>>>> +++ b/drivers/ata/ahci.h
>>>> @@ -349,6 +349,7 @@ struct ahci_host_priv {
>>>>          u32                     em_buf_sz;      /* EM buffer size in
>>>> byte */
>>>>          u32                     em_msg_type;    /* EM message type */
>>>>          bool                    got_runtime_pm; /* Did we do
>>>> pm_runtime_get? */
>>>> +       bool                    initialized;
>>>>          struct clk              *clks[AHCI_MAX_CLKS]; /* Optional */
>>>>          struct regulator        **target_pwrs;  /* Optional */
>>>>          /*
>>>> diff --git a/drivers/ata/libahci_platform.c
>>>> b/drivers/ata/libahci_platform.c
>>>> index feee2e11fb33..baad85adf90c 100644
>>>> --- a/drivers/ata/libahci_platform.c
>>>> +++ b/drivers/ata/libahci_platform.c
>>>> @@ -476,11 +476,6 @@ struct ahci_host_priv
>>>> *ahci_platform_get_resources(struct platform_device *pdev)
>>>>                          goto err_out;
>>>>          }
>>>>
>>>> -       pm_runtime_set_active(dev);
>>
>>
>> The set_active before enable you are removing here should already avoid
>> resume being called on init and thus enable_resources being called
>> twice (which I assume is the problem, resume should never be called
>> twice itself).
>>
>>>> -       pm_runtime_enable(dev);
>>>> -       pm_runtime_forbid(dev);
>>>> -       hpriv->got_runtime_pm = true;
>>>> -
>>>>          devres_remove_group(dev, NULL);
>>>>          return hpriv;
>>>>
>>>> @@ -594,7 +589,16 @@ int ahci_platform_init_host(struct platform_device
>>>> *pdev,
>>>>          ahci_init_controller(host);
>>>>          ahci_print_info(host, "platform");
>>>>
>>>> -       return ahci_host_activate(host, sht);
>>>> +       rc = ahci_host_activate(host, sht);
>>>> +       if (rc)
>>>> +               return rc;
>>>> +
>>>> +       pm_runtime_enable(dev);
>>>> +       pm_runtime_forbid(dev);
>>>> +       hpriv->got_runtime_pm = true;
>>>> +       hpriv->initialized = true;
>>>> +
>>>> +       return 0;
>>>>   }
>>>>   EXPORT_SYMBOL_GPL(ahci_platform_init_host);
>>>>
>>
>> Hmm, moving thus from get_resources to platform_init_host while keeping
>> the counter parts in put_resources makes get_resources and
>> put_resources asymmetrical. As such I'm not a fan of this change.
> 
> I don't much like the ordering either, but if runtime_resume is
> called, then it needs the platform data, which is not set until
> ahci_platform_get_resources returns, naturally. This wouldn't be a
> problem if we didn't need to resume the parent devices for these OMAP
> devices, but again, I'm just guessing that's what caused the
> beagleboard issue, and making sure we do exactly the same operations
> on probe as before is my way of sidestepping that problem for now. A
> better solution if I'm right perhaps would be to move or copy whatever
> resume operations are necessary for those parent devices to their
> probe, rather than relying on runtime_pm to initialize the device.
> Then, to make sure the parent module loads before ahci_platform, I
> typically use modprobe.d, or just build both dependent drivers into
> the kernel. Or, at runtime, if you can keep track of that dependency,
> you could just defer until it's ready, like the regulator subsystem.
> 
> As is though, it might be best to move the runtime_put out of
> put_resources and into a new remove callback.

Is this something that can be fixed in OMAP PM/bus code? It seems like
OMAP is behaving oddly here and requires the driver to do some weird things.

If we ensure that the device is enabled by bus driver during probe then
it should make things easier for the device driver.

> 
>>
>> Regards,
>>
>> Hans
>>
>>
>>
>>
>>>> @@ -760,6 +764,9 @@ static int _ahci_platform_resume(struct device *dev)
>>>>          struct ahci_host_priv *hpriv = host->private_data;
>>>>          int rc;
>>>>
>>>> +       if (!hpriv->initialized)
>>>> +               return 0;
>>>> +
>>>>          rc = ahci_platform_enable_resources(hpriv);
>>>>          if (rc)
>>>>                  return rc;
>>>> --
>>>> 2.17.0
>>>>
>>
diff mbox

Patch

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 1609ebab4e23..8ec39f69fae4 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -349,6 +349,7 @@  struct ahci_host_priv {
 	u32			em_buf_sz;	/* EM buffer size in byte */
 	u32			em_msg_type;	/* EM message type */
 	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
+	bool			initialized;
 	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
 	struct regulator	**target_pwrs;	/* Optional */
 	/*
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index feee2e11fb33..baad85adf90c 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -476,11 +476,6 @@  struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
 			goto err_out;
 	}
 
-	pm_runtime_set_active(dev);
-	pm_runtime_enable(dev);
-	pm_runtime_forbid(dev);
-	hpriv->got_runtime_pm = true;
-
 	devres_remove_group(dev, NULL);
 	return hpriv;
 
@@ -594,7 +589,16 @@  int ahci_platform_init_host(struct platform_device *pdev,
 	ahci_init_controller(host);
 	ahci_print_info(host, "platform");
 
-	return ahci_host_activate(host, sht);
+	rc = ahci_host_activate(host, sht);
+	if (rc)
+		return rc;
+
+	pm_runtime_enable(dev);
+	pm_runtime_forbid(dev);
+	hpriv->got_runtime_pm = true;
+	hpriv->initialized = true;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(ahci_platform_init_host);
 
@@ -760,6 +764,9 @@  static int _ahci_platform_resume(struct device *dev)
 	struct ahci_host_priv *hpriv = host->private_data;
 	int rc;
 
+	if (!hpriv->initialized)
+		return 0;
+
 	rc = ahci_platform_enable_resources(hpriv);
 	if (rc)
 		return rc;