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 | } |