[Skiboot] [RFC PATCH 1/3] core/pci: Add functions for iterating pci devices

Jordan Niethe jniethe5 at gmail.com
Tue Oct 22 14:32:00 AEDT 2019


Currently to visit all the devices under a phb/pci device the recursive
pci_walk_dev() function is used. This does not make the state of where
the walk is up to accessible which limits how it can be used. For
example we might like to visit each device and perform tasks that
require waiting. Rather than waiting in skiboot we would like to be able
to return a timeout value to the caller. This requires keeping the state
of the walk so that we can return to the device after waiting. To do
this give each pci_device a member to record if it has been visited or
not and add a member to each phb to keep track of the current pci device
in the walk.

Signed-off-by: Jordan Niethe <jniethe5 at gmail.com>
---
 core/pci.c    | 37 +++++++++++++++++++++++++++++++++++++
 include/pci.h |  6 ++++++
 2 files changed, 43 insertions(+)

diff --git a/core/pci.c b/core/pci.c
index 9ee70f4fddc5..547c8e32272b 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -1889,6 +1889,43 @@ struct pci_device *pci_find_dev(struct phb *phb, uint16_t bdfn)
 	return pci_walk_dev(phb, NULL, __pci_find_dev, &bdfn);
 }
 
+static int __pci_unsee_device(struct phb *phb,
+			       struct pci_device *pd,
+			       void *data __unused)
+{
+	if (!phb || !pd) {
+		return 0;
+	}
+
+	pd->seen = false;
+	return 0;
+}
+
+void pci_device_iter_reset(struct phb *phb, struct pci_device *pd)
+{
+	pci_walk_dev(phb, pd, __pci_unsee_device, NULL);
+}
+
+static int __pci_device_iter_next(struct phb *phb,
+			       struct pci_device *pd,
+			       void *data __unused)
+{
+	if (!phb || !pd) {
+		return 0;
+	}
+
+	if (pd->seen)
+		return 0;
+
+	pd->seen = true;
+	return 1;
+}
+
+struct pci_device *pci_device_iter_next(struct phb *phb, struct pci_device *pd)
+{
+	return  pci_walk_dev(phb, pd, __pci_device_iter_next, NULL);
+}
+
 static int __pci_restore_bridge_buses(struct phb *phb,
 				      struct pci_device *pd,
 				      void *data __unused)
diff --git a/include/pci.h b/include/pci.h
index dcd354a7cfef..9672a2d342f6 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -75,6 +75,7 @@ struct pci_device {
 	bool			is_bridge;
 	bool			is_multifunction;
 	bool			is_vf;
+	bool			seen;
 	uint8_t			dev_type; /* PCIE */
 	uint8_t			primary_bus;
 	uint8_t			secondary_bus;
@@ -378,6 +379,9 @@ struct phb {
 	/* PCI-X only slot info, for PCI-E this is in the RC bridge */
 	struct pci_slot		*slot;
 
+	/* Used for iteration */
+	struct pci_device *current_pd;
+
 	/* Base location code used to generate the children one */
 	const char		*base_loc_code;
 
@@ -451,6 +455,8 @@ extern void pci_init_capabilities(struct phb *phb, struct pci_device *pd);
 extern bool pci_wait_crs(struct phb *phb, uint16_t bdfn, uint32_t *out_vdid);
 extern void pci_restore_slot_bus_configs(struct pci_slot *slot);
 extern void pci_device_init(struct phb *phb, struct pci_device *pd);
+extern void pci_device_iter_reset(struct phb *phb, struct pci_device *pd);
+extern struct pci_device *pci_device_iter_next(struct phb *phb, struct pci_device *pd);
 extern struct pci_device *pci_walk_dev(struct phb *phb,
 				       struct pci_device *pd,
 				       int (*cb)(struct phb *,
-- 
2.20.1



More information about the Skiboot mailing list