All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vikas Gupta <vikas.gupta@broadcom.com>
To: jiri@nvidia.com, dsahern@kernel.org, stephen@networkplumber.org
Cc: kuba@kernel.org, netdev@vger.kernel.org, edumazet@google.com,
	michael.chan@broadcom.com, andrew.gospodarek@broadcom.com,
	Vikas Gupta <vikas.gupta@broadcom.com>
Subject: [PATCH iproute2-next v2 2/3] devlink: add support for running selftests
Date: Fri,  8 Jul 2022 00:01:15 +0530	[thread overview]
Message-ID: <20220707183116.29422-3-vikas.gupta@broadcom.com> (raw)
In-Reply-To: <20220707183116.29422-1-vikas.gupta@broadcom.com>

[-- Attachment #1: Type: text/plain, Size: 8525 bytes --]

Add command and helper APIs to run selfests.
Also add a seltest for flash on the device.

Examples:
$ devlink dev selftests run pci/0000:03:00.0 test flash
   selftests results:
      flash failed

$ devlink dev selftests show pci/0000:03:00.0
   supported selftests:
      flash

Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com>
Reviewed-by: Michael Chan <michael.chan@broadcom.com>
Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
---
 devlink/devlink.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index ddf430bb..ebd33f9d 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -294,6 +294,7 @@ static void ifname_map_free(struct ifname_map *ifname_map)
 #define DL_OPT_PORT_FN_RATE_TX_MAX	BIT(49)
 #define DL_OPT_PORT_FN_RATE_NODE_NAME	BIT(50)
 #define DL_OPT_PORT_FN_RATE_PARENT	BIT(51)
+#define DL_OPT_SELFTESTS		BIT(52)
 
 struct dl_opts {
 	uint64_t present; /* flags of present items */
@@ -344,6 +345,7 @@ struct dl_opts {
 	uint32_t overwrite_mask;
 	enum devlink_reload_action reload_action;
 	enum devlink_reload_limit reload_limit;
+	uint32_t selftests_mask;
 	uint32_t port_controller;
 	uint32_t port_sfnumber;
 	uint16_t port_flavour;
@@ -693,6 +695,7 @@ static const enum mnl_attr_data_type devlink_policy[DEVLINK_ATTR_MAX + 1] = {
 	[DEVLINK_ATTR_TRAP_POLICER_ID] = MNL_TYPE_U32,
 	[DEVLINK_ATTR_TRAP_POLICER_RATE] = MNL_TYPE_U64,
 	[DEVLINK_ATTR_TRAP_POLICER_BURST] = MNL_TYPE_U64,
+	[DEVLINK_ATTR_TEST_RESULT] = MNL_TYPE_NESTED
 };
 
 static const enum mnl_attr_data_type
@@ -1401,6 +1404,19 @@ static struct str_num_map port_fn_opstate_map[] = {
 	{ .str = NULL, }
 };
 
+static int selftests_get(const char *testname, uint32_t *mask)
+{
+	if (strcmp(testname, "flash") == 0) {
+		*mask |= DEVLINK_SELFTEST_FLASH;
+	} else if (strcmp(testname, "all") == 0) {
+		*mask = DEVLINK_SELFTESTS_MASK;
+	} else {
+		pr_err("Unknown selftest \"%s\"\n", testname);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int port_flavour_parse(const char *flavour, uint16_t *value)
 {
 	int num;
@@ -1490,6 +1506,7 @@ static const struct dl_args_metadata dl_args_required[] = {
 	{DL_OPT_PORT_FUNCTION_HW_ADDR, "Port function's hardware address is expected."},
 	{DL_OPT_PORT_FLAVOUR,          "Port flavour is expected."},
 	{DL_OPT_PORT_PFNUMBER,         "Port PCI PF number is expected."},
+	{DL_OPT_SELFTESTS,             "Test name is expected"},
 };
 
 static int dl_args_finding_required_validate(uint64_t o_required,
@@ -1793,6 +1810,20 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required,
 				return err;
 			o_found |= DL_OPT_FLASH_OVERWRITE;
 
+		} else if (dl_argv_match(dl, "test") &&
+				(o_all & DL_OPT_SELFTESTS)) {
+			const char *testname;
+
+			dl_arg_inc(dl);
+			err = dl_argv_str(dl, &testname);
+			if (err)
+				return err;
+			err = selftests_get(testname,
+					    &opts->selftests_mask);
+			if (err)
+				return err;
+			o_found |= DL_OPT_SELFTESTS;
+
 		} else if (dl_argv_match(dl, "reporter") &&
 			   (o_all & DL_OPT_HEALTH_REPORTER_NAME)) {
 			dl_arg_inc(dl);
@@ -2063,6 +2094,17 @@ dl_reload_limits_put(struct nlmsghdr *nlh, const struct dl_opts *opts)
 	mnl_attr_put(nlh, DEVLINK_ATTR_RELOAD_LIMITS, sizeof(limits), &limits);
 }
 
+static void
+dl_selftests_put(struct nlmsghdr *nlh, const struct dl_opts *opts)
+{
+	uint32_t selftests_mask;
+
+	selftests_mask = opts->selftests_mask;
+
+	mnl_attr_put(nlh, DEVLINK_ATTR_SELFTESTS_MASK,
+		     sizeof(selftests_mask), &selftests_mask);
+}
+
 static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
 {
 	struct dl_opts *opts = &dl->opts;
@@ -2157,6 +2199,8 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
 				  opts->flash_component);
 	if (opts->present & DL_OPT_FLASH_OVERWRITE)
 		dl_flash_update_overwrite_put(nlh, opts);
+	if (opts->present & DL_OPT_SELFTESTS)
+		dl_selftests_put(nlh, opts);
 	if (opts->present & DL_OPT_HEALTH_REPORTER_NAME)
 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
 				  opts->reporter_name);
@@ -2285,6 +2329,8 @@ static void cmd_dev_help(void)
 	pr_err("                              [ action { driver_reinit | fw_activate } ] [ limit no_reset ]\n");
 	pr_err("       devlink dev info [ DEV ]\n");
 	pr_err("       devlink dev flash DEV file PATH [ component NAME ] [ overwrite SECTION ]\n");
+	pr_err("       devlink dev selftests show DEV\n");
+	pr_err("       devlink dev selftests run DEV test { TESTNAME | all }\n");
 }
 
 static bool cmp_arr_last_handle(struct dl *dl, const char *bus_name,
@@ -3904,6 +3950,150 @@ err_socket:
 	return err;
 }
 
+static int cmd_dev_selftests_show_tests(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *version;
+	struct dl *dl = data;
+	int avail = 0;
+
+	mnl_attr_for_each(version, nlh, sizeof(struct genlmsghdr)) {
+		int type = mnl_attr_get_type(version);
+
+		if (type == DEVLINK_ATTR_BUS_NAME || type == DEVLINK_ATTR_DEV_NAME)
+			continue;
+
+		if (type != DEVLINK_ATTR_TEST_NAME)
+			return MNL_CB_ERROR;
+
+		if (!avail) {
+			pr_out_object_start(dl, "supported selftests");
+			avail = 1;
+		}
+
+		check_indent_newline(dl);
+		print_string(PRINT_ANY, NULL, "%s", mnl_attr_get_str(version));
+		if (!dl->json_output)
+			__pr_out_newline();
+	}
+
+	if (avail)
+		pr_out_object_end(dl);
+
+	return MNL_CB_OK;
+}
+
+static const char *selftest_result_to_str(uint8_t res)
+{
+	switch (res) {
+	case DEVLINK_SELFTEST_SKIP:
+		return "skipped";
+	case DEVLINK_SELFTEST_PASS:
+		return "passed";
+	case DEVLINK_SELFTEST_FAIL:
+		return "failed";
+	default:
+		return "unknown";
+	}
+}
+
+static int cmd_dev_selftests_result_show(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *version;
+	struct dl *dl = data;
+	int avail = 0;
+
+	mnl_attr_for_each(version, nlh, sizeof(struct genlmsghdr)) {
+		struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
+		int type = mnl_attr_get_type(version);
+		const char *test_name;
+		const char *test_res;
+		uint8_t res_val;
+		int err;
+
+		if (type == DEVLINK_ATTR_BUS_NAME || type == DEVLINK_ATTR_DEV_NAME)
+			continue;
+
+		if (type != DEVLINK_ATTR_TEST_RESULT)
+			return MNL_CB_ERROR;
+
+		err = mnl_attr_parse_nested(version, attr_cb, tb);
+		if (err != MNL_CB_OK)
+			return MNL_CB_ERROR;
+
+		if (!tb[DEVLINK_ATTR_TEST_NAME] ||
+		    !tb[DEVLINK_ATTR_TEST_RESULT_VAL])
+			return MNL_CB_ERROR;
+
+		if (!avail) {
+			pr_out_object_start(dl, "selftests results");
+			avail = 1;
+		}
+
+		test_name = mnl_attr_get_str(tb[DEVLINK_ATTR_TEST_NAME]);
+		res_val = mnl_attr_get_u8(tb[DEVLINK_ATTR_TEST_RESULT_VAL]);
+		test_res = selftest_result_to_str(res_val);
+
+		check_indent_newline(dl);
+		print_string_name_value(test_name, test_res);
+		if (!dl->json_output)
+			__pr_out_newline();
+	}
+
+	if (avail)
+		pr_out_object_end(dl);
+
+	return MNL_CB_OK;
+}
+
+static int cmd_dev_selftests_run(struct dl *dl)
+{
+	struct nlmsghdr *nlh;
+	uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
+	int err;
+
+	nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SELFTESTS_RUN, flags);
+
+	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_SELFTESTS, 0);
+	if (err)
+		return err;
+
+	err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_selftests_result_show, dl);
+	return err;
+}
+
+static int cmd_dev_selftests_show(struct dl *dl)
+{
+	uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
+	struct nlmsghdr *nlh;
+	int err;
+
+	nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SELFTESTS_SHOW, flags);
+
+	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0);
+	if (err)
+		return err;
+
+	err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_selftests_show_tests, dl);
+	return err;
+}
+
+static int cmd_dev_selftests(struct dl *dl)
+{
+	if (dl_argv_match(dl, "help")) {
+		cmd_dev_help();
+		return 0;
+	} else if (dl_argv_match(dl, "show") ||
+		   dl_argv_match(dl, "list") || dl_no_arg(dl)) {
+		dl_arg_inc(dl);
+		return cmd_dev_selftests_show(dl);
+	} else if (dl_argv_match(dl, "run")) {
+		dl_arg_inc(dl);
+		return cmd_dev_selftests_run(dl);
+	}
+	pr_err("Command \"%s\" not found\n", dl_argv(dl));
+	return -ENOENT;
+}
+
 static int cmd_dev(struct dl *dl)
 {
 	if (dl_argv_match(dl, "help")) {
@@ -3928,6 +4118,9 @@ static int cmd_dev(struct dl *dl)
 	} else if (dl_argv_match(dl, "flash")) {
 		dl_arg_inc(dl);
 		return cmd_dev_flash(dl);
+	} else if (dl_argv_match(dl, "selftests")) {
+		dl_arg_inc(dl);
+		return cmd_dev_selftests(dl);
 	}
 	pr_err("Command \"%s\" not found\n", dl_argv(dl));
 	return -ENOENT;
-- 
2.31.1


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4206 bytes --]

  parent reply	other threads:[~2022-07-07 18:34 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-28 16:44 [PATCH iproute2-next v1 0/2] devlink: add support to run selftests Vikas Gupta
2022-06-28 16:44 ` [PATCH iproute2-next v1 1/2] Update kernel header Vikas Gupta
2022-06-28 16:44 ` [PATCH iproute2-next v1 2/2] devlink: add support for running selftests Vikas Gupta
2022-06-29 11:37 ` [PATCH iproute2-next v1 0/2] devlink: add support to run selftests Ido Schimmel
2022-07-07 18:31 ` [PATCH iproute2-next v2 0/3] " Vikas Gupta
2022-07-07 18:31   ` [PATCH iproute2-next v2 1/3] devlink: update the devlink.h Vikas Gupta
2022-07-07 18:31   ` Vikas Gupta [this message]
2022-07-07 18:31   ` [PATCH iproute2-next v2 3/3] devlink : update man page for new commands Vikas Gupta
2022-07-10  8:56   ` [PATCH iproute2-next v2 0/3] devlink: add support to run selftests Ido Schimmel
2022-07-18  6:22   ` [PATCH iproute2-next v3 0/3] devlink: add support to run selftest Vikas Gupta
2022-07-18  6:22     ` [PATCH iproute2-next v3 1/3] devlink: update the devlink.h Vikas Gupta
2022-07-18  6:22     ` [PATCH iproute2-next v3 2/3] devlink: add support for running selftests Vikas Gupta
2022-07-18  6:22     ` [PATCH iproute2-next v3 3/3] devlink : update man page and bash-completion for new commands Vikas Gupta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220707183116.29422-3-vikas.gupta@broadcom.com \
    --to=vikas.gupta@broadcom.com \
    --cc=andrew.gospodarek@broadcom.com \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=jiri@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=michael.chan@broadcom.com \
    --cc=netdev@vger.kernel.org \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.