zkey: add function to iterate over all available CCA APQNs

Add a utility function to iterate over all available APQNs of
type CCA-Coprocessor. This function is required for various
future enhancements.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Ingo Franzki
2019-06-13 15:49:34 +02:00
committed by Jan Höppner
parent bf8872e94a
commit 625b81130a
2 changed files with 132 additions and 0 deletions
+127
View File
@@ -7,6 +7,7 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <stdbool.h>
@@ -19,8 +20,13 @@
#include "lib/util_path.h"
#include "lib/util_file.h"
#include "lib/util_scandir.h"
#include "lib/util_libc.h"
#include "lib/util_rec.h"
#include "lib/util_base.h"
#include "utils.h"
#include "properties.h"
#define pr_verbose(verbose, fmt...) do { \
if (verbose) \
@@ -299,3 +305,124 @@ out:
free(dev_path);
return rc;
}
static int scan_for_domains(int card, apqn_handler_t handler,
void *handler_data, bool verbose)
{
struct dirent **namelist;
char fname[290];
int i, n, domain, rc = 0;
sprintf(fname, "/sys/devices/ap/card%02x/", card);
n = util_scandir(&namelist, alphasort, fname,
"[0-9a-fA-F]+\\.[0-9a-fA-F]+");
if (n < 0)
return -EIO;
for (i = 0; i < n; i++) {
if (sscanf(namelist[i]->d_name, "%x.%x", &card, &domain) != 2)
continue;
pr_verbose(verbose, "Found %02x.%04x", card, domain);
if (sysfs_is_apqn_online(card, domain) != 1) {
pr_verbose(verbose, "APQN %02x.%04x is offline or not "
"CCA", card, domain);
continue;
}
rc = handler(card, domain, handler_data);
if (rc != 0)
break;
}
util_scandir_free(namelist, n);
return rc;
}
static int scan_for_apqns(apqn_handler_t handler, void *handler_data,
bool verbose)
{
struct dirent **namelist;
int i, n, card, rc = 0;
if (handler == NULL)
return -EINVAL;
n = util_scandir(&namelist, alphasort, "/sys/devices/ap/",
"card[0-9a-fA-F]+");
if (n < 0)
return -EIO;
for (i = 0; i < n; i++) {
if (sscanf(namelist[i]->d_name, "card%x", &card) != 1)
continue;
pr_verbose(verbose, "Found card %02x", card);
if (sysfs_is_card_online(card) != 1) {
pr_verbose(verbose, "Card %02x is offline or not CCA",
card);
continue;
}
rc = scan_for_domains(card, handler, handler_data, verbose);
if (rc != 0)
break;
}
util_scandir_free(namelist, n);
return rc;
}
/**
* Calls the handler for all APQNs specified in the apqns parameter, or of this
* is NULL, for all online CCA APQNs found in sysfs. In case sysfs is inspected,
* the cards and domains are processed in alphabetical order.
*
* @param[in] apqns a comma separated list of APQNs. If NULL is specified,
* or an empty string, then all online CCA APQNs are
* handled.
* @param[in] handler a handler function that is called for each APQN
* @param[in] handler_data private data that is passed to the handler
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 for success or a negative errno in case of an error
*/
int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
bool verbose)
{
int card, domain;
char *copy, *tok;
char *save;
int rc = 0;
if (apqns == NULL || (apqns != NULL && strlen(apqns) == 0)) {
rc = scan_for_apqns(handler, handler_data, verbose);
} else {
copy = util_strdup(apqns);
tok = strtok_r(copy, ",", &save);
while (tok != NULL) {
if (sscanf(tok, "%x.%x", &card, &domain) != 2) {
warnx("the APQN '%s' is not valid",
tok);
rc = -EINVAL;
break;
}
pr_verbose(verbose, "Specified: %02x.%04x", card,
domain);
rc = handler(card, domain, handler_data);
if (rc != 0)
break;
tok = strtok_r(NULL, ",", &save);
}
free(copy);
}
return rc;
}
+5
View File
@@ -41,4 +41,9 @@ struct mk_info {
int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info,
bool verbose);
typedef int(*apqn_handler_t) (int card, int domain, void *handler_data);
int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
bool verbose);
#endif