All of lore.kernel.org
 help / color / mirror / Atom feed
From: Deepa Dinamani <deepa.kernel@gmail.com>
To: bhelgaas@google.com
Cc: mika.westerberg@linux.intel.com, alex.williamson@redhat.com,
	logang@deltatee.com, linux-pci@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH] drivers: pci: Clear ACS state at kexec
Date: Sat,  4 Jan 2020 14:51:49 -0800	[thread overview]
Message-ID: <20200104225149.27342-1-deepa.kernel@gmail.com> (raw)

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


             reply	other threads:[~2020-01-04 22:51 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-04 22:51 Deepa Dinamani [this message]
2020-01-06 14:38 ` [PATCH] drivers: pci: Clear ACS state at kexec Bjorn Helgaas
2020-01-08 17:39   ` Deepa Dinamani
2020-01-06 16:51 ` Logan Gunthorpe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200104225149.27342-1-deepa.kernel@gmail.com \
    --to=deepa.kernel@gmail.com \
    --cc=alex.williamson@redhat.com \
    --cc=bhelgaas@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=logang@deltatee.com \
    --cc=mika.westerberg@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.