diff mbox series

[iproute2-next,2/4] devlink: Support setting port function roce cap

Message ID 20221211115849.510284-3-shayd@nvidia.com (mailing list archive)
State Accepted
Commit bb2eea918be757b899c9bb8beba992281a51f8f0
Delegated to: David Ahern
Headers show
Series Implement new netlink attribute for devlink-port function in iproute2 | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Shay Drori Dec. 11, 2022, 11:58 a.m. UTC
Support port function commands to enable / disable RoCE, this is used to
control the port RoCE device capabilities.

When RoCE is disabled for a function of the port, function cannot create
any RoCE specific resources (e.g GID table).
It also saves system memory utilization. For example disabling RoCE
enable a VF/SF to save 1 Mbytes of system memory per function.

Example of a PCI VF port which supports a port function:

$ devlink port show pci/0000:06:00.0/2
    pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum
    0 vfnum 1
      function:
        hw_addr 00:00:00:00:00:00 roce enabled

$ devlink port function set pci/0000:06:00.0/2 roce disable

$ devlink port show pci/0000:06:00.0/2
    pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum
    0 vfnum 1
      function:
        hw_addr 00:00:00:00:00:00 roce disabled

Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Signed-off-by: Shay Drory <shayd@nvidia.com>
Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
---
 devlink/devlink.c | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 4a5eee7a..66cc0415 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -297,6 +297,7 @@  static void ifname_map_free(struct ifname_map *ifname_map)
 #define DL_OPT_SELFTESTS	BIT(54)
 #define DL_OPT_PORT_FN_RATE_TX_PRIORITY	BIT(55)
 #define DL_OPT_PORT_FN_RATE_TX_WEIGHT	BIT(56)
+#define DL_OPT_PORT_FN_CAPS	BIT(57)
 
 struct dl_opts {
 	uint64_t present; /* flags of present items */
@@ -362,6 +363,7 @@  struct dl_opts {
 	uint32_t linecard_index;
 	const char *linecard_type;
 	bool selftests_opt[DEVLINK_ATTR_SELFTEST_ID_MAX + 1];
+	struct nla_bitfield32 port_fn_caps;
 };
 
 struct dl {
@@ -2116,6 +2118,18 @@  static int dl_argv_parse(struct dl *dl, uint64_t o_required,
 			dl_arg_inc(dl);
 			opts->linecard_type = "";
 			o_found |= DL_OPT_LINECARD_TYPE;
+		} else if (dl_argv_match(dl, "roce") &&
+			   (o_all & DL_OPT_PORT_FN_CAPS)) {
+			bool roce;
+
+			dl_arg_inc(dl);
+			err = dl_argv_bool(dl, &roce);
+			if (err)
+				return err;
+			opts->port_fn_caps.selector |= DEVLINK_PORT_FN_CAP_ROCE;
+			if (roce)
+				opts->port_fn_caps.value |= DEVLINK_PORT_FN_CAP_ROCE;
+			o_found |= DL_OPT_PORT_FN_CAPS;
 		} else {
 			pr_err("Unknown option \"%s\"\n", dl_argv(dl));
 			return -EINVAL;
@@ -2146,6 +2160,10 @@  dl_function_attr_put(struct nlmsghdr *nlh, const struct dl_opts *opts)
 	if (opts->present & DL_OPT_PORT_FUNCTION_STATE)
 		mnl_attr_put_u8(nlh, DEVLINK_PORT_FN_ATTR_STATE,
 				opts->port_fn_state);
+	if (opts->present & DL_OPT_PORT_FN_CAPS)
+		mnl_attr_put(nlh, DEVLINK_PORT_FN_ATTR_CAPS,
+			     sizeof(opts->port_fn_caps), &opts->port_fn_caps);
+
 	mnl_attr_nest_end(nlh, nest);
 }
 
@@ -2336,7 +2354,8 @@  static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
 	if (opts->present & DL_OPT_TRAP_POLICER_BURST)
 		mnl_attr_put_u64(nlh, DEVLINK_ATTR_TRAP_POLICER_BURST,
 				 opts->trap_policer_burst);
-	if (opts->present & (DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE))
+	if (opts->present & (DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE |
+			     DL_OPT_PORT_FN_CAPS))
 		dl_function_attr_put(nlh, opts);
 	if (opts->present & DL_OPT_PORT_FLAVOUR)
 		mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_FLAVOUR, opts->port_flavour);
@@ -4386,6 +4405,7 @@  static void cmd_port_help(void)
 	pr_err("       devlink port split DEV/PORT_INDEX count COUNT\n");
 	pr_err("       devlink port unsplit DEV/PORT_INDEX\n");
 	pr_err("       devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state { active | inactive } ]\n");
+	pr_err("                      [ roce { enable | disable } ]\n");
 	pr_err("       devlink port function rate { help | show | add | del | set }\n");
 	pr_err("       devlink port param set DEV/PORT_INDEX name PARAMETER value VALUE cmode { permanent | driverinit | runtime }\n");
 	pr_err("       devlink port param show [DEV/PORT_INDEX name PARAMETER]\n");
@@ -4499,6 +4519,15 @@  static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
 		print_string(PRINT_ANY, "opstate", " opstate %s",
 			     port_fn_opstate(state));
 	}
+	if (tb[DEVLINK_PORT_FN_ATTR_CAPS]) {
+		struct nla_bitfield32 *port_fn_caps =
+			mnl_attr_get_payload(tb[DEVLINK_PORT_FN_ATTR_CAPS]);
+
+		if (port_fn_caps->selector & DEVLINK_PORT_FN_CAP_ROCE)
+			print_string(PRINT_ANY, "roce", " roce %s",
+				     port_fn_caps->value & DEVLINK_PORT_FN_CAP_ROCE ?
+				     "enable" : "disable");
+	}
 
 	if (!dl->json_output)
 		__pr_out_indent_dec();
@@ -4693,6 +4722,7 @@  static int cmd_port_param_show(struct dl *dl)
 static void cmd_port_function_help(void)
 {
 	pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state STATE ]\n");
+	pr_err("                      [ roce { enable | disable } ]\n");
 	pr_err("       devlink port function rate { help | show | add | del | set }\n");
 }
 
@@ -4706,7 +4736,8 @@  static int cmd_port_function_set(struct dl *dl)
 		return 0;
 	}
 	err = dl_argv_parse(dl, DL_OPT_HANDLEP,
-			    DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE);
+			    DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE |
+			    DL_OPT_PORT_FN_CAPS);
 	if (err)
 		return err;