diff options
author | Tejun Heo <htejun@gmail.com> | 2008-03-24 23:22:47 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-17 15:44:16 -0400 |
commit | f08048e94564d009b19038cfbdd800aa83e79c7f (patch) | |
tree | 4afa7e4fff9ec716e9acbe746a464cda5daec063 /drivers/ata/pata_serverworks.c | |
parent | b558edddb1c42c70a30cfe494984d4be409f7b2b (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_serverworks.c')
-rw-r--r-- | drivers/ata/pata_serverworks.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index a589c0fa0dbb..6702df37cfed 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c | |||
@@ -498,6 +498,11 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id | |||
498 | } | 498 | } |
499 | }; | 499 | }; |
500 | const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; | 500 | const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; |
501 | int rc; | ||
502 | |||
503 | rc = pcim_enable_device(pdev); | ||
504 | if (rc) | ||
505 | return rc; | ||
501 | 506 | ||
502 | /* Force master latency timer to 64 PCI clocks */ | 507 | /* Force master latency timer to 64 PCI clocks */ |
503 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); | 508 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); |
@@ -535,11 +540,17 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id | |||
535 | #ifdef CONFIG_PM | 540 | #ifdef CONFIG_PM |
536 | static int serverworks_reinit_one(struct pci_dev *pdev) | 541 | static int serverworks_reinit_one(struct pci_dev *pdev) |
537 | { | 542 | { |
543 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
544 | int rc; | ||
545 | |||
546 | rc = ata_pci_device_do_resume(pdev); | ||
547 | if (rc) | ||
548 | return rc; | ||
549 | |||
538 | /* Force master latency timer to 64 PCI clocks */ | 550 | /* Force master latency timer to 64 PCI clocks */ |
539 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); | 551 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); |
540 | 552 | ||
541 | switch (pdev->device) | 553 | switch (pdev->device) { |
542 | { | ||
543 | case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: | 554 | case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: |
544 | serverworks_fixup_osb4(pdev); | 555 | serverworks_fixup_osb4(pdev); |
545 | break; | 556 | break; |
@@ -554,7 +565,9 @@ static int serverworks_reinit_one(struct pci_dev *pdev) | |||
554 | serverworks_fixup_ht1000(pdev); | 565 | serverworks_fixup_ht1000(pdev); |
555 | break; | 566 | break; |
556 | } | 567 | } |
557 | return ata_pci_device_resume(pdev); | 568 | |
569 | ata_host_resume(host); | ||
570 | return 0; | ||
558 | } | 571 | } |
559 | #endif | 572 | #endif |
560 | 573 | ||