linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chang Liu <cl91tp@gmail.com>
To: linux-pci@vger.kernel.org
Cc: Chang Liu <cl91tp@gmail.com>
Subject: [PATCH] PCI: Blacklist certain hardware from clearing Bus Master bit
Date: Wed, 30 Oct 2013 09:50:37 +0000	[thread overview]
Message-ID: <1383126637-4641-1-git-send-email-cl91tp@gmail.com> (raw)

This patch adds a blacklist that prevents pci device shutdown code
from clearing Bus Master bit on certain hardware that cannot tolerate it.

Clearing Bus Master bit was originally added in commit b566a22 to address
the issue of some PCI device breaking kexec by continuing to do DMA
after having been signaled to shutdown. However, this introduced a
regression (https://bugzilla.kernel.org/show_bug.cgi?id=63861) that
hangs the machine on kernel power off path.

It has been pointed out previously (https://lkml.org/lkml/2012/6/6/545)
that clearing Bus Master bit during PCI shutdown may have surprising
consequences as some devices may not tolerate this, and may hang the
system indefinitely. However, not doing so may break kexec. Since only
one bug report has come up since the introduction of b566a22, therefore
indicating that these misbehaving devices are in the minority, the
logical way to fix the hang while not breaking kexec is to blacklist
these devices from having their Bus Master bit cleared during the PCI
shutdown routine.
---
This fixes the above mentioned bug https://bugzilla.kernel.org/show_bug.cgi?id=63861

As Alan Cox has warned in https://lkml.org/lkml/2012/6/6/545, some device
will break if we clear bus master bit on shutdown. So sooner or later
we will need to blacklist some device if we are to keep Bus Master being cleared
as the default behavior. Now with the first (as I have been aware) device
that breaks under this default behavior has surfaced, we might as well
add the infrastructure code now in case some other devices break down
in the future. These devices may not be many so a blacklist likely won't 
add much maintainance overhead. And we should keep the blacklist here in
the pci shutdown code instead of in individual device drivers since this
is the most direct way and will likely aid future debug process.

 drivers/pci/pci-driver.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 98f7b9b..1744ebf 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -376,6 +376,29 @@ static int pci_device_remove(struct device * dev)
 	return 0;
 }
 
+/*
+ * Blacklisting certain hardware from having their Bus Master bit cleared
+ * during device shutdown. This is to workaround certain hardware's issue
+ * with clearing Bus Master bit that hangs the entire system.
+ */
+struct {
+	unsigned short vendor;
+	unsigned short device;
+} pci_bus_master_blacklist[] = {
+	{ 0x8086, 0x9c03 },	/* Intel Corporation Lynx Point-LP SATA Controller */
+};
+
+static bool pci_should_clear_master(struct pci_dev *pdev)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(pci_bus_master_blacklist); i++) {
+		if (pdev->vendor == pci_bus_master_blacklist[i].vendor
+		    && pdev->device == pci_bus_master_blacklist[i].device)
+			return false;
+	}
+	return true;
+}
+
 static void pci_device_shutdown(struct device *dev)
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -391,9 +414,18 @@ static void pci_device_shutdown(struct device *dev)
 	/*
 	 * Turn off Bus Master bit on the device to tell it to not
 	 * continue to do DMA. Don't touch devices in D3cold or unknown states.
+	 * This is useful for proper kexec. However, a number of hardware
+	 * aren't happy with this. At the slightest, some hardware simply
+	 * ignore the bus master bit. For some other hardware, clearing
+	 * the bit on shutdown path hangs the entire system.
+	 * This is likely to be a firmware or hardware problem, but
+	 * we can workaround it here by blacklisting these hardware
+	 * from having their bus master bit cleared during device shutdown.
 	 */
-	if (pci_dev->current_state <= PCI_D3hot)
+	if (pci_should_clear_master(pci_dev)
+	    && pci_dev->current_state <= PCI_D3hot) {
 		pci_clear_master(pci_dev);
+	}
 }
 
 #ifdef CONFIG_PM
-- 
1.8.4.1


             reply	other threads:[~2013-10-30  1:50 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-30  9:50 Chang Liu [this message]
2013-10-30  3:18 ` [PATCH] PCI: Blacklist certain hardware from clearing Bus Master bit Chang Liu
  -- strict thread matches above, loose matches on Subject: below --
2013-10-30 11:22 Chang Liu
2013-11-12  7:21 ` Takao Indoh
2013-11-12  7:59   ` Chang Liu
     [not found]   ` <CAMZVYU9Vwarz=Fn6AHjbYPw1q4EDda7shp9ZXMsuQd+Zo_BsiQ@mail.gmail.com>
2013-11-12  8:21     ` Takao Indoh
2013-11-12  8:45       ` Chang Liu
2013-11-12 11:46         ` Chang Liu

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=1383126637-4641-1-git-send-email-cl91tp@gmail.com \
    --to=cl91tp@gmail.com \
    --cc=linux-pci@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).