public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pci_get_device call from interrupt in reboot fixups
@ 2007-08-03 10:39 Denis V. Lunev
  2007-08-04  4:08 ` Greg KH
  2007-08-06 20:03 ` Andrew Morton
  0 siblings, 2 replies; 11+ messages in thread
From: Denis V. Lunev @ 2007-08-03 10:39 UTC (permalink / raw)
  To: dev, gregkh, akpm; +Cc: devel, linux-kernel

The following calltrace is possible now:
 handle_sysrq
   machine_emergency_restart
     mach_reboot_fixups
       pci_get_device
         pci_get_subsys
	   down_read
The patch obtains PCI device during initialization to avoid bothering PCI
search engine in interrupt. Devices used in this code are not supposed to
be pluggable, so it looks safe to keep them.

Signed-off-by: Denis V. Lunev <den@openvz.org>
---

diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 03e1cce..873ad55 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -37,6 +37,7 @@ struct device_fixup {
 	unsigned int vendor;
 	unsigned int device;
 	void (*reboot_fixup)(struct pci_dev *);
+	struct pci_dev *dev;
 };
 
 static struct device_fixup fixups_table[] = {
@@ -49,20 +50,35 @@ static struct device_fixup fixups_table[] = {
  * is a fixup, we call it and we expect to never return from it. if we
  * do return, we keep looking and then eventually fall back to the
  * standard mach_reboot on return.
+ *
+ * Unfortunately, this code can be called from an interrupt and it is
+ * impossible to get PCI device directly. So, lets prepare the list
+ * beforehand.
  */
 void mach_reboot_fixups(void)
 {
 	struct device_fixup *cur;
-	struct pci_dev *dev;
 	int i;
 
 	for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
 		cur = &(fixups_table[i]);
-		dev = pci_get_device(cur->vendor, cur->device, NULL);
-		if (!dev)
+		if (cur->dev == NULL)
 			continue;
 
-		cur->reboot_fixup(dev);
+		cur->reboot_fixup(cur->dev);
+	}
+}
+
+int mach_fixup_init(void)
+{
+	struct device_fixup *cur;
+	int i;
+
+	for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
+		cur = &(fixups_table[i]);
+		cur->dev = pci_get_device(cur->vendor, cur->device, NULL);
 	}
+	return 0;
 }
 
+module_init(mach_fixup_init);

^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] pci_get_device call from interrupt in reboot fixups
@ 2007-08-07  9:04 Denis V. Lunev
  0 siblings, 0 replies; 11+ messages in thread
From: Denis V. Lunev @ 2007-08-07  9:04 UTC (permalink / raw)
  To: den, dev, akpm, gregkh; +Cc: devel, linux-kernel, xemul

The following calltrace is possible now:
 handle_sysrq
   machine_emergency_restart
     mach_reboot_fixups
       pci_get_device
         pci_get_subsys
	   down_read
The patch skips reboot fixup if called from sysrq-B code.
---

--- ./arch/i386/kernel/reboot_fixups.c.fixup2	2007-08-07 12:30:30.000000000 +0400
+++ ./arch/i386/kernel/reboot_fixups.c	2007-08-07 12:31:22.000000000 +0400
@@ -11,6 +11,7 @@
 #include <asm/delay.h>
 #include <linux/pci.h>
 #include <linux/reboot_fixups.h>
+#include <linux/interrupt.h>
 
 static void cs5530a_warm_reset(struct pci_dev *dev)
 {
@@ -43,6 +44,11 @@ void mach_reboot_fixups(void)
 	struct pci_dev *dev;
 	int i;
 
+	/* we can be called from sysrq-B code. In such a case it is
+	 * prohibited to dig PCI */
+	if (in_interrupt())
+		return;
+
 	for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
 		cur = &(fixups_table[i]);
 		dev = pci_get_device(cur->vendor, cur->device, NULL);

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2007-08-07  9:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-03 10:39 [PATCH] pci_get_device call from interrupt in reboot fixups Denis V. Lunev
2007-08-04  4:08 ` Greg KH
2007-08-06  7:16   ` Denis V. Lunev
2007-08-07  2:49     ` Greg KH
2007-08-07  7:24       ` Andrew Morton
2007-08-07  7:44         ` Andrew Morton
2007-08-07  7:42           ` Greg KH
2007-08-07  7:50             ` Denis V. Lunev
2007-08-07  7:48         ` Denis V. Lunev
2007-08-06 20:03 ` Andrew Morton
  -- strict thread matches above, loose matches on Subject: below --
2007-08-07  9:04 Denis V. Lunev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox