diff mbox series

[RFC,v2,1/3] core/pci: Add functions for iterating PCI devices

Message ID 20191029021106.29396-2-jniethe5@gmail.com
State New
Headers show
Series Changes to restoring buses after PCI reset | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success Successfully applied on branch master (d75e82dbfbb9443efeb3f9a5921ac23605aab469)
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot success Test snowpatch/job/snowpatch-skiboot on branch master
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot-dco success Signed-off-by present

Commit Message

Jordan Niethe Oct. 29, 2019, 2:11 a.m. UTC
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@gmail.com>
---
v2: No changes

 core/pci.c    | 37 +++++++++++++++++++++++++++++++++++++
 include/pci.h |  6 ++++++
 2 files changed, 43 insertions(+)
diff mbox series

Patch

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 *,