[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v5 17/18] pcie: implement HOTPLUG_STATE event and query-hotplug
From: |
Vladimir Sementsov-Ogievskiy |
Subject: |
[PATCH v5 17/18] pcie: implement HOTPLUG_STATE event and query-hotplug |
Date: |
Thu, 16 Feb 2023 21:03:55 +0300 |
For PCIe and SHPC hotplug it's important to track led indicators,
especially the power led. At this step implement the prepared
infrastructure in PCIe.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
include/hw/pci/pcie.h | 2 ++
hw/pci/pcie.c | 78 +++++++++++++++++++++++++++++++++++++++++++
hw/pci/pcie_port.c | 1 +
3 files changed, 81 insertions(+)
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 3cc2b15957..f755a7cacb 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -146,4 +146,6 @@ void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev,
Error **errp);
void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
+HotplugInfo *pcie_cap_slot_get_hotplug_state(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
#endif /* QEMU_PCIE_H */
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index b8c24cf45f..636f962a23 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -19,6 +19,8 @@
*/
#include "qemu/osdep.h"
+
+#include "monitor/qdev.h"
#include "qapi/error.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pcie.h"
@@ -45,6 +47,23 @@ static bool pcie_sltctl_powered_off(uint16_t sltctl)
&& (sltctl & PCI_EXP_SLTCTL_PIC) == PCI_EXP_SLTCTL_PWR_IND_OFF;
}
+static LedActivity pcie_led_state_to_qapi(uint16_t value)
+{
+ switch (value) {
+ case PCI_EXP_SLTCTL_PWR_IND_ON:
+ case PCI_EXP_SLTCTL_ATTN_IND_ON:
+ return LED_ACTIVITY_ON;
+ case PCI_EXP_SLTCTL_PWR_IND_BLINK:
+ case PCI_EXP_SLTCTL_ATTN_IND_BLINK:
+ return LED_ACTIVITY_BLINK;
+ case PCI_EXP_SLTCTL_PWR_IND_OFF:
+ case PCI_EXP_SLTCTL_ATTN_IND_OFF:
+ return LED_ACTIVITY_OFF;
+ default:
+ abort();
+ }
+}
+
/***************************************************************************
* pci express capability helper functions
*/
@@ -728,9 +747,17 @@ 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)
{
+ PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
uint32_t pos = dev->exp.exp_cap;
uint8_t *exp_cap = dev->config + pos;
uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
+ uint16_t power_led, attn_led, pcc, old_power_led, old_attn_led, old_pcc;
+ DeviceState *child_dev =
+ DEVICE(pci_find_the_only_child(sec_bus, pci_bus_num(sec_bus), NULL));
+ HotplugState changed_state = {
+ .type = HOTPLUG_TYPE_PCIE_NATIVE,
+ };
+ HotplugPCIeNativeState *cs = &changed_state.u.pcie_native;
if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) {
/*
@@ -768,6 +795,27 @@ void pcie_cap_slot_write_config(PCIDevice *dev,
sltsta);
}
+ power_led = val & PCI_EXP_SLTCTL_PIC;
+ old_power_led = old_slt_ctl & PCI_EXP_SLTCTL_PIC;
+ cs->has_power_led = power_led != old_power_led;
+ cs->power_led = cs->has_power_led ? pcie_led_state_to_qapi(power_led) : 0;
+
+ attn_led = val & PCI_EXP_SLTCTL_AIC;
+ old_attn_led = old_slt_ctl & PCI_EXP_SLTCTL_AIC;
+ cs->has_attention_led = attn_led != old_attn_led;
+ cs->attention_led =
+ cs->has_attention_led ? pcie_led_state_to_qapi(attn_led) : 0;
+
+ pcc = val & PCI_EXP_SLTCTL_PCC;
+ old_pcc = old_slt_ctl & PCI_EXP_SLTCTL_PCC;
+ cs->has_power_on = pcc != old_pcc;
+ cs->power_on = cs->has_power_on ? pcc == PCI_EXP_SLTCTL_PWR_ON : false;
+
+
+ if (cs->has_power_led || cs->has_attention_led || cs->has_power_on) {
+ qdev_hotplug_state_event(DEVICE(dev), NULL, child_dev, &changed_state);
+ }
+
/*
* If the slot is populated, power indicator is off and power
* controller is off, it is safe to detach the devices.
@@ -1100,3 +1148,33 @@ void pcie_acs_reset(PCIDevice *dev)
pci_set_word(dev->config + dev->exp.acs_cap + PCI_ACS_CTRL, 0);
}
}
+
+HotplugInfo *pcie_cap_slot_get_hotplug_state(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
+ uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
+ uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
+ uint16_t power_led = sltctl & PCI_EXP_SLTCTL_PIC;
+ uint16_t attn_led = sltctl & PCI_EXP_SLTCTL_AIC;
+ uint16_t pcc = sltctl & PCI_EXP_SLTCTL_PCC;
+ HotplugInfo *res = g_new(HotplugInfo, 1);
+
+ *res = (HotplugInfo) {
+ .bus = qdev_new_device_and_path(DEVICE(hotplug_pdev)),
+ .child = qdev_new_device_and_path(dev),
+ .state = g_new(HotplugState, 1),
+ };
+
+ *res->state = (HotplugState) {
+ .type = HOTPLUG_TYPE_PCIE_NATIVE,
+ .u.pcie_native.has_power_led = true,
+ .u.pcie_native.power_led = pcie_led_state_to_qapi(power_led),
+ .u.pcie_native.has_attention_led = true,
+ .u.pcie_native.attention_led = pcie_led_state_to_qapi(attn_led),
+ .u.pcie_native.has_power_on = true,
+ .u.pcie_native.power_on = pcc == PCI_EXP_SLTCTL_PWR_ON,
+ };
+
+ return res;
+}
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 65a397ad23..8b28efc52d 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -188,6 +188,7 @@ static void pcie_slot_class_init(ObjectClass *oc, void
*data)
hc->plug = pcie_cap_slot_plug_cb;
hc->unplug = pcie_cap_slot_unplug_cb;
hc->unplug_request = pcie_cap_slot_unplug_request_cb;
+ hc->get_hotplug_state = pcie_cap_slot_get_hotplug_state;
}
static const TypeInfo pcie_slot_type_info = {
--
2.34.1
- [PATCH v5 07/18] pcie: pcie_cap_slot_write_config(): use correct macro, (continued)
- [PATCH v5 07/18] pcie: pcie_cap_slot_write_config(): use correct macro, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 09/18] pcie: drop unused PCIExpressIndicator, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 11/18] pcie: introduce pcie_sltctl_powered_off() helper, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 08/18] pcie_regs: drop duplicated indicator value macros, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 10/18] pcie: pcie_cap_slot_enable_power() use correct helper, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 12/18] pcie: set power indicator to off on reset by default, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 13/18] pci: introduce pci_find_the_only_child(), Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 14/18] qapi/qdev.json: unite DEVICE_* event data into single structure, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 15/18] qapi: add HOTPLUG_STATE infrastructure, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 16/18] shpc: implement HOTPLUG_STATE event and query-hotplug, Vladimir Sementsov-Ogievskiy, 2023/02/16
- [PATCH v5 17/18] pcie: implement HOTPLUG_STATE event and query-hotplug,
Vladimir Sementsov-Ogievskiy <=
- [PATCH v5 18/18] qapi: introduce DEVICE_ON event, Vladimir Sementsov-Ogievskiy, 2023/02/16