Merge branch 'remotes/lorenzo/pci/tegra194'

- Fix handling BME_CHGED event (Om Prakash Singh)

- Fix MSI-X programming (Om Prakash Singh)

- Disable interrupts before entering L2 (Om Prakash Singh)

- Don't allow suspend when Tegra PCIe is in EP mode (Om Prakash Singh)

* remotes/lorenzo/pci/tegra194:
  PCI: tegra194: Cleanup unused code
  PCI: tegra194: Don't allow suspend when Tegra PCIe is in EP mode
  PCI: tegra194: Disable interrupts before entering L2
  PCI: tegra194: Fix MSI-X programming
  PCI: tegra194: Fix handling BME_CHGED event
This commit is contained in:
Bjorn Helgaas 2021-09-02 14:56:50 -05:00
commit 4a4547db56

View file

@ -497,19 +497,19 @@ static irqreturn_t tegra_pcie_ep_hard_irq(int irq, void *arg)
struct tegra_pcie_dw *pcie = arg;
struct dw_pcie_ep *ep = &pcie->pci.ep;
int spurious = 1;
u32 val, tmp;
u32 status_l0, status_l1, link_status;
val = appl_readl(pcie, APPL_INTR_STATUS_L0);
if (val & APPL_INTR_STATUS_L0_LINK_STATE_INT) {
val = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0);
appl_writel(pcie, val, APPL_INTR_STATUS_L1_0_0);
status_l0 = appl_readl(pcie, APPL_INTR_STATUS_L0);
if (status_l0 & APPL_INTR_STATUS_L0_LINK_STATE_INT) {
status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0);
appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_0_0);
if (val & APPL_INTR_STATUS_L1_0_0_HOT_RESET_DONE)
if (status_l1 & APPL_INTR_STATUS_L1_0_0_HOT_RESET_DONE)
pex_ep_event_hot_rst_done(pcie);
if (val & APPL_INTR_STATUS_L1_0_0_RDLH_LINK_UP_CHGED) {
tmp = appl_readl(pcie, APPL_LINK_STATUS);
if (tmp & APPL_LINK_STATUS_RDLH_LINK_UP) {
if (status_l1 & APPL_INTR_STATUS_L1_0_0_RDLH_LINK_UP_CHGED) {
link_status = appl_readl(pcie, APPL_LINK_STATUS);
if (link_status & APPL_LINK_STATUS_RDLH_LINK_UP) {
dev_dbg(pcie->dev, "Link is up with Host\n");
dw_pcie_ep_linkup(ep);
}
@ -518,11 +518,11 @@ static irqreturn_t tegra_pcie_ep_hard_irq(int irq, void *arg)
spurious = 0;
}
if (val & APPL_INTR_STATUS_L0_PCI_CMD_EN_INT) {
val = appl_readl(pcie, APPL_INTR_STATUS_L1_15);
appl_writel(pcie, val, APPL_INTR_STATUS_L1_15);
if (status_l0 & APPL_INTR_STATUS_L0_PCI_CMD_EN_INT) {
status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_15);
appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_15);
if (val & APPL_INTR_STATUS_L1_15_CFG_BME_CHGED)
if (status_l1 & APPL_INTR_STATUS_L1_15_CFG_BME_CHGED)
return IRQ_WAKE_THREAD;
spurious = 0;
@ -530,8 +530,8 @@ static irqreturn_t tegra_pcie_ep_hard_irq(int irq, void *arg)
if (spurious) {
dev_warn(pcie->dev, "Random interrupt (STATUS = 0x%08X)\n",
val);
appl_writel(pcie, val, APPL_INTR_STATUS_L0);
status_l0);
appl_writel(pcie, status_l0, APPL_INTR_STATUS_L0);
}
return IRQ_HANDLED;
@ -1493,6 +1493,16 @@ static void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie)
return;
}
/*
* PCIe controller exits from L2 only if reset is applied, so
* controller doesn't handle interrupts. But in cases where
* L2 entry fails, PERST# is asserted which can trigger surprise
* link down AER. However this function call happens in
* suspend_noirq(), so AER interrupt will not be processed.
* Disable all interrupts to avoid such a scenario.
*/
appl_writel(pcie, 0x0, APPL_INTR_EN_L0_0);
if (tegra_pcie_try_link_l2(pcie)) {
dev_info(pcie->dev, "Link didn't transition to L2 state\n");
/*
@ -1763,7 +1773,7 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
val = (ep->msi_mem_phys & MSIX_ADDR_MATCH_LOW_OFF_MASK);
val |= MSIX_ADDR_MATCH_LOW_OFF_EN;
dw_pcie_writel_dbi(pci, MSIX_ADDR_MATCH_LOW_OFF, val);
val = (lower_32_bits(ep->msi_mem_phys) & MSIX_ADDR_MATCH_HIGH_OFF_MASK);
val = (upper_32_bits(ep->msi_mem_phys) & MSIX_ADDR_MATCH_HIGH_OFF_MASK);
dw_pcie_writel_dbi(pci, MSIX_ADDR_MATCH_HIGH_OFF, val);
ret = dw_pcie_ep_init_complete(ep);
@ -1935,13 +1945,6 @@ static int tegra_pcie_config_ep(struct tegra_pcie_dw *pcie,
return ret;
}
name = devm_kasprintf(dev, GFP_KERNEL, "tegra_pcie_%u_ep_work",
pcie->cid);
if (!name) {
dev_err(dev, "Failed to create PCIe EP work thread string\n");
return -ENOMEM;
}
pm_runtime_enable(dev);
ret = dw_pcie_ep_init(ep);
@ -2236,6 +2239,11 @@ static int tegra_pcie_dw_resume_early(struct device *dev)
struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
u32 val;
if (pcie->mode == DW_PCIE_EP_TYPE) {
dev_err(dev, "Suspend is not supported in EP mode");
return -ENOTSUPP;
}
if (!pcie->link_state)
return 0;