diff options
| author | Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | 2024-03-01 18:41:46 +0300 |
|---|---|---|
| committer | Philippe Mathieu-Daudé <philmd@linaro.org> | 2024-03-11 22:09:42 +0100 |
| commit | 86f0aa1d438e0db61015678164b835cedc80795c (patch) | |
| tree | 6604d7f7d34f859dde8fbe0a72944c88df208036 /hw/pci/pcie.c | |
| parent | 2f73edac568fb6a49594a7367c85c0a4425c7ea6 (diff) | |
| download | focaccia-qemu-86f0aa1d438e0db61015678164b835cedc80795c.tar.gz focaccia-qemu-86f0aa1d438e0db61015678164b835cedc80795c.zip | |
hw/pci: add some convenient trace-events for pcie and shpc hotplug
Add trace-events that may help to debug problems with hotplugging. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20240301154146.761531-2-vsementsov@yandex-team.ru> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Diffstat (limited to 'hw/pci/pcie.c')
| -rw-r--r-- | hw/pci/pcie.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 6db0cf69cd..f56079acf5 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -28,6 +28,7 @@ #include "hw/pci/pcie_regs.h" #include "hw/pci/pcie_port.h" #include "qemu/range.h" +#include "trace.h" //#define DEBUG_PCIE #ifdef DEBUG_PCIE @@ -45,6 +46,23 @@ static bool pcie_sltctl_powered_off(uint16_t sltctl) && (sltctl & PCI_EXP_SLTCTL_PIC) == PCI_EXP_SLTCTL_PWR_IND_OFF; } +static const char *pcie_led_state_to_str(uint16_t value) +{ + switch (value) { + case PCI_EXP_SLTCTL_PWR_IND_ON: + case PCI_EXP_SLTCTL_ATTN_IND_ON: + return "on"; + case PCI_EXP_SLTCTL_PWR_IND_BLINK: + case PCI_EXP_SLTCTL_ATTN_IND_BLINK: + return "blink"; + case PCI_EXP_SLTCTL_PWR_IND_OFF: + case PCI_EXP_SLTCTL_ATTN_IND_OFF: + return "off"; + default: + return "invalid"; + } +} + /*************************************************************************** * pci express capability helper functions */ @@ -735,6 +753,28 @@ void pcie_cap_slot_get(PCIDevice *dev, uint16_t *slt_ctl, uint16_t *slt_sta) *slt_sta = pci_get_word(exp_cap + PCI_EXP_SLTSTA); } +static void find_child_fn(PCIBus *bus, PCIDevice *dev, void *opaque) +{ + PCIDevice **child = opaque; + + if (!*child) { + *child = dev; + } +} + +/* + * Returns the plugged device or first function of multifunction plugged device + */ +static PCIDevice *pcie_cap_slot_find_child(PCIDevice *dev) +{ + PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev)); + PCIDevice *child = NULL; + + pci_for_each_device(sec_bus, pci_bus_num(sec_bus), find_child_fn, &child); + + return child; +} + void pcie_cap_slot_write_config(PCIDevice *dev, uint16_t old_slt_ctl, uint16_t old_slt_sta, uint32_t addr, uint32_t val, int len) @@ -779,6 +819,22 @@ void pcie_cap_slot_write_config(PCIDevice *dev, sltsta); } + if (trace_event_get_state_backends(TRACE_PCIE_CAP_SLOT_WRITE_CONFIG)) { + DeviceState *parent = DEVICE(dev); + DeviceState *child = DEVICE(pcie_cap_slot_find_child(dev)); + + trace_pcie_cap_slot_write_config( + parent->canonical_path, + child ? child->canonical_path : "no-child", + (sltsta & PCI_EXP_SLTSTA_PDS) ? "present" : "not present", + pcie_led_state_to_str(old_slt_ctl & PCI_EXP_SLTCTL_PIC), + pcie_led_state_to_str(val & PCI_EXP_SLTCTL_PIC), + pcie_led_state_to_str(old_slt_ctl & PCI_EXP_SLTCTL_AIC), + pcie_led_state_to_str(val & PCI_EXP_SLTCTL_AIC), + (old_slt_ctl & PCI_EXP_SLTCTL_PWR_OFF) ? "off" : "on", + (val & PCI_EXP_SLTCTL_PWR_OFF) ? "off" : "on"); + } + /* * If the slot is populated, power indicator is off and power * controller is off, it is safe to detach the devices. |