lkml.org 
[lkml]   [2020]   [Jan]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] drivers: pci: Clear ACS state at kexec
Date
ACS bits remain sticky through kexec reset. This is not really a
problem for Linux because turning IOMMU on assumes ACS on. But,
this becomes a problem if we kexec into something other than
Linux and that does not turn ACS on always.

Reset the ACS bits to default before kexec or device remove.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
drivers/pci/pci-driver.c | 4 ++++
drivers/pci/pci.c | 39 +++++++++++++++++++++++++++------------
drivers/pci/pci.h | 1 +
3 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 0454ca0e4e3f..bd8d08e50b97 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -453,6 +453,8 @@ static int pci_device_remove(struct device *dev)

/* Undo the runtime PM settings in local_pci_probe() */
pm_runtime_put_sync(dev);
+ /* Undo the PCI ACS settings in pci_init_capabilities() */
+ pci_disable_acs(pci_dev);

/*
* If the device is still on, set the power state as "unknown",
@@ -493,6 +495,8 @@ static void pci_device_shutdown(struct device *dev)
*/
if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot))
pci_clear_master(pci_dev);
+ if (kexec_in_progress)
+ pci_disable_acs(pci_dev);
}

#ifdef CONFIG_PM
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index da2e59daad6f..8254617cff03 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3261,15 +3261,23 @@ static void pci_disable_acs_redir(struct pci_dev *dev)
pci_info(dev, "disabled ACS redirect\n");
}

+
+/* Standard PCI ACS capailities
+ * Source Validation | P2P Request Redirect | P2P Completion Redirect | Upstream Forwarding
+ */
+#define PCI_STD_ACS_CAP (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
+
/**
- * pci_std_enable_acs - enable ACS on devices using standard ACS capabilities
+ * pci_std_enable_disable_acs - enable/disable ACS on devices using standard
+ * ACS capabilities
* @dev: the PCI device
*/
-static void pci_std_enable_acs(struct pci_dev *dev)
+static void pci_std_enable_disable_acs(struct pci_dev *dev, int enable)
{
int pos;
u16 cap;
u16 ctrl;
+ u16 val = 0;

pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
if (!pos)
@@ -3278,19 +3286,26 @@ static void pci_std_enable_acs(struct pci_dev *dev)
pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);

- /* Source Validation */
- ctrl |= (cap & PCI_ACS_SV);
+ val = (cap & PCI_STD_ACS_CAP);

- /* P2P Request Redirect */
- ctrl |= (cap & PCI_ACS_RR);
+ if (enable)
+ ctrl |= val;
+ else
+ ctrl &= ~val;

- /* P2P Completion Redirect */
- ctrl |= (cap & PCI_ACS_CR);
+ pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+}

- /* Upstream Forwarding */
- ctrl |= (cap & PCI_ACS_UF);
+/**
+ * pci_disable_acs - enable ACS if hardware support it
+ * @dev: the PCI device
+ */
+void pci_disable_acs(struct pci_dev *dev)
+{
+ if (pci_acs_enable)
+ pci_std_enable_disable_acs(dev, 0);

- pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+ pci_disable_acs_redir(dev);
}

/**
@@ -3305,7 +3320,7 @@ void pci_enable_acs(struct pci_dev *dev)
if (!pci_dev_specific_enable_acs(dev))
goto disable_acs_redir;

- pci_std_enable_acs(dev);
+ pci_std_enable_disable_acs(dev, 1);

disable_acs_redir:
/*
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6394e7746fb5..480e4de46fa8 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -526,6 +526,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
}

void pci_enable_acs(struct pci_dev *dev);
+void pci_disable_acs(struct pci_dev *dev);
#ifdef CONFIG_PCI_QUIRKS
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
int pci_dev_specific_enable_acs(struct pci_dev *dev);
--
2.17.1
\
 
 \ /
  Last update: 2020-01-04 23:52    [W:0.104 / U:0.188 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site