summaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorPreetham Chandru R <pchandru@nvidia.com>2016-06-30 07:41:04 -0400
committerPreetham Chandru R <pchandru@nvidia.com>2017-08-21 05:16:34 -0400
commitc31007a3b0e7ceb3f66ecf63596711ff387049f8 (patch)
treee042382bc41c3b9a778b881af2740c10050b58a8 /drivers/ata
parentd84c1bd16c5d92f849741d90ab314ec8b8967134 (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.c31
-rw-r--r--drivers/ata/tegra/ahci_tegra.h1
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);
38static int tegra_ahci_resume(struct device *dev); 38static int tegra_ahci_resume(struct device *dev);
39#endif 39#endif
40 40
41static void tegra_ahci_shutdown(struct platform_device *pdev);
42
41static char * const tegra_rail_names[] = {}; 43static char * const tegra_rail_names[] = {};
42 44
43static const struct tegra_ahci_soc_data tegra_ahci_data = { 45static 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
270static 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
283static 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
268static struct ata_port_operations ahci_tegra_port_ops = { 298static 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
278static struct ata_port_info ahci_tegra_port_info = { 309static 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;