소스 검색

[PATCH] PCI: Provide a boot parameter to disable MSI

Several drivers are starting to grow options to disable MSI.  However,
it's often a host chipset issue, not something which individual drivers
should handle.  So we add the pci=nomsi kernel parameter to allow the user
to disable MSI modes for systems we haven't added to the quirk list yet.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Acked-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Matthew Wilcox 19 년 전
부모
커밋
309e57df7b
5개의 변경된 파일26개의 추가작업 그리고 2개의 파일을 삭제
  1. 4 0
      Documentation/kernel-parameters.txt
  2. 4 0
      drivers/pci/Kconfig
  3. 10 0
      drivers/pci/msi.c
  4. 6 2
      drivers/pci/pci.c
  5. 2 0
      drivers/pci/pci.h

+ 4 - 0
Documentation/kernel-parameters.txt

@@ -49,6 +49,7 @@ restrictions referred to are that the relevant option is valid if:
 	MCA	MCA bus support is enabled.
 	MCA	MCA bus support is enabled.
 	MDA	MDA console support is enabled.
 	MDA	MDA console support is enabled.
 	MOUSE	Appropriate mouse support is enabled.
 	MOUSE	Appropriate mouse support is enabled.
+	MSI	Message Signaled Interrupts (PCI).
 	MTD	MTD support is enabled.
 	MTD	MTD support is enabled.
 	NET	Appropriate network support is enabled.
 	NET	Appropriate network support is enabled.
 	NUMA	NUMA support is enabled.
 	NUMA	NUMA support is enabled.
@@ -1152,6 +1153,9 @@ running once the system is up.
 				Mechanism 2.
 				Mechanism 2.
 		nommconf	[IA-32,X86_64] Disable use of MMCONFIG for PCI
 		nommconf	[IA-32,X86_64] Disable use of MMCONFIG for PCI
 				Configuration
 				Configuration
+		nomsi		[MSI] If the PCI_MSI kernel config parameter is
+				enabled, this kernel boot option can be used to
+				disable the use of MSI interrupts system-wide.
 		nosort		[IA-32] Don't sort PCI devices according to
 		nosort		[IA-32] Don't sort PCI devices according to
 				order given by the PCI BIOS. This sorting is
 				order given by the PCI BIOS. This sorting is
 				done to get a device order compatible with
 				done to get a device order compatible with

+ 4 - 0
drivers/pci/Kconfig

@@ -11,6 +11,10 @@ config PCI_MSI
 	   generate an interrupt using an inbound Memory Write on its
 	   generate an interrupt using an inbound Memory Write on its
 	   PCI bus instead of asserting a device IRQ pin.
 	   PCI bus instead of asserting a device IRQ pin.
 
 
+	   Use of PCI MSI interrupts can be disabled at kernel boot time
+	   by using the 'pci=nomsi' option.  This disables MSI for the
+	   entire system.
+
 	   If you don't know what to do here, say N.
 	   If you don't know what to do here, say N.
 
 
 config PCI_DEBUG
 config PCI_DEBUG

+ 10 - 0
drivers/pci/msi.c

@@ -765,8 +765,11 @@ void pci_disable_msi(struct pci_dev* dev)
 	u16 control;
 	u16 control;
 	unsigned long flags;
 	unsigned long flags;
 
 
+	if (!pci_msi_enable)
+		return;
 	if (!dev)
 	if (!dev)
 		return;
 		return;
+
 	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
 	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
 	if (!pos)
 	if (!pos)
 		return;
 		return;
@@ -1026,6 +1029,8 @@ void pci_disable_msix(struct pci_dev* dev)
 	int pos, temp;
 	int pos, temp;
 	u16 control;
 	u16 control;
 
 
+	if (!pci_msi_enable)
+		return;
 	if (!dev)
 	if (!dev)
 		return;
 		return;
 
 
@@ -1152,6 +1157,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
 	}
 	}
 }
 }
 
 
+void pci_no_msi(void)
+{
+	pci_msi_enable = 0;
+}
+
 EXPORT_SYMBOL(pci_enable_msi);
 EXPORT_SYMBOL(pci_enable_msi);
 EXPORT_SYMBOL(pci_disable_msi);
 EXPORT_SYMBOL(pci_disable_msi);
 EXPORT_SYMBOL(pci_enable_msix);
 EXPORT_SYMBOL(pci_enable_msix);

+ 6 - 2
drivers/pci/pci.c

@@ -900,8 +900,12 @@ static int __devinit pci_setup(char *str)
 		if (k)
 		if (k)
 			*k++ = 0;
 			*k++ = 0;
 		if (*str && (str = pcibios_setup(str)) && *str) {
 		if (*str && (str = pcibios_setup(str)) && *str) {
-			/* PCI layer options should be handled here */
-			printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
+			if (!strcmp(str, "nomsi")) {
+				pci_no_msi();
+			} else {
+				printk(KERN_ERR "PCI: Unknown option `%s'\n",
+						str);
+			}
 		}
 		}
 		str = k;
 		str = k;
 	}
 	}

+ 2 - 0
drivers/pci/pci.h

@@ -50,8 +50,10 @@ extern int pci_msi_quirk;
 
 
 #ifdef CONFIG_PCI_MSI
 #ifdef CONFIG_PCI_MSI
 void disable_msi_mode(struct pci_dev *dev, int pos, int type);
 void disable_msi_mode(struct pci_dev *dev, int pos, int type);
+void pci_no_msi(void);
 #else
 #else
 static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
 static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
+static inline void pci_no_msi(void) { }
 #endif
 #endif
 
 
 extern int pcie_mch_quirk;
 extern int pcie_mch_quirk;