libzpci: opticsmon: Refactor on_link_change() using new zpci_find_by_netdev()

Finding a PCI device given the name of a netdev seems generally useful
so pull this out into a new zpci_find_by_netdev() function in libzpci
and use this to simplify on_link_change() removing the need for
backwards goto.

Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Niklas Schnelle
2024-12-09 15:08:03 +01:00
committed by Jan Höppner
parent dff965465c
commit cf5560a100
3 changed files with 45 additions and 16 deletions

View File

@@ -93,4 +93,7 @@ const char *zpci_pft_str(struct zpci_dev *zdev);
const char *zpci_operstate_str(operstate_t state);
operstate_t zpci_operstate_from_str(const char *oper_str);
struct zpci_dev *zpci_find_by_netdev(struct util_list *zpci_list, char *netdev_name,
struct zpci_netdev **netdev);
#endif /* LIB_ZPCI_PCI_LIST_H */

View File

@@ -356,3 +356,34 @@ void zpci_free_dev_list(struct util_list *zpci_list)
}
util_list_free(zpci_list);
}
/**
* Find a PCI device given the name of a netdev
*
* This function allows finding a PCI device when only the name of one
* of its netdevs is known.
*
* @param[in] zpci_list The device list to search
* @param[in] netdev_name The name of the netdev
* @param[out] netdev Pointer to store the netdev or NULL if
* only the PCI device is needed
*
* @return The PCI device if one is found NULL otherwise
*/
struct zpci_dev *zpci_find_by_netdev(struct util_list *zpci_list, char *netdev_name,
struct zpci_netdev **netdev)
{
struct zpci_dev *zdev = NULL;
int i;
util_list_iterate(zpci_list, zdev) {
for (i = 0; i < zdev->num_netdevs; i++) {
if (!strcmp(zdev->netdevs[i].name, netdev_name)) {
if (netdev)
*netdev = &zdev->netdevs[i];
return zdev;
}
}
}
return NULL;
}

View File

@@ -274,38 +274,33 @@ static int oneshot_mode(struct opticsmon_ctx *ctx)
void on_link_change(struct zpci_netdev *netdev, void *arg)
{
struct opticsmon_ctx *ctx = arg;
struct zpci_dev *zdev;
int i, reloads = 1;
struct zpci_netdev *found_netdev;
struct zpci_dev *zdev = NULL;
int reloads = 1;
if (!ctx->zpci_list || util_list_is_empty(ctx->zpci_list))
zpci_list_reload(&ctx->zpci_list);
find:
util_list_iterate(ctx->zpci_list, zdev) {
for (i = 0; i < zdev->num_netdevs; i++) {
if (!strcmp(zdev->netdevs[i].name, netdev->name)) {
do {
if (ctx->zpci_list) {
zdev = zpci_find_by_netdev(ctx->zpci_list, netdev->name, &found_netdev);
if (zdev) {
/* Skip data collection if operational state is
* unchanged
*/
if (zdev->netdevs[i].operstate == netdev->operstate)
if (found_netdev->operstate == netdev->operstate)
return;
/* Update operation state for VFs even though
* they are skipped just for a consistent view
*/
zdev->netdevs[i].operstate = netdev->operstate;
found_netdev->operstate = netdev->operstate;
/* Only collect optics data for PFs */
if (!zpci_is_vf(zdev))
dump_adapter_data(ctx, zdev);
return;
}
}
}
/* Might be a new device, reload list of devices and retry */
if (reloads > 0) {
/* Could be uninitalized list or a new device, retry after reload */
zpci_list_reload(&ctx->zpci_list);
reloads--;
goto find;
}
} while (reloads > 0);
}
#define MAX_EVENTS 8