[Skiboot] [PATCH 2/2] pci: Shared slot state synchronisation for hot reset

Russell Currey ruscur at russell.cc
Mon Nov 20 17:32:13 AEDT 2017


When a device is shared between two PHBs, it doesn't get reset properly
unless both PHBs issue a hot reset at "the same time".  Practically this
means a hot reset needs to be issued on both sides, and neither should
bring the link up until the reset on both has completed.

Signed-off-by: Russell Currey <ruscur at russell.cc>
---
 core/pci-slot.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/core/pci-slot.c b/core/pci-slot.c
index 8bddc147..f8922df5 100644
--- a/core/pci-slot.c
+++ b/core/pci-slot.c
@@ -78,6 +78,7 @@ static void pci_slot_prepare_link_change(struct pci_slot *slot, bool up)
 
 static int64_t pci_slot_run_sm(struct pci_slot *slot)
 {
+	struct pci_slot *peer = slot->peer_slot;
 	uint64_t now = mftb();
 	int64_t ret;
 
@@ -89,10 +90,23 @@ static int64_t pci_slot_run_sm(struct pci_slot *slot)
 	slot->delay_tgt_tb = 0;
 	switch (slot->state & PCI_SLOT_STATE_MASK) {
 	case PCI_SLOT_STATE_LINK:
+		// If the peer slot hasn't finished its hreset, need to wait
+		if (peer && peer->state & PCI_SLOT_STATE_HRESET &&
+		    !pci_slot_has_flags(peer, PCI_SLOT_FLAG_BOOTUP))
+			return slot->ops.hreset(peer);
+
 		ret = slot->ops.poll_link(slot);
+		if (peer && peer->state & PCI_SLOT_STATE_LINK &&
+		    !pci_slot_has_flags(peer, PCI_SLOT_FLAG_BOOTUP))
+			ret = MAX(ret, slot->ops.poll_link(peer));
 		break;
 	case PCI_SLOT_STATE_HRESET:
 		ret = slot->ops.hreset(slot);
+
+		// If the slot has a peer, it needs to hreset as well.
+		if (peer && peer->state == PCI_SLOT_STATE_NORMAL &&
+		    !pci_slot_has_flags(peer, PCI_SLOT_FLAG_BOOTUP))
+			slot->ops.hreset(peer);
 		break;
 	case PCI_SLOT_STATE_FRESET:
 		ret = slot->ops.freset(slot);
-- 
2.14.1



More information about the Skiboot mailing list