From d96a3b8ae8b9a1777ff56c4726fb2a3688217cb0 Mon Sep 17 00:00:00 2001 From: LeoLiu-oc Date: Tue, 26 Apr 2022 17:28:32 +0800 Subject: [PATCH openEuler-1.0-LTS] Adding support for PxSCT.LPM setting based on actual LPM circumstances zhaoxin inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I54V27 CVE: NA ---------------------------------------------------------------- In AHCI spec, PhyRdy Change Interrupt cannot coexist with Link Power Management (LPM). While LPM driver would disable PhyRdy Change interrupt without checking whether HBA supports LPM or not before enabling it. Therefore, if enabling LPM from LPM driver by default, we can not disable it from BIOS without influence Hotplug out capability. Signed-off-by: LeoLiu-oc --- drivers/ata/ahci.c | 11 +++++++++++ drivers/ata/libata-eh.c | 7 +++++++ include/linux/libata.h | 3 +++ 3 files changed, 21 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ebb2bfd4ab0a..8ed2f42b85fd 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1855,6 +1855,17 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) else dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); + if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) { + if (hpriv->cap & HOST_CAP_PART) + host->flags |= ATA_HOST_PART; + + if (hpriv->cap & HOST_CAP_SSC) + host->flags |= ATA_HOST_SSC; + + if (hpriv->cap2 & HOST_CAP2_SDS) + host->flags |= ATA_HOST_DEVSLP; + } + if (pi.flags & ATA_FLAG_EM) ahci_reset_em(host); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ccc80ff57eb2..e4e0e6d94741 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3448,6 +3448,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, struct ata_device **r_failed_dev) { struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL; + struct device *device = ap->host->dev; + struct pci_dev *pdev = (!device || !dev_is_pci(device)) ? NULL : to_pci_dev(device); struct ata_eh_context *ehc = &link->eh_context; struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; enum ata_lpm_policy old_policy = link->lpm_policy; @@ -3456,6 +3458,11 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, unsigned int err_mask; int rc; + /* if controller does not support lpm, then sets no LPM flags */ + if ((pdev && pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) && + !(ap->host->flags & (ATA_HOST_PART | ATA_HOST_SSC | ATA_HOST_DEVSLP))) + link->flags |= ATA_LFLAG_NO_LPM; + /* if the link or host doesn't do LPM, noop */ if ((link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm)) return 0; diff --git a/include/linux/libata.h b/include/linux/libata.h index dc164b7ebbb0..1cec68e5b104 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -276,6 +276,9 @@ enum { ATA_HOST_STARTED = (1 << 1), /* Host started */ ATA_HOST_PARALLEL_SCAN = (1 << 2), /* Ports on this host can be scanned in parallel */ ATA_HOST_IGNORE_ATA = (1 << 3), /* Ignore ATA devices on this host. */ + ATA_HOST_PART = (1 << 4), /* Host support partial. */ + ATA_HOST_SSC = (1 << 5), /* Host support slumber. */ + ATA_HOST_DEVSLP = (1 << 6), /* Host support devslp. */ /* bits 24:31 of host->flags are reserved for LLD specific flags */ -- 2.20.1