[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/6] hw/pcie: Factor out PCI Express link register filling common
From: |
Jonathan Cameron |
Subject: |
[PATCH 3/6] hw/pcie: Factor out PCI Express link register filling common to EP. |
Date: |
Mon, 16 Sep 2024 18:35:15 +0100 |
Whilst not all link related registers are common between RP / Switch DSP
and EP / Switch USP many of them are. Factor that group out to save
on duplication when adding EP / Swtich USP configurability.
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
hw/pci/pcie.c | 87 ++++++++++++++++++++++++++++-----------------------
1 file changed, 48 insertions(+), 39 deletions(-)
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 4b2f0805c6..1ac6d89dcf 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -105,46 +105,18 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t
type, uint8_t version)
pci_set_word(cmask + PCI_EXP_LNKSTA, 0);
}
-static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
+/* Includes setting the target speed default */
+static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
+ PCIExpLinkSpeed speed)
{
- PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
- uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
-
- /* Skip anything that isn't a PCIESlot */
- if (!s) {
- return;
- }
-
/* Clear and fill LNKCAP from what was configured above */
pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
- QEMU_PCI_EXP_LNKCAP_MLW(s->width) |
- QEMU_PCI_EXP_LNKCAP_MLS(s->speed));
-
- /*
- * Link bandwidth notification is required for all root ports and
- * downstream ports supporting links wider than x1 or multiple link
- * speeds.
- */
- if (s->width > QEMU_PCI_EXP_LNK_X1 ||
- s->speed > QEMU_PCI_EXP_LNK_2_5GT) {
- pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
- PCI_EXP_LNKCAP_LBNC);
- }
-
- if (s->speed > QEMU_PCI_EXP_LNK_2_5GT) {
- /*
- * Hot-plug capable downstream ports and downstream ports supporting
- * link speeds greater than 5GT/s must hardwire PCI_EXP_LNKCAP_DLLLARC
- * to 1b. PCI_EXP_LNKCAP_DLLLARC implies PCI_EXP_LNKSTA_DLLLA, which
- * we also hardwire to 1b here. 2.5GT/s hot-plug slots should also
- * technically implement this, but it's not done here for
compatibility.
- */
- pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
- PCI_EXP_LNKCAP_DLLLARC);
- /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
+ QEMU_PCI_EXP_LNKCAP_MLW(width) |
+ QEMU_PCI_EXP_LNKCAP_MLS(speed));
+ if (speed > QEMU_PCI_EXP_LNK_2_5GT) {
/*
* Target Link Speed defaults to the highest link speed supported by
* the component. 2.5GT/s devices are permitted to hardwire to zero.
@@ -152,7 +124,7 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKCTL2,
PCI_EXP_LNKCTL2_TLS);
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKCTL2,
- QEMU_PCI_EXP_LNKCAP_MLS(s->speed) &
+ QEMU_PCI_EXP_LNKCAP_MLS(speed) &
PCI_EXP_LNKCTL2_TLS);
}
@@ -161,27 +133,64 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
* actually a reference to the highest bit supported in this register.
* We assume the device supports all link speeds.
*/
- if (s->speed > QEMU_PCI_EXP_LNK_5GT) {
+ if (speed > QEMU_PCI_EXP_LNK_5GT) {
pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP2, ~0U);
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
PCI_EXP_LNKCAP2_SLS_2_5GB |
PCI_EXP_LNKCAP2_SLS_5_0GB |
PCI_EXP_LNKCAP2_SLS_8_0GB);
- if (s->speed > QEMU_PCI_EXP_LNK_8GT) {
+ if (speed > QEMU_PCI_EXP_LNK_8GT) {
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
PCI_EXP_LNKCAP2_SLS_16_0GB);
}
- if (s->speed > QEMU_PCI_EXP_LNK_16GT) {
+ if (speed > QEMU_PCI_EXP_LNK_16GT) {
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
PCI_EXP_LNKCAP2_SLS_32_0GB);
}
- if (s->speed > QEMU_PCI_EXP_LNK_32GT) {
+ if (speed > QEMU_PCI_EXP_LNK_32GT) {
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
PCI_EXP_LNKCAP2_SLS_64_0GB);
}
}
}
+static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
+{
+ PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
+ uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+
+ /* Skip anything that isn't a PCIESlot */
+ if (!s) {
+ return;
+ }
+
+ /*
+ * Link bandwidth notification is required for all root ports and
+ * downstream ports supporting links wider than x1 or multiple link
+ * speeds.
+ */
+ if (s->width > QEMU_PCI_EXP_LNK_X1 ||
+ s->speed > QEMU_PCI_EXP_LNK_2_5GT) {
+ pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
+ PCI_EXP_LNKCAP_LBNC);
+ }
+
+ if (s->speed > QEMU_PCI_EXP_LNK_2_5GT) {
+ /*
+ * Hot-plug capable downstream ports and downstream ports supporting
+ * link speeds greater than 5GT/s must hardwire PCI_EXP_LNKCAP_DLLLARC
+ * to 1b. PCI_EXP_LNKCAP_DLLLARC implies PCI_EXP_LNKSTA_DLLLA, which
+ * we also hardwire to 1b here. 2.5GT/s hot-plug slots should also
+ * technically implement this, but it's not done here for
compatibility.
+ */
+ pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
+ PCI_EXP_LNKCAP_DLLLARC);
+ /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
+ }
+
+ pcie_cap_fill_lnk(exp_cap, s->width, s->speed);
+}
+
int pcie_cap_init(PCIDevice *dev, uint8_t offset,
uint8_t type, uint8_t port,
Error **errp)
--
2.43.0
- [PATCH qemu 0/6] hw/cxl: Link speed and width control, Jonathan Cameron, 2024/09/16
- [PATCH 1/6] hw/pci-bridge/cxl_root_port: Provide x-speed and x-width properties., Jonathan Cameron, 2024/09/16
- [PATCH 2/6] hw/pci-bridge/cxl_upstream: Provide x-speed and x-width properties., Jonathan Cameron, 2024/09/16
- [PATCH 3/6] hw/pcie: Factor out PCI Express link register filling common to EP.,
Jonathan Cameron <=
- [PATCH 4/6] hw/pcie: Provide a utility function for control of EP / SW USP link, Jonathan Cameron, 2024/09/16
- [PATCH 5/6] hw/mem/cxl-type3: Add properties to control link speed and width, Jonathan Cameron, 2024/09/16
- [PATCH 6/6] hw/pci-bridge/cxl-upstream: Add properties to control link speed and width, Jonathan Cameron, 2024/09/16