aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_cmd640.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-03-24 23:22:47 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:44:16 -0400
commitf08048e94564d009b19038cfbdd800aa83e79c7f (patch)
tree4afa7e4fff9ec716e9acbe746a464cda5daec063 /drivers/ata/pata_cmd640.c
parentb558edddb1c42c70a30cfe494984d4be409f7b2b (diff)
libata: PCI device should be powered up before being accessed
PCI device should be powered up or powered up before its PCI regsiters are accessed. Although PCI configuration register access is allowed in D3hot, PCI device is free to reset its status when transiting from D3hot to D0 causing configuration data to change. Many libata SFF drivers which use ata_pci_init_one() read and update configuration registers before calling ata_pci_init_one() which enables the PCI device. Also, in resume paths, some drivers access registers without resuming the PCI device. This patch adds a call to pcim_enable_device() in init path if register is accessed before calling ata_pci_init_one() and make resume paths first resume PCI devices, access PCI configuration regiters then resume ATA host. While at it... * cmd640 was strange in that it set ->resume even when CONFIG_PM is not. This is by-product of minimal build fix. Updated. * In cs5530, Don't BUG() on reinit failure. Just whine and fail resume. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata/pata_cmd640.c')
-rw-r--r--drivers/ata/pata_cmd640.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 43d198f90968..0ef1d1ded1f8 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -254,20 +254,31 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
254 .port_ops = &cmd640_port_ops 254 .port_ops = &cmd640_port_ops
255 }; 255 };
256 const struct ata_port_info *ppi[] = { &info, NULL }; 256 const struct ata_port_info *ppi[] = { &info, NULL };
257 int rc;
258
259 rc = pcim_enable_device(pdev);
260 if (rc)
261 return rc;
257 262
258 cmd640_hardware_init(pdev); 263 cmd640_hardware_init(pdev);
264
259 return ata_pci_init_one(pdev, ppi); 265 return ata_pci_init_one(pdev, ppi);
260} 266}
261 267
268#ifdef CONFIG_PM
262static int cmd640_reinit_one(struct pci_dev *pdev) 269static int cmd640_reinit_one(struct pci_dev *pdev)
263{ 270{
271 struct ata_host *host = dev_get_drvdata(&pdev->dev);
272 int rc;
273
274 rc = ata_pci_device_do_resume(pdev);
275 if (rc)
276 return rc;
264 cmd640_hardware_init(pdev); 277 cmd640_hardware_init(pdev);
265#ifdef CONFIG_PM 278 ata_host_resume(host);
266 return ata_pci_device_resume(pdev);
267#else
268 return 0; 279 return 0;
269#endif
270} 280}
281#endif
271 282
272static const struct pci_device_id cmd640[] = { 283static const struct pci_device_id cmd640[] = {
273 { PCI_VDEVICE(CMD, 0x640), 0 }, 284 { PCI_VDEVICE(CMD, 0x640), 0 },
@@ -281,8 +292,8 @@ static struct pci_driver cmd640_pci_driver = {
281 .remove = ata_pci_remove_one, 292 .remove = ata_pci_remove_one,
282#ifdef CONFIG_PM 293#ifdef CONFIG_PM
283 .suspend = ata_pci_device_suspend, 294 .suspend = ata_pci_device_suspend,
284#endif
285 .resume = cmd640_reinit_one, 295 .resume = cmd640_reinit_one,
296#endif
286}; 297};
287 298
288static int __init cmd640_init(void) 299static int __init cmd640_init(void)