From: LeoLiu-oc LeoLiu-oc@zhaoxin.com
zhaoxin inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I40QDN CVE: NA
----------------------------------------------------------------
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 | 15 +++++++++++++++ 2 files changed, 28 insertions(+)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ff2add0101fe..8a7140ee88b5 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -869,6 +869,19 @@ static int ahci_pci_device_runtime_resume(struct device *dev) if (rc) return rc; ahci_pci_init_controller(host); + + /* Port resume for Zhaoxin platform */ + if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) { + if (pdev->revision == 0x01) + 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 fec2e9754aed..4514f3f28b7c 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -823,9 +823,15 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, static void ahci_power_down(struct ata_port *ap) { struct ahci_host_priv *hpriv = ap->host->private_data; + struct pci_dev *pdev; void __iomem *port_mmio = ahci_port_base(ap); u32 cmd, scontrol;
+ /* port suspended enable Plugin intr for Zhaoxin platform */ + pdev = (ap->dev && dev_is_pci(ap->dev)) ? to_pci_dev(ap->dev) : NULL; + if ((pdev && 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;
@@ -1701,6 +1707,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) struct ata_link *link = NULL; struct ata_queued_cmd *active_qc; struct ata_eh_info *active_ehi; + struct pci_dev *pdev; bool fbs_need_dec = false; u32 serror;
@@ -1791,6 +1798,14 @@ 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 Zhaoxin platform */ + pdev = (ap->dev && dev_is_pci(ap->dev)) ? to_pci_dev(ap->dev) : NULL; + if ((pdev && pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) && + (ap->pflags & ATA_PFLAG_SUSPENDED)) { + pm_request_resume(&ap->tdev); + return; + } }
/* okay, let's hand over to EH */