未验证 提交 da1a828a 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!185 [openEuler-1.0-LTS] Add support sata lpm for Zhaoxin CPUs

Merge Pull Request from: @leoliu-oc 
 
The ahci spec mentions that PhyRdy Change Interrupt and Link Power Management (LPM) do not coexist.
However, before enabling LPM, the driver did not check whether the host supports LPM, but directly disabled PhyRdy Change Interrupt.
Increase the judgment on the actual support of LPM, and disable PhyRdy Change Interrupt only when it is supported.

AHCI Spec shows that the PxSCTL.IPM field in each port must be programmed to disallow device initiated LPM requests when HBA can not support transitions to the LPM state. The current LPM driver has no restrictions on LPM transitions when enabling device initiated LPM.

### Issue
#I54V27:[openEuler-1.0-LTS] Adding support for PxSCT.LPM setting based on actual LPM circumstances
[openEuler-1.0-LTS] Add support for PxSCT.LPM set based on actual LPM circumstances
https://e.gitee.com/open_euler/dashboard?issue=I54V2K

### Test
Plugout will have a log prompt. After a period of time, the drive letter will disappear. Then, plug in again. The disk can be identified normally. Repeat plugout / in several times, and the disk can be displayed normally.

### Known Issue
N/A

Default config change
N/A 
 
Link:https://gitee.com/openeuler/kernel/pulls/185 
Reviewed-by: Laibin Qiu <qiulaibin@huawei.com> 
Signed-off-by: Xie XiuQi <xiexiuqi@huawei.com> 
......@@ -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);
......
......@@ -3975,6 +3975,9 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
bool spm_wakeup)
{
struct ata_eh_context *ehc = &link->eh_context;
struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
struct device *dev = ap ? ap->host->dev : NULL;
struct pci_dev *pdev = (!dev || !dev_is_pci(dev)) ? NULL : to_pci_dev(dev);
bool woken_up = false;
u32 scontrol;
int rc;
......@@ -4001,10 +4004,20 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
case ATA_LPM_MED_POWER_WITH_DIPM:
case ATA_LPM_MIN_POWER_WITH_PARTIAL:
case ATA_LPM_MIN_POWER:
if (ata_link_nr_enabled(link) > 0)
if (ata_link_nr_enabled(link) > 0) {
/* no restrictions on LPM transitions */
scontrol &= ~(0x7 << 8);
else {
/*
* If Host does not support partial, then disallows it,
* the same for slumber.
*/
if (pdev && pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) {
if (!(link->ap->host->flags & ATA_HOST_PART))
scontrol |= (0x1 << 8);
if (!(link->ap->host->flags & ATA_HOST_SSC))
scontrol |= (0x2 << 8);
}
} else {
/* empty port, power off */
scontrol &= ~0xf;
scontrol |= (0x1 << 2);
......
......@@ -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;
......
......@@ -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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册