Unverified Commit 26d68684 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4091 x86/quirks: Add parameter to clear MSIs early

Merge Pull Request from: @ci-robot 
 
PR sync from: Zheng Zengkai <zhengzengkai@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/HCLNL3C6YWUEAGH5U4RWTDDNVMP7D3XD/ 
A crash kernel boot failure issue is reported in openeuler 5.10 series kernel(in
x86 virtual machine with Hi1822 virtual nic). Finally the issue was narrowed
down to irq vector conflict.

Backport following patchset from kernel maillist to fix this issue.
https://lore.kernel.org/linux-pci/20181018183721.27467-3-gpiccoli@canonical.com/
Due to the virtual NICs in this issue is present under bus0, In order to avoid introducing
some more influence to the x86 early quirks handling, just backport the last 2 patches from
the original patchset.

Guilherme G. Piccoli (2):
  x86/PCI: Export find_cap() to be used in early PCI code
  x86/quirks: Add parameter to clear MSIs early on boot


-- 
2.20.1
 
https://gitee.com/openeuler/kernel/issues/I8X2RA 
 
Link:https://gitee.com/openeuler/kernel/pulls/4091

 

Reviewed-by: default avatarJason Zeng <jason.zeng@intel.com>
Reviewed-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Reviewed-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 26f718c6 b8017dd6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3905,6 +3905,12 @@
		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.
		clearmsi	[X86] Clears MSI/MSI-X enable bits early in boot
				time in order to avoid issues like adapters
				screaming irqs and preventing boot progress.
				Also, it enforces the PCI Local Bus spec
				rule that those bits should be 0 in system reset
				events (useful for kexec/kdump cases).
		noioapicquirk	[APIC] Disable all boot interrupt quirks.
				Safety option to keep boot IRQs enabled. This
				should never be necessary.
+2 −0
Original line number Diff line number Diff line
@@ -10,9 +10,11 @@
extern u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset);
extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset);
extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset);
extern u32 pci_early_find_cap(int bus, int slot, int func, int cap);
extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val);
extern void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val);
extern void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val);

extern unsigned int pci_early_clear_msi;
extern int early_pci_allowed(void);
#endif /* _ASM_X86_PCI_DIRECT_H */
+2 −28
Original line number Diff line number Diff line
@@ -126,32 +126,6 @@ static u32 __init allocate_aperture(void)
}


/* Find a PCI capability */
static u32 __init find_cap(int bus, int slot, int func, int cap)
{
	int bytes;
	u8 pos;

	if (!(read_pci_config_16(bus, slot, func, PCI_STATUS) &
						PCI_STATUS_CAP_LIST))
		return 0;

	pos = read_pci_config_byte(bus, slot, func, PCI_CAPABILITY_LIST);
	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
		u8 id;

		pos &= ~3;
		id = read_pci_config_byte(bus, slot, func, pos+PCI_CAP_LIST_ID);
		if (id == 0xff)
			break;
		if (id == cap)
			return pos;
		pos = read_pci_config_byte(bus, slot, func,
						pos+PCI_CAP_LIST_NEXT);
	}
	return 0;
}

/* Read a standard AGPv3 bridge header */
static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order)
{
@@ -240,8 +214,8 @@ static u32 __init search_agp_bridge(u32 *order, int *valid_agp)
				case PCI_CLASS_BRIDGE_HOST:
				case PCI_CLASS_BRIDGE_OTHER: /* needed? */
					/* AGP bridge? */
					cap = find_cap(bus, slot, func,
							PCI_CAP_ID_AGP);
					cap = pci_early_find_cap(bus, slot,
						 func, PCI_CAP_ID_AGP);
					if (!cap)
						break;
					*valid_agp = 1;
+32 −0
Original line number Diff line number Diff line
@@ -28,6 +28,37 @@
#include <asm/irq_remapping.h>
#include <asm/early_ioremap.h>

static void __init early_pci_clear_msi(int bus, int slot, int func)
{
	int pos;
	u16 ctrl;

	if (likely(!pci_early_clear_msi))
		return;

	pr_info_once("Clearing MSI/MSI-X enable bits early in boot (quirk)\n");

	pos = pci_early_find_cap(bus, slot, func, PCI_CAP_ID_MSI);
	if (pos) {
		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSI_FLAGS);
		ctrl &= ~PCI_MSI_FLAGS_ENABLE;
		write_pci_config_16(bus, slot, func, pos + PCI_MSI_FLAGS, ctrl);

		/* Read again to flush previous write */
		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSI_FLAGS);
	}

	pos = pci_early_find_cap(bus, slot, func, PCI_CAP_ID_MSIX);
	if (pos) {
		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSIX_FLAGS);
		ctrl &= ~PCI_MSIX_FLAGS_ENABLE;
		write_pci_config_16(bus, slot, func, pos + PCI_MSIX_FLAGS, ctrl);

		/* Read again to flush previous write */
		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSIX_FLAGS);
	}
}

static void __init fix_hypertransport_config(int num, int slot, int func)
{
	u32 htcfg;
@@ -721,6 +752,7 @@ static struct chipset early_qrk[] __initdata = {
		PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
	{ PCI_VENDOR_ID_BROADCOM, 0x4331,
	  PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset},
	{ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, early_pci_clear_msi},
	{}
};

+4 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ int noioapicreroute = 1;
#endif
int pcibios_last_bus = -1;
unsigned long pirq_table_addr;
unsigned int pci_early_clear_msi;
const struct pci_raw_ops *__read_mostly raw_pci_ops;
const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;

@@ -606,6 +607,9 @@ char *__init pcibios_setup(char *str)
	} else if (!strcmp(str, "skip_isa_align")) {
		pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
		return NULL;
	} else if (!strcmp(str, "clearmsi")) {
		pci_early_clear_msi = 1;
		return NULL;
	} else if (!strcmp(str, "noioapicquirk")) {
		noioapicquirk = 1;
		return NULL;
Loading