The kernel driver now will disable interrupt when port is suspended, causing plugin not work. It is useful to make plugin work,when the plugin interrupt is enabled with power management status. Adding pm_request_resume() is to reume port for plugin or PME signal waking up controller which in D3.
with the AHCI controller frequently enters into D3 and leaves from D3, the identify cmd may be timeout when controller resumes and establishes a connect with the device.it is effective to delay 10ms between controller resume and port resume,with link’s smooth transition.
with non power management request and power management competing with each other in queue, it is often found that block IO hang 120s when system disk is suspending or resuming.it is now guaranteed that PM requests will enter the queue no matter other non-PM requests are waiting. Increase the pm_only counter before checking whether any non-PM blk_queue_enter() calls are in progress. Meanwhile, the new blk_pm_request_resume() call is necessary to occur during request assigned to a queue when device is suspended.
Signed-off-by: LeoLiu-oc LeoLiu-oc@zhaoxin.com --- drivers/ata/ahci.c | 13 +++++++++++++ drivers/ata/libahci.c | 14 ++++++++++++++ 2 files changed, 27 insertions(+)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 33192a8f6..617cfcb2b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -868,6 +868,19 @@ static int ahci_pci_device_runtime_resume(struct device *dev) if (rc) return rc; ahci_pci_init_controller(host); + + /* controller delay for 10ms when being reusmed && + * port resume for Zx platform + */ + if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) { + ata_msleep(NULL, 10); + for (rc = 0; rc < host->n_ports; rc++) { + struct ata_port *ap = host->ports[rc]; + + pm_request_resume(&ap->tdev); + } + } + return 0; }
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index fec2e9754..a37eac335 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -826,6 +826,12 @@ static void ahci_power_down(struct ata_port *ap) void __iomem *port_mmio = ahci_port_base(ap); u32 cmd, scontrol;
+ /* port suspended enable Plugin intr for Zx platform */ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + + if ((pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) && (!ap->link.device->sdev)) + writel(PORT_IRQ_CONNECT, port_mmio + PORT_IRQ_MASK); + if (!(hpriv->cap & HOST_CAP_SSS)) return;
@@ -1703,6 +1709,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) struct ata_eh_info *active_ehi; bool fbs_need_dec = false; u32 serror; + struct pci_dev *pdev;
/* determine active link with error */ if (pp->fbs_enabled) { @@ -1791,6 +1798,13 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) ata_ehi_push_desc(host_ehi, "%s", irq_stat & PORT_IRQ_CONNECT ? "connection status changed" : "PHY RDY changed"); + /* when plugin intr happen,now resume suspended port for Zx platform */ + pdev = to_pci_dev(ap->host->dev); + if ((pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) && + (ap->pflags & ATA_PFLAG_SUSPENDED)) { + pm_request_resume(&ap->tdev); + return; + } }
/* okay, let's hand over to EH */