diff options
| author | Peter Griffin <peter.griffin@linaro.org> | 2015-04-20 09:41:05 -0400 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2015-04-20 13:36:38 -0400 |
| commit | e0e2674b92056c24c69940d5f405ea4aef5e4010 (patch) | |
| tree | ab0213bd4d1259819f640373d15ea430f11b5e31 /drivers/ata | |
| parent | 5df07b74f671d1dfc1d81c3e791c335183cfc515 (diff) | |
ata: ahci_st: fixup layering violations / drvdata errors
Brian noticed while working on another SATA driver that uses libahci_platform,
an error in this driver; it tries to the the driver data for its
device, while libata also thinks it can set the driver data. See:
ahci_platform_init_host()
-> ata_host_alloc_pinfo()
-> ata_host_alloc()
-> dev_set_drvdata()
So instead of sticking the IP-specific platform data into drvdata, let's
use the plat_data variable that is reserved for this use.
Addtionally plat_data isn't set until ahci_platform_init_host() has been
called further down in probe(). So re-work the st_ahci_probe_resets and
st_ahci_deassert_resets functions to take ahci_host_priv *hpriv as a
parameter.
Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
Suggested-by: Brian Norris <computersforpeace@gmail.com>
Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com>
Cc: Maxime Coquelin <maxime.coquelin@st.com>
Cc: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
| -rw-r--r-- | drivers/ata/ahci_st.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index ea0ff005b86c..8ff428fe8e0f 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c | |||
| @@ -37,7 +37,6 @@ struct st_ahci_drv_data { | |||
| 37 | struct reset_control *pwr; | 37 | struct reset_control *pwr; |
| 38 | struct reset_control *sw_rst; | 38 | struct reset_control *sw_rst; |
| 39 | struct reset_control *pwr_rst; | 39 | struct reset_control *pwr_rst; |
| 40 | struct ahci_host_priv *hpriv; | ||
| 41 | }; | 40 | }; |
| 42 | 41 | ||
| 43 | static void st_ahci_configure_oob(void __iomem *mmio) | 42 | static void st_ahci_configure_oob(void __iomem *mmio) |
| @@ -55,9 +54,10 @@ static void st_ahci_configure_oob(void __iomem *mmio) | |||
| 55 | writel(new_val, mmio + ST_AHCI_OOBR); | 54 | writel(new_val, mmio + ST_AHCI_OOBR); |
| 56 | } | 55 | } |
| 57 | 56 | ||
| 58 | static int st_ahci_deassert_resets(struct device *dev) | 57 | static int st_ahci_deassert_resets(struct ahci_host_priv *hpriv, |
| 58 | struct device *dev) | ||
| 59 | { | 59 | { |
| 60 | struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); | 60 | struct st_ahci_drv_data *drv_data = hpriv->plat_data; |
| 61 | int err; | 61 | int err; |
| 62 | 62 | ||
| 63 | if (drv_data->pwr) { | 63 | if (drv_data->pwr) { |
| @@ -90,8 +90,8 @@ static int st_ahci_deassert_resets(struct device *dev) | |||
| 90 | static void st_ahci_host_stop(struct ata_host *host) | 90 | static void st_ahci_host_stop(struct ata_host *host) |
| 91 | { | 91 | { |
| 92 | struct ahci_host_priv *hpriv = host->private_data; | 92 | struct ahci_host_priv *hpriv = host->private_data; |
| 93 | struct st_ahci_drv_data *drv_data = hpriv->plat_data; | ||
| 93 | struct device *dev = host->dev; | 94 | struct device *dev = host->dev; |
| 94 | struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); | ||
| 95 | int err; | 95 | int err; |
| 96 | 96 | ||
| 97 | if (drv_data->pwr) { | 97 | if (drv_data->pwr) { |
| @@ -103,29 +103,30 @@ static void st_ahci_host_stop(struct ata_host *host) | |||
| 103 | ahci_platform_disable_resources(hpriv); | 103 | ahci_platform_disable_resources(hpriv); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static int st_ahci_probe_resets(struct platform_device *pdev) | 106 | static int st_ahci_probe_resets(struct ahci_host_priv *hpriv, |
| 107 | struct device *dev) | ||
| 107 | { | 108 | { |
| 108 | struct st_ahci_drv_data *drv_data = platform_get_drvdata(pdev); | 109 | struct st_ahci_drv_data *drv_data = hpriv->plat_data; |
| 109 | 110 | ||
| 110 | drv_data->pwr = devm_reset_control_get(&pdev->dev, "pwr-dwn"); | 111 | drv_data->pwr = devm_reset_control_get(dev, "pwr-dwn"); |
| 111 | if (IS_ERR(drv_data->pwr)) { | 112 | if (IS_ERR(drv_data->pwr)) { |
| 112 | dev_info(&pdev->dev, "power reset control not defined\n"); | 113 | dev_info(dev, "power reset control not defined\n"); |
| 113 | drv_data->pwr = NULL; | 114 | drv_data->pwr = NULL; |
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | drv_data->sw_rst = devm_reset_control_get(&pdev->dev, "sw-rst"); | 117 | drv_data->sw_rst = devm_reset_control_get(dev, "sw-rst"); |
| 117 | if (IS_ERR(drv_data->sw_rst)) { | 118 | if (IS_ERR(drv_data->sw_rst)) { |
| 118 | dev_info(&pdev->dev, "soft reset control not defined\n"); | 119 | dev_info(dev, "soft reset control not defined\n"); |
| 119 | drv_data->sw_rst = NULL; | 120 | drv_data->sw_rst = NULL; |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | drv_data->pwr_rst = devm_reset_control_get(&pdev->dev, "pwr-rst"); | 123 | drv_data->pwr_rst = devm_reset_control_get(dev, "pwr-rst"); |
| 123 | if (IS_ERR(drv_data->pwr_rst)) { | 124 | if (IS_ERR(drv_data->pwr_rst)) { |
| 124 | dev_dbg(&pdev->dev, "power soft reset control not defined\n"); | 125 | dev_dbg(dev, "power soft reset control not defined\n"); |
| 125 | drv_data->pwr_rst = NULL; | 126 | drv_data->pwr_rst = NULL; |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 128 | return st_ahci_deassert_resets(&pdev->dev); | 129 | return st_ahci_deassert_resets(hpriv, dev); |
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | static struct ata_port_operations st_ahci_port_ops = { | 132 | static struct ata_port_operations st_ahci_port_ops = { |
| @@ -154,15 +155,12 @@ static int st_ahci_probe(struct platform_device *pdev) | |||
| 154 | if (!drv_data) | 155 | if (!drv_data) |
| 155 | return -ENOMEM; | 156 | return -ENOMEM; |
| 156 | 157 | ||
| 157 | platform_set_drvdata(pdev, drv_data); | ||
| 158 | |||
| 159 | hpriv = ahci_platform_get_resources(pdev); | 158 | hpriv = ahci_platform_get_resources(pdev); |
| 160 | if (IS_ERR(hpriv)) | 159 | if (IS_ERR(hpriv)) |
| 161 | return PTR_ERR(hpriv); | 160 | return PTR_ERR(hpriv); |
| 161 | hpriv->plat_data = drv_data; | ||
| 162 | 162 | ||
| 163 | drv_data->hpriv = hpriv; | 163 | err = st_ahci_probe_resets(hpriv, &pdev->dev); |
| 164 | |||
| 165 | err = st_ahci_probe_resets(pdev); | ||
| 166 | if (err) | 164 | if (err) |
| 167 | return err; | 165 | return err; |
| 168 | 166 | ||
| @@ -170,7 +168,7 @@ static int st_ahci_probe(struct platform_device *pdev) | |||
| 170 | if (err) | 168 | if (err) |
| 171 | return err; | 169 | return err; |
| 172 | 170 | ||
| 173 | st_ahci_configure_oob(drv_data->hpriv->mmio); | 171 | st_ahci_configure_oob(hpriv->mmio); |
| 174 | 172 | ||
| 175 | err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, | 173 | err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, |
| 176 | &ahci_platform_sht); | 174 | &ahci_platform_sht); |
| @@ -185,8 +183,9 @@ static int st_ahci_probe(struct platform_device *pdev) | |||
| 185 | #ifdef CONFIG_PM_SLEEP | 183 | #ifdef CONFIG_PM_SLEEP |
| 186 | static int st_ahci_suspend(struct device *dev) | 184 | static int st_ahci_suspend(struct device *dev) |
| 187 | { | 185 | { |
| 188 | struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); | 186 | struct ata_host *host = dev_get_drvdata(dev); |
| 189 | struct ahci_host_priv *hpriv = drv_data->hpriv; | 187 | struct ahci_host_priv *hpriv = host->private_data; |
| 188 | struct st_ahci_drv_data *drv_data = hpriv->plat_data; | ||
| 190 | int err; | 189 | int err; |
| 191 | 190 | ||
| 192 | err = ahci_platform_suspend_host(dev); | 191 | err = ahci_platform_suspend_host(dev); |
| @@ -208,21 +207,21 @@ static int st_ahci_suspend(struct device *dev) | |||
| 208 | 207 | ||
| 209 | static int st_ahci_resume(struct device *dev) | 208 | static int st_ahci_resume(struct device *dev) |
| 210 | { | 209 | { |
| 211 | struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); | 210 | struct ata_host *host = dev_get_drvdata(dev); |
| 212 | struct ahci_host_priv *hpriv = drv_data->hpriv; | 211 | struct ahci_host_priv *hpriv = host->private_data; |
| 213 | int err; | 212 | int err; |
| 214 | 213 | ||
| 215 | err = ahci_platform_enable_resources(hpriv); | 214 | err = ahci_platform_enable_resources(hpriv); |
| 216 | if (err) | 215 | if (err) |
| 217 | return err; | 216 | return err; |
| 218 | 217 | ||
| 219 | err = st_ahci_deassert_resets(dev); | 218 | err = st_ahci_deassert_resets(hpriv, dev); |
| 220 | if (err) { | 219 | if (err) { |
| 221 | ahci_platform_disable_resources(hpriv); | 220 | ahci_platform_disable_resources(hpriv); |
| 222 | return err; | 221 | return err; |
| 223 | } | 222 | } |
| 224 | 223 | ||
| 225 | st_ahci_configure_oob(drv_data->hpriv->mmio); | 224 | st_ahci_configure_oob(hpriv->mmio); |
| 226 | 225 | ||
| 227 | return ahci_platform_resume_host(dev); | 226 | return ahci_platform_resume_host(dev); |
| 228 | } | 227 | } |
