100 lines
4.1 KiB
Diff
100 lines
4.1 KiB
Diff
From 7381599d4222f9b5cff6935a66e8b311af77f620 Mon Sep 17 00:00:00 2001
|
|
From: Li Mingwang <limingwang@huawei.com>
|
|
Date: Thu, 17 Oct 2019 16:57:52 +0800
|
|
Subject: [PATCH] Subject: [PATCH] pcie: disable the PCI_EXP_LINKSTA_DLLA cap
|
|
for pcie-root-port by default
|
|
|
|
If the PCI_EXP_LNKSTA_DLLLA capability is set by default, linux
|
|
kernel will send PDC event to detect whether there is a device in
|
|
pcie slot. If a device is pluged in the pcie-root-port at the same
|
|
time, hot-plug device will send ABP + PDC events to the kernel. The
|
|
VM kernel will wrongly unplug the device if two PDC events get too
|
|
close. Thus we'd better set the PCI_EXP_LNKSTA_DLLLA capability only
|
|
in hotplug scenario
|
|
|
|
Signed-off-by: Li Mingwang <limingwang@huawei.com>
|
|
---
|
|
hw/core/machine.c | 1 +
|
|
hw/pci-bridge/gen_pcie_root_port.c | 1 +
|
|
hw/pci/pcie.c | 18 ++++++++++++++----
|
|
include/hw/pci/pcie_port.h | 2 ++
|
|
4 files changed, 18 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
|
index 5d046a43..29a708da 100644
|
|
--- a/hw/core/machine.c
|
|
+++ b/hw/core/machine.c
|
|
@@ -30,6 +30,7 @@ const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
|
|
GlobalProperty hw_compat_3_1[] = {
|
|
{ "pcie-root-port", "x-speed", "2_5" },
|
|
{ "pcie-root-port", "x-width", "1" },
|
|
+ { "pcie-root-port", "fast-plug", "0" },
|
|
{ "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" },
|
|
{ "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" },
|
|
{ "tpm-crb", "ppi", "false" },
|
|
diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
|
|
index 26bda73e..3179c4ea 100644
|
|
--- a/hw/pci-bridge/gen_pcie_root_port.c
|
|
+++ b/hw/pci-bridge/gen_pcie_root_port.c
|
|
@@ -131,6 +131,7 @@ static Property gen_rp_props[] = {
|
|
speed, PCIE_LINK_SPEED_16),
|
|
DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
|
|
width, PCIE_LINK_WIDTH_32),
|
|
+ DEFINE_PROP_UINT8("fast-plug", PCIESlot, disable_lnksta_dllla, 0),
|
|
DEFINE_PROP_END_OF_LIST()
|
|
};
|
|
|
|
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
|
|
index cf1ca30f..c0d6ff13 100644
|
|
--- a/hw/pci/pcie.c
|
|
+++ b/hw/pci/pcie.c
|
|
@@ -50,6 +50,7 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
|
|
{
|
|
uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
|
|
uint8_t *cmask = dev->cmask + dev->exp.exp_cap;
|
|
+ PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
|
|
|
|
/* capability register
|
|
interrupt message number defaults to 0 */
|
|
@@ -76,11 +77,20 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
|
|
QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1) |
|
|
QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT));
|
|
|
|
- if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) {
|
|
- pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
|
|
- PCI_EXP_LNKSTA_DLLLA);
|
|
+ /* If a device is plugged in the pcie-root-port when VM kernel
|
|
+ * is just booting, the kernel will wrongly disable the device.
|
|
+ * This bug was brought in two patches of the linux kernel, i.e.
|
|
+ * https://patchwork.kernel.org/patch/10575355/ and
|
|
+ * https://patchwork.kernel.org/patch/10766219/.
|
|
+ * To fix this up, let's enable the PCI_EXP_LNKSTA_DLLLA
|
|
+ * only if it is a PCIESlot device.
|
|
+ */
|
|
+ if (s == NULL || s->disable_lnksta_dllla == 0) {
|
|
+ if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) {
|
|
+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
|
|
+ PCI_EXP_LNKSTA_DLLLA);
|
|
+ }
|
|
}
|
|
-
|
|
/* We changed link status bits over time, and changing them across
|
|
* migrations is generally fine as hardware changes them too.
|
|
* Let's not bother checking.
|
|
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
|
|
index 09586f46..c3969921 100644
|
|
--- a/include/hw/pci/pcie_port.h
|
|
+++ b/include/hw/pci/pcie_port.h
|
|
@@ -50,6 +50,8 @@ struct PCIESlot {
|
|
uint8_t chassis;
|
|
uint16_t slot;
|
|
|
|
+ uint8_t disable_lnksta_dllla;
|
|
+
|
|
PCIExpLinkSpeed speed;
|
|
PCIExpLinkWidth width;
|
|
|
|
--
|
|
2.19.1
|
|
|