Commit abe9e1a8 authored by LeoLiu-oc's avatar LeoLiu-oc Committed by Zheng Zengkai
Browse files

ahci: Fix some bugs like plugin support and sata link stability when user enable ahci RTD3

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: default avatarLeoLiu-oc <LeoLiu-oc@zhaoxin.com>
Reviewed-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 7d2f5624
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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;
}

+15 −0
Original line number Diff line number Diff line
@@ -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 */