diff options
author | Preetham Chandru R <pchandru@nvidia.com> | 2016-06-30 07:41:04 -0400 |
---|---|---|
committer | Preetham Chandru R <pchandru@nvidia.com> | 2017-08-21 05:16:34 -0400 |
commit | c31007a3b0e7ceb3f66ecf63596711ff387049f8 (patch) | |
tree | e042382bc41c3b9a778b881af2740c10050b58a8 /drivers/ata | |
parent | d84c1bd16c5d92f849741d90ab314ec8b8967134 (diff) |
ata: ahci_tegra: suspend host if drive not present
Bug 200213053
Change-Id: I54f3322a13f839922a1a3da49d2eb24aee8b0ed0
Signed-off-by: Preetham Chandru R <pchandru@nvidia.com>
Reviewed-on: http://git-master/r/1173821
(cherry picked from commit b8c0276c9899693134394a130202120781404e16)
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/tegra/ahci_tegra.c | 31 | ||||
-rw-r--r-- | drivers/ata/tegra/ahci_tegra.h | 1 |
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/ata/tegra/ahci_tegra.c b/drivers/ata/tegra/ahci_tegra.c index bbe777b2b..be7684126 100644 --- a/drivers/ata/tegra/ahci_tegra.c +++ b/drivers/ata/tegra/ahci_tegra.c | |||
@@ -38,6 +38,8 @@ static int tegra_ahci_suspend(struct device *dev); | |||
38 | static int tegra_ahci_resume(struct device *dev); | 38 | static int tegra_ahci_resume(struct device *dev); |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | static void tegra_ahci_shutdown(struct platform_device *pdev); | ||
42 | |||
41 | static char * const tegra_rail_names[] = {}; | 43 | static char * const tegra_rail_names[] = {}; |
42 | 44 | ||
43 | static const struct tegra_ahci_soc_data tegra_ahci_data = { | 45 | static const struct tegra_ahci_soc_data tegra_ahci_data = { |
@@ -265,6 +267,34 @@ static int tegra_ahci_softreset(struct ata_link *link, unsigned int *class, | |||
265 | 267 | ||
266 | } | 268 | } |
267 | 269 | ||
270 | static void tegra_ahci_unbind(struct work_struct *work) | ||
271 | { | ||
272 | struct tegra_ahci_priv *tegra = | ||
273 | container_of(work, struct tegra_ahci_priv, work); | ||
274 | struct platform_device *pdev = tegra->pdev; | ||
275 | |||
276 | tegra_ahci_shutdown(pdev); | ||
277 | pm_runtime_put_sync(&pdev->dev); | ||
278 | pm_runtime_disable(&pdev->dev); | ||
279 | pdev->dev.driver->pm = NULL; | ||
280 | pdev->dev.driver->shutdown = NULL; | ||
281 | } | ||
282 | |||
283 | static void tegra_ahci_error_handler(struct ata_port *ap) | ||
284 | { | ||
285 | ahci_ops.error_handler(ap); | ||
286 | if (!ata_dev_enabled(ap->link.device)) { | ||
287 | if (!(ap->pflags & ATA_PFLAG_SUSPENDED)) { | ||
288 | struct ata_host *host = ap->host; | ||
289 | struct ahci_host_priv *hpriv = host->private_data; | ||
290 | struct tegra_ahci_priv *tegra = hpriv->plat_data; | ||
291 | |||
292 | INIT_WORK(&tegra->work, tegra_ahci_unbind); | ||
293 | schedule_work(&tegra->work); | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | |||
268 | static struct ata_port_operations ahci_tegra_port_ops = { | 298 | static struct ata_port_operations ahci_tegra_port_ops = { |
269 | .inherits = &ahci_ops, | 299 | .inherits = &ahci_ops, |
270 | .qc_issue = tegra_ahci_qc_issue, | 300 | .qc_issue = tegra_ahci_qc_issue, |
@@ -273,6 +303,7 @@ static struct ata_port_operations ahci_tegra_port_ops = { | |||
273 | .port_resume = tegra_ahci_port_resume, | 303 | .port_resume = tegra_ahci_port_resume, |
274 | .hardreset = tegra_ahci_hardreset, | 304 | .hardreset = tegra_ahci_hardreset, |
275 | .softreset = tegra_ahci_softreset, | 305 | .softreset = tegra_ahci_softreset, |
306 | .error_handler = tegra_ahci_error_handler, | ||
276 | }; | 307 | }; |
277 | 308 | ||
278 | static struct ata_port_info ahci_tegra_port_info = { | 309 | static struct ata_port_info ahci_tegra_port_info = { |
diff --git a/drivers/ata/tegra/ahci_tegra.h b/drivers/ata/tegra/ahci_tegra.h index da2c79731..c1ed476bf 100644 --- a/drivers/ata/tegra/ahci_tegra.h +++ b/drivers/ata/tegra/ahci_tegra.h | |||
@@ -208,6 +208,7 @@ struct tegra_ahci_priv { | |||
208 | struct pinctrl_state *devslp_active; | 208 | struct pinctrl_state *devslp_active; |
209 | struct pinctrl_state *devslp_pullup; | 209 | struct pinctrl_state *devslp_pullup; |
210 | struct tegra_prod *prod_list; | 210 | struct tegra_prod *prod_list; |
211 | struct work_struct work; | ||
211 | int devslp_gpio; | 212 | int devslp_gpio; |
212 | bool devslp_override; | 213 | bool devslp_override; |
213 | bool devslp_pinmux_override; | 214 | bool devslp_pinmux_override; |