@@ -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)
@@ -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 *,
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(+)