Hi Jackie,
在 2022/2/22 17:49, Jackie Liu 写道:
在 2022/2/22 下午4:16, Zheng Zengkai 写道:
From: LeoLiu-oc LeoLiu-oc@zhaoxin.com
zhaoxin inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I40QDN CVE: NA
If we plug in a LS/FS device on USB2 port of EHCI, it will latch a wakeup signal in EHCI internal. This is a bug of EHCI for Some project of ZhaoXin. If enable EHCI runtime suspend and no device attach. PM core will let EHCI go to D3 to save power. However, once EHCI go to D3, it will release wakeup signal that latched on device connect to port during S0. Which will generate a SCI interrupt and bring EHCI to D0. But without device connect, EHCI will go to D3 again. So, there is suspend-resume loop and generate SCI interrupt Continuously.
In order to fix this issues, we need to clear the wakeup signal latched in EHCI when EHCI suspend function is called.
Signed-off-by: LeoLiu-oc LeoLiu-oc@zhaoxin.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com
drivers/pci/pci-driver.c | 6 +++++- drivers/usb/host/ehci-hcd.c | 21 +++++++++++++++++++++ drivers/usb/host/ehci-pci.c | 4 ++++ drivers/usb/host/ehci.h | 1 + 4 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 8b587fc97f7b..c33d7e0a60b5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -518,7 +518,11 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) }
pci_restore_state(pci_dev);
- pci_pme_restore(pci_dev);
- if (!((pci_dev->vendor == PCI_VENDOR_ID_ZHAOXIN) &&
(pci_dev->device == 0x3104) &&
((pci_dev->revision & 0xf0) == 0x90)) ||
!(pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI))
上面这句话是不是改变了通用逻辑?增加了一个 pci_dev->class != PCI_CLASS_SERIAL_USB_EHCI 才进行 restore?
pci_pme_restore(pci_dev);
逻辑上应该是和
!((pci_dev->vendor == PCI_VENDOR_ID_ZHAOXIN) && (pci_dev->device == 0x3104) && ((pci_dev->revision & 0xf0) == 0x90) && (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI))
等同的, 即只有zhaoxin的0x3104 devid的PCI_CLASS_SERIAL_USB_EHCI设备 不做pci_pme_restore(pci_dev)操作
return 0;
}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 8aff19ff8e8f..586e2735d6e0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1142,6 +1142,27 @@ int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) return -EBUSY; }
- /*clear wakeup signal locked in S0 state when device plug in*/
- if (ehci->zx_wakeup_clear == 1) {
u32 __iomem *reg = &ehci->regs->port_status[4];
u32 t1 = ehci_readl(ehci, reg);
t1 &= (u32)~0xf0000;
t1 |= PORT_TEST_FORCE;
ehci_writel(ehci, t1, reg);
t1 = ehci_readl(ehci, reg);
usleep_range(1000, 2000);
t1 &= (u32)~0xf0000;
ehci_writel(ehci, t1, reg);
usleep_range(1000, 2000);
t1 = ehci_readl(ehci, reg);
ehci_writel(ehci, t1 | PORT_CSC, reg);
udelay(500);
t1 = ehci_readl(ehci, &ehci->regs->status);
ehci_writel(ehci, t1 & STS_PCD, &ehci->regs->status);
ehci_readl(ehci, &ehci->regs->status);
- }
- return 0; } EXPORT_SYMBOL_GPL(ehci_suspend);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index e87cf3a00fa4..a5e27deda83a 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -222,6 +222,10 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci->has_synopsys_hc_bug = 1; } break;
case PCI_VENDOR_ID_ZHAOXIN:
if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x90)
ehci->zx_wakeup_clear = 1;
break;
}
/* optional debug port, normally in the first BAR */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 59fd523c55f3..8da080a54668 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controller */ unsigned need_oc_pp_cycle:1; /* MPC834X port power */ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ unsigned is_aspeed:1;
unsigned zx_wakeup_clear:1;
/* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6)
Content-type: Text/plain
No virus found Checked by Hillstone Network AntiVirus