Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'devlink-finish-file-split-and-get-retire-leftover-c'

Jiri Pirko says:

====================
devlink: finish file split and get retire leftover.c

This patchset finishes a move Jakub started and Moshe continued in the
past. I was planning to do this for a long time, so here it is, finally.

This patchset does not change any behaviour. It just splits leftover.c
into per-object files and do necessary changes, like declaring functions
used from other code, on the way.

The last 3 patches are pushing the rest of the code into appropriate
existing files.
====================

Link: https://lore.kernel.org/r/20230828061657.300667-1-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+9710 -9540
+2 -1
net/devlink/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - obj-y := leftover.o core.o netlink.o netlink_gen.o dev.o health.o 3 + obj-y := core.o netlink.o netlink_gen.o dev.o port.o sb.o dpipe.o \ 4 + resource.o param.o region.o health.o trap.o rate.o linecard.o
+6
net/devlink/core.c
··· 5 5 */ 6 6 7 7 #include <net/genetlink.h> 8 + #define CREATE_TRACE_POINTS 9 + #include <trace/events/devlink.h> 8 10 9 11 #include "devl_internal.h" 12 + 13 + EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg); 14 + EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr); 15 + EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_trap_report); 10 16 11 17 DEFINE_XARRAY_FLAGS(devlinks, XA_FLAGS_ALLOC); 12 18
+27 -1
net/devlink/dev.c
··· 174 174 return -EMSGSIZE; 175 175 } 176 176 177 - void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 177 + static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 178 178 { 179 179 struct sk_buff *msg; 180 180 int err; ··· 228 228 int devlink_nl_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb) 229 229 { 230 230 return devlink_nl_dumpit(msg, cb, devlink_nl_get_dump_one); 231 + } 232 + 233 + void devlink_notify_register(struct devlink *devlink) 234 + { 235 + devlink_notify(devlink, DEVLINK_CMD_NEW); 236 + devlink_linecards_notify_register(devlink); 237 + devlink_ports_notify_register(devlink); 238 + devlink_trap_policers_notify_register(devlink); 239 + devlink_trap_groups_notify_register(devlink); 240 + devlink_traps_notify_register(devlink); 241 + devlink_rates_notify_register(devlink); 242 + devlink_regions_notify_register(devlink); 243 + devlink_params_notify_register(devlink); 244 + } 245 + 246 + void devlink_notify_unregister(struct devlink *devlink) 247 + { 248 + devlink_params_notify_unregister(devlink); 249 + devlink_regions_notify_unregister(devlink); 250 + devlink_rates_notify_unregister(devlink); 251 + devlink_traps_notify_unregister(devlink); 252 + devlink_trap_groups_notify_unregister(devlink); 253 + devlink_trap_policers_notify_unregister(devlink); 254 + devlink_ports_notify_unregister(devlink); 255 + devlink_linecards_notify_unregister(devlink); 256 + devlink_notify(devlink, DEVLINK_CMD_DEL); 231 257 } 232 258 233 259 static void devlink_reload_failed_set(struct devlink *devlink,
+88 -7
net/devlink/devl_internal.h
··· 3 3 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 4 4 */ 5 5 6 + #include <linux/etherdevice.h> 6 7 #include <linux/mutex.h> 7 8 #include <linux/netdevice.h> 8 9 #include <linux/notifier.h> ··· 12 11 #include <linux/xarray.h> 13 12 #include <net/devlink.h> 14 13 #include <net/net_namespace.h> 14 + #include <net/rtnetlink.h> 15 + #include <rdma/ib_verbs.h> 15 16 16 17 #include "netlink_gen.h" 17 18 ··· 121 118 struct netlink_callback *cb, 122 119 int flags); 123 120 124 - extern const struct genl_small_ops devlink_nl_small_ops[40]; 125 - 126 121 struct devlink * 127 122 devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs); 128 - 129 - void devlink_notify_unregister(struct devlink *devlink); 130 - void devlink_notify_register(struct devlink *devlink); 131 123 132 124 int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb, 133 125 devlink_nl_dump_one_func_t *dump_one); ··· 145 147 return 0; 146 148 } 147 149 150 + int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info); 151 + 148 152 /* Notify */ 149 - void devlink_notify(struct devlink *devlink, enum devlink_command cmd); 153 + void devlink_notify_register(struct devlink *devlink); 154 + void devlink_notify_unregister(struct devlink *devlink); 155 + void devlink_ports_notify_register(struct devlink *devlink); 156 + void devlink_ports_notify_unregister(struct devlink *devlink); 157 + void devlink_params_notify_register(struct devlink *devlink); 158 + void devlink_params_notify_unregister(struct devlink *devlink); 159 + void devlink_regions_notify_register(struct devlink *devlink); 160 + void devlink_regions_notify_unregister(struct devlink *devlink); 161 + void devlink_trap_policers_notify_register(struct devlink *devlink); 162 + void devlink_trap_policers_notify_unregister(struct devlink *devlink); 163 + void devlink_trap_groups_notify_register(struct devlink *devlink); 164 + void devlink_trap_groups_notify_unregister(struct devlink *devlink); 165 + void devlink_traps_notify_register(struct devlink *devlink); 166 + void devlink_traps_notify_unregister(struct devlink *devlink); 167 + void devlink_rates_notify_register(struct devlink *devlink); 168 + void devlink_rates_notify_unregister(struct devlink *devlink); 169 + void devlink_linecards_notify_register(struct devlink *devlink); 170 + void devlink_linecards_notify_unregister(struct devlink *devlink); 150 171 151 172 /* Ports */ 173 + #define ASSERT_DEVLINK_PORT_INITIALIZED(devlink_port) \ 174 + WARN_ON_ONCE(!(devlink_port)->initialized) 175 + 176 + struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 177 + unsigned int port_index); 152 178 int devlink_port_netdevice_event(struct notifier_block *nb, 153 179 unsigned long event, void *ptr); 154 - 155 180 struct devlink_port * 156 181 devlink_port_get_from_info(struct devlink *devlink, struct genl_info *info); 157 182 struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, ··· 205 184 int devlink_rate_nodes_check(struct devlink *devlink, u16 mode, 206 185 struct netlink_ext_ack *extack); 207 186 187 + /* Linecards */ 188 + struct devlink_linecard { 189 + struct list_head list; 190 + struct devlink *devlink; 191 + unsigned int index; 192 + const struct devlink_linecard_ops *ops; 193 + void *priv; 194 + enum devlink_linecard_state state; 195 + struct mutex state_lock; /* Protects state */ 196 + const char *type; 197 + struct devlink_linecard_type *types; 198 + unsigned int types_count; 199 + struct devlink *nested_devlink; 200 + }; 201 + 208 202 /* Devlink nl cmds */ 209 203 int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info); 210 204 int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, struct genl_info *info); 211 205 int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, struct genl_info *info); 212 206 int devlink_nl_cmd_flash_update(struct sk_buff *skb, struct genl_info *info); 213 207 int devlink_nl_cmd_selftests_run(struct sk_buff *skb, struct genl_info *info); 208 + int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, struct genl_info *info); 209 + int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, struct genl_info *info); 210 + int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 211 + struct genl_info *info); 212 + int devlink_nl_cmd_port_new_doit(struct sk_buff *skb, struct genl_info *info); 213 + int devlink_nl_cmd_port_del_doit(struct sk_buff *skb, struct genl_info *info); 214 + int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, struct genl_info *info); 215 + int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 216 + struct genl_info *info); 217 + int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 218 + struct genl_info *info); 219 + int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 220 + struct genl_info *info); 221 + int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 222 + struct genl_info *info); 223 + int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, struct genl_info *info); 224 + int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 225 + struct genl_info *info); 226 + int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 227 + struct genl_info *info); 228 + int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 229 + struct genl_info *info); 230 + int devlink_nl_cmd_resource_set(struct sk_buff *skb, struct genl_info *info); 231 + int devlink_nl_cmd_resource_dump(struct sk_buff *skb, struct genl_info *info); 232 + int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, struct genl_info *info); 233 + int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg, 234 + struct netlink_callback *cb); 235 + int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb, 236 + struct genl_info *info); 237 + int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb, 238 + struct genl_info *info); 239 + int devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info); 240 + int devlink_nl_cmd_region_del(struct sk_buff *skb, struct genl_info *info); 241 + int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 242 + struct netlink_callback *cb); 214 243 int devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, 215 244 struct genl_info *info); 216 245 int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, ··· 273 202 struct genl_info *info); 274 203 int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb, 275 204 struct genl_info *info); 205 + int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb, struct genl_info *info); 206 + int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb, 207 + struct genl_info *info); 208 + int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb, 209 + struct genl_info *info); 210 + int devlink_nl_cmd_rate_set_doit(struct sk_buff *skb, struct genl_info *info); 211 + int devlink_nl_cmd_rate_new_doit(struct sk_buff *skb, struct genl_info *info); 212 + int devlink_nl_cmd_rate_del_doit(struct sk_buff *skb, struct genl_info *info); 213 + int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb, 214 + struct genl_info *info);
+917
net/devlink/dpipe.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = { 10 + { 11 + .name = "destination mac", 12 + .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC, 13 + .bitwidth = 48, 14 + }, 15 + }; 16 + 17 + struct devlink_dpipe_header devlink_dpipe_header_ethernet = { 18 + .name = "ethernet", 19 + .id = DEVLINK_DPIPE_HEADER_ETHERNET, 20 + .fields = devlink_dpipe_fields_ethernet, 21 + .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet), 22 + .global = true, 23 + }; 24 + EXPORT_SYMBOL_GPL(devlink_dpipe_header_ethernet); 25 + 26 + static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = { 27 + { 28 + .name = "destination ip", 29 + .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP, 30 + .bitwidth = 32, 31 + }, 32 + }; 33 + 34 + struct devlink_dpipe_header devlink_dpipe_header_ipv4 = { 35 + .name = "ipv4", 36 + .id = DEVLINK_DPIPE_HEADER_IPV4, 37 + .fields = devlink_dpipe_fields_ipv4, 38 + .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4), 39 + .global = true, 40 + }; 41 + EXPORT_SYMBOL_GPL(devlink_dpipe_header_ipv4); 42 + 43 + static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = { 44 + { 45 + .name = "destination ip", 46 + .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP, 47 + .bitwidth = 128, 48 + }, 49 + }; 50 + 51 + struct devlink_dpipe_header devlink_dpipe_header_ipv6 = { 52 + .name = "ipv6", 53 + .id = DEVLINK_DPIPE_HEADER_IPV6, 54 + .fields = devlink_dpipe_fields_ipv6, 55 + .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6), 56 + .global = true, 57 + }; 58 + EXPORT_SYMBOL_GPL(devlink_dpipe_header_ipv6); 59 + 60 + int devlink_dpipe_match_put(struct sk_buff *skb, 61 + struct devlink_dpipe_match *match) 62 + { 63 + struct devlink_dpipe_header *header = match->header; 64 + struct devlink_dpipe_field *field = &header->fields[match->field_id]; 65 + struct nlattr *match_attr; 66 + 67 + match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH); 68 + if (!match_attr) 69 + return -EMSGSIZE; 70 + 71 + if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 72 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 73 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 74 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 75 + nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 76 + goto nla_put_failure; 77 + 78 + nla_nest_end(skb, match_attr); 79 + return 0; 80 + 81 + nla_put_failure: 82 + nla_nest_cancel(skb, match_attr); 83 + return -EMSGSIZE; 84 + } 85 + EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 86 + 87 + static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 88 + struct sk_buff *skb) 89 + { 90 + struct nlattr *matches_attr; 91 + 92 + matches_attr = nla_nest_start_noflag(skb, 93 + DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 94 + if (!matches_attr) 95 + return -EMSGSIZE; 96 + 97 + if (table->table_ops->matches_dump(table->priv, skb)) 98 + goto nla_put_failure; 99 + 100 + nla_nest_end(skb, matches_attr); 101 + return 0; 102 + 103 + nla_put_failure: 104 + nla_nest_cancel(skb, matches_attr); 105 + return -EMSGSIZE; 106 + } 107 + 108 + int devlink_dpipe_action_put(struct sk_buff *skb, 109 + struct devlink_dpipe_action *action) 110 + { 111 + struct devlink_dpipe_header *header = action->header; 112 + struct devlink_dpipe_field *field = &header->fields[action->field_id]; 113 + struct nlattr *action_attr; 114 + 115 + action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION); 116 + if (!action_attr) 117 + return -EMSGSIZE; 118 + 119 + if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 120 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 121 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 122 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 123 + nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 124 + goto nla_put_failure; 125 + 126 + nla_nest_end(skb, action_attr); 127 + return 0; 128 + 129 + nla_put_failure: 130 + nla_nest_cancel(skb, action_attr); 131 + return -EMSGSIZE; 132 + } 133 + EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 134 + 135 + static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 136 + struct sk_buff *skb) 137 + { 138 + struct nlattr *actions_attr; 139 + 140 + actions_attr = nla_nest_start_noflag(skb, 141 + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 142 + if (!actions_attr) 143 + return -EMSGSIZE; 144 + 145 + if (table->table_ops->actions_dump(table->priv, skb)) 146 + goto nla_put_failure; 147 + 148 + nla_nest_end(skb, actions_attr); 149 + return 0; 150 + 151 + nla_put_failure: 152 + nla_nest_cancel(skb, actions_attr); 153 + return -EMSGSIZE; 154 + } 155 + 156 + static int devlink_dpipe_table_put(struct sk_buff *skb, 157 + struct devlink_dpipe_table *table) 158 + { 159 + struct nlattr *table_attr; 160 + u64 table_size; 161 + 162 + table_size = table->table_ops->size_get(table->priv); 163 + table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE); 164 + if (!table_attr) 165 + return -EMSGSIZE; 166 + 167 + if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 168 + nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 169 + DEVLINK_ATTR_PAD)) 170 + goto nla_put_failure; 171 + if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 172 + table->counters_enabled)) 173 + goto nla_put_failure; 174 + 175 + if (table->resource_valid) { 176 + if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 177 + table->resource_id, DEVLINK_ATTR_PAD) || 178 + nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 179 + table->resource_units, DEVLINK_ATTR_PAD)) 180 + goto nla_put_failure; 181 + } 182 + if (devlink_dpipe_matches_put(table, skb)) 183 + goto nla_put_failure; 184 + 185 + if (devlink_dpipe_actions_put(table, skb)) 186 + goto nla_put_failure; 187 + 188 + nla_nest_end(skb, table_attr); 189 + return 0; 190 + 191 + nla_put_failure: 192 + nla_nest_cancel(skb, table_attr); 193 + return -EMSGSIZE; 194 + } 195 + 196 + static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 197 + struct genl_info *info) 198 + { 199 + int err; 200 + 201 + if (*pskb) { 202 + err = genlmsg_reply(*pskb, info); 203 + if (err) 204 + return err; 205 + } 206 + *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 207 + if (!*pskb) 208 + return -ENOMEM; 209 + return 0; 210 + } 211 + 212 + static int devlink_dpipe_tables_fill(struct genl_info *info, 213 + enum devlink_command cmd, int flags, 214 + struct list_head *dpipe_tables, 215 + const char *table_name) 216 + { 217 + struct devlink *devlink = info->user_ptr[0]; 218 + struct devlink_dpipe_table *table; 219 + struct nlattr *tables_attr; 220 + struct sk_buff *skb = NULL; 221 + struct nlmsghdr *nlh; 222 + bool incomplete; 223 + void *hdr; 224 + int i; 225 + int err; 226 + 227 + table = list_first_entry(dpipe_tables, 228 + struct devlink_dpipe_table, list); 229 + start_again: 230 + err = devlink_dpipe_send_and_alloc_skb(&skb, info); 231 + if (err) 232 + return err; 233 + 234 + hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 235 + &devlink_nl_family, NLM_F_MULTI, cmd); 236 + if (!hdr) { 237 + nlmsg_free(skb); 238 + return -EMSGSIZE; 239 + } 240 + 241 + if (devlink_nl_put_handle(skb, devlink)) 242 + goto nla_put_failure; 243 + tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES); 244 + if (!tables_attr) 245 + goto nla_put_failure; 246 + 247 + i = 0; 248 + incomplete = false; 249 + list_for_each_entry_from(table, dpipe_tables, list) { 250 + if (!table_name) { 251 + err = devlink_dpipe_table_put(skb, table); 252 + if (err) { 253 + if (!i) 254 + goto err_table_put; 255 + incomplete = true; 256 + break; 257 + } 258 + } else { 259 + if (!strcmp(table->name, table_name)) { 260 + err = devlink_dpipe_table_put(skb, table); 261 + if (err) 262 + break; 263 + } 264 + } 265 + i++; 266 + } 267 + 268 + nla_nest_end(skb, tables_attr); 269 + genlmsg_end(skb, hdr); 270 + if (incomplete) 271 + goto start_again; 272 + 273 + send_done: 274 + nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 275 + NLMSG_DONE, 0, flags | NLM_F_MULTI); 276 + if (!nlh) { 277 + err = devlink_dpipe_send_and_alloc_skb(&skb, info); 278 + if (err) 279 + return err; 280 + goto send_done; 281 + } 282 + 283 + return genlmsg_reply(skb, info); 284 + 285 + nla_put_failure: 286 + err = -EMSGSIZE; 287 + err_table_put: 288 + nlmsg_free(skb); 289 + return err; 290 + } 291 + 292 + int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, struct genl_info *info) 293 + { 294 + struct devlink *devlink = info->user_ptr[0]; 295 + const char *table_name = NULL; 296 + 297 + if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 298 + table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 299 + 300 + return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 301 + &devlink->dpipe_table_list, 302 + table_name); 303 + } 304 + 305 + static int devlink_dpipe_value_put(struct sk_buff *skb, 306 + struct devlink_dpipe_value *value) 307 + { 308 + if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 309 + value->value_size, value->value)) 310 + return -EMSGSIZE; 311 + if (value->mask) 312 + if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 313 + value->value_size, value->mask)) 314 + return -EMSGSIZE; 315 + if (value->mapping_valid) 316 + if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 317 + value->mapping_value)) 318 + return -EMSGSIZE; 319 + return 0; 320 + } 321 + 322 + static int devlink_dpipe_action_value_put(struct sk_buff *skb, 323 + struct devlink_dpipe_value *value) 324 + { 325 + if (!value->action) 326 + return -EINVAL; 327 + if (devlink_dpipe_action_put(skb, value->action)) 328 + return -EMSGSIZE; 329 + if (devlink_dpipe_value_put(skb, value)) 330 + return -EMSGSIZE; 331 + return 0; 332 + } 333 + 334 + static int devlink_dpipe_action_values_put(struct sk_buff *skb, 335 + struct devlink_dpipe_value *values, 336 + unsigned int values_count) 337 + { 338 + struct nlattr *action_attr; 339 + int i; 340 + int err; 341 + 342 + for (i = 0; i < values_count; i++) { 343 + action_attr = nla_nest_start_noflag(skb, 344 + DEVLINK_ATTR_DPIPE_ACTION_VALUE); 345 + if (!action_attr) 346 + return -EMSGSIZE; 347 + err = devlink_dpipe_action_value_put(skb, &values[i]); 348 + if (err) 349 + goto err_action_value_put; 350 + nla_nest_end(skb, action_attr); 351 + } 352 + return 0; 353 + 354 + err_action_value_put: 355 + nla_nest_cancel(skb, action_attr); 356 + return err; 357 + } 358 + 359 + static int devlink_dpipe_match_value_put(struct sk_buff *skb, 360 + struct devlink_dpipe_value *value) 361 + { 362 + if (!value->match) 363 + return -EINVAL; 364 + if (devlink_dpipe_match_put(skb, value->match)) 365 + return -EMSGSIZE; 366 + if (devlink_dpipe_value_put(skb, value)) 367 + return -EMSGSIZE; 368 + return 0; 369 + } 370 + 371 + static int devlink_dpipe_match_values_put(struct sk_buff *skb, 372 + struct devlink_dpipe_value *values, 373 + unsigned int values_count) 374 + { 375 + struct nlattr *match_attr; 376 + int i; 377 + int err; 378 + 379 + for (i = 0; i < values_count; i++) { 380 + match_attr = nla_nest_start_noflag(skb, 381 + DEVLINK_ATTR_DPIPE_MATCH_VALUE); 382 + if (!match_attr) 383 + return -EMSGSIZE; 384 + err = devlink_dpipe_match_value_put(skb, &values[i]); 385 + if (err) 386 + goto err_match_value_put; 387 + nla_nest_end(skb, match_attr); 388 + } 389 + return 0; 390 + 391 + err_match_value_put: 392 + nla_nest_cancel(skb, match_attr); 393 + return err; 394 + } 395 + 396 + static int devlink_dpipe_entry_put(struct sk_buff *skb, 397 + struct devlink_dpipe_entry *entry) 398 + { 399 + struct nlattr *entry_attr, *matches_attr, *actions_attr; 400 + int err; 401 + 402 + entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY); 403 + if (!entry_attr) 404 + return -EMSGSIZE; 405 + 406 + if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 407 + DEVLINK_ATTR_PAD)) 408 + goto nla_put_failure; 409 + if (entry->counter_valid) 410 + if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 411 + entry->counter, DEVLINK_ATTR_PAD)) 412 + goto nla_put_failure; 413 + 414 + matches_attr = nla_nest_start_noflag(skb, 415 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 416 + if (!matches_attr) 417 + goto nla_put_failure; 418 + 419 + err = devlink_dpipe_match_values_put(skb, entry->match_values, 420 + entry->match_values_count); 421 + if (err) { 422 + nla_nest_cancel(skb, matches_attr); 423 + goto err_match_values_put; 424 + } 425 + nla_nest_end(skb, matches_attr); 426 + 427 + actions_attr = nla_nest_start_noflag(skb, 428 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 429 + if (!actions_attr) 430 + goto nla_put_failure; 431 + 432 + err = devlink_dpipe_action_values_put(skb, entry->action_values, 433 + entry->action_values_count); 434 + if (err) { 435 + nla_nest_cancel(skb, actions_attr); 436 + goto err_action_values_put; 437 + } 438 + nla_nest_end(skb, actions_attr); 439 + 440 + nla_nest_end(skb, entry_attr); 441 + return 0; 442 + 443 + nla_put_failure: 444 + err = -EMSGSIZE; 445 + err_match_values_put: 446 + err_action_values_put: 447 + nla_nest_cancel(skb, entry_attr); 448 + return err; 449 + } 450 + 451 + static struct devlink_dpipe_table * 452 + devlink_dpipe_table_find(struct list_head *dpipe_tables, 453 + const char *table_name, struct devlink *devlink) 454 + { 455 + struct devlink_dpipe_table *table; 456 + 457 + list_for_each_entry_rcu(table, dpipe_tables, list, 458 + lockdep_is_held(&devlink->lock)) { 459 + if (!strcmp(table->name, table_name)) 460 + return table; 461 + } 462 + return NULL; 463 + } 464 + 465 + int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 466 + { 467 + struct devlink *devlink; 468 + int err; 469 + 470 + err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 471 + dump_ctx->info); 472 + if (err) 473 + return err; 474 + 475 + dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 476 + dump_ctx->info->snd_portid, 477 + dump_ctx->info->snd_seq, 478 + &devlink_nl_family, NLM_F_MULTI, 479 + dump_ctx->cmd); 480 + if (!dump_ctx->hdr) 481 + goto nla_put_failure; 482 + 483 + devlink = dump_ctx->info->user_ptr[0]; 484 + if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 485 + goto nla_put_failure; 486 + dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb, 487 + DEVLINK_ATTR_DPIPE_ENTRIES); 488 + if (!dump_ctx->nest) 489 + goto nla_put_failure; 490 + return 0; 491 + 492 + nla_put_failure: 493 + nlmsg_free(dump_ctx->skb); 494 + return -EMSGSIZE; 495 + } 496 + EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 497 + 498 + int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 499 + struct devlink_dpipe_entry *entry) 500 + { 501 + return devlink_dpipe_entry_put(dump_ctx->skb, entry); 502 + } 503 + EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 504 + 505 + int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 506 + { 507 + nla_nest_end(dump_ctx->skb, dump_ctx->nest); 508 + genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 509 + return 0; 510 + } 511 + EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 512 + 513 + void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 514 + 515 + { 516 + unsigned int value_count, value_index; 517 + struct devlink_dpipe_value *value; 518 + 519 + value = entry->action_values; 520 + value_count = entry->action_values_count; 521 + for (value_index = 0; value_index < value_count; value_index++) { 522 + kfree(value[value_index].value); 523 + kfree(value[value_index].mask); 524 + } 525 + 526 + value = entry->match_values; 527 + value_count = entry->match_values_count; 528 + for (value_index = 0; value_index < value_count; value_index++) { 529 + kfree(value[value_index].value); 530 + kfree(value[value_index].mask); 531 + } 532 + } 533 + EXPORT_SYMBOL_GPL(devlink_dpipe_entry_clear); 534 + 535 + static int devlink_dpipe_entries_fill(struct genl_info *info, 536 + enum devlink_command cmd, int flags, 537 + struct devlink_dpipe_table *table) 538 + { 539 + struct devlink_dpipe_dump_ctx dump_ctx; 540 + struct nlmsghdr *nlh; 541 + int err; 542 + 543 + dump_ctx.skb = NULL; 544 + dump_ctx.cmd = cmd; 545 + dump_ctx.info = info; 546 + 547 + err = table->table_ops->entries_dump(table->priv, 548 + table->counters_enabled, 549 + &dump_ctx); 550 + if (err) 551 + return err; 552 + 553 + send_done: 554 + nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 555 + NLMSG_DONE, 0, flags | NLM_F_MULTI); 556 + if (!nlh) { 557 + err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 558 + if (err) 559 + return err; 560 + goto send_done; 561 + } 562 + return genlmsg_reply(dump_ctx.skb, info); 563 + } 564 + 565 + int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 566 + struct genl_info *info) 567 + { 568 + struct devlink *devlink = info->user_ptr[0]; 569 + struct devlink_dpipe_table *table; 570 + const char *table_name; 571 + 572 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME)) 573 + return -EINVAL; 574 + 575 + table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 576 + table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 577 + table_name, devlink); 578 + if (!table) 579 + return -EINVAL; 580 + 581 + if (!table->table_ops->entries_dump) 582 + return -EINVAL; 583 + 584 + return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 585 + 0, table); 586 + } 587 + 588 + static int devlink_dpipe_fields_put(struct sk_buff *skb, 589 + const struct devlink_dpipe_header *header) 590 + { 591 + struct devlink_dpipe_field *field; 592 + struct nlattr *field_attr; 593 + int i; 594 + 595 + for (i = 0; i < header->fields_count; i++) { 596 + field = &header->fields[i]; 597 + field_attr = nla_nest_start_noflag(skb, 598 + DEVLINK_ATTR_DPIPE_FIELD); 599 + if (!field_attr) 600 + return -EMSGSIZE; 601 + if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 602 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 603 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 604 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 605 + goto nla_put_failure; 606 + nla_nest_end(skb, field_attr); 607 + } 608 + return 0; 609 + 610 + nla_put_failure: 611 + nla_nest_cancel(skb, field_attr); 612 + return -EMSGSIZE; 613 + } 614 + 615 + static int devlink_dpipe_header_put(struct sk_buff *skb, 616 + struct devlink_dpipe_header *header) 617 + { 618 + struct nlattr *fields_attr, *header_attr; 619 + int err; 620 + 621 + header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER); 622 + if (!header_attr) 623 + return -EMSGSIZE; 624 + 625 + if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 626 + nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 627 + nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 628 + goto nla_put_failure; 629 + 630 + fields_attr = nla_nest_start_noflag(skb, 631 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 632 + if (!fields_attr) 633 + goto nla_put_failure; 634 + 635 + err = devlink_dpipe_fields_put(skb, header); 636 + if (err) { 637 + nla_nest_cancel(skb, fields_attr); 638 + goto nla_put_failure; 639 + } 640 + nla_nest_end(skb, fields_attr); 641 + nla_nest_end(skb, header_attr); 642 + return 0; 643 + 644 + nla_put_failure: 645 + err = -EMSGSIZE; 646 + nla_nest_cancel(skb, header_attr); 647 + return err; 648 + } 649 + 650 + static int devlink_dpipe_headers_fill(struct genl_info *info, 651 + enum devlink_command cmd, int flags, 652 + struct devlink_dpipe_headers * 653 + dpipe_headers) 654 + { 655 + struct devlink *devlink = info->user_ptr[0]; 656 + struct nlattr *headers_attr; 657 + struct sk_buff *skb = NULL; 658 + struct nlmsghdr *nlh; 659 + void *hdr; 660 + int i, j; 661 + int err; 662 + 663 + i = 0; 664 + start_again: 665 + err = devlink_dpipe_send_and_alloc_skb(&skb, info); 666 + if (err) 667 + return err; 668 + 669 + hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 670 + &devlink_nl_family, NLM_F_MULTI, cmd); 671 + if (!hdr) { 672 + nlmsg_free(skb); 673 + return -EMSGSIZE; 674 + } 675 + 676 + if (devlink_nl_put_handle(skb, devlink)) 677 + goto nla_put_failure; 678 + headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS); 679 + if (!headers_attr) 680 + goto nla_put_failure; 681 + 682 + j = 0; 683 + for (; i < dpipe_headers->headers_count; i++) { 684 + err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 685 + if (err) { 686 + if (!j) 687 + goto err_table_put; 688 + break; 689 + } 690 + j++; 691 + } 692 + nla_nest_end(skb, headers_attr); 693 + genlmsg_end(skb, hdr); 694 + if (i != dpipe_headers->headers_count) 695 + goto start_again; 696 + 697 + send_done: 698 + nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 699 + NLMSG_DONE, 0, flags | NLM_F_MULTI); 700 + if (!nlh) { 701 + err = devlink_dpipe_send_and_alloc_skb(&skb, info); 702 + if (err) 703 + return err; 704 + goto send_done; 705 + } 706 + return genlmsg_reply(skb, info); 707 + 708 + nla_put_failure: 709 + err = -EMSGSIZE; 710 + err_table_put: 711 + nlmsg_free(skb); 712 + return err; 713 + } 714 + 715 + int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 716 + struct genl_info *info) 717 + { 718 + struct devlink *devlink = info->user_ptr[0]; 719 + 720 + if (!devlink->dpipe_headers) 721 + return -EOPNOTSUPP; 722 + return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 723 + 0, devlink->dpipe_headers); 724 + } 725 + 726 + static int devlink_dpipe_table_counters_set(struct devlink *devlink, 727 + const char *table_name, 728 + bool enable) 729 + { 730 + struct devlink_dpipe_table *table; 731 + 732 + table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 733 + table_name, devlink); 734 + if (!table) 735 + return -EINVAL; 736 + 737 + if (table->counter_control_extern) 738 + return -EOPNOTSUPP; 739 + 740 + if (!(table->counters_enabled ^ enable)) 741 + return 0; 742 + 743 + table->counters_enabled = enable; 744 + if (table->table_ops->counters_set_update) 745 + table->table_ops->counters_set_update(table->priv, enable); 746 + return 0; 747 + } 748 + 749 + int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 750 + struct genl_info *info) 751 + { 752 + struct devlink *devlink = info->user_ptr[0]; 753 + const char *table_name; 754 + bool counters_enable; 755 + 756 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME) || 757 + GENL_REQ_ATTR_CHECK(info, 758 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED)) 759 + return -EINVAL; 760 + 761 + table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 762 + counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 763 + 764 + return devlink_dpipe_table_counters_set(devlink, table_name, 765 + counters_enable); 766 + } 767 + 768 + /** 769 + * devl_dpipe_headers_register - register dpipe headers 770 + * 771 + * @devlink: devlink 772 + * @dpipe_headers: dpipe header array 773 + * 774 + * Register the headers supported by hardware. 775 + */ 776 + void devl_dpipe_headers_register(struct devlink *devlink, 777 + struct devlink_dpipe_headers *dpipe_headers) 778 + { 779 + lockdep_assert_held(&devlink->lock); 780 + 781 + devlink->dpipe_headers = dpipe_headers; 782 + } 783 + EXPORT_SYMBOL_GPL(devl_dpipe_headers_register); 784 + 785 + /** 786 + * devl_dpipe_headers_unregister - unregister dpipe headers 787 + * 788 + * @devlink: devlink 789 + * 790 + * Unregister the headers supported by hardware. 791 + */ 792 + void devl_dpipe_headers_unregister(struct devlink *devlink) 793 + { 794 + lockdep_assert_held(&devlink->lock); 795 + 796 + devlink->dpipe_headers = NULL; 797 + } 798 + EXPORT_SYMBOL_GPL(devl_dpipe_headers_unregister); 799 + 800 + /** 801 + * devlink_dpipe_table_counter_enabled - check if counter allocation 802 + * required 803 + * @devlink: devlink 804 + * @table_name: tables name 805 + * 806 + * Used by driver to check if counter allocation is required. 807 + * After counter allocation is turned on the table entries 808 + * are updated to include counter statistics. 809 + * 810 + * After that point on the driver must respect the counter 811 + * state so that each entry added to the table is added 812 + * with a counter. 813 + */ 814 + bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 815 + const char *table_name) 816 + { 817 + struct devlink_dpipe_table *table; 818 + bool enabled; 819 + 820 + rcu_read_lock(); 821 + table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 822 + table_name, devlink); 823 + enabled = false; 824 + if (table) 825 + enabled = table->counters_enabled; 826 + rcu_read_unlock(); 827 + return enabled; 828 + } 829 + EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 830 + 831 + /** 832 + * devl_dpipe_table_register - register dpipe table 833 + * 834 + * @devlink: devlink 835 + * @table_name: table name 836 + * @table_ops: table ops 837 + * @priv: priv 838 + * @counter_control_extern: external control for counters 839 + */ 840 + int devl_dpipe_table_register(struct devlink *devlink, 841 + const char *table_name, 842 + struct devlink_dpipe_table_ops *table_ops, 843 + void *priv, bool counter_control_extern) 844 + { 845 + struct devlink_dpipe_table *table; 846 + 847 + lockdep_assert_held(&devlink->lock); 848 + 849 + if (WARN_ON(!table_ops->size_get)) 850 + return -EINVAL; 851 + 852 + if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name, 853 + devlink)) 854 + return -EEXIST; 855 + 856 + table = kzalloc(sizeof(*table), GFP_KERNEL); 857 + if (!table) 858 + return -ENOMEM; 859 + 860 + table->name = table_name; 861 + table->table_ops = table_ops; 862 + table->priv = priv; 863 + table->counter_control_extern = counter_control_extern; 864 + 865 + list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 866 + 867 + return 0; 868 + } 869 + EXPORT_SYMBOL_GPL(devl_dpipe_table_register); 870 + 871 + /** 872 + * devl_dpipe_table_unregister - unregister dpipe table 873 + * 874 + * @devlink: devlink 875 + * @table_name: table name 876 + */ 877 + void devl_dpipe_table_unregister(struct devlink *devlink, 878 + const char *table_name) 879 + { 880 + struct devlink_dpipe_table *table; 881 + 882 + lockdep_assert_held(&devlink->lock); 883 + 884 + table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 885 + table_name, devlink); 886 + if (!table) 887 + return; 888 + list_del_rcu(&table->list); 889 + kfree_rcu(table, rcu); 890 + } 891 + EXPORT_SYMBOL_GPL(devl_dpipe_table_unregister); 892 + 893 + /** 894 + * devl_dpipe_table_resource_set - set the resource id 895 + * 896 + * @devlink: devlink 897 + * @table_name: table name 898 + * @resource_id: resource id 899 + * @resource_units: number of resource's units consumed per table's entry 900 + */ 901 + int devl_dpipe_table_resource_set(struct devlink *devlink, 902 + const char *table_name, u64 resource_id, 903 + u64 resource_units) 904 + { 905 + struct devlink_dpipe_table *table; 906 + 907 + table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 908 + table_name, devlink); 909 + if (!table) 910 + return -EINVAL; 911 + 912 + table->resource_id = resource_id; 913 + table->resource_units = resource_units; 914 + table->resource_valid = true; 915 + return 0; 916 + } 917 + EXPORT_SYMBOL_GPL(devl_dpipe_table_resource_set);
-9531
net/devlink/leftover.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * net/core/devlink.c - Network physical/parent device Netlink interface 4 - * 5 - * Heavily inspired by net/wireless/ 6 - * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 7 - * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 8 - */ 9 - 10 - #include <linux/etherdevice.h> 11 - #include <linux/kernel.h> 12 - #include <linux/module.h> 13 - #include <linux/types.h> 14 - #include <linux/slab.h> 15 - #include <linux/gfp.h> 16 - #include <linux/device.h> 17 - #include <linux/list.h> 18 - #include <linux/netdevice.h> 19 - #include <linux/spinlock.h> 20 - #include <linux/refcount.h> 21 - #include <linux/workqueue.h> 22 - #include <linux/u64_stats_sync.h> 23 - #include <linux/timekeeping.h> 24 - #include <rdma/ib_verbs.h> 25 - #include <net/netlink.h> 26 - #include <net/genetlink.h> 27 - #include <net/rtnetlink.h> 28 - #include <net/net_namespace.h> 29 - #include <net/sock.h> 30 - #include <net/devlink.h> 31 - #define CREATE_TRACE_POINTS 32 - #include <trace/events/devlink.h> 33 - 34 - #include "devl_internal.h" 35 - 36 - struct devlink_linecard { 37 - struct list_head list; 38 - struct devlink *devlink; 39 - unsigned int index; 40 - const struct devlink_linecard_ops *ops; 41 - void *priv; 42 - enum devlink_linecard_state state; 43 - struct mutex state_lock; /* Protects state */ 44 - const char *type; 45 - struct devlink_linecard_type *types; 46 - unsigned int types_count; 47 - struct devlink *nested_devlink; 48 - }; 49 - 50 - /** 51 - * struct devlink_resource - devlink resource 52 - * @name: name of the resource 53 - * @id: id, per devlink instance 54 - * @size: size of the resource 55 - * @size_new: updated size of the resource, reload is needed 56 - * @size_valid: valid in case the total size of the resource is valid 57 - * including its children 58 - * @parent: parent resource 59 - * @size_params: size parameters 60 - * @list: parent list 61 - * @resource_list: list of child resources 62 - * @occ_get: occupancy getter callback 63 - * @occ_get_priv: occupancy getter callback priv 64 - */ 65 - struct devlink_resource { 66 - const char *name; 67 - u64 id; 68 - u64 size; 69 - u64 size_new; 70 - bool size_valid; 71 - struct devlink_resource *parent; 72 - struct devlink_resource_size_params size_params; 73 - struct list_head list; 74 - struct list_head resource_list; 75 - devlink_resource_occ_get_t *occ_get; 76 - void *occ_get_priv; 77 - }; 78 - 79 - static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = { 80 - { 81 - .name = "destination mac", 82 - .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC, 83 - .bitwidth = 48, 84 - }, 85 - }; 86 - 87 - struct devlink_dpipe_header devlink_dpipe_header_ethernet = { 88 - .name = "ethernet", 89 - .id = DEVLINK_DPIPE_HEADER_ETHERNET, 90 - .fields = devlink_dpipe_fields_ethernet, 91 - .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet), 92 - .global = true, 93 - }; 94 - EXPORT_SYMBOL_GPL(devlink_dpipe_header_ethernet); 95 - 96 - static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = { 97 - { 98 - .name = "destination ip", 99 - .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP, 100 - .bitwidth = 32, 101 - }, 102 - }; 103 - 104 - struct devlink_dpipe_header devlink_dpipe_header_ipv4 = { 105 - .name = "ipv4", 106 - .id = DEVLINK_DPIPE_HEADER_IPV4, 107 - .fields = devlink_dpipe_fields_ipv4, 108 - .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4), 109 - .global = true, 110 - }; 111 - EXPORT_SYMBOL_GPL(devlink_dpipe_header_ipv4); 112 - 113 - static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = { 114 - { 115 - .name = "destination ip", 116 - .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP, 117 - .bitwidth = 128, 118 - }, 119 - }; 120 - 121 - struct devlink_dpipe_header devlink_dpipe_header_ipv6 = { 122 - .name = "ipv6", 123 - .id = DEVLINK_DPIPE_HEADER_IPV6, 124 - .fields = devlink_dpipe_fields_ipv6, 125 - .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6), 126 - .global = true, 127 - }; 128 - EXPORT_SYMBOL_GPL(devlink_dpipe_header_ipv6); 129 - 130 - EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg); 131 - EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr); 132 - EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_trap_report); 133 - 134 - #define DEVLINK_PORT_FN_CAPS_VALID_MASK \ 135 - (_BITUL(__DEVLINK_PORT_FN_ATTR_CAPS_MAX) - 1) 136 - 137 - static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = { 138 - [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY }, 139 - [DEVLINK_PORT_FN_ATTR_STATE] = 140 - NLA_POLICY_RANGE(NLA_U8, DEVLINK_PORT_FN_STATE_INACTIVE, 141 - DEVLINK_PORT_FN_STATE_ACTIVE), 142 - [DEVLINK_PORT_FN_ATTR_CAPS] = 143 - NLA_POLICY_BITFIELD32(DEVLINK_PORT_FN_CAPS_VALID_MASK), 144 - }; 145 - 146 - #define ASSERT_DEVLINK_PORT_REGISTERED(devlink_port) \ 147 - WARN_ON_ONCE(!(devlink_port)->registered) 148 - #define ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port) \ 149 - WARN_ON_ONCE((devlink_port)->registered) 150 - #define ASSERT_DEVLINK_PORT_INITIALIZED(devlink_port) \ 151 - WARN_ON_ONCE(!(devlink_port)->initialized) 152 - 153 - static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 154 - unsigned int port_index) 155 - { 156 - return xa_load(&devlink->ports, port_index); 157 - } 158 - 159 - struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, 160 - struct nlattr **attrs) 161 - { 162 - if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 163 - u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 164 - struct devlink_port *devlink_port; 165 - 166 - devlink_port = devlink_port_get_by_index(devlink, port_index); 167 - if (!devlink_port) 168 - return ERR_PTR(-ENODEV); 169 - return devlink_port; 170 - } 171 - return ERR_PTR(-EINVAL); 172 - } 173 - 174 - struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, 175 - struct genl_info *info) 176 - { 177 - return devlink_port_get_from_attrs(devlink, info->attrs); 178 - } 179 - 180 - static inline bool 181 - devlink_rate_is_leaf(struct devlink_rate *devlink_rate) 182 - { 183 - return devlink_rate->type == DEVLINK_RATE_TYPE_LEAF; 184 - } 185 - 186 - static inline bool 187 - devlink_rate_is_node(struct devlink_rate *devlink_rate) 188 - { 189 - return devlink_rate->type == DEVLINK_RATE_TYPE_NODE; 190 - } 191 - 192 - static struct devlink_rate * 193 - devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info) 194 - { 195 - struct devlink_rate *devlink_rate; 196 - struct devlink_port *devlink_port; 197 - 198 - devlink_port = devlink_port_get_from_attrs(devlink, info->attrs); 199 - if (IS_ERR(devlink_port)) 200 - return ERR_CAST(devlink_port); 201 - devlink_rate = devlink_port->devlink_rate; 202 - return devlink_rate ?: ERR_PTR(-ENODEV); 203 - } 204 - 205 - static struct devlink_rate * 206 - devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name) 207 - { 208 - static struct devlink_rate *devlink_rate; 209 - 210 - list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 211 - if (devlink_rate_is_node(devlink_rate) && 212 - !strcmp(node_name, devlink_rate->name)) 213 - return devlink_rate; 214 - } 215 - return ERR_PTR(-ENODEV); 216 - } 217 - 218 - static struct devlink_rate * 219 - devlink_rate_node_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) 220 - { 221 - const char *rate_node_name; 222 - size_t len; 223 - 224 - if (!attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 225 - return ERR_PTR(-EINVAL); 226 - rate_node_name = nla_data(attrs[DEVLINK_ATTR_RATE_NODE_NAME]); 227 - len = strlen(rate_node_name); 228 - /* Name cannot be empty or decimal number */ 229 - if (!len || strspn(rate_node_name, "0123456789") == len) 230 - return ERR_PTR(-EINVAL); 231 - 232 - return devlink_rate_node_get_by_name(devlink, rate_node_name); 233 - } 234 - 235 - static struct devlink_rate * 236 - devlink_rate_node_get_from_info(struct devlink *devlink, struct genl_info *info) 237 - { 238 - return devlink_rate_node_get_from_attrs(devlink, info->attrs); 239 - } 240 - 241 - static struct devlink_rate * 242 - devlink_rate_get_from_info(struct devlink *devlink, struct genl_info *info) 243 - { 244 - struct nlattr **attrs = info->attrs; 245 - 246 - if (attrs[DEVLINK_ATTR_PORT_INDEX]) 247 - return devlink_rate_leaf_get_from_info(devlink, info); 248 - else if (attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 249 - return devlink_rate_node_get_from_info(devlink, info); 250 - else 251 - return ERR_PTR(-EINVAL); 252 - } 253 - 254 - static struct devlink_linecard * 255 - devlink_linecard_get_by_index(struct devlink *devlink, 256 - unsigned int linecard_index) 257 - { 258 - struct devlink_linecard *devlink_linecard; 259 - 260 - list_for_each_entry(devlink_linecard, &devlink->linecard_list, list) { 261 - if (devlink_linecard->index == linecard_index) 262 - return devlink_linecard; 263 - } 264 - return NULL; 265 - } 266 - 267 - static bool devlink_linecard_index_exists(struct devlink *devlink, 268 - unsigned int linecard_index) 269 - { 270 - return devlink_linecard_get_by_index(devlink, linecard_index); 271 - } 272 - 273 - static struct devlink_linecard * 274 - devlink_linecard_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) 275 - { 276 - if (attrs[DEVLINK_ATTR_LINECARD_INDEX]) { 277 - u32 linecard_index = nla_get_u32(attrs[DEVLINK_ATTR_LINECARD_INDEX]); 278 - struct devlink_linecard *linecard; 279 - 280 - linecard = devlink_linecard_get_by_index(devlink, linecard_index); 281 - if (!linecard) 282 - return ERR_PTR(-ENODEV); 283 - return linecard; 284 - } 285 - return ERR_PTR(-EINVAL); 286 - } 287 - 288 - static struct devlink_linecard * 289 - devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info) 290 - { 291 - return devlink_linecard_get_from_attrs(devlink, info->attrs); 292 - } 293 - 294 - struct devlink_sb { 295 - struct list_head list; 296 - unsigned int index; 297 - u32 size; 298 - u16 ingress_pools_count; 299 - u16 egress_pools_count; 300 - u16 ingress_tc_count; 301 - u16 egress_tc_count; 302 - }; 303 - 304 - static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 305 - { 306 - return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 307 - } 308 - 309 - static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 310 - unsigned int sb_index) 311 - { 312 - struct devlink_sb *devlink_sb; 313 - 314 - list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 315 - if (devlink_sb->index == sb_index) 316 - return devlink_sb; 317 - } 318 - return NULL; 319 - } 320 - 321 - static bool devlink_sb_index_exists(struct devlink *devlink, 322 - unsigned int sb_index) 323 - { 324 - return devlink_sb_get_by_index(devlink, sb_index); 325 - } 326 - 327 - static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 328 - struct nlattr **attrs) 329 - { 330 - if (attrs[DEVLINK_ATTR_SB_INDEX]) { 331 - u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 332 - struct devlink_sb *devlink_sb; 333 - 334 - devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 335 - if (!devlink_sb) 336 - return ERR_PTR(-ENODEV); 337 - return devlink_sb; 338 - } 339 - return ERR_PTR(-EINVAL); 340 - } 341 - 342 - static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 343 - struct genl_info *info) 344 - { 345 - return devlink_sb_get_from_attrs(devlink, info->attrs); 346 - } 347 - 348 - static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 349 - struct nlattr **attrs, 350 - u16 *p_pool_index) 351 - { 352 - u16 val; 353 - 354 - if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 355 - return -EINVAL; 356 - 357 - val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 358 - if (val >= devlink_sb_pool_count(devlink_sb)) 359 - return -EINVAL; 360 - *p_pool_index = val; 361 - return 0; 362 - } 363 - 364 - static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 365 - struct genl_info *info, 366 - u16 *p_pool_index) 367 - { 368 - return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 369 - p_pool_index); 370 - } 371 - 372 - static int 373 - devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 374 - enum devlink_sb_pool_type *p_pool_type) 375 - { 376 - u8 val; 377 - 378 - if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 379 - return -EINVAL; 380 - 381 - val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 382 - if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 383 - val != DEVLINK_SB_POOL_TYPE_EGRESS) 384 - return -EINVAL; 385 - *p_pool_type = val; 386 - return 0; 387 - } 388 - 389 - static int 390 - devlink_sb_pool_type_get_from_info(struct genl_info *info, 391 - enum devlink_sb_pool_type *p_pool_type) 392 - { 393 - return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 394 - } 395 - 396 - static int 397 - devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 398 - enum devlink_sb_threshold_type *p_th_type) 399 - { 400 - u8 val; 401 - 402 - if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 403 - return -EINVAL; 404 - 405 - val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 406 - if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 407 - val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 408 - return -EINVAL; 409 - *p_th_type = val; 410 - return 0; 411 - } 412 - 413 - static int 414 - devlink_sb_th_type_get_from_info(struct genl_info *info, 415 - enum devlink_sb_threshold_type *p_th_type) 416 - { 417 - return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 418 - } 419 - 420 - static int 421 - devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 422 - struct nlattr **attrs, 423 - enum devlink_sb_pool_type pool_type, 424 - u16 *p_tc_index) 425 - { 426 - u16 val; 427 - 428 - if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 429 - return -EINVAL; 430 - 431 - val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 432 - if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 433 - val >= devlink_sb->ingress_tc_count) 434 - return -EINVAL; 435 - if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 436 - val >= devlink_sb->egress_tc_count) 437 - return -EINVAL; 438 - *p_tc_index = val; 439 - return 0; 440 - } 441 - 442 - static void devlink_port_fn_cap_fill(struct nla_bitfield32 *caps, 443 - u32 cap, bool is_enable) 444 - { 445 - caps->selector |= cap; 446 - if (is_enable) 447 - caps->value |= cap; 448 - } 449 - 450 - static int devlink_port_fn_roce_fill(struct devlink_port *devlink_port, 451 - struct nla_bitfield32 *caps, 452 - struct netlink_ext_ack *extack) 453 - { 454 - bool is_enable; 455 - int err; 456 - 457 - if (!devlink_port->ops->port_fn_roce_get) 458 - return 0; 459 - 460 - err = devlink_port->ops->port_fn_roce_get(devlink_port, &is_enable, 461 - extack); 462 - if (err) { 463 - if (err == -EOPNOTSUPP) 464 - return 0; 465 - return err; 466 - } 467 - 468 - devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_ROCE, is_enable); 469 - return 0; 470 - } 471 - 472 - static int devlink_port_fn_migratable_fill(struct devlink_port *devlink_port, 473 - struct nla_bitfield32 *caps, 474 - struct netlink_ext_ack *extack) 475 - { 476 - bool is_enable; 477 - int err; 478 - 479 - if (!devlink_port->ops->port_fn_migratable_get || 480 - devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) 481 - return 0; 482 - 483 - err = devlink_port->ops->port_fn_migratable_get(devlink_port, 484 - &is_enable, extack); 485 - if (err) { 486 - if (err == -EOPNOTSUPP) 487 - return 0; 488 - return err; 489 - } 490 - 491 - devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_MIGRATABLE, is_enable); 492 - return 0; 493 - } 494 - 495 - static int devlink_port_fn_ipsec_crypto_fill(struct devlink_port *devlink_port, 496 - struct nla_bitfield32 *caps, 497 - struct netlink_ext_ack *extack) 498 - { 499 - bool is_enable; 500 - int err; 501 - 502 - if (!devlink_port->ops->port_fn_ipsec_crypto_get || 503 - devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) 504 - return 0; 505 - 506 - err = devlink_port->ops->port_fn_ipsec_crypto_get(devlink_port, &is_enable, extack); 507 - if (err) { 508 - if (err == -EOPNOTSUPP) 509 - return 0; 510 - return err; 511 - } 512 - 513 - devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO, is_enable); 514 - return 0; 515 - } 516 - 517 - static int devlink_port_fn_ipsec_packet_fill(struct devlink_port *devlink_port, 518 - struct nla_bitfield32 *caps, 519 - struct netlink_ext_ack *extack) 520 - { 521 - bool is_enable; 522 - int err; 523 - 524 - if (!devlink_port->ops->port_fn_ipsec_packet_get || 525 - devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) 526 - return 0; 527 - 528 - err = devlink_port->ops->port_fn_ipsec_packet_get(devlink_port, &is_enable, extack); 529 - if (err) { 530 - if (err == -EOPNOTSUPP) 531 - return 0; 532 - return err; 533 - } 534 - 535 - devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_IPSEC_PACKET, is_enable); 536 - return 0; 537 - } 538 - 539 - static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port, 540 - struct sk_buff *msg, 541 - struct netlink_ext_ack *extack, 542 - bool *msg_updated) 543 - { 544 - struct nla_bitfield32 caps = {}; 545 - int err; 546 - 547 - err = devlink_port_fn_roce_fill(devlink_port, &caps, extack); 548 - if (err) 549 - return err; 550 - 551 - err = devlink_port_fn_migratable_fill(devlink_port, &caps, extack); 552 - if (err) 553 - return err; 554 - 555 - err = devlink_port_fn_ipsec_crypto_fill(devlink_port, &caps, extack); 556 - if (err) 557 - return err; 558 - 559 - err = devlink_port_fn_ipsec_packet_fill(devlink_port, &caps, extack); 560 - if (err) 561 - return err; 562 - 563 - if (!caps.selector) 564 - return 0; 565 - err = nla_put_bitfield32(msg, DEVLINK_PORT_FN_ATTR_CAPS, caps.value, 566 - caps.selector); 567 - if (err) 568 - return err; 569 - 570 - *msg_updated = true; 571 - return 0; 572 - } 573 - 574 - static int 575 - devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 576 - struct genl_info *info, 577 - enum devlink_sb_pool_type pool_type, 578 - u16 *p_tc_index) 579 - { 580 - return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 581 - pool_type, p_tc_index); 582 - } 583 - 584 - struct devlink_region { 585 - struct devlink *devlink; 586 - struct devlink_port *port; 587 - struct list_head list; 588 - union { 589 - const struct devlink_region_ops *ops; 590 - const struct devlink_port_region_ops *port_ops; 591 - }; 592 - struct mutex snapshot_lock; /* protects snapshot_list, 593 - * max_snapshots and cur_snapshots 594 - * consistency. 595 - */ 596 - struct list_head snapshot_list; 597 - u32 max_snapshots; 598 - u32 cur_snapshots; 599 - u64 size; 600 - }; 601 - 602 - struct devlink_snapshot { 603 - struct list_head list; 604 - struct devlink_region *region; 605 - u8 *data; 606 - u32 id; 607 - }; 608 - 609 - static struct devlink_region * 610 - devlink_region_get_by_name(struct devlink *devlink, const char *region_name) 611 - { 612 - struct devlink_region *region; 613 - 614 - list_for_each_entry(region, &devlink->region_list, list) 615 - if (!strcmp(region->ops->name, region_name)) 616 - return region; 617 - 618 - return NULL; 619 - } 620 - 621 - static struct devlink_region * 622 - devlink_port_region_get_by_name(struct devlink_port *port, 623 - const char *region_name) 624 - { 625 - struct devlink_region *region; 626 - 627 - list_for_each_entry(region, &port->region_list, list) 628 - if (!strcmp(region->ops->name, region_name)) 629 - return region; 630 - 631 - return NULL; 632 - } 633 - 634 - static struct devlink_snapshot * 635 - devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) 636 - { 637 - struct devlink_snapshot *snapshot; 638 - 639 - list_for_each_entry(snapshot, &region->snapshot_list, list) 640 - if (snapshot->id == id) 641 - return snapshot; 642 - 643 - return NULL; 644 - } 645 - 646 - static int devlink_nl_put_nested_handle(struct sk_buff *msg, struct devlink *devlink) 647 - { 648 - struct nlattr *nested_attr; 649 - 650 - nested_attr = nla_nest_start(msg, DEVLINK_ATTR_NESTED_DEVLINK); 651 - if (!nested_attr) 652 - return -EMSGSIZE; 653 - if (devlink_nl_put_handle(msg, devlink)) 654 - goto nla_put_failure; 655 - 656 - nla_nest_end(msg, nested_attr); 657 - return 0; 658 - 659 - nla_put_failure: 660 - nla_nest_cancel(msg, nested_attr); 661 - return -EMSGSIZE; 662 - } 663 - 664 - int devlink_nl_port_handle_fill(struct sk_buff *msg, struct devlink_port *devlink_port) 665 - { 666 - if (devlink_nl_put_handle(msg, devlink_port->devlink)) 667 - return -EMSGSIZE; 668 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 669 - return -EMSGSIZE; 670 - return 0; 671 - } 672 - 673 - size_t devlink_nl_port_handle_size(struct devlink_port *devlink_port) 674 - { 675 - struct devlink *devlink = devlink_port->devlink; 676 - 677 - return nla_total_size(strlen(devlink->dev->bus->name) + 1) /* DEVLINK_ATTR_BUS_NAME */ 678 - + nla_total_size(strlen(dev_name(devlink->dev)) + 1) /* DEVLINK_ATTR_DEV_NAME */ 679 - + nla_total_size(4); /* DEVLINK_ATTR_PORT_INDEX */ 680 - } 681 - 682 - static int devlink_nl_port_attrs_put(struct sk_buff *msg, 683 - struct devlink_port *devlink_port) 684 - { 685 - struct devlink_port_attrs *attrs = &devlink_port->attrs; 686 - 687 - if (!devlink_port->attrs_set) 688 - return 0; 689 - if (attrs->lanes) { 690 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_LANES, attrs->lanes)) 691 - return -EMSGSIZE; 692 - } 693 - if (nla_put_u8(msg, DEVLINK_ATTR_PORT_SPLITTABLE, attrs->splittable)) 694 - return -EMSGSIZE; 695 - if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour)) 696 - return -EMSGSIZE; 697 - switch (devlink_port->attrs.flavour) { 698 - case DEVLINK_PORT_FLAVOUR_PCI_PF: 699 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, 700 - attrs->pci_pf.controller) || 701 - nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_pf.pf)) 702 - return -EMSGSIZE; 703 - if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_pf.external)) 704 - return -EMSGSIZE; 705 - break; 706 - case DEVLINK_PORT_FLAVOUR_PCI_VF: 707 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, 708 - attrs->pci_vf.controller) || 709 - nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_vf.pf) || 710 - nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER, attrs->pci_vf.vf)) 711 - return -EMSGSIZE; 712 - if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_vf.external)) 713 - return -EMSGSIZE; 714 - break; 715 - case DEVLINK_PORT_FLAVOUR_PCI_SF: 716 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, 717 - attrs->pci_sf.controller) || 718 - nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, 719 - attrs->pci_sf.pf) || 720 - nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_SF_NUMBER, 721 - attrs->pci_sf.sf)) 722 - return -EMSGSIZE; 723 - break; 724 - case DEVLINK_PORT_FLAVOUR_PHYSICAL: 725 - case DEVLINK_PORT_FLAVOUR_CPU: 726 - case DEVLINK_PORT_FLAVOUR_DSA: 727 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, 728 - attrs->phys.port_number)) 729 - return -EMSGSIZE; 730 - if (!attrs->split) 731 - return 0; 732 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, 733 - attrs->phys.port_number)) 734 - return -EMSGSIZE; 735 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, 736 - attrs->phys.split_subport_number)) 737 - return -EMSGSIZE; 738 - break; 739 - default: 740 - break; 741 - } 742 - return 0; 743 - } 744 - 745 - static int devlink_port_fn_hw_addr_fill(struct devlink_port *port, 746 - struct sk_buff *msg, 747 - struct netlink_ext_ack *extack, 748 - bool *msg_updated) 749 - { 750 - u8 hw_addr[MAX_ADDR_LEN]; 751 - int hw_addr_len; 752 - int err; 753 - 754 - if (!port->ops->port_fn_hw_addr_get) 755 - return 0; 756 - 757 - err = port->ops->port_fn_hw_addr_get(port, hw_addr, &hw_addr_len, 758 - extack); 759 - if (err) { 760 - if (err == -EOPNOTSUPP) 761 - return 0; 762 - return err; 763 - } 764 - err = nla_put(msg, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, hw_addr_len, hw_addr); 765 - if (err) 766 - return err; 767 - *msg_updated = true; 768 - return 0; 769 - } 770 - 771 - static int devlink_nl_rate_fill(struct sk_buff *msg, 772 - struct devlink_rate *devlink_rate, 773 - enum devlink_command cmd, u32 portid, u32 seq, 774 - int flags, struct netlink_ext_ack *extack) 775 - { 776 - struct devlink *devlink = devlink_rate->devlink; 777 - void *hdr; 778 - 779 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 780 - if (!hdr) 781 - return -EMSGSIZE; 782 - 783 - if (devlink_nl_put_handle(msg, devlink)) 784 - goto nla_put_failure; 785 - 786 - if (nla_put_u16(msg, DEVLINK_ATTR_RATE_TYPE, devlink_rate->type)) 787 - goto nla_put_failure; 788 - 789 - if (devlink_rate_is_leaf(devlink_rate)) { 790 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 791 - devlink_rate->devlink_port->index)) 792 - goto nla_put_failure; 793 - } else if (devlink_rate_is_node(devlink_rate)) { 794 - if (nla_put_string(msg, DEVLINK_ATTR_RATE_NODE_NAME, 795 - devlink_rate->name)) 796 - goto nla_put_failure; 797 - } 798 - 799 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE, 800 - devlink_rate->tx_share, DEVLINK_ATTR_PAD)) 801 - goto nla_put_failure; 802 - 803 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_MAX, 804 - devlink_rate->tx_max, DEVLINK_ATTR_PAD)) 805 - goto nla_put_failure; 806 - 807 - if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_PRIORITY, 808 - devlink_rate->tx_priority)) 809 - goto nla_put_failure; 810 - 811 - if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_WEIGHT, 812 - devlink_rate->tx_weight)) 813 - goto nla_put_failure; 814 - 815 - if (devlink_rate->parent) 816 - if (nla_put_string(msg, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, 817 - devlink_rate->parent->name)) 818 - goto nla_put_failure; 819 - 820 - genlmsg_end(msg, hdr); 821 - return 0; 822 - 823 - nla_put_failure: 824 - genlmsg_cancel(msg, hdr); 825 - return -EMSGSIZE; 826 - } 827 - 828 - static bool 829 - devlink_port_fn_state_valid(enum devlink_port_fn_state state) 830 - { 831 - return state == DEVLINK_PORT_FN_STATE_INACTIVE || 832 - state == DEVLINK_PORT_FN_STATE_ACTIVE; 833 - } 834 - 835 - static bool 836 - devlink_port_fn_opstate_valid(enum devlink_port_fn_opstate opstate) 837 - { 838 - return opstate == DEVLINK_PORT_FN_OPSTATE_DETACHED || 839 - opstate == DEVLINK_PORT_FN_OPSTATE_ATTACHED; 840 - } 841 - 842 - static int devlink_port_fn_state_fill(struct devlink_port *port, 843 - struct sk_buff *msg, 844 - struct netlink_ext_ack *extack, 845 - bool *msg_updated) 846 - { 847 - enum devlink_port_fn_opstate opstate; 848 - enum devlink_port_fn_state state; 849 - int err; 850 - 851 - if (!port->ops->port_fn_state_get) 852 - return 0; 853 - 854 - err = port->ops->port_fn_state_get(port, &state, &opstate, extack); 855 - if (err) { 856 - if (err == -EOPNOTSUPP) 857 - return 0; 858 - return err; 859 - } 860 - if (!devlink_port_fn_state_valid(state)) { 861 - WARN_ON_ONCE(1); 862 - NL_SET_ERR_MSG(extack, "Invalid state read from driver"); 863 - return -EINVAL; 864 - } 865 - if (!devlink_port_fn_opstate_valid(opstate)) { 866 - WARN_ON_ONCE(1); 867 - NL_SET_ERR_MSG(extack, "Invalid operational state read from driver"); 868 - return -EINVAL; 869 - } 870 - if (nla_put_u8(msg, DEVLINK_PORT_FN_ATTR_STATE, state) || 871 - nla_put_u8(msg, DEVLINK_PORT_FN_ATTR_OPSTATE, opstate)) 872 - return -EMSGSIZE; 873 - *msg_updated = true; 874 - return 0; 875 - } 876 - 877 - static int 878 - devlink_port_fn_mig_set(struct devlink_port *devlink_port, bool enable, 879 - struct netlink_ext_ack *extack) 880 - { 881 - return devlink_port->ops->port_fn_migratable_set(devlink_port, enable, 882 - extack); 883 - } 884 - 885 - static int 886 - devlink_port_fn_roce_set(struct devlink_port *devlink_port, bool enable, 887 - struct netlink_ext_ack *extack) 888 - { 889 - return devlink_port->ops->port_fn_roce_set(devlink_port, enable, 890 - extack); 891 - } 892 - 893 - static int 894 - devlink_port_fn_ipsec_crypto_set(struct devlink_port *devlink_port, bool enable, 895 - struct netlink_ext_ack *extack) 896 - { 897 - return devlink_port->ops->port_fn_ipsec_crypto_set(devlink_port, enable, extack); 898 - } 899 - 900 - static int 901 - devlink_port_fn_ipsec_packet_set(struct devlink_port *devlink_port, bool enable, 902 - struct netlink_ext_ack *extack) 903 - { 904 - return devlink_port->ops->port_fn_ipsec_packet_set(devlink_port, enable, extack); 905 - } 906 - 907 - static int devlink_port_fn_caps_set(struct devlink_port *devlink_port, 908 - const struct nlattr *attr, 909 - struct netlink_ext_ack *extack) 910 - { 911 - struct nla_bitfield32 caps; 912 - u32 caps_value; 913 - int err; 914 - 915 - caps = nla_get_bitfield32(attr); 916 - caps_value = caps.value & caps.selector; 917 - if (caps.selector & DEVLINK_PORT_FN_CAP_ROCE) { 918 - err = devlink_port_fn_roce_set(devlink_port, 919 - caps_value & DEVLINK_PORT_FN_CAP_ROCE, 920 - extack); 921 - if (err) 922 - return err; 923 - } 924 - if (caps.selector & DEVLINK_PORT_FN_CAP_MIGRATABLE) { 925 - err = devlink_port_fn_mig_set(devlink_port, caps_value & 926 - DEVLINK_PORT_FN_CAP_MIGRATABLE, 927 - extack); 928 - if (err) 929 - return err; 930 - } 931 - if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO) { 932 - err = devlink_port_fn_ipsec_crypto_set(devlink_port, caps_value & 933 - DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO, 934 - extack); 935 - if (err) 936 - return err; 937 - } 938 - if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_PACKET) { 939 - err = devlink_port_fn_ipsec_packet_set(devlink_port, caps_value & 940 - DEVLINK_PORT_FN_CAP_IPSEC_PACKET, 941 - extack); 942 - if (err) 943 - return err; 944 - } 945 - return 0; 946 - } 947 - 948 - static int 949 - devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *port, 950 - struct netlink_ext_ack *extack) 951 - { 952 - struct nlattr *function_attr; 953 - bool msg_updated = false; 954 - int err; 955 - 956 - function_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PORT_FUNCTION); 957 - if (!function_attr) 958 - return -EMSGSIZE; 959 - 960 - err = devlink_port_fn_hw_addr_fill(port, msg, extack, &msg_updated); 961 - if (err) 962 - goto out; 963 - err = devlink_port_fn_caps_fill(port, msg, extack, &msg_updated); 964 - if (err) 965 - goto out; 966 - err = devlink_port_fn_state_fill(port, msg, extack, &msg_updated); 967 - out: 968 - if (err || !msg_updated) 969 - nla_nest_cancel(msg, function_attr); 970 - else 971 - nla_nest_end(msg, function_attr); 972 - return err; 973 - } 974 - 975 - static int devlink_nl_port_fill(struct sk_buff *msg, 976 - struct devlink_port *devlink_port, 977 - enum devlink_command cmd, u32 portid, u32 seq, 978 - int flags, struct netlink_ext_ack *extack) 979 - { 980 - struct devlink *devlink = devlink_port->devlink; 981 - void *hdr; 982 - 983 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 984 - if (!hdr) 985 - return -EMSGSIZE; 986 - 987 - if (devlink_nl_put_handle(msg, devlink)) 988 - goto nla_put_failure; 989 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 990 - goto nla_put_failure; 991 - 992 - spin_lock_bh(&devlink_port->type_lock); 993 - if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 994 - goto nla_put_failure_type_locked; 995 - if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 996 - nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 997 - devlink_port->desired_type)) 998 - goto nla_put_failure_type_locked; 999 - if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 1000 - if (devlink_port->type_eth.netdev && 1001 - (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 1002 - devlink_port->type_eth.ifindex) || 1003 - nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 1004 - devlink_port->type_eth.ifname))) 1005 - goto nla_put_failure_type_locked; 1006 - } 1007 - if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 1008 - struct ib_device *ibdev = devlink_port->type_ib.ibdev; 1009 - 1010 - if (ibdev && 1011 - nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 1012 - ibdev->name)) 1013 - goto nla_put_failure_type_locked; 1014 - } 1015 - spin_unlock_bh(&devlink_port->type_lock); 1016 - if (devlink_nl_port_attrs_put(msg, devlink_port)) 1017 - goto nla_put_failure; 1018 - if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack)) 1019 - goto nla_put_failure; 1020 - if (devlink_port->linecard && 1021 - nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, 1022 - devlink_port->linecard->index)) 1023 - goto nla_put_failure; 1024 - 1025 - genlmsg_end(msg, hdr); 1026 - return 0; 1027 - 1028 - nla_put_failure_type_locked: 1029 - spin_unlock_bh(&devlink_port->type_lock); 1030 - nla_put_failure: 1031 - genlmsg_cancel(msg, hdr); 1032 - return -EMSGSIZE; 1033 - } 1034 - 1035 - static void devlink_port_notify(struct devlink_port *devlink_port, 1036 - enum devlink_command cmd) 1037 - { 1038 - struct devlink *devlink = devlink_port->devlink; 1039 - struct sk_buff *msg; 1040 - int err; 1041 - 1042 - WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 1043 - 1044 - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 1045 - return; 1046 - 1047 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1048 - if (!msg) 1049 - return; 1050 - 1051 - err = devlink_nl_port_fill(msg, devlink_port, cmd, 0, 0, 0, NULL); 1052 - if (err) { 1053 - nlmsg_free(msg); 1054 - return; 1055 - } 1056 - 1057 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg, 1058 - 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 1059 - } 1060 - 1061 - static void devlink_rate_notify(struct devlink_rate *devlink_rate, 1062 - enum devlink_command cmd) 1063 - { 1064 - struct devlink *devlink = devlink_rate->devlink; 1065 - struct sk_buff *msg; 1066 - int err; 1067 - 1068 - WARN_ON(cmd != DEVLINK_CMD_RATE_NEW && cmd != DEVLINK_CMD_RATE_DEL); 1069 - 1070 - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 1071 - return; 1072 - 1073 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1074 - if (!msg) 1075 - return; 1076 - 1077 - err = devlink_nl_rate_fill(msg, devlink_rate, cmd, 0, 0, 0, NULL); 1078 - if (err) { 1079 - nlmsg_free(msg); 1080 - return; 1081 - } 1082 - 1083 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg, 1084 - 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 1085 - } 1086 - 1087 - static int 1088 - devlink_nl_rate_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 1089 - struct netlink_callback *cb, int flags) 1090 - { 1091 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 1092 - struct devlink_rate *devlink_rate; 1093 - int idx = 0; 1094 - int err = 0; 1095 - 1096 - list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 1097 - enum devlink_command cmd = DEVLINK_CMD_RATE_NEW; 1098 - u32 id = NETLINK_CB(cb->skb).portid; 1099 - 1100 - if (idx < state->idx) { 1101 - idx++; 1102 - continue; 1103 - } 1104 - err = devlink_nl_rate_fill(msg, devlink_rate, cmd, id, 1105 - cb->nlh->nlmsg_seq, flags, NULL); 1106 - if (err) { 1107 - state->idx = idx; 1108 - break; 1109 - } 1110 - idx++; 1111 - } 1112 - 1113 - return err; 1114 - } 1115 - 1116 - int devlink_nl_rate_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 1117 - { 1118 - return devlink_nl_dumpit(skb, cb, devlink_nl_rate_get_dump_one); 1119 - } 1120 - 1121 - int devlink_nl_rate_get_doit(struct sk_buff *skb, struct genl_info *info) 1122 - { 1123 - struct devlink *devlink = info->user_ptr[0]; 1124 - struct devlink_rate *devlink_rate; 1125 - struct sk_buff *msg; 1126 - int err; 1127 - 1128 - devlink_rate = devlink_rate_get_from_info(devlink, info); 1129 - if (IS_ERR(devlink_rate)) 1130 - return PTR_ERR(devlink_rate); 1131 - 1132 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1133 - if (!msg) 1134 - return -ENOMEM; 1135 - 1136 - err = devlink_nl_rate_fill(msg, devlink_rate, DEVLINK_CMD_RATE_NEW, 1137 - info->snd_portid, info->snd_seq, 0, 1138 - info->extack); 1139 - if (err) { 1140 - nlmsg_free(msg); 1141 - return err; 1142 - } 1143 - 1144 - return genlmsg_reply(msg, info); 1145 - } 1146 - 1147 - static bool 1148 - devlink_rate_is_parent_node(struct devlink_rate *devlink_rate, 1149 - struct devlink_rate *parent) 1150 - { 1151 - while (parent) { 1152 - if (parent == devlink_rate) 1153 - return true; 1154 - parent = parent->parent; 1155 - } 1156 - return false; 1157 - } 1158 - 1159 - int devlink_nl_port_get_doit(struct sk_buff *skb, struct genl_info *info) 1160 - { 1161 - struct devlink_port *devlink_port = info->user_ptr[1]; 1162 - struct sk_buff *msg; 1163 - int err; 1164 - 1165 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1166 - if (!msg) 1167 - return -ENOMEM; 1168 - 1169 - err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_PORT_NEW, 1170 - info->snd_portid, info->snd_seq, 0, 1171 - info->extack); 1172 - if (err) { 1173 - nlmsg_free(msg); 1174 - return err; 1175 - } 1176 - 1177 - return genlmsg_reply(msg, info); 1178 - } 1179 - 1180 - static int 1181 - devlink_nl_port_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 1182 - struct netlink_callback *cb, int flags) 1183 - { 1184 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 1185 - struct devlink_port *devlink_port; 1186 - unsigned long port_index; 1187 - int err = 0; 1188 - 1189 - xa_for_each_start(&devlink->ports, port_index, devlink_port, state->idx) { 1190 - err = devlink_nl_port_fill(msg, devlink_port, 1191 - DEVLINK_CMD_NEW, 1192 - NETLINK_CB(cb->skb).portid, 1193 - cb->nlh->nlmsg_seq, flags, 1194 - cb->extack); 1195 - if (err) { 1196 - state->idx = port_index; 1197 - break; 1198 - } 1199 - } 1200 - 1201 - return err; 1202 - } 1203 - 1204 - int devlink_nl_port_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 1205 - { 1206 - return devlink_nl_dumpit(skb, cb, devlink_nl_port_get_dump_one); 1207 - } 1208 - 1209 - static int devlink_port_type_set(struct devlink_port *devlink_port, 1210 - enum devlink_port_type port_type) 1211 - 1212 - { 1213 - int err; 1214 - 1215 - if (!devlink_port->ops->port_type_set) 1216 - return -EOPNOTSUPP; 1217 - 1218 - if (port_type == devlink_port->type) 1219 - return 0; 1220 - 1221 - err = devlink_port->ops->port_type_set(devlink_port, port_type); 1222 - if (err) 1223 - return err; 1224 - 1225 - devlink_port->desired_type = port_type; 1226 - devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 1227 - return 0; 1228 - } 1229 - 1230 - static int devlink_port_function_hw_addr_set(struct devlink_port *port, 1231 - const struct nlattr *attr, 1232 - struct netlink_ext_ack *extack) 1233 - { 1234 - const u8 *hw_addr; 1235 - int hw_addr_len; 1236 - 1237 - hw_addr = nla_data(attr); 1238 - hw_addr_len = nla_len(attr); 1239 - if (hw_addr_len > MAX_ADDR_LEN) { 1240 - NL_SET_ERR_MSG(extack, "Port function hardware address too long"); 1241 - return -EINVAL; 1242 - } 1243 - if (port->type == DEVLINK_PORT_TYPE_ETH) { 1244 - if (hw_addr_len != ETH_ALEN) { 1245 - NL_SET_ERR_MSG(extack, "Address must be 6 bytes for Ethernet device"); 1246 - return -EINVAL; 1247 - } 1248 - if (!is_unicast_ether_addr(hw_addr)) { 1249 - NL_SET_ERR_MSG(extack, "Non-unicast hardware address unsupported"); 1250 - return -EINVAL; 1251 - } 1252 - } 1253 - 1254 - return port->ops->port_fn_hw_addr_set(port, hw_addr, hw_addr_len, 1255 - extack); 1256 - } 1257 - 1258 - static int devlink_port_fn_state_set(struct devlink_port *port, 1259 - const struct nlattr *attr, 1260 - struct netlink_ext_ack *extack) 1261 - { 1262 - enum devlink_port_fn_state state; 1263 - 1264 - state = nla_get_u8(attr); 1265 - return port->ops->port_fn_state_set(port, state, extack); 1266 - } 1267 - 1268 - static int devlink_port_function_validate(struct devlink_port *devlink_port, 1269 - struct nlattr **tb, 1270 - struct netlink_ext_ack *extack) 1271 - { 1272 - const struct devlink_port_ops *ops = devlink_port->ops; 1273 - struct nlattr *attr; 1274 - 1275 - if (tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] && 1276 - !ops->port_fn_hw_addr_set) { 1277 - NL_SET_ERR_MSG_ATTR(extack, tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR], 1278 - "Port doesn't support function attributes"); 1279 - return -EOPNOTSUPP; 1280 - } 1281 - if (tb[DEVLINK_PORT_FN_ATTR_STATE] && !ops->port_fn_state_set) { 1282 - NL_SET_ERR_MSG_ATTR(extack, tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR], 1283 - "Function does not support state setting"); 1284 - return -EOPNOTSUPP; 1285 - } 1286 - attr = tb[DEVLINK_PORT_FN_ATTR_CAPS]; 1287 - if (attr) { 1288 - struct nla_bitfield32 caps; 1289 - 1290 - caps = nla_get_bitfield32(attr); 1291 - if (caps.selector & DEVLINK_PORT_FN_CAP_ROCE && 1292 - !ops->port_fn_roce_set) { 1293 - NL_SET_ERR_MSG_ATTR(extack, attr, 1294 - "Port doesn't support RoCE function attribute"); 1295 - return -EOPNOTSUPP; 1296 - } 1297 - if (caps.selector & DEVLINK_PORT_FN_CAP_MIGRATABLE) { 1298 - if (!ops->port_fn_migratable_set) { 1299 - NL_SET_ERR_MSG_ATTR(extack, attr, 1300 - "Port doesn't support migratable function attribute"); 1301 - return -EOPNOTSUPP; 1302 - } 1303 - if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) { 1304 - NL_SET_ERR_MSG_ATTR(extack, attr, 1305 - "migratable function attribute supported for VFs only"); 1306 - return -EOPNOTSUPP; 1307 - } 1308 - } 1309 - if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO) { 1310 - if (!ops->port_fn_ipsec_crypto_set) { 1311 - NL_SET_ERR_MSG_ATTR(extack, attr, 1312 - "Port doesn't support ipsec_crypto function attribute"); 1313 - return -EOPNOTSUPP; 1314 - } 1315 - if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) { 1316 - NL_SET_ERR_MSG_ATTR(extack, attr, 1317 - "ipsec_crypto function attribute supported for VFs only"); 1318 - return -EOPNOTSUPP; 1319 - } 1320 - } 1321 - if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_PACKET) { 1322 - if (!ops->port_fn_ipsec_packet_set) { 1323 - NL_SET_ERR_MSG_ATTR(extack, attr, 1324 - "Port doesn't support ipsec_packet function attribute"); 1325 - return -EOPNOTSUPP; 1326 - } 1327 - if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) { 1328 - NL_SET_ERR_MSG_ATTR(extack, attr, 1329 - "ipsec_packet function attribute supported for VFs only"); 1330 - return -EOPNOTSUPP; 1331 - } 1332 - } 1333 - } 1334 - return 0; 1335 - } 1336 - 1337 - static int devlink_port_function_set(struct devlink_port *port, 1338 - const struct nlattr *attr, 1339 - struct netlink_ext_ack *extack) 1340 - { 1341 - struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1]; 1342 - int err; 1343 - 1344 - err = nla_parse_nested(tb, DEVLINK_PORT_FUNCTION_ATTR_MAX, attr, 1345 - devlink_function_nl_policy, extack); 1346 - if (err < 0) { 1347 - NL_SET_ERR_MSG(extack, "Fail to parse port function attributes"); 1348 - return err; 1349 - } 1350 - 1351 - err = devlink_port_function_validate(port, tb, extack); 1352 - if (err) 1353 - return err; 1354 - 1355 - attr = tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]; 1356 - if (attr) { 1357 - err = devlink_port_function_hw_addr_set(port, attr, extack); 1358 - if (err) 1359 - return err; 1360 - } 1361 - 1362 - attr = tb[DEVLINK_PORT_FN_ATTR_CAPS]; 1363 - if (attr) { 1364 - err = devlink_port_fn_caps_set(port, attr, extack); 1365 - if (err) 1366 - return err; 1367 - } 1368 - 1369 - /* Keep this as the last function attribute set, so that when 1370 - * multiple port function attributes are set along with state, 1371 - * Those can be applied first before activating the state. 1372 - */ 1373 - attr = tb[DEVLINK_PORT_FN_ATTR_STATE]; 1374 - if (attr) 1375 - err = devlink_port_fn_state_set(port, attr, extack); 1376 - 1377 - if (!err) 1378 - devlink_port_notify(port, DEVLINK_CMD_PORT_NEW); 1379 - return err; 1380 - } 1381 - 1382 - static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, 1383 - struct genl_info *info) 1384 - { 1385 - struct devlink_port *devlink_port = info->user_ptr[1]; 1386 - int err; 1387 - 1388 - if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 1389 - enum devlink_port_type port_type; 1390 - 1391 - port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 1392 - err = devlink_port_type_set(devlink_port, port_type); 1393 - if (err) 1394 - return err; 1395 - } 1396 - 1397 - if (info->attrs[DEVLINK_ATTR_PORT_FUNCTION]) { 1398 - struct nlattr *attr = info->attrs[DEVLINK_ATTR_PORT_FUNCTION]; 1399 - struct netlink_ext_ack *extack = info->extack; 1400 - 1401 - err = devlink_port_function_set(devlink_port, attr, extack); 1402 - if (err) 1403 - return err; 1404 - } 1405 - 1406 - return 0; 1407 - } 1408 - 1409 - static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, 1410 - struct genl_info *info) 1411 - { 1412 - struct devlink_port *devlink_port = info->user_ptr[1]; 1413 - struct devlink *devlink = info->user_ptr[0]; 1414 - u32 count; 1415 - 1416 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PORT_SPLIT_COUNT)) 1417 - return -EINVAL; 1418 - if (!devlink_port->ops->port_split) 1419 - return -EOPNOTSUPP; 1420 - 1421 - count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 1422 - 1423 - if (!devlink_port->attrs.splittable) { 1424 - /* Split ports cannot be split. */ 1425 - if (devlink_port->attrs.split) 1426 - NL_SET_ERR_MSG(info->extack, "Port cannot be split further"); 1427 - else 1428 - NL_SET_ERR_MSG(info->extack, "Port cannot be split"); 1429 - return -EINVAL; 1430 - } 1431 - 1432 - if (count < 2 || !is_power_of_2(count) || count > devlink_port->attrs.lanes) { 1433 - NL_SET_ERR_MSG(info->extack, "Invalid split count"); 1434 - return -EINVAL; 1435 - } 1436 - 1437 - return devlink_port->ops->port_split(devlink, devlink_port, count, 1438 - info->extack); 1439 - } 1440 - 1441 - static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 1442 - struct genl_info *info) 1443 - { 1444 - struct devlink_port *devlink_port = info->user_ptr[1]; 1445 - struct devlink *devlink = info->user_ptr[0]; 1446 - 1447 - if (!devlink_port->ops->port_unsplit) 1448 - return -EOPNOTSUPP; 1449 - return devlink_port->ops->port_unsplit(devlink, devlink_port, info->extack); 1450 - } 1451 - 1452 - static int devlink_nl_cmd_port_new_doit(struct sk_buff *skb, 1453 - struct genl_info *info) 1454 - { 1455 - struct netlink_ext_ack *extack = info->extack; 1456 - struct devlink_port_new_attrs new_attrs = {}; 1457 - struct devlink *devlink = info->user_ptr[0]; 1458 - struct devlink_port *devlink_port; 1459 - struct sk_buff *msg; 1460 - int err; 1461 - 1462 - if (!devlink->ops->port_new) 1463 - return -EOPNOTSUPP; 1464 - 1465 - if (!info->attrs[DEVLINK_ATTR_PORT_FLAVOUR] || 1466 - !info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]) { 1467 - NL_SET_ERR_MSG(extack, "Port flavour or PCI PF are not specified"); 1468 - return -EINVAL; 1469 - } 1470 - new_attrs.flavour = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_FLAVOUR]); 1471 - new_attrs.pfnum = 1472 - nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]); 1473 - 1474 - if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 1475 - /* Port index of the new port being created by driver. */ 1476 - new_attrs.port_index = 1477 - nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 1478 - new_attrs.port_index_valid = true; 1479 - } 1480 - if (info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]) { 1481 - new_attrs.controller = 1482 - nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]); 1483 - new_attrs.controller_valid = true; 1484 - } 1485 - if (new_attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF && 1486 - info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]) { 1487 - new_attrs.sfnum = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]); 1488 - new_attrs.sfnum_valid = true; 1489 - } 1490 - 1491 - err = devlink->ops->port_new(devlink, &new_attrs, 1492 - extack, &devlink_port); 1493 - if (err) 1494 - return err; 1495 - 1496 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1497 - if (!msg) { 1498 - err = -ENOMEM; 1499 - goto err_out_port_del; 1500 - } 1501 - err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_NEW, 1502 - info->snd_portid, info->snd_seq, 0, NULL); 1503 - if (WARN_ON_ONCE(err)) 1504 - goto err_out_msg_free; 1505 - err = genlmsg_reply(msg, info); 1506 - if (err) 1507 - goto err_out_port_del; 1508 - return 0; 1509 - 1510 - err_out_msg_free: 1511 - nlmsg_free(msg); 1512 - err_out_port_del: 1513 - devlink_port->ops->port_del(devlink, devlink_port, NULL); 1514 - return err; 1515 - } 1516 - 1517 - static int devlink_nl_cmd_port_del_doit(struct sk_buff *skb, 1518 - struct genl_info *info) 1519 - { 1520 - struct devlink_port *devlink_port = info->user_ptr[1]; 1521 - struct netlink_ext_ack *extack = info->extack; 1522 - struct devlink *devlink = info->user_ptr[0]; 1523 - 1524 - if (!devlink_port->ops->port_del) 1525 - return -EOPNOTSUPP; 1526 - 1527 - return devlink_port->ops->port_del(devlink, devlink_port, extack); 1528 - } 1529 - 1530 - static int 1531 - devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate, 1532 - struct genl_info *info, 1533 - struct nlattr *nla_parent) 1534 - { 1535 - struct devlink *devlink = devlink_rate->devlink; 1536 - const char *parent_name = nla_data(nla_parent); 1537 - const struct devlink_ops *ops = devlink->ops; 1538 - size_t len = strlen(parent_name); 1539 - struct devlink_rate *parent; 1540 - int err = -EOPNOTSUPP; 1541 - 1542 - parent = devlink_rate->parent; 1543 - 1544 - if (parent && !len) { 1545 - if (devlink_rate_is_leaf(devlink_rate)) 1546 - err = ops->rate_leaf_parent_set(devlink_rate, NULL, 1547 - devlink_rate->priv, NULL, 1548 - info->extack); 1549 - else if (devlink_rate_is_node(devlink_rate)) 1550 - err = ops->rate_node_parent_set(devlink_rate, NULL, 1551 - devlink_rate->priv, NULL, 1552 - info->extack); 1553 - if (err) 1554 - return err; 1555 - 1556 - refcount_dec(&parent->refcnt); 1557 - devlink_rate->parent = NULL; 1558 - } else if (len) { 1559 - parent = devlink_rate_node_get_by_name(devlink, parent_name); 1560 - if (IS_ERR(parent)) 1561 - return -ENODEV; 1562 - 1563 - if (parent == devlink_rate) { 1564 - NL_SET_ERR_MSG(info->extack, "Parent to self is not allowed"); 1565 - return -EINVAL; 1566 - } 1567 - 1568 - if (devlink_rate_is_node(devlink_rate) && 1569 - devlink_rate_is_parent_node(devlink_rate, parent->parent)) { 1570 - NL_SET_ERR_MSG(info->extack, "Node is already a parent of parent node."); 1571 - return -EEXIST; 1572 - } 1573 - 1574 - if (devlink_rate_is_leaf(devlink_rate)) 1575 - err = ops->rate_leaf_parent_set(devlink_rate, parent, 1576 - devlink_rate->priv, parent->priv, 1577 - info->extack); 1578 - else if (devlink_rate_is_node(devlink_rate)) 1579 - err = ops->rate_node_parent_set(devlink_rate, parent, 1580 - devlink_rate->priv, parent->priv, 1581 - info->extack); 1582 - if (err) 1583 - return err; 1584 - 1585 - if (devlink_rate->parent) 1586 - /* we're reassigning to other parent in this case */ 1587 - refcount_dec(&devlink_rate->parent->refcnt); 1588 - 1589 - refcount_inc(&parent->refcnt); 1590 - devlink_rate->parent = parent; 1591 - } 1592 - 1593 - return 0; 1594 - } 1595 - 1596 - static int devlink_nl_rate_set(struct devlink_rate *devlink_rate, 1597 - const struct devlink_ops *ops, 1598 - struct genl_info *info) 1599 - { 1600 - struct nlattr *nla_parent, **attrs = info->attrs; 1601 - int err = -EOPNOTSUPP; 1602 - u32 priority; 1603 - u32 weight; 1604 - u64 rate; 1605 - 1606 - if (attrs[DEVLINK_ATTR_RATE_TX_SHARE]) { 1607 - rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]); 1608 - if (devlink_rate_is_leaf(devlink_rate)) 1609 - err = ops->rate_leaf_tx_share_set(devlink_rate, devlink_rate->priv, 1610 - rate, info->extack); 1611 - else if (devlink_rate_is_node(devlink_rate)) 1612 - err = ops->rate_node_tx_share_set(devlink_rate, devlink_rate->priv, 1613 - rate, info->extack); 1614 - if (err) 1615 - return err; 1616 - devlink_rate->tx_share = rate; 1617 - } 1618 - 1619 - if (attrs[DEVLINK_ATTR_RATE_TX_MAX]) { 1620 - rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]); 1621 - if (devlink_rate_is_leaf(devlink_rate)) 1622 - err = ops->rate_leaf_tx_max_set(devlink_rate, devlink_rate->priv, 1623 - rate, info->extack); 1624 - else if (devlink_rate_is_node(devlink_rate)) 1625 - err = ops->rate_node_tx_max_set(devlink_rate, devlink_rate->priv, 1626 - rate, info->extack); 1627 - if (err) 1628 - return err; 1629 - devlink_rate->tx_max = rate; 1630 - } 1631 - 1632 - if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]) { 1633 - priority = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]); 1634 - if (devlink_rate_is_leaf(devlink_rate)) 1635 - err = ops->rate_leaf_tx_priority_set(devlink_rate, devlink_rate->priv, 1636 - priority, info->extack); 1637 - else if (devlink_rate_is_node(devlink_rate)) 1638 - err = ops->rate_node_tx_priority_set(devlink_rate, devlink_rate->priv, 1639 - priority, info->extack); 1640 - 1641 - if (err) 1642 - return err; 1643 - devlink_rate->tx_priority = priority; 1644 - } 1645 - 1646 - if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]) { 1647 - weight = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]); 1648 - if (devlink_rate_is_leaf(devlink_rate)) 1649 - err = ops->rate_leaf_tx_weight_set(devlink_rate, devlink_rate->priv, 1650 - weight, info->extack); 1651 - else if (devlink_rate_is_node(devlink_rate)) 1652 - err = ops->rate_node_tx_weight_set(devlink_rate, devlink_rate->priv, 1653 - weight, info->extack); 1654 - 1655 - if (err) 1656 - return err; 1657 - devlink_rate->tx_weight = weight; 1658 - } 1659 - 1660 - nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME]; 1661 - if (nla_parent) { 1662 - err = devlink_nl_rate_parent_node_set(devlink_rate, info, 1663 - nla_parent); 1664 - if (err) 1665 - return err; 1666 - } 1667 - 1668 - return 0; 1669 - } 1670 - 1671 - static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops, 1672 - struct genl_info *info, 1673 - enum devlink_rate_type type) 1674 - { 1675 - struct nlattr **attrs = info->attrs; 1676 - 1677 - if (type == DEVLINK_RATE_TYPE_LEAF) { 1678 - if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_leaf_tx_share_set) { 1679 - NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the leafs"); 1680 - return false; 1681 - } 1682 - if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) { 1683 - NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the leafs"); 1684 - return false; 1685 - } 1686 - if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 1687 - !ops->rate_leaf_parent_set) { 1688 - NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the leafs"); 1689 - return false; 1690 - } 1691 - if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_leaf_tx_priority_set) { 1692 - NL_SET_ERR_MSG_ATTR(info->extack, 1693 - attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 1694 - "TX priority set isn't supported for the leafs"); 1695 - return false; 1696 - } 1697 - if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_leaf_tx_weight_set) { 1698 - NL_SET_ERR_MSG_ATTR(info->extack, 1699 - attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 1700 - "TX weight set isn't supported for the leafs"); 1701 - return false; 1702 - } 1703 - } else if (type == DEVLINK_RATE_TYPE_NODE) { 1704 - if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_node_tx_share_set) { 1705 - NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the nodes"); 1706 - return false; 1707 - } 1708 - if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_node_tx_max_set) { 1709 - NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the nodes"); 1710 - return false; 1711 - } 1712 - if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 1713 - !ops->rate_node_parent_set) { 1714 - NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the nodes"); 1715 - return false; 1716 - } 1717 - if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_node_tx_priority_set) { 1718 - NL_SET_ERR_MSG_ATTR(info->extack, 1719 - attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 1720 - "TX priority set isn't supported for the nodes"); 1721 - return false; 1722 - } 1723 - if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_node_tx_weight_set) { 1724 - NL_SET_ERR_MSG_ATTR(info->extack, 1725 - attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 1726 - "TX weight set isn't supported for the nodes"); 1727 - return false; 1728 - } 1729 - } else { 1730 - WARN(1, "Unknown type of rate object"); 1731 - return false; 1732 - } 1733 - 1734 - return true; 1735 - } 1736 - 1737 - static int devlink_nl_cmd_rate_set_doit(struct sk_buff *skb, 1738 - struct genl_info *info) 1739 - { 1740 - struct devlink *devlink = info->user_ptr[0]; 1741 - struct devlink_rate *devlink_rate; 1742 - const struct devlink_ops *ops; 1743 - int err; 1744 - 1745 - devlink_rate = devlink_rate_get_from_info(devlink, info); 1746 - if (IS_ERR(devlink_rate)) 1747 - return PTR_ERR(devlink_rate); 1748 - 1749 - ops = devlink->ops; 1750 - if (!ops || !devlink_rate_set_ops_supported(ops, info, devlink_rate->type)) 1751 - return -EOPNOTSUPP; 1752 - 1753 - err = devlink_nl_rate_set(devlink_rate, ops, info); 1754 - 1755 - if (!err) 1756 - devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 1757 - return err; 1758 - } 1759 - 1760 - static int devlink_nl_cmd_rate_new_doit(struct sk_buff *skb, 1761 - struct genl_info *info) 1762 - { 1763 - struct devlink *devlink = info->user_ptr[0]; 1764 - struct devlink_rate *rate_node; 1765 - const struct devlink_ops *ops; 1766 - int err; 1767 - 1768 - ops = devlink->ops; 1769 - if (!ops || !ops->rate_node_new || !ops->rate_node_del) { 1770 - NL_SET_ERR_MSG(info->extack, "Rate nodes aren't supported"); 1771 - return -EOPNOTSUPP; 1772 - } 1773 - 1774 - if (!devlink_rate_set_ops_supported(ops, info, DEVLINK_RATE_TYPE_NODE)) 1775 - return -EOPNOTSUPP; 1776 - 1777 - rate_node = devlink_rate_node_get_from_attrs(devlink, info->attrs); 1778 - if (!IS_ERR(rate_node)) 1779 - return -EEXIST; 1780 - else if (rate_node == ERR_PTR(-EINVAL)) 1781 - return -EINVAL; 1782 - 1783 - rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 1784 - if (!rate_node) 1785 - return -ENOMEM; 1786 - 1787 - rate_node->devlink = devlink; 1788 - rate_node->type = DEVLINK_RATE_TYPE_NODE; 1789 - rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL); 1790 - if (!rate_node->name) { 1791 - err = -ENOMEM; 1792 - goto err_strdup; 1793 - } 1794 - 1795 - err = ops->rate_node_new(rate_node, &rate_node->priv, info->extack); 1796 - if (err) 1797 - goto err_node_new; 1798 - 1799 - err = devlink_nl_rate_set(rate_node, ops, info); 1800 - if (err) 1801 - goto err_rate_set; 1802 - 1803 - refcount_set(&rate_node->refcnt, 1); 1804 - list_add(&rate_node->list, &devlink->rate_list); 1805 - devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 1806 - return 0; 1807 - 1808 - err_rate_set: 1809 - ops->rate_node_del(rate_node, rate_node->priv, info->extack); 1810 - err_node_new: 1811 - kfree(rate_node->name); 1812 - err_strdup: 1813 - kfree(rate_node); 1814 - return err; 1815 - } 1816 - 1817 - static int devlink_nl_cmd_rate_del_doit(struct sk_buff *skb, 1818 - struct genl_info *info) 1819 - { 1820 - struct devlink *devlink = info->user_ptr[0]; 1821 - struct devlink_rate *rate_node; 1822 - int err; 1823 - 1824 - rate_node = devlink_rate_node_get_from_info(devlink, info); 1825 - if (IS_ERR(rate_node)) 1826 - return PTR_ERR(rate_node); 1827 - 1828 - if (refcount_read(&rate_node->refcnt) > 1) { 1829 - NL_SET_ERR_MSG(info->extack, "Node has children. Cannot delete node."); 1830 - return -EBUSY; 1831 - } 1832 - 1833 - devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 1834 - err = devlink->ops->rate_node_del(rate_node, rate_node->priv, 1835 - info->extack); 1836 - if (rate_node->parent) 1837 - refcount_dec(&rate_node->parent->refcnt); 1838 - list_del(&rate_node->list); 1839 - kfree(rate_node->name); 1840 - kfree(rate_node); 1841 - return err; 1842 - } 1843 - 1844 - struct devlink_linecard_type { 1845 - const char *type; 1846 - const void *priv; 1847 - }; 1848 - 1849 - static int devlink_nl_linecard_fill(struct sk_buff *msg, 1850 - struct devlink *devlink, 1851 - struct devlink_linecard *linecard, 1852 - enum devlink_command cmd, u32 portid, 1853 - u32 seq, int flags, 1854 - struct netlink_ext_ack *extack) 1855 - { 1856 - struct devlink_linecard_type *linecard_type; 1857 - struct nlattr *attr; 1858 - void *hdr; 1859 - int i; 1860 - 1861 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1862 - if (!hdr) 1863 - return -EMSGSIZE; 1864 - 1865 - if (devlink_nl_put_handle(msg, devlink)) 1866 - goto nla_put_failure; 1867 - if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index)) 1868 - goto nla_put_failure; 1869 - if (nla_put_u8(msg, DEVLINK_ATTR_LINECARD_STATE, linecard->state)) 1870 - goto nla_put_failure; 1871 - if (linecard->type && 1872 - nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, linecard->type)) 1873 - goto nla_put_failure; 1874 - 1875 - if (linecard->types_count) { 1876 - attr = nla_nest_start(msg, 1877 - DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES); 1878 - if (!attr) 1879 - goto nla_put_failure; 1880 - for (i = 0; i < linecard->types_count; i++) { 1881 - linecard_type = &linecard->types[i]; 1882 - if (nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, 1883 - linecard_type->type)) { 1884 - nla_nest_cancel(msg, attr); 1885 - goto nla_put_failure; 1886 - } 1887 - } 1888 - nla_nest_end(msg, attr); 1889 - } 1890 - 1891 - if (linecard->nested_devlink && 1892 - devlink_nl_put_nested_handle(msg, linecard->nested_devlink)) 1893 - goto nla_put_failure; 1894 - 1895 - genlmsg_end(msg, hdr); 1896 - return 0; 1897 - 1898 - nla_put_failure: 1899 - genlmsg_cancel(msg, hdr); 1900 - return -EMSGSIZE; 1901 - } 1902 - 1903 - static void devlink_linecard_notify(struct devlink_linecard *linecard, 1904 - enum devlink_command cmd) 1905 - { 1906 - struct devlink *devlink = linecard->devlink; 1907 - struct sk_buff *msg; 1908 - int err; 1909 - 1910 - WARN_ON(cmd != DEVLINK_CMD_LINECARD_NEW && 1911 - cmd != DEVLINK_CMD_LINECARD_DEL); 1912 - 1913 - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 1914 - return; 1915 - 1916 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1917 - if (!msg) 1918 - return; 1919 - 1920 - err = devlink_nl_linecard_fill(msg, devlink, linecard, cmd, 0, 0, 0, 1921 - NULL); 1922 - if (err) { 1923 - nlmsg_free(msg); 1924 - return; 1925 - } 1926 - 1927 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 1928 - msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 1929 - } 1930 - 1931 - int devlink_nl_linecard_get_doit(struct sk_buff *skb, struct genl_info *info) 1932 - { 1933 - struct devlink *devlink = info->user_ptr[0]; 1934 - struct devlink_linecard *linecard; 1935 - struct sk_buff *msg; 1936 - int err; 1937 - 1938 - linecard = devlink_linecard_get_from_info(devlink, info); 1939 - if (IS_ERR(linecard)) 1940 - return PTR_ERR(linecard); 1941 - 1942 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1943 - if (!msg) 1944 - return -ENOMEM; 1945 - 1946 - mutex_lock(&linecard->state_lock); 1947 - err = devlink_nl_linecard_fill(msg, devlink, linecard, 1948 - DEVLINK_CMD_LINECARD_NEW, 1949 - info->snd_portid, info->snd_seq, 0, 1950 - info->extack); 1951 - mutex_unlock(&linecard->state_lock); 1952 - if (err) { 1953 - nlmsg_free(msg); 1954 - return err; 1955 - } 1956 - 1957 - return genlmsg_reply(msg, info); 1958 - } 1959 - 1960 - static int devlink_nl_linecard_get_dump_one(struct sk_buff *msg, 1961 - struct devlink *devlink, 1962 - struct netlink_callback *cb, 1963 - int flags) 1964 - { 1965 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 1966 - struct devlink_linecard *linecard; 1967 - int idx = 0; 1968 - int err = 0; 1969 - 1970 - list_for_each_entry(linecard, &devlink->linecard_list, list) { 1971 - if (idx < state->idx) { 1972 - idx++; 1973 - continue; 1974 - } 1975 - mutex_lock(&linecard->state_lock); 1976 - err = devlink_nl_linecard_fill(msg, devlink, linecard, 1977 - DEVLINK_CMD_LINECARD_NEW, 1978 - NETLINK_CB(cb->skb).portid, 1979 - cb->nlh->nlmsg_seq, flags, 1980 - cb->extack); 1981 - mutex_unlock(&linecard->state_lock); 1982 - if (err) { 1983 - state->idx = idx; 1984 - break; 1985 - } 1986 - idx++; 1987 - } 1988 - 1989 - return err; 1990 - } 1991 - 1992 - int devlink_nl_linecard_get_dumpit(struct sk_buff *skb, 1993 - struct netlink_callback *cb) 1994 - { 1995 - return devlink_nl_dumpit(skb, cb, devlink_nl_linecard_get_dump_one); 1996 - } 1997 - 1998 - static struct devlink_linecard_type * 1999 - devlink_linecard_type_lookup(struct devlink_linecard *linecard, 2000 - const char *type) 2001 - { 2002 - struct devlink_linecard_type *linecard_type; 2003 - int i; 2004 - 2005 - for (i = 0; i < linecard->types_count; i++) { 2006 - linecard_type = &linecard->types[i]; 2007 - if (!strcmp(type, linecard_type->type)) 2008 - return linecard_type; 2009 - } 2010 - return NULL; 2011 - } 2012 - 2013 - static int devlink_linecard_type_set(struct devlink_linecard *linecard, 2014 - const char *type, 2015 - struct netlink_ext_ack *extack) 2016 - { 2017 - const struct devlink_linecard_ops *ops = linecard->ops; 2018 - struct devlink_linecard_type *linecard_type; 2019 - int err; 2020 - 2021 - mutex_lock(&linecard->state_lock); 2022 - if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) { 2023 - NL_SET_ERR_MSG(extack, "Line card is currently being provisioned"); 2024 - err = -EBUSY; 2025 - goto out; 2026 - } 2027 - if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) { 2028 - NL_SET_ERR_MSG(extack, "Line card is currently being unprovisioned"); 2029 - err = -EBUSY; 2030 - goto out; 2031 - } 2032 - 2033 - linecard_type = devlink_linecard_type_lookup(linecard, type); 2034 - if (!linecard_type) { 2035 - NL_SET_ERR_MSG(extack, "Unsupported line card type provided"); 2036 - err = -EINVAL; 2037 - goto out; 2038 - } 2039 - 2040 - if (linecard->state != DEVLINK_LINECARD_STATE_UNPROVISIONED && 2041 - linecard->state != DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) { 2042 - NL_SET_ERR_MSG(extack, "Line card already provisioned"); 2043 - err = -EBUSY; 2044 - /* Check if the line card is provisioned in the same 2045 - * way the user asks. In case it is, make the operation 2046 - * to return success. 2047 - */ 2048 - if (ops->same_provision && 2049 - ops->same_provision(linecard, linecard->priv, 2050 - linecard_type->type, 2051 - linecard_type->priv)) 2052 - err = 0; 2053 - goto out; 2054 - } 2055 - 2056 - linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING; 2057 - linecard->type = linecard_type->type; 2058 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 2059 - mutex_unlock(&linecard->state_lock); 2060 - err = ops->provision(linecard, linecard->priv, linecard_type->type, 2061 - linecard_type->priv, extack); 2062 - if (err) { 2063 - /* Provisioning failed. Assume the linecard is unprovisioned 2064 - * for future operations. 2065 - */ 2066 - mutex_lock(&linecard->state_lock); 2067 - linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 2068 - linecard->type = NULL; 2069 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 2070 - mutex_unlock(&linecard->state_lock); 2071 - } 2072 - return err; 2073 - 2074 - out: 2075 - mutex_unlock(&linecard->state_lock); 2076 - return err; 2077 - } 2078 - 2079 - static int devlink_linecard_type_unset(struct devlink_linecard *linecard, 2080 - struct netlink_ext_ack *extack) 2081 - { 2082 - int err; 2083 - 2084 - mutex_lock(&linecard->state_lock); 2085 - if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) { 2086 - NL_SET_ERR_MSG(extack, "Line card is currently being provisioned"); 2087 - err = -EBUSY; 2088 - goto out; 2089 - } 2090 - if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) { 2091 - NL_SET_ERR_MSG(extack, "Line card is currently being unprovisioned"); 2092 - err = -EBUSY; 2093 - goto out; 2094 - } 2095 - if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) { 2096 - linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 2097 - linecard->type = NULL; 2098 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 2099 - err = 0; 2100 - goto out; 2101 - } 2102 - 2103 - if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONED) { 2104 - NL_SET_ERR_MSG(extack, "Line card is not provisioned"); 2105 - err = 0; 2106 - goto out; 2107 - } 2108 - linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONING; 2109 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 2110 - mutex_unlock(&linecard->state_lock); 2111 - err = linecard->ops->unprovision(linecard, linecard->priv, 2112 - extack); 2113 - if (err) { 2114 - /* Unprovisioning failed. Assume the linecard is unprovisioned 2115 - * for future operations. 2116 - */ 2117 - mutex_lock(&linecard->state_lock); 2118 - linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 2119 - linecard->type = NULL; 2120 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 2121 - mutex_unlock(&linecard->state_lock); 2122 - } 2123 - return err; 2124 - 2125 - out: 2126 - mutex_unlock(&linecard->state_lock); 2127 - return err; 2128 - } 2129 - 2130 - static int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb, 2131 - struct genl_info *info) 2132 - { 2133 - struct netlink_ext_ack *extack = info->extack; 2134 - struct devlink *devlink = info->user_ptr[0]; 2135 - struct devlink_linecard *linecard; 2136 - int err; 2137 - 2138 - linecard = devlink_linecard_get_from_info(devlink, info); 2139 - if (IS_ERR(linecard)) 2140 - return PTR_ERR(linecard); 2141 - 2142 - if (info->attrs[DEVLINK_ATTR_LINECARD_TYPE]) { 2143 - const char *type; 2144 - 2145 - type = nla_data(info->attrs[DEVLINK_ATTR_LINECARD_TYPE]); 2146 - if (strcmp(type, "")) { 2147 - err = devlink_linecard_type_set(linecard, type, extack); 2148 - if (err) 2149 - return err; 2150 - } else { 2151 - err = devlink_linecard_type_unset(linecard, extack); 2152 - if (err) 2153 - return err; 2154 - } 2155 - } 2156 - 2157 - return 0; 2158 - } 2159 - 2160 - static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 2161 - struct devlink_sb *devlink_sb, 2162 - enum devlink_command cmd, u32 portid, 2163 - u32 seq, int flags) 2164 - { 2165 - void *hdr; 2166 - 2167 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 2168 - if (!hdr) 2169 - return -EMSGSIZE; 2170 - 2171 - if (devlink_nl_put_handle(msg, devlink)) 2172 - goto nla_put_failure; 2173 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 2174 - goto nla_put_failure; 2175 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 2176 - goto nla_put_failure; 2177 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 2178 - devlink_sb->ingress_pools_count)) 2179 - goto nla_put_failure; 2180 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 2181 - devlink_sb->egress_pools_count)) 2182 - goto nla_put_failure; 2183 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 2184 - devlink_sb->ingress_tc_count)) 2185 - goto nla_put_failure; 2186 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 2187 - devlink_sb->egress_tc_count)) 2188 - goto nla_put_failure; 2189 - 2190 - genlmsg_end(msg, hdr); 2191 - return 0; 2192 - 2193 - nla_put_failure: 2194 - genlmsg_cancel(msg, hdr); 2195 - return -EMSGSIZE; 2196 - } 2197 - 2198 - int devlink_nl_sb_get_doit(struct sk_buff *skb, struct genl_info *info) 2199 - { 2200 - struct devlink *devlink = info->user_ptr[0]; 2201 - struct devlink_sb *devlink_sb; 2202 - struct sk_buff *msg; 2203 - int err; 2204 - 2205 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2206 - if (IS_ERR(devlink_sb)) 2207 - return PTR_ERR(devlink_sb); 2208 - 2209 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2210 - if (!msg) 2211 - return -ENOMEM; 2212 - 2213 - err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 2214 - DEVLINK_CMD_SB_NEW, 2215 - info->snd_portid, info->snd_seq, 0); 2216 - if (err) { 2217 - nlmsg_free(msg); 2218 - return err; 2219 - } 2220 - 2221 - return genlmsg_reply(msg, info); 2222 - } 2223 - 2224 - static int 2225 - devlink_nl_sb_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 2226 - struct netlink_callback *cb, int flags) 2227 - { 2228 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 2229 - struct devlink_sb *devlink_sb; 2230 - int idx = 0; 2231 - int err = 0; 2232 - 2233 - list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 2234 - if (idx < state->idx) { 2235 - idx++; 2236 - continue; 2237 - } 2238 - err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 2239 - DEVLINK_CMD_SB_NEW, 2240 - NETLINK_CB(cb->skb).portid, 2241 - cb->nlh->nlmsg_seq, flags); 2242 - if (err) { 2243 - state->idx = idx; 2244 - break; 2245 - } 2246 - idx++; 2247 - } 2248 - 2249 - return err; 2250 - } 2251 - 2252 - int devlink_nl_sb_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 2253 - { 2254 - return devlink_nl_dumpit(skb, cb, devlink_nl_sb_get_dump_one); 2255 - } 2256 - 2257 - static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 2258 - struct devlink_sb *devlink_sb, 2259 - u16 pool_index, enum devlink_command cmd, 2260 - u32 portid, u32 seq, int flags) 2261 - { 2262 - struct devlink_sb_pool_info pool_info; 2263 - void *hdr; 2264 - int err; 2265 - 2266 - err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 2267 - pool_index, &pool_info); 2268 - if (err) 2269 - return err; 2270 - 2271 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 2272 - if (!hdr) 2273 - return -EMSGSIZE; 2274 - 2275 - if (devlink_nl_put_handle(msg, devlink)) 2276 - goto nla_put_failure; 2277 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 2278 - goto nla_put_failure; 2279 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 2280 - goto nla_put_failure; 2281 - if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 2282 - goto nla_put_failure; 2283 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 2284 - goto nla_put_failure; 2285 - if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 2286 - pool_info.threshold_type)) 2287 - goto nla_put_failure; 2288 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE, 2289 - pool_info.cell_size)) 2290 - goto nla_put_failure; 2291 - 2292 - genlmsg_end(msg, hdr); 2293 - return 0; 2294 - 2295 - nla_put_failure: 2296 - genlmsg_cancel(msg, hdr); 2297 - return -EMSGSIZE; 2298 - } 2299 - 2300 - int devlink_nl_sb_pool_get_doit(struct sk_buff *skb, struct genl_info *info) 2301 - { 2302 - struct devlink *devlink = info->user_ptr[0]; 2303 - struct devlink_sb *devlink_sb; 2304 - struct sk_buff *msg; 2305 - u16 pool_index; 2306 - int err; 2307 - 2308 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2309 - if (IS_ERR(devlink_sb)) 2310 - return PTR_ERR(devlink_sb); 2311 - 2312 - err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 2313 - &pool_index); 2314 - if (err) 2315 - return err; 2316 - 2317 - if (!devlink->ops->sb_pool_get) 2318 - return -EOPNOTSUPP; 2319 - 2320 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2321 - if (!msg) 2322 - return -ENOMEM; 2323 - 2324 - err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 2325 - DEVLINK_CMD_SB_POOL_NEW, 2326 - info->snd_portid, info->snd_seq, 0); 2327 - if (err) { 2328 - nlmsg_free(msg); 2329 - return err; 2330 - } 2331 - 2332 - return genlmsg_reply(msg, info); 2333 - } 2334 - 2335 - static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 2336 - struct devlink *devlink, 2337 - struct devlink_sb *devlink_sb, 2338 - u32 portid, u32 seq, int flags) 2339 - { 2340 - u16 pool_count = devlink_sb_pool_count(devlink_sb); 2341 - u16 pool_index; 2342 - int err; 2343 - 2344 - for (pool_index = 0; pool_index < pool_count; pool_index++) { 2345 - if (*p_idx < start) { 2346 - (*p_idx)++; 2347 - continue; 2348 - } 2349 - err = devlink_nl_sb_pool_fill(msg, devlink, 2350 - devlink_sb, 2351 - pool_index, 2352 - DEVLINK_CMD_SB_POOL_NEW, 2353 - portid, seq, flags); 2354 - if (err) 2355 - return err; 2356 - (*p_idx)++; 2357 - } 2358 - return 0; 2359 - } 2360 - 2361 - static int 2362 - devlink_nl_sb_pool_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 2363 - struct netlink_callback *cb, int flags) 2364 - { 2365 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 2366 - struct devlink_sb *devlink_sb; 2367 - int err = 0; 2368 - int idx = 0; 2369 - 2370 - if (!devlink->ops->sb_pool_get) 2371 - return 0; 2372 - 2373 - list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 2374 - err = __sb_pool_get_dumpit(msg, state->idx, &idx, 2375 - devlink, devlink_sb, 2376 - NETLINK_CB(cb->skb).portid, 2377 - cb->nlh->nlmsg_seq, flags); 2378 - if (err == -EOPNOTSUPP) { 2379 - err = 0; 2380 - } else if (err) { 2381 - state->idx = idx; 2382 - break; 2383 - } 2384 - } 2385 - 2386 - return err; 2387 - } 2388 - 2389 - int devlink_nl_sb_pool_get_dumpit(struct sk_buff *skb, 2390 - struct netlink_callback *cb) 2391 - { 2392 - return devlink_nl_dumpit(skb, cb, devlink_nl_sb_pool_get_dump_one); 2393 - } 2394 - 2395 - static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 2396 - u16 pool_index, u32 size, 2397 - enum devlink_sb_threshold_type threshold_type, 2398 - struct netlink_ext_ack *extack) 2399 - 2400 - { 2401 - const struct devlink_ops *ops = devlink->ops; 2402 - 2403 - if (ops->sb_pool_set) 2404 - return ops->sb_pool_set(devlink, sb_index, pool_index, 2405 - size, threshold_type, extack); 2406 - return -EOPNOTSUPP; 2407 - } 2408 - 2409 - static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, 2410 - struct genl_info *info) 2411 - { 2412 - struct devlink *devlink = info->user_ptr[0]; 2413 - enum devlink_sb_threshold_type threshold_type; 2414 - struct devlink_sb *devlink_sb; 2415 - u16 pool_index; 2416 - u32 size; 2417 - int err; 2418 - 2419 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2420 - if (IS_ERR(devlink_sb)) 2421 - return PTR_ERR(devlink_sb); 2422 - 2423 - err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 2424 - &pool_index); 2425 - if (err) 2426 - return err; 2427 - 2428 - err = devlink_sb_th_type_get_from_info(info, &threshold_type); 2429 - if (err) 2430 - return err; 2431 - 2432 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE)) 2433 - return -EINVAL; 2434 - 2435 - size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 2436 - return devlink_sb_pool_set(devlink, devlink_sb->index, 2437 - pool_index, size, threshold_type, 2438 - info->extack); 2439 - } 2440 - 2441 - static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 2442 - struct devlink *devlink, 2443 - struct devlink_port *devlink_port, 2444 - struct devlink_sb *devlink_sb, 2445 - u16 pool_index, 2446 - enum devlink_command cmd, 2447 - u32 portid, u32 seq, int flags) 2448 - { 2449 - const struct devlink_ops *ops = devlink->ops; 2450 - u32 threshold; 2451 - void *hdr; 2452 - int err; 2453 - 2454 - err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 2455 - pool_index, &threshold); 2456 - if (err) 2457 - return err; 2458 - 2459 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 2460 - if (!hdr) 2461 - return -EMSGSIZE; 2462 - 2463 - if (devlink_nl_put_handle(msg, devlink)) 2464 - goto nla_put_failure; 2465 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 2466 - goto nla_put_failure; 2467 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 2468 - goto nla_put_failure; 2469 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 2470 - goto nla_put_failure; 2471 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 2472 - goto nla_put_failure; 2473 - 2474 - if (ops->sb_occ_port_pool_get) { 2475 - u32 cur; 2476 - u32 max; 2477 - 2478 - err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 2479 - pool_index, &cur, &max); 2480 - if (err && err != -EOPNOTSUPP) 2481 - goto sb_occ_get_failure; 2482 - if (!err) { 2483 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 2484 - goto nla_put_failure; 2485 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 2486 - goto nla_put_failure; 2487 - } 2488 - } 2489 - 2490 - genlmsg_end(msg, hdr); 2491 - return 0; 2492 - 2493 - nla_put_failure: 2494 - err = -EMSGSIZE; 2495 - sb_occ_get_failure: 2496 - genlmsg_cancel(msg, hdr); 2497 - return err; 2498 - } 2499 - 2500 - int devlink_nl_sb_port_pool_get_doit(struct sk_buff *skb, 2501 - struct genl_info *info) 2502 - { 2503 - struct devlink_port *devlink_port = info->user_ptr[1]; 2504 - struct devlink *devlink = devlink_port->devlink; 2505 - struct devlink_sb *devlink_sb; 2506 - struct sk_buff *msg; 2507 - u16 pool_index; 2508 - int err; 2509 - 2510 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2511 - if (IS_ERR(devlink_sb)) 2512 - return PTR_ERR(devlink_sb); 2513 - 2514 - err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 2515 - &pool_index); 2516 - if (err) 2517 - return err; 2518 - 2519 - if (!devlink->ops->sb_port_pool_get) 2520 - return -EOPNOTSUPP; 2521 - 2522 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2523 - if (!msg) 2524 - return -ENOMEM; 2525 - 2526 - err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 2527 - devlink_sb, pool_index, 2528 - DEVLINK_CMD_SB_PORT_POOL_NEW, 2529 - info->snd_portid, info->snd_seq, 0); 2530 - if (err) { 2531 - nlmsg_free(msg); 2532 - return err; 2533 - } 2534 - 2535 - return genlmsg_reply(msg, info); 2536 - } 2537 - 2538 - static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 2539 - struct devlink *devlink, 2540 - struct devlink_sb *devlink_sb, 2541 - u32 portid, u32 seq, int flags) 2542 - { 2543 - struct devlink_port *devlink_port; 2544 - u16 pool_count = devlink_sb_pool_count(devlink_sb); 2545 - unsigned long port_index; 2546 - u16 pool_index; 2547 - int err; 2548 - 2549 - xa_for_each(&devlink->ports, port_index, devlink_port) { 2550 - for (pool_index = 0; pool_index < pool_count; pool_index++) { 2551 - if (*p_idx < start) { 2552 - (*p_idx)++; 2553 - continue; 2554 - } 2555 - err = devlink_nl_sb_port_pool_fill(msg, devlink, 2556 - devlink_port, 2557 - devlink_sb, 2558 - pool_index, 2559 - DEVLINK_CMD_SB_PORT_POOL_NEW, 2560 - portid, seq, flags); 2561 - if (err) 2562 - return err; 2563 - (*p_idx)++; 2564 - } 2565 - } 2566 - return 0; 2567 - } 2568 - 2569 - static int 2570 - devlink_nl_sb_port_pool_get_dump_one(struct sk_buff *msg, 2571 - struct devlink *devlink, 2572 - struct netlink_callback *cb, int flags) 2573 - { 2574 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 2575 - struct devlink_sb *devlink_sb; 2576 - int idx = 0; 2577 - int err = 0; 2578 - 2579 - if (!devlink->ops->sb_port_pool_get) 2580 - return 0; 2581 - 2582 - list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 2583 - err = __sb_port_pool_get_dumpit(msg, state->idx, &idx, 2584 - devlink, devlink_sb, 2585 - NETLINK_CB(cb->skb).portid, 2586 - cb->nlh->nlmsg_seq, flags); 2587 - if (err == -EOPNOTSUPP) { 2588 - err = 0; 2589 - } else if (err) { 2590 - state->idx = idx; 2591 - break; 2592 - } 2593 - } 2594 - 2595 - return err; 2596 - } 2597 - 2598 - int devlink_nl_sb_port_pool_get_dumpit(struct sk_buff *skb, 2599 - struct netlink_callback *cb) 2600 - { 2601 - return devlink_nl_dumpit(skb, cb, devlink_nl_sb_port_pool_get_dump_one); 2602 - } 2603 - 2604 - static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 2605 - unsigned int sb_index, u16 pool_index, 2606 - u32 threshold, 2607 - struct netlink_ext_ack *extack) 2608 - 2609 - { 2610 - const struct devlink_ops *ops = devlink_port->devlink->ops; 2611 - 2612 - if (ops->sb_port_pool_set) 2613 - return ops->sb_port_pool_set(devlink_port, sb_index, 2614 - pool_index, threshold, extack); 2615 - return -EOPNOTSUPP; 2616 - } 2617 - 2618 - static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 2619 - struct genl_info *info) 2620 - { 2621 - struct devlink_port *devlink_port = info->user_ptr[1]; 2622 - struct devlink *devlink = info->user_ptr[0]; 2623 - struct devlink_sb *devlink_sb; 2624 - u16 pool_index; 2625 - u32 threshold; 2626 - int err; 2627 - 2628 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2629 - if (IS_ERR(devlink_sb)) 2630 - return PTR_ERR(devlink_sb); 2631 - 2632 - err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 2633 - &pool_index); 2634 - if (err) 2635 - return err; 2636 - 2637 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD)) 2638 - return -EINVAL; 2639 - 2640 - threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 2641 - return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 2642 - pool_index, threshold, info->extack); 2643 - } 2644 - 2645 - static int 2646 - devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 2647 - struct devlink_port *devlink_port, 2648 - struct devlink_sb *devlink_sb, u16 tc_index, 2649 - enum devlink_sb_pool_type pool_type, 2650 - enum devlink_command cmd, 2651 - u32 portid, u32 seq, int flags) 2652 - { 2653 - const struct devlink_ops *ops = devlink->ops; 2654 - u16 pool_index; 2655 - u32 threshold; 2656 - void *hdr; 2657 - int err; 2658 - 2659 - err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 2660 - tc_index, pool_type, 2661 - &pool_index, &threshold); 2662 - if (err) 2663 - return err; 2664 - 2665 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 2666 - if (!hdr) 2667 - return -EMSGSIZE; 2668 - 2669 - if (devlink_nl_put_handle(msg, devlink)) 2670 - goto nla_put_failure; 2671 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 2672 - goto nla_put_failure; 2673 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 2674 - goto nla_put_failure; 2675 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 2676 - goto nla_put_failure; 2677 - if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 2678 - goto nla_put_failure; 2679 - if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 2680 - goto nla_put_failure; 2681 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 2682 - goto nla_put_failure; 2683 - 2684 - if (ops->sb_occ_tc_port_bind_get) { 2685 - u32 cur; 2686 - u32 max; 2687 - 2688 - err = ops->sb_occ_tc_port_bind_get(devlink_port, 2689 - devlink_sb->index, 2690 - tc_index, pool_type, 2691 - &cur, &max); 2692 - if (err && err != -EOPNOTSUPP) 2693 - return err; 2694 - if (!err) { 2695 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 2696 - goto nla_put_failure; 2697 - if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 2698 - goto nla_put_failure; 2699 - } 2700 - } 2701 - 2702 - genlmsg_end(msg, hdr); 2703 - return 0; 2704 - 2705 - nla_put_failure: 2706 - genlmsg_cancel(msg, hdr); 2707 - return -EMSGSIZE; 2708 - } 2709 - 2710 - int devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 2711 - struct genl_info *info) 2712 - { 2713 - struct devlink_port *devlink_port = info->user_ptr[1]; 2714 - struct devlink *devlink = devlink_port->devlink; 2715 - struct devlink_sb *devlink_sb; 2716 - struct sk_buff *msg; 2717 - enum devlink_sb_pool_type pool_type; 2718 - u16 tc_index; 2719 - int err; 2720 - 2721 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2722 - if (IS_ERR(devlink_sb)) 2723 - return PTR_ERR(devlink_sb); 2724 - 2725 - err = devlink_sb_pool_type_get_from_info(info, &pool_type); 2726 - if (err) 2727 - return err; 2728 - 2729 - err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 2730 - pool_type, &tc_index); 2731 - if (err) 2732 - return err; 2733 - 2734 - if (!devlink->ops->sb_tc_pool_bind_get) 2735 - return -EOPNOTSUPP; 2736 - 2737 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2738 - if (!msg) 2739 - return -ENOMEM; 2740 - 2741 - err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 2742 - devlink_sb, tc_index, pool_type, 2743 - DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 2744 - info->snd_portid, 2745 - info->snd_seq, 0); 2746 - if (err) { 2747 - nlmsg_free(msg); 2748 - return err; 2749 - } 2750 - 2751 - return genlmsg_reply(msg, info); 2752 - } 2753 - 2754 - static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 2755 - int start, int *p_idx, 2756 - struct devlink *devlink, 2757 - struct devlink_sb *devlink_sb, 2758 - u32 portid, u32 seq, int flags) 2759 - { 2760 - struct devlink_port *devlink_port; 2761 - unsigned long port_index; 2762 - u16 tc_index; 2763 - int err; 2764 - 2765 - xa_for_each(&devlink->ports, port_index, devlink_port) { 2766 - for (tc_index = 0; 2767 - tc_index < devlink_sb->ingress_tc_count; tc_index++) { 2768 - if (*p_idx < start) { 2769 - (*p_idx)++; 2770 - continue; 2771 - } 2772 - err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 2773 - devlink_port, 2774 - devlink_sb, 2775 - tc_index, 2776 - DEVLINK_SB_POOL_TYPE_INGRESS, 2777 - DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 2778 - portid, seq, 2779 - flags); 2780 - if (err) 2781 - return err; 2782 - (*p_idx)++; 2783 - } 2784 - for (tc_index = 0; 2785 - tc_index < devlink_sb->egress_tc_count; tc_index++) { 2786 - if (*p_idx < start) { 2787 - (*p_idx)++; 2788 - continue; 2789 - } 2790 - err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 2791 - devlink_port, 2792 - devlink_sb, 2793 - tc_index, 2794 - DEVLINK_SB_POOL_TYPE_EGRESS, 2795 - DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 2796 - portid, seq, 2797 - flags); 2798 - if (err) 2799 - return err; 2800 - (*p_idx)++; 2801 - } 2802 - } 2803 - return 0; 2804 - } 2805 - 2806 - static int devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff *msg, 2807 - struct devlink *devlink, 2808 - struct netlink_callback *cb, 2809 - int flags) 2810 - { 2811 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 2812 - struct devlink_sb *devlink_sb; 2813 - int idx = 0; 2814 - int err = 0; 2815 - 2816 - if (!devlink->ops->sb_tc_pool_bind_get) 2817 - return 0; 2818 - 2819 - list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 2820 - err = __sb_tc_pool_bind_get_dumpit(msg, state->idx, &idx, 2821 - devlink, devlink_sb, 2822 - NETLINK_CB(cb->skb).portid, 2823 - cb->nlh->nlmsg_seq, flags); 2824 - if (err == -EOPNOTSUPP) { 2825 - err = 0; 2826 - } else if (err) { 2827 - state->idx = idx; 2828 - break; 2829 - } 2830 - } 2831 - 2832 - return err; 2833 - } 2834 - 2835 - int devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff *skb, 2836 - struct netlink_callback *cb) 2837 - { 2838 - return devlink_nl_dumpit(skb, cb, 2839 - devlink_nl_sb_tc_pool_bind_get_dump_one); 2840 - } 2841 - 2842 - static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 2843 - unsigned int sb_index, u16 tc_index, 2844 - enum devlink_sb_pool_type pool_type, 2845 - u16 pool_index, u32 threshold, 2846 - struct netlink_ext_ack *extack) 2847 - 2848 - { 2849 - const struct devlink_ops *ops = devlink_port->devlink->ops; 2850 - 2851 - if (ops->sb_tc_pool_bind_set) 2852 - return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 2853 - tc_index, pool_type, 2854 - pool_index, threshold, extack); 2855 - return -EOPNOTSUPP; 2856 - } 2857 - 2858 - static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 2859 - struct genl_info *info) 2860 - { 2861 - struct devlink_port *devlink_port = info->user_ptr[1]; 2862 - struct devlink *devlink = info->user_ptr[0]; 2863 - enum devlink_sb_pool_type pool_type; 2864 - struct devlink_sb *devlink_sb; 2865 - u16 tc_index; 2866 - u16 pool_index; 2867 - u32 threshold; 2868 - int err; 2869 - 2870 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2871 - if (IS_ERR(devlink_sb)) 2872 - return PTR_ERR(devlink_sb); 2873 - 2874 - err = devlink_sb_pool_type_get_from_info(info, &pool_type); 2875 - if (err) 2876 - return err; 2877 - 2878 - err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 2879 - pool_type, &tc_index); 2880 - if (err) 2881 - return err; 2882 - 2883 - err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 2884 - &pool_index); 2885 - if (err) 2886 - return err; 2887 - 2888 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD)) 2889 - return -EINVAL; 2890 - 2891 - threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 2892 - return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 2893 - tc_index, pool_type, 2894 - pool_index, threshold, info->extack); 2895 - } 2896 - 2897 - static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 2898 - struct genl_info *info) 2899 - { 2900 - struct devlink *devlink = info->user_ptr[0]; 2901 - const struct devlink_ops *ops = devlink->ops; 2902 - struct devlink_sb *devlink_sb; 2903 - 2904 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2905 - if (IS_ERR(devlink_sb)) 2906 - return PTR_ERR(devlink_sb); 2907 - 2908 - if (ops->sb_occ_snapshot) 2909 - return ops->sb_occ_snapshot(devlink, devlink_sb->index); 2910 - return -EOPNOTSUPP; 2911 - } 2912 - 2913 - static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 2914 - struct genl_info *info) 2915 - { 2916 - struct devlink *devlink = info->user_ptr[0]; 2917 - const struct devlink_ops *ops = devlink->ops; 2918 - struct devlink_sb *devlink_sb; 2919 - 2920 - devlink_sb = devlink_sb_get_from_info(devlink, info); 2921 - if (IS_ERR(devlink_sb)) 2922 - return PTR_ERR(devlink_sb); 2923 - 2924 - if (ops->sb_occ_max_clear) 2925 - return ops->sb_occ_max_clear(devlink, devlink_sb->index); 2926 - return -EOPNOTSUPP; 2927 - } 2928 - 2929 - int devlink_rate_nodes_check(struct devlink *devlink, u16 mode, 2930 - struct netlink_ext_ack *extack) 2931 - { 2932 - struct devlink_rate *devlink_rate; 2933 - 2934 - list_for_each_entry(devlink_rate, &devlink->rate_list, list) 2935 - if (devlink_rate_is_node(devlink_rate)) { 2936 - NL_SET_ERR_MSG(extack, "Rate node(s) exists."); 2937 - return -EBUSY; 2938 - } 2939 - return 0; 2940 - } 2941 - 2942 - int devlink_dpipe_match_put(struct sk_buff *skb, 2943 - struct devlink_dpipe_match *match) 2944 - { 2945 - struct devlink_dpipe_header *header = match->header; 2946 - struct devlink_dpipe_field *field = &header->fields[match->field_id]; 2947 - struct nlattr *match_attr; 2948 - 2949 - match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH); 2950 - if (!match_attr) 2951 - return -EMSGSIZE; 2952 - 2953 - if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 2954 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 2955 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2956 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2957 - nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2958 - goto nla_put_failure; 2959 - 2960 - nla_nest_end(skb, match_attr); 2961 - return 0; 2962 - 2963 - nla_put_failure: 2964 - nla_nest_cancel(skb, match_attr); 2965 - return -EMSGSIZE; 2966 - } 2967 - EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 2968 - 2969 - static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 2970 - struct sk_buff *skb) 2971 - { 2972 - struct nlattr *matches_attr; 2973 - 2974 - matches_attr = nla_nest_start_noflag(skb, 2975 - DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 2976 - if (!matches_attr) 2977 - return -EMSGSIZE; 2978 - 2979 - if (table->table_ops->matches_dump(table->priv, skb)) 2980 - goto nla_put_failure; 2981 - 2982 - nla_nest_end(skb, matches_attr); 2983 - return 0; 2984 - 2985 - nla_put_failure: 2986 - nla_nest_cancel(skb, matches_attr); 2987 - return -EMSGSIZE; 2988 - } 2989 - 2990 - int devlink_dpipe_action_put(struct sk_buff *skb, 2991 - struct devlink_dpipe_action *action) 2992 - { 2993 - struct devlink_dpipe_header *header = action->header; 2994 - struct devlink_dpipe_field *field = &header->fields[action->field_id]; 2995 - struct nlattr *action_attr; 2996 - 2997 - action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION); 2998 - if (!action_attr) 2999 - return -EMSGSIZE; 3000 - 3001 - if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 3002 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 3003 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 3004 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 3005 - nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 3006 - goto nla_put_failure; 3007 - 3008 - nla_nest_end(skb, action_attr); 3009 - return 0; 3010 - 3011 - nla_put_failure: 3012 - nla_nest_cancel(skb, action_attr); 3013 - return -EMSGSIZE; 3014 - } 3015 - EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 3016 - 3017 - static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 3018 - struct sk_buff *skb) 3019 - { 3020 - struct nlattr *actions_attr; 3021 - 3022 - actions_attr = nla_nest_start_noflag(skb, 3023 - DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 3024 - if (!actions_attr) 3025 - return -EMSGSIZE; 3026 - 3027 - if (table->table_ops->actions_dump(table->priv, skb)) 3028 - goto nla_put_failure; 3029 - 3030 - nla_nest_end(skb, actions_attr); 3031 - return 0; 3032 - 3033 - nla_put_failure: 3034 - nla_nest_cancel(skb, actions_attr); 3035 - return -EMSGSIZE; 3036 - } 3037 - 3038 - static int devlink_dpipe_table_put(struct sk_buff *skb, 3039 - struct devlink_dpipe_table *table) 3040 - { 3041 - struct nlattr *table_attr; 3042 - u64 table_size; 3043 - 3044 - table_size = table->table_ops->size_get(table->priv); 3045 - table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE); 3046 - if (!table_attr) 3047 - return -EMSGSIZE; 3048 - 3049 - if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 3050 - nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 3051 - DEVLINK_ATTR_PAD)) 3052 - goto nla_put_failure; 3053 - if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 3054 - table->counters_enabled)) 3055 - goto nla_put_failure; 3056 - 3057 - if (table->resource_valid) { 3058 - if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 3059 - table->resource_id, DEVLINK_ATTR_PAD) || 3060 - nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 3061 - table->resource_units, DEVLINK_ATTR_PAD)) 3062 - goto nla_put_failure; 3063 - } 3064 - if (devlink_dpipe_matches_put(table, skb)) 3065 - goto nla_put_failure; 3066 - 3067 - if (devlink_dpipe_actions_put(table, skb)) 3068 - goto nla_put_failure; 3069 - 3070 - nla_nest_end(skb, table_attr); 3071 - return 0; 3072 - 3073 - nla_put_failure: 3074 - nla_nest_cancel(skb, table_attr); 3075 - return -EMSGSIZE; 3076 - } 3077 - 3078 - static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 3079 - struct genl_info *info) 3080 - { 3081 - int err; 3082 - 3083 - if (*pskb) { 3084 - err = genlmsg_reply(*pskb, info); 3085 - if (err) 3086 - return err; 3087 - } 3088 - *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 3089 - if (!*pskb) 3090 - return -ENOMEM; 3091 - return 0; 3092 - } 3093 - 3094 - static int devlink_dpipe_tables_fill(struct genl_info *info, 3095 - enum devlink_command cmd, int flags, 3096 - struct list_head *dpipe_tables, 3097 - const char *table_name) 3098 - { 3099 - struct devlink *devlink = info->user_ptr[0]; 3100 - struct devlink_dpipe_table *table; 3101 - struct nlattr *tables_attr; 3102 - struct sk_buff *skb = NULL; 3103 - struct nlmsghdr *nlh; 3104 - bool incomplete; 3105 - void *hdr; 3106 - int i; 3107 - int err; 3108 - 3109 - table = list_first_entry(dpipe_tables, 3110 - struct devlink_dpipe_table, list); 3111 - start_again: 3112 - err = devlink_dpipe_send_and_alloc_skb(&skb, info); 3113 - if (err) 3114 - return err; 3115 - 3116 - hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 3117 - &devlink_nl_family, NLM_F_MULTI, cmd); 3118 - if (!hdr) { 3119 - nlmsg_free(skb); 3120 - return -EMSGSIZE; 3121 - } 3122 - 3123 - if (devlink_nl_put_handle(skb, devlink)) 3124 - goto nla_put_failure; 3125 - tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES); 3126 - if (!tables_attr) 3127 - goto nla_put_failure; 3128 - 3129 - i = 0; 3130 - incomplete = false; 3131 - list_for_each_entry_from(table, dpipe_tables, list) { 3132 - if (!table_name) { 3133 - err = devlink_dpipe_table_put(skb, table); 3134 - if (err) { 3135 - if (!i) 3136 - goto err_table_put; 3137 - incomplete = true; 3138 - break; 3139 - } 3140 - } else { 3141 - if (!strcmp(table->name, table_name)) { 3142 - err = devlink_dpipe_table_put(skb, table); 3143 - if (err) 3144 - break; 3145 - } 3146 - } 3147 - i++; 3148 - } 3149 - 3150 - nla_nest_end(skb, tables_attr); 3151 - genlmsg_end(skb, hdr); 3152 - if (incomplete) 3153 - goto start_again; 3154 - 3155 - send_done: 3156 - nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 3157 - NLMSG_DONE, 0, flags | NLM_F_MULTI); 3158 - if (!nlh) { 3159 - err = devlink_dpipe_send_and_alloc_skb(&skb, info); 3160 - if (err) 3161 - return err; 3162 - goto send_done; 3163 - } 3164 - 3165 - return genlmsg_reply(skb, info); 3166 - 3167 - nla_put_failure: 3168 - err = -EMSGSIZE; 3169 - err_table_put: 3170 - nlmsg_free(skb); 3171 - return err; 3172 - } 3173 - 3174 - static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 3175 - struct genl_info *info) 3176 - { 3177 - struct devlink *devlink = info->user_ptr[0]; 3178 - const char *table_name = NULL; 3179 - 3180 - if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 3181 - table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 3182 - 3183 - return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 3184 - &devlink->dpipe_table_list, 3185 - table_name); 3186 - } 3187 - 3188 - static int devlink_dpipe_value_put(struct sk_buff *skb, 3189 - struct devlink_dpipe_value *value) 3190 - { 3191 - if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 3192 - value->value_size, value->value)) 3193 - return -EMSGSIZE; 3194 - if (value->mask) 3195 - if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 3196 - value->value_size, value->mask)) 3197 - return -EMSGSIZE; 3198 - if (value->mapping_valid) 3199 - if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 3200 - value->mapping_value)) 3201 - return -EMSGSIZE; 3202 - return 0; 3203 - } 3204 - 3205 - static int devlink_dpipe_action_value_put(struct sk_buff *skb, 3206 - struct devlink_dpipe_value *value) 3207 - { 3208 - if (!value->action) 3209 - return -EINVAL; 3210 - if (devlink_dpipe_action_put(skb, value->action)) 3211 - return -EMSGSIZE; 3212 - if (devlink_dpipe_value_put(skb, value)) 3213 - return -EMSGSIZE; 3214 - return 0; 3215 - } 3216 - 3217 - static int devlink_dpipe_action_values_put(struct sk_buff *skb, 3218 - struct devlink_dpipe_value *values, 3219 - unsigned int values_count) 3220 - { 3221 - struct nlattr *action_attr; 3222 - int i; 3223 - int err; 3224 - 3225 - for (i = 0; i < values_count; i++) { 3226 - action_attr = nla_nest_start_noflag(skb, 3227 - DEVLINK_ATTR_DPIPE_ACTION_VALUE); 3228 - if (!action_attr) 3229 - return -EMSGSIZE; 3230 - err = devlink_dpipe_action_value_put(skb, &values[i]); 3231 - if (err) 3232 - goto err_action_value_put; 3233 - nla_nest_end(skb, action_attr); 3234 - } 3235 - return 0; 3236 - 3237 - err_action_value_put: 3238 - nla_nest_cancel(skb, action_attr); 3239 - return err; 3240 - } 3241 - 3242 - static int devlink_dpipe_match_value_put(struct sk_buff *skb, 3243 - struct devlink_dpipe_value *value) 3244 - { 3245 - if (!value->match) 3246 - return -EINVAL; 3247 - if (devlink_dpipe_match_put(skb, value->match)) 3248 - return -EMSGSIZE; 3249 - if (devlink_dpipe_value_put(skb, value)) 3250 - return -EMSGSIZE; 3251 - return 0; 3252 - } 3253 - 3254 - static int devlink_dpipe_match_values_put(struct sk_buff *skb, 3255 - struct devlink_dpipe_value *values, 3256 - unsigned int values_count) 3257 - { 3258 - struct nlattr *match_attr; 3259 - int i; 3260 - int err; 3261 - 3262 - for (i = 0; i < values_count; i++) { 3263 - match_attr = nla_nest_start_noflag(skb, 3264 - DEVLINK_ATTR_DPIPE_MATCH_VALUE); 3265 - if (!match_attr) 3266 - return -EMSGSIZE; 3267 - err = devlink_dpipe_match_value_put(skb, &values[i]); 3268 - if (err) 3269 - goto err_match_value_put; 3270 - nla_nest_end(skb, match_attr); 3271 - } 3272 - return 0; 3273 - 3274 - err_match_value_put: 3275 - nla_nest_cancel(skb, match_attr); 3276 - return err; 3277 - } 3278 - 3279 - static int devlink_dpipe_entry_put(struct sk_buff *skb, 3280 - struct devlink_dpipe_entry *entry) 3281 - { 3282 - struct nlattr *entry_attr, *matches_attr, *actions_attr; 3283 - int err; 3284 - 3285 - entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY); 3286 - if (!entry_attr) 3287 - return -EMSGSIZE; 3288 - 3289 - if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 3290 - DEVLINK_ATTR_PAD)) 3291 - goto nla_put_failure; 3292 - if (entry->counter_valid) 3293 - if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 3294 - entry->counter, DEVLINK_ATTR_PAD)) 3295 - goto nla_put_failure; 3296 - 3297 - matches_attr = nla_nest_start_noflag(skb, 3298 - DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 3299 - if (!matches_attr) 3300 - goto nla_put_failure; 3301 - 3302 - err = devlink_dpipe_match_values_put(skb, entry->match_values, 3303 - entry->match_values_count); 3304 - if (err) { 3305 - nla_nest_cancel(skb, matches_attr); 3306 - goto err_match_values_put; 3307 - } 3308 - nla_nest_end(skb, matches_attr); 3309 - 3310 - actions_attr = nla_nest_start_noflag(skb, 3311 - DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 3312 - if (!actions_attr) 3313 - goto nla_put_failure; 3314 - 3315 - err = devlink_dpipe_action_values_put(skb, entry->action_values, 3316 - entry->action_values_count); 3317 - if (err) { 3318 - nla_nest_cancel(skb, actions_attr); 3319 - goto err_action_values_put; 3320 - } 3321 - nla_nest_end(skb, actions_attr); 3322 - 3323 - nla_nest_end(skb, entry_attr); 3324 - return 0; 3325 - 3326 - nla_put_failure: 3327 - err = -EMSGSIZE; 3328 - err_match_values_put: 3329 - err_action_values_put: 3330 - nla_nest_cancel(skb, entry_attr); 3331 - return err; 3332 - } 3333 - 3334 - static struct devlink_dpipe_table * 3335 - devlink_dpipe_table_find(struct list_head *dpipe_tables, 3336 - const char *table_name, struct devlink *devlink) 3337 - { 3338 - struct devlink_dpipe_table *table; 3339 - list_for_each_entry_rcu(table, dpipe_tables, list, 3340 - lockdep_is_held(&devlink->lock)) { 3341 - if (!strcmp(table->name, table_name)) 3342 - return table; 3343 - } 3344 - return NULL; 3345 - } 3346 - 3347 - int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 3348 - { 3349 - struct devlink *devlink; 3350 - int err; 3351 - 3352 - err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 3353 - dump_ctx->info); 3354 - if (err) 3355 - return err; 3356 - 3357 - dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 3358 - dump_ctx->info->snd_portid, 3359 - dump_ctx->info->snd_seq, 3360 - &devlink_nl_family, NLM_F_MULTI, 3361 - dump_ctx->cmd); 3362 - if (!dump_ctx->hdr) 3363 - goto nla_put_failure; 3364 - 3365 - devlink = dump_ctx->info->user_ptr[0]; 3366 - if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 3367 - goto nla_put_failure; 3368 - dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb, 3369 - DEVLINK_ATTR_DPIPE_ENTRIES); 3370 - if (!dump_ctx->nest) 3371 - goto nla_put_failure; 3372 - return 0; 3373 - 3374 - nla_put_failure: 3375 - nlmsg_free(dump_ctx->skb); 3376 - return -EMSGSIZE; 3377 - } 3378 - EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 3379 - 3380 - int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 3381 - struct devlink_dpipe_entry *entry) 3382 - { 3383 - return devlink_dpipe_entry_put(dump_ctx->skb, entry); 3384 - } 3385 - EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 3386 - 3387 - int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 3388 - { 3389 - nla_nest_end(dump_ctx->skb, dump_ctx->nest); 3390 - genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 3391 - return 0; 3392 - } 3393 - EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 3394 - 3395 - void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 3396 - 3397 - { 3398 - unsigned int value_count, value_index; 3399 - struct devlink_dpipe_value *value; 3400 - 3401 - value = entry->action_values; 3402 - value_count = entry->action_values_count; 3403 - for (value_index = 0; value_index < value_count; value_index++) { 3404 - kfree(value[value_index].value); 3405 - kfree(value[value_index].mask); 3406 - } 3407 - 3408 - value = entry->match_values; 3409 - value_count = entry->match_values_count; 3410 - for (value_index = 0; value_index < value_count; value_index++) { 3411 - kfree(value[value_index].value); 3412 - kfree(value[value_index].mask); 3413 - } 3414 - } 3415 - EXPORT_SYMBOL_GPL(devlink_dpipe_entry_clear); 3416 - 3417 - static int devlink_dpipe_entries_fill(struct genl_info *info, 3418 - enum devlink_command cmd, int flags, 3419 - struct devlink_dpipe_table *table) 3420 - { 3421 - struct devlink_dpipe_dump_ctx dump_ctx; 3422 - struct nlmsghdr *nlh; 3423 - int err; 3424 - 3425 - dump_ctx.skb = NULL; 3426 - dump_ctx.cmd = cmd; 3427 - dump_ctx.info = info; 3428 - 3429 - err = table->table_ops->entries_dump(table->priv, 3430 - table->counters_enabled, 3431 - &dump_ctx); 3432 - if (err) 3433 - return err; 3434 - 3435 - send_done: 3436 - nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 3437 - NLMSG_DONE, 0, flags | NLM_F_MULTI); 3438 - if (!nlh) { 3439 - err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 3440 - if (err) 3441 - return err; 3442 - goto send_done; 3443 - } 3444 - return genlmsg_reply(dump_ctx.skb, info); 3445 - } 3446 - 3447 - static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 3448 - struct genl_info *info) 3449 - { 3450 - struct devlink *devlink = info->user_ptr[0]; 3451 - struct devlink_dpipe_table *table; 3452 - const char *table_name; 3453 - 3454 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME)) 3455 - return -EINVAL; 3456 - 3457 - table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 3458 - table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3459 - table_name, devlink); 3460 - if (!table) 3461 - return -EINVAL; 3462 - 3463 - if (!table->table_ops->entries_dump) 3464 - return -EINVAL; 3465 - 3466 - return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 3467 - 0, table); 3468 - } 3469 - 3470 - static int devlink_dpipe_fields_put(struct sk_buff *skb, 3471 - const struct devlink_dpipe_header *header) 3472 - { 3473 - struct devlink_dpipe_field *field; 3474 - struct nlattr *field_attr; 3475 - int i; 3476 - 3477 - for (i = 0; i < header->fields_count; i++) { 3478 - field = &header->fields[i]; 3479 - field_attr = nla_nest_start_noflag(skb, 3480 - DEVLINK_ATTR_DPIPE_FIELD); 3481 - if (!field_attr) 3482 - return -EMSGSIZE; 3483 - if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 3484 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 3485 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 3486 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 3487 - goto nla_put_failure; 3488 - nla_nest_end(skb, field_attr); 3489 - } 3490 - return 0; 3491 - 3492 - nla_put_failure: 3493 - nla_nest_cancel(skb, field_attr); 3494 - return -EMSGSIZE; 3495 - } 3496 - 3497 - static int devlink_dpipe_header_put(struct sk_buff *skb, 3498 - struct devlink_dpipe_header *header) 3499 - { 3500 - struct nlattr *fields_attr, *header_attr; 3501 - int err; 3502 - 3503 - header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER); 3504 - if (!header_attr) 3505 - return -EMSGSIZE; 3506 - 3507 - if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 3508 - nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 3509 - nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 3510 - goto nla_put_failure; 3511 - 3512 - fields_attr = nla_nest_start_noflag(skb, 3513 - DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 3514 - if (!fields_attr) 3515 - goto nla_put_failure; 3516 - 3517 - err = devlink_dpipe_fields_put(skb, header); 3518 - if (err) { 3519 - nla_nest_cancel(skb, fields_attr); 3520 - goto nla_put_failure; 3521 - } 3522 - nla_nest_end(skb, fields_attr); 3523 - nla_nest_end(skb, header_attr); 3524 - return 0; 3525 - 3526 - nla_put_failure: 3527 - err = -EMSGSIZE; 3528 - nla_nest_cancel(skb, header_attr); 3529 - return err; 3530 - } 3531 - 3532 - static int devlink_dpipe_headers_fill(struct genl_info *info, 3533 - enum devlink_command cmd, int flags, 3534 - struct devlink_dpipe_headers * 3535 - dpipe_headers) 3536 - { 3537 - struct devlink *devlink = info->user_ptr[0]; 3538 - struct nlattr *headers_attr; 3539 - struct sk_buff *skb = NULL; 3540 - struct nlmsghdr *nlh; 3541 - void *hdr; 3542 - int i, j; 3543 - int err; 3544 - 3545 - i = 0; 3546 - start_again: 3547 - err = devlink_dpipe_send_and_alloc_skb(&skb, info); 3548 - if (err) 3549 - return err; 3550 - 3551 - hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 3552 - &devlink_nl_family, NLM_F_MULTI, cmd); 3553 - if (!hdr) { 3554 - nlmsg_free(skb); 3555 - return -EMSGSIZE; 3556 - } 3557 - 3558 - if (devlink_nl_put_handle(skb, devlink)) 3559 - goto nla_put_failure; 3560 - headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS); 3561 - if (!headers_attr) 3562 - goto nla_put_failure; 3563 - 3564 - j = 0; 3565 - for (; i < dpipe_headers->headers_count; i++) { 3566 - err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 3567 - if (err) { 3568 - if (!j) 3569 - goto err_table_put; 3570 - break; 3571 - } 3572 - j++; 3573 - } 3574 - nla_nest_end(skb, headers_attr); 3575 - genlmsg_end(skb, hdr); 3576 - if (i != dpipe_headers->headers_count) 3577 - goto start_again; 3578 - 3579 - send_done: 3580 - nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 3581 - NLMSG_DONE, 0, flags | NLM_F_MULTI); 3582 - if (!nlh) { 3583 - err = devlink_dpipe_send_and_alloc_skb(&skb, info); 3584 - if (err) 3585 - return err; 3586 - goto send_done; 3587 - } 3588 - return genlmsg_reply(skb, info); 3589 - 3590 - nla_put_failure: 3591 - err = -EMSGSIZE; 3592 - err_table_put: 3593 - nlmsg_free(skb); 3594 - return err; 3595 - } 3596 - 3597 - static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 3598 - struct genl_info *info) 3599 - { 3600 - struct devlink *devlink = info->user_ptr[0]; 3601 - 3602 - if (!devlink->dpipe_headers) 3603 - return -EOPNOTSUPP; 3604 - return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 3605 - 0, devlink->dpipe_headers); 3606 - } 3607 - 3608 - static int devlink_dpipe_table_counters_set(struct devlink *devlink, 3609 - const char *table_name, 3610 - bool enable) 3611 - { 3612 - struct devlink_dpipe_table *table; 3613 - 3614 - table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3615 - table_name, devlink); 3616 - if (!table) 3617 - return -EINVAL; 3618 - 3619 - if (table->counter_control_extern) 3620 - return -EOPNOTSUPP; 3621 - 3622 - if (!(table->counters_enabled ^ enable)) 3623 - return 0; 3624 - 3625 - table->counters_enabled = enable; 3626 - if (table->table_ops->counters_set_update) 3627 - table->table_ops->counters_set_update(table->priv, enable); 3628 - return 0; 3629 - } 3630 - 3631 - static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 3632 - struct genl_info *info) 3633 - { 3634 - struct devlink *devlink = info->user_ptr[0]; 3635 - const char *table_name; 3636 - bool counters_enable; 3637 - 3638 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME) || 3639 - GENL_REQ_ATTR_CHECK(info, 3640 - DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED)) 3641 - return -EINVAL; 3642 - 3643 - table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 3644 - counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 3645 - 3646 - return devlink_dpipe_table_counters_set(devlink, table_name, 3647 - counters_enable); 3648 - } 3649 - 3650 - static struct devlink_resource * 3651 - devlink_resource_find(struct devlink *devlink, 3652 - struct devlink_resource *resource, u64 resource_id) 3653 - { 3654 - struct list_head *resource_list; 3655 - 3656 - if (resource) 3657 - resource_list = &resource->resource_list; 3658 - else 3659 - resource_list = &devlink->resource_list; 3660 - 3661 - list_for_each_entry(resource, resource_list, list) { 3662 - struct devlink_resource *child_resource; 3663 - 3664 - if (resource->id == resource_id) 3665 - return resource; 3666 - 3667 - child_resource = devlink_resource_find(devlink, resource, 3668 - resource_id); 3669 - if (child_resource) 3670 - return child_resource; 3671 - } 3672 - return NULL; 3673 - } 3674 - 3675 - static void 3676 - devlink_resource_validate_children(struct devlink_resource *resource) 3677 - { 3678 - struct devlink_resource *child_resource; 3679 - bool size_valid = true; 3680 - u64 parts_size = 0; 3681 - 3682 - if (list_empty(&resource->resource_list)) 3683 - goto out; 3684 - 3685 - list_for_each_entry(child_resource, &resource->resource_list, list) 3686 - parts_size += child_resource->size_new; 3687 - 3688 - if (parts_size > resource->size_new) 3689 - size_valid = false; 3690 - out: 3691 - resource->size_valid = size_valid; 3692 - } 3693 - 3694 - static int 3695 - devlink_resource_validate_size(struct devlink_resource *resource, u64 size, 3696 - struct netlink_ext_ack *extack) 3697 - { 3698 - u64 reminder; 3699 - int err = 0; 3700 - 3701 - if (size > resource->size_params.size_max) { 3702 - NL_SET_ERR_MSG(extack, "Size larger than maximum"); 3703 - err = -EINVAL; 3704 - } 3705 - 3706 - if (size < resource->size_params.size_min) { 3707 - NL_SET_ERR_MSG(extack, "Size smaller than minimum"); 3708 - err = -EINVAL; 3709 - } 3710 - 3711 - div64_u64_rem(size, resource->size_params.size_granularity, &reminder); 3712 - if (reminder) { 3713 - NL_SET_ERR_MSG(extack, "Wrong granularity"); 3714 - err = -EINVAL; 3715 - } 3716 - 3717 - return err; 3718 - } 3719 - 3720 - static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 3721 - struct genl_info *info) 3722 - { 3723 - struct devlink *devlink = info->user_ptr[0]; 3724 - struct devlink_resource *resource; 3725 - u64 resource_id; 3726 - u64 size; 3727 - int err; 3728 - 3729 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_ID) || 3730 - GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_SIZE)) 3731 - return -EINVAL; 3732 - resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 3733 - 3734 - resource = devlink_resource_find(devlink, NULL, resource_id); 3735 - if (!resource) 3736 - return -EINVAL; 3737 - 3738 - size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 3739 - err = devlink_resource_validate_size(resource, size, info->extack); 3740 - if (err) 3741 - return err; 3742 - 3743 - resource->size_new = size; 3744 - devlink_resource_validate_children(resource); 3745 - if (resource->parent) 3746 - devlink_resource_validate_children(resource->parent); 3747 - return 0; 3748 - } 3749 - 3750 - static int 3751 - devlink_resource_size_params_put(struct devlink_resource *resource, 3752 - struct sk_buff *skb) 3753 - { 3754 - struct devlink_resource_size_params *size_params; 3755 - 3756 - size_params = &resource->size_params; 3757 - if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 3758 - size_params->size_granularity, DEVLINK_ATTR_PAD) || 3759 - nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 3760 - size_params->size_max, DEVLINK_ATTR_PAD) || 3761 - nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 3762 - size_params->size_min, DEVLINK_ATTR_PAD) || 3763 - nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 3764 - return -EMSGSIZE; 3765 - return 0; 3766 - } 3767 - 3768 - static int devlink_resource_occ_put(struct devlink_resource *resource, 3769 - struct sk_buff *skb) 3770 - { 3771 - if (!resource->occ_get) 3772 - return 0; 3773 - return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 3774 - resource->occ_get(resource->occ_get_priv), 3775 - DEVLINK_ATTR_PAD); 3776 - } 3777 - 3778 - static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 3779 - struct devlink_resource *resource) 3780 - { 3781 - struct devlink_resource *child_resource; 3782 - struct nlattr *child_resource_attr; 3783 - struct nlattr *resource_attr; 3784 - 3785 - resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE); 3786 - if (!resource_attr) 3787 - return -EMSGSIZE; 3788 - 3789 - if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 3790 - nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 3791 - DEVLINK_ATTR_PAD) || 3792 - nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 3793 - DEVLINK_ATTR_PAD)) 3794 - goto nla_put_failure; 3795 - if (resource->size != resource->size_new && 3796 - nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 3797 - resource->size_new, DEVLINK_ATTR_PAD)) 3798 - goto nla_put_failure; 3799 - if (devlink_resource_occ_put(resource, skb)) 3800 - goto nla_put_failure; 3801 - if (devlink_resource_size_params_put(resource, skb)) 3802 - goto nla_put_failure; 3803 - if (list_empty(&resource->resource_list)) 3804 - goto out; 3805 - 3806 - if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 3807 - resource->size_valid)) 3808 - goto nla_put_failure; 3809 - 3810 - child_resource_attr = nla_nest_start_noflag(skb, 3811 - DEVLINK_ATTR_RESOURCE_LIST); 3812 - if (!child_resource_attr) 3813 - goto nla_put_failure; 3814 - 3815 - list_for_each_entry(child_resource, &resource->resource_list, list) { 3816 - if (devlink_resource_put(devlink, skb, child_resource)) 3817 - goto resource_put_failure; 3818 - } 3819 - 3820 - nla_nest_end(skb, child_resource_attr); 3821 - out: 3822 - nla_nest_end(skb, resource_attr); 3823 - return 0; 3824 - 3825 - resource_put_failure: 3826 - nla_nest_cancel(skb, child_resource_attr); 3827 - nla_put_failure: 3828 - nla_nest_cancel(skb, resource_attr); 3829 - return -EMSGSIZE; 3830 - } 3831 - 3832 - static int devlink_resource_fill(struct genl_info *info, 3833 - enum devlink_command cmd, int flags) 3834 - { 3835 - struct devlink *devlink = info->user_ptr[0]; 3836 - struct devlink_resource *resource; 3837 - struct nlattr *resources_attr; 3838 - struct sk_buff *skb = NULL; 3839 - struct nlmsghdr *nlh; 3840 - bool incomplete; 3841 - void *hdr; 3842 - int i; 3843 - int err; 3844 - 3845 - resource = list_first_entry(&devlink->resource_list, 3846 - struct devlink_resource, list); 3847 - start_again: 3848 - err = devlink_dpipe_send_and_alloc_skb(&skb, info); 3849 - if (err) 3850 - return err; 3851 - 3852 - hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 3853 - &devlink_nl_family, NLM_F_MULTI, cmd); 3854 - if (!hdr) { 3855 - nlmsg_free(skb); 3856 - return -EMSGSIZE; 3857 - } 3858 - 3859 - if (devlink_nl_put_handle(skb, devlink)) 3860 - goto nla_put_failure; 3861 - 3862 - resources_attr = nla_nest_start_noflag(skb, 3863 - DEVLINK_ATTR_RESOURCE_LIST); 3864 - if (!resources_attr) 3865 - goto nla_put_failure; 3866 - 3867 - incomplete = false; 3868 - i = 0; 3869 - list_for_each_entry_from(resource, &devlink->resource_list, list) { 3870 - err = devlink_resource_put(devlink, skb, resource); 3871 - if (err) { 3872 - if (!i) 3873 - goto err_resource_put; 3874 - incomplete = true; 3875 - break; 3876 - } 3877 - i++; 3878 - } 3879 - nla_nest_end(skb, resources_attr); 3880 - genlmsg_end(skb, hdr); 3881 - if (incomplete) 3882 - goto start_again; 3883 - send_done: 3884 - nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 3885 - NLMSG_DONE, 0, flags | NLM_F_MULTI); 3886 - if (!nlh) { 3887 - err = devlink_dpipe_send_and_alloc_skb(&skb, info); 3888 - if (err) 3889 - return err; 3890 - goto send_done; 3891 - } 3892 - return genlmsg_reply(skb, info); 3893 - 3894 - nla_put_failure: 3895 - err = -EMSGSIZE; 3896 - err_resource_put: 3897 - nlmsg_free(skb); 3898 - return err; 3899 - } 3900 - 3901 - static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 3902 - struct genl_info *info) 3903 - { 3904 - struct devlink *devlink = info->user_ptr[0]; 3905 - 3906 - if (list_empty(&devlink->resource_list)) 3907 - return -EOPNOTSUPP; 3908 - 3909 - return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 3910 - } 3911 - 3912 - int devlink_resources_validate(struct devlink *devlink, 3913 - struct devlink_resource *resource, 3914 - struct genl_info *info) 3915 - { 3916 - struct list_head *resource_list; 3917 - int err = 0; 3918 - 3919 - if (resource) 3920 - resource_list = &resource->resource_list; 3921 - else 3922 - resource_list = &devlink->resource_list; 3923 - 3924 - list_for_each_entry(resource, resource_list, list) { 3925 - if (!resource->size_valid) 3926 - return -EINVAL; 3927 - err = devlink_resources_validate(devlink, resource, info); 3928 - if (err) 3929 - return err; 3930 - } 3931 - return err; 3932 - } 3933 - 3934 - static const struct devlink_param devlink_param_generic[] = { 3935 - { 3936 - .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, 3937 - .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME, 3938 - .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE, 3939 - }, 3940 - { 3941 - .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 3942 - .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME, 3943 - .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE, 3944 - }, 3945 - { 3946 - .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, 3947 - .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME, 3948 - .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE, 3949 - }, 3950 - { 3951 - .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT, 3952 - .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME, 3953 - .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE, 3954 - }, 3955 - { 3956 - .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, 3957 - .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME, 3958 - .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE, 3959 - }, 3960 - { 3961 - .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 3962 - .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME, 3963 - .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE, 3964 - }, 3965 - { 3966 - .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 3967 - .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME, 3968 - .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE, 3969 - }, 3970 - { 3971 - .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, 3972 - .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME, 3973 - .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE, 3974 - }, 3975 - { 3976 - .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE, 3977 - .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME, 3978 - .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE, 3979 - }, 3980 - { 3981 - .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 3982 - .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME, 3983 - .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE, 3984 - }, 3985 - { 3986 - .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET, 3987 - .name = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_NAME, 3988 - .type = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_TYPE, 3989 - }, 3990 - { 3991 - .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, 3992 - .name = DEVLINK_PARAM_GENERIC_ENABLE_ETH_NAME, 3993 - .type = DEVLINK_PARAM_GENERIC_ENABLE_ETH_TYPE, 3994 - }, 3995 - { 3996 - .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, 3997 - .name = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_NAME, 3998 - .type = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_TYPE, 3999 - }, 4000 - { 4001 - .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, 4002 - .name = DEVLINK_PARAM_GENERIC_ENABLE_VNET_NAME, 4003 - .type = DEVLINK_PARAM_GENERIC_ENABLE_VNET_TYPE, 4004 - }, 4005 - { 4006 - .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP, 4007 - .name = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_NAME, 4008 - .type = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_TYPE, 4009 - }, 4010 - { 4011 - .id = DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE, 4012 - .name = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_NAME, 4013 - .type = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_TYPE, 4014 - }, 4015 - { 4016 - .id = DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE, 4017 - .name = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_NAME, 4018 - .type = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_TYPE, 4019 - }, 4020 - }; 4021 - 4022 - static int devlink_param_generic_verify(const struct devlink_param *param) 4023 - { 4024 - /* verify it match generic parameter by id and name */ 4025 - if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 4026 - return -EINVAL; 4027 - if (strcmp(param->name, devlink_param_generic[param->id].name)) 4028 - return -ENOENT; 4029 - 4030 - WARN_ON(param->type != devlink_param_generic[param->id].type); 4031 - 4032 - return 0; 4033 - } 4034 - 4035 - static int devlink_param_driver_verify(const struct devlink_param *param) 4036 - { 4037 - int i; 4038 - 4039 - if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 4040 - return -EINVAL; 4041 - /* verify no such name in generic params */ 4042 - for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 4043 - if (!strcmp(param->name, devlink_param_generic[i].name)) 4044 - return -EEXIST; 4045 - 4046 - return 0; 4047 - } 4048 - 4049 - static struct devlink_param_item * 4050 - devlink_param_find_by_name(struct xarray *params, const char *param_name) 4051 - { 4052 - struct devlink_param_item *param_item; 4053 - unsigned long param_id; 4054 - 4055 - xa_for_each(params, param_id, param_item) { 4056 - if (!strcmp(param_item->param->name, param_name)) 4057 - return param_item; 4058 - } 4059 - return NULL; 4060 - } 4061 - 4062 - static struct devlink_param_item * 4063 - devlink_param_find_by_id(struct xarray *params, u32 param_id) 4064 - { 4065 - return xa_load(params, param_id); 4066 - } 4067 - 4068 - static bool 4069 - devlink_param_cmode_is_supported(const struct devlink_param *param, 4070 - enum devlink_param_cmode cmode) 4071 - { 4072 - return test_bit(cmode, &param->supported_cmodes); 4073 - } 4074 - 4075 - static int devlink_param_get(struct devlink *devlink, 4076 - const struct devlink_param *param, 4077 - struct devlink_param_gset_ctx *ctx) 4078 - { 4079 - if (!param->get) 4080 - return -EOPNOTSUPP; 4081 - return param->get(devlink, param->id, ctx); 4082 - } 4083 - 4084 - static int devlink_param_set(struct devlink *devlink, 4085 - const struct devlink_param *param, 4086 - struct devlink_param_gset_ctx *ctx) 4087 - { 4088 - if (!param->set) 4089 - return -EOPNOTSUPP; 4090 - return param->set(devlink, param->id, ctx); 4091 - } 4092 - 4093 - static int 4094 - devlink_param_type_to_nla_type(enum devlink_param_type param_type) 4095 - { 4096 - switch (param_type) { 4097 - case DEVLINK_PARAM_TYPE_U8: 4098 - return NLA_U8; 4099 - case DEVLINK_PARAM_TYPE_U16: 4100 - return NLA_U16; 4101 - case DEVLINK_PARAM_TYPE_U32: 4102 - return NLA_U32; 4103 - case DEVLINK_PARAM_TYPE_STRING: 4104 - return NLA_STRING; 4105 - case DEVLINK_PARAM_TYPE_BOOL: 4106 - return NLA_FLAG; 4107 - default: 4108 - return -EINVAL; 4109 - } 4110 - } 4111 - 4112 - static int 4113 - devlink_nl_param_value_fill_one(struct sk_buff *msg, 4114 - enum devlink_param_type type, 4115 - enum devlink_param_cmode cmode, 4116 - union devlink_param_value val) 4117 - { 4118 - struct nlattr *param_value_attr; 4119 - 4120 - param_value_attr = nla_nest_start_noflag(msg, 4121 - DEVLINK_ATTR_PARAM_VALUE); 4122 - if (!param_value_attr) 4123 - goto nla_put_failure; 4124 - 4125 - if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 4126 - goto value_nest_cancel; 4127 - 4128 - switch (type) { 4129 - case DEVLINK_PARAM_TYPE_U8: 4130 - if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 4131 - goto value_nest_cancel; 4132 - break; 4133 - case DEVLINK_PARAM_TYPE_U16: 4134 - if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 4135 - goto value_nest_cancel; 4136 - break; 4137 - case DEVLINK_PARAM_TYPE_U32: 4138 - if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 4139 - goto value_nest_cancel; 4140 - break; 4141 - case DEVLINK_PARAM_TYPE_STRING: 4142 - if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 4143 - val.vstr)) 4144 - goto value_nest_cancel; 4145 - break; 4146 - case DEVLINK_PARAM_TYPE_BOOL: 4147 - if (val.vbool && 4148 - nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 4149 - goto value_nest_cancel; 4150 - break; 4151 - } 4152 - 4153 - nla_nest_end(msg, param_value_attr); 4154 - return 0; 4155 - 4156 - value_nest_cancel: 4157 - nla_nest_cancel(msg, param_value_attr); 4158 - nla_put_failure: 4159 - return -EMSGSIZE; 4160 - } 4161 - 4162 - static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 4163 - unsigned int port_index, 4164 - struct devlink_param_item *param_item, 4165 - enum devlink_command cmd, 4166 - u32 portid, u32 seq, int flags) 4167 - { 4168 - union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 4169 - bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {}; 4170 - const struct devlink_param *param = param_item->param; 4171 - struct devlink_param_gset_ctx ctx; 4172 - struct nlattr *param_values_list; 4173 - struct nlattr *param_attr; 4174 - int nla_type; 4175 - void *hdr; 4176 - int err; 4177 - int i; 4178 - 4179 - /* Get value from driver part to driverinit configuration mode */ 4180 - for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 4181 - if (!devlink_param_cmode_is_supported(param, i)) 4182 - continue; 4183 - if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 4184 - if (param_item->driverinit_value_new_valid) 4185 - param_value[i] = param_item->driverinit_value_new; 4186 - else if (param_item->driverinit_value_valid) 4187 - param_value[i] = param_item->driverinit_value; 4188 - else 4189 - return -EOPNOTSUPP; 4190 - } else { 4191 - ctx.cmode = i; 4192 - err = devlink_param_get(devlink, param, &ctx); 4193 - if (err) 4194 - return err; 4195 - param_value[i] = ctx.val; 4196 - } 4197 - param_value_set[i] = true; 4198 - } 4199 - 4200 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 4201 - if (!hdr) 4202 - return -EMSGSIZE; 4203 - 4204 - if (devlink_nl_put_handle(msg, devlink)) 4205 - goto genlmsg_cancel; 4206 - 4207 - if (cmd == DEVLINK_CMD_PORT_PARAM_GET || 4208 - cmd == DEVLINK_CMD_PORT_PARAM_NEW || 4209 - cmd == DEVLINK_CMD_PORT_PARAM_DEL) 4210 - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index)) 4211 - goto genlmsg_cancel; 4212 - 4213 - param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM); 4214 - if (!param_attr) 4215 - goto genlmsg_cancel; 4216 - if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 4217 - goto param_nest_cancel; 4218 - if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 4219 - goto param_nest_cancel; 4220 - 4221 - nla_type = devlink_param_type_to_nla_type(param->type); 4222 - if (nla_type < 0) 4223 - goto param_nest_cancel; 4224 - if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 4225 - goto param_nest_cancel; 4226 - 4227 - param_values_list = nla_nest_start_noflag(msg, 4228 - DEVLINK_ATTR_PARAM_VALUES_LIST); 4229 - if (!param_values_list) 4230 - goto param_nest_cancel; 4231 - 4232 - for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 4233 - if (!param_value_set[i]) 4234 - continue; 4235 - err = devlink_nl_param_value_fill_one(msg, param->type, 4236 - i, param_value[i]); 4237 - if (err) 4238 - goto values_list_nest_cancel; 4239 - } 4240 - 4241 - nla_nest_end(msg, param_values_list); 4242 - nla_nest_end(msg, param_attr); 4243 - genlmsg_end(msg, hdr); 4244 - return 0; 4245 - 4246 - values_list_nest_cancel: 4247 - nla_nest_end(msg, param_values_list); 4248 - param_nest_cancel: 4249 - nla_nest_cancel(msg, param_attr); 4250 - genlmsg_cancel: 4251 - genlmsg_cancel(msg, hdr); 4252 - return -EMSGSIZE; 4253 - } 4254 - 4255 - static void devlink_param_notify(struct devlink *devlink, 4256 - unsigned int port_index, 4257 - struct devlink_param_item *param_item, 4258 - enum devlink_command cmd) 4259 - { 4260 - struct sk_buff *msg; 4261 - int err; 4262 - 4263 - WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL && 4264 - cmd != DEVLINK_CMD_PORT_PARAM_NEW && 4265 - cmd != DEVLINK_CMD_PORT_PARAM_DEL); 4266 - 4267 - /* devlink_notify_register() / devlink_notify_unregister() 4268 - * will replay the notifications if the params are added/removed 4269 - * outside of the lifetime of the instance. 4270 - */ 4271 - if (!devl_is_registered(devlink)) 4272 - return; 4273 - 4274 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4275 - if (!msg) 4276 - return; 4277 - err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd, 4278 - 0, 0, 0); 4279 - if (err) { 4280 - nlmsg_free(msg); 4281 - return; 4282 - } 4283 - 4284 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 4285 - msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 4286 - } 4287 - 4288 - static int devlink_nl_param_get_dump_one(struct sk_buff *msg, 4289 - struct devlink *devlink, 4290 - struct netlink_callback *cb, 4291 - int flags) 4292 - { 4293 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 4294 - struct devlink_param_item *param_item; 4295 - unsigned long param_id; 4296 - int err = 0; 4297 - 4298 - xa_for_each_start(&devlink->params, param_id, param_item, state->idx) { 4299 - err = devlink_nl_param_fill(msg, devlink, 0, param_item, 4300 - DEVLINK_CMD_PARAM_GET, 4301 - NETLINK_CB(cb->skb).portid, 4302 - cb->nlh->nlmsg_seq, flags); 4303 - if (err == -EOPNOTSUPP) { 4304 - err = 0; 4305 - } else if (err) { 4306 - state->idx = param_id; 4307 - break; 4308 - } 4309 - } 4310 - 4311 - return err; 4312 - } 4313 - 4314 - int devlink_nl_param_get_dumpit(struct sk_buff *skb, 4315 - struct netlink_callback *cb) 4316 - { 4317 - return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one); 4318 - } 4319 - 4320 - static int 4321 - devlink_param_type_get_from_info(struct genl_info *info, 4322 - enum devlink_param_type *param_type) 4323 - { 4324 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE)) 4325 - return -EINVAL; 4326 - 4327 - switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { 4328 - case NLA_U8: 4329 - *param_type = DEVLINK_PARAM_TYPE_U8; 4330 - break; 4331 - case NLA_U16: 4332 - *param_type = DEVLINK_PARAM_TYPE_U16; 4333 - break; 4334 - case NLA_U32: 4335 - *param_type = DEVLINK_PARAM_TYPE_U32; 4336 - break; 4337 - case NLA_STRING: 4338 - *param_type = DEVLINK_PARAM_TYPE_STRING; 4339 - break; 4340 - case NLA_FLAG: 4341 - *param_type = DEVLINK_PARAM_TYPE_BOOL; 4342 - break; 4343 - default: 4344 - return -EINVAL; 4345 - } 4346 - 4347 - return 0; 4348 - } 4349 - 4350 - static int 4351 - devlink_param_value_get_from_info(const struct devlink_param *param, 4352 - struct genl_info *info, 4353 - union devlink_param_value *value) 4354 - { 4355 - struct nlattr *param_data; 4356 - int len; 4357 - 4358 - param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]; 4359 - 4360 - if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data) 4361 - return -EINVAL; 4362 - 4363 - switch (param->type) { 4364 - case DEVLINK_PARAM_TYPE_U8: 4365 - if (nla_len(param_data) != sizeof(u8)) 4366 - return -EINVAL; 4367 - value->vu8 = nla_get_u8(param_data); 4368 - break; 4369 - case DEVLINK_PARAM_TYPE_U16: 4370 - if (nla_len(param_data) != sizeof(u16)) 4371 - return -EINVAL; 4372 - value->vu16 = nla_get_u16(param_data); 4373 - break; 4374 - case DEVLINK_PARAM_TYPE_U32: 4375 - if (nla_len(param_data) != sizeof(u32)) 4376 - return -EINVAL; 4377 - value->vu32 = nla_get_u32(param_data); 4378 - break; 4379 - case DEVLINK_PARAM_TYPE_STRING: 4380 - len = strnlen(nla_data(param_data), nla_len(param_data)); 4381 - if (len == nla_len(param_data) || 4382 - len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 4383 - return -EINVAL; 4384 - strcpy(value->vstr, nla_data(param_data)); 4385 - break; 4386 - case DEVLINK_PARAM_TYPE_BOOL: 4387 - if (param_data && nla_len(param_data)) 4388 - return -EINVAL; 4389 - value->vbool = nla_get_flag(param_data); 4390 - break; 4391 - } 4392 - return 0; 4393 - } 4394 - 4395 - static struct devlink_param_item * 4396 - devlink_param_get_from_info(struct xarray *params, struct genl_info *info) 4397 - { 4398 - char *param_name; 4399 - 4400 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME)) 4401 - return NULL; 4402 - 4403 - param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 4404 - return devlink_param_find_by_name(params, param_name); 4405 - } 4406 - 4407 - int devlink_nl_param_get_doit(struct sk_buff *skb, 4408 - struct genl_info *info) 4409 - { 4410 - struct devlink *devlink = info->user_ptr[0]; 4411 - struct devlink_param_item *param_item; 4412 - struct sk_buff *msg; 4413 - int err; 4414 - 4415 - param_item = devlink_param_get_from_info(&devlink->params, info); 4416 - if (!param_item) 4417 - return -EINVAL; 4418 - 4419 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4420 - if (!msg) 4421 - return -ENOMEM; 4422 - 4423 - err = devlink_nl_param_fill(msg, devlink, 0, param_item, 4424 - DEVLINK_CMD_PARAM_GET, 4425 - info->snd_portid, info->snd_seq, 0); 4426 - if (err) { 4427 - nlmsg_free(msg); 4428 - return err; 4429 - } 4430 - 4431 - return genlmsg_reply(msg, info); 4432 - } 4433 - 4434 - static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, 4435 - unsigned int port_index, 4436 - struct xarray *params, 4437 - struct genl_info *info, 4438 - enum devlink_command cmd) 4439 - { 4440 - enum devlink_param_type param_type; 4441 - struct devlink_param_gset_ctx ctx; 4442 - enum devlink_param_cmode cmode; 4443 - struct devlink_param_item *param_item; 4444 - const struct devlink_param *param; 4445 - union devlink_param_value value; 4446 - int err = 0; 4447 - 4448 - param_item = devlink_param_get_from_info(params, info); 4449 - if (!param_item) 4450 - return -EINVAL; 4451 - param = param_item->param; 4452 - err = devlink_param_type_get_from_info(info, &param_type); 4453 - if (err) 4454 - return err; 4455 - if (param_type != param->type) 4456 - return -EINVAL; 4457 - err = devlink_param_value_get_from_info(param, info, &value); 4458 - if (err) 4459 - return err; 4460 - if (param->validate) { 4461 - err = param->validate(devlink, param->id, value, info->extack); 4462 - if (err) 4463 - return err; 4464 - } 4465 - 4466 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE)) 4467 - return -EINVAL; 4468 - cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 4469 - if (!devlink_param_cmode_is_supported(param, cmode)) 4470 - return -EOPNOTSUPP; 4471 - 4472 - if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 4473 - param_item->driverinit_value_new = value; 4474 - param_item->driverinit_value_new_valid = true; 4475 - } else { 4476 - if (!param->set) 4477 - return -EOPNOTSUPP; 4478 - ctx.val = value; 4479 - ctx.cmode = cmode; 4480 - err = devlink_param_set(devlink, param, &ctx); 4481 - if (err) 4482 - return err; 4483 - } 4484 - 4485 - devlink_param_notify(devlink, port_index, param_item, cmd); 4486 - return 0; 4487 - } 4488 - 4489 - static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, 4490 - struct genl_info *info) 4491 - { 4492 - struct devlink *devlink = info->user_ptr[0]; 4493 - 4494 - return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params, 4495 - info, DEVLINK_CMD_PARAM_NEW); 4496 - } 4497 - 4498 - static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg, 4499 - struct netlink_callback *cb) 4500 - { 4501 - NL_SET_ERR_MSG(cb->extack, "Port params are not supported"); 4502 - return msg->len; 4503 - } 4504 - 4505 - static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb, 4506 - struct genl_info *info) 4507 - { 4508 - NL_SET_ERR_MSG(info->extack, "Port params are not supported"); 4509 - return -EINVAL; 4510 - } 4511 - 4512 - static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb, 4513 - struct genl_info *info) 4514 - { 4515 - NL_SET_ERR_MSG(info->extack, "Port params are not supported"); 4516 - return -EINVAL; 4517 - } 4518 - 4519 - static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 4520 - struct devlink *devlink, 4521 - struct devlink_snapshot *snapshot) 4522 - { 4523 - struct nlattr *snap_attr; 4524 - int err; 4525 - 4526 - snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 4527 - if (!snap_attr) 4528 - return -EINVAL; 4529 - 4530 - err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 4531 - if (err) 4532 - goto nla_put_failure; 4533 - 4534 - nla_nest_end(msg, snap_attr); 4535 - return 0; 4536 - 4537 - nla_put_failure: 4538 - nla_nest_cancel(msg, snap_attr); 4539 - return err; 4540 - } 4541 - 4542 - static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 4543 - struct devlink *devlink, 4544 - struct devlink_region *region) 4545 - { 4546 - struct devlink_snapshot *snapshot; 4547 - struct nlattr *snapshots_attr; 4548 - int err; 4549 - 4550 - snapshots_attr = nla_nest_start_noflag(msg, 4551 - DEVLINK_ATTR_REGION_SNAPSHOTS); 4552 - if (!snapshots_attr) 4553 - return -EINVAL; 4554 - 4555 - list_for_each_entry(snapshot, &region->snapshot_list, list) { 4556 - err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 4557 - if (err) 4558 - goto nla_put_failure; 4559 - } 4560 - 4561 - nla_nest_end(msg, snapshots_attr); 4562 - return 0; 4563 - 4564 - nla_put_failure: 4565 - nla_nest_cancel(msg, snapshots_attr); 4566 - return err; 4567 - } 4568 - 4569 - static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 4570 - enum devlink_command cmd, u32 portid, 4571 - u32 seq, int flags, 4572 - struct devlink_region *region) 4573 - { 4574 - void *hdr; 4575 - int err; 4576 - 4577 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 4578 - if (!hdr) 4579 - return -EMSGSIZE; 4580 - 4581 - err = devlink_nl_put_handle(msg, devlink); 4582 - if (err) 4583 - goto nla_put_failure; 4584 - 4585 - if (region->port) { 4586 - err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 4587 - region->port->index); 4588 - if (err) 4589 - goto nla_put_failure; 4590 - } 4591 - 4592 - err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name); 4593 - if (err) 4594 - goto nla_put_failure; 4595 - 4596 - err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 4597 - region->size, 4598 - DEVLINK_ATTR_PAD); 4599 - if (err) 4600 - goto nla_put_failure; 4601 - 4602 - err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS, 4603 - region->max_snapshots); 4604 - if (err) 4605 - goto nla_put_failure; 4606 - 4607 - err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 4608 - if (err) 4609 - goto nla_put_failure; 4610 - 4611 - genlmsg_end(msg, hdr); 4612 - return 0; 4613 - 4614 - nla_put_failure: 4615 - genlmsg_cancel(msg, hdr); 4616 - return err; 4617 - } 4618 - 4619 - static struct sk_buff * 4620 - devlink_nl_region_notify_build(struct devlink_region *region, 4621 - struct devlink_snapshot *snapshot, 4622 - enum devlink_command cmd, u32 portid, u32 seq) 4623 - { 4624 - struct devlink *devlink = region->devlink; 4625 - struct sk_buff *msg; 4626 - void *hdr; 4627 - int err; 4628 - 4629 - 4630 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4631 - if (!msg) 4632 - return ERR_PTR(-ENOMEM); 4633 - 4634 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd); 4635 - if (!hdr) { 4636 - err = -EMSGSIZE; 4637 - goto out_free_msg; 4638 - } 4639 - 4640 - err = devlink_nl_put_handle(msg, devlink); 4641 - if (err) 4642 - goto out_cancel_msg; 4643 - 4644 - if (region->port) { 4645 - err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 4646 - region->port->index); 4647 - if (err) 4648 - goto out_cancel_msg; 4649 - } 4650 - 4651 - err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 4652 - region->ops->name); 4653 - if (err) 4654 - goto out_cancel_msg; 4655 - 4656 - if (snapshot) { 4657 - err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 4658 - snapshot->id); 4659 - if (err) 4660 - goto out_cancel_msg; 4661 - } else { 4662 - err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 4663 - region->size, DEVLINK_ATTR_PAD); 4664 - if (err) 4665 - goto out_cancel_msg; 4666 - } 4667 - genlmsg_end(msg, hdr); 4668 - 4669 - return msg; 4670 - 4671 - out_cancel_msg: 4672 - genlmsg_cancel(msg, hdr); 4673 - out_free_msg: 4674 - nlmsg_free(msg); 4675 - return ERR_PTR(err); 4676 - } 4677 - 4678 - static void devlink_nl_region_notify(struct devlink_region *region, 4679 - struct devlink_snapshot *snapshot, 4680 - enum devlink_command cmd) 4681 - { 4682 - struct devlink *devlink = region->devlink; 4683 - struct sk_buff *msg; 4684 - 4685 - WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 4686 - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 4687 - return; 4688 - 4689 - msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0); 4690 - if (IS_ERR(msg)) 4691 - return; 4692 - 4693 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg, 4694 - 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 4695 - } 4696 - 4697 - /** 4698 - * __devlink_snapshot_id_increment - Increment number of snapshots using an id 4699 - * @devlink: devlink instance 4700 - * @id: the snapshot id 4701 - * 4702 - * Track when a new snapshot begins using an id. Load the count for the 4703 - * given id from the snapshot xarray, increment it, and store it back. 4704 - * 4705 - * Called when a new snapshot is created with the given id. 4706 - * 4707 - * The id *must* have been previously allocated by 4708 - * devlink_region_snapshot_id_get(). 4709 - * 4710 - * Returns 0 on success, or an error on failure. 4711 - */ 4712 - static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id) 4713 - { 4714 - unsigned long count; 4715 - void *p; 4716 - int err; 4717 - 4718 - xa_lock(&devlink->snapshot_ids); 4719 - p = xa_load(&devlink->snapshot_ids, id); 4720 - if (WARN_ON(!p)) { 4721 - err = -EINVAL; 4722 - goto unlock; 4723 - } 4724 - 4725 - if (WARN_ON(!xa_is_value(p))) { 4726 - err = -EINVAL; 4727 - goto unlock; 4728 - } 4729 - 4730 - count = xa_to_value(p); 4731 - count++; 4732 - 4733 - err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), 4734 - GFP_ATOMIC)); 4735 - unlock: 4736 - xa_unlock(&devlink->snapshot_ids); 4737 - return err; 4738 - } 4739 - 4740 - /** 4741 - * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id 4742 - * @devlink: devlink instance 4743 - * @id: the snapshot id 4744 - * 4745 - * Track when a snapshot is deleted and stops using an id. Load the count 4746 - * for the given id from the snapshot xarray, decrement it, and store it 4747 - * back. 4748 - * 4749 - * If the count reaches zero, erase this id from the xarray, freeing it 4750 - * up for future re-use by devlink_region_snapshot_id_get(). 4751 - * 4752 - * Called when a snapshot using the given id is deleted, and when the 4753 - * initial allocator of the id is finished using it. 4754 - */ 4755 - static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id) 4756 - { 4757 - unsigned long count; 4758 - void *p; 4759 - 4760 - xa_lock(&devlink->snapshot_ids); 4761 - p = xa_load(&devlink->snapshot_ids, id); 4762 - if (WARN_ON(!p)) 4763 - goto unlock; 4764 - 4765 - if (WARN_ON(!xa_is_value(p))) 4766 - goto unlock; 4767 - 4768 - count = xa_to_value(p); 4769 - 4770 - if (count > 1) { 4771 - count--; 4772 - __xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), 4773 - GFP_ATOMIC); 4774 - } else { 4775 - /* If this was the last user, we can erase this id */ 4776 - __xa_erase(&devlink->snapshot_ids, id); 4777 - } 4778 - unlock: 4779 - xa_unlock(&devlink->snapshot_ids); 4780 - } 4781 - 4782 - /** 4783 - * __devlink_snapshot_id_insert - Insert a specific snapshot ID 4784 - * @devlink: devlink instance 4785 - * @id: the snapshot id 4786 - * 4787 - * Mark the given snapshot id as used by inserting a zero value into the 4788 - * snapshot xarray. 4789 - * 4790 - * This must be called while holding the devlink instance lock. Unlike 4791 - * devlink_snapshot_id_get, the initial reference count is zero, not one. 4792 - * It is expected that the id will immediately be used before 4793 - * releasing the devlink instance lock. 4794 - * 4795 - * Returns zero on success, or an error code if the snapshot id could not 4796 - * be inserted. 4797 - */ 4798 - static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id) 4799 - { 4800 - int err; 4801 - 4802 - xa_lock(&devlink->snapshot_ids); 4803 - if (xa_load(&devlink->snapshot_ids, id)) { 4804 - xa_unlock(&devlink->snapshot_ids); 4805 - return -EEXIST; 4806 - } 4807 - err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0), 4808 - GFP_ATOMIC)); 4809 - xa_unlock(&devlink->snapshot_ids); 4810 - return err; 4811 - } 4812 - 4813 - /** 4814 - * __devlink_region_snapshot_id_get - get snapshot ID 4815 - * @devlink: devlink instance 4816 - * @id: storage to return snapshot id 4817 - * 4818 - * Allocates a new snapshot id. Returns zero on success, or a negative 4819 - * error on failure. Must be called while holding the devlink instance 4820 - * lock. 4821 - * 4822 - * Snapshot IDs are tracked using an xarray which stores the number of 4823 - * users of the snapshot id. 4824 - * 4825 - * Note that the caller of this function counts as a 'user', in order to 4826 - * avoid race conditions. The caller must release its hold on the 4827 - * snapshot by using devlink_region_snapshot_id_put. 4828 - */ 4829 - static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id) 4830 - { 4831 - return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1), 4832 - xa_limit_32b, GFP_KERNEL); 4833 - } 4834 - 4835 - /** 4836 - * __devlink_region_snapshot_create - create a new snapshot 4837 - * This will add a new snapshot of a region. The snapshot 4838 - * will be stored on the region struct and can be accessed 4839 - * from devlink. This is useful for future analyses of snapshots. 4840 - * Multiple snapshots can be created on a region. 4841 - * The @snapshot_id should be obtained using the getter function. 4842 - * 4843 - * Must be called only while holding the region snapshot lock. 4844 - * 4845 - * @region: devlink region of the snapshot 4846 - * @data: snapshot data 4847 - * @snapshot_id: snapshot id to be created 4848 - */ 4849 - static int 4850 - __devlink_region_snapshot_create(struct devlink_region *region, 4851 - u8 *data, u32 snapshot_id) 4852 - { 4853 - struct devlink *devlink = region->devlink; 4854 - struct devlink_snapshot *snapshot; 4855 - int err; 4856 - 4857 - lockdep_assert_held(&region->snapshot_lock); 4858 - 4859 - /* check if region can hold one more snapshot */ 4860 - if (region->cur_snapshots == region->max_snapshots) 4861 - return -ENOSPC; 4862 - 4863 - if (devlink_region_snapshot_get_by_id(region, snapshot_id)) 4864 - return -EEXIST; 4865 - 4866 - snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 4867 - if (!snapshot) 4868 - return -ENOMEM; 4869 - 4870 - err = __devlink_snapshot_id_increment(devlink, snapshot_id); 4871 - if (err) 4872 - goto err_snapshot_id_increment; 4873 - 4874 - snapshot->id = snapshot_id; 4875 - snapshot->region = region; 4876 - snapshot->data = data; 4877 - 4878 - list_add_tail(&snapshot->list, &region->snapshot_list); 4879 - 4880 - region->cur_snapshots++; 4881 - 4882 - devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 4883 - return 0; 4884 - 4885 - err_snapshot_id_increment: 4886 - kfree(snapshot); 4887 - return err; 4888 - } 4889 - 4890 - static void devlink_region_snapshot_del(struct devlink_region *region, 4891 - struct devlink_snapshot *snapshot) 4892 - { 4893 - struct devlink *devlink = region->devlink; 4894 - 4895 - lockdep_assert_held(&region->snapshot_lock); 4896 - 4897 - devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 4898 - region->cur_snapshots--; 4899 - list_del(&snapshot->list); 4900 - region->ops->destructor(snapshot->data); 4901 - __devlink_snapshot_id_decrement(devlink, snapshot->id); 4902 - kfree(snapshot); 4903 - } 4904 - 4905 - int devlink_nl_region_get_doit(struct sk_buff *skb, struct genl_info *info) 4906 - { 4907 - struct devlink *devlink = info->user_ptr[0]; 4908 - struct devlink_port *port = NULL; 4909 - struct devlink_region *region; 4910 - const char *region_name; 4911 - struct sk_buff *msg; 4912 - unsigned int index; 4913 - int err; 4914 - 4915 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) 4916 - return -EINVAL; 4917 - 4918 - if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 4919 - index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 4920 - 4921 - port = devlink_port_get_by_index(devlink, index); 4922 - if (!port) 4923 - return -ENODEV; 4924 - } 4925 - 4926 - region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 4927 - if (port) 4928 - region = devlink_port_region_get_by_name(port, region_name); 4929 - else 4930 - region = devlink_region_get_by_name(devlink, region_name); 4931 - 4932 - if (!region) 4933 - return -EINVAL; 4934 - 4935 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4936 - if (!msg) 4937 - return -ENOMEM; 4938 - 4939 - err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 4940 - info->snd_portid, info->snd_seq, 0, 4941 - region); 4942 - if (err) { 4943 - nlmsg_free(msg); 4944 - return err; 4945 - } 4946 - 4947 - return genlmsg_reply(msg, info); 4948 - } 4949 - 4950 - static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg, 4951 - struct netlink_callback *cb, 4952 - struct devlink_port *port, 4953 - int *idx, int start, int flags) 4954 - { 4955 - struct devlink_region *region; 4956 - int err = 0; 4957 - 4958 - list_for_each_entry(region, &port->region_list, list) { 4959 - if (*idx < start) { 4960 - (*idx)++; 4961 - continue; 4962 - } 4963 - err = devlink_nl_region_fill(msg, port->devlink, 4964 - DEVLINK_CMD_REGION_GET, 4965 - NETLINK_CB(cb->skb).portid, 4966 - cb->nlh->nlmsg_seq, 4967 - flags, region); 4968 - if (err) 4969 - goto out; 4970 - (*idx)++; 4971 - } 4972 - 4973 - out: 4974 - return err; 4975 - } 4976 - 4977 - static int devlink_nl_region_get_dump_one(struct sk_buff *msg, 4978 - struct devlink *devlink, 4979 - struct netlink_callback *cb, 4980 - int flags) 4981 - { 4982 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 4983 - struct devlink_region *region; 4984 - struct devlink_port *port; 4985 - unsigned long port_index; 4986 - int idx = 0; 4987 - int err; 4988 - 4989 - list_for_each_entry(region, &devlink->region_list, list) { 4990 - if (idx < state->idx) { 4991 - idx++; 4992 - continue; 4993 - } 4994 - err = devlink_nl_region_fill(msg, devlink, 4995 - DEVLINK_CMD_REGION_GET, 4996 - NETLINK_CB(cb->skb).portid, 4997 - cb->nlh->nlmsg_seq, flags, 4998 - region); 4999 - if (err) { 5000 - state->idx = idx; 5001 - return err; 5002 - } 5003 - idx++; 5004 - } 5005 - 5006 - xa_for_each(&devlink->ports, port_index, port) { 5007 - err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, &idx, 5008 - state->idx, flags); 5009 - if (err) { 5010 - state->idx = idx; 5011 - return err; 5012 - } 5013 - } 5014 - 5015 - return 0; 5016 - } 5017 - 5018 - int devlink_nl_region_get_dumpit(struct sk_buff *skb, 5019 - struct netlink_callback *cb) 5020 - { 5021 - return devlink_nl_dumpit(skb, cb, devlink_nl_region_get_dump_one); 5022 - } 5023 - 5024 - static int devlink_nl_cmd_region_del(struct sk_buff *skb, 5025 - struct genl_info *info) 5026 - { 5027 - struct devlink *devlink = info->user_ptr[0]; 5028 - struct devlink_snapshot *snapshot; 5029 - struct devlink_port *port = NULL; 5030 - struct devlink_region *region; 5031 - const char *region_name; 5032 - unsigned int index; 5033 - u32 snapshot_id; 5034 - 5035 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) || 5036 - GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID)) 5037 - return -EINVAL; 5038 - 5039 - region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 5040 - snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 5041 - 5042 - if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 5043 - index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 5044 - 5045 - port = devlink_port_get_by_index(devlink, index); 5046 - if (!port) 5047 - return -ENODEV; 5048 - } 5049 - 5050 - if (port) 5051 - region = devlink_port_region_get_by_name(port, region_name); 5052 - else 5053 - region = devlink_region_get_by_name(devlink, region_name); 5054 - 5055 - if (!region) 5056 - return -EINVAL; 5057 - 5058 - mutex_lock(&region->snapshot_lock); 5059 - snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 5060 - if (!snapshot) { 5061 - mutex_unlock(&region->snapshot_lock); 5062 - return -EINVAL; 5063 - } 5064 - 5065 - devlink_region_snapshot_del(region, snapshot); 5066 - mutex_unlock(&region->snapshot_lock); 5067 - return 0; 5068 - } 5069 - 5070 - static int 5071 - devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) 5072 - { 5073 - struct devlink *devlink = info->user_ptr[0]; 5074 - struct devlink_snapshot *snapshot; 5075 - struct devlink_port *port = NULL; 5076 - struct nlattr *snapshot_id_attr; 5077 - struct devlink_region *region; 5078 - const char *region_name; 5079 - unsigned int index; 5080 - u32 snapshot_id; 5081 - u8 *data; 5082 - int err; 5083 - 5084 - if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) { 5085 - NL_SET_ERR_MSG(info->extack, "No region name provided"); 5086 - return -EINVAL; 5087 - } 5088 - 5089 - region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 5090 - 5091 - if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 5092 - index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 5093 - 5094 - port = devlink_port_get_by_index(devlink, index); 5095 - if (!port) 5096 - return -ENODEV; 5097 - } 5098 - 5099 - if (port) 5100 - region = devlink_port_region_get_by_name(port, region_name); 5101 - else 5102 - region = devlink_region_get_by_name(devlink, region_name); 5103 - 5104 - if (!region) { 5105 - NL_SET_ERR_MSG(info->extack, "The requested region does not exist"); 5106 - return -EINVAL; 5107 - } 5108 - 5109 - if (!region->ops->snapshot) { 5110 - NL_SET_ERR_MSG(info->extack, "The requested region does not support taking an immediate snapshot"); 5111 - return -EOPNOTSUPP; 5112 - } 5113 - 5114 - mutex_lock(&region->snapshot_lock); 5115 - 5116 - if (region->cur_snapshots == region->max_snapshots) { 5117 - NL_SET_ERR_MSG(info->extack, "The region has reached the maximum number of stored snapshots"); 5118 - err = -ENOSPC; 5119 - goto unlock; 5120 - } 5121 - 5122 - snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; 5123 - if (snapshot_id_attr) { 5124 - snapshot_id = nla_get_u32(snapshot_id_attr); 5125 - 5126 - if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 5127 - NL_SET_ERR_MSG(info->extack, "The requested snapshot id is already in use"); 5128 - err = -EEXIST; 5129 - goto unlock; 5130 - } 5131 - 5132 - err = __devlink_snapshot_id_insert(devlink, snapshot_id); 5133 - if (err) 5134 - goto unlock; 5135 - } else { 5136 - err = __devlink_region_snapshot_id_get(devlink, &snapshot_id); 5137 - if (err) { 5138 - NL_SET_ERR_MSG(info->extack, "Failed to allocate a new snapshot id"); 5139 - goto unlock; 5140 - } 5141 - } 5142 - 5143 - if (port) 5144 - err = region->port_ops->snapshot(port, region->port_ops, 5145 - info->extack, &data); 5146 - else 5147 - err = region->ops->snapshot(devlink, region->ops, 5148 - info->extack, &data); 5149 - if (err) 5150 - goto err_snapshot_capture; 5151 - 5152 - err = __devlink_region_snapshot_create(region, data, snapshot_id); 5153 - if (err) 5154 - goto err_snapshot_create; 5155 - 5156 - if (!snapshot_id_attr) { 5157 - struct sk_buff *msg; 5158 - 5159 - snapshot = devlink_region_snapshot_get_by_id(region, 5160 - snapshot_id); 5161 - if (WARN_ON(!snapshot)) { 5162 - err = -EINVAL; 5163 - goto unlock; 5164 - } 5165 - 5166 - msg = devlink_nl_region_notify_build(region, snapshot, 5167 - DEVLINK_CMD_REGION_NEW, 5168 - info->snd_portid, 5169 - info->snd_seq); 5170 - err = PTR_ERR_OR_ZERO(msg); 5171 - if (err) 5172 - goto err_notify; 5173 - 5174 - err = genlmsg_reply(msg, info); 5175 - if (err) 5176 - goto err_notify; 5177 - } 5178 - 5179 - mutex_unlock(&region->snapshot_lock); 5180 - return 0; 5181 - 5182 - err_snapshot_create: 5183 - region->ops->destructor(data); 5184 - err_snapshot_capture: 5185 - __devlink_snapshot_id_decrement(devlink, snapshot_id); 5186 - mutex_unlock(&region->snapshot_lock); 5187 - return err; 5188 - 5189 - err_notify: 5190 - devlink_region_snapshot_del(region, snapshot); 5191 - unlock: 5192 - mutex_unlock(&region->snapshot_lock); 5193 - return err; 5194 - } 5195 - 5196 - static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 5197 - u8 *chunk, u32 chunk_size, 5198 - u64 addr) 5199 - { 5200 - struct nlattr *chunk_attr; 5201 - int err; 5202 - 5203 - chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK); 5204 - if (!chunk_attr) 5205 - return -EINVAL; 5206 - 5207 - err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 5208 - if (err) 5209 - goto nla_put_failure; 5210 - 5211 - err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 5212 - DEVLINK_ATTR_PAD); 5213 - if (err) 5214 - goto nla_put_failure; 5215 - 5216 - nla_nest_end(msg, chunk_attr); 5217 - return 0; 5218 - 5219 - nla_put_failure: 5220 - nla_nest_cancel(msg, chunk_attr); 5221 - return err; 5222 - } 5223 - 5224 - #define DEVLINK_REGION_READ_CHUNK_SIZE 256 5225 - 5226 - typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size, 5227 - u64 curr_offset, 5228 - struct netlink_ext_ack *extack); 5229 - 5230 - static int 5231 - devlink_nl_region_read_fill(struct sk_buff *skb, devlink_chunk_fill_t *cb, 5232 - void *cb_priv, u64 start_offset, u64 end_offset, 5233 - u64 *new_offset, struct netlink_ext_ack *extack) 5234 - { 5235 - u64 curr_offset = start_offset; 5236 - int err = 0; 5237 - u8 *data; 5238 - 5239 - /* Allocate and re-use a single buffer */ 5240 - data = kmalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL); 5241 - if (!data) 5242 - return -ENOMEM; 5243 - 5244 - *new_offset = start_offset; 5245 - 5246 - while (curr_offset < end_offset) { 5247 - u32 data_size; 5248 - 5249 - data_size = min_t(u32, end_offset - curr_offset, 5250 - DEVLINK_REGION_READ_CHUNK_SIZE); 5251 - 5252 - err = cb(cb_priv, data, data_size, curr_offset, extack); 5253 - if (err) 5254 - break; 5255 - 5256 - err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset); 5257 - if (err) 5258 - break; 5259 - 5260 - curr_offset += data_size; 5261 - } 5262 - *new_offset = curr_offset; 5263 - 5264 - kfree(data); 5265 - 5266 - return err; 5267 - } 5268 - 5269 - static int 5270 - devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size, 5271 - u64 curr_offset, 5272 - struct netlink_ext_ack __always_unused *extack) 5273 - { 5274 - struct devlink_snapshot *snapshot = cb_priv; 5275 - 5276 - memcpy(chunk, &snapshot->data[curr_offset], chunk_size); 5277 - 5278 - return 0; 5279 - } 5280 - 5281 - static int 5282 - devlink_region_port_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size, 5283 - u64 curr_offset, struct netlink_ext_ack *extack) 5284 - { 5285 - struct devlink_region *region = cb_priv; 5286 - 5287 - return region->port_ops->read(region->port, region->port_ops, extack, 5288 - curr_offset, chunk_size, chunk); 5289 - } 5290 - 5291 - static int 5292 - devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size, 5293 - u64 curr_offset, struct netlink_ext_ack *extack) 5294 - { 5295 - struct devlink_region *region = cb_priv; 5296 - 5297 - return region->ops->read(region->devlink, region->ops, extack, 5298 - curr_offset, chunk_size, chunk); 5299 - } 5300 - 5301 - static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 5302 - struct netlink_callback *cb) 5303 - { 5304 - const struct genl_dumpit_info *info = genl_dumpit_info(cb); 5305 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 5306 - struct nlattr *chunks_attr, *region_attr, *snapshot_attr; 5307 - u64 ret_offset, start_offset, end_offset = U64_MAX; 5308 - struct nlattr **attrs = info->info.attrs; 5309 - struct devlink_port *port = NULL; 5310 - devlink_chunk_fill_t *region_cb; 5311 - struct devlink_region *region; 5312 - const char *region_name; 5313 - struct devlink *devlink; 5314 - unsigned int index; 5315 - void *region_cb_priv; 5316 - void *hdr; 5317 - int err; 5318 - 5319 - start_offset = state->start_offset; 5320 - 5321 - devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs); 5322 - if (IS_ERR(devlink)) 5323 - return PTR_ERR(devlink); 5324 - 5325 - if (!attrs[DEVLINK_ATTR_REGION_NAME]) { 5326 - NL_SET_ERR_MSG(cb->extack, "No region name provided"); 5327 - err = -EINVAL; 5328 - goto out_unlock; 5329 - } 5330 - 5331 - if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 5332 - index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 5333 - 5334 - port = devlink_port_get_by_index(devlink, index); 5335 - if (!port) { 5336 - err = -ENODEV; 5337 - goto out_unlock; 5338 - } 5339 - } 5340 - 5341 - region_attr = attrs[DEVLINK_ATTR_REGION_NAME]; 5342 - region_name = nla_data(region_attr); 5343 - 5344 - if (port) 5345 - region = devlink_port_region_get_by_name(port, region_name); 5346 - else 5347 - region = devlink_region_get_by_name(devlink, region_name); 5348 - 5349 - if (!region) { 5350 - NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist"); 5351 - err = -EINVAL; 5352 - goto out_unlock; 5353 - } 5354 - 5355 - snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; 5356 - if (!snapshot_attr) { 5357 - if (!nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) { 5358 - NL_SET_ERR_MSG(cb->extack, "No snapshot id provided"); 5359 - err = -EINVAL; 5360 - goto out_unlock; 5361 - } 5362 - 5363 - if (!region->ops->read) { 5364 - NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read"); 5365 - err = -EOPNOTSUPP; 5366 - goto out_unlock; 5367 - } 5368 - 5369 - if (port) 5370 - region_cb = &devlink_region_port_direct_fill; 5371 - else 5372 - region_cb = &devlink_region_direct_fill; 5373 - region_cb_priv = region; 5374 - } else { 5375 - struct devlink_snapshot *snapshot; 5376 - u32 snapshot_id; 5377 - 5378 - if (nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) { 5379 - NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot"); 5380 - err = -EINVAL; 5381 - goto out_unlock; 5382 - } 5383 - 5384 - snapshot_id = nla_get_u32(snapshot_attr); 5385 - snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 5386 - if (!snapshot) { 5387 - NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist"); 5388 - err = -EINVAL; 5389 - goto out_unlock; 5390 - } 5391 - region_cb = &devlink_region_snapshot_fill; 5392 - region_cb_priv = snapshot; 5393 - } 5394 - 5395 - if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 5396 - attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 5397 - if (!start_offset) 5398 - start_offset = 5399 - nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 5400 - 5401 - end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 5402 - end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 5403 - } 5404 - 5405 - if (end_offset > region->size) 5406 - end_offset = region->size; 5407 - 5408 - /* return 0 if there is no further data to read */ 5409 - if (start_offset == end_offset) { 5410 - err = 0; 5411 - goto out_unlock; 5412 - } 5413 - 5414 - hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 5415 - &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 5416 - DEVLINK_CMD_REGION_READ); 5417 - if (!hdr) { 5418 - err = -EMSGSIZE; 5419 - goto out_unlock; 5420 - } 5421 - 5422 - err = devlink_nl_put_handle(skb, devlink); 5423 - if (err) 5424 - goto nla_put_failure; 5425 - 5426 - if (region->port) { 5427 - err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX, 5428 - region->port->index); 5429 - if (err) 5430 - goto nla_put_failure; 5431 - } 5432 - 5433 - err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 5434 - if (err) 5435 - goto nla_put_failure; 5436 - 5437 - chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS); 5438 - if (!chunks_attr) { 5439 - err = -EMSGSIZE; 5440 - goto nla_put_failure; 5441 - } 5442 - 5443 - err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv, 5444 - start_offset, end_offset, &ret_offset, 5445 - cb->extack); 5446 - 5447 - if (err && err != -EMSGSIZE) 5448 - goto nla_put_failure; 5449 - 5450 - /* Check if there was any progress done to prevent infinite loop */ 5451 - if (ret_offset == start_offset) { 5452 - err = -EINVAL; 5453 - goto nla_put_failure; 5454 - } 5455 - 5456 - state->start_offset = ret_offset; 5457 - 5458 - nla_nest_end(skb, chunks_attr); 5459 - genlmsg_end(skb, hdr); 5460 - devl_unlock(devlink); 5461 - devlink_put(devlink); 5462 - return skb->len; 5463 - 5464 - nla_put_failure: 5465 - genlmsg_cancel(skb, hdr); 5466 - out_unlock: 5467 - devl_unlock(devlink); 5468 - devlink_put(devlink); 5469 - return err; 5470 - } 5471 - 5472 - struct devlink_stats { 5473 - u64_stats_t rx_bytes; 5474 - u64_stats_t rx_packets; 5475 - struct u64_stats_sync syncp; 5476 - }; 5477 - 5478 - /** 5479 - * struct devlink_trap_policer_item - Packet trap policer attributes. 5480 - * @policer: Immutable packet trap policer attributes. 5481 - * @rate: Rate in packets / sec. 5482 - * @burst: Burst size in packets. 5483 - * @list: trap_policer_list member. 5484 - * 5485 - * Describes packet trap policer attributes. Created by devlink during trap 5486 - * policer registration. 5487 - */ 5488 - struct devlink_trap_policer_item { 5489 - const struct devlink_trap_policer *policer; 5490 - u64 rate; 5491 - u64 burst; 5492 - struct list_head list; 5493 - }; 5494 - 5495 - /** 5496 - * struct devlink_trap_group_item - Packet trap group attributes. 5497 - * @group: Immutable packet trap group attributes. 5498 - * @policer_item: Associated policer item. Can be NULL. 5499 - * @list: trap_group_list member. 5500 - * @stats: Trap group statistics. 5501 - * 5502 - * Describes packet trap group attributes. Created by devlink during trap 5503 - * group registration. 5504 - */ 5505 - struct devlink_trap_group_item { 5506 - const struct devlink_trap_group *group; 5507 - struct devlink_trap_policer_item *policer_item; 5508 - struct list_head list; 5509 - struct devlink_stats __percpu *stats; 5510 - }; 5511 - 5512 - /** 5513 - * struct devlink_trap_item - Packet trap attributes. 5514 - * @trap: Immutable packet trap attributes. 5515 - * @group_item: Associated group item. 5516 - * @list: trap_list member. 5517 - * @action: Trap action. 5518 - * @stats: Trap statistics. 5519 - * @priv: Driver private information. 5520 - * 5521 - * Describes both mutable and immutable packet trap attributes. Created by 5522 - * devlink during trap registration and used for all trap related operations. 5523 - */ 5524 - struct devlink_trap_item { 5525 - const struct devlink_trap *trap; 5526 - struct devlink_trap_group_item *group_item; 5527 - struct list_head list; 5528 - enum devlink_trap_action action; 5529 - struct devlink_stats __percpu *stats; 5530 - void *priv; 5531 - }; 5532 - 5533 - static struct devlink_trap_policer_item * 5534 - devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id) 5535 - { 5536 - struct devlink_trap_policer_item *policer_item; 5537 - 5538 - list_for_each_entry(policer_item, &devlink->trap_policer_list, list) { 5539 - if (policer_item->policer->id == id) 5540 - return policer_item; 5541 - } 5542 - 5543 - return NULL; 5544 - } 5545 - 5546 - static struct devlink_trap_item * 5547 - devlink_trap_item_lookup(struct devlink *devlink, const char *name) 5548 - { 5549 - struct devlink_trap_item *trap_item; 5550 - 5551 - list_for_each_entry(trap_item, &devlink->trap_list, list) { 5552 - if (!strcmp(trap_item->trap->name, name)) 5553 - return trap_item; 5554 - } 5555 - 5556 - return NULL; 5557 - } 5558 - 5559 - static struct devlink_trap_item * 5560 - devlink_trap_item_get_from_info(struct devlink *devlink, 5561 - struct genl_info *info) 5562 - { 5563 - struct nlattr *attr; 5564 - 5565 - if (!info->attrs[DEVLINK_ATTR_TRAP_NAME]) 5566 - return NULL; 5567 - attr = info->attrs[DEVLINK_ATTR_TRAP_NAME]; 5568 - 5569 - return devlink_trap_item_lookup(devlink, nla_data(attr)); 5570 - } 5571 - 5572 - static int 5573 - devlink_trap_action_get_from_info(struct genl_info *info, 5574 - enum devlink_trap_action *p_trap_action) 5575 - { 5576 - u8 val; 5577 - 5578 - val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]); 5579 - switch (val) { 5580 - case DEVLINK_TRAP_ACTION_DROP: 5581 - case DEVLINK_TRAP_ACTION_TRAP: 5582 - case DEVLINK_TRAP_ACTION_MIRROR: 5583 - *p_trap_action = val; 5584 - break; 5585 - default: 5586 - return -EINVAL; 5587 - } 5588 - 5589 - return 0; 5590 - } 5591 - 5592 - static int devlink_trap_metadata_put(struct sk_buff *msg, 5593 - const struct devlink_trap *trap) 5594 - { 5595 - struct nlattr *attr; 5596 - 5597 - attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA); 5598 - if (!attr) 5599 - return -EMSGSIZE; 5600 - 5601 - if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) && 5602 - nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT)) 5603 - goto nla_put_failure; 5604 - if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) && 5605 - nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE)) 5606 - goto nla_put_failure; 5607 - 5608 - nla_nest_end(msg, attr); 5609 - 5610 - return 0; 5611 - 5612 - nla_put_failure: 5613 - nla_nest_cancel(msg, attr); 5614 - return -EMSGSIZE; 5615 - } 5616 - 5617 - static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats, 5618 - struct devlink_stats *stats) 5619 - { 5620 - int i; 5621 - 5622 - memset(stats, 0, sizeof(*stats)); 5623 - for_each_possible_cpu(i) { 5624 - struct devlink_stats *cpu_stats; 5625 - u64 rx_packets, rx_bytes; 5626 - unsigned int start; 5627 - 5628 - cpu_stats = per_cpu_ptr(trap_stats, i); 5629 - do { 5630 - start = u64_stats_fetch_begin(&cpu_stats->syncp); 5631 - rx_packets = u64_stats_read(&cpu_stats->rx_packets); 5632 - rx_bytes = u64_stats_read(&cpu_stats->rx_bytes); 5633 - } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); 5634 - 5635 - u64_stats_add(&stats->rx_packets, rx_packets); 5636 - u64_stats_add(&stats->rx_bytes, rx_bytes); 5637 - } 5638 - } 5639 - 5640 - static int 5641 - devlink_trap_group_stats_put(struct sk_buff *msg, 5642 - struct devlink_stats __percpu *trap_stats) 5643 - { 5644 - struct devlink_stats stats; 5645 - struct nlattr *attr; 5646 - 5647 - devlink_trap_stats_read(trap_stats, &stats); 5648 - 5649 - attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 5650 - if (!attr) 5651 - return -EMSGSIZE; 5652 - 5653 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS, 5654 - u64_stats_read(&stats.rx_packets), 5655 - DEVLINK_ATTR_PAD)) 5656 - goto nla_put_failure; 5657 - 5658 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES, 5659 - u64_stats_read(&stats.rx_bytes), 5660 - DEVLINK_ATTR_PAD)) 5661 - goto nla_put_failure; 5662 - 5663 - nla_nest_end(msg, attr); 5664 - 5665 - return 0; 5666 - 5667 - nla_put_failure: 5668 - nla_nest_cancel(msg, attr); 5669 - return -EMSGSIZE; 5670 - } 5671 - 5672 - static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink, 5673 - const struct devlink_trap_item *trap_item) 5674 - { 5675 - struct devlink_stats stats; 5676 - struct nlattr *attr; 5677 - u64 drops = 0; 5678 - int err; 5679 - 5680 - if (devlink->ops->trap_drop_counter_get) { 5681 - err = devlink->ops->trap_drop_counter_get(devlink, 5682 - trap_item->trap, 5683 - &drops); 5684 - if (err) 5685 - return err; 5686 - } 5687 - 5688 - devlink_trap_stats_read(trap_item->stats, &stats); 5689 - 5690 - attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 5691 - if (!attr) 5692 - return -EMSGSIZE; 5693 - 5694 - if (devlink->ops->trap_drop_counter_get && 5695 - nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops, 5696 - DEVLINK_ATTR_PAD)) 5697 - goto nla_put_failure; 5698 - 5699 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS, 5700 - u64_stats_read(&stats.rx_packets), 5701 - DEVLINK_ATTR_PAD)) 5702 - goto nla_put_failure; 5703 - 5704 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES, 5705 - u64_stats_read(&stats.rx_bytes), 5706 - DEVLINK_ATTR_PAD)) 5707 - goto nla_put_failure; 5708 - 5709 - nla_nest_end(msg, attr); 5710 - 5711 - return 0; 5712 - 5713 - nla_put_failure: 5714 - nla_nest_cancel(msg, attr); 5715 - return -EMSGSIZE; 5716 - } 5717 - 5718 - static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink, 5719 - const struct devlink_trap_item *trap_item, 5720 - enum devlink_command cmd, u32 portid, u32 seq, 5721 - int flags) 5722 - { 5723 - struct devlink_trap_group_item *group_item = trap_item->group_item; 5724 - void *hdr; 5725 - int err; 5726 - 5727 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 5728 - if (!hdr) 5729 - return -EMSGSIZE; 5730 - 5731 - if (devlink_nl_put_handle(msg, devlink)) 5732 - goto nla_put_failure; 5733 - 5734 - if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 5735 - group_item->group->name)) 5736 - goto nla_put_failure; 5737 - 5738 - if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name)) 5739 - goto nla_put_failure; 5740 - 5741 - if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type)) 5742 - goto nla_put_failure; 5743 - 5744 - if (trap_item->trap->generic && 5745 - nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 5746 - goto nla_put_failure; 5747 - 5748 - if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action)) 5749 - goto nla_put_failure; 5750 - 5751 - err = devlink_trap_metadata_put(msg, trap_item->trap); 5752 - if (err) 5753 - goto nla_put_failure; 5754 - 5755 - err = devlink_trap_stats_put(msg, devlink, trap_item); 5756 - if (err) 5757 - goto nla_put_failure; 5758 - 5759 - genlmsg_end(msg, hdr); 5760 - 5761 - return 0; 5762 - 5763 - nla_put_failure: 5764 - genlmsg_cancel(msg, hdr); 5765 - return -EMSGSIZE; 5766 - } 5767 - 5768 - int devlink_nl_trap_get_doit(struct sk_buff *skb, struct genl_info *info) 5769 - { 5770 - struct netlink_ext_ack *extack = info->extack; 5771 - struct devlink *devlink = info->user_ptr[0]; 5772 - struct devlink_trap_item *trap_item; 5773 - struct sk_buff *msg; 5774 - int err; 5775 - 5776 - if (list_empty(&devlink->trap_list)) 5777 - return -EOPNOTSUPP; 5778 - 5779 - trap_item = devlink_trap_item_get_from_info(devlink, info); 5780 - if (!trap_item) { 5781 - NL_SET_ERR_MSG(extack, "Device did not register this trap"); 5782 - return -ENOENT; 5783 - } 5784 - 5785 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 5786 - if (!msg) 5787 - return -ENOMEM; 5788 - 5789 - err = devlink_nl_trap_fill(msg, devlink, trap_item, 5790 - DEVLINK_CMD_TRAP_NEW, info->snd_portid, 5791 - info->snd_seq, 0); 5792 - if (err) 5793 - goto err_trap_fill; 5794 - 5795 - return genlmsg_reply(msg, info); 5796 - 5797 - err_trap_fill: 5798 - nlmsg_free(msg); 5799 - return err; 5800 - } 5801 - 5802 - static int devlink_nl_trap_get_dump_one(struct sk_buff *msg, 5803 - struct devlink *devlink, 5804 - struct netlink_callback *cb, int flags) 5805 - { 5806 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 5807 - struct devlink_trap_item *trap_item; 5808 - int idx = 0; 5809 - int err = 0; 5810 - 5811 - list_for_each_entry(trap_item, &devlink->trap_list, list) { 5812 - if (idx < state->idx) { 5813 - idx++; 5814 - continue; 5815 - } 5816 - err = devlink_nl_trap_fill(msg, devlink, trap_item, 5817 - DEVLINK_CMD_TRAP_NEW, 5818 - NETLINK_CB(cb->skb).portid, 5819 - cb->nlh->nlmsg_seq, flags); 5820 - if (err) { 5821 - state->idx = idx; 5822 - break; 5823 - } 5824 - idx++; 5825 - } 5826 - 5827 - return err; 5828 - } 5829 - 5830 - int devlink_nl_trap_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 5831 - { 5832 - return devlink_nl_dumpit(skb, cb, devlink_nl_trap_get_dump_one); 5833 - } 5834 - 5835 - static int __devlink_trap_action_set(struct devlink *devlink, 5836 - struct devlink_trap_item *trap_item, 5837 - enum devlink_trap_action trap_action, 5838 - struct netlink_ext_ack *extack) 5839 - { 5840 - int err; 5841 - 5842 - if (trap_item->action != trap_action && 5843 - trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) { 5844 - NL_SET_ERR_MSG(extack, "Cannot change action of non-drop traps. Skipping"); 5845 - return 0; 5846 - } 5847 - 5848 - err = devlink->ops->trap_action_set(devlink, trap_item->trap, 5849 - trap_action, extack); 5850 - if (err) 5851 - return err; 5852 - 5853 - trap_item->action = trap_action; 5854 - 5855 - return 0; 5856 - } 5857 - 5858 - static int devlink_trap_action_set(struct devlink *devlink, 5859 - struct devlink_trap_item *trap_item, 5860 - struct genl_info *info) 5861 - { 5862 - enum devlink_trap_action trap_action; 5863 - int err; 5864 - 5865 - if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 5866 - return 0; 5867 - 5868 - err = devlink_trap_action_get_from_info(info, &trap_action); 5869 - if (err) { 5870 - NL_SET_ERR_MSG(info->extack, "Invalid trap action"); 5871 - return -EINVAL; 5872 - } 5873 - 5874 - return __devlink_trap_action_set(devlink, trap_item, trap_action, 5875 - info->extack); 5876 - } 5877 - 5878 - static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb, 5879 - struct genl_info *info) 5880 - { 5881 - struct netlink_ext_ack *extack = info->extack; 5882 - struct devlink *devlink = info->user_ptr[0]; 5883 - struct devlink_trap_item *trap_item; 5884 - 5885 - if (list_empty(&devlink->trap_list)) 5886 - return -EOPNOTSUPP; 5887 - 5888 - trap_item = devlink_trap_item_get_from_info(devlink, info); 5889 - if (!trap_item) { 5890 - NL_SET_ERR_MSG(extack, "Device did not register this trap"); 5891 - return -ENOENT; 5892 - } 5893 - 5894 - return devlink_trap_action_set(devlink, trap_item, info); 5895 - } 5896 - 5897 - static struct devlink_trap_group_item * 5898 - devlink_trap_group_item_lookup(struct devlink *devlink, const char *name) 5899 - { 5900 - struct devlink_trap_group_item *group_item; 5901 - 5902 - list_for_each_entry(group_item, &devlink->trap_group_list, list) { 5903 - if (!strcmp(group_item->group->name, name)) 5904 - return group_item; 5905 - } 5906 - 5907 - return NULL; 5908 - } 5909 - 5910 - static struct devlink_trap_group_item * 5911 - devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id) 5912 - { 5913 - struct devlink_trap_group_item *group_item; 5914 - 5915 - list_for_each_entry(group_item, &devlink->trap_group_list, list) { 5916 - if (group_item->group->id == id) 5917 - return group_item; 5918 - } 5919 - 5920 - return NULL; 5921 - } 5922 - 5923 - static struct devlink_trap_group_item * 5924 - devlink_trap_group_item_get_from_info(struct devlink *devlink, 5925 - struct genl_info *info) 5926 - { 5927 - char *name; 5928 - 5929 - if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]) 5930 - return NULL; 5931 - name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]); 5932 - 5933 - return devlink_trap_group_item_lookup(devlink, name); 5934 - } 5935 - 5936 - static int 5937 - devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink, 5938 - const struct devlink_trap_group_item *group_item, 5939 - enum devlink_command cmd, u32 portid, u32 seq, 5940 - int flags) 5941 - { 5942 - void *hdr; 5943 - int err; 5944 - 5945 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 5946 - if (!hdr) 5947 - return -EMSGSIZE; 5948 - 5949 - if (devlink_nl_put_handle(msg, devlink)) 5950 - goto nla_put_failure; 5951 - 5952 - if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 5953 - group_item->group->name)) 5954 - goto nla_put_failure; 5955 - 5956 - if (group_item->group->generic && 5957 - nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 5958 - goto nla_put_failure; 5959 - 5960 - if (group_item->policer_item && 5961 - nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 5962 - group_item->policer_item->policer->id)) 5963 - goto nla_put_failure; 5964 - 5965 - err = devlink_trap_group_stats_put(msg, group_item->stats); 5966 - if (err) 5967 - goto nla_put_failure; 5968 - 5969 - genlmsg_end(msg, hdr); 5970 - 5971 - return 0; 5972 - 5973 - nla_put_failure: 5974 - genlmsg_cancel(msg, hdr); 5975 - return -EMSGSIZE; 5976 - } 5977 - 5978 - int devlink_nl_trap_group_get_doit(struct sk_buff *skb, struct genl_info *info) 5979 - { 5980 - struct netlink_ext_ack *extack = info->extack; 5981 - struct devlink *devlink = info->user_ptr[0]; 5982 - struct devlink_trap_group_item *group_item; 5983 - struct sk_buff *msg; 5984 - int err; 5985 - 5986 - if (list_empty(&devlink->trap_group_list)) 5987 - return -EOPNOTSUPP; 5988 - 5989 - group_item = devlink_trap_group_item_get_from_info(devlink, info); 5990 - if (!group_item) { 5991 - NL_SET_ERR_MSG(extack, "Device did not register this trap group"); 5992 - return -ENOENT; 5993 - } 5994 - 5995 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 5996 - if (!msg) 5997 - return -ENOMEM; 5998 - 5999 - err = devlink_nl_trap_group_fill(msg, devlink, group_item, 6000 - DEVLINK_CMD_TRAP_GROUP_NEW, 6001 - info->snd_portid, info->snd_seq, 0); 6002 - if (err) 6003 - goto err_trap_group_fill; 6004 - 6005 - return genlmsg_reply(msg, info); 6006 - 6007 - err_trap_group_fill: 6008 - nlmsg_free(msg); 6009 - return err; 6010 - } 6011 - 6012 - static int devlink_nl_trap_group_get_dump_one(struct sk_buff *msg, 6013 - struct devlink *devlink, 6014 - struct netlink_callback *cb, 6015 - int flags) 6016 - { 6017 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 6018 - struct devlink_trap_group_item *group_item; 6019 - int idx = 0; 6020 - int err = 0; 6021 - 6022 - 6023 - list_for_each_entry(group_item, &devlink->trap_group_list, list) { 6024 - if (idx < state->idx) { 6025 - idx++; 6026 - continue; 6027 - } 6028 - err = devlink_nl_trap_group_fill(msg, devlink, group_item, 6029 - DEVLINK_CMD_TRAP_GROUP_NEW, 6030 - NETLINK_CB(cb->skb).portid, 6031 - cb->nlh->nlmsg_seq, flags); 6032 - if (err) { 6033 - state->idx = idx; 6034 - break; 6035 - } 6036 - idx++; 6037 - } 6038 - 6039 - return err; 6040 - } 6041 - 6042 - int devlink_nl_trap_group_get_dumpit(struct sk_buff *skb, 6043 - struct netlink_callback *cb) 6044 - { 6045 - return devlink_nl_dumpit(skb, cb, devlink_nl_trap_group_get_dump_one); 6046 - } 6047 - 6048 - static int 6049 - __devlink_trap_group_action_set(struct devlink *devlink, 6050 - struct devlink_trap_group_item *group_item, 6051 - enum devlink_trap_action trap_action, 6052 - struct netlink_ext_ack *extack) 6053 - { 6054 - const char *group_name = group_item->group->name; 6055 - struct devlink_trap_item *trap_item; 6056 - int err; 6057 - 6058 - if (devlink->ops->trap_group_action_set) { 6059 - err = devlink->ops->trap_group_action_set(devlink, group_item->group, 6060 - trap_action, extack); 6061 - if (err) 6062 - return err; 6063 - 6064 - list_for_each_entry(trap_item, &devlink->trap_list, list) { 6065 - if (strcmp(trap_item->group_item->group->name, group_name)) 6066 - continue; 6067 - if (trap_item->action != trap_action && 6068 - trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) 6069 - continue; 6070 - trap_item->action = trap_action; 6071 - } 6072 - 6073 - return 0; 6074 - } 6075 - 6076 - list_for_each_entry(trap_item, &devlink->trap_list, list) { 6077 - if (strcmp(trap_item->group_item->group->name, group_name)) 6078 - continue; 6079 - err = __devlink_trap_action_set(devlink, trap_item, 6080 - trap_action, extack); 6081 - if (err) 6082 - return err; 6083 - } 6084 - 6085 - return 0; 6086 - } 6087 - 6088 - static int 6089 - devlink_trap_group_action_set(struct devlink *devlink, 6090 - struct devlink_trap_group_item *group_item, 6091 - struct genl_info *info, bool *p_modified) 6092 - { 6093 - enum devlink_trap_action trap_action; 6094 - int err; 6095 - 6096 - if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 6097 - return 0; 6098 - 6099 - err = devlink_trap_action_get_from_info(info, &trap_action); 6100 - if (err) { 6101 - NL_SET_ERR_MSG(info->extack, "Invalid trap action"); 6102 - return -EINVAL; 6103 - } 6104 - 6105 - err = __devlink_trap_group_action_set(devlink, group_item, trap_action, 6106 - info->extack); 6107 - if (err) 6108 - return err; 6109 - 6110 - *p_modified = true; 6111 - 6112 - return 0; 6113 - } 6114 - 6115 - static int devlink_trap_group_set(struct devlink *devlink, 6116 - struct devlink_trap_group_item *group_item, 6117 - struct genl_info *info) 6118 - { 6119 - struct devlink_trap_policer_item *policer_item; 6120 - struct netlink_ext_ack *extack = info->extack; 6121 - const struct devlink_trap_policer *policer; 6122 - struct nlattr **attrs = info->attrs; 6123 - u32 policer_id; 6124 - int err; 6125 - 6126 - if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 6127 - return 0; 6128 - 6129 - if (!devlink->ops->trap_group_set) 6130 - return -EOPNOTSUPP; 6131 - 6132 - policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 6133 - policer_item = devlink_trap_policer_item_lookup(devlink, policer_id); 6134 - if (policer_id && !policer_item) { 6135 - NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 6136 - return -ENOENT; 6137 - } 6138 - policer = policer_item ? policer_item->policer : NULL; 6139 - 6140 - err = devlink->ops->trap_group_set(devlink, group_item->group, policer, 6141 - extack); 6142 - if (err) 6143 - return err; 6144 - 6145 - group_item->policer_item = policer_item; 6146 - 6147 - return 0; 6148 - } 6149 - 6150 - static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb, 6151 - struct genl_info *info) 6152 - { 6153 - struct netlink_ext_ack *extack = info->extack; 6154 - struct devlink *devlink = info->user_ptr[0]; 6155 - struct devlink_trap_group_item *group_item; 6156 - bool modified = false; 6157 - int err; 6158 - 6159 - if (list_empty(&devlink->trap_group_list)) 6160 - return -EOPNOTSUPP; 6161 - 6162 - group_item = devlink_trap_group_item_get_from_info(devlink, info); 6163 - if (!group_item) { 6164 - NL_SET_ERR_MSG(extack, "Device did not register this trap group"); 6165 - return -ENOENT; 6166 - } 6167 - 6168 - err = devlink_trap_group_action_set(devlink, group_item, info, 6169 - &modified); 6170 - if (err) 6171 - return err; 6172 - 6173 - err = devlink_trap_group_set(devlink, group_item, info); 6174 - if (err) 6175 - goto err_trap_group_set; 6176 - 6177 - return 0; 6178 - 6179 - err_trap_group_set: 6180 - if (modified) 6181 - NL_SET_ERR_MSG(extack, "Trap group set failed, but some changes were committed already"); 6182 - return err; 6183 - } 6184 - 6185 - static struct devlink_trap_policer_item * 6186 - devlink_trap_policer_item_get_from_info(struct devlink *devlink, 6187 - struct genl_info *info) 6188 - { 6189 - u32 id; 6190 - 6191 - if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 6192 - return NULL; 6193 - id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 6194 - 6195 - return devlink_trap_policer_item_lookup(devlink, id); 6196 - } 6197 - 6198 - static int 6199 - devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink, 6200 - const struct devlink_trap_policer *policer) 6201 - { 6202 - struct nlattr *attr; 6203 - u64 drops; 6204 - int err; 6205 - 6206 - if (!devlink->ops->trap_policer_counter_get) 6207 - return 0; 6208 - 6209 - err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops); 6210 - if (err) 6211 - return err; 6212 - 6213 - attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 6214 - if (!attr) 6215 - return -EMSGSIZE; 6216 - 6217 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops, 6218 - DEVLINK_ATTR_PAD)) 6219 - goto nla_put_failure; 6220 - 6221 - nla_nest_end(msg, attr); 6222 - 6223 - return 0; 6224 - 6225 - nla_put_failure: 6226 - nla_nest_cancel(msg, attr); 6227 - return -EMSGSIZE; 6228 - } 6229 - 6230 - static int 6231 - devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink, 6232 - const struct devlink_trap_policer_item *policer_item, 6233 - enum devlink_command cmd, u32 portid, u32 seq, 6234 - int flags) 6235 - { 6236 - void *hdr; 6237 - int err; 6238 - 6239 - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 6240 - if (!hdr) 6241 - return -EMSGSIZE; 6242 - 6243 - if (devlink_nl_put_handle(msg, devlink)) 6244 - goto nla_put_failure; 6245 - 6246 - if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 6247 - policer_item->policer->id)) 6248 - goto nla_put_failure; 6249 - 6250 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE, 6251 - policer_item->rate, DEVLINK_ATTR_PAD)) 6252 - goto nla_put_failure; 6253 - 6254 - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST, 6255 - policer_item->burst, DEVLINK_ATTR_PAD)) 6256 - goto nla_put_failure; 6257 - 6258 - err = devlink_trap_policer_stats_put(msg, devlink, 6259 - policer_item->policer); 6260 - if (err) 6261 - goto nla_put_failure; 6262 - 6263 - genlmsg_end(msg, hdr); 6264 - 6265 - return 0; 6266 - 6267 - nla_put_failure: 6268 - genlmsg_cancel(msg, hdr); 6269 - return -EMSGSIZE; 6270 - } 6271 - 6272 - int devlink_nl_trap_policer_get_doit(struct sk_buff *skb, 6273 - struct genl_info *info) 6274 - { 6275 - struct devlink_trap_policer_item *policer_item; 6276 - struct netlink_ext_ack *extack = info->extack; 6277 - struct devlink *devlink = info->user_ptr[0]; 6278 - struct sk_buff *msg; 6279 - int err; 6280 - 6281 - if (list_empty(&devlink->trap_policer_list)) 6282 - return -EOPNOTSUPP; 6283 - 6284 - policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 6285 - if (!policer_item) { 6286 - NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 6287 - return -ENOENT; 6288 - } 6289 - 6290 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 6291 - if (!msg) 6292 - return -ENOMEM; 6293 - 6294 - err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, 6295 - DEVLINK_CMD_TRAP_POLICER_NEW, 6296 - info->snd_portid, info->snd_seq, 0); 6297 - if (err) 6298 - goto err_trap_policer_fill; 6299 - 6300 - return genlmsg_reply(msg, info); 6301 - 6302 - err_trap_policer_fill: 6303 - nlmsg_free(msg); 6304 - return err; 6305 - } 6306 - 6307 - static int devlink_nl_trap_policer_get_dump_one(struct sk_buff *msg, 6308 - struct devlink *devlink, 6309 - struct netlink_callback *cb, 6310 - int flags) 6311 - { 6312 - struct devlink_nl_dump_state *state = devlink_dump_state(cb); 6313 - struct devlink_trap_policer_item *policer_item; 6314 - int idx = 0; 6315 - int err = 0; 6316 - 6317 - list_for_each_entry(policer_item, &devlink->trap_policer_list, list) { 6318 - if (idx < state->idx) { 6319 - idx++; 6320 - continue; 6321 - } 6322 - err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, 6323 - DEVLINK_CMD_TRAP_POLICER_NEW, 6324 - NETLINK_CB(cb->skb).portid, 6325 - cb->nlh->nlmsg_seq, flags); 6326 - if (err) { 6327 - state->idx = idx; 6328 - break; 6329 - } 6330 - idx++; 6331 - } 6332 - 6333 - return err; 6334 - } 6335 - 6336 - int devlink_nl_trap_policer_get_dumpit(struct sk_buff *skb, 6337 - struct netlink_callback *cb) 6338 - { 6339 - return devlink_nl_dumpit(skb, cb, devlink_nl_trap_policer_get_dump_one); 6340 - } 6341 - 6342 - static int 6343 - devlink_trap_policer_set(struct devlink *devlink, 6344 - struct devlink_trap_policer_item *policer_item, 6345 - struct genl_info *info) 6346 - { 6347 - struct netlink_ext_ack *extack = info->extack; 6348 - struct nlattr **attrs = info->attrs; 6349 - u64 rate, burst; 6350 - int err; 6351 - 6352 - rate = policer_item->rate; 6353 - burst = policer_item->burst; 6354 - 6355 - if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]) 6356 - rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]); 6357 - 6358 - if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]) 6359 - burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]); 6360 - 6361 - if (rate < policer_item->policer->min_rate) { 6362 - NL_SET_ERR_MSG(extack, "Policer rate lower than limit"); 6363 - return -EINVAL; 6364 - } 6365 - 6366 - if (rate > policer_item->policer->max_rate) { 6367 - NL_SET_ERR_MSG(extack, "Policer rate higher than limit"); 6368 - return -EINVAL; 6369 - } 6370 - 6371 - if (burst < policer_item->policer->min_burst) { 6372 - NL_SET_ERR_MSG(extack, "Policer burst size lower than limit"); 6373 - return -EINVAL; 6374 - } 6375 - 6376 - if (burst > policer_item->policer->max_burst) { 6377 - NL_SET_ERR_MSG(extack, "Policer burst size higher than limit"); 6378 - return -EINVAL; 6379 - } 6380 - 6381 - err = devlink->ops->trap_policer_set(devlink, policer_item->policer, 6382 - rate, burst, info->extack); 6383 - if (err) 6384 - return err; 6385 - 6386 - policer_item->rate = rate; 6387 - policer_item->burst = burst; 6388 - 6389 - return 0; 6390 - } 6391 - 6392 - static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb, 6393 - struct genl_info *info) 6394 - { 6395 - struct devlink_trap_policer_item *policer_item; 6396 - struct netlink_ext_ack *extack = info->extack; 6397 - struct devlink *devlink = info->user_ptr[0]; 6398 - 6399 - if (list_empty(&devlink->trap_policer_list)) 6400 - return -EOPNOTSUPP; 6401 - 6402 - if (!devlink->ops->trap_policer_set) 6403 - return -EOPNOTSUPP; 6404 - 6405 - policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 6406 - if (!policer_item) { 6407 - NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 6408 - return -ENOENT; 6409 - } 6410 - 6411 - return devlink_trap_policer_set(devlink, policer_item, info); 6412 - } 6413 - 6414 - const struct genl_small_ops devlink_nl_small_ops[40] = { 6415 - { 6416 - .cmd = DEVLINK_CMD_PORT_SET, 6417 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6418 - .doit = devlink_nl_cmd_port_set_doit, 6419 - .flags = GENL_ADMIN_PERM, 6420 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6421 - }, 6422 - { 6423 - .cmd = DEVLINK_CMD_RATE_SET, 6424 - .doit = devlink_nl_cmd_rate_set_doit, 6425 - .flags = GENL_ADMIN_PERM, 6426 - }, 6427 - { 6428 - .cmd = DEVLINK_CMD_RATE_NEW, 6429 - .doit = devlink_nl_cmd_rate_new_doit, 6430 - .flags = GENL_ADMIN_PERM, 6431 - }, 6432 - { 6433 - .cmd = DEVLINK_CMD_RATE_DEL, 6434 - .doit = devlink_nl_cmd_rate_del_doit, 6435 - .flags = GENL_ADMIN_PERM, 6436 - }, 6437 - { 6438 - .cmd = DEVLINK_CMD_PORT_SPLIT, 6439 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6440 - .doit = devlink_nl_cmd_port_split_doit, 6441 - .flags = GENL_ADMIN_PERM, 6442 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6443 - }, 6444 - { 6445 - .cmd = DEVLINK_CMD_PORT_UNSPLIT, 6446 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6447 - .doit = devlink_nl_cmd_port_unsplit_doit, 6448 - .flags = GENL_ADMIN_PERM, 6449 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6450 - }, 6451 - { 6452 - .cmd = DEVLINK_CMD_PORT_NEW, 6453 - .doit = devlink_nl_cmd_port_new_doit, 6454 - .flags = GENL_ADMIN_PERM, 6455 - }, 6456 - { 6457 - .cmd = DEVLINK_CMD_PORT_DEL, 6458 - .doit = devlink_nl_cmd_port_del_doit, 6459 - .flags = GENL_ADMIN_PERM, 6460 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6461 - }, 6462 - 6463 - { 6464 - .cmd = DEVLINK_CMD_LINECARD_SET, 6465 - .doit = devlink_nl_cmd_linecard_set_doit, 6466 - .flags = GENL_ADMIN_PERM, 6467 - }, 6468 - { 6469 - .cmd = DEVLINK_CMD_SB_POOL_SET, 6470 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6471 - .doit = devlink_nl_cmd_sb_pool_set_doit, 6472 - .flags = GENL_ADMIN_PERM, 6473 - }, 6474 - { 6475 - .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 6476 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6477 - .doit = devlink_nl_cmd_sb_port_pool_set_doit, 6478 - .flags = GENL_ADMIN_PERM, 6479 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6480 - }, 6481 - { 6482 - .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 6483 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6484 - .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 6485 - .flags = GENL_ADMIN_PERM, 6486 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6487 - }, 6488 - { 6489 - .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 6490 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6491 - .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 6492 - .flags = GENL_ADMIN_PERM, 6493 - }, 6494 - { 6495 - .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 6496 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6497 - .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 6498 - .flags = GENL_ADMIN_PERM, 6499 - }, 6500 - { 6501 - .cmd = DEVLINK_CMD_ESWITCH_GET, 6502 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6503 - .doit = devlink_nl_cmd_eswitch_get_doit, 6504 - .flags = GENL_ADMIN_PERM, 6505 - }, 6506 - { 6507 - .cmd = DEVLINK_CMD_ESWITCH_SET, 6508 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6509 - .doit = devlink_nl_cmd_eswitch_set_doit, 6510 - .flags = GENL_ADMIN_PERM, 6511 - }, 6512 - { 6513 - .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 6514 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6515 - .doit = devlink_nl_cmd_dpipe_table_get, 6516 - /* can be retrieved by unprivileged users */ 6517 - }, 6518 - { 6519 - .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 6520 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6521 - .doit = devlink_nl_cmd_dpipe_entries_get, 6522 - /* can be retrieved by unprivileged users */ 6523 - }, 6524 - { 6525 - .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 6526 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6527 - .doit = devlink_nl_cmd_dpipe_headers_get, 6528 - /* can be retrieved by unprivileged users */ 6529 - }, 6530 - { 6531 - .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 6532 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6533 - .doit = devlink_nl_cmd_dpipe_table_counters_set, 6534 - .flags = GENL_ADMIN_PERM, 6535 - }, 6536 - { 6537 - .cmd = DEVLINK_CMD_RESOURCE_SET, 6538 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6539 - .doit = devlink_nl_cmd_resource_set, 6540 - .flags = GENL_ADMIN_PERM, 6541 - }, 6542 - { 6543 - .cmd = DEVLINK_CMD_RESOURCE_DUMP, 6544 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6545 - .doit = devlink_nl_cmd_resource_dump, 6546 - /* can be retrieved by unprivileged users */ 6547 - }, 6548 - { 6549 - .cmd = DEVLINK_CMD_RELOAD, 6550 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6551 - .doit = devlink_nl_cmd_reload, 6552 - .flags = GENL_ADMIN_PERM, 6553 - }, 6554 - { 6555 - .cmd = DEVLINK_CMD_PARAM_SET, 6556 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6557 - .doit = devlink_nl_cmd_param_set_doit, 6558 - .flags = GENL_ADMIN_PERM, 6559 - }, 6560 - { 6561 - .cmd = DEVLINK_CMD_PORT_PARAM_GET, 6562 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6563 - .doit = devlink_nl_cmd_port_param_get_doit, 6564 - .dumpit = devlink_nl_cmd_port_param_get_dumpit, 6565 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6566 - /* can be retrieved by unprivileged users */ 6567 - }, 6568 - { 6569 - .cmd = DEVLINK_CMD_PORT_PARAM_SET, 6570 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6571 - .doit = devlink_nl_cmd_port_param_set_doit, 6572 - .flags = GENL_ADMIN_PERM, 6573 - .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 6574 - }, 6575 - { 6576 - .cmd = DEVLINK_CMD_REGION_NEW, 6577 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6578 - .doit = devlink_nl_cmd_region_new, 6579 - .flags = GENL_ADMIN_PERM, 6580 - }, 6581 - { 6582 - .cmd = DEVLINK_CMD_REGION_DEL, 6583 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6584 - .doit = devlink_nl_cmd_region_del, 6585 - .flags = GENL_ADMIN_PERM, 6586 - }, 6587 - { 6588 - .cmd = DEVLINK_CMD_REGION_READ, 6589 - .validate = GENL_DONT_VALIDATE_STRICT | 6590 - GENL_DONT_VALIDATE_DUMP_STRICT, 6591 - .dumpit = devlink_nl_cmd_region_read_dumpit, 6592 - .flags = GENL_ADMIN_PERM, 6593 - }, 6594 - { 6595 - .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET, 6596 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6597 - .doit = devlink_nl_cmd_health_reporter_set_doit, 6598 - .flags = GENL_ADMIN_PERM, 6599 - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 6600 - }, 6601 - { 6602 - .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER, 6603 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6604 - .doit = devlink_nl_cmd_health_reporter_recover_doit, 6605 - .flags = GENL_ADMIN_PERM, 6606 - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 6607 - }, 6608 - { 6609 - .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 6610 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6611 - .doit = devlink_nl_cmd_health_reporter_diagnose_doit, 6612 - .flags = GENL_ADMIN_PERM, 6613 - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 6614 - }, 6615 - { 6616 - .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, 6617 - .validate = GENL_DONT_VALIDATE_STRICT | 6618 - GENL_DONT_VALIDATE_DUMP_STRICT, 6619 - .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit, 6620 - .flags = GENL_ADMIN_PERM, 6621 - }, 6622 - { 6623 - .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, 6624 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6625 - .doit = devlink_nl_cmd_health_reporter_dump_clear_doit, 6626 - .flags = GENL_ADMIN_PERM, 6627 - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 6628 - }, 6629 - { 6630 - .cmd = DEVLINK_CMD_HEALTH_REPORTER_TEST, 6631 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6632 - .doit = devlink_nl_cmd_health_reporter_test_doit, 6633 - .flags = GENL_ADMIN_PERM, 6634 - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 6635 - }, 6636 - { 6637 - .cmd = DEVLINK_CMD_FLASH_UPDATE, 6638 - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 6639 - .doit = devlink_nl_cmd_flash_update, 6640 - .flags = GENL_ADMIN_PERM, 6641 - }, 6642 - { 6643 - .cmd = DEVLINK_CMD_TRAP_SET, 6644 - .doit = devlink_nl_cmd_trap_set_doit, 6645 - .flags = GENL_ADMIN_PERM, 6646 - }, 6647 - { 6648 - .cmd = DEVLINK_CMD_TRAP_GROUP_SET, 6649 - .doit = devlink_nl_cmd_trap_group_set_doit, 6650 - .flags = GENL_ADMIN_PERM, 6651 - }, 6652 - { 6653 - .cmd = DEVLINK_CMD_TRAP_POLICER_SET, 6654 - .doit = devlink_nl_cmd_trap_policer_set_doit, 6655 - .flags = GENL_ADMIN_PERM, 6656 - }, 6657 - { 6658 - .cmd = DEVLINK_CMD_SELFTESTS_RUN, 6659 - .doit = devlink_nl_cmd_selftests_run, 6660 - .flags = GENL_ADMIN_PERM, 6661 - }, 6662 - /* -- No new ops here! Use split ops going forward! -- */ 6663 - }; 6664 - 6665 - static void 6666 - devlink_trap_policer_notify(struct devlink *devlink, 6667 - const struct devlink_trap_policer_item *policer_item, 6668 - enum devlink_command cmd); 6669 - static void 6670 - devlink_trap_group_notify(struct devlink *devlink, 6671 - const struct devlink_trap_group_item *group_item, 6672 - enum devlink_command cmd); 6673 - static void devlink_trap_notify(struct devlink *devlink, 6674 - const struct devlink_trap_item *trap_item, 6675 - enum devlink_command cmd); 6676 - 6677 - void devlink_notify_register(struct devlink *devlink) 6678 - { 6679 - struct devlink_trap_policer_item *policer_item; 6680 - struct devlink_trap_group_item *group_item; 6681 - struct devlink_param_item *param_item; 6682 - struct devlink_trap_item *trap_item; 6683 - struct devlink_port *devlink_port; 6684 - struct devlink_linecard *linecard; 6685 - struct devlink_rate *rate_node; 6686 - struct devlink_region *region; 6687 - unsigned long port_index; 6688 - unsigned long param_id; 6689 - 6690 - devlink_notify(devlink, DEVLINK_CMD_NEW); 6691 - list_for_each_entry(linecard, &devlink->linecard_list, list) 6692 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 6693 - 6694 - xa_for_each(&devlink->ports, port_index, devlink_port) 6695 - devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 6696 - 6697 - list_for_each_entry(policer_item, &devlink->trap_policer_list, list) 6698 - devlink_trap_policer_notify(devlink, policer_item, 6699 - DEVLINK_CMD_TRAP_POLICER_NEW); 6700 - 6701 - list_for_each_entry(group_item, &devlink->trap_group_list, list) 6702 - devlink_trap_group_notify(devlink, group_item, 6703 - DEVLINK_CMD_TRAP_GROUP_NEW); 6704 - 6705 - list_for_each_entry(trap_item, &devlink->trap_list, list) 6706 - devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW); 6707 - 6708 - list_for_each_entry(rate_node, &devlink->rate_list, list) 6709 - devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 6710 - 6711 - list_for_each_entry(region, &devlink->region_list, list) 6712 - devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 6713 - 6714 - xa_for_each(&devlink->params, param_id, param_item) 6715 - devlink_param_notify(devlink, 0, param_item, 6716 - DEVLINK_CMD_PARAM_NEW); 6717 - } 6718 - 6719 - void devlink_notify_unregister(struct devlink *devlink) 6720 - { 6721 - struct devlink_trap_policer_item *policer_item; 6722 - struct devlink_trap_group_item *group_item; 6723 - struct devlink_param_item *param_item; 6724 - struct devlink_trap_item *trap_item; 6725 - struct devlink_port *devlink_port; 6726 - struct devlink_linecard *linecard; 6727 - struct devlink_rate *rate_node; 6728 - struct devlink_region *region; 6729 - unsigned long port_index; 6730 - unsigned long param_id; 6731 - 6732 - xa_for_each(&devlink->params, param_id, param_item) 6733 - devlink_param_notify(devlink, 0, param_item, 6734 - DEVLINK_CMD_PARAM_DEL); 6735 - 6736 - list_for_each_entry_reverse(region, &devlink->region_list, list) 6737 - devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 6738 - 6739 - list_for_each_entry_reverse(rate_node, &devlink->rate_list, list) 6740 - devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 6741 - 6742 - list_for_each_entry_reverse(trap_item, &devlink->trap_list, list) 6743 - devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL); 6744 - 6745 - list_for_each_entry_reverse(group_item, &devlink->trap_group_list, list) 6746 - devlink_trap_group_notify(devlink, group_item, 6747 - DEVLINK_CMD_TRAP_GROUP_DEL); 6748 - list_for_each_entry_reverse(policer_item, &devlink->trap_policer_list, 6749 - list) 6750 - devlink_trap_policer_notify(devlink, policer_item, 6751 - DEVLINK_CMD_TRAP_POLICER_DEL); 6752 - 6753 - xa_for_each(&devlink->ports, port_index, devlink_port) 6754 - devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 6755 - list_for_each_entry_reverse(linecard, &devlink->linecard_list, list) 6756 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); 6757 - devlink_notify(devlink, DEVLINK_CMD_DEL); 6758 - } 6759 - 6760 - static void devlink_port_type_warn(struct work_struct *work) 6761 - { 6762 - struct devlink_port *port = container_of(to_delayed_work(work), 6763 - struct devlink_port, 6764 - type_warn_dw); 6765 - dev_warn(port->devlink->dev, "Type was not set for devlink port."); 6766 - } 6767 - 6768 - static bool devlink_port_type_should_warn(struct devlink_port *devlink_port) 6769 - { 6770 - /* Ignore CPU and DSA flavours. */ 6771 - return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU && 6772 - devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA && 6773 - devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_UNUSED; 6774 - } 6775 - 6776 - #define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600) 6777 - 6778 - static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port) 6779 - { 6780 - if (!devlink_port_type_should_warn(devlink_port)) 6781 - return; 6782 - /* Schedule a work to WARN in case driver does not set port 6783 - * type within timeout. 6784 - */ 6785 - schedule_delayed_work(&devlink_port->type_warn_dw, 6786 - DEVLINK_PORT_TYPE_WARN_TIMEOUT); 6787 - } 6788 - 6789 - static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port) 6790 - { 6791 - if (!devlink_port_type_should_warn(devlink_port)) 6792 - return; 6793 - cancel_delayed_work_sync(&devlink_port->type_warn_dw); 6794 - } 6795 - 6796 - /** 6797 - * devlink_port_init() - Init devlink port 6798 - * 6799 - * @devlink: devlink 6800 - * @devlink_port: devlink port 6801 - * 6802 - * Initialize essential stuff that is needed for functions 6803 - * that may be called before devlink port registration. 6804 - * Call to this function is optional and not needed 6805 - * in case the driver does not use such functions. 6806 - */ 6807 - void devlink_port_init(struct devlink *devlink, 6808 - struct devlink_port *devlink_port) 6809 - { 6810 - if (devlink_port->initialized) 6811 - return; 6812 - devlink_port->devlink = devlink; 6813 - INIT_LIST_HEAD(&devlink_port->region_list); 6814 - devlink_port->initialized = true; 6815 - } 6816 - EXPORT_SYMBOL_GPL(devlink_port_init); 6817 - 6818 - /** 6819 - * devlink_port_fini() - Deinitialize devlink port 6820 - * 6821 - * @devlink_port: devlink port 6822 - * 6823 - * Deinitialize essential stuff that is in use for functions 6824 - * that may be called after devlink port unregistration. 6825 - * Call to this function is optional and not needed 6826 - * in case the driver does not use such functions. 6827 - */ 6828 - void devlink_port_fini(struct devlink_port *devlink_port) 6829 - { 6830 - WARN_ON(!list_empty(&devlink_port->region_list)); 6831 - } 6832 - EXPORT_SYMBOL_GPL(devlink_port_fini); 6833 - 6834 - static const struct devlink_port_ops devlink_port_dummy_ops = {}; 6835 - 6836 - /** 6837 - * devl_port_register_with_ops() - Register devlink port 6838 - * 6839 - * @devlink: devlink 6840 - * @devlink_port: devlink port 6841 - * @port_index: driver-specific numerical identifier of the port 6842 - * @ops: port ops 6843 - * 6844 - * Register devlink port with provided port index. User can use 6845 - * any indexing, even hw-related one. devlink_port structure 6846 - * is convenient to be embedded inside user driver private structure. 6847 - * Note that the caller should take care of zeroing the devlink_port 6848 - * structure. 6849 - */ 6850 - int devl_port_register_with_ops(struct devlink *devlink, 6851 - struct devlink_port *devlink_port, 6852 - unsigned int port_index, 6853 - const struct devlink_port_ops *ops) 6854 - { 6855 - int err; 6856 - 6857 - devl_assert_locked(devlink); 6858 - 6859 - ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 6860 - 6861 - devlink_port_init(devlink, devlink_port); 6862 - devlink_port->registered = true; 6863 - devlink_port->index = port_index; 6864 - devlink_port->ops = ops ? ops : &devlink_port_dummy_ops; 6865 - spin_lock_init(&devlink_port->type_lock); 6866 - INIT_LIST_HEAD(&devlink_port->reporter_list); 6867 - err = xa_insert(&devlink->ports, port_index, devlink_port, GFP_KERNEL); 6868 - if (err) { 6869 - devlink_port->registered = false; 6870 - return err; 6871 - } 6872 - 6873 - INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn); 6874 - devlink_port_type_warn_schedule(devlink_port); 6875 - devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 6876 - return 0; 6877 - } 6878 - EXPORT_SYMBOL_GPL(devl_port_register_with_ops); 6879 - 6880 - /** 6881 - * devlink_port_register_with_ops - Register devlink port 6882 - * 6883 - * @devlink: devlink 6884 - * @devlink_port: devlink port 6885 - * @port_index: driver-specific numerical identifier of the port 6886 - * @ops: port ops 6887 - * 6888 - * Register devlink port with provided port index. User can use 6889 - * any indexing, even hw-related one. devlink_port structure 6890 - * is convenient to be embedded inside user driver private structure. 6891 - * Note that the caller should take care of zeroing the devlink_port 6892 - * structure. 6893 - * 6894 - * Context: Takes and release devlink->lock <mutex>. 6895 - */ 6896 - int devlink_port_register_with_ops(struct devlink *devlink, 6897 - struct devlink_port *devlink_port, 6898 - unsigned int port_index, 6899 - const struct devlink_port_ops *ops) 6900 - { 6901 - int err; 6902 - 6903 - devl_lock(devlink); 6904 - err = devl_port_register_with_ops(devlink, devlink_port, 6905 - port_index, ops); 6906 - devl_unlock(devlink); 6907 - return err; 6908 - } 6909 - EXPORT_SYMBOL_GPL(devlink_port_register_with_ops); 6910 - 6911 - /** 6912 - * devl_port_unregister() - Unregister devlink port 6913 - * 6914 - * @devlink_port: devlink port 6915 - */ 6916 - void devl_port_unregister(struct devlink_port *devlink_port) 6917 - { 6918 - lockdep_assert_held(&devlink_port->devlink->lock); 6919 - WARN_ON(devlink_port->type != DEVLINK_PORT_TYPE_NOTSET); 6920 - 6921 - devlink_port_type_warn_cancel(devlink_port); 6922 - devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 6923 - xa_erase(&devlink_port->devlink->ports, devlink_port->index); 6924 - WARN_ON(!list_empty(&devlink_port->reporter_list)); 6925 - devlink_port->registered = false; 6926 - } 6927 - EXPORT_SYMBOL_GPL(devl_port_unregister); 6928 - 6929 - /** 6930 - * devlink_port_unregister - Unregister devlink port 6931 - * 6932 - * @devlink_port: devlink port 6933 - * 6934 - * Context: Takes and release devlink->lock <mutex>. 6935 - */ 6936 - void devlink_port_unregister(struct devlink_port *devlink_port) 6937 - { 6938 - struct devlink *devlink = devlink_port->devlink; 6939 - 6940 - devl_lock(devlink); 6941 - devl_port_unregister(devlink_port); 6942 - devl_unlock(devlink); 6943 - } 6944 - EXPORT_SYMBOL_GPL(devlink_port_unregister); 6945 - 6946 - static void devlink_port_type_netdev_checks(struct devlink_port *devlink_port, 6947 - struct net_device *netdev) 6948 - { 6949 - const struct net_device_ops *ops = netdev->netdev_ops; 6950 - 6951 - /* If driver registers devlink port, it should set devlink port 6952 - * attributes accordingly so the compat functions are called 6953 - * and the original ops are not used. 6954 - */ 6955 - if (ops->ndo_get_phys_port_name) { 6956 - /* Some drivers use the same set of ndos for netdevs 6957 - * that have devlink_port registered and also for 6958 - * those who don't. Make sure that ndo_get_phys_port_name 6959 - * returns -EOPNOTSUPP here in case it is defined. 6960 - * Warn if not. 6961 - */ 6962 - char name[IFNAMSIZ]; 6963 - int err; 6964 - 6965 - err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name)); 6966 - WARN_ON(err != -EOPNOTSUPP); 6967 - } 6968 - if (ops->ndo_get_port_parent_id) { 6969 - /* Some drivers use the same set of ndos for netdevs 6970 - * that have devlink_port registered and also for 6971 - * those who don't. Make sure that ndo_get_port_parent_id 6972 - * returns -EOPNOTSUPP here in case it is defined. 6973 - * Warn if not. 6974 - */ 6975 - struct netdev_phys_item_id ppid; 6976 - int err; 6977 - 6978 - err = ops->ndo_get_port_parent_id(netdev, &ppid); 6979 - WARN_ON(err != -EOPNOTSUPP); 6980 - } 6981 - } 6982 - 6983 - static void __devlink_port_type_set(struct devlink_port *devlink_port, 6984 - enum devlink_port_type type, 6985 - void *type_dev) 6986 - { 6987 - struct net_device *netdev = type_dev; 6988 - 6989 - ASSERT_DEVLINK_PORT_REGISTERED(devlink_port); 6990 - 6991 - if (type == DEVLINK_PORT_TYPE_NOTSET) { 6992 - devlink_port_type_warn_schedule(devlink_port); 6993 - } else { 6994 - devlink_port_type_warn_cancel(devlink_port); 6995 - if (type == DEVLINK_PORT_TYPE_ETH && netdev) 6996 - devlink_port_type_netdev_checks(devlink_port, netdev); 6997 - } 6998 - 6999 - spin_lock_bh(&devlink_port->type_lock); 7000 - devlink_port->type = type; 7001 - switch (type) { 7002 - case DEVLINK_PORT_TYPE_ETH: 7003 - devlink_port->type_eth.netdev = netdev; 7004 - if (netdev) { 7005 - ASSERT_RTNL(); 7006 - devlink_port->type_eth.ifindex = netdev->ifindex; 7007 - BUILD_BUG_ON(sizeof(devlink_port->type_eth.ifname) != 7008 - sizeof(netdev->name)); 7009 - strcpy(devlink_port->type_eth.ifname, netdev->name); 7010 - } 7011 - break; 7012 - case DEVLINK_PORT_TYPE_IB: 7013 - devlink_port->type_ib.ibdev = type_dev; 7014 - break; 7015 - default: 7016 - break; 7017 - } 7018 - spin_unlock_bh(&devlink_port->type_lock); 7019 - devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 7020 - } 7021 - 7022 - /** 7023 - * devlink_port_type_eth_set - Set port type to Ethernet 7024 - * 7025 - * @devlink_port: devlink port 7026 - * 7027 - * If driver is calling this, most likely it is doing something wrong. 7028 - */ 7029 - void devlink_port_type_eth_set(struct devlink_port *devlink_port) 7030 - { 7031 - dev_warn(devlink_port->devlink->dev, 7032 - "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n", 7033 - devlink_port->index); 7034 - __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, NULL); 7035 - } 7036 - EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 7037 - 7038 - /** 7039 - * devlink_port_type_ib_set - Set port type to InfiniBand 7040 - * 7041 - * @devlink_port: devlink port 7042 - * @ibdev: related IB device 7043 - */ 7044 - void devlink_port_type_ib_set(struct devlink_port *devlink_port, 7045 - struct ib_device *ibdev) 7046 - { 7047 - __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev); 7048 - } 7049 - EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 7050 - 7051 - /** 7052 - * devlink_port_type_clear - Clear port type 7053 - * 7054 - * @devlink_port: devlink port 7055 - * 7056 - * If driver is calling this for clearing Ethernet type, most likely 7057 - * it is doing something wrong. 7058 - */ 7059 - void devlink_port_type_clear(struct devlink_port *devlink_port) 7060 - { 7061 - if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) 7062 - dev_warn(devlink_port->devlink->dev, 7063 - "devlink port type for port %d cleared without a software interface reference, device type not supported by the kernel?\n", 7064 - devlink_port->index); 7065 - __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL); 7066 - } 7067 - EXPORT_SYMBOL_GPL(devlink_port_type_clear); 7068 - 7069 - int devlink_port_netdevice_event(struct notifier_block *nb, 7070 - unsigned long event, void *ptr) 7071 - { 7072 - struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 7073 - struct devlink_port *devlink_port = netdev->devlink_port; 7074 - struct devlink *devlink; 7075 - 7076 - if (!devlink_port) 7077 - return NOTIFY_OK; 7078 - devlink = devlink_port->devlink; 7079 - 7080 - switch (event) { 7081 - case NETDEV_POST_INIT: 7082 - /* Set the type but not netdev pointer. It is going to be set 7083 - * later on by NETDEV_REGISTER event. Happens once during 7084 - * netdevice register 7085 - */ 7086 - __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, 7087 - NULL); 7088 - break; 7089 - case NETDEV_REGISTER: 7090 - case NETDEV_CHANGENAME: 7091 - if (devlink_net(devlink) != dev_net(netdev)) 7092 - return NOTIFY_OK; 7093 - /* Set the netdev on top of previously set type. Note this 7094 - * event happens also during net namespace change so here 7095 - * we take into account netdev pointer appearing in this 7096 - * namespace. 7097 - */ 7098 - __devlink_port_type_set(devlink_port, devlink_port->type, 7099 - netdev); 7100 - break; 7101 - case NETDEV_UNREGISTER: 7102 - if (devlink_net(devlink) != dev_net(netdev)) 7103 - return NOTIFY_OK; 7104 - /* Clear netdev pointer, but not the type. This event happens 7105 - * also during net namespace change so we need to clear 7106 - * pointer to netdev that is going to another net namespace. 7107 - */ 7108 - __devlink_port_type_set(devlink_port, devlink_port->type, 7109 - NULL); 7110 - break; 7111 - case NETDEV_PRE_UNINIT: 7112 - /* Clear the type and the netdev pointer. Happens one during 7113 - * netdevice unregister. 7114 - */ 7115 - __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, 7116 - NULL); 7117 - break; 7118 - } 7119 - 7120 - return NOTIFY_OK; 7121 - } 7122 - 7123 - static int __devlink_port_attrs_set(struct devlink_port *devlink_port, 7124 - enum devlink_port_flavour flavour) 7125 - { 7126 - struct devlink_port_attrs *attrs = &devlink_port->attrs; 7127 - 7128 - devlink_port->attrs_set = true; 7129 - attrs->flavour = flavour; 7130 - if (attrs->switch_id.id_len) { 7131 - devlink_port->switch_port = true; 7132 - if (WARN_ON(attrs->switch_id.id_len > MAX_PHYS_ITEM_ID_LEN)) 7133 - attrs->switch_id.id_len = MAX_PHYS_ITEM_ID_LEN; 7134 - } else { 7135 - devlink_port->switch_port = false; 7136 - } 7137 - return 0; 7138 - } 7139 - 7140 - /** 7141 - * devlink_port_attrs_set - Set port attributes 7142 - * 7143 - * @devlink_port: devlink port 7144 - * @attrs: devlink port attrs 7145 - */ 7146 - void devlink_port_attrs_set(struct devlink_port *devlink_port, 7147 - struct devlink_port_attrs *attrs) 7148 - { 7149 - int ret; 7150 - 7151 - ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 7152 - 7153 - devlink_port->attrs = *attrs; 7154 - ret = __devlink_port_attrs_set(devlink_port, attrs->flavour); 7155 - if (ret) 7156 - return; 7157 - WARN_ON(attrs->splittable && attrs->split); 7158 - } 7159 - EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 7160 - 7161 - /** 7162 - * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes 7163 - * 7164 - * @devlink_port: devlink port 7165 - * @controller: associated controller number for the devlink port instance 7166 - * @pf: associated PF for the devlink port instance 7167 - * @external: indicates if the port is for an external controller 7168 - */ 7169 - void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller, 7170 - u16 pf, bool external) 7171 - { 7172 - struct devlink_port_attrs *attrs = &devlink_port->attrs; 7173 - int ret; 7174 - 7175 - ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 7176 - 7177 - ret = __devlink_port_attrs_set(devlink_port, 7178 - DEVLINK_PORT_FLAVOUR_PCI_PF); 7179 - if (ret) 7180 - return; 7181 - attrs->pci_pf.controller = controller; 7182 - attrs->pci_pf.pf = pf; 7183 - attrs->pci_pf.external = external; 7184 - } 7185 - EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set); 7186 - 7187 - /** 7188 - * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes 7189 - * 7190 - * @devlink_port: devlink port 7191 - * @controller: associated controller number for the devlink port instance 7192 - * @pf: associated PF for the devlink port instance 7193 - * @vf: associated VF of a PF for the devlink port instance 7194 - * @external: indicates if the port is for an external controller 7195 - */ 7196 - void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller, 7197 - u16 pf, u16 vf, bool external) 7198 - { 7199 - struct devlink_port_attrs *attrs = &devlink_port->attrs; 7200 - int ret; 7201 - 7202 - ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 7203 - 7204 - ret = __devlink_port_attrs_set(devlink_port, 7205 - DEVLINK_PORT_FLAVOUR_PCI_VF); 7206 - if (ret) 7207 - return; 7208 - attrs->pci_vf.controller = controller; 7209 - attrs->pci_vf.pf = pf; 7210 - attrs->pci_vf.vf = vf; 7211 - attrs->pci_vf.external = external; 7212 - } 7213 - EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set); 7214 - 7215 - /** 7216 - * devlink_port_attrs_pci_sf_set - Set PCI SF port attributes 7217 - * 7218 - * @devlink_port: devlink port 7219 - * @controller: associated controller number for the devlink port instance 7220 - * @pf: associated PF for the devlink port instance 7221 - * @sf: associated SF of a PF for the devlink port instance 7222 - * @external: indicates if the port is for an external controller 7223 - */ 7224 - void devlink_port_attrs_pci_sf_set(struct devlink_port *devlink_port, u32 controller, 7225 - u16 pf, u32 sf, bool external) 7226 - { 7227 - struct devlink_port_attrs *attrs = &devlink_port->attrs; 7228 - int ret; 7229 - 7230 - ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 7231 - 7232 - ret = __devlink_port_attrs_set(devlink_port, 7233 - DEVLINK_PORT_FLAVOUR_PCI_SF); 7234 - if (ret) 7235 - return; 7236 - attrs->pci_sf.controller = controller; 7237 - attrs->pci_sf.pf = pf; 7238 - attrs->pci_sf.sf = sf; 7239 - attrs->pci_sf.external = external; 7240 - } 7241 - EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_sf_set); 7242 - 7243 - /** 7244 - * devl_rate_node_create - create devlink rate node 7245 - * @devlink: devlink instance 7246 - * @priv: driver private data 7247 - * @node_name: name of the resulting node 7248 - * @parent: parent devlink_rate struct 7249 - * 7250 - * Create devlink rate object of type node 7251 - */ 7252 - struct devlink_rate * 7253 - devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name, 7254 - struct devlink_rate *parent) 7255 - { 7256 - struct devlink_rate *rate_node; 7257 - 7258 - rate_node = devlink_rate_node_get_by_name(devlink, node_name); 7259 - if (!IS_ERR(rate_node)) 7260 - return ERR_PTR(-EEXIST); 7261 - 7262 - rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 7263 - if (!rate_node) 7264 - return ERR_PTR(-ENOMEM); 7265 - 7266 - if (parent) { 7267 - rate_node->parent = parent; 7268 - refcount_inc(&rate_node->parent->refcnt); 7269 - } 7270 - 7271 - rate_node->type = DEVLINK_RATE_TYPE_NODE; 7272 - rate_node->devlink = devlink; 7273 - rate_node->priv = priv; 7274 - 7275 - rate_node->name = kstrdup(node_name, GFP_KERNEL); 7276 - if (!rate_node->name) { 7277 - kfree(rate_node); 7278 - return ERR_PTR(-ENOMEM); 7279 - } 7280 - 7281 - refcount_set(&rate_node->refcnt, 1); 7282 - list_add(&rate_node->list, &devlink->rate_list); 7283 - devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 7284 - return rate_node; 7285 - } 7286 - EXPORT_SYMBOL_GPL(devl_rate_node_create); 7287 - 7288 - /** 7289 - * devl_rate_leaf_create - create devlink rate leaf 7290 - * @devlink_port: devlink port object to create rate object on 7291 - * @priv: driver private data 7292 - * @parent: parent devlink_rate struct 7293 - * 7294 - * Create devlink rate object of type leaf on provided @devlink_port. 7295 - */ 7296 - int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv, 7297 - struct devlink_rate *parent) 7298 - { 7299 - struct devlink *devlink = devlink_port->devlink; 7300 - struct devlink_rate *devlink_rate; 7301 - 7302 - devl_assert_locked(devlink_port->devlink); 7303 - 7304 - if (WARN_ON(devlink_port->devlink_rate)) 7305 - return -EBUSY; 7306 - 7307 - devlink_rate = kzalloc(sizeof(*devlink_rate), GFP_KERNEL); 7308 - if (!devlink_rate) 7309 - return -ENOMEM; 7310 - 7311 - if (parent) { 7312 - devlink_rate->parent = parent; 7313 - refcount_inc(&devlink_rate->parent->refcnt); 7314 - } 7315 - 7316 - devlink_rate->type = DEVLINK_RATE_TYPE_LEAF; 7317 - devlink_rate->devlink = devlink; 7318 - devlink_rate->devlink_port = devlink_port; 7319 - devlink_rate->priv = priv; 7320 - list_add_tail(&devlink_rate->list, &devlink->rate_list); 7321 - devlink_port->devlink_rate = devlink_rate; 7322 - devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 7323 - 7324 - return 0; 7325 - } 7326 - EXPORT_SYMBOL_GPL(devl_rate_leaf_create); 7327 - 7328 - /** 7329 - * devl_rate_leaf_destroy - destroy devlink rate leaf 7330 - * 7331 - * @devlink_port: devlink port linked to the rate object 7332 - * 7333 - * Destroy the devlink rate object of type leaf on provided @devlink_port. 7334 - */ 7335 - void devl_rate_leaf_destroy(struct devlink_port *devlink_port) 7336 - { 7337 - struct devlink_rate *devlink_rate = devlink_port->devlink_rate; 7338 - 7339 - devl_assert_locked(devlink_port->devlink); 7340 - if (!devlink_rate) 7341 - return; 7342 - 7343 - devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL); 7344 - if (devlink_rate->parent) 7345 - refcount_dec(&devlink_rate->parent->refcnt); 7346 - list_del(&devlink_rate->list); 7347 - devlink_port->devlink_rate = NULL; 7348 - kfree(devlink_rate); 7349 - } 7350 - EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy); 7351 - 7352 - /** 7353 - * devl_rate_nodes_destroy - destroy all devlink rate nodes on device 7354 - * @devlink: devlink instance 7355 - * 7356 - * Unset parent for all rate objects and destroy all rate nodes 7357 - * on specified device. 7358 - */ 7359 - void devl_rate_nodes_destroy(struct devlink *devlink) 7360 - { 7361 - static struct devlink_rate *devlink_rate, *tmp; 7362 - const struct devlink_ops *ops = devlink->ops; 7363 - 7364 - devl_assert_locked(devlink); 7365 - 7366 - list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 7367 - if (!devlink_rate->parent) 7368 - continue; 7369 - 7370 - refcount_dec(&devlink_rate->parent->refcnt); 7371 - if (devlink_rate_is_leaf(devlink_rate)) 7372 - ops->rate_leaf_parent_set(devlink_rate, NULL, devlink_rate->priv, 7373 - NULL, NULL); 7374 - else if (devlink_rate_is_node(devlink_rate)) 7375 - ops->rate_node_parent_set(devlink_rate, NULL, devlink_rate->priv, 7376 - NULL, NULL); 7377 - } 7378 - list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) { 7379 - if (devlink_rate_is_node(devlink_rate)) { 7380 - ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL); 7381 - list_del(&devlink_rate->list); 7382 - kfree(devlink_rate->name); 7383 - kfree(devlink_rate); 7384 - } 7385 - } 7386 - } 7387 - EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy); 7388 - 7389 - /** 7390 - * devlink_port_linecard_set - Link port with a linecard 7391 - * 7392 - * @devlink_port: devlink port 7393 - * @linecard: devlink linecard 7394 - */ 7395 - void devlink_port_linecard_set(struct devlink_port *devlink_port, 7396 - struct devlink_linecard *linecard) 7397 - { 7398 - ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 7399 - 7400 - devlink_port->linecard = linecard; 7401 - } 7402 - EXPORT_SYMBOL_GPL(devlink_port_linecard_set); 7403 - 7404 - static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, 7405 - char *name, size_t len) 7406 - { 7407 - struct devlink_port_attrs *attrs = &devlink_port->attrs; 7408 - int n = 0; 7409 - 7410 - if (!devlink_port->attrs_set) 7411 - return -EOPNOTSUPP; 7412 - 7413 - switch (attrs->flavour) { 7414 - case DEVLINK_PORT_FLAVOUR_PHYSICAL: 7415 - if (devlink_port->linecard) 7416 - n = snprintf(name, len, "l%u", 7417 - devlink_port->linecard->index); 7418 - if (n < len) 7419 - n += snprintf(name + n, len - n, "p%u", 7420 - attrs->phys.port_number); 7421 - if (n < len && attrs->split) 7422 - n += snprintf(name + n, len - n, "s%u", 7423 - attrs->phys.split_subport_number); 7424 - break; 7425 - case DEVLINK_PORT_FLAVOUR_CPU: 7426 - case DEVLINK_PORT_FLAVOUR_DSA: 7427 - case DEVLINK_PORT_FLAVOUR_UNUSED: 7428 - /* As CPU and DSA ports do not have a netdevice associated 7429 - * case should not ever happen. 7430 - */ 7431 - WARN_ON(1); 7432 - return -EINVAL; 7433 - case DEVLINK_PORT_FLAVOUR_PCI_PF: 7434 - if (attrs->pci_pf.external) { 7435 - n = snprintf(name, len, "c%u", attrs->pci_pf.controller); 7436 - if (n >= len) 7437 - return -EINVAL; 7438 - len -= n; 7439 - name += n; 7440 - } 7441 - n = snprintf(name, len, "pf%u", attrs->pci_pf.pf); 7442 - break; 7443 - case DEVLINK_PORT_FLAVOUR_PCI_VF: 7444 - if (attrs->pci_vf.external) { 7445 - n = snprintf(name, len, "c%u", attrs->pci_vf.controller); 7446 - if (n >= len) 7447 - return -EINVAL; 7448 - len -= n; 7449 - name += n; 7450 - } 7451 - n = snprintf(name, len, "pf%uvf%u", 7452 - attrs->pci_vf.pf, attrs->pci_vf.vf); 7453 - break; 7454 - case DEVLINK_PORT_FLAVOUR_PCI_SF: 7455 - if (attrs->pci_sf.external) { 7456 - n = snprintf(name, len, "c%u", attrs->pci_sf.controller); 7457 - if (n >= len) 7458 - return -EINVAL; 7459 - len -= n; 7460 - name += n; 7461 - } 7462 - n = snprintf(name, len, "pf%usf%u", attrs->pci_sf.pf, 7463 - attrs->pci_sf.sf); 7464 - break; 7465 - case DEVLINK_PORT_FLAVOUR_VIRTUAL: 7466 - return -EOPNOTSUPP; 7467 - } 7468 - 7469 - if (n >= len) 7470 - return -EINVAL; 7471 - 7472 - return 0; 7473 - } 7474 - 7475 - static int devlink_linecard_types_init(struct devlink_linecard *linecard) 7476 - { 7477 - struct devlink_linecard_type *linecard_type; 7478 - unsigned int count; 7479 - int i; 7480 - 7481 - count = linecard->ops->types_count(linecard, linecard->priv); 7482 - linecard->types = kmalloc_array(count, sizeof(*linecard_type), 7483 - GFP_KERNEL); 7484 - if (!linecard->types) 7485 - return -ENOMEM; 7486 - linecard->types_count = count; 7487 - 7488 - for (i = 0; i < count; i++) { 7489 - linecard_type = &linecard->types[i]; 7490 - linecard->ops->types_get(linecard, linecard->priv, i, 7491 - &linecard_type->type, 7492 - &linecard_type->priv); 7493 - } 7494 - return 0; 7495 - } 7496 - 7497 - static void devlink_linecard_types_fini(struct devlink_linecard *linecard) 7498 - { 7499 - kfree(linecard->types); 7500 - } 7501 - 7502 - /** 7503 - * devl_linecard_create - Create devlink linecard 7504 - * 7505 - * @devlink: devlink 7506 - * @linecard_index: driver-specific numerical identifier of the linecard 7507 - * @ops: linecards ops 7508 - * @priv: user priv pointer 7509 - * 7510 - * Create devlink linecard instance with provided linecard index. 7511 - * Caller can use any indexing, even hw-related one. 7512 - * 7513 - * Return: Line card structure or an ERR_PTR() encoded error code. 7514 - */ 7515 - struct devlink_linecard * 7516 - devl_linecard_create(struct devlink *devlink, unsigned int linecard_index, 7517 - const struct devlink_linecard_ops *ops, void *priv) 7518 - { 7519 - struct devlink_linecard *linecard; 7520 - int err; 7521 - 7522 - if (WARN_ON(!ops || !ops->provision || !ops->unprovision || 7523 - !ops->types_count || !ops->types_get)) 7524 - return ERR_PTR(-EINVAL); 7525 - 7526 - if (devlink_linecard_index_exists(devlink, linecard_index)) 7527 - return ERR_PTR(-EEXIST); 7528 - 7529 - linecard = kzalloc(sizeof(*linecard), GFP_KERNEL); 7530 - if (!linecard) 7531 - return ERR_PTR(-ENOMEM); 7532 - 7533 - linecard->devlink = devlink; 7534 - linecard->index = linecard_index; 7535 - linecard->ops = ops; 7536 - linecard->priv = priv; 7537 - linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 7538 - mutex_init(&linecard->state_lock); 7539 - 7540 - err = devlink_linecard_types_init(linecard); 7541 - if (err) { 7542 - mutex_destroy(&linecard->state_lock); 7543 - kfree(linecard); 7544 - return ERR_PTR(err); 7545 - } 7546 - 7547 - list_add_tail(&linecard->list, &devlink->linecard_list); 7548 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 7549 - return linecard; 7550 - } 7551 - EXPORT_SYMBOL_GPL(devl_linecard_create); 7552 - 7553 - /** 7554 - * devl_linecard_destroy - Destroy devlink linecard 7555 - * 7556 - * @linecard: devlink linecard 7557 - */ 7558 - void devl_linecard_destroy(struct devlink_linecard *linecard) 7559 - { 7560 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); 7561 - list_del(&linecard->list); 7562 - devlink_linecard_types_fini(linecard); 7563 - mutex_destroy(&linecard->state_lock); 7564 - kfree(linecard); 7565 - } 7566 - EXPORT_SYMBOL_GPL(devl_linecard_destroy); 7567 - 7568 - /** 7569 - * devlink_linecard_provision_set - Set provisioning on linecard 7570 - * 7571 - * @linecard: devlink linecard 7572 - * @type: linecard type 7573 - * 7574 - * This is either called directly from the provision() op call or 7575 - * as a result of the provision() op call asynchronously. 7576 - */ 7577 - void devlink_linecard_provision_set(struct devlink_linecard *linecard, 7578 - const char *type) 7579 - { 7580 - mutex_lock(&linecard->state_lock); 7581 - WARN_ON(linecard->type && strcmp(linecard->type, type)); 7582 - linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED; 7583 - linecard->type = type; 7584 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 7585 - mutex_unlock(&linecard->state_lock); 7586 - } 7587 - EXPORT_SYMBOL_GPL(devlink_linecard_provision_set); 7588 - 7589 - /** 7590 - * devlink_linecard_provision_clear - Clear provisioning on linecard 7591 - * 7592 - * @linecard: devlink linecard 7593 - * 7594 - * This is either called directly from the unprovision() op call or 7595 - * as a result of the unprovision() op call asynchronously. 7596 - */ 7597 - void devlink_linecard_provision_clear(struct devlink_linecard *linecard) 7598 - { 7599 - mutex_lock(&linecard->state_lock); 7600 - WARN_ON(linecard->nested_devlink); 7601 - linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 7602 - linecard->type = NULL; 7603 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 7604 - mutex_unlock(&linecard->state_lock); 7605 - } 7606 - EXPORT_SYMBOL_GPL(devlink_linecard_provision_clear); 7607 - 7608 - /** 7609 - * devlink_linecard_provision_fail - Fail provisioning on linecard 7610 - * 7611 - * @linecard: devlink linecard 7612 - * 7613 - * This is either called directly from the provision() op call or 7614 - * as a result of the provision() op call asynchronously. 7615 - */ 7616 - void devlink_linecard_provision_fail(struct devlink_linecard *linecard) 7617 - { 7618 - mutex_lock(&linecard->state_lock); 7619 - WARN_ON(linecard->nested_devlink); 7620 - linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED; 7621 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 7622 - mutex_unlock(&linecard->state_lock); 7623 - } 7624 - EXPORT_SYMBOL_GPL(devlink_linecard_provision_fail); 7625 - 7626 - /** 7627 - * devlink_linecard_activate - Set linecard active 7628 - * 7629 - * @linecard: devlink linecard 7630 - */ 7631 - void devlink_linecard_activate(struct devlink_linecard *linecard) 7632 - { 7633 - mutex_lock(&linecard->state_lock); 7634 - WARN_ON(linecard->state != DEVLINK_LINECARD_STATE_PROVISIONED); 7635 - linecard->state = DEVLINK_LINECARD_STATE_ACTIVE; 7636 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 7637 - mutex_unlock(&linecard->state_lock); 7638 - } 7639 - EXPORT_SYMBOL_GPL(devlink_linecard_activate); 7640 - 7641 - /** 7642 - * devlink_linecard_deactivate - Set linecard inactive 7643 - * 7644 - * @linecard: devlink linecard 7645 - */ 7646 - void devlink_linecard_deactivate(struct devlink_linecard *linecard) 7647 - { 7648 - mutex_lock(&linecard->state_lock); 7649 - switch (linecard->state) { 7650 - case DEVLINK_LINECARD_STATE_ACTIVE: 7651 - linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED; 7652 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 7653 - break; 7654 - case DEVLINK_LINECARD_STATE_UNPROVISIONING: 7655 - /* Line card is being deactivated as part 7656 - * of unprovisioning flow. 7657 - */ 7658 - break; 7659 - default: 7660 - WARN_ON(1); 7661 - break; 7662 - } 7663 - mutex_unlock(&linecard->state_lock); 7664 - } 7665 - EXPORT_SYMBOL_GPL(devlink_linecard_deactivate); 7666 - 7667 - /** 7668 - * devlink_linecard_nested_dl_set - Attach/detach nested devlink 7669 - * instance to linecard. 7670 - * 7671 - * @linecard: devlink linecard 7672 - * @nested_devlink: devlink instance to attach or NULL to detach 7673 - */ 7674 - void devlink_linecard_nested_dl_set(struct devlink_linecard *linecard, 7675 - struct devlink *nested_devlink) 7676 - { 7677 - mutex_lock(&linecard->state_lock); 7678 - linecard->nested_devlink = nested_devlink; 7679 - devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 7680 - mutex_unlock(&linecard->state_lock); 7681 - } 7682 - EXPORT_SYMBOL_GPL(devlink_linecard_nested_dl_set); 7683 - 7684 - int devl_sb_register(struct devlink *devlink, unsigned int sb_index, 7685 - u32 size, u16 ingress_pools_count, 7686 - u16 egress_pools_count, u16 ingress_tc_count, 7687 - u16 egress_tc_count) 7688 - { 7689 - struct devlink_sb *devlink_sb; 7690 - 7691 - lockdep_assert_held(&devlink->lock); 7692 - 7693 - if (devlink_sb_index_exists(devlink, sb_index)) 7694 - return -EEXIST; 7695 - 7696 - devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 7697 - if (!devlink_sb) 7698 - return -ENOMEM; 7699 - devlink_sb->index = sb_index; 7700 - devlink_sb->size = size; 7701 - devlink_sb->ingress_pools_count = ingress_pools_count; 7702 - devlink_sb->egress_pools_count = egress_pools_count; 7703 - devlink_sb->ingress_tc_count = ingress_tc_count; 7704 - devlink_sb->egress_tc_count = egress_tc_count; 7705 - list_add_tail(&devlink_sb->list, &devlink->sb_list); 7706 - return 0; 7707 - } 7708 - EXPORT_SYMBOL_GPL(devl_sb_register); 7709 - 7710 - int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 7711 - u32 size, u16 ingress_pools_count, 7712 - u16 egress_pools_count, u16 ingress_tc_count, 7713 - u16 egress_tc_count) 7714 - { 7715 - int err; 7716 - 7717 - devl_lock(devlink); 7718 - err = devl_sb_register(devlink, sb_index, size, ingress_pools_count, 7719 - egress_pools_count, ingress_tc_count, 7720 - egress_tc_count); 7721 - devl_unlock(devlink); 7722 - return err; 7723 - } 7724 - EXPORT_SYMBOL_GPL(devlink_sb_register); 7725 - 7726 - void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index) 7727 - { 7728 - struct devlink_sb *devlink_sb; 7729 - 7730 - lockdep_assert_held(&devlink->lock); 7731 - 7732 - devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 7733 - WARN_ON(!devlink_sb); 7734 - list_del(&devlink_sb->list); 7735 - kfree(devlink_sb); 7736 - } 7737 - EXPORT_SYMBOL_GPL(devl_sb_unregister); 7738 - 7739 - void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 7740 - { 7741 - devl_lock(devlink); 7742 - devl_sb_unregister(devlink, sb_index); 7743 - devl_unlock(devlink); 7744 - } 7745 - EXPORT_SYMBOL_GPL(devlink_sb_unregister); 7746 - 7747 - /** 7748 - * devl_dpipe_headers_register - register dpipe headers 7749 - * 7750 - * @devlink: devlink 7751 - * @dpipe_headers: dpipe header array 7752 - * 7753 - * Register the headers supported by hardware. 7754 - */ 7755 - void devl_dpipe_headers_register(struct devlink *devlink, 7756 - struct devlink_dpipe_headers *dpipe_headers) 7757 - { 7758 - lockdep_assert_held(&devlink->lock); 7759 - 7760 - devlink->dpipe_headers = dpipe_headers; 7761 - } 7762 - EXPORT_SYMBOL_GPL(devl_dpipe_headers_register); 7763 - 7764 - /** 7765 - * devl_dpipe_headers_unregister - unregister dpipe headers 7766 - * 7767 - * @devlink: devlink 7768 - * 7769 - * Unregister the headers supported by hardware. 7770 - */ 7771 - void devl_dpipe_headers_unregister(struct devlink *devlink) 7772 - { 7773 - lockdep_assert_held(&devlink->lock); 7774 - 7775 - devlink->dpipe_headers = NULL; 7776 - } 7777 - EXPORT_SYMBOL_GPL(devl_dpipe_headers_unregister); 7778 - 7779 - /** 7780 - * devlink_dpipe_table_counter_enabled - check if counter allocation 7781 - * required 7782 - * @devlink: devlink 7783 - * @table_name: tables name 7784 - * 7785 - * Used by driver to check if counter allocation is required. 7786 - * After counter allocation is turned on the table entries 7787 - * are updated to include counter statistics. 7788 - * 7789 - * After that point on the driver must respect the counter 7790 - * state so that each entry added to the table is added 7791 - * with a counter. 7792 - */ 7793 - bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 7794 - const char *table_name) 7795 - { 7796 - struct devlink_dpipe_table *table; 7797 - bool enabled; 7798 - 7799 - rcu_read_lock(); 7800 - table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 7801 - table_name, devlink); 7802 - enabled = false; 7803 - if (table) 7804 - enabled = table->counters_enabled; 7805 - rcu_read_unlock(); 7806 - return enabled; 7807 - } 7808 - EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 7809 - 7810 - /** 7811 - * devl_dpipe_table_register - register dpipe table 7812 - * 7813 - * @devlink: devlink 7814 - * @table_name: table name 7815 - * @table_ops: table ops 7816 - * @priv: priv 7817 - * @counter_control_extern: external control for counters 7818 - */ 7819 - int devl_dpipe_table_register(struct devlink *devlink, 7820 - const char *table_name, 7821 - struct devlink_dpipe_table_ops *table_ops, 7822 - void *priv, bool counter_control_extern) 7823 - { 7824 - struct devlink_dpipe_table *table; 7825 - 7826 - lockdep_assert_held(&devlink->lock); 7827 - 7828 - if (WARN_ON(!table_ops->size_get)) 7829 - return -EINVAL; 7830 - 7831 - if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name, 7832 - devlink)) 7833 - return -EEXIST; 7834 - 7835 - table = kzalloc(sizeof(*table), GFP_KERNEL); 7836 - if (!table) 7837 - return -ENOMEM; 7838 - 7839 - table->name = table_name; 7840 - table->table_ops = table_ops; 7841 - table->priv = priv; 7842 - table->counter_control_extern = counter_control_extern; 7843 - 7844 - list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 7845 - 7846 - return 0; 7847 - } 7848 - EXPORT_SYMBOL_GPL(devl_dpipe_table_register); 7849 - 7850 - /** 7851 - * devl_dpipe_table_unregister - unregister dpipe table 7852 - * 7853 - * @devlink: devlink 7854 - * @table_name: table name 7855 - */ 7856 - void devl_dpipe_table_unregister(struct devlink *devlink, 7857 - const char *table_name) 7858 - { 7859 - struct devlink_dpipe_table *table; 7860 - 7861 - lockdep_assert_held(&devlink->lock); 7862 - 7863 - table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 7864 - table_name, devlink); 7865 - if (!table) 7866 - return; 7867 - list_del_rcu(&table->list); 7868 - kfree_rcu(table, rcu); 7869 - } 7870 - EXPORT_SYMBOL_GPL(devl_dpipe_table_unregister); 7871 - 7872 - /** 7873 - * devl_resource_register - devlink resource register 7874 - * 7875 - * @devlink: devlink 7876 - * @resource_name: resource's name 7877 - * @resource_size: resource's size 7878 - * @resource_id: resource's id 7879 - * @parent_resource_id: resource's parent id 7880 - * @size_params: size parameters 7881 - * 7882 - * Generic resources should reuse the same names across drivers. 7883 - * Please see the generic resources list at: 7884 - * Documentation/networking/devlink/devlink-resource.rst 7885 - */ 7886 - int devl_resource_register(struct devlink *devlink, 7887 - const char *resource_name, 7888 - u64 resource_size, 7889 - u64 resource_id, 7890 - u64 parent_resource_id, 7891 - const struct devlink_resource_size_params *size_params) 7892 - { 7893 - struct devlink_resource *resource; 7894 - struct list_head *resource_list; 7895 - bool top_hierarchy; 7896 - 7897 - lockdep_assert_held(&devlink->lock); 7898 - 7899 - top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 7900 - 7901 - resource = devlink_resource_find(devlink, NULL, resource_id); 7902 - if (resource) 7903 - return -EINVAL; 7904 - 7905 - resource = kzalloc(sizeof(*resource), GFP_KERNEL); 7906 - if (!resource) 7907 - return -ENOMEM; 7908 - 7909 - if (top_hierarchy) { 7910 - resource_list = &devlink->resource_list; 7911 - } else { 7912 - struct devlink_resource *parent_resource; 7913 - 7914 - parent_resource = devlink_resource_find(devlink, NULL, 7915 - parent_resource_id); 7916 - if (parent_resource) { 7917 - resource_list = &parent_resource->resource_list; 7918 - resource->parent = parent_resource; 7919 - } else { 7920 - kfree(resource); 7921 - return -EINVAL; 7922 - } 7923 - } 7924 - 7925 - resource->name = resource_name; 7926 - resource->size = resource_size; 7927 - resource->size_new = resource_size; 7928 - resource->id = resource_id; 7929 - resource->size_valid = true; 7930 - memcpy(&resource->size_params, size_params, 7931 - sizeof(resource->size_params)); 7932 - INIT_LIST_HEAD(&resource->resource_list); 7933 - list_add_tail(&resource->list, resource_list); 7934 - 7935 - return 0; 7936 - } 7937 - EXPORT_SYMBOL_GPL(devl_resource_register); 7938 - 7939 - /** 7940 - * devlink_resource_register - devlink resource register 7941 - * 7942 - * @devlink: devlink 7943 - * @resource_name: resource's name 7944 - * @resource_size: resource's size 7945 - * @resource_id: resource's id 7946 - * @parent_resource_id: resource's parent id 7947 - * @size_params: size parameters 7948 - * 7949 - * Generic resources should reuse the same names across drivers. 7950 - * Please see the generic resources list at: 7951 - * Documentation/networking/devlink/devlink-resource.rst 7952 - * 7953 - * Context: Takes and release devlink->lock <mutex>. 7954 - */ 7955 - int devlink_resource_register(struct devlink *devlink, 7956 - const char *resource_name, 7957 - u64 resource_size, 7958 - u64 resource_id, 7959 - u64 parent_resource_id, 7960 - const struct devlink_resource_size_params *size_params) 7961 - { 7962 - int err; 7963 - 7964 - devl_lock(devlink); 7965 - err = devl_resource_register(devlink, resource_name, resource_size, 7966 - resource_id, parent_resource_id, size_params); 7967 - devl_unlock(devlink); 7968 - return err; 7969 - } 7970 - EXPORT_SYMBOL_GPL(devlink_resource_register); 7971 - 7972 - static void devlink_resource_unregister(struct devlink *devlink, 7973 - struct devlink_resource *resource) 7974 - { 7975 - struct devlink_resource *tmp, *child_resource; 7976 - 7977 - list_for_each_entry_safe(child_resource, tmp, &resource->resource_list, 7978 - list) { 7979 - devlink_resource_unregister(devlink, child_resource); 7980 - list_del(&child_resource->list); 7981 - kfree(child_resource); 7982 - } 7983 - } 7984 - 7985 - /** 7986 - * devl_resources_unregister - free all resources 7987 - * 7988 - * @devlink: devlink 7989 - */ 7990 - void devl_resources_unregister(struct devlink *devlink) 7991 - { 7992 - struct devlink_resource *tmp, *child_resource; 7993 - 7994 - lockdep_assert_held(&devlink->lock); 7995 - 7996 - list_for_each_entry_safe(child_resource, tmp, &devlink->resource_list, 7997 - list) { 7998 - devlink_resource_unregister(devlink, child_resource); 7999 - list_del(&child_resource->list); 8000 - kfree(child_resource); 8001 - } 8002 - } 8003 - EXPORT_SYMBOL_GPL(devl_resources_unregister); 8004 - 8005 - /** 8006 - * devlink_resources_unregister - free all resources 8007 - * 8008 - * @devlink: devlink 8009 - * 8010 - * Context: Takes and release devlink->lock <mutex>. 8011 - */ 8012 - void devlink_resources_unregister(struct devlink *devlink) 8013 - { 8014 - devl_lock(devlink); 8015 - devl_resources_unregister(devlink); 8016 - devl_unlock(devlink); 8017 - } 8018 - EXPORT_SYMBOL_GPL(devlink_resources_unregister); 8019 - 8020 - /** 8021 - * devl_resource_size_get - get and update size 8022 - * 8023 - * @devlink: devlink 8024 - * @resource_id: the requested resource id 8025 - * @p_resource_size: ptr to update 8026 - */ 8027 - int devl_resource_size_get(struct devlink *devlink, 8028 - u64 resource_id, 8029 - u64 *p_resource_size) 8030 - { 8031 - struct devlink_resource *resource; 8032 - 8033 - lockdep_assert_held(&devlink->lock); 8034 - 8035 - resource = devlink_resource_find(devlink, NULL, resource_id); 8036 - if (!resource) 8037 - return -EINVAL; 8038 - *p_resource_size = resource->size_new; 8039 - resource->size = resource->size_new; 8040 - return 0; 8041 - } 8042 - EXPORT_SYMBOL_GPL(devl_resource_size_get); 8043 - 8044 - /** 8045 - * devl_dpipe_table_resource_set - set the resource id 8046 - * 8047 - * @devlink: devlink 8048 - * @table_name: table name 8049 - * @resource_id: resource id 8050 - * @resource_units: number of resource's units consumed per table's entry 8051 - */ 8052 - int devl_dpipe_table_resource_set(struct devlink *devlink, 8053 - const char *table_name, u64 resource_id, 8054 - u64 resource_units) 8055 - { 8056 - struct devlink_dpipe_table *table; 8057 - 8058 - table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 8059 - table_name, devlink); 8060 - if (!table) 8061 - return -EINVAL; 8062 - 8063 - table->resource_id = resource_id; 8064 - table->resource_units = resource_units; 8065 - table->resource_valid = true; 8066 - return 0; 8067 - } 8068 - EXPORT_SYMBOL_GPL(devl_dpipe_table_resource_set); 8069 - 8070 - /** 8071 - * devl_resource_occ_get_register - register occupancy getter 8072 - * 8073 - * @devlink: devlink 8074 - * @resource_id: resource id 8075 - * @occ_get: occupancy getter callback 8076 - * @occ_get_priv: occupancy getter callback priv 8077 - */ 8078 - void devl_resource_occ_get_register(struct devlink *devlink, 8079 - u64 resource_id, 8080 - devlink_resource_occ_get_t *occ_get, 8081 - void *occ_get_priv) 8082 - { 8083 - struct devlink_resource *resource; 8084 - 8085 - lockdep_assert_held(&devlink->lock); 8086 - 8087 - resource = devlink_resource_find(devlink, NULL, resource_id); 8088 - if (WARN_ON(!resource)) 8089 - return; 8090 - WARN_ON(resource->occ_get); 8091 - 8092 - resource->occ_get = occ_get; 8093 - resource->occ_get_priv = occ_get_priv; 8094 - } 8095 - EXPORT_SYMBOL_GPL(devl_resource_occ_get_register); 8096 - 8097 - /** 8098 - * devlink_resource_occ_get_register - register occupancy getter 8099 - * 8100 - * @devlink: devlink 8101 - * @resource_id: resource id 8102 - * @occ_get: occupancy getter callback 8103 - * @occ_get_priv: occupancy getter callback priv 8104 - * 8105 - * Context: Takes and release devlink->lock <mutex>. 8106 - */ 8107 - void devlink_resource_occ_get_register(struct devlink *devlink, 8108 - u64 resource_id, 8109 - devlink_resource_occ_get_t *occ_get, 8110 - void *occ_get_priv) 8111 - { 8112 - devl_lock(devlink); 8113 - devl_resource_occ_get_register(devlink, resource_id, 8114 - occ_get, occ_get_priv); 8115 - devl_unlock(devlink); 8116 - } 8117 - EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 8118 - 8119 - /** 8120 - * devl_resource_occ_get_unregister - unregister occupancy getter 8121 - * 8122 - * @devlink: devlink 8123 - * @resource_id: resource id 8124 - */ 8125 - void devl_resource_occ_get_unregister(struct devlink *devlink, 8126 - u64 resource_id) 8127 - { 8128 - struct devlink_resource *resource; 8129 - 8130 - lockdep_assert_held(&devlink->lock); 8131 - 8132 - resource = devlink_resource_find(devlink, NULL, resource_id); 8133 - if (WARN_ON(!resource)) 8134 - return; 8135 - WARN_ON(!resource->occ_get); 8136 - 8137 - resource->occ_get = NULL; 8138 - resource->occ_get_priv = NULL; 8139 - } 8140 - EXPORT_SYMBOL_GPL(devl_resource_occ_get_unregister); 8141 - 8142 - /** 8143 - * devlink_resource_occ_get_unregister - unregister occupancy getter 8144 - * 8145 - * @devlink: devlink 8146 - * @resource_id: resource id 8147 - * 8148 - * Context: Takes and release devlink->lock <mutex>. 8149 - */ 8150 - void devlink_resource_occ_get_unregister(struct devlink *devlink, 8151 - u64 resource_id) 8152 - { 8153 - devl_lock(devlink); 8154 - devl_resource_occ_get_unregister(devlink, resource_id); 8155 - devl_unlock(devlink); 8156 - } 8157 - EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 8158 - 8159 - static int devlink_param_verify(const struct devlink_param *param) 8160 - { 8161 - if (!param || !param->name || !param->supported_cmodes) 8162 - return -EINVAL; 8163 - if (param->generic) 8164 - return devlink_param_generic_verify(param); 8165 - else 8166 - return devlink_param_driver_verify(param); 8167 - } 8168 - 8169 - static int devlink_param_register(struct devlink *devlink, 8170 - const struct devlink_param *param) 8171 - { 8172 - struct devlink_param_item *param_item; 8173 - int err; 8174 - 8175 - WARN_ON(devlink_param_verify(param)); 8176 - WARN_ON(devlink_param_find_by_name(&devlink->params, param->name)); 8177 - 8178 - if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 8179 - WARN_ON(param->get || param->set); 8180 - else 8181 - WARN_ON(!param->get || !param->set); 8182 - 8183 - param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 8184 - if (!param_item) 8185 - return -ENOMEM; 8186 - 8187 - param_item->param = param; 8188 - 8189 - err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL); 8190 - if (err) 8191 - goto err_xa_insert; 8192 - 8193 - devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 8194 - return 0; 8195 - 8196 - err_xa_insert: 8197 - kfree(param_item); 8198 - return err; 8199 - } 8200 - 8201 - static void devlink_param_unregister(struct devlink *devlink, 8202 - const struct devlink_param *param) 8203 - { 8204 - struct devlink_param_item *param_item; 8205 - 8206 - param_item = devlink_param_find_by_id(&devlink->params, param->id); 8207 - if (WARN_ON(!param_item)) 8208 - return; 8209 - devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL); 8210 - xa_erase(&devlink->params, param->id); 8211 - kfree(param_item); 8212 - } 8213 - 8214 - /** 8215 - * devl_params_register - register configuration parameters 8216 - * 8217 - * @devlink: devlink 8218 - * @params: configuration parameters array 8219 - * @params_count: number of parameters provided 8220 - * 8221 - * Register the configuration parameters supported by the driver. 8222 - */ 8223 - int devl_params_register(struct devlink *devlink, 8224 - const struct devlink_param *params, 8225 - size_t params_count) 8226 - { 8227 - const struct devlink_param *param = params; 8228 - int i, err; 8229 - 8230 - lockdep_assert_held(&devlink->lock); 8231 - 8232 - for (i = 0; i < params_count; i++, param++) { 8233 - err = devlink_param_register(devlink, param); 8234 - if (err) 8235 - goto rollback; 8236 - } 8237 - return 0; 8238 - 8239 - rollback: 8240 - if (!i) 8241 - return err; 8242 - 8243 - for (param--; i > 0; i--, param--) 8244 - devlink_param_unregister(devlink, param); 8245 - return err; 8246 - } 8247 - EXPORT_SYMBOL_GPL(devl_params_register); 8248 - 8249 - int devlink_params_register(struct devlink *devlink, 8250 - const struct devlink_param *params, 8251 - size_t params_count) 8252 - { 8253 - int err; 8254 - 8255 - devl_lock(devlink); 8256 - err = devl_params_register(devlink, params, params_count); 8257 - devl_unlock(devlink); 8258 - return err; 8259 - } 8260 - EXPORT_SYMBOL_GPL(devlink_params_register); 8261 - 8262 - /** 8263 - * devl_params_unregister - unregister configuration parameters 8264 - * @devlink: devlink 8265 - * @params: configuration parameters to unregister 8266 - * @params_count: number of parameters provided 8267 - */ 8268 - void devl_params_unregister(struct devlink *devlink, 8269 - const struct devlink_param *params, 8270 - size_t params_count) 8271 - { 8272 - const struct devlink_param *param = params; 8273 - int i; 8274 - 8275 - lockdep_assert_held(&devlink->lock); 8276 - 8277 - for (i = 0; i < params_count; i++, param++) 8278 - devlink_param_unregister(devlink, param); 8279 - } 8280 - EXPORT_SYMBOL_GPL(devl_params_unregister); 8281 - 8282 - void devlink_params_unregister(struct devlink *devlink, 8283 - const struct devlink_param *params, 8284 - size_t params_count) 8285 - { 8286 - devl_lock(devlink); 8287 - devl_params_unregister(devlink, params, params_count); 8288 - devl_unlock(devlink); 8289 - } 8290 - EXPORT_SYMBOL_GPL(devlink_params_unregister); 8291 - 8292 - /** 8293 - * devl_param_driverinit_value_get - get configuration parameter 8294 - * value for driver initializing 8295 - * 8296 - * @devlink: devlink 8297 - * @param_id: parameter ID 8298 - * @val: pointer to store the value of parameter in driverinit 8299 - * configuration mode 8300 - * 8301 - * This function should be used by the driver to get driverinit 8302 - * configuration for initialization after reload command. 8303 - * 8304 - * Note that lockless call of this function relies on the 8305 - * driver to maintain following basic sane behavior: 8306 - * 1) Driver ensures a call to this function cannot race with 8307 - * registering/unregistering the parameter with the same parameter ID. 8308 - * 2) Driver ensures a call to this function cannot race with 8309 - * devl_param_driverinit_value_set() call with the same parameter ID. 8310 - * 3) Driver ensures a call to this function cannot race with 8311 - * reload operation. 8312 - * If the driver is not able to comply, it has to take the devlink->lock 8313 - * while calling this. 8314 - */ 8315 - int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 8316 - union devlink_param_value *val) 8317 - { 8318 - struct devlink_param_item *param_item; 8319 - 8320 - if (WARN_ON(!devlink_reload_supported(devlink->ops))) 8321 - return -EOPNOTSUPP; 8322 - 8323 - param_item = devlink_param_find_by_id(&devlink->params, param_id); 8324 - if (!param_item) 8325 - return -EINVAL; 8326 - 8327 - if (!param_item->driverinit_value_valid) 8328 - return -EOPNOTSUPP; 8329 - 8330 - if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param, 8331 - DEVLINK_PARAM_CMODE_DRIVERINIT))) 8332 - return -EOPNOTSUPP; 8333 - 8334 - *val = param_item->driverinit_value; 8335 - 8336 - return 0; 8337 - } 8338 - EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get); 8339 - 8340 - /** 8341 - * devl_param_driverinit_value_set - set value of configuration 8342 - * parameter for driverinit 8343 - * configuration mode 8344 - * 8345 - * @devlink: devlink 8346 - * @param_id: parameter ID 8347 - * @init_val: value of parameter to set for driverinit configuration mode 8348 - * 8349 - * This function should be used by the driver to set driverinit 8350 - * configuration mode default value. 8351 - */ 8352 - void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 8353 - union devlink_param_value init_val) 8354 - { 8355 - struct devlink_param_item *param_item; 8356 - 8357 - devl_assert_locked(devlink); 8358 - 8359 - param_item = devlink_param_find_by_id(&devlink->params, param_id); 8360 - if (WARN_ON(!param_item)) 8361 - return; 8362 - 8363 - if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param, 8364 - DEVLINK_PARAM_CMODE_DRIVERINIT))) 8365 - return; 8366 - 8367 - param_item->driverinit_value = init_val; 8368 - param_item->driverinit_value_valid = true; 8369 - 8370 - devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 8371 - } 8372 - EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set); 8373 - 8374 - void devlink_params_driverinit_load_new(struct devlink *devlink) 8375 - { 8376 - struct devlink_param_item *param_item; 8377 - unsigned long param_id; 8378 - 8379 - xa_for_each(&devlink->params, param_id, param_item) { 8380 - if (!devlink_param_cmode_is_supported(param_item->param, 8381 - DEVLINK_PARAM_CMODE_DRIVERINIT) || 8382 - !param_item->driverinit_value_new_valid) 8383 - continue; 8384 - param_item->driverinit_value = param_item->driverinit_value_new; 8385 - param_item->driverinit_value_valid = true; 8386 - param_item->driverinit_value_new_valid = false; 8387 - } 8388 - } 8389 - 8390 - /** 8391 - * devl_param_value_changed - notify devlink on a parameter's value 8392 - * change. Should be called by the driver 8393 - * right after the change. 8394 - * 8395 - * @devlink: devlink 8396 - * @param_id: parameter ID 8397 - * 8398 - * This function should be used by the driver to notify devlink on value 8399 - * change, excluding driverinit configuration mode. 8400 - * For driverinit configuration mode driver should use the function 8401 - */ 8402 - void devl_param_value_changed(struct devlink *devlink, u32 param_id) 8403 - { 8404 - struct devlink_param_item *param_item; 8405 - 8406 - param_item = devlink_param_find_by_id(&devlink->params, param_id); 8407 - WARN_ON(!param_item); 8408 - 8409 - devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 8410 - } 8411 - EXPORT_SYMBOL_GPL(devl_param_value_changed); 8412 - 8413 - /** 8414 - * devl_region_create - create a new address region 8415 - * 8416 - * @devlink: devlink 8417 - * @ops: region operations and name 8418 - * @region_max_snapshots: Maximum supported number of snapshots for region 8419 - * @region_size: size of region 8420 - */ 8421 - struct devlink_region *devl_region_create(struct devlink *devlink, 8422 - const struct devlink_region_ops *ops, 8423 - u32 region_max_snapshots, 8424 - u64 region_size) 8425 - { 8426 - struct devlink_region *region; 8427 - 8428 - devl_assert_locked(devlink); 8429 - 8430 - if (WARN_ON(!ops) || WARN_ON(!ops->destructor)) 8431 - return ERR_PTR(-EINVAL); 8432 - 8433 - if (devlink_region_get_by_name(devlink, ops->name)) 8434 - return ERR_PTR(-EEXIST); 8435 - 8436 - region = kzalloc(sizeof(*region), GFP_KERNEL); 8437 - if (!region) 8438 - return ERR_PTR(-ENOMEM); 8439 - 8440 - region->devlink = devlink; 8441 - region->max_snapshots = region_max_snapshots; 8442 - region->ops = ops; 8443 - region->size = region_size; 8444 - INIT_LIST_HEAD(&region->snapshot_list); 8445 - mutex_init(&region->snapshot_lock); 8446 - list_add_tail(&region->list, &devlink->region_list); 8447 - devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 8448 - 8449 - return region; 8450 - } 8451 - EXPORT_SYMBOL_GPL(devl_region_create); 8452 - 8453 - /** 8454 - * devlink_region_create - create a new address region 8455 - * 8456 - * @devlink: devlink 8457 - * @ops: region operations and name 8458 - * @region_max_snapshots: Maximum supported number of snapshots for region 8459 - * @region_size: size of region 8460 - * 8461 - * Context: Takes and release devlink->lock <mutex>. 8462 - */ 8463 - struct devlink_region * 8464 - devlink_region_create(struct devlink *devlink, 8465 - const struct devlink_region_ops *ops, 8466 - u32 region_max_snapshots, u64 region_size) 8467 - { 8468 - struct devlink_region *region; 8469 - 8470 - devl_lock(devlink); 8471 - region = devl_region_create(devlink, ops, region_max_snapshots, 8472 - region_size); 8473 - devl_unlock(devlink); 8474 - return region; 8475 - } 8476 - EXPORT_SYMBOL_GPL(devlink_region_create); 8477 - 8478 - /** 8479 - * devlink_port_region_create - create a new address region for a port 8480 - * 8481 - * @port: devlink port 8482 - * @ops: region operations and name 8483 - * @region_max_snapshots: Maximum supported number of snapshots for region 8484 - * @region_size: size of region 8485 - * 8486 - * Context: Takes and release devlink->lock <mutex>. 8487 - */ 8488 - struct devlink_region * 8489 - devlink_port_region_create(struct devlink_port *port, 8490 - const struct devlink_port_region_ops *ops, 8491 - u32 region_max_snapshots, u64 region_size) 8492 - { 8493 - struct devlink *devlink = port->devlink; 8494 - struct devlink_region *region; 8495 - int err = 0; 8496 - 8497 - ASSERT_DEVLINK_PORT_INITIALIZED(port); 8498 - 8499 - if (WARN_ON(!ops) || WARN_ON(!ops->destructor)) 8500 - return ERR_PTR(-EINVAL); 8501 - 8502 - devl_lock(devlink); 8503 - 8504 - if (devlink_port_region_get_by_name(port, ops->name)) { 8505 - err = -EEXIST; 8506 - goto unlock; 8507 - } 8508 - 8509 - region = kzalloc(sizeof(*region), GFP_KERNEL); 8510 - if (!region) { 8511 - err = -ENOMEM; 8512 - goto unlock; 8513 - } 8514 - 8515 - region->devlink = devlink; 8516 - region->port = port; 8517 - region->max_snapshots = region_max_snapshots; 8518 - region->port_ops = ops; 8519 - region->size = region_size; 8520 - INIT_LIST_HEAD(&region->snapshot_list); 8521 - mutex_init(&region->snapshot_lock); 8522 - list_add_tail(&region->list, &port->region_list); 8523 - devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 8524 - 8525 - devl_unlock(devlink); 8526 - return region; 8527 - 8528 - unlock: 8529 - devl_unlock(devlink); 8530 - return ERR_PTR(err); 8531 - } 8532 - EXPORT_SYMBOL_GPL(devlink_port_region_create); 8533 - 8534 - /** 8535 - * devl_region_destroy - destroy address region 8536 - * 8537 - * @region: devlink region to destroy 8538 - */ 8539 - void devl_region_destroy(struct devlink_region *region) 8540 - { 8541 - struct devlink *devlink = region->devlink; 8542 - struct devlink_snapshot *snapshot, *ts; 8543 - 8544 - devl_assert_locked(devlink); 8545 - 8546 - /* Free all snapshots of region */ 8547 - mutex_lock(&region->snapshot_lock); 8548 - list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 8549 - devlink_region_snapshot_del(region, snapshot); 8550 - mutex_unlock(&region->snapshot_lock); 8551 - 8552 - list_del(&region->list); 8553 - mutex_destroy(&region->snapshot_lock); 8554 - 8555 - devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 8556 - kfree(region); 8557 - } 8558 - EXPORT_SYMBOL_GPL(devl_region_destroy); 8559 - 8560 - /** 8561 - * devlink_region_destroy - destroy address region 8562 - * 8563 - * @region: devlink region to destroy 8564 - * 8565 - * Context: Takes and release devlink->lock <mutex>. 8566 - */ 8567 - void devlink_region_destroy(struct devlink_region *region) 8568 - { 8569 - struct devlink *devlink = region->devlink; 8570 - 8571 - devl_lock(devlink); 8572 - devl_region_destroy(region); 8573 - devl_unlock(devlink); 8574 - } 8575 - EXPORT_SYMBOL_GPL(devlink_region_destroy); 8576 - 8577 - /** 8578 - * devlink_region_snapshot_id_get - get snapshot ID 8579 - * 8580 - * This callback should be called when adding a new snapshot, 8581 - * Driver should use the same id for multiple snapshots taken 8582 - * on multiple regions at the same time/by the same trigger. 8583 - * 8584 - * The caller of this function must use devlink_region_snapshot_id_put 8585 - * when finished creating regions using this id. 8586 - * 8587 - * Returns zero on success, or a negative error code on failure. 8588 - * 8589 - * @devlink: devlink 8590 - * @id: storage to return id 8591 - */ 8592 - int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id) 8593 - { 8594 - return __devlink_region_snapshot_id_get(devlink, id); 8595 - } 8596 - EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get); 8597 - 8598 - /** 8599 - * devlink_region_snapshot_id_put - put snapshot ID reference 8600 - * 8601 - * This should be called by a driver after finishing creating snapshots 8602 - * with an id. Doing so ensures that the ID can later be released in the 8603 - * event that all snapshots using it have been destroyed. 8604 - * 8605 - * @devlink: devlink 8606 - * @id: id to release reference on 8607 - */ 8608 - void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id) 8609 - { 8610 - __devlink_snapshot_id_decrement(devlink, id); 8611 - } 8612 - EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put); 8613 - 8614 - /** 8615 - * devlink_region_snapshot_create - create a new snapshot 8616 - * This will add a new snapshot of a region. The snapshot 8617 - * will be stored on the region struct and can be accessed 8618 - * from devlink. This is useful for future analyses of snapshots. 8619 - * Multiple snapshots can be created on a region. 8620 - * The @snapshot_id should be obtained using the getter function. 8621 - * 8622 - * @region: devlink region of the snapshot 8623 - * @data: snapshot data 8624 - * @snapshot_id: snapshot id to be created 8625 - */ 8626 - int devlink_region_snapshot_create(struct devlink_region *region, 8627 - u8 *data, u32 snapshot_id) 8628 - { 8629 - int err; 8630 - 8631 - mutex_lock(&region->snapshot_lock); 8632 - err = __devlink_region_snapshot_create(region, data, snapshot_id); 8633 - mutex_unlock(&region->snapshot_lock); 8634 - return err; 8635 - } 8636 - EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 8637 - 8638 - #define DEVLINK_TRAP(_id, _type) \ 8639 - { \ 8640 - .type = DEVLINK_TRAP_TYPE_##_type, \ 8641 - .id = DEVLINK_TRAP_GENERIC_ID_##_id, \ 8642 - .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \ 8643 - } 8644 - 8645 - static const struct devlink_trap devlink_trap_generic[] = { 8646 - DEVLINK_TRAP(SMAC_MC, DROP), 8647 - DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP), 8648 - DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP), 8649 - DEVLINK_TRAP(INGRESS_STP_FILTER, DROP), 8650 - DEVLINK_TRAP(EMPTY_TX_LIST, DROP), 8651 - DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP), 8652 - DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP), 8653 - DEVLINK_TRAP(TTL_ERROR, EXCEPTION), 8654 - DEVLINK_TRAP(TAIL_DROP, DROP), 8655 - DEVLINK_TRAP(NON_IP_PACKET, DROP), 8656 - DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP), 8657 - DEVLINK_TRAP(DIP_LB, DROP), 8658 - DEVLINK_TRAP(SIP_MC, DROP), 8659 - DEVLINK_TRAP(SIP_LB, DROP), 8660 - DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP), 8661 - DEVLINK_TRAP(IPV4_SIP_BC, DROP), 8662 - DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP), 8663 - DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP), 8664 - DEVLINK_TRAP(MTU_ERROR, EXCEPTION), 8665 - DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION), 8666 - DEVLINK_TRAP(RPF, EXCEPTION), 8667 - DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION), 8668 - DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION), 8669 - DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION), 8670 - DEVLINK_TRAP(NON_ROUTABLE, DROP), 8671 - DEVLINK_TRAP(DECAP_ERROR, EXCEPTION), 8672 - DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP), 8673 - DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP), 8674 - DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP), 8675 - DEVLINK_TRAP(STP, CONTROL), 8676 - DEVLINK_TRAP(LACP, CONTROL), 8677 - DEVLINK_TRAP(LLDP, CONTROL), 8678 - DEVLINK_TRAP(IGMP_QUERY, CONTROL), 8679 - DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL), 8680 - DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL), 8681 - DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL), 8682 - DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL), 8683 - DEVLINK_TRAP(MLD_QUERY, CONTROL), 8684 - DEVLINK_TRAP(MLD_V1_REPORT, CONTROL), 8685 - DEVLINK_TRAP(MLD_V2_REPORT, CONTROL), 8686 - DEVLINK_TRAP(MLD_V1_DONE, CONTROL), 8687 - DEVLINK_TRAP(IPV4_DHCP, CONTROL), 8688 - DEVLINK_TRAP(IPV6_DHCP, CONTROL), 8689 - DEVLINK_TRAP(ARP_REQUEST, CONTROL), 8690 - DEVLINK_TRAP(ARP_RESPONSE, CONTROL), 8691 - DEVLINK_TRAP(ARP_OVERLAY, CONTROL), 8692 - DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL), 8693 - DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL), 8694 - DEVLINK_TRAP(IPV4_BFD, CONTROL), 8695 - DEVLINK_TRAP(IPV6_BFD, CONTROL), 8696 - DEVLINK_TRAP(IPV4_OSPF, CONTROL), 8697 - DEVLINK_TRAP(IPV6_OSPF, CONTROL), 8698 - DEVLINK_TRAP(IPV4_BGP, CONTROL), 8699 - DEVLINK_TRAP(IPV6_BGP, CONTROL), 8700 - DEVLINK_TRAP(IPV4_VRRP, CONTROL), 8701 - DEVLINK_TRAP(IPV6_VRRP, CONTROL), 8702 - DEVLINK_TRAP(IPV4_PIM, CONTROL), 8703 - DEVLINK_TRAP(IPV6_PIM, CONTROL), 8704 - DEVLINK_TRAP(UC_LB, CONTROL), 8705 - DEVLINK_TRAP(LOCAL_ROUTE, CONTROL), 8706 - DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL), 8707 - DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL), 8708 - DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL), 8709 - DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL), 8710 - DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL), 8711 - DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL), 8712 - DEVLINK_TRAP(IPV6_REDIRECT, CONTROL), 8713 - DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL), 8714 - DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL), 8715 - DEVLINK_TRAP(PTP_EVENT, CONTROL), 8716 - DEVLINK_TRAP(PTP_GENERAL, CONTROL), 8717 - DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL), 8718 - DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL), 8719 - DEVLINK_TRAP(EARLY_DROP, DROP), 8720 - DEVLINK_TRAP(VXLAN_PARSING, DROP), 8721 - DEVLINK_TRAP(LLC_SNAP_PARSING, DROP), 8722 - DEVLINK_TRAP(VLAN_PARSING, DROP), 8723 - DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP), 8724 - DEVLINK_TRAP(MPLS_PARSING, DROP), 8725 - DEVLINK_TRAP(ARP_PARSING, DROP), 8726 - DEVLINK_TRAP(IP_1_PARSING, DROP), 8727 - DEVLINK_TRAP(IP_N_PARSING, DROP), 8728 - DEVLINK_TRAP(GRE_PARSING, DROP), 8729 - DEVLINK_TRAP(UDP_PARSING, DROP), 8730 - DEVLINK_TRAP(TCP_PARSING, DROP), 8731 - DEVLINK_TRAP(IPSEC_PARSING, DROP), 8732 - DEVLINK_TRAP(SCTP_PARSING, DROP), 8733 - DEVLINK_TRAP(DCCP_PARSING, DROP), 8734 - DEVLINK_TRAP(GTP_PARSING, DROP), 8735 - DEVLINK_TRAP(ESP_PARSING, DROP), 8736 - DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP), 8737 - DEVLINK_TRAP(DMAC_FILTER, DROP), 8738 - DEVLINK_TRAP(EAPOL, CONTROL), 8739 - DEVLINK_TRAP(LOCKED_PORT, DROP), 8740 - }; 8741 - 8742 - #define DEVLINK_TRAP_GROUP(_id) \ 8743 - { \ 8744 - .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \ 8745 - .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \ 8746 - } 8747 - 8748 - static const struct devlink_trap_group devlink_trap_group_generic[] = { 8749 - DEVLINK_TRAP_GROUP(L2_DROPS), 8750 - DEVLINK_TRAP_GROUP(L3_DROPS), 8751 - DEVLINK_TRAP_GROUP(L3_EXCEPTIONS), 8752 - DEVLINK_TRAP_GROUP(BUFFER_DROPS), 8753 - DEVLINK_TRAP_GROUP(TUNNEL_DROPS), 8754 - DEVLINK_TRAP_GROUP(ACL_DROPS), 8755 - DEVLINK_TRAP_GROUP(STP), 8756 - DEVLINK_TRAP_GROUP(LACP), 8757 - DEVLINK_TRAP_GROUP(LLDP), 8758 - DEVLINK_TRAP_GROUP(MC_SNOOPING), 8759 - DEVLINK_TRAP_GROUP(DHCP), 8760 - DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY), 8761 - DEVLINK_TRAP_GROUP(BFD), 8762 - DEVLINK_TRAP_GROUP(OSPF), 8763 - DEVLINK_TRAP_GROUP(BGP), 8764 - DEVLINK_TRAP_GROUP(VRRP), 8765 - DEVLINK_TRAP_GROUP(PIM), 8766 - DEVLINK_TRAP_GROUP(UC_LB), 8767 - DEVLINK_TRAP_GROUP(LOCAL_DELIVERY), 8768 - DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY), 8769 - DEVLINK_TRAP_GROUP(IPV6), 8770 - DEVLINK_TRAP_GROUP(PTP_EVENT), 8771 - DEVLINK_TRAP_GROUP(PTP_GENERAL), 8772 - DEVLINK_TRAP_GROUP(ACL_SAMPLE), 8773 - DEVLINK_TRAP_GROUP(ACL_TRAP), 8774 - DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS), 8775 - DEVLINK_TRAP_GROUP(EAPOL), 8776 - }; 8777 - 8778 - static int devlink_trap_generic_verify(const struct devlink_trap *trap) 8779 - { 8780 - if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX) 8781 - return -EINVAL; 8782 - 8783 - if (strcmp(trap->name, devlink_trap_generic[trap->id].name)) 8784 - return -EINVAL; 8785 - 8786 - if (trap->type != devlink_trap_generic[trap->id].type) 8787 - return -EINVAL; 8788 - 8789 - return 0; 8790 - } 8791 - 8792 - static int devlink_trap_driver_verify(const struct devlink_trap *trap) 8793 - { 8794 - int i; 8795 - 8796 - if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX) 8797 - return -EINVAL; 8798 - 8799 - for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) { 8800 - if (!strcmp(trap->name, devlink_trap_generic[i].name)) 8801 - return -EEXIST; 8802 - } 8803 - 8804 - return 0; 8805 - } 8806 - 8807 - static int devlink_trap_verify(const struct devlink_trap *trap) 8808 - { 8809 - if (!trap || !trap->name) 8810 - return -EINVAL; 8811 - 8812 - if (trap->generic) 8813 - return devlink_trap_generic_verify(trap); 8814 - else 8815 - return devlink_trap_driver_verify(trap); 8816 - } 8817 - 8818 - static int 8819 - devlink_trap_group_generic_verify(const struct devlink_trap_group *group) 8820 - { 8821 - if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 8822 - return -EINVAL; 8823 - 8824 - if (strcmp(group->name, devlink_trap_group_generic[group->id].name)) 8825 - return -EINVAL; 8826 - 8827 - return 0; 8828 - } 8829 - 8830 - static int 8831 - devlink_trap_group_driver_verify(const struct devlink_trap_group *group) 8832 - { 8833 - int i; 8834 - 8835 - if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 8836 - return -EINVAL; 8837 - 8838 - for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) { 8839 - if (!strcmp(group->name, devlink_trap_group_generic[i].name)) 8840 - return -EEXIST; 8841 - } 8842 - 8843 - return 0; 8844 - } 8845 - 8846 - static int devlink_trap_group_verify(const struct devlink_trap_group *group) 8847 - { 8848 - if (group->generic) 8849 - return devlink_trap_group_generic_verify(group); 8850 - else 8851 - return devlink_trap_group_driver_verify(group); 8852 - } 8853 - 8854 - static void 8855 - devlink_trap_group_notify(struct devlink *devlink, 8856 - const struct devlink_trap_group_item *group_item, 8857 - enum devlink_command cmd) 8858 - { 8859 - struct sk_buff *msg; 8860 - int err; 8861 - 8862 - WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW && 8863 - cmd != DEVLINK_CMD_TRAP_GROUP_DEL); 8864 - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 8865 - return; 8866 - 8867 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 8868 - if (!msg) 8869 - return; 8870 - 8871 - err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0, 8872 - 0); 8873 - if (err) { 8874 - nlmsg_free(msg); 8875 - return; 8876 - } 8877 - 8878 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 8879 - msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 8880 - } 8881 - 8882 - static int 8883 - devlink_trap_item_group_link(struct devlink *devlink, 8884 - struct devlink_trap_item *trap_item) 8885 - { 8886 - u16 group_id = trap_item->trap->init_group_id; 8887 - struct devlink_trap_group_item *group_item; 8888 - 8889 - group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id); 8890 - if (WARN_ON_ONCE(!group_item)) 8891 - return -EINVAL; 8892 - 8893 - trap_item->group_item = group_item; 8894 - 8895 - return 0; 8896 - } 8897 - 8898 - static void devlink_trap_notify(struct devlink *devlink, 8899 - const struct devlink_trap_item *trap_item, 8900 - enum devlink_command cmd) 8901 - { 8902 - struct sk_buff *msg; 8903 - int err; 8904 - 8905 - WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW && 8906 - cmd != DEVLINK_CMD_TRAP_DEL); 8907 - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 8908 - return; 8909 - 8910 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 8911 - if (!msg) 8912 - return; 8913 - 8914 - err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0); 8915 - if (err) { 8916 - nlmsg_free(msg); 8917 - return; 8918 - } 8919 - 8920 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 8921 - msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 8922 - } 8923 - 8924 - static int 8925 - devlink_trap_register(struct devlink *devlink, 8926 - const struct devlink_trap *trap, void *priv) 8927 - { 8928 - struct devlink_trap_item *trap_item; 8929 - int err; 8930 - 8931 - if (devlink_trap_item_lookup(devlink, trap->name)) 8932 - return -EEXIST; 8933 - 8934 - trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL); 8935 - if (!trap_item) 8936 - return -ENOMEM; 8937 - 8938 - trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 8939 - if (!trap_item->stats) { 8940 - err = -ENOMEM; 8941 - goto err_stats_alloc; 8942 - } 8943 - 8944 - trap_item->trap = trap; 8945 - trap_item->action = trap->init_action; 8946 - trap_item->priv = priv; 8947 - 8948 - err = devlink_trap_item_group_link(devlink, trap_item); 8949 - if (err) 8950 - goto err_group_link; 8951 - 8952 - err = devlink->ops->trap_init(devlink, trap, trap_item); 8953 - if (err) 8954 - goto err_trap_init; 8955 - 8956 - list_add_tail(&trap_item->list, &devlink->trap_list); 8957 - devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW); 8958 - 8959 - return 0; 8960 - 8961 - err_trap_init: 8962 - err_group_link: 8963 - free_percpu(trap_item->stats); 8964 - err_stats_alloc: 8965 - kfree(trap_item); 8966 - return err; 8967 - } 8968 - 8969 - static void devlink_trap_unregister(struct devlink *devlink, 8970 - const struct devlink_trap *trap) 8971 - { 8972 - struct devlink_trap_item *trap_item; 8973 - 8974 - trap_item = devlink_trap_item_lookup(devlink, trap->name); 8975 - if (WARN_ON_ONCE(!trap_item)) 8976 - return; 8977 - 8978 - devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL); 8979 - list_del(&trap_item->list); 8980 - if (devlink->ops->trap_fini) 8981 - devlink->ops->trap_fini(devlink, trap, trap_item); 8982 - free_percpu(trap_item->stats); 8983 - kfree(trap_item); 8984 - } 8985 - 8986 - static void devlink_trap_disable(struct devlink *devlink, 8987 - const struct devlink_trap *trap) 8988 - { 8989 - struct devlink_trap_item *trap_item; 8990 - 8991 - trap_item = devlink_trap_item_lookup(devlink, trap->name); 8992 - if (WARN_ON_ONCE(!trap_item)) 8993 - return; 8994 - 8995 - devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP, 8996 - NULL); 8997 - trap_item->action = DEVLINK_TRAP_ACTION_DROP; 8998 - } 8999 - 9000 - /** 9001 - * devl_traps_register - Register packet traps with devlink. 9002 - * @devlink: devlink. 9003 - * @traps: Packet traps. 9004 - * @traps_count: Count of provided packet traps. 9005 - * @priv: Driver private information. 9006 - * 9007 - * Return: Non-zero value on failure. 9008 - */ 9009 - int devl_traps_register(struct devlink *devlink, 9010 - const struct devlink_trap *traps, 9011 - size_t traps_count, void *priv) 9012 - { 9013 - int i, err; 9014 - 9015 - if (!devlink->ops->trap_init || !devlink->ops->trap_action_set) 9016 - return -EINVAL; 9017 - 9018 - devl_assert_locked(devlink); 9019 - for (i = 0; i < traps_count; i++) { 9020 - const struct devlink_trap *trap = &traps[i]; 9021 - 9022 - err = devlink_trap_verify(trap); 9023 - if (err) 9024 - goto err_trap_verify; 9025 - 9026 - err = devlink_trap_register(devlink, trap, priv); 9027 - if (err) 9028 - goto err_trap_register; 9029 - } 9030 - 9031 - return 0; 9032 - 9033 - err_trap_register: 9034 - err_trap_verify: 9035 - for (i--; i >= 0; i--) 9036 - devlink_trap_unregister(devlink, &traps[i]); 9037 - return err; 9038 - } 9039 - EXPORT_SYMBOL_GPL(devl_traps_register); 9040 - 9041 - /** 9042 - * devlink_traps_register - Register packet traps with devlink. 9043 - * @devlink: devlink. 9044 - * @traps: Packet traps. 9045 - * @traps_count: Count of provided packet traps. 9046 - * @priv: Driver private information. 9047 - * 9048 - * Context: Takes and release devlink->lock <mutex>. 9049 - * 9050 - * Return: Non-zero value on failure. 9051 - */ 9052 - int devlink_traps_register(struct devlink *devlink, 9053 - const struct devlink_trap *traps, 9054 - size_t traps_count, void *priv) 9055 - { 9056 - int err; 9057 - 9058 - devl_lock(devlink); 9059 - err = devl_traps_register(devlink, traps, traps_count, priv); 9060 - devl_unlock(devlink); 9061 - return err; 9062 - } 9063 - EXPORT_SYMBOL_GPL(devlink_traps_register); 9064 - 9065 - /** 9066 - * devl_traps_unregister - Unregister packet traps from devlink. 9067 - * @devlink: devlink. 9068 - * @traps: Packet traps. 9069 - * @traps_count: Count of provided packet traps. 9070 - */ 9071 - void devl_traps_unregister(struct devlink *devlink, 9072 - const struct devlink_trap *traps, 9073 - size_t traps_count) 9074 - { 9075 - int i; 9076 - 9077 - devl_assert_locked(devlink); 9078 - /* Make sure we do not have any packets in-flight while unregistering 9079 - * traps by disabling all of them and waiting for a grace period. 9080 - */ 9081 - for (i = traps_count - 1; i >= 0; i--) 9082 - devlink_trap_disable(devlink, &traps[i]); 9083 - synchronize_rcu(); 9084 - for (i = traps_count - 1; i >= 0; i--) 9085 - devlink_trap_unregister(devlink, &traps[i]); 9086 - } 9087 - EXPORT_SYMBOL_GPL(devl_traps_unregister); 9088 - 9089 - /** 9090 - * devlink_traps_unregister - Unregister packet traps from devlink. 9091 - * @devlink: devlink. 9092 - * @traps: Packet traps. 9093 - * @traps_count: Count of provided packet traps. 9094 - * 9095 - * Context: Takes and release devlink->lock <mutex>. 9096 - */ 9097 - void devlink_traps_unregister(struct devlink *devlink, 9098 - const struct devlink_trap *traps, 9099 - size_t traps_count) 9100 - { 9101 - devl_lock(devlink); 9102 - devl_traps_unregister(devlink, traps, traps_count); 9103 - devl_unlock(devlink); 9104 - } 9105 - EXPORT_SYMBOL_GPL(devlink_traps_unregister); 9106 - 9107 - static void 9108 - devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats, 9109 - size_t skb_len) 9110 - { 9111 - struct devlink_stats *stats; 9112 - 9113 - stats = this_cpu_ptr(trap_stats); 9114 - u64_stats_update_begin(&stats->syncp); 9115 - u64_stats_add(&stats->rx_bytes, skb_len); 9116 - u64_stats_inc(&stats->rx_packets); 9117 - u64_stats_update_end(&stats->syncp); 9118 - } 9119 - 9120 - static void 9121 - devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata, 9122 - const struct devlink_trap_item *trap_item, 9123 - struct devlink_port *in_devlink_port, 9124 - const struct flow_action_cookie *fa_cookie) 9125 - { 9126 - metadata->trap_name = trap_item->trap->name; 9127 - metadata->trap_group_name = trap_item->group_item->group->name; 9128 - metadata->fa_cookie = fa_cookie; 9129 - metadata->trap_type = trap_item->trap->type; 9130 - 9131 - spin_lock(&in_devlink_port->type_lock); 9132 - if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH) 9133 - metadata->input_dev = in_devlink_port->type_eth.netdev; 9134 - spin_unlock(&in_devlink_port->type_lock); 9135 - } 9136 - 9137 - /** 9138 - * devlink_trap_report - Report trapped packet to drop monitor. 9139 - * @devlink: devlink. 9140 - * @skb: Trapped packet. 9141 - * @trap_ctx: Trap context. 9142 - * @in_devlink_port: Input devlink port. 9143 - * @fa_cookie: Flow action cookie. Could be NULL. 9144 - */ 9145 - void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb, 9146 - void *trap_ctx, struct devlink_port *in_devlink_port, 9147 - const struct flow_action_cookie *fa_cookie) 9148 - 9149 - { 9150 - struct devlink_trap_item *trap_item = trap_ctx; 9151 - 9152 - devlink_trap_stats_update(trap_item->stats, skb->len); 9153 - devlink_trap_stats_update(trap_item->group_item->stats, skb->len); 9154 - 9155 - if (trace_devlink_trap_report_enabled()) { 9156 - struct devlink_trap_metadata metadata = {}; 9157 - 9158 - devlink_trap_report_metadata_set(&metadata, trap_item, 9159 - in_devlink_port, fa_cookie); 9160 - trace_devlink_trap_report(devlink, skb, &metadata); 9161 - } 9162 - } 9163 - EXPORT_SYMBOL_GPL(devlink_trap_report); 9164 - 9165 - /** 9166 - * devlink_trap_ctx_priv - Trap context to driver private information. 9167 - * @trap_ctx: Trap context. 9168 - * 9169 - * Return: Driver private information passed during registration. 9170 - */ 9171 - void *devlink_trap_ctx_priv(void *trap_ctx) 9172 - { 9173 - struct devlink_trap_item *trap_item = trap_ctx; 9174 - 9175 - return trap_item->priv; 9176 - } 9177 - EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv); 9178 - 9179 - static int 9180 - devlink_trap_group_item_policer_link(struct devlink *devlink, 9181 - struct devlink_trap_group_item *group_item) 9182 - { 9183 - u32 policer_id = group_item->group->init_policer_id; 9184 - struct devlink_trap_policer_item *policer_item; 9185 - 9186 - if (policer_id == 0) 9187 - return 0; 9188 - 9189 - policer_item = devlink_trap_policer_item_lookup(devlink, policer_id); 9190 - if (WARN_ON_ONCE(!policer_item)) 9191 - return -EINVAL; 9192 - 9193 - group_item->policer_item = policer_item; 9194 - 9195 - return 0; 9196 - } 9197 - 9198 - static int 9199 - devlink_trap_group_register(struct devlink *devlink, 9200 - const struct devlink_trap_group *group) 9201 - { 9202 - struct devlink_trap_group_item *group_item; 9203 - int err; 9204 - 9205 - if (devlink_trap_group_item_lookup(devlink, group->name)) 9206 - return -EEXIST; 9207 - 9208 - group_item = kzalloc(sizeof(*group_item), GFP_KERNEL); 9209 - if (!group_item) 9210 - return -ENOMEM; 9211 - 9212 - group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 9213 - if (!group_item->stats) { 9214 - err = -ENOMEM; 9215 - goto err_stats_alloc; 9216 - } 9217 - 9218 - group_item->group = group; 9219 - 9220 - err = devlink_trap_group_item_policer_link(devlink, group_item); 9221 - if (err) 9222 - goto err_policer_link; 9223 - 9224 - if (devlink->ops->trap_group_init) { 9225 - err = devlink->ops->trap_group_init(devlink, group); 9226 - if (err) 9227 - goto err_group_init; 9228 - } 9229 - 9230 - list_add_tail(&group_item->list, &devlink->trap_group_list); 9231 - devlink_trap_group_notify(devlink, group_item, 9232 - DEVLINK_CMD_TRAP_GROUP_NEW); 9233 - 9234 - return 0; 9235 - 9236 - err_group_init: 9237 - err_policer_link: 9238 - free_percpu(group_item->stats); 9239 - err_stats_alloc: 9240 - kfree(group_item); 9241 - return err; 9242 - } 9243 - 9244 - static void 9245 - devlink_trap_group_unregister(struct devlink *devlink, 9246 - const struct devlink_trap_group *group) 9247 - { 9248 - struct devlink_trap_group_item *group_item; 9249 - 9250 - group_item = devlink_trap_group_item_lookup(devlink, group->name); 9251 - if (WARN_ON_ONCE(!group_item)) 9252 - return; 9253 - 9254 - devlink_trap_group_notify(devlink, group_item, 9255 - DEVLINK_CMD_TRAP_GROUP_DEL); 9256 - list_del(&group_item->list); 9257 - free_percpu(group_item->stats); 9258 - kfree(group_item); 9259 - } 9260 - 9261 - /** 9262 - * devl_trap_groups_register - Register packet trap groups with devlink. 9263 - * @devlink: devlink. 9264 - * @groups: Packet trap groups. 9265 - * @groups_count: Count of provided packet trap groups. 9266 - * 9267 - * Return: Non-zero value on failure. 9268 - */ 9269 - int devl_trap_groups_register(struct devlink *devlink, 9270 - const struct devlink_trap_group *groups, 9271 - size_t groups_count) 9272 - { 9273 - int i, err; 9274 - 9275 - devl_assert_locked(devlink); 9276 - for (i = 0; i < groups_count; i++) { 9277 - const struct devlink_trap_group *group = &groups[i]; 9278 - 9279 - err = devlink_trap_group_verify(group); 9280 - if (err) 9281 - goto err_trap_group_verify; 9282 - 9283 - err = devlink_trap_group_register(devlink, group); 9284 - if (err) 9285 - goto err_trap_group_register; 9286 - } 9287 - 9288 - return 0; 9289 - 9290 - err_trap_group_register: 9291 - err_trap_group_verify: 9292 - for (i--; i >= 0; i--) 9293 - devlink_trap_group_unregister(devlink, &groups[i]); 9294 - return err; 9295 - } 9296 - EXPORT_SYMBOL_GPL(devl_trap_groups_register); 9297 - 9298 - /** 9299 - * devlink_trap_groups_register - Register packet trap groups with devlink. 9300 - * @devlink: devlink. 9301 - * @groups: Packet trap groups. 9302 - * @groups_count: Count of provided packet trap groups. 9303 - * 9304 - * Context: Takes and release devlink->lock <mutex>. 9305 - * 9306 - * Return: Non-zero value on failure. 9307 - */ 9308 - int devlink_trap_groups_register(struct devlink *devlink, 9309 - const struct devlink_trap_group *groups, 9310 - size_t groups_count) 9311 - { 9312 - int err; 9313 - 9314 - devl_lock(devlink); 9315 - err = devl_trap_groups_register(devlink, groups, groups_count); 9316 - devl_unlock(devlink); 9317 - return err; 9318 - } 9319 - EXPORT_SYMBOL_GPL(devlink_trap_groups_register); 9320 - 9321 - /** 9322 - * devl_trap_groups_unregister - Unregister packet trap groups from devlink. 9323 - * @devlink: devlink. 9324 - * @groups: Packet trap groups. 9325 - * @groups_count: Count of provided packet trap groups. 9326 - */ 9327 - void devl_trap_groups_unregister(struct devlink *devlink, 9328 - const struct devlink_trap_group *groups, 9329 - size_t groups_count) 9330 - { 9331 - int i; 9332 - 9333 - devl_assert_locked(devlink); 9334 - for (i = groups_count - 1; i >= 0; i--) 9335 - devlink_trap_group_unregister(devlink, &groups[i]); 9336 - } 9337 - EXPORT_SYMBOL_GPL(devl_trap_groups_unregister); 9338 - 9339 - /** 9340 - * devlink_trap_groups_unregister - Unregister packet trap groups from devlink. 9341 - * @devlink: devlink. 9342 - * @groups: Packet trap groups. 9343 - * @groups_count: Count of provided packet trap groups. 9344 - * 9345 - * Context: Takes and release devlink->lock <mutex>. 9346 - */ 9347 - void devlink_trap_groups_unregister(struct devlink *devlink, 9348 - const struct devlink_trap_group *groups, 9349 - size_t groups_count) 9350 - { 9351 - devl_lock(devlink); 9352 - devl_trap_groups_unregister(devlink, groups, groups_count); 9353 - devl_unlock(devlink); 9354 - } 9355 - EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister); 9356 - 9357 - static void 9358 - devlink_trap_policer_notify(struct devlink *devlink, 9359 - const struct devlink_trap_policer_item *policer_item, 9360 - enum devlink_command cmd) 9361 - { 9362 - struct sk_buff *msg; 9363 - int err; 9364 - 9365 - WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW && 9366 - cmd != DEVLINK_CMD_TRAP_POLICER_DEL); 9367 - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 9368 - return; 9369 - 9370 - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 9371 - if (!msg) 9372 - return; 9373 - 9374 - err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0, 9375 - 0, 0); 9376 - if (err) { 9377 - nlmsg_free(msg); 9378 - return; 9379 - } 9380 - 9381 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 9382 - msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 9383 - } 9384 - 9385 - static int 9386 - devlink_trap_policer_register(struct devlink *devlink, 9387 - const struct devlink_trap_policer *policer) 9388 - { 9389 - struct devlink_trap_policer_item *policer_item; 9390 - int err; 9391 - 9392 - if (devlink_trap_policer_item_lookup(devlink, policer->id)) 9393 - return -EEXIST; 9394 - 9395 - policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL); 9396 - if (!policer_item) 9397 - return -ENOMEM; 9398 - 9399 - policer_item->policer = policer; 9400 - policer_item->rate = policer->init_rate; 9401 - policer_item->burst = policer->init_burst; 9402 - 9403 - if (devlink->ops->trap_policer_init) { 9404 - err = devlink->ops->trap_policer_init(devlink, policer); 9405 - if (err) 9406 - goto err_policer_init; 9407 - } 9408 - 9409 - list_add_tail(&policer_item->list, &devlink->trap_policer_list); 9410 - devlink_trap_policer_notify(devlink, policer_item, 9411 - DEVLINK_CMD_TRAP_POLICER_NEW); 9412 - 9413 - return 0; 9414 - 9415 - err_policer_init: 9416 - kfree(policer_item); 9417 - return err; 9418 - } 9419 - 9420 - static void 9421 - devlink_trap_policer_unregister(struct devlink *devlink, 9422 - const struct devlink_trap_policer *policer) 9423 - { 9424 - struct devlink_trap_policer_item *policer_item; 9425 - 9426 - policer_item = devlink_trap_policer_item_lookup(devlink, policer->id); 9427 - if (WARN_ON_ONCE(!policer_item)) 9428 - return; 9429 - 9430 - devlink_trap_policer_notify(devlink, policer_item, 9431 - DEVLINK_CMD_TRAP_POLICER_DEL); 9432 - list_del(&policer_item->list); 9433 - if (devlink->ops->trap_policer_fini) 9434 - devlink->ops->trap_policer_fini(devlink, policer); 9435 - kfree(policer_item); 9436 - } 9437 - 9438 - /** 9439 - * devl_trap_policers_register - Register packet trap policers with devlink. 9440 - * @devlink: devlink. 9441 - * @policers: Packet trap policers. 9442 - * @policers_count: Count of provided packet trap policers. 9443 - * 9444 - * Return: Non-zero value on failure. 9445 - */ 9446 - int 9447 - devl_trap_policers_register(struct devlink *devlink, 9448 - const struct devlink_trap_policer *policers, 9449 - size_t policers_count) 9450 - { 9451 - int i, err; 9452 - 9453 - devl_assert_locked(devlink); 9454 - for (i = 0; i < policers_count; i++) { 9455 - const struct devlink_trap_policer *policer = &policers[i]; 9456 - 9457 - if (WARN_ON(policer->id == 0 || 9458 - policer->max_rate < policer->min_rate || 9459 - policer->max_burst < policer->min_burst)) { 9460 - err = -EINVAL; 9461 - goto err_trap_policer_verify; 9462 - } 9463 - 9464 - err = devlink_trap_policer_register(devlink, policer); 9465 - if (err) 9466 - goto err_trap_policer_register; 9467 - } 9468 - return 0; 9469 - 9470 - err_trap_policer_register: 9471 - err_trap_policer_verify: 9472 - for (i--; i >= 0; i--) 9473 - devlink_trap_policer_unregister(devlink, &policers[i]); 9474 - return err; 9475 - } 9476 - EXPORT_SYMBOL_GPL(devl_trap_policers_register); 9477 - 9478 - /** 9479 - * devl_trap_policers_unregister - Unregister packet trap policers from devlink. 9480 - * @devlink: devlink. 9481 - * @policers: Packet trap policers. 9482 - * @policers_count: Count of provided packet trap policers. 9483 - */ 9484 - void 9485 - devl_trap_policers_unregister(struct devlink *devlink, 9486 - const struct devlink_trap_policer *policers, 9487 - size_t policers_count) 9488 - { 9489 - int i; 9490 - 9491 - devl_assert_locked(devlink); 9492 - for (i = policers_count - 1; i >= 0; i--) 9493 - devlink_trap_policer_unregister(devlink, &policers[i]); 9494 - } 9495 - EXPORT_SYMBOL_GPL(devl_trap_policers_unregister); 9496 - 9497 - int devlink_compat_phys_port_name_get(struct net_device *dev, 9498 - char *name, size_t len) 9499 - { 9500 - struct devlink_port *devlink_port; 9501 - 9502 - /* RTNL mutex is held here which ensures that devlink_port 9503 - * instance cannot disappear in the middle. No need to take 9504 - * any devlink lock as only permanent values are accessed. 9505 - */ 9506 - ASSERT_RTNL(); 9507 - 9508 - devlink_port = dev->devlink_port; 9509 - if (!devlink_port) 9510 - return -EOPNOTSUPP; 9511 - 9512 - return __devlink_port_phys_port_name_get(devlink_port, name, len); 9513 - } 9514 - 9515 - int devlink_compat_switch_id_get(struct net_device *dev, 9516 - struct netdev_phys_item_id *ppid) 9517 - { 9518 - struct devlink_port *devlink_port; 9519 - 9520 - /* Caller must hold RTNL mutex or reference to dev, which ensures that 9521 - * devlink_port instance cannot disappear in the middle. No need to take 9522 - * any devlink lock as only permanent values are accessed. 9523 - */ 9524 - devlink_port = dev->devlink_port; 9525 - if (!devlink_port || !devlink_port->switch_port) 9526 - return -EOPNOTSUPP; 9527 - 9528 - memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid)); 9529 - 9530 - return 0; 9531 - }
+606
net/devlink/linecard.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + static struct devlink_linecard * 10 + devlink_linecard_get_by_index(struct devlink *devlink, 11 + unsigned int linecard_index) 12 + { 13 + struct devlink_linecard *devlink_linecard; 14 + 15 + list_for_each_entry(devlink_linecard, &devlink->linecard_list, list) { 16 + if (devlink_linecard->index == linecard_index) 17 + return devlink_linecard; 18 + } 19 + return NULL; 20 + } 21 + 22 + static bool devlink_linecard_index_exists(struct devlink *devlink, 23 + unsigned int linecard_index) 24 + { 25 + return devlink_linecard_get_by_index(devlink, linecard_index); 26 + } 27 + 28 + static struct devlink_linecard * 29 + devlink_linecard_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) 30 + { 31 + if (attrs[DEVLINK_ATTR_LINECARD_INDEX]) { 32 + u32 linecard_index = nla_get_u32(attrs[DEVLINK_ATTR_LINECARD_INDEX]); 33 + struct devlink_linecard *linecard; 34 + 35 + linecard = devlink_linecard_get_by_index(devlink, linecard_index); 36 + if (!linecard) 37 + return ERR_PTR(-ENODEV); 38 + return linecard; 39 + } 40 + return ERR_PTR(-EINVAL); 41 + } 42 + 43 + static struct devlink_linecard * 44 + devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info) 45 + { 46 + return devlink_linecard_get_from_attrs(devlink, info->attrs); 47 + } 48 + 49 + static int devlink_nl_put_nested_handle(struct sk_buff *msg, struct devlink *devlink) 50 + { 51 + struct nlattr *nested_attr; 52 + 53 + nested_attr = nla_nest_start(msg, DEVLINK_ATTR_NESTED_DEVLINK); 54 + if (!nested_attr) 55 + return -EMSGSIZE; 56 + if (devlink_nl_put_handle(msg, devlink)) 57 + goto nla_put_failure; 58 + 59 + nla_nest_end(msg, nested_attr); 60 + return 0; 61 + 62 + nla_put_failure: 63 + nla_nest_cancel(msg, nested_attr); 64 + return -EMSGSIZE; 65 + } 66 + 67 + struct devlink_linecard_type { 68 + const char *type; 69 + const void *priv; 70 + }; 71 + 72 + static int devlink_nl_linecard_fill(struct sk_buff *msg, 73 + struct devlink *devlink, 74 + struct devlink_linecard *linecard, 75 + enum devlink_command cmd, u32 portid, 76 + u32 seq, int flags, 77 + struct netlink_ext_ack *extack) 78 + { 79 + struct devlink_linecard_type *linecard_type; 80 + struct nlattr *attr; 81 + void *hdr; 82 + int i; 83 + 84 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 85 + if (!hdr) 86 + return -EMSGSIZE; 87 + 88 + if (devlink_nl_put_handle(msg, devlink)) 89 + goto nla_put_failure; 90 + if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index)) 91 + goto nla_put_failure; 92 + if (nla_put_u8(msg, DEVLINK_ATTR_LINECARD_STATE, linecard->state)) 93 + goto nla_put_failure; 94 + if (linecard->type && 95 + nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, linecard->type)) 96 + goto nla_put_failure; 97 + 98 + if (linecard->types_count) { 99 + attr = nla_nest_start(msg, 100 + DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES); 101 + if (!attr) 102 + goto nla_put_failure; 103 + for (i = 0; i < linecard->types_count; i++) { 104 + linecard_type = &linecard->types[i]; 105 + if (nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, 106 + linecard_type->type)) { 107 + nla_nest_cancel(msg, attr); 108 + goto nla_put_failure; 109 + } 110 + } 111 + nla_nest_end(msg, attr); 112 + } 113 + 114 + if (linecard->nested_devlink && 115 + devlink_nl_put_nested_handle(msg, linecard->nested_devlink)) 116 + goto nla_put_failure; 117 + 118 + genlmsg_end(msg, hdr); 119 + return 0; 120 + 121 + nla_put_failure: 122 + genlmsg_cancel(msg, hdr); 123 + return -EMSGSIZE; 124 + } 125 + 126 + static void devlink_linecard_notify(struct devlink_linecard *linecard, 127 + enum devlink_command cmd) 128 + { 129 + struct devlink *devlink = linecard->devlink; 130 + struct sk_buff *msg; 131 + int err; 132 + 133 + WARN_ON(cmd != DEVLINK_CMD_LINECARD_NEW && 134 + cmd != DEVLINK_CMD_LINECARD_DEL); 135 + 136 + if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 137 + return; 138 + 139 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 140 + if (!msg) 141 + return; 142 + 143 + err = devlink_nl_linecard_fill(msg, devlink, linecard, cmd, 0, 0, 0, 144 + NULL); 145 + if (err) { 146 + nlmsg_free(msg); 147 + return; 148 + } 149 + 150 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 151 + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 152 + } 153 + 154 + void devlink_linecards_notify_register(struct devlink *devlink) 155 + { 156 + struct devlink_linecard *linecard; 157 + 158 + list_for_each_entry(linecard, &devlink->linecard_list, list) 159 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 160 + } 161 + 162 + void devlink_linecards_notify_unregister(struct devlink *devlink) 163 + { 164 + struct devlink_linecard *linecard; 165 + 166 + list_for_each_entry_reverse(linecard, &devlink->linecard_list, list) 167 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); 168 + } 169 + 170 + int devlink_nl_linecard_get_doit(struct sk_buff *skb, struct genl_info *info) 171 + { 172 + struct devlink *devlink = info->user_ptr[0]; 173 + struct devlink_linecard *linecard; 174 + struct sk_buff *msg; 175 + int err; 176 + 177 + linecard = devlink_linecard_get_from_info(devlink, info); 178 + if (IS_ERR(linecard)) 179 + return PTR_ERR(linecard); 180 + 181 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 182 + if (!msg) 183 + return -ENOMEM; 184 + 185 + mutex_lock(&linecard->state_lock); 186 + err = devlink_nl_linecard_fill(msg, devlink, linecard, 187 + DEVLINK_CMD_LINECARD_NEW, 188 + info->snd_portid, info->snd_seq, 0, 189 + info->extack); 190 + mutex_unlock(&linecard->state_lock); 191 + if (err) { 192 + nlmsg_free(msg); 193 + return err; 194 + } 195 + 196 + return genlmsg_reply(msg, info); 197 + } 198 + 199 + static int devlink_nl_linecard_get_dump_one(struct sk_buff *msg, 200 + struct devlink *devlink, 201 + struct netlink_callback *cb, 202 + int flags) 203 + { 204 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 205 + struct devlink_linecard *linecard; 206 + int idx = 0; 207 + int err = 0; 208 + 209 + list_for_each_entry(linecard, &devlink->linecard_list, list) { 210 + if (idx < state->idx) { 211 + idx++; 212 + continue; 213 + } 214 + mutex_lock(&linecard->state_lock); 215 + err = devlink_nl_linecard_fill(msg, devlink, linecard, 216 + DEVLINK_CMD_LINECARD_NEW, 217 + NETLINK_CB(cb->skb).portid, 218 + cb->nlh->nlmsg_seq, flags, 219 + cb->extack); 220 + mutex_unlock(&linecard->state_lock); 221 + if (err) { 222 + state->idx = idx; 223 + break; 224 + } 225 + idx++; 226 + } 227 + 228 + return err; 229 + } 230 + 231 + int devlink_nl_linecard_get_dumpit(struct sk_buff *skb, 232 + struct netlink_callback *cb) 233 + { 234 + return devlink_nl_dumpit(skb, cb, devlink_nl_linecard_get_dump_one); 235 + } 236 + 237 + static struct devlink_linecard_type * 238 + devlink_linecard_type_lookup(struct devlink_linecard *linecard, 239 + const char *type) 240 + { 241 + struct devlink_linecard_type *linecard_type; 242 + int i; 243 + 244 + for (i = 0; i < linecard->types_count; i++) { 245 + linecard_type = &linecard->types[i]; 246 + if (!strcmp(type, linecard_type->type)) 247 + return linecard_type; 248 + } 249 + return NULL; 250 + } 251 + 252 + static int devlink_linecard_type_set(struct devlink_linecard *linecard, 253 + const char *type, 254 + struct netlink_ext_ack *extack) 255 + { 256 + const struct devlink_linecard_ops *ops = linecard->ops; 257 + struct devlink_linecard_type *linecard_type; 258 + int err; 259 + 260 + mutex_lock(&linecard->state_lock); 261 + if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) { 262 + NL_SET_ERR_MSG(extack, "Line card is currently being provisioned"); 263 + err = -EBUSY; 264 + goto out; 265 + } 266 + if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) { 267 + NL_SET_ERR_MSG(extack, "Line card is currently being unprovisioned"); 268 + err = -EBUSY; 269 + goto out; 270 + } 271 + 272 + linecard_type = devlink_linecard_type_lookup(linecard, type); 273 + if (!linecard_type) { 274 + NL_SET_ERR_MSG(extack, "Unsupported line card type provided"); 275 + err = -EINVAL; 276 + goto out; 277 + } 278 + 279 + if (linecard->state != DEVLINK_LINECARD_STATE_UNPROVISIONED && 280 + linecard->state != DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) { 281 + NL_SET_ERR_MSG(extack, "Line card already provisioned"); 282 + err = -EBUSY; 283 + /* Check if the line card is provisioned in the same 284 + * way the user asks. In case it is, make the operation 285 + * to return success. 286 + */ 287 + if (ops->same_provision && 288 + ops->same_provision(linecard, linecard->priv, 289 + linecard_type->type, 290 + linecard_type->priv)) 291 + err = 0; 292 + goto out; 293 + } 294 + 295 + linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING; 296 + linecard->type = linecard_type->type; 297 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 298 + mutex_unlock(&linecard->state_lock); 299 + err = ops->provision(linecard, linecard->priv, linecard_type->type, 300 + linecard_type->priv, extack); 301 + if (err) { 302 + /* Provisioning failed. Assume the linecard is unprovisioned 303 + * for future operations. 304 + */ 305 + mutex_lock(&linecard->state_lock); 306 + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 307 + linecard->type = NULL; 308 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 309 + mutex_unlock(&linecard->state_lock); 310 + } 311 + return err; 312 + 313 + out: 314 + mutex_unlock(&linecard->state_lock); 315 + return err; 316 + } 317 + 318 + static int devlink_linecard_type_unset(struct devlink_linecard *linecard, 319 + struct netlink_ext_ack *extack) 320 + { 321 + int err; 322 + 323 + mutex_lock(&linecard->state_lock); 324 + if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) { 325 + NL_SET_ERR_MSG(extack, "Line card is currently being provisioned"); 326 + err = -EBUSY; 327 + goto out; 328 + } 329 + if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) { 330 + NL_SET_ERR_MSG(extack, "Line card is currently being unprovisioned"); 331 + err = -EBUSY; 332 + goto out; 333 + } 334 + if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) { 335 + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 336 + linecard->type = NULL; 337 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 338 + err = 0; 339 + goto out; 340 + } 341 + 342 + if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONED) { 343 + NL_SET_ERR_MSG(extack, "Line card is not provisioned"); 344 + err = 0; 345 + goto out; 346 + } 347 + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONING; 348 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 349 + mutex_unlock(&linecard->state_lock); 350 + err = linecard->ops->unprovision(linecard, linecard->priv, 351 + extack); 352 + if (err) { 353 + /* Unprovisioning failed. Assume the linecard is unprovisioned 354 + * for future operations. 355 + */ 356 + mutex_lock(&linecard->state_lock); 357 + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 358 + linecard->type = NULL; 359 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 360 + mutex_unlock(&linecard->state_lock); 361 + } 362 + return err; 363 + 364 + out: 365 + mutex_unlock(&linecard->state_lock); 366 + return err; 367 + } 368 + 369 + int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb, 370 + struct genl_info *info) 371 + { 372 + struct netlink_ext_ack *extack = info->extack; 373 + struct devlink *devlink = info->user_ptr[0]; 374 + struct devlink_linecard *linecard; 375 + int err; 376 + 377 + linecard = devlink_linecard_get_from_info(devlink, info); 378 + if (IS_ERR(linecard)) 379 + return PTR_ERR(linecard); 380 + 381 + if (info->attrs[DEVLINK_ATTR_LINECARD_TYPE]) { 382 + const char *type; 383 + 384 + type = nla_data(info->attrs[DEVLINK_ATTR_LINECARD_TYPE]); 385 + if (strcmp(type, "")) { 386 + err = devlink_linecard_type_set(linecard, type, extack); 387 + if (err) 388 + return err; 389 + } else { 390 + err = devlink_linecard_type_unset(linecard, extack); 391 + if (err) 392 + return err; 393 + } 394 + } 395 + 396 + return 0; 397 + } 398 + 399 + static int devlink_linecard_types_init(struct devlink_linecard *linecard) 400 + { 401 + struct devlink_linecard_type *linecard_type; 402 + unsigned int count; 403 + int i; 404 + 405 + count = linecard->ops->types_count(linecard, linecard->priv); 406 + linecard->types = kmalloc_array(count, sizeof(*linecard_type), 407 + GFP_KERNEL); 408 + if (!linecard->types) 409 + return -ENOMEM; 410 + linecard->types_count = count; 411 + 412 + for (i = 0; i < count; i++) { 413 + linecard_type = &linecard->types[i]; 414 + linecard->ops->types_get(linecard, linecard->priv, i, 415 + &linecard_type->type, 416 + &linecard_type->priv); 417 + } 418 + return 0; 419 + } 420 + 421 + static void devlink_linecard_types_fini(struct devlink_linecard *linecard) 422 + { 423 + kfree(linecard->types); 424 + } 425 + 426 + /** 427 + * devl_linecard_create - Create devlink linecard 428 + * 429 + * @devlink: devlink 430 + * @linecard_index: driver-specific numerical identifier of the linecard 431 + * @ops: linecards ops 432 + * @priv: user priv pointer 433 + * 434 + * Create devlink linecard instance with provided linecard index. 435 + * Caller can use any indexing, even hw-related one. 436 + * 437 + * Return: Line card structure or an ERR_PTR() encoded error code. 438 + */ 439 + struct devlink_linecard * 440 + devl_linecard_create(struct devlink *devlink, unsigned int linecard_index, 441 + const struct devlink_linecard_ops *ops, void *priv) 442 + { 443 + struct devlink_linecard *linecard; 444 + int err; 445 + 446 + if (WARN_ON(!ops || !ops->provision || !ops->unprovision || 447 + !ops->types_count || !ops->types_get)) 448 + return ERR_PTR(-EINVAL); 449 + 450 + if (devlink_linecard_index_exists(devlink, linecard_index)) 451 + return ERR_PTR(-EEXIST); 452 + 453 + linecard = kzalloc(sizeof(*linecard), GFP_KERNEL); 454 + if (!linecard) 455 + return ERR_PTR(-ENOMEM); 456 + 457 + linecard->devlink = devlink; 458 + linecard->index = linecard_index; 459 + linecard->ops = ops; 460 + linecard->priv = priv; 461 + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 462 + mutex_init(&linecard->state_lock); 463 + 464 + err = devlink_linecard_types_init(linecard); 465 + if (err) { 466 + mutex_destroy(&linecard->state_lock); 467 + kfree(linecard); 468 + return ERR_PTR(err); 469 + } 470 + 471 + list_add_tail(&linecard->list, &devlink->linecard_list); 472 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 473 + return linecard; 474 + } 475 + EXPORT_SYMBOL_GPL(devl_linecard_create); 476 + 477 + /** 478 + * devl_linecard_destroy - Destroy devlink linecard 479 + * 480 + * @linecard: devlink linecard 481 + */ 482 + void devl_linecard_destroy(struct devlink_linecard *linecard) 483 + { 484 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); 485 + list_del(&linecard->list); 486 + devlink_linecard_types_fini(linecard); 487 + mutex_destroy(&linecard->state_lock); 488 + kfree(linecard); 489 + } 490 + EXPORT_SYMBOL_GPL(devl_linecard_destroy); 491 + 492 + /** 493 + * devlink_linecard_provision_set - Set provisioning on linecard 494 + * 495 + * @linecard: devlink linecard 496 + * @type: linecard type 497 + * 498 + * This is either called directly from the provision() op call or 499 + * as a result of the provision() op call asynchronously. 500 + */ 501 + void devlink_linecard_provision_set(struct devlink_linecard *linecard, 502 + const char *type) 503 + { 504 + mutex_lock(&linecard->state_lock); 505 + WARN_ON(linecard->type && strcmp(linecard->type, type)); 506 + linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED; 507 + linecard->type = type; 508 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 509 + mutex_unlock(&linecard->state_lock); 510 + } 511 + EXPORT_SYMBOL_GPL(devlink_linecard_provision_set); 512 + 513 + /** 514 + * devlink_linecard_provision_clear - Clear provisioning on linecard 515 + * 516 + * @linecard: devlink linecard 517 + * 518 + * This is either called directly from the unprovision() op call or 519 + * as a result of the unprovision() op call asynchronously. 520 + */ 521 + void devlink_linecard_provision_clear(struct devlink_linecard *linecard) 522 + { 523 + mutex_lock(&linecard->state_lock); 524 + WARN_ON(linecard->nested_devlink); 525 + linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 526 + linecard->type = NULL; 527 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 528 + mutex_unlock(&linecard->state_lock); 529 + } 530 + EXPORT_SYMBOL_GPL(devlink_linecard_provision_clear); 531 + 532 + /** 533 + * devlink_linecard_provision_fail - Fail provisioning on linecard 534 + * 535 + * @linecard: devlink linecard 536 + * 537 + * This is either called directly from the provision() op call or 538 + * as a result of the provision() op call asynchronously. 539 + */ 540 + void devlink_linecard_provision_fail(struct devlink_linecard *linecard) 541 + { 542 + mutex_lock(&linecard->state_lock); 543 + WARN_ON(linecard->nested_devlink); 544 + linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED; 545 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 546 + mutex_unlock(&linecard->state_lock); 547 + } 548 + EXPORT_SYMBOL_GPL(devlink_linecard_provision_fail); 549 + 550 + /** 551 + * devlink_linecard_activate - Set linecard active 552 + * 553 + * @linecard: devlink linecard 554 + */ 555 + void devlink_linecard_activate(struct devlink_linecard *linecard) 556 + { 557 + mutex_lock(&linecard->state_lock); 558 + WARN_ON(linecard->state != DEVLINK_LINECARD_STATE_PROVISIONED); 559 + linecard->state = DEVLINK_LINECARD_STATE_ACTIVE; 560 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 561 + mutex_unlock(&linecard->state_lock); 562 + } 563 + EXPORT_SYMBOL_GPL(devlink_linecard_activate); 564 + 565 + /** 566 + * devlink_linecard_deactivate - Set linecard inactive 567 + * 568 + * @linecard: devlink linecard 569 + */ 570 + void devlink_linecard_deactivate(struct devlink_linecard *linecard) 571 + { 572 + mutex_lock(&linecard->state_lock); 573 + switch (linecard->state) { 574 + case DEVLINK_LINECARD_STATE_ACTIVE: 575 + linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED; 576 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 577 + break; 578 + case DEVLINK_LINECARD_STATE_UNPROVISIONING: 579 + /* Line card is being deactivated as part 580 + * of unprovisioning flow. 581 + */ 582 + break; 583 + default: 584 + WARN_ON(1); 585 + break; 586 + } 587 + mutex_unlock(&linecard->state_lock); 588 + } 589 + EXPORT_SYMBOL_GPL(devlink_linecard_deactivate); 590 + 591 + /** 592 + * devlink_linecard_nested_dl_set - Attach/detach nested devlink 593 + * instance to linecard. 594 + * 595 + * @linecard: devlink linecard 596 + * @nested_devlink: devlink instance to attach or NULL to detach 597 + */ 598 + void devlink_linecard_nested_dl_set(struct devlink_linecard *linecard, 599 + struct devlink *nested_devlink) 600 + { 601 + mutex_lock(&linecard->state_lock); 602 + linecard->nested_devlink = nested_devlink; 603 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 604 + mutex_unlock(&linecard->state_lock); 605 + } 606 + EXPORT_SYMBOL_GPL(devlink_linecard_nested_dl_set);
+266
net/devlink/netlink.c
··· 82 82 [DEVLINK_ATTR_REGION_DIRECT] = { .type = NLA_FLAG }, 83 83 }; 84 84 85 + int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info) 86 + { 87 + int err; 88 + 89 + if (*msg) { 90 + err = genlmsg_reply(*msg, info); 91 + if (err) 92 + return err; 93 + } 94 + *msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 95 + if (!*msg) 96 + return -ENOMEM; 97 + return 0; 98 + } 99 + 85 100 struct devlink * 86 101 devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs) 87 102 { ··· 254 239 else 255 240 return devlink_nl_inst_iter_dumpit(msg, cb, flags, dump_one); 256 241 } 242 + 243 + static const struct genl_small_ops devlink_nl_small_ops[40] = { 244 + { 245 + .cmd = DEVLINK_CMD_PORT_SET, 246 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 247 + .doit = devlink_nl_cmd_port_set_doit, 248 + .flags = GENL_ADMIN_PERM, 249 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 250 + }, 251 + { 252 + .cmd = DEVLINK_CMD_RATE_SET, 253 + .doit = devlink_nl_cmd_rate_set_doit, 254 + .flags = GENL_ADMIN_PERM, 255 + }, 256 + { 257 + .cmd = DEVLINK_CMD_RATE_NEW, 258 + .doit = devlink_nl_cmd_rate_new_doit, 259 + .flags = GENL_ADMIN_PERM, 260 + }, 261 + { 262 + .cmd = DEVLINK_CMD_RATE_DEL, 263 + .doit = devlink_nl_cmd_rate_del_doit, 264 + .flags = GENL_ADMIN_PERM, 265 + }, 266 + { 267 + .cmd = DEVLINK_CMD_PORT_SPLIT, 268 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 269 + .doit = devlink_nl_cmd_port_split_doit, 270 + .flags = GENL_ADMIN_PERM, 271 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 272 + }, 273 + { 274 + .cmd = DEVLINK_CMD_PORT_UNSPLIT, 275 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 276 + .doit = devlink_nl_cmd_port_unsplit_doit, 277 + .flags = GENL_ADMIN_PERM, 278 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 279 + }, 280 + { 281 + .cmd = DEVLINK_CMD_PORT_NEW, 282 + .doit = devlink_nl_cmd_port_new_doit, 283 + .flags = GENL_ADMIN_PERM, 284 + }, 285 + { 286 + .cmd = DEVLINK_CMD_PORT_DEL, 287 + .doit = devlink_nl_cmd_port_del_doit, 288 + .flags = GENL_ADMIN_PERM, 289 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 290 + }, 291 + 292 + { 293 + .cmd = DEVLINK_CMD_LINECARD_SET, 294 + .doit = devlink_nl_cmd_linecard_set_doit, 295 + .flags = GENL_ADMIN_PERM, 296 + }, 297 + { 298 + .cmd = DEVLINK_CMD_SB_POOL_SET, 299 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 300 + .doit = devlink_nl_cmd_sb_pool_set_doit, 301 + .flags = GENL_ADMIN_PERM, 302 + }, 303 + { 304 + .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 305 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 306 + .doit = devlink_nl_cmd_sb_port_pool_set_doit, 307 + .flags = GENL_ADMIN_PERM, 308 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 309 + }, 310 + { 311 + .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 312 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 313 + .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 314 + .flags = GENL_ADMIN_PERM, 315 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 316 + }, 317 + { 318 + .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 319 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 320 + .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 321 + .flags = GENL_ADMIN_PERM, 322 + }, 323 + { 324 + .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 325 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 326 + .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 327 + .flags = GENL_ADMIN_PERM, 328 + }, 329 + { 330 + .cmd = DEVLINK_CMD_ESWITCH_GET, 331 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 332 + .doit = devlink_nl_cmd_eswitch_get_doit, 333 + .flags = GENL_ADMIN_PERM, 334 + }, 335 + { 336 + .cmd = DEVLINK_CMD_ESWITCH_SET, 337 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 338 + .doit = devlink_nl_cmd_eswitch_set_doit, 339 + .flags = GENL_ADMIN_PERM, 340 + }, 341 + { 342 + .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 343 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 344 + .doit = devlink_nl_cmd_dpipe_table_get, 345 + /* can be retrieved by unprivileged users */ 346 + }, 347 + { 348 + .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 349 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 350 + .doit = devlink_nl_cmd_dpipe_entries_get, 351 + /* can be retrieved by unprivileged users */ 352 + }, 353 + { 354 + .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 355 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 356 + .doit = devlink_nl_cmd_dpipe_headers_get, 357 + /* can be retrieved by unprivileged users */ 358 + }, 359 + { 360 + .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 361 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 362 + .doit = devlink_nl_cmd_dpipe_table_counters_set, 363 + .flags = GENL_ADMIN_PERM, 364 + }, 365 + { 366 + .cmd = DEVLINK_CMD_RESOURCE_SET, 367 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 368 + .doit = devlink_nl_cmd_resource_set, 369 + .flags = GENL_ADMIN_PERM, 370 + }, 371 + { 372 + .cmd = DEVLINK_CMD_RESOURCE_DUMP, 373 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 374 + .doit = devlink_nl_cmd_resource_dump, 375 + /* can be retrieved by unprivileged users */ 376 + }, 377 + { 378 + .cmd = DEVLINK_CMD_RELOAD, 379 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 380 + .doit = devlink_nl_cmd_reload, 381 + .flags = GENL_ADMIN_PERM, 382 + }, 383 + { 384 + .cmd = DEVLINK_CMD_PARAM_SET, 385 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 386 + .doit = devlink_nl_cmd_param_set_doit, 387 + .flags = GENL_ADMIN_PERM, 388 + }, 389 + { 390 + .cmd = DEVLINK_CMD_PORT_PARAM_GET, 391 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 392 + .doit = devlink_nl_cmd_port_param_get_doit, 393 + .dumpit = devlink_nl_cmd_port_param_get_dumpit, 394 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 395 + /* can be retrieved by unprivileged users */ 396 + }, 397 + { 398 + .cmd = DEVLINK_CMD_PORT_PARAM_SET, 399 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 400 + .doit = devlink_nl_cmd_port_param_set_doit, 401 + .flags = GENL_ADMIN_PERM, 402 + .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 403 + }, 404 + { 405 + .cmd = DEVLINK_CMD_REGION_NEW, 406 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 407 + .doit = devlink_nl_cmd_region_new, 408 + .flags = GENL_ADMIN_PERM, 409 + }, 410 + { 411 + .cmd = DEVLINK_CMD_REGION_DEL, 412 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 413 + .doit = devlink_nl_cmd_region_del, 414 + .flags = GENL_ADMIN_PERM, 415 + }, 416 + { 417 + .cmd = DEVLINK_CMD_REGION_READ, 418 + .validate = GENL_DONT_VALIDATE_STRICT | 419 + GENL_DONT_VALIDATE_DUMP_STRICT, 420 + .dumpit = devlink_nl_cmd_region_read_dumpit, 421 + .flags = GENL_ADMIN_PERM, 422 + }, 423 + { 424 + .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET, 425 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 426 + .doit = devlink_nl_cmd_health_reporter_set_doit, 427 + .flags = GENL_ADMIN_PERM, 428 + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 429 + }, 430 + { 431 + .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER, 432 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 433 + .doit = devlink_nl_cmd_health_reporter_recover_doit, 434 + .flags = GENL_ADMIN_PERM, 435 + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 436 + }, 437 + { 438 + .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 439 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 440 + .doit = devlink_nl_cmd_health_reporter_diagnose_doit, 441 + .flags = GENL_ADMIN_PERM, 442 + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 443 + }, 444 + { 445 + .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, 446 + .validate = GENL_DONT_VALIDATE_STRICT | 447 + GENL_DONT_VALIDATE_DUMP_STRICT, 448 + .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit, 449 + .flags = GENL_ADMIN_PERM, 450 + }, 451 + { 452 + .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, 453 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 454 + .doit = devlink_nl_cmd_health_reporter_dump_clear_doit, 455 + .flags = GENL_ADMIN_PERM, 456 + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 457 + }, 458 + { 459 + .cmd = DEVLINK_CMD_HEALTH_REPORTER_TEST, 460 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 461 + .doit = devlink_nl_cmd_health_reporter_test_doit, 462 + .flags = GENL_ADMIN_PERM, 463 + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT, 464 + }, 465 + { 466 + .cmd = DEVLINK_CMD_FLASH_UPDATE, 467 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 468 + .doit = devlink_nl_cmd_flash_update, 469 + .flags = GENL_ADMIN_PERM, 470 + }, 471 + { 472 + .cmd = DEVLINK_CMD_TRAP_SET, 473 + .doit = devlink_nl_cmd_trap_set_doit, 474 + .flags = GENL_ADMIN_PERM, 475 + }, 476 + { 477 + .cmd = DEVLINK_CMD_TRAP_GROUP_SET, 478 + .doit = devlink_nl_cmd_trap_group_set_doit, 479 + .flags = GENL_ADMIN_PERM, 480 + }, 481 + { 482 + .cmd = DEVLINK_CMD_TRAP_POLICER_SET, 483 + .doit = devlink_nl_cmd_trap_policer_set_doit, 484 + .flags = GENL_ADMIN_PERM, 485 + }, 486 + { 487 + .cmd = DEVLINK_CMD_SELFTESTS_RUN, 488 + .doit = devlink_nl_cmd_selftests_run, 489 + .flags = GENL_ADMIN_PERM, 490 + }, 491 + /* -- No new ops here! Use split ops going forward! -- */ 492 + }; 257 493 258 494 struct genl_family devlink_nl_family __ro_after_init = { 259 495 .name = DEVLINK_GENL_NAME,
+865
net/devlink/param.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + static const struct devlink_param devlink_param_generic[] = { 10 + { 11 + .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, 12 + .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME, 13 + .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE, 14 + }, 15 + { 16 + .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 17 + .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME, 18 + .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE, 19 + }, 20 + { 21 + .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, 22 + .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME, 23 + .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE, 24 + }, 25 + { 26 + .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT, 27 + .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME, 28 + .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE, 29 + }, 30 + { 31 + .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, 32 + .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME, 33 + .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE, 34 + }, 35 + { 36 + .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 37 + .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME, 38 + .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE, 39 + }, 40 + { 41 + .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 42 + .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME, 43 + .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE, 44 + }, 45 + { 46 + .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, 47 + .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME, 48 + .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE, 49 + }, 50 + { 51 + .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE, 52 + .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME, 53 + .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE, 54 + }, 55 + { 56 + .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 57 + .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME, 58 + .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE, 59 + }, 60 + { 61 + .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET, 62 + .name = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_NAME, 63 + .type = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_TYPE, 64 + }, 65 + { 66 + .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, 67 + .name = DEVLINK_PARAM_GENERIC_ENABLE_ETH_NAME, 68 + .type = DEVLINK_PARAM_GENERIC_ENABLE_ETH_TYPE, 69 + }, 70 + { 71 + .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, 72 + .name = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_NAME, 73 + .type = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_TYPE, 74 + }, 75 + { 76 + .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, 77 + .name = DEVLINK_PARAM_GENERIC_ENABLE_VNET_NAME, 78 + .type = DEVLINK_PARAM_GENERIC_ENABLE_VNET_TYPE, 79 + }, 80 + { 81 + .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP, 82 + .name = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_NAME, 83 + .type = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_TYPE, 84 + }, 85 + { 86 + .id = DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE, 87 + .name = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_NAME, 88 + .type = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_TYPE, 89 + }, 90 + { 91 + .id = DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE, 92 + .name = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_NAME, 93 + .type = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_TYPE, 94 + }, 95 + }; 96 + 97 + static int devlink_param_generic_verify(const struct devlink_param *param) 98 + { 99 + /* verify it match generic parameter by id and name */ 100 + if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 101 + return -EINVAL; 102 + if (strcmp(param->name, devlink_param_generic[param->id].name)) 103 + return -ENOENT; 104 + 105 + WARN_ON(param->type != devlink_param_generic[param->id].type); 106 + 107 + return 0; 108 + } 109 + 110 + static int devlink_param_driver_verify(const struct devlink_param *param) 111 + { 112 + int i; 113 + 114 + if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 115 + return -EINVAL; 116 + /* verify no such name in generic params */ 117 + for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 118 + if (!strcmp(param->name, devlink_param_generic[i].name)) 119 + return -EEXIST; 120 + 121 + return 0; 122 + } 123 + 124 + static struct devlink_param_item * 125 + devlink_param_find_by_name(struct xarray *params, const char *param_name) 126 + { 127 + struct devlink_param_item *param_item; 128 + unsigned long param_id; 129 + 130 + xa_for_each(params, param_id, param_item) { 131 + if (!strcmp(param_item->param->name, param_name)) 132 + return param_item; 133 + } 134 + return NULL; 135 + } 136 + 137 + static struct devlink_param_item * 138 + devlink_param_find_by_id(struct xarray *params, u32 param_id) 139 + { 140 + return xa_load(params, param_id); 141 + } 142 + 143 + static bool 144 + devlink_param_cmode_is_supported(const struct devlink_param *param, 145 + enum devlink_param_cmode cmode) 146 + { 147 + return test_bit(cmode, &param->supported_cmodes); 148 + } 149 + 150 + static int devlink_param_get(struct devlink *devlink, 151 + const struct devlink_param *param, 152 + struct devlink_param_gset_ctx *ctx) 153 + { 154 + if (!param->get) 155 + return -EOPNOTSUPP; 156 + return param->get(devlink, param->id, ctx); 157 + } 158 + 159 + static int devlink_param_set(struct devlink *devlink, 160 + const struct devlink_param *param, 161 + struct devlink_param_gset_ctx *ctx) 162 + { 163 + if (!param->set) 164 + return -EOPNOTSUPP; 165 + return param->set(devlink, param->id, ctx); 166 + } 167 + 168 + static int 169 + devlink_param_type_to_nla_type(enum devlink_param_type param_type) 170 + { 171 + switch (param_type) { 172 + case DEVLINK_PARAM_TYPE_U8: 173 + return NLA_U8; 174 + case DEVLINK_PARAM_TYPE_U16: 175 + return NLA_U16; 176 + case DEVLINK_PARAM_TYPE_U32: 177 + return NLA_U32; 178 + case DEVLINK_PARAM_TYPE_STRING: 179 + return NLA_STRING; 180 + case DEVLINK_PARAM_TYPE_BOOL: 181 + return NLA_FLAG; 182 + default: 183 + return -EINVAL; 184 + } 185 + } 186 + 187 + static int 188 + devlink_nl_param_value_fill_one(struct sk_buff *msg, 189 + enum devlink_param_type type, 190 + enum devlink_param_cmode cmode, 191 + union devlink_param_value val) 192 + { 193 + struct nlattr *param_value_attr; 194 + 195 + param_value_attr = nla_nest_start_noflag(msg, 196 + DEVLINK_ATTR_PARAM_VALUE); 197 + if (!param_value_attr) 198 + goto nla_put_failure; 199 + 200 + if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 201 + goto value_nest_cancel; 202 + 203 + switch (type) { 204 + case DEVLINK_PARAM_TYPE_U8: 205 + if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 206 + goto value_nest_cancel; 207 + break; 208 + case DEVLINK_PARAM_TYPE_U16: 209 + if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 210 + goto value_nest_cancel; 211 + break; 212 + case DEVLINK_PARAM_TYPE_U32: 213 + if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 214 + goto value_nest_cancel; 215 + break; 216 + case DEVLINK_PARAM_TYPE_STRING: 217 + if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 218 + val.vstr)) 219 + goto value_nest_cancel; 220 + break; 221 + case DEVLINK_PARAM_TYPE_BOOL: 222 + if (val.vbool && 223 + nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 224 + goto value_nest_cancel; 225 + break; 226 + } 227 + 228 + nla_nest_end(msg, param_value_attr); 229 + return 0; 230 + 231 + value_nest_cancel: 232 + nla_nest_cancel(msg, param_value_attr); 233 + nla_put_failure: 234 + return -EMSGSIZE; 235 + } 236 + 237 + static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 238 + unsigned int port_index, 239 + struct devlink_param_item *param_item, 240 + enum devlink_command cmd, 241 + u32 portid, u32 seq, int flags) 242 + { 243 + union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 244 + bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {}; 245 + const struct devlink_param *param = param_item->param; 246 + struct devlink_param_gset_ctx ctx; 247 + struct nlattr *param_values_list; 248 + struct nlattr *param_attr; 249 + int nla_type; 250 + void *hdr; 251 + int err; 252 + int i; 253 + 254 + /* Get value from driver part to driverinit configuration mode */ 255 + for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 256 + if (!devlink_param_cmode_is_supported(param, i)) 257 + continue; 258 + if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 259 + if (param_item->driverinit_value_new_valid) 260 + param_value[i] = param_item->driverinit_value_new; 261 + else if (param_item->driverinit_value_valid) 262 + param_value[i] = param_item->driverinit_value; 263 + else 264 + return -EOPNOTSUPP; 265 + } else { 266 + ctx.cmode = i; 267 + err = devlink_param_get(devlink, param, &ctx); 268 + if (err) 269 + return err; 270 + param_value[i] = ctx.val; 271 + } 272 + param_value_set[i] = true; 273 + } 274 + 275 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 276 + if (!hdr) 277 + return -EMSGSIZE; 278 + 279 + if (devlink_nl_put_handle(msg, devlink)) 280 + goto genlmsg_cancel; 281 + 282 + if (cmd == DEVLINK_CMD_PORT_PARAM_GET || 283 + cmd == DEVLINK_CMD_PORT_PARAM_NEW || 284 + cmd == DEVLINK_CMD_PORT_PARAM_DEL) 285 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index)) 286 + goto genlmsg_cancel; 287 + 288 + param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM); 289 + if (!param_attr) 290 + goto genlmsg_cancel; 291 + if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 292 + goto param_nest_cancel; 293 + if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 294 + goto param_nest_cancel; 295 + 296 + nla_type = devlink_param_type_to_nla_type(param->type); 297 + if (nla_type < 0) 298 + goto param_nest_cancel; 299 + if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 300 + goto param_nest_cancel; 301 + 302 + param_values_list = nla_nest_start_noflag(msg, 303 + DEVLINK_ATTR_PARAM_VALUES_LIST); 304 + if (!param_values_list) 305 + goto param_nest_cancel; 306 + 307 + for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 308 + if (!param_value_set[i]) 309 + continue; 310 + err = devlink_nl_param_value_fill_one(msg, param->type, 311 + i, param_value[i]); 312 + if (err) 313 + goto values_list_nest_cancel; 314 + } 315 + 316 + nla_nest_end(msg, param_values_list); 317 + nla_nest_end(msg, param_attr); 318 + genlmsg_end(msg, hdr); 319 + return 0; 320 + 321 + values_list_nest_cancel: 322 + nla_nest_end(msg, param_values_list); 323 + param_nest_cancel: 324 + nla_nest_cancel(msg, param_attr); 325 + genlmsg_cancel: 326 + genlmsg_cancel(msg, hdr); 327 + return -EMSGSIZE; 328 + } 329 + 330 + static void devlink_param_notify(struct devlink *devlink, 331 + unsigned int port_index, 332 + struct devlink_param_item *param_item, 333 + enum devlink_command cmd) 334 + { 335 + struct sk_buff *msg; 336 + int err; 337 + 338 + WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL && 339 + cmd != DEVLINK_CMD_PORT_PARAM_NEW && 340 + cmd != DEVLINK_CMD_PORT_PARAM_DEL); 341 + 342 + /* devlink_notify_register() / devlink_notify_unregister() 343 + * will replay the notifications if the params are added/removed 344 + * outside of the lifetime of the instance. 345 + */ 346 + if (!devl_is_registered(devlink)) 347 + return; 348 + 349 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 350 + if (!msg) 351 + return; 352 + err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd, 353 + 0, 0, 0); 354 + if (err) { 355 + nlmsg_free(msg); 356 + return; 357 + } 358 + 359 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 360 + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 361 + } 362 + 363 + static void devlink_params_notify(struct devlink *devlink, 364 + enum devlink_command cmd) 365 + { 366 + struct devlink_param_item *param_item; 367 + unsigned long param_id; 368 + 369 + xa_for_each(&devlink->params, param_id, param_item) 370 + devlink_param_notify(devlink, 0, param_item, cmd); 371 + } 372 + 373 + void devlink_params_notify_register(struct devlink *devlink) 374 + { 375 + devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW); 376 + } 377 + 378 + void devlink_params_notify_unregister(struct devlink *devlink) 379 + { 380 + devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL); 381 + } 382 + 383 + static int devlink_nl_param_get_dump_one(struct sk_buff *msg, 384 + struct devlink *devlink, 385 + struct netlink_callback *cb, 386 + int flags) 387 + { 388 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 389 + struct devlink_param_item *param_item; 390 + unsigned long param_id; 391 + int err = 0; 392 + 393 + xa_for_each_start(&devlink->params, param_id, param_item, state->idx) { 394 + err = devlink_nl_param_fill(msg, devlink, 0, param_item, 395 + DEVLINK_CMD_PARAM_GET, 396 + NETLINK_CB(cb->skb).portid, 397 + cb->nlh->nlmsg_seq, flags); 398 + if (err == -EOPNOTSUPP) { 399 + err = 0; 400 + } else if (err) { 401 + state->idx = param_id; 402 + break; 403 + } 404 + } 405 + 406 + return err; 407 + } 408 + 409 + int devlink_nl_param_get_dumpit(struct sk_buff *skb, 410 + struct netlink_callback *cb) 411 + { 412 + return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one); 413 + } 414 + 415 + static int 416 + devlink_param_type_get_from_info(struct genl_info *info, 417 + enum devlink_param_type *param_type) 418 + { 419 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE)) 420 + return -EINVAL; 421 + 422 + switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { 423 + case NLA_U8: 424 + *param_type = DEVLINK_PARAM_TYPE_U8; 425 + break; 426 + case NLA_U16: 427 + *param_type = DEVLINK_PARAM_TYPE_U16; 428 + break; 429 + case NLA_U32: 430 + *param_type = DEVLINK_PARAM_TYPE_U32; 431 + break; 432 + case NLA_STRING: 433 + *param_type = DEVLINK_PARAM_TYPE_STRING; 434 + break; 435 + case NLA_FLAG: 436 + *param_type = DEVLINK_PARAM_TYPE_BOOL; 437 + break; 438 + default: 439 + return -EINVAL; 440 + } 441 + 442 + return 0; 443 + } 444 + 445 + static int 446 + devlink_param_value_get_from_info(const struct devlink_param *param, 447 + struct genl_info *info, 448 + union devlink_param_value *value) 449 + { 450 + struct nlattr *param_data; 451 + int len; 452 + 453 + param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]; 454 + 455 + if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data) 456 + return -EINVAL; 457 + 458 + switch (param->type) { 459 + case DEVLINK_PARAM_TYPE_U8: 460 + if (nla_len(param_data) != sizeof(u8)) 461 + return -EINVAL; 462 + value->vu8 = nla_get_u8(param_data); 463 + break; 464 + case DEVLINK_PARAM_TYPE_U16: 465 + if (nla_len(param_data) != sizeof(u16)) 466 + return -EINVAL; 467 + value->vu16 = nla_get_u16(param_data); 468 + break; 469 + case DEVLINK_PARAM_TYPE_U32: 470 + if (nla_len(param_data) != sizeof(u32)) 471 + return -EINVAL; 472 + value->vu32 = nla_get_u32(param_data); 473 + break; 474 + case DEVLINK_PARAM_TYPE_STRING: 475 + len = strnlen(nla_data(param_data), nla_len(param_data)); 476 + if (len == nla_len(param_data) || 477 + len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 478 + return -EINVAL; 479 + strcpy(value->vstr, nla_data(param_data)); 480 + break; 481 + case DEVLINK_PARAM_TYPE_BOOL: 482 + if (param_data && nla_len(param_data)) 483 + return -EINVAL; 484 + value->vbool = nla_get_flag(param_data); 485 + break; 486 + } 487 + return 0; 488 + } 489 + 490 + static struct devlink_param_item * 491 + devlink_param_get_from_info(struct xarray *params, struct genl_info *info) 492 + { 493 + char *param_name; 494 + 495 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME)) 496 + return NULL; 497 + 498 + param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 499 + return devlink_param_find_by_name(params, param_name); 500 + } 501 + 502 + int devlink_nl_param_get_doit(struct sk_buff *skb, 503 + struct genl_info *info) 504 + { 505 + struct devlink *devlink = info->user_ptr[0]; 506 + struct devlink_param_item *param_item; 507 + struct sk_buff *msg; 508 + int err; 509 + 510 + param_item = devlink_param_get_from_info(&devlink->params, info); 511 + if (!param_item) 512 + return -EINVAL; 513 + 514 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 515 + if (!msg) 516 + return -ENOMEM; 517 + 518 + err = devlink_nl_param_fill(msg, devlink, 0, param_item, 519 + DEVLINK_CMD_PARAM_GET, 520 + info->snd_portid, info->snd_seq, 0); 521 + if (err) { 522 + nlmsg_free(msg); 523 + return err; 524 + } 525 + 526 + return genlmsg_reply(msg, info); 527 + } 528 + 529 + static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, 530 + unsigned int port_index, 531 + struct xarray *params, 532 + struct genl_info *info, 533 + enum devlink_command cmd) 534 + { 535 + enum devlink_param_type param_type; 536 + struct devlink_param_gset_ctx ctx; 537 + enum devlink_param_cmode cmode; 538 + struct devlink_param_item *param_item; 539 + const struct devlink_param *param; 540 + union devlink_param_value value; 541 + int err = 0; 542 + 543 + param_item = devlink_param_get_from_info(params, info); 544 + if (!param_item) 545 + return -EINVAL; 546 + param = param_item->param; 547 + err = devlink_param_type_get_from_info(info, &param_type); 548 + if (err) 549 + return err; 550 + if (param_type != param->type) 551 + return -EINVAL; 552 + err = devlink_param_value_get_from_info(param, info, &value); 553 + if (err) 554 + return err; 555 + if (param->validate) { 556 + err = param->validate(devlink, param->id, value, info->extack); 557 + if (err) 558 + return err; 559 + } 560 + 561 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE)) 562 + return -EINVAL; 563 + cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 564 + if (!devlink_param_cmode_is_supported(param, cmode)) 565 + return -EOPNOTSUPP; 566 + 567 + if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 568 + param_item->driverinit_value_new = value; 569 + param_item->driverinit_value_new_valid = true; 570 + } else { 571 + if (!param->set) 572 + return -EOPNOTSUPP; 573 + ctx.val = value; 574 + ctx.cmode = cmode; 575 + err = devlink_param_set(devlink, param, &ctx); 576 + if (err) 577 + return err; 578 + } 579 + 580 + devlink_param_notify(devlink, port_index, param_item, cmd); 581 + return 0; 582 + } 583 + 584 + int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, struct genl_info *info) 585 + { 586 + struct devlink *devlink = info->user_ptr[0]; 587 + 588 + return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params, 589 + info, DEVLINK_CMD_PARAM_NEW); 590 + } 591 + 592 + int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg, 593 + struct netlink_callback *cb) 594 + { 595 + NL_SET_ERR_MSG(cb->extack, "Port params are not supported"); 596 + return msg->len; 597 + } 598 + 599 + int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb, 600 + struct genl_info *info) 601 + { 602 + NL_SET_ERR_MSG(info->extack, "Port params are not supported"); 603 + return -EINVAL; 604 + } 605 + 606 + int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb, 607 + struct genl_info *info) 608 + { 609 + NL_SET_ERR_MSG(info->extack, "Port params are not supported"); 610 + return -EINVAL; 611 + } 612 + 613 + static int devlink_param_verify(const struct devlink_param *param) 614 + { 615 + if (!param || !param->name || !param->supported_cmodes) 616 + return -EINVAL; 617 + if (param->generic) 618 + return devlink_param_generic_verify(param); 619 + else 620 + return devlink_param_driver_verify(param); 621 + } 622 + 623 + static int devlink_param_register(struct devlink *devlink, 624 + const struct devlink_param *param) 625 + { 626 + struct devlink_param_item *param_item; 627 + int err; 628 + 629 + WARN_ON(devlink_param_verify(param)); 630 + WARN_ON(devlink_param_find_by_name(&devlink->params, param->name)); 631 + 632 + if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 633 + WARN_ON(param->get || param->set); 634 + else 635 + WARN_ON(!param->get || !param->set); 636 + 637 + param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 638 + if (!param_item) 639 + return -ENOMEM; 640 + 641 + param_item->param = param; 642 + 643 + err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL); 644 + if (err) 645 + goto err_xa_insert; 646 + 647 + devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 648 + return 0; 649 + 650 + err_xa_insert: 651 + kfree(param_item); 652 + return err; 653 + } 654 + 655 + static void devlink_param_unregister(struct devlink *devlink, 656 + const struct devlink_param *param) 657 + { 658 + struct devlink_param_item *param_item; 659 + 660 + param_item = devlink_param_find_by_id(&devlink->params, param->id); 661 + if (WARN_ON(!param_item)) 662 + return; 663 + devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL); 664 + xa_erase(&devlink->params, param->id); 665 + kfree(param_item); 666 + } 667 + 668 + /** 669 + * devl_params_register - register configuration parameters 670 + * 671 + * @devlink: devlink 672 + * @params: configuration parameters array 673 + * @params_count: number of parameters provided 674 + * 675 + * Register the configuration parameters supported by the driver. 676 + */ 677 + int devl_params_register(struct devlink *devlink, 678 + const struct devlink_param *params, 679 + size_t params_count) 680 + { 681 + const struct devlink_param *param = params; 682 + int i, err; 683 + 684 + lockdep_assert_held(&devlink->lock); 685 + 686 + for (i = 0; i < params_count; i++, param++) { 687 + err = devlink_param_register(devlink, param); 688 + if (err) 689 + goto rollback; 690 + } 691 + return 0; 692 + 693 + rollback: 694 + if (!i) 695 + return err; 696 + 697 + for (param--; i > 0; i--, param--) 698 + devlink_param_unregister(devlink, param); 699 + return err; 700 + } 701 + EXPORT_SYMBOL_GPL(devl_params_register); 702 + 703 + int devlink_params_register(struct devlink *devlink, 704 + const struct devlink_param *params, 705 + size_t params_count) 706 + { 707 + int err; 708 + 709 + devl_lock(devlink); 710 + err = devl_params_register(devlink, params, params_count); 711 + devl_unlock(devlink); 712 + return err; 713 + } 714 + EXPORT_SYMBOL_GPL(devlink_params_register); 715 + 716 + /** 717 + * devl_params_unregister - unregister configuration parameters 718 + * @devlink: devlink 719 + * @params: configuration parameters to unregister 720 + * @params_count: number of parameters provided 721 + */ 722 + void devl_params_unregister(struct devlink *devlink, 723 + const struct devlink_param *params, 724 + size_t params_count) 725 + { 726 + const struct devlink_param *param = params; 727 + int i; 728 + 729 + lockdep_assert_held(&devlink->lock); 730 + 731 + for (i = 0; i < params_count; i++, param++) 732 + devlink_param_unregister(devlink, param); 733 + } 734 + EXPORT_SYMBOL_GPL(devl_params_unregister); 735 + 736 + void devlink_params_unregister(struct devlink *devlink, 737 + const struct devlink_param *params, 738 + size_t params_count) 739 + { 740 + devl_lock(devlink); 741 + devl_params_unregister(devlink, params, params_count); 742 + devl_unlock(devlink); 743 + } 744 + EXPORT_SYMBOL_GPL(devlink_params_unregister); 745 + 746 + /** 747 + * devl_param_driverinit_value_get - get configuration parameter 748 + * value for driver initializing 749 + * 750 + * @devlink: devlink 751 + * @param_id: parameter ID 752 + * @val: pointer to store the value of parameter in driverinit 753 + * configuration mode 754 + * 755 + * This function should be used by the driver to get driverinit 756 + * configuration for initialization after reload command. 757 + * 758 + * Note that lockless call of this function relies on the 759 + * driver to maintain following basic sane behavior: 760 + * 1) Driver ensures a call to this function cannot race with 761 + * registering/unregistering the parameter with the same parameter ID. 762 + * 2) Driver ensures a call to this function cannot race with 763 + * devl_param_driverinit_value_set() call with the same parameter ID. 764 + * 3) Driver ensures a call to this function cannot race with 765 + * reload operation. 766 + * If the driver is not able to comply, it has to take the devlink->lock 767 + * while calling this. 768 + */ 769 + int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 770 + union devlink_param_value *val) 771 + { 772 + struct devlink_param_item *param_item; 773 + 774 + if (WARN_ON(!devlink_reload_supported(devlink->ops))) 775 + return -EOPNOTSUPP; 776 + 777 + param_item = devlink_param_find_by_id(&devlink->params, param_id); 778 + if (!param_item) 779 + return -EINVAL; 780 + 781 + if (!param_item->driverinit_value_valid) 782 + return -EOPNOTSUPP; 783 + 784 + if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param, 785 + DEVLINK_PARAM_CMODE_DRIVERINIT))) 786 + return -EOPNOTSUPP; 787 + 788 + *val = param_item->driverinit_value; 789 + 790 + return 0; 791 + } 792 + EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get); 793 + 794 + /** 795 + * devl_param_driverinit_value_set - set value of configuration 796 + * parameter for driverinit 797 + * configuration mode 798 + * 799 + * @devlink: devlink 800 + * @param_id: parameter ID 801 + * @init_val: value of parameter to set for driverinit configuration mode 802 + * 803 + * This function should be used by the driver to set driverinit 804 + * configuration mode default value. 805 + */ 806 + void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 807 + union devlink_param_value init_val) 808 + { 809 + struct devlink_param_item *param_item; 810 + 811 + devl_assert_locked(devlink); 812 + 813 + param_item = devlink_param_find_by_id(&devlink->params, param_id); 814 + if (WARN_ON(!param_item)) 815 + return; 816 + 817 + if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param, 818 + DEVLINK_PARAM_CMODE_DRIVERINIT))) 819 + return; 820 + 821 + param_item->driverinit_value = init_val; 822 + param_item->driverinit_value_valid = true; 823 + 824 + devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 825 + } 826 + EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set); 827 + 828 + void devlink_params_driverinit_load_new(struct devlink *devlink) 829 + { 830 + struct devlink_param_item *param_item; 831 + unsigned long param_id; 832 + 833 + xa_for_each(&devlink->params, param_id, param_item) { 834 + if (!devlink_param_cmode_is_supported(param_item->param, 835 + DEVLINK_PARAM_CMODE_DRIVERINIT) || 836 + !param_item->driverinit_value_new_valid) 837 + continue; 838 + param_item->driverinit_value = param_item->driverinit_value_new; 839 + param_item->driverinit_value_valid = true; 840 + param_item->driverinit_value_new_valid = false; 841 + } 842 + } 843 + 844 + /** 845 + * devl_param_value_changed - notify devlink on a parameter's value 846 + * change. Should be called by the driver 847 + * right after the change. 848 + * 849 + * @devlink: devlink 850 + * @param_id: parameter ID 851 + * 852 + * This function should be used by the driver to notify devlink on value 853 + * change, excluding driverinit configuration mode. 854 + * For driverinit configuration mode driver should use the function 855 + */ 856 + void devl_param_value_changed(struct devlink *devlink, u32 param_id) 857 + { 858 + struct devlink_param_item *param_item; 859 + 860 + param_item = devlink_param_find_by_id(&devlink->params, param_id); 861 + WARN_ON(!param_item); 862 + 863 + devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 864 + } 865 + EXPORT_SYMBOL_GPL(devl_param_value_changed);
+1515
net/devlink/port.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + #define DEVLINK_PORT_FN_CAPS_VALID_MASK \ 10 + (_BITUL(__DEVLINK_PORT_FN_ATTR_CAPS_MAX) - 1) 11 + 12 + static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = { 13 + [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY }, 14 + [DEVLINK_PORT_FN_ATTR_STATE] = 15 + NLA_POLICY_RANGE(NLA_U8, DEVLINK_PORT_FN_STATE_INACTIVE, 16 + DEVLINK_PORT_FN_STATE_ACTIVE), 17 + [DEVLINK_PORT_FN_ATTR_CAPS] = 18 + NLA_POLICY_BITFIELD32(DEVLINK_PORT_FN_CAPS_VALID_MASK), 19 + }; 20 + 21 + #define ASSERT_DEVLINK_PORT_REGISTERED(devlink_port) \ 22 + WARN_ON_ONCE(!(devlink_port)->registered) 23 + #define ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port) \ 24 + WARN_ON_ONCE((devlink_port)->registered) 25 + 26 + struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 27 + unsigned int port_index) 28 + { 29 + return xa_load(&devlink->ports, port_index); 30 + } 31 + 32 + struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, 33 + struct nlattr **attrs) 34 + { 35 + if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 36 + u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 37 + struct devlink_port *devlink_port; 38 + 39 + devlink_port = devlink_port_get_by_index(devlink, port_index); 40 + if (!devlink_port) 41 + return ERR_PTR(-ENODEV); 42 + return devlink_port; 43 + } 44 + return ERR_PTR(-EINVAL); 45 + } 46 + 47 + struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, 48 + struct genl_info *info) 49 + { 50 + return devlink_port_get_from_attrs(devlink, info->attrs); 51 + } 52 + 53 + static void devlink_port_fn_cap_fill(struct nla_bitfield32 *caps, 54 + u32 cap, bool is_enable) 55 + { 56 + caps->selector |= cap; 57 + if (is_enable) 58 + caps->value |= cap; 59 + } 60 + 61 + static int devlink_port_fn_roce_fill(struct devlink_port *devlink_port, 62 + struct nla_bitfield32 *caps, 63 + struct netlink_ext_ack *extack) 64 + { 65 + bool is_enable; 66 + int err; 67 + 68 + if (!devlink_port->ops->port_fn_roce_get) 69 + return 0; 70 + 71 + err = devlink_port->ops->port_fn_roce_get(devlink_port, &is_enable, 72 + extack); 73 + if (err) { 74 + if (err == -EOPNOTSUPP) 75 + return 0; 76 + return err; 77 + } 78 + 79 + devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_ROCE, is_enable); 80 + return 0; 81 + } 82 + 83 + static int devlink_port_fn_migratable_fill(struct devlink_port *devlink_port, 84 + struct nla_bitfield32 *caps, 85 + struct netlink_ext_ack *extack) 86 + { 87 + bool is_enable; 88 + int err; 89 + 90 + if (!devlink_port->ops->port_fn_migratable_get || 91 + devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) 92 + return 0; 93 + 94 + err = devlink_port->ops->port_fn_migratable_get(devlink_port, 95 + &is_enable, extack); 96 + if (err) { 97 + if (err == -EOPNOTSUPP) 98 + return 0; 99 + return err; 100 + } 101 + 102 + devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_MIGRATABLE, is_enable); 103 + return 0; 104 + } 105 + 106 + static int devlink_port_fn_ipsec_crypto_fill(struct devlink_port *devlink_port, 107 + struct nla_bitfield32 *caps, 108 + struct netlink_ext_ack *extack) 109 + { 110 + bool is_enable; 111 + int err; 112 + 113 + if (!devlink_port->ops->port_fn_ipsec_crypto_get || 114 + devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) 115 + return 0; 116 + 117 + err = devlink_port->ops->port_fn_ipsec_crypto_get(devlink_port, &is_enable, extack); 118 + if (err) { 119 + if (err == -EOPNOTSUPP) 120 + return 0; 121 + return err; 122 + } 123 + 124 + devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO, is_enable); 125 + return 0; 126 + } 127 + 128 + static int devlink_port_fn_ipsec_packet_fill(struct devlink_port *devlink_port, 129 + struct nla_bitfield32 *caps, 130 + struct netlink_ext_ack *extack) 131 + { 132 + bool is_enable; 133 + int err; 134 + 135 + if (!devlink_port->ops->port_fn_ipsec_packet_get || 136 + devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) 137 + return 0; 138 + 139 + err = devlink_port->ops->port_fn_ipsec_packet_get(devlink_port, &is_enable, extack); 140 + if (err) { 141 + if (err == -EOPNOTSUPP) 142 + return 0; 143 + return err; 144 + } 145 + 146 + devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_IPSEC_PACKET, is_enable); 147 + return 0; 148 + } 149 + 150 + static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port, 151 + struct sk_buff *msg, 152 + struct netlink_ext_ack *extack, 153 + bool *msg_updated) 154 + { 155 + struct nla_bitfield32 caps = {}; 156 + int err; 157 + 158 + err = devlink_port_fn_roce_fill(devlink_port, &caps, extack); 159 + if (err) 160 + return err; 161 + 162 + err = devlink_port_fn_migratable_fill(devlink_port, &caps, extack); 163 + if (err) 164 + return err; 165 + 166 + err = devlink_port_fn_ipsec_crypto_fill(devlink_port, &caps, extack); 167 + if (err) 168 + return err; 169 + 170 + err = devlink_port_fn_ipsec_packet_fill(devlink_port, &caps, extack); 171 + if (err) 172 + return err; 173 + 174 + if (!caps.selector) 175 + return 0; 176 + err = nla_put_bitfield32(msg, DEVLINK_PORT_FN_ATTR_CAPS, caps.value, 177 + caps.selector); 178 + if (err) 179 + return err; 180 + 181 + *msg_updated = true; 182 + return 0; 183 + } 184 + 185 + int devlink_nl_port_handle_fill(struct sk_buff *msg, struct devlink_port *devlink_port) 186 + { 187 + if (devlink_nl_put_handle(msg, devlink_port->devlink)) 188 + return -EMSGSIZE; 189 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 190 + return -EMSGSIZE; 191 + return 0; 192 + } 193 + 194 + size_t devlink_nl_port_handle_size(struct devlink_port *devlink_port) 195 + { 196 + struct devlink *devlink = devlink_port->devlink; 197 + 198 + return nla_total_size(strlen(devlink->dev->bus->name) + 1) /* DEVLINK_ATTR_BUS_NAME */ 199 + + nla_total_size(strlen(dev_name(devlink->dev)) + 1) /* DEVLINK_ATTR_DEV_NAME */ 200 + + nla_total_size(4); /* DEVLINK_ATTR_PORT_INDEX */ 201 + } 202 + 203 + static int devlink_nl_port_attrs_put(struct sk_buff *msg, 204 + struct devlink_port *devlink_port) 205 + { 206 + struct devlink_port_attrs *attrs = &devlink_port->attrs; 207 + 208 + if (!devlink_port->attrs_set) 209 + return 0; 210 + if (attrs->lanes) { 211 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_LANES, attrs->lanes)) 212 + return -EMSGSIZE; 213 + } 214 + if (nla_put_u8(msg, DEVLINK_ATTR_PORT_SPLITTABLE, attrs->splittable)) 215 + return -EMSGSIZE; 216 + if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour)) 217 + return -EMSGSIZE; 218 + switch (devlink_port->attrs.flavour) { 219 + case DEVLINK_PORT_FLAVOUR_PCI_PF: 220 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, 221 + attrs->pci_pf.controller) || 222 + nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_pf.pf)) 223 + return -EMSGSIZE; 224 + if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_pf.external)) 225 + return -EMSGSIZE; 226 + break; 227 + case DEVLINK_PORT_FLAVOUR_PCI_VF: 228 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, 229 + attrs->pci_vf.controller) || 230 + nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_vf.pf) || 231 + nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER, attrs->pci_vf.vf)) 232 + return -EMSGSIZE; 233 + if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_vf.external)) 234 + return -EMSGSIZE; 235 + break; 236 + case DEVLINK_PORT_FLAVOUR_PCI_SF: 237 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, 238 + attrs->pci_sf.controller) || 239 + nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, 240 + attrs->pci_sf.pf) || 241 + nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_SF_NUMBER, 242 + attrs->pci_sf.sf)) 243 + return -EMSGSIZE; 244 + break; 245 + case DEVLINK_PORT_FLAVOUR_PHYSICAL: 246 + case DEVLINK_PORT_FLAVOUR_CPU: 247 + case DEVLINK_PORT_FLAVOUR_DSA: 248 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, 249 + attrs->phys.port_number)) 250 + return -EMSGSIZE; 251 + if (!attrs->split) 252 + return 0; 253 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, 254 + attrs->phys.port_number)) 255 + return -EMSGSIZE; 256 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, 257 + attrs->phys.split_subport_number)) 258 + return -EMSGSIZE; 259 + break; 260 + default: 261 + break; 262 + } 263 + return 0; 264 + } 265 + 266 + static int devlink_port_fn_hw_addr_fill(struct devlink_port *port, 267 + struct sk_buff *msg, 268 + struct netlink_ext_ack *extack, 269 + bool *msg_updated) 270 + { 271 + u8 hw_addr[MAX_ADDR_LEN]; 272 + int hw_addr_len; 273 + int err; 274 + 275 + if (!port->ops->port_fn_hw_addr_get) 276 + return 0; 277 + 278 + err = port->ops->port_fn_hw_addr_get(port, hw_addr, &hw_addr_len, 279 + extack); 280 + if (err) { 281 + if (err == -EOPNOTSUPP) 282 + return 0; 283 + return err; 284 + } 285 + err = nla_put(msg, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, hw_addr_len, hw_addr); 286 + if (err) 287 + return err; 288 + *msg_updated = true; 289 + return 0; 290 + } 291 + 292 + static bool 293 + devlink_port_fn_state_valid(enum devlink_port_fn_state state) 294 + { 295 + return state == DEVLINK_PORT_FN_STATE_INACTIVE || 296 + state == DEVLINK_PORT_FN_STATE_ACTIVE; 297 + } 298 + 299 + static bool 300 + devlink_port_fn_opstate_valid(enum devlink_port_fn_opstate opstate) 301 + { 302 + return opstate == DEVLINK_PORT_FN_OPSTATE_DETACHED || 303 + opstate == DEVLINK_PORT_FN_OPSTATE_ATTACHED; 304 + } 305 + 306 + static int devlink_port_fn_state_fill(struct devlink_port *port, 307 + struct sk_buff *msg, 308 + struct netlink_ext_ack *extack, 309 + bool *msg_updated) 310 + { 311 + enum devlink_port_fn_opstate opstate; 312 + enum devlink_port_fn_state state; 313 + int err; 314 + 315 + if (!port->ops->port_fn_state_get) 316 + return 0; 317 + 318 + err = port->ops->port_fn_state_get(port, &state, &opstate, extack); 319 + if (err) { 320 + if (err == -EOPNOTSUPP) 321 + return 0; 322 + return err; 323 + } 324 + if (!devlink_port_fn_state_valid(state)) { 325 + WARN_ON_ONCE(1); 326 + NL_SET_ERR_MSG(extack, "Invalid state read from driver"); 327 + return -EINVAL; 328 + } 329 + if (!devlink_port_fn_opstate_valid(opstate)) { 330 + WARN_ON_ONCE(1); 331 + NL_SET_ERR_MSG(extack, "Invalid operational state read from driver"); 332 + return -EINVAL; 333 + } 334 + if (nla_put_u8(msg, DEVLINK_PORT_FN_ATTR_STATE, state) || 335 + nla_put_u8(msg, DEVLINK_PORT_FN_ATTR_OPSTATE, opstate)) 336 + return -EMSGSIZE; 337 + *msg_updated = true; 338 + return 0; 339 + } 340 + 341 + static int 342 + devlink_port_fn_mig_set(struct devlink_port *devlink_port, bool enable, 343 + struct netlink_ext_ack *extack) 344 + { 345 + return devlink_port->ops->port_fn_migratable_set(devlink_port, enable, 346 + extack); 347 + } 348 + 349 + static int 350 + devlink_port_fn_roce_set(struct devlink_port *devlink_port, bool enable, 351 + struct netlink_ext_ack *extack) 352 + { 353 + return devlink_port->ops->port_fn_roce_set(devlink_port, enable, 354 + extack); 355 + } 356 + 357 + static int 358 + devlink_port_fn_ipsec_crypto_set(struct devlink_port *devlink_port, bool enable, 359 + struct netlink_ext_ack *extack) 360 + { 361 + return devlink_port->ops->port_fn_ipsec_crypto_set(devlink_port, enable, extack); 362 + } 363 + 364 + static int 365 + devlink_port_fn_ipsec_packet_set(struct devlink_port *devlink_port, bool enable, 366 + struct netlink_ext_ack *extack) 367 + { 368 + return devlink_port->ops->port_fn_ipsec_packet_set(devlink_port, enable, extack); 369 + } 370 + 371 + static int devlink_port_fn_caps_set(struct devlink_port *devlink_port, 372 + const struct nlattr *attr, 373 + struct netlink_ext_ack *extack) 374 + { 375 + struct nla_bitfield32 caps; 376 + u32 caps_value; 377 + int err; 378 + 379 + caps = nla_get_bitfield32(attr); 380 + caps_value = caps.value & caps.selector; 381 + if (caps.selector & DEVLINK_PORT_FN_CAP_ROCE) { 382 + err = devlink_port_fn_roce_set(devlink_port, 383 + caps_value & DEVLINK_PORT_FN_CAP_ROCE, 384 + extack); 385 + if (err) 386 + return err; 387 + } 388 + if (caps.selector & DEVLINK_PORT_FN_CAP_MIGRATABLE) { 389 + err = devlink_port_fn_mig_set(devlink_port, caps_value & 390 + DEVLINK_PORT_FN_CAP_MIGRATABLE, 391 + extack); 392 + if (err) 393 + return err; 394 + } 395 + if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO) { 396 + err = devlink_port_fn_ipsec_crypto_set(devlink_port, caps_value & 397 + DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO, 398 + extack); 399 + if (err) 400 + return err; 401 + } 402 + if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_PACKET) { 403 + err = devlink_port_fn_ipsec_packet_set(devlink_port, caps_value & 404 + DEVLINK_PORT_FN_CAP_IPSEC_PACKET, 405 + extack); 406 + if (err) 407 + return err; 408 + } 409 + return 0; 410 + } 411 + 412 + static int 413 + devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *port, 414 + struct netlink_ext_ack *extack) 415 + { 416 + struct nlattr *function_attr; 417 + bool msg_updated = false; 418 + int err; 419 + 420 + function_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PORT_FUNCTION); 421 + if (!function_attr) 422 + return -EMSGSIZE; 423 + 424 + err = devlink_port_fn_hw_addr_fill(port, msg, extack, &msg_updated); 425 + if (err) 426 + goto out; 427 + err = devlink_port_fn_caps_fill(port, msg, extack, &msg_updated); 428 + if (err) 429 + goto out; 430 + err = devlink_port_fn_state_fill(port, msg, extack, &msg_updated); 431 + out: 432 + if (err || !msg_updated) 433 + nla_nest_cancel(msg, function_attr); 434 + else 435 + nla_nest_end(msg, function_attr); 436 + return err; 437 + } 438 + 439 + static int devlink_nl_port_fill(struct sk_buff *msg, 440 + struct devlink_port *devlink_port, 441 + enum devlink_command cmd, u32 portid, u32 seq, 442 + int flags, struct netlink_ext_ack *extack) 443 + { 444 + struct devlink *devlink = devlink_port->devlink; 445 + void *hdr; 446 + 447 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 448 + if (!hdr) 449 + return -EMSGSIZE; 450 + 451 + if (devlink_nl_put_handle(msg, devlink)) 452 + goto nla_put_failure; 453 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 454 + goto nla_put_failure; 455 + 456 + spin_lock_bh(&devlink_port->type_lock); 457 + if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 458 + goto nla_put_failure_type_locked; 459 + if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 460 + nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 461 + devlink_port->desired_type)) 462 + goto nla_put_failure_type_locked; 463 + if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 464 + if (devlink_port->type_eth.netdev && 465 + (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 466 + devlink_port->type_eth.ifindex) || 467 + nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 468 + devlink_port->type_eth.ifname))) 469 + goto nla_put_failure_type_locked; 470 + } 471 + if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 472 + struct ib_device *ibdev = devlink_port->type_ib.ibdev; 473 + 474 + if (ibdev && 475 + nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 476 + ibdev->name)) 477 + goto nla_put_failure_type_locked; 478 + } 479 + spin_unlock_bh(&devlink_port->type_lock); 480 + if (devlink_nl_port_attrs_put(msg, devlink_port)) 481 + goto nla_put_failure; 482 + if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack)) 483 + goto nla_put_failure; 484 + if (devlink_port->linecard && 485 + nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, 486 + devlink_port->linecard->index)) 487 + goto nla_put_failure; 488 + 489 + genlmsg_end(msg, hdr); 490 + return 0; 491 + 492 + nla_put_failure_type_locked: 493 + spin_unlock_bh(&devlink_port->type_lock); 494 + nla_put_failure: 495 + genlmsg_cancel(msg, hdr); 496 + return -EMSGSIZE; 497 + } 498 + 499 + static void devlink_port_notify(struct devlink_port *devlink_port, 500 + enum devlink_command cmd) 501 + { 502 + struct devlink *devlink = devlink_port->devlink; 503 + struct sk_buff *msg; 504 + int err; 505 + 506 + WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 507 + 508 + if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 509 + return; 510 + 511 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 512 + if (!msg) 513 + return; 514 + 515 + err = devlink_nl_port_fill(msg, devlink_port, cmd, 0, 0, 0, NULL); 516 + if (err) { 517 + nlmsg_free(msg); 518 + return; 519 + } 520 + 521 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg, 522 + 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 523 + } 524 + 525 + static void devlink_ports_notify(struct devlink *devlink, 526 + enum devlink_command cmd) 527 + { 528 + struct devlink_port *devlink_port; 529 + unsigned long port_index; 530 + 531 + xa_for_each(&devlink->ports, port_index, devlink_port) 532 + devlink_port_notify(devlink_port, cmd); 533 + } 534 + 535 + void devlink_ports_notify_register(struct devlink *devlink) 536 + { 537 + devlink_ports_notify(devlink, DEVLINK_CMD_PORT_NEW); 538 + } 539 + 540 + void devlink_ports_notify_unregister(struct devlink *devlink) 541 + { 542 + devlink_ports_notify(devlink, DEVLINK_CMD_PORT_DEL); 543 + } 544 + 545 + int devlink_nl_port_get_doit(struct sk_buff *skb, struct genl_info *info) 546 + { 547 + struct devlink_port *devlink_port = info->user_ptr[1]; 548 + struct sk_buff *msg; 549 + int err; 550 + 551 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 552 + if (!msg) 553 + return -ENOMEM; 554 + 555 + err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_PORT_NEW, 556 + info->snd_portid, info->snd_seq, 0, 557 + info->extack); 558 + if (err) { 559 + nlmsg_free(msg); 560 + return err; 561 + } 562 + 563 + return genlmsg_reply(msg, info); 564 + } 565 + 566 + static int 567 + devlink_nl_port_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 568 + struct netlink_callback *cb, int flags) 569 + { 570 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 571 + struct devlink_port *devlink_port; 572 + unsigned long port_index; 573 + int err = 0; 574 + 575 + xa_for_each_start(&devlink->ports, port_index, devlink_port, state->idx) { 576 + err = devlink_nl_port_fill(msg, devlink_port, 577 + DEVLINK_CMD_NEW, 578 + NETLINK_CB(cb->skb).portid, 579 + cb->nlh->nlmsg_seq, flags, 580 + cb->extack); 581 + if (err) { 582 + state->idx = port_index; 583 + break; 584 + } 585 + } 586 + 587 + return err; 588 + } 589 + 590 + int devlink_nl_port_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 591 + { 592 + return devlink_nl_dumpit(skb, cb, devlink_nl_port_get_dump_one); 593 + } 594 + 595 + static int devlink_port_type_set(struct devlink_port *devlink_port, 596 + enum devlink_port_type port_type) 597 + 598 + { 599 + int err; 600 + 601 + if (!devlink_port->ops->port_type_set) 602 + return -EOPNOTSUPP; 603 + 604 + if (port_type == devlink_port->type) 605 + return 0; 606 + 607 + err = devlink_port->ops->port_type_set(devlink_port, port_type); 608 + if (err) 609 + return err; 610 + 611 + devlink_port->desired_type = port_type; 612 + devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 613 + return 0; 614 + } 615 + 616 + static int devlink_port_function_hw_addr_set(struct devlink_port *port, 617 + const struct nlattr *attr, 618 + struct netlink_ext_ack *extack) 619 + { 620 + const u8 *hw_addr; 621 + int hw_addr_len; 622 + 623 + hw_addr = nla_data(attr); 624 + hw_addr_len = nla_len(attr); 625 + if (hw_addr_len > MAX_ADDR_LEN) { 626 + NL_SET_ERR_MSG(extack, "Port function hardware address too long"); 627 + return -EINVAL; 628 + } 629 + if (port->type == DEVLINK_PORT_TYPE_ETH) { 630 + if (hw_addr_len != ETH_ALEN) { 631 + NL_SET_ERR_MSG(extack, "Address must be 6 bytes for Ethernet device"); 632 + return -EINVAL; 633 + } 634 + if (!is_unicast_ether_addr(hw_addr)) { 635 + NL_SET_ERR_MSG(extack, "Non-unicast hardware address unsupported"); 636 + return -EINVAL; 637 + } 638 + } 639 + 640 + return port->ops->port_fn_hw_addr_set(port, hw_addr, hw_addr_len, 641 + extack); 642 + } 643 + 644 + static int devlink_port_fn_state_set(struct devlink_port *port, 645 + const struct nlattr *attr, 646 + struct netlink_ext_ack *extack) 647 + { 648 + enum devlink_port_fn_state state; 649 + 650 + state = nla_get_u8(attr); 651 + return port->ops->port_fn_state_set(port, state, extack); 652 + } 653 + 654 + static int devlink_port_function_validate(struct devlink_port *devlink_port, 655 + struct nlattr **tb, 656 + struct netlink_ext_ack *extack) 657 + { 658 + const struct devlink_port_ops *ops = devlink_port->ops; 659 + struct nlattr *attr; 660 + 661 + if (tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] && 662 + !ops->port_fn_hw_addr_set) { 663 + NL_SET_ERR_MSG_ATTR(extack, tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR], 664 + "Port doesn't support function attributes"); 665 + return -EOPNOTSUPP; 666 + } 667 + if (tb[DEVLINK_PORT_FN_ATTR_STATE] && !ops->port_fn_state_set) { 668 + NL_SET_ERR_MSG_ATTR(extack, tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR], 669 + "Function does not support state setting"); 670 + return -EOPNOTSUPP; 671 + } 672 + attr = tb[DEVLINK_PORT_FN_ATTR_CAPS]; 673 + if (attr) { 674 + struct nla_bitfield32 caps; 675 + 676 + caps = nla_get_bitfield32(attr); 677 + if (caps.selector & DEVLINK_PORT_FN_CAP_ROCE && 678 + !ops->port_fn_roce_set) { 679 + NL_SET_ERR_MSG_ATTR(extack, attr, 680 + "Port doesn't support RoCE function attribute"); 681 + return -EOPNOTSUPP; 682 + } 683 + if (caps.selector & DEVLINK_PORT_FN_CAP_MIGRATABLE) { 684 + if (!ops->port_fn_migratable_set) { 685 + NL_SET_ERR_MSG_ATTR(extack, attr, 686 + "Port doesn't support migratable function attribute"); 687 + return -EOPNOTSUPP; 688 + } 689 + if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) { 690 + NL_SET_ERR_MSG_ATTR(extack, attr, 691 + "migratable function attribute supported for VFs only"); 692 + return -EOPNOTSUPP; 693 + } 694 + } 695 + if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO) { 696 + if (!ops->port_fn_ipsec_crypto_set) { 697 + NL_SET_ERR_MSG_ATTR(extack, attr, 698 + "Port doesn't support ipsec_crypto function attribute"); 699 + return -EOPNOTSUPP; 700 + } 701 + if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) { 702 + NL_SET_ERR_MSG_ATTR(extack, attr, 703 + "ipsec_crypto function attribute supported for VFs only"); 704 + return -EOPNOTSUPP; 705 + } 706 + } 707 + if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_PACKET) { 708 + if (!ops->port_fn_ipsec_packet_set) { 709 + NL_SET_ERR_MSG_ATTR(extack, attr, 710 + "Port doesn't support ipsec_packet function attribute"); 711 + return -EOPNOTSUPP; 712 + } 713 + if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) { 714 + NL_SET_ERR_MSG_ATTR(extack, attr, 715 + "ipsec_packet function attribute supported for VFs only"); 716 + return -EOPNOTSUPP; 717 + } 718 + } 719 + } 720 + return 0; 721 + } 722 + 723 + static int devlink_port_function_set(struct devlink_port *port, 724 + const struct nlattr *attr, 725 + struct netlink_ext_ack *extack) 726 + { 727 + struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1]; 728 + int err; 729 + 730 + err = nla_parse_nested(tb, DEVLINK_PORT_FUNCTION_ATTR_MAX, attr, 731 + devlink_function_nl_policy, extack); 732 + if (err < 0) { 733 + NL_SET_ERR_MSG(extack, "Fail to parse port function attributes"); 734 + return err; 735 + } 736 + 737 + err = devlink_port_function_validate(port, tb, extack); 738 + if (err) 739 + return err; 740 + 741 + attr = tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]; 742 + if (attr) { 743 + err = devlink_port_function_hw_addr_set(port, attr, extack); 744 + if (err) 745 + return err; 746 + } 747 + 748 + attr = tb[DEVLINK_PORT_FN_ATTR_CAPS]; 749 + if (attr) { 750 + err = devlink_port_fn_caps_set(port, attr, extack); 751 + if (err) 752 + return err; 753 + } 754 + 755 + /* Keep this as the last function attribute set, so that when 756 + * multiple port function attributes are set along with state, 757 + * Those can be applied first before activating the state. 758 + */ 759 + attr = tb[DEVLINK_PORT_FN_ATTR_STATE]; 760 + if (attr) 761 + err = devlink_port_fn_state_set(port, attr, extack); 762 + 763 + if (!err) 764 + devlink_port_notify(port, DEVLINK_CMD_PORT_NEW); 765 + return err; 766 + } 767 + 768 + int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, struct genl_info *info) 769 + { 770 + struct devlink_port *devlink_port = info->user_ptr[1]; 771 + int err; 772 + 773 + if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 774 + enum devlink_port_type port_type; 775 + 776 + port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 777 + err = devlink_port_type_set(devlink_port, port_type); 778 + if (err) 779 + return err; 780 + } 781 + 782 + if (info->attrs[DEVLINK_ATTR_PORT_FUNCTION]) { 783 + struct nlattr *attr = info->attrs[DEVLINK_ATTR_PORT_FUNCTION]; 784 + struct netlink_ext_ack *extack = info->extack; 785 + 786 + err = devlink_port_function_set(devlink_port, attr, extack); 787 + if (err) 788 + return err; 789 + } 790 + 791 + return 0; 792 + } 793 + 794 + int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, struct genl_info *info) 795 + { 796 + struct devlink_port *devlink_port = info->user_ptr[1]; 797 + struct devlink *devlink = info->user_ptr[0]; 798 + u32 count; 799 + 800 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PORT_SPLIT_COUNT)) 801 + return -EINVAL; 802 + if (!devlink_port->ops->port_split) 803 + return -EOPNOTSUPP; 804 + 805 + count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 806 + 807 + if (!devlink_port->attrs.splittable) { 808 + /* Split ports cannot be split. */ 809 + if (devlink_port->attrs.split) 810 + NL_SET_ERR_MSG(info->extack, "Port cannot be split further"); 811 + else 812 + NL_SET_ERR_MSG(info->extack, "Port cannot be split"); 813 + return -EINVAL; 814 + } 815 + 816 + if (count < 2 || !is_power_of_2(count) || count > devlink_port->attrs.lanes) { 817 + NL_SET_ERR_MSG(info->extack, "Invalid split count"); 818 + return -EINVAL; 819 + } 820 + 821 + return devlink_port->ops->port_split(devlink, devlink_port, count, 822 + info->extack); 823 + } 824 + 825 + int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 826 + struct genl_info *info) 827 + { 828 + struct devlink_port *devlink_port = info->user_ptr[1]; 829 + struct devlink *devlink = info->user_ptr[0]; 830 + 831 + if (!devlink_port->ops->port_unsplit) 832 + return -EOPNOTSUPP; 833 + return devlink_port->ops->port_unsplit(devlink, devlink_port, info->extack); 834 + } 835 + 836 + int devlink_nl_cmd_port_new_doit(struct sk_buff *skb, struct genl_info *info) 837 + { 838 + struct netlink_ext_ack *extack = info->extack; 839 + struct devlink_port_new_attrs new_attrs = {}; 840 + struct devlink *devlink = info->user_ptr[0]; 841 + struct devlink_port *devlink_port; 842 + struct sk_buff *msg; 843 + int err; 844 + 845 + if (!devlink->ops->port_new) 846 + return -EOPNOTSUPP; 847 + 848 + if (!info->attrs[DEVLINK_ATTR_PORT_FLAVOUR] || 849 + !info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]) { 850 + NL_SET_ERR_MSG(extack, "Port flavour or PCI PF are not specified"); 851 + return -EINVAL; 852 + } 853 + new_attrs.flavour = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_FLAVOUR]); 854 + new_attrs.pfnum = 855 + nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]); 856 + 857 + if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 858 + /* Port index of the new port being created by driver. */ 859 + new_attrs.port_index = 860 + nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 861 + new_attrs.port_index_valid = true; 862 + } 863 + if (info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]) { 864 + new_attrs.controller = 865 + nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]); 866 + new_attrs.controller_valid = true; 867 + } 868 + if (new_attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF && 869 + info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]) { 870 + new_attrs.sfnum = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]); 871 + new_attrs.sfnum_valid = true; 872 + } 873 + 874 + err = devlink->ops->port_new(devlink, &new_attrs, 875 + extack, &devlink_port); 876 + if (err) 877 + return err; 878 + 879 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 880 + if (!msg) { 881 + err = -ENOMEM; 882 + goto err_out_port_del; 883 + } 884 + err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_NEW, 885 + info->snd_portid, info->snd_seq, 0, NULL); 886 + if (WARN_ON_ONCE(err)) 887 + goto err_out_msg_free; 888 + err = genlmsg_reply(msg, info); 889 + if (err) 890 + goto err_out_port_del; 891 + return 0; 892 + 893 + err_out_msg_free: 894 + nlmsg_free(msg); 895 + err_out_port_del: 896 + devlink_port->ops->port_del(devlink, devlink_port, NULL); 897 + return err; 898 + } 899 + 900 + int devlink_nl_cmd_port_del_doit(struct sk_buff *skb, struct genl_info *info) 901 + { 902 + struct devlink_port *devlink_port = info->user_ptr[1]; 903 + struct netlink_ext_ack *extack = info->extack; 904 + struct devlink *devlink = info->user_ptr[0]; 905 + 906 + if (!devlink_port->ops->port_del) 907 + return -EOPNOTSUPP; 908 + 909 + return devlink_port->ops->port_del(devlink, devlink_port, extack); 910 + } 911 + 912 + static void devlink_port_type_warn(struct work_struct *work) 913 + { 914 + struct devlink_port *port = container_of(to_delayed_work(work), 915 + struct devlink_port, 916 + type_warn_dw); 917 + dev_warn(port->devlink->dev, "Type was not set for devlink port."); 918 + } 919 + 920 + static bool devlink_port_type_should_warn(struct devlink_port *devlink_port) 921 + { 922 + /* Ignore CPU and DSA flavours. */ 923 + return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU && 924 + devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA && 925 + devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_UNUSED; 926 + } 927 + 928 + #define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600) 929 + 930 + static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port) 931 + { 932 + if (!devlink_port_type_should_warn(devlink_port)) 933 + return; 934 + /* Schedule a work to WARN in case driver does not set port 935 + * type within timeout. 936 + */ 937 + schedule_delayed_work(&devlink_port->type_warn_dw, 938 + DEVLINK_PORT_TYPE_WARN_TIMEOUT); 939 + } 940 + 941 + static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port) 942 + { 943 + if (!devlink_port_type_should_warn(devlink_port)) 944 + return; 945 + cancel_delayed_work_sync(&devlink_port->type_warn_dw); 946 + } 947 + 948 + /** 949 + * devlink_port_init() - Init devlink port 950 + * 951 + * @devlink: devlink 952 + * @devlink_port: devlink port 953 + * 954 + * Initialize essential stuff that is needed for functions 955 + * that may be called before devlink port registration. 956 + * Call to this function is optional and not needed 957 + * in case the driver does not use such functions. 958 + */ 959 + void devlink_port_init(struct devlink *devlink, 960 + struct devlink_port *devlink_port) 961 + { 962 + if (devlink_port->initialized) 963 + return; 964 + devlink_port->devlink = devlink; 965 + INIT_LIST_HEAD(&devlink_port->region_list); 966 + devlink_port->initialized = true; 967 + } 968 + EXPORT_SYMBOL_GPL(devlink_port_init); 969 + 970 + /** 971 + * devlink_port_fini() - Deinitialize devlink port 972 + * 973 + * @devlink_port: devlink port 974 + * 975 + * Deinitialize essential stuff that is in use for functions 976 + * that may be called after devlink port unregistration. 977 + * Call to this function is optional and not needed 978 + * in case the driver does not use such functions. 979 + */ 980 + void devlink_port_fini(struct devlink_port *devlink_port) 981 + { 982 + WARN_ON(!list_empty(&devlink_port->region_list)); 983 + } 984 + EXPORT_SYMBOL_GPL(devlink_port_fini); 985 + 986 + static const struct devlink_port_ops devlink_port_dummy_ops = {}; 987 + 988 + /** 989 + * devl_port_register_with_ops() - Register devlink port 990 + * 991 + * @devlink: devlink 992 + * @devlink_port: devlink port 993 + * @port_index: driver-specific numerical identifier of the port 994 + * @ops: port ops 995 + * 996 + * Register devlink port with provided port index. User can use 997 + * any indexing, even hw-related one. devlink_port structure 998 + * is convenient to be embedded inside user driver private structure. 999 + * Note that the caller should take care of zeroing the devlink_port 1000 + * structure. 1001 + */ 1002 + int devl_port_register_with_ops(struct devlink *devlink, 1003 + struct devlink_port *devlink_port, 1004 + unsigned int port_index, 1005 + const struct devlink_port_ops *ops) 1006 + { 1007 + int err; 1008 + 1009 + devl_assert_locked(devlink); 1010 + 1011 + ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 1012 + 1013 + devlink_port_init(devlink, devlink_port); 1014 + devlink_port->registered = true; 1015 + devlink_port->index = port_index; 1016 + devlink_port->ops = ops ? ops : &devlink_port_dummy_ops; 1017 + spin_lock_init(&devlink_port->type_lock); 1018 + INIT_LIST_HEAD(&devlink_port->reporter_list); 1019 + err = xa_insert(&devlink->ports, port_index, devlink_port, GFP_KERNEL); 1020 + if (err) { 1021 + devlink_port->registered = false; 1022 + return err; 1023 + } 1024 + 1025 + INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn); 1026 + devlink_port_type_warn_schedule(devlink_port); 1027 + devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 1028 + return 0; 1029 + } 1030 + EXPORT_SYMBOL_GPL(devl_port_register_with_ops); 1031 + 1032 + /** 1033 + * devlink_port_register_with_ops - Register devlink port 1034 + * 1035 + * @devlink: devlink 1036 + * @devlink_port: devlink port 1037 + * @port_index: driver-specific numerical identifier of the port 1038 + * @ops: port ops 1039 + * 1040 + * Register devlink port with provided port index. User can use 1041 + * any indexing, even hw-related one. devlink_port structure 1042 + * is convenient to be embedded inside user driver private structure. 1043 + * Note that the caller should take care of zeroing the devlink_port 1044 + * structure. 1045 + * 1046 + * Context: Takes and release devlink->lock <mutex>. 1047 + */ 1048 + int devlink_port_register_with_ops(struct devlink *devlink, 1049 + struct devlink_port *devlink_port, 1050 + unsigned int port_index, 1051 + const struct devlink_port_ops *ops) 1052 + { 1053 + int err; 1054 + 1055 + devl_lock(devlink); 1056 + err = devl_port_register_with_ops(devlink, devlink_port, 1057 + port_index, ops); 1058 + devl_unlock(devlink); 1059 + return err; 1060 + } 1061 + EXPORT_SYMBOL_GPL(devlink_port_register_with_ops); 1062 + 1063 + /** 1064 + * devl_port_unregister() - Unregister devlink port 1065 + * 1066 + * @devlink_port: devlink port 1067 + */ 1068 + void devl_port_unregister(struct devlink_port *devlink_port) 1069 + { 1070 + lockdep_assert_held(&devlink_port->devlink->lock); 1071 + WARN_ON(devlink_port->type != DEVLINK_PORT_TYPE_NOTSET); 1072 + 1073 + devlink_port_type_warn_cancel(devlink_port); 1074 + devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 1075 + xa_erase(&devlink_port->devlink->ports, devlink_port->index); 1076 + WARN_ON(!list_empty(&devlink_port->reporter_list)); 1077 + devlink_port->registered = false; 1078 + } 1079 + EXPORT_SYMBOL_GPL(devl_port_unregister); 1080 + 1081 + /** 1082 + * devlink_port_unregister - Unregister devlink port 1083 + * 1084 + * @devlink_port: devlink port 1085 + * 1086 + * Context: Takes and release devlink->lock <mutex>. 1087 + */ 1088 + void devlink_port_unregister(struct devlink_port *devlink_port) 1089 + { 1090 + struct devlink *devlink = devlink_port->devlink; 1091 + 1092 + devl_lock(devlink); 1093 + devl_port_unregister(devlink_port); 1094 + devl_unlock(devlink); 1095 + } 1096 + EXPORT_SYMBOL_GPL(devlink_port_unregister); 1097 + 1098 + static void devlink_port_type_netdev_checks(struct devlink_port *devlink_port, 1099 + struct net_device *netdev) 1100 + { 1101 + const struct net_device_ops *ops = netdev->netdev_ops; 1102 + 1103 + /* If driver registers devlink port, it should set devlink port 1104 + * attributes accordingly so the compat functions are called 1105 + * and the original ops are not used. 1106 + */ 1107 + if (ops->ndo_get_phys_port_name) { 1108 + /* Some drivers use the same set of ndos for netdevs 1109 + * that have devlink_port registered and also for 1110 + * those who don't. Make sure that ndo_get_phys_port_name 1111 + * returns -EOPNOTSUPP here in case it is defined. 1112 + * Warn if not. 1113 + */ 1114 + char name[IFNAMSIZ]; 1115 + int err; 1116 + 1117 + err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name)); 1118 + WARN_ON(err != -EOPNOTSUPP); 1119 + } 1120 + if (ops->ndo_get_port_parent_id) { 1121 + /* Some drivers use the same set of ndos for netdevs 1122 + * that have devlink_port registered and also for 1123 + * those who don't. Make sure that ndo_get_port_parent_id 1124 + * returns -EOPNOTSUPP here in case it is defined. 1125 + * Warn if not. 1126 + */ 1127 + struct netdev_phys_item_id ppid; 1128 + int err; 1129 + 1130 + err = ops->ndo_get_port_parent_id(netdev, &ppid); 1131 + WARN_ON(err != -EOPNOTSUPP); 1132 + } 1133 + } 1134 + 1135 + static void __devlink_port_type_set(struct devlink_port *devlink_port, 1136 + enum devlink_port_type type, 1137 + void *type_dev) 1138 + { 1139 + struct net_device *netdev = type_dev; 1140 + 1141 + ASSERT_DEVLINK_PORT_REGISTERED(devlink_port); 1142 + 1143 + if (type == DEVLINK_PORT_TYPE_NOTSET) { 1144 + devlink_port_type_warn_schedule(devlink_port); 1145 + } else { 1146 + devlink_port_type_warn_cancel(devlink_port); 1147 + if (type == DEVLINK_PORT_TYPE_ETH && netdev) 1148 + devlink_port_type_netdev_checks(devlink_port, netdev); 1149 + } 1150 + 1151 + spin_lock_bh(&devlink_port->type_lock); 1152 + devlink_port->type = type; 1153 + switch (type) { 1154 + case DEVLINK_PORT_TYPE_ETH: 1155 + devlink_port->type_eth.netdev = netdev; 1156 + if (netdev) { 1157 + ASSERT_RTNL(); 1158 + devlink_port->type_eth.ifindex = netdev->ifindex; 1159 + BUILD_BUG_ON(sizeof(devlink_port->type_eth.ifname) != 1160 + sizeof(netdev->name)); 1161 + strcpy(devlink_port->type_eth.ifname, netdev->name); 1162 + } 1163 + break; 1164 + case DEVLINK_PORT_TYPE_IB: 1165 + devlink_port->type_ib.ibdev = type_dev; 1166 + break; 1167 + default: 1168 + break; 1169 + } 1170 + spin_unlock_bh(&devlink_port->type_lock); 1171 + devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 1172 + } 1173 + 1174 + /** 1175 + * devlink_port_type_eth_set - Set port type to Ethernet 1176 + * 1177 + * @devlink_port: devlink port 1178 + * 1179 + * If driver is calling this, most likely it is doing something wrong. 1180 + */ 1181 + void devlink_port_type_eth_set(struct devlink_port *devlink_port) 1182 + { 1183 + dev_warn(devlink_port->devlink->dev, 1184 + "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n", 1185 + devlink_port->index); 1186 + __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, NULL); 1187 + } 1188 + EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 1189 + 1190 + /** 1191 + * devlink_port_type_ib_set - Set port type to InfiniBand 1192 + * 1193 + * @devlink_port: devlink port 1194 + * @ibdev: related IB device 1195 + */ 1196 + void devlink_port_type_ib_set(struct devlink_port *devlink_port, 1197 + struct ib_device *ibdev) 1198 + { 1199 + __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev); 1200 + } 1201 + EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 1202 + 1203 + /** 1204 + * devlink_port_type_clear - Clear port type 1205 + * 1206 + * @devlink_port: devlink port 1207 + * 1208 + * If driver is calling this for clearing Ethernet type, most likely 1209 + * it is doing something wrong. 1210 + */ 1211 + void devlink_port_type_clear(struct devlink_port *devlink_port) 1212 + { 1213 + if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) 1214 + dev_warn(devlink_port->devlink->dev, 1215 + "devlink port type for port %d cleared without a software interface reference, device type not supported by the kernel?\n", 1216 + devlink_port->index); 1217 + __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL); 1218 + } 1219 + EXPORT_SYMBOL_GPL(devlink_port_type_clear); 1220 + 1221 + int devlink_port_netdevice_event(struct notifier_block *nb, 1222 + unsigned long event, void *ptr) 1223 + { 1224 + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 1225 + struct devlink_port *devlink_port = netdev->devlink_port; 1226 + struct devlink *devlink; 1227 + 1228 + if (!devlink_port) 1229 + return NOTIFY_OK; 1230 + devlink = devlink_port->devlink; 1231 + 1232 + switch (event) { 1233 + case NETDEV_POST_INIT: 1234 + /* Set the type but not netdev pointer. It is going to be set 1235 + * later on by NETDEV_REGISTER event. Happens once during 1236 + * netdevice register 1237 + */ 1238 + __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, 1239 + NULL); 1240 + break; 1241 + case NETDEV_REGISTER: 1242 + case NETDEV_CHANGENAME: 1243 + if (devlink_net(devlink) != dev_net(netdev)) 1244 + return NOTIFY_OK; 1245 + /* Set the netdev on top of previously set type. Note this 1246 + * event happens also during net namespace change so here 1247 + * we take into account netdev pointer appearing in this 1248 + * namespace. 1249 + */ 1250 + __devlink_port_type_set(devlink_port, devlink_port->type, 1251 + netdev); 1252 + break; 1253 + case NETDEV_UNREGISTER: 1254 + if (devlink_net(devlink) != dev_net(netdev)) 1255 + return NOTIFY_OK; 1256 + /* Clear netdev pointer, but not the type. This event happens 1257 + * also during net namespace change so we need to clear 1258 + * pointer to netdev that is going to another net namespace. 1259 + */ 1260 + __devlink_port_type_set(devlink_port, devlink_port->type, 1261 + NULL); 1262 + break; 1263 + case NETDEV_PRE_UNINIT: 1264 + /* Clear the type and the netdev pointer. Happens one during 1265 + * netdevice unregister. 1266 + */ 1267 + __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, 1268 + NULL); 1269 + break; 1270 + } 1271 + 1272 + return NOTIFY_OK; 1273 + } 1274 + 1275 + static int __devlink_port_attrs_set(struct devlink_port *devlink_port, 1276 + enum devlink_port_flavour flavour) 1277 + { 1278 + struct devlink_port_attrs *attrs = &devlink_port->attrs; 1279 + 1280 + devlink_port->attrs_set = true; 1281 + attrs->flavour = flavour; 1282 + if (attrs->switch_id.id_len) { 1283 + devlink_port->switch_port = true; 1284 + if (WARN_ON(attrs->switch_id.id_len > MAX_PHYS_ITEM_ID_LEN)) 1285 + attrs->switch_id.id_len = MAX_PHYS_ITEM_ID_LEN; 1286 + } else { 1287 + devlink_port->switch_port = false; 1288 + } 1289 + return 0; 1290 + } 1291 + 1292 + /** 1293 + * devlink_port_attrs_set - Set port attributes 1294 + * 1295 + * @devlink_port: devlink port 1296 + * @attrs: devlink port attrs 1297 + */ 1298 + void devlink_port_attrs_set(struct devlink_port *devlink_port, 1299 + struct devlink_port_attrs *attrs) 1300 + { 1301 + int ret; 1302 + 1303 + ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 1304 + 1305 + devlink_port->attrs = *attrs; 1306 + ret = __devlink_port_attrs_set(devlink_port, attrs->flavour); 1307 + if (ret) 1308 + return; 1309 + WARN_ON(attrs->splittable && attrs->split); 1310 + } 1311 + EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 1312 + 1313 + /** 1314 + * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes 1315 + * 1316 + * @devlink_port: devlink port 1317 + * @controller: associated controller number for the devlink port instance 1318 + * @pf: associated PF for the devlink port instance 1319 + * @external: indicates if the port is for an external controller 1320 + */ 1321 + void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller, 1322 + u16 pf, bool external) 1323 + { 1324 + struct devlink_port_attrs *attrs = &devlink_port->attrs; 1325 + int ret; 1326 + 1327 + ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 1328 + 1329 + ret = __devlink_port_attrs_set(devlink_port, 1330 + DEVLINK_PORT_FLAVOUR_PCI_PF); 1331 + if (ret) 1332 + return; 1333 + attrs->pci_pf.controller = controller; 1334 + attrs->pci_pf.pf = pf; 1335 + attrs->pci_pf.external = external; 1336 + } 1337 + EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set); 1338 + 1339 + /** 1340 + * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes 1341 + * 1342 + * @devlink_port: devlink port 1343 + * @controller: associated controller number for the devlink port instance 1344 + * @pf: associated PF for the devlink port instance 1345 + * @vf: associated VF of a PF for the devlink port instance 1346 + * @external: indicates if the port is for an external controller 1347 + */ 1348 + void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller, 1349 + u16 pf, u16 vf, bool external) 1350 + { 1351 + struct devlink_port_attrs *attrs = &devlink_port->attrs; 1352 + int ret; 1353 + 1354 + ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 1355 + 1356 + ret = __devlink_port_attrs_set(devlink_port, 1357 + DEVLINK_PORT_FLAVOUR_PCI_VF); 1358 + if (ret) 1359 + return; 1360 + attrs->pci_vf.controller = controller; 1361 + attrs->pci_vf.pf = pf; 1362 + attrs->pci_vf.vf = vf; 1363 + attrs->pci_vf.external = external; 1364 + } 1365 + EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set); 1366 + 1367 + /** 1368 + * devlink_port_attrs_pci_sf_set - Set PCI SF port attributes 1369 + * 1370 + * @devlink_port: devlink port 1371 + * @controller: associated controller number for the devlink port instance 1372 + * @pf: associated PF for the devlink port instance 1373 + * @sf: associated SF of a PF for the devlink port instance 1374 + * @external: indicates if the port is for an external controller 1375 + */ 1376 + void devlink_port_attrs_pci_sf_set(struct devlink_port *devlink_port, u32 controller, 1377 + u16 pf, u32 sf, bool external) 1378 + { 1379 + struct devlink_port_attrs *attrs = &devlink_port->attrs; 1380 + int ret; 1381 + 1382 + ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 1383 + 1384 + ret = __devlink_port_attrs_set(devlink_port, 1385 + DEVLINK_PORT_FLAVOUR_PCI_SF); 1386 + if (ret) 1387 + return; 1388 + attrs->pci_sf.controller = controller; 1389 + attrs->pci_sf.pf = pf; 1390 + attrs->pci_sf.sf = sf; 1391 + attrs->pci_sf.external = external; 1392 + } 1393 + EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_sf_set); 1394 + 1395 + /** 1396 + * devlink_port_linecard_set - Link port with a linecard 1397 + * 1398 + * @devlink_port: devlink port 1399 + * @linecard: devlink linecard 1400 + */ 1401 + void devlink_port_linecard_set(struct devlink_port *devlink_port, 1402 + struct devlink_linecard *linecard) 1403 + { 1404 + ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port); 1405 + 1406 + devlink_port->linecard = linecard; 1407 + } 1408 + EXPORT_SYMBOL_GPL(devlink_port_linecard_set); 1409 + 1410 + static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, 1411 + char *name, size_t len) 1412 + { 1413 + struct devlink_port_attrs *attrs = &devlink_port->attrs; 1414 + int n = 0; 1415 + 1416 + if (!devlink_port->attrs_set) 1417 + return -EOPNOTSUPP; 1418 + 1419 + switch (attrs->flavour) { 1420 + case DEVLINK_PORT_FLAVOUR_PHYSICAL: 1421 + if (devlink_port->linecard) 1422 + n = snprintf(name, len, "l%u", 1423 + devlink_port->linecard->index); 1424 + if (n < len) 1425 + n += snprintf(name + n, len - n, "p%u", 1426 + attrs->phys.port_number); 1427 + if (n < len && attrs->split) 1428 + n += snprintf(name + n, len - n, "s%u", 1429 + attrs->phys.split_subport_number); 1430 + break; 1431 + case DEVLINK_PORT_FLAVOUR_CPU: 1432 + case DEVLINK_PORT_FLAVOUR_DSA: 1433 + case DEVLINK_PORT_FLAVOUR_UNUSED: 1434 + /* As CPU and DSA ports do not have a netdevice associated 1435 + * case should not ever happen. 1436 + */ 1437 + WARN_ON(1); 1438 + return -EINVAL; 1439 + case DEVLINK_PORT_FLAVOUR_PCI_PF: 1440 + if (attrs->pci_pf.external) { 1441 + n = snprintf(name, len, "c%u", attrs->pci_pf.controller); 1442 + if (n >= len) 1443 + return -EINVAL; 1444 + len -= n; 1445 + name += n; 1446 + } 1447 + n = snprintf(name, len, "pf%u", attrs->pci_pf.pf); 1448 + break; 1449 + case DEVLINK_PORT_FLAVOUR_PCI_VF: 1450 + if (attrs->pci_vf.external) { 1451 + n = snprintf(name, len, "c%u", attrs->pci_vf.controller); 1452 + if (n >= len) 1453 + return -EINVAL; 1454 + len -= n; 1455 + name += n; 1456 + } 1457 + n = snprintf(name, len, "pf%uvf%u", 1458 + attrs->pci_vf.pf, attrs->pci_vf.vf); 1459 + break; 1460 + case DEVLINK_PORT_FLAVOUR_PCI_SF: 1461 + if (attrs->pci_sf.external) { 1462 + n = snprintf(name, len, "c%u", attrs->pci_sf.controller); 1463 + if (n >= len) 1464 + return -EINVAL; 1465 + len -= n; 1466 + name += n; 1467 + } 1468 + n = snprintf(name, len, "pf%usf%u", attrs->pci_sf.pf, 1469 + attrs->pci_sf.sf); 1470 + break; 1471 + case DEVLINK_PORT_FLAVOUR_VIRTUAL: 1472 + return -EOPNOTSUPP; 1473 + } 1474 + 1475 + if (n >= len) 1476 + return -EINVAL; 1477 + 1478 + return 0; 1479 + } 1480 + 1481 + int devlink_compat_phys_port_name_get(struct net_device *dev, 1482 + char *name, size_t len) 1483 + { 1484 + struct devlink_port *devlink_port; 1485 + 1486 + /* RTNL mutex is held here which ensures that devlink_port 1487 + * instance cannot disappear in the middle. No need to take 1488 + * any devlink lock as only permanent values are accessed. 1489 + */ 1490 + ASSERT_RTNL(); 1491 + 1492 + devlink_port = dev->devlink_port; 1493 + if (!devlink_port) 1494 + return -EOPNOTSUPP; 1495 + 1496 + return __devlink_port_phys_port_name_get(devlink_port, name, len); 1497 + } 1498 + 1499 + int devlink_compat_switch_id_get(struct net_device *dev, 1500 + struct netdev_phys_item_id *ppid) 1501 + { 1502 + struct devlink_port *devlink_port; 1503 + 1504 + /* Caller must hold RTNL mutex or reference to dev, which ensures that 1505 + * devlink_port instance cannot disappear in the middle. No need to take 1506 + * any devlink lock as only permanent values are accessed. 1507 + */ 1508 + devlink_port = dev->devlink_port; 1509 + if (!devlink_port || !devlink_port->switch_port) 1510 + return -EOPNOTSUPP; 1511 + 1512 + memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid)); 1513 + 1514 + return 0; 1515 + }
+722
net/devlink/rate.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + static inline bool 10 + devlink_rate_is_leaf(struct devlink_rate *devlink_rate) 11 + { 12 + return devlink_rate->type == DEVLINK_RATE_TYPE_LEAF; 13 + } 14 + 15 + static inline bool 16 + devlink_rate_is_node(struct devlink_rate *devlink_rate) 17 + { 18 + return devlink_rate->type == DEVLINK_RATE_TYPE_NODE; 19 + } 20 + 21 + static struct devlink_rate * 22 + devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info) 23 + { 24 + struct devlink_rate *devlink_rate; 25 + struct devlink_port *devlink_port; 26 + 27 + devlink_port = devlink_port_get_from_attrs(devlink, info->attrs); 28 + if (IS_ERR(devlink_port)) 29 + return ERR_CAST(devlink_port); 30 + devlink_rate = devlink_port->devlink_rate; 31 + return devlink_rate ?: ERR_PTR(-ENODEV); 32 + } 33 + 34 + static struct devlink_rate * 35 + devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name) 36 + { 37 + static struct devlink_rate *devlink_rate; 38 + 39 + list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 40 + if (devlink_rate_is_node(devlink_rate) && 41 + !strcmp(node_name, devlink_rate->name)) 42 + return devlink_rate; 43 + } 44 + return ERR_PTR(-ENODEV); 45 + } 46 + 47 + static struct devlink_rate * 48 + devlink_rate_node_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) 49 + { 50 + const char *rate_node_name; 51 + size_t len; 52 + 53 + if (!attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 54 + return ERR_PTR(-EINVAL); 55 + rate_node_name = nla_data(attrs[DEVLINK_ATTR_RATE_NODE_NAME]); 56 + len = strlen(rate_node_name); 57 + /* Name cannot be empty or decimal number */ 58 + if (!len || strspn(rate_node_name, "0123456789") == len) 59 + return ERR_PTR(-EINVAL); 60 + 61 + return devlink_rate_node_get_by_name(devlink, rate_node_name); 62 + } 63 + 64 + static struct devlink_rate * 65 + devlink_rate_node_get_from_info(struct devlink *devlink, struct genl_info *info) 66 + { 67 + return devlink_rate_node_get_from_attrs(devlink, info->attrs); 68 + } 69 + 70 + static struct devlink_rate * 71 + devlink_rate_get_from_info(struct devlink *devlink, struct genl_info *info) 72 + { 73 + struct nlattr **attrs = info->attrs; 74 + 75 + if (attrs[DEVLINK_ATTR_PORT_INDEX]) 76 + return devlink_rate_leaf_get_from_info(devlink, info); 77 + else if (attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 78 + return devlink_rate_node_get_from_info(devlink, info); 79 + else 80 + return ERR_PTR(-EINVAL); 81 + } 82 + 83 + static int devlink_nl_rate_fill(struct sk_buff *msg, 84 + struct devlink_rate *devlink_rate, 85 + enum devlink_command cmd, u32 portid, u32 seq, 86 + int flags, struct netlink_ext_ack *extack) 87 + { 88 + struct devlink *devlink = devlink_rate->devlink; 89 + void *hdr; 90 + 91 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 92 + if (!hdr) 93 + return -EMSGSIZE; 94 + 95 + if (devlink_nl_put_handle(msg, devlink)) 96 + goto nla_put_failure; 97 + 98 + if (nla_put_u16(msg, DEVLINK_ATTR_RATE_TYPE, devlink_rate->type)) 99 + goto nla_put_failure; 100 + 101 + if (devlink_rate_is_leaf(devlink_rate)) { 102 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 103 + devlink_rate->devlink_port->index)) 104 + goto nla_put_failure; 105 + } else if (devlink_rate_is_node(devlink_rate)) { 106 + if (nla_put_string(msg, DEVLINK_ATTR_RATE_NODE_NAME, 107 + devlink_rate->name)) 108 + goto nla_put_failure; 109 + } 110 + 111 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE, 112 + devlink_rate->tx_share, DEVLINK_ATTR_PAD)) 113 + goto nla_put_failure; 114 + 115 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_MAX, 116 + devlink_rate->tx_max, DEVLINK_ATTR_PAD)) 117 + goto nla_put_failure; 118 + 119 + if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_PRIORITY, 120 + devlink_rate->tx_priority)) 121 + goto nla_put_failure; 122 + 123 + if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_WEIGHT, 124 + devlink_rate->tx_weight)) 125 + goto nla_put_failure; 126 + 127 + if (devlink_rate->parent) 128 + if (nla_put_string(msg, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, 129 + devlink_rate->parent->name)) 130 + goto nla_put_failure; 131 + 132 + genlmsg_end(msg, hdr); 133 + return 0; 134 + 135 + nla_put_failure: 136 + genlmsg_cancel(msg, hdr); 137 + return -EMSGSIZE; 138 + } 139 + 140 + static void devlink_rate_notify(struct devlink_rate *devlink_rate, 141 + enum devlink_command cmd) 142 + { 143 + struct devlink *devlink = devlink_rate->devlink; 144 + struct sk_buff *msg; 145 + int err; 146 + 147 + WARN_ON(cmd != DEVLINK_CMD_RATE_NEW && cmd != DEVLINK_CMD_RATE_DEL); 148 + 149 + if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 150 + return; 151 + 152 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 153 + if (!msg) 154 + return; 155 + 156 + err = devlink_nl_rate_fill(msg, devlink_rate, cmd, 0, 0, 0, NULL); 157 + if (err) { 158 + nlmsg_free(msg); 159 + return; 160 + } 161 + 162 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg, 163 + 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 164 + } 165 + 166 + void devlink_rates_notify_register(struct devlink *devlink) 167 + { 168 + struct devlink_rate *rate_node; 169 + 170 + list_for_each_entry(rate_node, &devlink->rate_list, list) 171 + devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 172 + } 173 + 174 + void devlink_rates_notify_unregister(struct devlink *devlink) 175 + { 176 + struct devlink_rate *rate_node; 177 + 178 + list_for_each_entry_reverse(rate_node, &devlink->rate_list, list) 179 + devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 180 + } 181 + 182 + static int 183 + devlink_nl_rate_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 184 + struct netlink_callback *cb, int flags) 185 + { 186 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 187 + struct devlink_rate *devlink_rate; 188 + int idx = 0; 189 + int err = 0; 190 + 191 + list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 192 + enum devlink_command cmd = DEVLINK_CMD_RATE_NEW; 193 + u32 id = NETLINK_CB(cb->skb).portid; 194 + 195 + if (idx < state->idx) { 196 + idx++; 197 + continue; 198 + } 199 + err = devlink_nl_rate_fill(msg, devlink_rate, cmd, id, 200 + cb->nlh->nlmsg_seq, flags, NULL); 201 + if (err) { 202 + state->idx = idx; 203 + break; 204 + } 205 + idx++; 206 + } 207 + 208 + return err; 209 + } 210 + 211 + int devlink_nl_rate_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 212 + { 213 + return devlink_nl_dumpit(skb, cb, devlink_nl_rate_get_dump_one); 214 + } 215 + 216 + int devlink_nl_rate_get_doit(struct sk_buff *skb, struct genl_info *info) 217 + { 218 + struct devlink *devlink = info->user_ptr[0]; 219 + struct devlink_rate *devlink_rate; 220 + struct sk_buff *msg; 221 + int err; 222 + 223 + devlink_rate = devlink_rate_get_from_info(devlink, info); 224 + if (IS_ERR(devlink_rate)) 225 + return PTR_ERR(devlink_rate); 226 + 227 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 228 + if (!msg) 229 + return -ENOMEM; 230 + 231 + err = devlink_nl_rate_fill(msg, devlink_rate, DEVLINK_CMD_RATE_NEW, 232 + info->snd_portid, info->snd_seq, 0, 233 + info->extack); 234 + if (err) { 235 + nlmsg_free(msg); 236 + return err; 237 + } 238 + 239 + return genlmsg_reply(msg, info); 240 + } 241 + 242 + static bool 243 + devlink_rate_is_parent_node(struct devlink_rate *devlink_rate, 244 + struct devlink_rate *parent) 245 + { 246 + while (parent) { 247 + if (parent == devlink_rate) 248 + return true; 249 + parent = parent->parent; 250 + } 251 + return false; 252 + } 253 + 254 + static int 255 + devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate, 256 + struct genl_info *info, 257 + struct nlattr *nla_parent) 258 + { 259 + struct devlink *devlink = devlink_rate->devlink; 260 + const char *parent_name = nla_data(nla_parent); 261 + const struct devlink_ops *ops = devlink->ops; 262 + size_t len = strlen(parent_name); 263 + struct devlink_rate *parent; 264 + int err = -EOPNOTSUPP; 265 + 266 + parent = devlink_rate->parent; 267 + 268 + if (parent && !len) { 269 + if (devlink_rate_is_leaf(devlink_rate)) 270 + err = ops->rate_leaf_parent_set(devlink_rate, NULL, 271 + devlink_rate->priv, NULL, 272 + info->extack); 273 + else if (devlink_rate_is_node(devlink_rate)) 274 + err = ops->rate_node_parent_set(devlink_rate, NULL, 275 + devlink_rate->priv, NULL, 276 + info->extack); 277 + if (err) 278 + return err; 279 + 280 + refcount_dec(&parent->refcnt); 281 + devlink_rate->parent = NULL; 282 + } else if (len) { 283 + parent = devlink_rate_node_get_by_name(devlink, parent_name); 284 + if (IS_ERR(parent)) 285 + return -ENODEV; 286 + 287 + if (parent == devlink_rate) { 288 + NL_SET_ERR_MSG(info->extack, "Parent to self is not allowed"); 289 + return -EINVAL; 290 + } 291 + 292 + if (devlink_rate_is_node(devlink_rate) && 293 + devlink_rate_is_parent_node(devlink_rate, parent->parent)) { 294 + NL_SET_ERR_MSG(info->extack, "Node is already a parent of parent node."); 295 + return -EEXIST; 296 + } 297 + 298 + if (devlink_rate_is_leaf(devlink_rate)) 299 + err = ops->rate_leaf_parent_set(devlink_rate, parent, 300 + devlink_rate->priv, parent->priv, 301 + info->extack); 302 + else if (devlink_rate_is_node(devlink_rate)) 303 + err = ops->rate_node_parent_set(devlink_rate, parent, 304 + devlink_rate->priv, parent->priv, 305 + info->extack); 306 + if (err) 307 + return err; 308 + 309 + if (devlink_rate->parent) 310 + /* we're reassigning to other parent in this case */ 311 + refcount_dec(&devlink_rate->parent->refcnt); 312 + 313 + refcount_inc(&parent->refcnt); 314 + devlink_rate->parent = parent; 315 + } 316 + 317 + return 0; 318 + } 319 + 320 + static int devlink_nl_rate_set(struct devlink_rate *devlink_rate, 321 + const struct devlink_ops *ops, 322 + struct genl_info *info) 323 + { 324 + struct nlattr *nla_parent, **attrs = info->attrs; 325 + int err = -EOPNOTSUPP; 326 + u32 priority; 327 + u32 weight; 328 + u64 rate; 329 + 330 + if (attrs[DEVLINK_ATTR_RATE_TX_SHARE]) { 331 + rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]); 332 + if (devlink_rate_is_leaf(devlink_rate)) 333 + err = ops->rate_leaf_tx_share_set(devlink_rate, devlink_rate->priv, 334 + rate, info->extack); 335 + else if (devlink_rate_is_node(devlink_rate)) 336 + err = ops->rate_node_tx_share_set(devlink_rate, devlink_rate->priv, 337 + rate, info->extack); 338 + if (err) 339 + return err; 340 + devlink_rate->tx_share = rate; 341 + } 342 + 343 + if (attrs[DEVLINK_ATTR_RATE_TX_MAX]) { 344 + rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]); 345 + if (devlink_rate_is_leaf(devlink_rate)) 346 + err = ops->rate_leaf_tx_max_set(devlink_rate, devlink_rate->priv, 347 + rate, info->extack); 348 + else if (devlink_rate_is_node(devlink_rate)) 349 + err = ops->rate_node_tx_max_set(devlink_rate, devlink_rate->priv, 350 + rate, info->extack); 351 + if (err) 352 + return err; 353 + devlink_rate->tx_max = rate; 354 + } 355 + 356 + if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]) { 357 + priority = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]); 358 + if (devlink_rate_is_leaf(devlink_rate)) 359 + err = ops->rate_leaf_tx_priority_set(devlink_rate, devlink_rate->priv, 360 + priority, info->extack); 361 + else if (devlink_rate_is_node(devlink_rate)) 362 + err = ops->rate_node_tx_priority_set(devlink_rate, devlink_rate->priv, 363 + priority, info->extack); 364 + 365 + if (err) 366 + return err; 367 + devlink_rate->tx_priority = priority; 368 + } 369 + 370 + if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]) { 371 + weight = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]); 372 + if (devlink_rate_is_leaf(devlink_rate)) 373 + err = ops->rate_leaf_tx_weight_set(devlink_rate, devlink_rate->priv, 374 + weight, info->extack); 375 + else if (devlink_rate_is_node(devlink_rate)) 376 + err = ops->rate_node_tx_weight_set(devlink_rate, devlink_rate->priv, 377 + weight, info->extack); 378 + 379 + if (err) 380 + return err; 381 + devlink_rate->tx_weight = weight; 382 + } 383 + 384 + nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME]; 385 + if (nla_parent) { 386 + err = devlink_nl_rate_parent_node_set(devlink_rate, info, 387 + nla_parent); 388 + if (err) 389 + return err; 390 + } 391 + 392 + return 0; 393 + } 394 + 395 + static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops, 396 + struct genl_info *info, 397 + enum devlink_rate_type type) 398 + { 399 + struct nlattr **attrs = info->attrs; 400 + 401 + if (type == DEVLINK_RATE_TYPE_LEAF) { 402 + if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_leaf_tx_share_set) { 403 + NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the leafs"); 404 + return false; 405 + } 406 + if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) { 407 + NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the leafs"); 408 + return false; 409 + } 410 + if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 411 + !ops->rate_leaf_parent_set) { 412 + NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the leafs"); 413 + return false; 414 + } 415 + if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_leaf_tx_priority_set) { 416 + NL_SET_ERR_MSG_ATTR(info->extack, 417 + attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 418 + "TX priority set isn't supported for the leafs"); 419 + return false; 420 + } 421 + if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_leaf_tx_weight_set) { 422 + NL_SET_ERR_MSG_ATTR(info->extack, 423 + attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 424 + "TX weight set isn't supported for the leafs"); 425 + return false; 426 + } 427 + } else if (type == DEVLINK_RATE_TYPE_NODE) { 428 + if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_node_tx_share_set) { 429 + NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the nodes"); 430 + return false; 431 + } 432 + if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_node_tx_max_set) { 433 + NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the nodes"); 434 + return false; 435 + } 436 + if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 437 + !ops->rate_node_parent_set) { 438 + NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the nodes"); 439 + return false; 440 + } 441 + if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_node_tx_priority_set) { 442 + NL_SET_ERR_MSG_ATTR(info->extack, 443 + attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 444 + "TX priority set isn't supported for the nodes"); 445 + return false; 446 + } 447 + if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_node_tx_weight_set) { 448 + NL_SET_ERR_MSG_ATTR(info->extack, 449 + attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 450 + "TX weight set isn't supported for the nodes"); 451 + return false; 452 + } 453 + } else { 454 + WARN(1, "Unknown type of rate object"); 455 + return false; 456 + } 457 + 458 + return true; 459 + } 460 + 461 + int devlink_nl_cmd_rate_set_doit(struct sk_buff *skb, struct genl_info *info) 462 + { 463 + struct devlink *devlink = info->user_ptr[0]; 464 + struct devlink_rate *devlink_rate; 465 + const struct devlink_ops *ops; 466 + int err; 467 + 468 + devlink_rate = devlink_rate_get_from_info(devlink, info); 469 + if (IS_ERR(devlink_rate)) 470 + return PTR_ERR(devlink_rate); 471 + 472 + ops = devlink->ops; 473 + if (!ops || !devlink_rate_set_ops_supported(ops, info, devlink_rate->type)) 474 + return -EOPNOTSUPP; 475 + 476 + err = devlink_nl_rate_set(devlink_rate, ops, info); 477 + 478 + if (!err) 479 + devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 480 + return err; 481 + } 482 + 483 + int devlink_nl_cmd_rate_new_doit(struct sk_buff *skb, struct genl_info *info) 484 + { 485 + struct devlink *devlink = info->user_ptr[0]; 486 + struct devlink_rate *rate_node; 487 + const struct devlink_ops *ops; 488 + int err; 489 + 490 + ops = devlink->ops; 491 + if (!ops || !ops->rate_node_new || !ops->rate_node_del) { 492 + NL_SET_ERR_MSG(info->extack, "Rate nodes aren't supported"); 493 + return -EOPNOTSUPP; 494 + } 495 + 496 + if (!devlink_rate_set_ops_supported(ops, info, DEVLINK_RATE_TYPE_NODE)) 497 + return -EOPNOTSUPP; 498 + 499 + rate_node = devlink_rate_node_get_from_attrs(devlink, info->attrs); 500 + if (!IS_ERR(rate_node)) 501 + return -EEXIST; 502 + else if (rate_node == ERR_PTR(-EINVAL)) 503 + return -EINVAL; 504 + 505 + rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 506 + if (!rate_node) 507 + return -ENOMEM; 508 + 509 + rate_node->devlink = devlink; 510 + rate_node->type = DEVLINK_RATE_TYPE_NODE; 511 + rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL); 512 + if (!rate_node->name) { 513 + err = -ENOMEM; 514 + goto err_strdup; 515 + } 516 + 517 + err = ops->rate_node_new(rate_node, &rate_node->priv, info->extack); 518 + if (err) 519 + goto err_node_new; 520 + 521 + err = devlink_nl_rate_set(rate_node, ops, info); 522 + if (err) 523 + goto err_rate_set; 524 + 525 + refcount_set(&rate_node->refcnt, 1); 526 + list_add(&rate_node->list, &devlink->rate_list); 527 + devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 528 + return 0; 529 + 530 + err_rate_set: 531 + ops->rate_node_del(rate_node, rate_node->priv, info->extack); 532 + err_node_new: 533 + kfree(rate_node->name); 534 + err_strdup: 535 + kfree(rate_node); 536 + return err; 537 + } 538 + 539 + int devlink_nl_cmd_rate_del_doit(struct sk_buff *skb, struct genl_info *info) 540 + { 541 + struct devlink *devlink = info->user_ptr[0]; 542 + struct devlink_rate *rate_node; 543 + int err; 544 + 545 + rate_node = devlink_rate_node_get_from_info(devlink, info); 546 + if (IS_ERR(rate_node)) 547 + return PTR_ERR(rate_node); 548 + 549 + if (refcount_read(&rate_node->refcnt) > 1) { 550 + NL_SET_ERR_MSG(info->extack, "Node has children. Cannot delete node."); 551 + return -EBUSY; 552 + } 553 + 554 + devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 555 + err = devlink->ops->rate_node_del(rate_node, rate_node->priv, 556 + info->extack); 557 + if (rate_node->parent) 558 + refcount_dec(&rate_node->parent->refcnt); 559 + list_del(&rate_node->list); 560 + kfree(rate_node->name); 561 + kfree(rate_node); 562 + return err; 563 + } 564 + 565 + int devlink_rate_nodes_check(struct devlink *devlink, u16 mode, 566 + struct netlink_ext_ack *extack) 567 + { 568 + struct devlink_rate *devlink_rate; 569 + 570 + list_for_each_entry(devlink_rate, &devlink->rate_list, list) 571 + if (devlink_rate_is_node(devlink_rate)) { 572 + NL_SET_ERR_MSG(extack, "Rate node(s) exists."); 573 + return -EBUSY; 574 + } 575 + return 0; 576 + } 577 + 578 + /** 579 + * devl_rate_node_create - create devlink rate node 580 + * @devlink: devlink instance 581 + * @priv: driver private data 582 + * @node_name: name of the resulting node 583 + * @parent: parent devlink_rate struct 584 + * 585 + * Create devlink rate object of type node 586 + */ 587 + struct devlink_rate * 588 + devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name, 589 + struct devlink_rate *parent) 590 + { 591 + struct devlink_rate *rate_node; 592 + 593 + rate_node = devlink_rate_node_get_by_name(devlink, node_name); 594 + if (!IS_ERR(rate_node)) 595 + return ERR_PTR(-EEXIST); 596 + 597 + rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 598 + if (!rate_node) 599 + return ERR_PTR(-ENOMEM); 600 + 601 + if (parent) { 602 + rate_node->parent = parent; 603 + refcount_inc(&rate_node->parent->refcnt); 604 + } 605 + 606 + rate_node->type = DEVLINK_RATE_TYPE_NODE; 607 + rate_node->devlink = devlink; 608 + rate_node->priv = priv; 609 + 610 + rate_node->name = kstrdup(node_name, GFP_KERNEL); 611 + if (!rate_node->name) { 612 + kfree(rate_node); 613 + return ERR_PTR(-ENOMEM); 614 + } 615 + 616 + refcount_set(&rate_node->refcnt, 1); 617 + list_add(&rate_node->list, &devlink->rate_list); 618 + devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 619 + return rate_node; 620 + } 621 + EXPORT_SYMBOL_GPL(devl_rate_node_create); 622 + 623 + /** 624 + * devl_rate_leaf_create - create devlink rate leaf 625 + * @devlink_port: devlink port object to create rate object on 626 + * @priv: driver private data 627 + * @parent: parent devlink_rate struct 628 + * 629 + * Create devlink rate object of type leaf on provided @devlink_port. 630 + */ 631 + int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv, 632 + struct devlink_rate *parent) 633 + { 634 + struct devlink *devlink = devlink_port->devlink; 635 + struct devlink_rate *devlink_rate; 636 + 637 + devl_assert_locked(devlink_port->devlink); 638 + 639 + if (WARN_ON(devlink_port->devlink_rate)) 640 + return -EBUSY; 641 + 642 + devlink_rate = kzalloc(sizeof(*devlink_rate), GFP_KERNEL); 643 + if (!devlink_rate) 644 + return -ENOMEM; 645 + 646 + if (parent) { 647 + devlink_rate->parent = parent; 648 + refcount_inc(&devlink_rate->parent->refcnt); 649 + } 650 + 651 + devlink_rate->type = DEVLINK_RATE_TYPE_LEAF; 652 + devlink_rate->devlink = devlink; 653 + devlink_rate->devlink_port = devlink_port; 654 + devlink_rate->priv = priv; 655 + list_add_tail(&devlink_rate->list, &devlink->rate_list); 656 + devlink_port->devlink_rate = devlink_rate; 657 + devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 658 + 659 + return 0; 660 + } 661 + EXPORT_SYMBOL_GPL(devl_rate_leaf_create); 662 + 663 + /** 664 + * devl_rate_leaf_destroy - destroy devlink rate leaf 665 + * 666 + * @devlink_port: devlink port linked to the rate object 667 + * 668 + * Destroy the devlink rate object of type leaf on provided @devlink_port. 669 + */ 670 + void devl_rate_leaf_destroy(struct devlink_port *devlink_port) 671 + { 672 + struct devlink_rate *devlink_rate = devlink_port->devlink_rate; 673 + 674 + devl_assert_locked(devlink_port->devlink); 675 + if (!devlink_rate) 676 + return; 677 + 678 + devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL); 679 + if (devlink_rate->parent) 680 + refcount_dec(&devlink_rate->parent->refcnt); 681 + list_del(&devlink_rate->list); 682 + devlink_port->devlink_rate = NULL; 683 + kfree(devlink_rate); 684 + } 685 + EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy); 686 + 687 + /** 688 + * devl_rate_nodes_destroy - destroy all devlink rate nodes on device 689 + * @devlink: devlink instance 690 + * 691 + * Unset parent for all rate objects and destroy all rate nodes 692 + * on specified device. 693 + */ 694 + void devl_rate_nodes_destroy(struct devlink *devlink) 695 + { 696 + static struct devlink_rate *devlink_rate, *tmp; 697 + const struct devlink_ops *ops = devlink->ops; 698 + 699 + devl_assert_locked(devlink); 700 + 701 + list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 702 + if (!devlink_rate->parent) 703 + continue; 704 + 705 + refcount_dec(&devlink_rate->parent->refcnt); 706 + if (devlink_rate_is_leaf(devlink_rate)) 707 + ops->rate_leaf_parent_set(devlink_rate, NULL, devlink_rate->priv, 708 + NULL, NULL); 709 + else if (devlink_rate_is_node(devlink_rate)) 710 + ops->rate_node_parent_set(devlink_rate, NULL, devlink_rate->priv, 711 + NULL, NULL); 712 + } 713 + list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) { 714 + if (devlink_rate_is_node(devlink_rate)) { 715 + ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL); 716 + list_del(&devlink_rate->list); 717 + kfree(devlink_rate->name); 718 + kfree(devlink_rate); 719 + } 720 + } 721 + } 722 + EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy);
+1260
net/devlink/region.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + struct devlink_region { 10 + struct devlink *devlink; 11 + struct devlink_port *port; 12 + struct list_head list; 13 + union { 14 + const struct devlink_region_ops *ops; 15 + const struct devlink_port_region_ops *port_ops; 16 + }; 17 + struct mutex snapshot_lock; /* protects snapshot_list, 18 + * max_snapshots and cur_snapshots 19 + * consistency. 20 + */ 21 + struct list_head snapshot_list; 22 + u32 max_snapshots; 23 + u32 cur_snapshots; 24 + u64 size; 25 + }; 26 + 27 + struct devlink_snapshot { 28 + struct list_head list; 29 + struct devlink_region *region; 30 + u8 *data; 31 + u32 id; 32 + }; 33 + 34 + static struct devlink_region * 35 + devlink_region_get_by_name(struct devlink *devlink, const char *region_name) 36 + { 37 + struct devlink_region *region; 38 + 39 + list_for_each_entry(region, &devlink->region_list, list) 40 + if (!strcmp(region->ops->name, region_name)) 41 + return region; 42 + 43 + return NULL; 44 + } 45 + 46 + static struct devlink_region * 47 + devlink_port_region_get_by_name(struct devlink_port *port, 48 + const char *region_name) 49 + { 50 + struct devlink_region *region; 51 + 52 + list_for_each_entry(region, &port->region_list, list) 53 + if (!strcmp(region->ops->name, region_name)) 54 + return region; 55 + 56 + return NULL; 57 + } 58 + 59 + static struct devlink_snapshot * 60 + devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) 61 + { 62 + struct devlink_snapshot *snapshot; 63 + 64 + list_for_each_entry(snapshot, &region->snapshot_list, list) 65 + if (snapshot->id == id) 66 + return snapshot; 67 + 68 + return NULL; 69 + } 70 + 71 + static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 72 + struct devlink *devlink, 73 + struct devlink_snapshot *snapshot) 74 + { 75 + struct nlattr *snap_attr; 76 + int err; 77 + 78 + snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 79 + if (!snap_attr) 80 + return -EINVAL; 81 + 82 + err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 83 + if (err) 84 + goto nla_put_failure; 85 + 86 + nla_nest_end(msg, snap_attr); 87 + return 0; 88 + 89 + nla_put_failure: 90 + nla_nest_cancel(msg, snap_attr); 91 + return err; 92 + } 93 + 94 + static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 95 + struct devlink *devlink, 96 + struct devlink_region *region) 97 + { 98 + struct devlink_snapshot *snapshot; 99 + struct nlattr *snapshots_attr; 100 + int err; 101 + 102 + snapshots_attr = nla_nest_start_noflag(msg, 103 + DEVLINK_ATTR_REGION_SNAPSHOTS); 104 + if (!snapshots_attr) 105 + return -EINVAL; 106 + 107 + list_for_each_entry(snapshot, &region->snapshot_list, list) { 108 + err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 109 + if (err) 110 + goto nla_put_failure; 111 + } 112 + 113 + nla_nest_end(msg, snapshots_attr); 114 + return 0; 115 + 116 + nla_put_failure: 117 + nla_nest_cancel(msg, snapshots_attr); 118 + return err; 119 + } 120 + 121 + static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 122 + enum devlink_command cmd, u32 portid, 123 + u32 seq, int flags, 124 + struct devlink_region *region) 125 + { 126 + void *hdr; 127 + int err; 128 + 129 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 130 + if (!hdr) 131 + return -EMSGSIZE; 132 + 133 + err = devlink_nl_put_handle(msg, devlink); 134 + if (err) 135 + goto nla_put_failure; 136 + 137 + if (region->port) { 138 + err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 139 + region->port->index); 140 + if (err) 141 + goto nla_put_failure; 142 + } 143 + 144 + err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name); 145 + if (err) 146 + goto nla_put_failure; 147 + 148 + err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 149 + region->size, 150 + DEVLINK_ATTR_PAD); 151 + if (err) 152 + goto nla_put_failure; 153 + 154 + err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS, 155 + region->max_snapshots); 156 + if (err) 157 + goto nla_put_failure; 158 + 159 + err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 160 + if (err) 161 + goto nla_put_failure; 162 + 163 + genlmsg_end(msg, hdr); 164 + return 0; 165 + 166 + nla_put_failure: 167 + genlmsg_cancel(msg, hdr); 168 + return err; 169 + } 170 + 171 + static struct sk_buff * 172 + devlink_nl_region_notify_build(struct devlink_region *region, 173 + struct devlink_snapshot *snapshot, 174 + enum devlink_command cmd, u32 portid, u32 seq) 175 + { 176 + struct devlink *devlink = region->devlink; 177 + struct sk_buff *msg; 178 + void *hdr; 179 + int err; 180 + 181 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 182 + if (!msg) 183 + return ERR_PTR(-ENOMEM); 184 + 185 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd); 186 + if (!hdr) { 187 + err = -EMSGSIZE; 188 + goto out_free_msg; 189 + } 190 + 191 + err = devlink_nl_put_handle(msg, devlink); 192 + if (err) 193 + goto out_cancel_msg; 194 + 195 + if (region->port) { 196 + err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 197 + region->port->index); 198 + if (err) 199 + goto out_cancel_msg; 200 + } 201 + 202 + err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 203 + region->ops->name); 204 + if (err) 205 + goto out_cancel_msg; 206 + 207 + if (snapshot) { 208 + err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 209 + snapshot->id); 210 + if (err) 211 + goto out_cancel_msg; 212 + } else { 213 + err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 214 + region->size, DEVLINK_ATTR_PAD); 215 + if (err) 216 + goto out_cancel_msg; 217 + } 218 + genlmsg_end(msg, hdr); 219 + 220 + return msg; 221 + 222 + out_cancel_msg: 223 + genlmsg_cancel(msg, hdr); 224 + out_free_msg: 225 + nlmsg_free(msg); 226 + return ERR_PTR(err); 227 + } 228 + 229 + static void devlink_nl_region_notify(struct devlink_region *region, 230 + struct devlink_snapshot *snapshot, 231 + enum devlink_command cmd) 232 + { 233 + struct devlink *devlink = region->devlink; 234 + struct sk_buff *msg; 235 + 236 + WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 237 + if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 238 + return; 239 + 240 + msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0); 241 + if (IS_ERR(msg)) 242 + return; 243 + 244 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg, 245 + 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 246 + } 247 + 248 + void devlink_regions_notify_register(struct devlink *devlink) 249 + { 250 + struct devlink_region *region; 251 + 252 + list_for_each_entry(region, &devlink->region_list, list) 253 + devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 254 + } 255 + 256 + void devlink_regions_notify_unregister(struct devlink *devlink) 257 + { 258 + struct devlink_region *region; 259 + 260 + list_for_each_entry_reverse(region, &devlink->region_list, list) 261 + devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 262 + } 263 + 264 + /** 265 + * __devlink_snapshot_id_increment - Increment number of snapshots using an id 266 + * @devlink: devlink instance 267 + * @id: the snapshot id 268 + * 269 + * Track when a new snapshot begins using an id. Load the count for the 270 + * given id from the snapshot xarray, increment it, and store it back. 271 + * 272 + * Called when a new snapshot is created with the given id. 273 + * 274 + * The id *must* have been previously allocated by 275 + * devlink_region_snapshot_id_get(). 276 + * 277 + * Returns 0 on success, or an error on failure. 278 + */ 279 + static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id) 280 + { 281 + unsigned long count; 282 + void *p; 283 + int err; 284 + 285 + xa_lock(&devlink->snapshot_ids); 286 + p = xa_load(&devlink->snapshot_ids, id); 287 + if (WARN_ON(!p)) { 288 + err = -EINVAL; 289 + goto unlock; 290 + } 291 + 292 + if (WARN_ON(!xa_is_value(p))) { 293 + err = -EINVAL; 294 + goto unlock; 295 + } 296 + 297 + count = xa_to_value(p); 298 + count++; 299 + 300 + err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), 301 + GFP_ATOMIC)); 302 + unlock: 303 + xa_unlock(&devlink->snapshot_ids); 304 + return err; 305 + } 306 + 307 + /** 308 + * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id 309 + * @devlink: devlink instance 310 + * @id: the snapshot id 311 + * 312 + * Track when a snapshot is deleted and stops using an id. Load the count 313 + * for the given id from the snapshot xarray, decrement it, and store it 314 + * back. 315 + * 316 + * If the count reaches zero, erase this id from the xarray, freeing it 317 + * up for future re-use by devlink_region_snapshot_id_get(). 318 + * 319 + * Called when a snapshot using the given id is deleted, and when the 320 + * initial allocator of the id is finished using it. 321 + */ 322 + static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id) 323 + { 324 + unsigned long count; 325 + void *p; 326 + 327 + xa_lock(&devlink->snapshot_ids); 328 + p = xa_load(&devlink->snapshot_ids, id); 329 + if (WARN_ON(!p)) 330 + goto unlock; 331 + 332 + if (WARN_ON(!xa_is_value(p))) 333 + goto unlock; 334 + 335 + count = xa_to_value(p); 336 + 337 + if (count > 1) { 338 + count--; 339 + __xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), 340 + GFP_ATOMIC); 341 + } else { 342 + /* If this was the last user, we can erase this id */ 343 + __xa_erase(&devlink->snapshot_ids, id); 344 + } 345 + unlock: 346 + xa_unlock(&devlink->snapshot_ids); 347 + } 348 + 349 + /** 350 + * __devlink_snapshot_id_insert - Insert a specific snapshot ID 351 + * @devlink: devlink instance 352 + * @id: the snapshot id 353 + * 354 + * Mark the given snapshot id as used by inserting a zero value into the 355 + * snapshot xarray. 356 + * 357 + * This must be called while holding the devlink instance lock. Unlike 358 + * devlink_snapshot_id_get, the initial reference count is zero, not one. 359 + * It is expected that the id will immediately be used before 360 + * releasing the devlink instance lock. 361 + * 362 + * Returns zero on success, or an error code if the snapshot id could not 363 + * be inserted. 364 + */ 365 + static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id) 366 + { 367 + int err; 368 + 369 + xa_lock(&devlink->snapshot_ids); 370 + if (xa_load(&devlink->snapshot_ids, id)) { 371 + xa_unlock(&devlink->snapshot_ids); 372 + return -EEXIST; 373 + } 374 + err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0), 375 + GFP_ATOMIC)); 376 + xa_unlock(&devlink->snapshot_ids); 377 + return err; 378 + } 379 + 380 + /** 381 + * __devlink_region_snapshot_id_get - get snapshot ID 382 + * @devlink: devlink instance 383 + * @id: storage to return snapshot id 384 + * 385 + * Allocates a new snapshot id. Returns zero on success, or a negative 386 + * error on failure. Must be called while holding the devlink instance 387 + * lock. 388 + * 389 + * Snapshot IDs are tracked using an xarray which stores the number of 390 + * users of the snapshot id. 391 + * 392 + * Note that the caller of this function counts as a 'user', in order to 393 + * avoid race conditions. The caller must release its hold on the 394 + * snapshot by using devlink_region_snapshot_id_put. 395 + */ 396 + static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id) 397 + { 398 + return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1), 399 + xa_limit_32b, GFP_KERNEL); 400 + } 401 + 402 + /** 403 + * __devlink_region_snapshot_create - create a new snapshot 404 + * This will add a new snapshot of a region. The snapshot 405 + * will be stored on the region struct and can be accessed 406 + * from devlink. This is useful for future analyses of snapshots. 407 + * Multiple snapshots can be created on a region. 408 + * The @snapshot_id should be obtained using the getter function. 409 + * 410 + * Must be called only while holding the region snapshot lock. 411 + * 412 + * @region: devlink region of the snapshot 413 + * @data: snapshot data 414 + * @snapshot_id: snapshot id to be created 415 + */ 416 + static int 417 + __devlink_region_snapshot_create(struct devlink_region *region, 418 + u8 *data, u32 snapshot_id) 419 + { 420 + struct devlink *devlink = region->devlink; 421 + struct devlink_snapshot *snapshot; 422 + int err; 423 + 424 + lockdep_assert_held(&region->snapshot_lock); 425 + 426 + /* check if region can hold one more snapshot */ 427 + if (region->cur_snapshots == region->max_snapshots) 428 + return -ENOSPC; 429 + 430 + if (devlink_region_snapshot_get_by_id(region, snapshot_id)) 431 + return -EEXIST; 432 + 433 + snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 434 + if (!snapshot) 435 + return -ENOMEM; 436 + 437 + err = __devlink_snapshot_id_increment(devlink, snapshot_id); 438 + if (err) 439 + goto err_snapshot_id_increment; 440 + 441 + snapshot->id = snapshot_id; 442 + snapshot->region = region; 443 + snapshot->data = data; 444 + 445 + list_add_tail(&snapshot->list, &region->snapshot_list); 446 + 447 + region->cur_snapshots++; 448 + 449 + devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 450 + return 0; 451 + 452 + err_snapshot_id_increment: 453 + kfree(snapshot); 454 + return err; 455 + } 456 + 457 + static void devlink_region_snapshot_del(struct devlink_region *region, 458 + struct devlink_snapshot *snapshot) 459 + { 460 + struct devlink *devlink = region->devlink; 461 + 462 + lockdep_assert_held(&region->snapshot_lock); 463 + 464 + devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 465 + region->cur_snapshots--; 466 + list_del(&snapshot->list); 467 + region->ops->destructor(snapshot->data); 468 + __devlink_snapshot_id_decrement(devlink, snapshot->id); 469 + kfree(snapshot); 470 + } 471 + 472 + int devlink_nl_region_get_doit(struct sk_buff *skb, struct genl_info *info) 473 + { 474 + struct devlink *devlink = info->user_ptr[0]; 475 + struct devlink_port *port = NULL; 476 + struct devlink_region *region; 477 + const char *region_name; 478 + struct sk_buff *msg; 479 + unsigned int index; 480 + int err; 481 + 482 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) 483 + return -EINVAL; 484 + 485 + if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 486 + index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 487 + 488 + port = devlink_port_get_by_index(devlink, index); 489 + if (!port) 490 + return -ENODEV; 491 + } 492 + 493 + region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 494 + if (port) 495 + region = devlink_port_region_get_by_name(port, region_name); 496 + else 497 + region = devlink_region_get_by_name(devlink, region_name); 498 + 499 + if (!region) 500 + return -EINVAL; 501 + 502 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 503 + if (!msg) 504 + return -ENOMEM; 505 + 506 + err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 507 + info->snd_portid, info->snd_seq, 0, 508 + region); 509 + if (err) { 510 + nlmsg_free(msg); 511 + return err; 512 + } 513 + 514 + return genlmsg_reply(msg, info); 515 + } 516 + 517 + static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg, 518 + struct netlink_callback *cb, 519 + struct devlink_port *port, 520 + int *idx, int start, int flags) 521 + { 522 + struct devlink_region *region; 523 + int err = 0; 524 + 525 + list_for_each_entry(region, &port->region_list, list) { 526 + if (*idx < start) { 527 + (*idx)++; 528 + continue; 529 + } 530 + err = devlink_nl_region_fill(msg, port->devlink, 531 + DEVLINK_CMD_REGION_GET, 532 + NETLINK_CB(cb->skb).portid, 533 + cb->nlh->nlmsg_seq, 534 + flags, region); 535 + if (err) 536 + goto out; 537 + (*idx)++; 538 + } 539 + 540 + out: 541 + return err; 542 + } 543 + 544 + static int devlink_nl_region_get_dump_one(struct sk_buff *msg, 545 + struct devlink *devlink, 546 + struct netlink_callback *cb, 547 + int flags) 548 + { 549 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 550 + struct devlink_region *region; 551 + struct devlink_port *port; 552 + unsigned long port_index; 553 + int idx = 0; 554 + int err; 555 + 556 + list_for_each_entry(region, &devlink->region_list, list) { 557 + if (idx < state->idx) { 558 + idx++; 559 + continue; 560 + } 561 + err = devlink_nl_region_fill(msg, devlink, 562 + DEVLINK_CMD_REGION_GET, 563 + NETLINK_CB(cb->skb).portid, 564 + cb->nlh->nlmsg_seq, flags, 565 + region); 566 + if (err) { 567 + state->idx = idx; 568 + return err; 569 + } 570 + idx++; 571 + } 572 + 573 + xa_for_each(&devlink->ports, port_index, port) { 574 + err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, &idx, 575 + state->idx, flags); 576 + if (err) { 577 + state->idx = idx; 578 + return err; 579 + } 580 + } 581 + 582 + return 0; 583 + } 584 + 585 + int devlink_nl_region_get_dumpit(struct sk_buff *skb, 586 + struct netlink_callback *cb) 587 + { 588 + return devlink_nl_dumpit(skb, cb, devlink_nl_region_get_dump_one); 589 + } 590 + 591 + int devlink_nl_cmd_region_del(struct sk_buff *skb, struct genl_info *info) 592 + { 593 + struct devlink *devlink = info->user_ptr[0]; 594 + struct devlink_snapshot *snapshot; 595 + struct devlink_port *port = NULL; 596 + struct devlink_region *region; 597 + const char *region_name; 598 + unsigned int index; 599 + u32 snapshot_id; 600 + 601 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) || 602 + GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID)) 603 + return -EINVAL; 604 + 605 + region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 606 + snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 607 + 608 + if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 609 + index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 610 + 611 + port = devlink_port_get_by_index(devlink, index); 612 + if (!port) 613 + return -ENODEV; 614 + } 615 + 616 + if (port) 617 + region = devlink_port_region_get_by_name(port, region_name); 618 + else 619 + region = devlink_region_get_by_name(devlink, region_name); 620 + 621 + if (!region) 622 + return -EINVAL; 623 + 624 + mutex_lock(&region->snapshot_lock); 625 + snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 626 + if (!snapshot) { 627 + mutex_unlock(&region->snapshot_lock); 628 + return -EINVAL; 629 + } 630 + 631 + devlink_region_snapshot_del(region, snapshot); 632 + mutex_unlock(&region->snapshot_lock); 633 + return 0; 634 + } 635 + 636 + int devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) 637 + { 638 + struct devlink *devlink = info->user_ptr[0]; 639 + struct devlink_snapshot *snapshot; 640 + struct devlink_port *port = NULL; 641 + struct nlattr *snapshot_id_attr; 642 + struct devlink_region *region; 643 + const char *region_name; 644 + unsigned int index; 645 + u32 snapshot_id; 646 + u8 *data; 647 + int err; 648 + 649 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) { 650 + NL_SET_ERR_MSG(info->extack, "No region name provided"); 651 + return -EINVAL; 652 + } 653 + 654 + region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 655 + 656 + if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { 657 + index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 658 + 659 + port = devlink_port_get_by_index(devlink, index); 660 + if (!port) 661 + return -ENODEV; 662 + } 663 + 664 + if (port) 665 + region = devlink_port_region_get_by_name(port, region_name); 666 + else 667 + region = devlink_region_get_by_name(devlink, region_name); 668 + 669 + if (!region) { 670 + NL_SET_ERR_MSG(info->extack, "The requested region does not exist"); 671 + return -EINVAL; 672 + } 673 + 674 + if (!region->ops->snapshot) { 675 + NL_SET_ERR_MSG(info->extack, "The requested region does not support taking an immediate snapshot"); 676 + return -EOPNOTSUPP; 677 + } 678 + 679 + mutex_lock(&region->snapshot_lock); 680 + 681 + if (region->cur_snapshots == region->max_snapshots) { 682 + NL_SET_ERR_MSG(info->extack, "The region has reached the maximum number of stored snapshots"); 683 + err = -ENOSPC; 684 + goto unlock; 685 + } 686 + 687 + snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; 688 + if (snapshot_id_attr) { 689 + snapshot_id = nla_get_u32(snapshot_id_attr); 690 + 691 + if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 692 + NL_SET_ERR_MSG(info->extack, "The requested snapshot id is already in use"); 693 + err = -EEXIST; 694 + goto unlock; 695 + } 696 + 697 + err = __devlink_snapshot_id_insert(devlink, snapshot_id); 698 + if (err) 699 + goto unlock; 700 + } else { 701 + err = __devlink_region_snapshot_id_get(devlink, &snapshot_id); 702 + if (err) { 703 + NL_SET_ERR_MSG(info->extack, "Failed to allocate a new snapshot id"); 704 + goto unlock; 705 + } 706 + } 707 + 708 + if (port) 709 + err = region->port_ops->snapshot(port, region->port_ops, 710 + info->extack, &data); 711 + else 712 + err = region->ops->snapshot(devlink, region->ops, 713 + info->extack, &data); 714 + if (err) 715 + goto err_snapshot_capture; 716 + 717 + err = __devlink_region_snapshot_create(region, data, snapshot_id); 718 + if (err) 719 + goto err_snapshot_create; 720 + 721 + if (!snapshot_id_attr) { 722 + struct sk_buff *msg; 723 + 724 + snapshot = devlink_region_snapshot_get_by_id(region, 725 + snapshot_id); 726 + if (WARN_ON(!snapshot)) { 727 + err = -EINVAL; 728 + goto unlock; 729 + } 730 + 731 + msg = devlink_nl_region_notify_build(region, snapshot, 732 + DEVLINK_CMD_REGION_NEW, 733 + info->snd_portid, 734 + info->snd_seq); 735 + err = PTR_ERR_OR_ZERO(msg); 736 + if (err) 737 + goto err_notify; 738 + 739 + err = genlmsg_reply(msg, info); 740 + if (err) 741 + goto err_notify; 742 + } 743 + 744 + mutex_unlock(&region->snapshot_lock); 745 + return 0; 746 + 747 + err_snapshot_create: 748 + region->ops->destructor(data); 749 + err_snapshot_capture: 750 + __devlink_snapshot_id_decrement(devlink, snapshot_id); 751 + mutex_unlock(&region->snapshot_lock); 752 + return err; 753 + 754 + err_notify: 755 + devlink_region_snapshot_del(region, snapshot); 756 + unlock: 757 + mutex_unlock(&region->snapshot_lock); 758 + return err; 759 + } 760 + 761 + static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 762 + u8 *chunk, u32 chunk_size, 763 + u64 addr) 764 + { 765 + struct nlattr *chunk_attr; 766 + int err; 767 + 768 + chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK); 769 + if (!chunk_attr) 770 + return -EINVAL; 771 + 772 + err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 773 + if (err) 774 + goto nla_put_failure; 775 + 776 + err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 777 + DEVLINK_ATTR_PAD); 778 + if (err) 779 + goto nla_put_failure; 780 + 781 + nla_nest_end(msg, chunk_attr); 782 + return 0; 783 + 784 + nla_put_failure: 785 + nla_nest_cancel(msg, chunk_attr); 786 + return err; 787 + } 788 + 789 + #define DEVLINK_REGION_READ_CHUNK_SIZE 256 790 + 791 + typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size, 792 + u64 curr_offset, 793 + struct netlink_ext_ack *extack); 794 + 795 + static int 796 + devlink_nl_region_read_fill(struct sk_buff *skb, devlink_chunk_fill_t *cb, 797 + void *cb_priv, u64 start_offset, u64 end_offset, 798 + u64 *new_offset, struct netlink_ext_ack *extack) 799 + { 800 + u64 curr_offset = start_offset; 801 + int err = 0; 802 + u8 *data; 803 + 804 + /* Allocate and re-use a single buffer */ 805 + data = kmalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL); 806 + if (!data) 807 + return -ENOMEM; 808 + 809 + *new_offset = start_offset; 810 + 811 + while (curr_offset < end_offset) { 812 + u32 data_size; 813 + 814 + data_size = min_t(u32, end_offset - curr_offset, 815 + DEVLINK_REGION_READ_CHUNK_SIZE); 816 + 817 + err = cb(cb_priv, data, data_size, curr_offset, extack); 818 + if (err) 819 + break; 820 + 821 + err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset); 822 + if (err) 823 + break; 824 + 825 + curr_offset += data_size; 826 + } 827 + *new_offset = curr_offset; 828 + 829 + kfree(data); 830 + 831 + return err; 832 + } 833 + 834 + static int 835 + devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size, 836 + u64 curr_offset, 837 + struct netlink_ext_ack __always_unused *extack) 838 + { 839 + struct devlink_snapshot *snapshot = cb_priv; 840 + 841 + memcpy(chunk, &snapshot->data[curr_offset], chunk_size); 842 + 843 + return 0; 844 + } 845 + 846 + static int 847 + devlink_region_port_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size, 848 + u64 curr_offset, struct netlink_ext_ack *extack) 849 + { 850 + struct devlink_region *region = cb_priv; 851 + 852 + return region->port_ops->read(region->port, region->port_ops, extack, 853 + curr_offset, chunk_size, chunk); 854 + } 855 + 856 + static int 857 + devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size, 858 + u64 curr_offset, struct netlink_ext_ack *extack) 859 + { 860 + struct devlink_region *region = cb_priv; 861 + 862 + return region->ops->read(region->devlink, region->ops, extack, 863 + curr_offset, chunk_size, chunk); 864 + } 865 + 866 + int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 867 + struct netlink_callback *cb) 868 + { 869 + const struct genl_dumpit_info *info = genl_dumpit_info(cb); 870 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 871 + struct nlattr *chunks_attr, *region_attr, *snapshot_attr; 872 + u64 ret_offset, start_offset, end_offset = U64_MAX; 873 + struct nlattr **attrs = info->info.attrs; 874 + struct devlink_port *port = NULL; 875 + devlink_chunk_fill_t *region_cb; 876 + struct devlink_region *region; 877 + const char *region_name; 878 + struct devlink *devlink; 879 + unsigned int index; 880 + void *region_cb_priv; 881 + void *hdr; 882 + int err; 883 + 884 + start_offset = state->start_offset; 885 + 886 + devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs); 887 + if (IS_ERR(devlink)) 888 + return PTR_ERR(devlink); 889 + 890 + if (!attrs[DEVLINK_ATTR_REGION_NAME]) { 891 + NL_SET_ERR_MSG(cb->extack, "No region name provided"); 892 + err = -EINVAL; 893 + goto out_unlock; 894 + } 895 + 896 + if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 897 + index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 898 + 899 + port = devlink_port_get_by_index(devlink, index); 900 + if (!port) { 901 + err = -ENODEV; 902 + goto out_unlock; 903 + } 904 + } 905 + 906 + region_attr = attrs[DEVLINK_ATTR_REGION_NAME]; 907 + region_name = nla_data(region_attr); 908 + 909 + if (port) 910 + region = devlink_port_region_get_by_name(port, region_name); 911 + else 912 + region = devlink_region_get_by_name(devlink, region_name); 913 + 914 + if (!region) { 915 + NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist"); 916 + err = -EINVAL; 917 + goto out_unlock; 918 + } 919 + 920 + snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; 921 + if (!snapshot_attr) { 922 + if (!nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) { 923 + NL_SET_ERR_MSG(cb->extack, "No snapshot id provided"); 924 + err = -EINVAL; 925 + goto out_unlock; 926 + } 927 + 928 + if (!region->ops->read) { 929 + NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read"); 930 + err = -EOPNOTSUPP; 931 + goto out_unlock; 932 + } 933 + 934 + if (port) 935 + region_cb = &devlink_region_port_direct_fill; 936 + else 937 + region_cb = &devlink_region_direct_fill; 938 + region_cb_priv = region; 939 + } else { 940 + struct devlink_snapshot *snapshot; 941 + u32 snapshot_id; 942 + 943 + if (nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) { 944 + NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot"); 945 + err = -EINVAL; 946 + goto out_unlock; 947 + } 948 + 949 + snapshot_id = nla_get_u32(snapshot_attr); 950 + snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 951 + if (!snapshot) { 952 + NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist"); 953 + err = -EINVAL; 954 + goto out_unlock; 955 + } 956 + region_cb = &devlink_region_snapshot_fill; 957 + region_cb_priv = snapshot; 958 + } 959 + 960 + if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 961 + attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 962 + if (!start_offset) 963 + start_offset = 964 + nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 965 + 966 + end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 967 + end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 968 + } 969 + 970 + if (end_offset > region->size) 971 + end_offset = region->size; 972 + 973 + /* return 0 if there is no further data to read */ 974 + if (start_offset == end_offset) { 975 + err = 0; 976 + goto out_unlock; 977 + } 978 + 979 + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 980 + &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 981 + DEVLINK_CMD_REGION_READ); 982 + if (!hdr) { 983 + err = -EMSGSIZE; 984 + goto out_unlock; 985 + } 986 + 987 + err = devlink_nl_put_handle(skb, devlink); 988 + if (err) 989 + goto nla_put_failure; 990 + 991 + if (region->port) { 992 + err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX, 993 + region->port->index); 994 + if (err) 995 + goto nla_put_failure; 996 + } 997 + 998 + err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 999 + if (err) 1000 + goto nla_put_failure; 1001 + 1002 + chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS); 1003 + if (!chunks_attr) { 1004 + err = -EMSGSIZE; 1005 + goto nla_put_failure; 1006 + } 1007 + 1008 + err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv, 1009 + start_offset, end_offset, &ret_offset, 1010 + cb->extack); 1011 + 1012 + if (err && err != -EMSGSIZE) 1013 + goto nla_put_failure; 1014 + 1015 + /* Check if there was any progress done to prevent infinite loop */ 1016 + if (ret_offset == start_offset) { 1017 + err = -EINVAL; 1018 + goto nla_put_failure; 1019 + } 1020 + 1021 + state->start_offset = ret_offset; 1022 + 1023 + nla_nest_end(skb, chunks_attr); 1024 + genlmsg_end(skb, hdr); 1025 + devl_unlock(devlink); 1026 + devlink_put(devlink); 1027 + return skb->len; 1028 + 1029 + nla_put_failure: 1030 + genlmsg_cancel(skb, hdr); 1031 + out_unlock: 1032 + devl_unlock(devlink); 1033 + devlink_put(devlink); 1034 + return err; 1035 + } 1036 + 1037 + /** 1038 + * devl_region_create - create a new address region 1039 + * 1040 + * @devlink: devlink 1041 + * @ops: region operations and name 1042 + * @region_max_snapshots: Maximum supported number of snapshots for region 1043 + * @region_size: size of region 1044 + */ 1045 + struct devlink_region *devl_region_create(struct devlink *devlink, 1046 + const struct devlink_region_ops *ops, 1047 + u32 region_max_snapshots, 1048 + u64 region_size) 1049 + { 1050 + struct devlink_region *region; 1051 + 1052 + devl_assert_locked(devlink); 1053 + 1054 + if (WARN_ON(!ops) || WARN_ON(!ops->destructor)) 1055 + return ERR_PTR(-EINVAL); 1056 + 1057 + if (devlink_region_get_by_name(devlink, ops->name)) 1058 + return ERR_PTR(-EEXIST); 1059 + 1060 + region = kzalloc(sizeof(*region), GFP_KERNEL); 1061 + if (!region) 1062 + return ERR_PTR(-ENOMEM); 1063 + 1064 + region->devlink = devlink; 1065 + region->max_snapshots = region_max_snapshots; 1066 + region->ops = ops; 1067 + region->size = region_size; 1068 + INIT_LIST_HEAD(&region->snapshot_list); 1069 + mutex_init(&region->snapshot_lock); 1070 + list_add_tail(&region->list, &devlink->region_list); 1071 + devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 1072 + 1073 + return region; 1074 + } 1075 + EXPORT_SYMBOL_GPL(devl_region_create); 1076 + 1077 + /** 1078 + * devlink_region_create - create a new address region 1079 + * 1080 + * @devlink: devlink 1081 + * @ops: region operations and name 1082 + * @region_max_snapshots: Maximum supported number of snapshots for region 1083 + * @region_size: size of region 1084 + * 1085 + * Context: Takes and release devlink->lock <mutex>. 1086 + */ 1087 + struct devlink_region * 1088 + devlink_region_create(struct devlink *devlink, 1089 + const struct devlink_region_ops *ops, 1090 + u32 region_max_snapshots, u64 region_size) 1091 + { 1092 + struct devlink_region *region; 1093 + 1094 + devl_lock(devlink); 1095 + region = devl_region_create(devlink, ops, region_max_snapshots, 1096 + region_size); 1097 + devl_unlock(devlink); 1098 + return region; 1099 + } 1100 + EXPORT_SYMBOL_GPL(devlink_region_create); 1101 + 1102 + /** 1103 + * devlink_port_region_create - create a new address region for a port 1104 + * 1105 + * @port: devlink port 1106 + * @ops: region operations and name 1107 + * @region_max_snapshots: Maximum supported number of snapshots for region 1108 + * @region_size: size of region 1109 + * 1110 + * Context: Takes and release devlink->lock <mutex>. 1111 + */ 1112 + struct devlink_region * 1113 + devlink_port_region_create(struct devlink_port *port, 1114 + const struct devlink_port_region_ops *ops, 1115 + u32 region_max_snapshots, u64 region_size) 1116 + { 1117 + struct devlink *devlink = port->devlink; 1118 + struct devlink_region *region; 1119 + int err = 0; 1120 + 1121 + ASSERT_DEVLINK_PORT_INITIALIZED(port); 1122 + 1123 + if (WARN_ON(!ops) || WARN_ON(!ops->destructor)) 1124 + return ERR_PTR(-EINVAL); 1125 + 1126 + devl_lock(devlink); 1127 + 1128 + if (devlink_port_region_get_by_name(port, ops->name)) { 1129 + err = -EEXIST; 1130 + goto unlock; 1131 + } 1132 + 1133 + region = kzalloc(sizeof(*region), GFP_KERNEL); 1134 + if (!region) { 1135 + err = -ENOMEM; 1136 + goto unlock; 1137 + } 1138 + 1139 + region->devlink = devlink; 1140 + region->port = port; 1141 + region->max_snapshots = region_max_snapshots; 1142 + region->port_ops = ops; 1143 + region->size = region_size; 1144 + INIT_LIST_HEAD(&region->snapshot_list); 1145 + mutex_init(&region->snapshot_lock); 1146 + list_add_tail(&region->list, &port->region_list); 1147 + devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 1148 + 1149 + devl_unlock(devlink); 1150 + return region; 1151 + 1152 + unlock: 1153 + devl_unlock(devlink); 1154 + return ERR_PTR(err); 1155 + } 1156 + EXPORT_SYMBOL_GPL(devlink_port_region_create); 1157 + 1158 + /** 1159 + * devl_region_destroy - destroy address region 1160 + * 1161 + * @region: devlink region to destroy 1162 + */ 1163 + void devl_region_destroy(struct devlink_region *region) 1164 + { 1165 + struct devlink *devlink = region->devlink; 1166 + struct devlink_snapshot *snapshot, *ts; 1167 + 1168 + devl_assert_locked(devlink); 1169 + 1170 + /* Free all snapshots of region */ 1171 + mutex_lock(&region->snapshot_lock); 1172 + list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 1173 + devlink_region_snapshot_del(region, snapshot); 1174 + mutex_unlock(&region->snapshot_lock); 1175 + 1176 + list_del(&region->list); 1177 + mutex_destroy(&region->snapshot_lock); 1178 + 1179 + devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 1180 + kfree(region); 1181 + } 1182 + EXPORT_SYMBOL_GPL(devl_region_destroy); 1183 + 1184 + /** 1185 + * devlink_region_destroy - destroy address region 1186 + * 1187 + * @region: devlink region to destroy 1188 + * 1189 + * Context: Takes and release devlink->lock <mutex>. 1190 + */ 1191 + void devlink_region_destroy(struct devlink_region *region) 1192 + { 1193 + struct devlink *devlink = region->devlink; 1194 + 1195 + devl_lock(devlink); 1196 + devl_region_destroy(region); 1197 + devl_unlock(devlink); 1198 + } 1199 + EXPORT_SYMBOL_GPL(devlink_region_destroy); 1200 + 1201 + /** 1202 + * devlink_region_snapshot_id_get - get snapshot ID 1203 + * 1204 + * This callback should be called when adding a new snapshot, 1205 + * Driver should use the same id for multiple snapshots taken 1206 + * on multiple regions at the same time/by the same trigger. 1207 + * 1208 + * The caller of this function must use devlink_region_snapshot_id_put 1209 + * when finished creating regions using this id. 1210 + * 1211 + * Returns zero on success, or a negative error code on failure. 1212 + * 1213 + * @devlink: devlink 1214 + * @id: storage to return id 1215 + */ 1216 + int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id) 1217 + { 1218 + return __devlink_region_snapshot_id_get(devlink, id); 1219 + } 1220 + EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get); 1221 + 1222 + /** 1223 + * devlink_region_snapshot_id_put - put snapshot ID reference 1224 + * 1225 + * This should be called by a driver after finishing creating snapshots 1226 + * with an id. Doing so ensures that the ID can later be released in the 1227 + * event that all snapshots using it have been destroyed. 1228 + * 1229 + * @devlink: devlink 1230 + * @id: id to release reference on 1231 + */ 1232 + void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id) 1233 + { 1234 + __devlink_snapshot_id_decrement(devlink, id); 1235 + } 1236 + EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put); 1237 + 1238 + /** 1239 + * devlink_region_snapshot_create - create a new snapshot 1240 + * This will add a new snapshot of a region. The snapshot 1241 + * will be stored on the region struct and can be accessed 1242 + * from devlink. This is useful for future analyses of snapshots. 1243 + * Multiple snapshots can be created on a region. 1244 + * The @snapshot_id should be obtained using the getter function. 1245 + * 1246 + * @region: devlink region of the snapshot 1247 + * @data: snapshot data 1248 + * @snapshot_id: snapshot id to be created 1249 + */ 1250 + int devlink_region_snapshot_create(struct devlink_region *region, 1251 + u8 *data, u32 snapshot_id) 1252 + { 1253 + int err; 1254 + 1255 + mutex_lock(&region->snapshot_lock); 1256 + err = __devlink_region_snapshot_create(region, data, snapshot_id); 1257 + mutex_unlock(&region->snapshot_lock); 1258 + return err; 1259 + } 1260 + EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
+579
net/devlink/resource.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + /** 10 + * struct devlink_resource - devlink resource 11 + * @name: name of the resource 12 + * @id: id, per devlink instance 13 + * @size: size of the resource 14 + * @size_new: updated size of the resource, reload is needed 15 + * @size_valid: valid in case the total size of the resource is valid 16 + * including its children 17 + * @parent: parent resource 18 + * @size_params: size parameters 19 + * @list: parent list 20 + * @resource_list: list of child resources 21 + * @occ_get: occupancy getter callback 22 + * @occ_get_priv: occupancy getter callback priv 23 + */ 24 + struct devlink_resource { 25 + const char *name; 26 + u64 id; 27 + u64 size; 28 + u64 size_new; 29 + bool size_valid; 30 + struct devlink_resource *parent; 31 + struct devlink_resource_size_params size_params; 32 + struct list_head list; 33 + struct list_head resource_list; 34 + devlink_resource_occ_get_t *occ_get; 35 + void *occ_get_priv; 36 + }; 37 + 38 + static struct devlink_resource * 39 + devlink_resource_find(struct devlink *devlink, 40 + struct devlink_resource *resource, u64 resource_id) 41 + { 42 + struct list_head *resource_list; 43 + 44 + if (resource) 45 + resource_list = &resource->resource_list; 46 + else 47 + resource_list = &devlink->resource_list; 48 + 49 + list_for_each_entry(resource, resource_list, list) { 50 + struct devlink_resource *child_resource; 51 + 52 + if (resource->id == resource_id) 53 + return resource; 54 + 55 + child_resource = devlink_resource_find(devlink, resource, 56 + resource_id); 57 + if (child_resource) 58 + return child_resource; 59 + } 60 + return NULL; 61 + } 62 + 63 + static void 64 + devlink_resource_validate_children(struct devlink_resource *resource) 65 + { 66 + struct devlink_resource *child_resource; 67 + bool size_valid = true; 68 + u64 parts_size = 0; 69 + 70 + if (list_empty(&resource->resource_list)) 71 + goto out; 72 + 73 + list_for_each_entry(child_resource, &resource->resource_list, list) 74 + parts_size += child_resource->size_new; 75 + 76 + if (parts_size > resource->size_new) 77 + size_valid = false; 78 + out: 79 + resource->size_valid = size_valid; 80 + } 81 + 82 + static int 83 + devlink_resource_validate_size(struct devlink_resource *resource, u64 size, 84 + struct netlink_ext_ack *extack) 85 + { 86 + u64 reminder; 87 + int err = 0; 88 + 89 + if (size > resource->size_params.size_max) { 90 + NL_SET_ERR_MSG(extack, "Size larger than maximum"); 91 + err = -EINVAL; 92 + } 93 + 94 + if (size < resource->size_params.size_min) { 95 + NL_SET_ERR_MSG(extack, "Size smaller than minimum"); 96 + err = -EINVAL; 97 + } 98 + 99 + div64_u64_rem(size, resource->size_params.size_granularity, &reminder); 100 + if (reminder) { 101 + NL_SET_ERR_MSG(extack, "Wrong granularity"); 102 + err = -EINVAL; 103 + } 104 + 105 + return err; 106 + } 107 + 108 + int devlink_nl_cmd_resource_set(struct sk_buff *skb, struct genl_info *info) 109 + { 110 + struct devlink *devlink = info->user_ptr[0]; 111 + struct devlink_resource *resource; 112 + u64 resource_id; 113 + u64 size; 114 + int err; 115 + 116 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_ID) || 117 + GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_SIZE)) 118 + return -EINVAL; 119 + resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 120 + 121 + resource = devlink_resource_find(devlink, NULL, resource_id); 122 + if (!resource) 123 + return -EINVAL; 124 + 125 + size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 126 + err = devlink_resource_validate_size(resource, size, info->extack); 127 + if (err) 128 + return err; 129 + 130 + resource->size_new = size; 131 + devlink_resource_validate_children(resource); 132 + if (resource->parent) 133 + devlink_resource_validate_children(resource->parent); 134 + return 0; 135 + } 136 + 137 + static int 138 + devlink_resource_size_params_put(struct devlink_resource *resource, 139 + struct sk_buff *skb) 140 + { 141 + struct devlink_resource_size_params *size_params; 142 + 143 + size_params = &resource->size_params; 144 + if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 145 + size_params->size_granularity, DEVLINK_ATTR_PAD) || 146 + nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 147 + size_params->size_max, DEVLINK_ATTR_PAD) || 148 + nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 149 + size_params->size_min, DEVLINK_ATTR_PAD) || 150 + nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 151 + return -EMSGSIZE; 152 + return 0; 153 + } 154 + 155 + static int devlink_resource_occ_put(struct devlink_resource *resource, 156 + struct sk_buff *skb) 157 + { 158 + if (!resource->occ_get) 159 + return 0; 160 + return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 161 + resource->occ_get(resource->occ_get_priv), 162 + DEVLINK_ATTR_PAD); 163 + } 164 + 165 + static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 166 + struct devlink_resource *resource) 167 + { 168 + struct devlink_resource *child_resource; 169 + struct nlattr *child_resource_attr; 170 + struct nlattr *resource_attr; 171 + 172 + resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE); 173 + if (!resource_attr) 174 + return -EMSGSIZE; 175 + 176 + if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 177 + nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 178 + DEVLINK_ATTR_PAD) || 179 + nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 180 + DEVLINK_ATTR_PAD)) 181 + goto nla_put_failure; 182 + if (resource->size != resource->size_new && 183 + nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 184 + resource->size_new, DEVLINK_ATTR_PAD)) 185 + goto nla_put_failure; 186 + if (devlink_resource_occ_put(resource, skb)) 187 + goto nla_put_failure; 188 + if (devlink_resource_size_params_put(resource, skb)) 189 + goto nla_put_failure; 190 + if (list_empty(&resource->resource_list)) 191 + goto out; 192 + 193 + if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 194 + resource->size_valid)) 195 + goto nla_put_failure; 196 + 197 + child_resource_attr = nla_nest_start_noflag(skb, 198 + DEVLINK_ATTR_RESOURCE_LIST); 199 + if (!child_resource_attr) 200 + goto nla_put_failure; 201 + 202 + list_for_each_entry(child_resource, &resource->resource_list, list) { 203 + if (devlink_resource_put(devlink, skb, child_resource)) 204 + goto resource_put_failure; 205 + } 206 + 207 + nla_nest_end(skb, child_resource_attr); 208 + out: 209 + nla_nest_end(skb, resource_attr); 210 + return 0; 211 + 212 + resource_put_failure: 213 + nla_nest_cancel(skb, child_resource_attr); 214 + nla_put_failure: 215 + nla_nest_cancel(skb, resource_attr); 216 + return -EMSGSIZE; 217 + } 218 + 219 + static int devlink_resource_fill(struct genl_info *info, 220 + enum devlink_command cmd, int flags) 221 + { 222 + struct devlink *devlink = info->user_ptr[0]; 223 + struct devlink_resource *resource; 224 + struct nlattr *resources_attr; 225 + struct sk_buff *skb = NULL; 226 + struct nlmsghdr *nlh; 227 + bool incomplete; 228 + void *hdr; 229 + int i; 230 + int err; 231 + 232 + resource = list_first_entry(&devlink->resource_list, 233 + struct devlink_resource, list); 234 + start_again: 235 + err = devlink_nl_msg_reply_and_new(&skb, info); 236 + if (err) 237 + return err; 238 + 239 + hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 240 + &devlink_nl_family, NLM_F_MULTI, cmd); 241 + if (!hdr) { 242 + nlmsg_free(skb); 243 + return -EMSGSIZE; 244 + } 245 + 246 + if (devlink_nl_put_handle(skb, devlink)) 247 + goto nla_put_failure; 248 + 249 + resources_attr = nla_nest_start_noflag(skb, 250 + DEVLINK_ATTR_RESOURCE_LIST); 251 + if (!resources_attr) 252 + goto nla_put_failure; 253 + 254 + incomplete = false; 255 + i = 0; 256 + list_for_each_entry_from(resource, &devlink->resource_list, list) { 257 + err = devlink_resource_put(devlink, skb, resource); 258 + if (err) { 259 + if (!i) 260 + goto err_resource_put; 261 + incomplete = true; 262 + break; 263 + } 264 + i++; 265 + } 266 + nla_nest_end(skb, resources_attr); 267 + genlmsg_end(skb, hdr); 268 + if (incomplete) 269 + goto start_again; 270 + send_done: 271 + nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 272 + NLMSG_DONE, 0, flags | NLM_F_MULTI); 273 + if (!nlh) { 274 + err = devlink_nl_msg_reply_and_new(&skb, info); 275 + if (err) 276 + return err; 277 + goto send_done; 278 + } 279 + return genlmsg_reply(skb, info); 280 + 281 + nla_put_failure: 282 + err = -EMSGSIZE; 283 + err_resource_put: 284 + nlmsg_free(skb); 285 + return err; 286 + } 287 + 288 + int devlink_nl_cmd_resource_dump(struct sk_buff *skb, struct genl_info *info) 289 + { 290 + struct devlink *devlink = info->user_ptr[0]; 291 + 292 + if (list_empty(&devlink->resource_list)) 293 + return -EOPNOTSUPP; 294 + 295 + return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 296 + } 297 + 298 + int devlink_resources_validate(struct devlink *devlink, 299 + struct devlink_resource *resource, 300 + struct genl_info *info) 301 + { 302 + struct list_head *resource_list; 303 + int err = 0; 304 + 305 + if (resource) 306 + resource_list = &resource->resource_list; 307 + else 308 + resource_list = &devlink->resource_list; 309 + 310 + list_for_each_entry(resource, resource_list, list) { 311 + if (!resource->size_valid) 312 + return -EINVAL; 313 + err = devlink_resources_validate(devlink, resource, info); 314 + if (err) 315 + return err; 316 + } 317 + return err; 318 + } 319 + 320 + /** 321 + * devl_resource_register - devlink resource register 322 + * 323 + * @devlink: devlink 324 + * @resource_name: resource's name 325 + * @resource_size: resource's size 326 + * @resource_id: resource's id 327 + * @parent_resource_id: resource's parent id 328 + * @size_params: size parameters 329 + * 330 + * Generic resources should reuse the same names across drivers. 331 + * Please see the generic resources list at: 332 + * Documentation/networking/devlink/devlink-resource.rst 333 + */ 334 + int devl_resource_register(struct devlink *devlink, 335 + const char *resource_name, 336 + u64 resource_size, 337 + u64 resource_id, 338 + u64 parent_resource_id, 339 + const struct devlink_resource_size_params *size_params) 340 + { 341 + struct devlink_resource *resource; 342 + struct list_head *resource_list; 343 + bool top_hierarchy; 344 + 345 + lockdep_assert_held(&devlink->lock); 346 + 347 + top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 348 + 349 + resource = devlink_resource_find(devlink, NULL, resource_id); 350 + if (resource) 351 + return -EINVAL; 352 + 353 + resource = kzalloc(sizeof(*resource), GFP_KERNEL); 354 + if (!resource) 355 + return -ENOMEM; 356 + 357 + if (top_hierarchy) { 358 + resource_list = &devlink->resource_list; 359 + } else { 360 + struct devlink_resource *parent_resource; 361 + 362 + parent_resource = devlink_resource_find(devlink, NULL, 363 + parent_resource_id); 364 + if (parent_resource) { 365 + resource_list = &parent_resource->resource_list; 366 + resource->parent = parent_resource; 367 + } else { 368 + kfree(resource); 369 + return -EINVAL; 370 + } 371 + } 372 + 373 + resource->name = resource_name; 374 + resource->size = resource_size; 375 + resource->size_new = resource_size; 376 + resource->id = resource_id; 377 + resource->size_valid = true; 378 + memcpy(&resource->size_params, size_params, 379 + sizeof(resource->size_params)); 380 + INIT_LIST_HEAD(&resource->resource_list); 381 + list_add_tail(&resource->list, resource_list); 382 + 383 + return 0; 384 + } 385 + EXPORT_SYMBOL_GPL(devl_resource_register); 386 + 387 + /** 388 + * devlink_resource_register - devlink resource register 389 + * 390 + * @devlink: devlink 391 + * @resource_name: resource's name 392 + * @resource_size: resource's size 393 + * @resource_id: resource's id 394 + * @parent_resource_id: resource's parent id 395 + * @size_params: size parameters 396 + * 397 + * Generic resources should reuse the same names across drivers. 398 + * Please see the generic resources list at: 399 + * Documentation/networking/devlink/devlink-resource.rst 400 + * 401 + * Context: Takes and release devlink->lock <mutex>. 402 + */ 403 + int devlink_resource_register(struct devlink *devlink, 404 + const char *resource_name, 405 + u64 resource_size, 406 + u64 resource_id, 407 + u64 parent_resource_id, 408 + const struct devlink_resource_size_params *size_params) 409 + { 410 + int err; 411 + 412 + devl_lock(devlink); 413 + err = devl_resource_register(devlink, resource_name, resource_size, 414 + resource_id, parent_resource_id, size_params); 415 + devl_unlock(devlink); 416 + return err; 417 + } 418 + EXPORT_SYMBOL_GPL(devlink_resource_register); 419 + 420 + static void devlink_resource_unregister(struct devlink *devlink, 421 + struct devlink_resource *resource) 422 + { 423 + struct devlink_resource *tmp, *child_resource; 424 + 425 + list_for_each_entry_safe(child_resource, tmp, &resource->resource_list, 426 + list) { 427 + devlink_resource_unregister(devlink, child_resource); 428 + list_del(&child_resource->list); 429 + kfree(child_resource); 430 + } 431 + } 432 + 433 + /** 434 + * devl_resources_unregister - free all resources 435 + * 436 + * @devlink: devlink 437 + */ 438 + void devl_resources_unregister(struct devlink *devlink) 439 + { 440 + struct devlink_resource *tmp, *child_resource; 441 + 442 + lockdep_assert_held(&devlink->lock); 443 + 444 + list_for_each_entry_safe(child_resource, tmp, &devlink->resource_list, 445 + list) { 446 + devlink_resource_unregister(devlink, child_resource); 447 + list_del(&child_resource->list); 448 + kfree(child_resource); 449 + } 450 + } 451 + EXPORT_SYMBOL_GPL(devl_resources_unregister); 452 + 453 + /** 454 + * devlink_resources_unregister - free all resources 455 + * 456 + * @devlink: devlink 457 + * 458 + * Context: Takes and release devlink->lock <mutex>. 459 + */ 460 + void devlink_resources_unregister(struct devlink *devlink) 461 + { 462 + devl_lock(devlink); 463 + devl_resources_unregister(devlink); 464 + devl_unlock(devlink); 465 + } 466 + EXPORT_SYMBOL_GPL(devlink_resources_unregister); 467 + 468 + /** 469 + * devl_resource_size_get - get and update size 470 + * 471 + * @devlink: devlink 472 + * @resource_id: the requested resource id 473 + * @p_resource_size: ptr to update 474 + */ 475 + int devl_resource_size_get(struct devlink *devlink, 476 + u64 resource_id, 477 + u64 *p_resource_size) 478 + { 479 + struct devlink_resource *resource; 480 + 481 + lockdep_assert_held(&devlink->lock); 482 + 483 + resource = devlink_resource_find(devlink, NULL, resource_id); 484 + if (!resource) 485 + return -EINVAL; 486 + *p_resource_size = resource->size_new; 487 + resource->size = resource->size_new; 488 + return 0; 489 + } 490 + EXPORT_SYMBOL_GPL(devl_resource_size_get); 491 + 492 + /** 493 + * devl_resource_occ_get_register - register occupancy getter 494 + * 495 + * @devlink: devlink 496 + * @resource_id: resource id 497 + * @occ_get: occupancy getter callback 498 + * @occ_get_priv: occupancy getter callback priv 499 + */ 500 + void devl_resource_occ_get_register(struct devlink *devlink, 501 + u64 resource_id, 502 + devlink_resource_occ_get_t *occ_get, 503 + void *occ_get_priv) 504 + { 505 + struct devlink_resource *resource; 506 + 507 + lockdep_assert_held(&devlink->lock); 508 + 509 + resource = devlink_resource_find(devlink, NULL, resource_id); 510 + if (WARN_ON(!resource)) 511 + return; 512 + WARN_ON(resource->occ_get); 513 + 514 + resource->occ_get = occ_get; 515 + resource->occ_get_priv = occ_get_priv; 516 + } 517 + EXPORT_SYMBOL_GPL(devl_resource_occ_get_register); 518 + 519 + /** 520 + * devlink_resource_occ_get_register - register occupancy getter 521 + * 522 + * @devlink: devlink 523 + * @resource_id: resource id 524 + * @occ_get: occupancy getter callback 525 + * @occ_get_priv: occupancy getter callback priv 526 + * 527 + * Context: Takes and release devlink->lock <mutex>. 528 + */ 529 + void devlink_resource_occ_get_register(struct devlink *devlink, 530 + u64 resource_id, 531 + devlink_resource_occ_get_t *occ_get, 532 + void *occ_get_priv) 533 + { 534 + devl_lock(devlink); 535 + devl_resource_occ_get_register(devlink, resource_id, 536 + occ_get, occ_get_priv); 537 + devl_unlock(devlink); 538 + } 539 + EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 540 + 541 + /** 542 + * devl_resource_occ_get_unregister - unregister occupancy getter 543 + * 544 + * @devlink: devlink 545 + * @resource_id: resource id 546 + */ 547 + void devl_resource_occ_get_unregister(struct devlink *devlink, 548 + u64 resource_id) 549 + { 550 + struct devlink_resource *resource; 551 + 552 + lockdep_assert_held(&devlink->lock); 553 + 554 + resource = devlink_resource_find(devlink, NULL, resource_id); 555 + if (WARN_ON(!resource)) 556 + return; 557 + WARN_ON(!resource->occ_get); 558 + 559 + resource->occ_get = NULL; 560 + resource->occ_get_priv = NULL; 561 + } 562 + EXPORT_SYMBOL_GPL(devl_resource_occ_get_unregister); 563 + 564 + /** 565 + * devlink_resource_occ_get_unregister - unregister occupancy getter 566 + * 567 + * @devlink: devlink 568 + * @resource_id: resource id 569 + * 570 + * Context: Takes and release devlink->lock <mutex>. 571 + */ 572 + void devlink_resource_occ_get_unregister(struct devlink *devlink, 573 + u64 resource_id) 574 + { 575 + devl_lock(devlink); 576 + devl_resource_occ_get_unregister(devlink, resource_id); 577 + devl_unlock(devlink); 578 + } 579 + EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
+996
net/devlink/sb.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include "devl_internal.h" 8 + 9 + struct devlink_sb { 10 + struct list_head list; 11 + unsigned int index; 12 + u32 size; 13 + u16 ingress_pools_count; 14 + u16 egress_pools_count; 15 + u16 ingress_tc_count; 16 + u16 egress_tc_count; 17 + }; 18 + 19 + static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 20 + { 21 + return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 22 + } 23 + 24 + static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 25 + unsigned int sb_index) 26 + { 27 + struct devlink_sb *devlink_sb; 28 + 29 + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 30 + if (devlink_sb->index == sb_index) 31 + return devlink_sb; 32 + } 33 + return NULL; 34 + } 35 + 36 + static bool devlink_sb_index_exists(struct devlink *devlink, 37 + unsigned int sb_index) 38 + { 39 + return devlink_sb_get_by_index(devlink, sb_index); 40 + } 41 + 42 + static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 43 + struct nlattr **attrs) 44 + { 45 + if (attrs[DEVLINK_ATTR_SB_INDEX]) { 46 + u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 47 + struct devlink_sb *devlink_sb; 48 + 49 + devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 50 + if (!devlink_sb) 51 + return ERR_PTR(-ENODEV); 52 + return devlink_sb; 53 + } 54 + return ERR_PTR(-EINVAL); 55 + } 56 + 57 + static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 58 + struct genl_info *info) 59 + { 60 + return devlink_sb_get_from_attrs(devlink, info->attrs); 61 + } 62 + 63 + static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 64 + struct nlattr **attrs, 65 + u16 *p_pool_index) 66 + { 67 + u16 val; 68 + 69 + if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 70 + return -EINVAL; 71 + 72 + val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 73 + if (val >= devlink_sb_pool_count(devlink_sb)) 74 + return -EINVAL; 75 + *p_pool_index = val; 76 + return 0; 77 + } 78 + 79 + static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 80 + struct genl_info *info, 81 + u16 *p_pool_index) 82 + { 83 + return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 84 + p_pool_index); 85 + } 86 + 87 + static int 88 + devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 89 + enum devlink_sb_pool_type *p_pool_type) 90 + { 91 + u8 val; 92 + 93 + if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 94 + return -EINVAL; 95 + 96 + val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 97 + if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 98 + val != DEVLINK_SB_POOL_TYPE_EGRESS) 99 + return -EINVAL; 100 + *p_pool_type = val; 101 + return 0; 102 + } 103 + 104 + static int 105 + devlink_sb_pool_type_get_from_info(struct genl_info *info, 106 + enum devlink_sb_pool_type *p_pool_type) 107 + { 108 + return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 109 + } 110 + 111 + static int 112 + devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 113 + enum devlink_sb_threshold_type *p_th_type) 114 + { 115 + u8 val; 116 + 117 + if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 118 + return -EINVAL; 119 + 120 + val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 121 + if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 122 + val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 123 + return -EINVAL; 124 + *p_th_type = val; 125 + return 0; 126 + } 127 + 128 + static int 129 + devlink_sb_th_type_get_from_info(struct genl_info *info, 130 + enum devlink_sb_threshold_type *p_th_type) 131 + { 132 + return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 133 + } 134 + 135 + static int 136 + devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 137 + struct nlattr **attrs, 138 + enum devlink_sb_pool_type pool_type, 139 + u16 *p_tc_index) 140 + { 141 + u16 val; 142 + 143 + if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 144 + return -EINVAL; 145 + 146 + val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 147 + if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 148 + val >= devlink_sb->ingress_tc_count) 149 + return -EINVAL; 150 + if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 151 + val >= devlink_sb->egress_tc_count) 152 + return -EINVAL; 153 + *p_tc_index = val; 154 + return 0; 155 + } 156 + 157 + static int 158 + devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 159 + struct genl_info *info, 160 + enum devlink_sb_pool_type pool_type, 161 + u16 *p_tc_index) 162 + { 163 + return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 164 + pool_type, p_tc_index); 165 + } 166 + 167 + static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 168 + struct devlink_sb *devlink_sb, 169 + enum devlink_command cmd, u32 portid, 170 + u32 seq, int flags) 171 + { 172 + void *hdr; 173 + 174 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 175 + if (!hdr) 176 + return -EMSGSIZE; 177 + 178 + if (devlink_nl_put_handle(msg, devlink)) 179 + goto nla_put_failure; 180 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 181 + goto nla_put_failure; 182 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 183 + goto nla_put_failure; 184 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 185 + devlink_sb->ingress_pools_count)) 186 + goto nla_put_failure; 187 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 188 + devlink_sb->egress_pools_count)) 189 + goto nla_put_failure; 190 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 191 + devlink_sb->ingress_tc_count)) 192 + goto nla_put_failure; 193 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 194 + devlink_sb->egress_tc_count)) 195 + goto nla_put_failure; 196 + 197 + genlmsg_end(msg, hdr); 198 + return 0; 199 + 200 + nla_put_failure: 201 + genlmsg_cancel(msg, hdr); 202 + return -EMSGSIZE; 203 + } 204 + 205 + int devlink_nl_sb_get_doit(struct sk_buff *skb, struct genl_info *info) 206 + { 207 + struct devlink *devlink = info->user_ptr[0]; 208 + struct devlink_sb *devlink_sb; 209 + struct sk_buff *msg; 210 + int err; 211 + 212 + devlink_sb = devlink_sb_get_from_info(devlink, info); 213 + if (IS_ERR(devlink_sb)) 214 + return PTR_ERR(devlink_sb); 215 + 216 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 217 + if (!msg) 218 + return -ENOMEM; 219 + 220 + err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 221 + DEVLINK_CMD_SB_NEW, 222 + info->snd_portid, info->snd_seq, 0); 223 + if (err) { 224 + nlmsg_free(msg); 225 + return err; 226 + } 227 + 228 + return genlmsg_reply(msg, info); 229 + } 230 + 231 + static int 232 + devlink_nl_sb_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 233 + struct netlink_callback *cb, int flags) 234 + { 235 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 236 + struct devlink_sb *devlink_sb; 237 + int idx = 0; 238 + int err = 0; 239 + 240 + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 241 + if (idx < state->idx) { 242 + idx++; 243 + continue; 244 + } 245 + err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 246 + DEVLINK_CMD_SB_NEW, 247 + NETLINK_CB(cb->skb).portid, 248 + cb->nlh->nlmsg_seq, flags); 249 + if (err) { 250 + state->idx = idx; 251 + break; 252 + } 253 + idx++; 254 + } 255 + 256 + return err; 257 + } 258 + 259 + int devlink_nl_sb_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 260 + { 261 + return devlink_nl_dumpit(skb, cb, devlink_nl_sb_get_dump_one); 262 + } 263 + 264 + static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 265 + struct devlink_sb *devlink_sb, 266 + u16 pool_index, enum devlink_command cmd, 267 + u32 portid, u32 seq, int flags) 268 + { 269 + struct devlink_sb_pool_info pool_info; 270 + void *hdr; 271 + int err; 272 + 273 + err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 274 + pool_index, &pool_info); 275 + if (err) 276 + return err; 277 + 278 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 279 + if (!hdr) 280 + return -EMSGSIZE; 281 + 282 + if (devlink_nl_put_handle(msg, devlink)) 283 + goto nla_put_failure; 284 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 285 + goto nla_put_failure; 286 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 287 + goto nla_put_failure; 288 + if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 289 + goto nla_put_failure; 290 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 291 + goto nla_put_failure; 292 + if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 293 + pool_info.threshold_type)) 294 + goto nla_put_failure; 295 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE, 296 + pool_info.cell_size)) 297 + goto nla_put_failure; 298 + 299 + genlmsg_end(msg, hdr); 300 + return 0; 301 + 302 + nla_put_failure: 303 + genlmsg_cancel(msg, hdr); 304 + return -EMSGSIZE; 305 + } 306 + 307 + int devlink_nl_sb_pool_get_doit(struct sk_buff *skb, struct genl_info *info) 308 + { 309 + struct devlink *devlink = info->user_ptr[0]; 310 + struct devlink_sb *devlink_sb; 311 + struct sk_buff *msg; 312 + u16 pool_index; 313 + int err; 314 + 315 + devlink_sb = devlink_sb_get_from_info(devlink, info); 316 + if (IS_ERR(devlink_sb)) 317 + return PTR_ERR(devlink_sb); 318 + 319 + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 320 + &pool_index); 321 + if (err) 322 + return err; 323 + 324 + if (!devlink->ops->sb_pool_get) 325 + return -EOPNOTSUPP; 326 + 327 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 328 + if (!msg) 329 + return -ENOMEM; 330 + 331 + err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 332 + DEVLINK_CMD_SB_POOL_NEW, 333 + info->snd_portid, info->snd_seq, 0); 334 + if (err) { 335 + nlmsg_free(msg); 336 + return err; 337 + } 338 + 339 + return genlmsg_reply(msg, info); 340 + } 341 + 342 + static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 343 + struct devlink *devlink, 344 + struct devlink_sb *devlink_sb, 345 + u32 portid, u32 seq, int flags) 346 + { 347 + u16 pool_count = devlink_sb_pool_count(devlink_sb); 348 + u16 pool_index; 349 + int err; 350 + 351 + for (pool_index = 0; pool_index < pool_count; pool_index++) { 352 + if (*p_idx < start) { 353 + (*p_idx)++; 354 + continue; 355 + } 356 + err = devlink_nl_sb_pool_fill(msg, devlink, 357 + devlink_sb, 358 + pool_index, 359 + DEVLINK_CMD_SB_POOL_NEW, 360 + portid, seq, flags); 361 + if (err) 362 + return err; 363 + (*p_idx)++; 364 + } 365 + return 0; 366 + } 367 + 368 + static int 369 + devlink_nl_sb_pool_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 370 + struct netlink_callback *cb, int flags) 371 + { 372 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 373 + struct devlink_sb *devlink_sb; 374 + int err = 0; 375 + int idx = 0; 376 + 377 + if (!devlink->ops->sb_pool_get) 378 + return 0; 379 + 380 + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 381 + err = __sb_pool_get_dumpit(msg, state->idx, &idx, 382 + devlink, devlink_sb, 383 + NETLINK_CB(cb->skb).portid, 384 + cb->nlh->nlmsg_seq, flags); 385 + if (err == -EOPNOTSUPP) { 386 + err = 0; 387 + } else if (err) { 388 + state->idx = idx; 389 + break; 390 + } 391 + } 392 + 393 + return err; 394 + } 395 + 396 + int devlink_nl_sb_pool_get_dumpit(struct sk_buff *skb, 397 + struct netlink_callback *cb) 398 + { 399 + return devlink_nl_dumpit(skb, cb, devlink_nl_sb_pool_get_dump_one); 400 + } 401 + 402 + static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 403 + u16 pool_index, u32 size, 404 + enum devlink_sb_threshold_type threshold_type, 405 + struct netlink_ext_ack *extack) 406 + 407 + { 408 + const struct devlink_ops *ops = devlink->ops; 409 + 410 + if (ops->sb_pool_set) 411 + return ops->sb_pool_set(devlink, sb_index, pool_index, 412 + size, threshold_type, extack); 413 + return -EOPNOTSUPP; 414 + } 415 + 416 + int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, struct genl_info *info) 417 + { 418 + struct devlink *devlink = info->user_ptr[0]; 419 + enum devlink_sb_threshold_type threshold_type; 420 + struct devlink_sb *devlink_sb; 421 + u16 pool_index; 422 + u32 size; 423 + int err; 424 + 425 + devlink_sb = devlink_sb_get_from_info(devlink, info); 426 + if (IS_ERR(devlink_sb)) 427 + return PTR_ERR(devlink_sb); 428 + 429 + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 430 + &pool_index); 431 + if (err) 432 + return err; 433 + 434 + err = devlink_sb_th_type_get_from_info(info, &threshold_type); 435 + if (err) 436 + return err; 437 + 438 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE)) 439 + return -EINVAL; 440 + 441 + size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 442 + return devlink_sb_pool_set(devlink, devlink_sb->index, 443 + pool_index, size, threshold_type, 444 + info->extack); 445 + } 446 + 447 + static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 448 + struct devlink *devlink, 449 + struct devlink_port *devlink_port, 450 + struct devlink_sb *devlink_sb, 451 + u16 pool_index, 452 + enum devlink_command cmd, 453 + u32 portid, u32 seq, int flags) 454 + { 455 + const struct devlink_ops *ops = devlink->ops; 456 + u32 threshold; 457 + void *hdr; 458 + int err; 459 + 460 + err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 461 + pool_index, &threshold); 462 + if (err) 463 + return err; 464 + 465 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 466 + if (!hdr) 467 + return -EMSGSIZE; 468 + 469 + if (devlink_nl_put_handle(msg, devlink)) 470 + goto nla_put_failure; 471 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 472 + goto nla_put_failure; 473 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 474 + goto nla_put_failure; 475 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 476 + goto nla_put_failure; 477 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 478 + goto nla_put_failure; 479 + 480 + if (ops->sb_occ_port_pool_get) { 481 + u32 cur; 482 + u32 max; 483 + 484 + err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 485 + pool_index, &cur, &max); 486 + if (err && err != -EOPNOTSUPP) 487 + goto sb_occ_get_failure; 488 + if (!err) { 489 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 490 + goto nla_put_failure; 491 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 492 + goto nla_put_failure; 493 + } 494 + } 495 + 496 + genlmsg_end(msg, hdr); 497 + return 0; 498 + 499 + nla_put_failure: 500 + err = -EMSGSIZE; 501 + sb_occ_get_failure: 502 + genlmsg_cancel(msg, hdr); 503 + return err; 504 + } 505 + 506 + int devlink_nl_sb_port_pool_get_doit(struct sk_buff *skb, 507 + struct genl_info *info) 508 + { 509 + struct devlink_port *devlink_port = info->user_ptr[1]; 510 + struct devlink *devlink = devlink_port->devlink; 511 + struct devlink_sb *devlink_sb; 512 + struct sk_buff *msg; 513 + u16 pool_index; 514 + int err; 515 + 516 + devlink_sb = devlink_sb_get_from_info(devlink, info); 517 + if (IS_ERR(devlink_sb)) 518 + return PTR_ERR(devlink_sb); 519 + 520 + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 521 + &pool_index); 522 + if (err) 523 + return err; 524 + 525 + if (!devlink->ops->sb_port_pool_get) 526 + return -EOPNOTSUPP; 527 + 528 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 529 + if (!msg) 530 + return -ENOMEM; 531 + 532 + err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 533 + devlink_sb, pool_index, 534 + DEVLINK_CMD_SB_PORT_POOL_NEW, 535 + info->snd_portid, info->snd_seq, 0); 536 + if (err) { 537 + nlmsg_free(msg); 538 + return err; 539 + } 540 + 541 + return genlmsg_reply(msg, info); 542 + } 543 + 544 + static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 545 + struct devlink *devlink, 546 + struct devlink_sb *devlink_sb, 547 + u32 portid, u32 seq, int flags) 548 + { 549 + struct devlink_port *devlink_port; 550 + u16 pool_count = devlink_sb_pool_count(devlink_sb); 551 + unsigned long port_index; 552 + u16 pool_index; 553 + int err; 554 + 555 + xa_for_each(&devlink->ports, port_index, devlink_port) { 556 + for (pool_index = 0; pool_index < pool_count; pool_index++) { 557 + if (*p_idx < start) { 558 + (*p_idx)++; 559 + continue; 560 + } 561 + err = devlink_nl_sb_port_pool_fill(msg, devlink, 562 + devlink_port, 563 + devlink_sb, 564 + pool_index, 565 + DEVLINK_CMD_SB_PORT_POOL_NEW, 566 + portid, seq, flags); 567 + if (err) 568 + return err; 569 + (*p_idx)++; 570 + } 571 + } 572 + return 0; 573 + } 574 + 575 + static int 576 + devlink_nl_sb_port_pool_get_dump_one(struct sk_buff *msg, 577 + struct devlink *devlink, 578 + struct netlink_callback *cb, int flags) 579 + { 580 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 581 + struct devlink_sb *devlink_sb; 582 + int idx = 0; 583 + int err = 0; 584 + 585 + if (!devlink->ops->sb_port_pool_get) 586 + return 0; 587 + 588 + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 589 + err = __sb_port_pool_get_dumpit(msg, state->idx, &idx, 590 + devlink, devlink_sb, 591 + NETLINK_CB(cb->skb).portid, 592 + cb->nlh->nlmsg_seq, flags); 593 + if (err == -EOPNOTSUPP) { 594 + err = 0; 595 + } else if (err) { 596 + state->idx = idx; 597 + break; 598 + } 599 + } 600 + 601 + return err; 602 + } 603 + 604 + int devlink_nl_sb_port_pool_get_dumpit(struct sk_buff *skb, 605 + struct netlink_callback *cb) 606 + { 607 + return devlink_nl_dumpit(skb, cb, devlink_nl_sb_port_pool_get_dump_one); 608 + } 609 + 610 + static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 611 + unsigned int sb_index, u16 pool_index, 612 + u32 threshold, 613 + struct netlink_ext_ack *extack) 614 + 615 + { 616 + const struct devlink_ops *ops = devlink_port->devlink->ops; 617 + 618 + if (ops->sb_port_pool_set) 619 + return ops->sb_port_pool_set(devlink_port, sb_index, 620 + pool_index, threshold, extack); 621 + return -EOPNOTSUPP; 622 + } 623 + 624 + int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 625 + struct genl_info *info) 626 + { 627 + struct devlink_port *devlink_port = info->user_ptr[1]; 628 + struct devlink *devlink = info->user_ptr[0]; 629 + struct devlink_sb *devlink_sb; 630 + u16 pool_index; 631 + u32 threshold; 632 + int err; 633 + 634 + devlink_sb = devlink_sb_get_from_info(devlink, info); 635 + if (IS_ERR(devlink_sb)) 636 + return PTR_ERR(devlink_sb); 637 + 638 + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 639 + &pool_index); 640 + if (err) 641 + return err; 642 + 643 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD)) 644 + return -EINVAL; 645 + 646 + threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 647 + return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 648 + pool_index, threshold, info->extack); 649 + } 650 + 651 + static int 652 + devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 653 + struct devlink_port *devlink_port, 654 + struct devlink_sb *devlink_sb, u16 tc_index, 655 + enum devlink_sb_pool_type pool_type, 656 + enum devlink_command cmd, 657 + u32 portid, u32 seq, int flags) 658 + { 659 + const struct devlink_ops *ops = devlink->ops; 660 + u16 pool_index; 661 + u32 threshold; 662 + void *hdr; 663 + int err; 664 + 665 + err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 666 + tc_index, pool_type, 667 + &pool_index, &threshold); 668 + if (err) 669 + return err; 670 + 671 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 672 + if (!hdr) 673 + return -EMSGSIZE; 674 + 675 + if (devlink_nl_put_handle(msg, devlink)) 676 + goto nla_put_failure; 677 + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 678 + goto nla_put_failure; 679 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 680 + goto nla_put_failure; 681 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 682 + goto nla_put_failure; 683 + if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 684 + goto nla_put_failure; 685 + if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 686 + goto nla_put_failure; 687 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 688 + goto nla_put_failure; 689 + 690 + if (ops->sb_occ_tc_port_bind_get) { 691 + u32 cur; 692 + u32 max; 693 + 694 + err = ops->sb_occ_tc_port_bind_get(devlink_port, 695 + devlink_sb->index, 696 + tc_index, pool_type, 697 + &cur, &max); 698 + if (err && err != -EOPNOTSUPP) 699 + return err; 700 + if (!err) { 701 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 702 + goto nla_put_failure; 703 + if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 704 + goto nla_put_failure; 705 + } 706 + } 707 + 708 + genlmsg_end(msg, hdr); 709 + return 0; 710 + 711 + nla_put_failure: 712 + genlmsg_cancel(msg, hdr); 713 + return -EMSGSIZE; 714 + } 715 + 716 + int devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 717 + struct genl_info *info) 718 + { 719 + struct devlink_port *devlink_port = info->user_ptr[1]; 720 + struct devlink *devlink = devlink_port->devlink; 721 + struct devlink_sb *devlink_sb; 722 + struct sk_buff *msg; 723 + enum devlink_sb_pool_type pool_type; 724 + u16 tc_index; 725 + int err; 726 + 727 + devlink_sb = devlink_sb_get_from_info(devlink, info); 728 + if (IS_ERR(devlink_sb)) 729 + return PTR_ERR(devlink_sb); 730 + 731 + err = devlink_sb_pool_type_get_from_info(info, &pool_type); 732 + if (err) 733 + return err; 734 + 735 + err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 736 + pool_type, &tc_index); 737 + if (err) 738 + return err; 739 + 740 + if (!devlink->ops->sb_tc_pool_bind_get) 741 + return -EOPNOTSUPP; 742 + 743 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 744 + if (!msg) 745 + return -ENOMEM; 746 + 747 + err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 748 + devlink_sb, tc_index, pool_type, 749 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 750 + info->snd_portid, 751 + info->snd_seq, 0); 752 + if (err) { 753 + nlmsg_free(msg); 754 + return err; 755 + } 756 + 757 + return genlmsg_reply(msg, info); 758 + } 759 + 760 + static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 761 + int start, int *p_idx, 762 + struct devlink *devlink, 763 + struct devlink_sb *devlink_sb, 764 + u32 portid, u32 seq, int flags) 765 + { 766 + struct devlink_port *devlink_port; 767 + unsigned long port_index; 768 + u16 tc_index; 769 + int err; 770 + 771 + xa_for_each(&devlink->ports, port_index, devlink_port) { 772 + for (tc_index = 0; 773 + tc_index < devlink_sb->ingress_tc_count; tc_index++) { 774 + if (*p_idx < start) { 775 + (*p_idx)++; 776 + continue; 777 + } 778 + err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 779 + devlink_port, 780 + devlink_sb, 781 + tc_index, 782 + DEVLINK_SB_POOL_TYPE_INGRESS, 783 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 784 + portid, seq, 785 + flags); 786 + if (err) 787 + return err; 788 + (*p_idx)++; 789 + } 790 + for (tc_index = 0; 791 + tc_index < devlink_sb->egress_tc_count; tc_index++) { 792 + if (*p_idx < start) { 793 + (*p_idx)++; 794 + continue; 795 + } 796 + err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 797 + devlink_port, 798 + devlink_sb, 799 + tc_index, 800 + DEVLINK_SB_POOL_TYPE_EGRESS, 801 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 802 + portid, seq, 803 + flags); 804 + if (err) 805 + return err; 806 + (*p_idx)++; 807 + } 808 + } 809 + return 0; 810 + } 811 + 812 + static int devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff *msg, 813 + struct devlink *devlink, 814 + struct netlink_callback *cb, 815 + int flags) 816 + { 817 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 818 + struct devlink_sb *devlink_sb; 819 + int idx = 0; 820 + int err = 0; 821 + 822 + if (!devlink->ops->sb_tc_pool_bind_get) 823 + return 0; 824 + 825 + list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 826 + err = __sb_tc_pool_bind_get_dumpit(msg, state->idx, &idx, 827 + devlink, devlink_sb, 828 + NETLINK_CB(cb->skb).portid, 829 + cb->nlh->nlmsg_seq, flags); 830 + if (err == -EOPNOTSUPP) { 831 + err = 0; 832 + } else if (err) { 833 + state->idx = idx; 834 + break; 835 + } 836 + } 837 + 838 + return err; 839 + } 840 + 841 + int devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff *skb, 842 + struct netlink_callback *cb) 843 + { 844 + return devlink_nl_dumpit(skb, cb, 845 + devlink_nl_sb_tc_pool_bind_get_dump_one); 846 + } 847 + 848 + static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 849 + unsigned int sb_index, u16 tc_index, 850 + enum devlink_sb_pool_type pool_type, 851 + u16 pool_index, u32 threshold, 852 + struct netlink_ext_ack *extack) 853 + 854 + { 855 + const struct devlink_ops *ops = devlink_port->devlink->ops; 856 + 857 + if (ops->sb_tc_pool_bind_set) 858 + return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 859 + tc_index, pool_type, 860 + pool_index, threshold, extack); 861 + return -EOPNOTSUPP; 862 + } 863 + 864 + int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 865 + struct genl_info *info) 866 + { 867 + struct devlink_port *devlink_port = info->user_ptr[1]; 868 + struct devlink *devlink = info->user_ptr[0]; 869 + enum devlink_sb_pool_type pool_type; 870 + struct devlink_sb *devlink_sb; 871 + u16 tc_index; 872 + u16 pool_index; 873 + u32 threshold; 874 + int err; 875 + 876 + devlink_sb = devlink_sb_get_from_info(devlink, info); 877 + if (IS_ERR(devlink_sb)) 878 + return PTR_ERR(devlink_sb); 879 + 880 + err = devlink_sb_pool_type_get_from_info(info, &pool_type); 881 + if (err) 882 + return err; 883 + 884 + err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 885 + pool_type, &tc_index); 886 + if (err) 887 + return err; 888 + 889 + err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 890 + &pool_index); 891 + if (err) 892 + return err; 893 + 894 + if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD)) 895 + return -EINVAL; 896 + 897 + threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 898 + return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 899 + tc_index, pool_type, 900 + pool_index, threshold, info->extack); 901 + } 902 + 903 + int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 904 + struct genl_info *info) 905 + { 906 + struct devlink *devlink = info->user_ptr[0]; 907 + const struct devlink_ops *ops = devlink->ops; 908 + struct devlink_sb *devlink_sb; 909 + 910 + devlink_sb = devlink_sb_get_from_info(devlink, info); 911 + if (IS_ERR(devlink_sb)) 912 + return PTR_ERR(devlink_sb); 913 + 914 + if (ops->sb_occ_snapshot) 915 + return ops->sb_occ_snapshot(devlink, devlink_sb->index); 916 + return -EOPNOTSUPP; 917 + } 918 + 919 + int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 920 + struct genl_info *info) 921 + { 922 + struct devlink *devlink = info->user_ptr[0]; 923 + const struct devlink_ops *ops = devlink->ops; 924 + struct devlink_sb *devlink_sb; 925 + 926 + devlink_sb = devlink_sb_get_from_info(devlink, info); 927 + if (IS_ERR(devlink_sb)) 928 + return PTR_ERR(devlink_sb); 929 + 930 + if (ops->sb_occ_max_clear) 931 + return ops->sb_occ_max_clear(devlink, devlink_sb->index); 932 + return -EOPNOTSUPP; 933 + } 934 + 935 + int devl_sb_register(struct devlink *devlink, unsigned int sb_index, 936 + u32 size, u16 ingress_pools_count, 937 + u16 egress_pools_count, u16 ingress_tc_count, 938 + u16 egress_tc_count) 939 + { 940 + struct devlink_sb *devlink_sb; 941 + 942 + lockdep_assert_held(&devlink->lock); 943 + 944 + if (devlink_sb_index_exists(devlink, sb_index)) 945 + return -EEXIST; 946 + 947 + devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 948 + if (!devlink_sb) 949 + return -ENOMEM; 950 + devlink_sb->index = sb_index; 951 + devlink_sb->size = size; 952 + devlink_sb->ingress_pools_count = ingress_pools_count; 953 + devlink_sb->egress_pools_count = egress_pools_count; 954 + devlink_sb->ingress_tc_count = ingress_tc_count; 955 + devlink_sb->egress_tc_count = egress_tc_count; 956 + list_add_tail(&devlink_sb->list, &devlink->sb_list); 957 + return 0; 958 + } 959 + EXPORT_SYMBOL_GPL(devl_sb_register); 960 + 961 + int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 962 + u32 size, u16 ingress_pools_count, 963 + u16 egress_pools_count, u16 ingress_tc_count, 964 + u16 egress_tc_count) 965 + { 966 + int err; 967 + 968 + devl_lock(devlink); 969 + err = devl_sb_register(devlink, sb_index, size, ingress_pools_count, 970 + egress_pools_count, ingress_tc_count, 971 + egress_tc_count); 972 + devl_unlock(devlink); 973 + return err; 974 + } 975 + EXPORT_SYMBOL_GPL(devlink_sb_register); 976 + 977 + void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index) 978 + { 979 + struct devlink_sb *devlink_sb; 980 + 981 + lockdep_assert_held(&devlink->lock); 982 + 983 + devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 984 + WARN_ON(!devlink_sb); 985 + list_del(&devlink_sb->list); 986 + kfree(devlink_sb); 987 + } 988 + EXPORT_SYMBOL_GPL(devl_sb_unregister); 989 + 990 + void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 991 + { 992 + devl_lock(devlink); 993 + devl_sb_unregister(devlink, sb_index); 994 + devl_unlock(devlink); 995 + } 996 + EXPORT_SYMBOL_GPL(devlink_sb_unregister);
+1861
net/devlink/trap.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 + * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 + */ 6 + 7 + #include <trace/events/devlink.h> 8 + 9 + #include "devl_internal.h" 10 + 11 + struct devlink_stats { 12 + u64_stats_t rx_bytes; 13 + u64_stats_t rx_packets; 14 + struct u64_stats_sync syncp; 15 + }; 16 + 17 + /** 18 + * struct devlink_trap_policer_item - Packet trap policer attributes. 19 + * @policer: Immutable packet trap policer attributes. 20 + * @rate: Rate in packets / sec. 21 + * @burst: Burst size in packets. 22 + * @list: trap_policer_list member. 23 + * 24 + * Describes packet trap policer attributes. Created by devlink during trap 25 + * policer registration. 26 + */ 27 + struct devlink_trap_policer_item { 28 + const struct devlink_trap_policer *policer; 29 + u64 rate; 30 + u64 burst; 31 + struct list_head list; 32 + }; 33 + 34 + /** 35 + * struct devlink_trap_group_item - Packet trap group attributes. 36 + * @group: Immutable packet trap group attributes. 37 + * @policer_item: Associated policer item. Can be NULL. 38 + * @list: trap_group_list member. 39 + * @stats: Trap group statistics. 40 + * 41 + * Describes packet trap group attributes. Created by devlink during trap 42 + * group registration. 43 + */ 44 + struct devlink_trap_group_item { 45 + const struct devlink_trap_group *group; 46 + struct devlink_trap_policer_item *policer_item; 47 + struct list_head list; 48 + struct devlink_stats __percpu *stats; 49 + }; 50 + 51 + /** 52 + * struct devlink_trap_item - Packet trap attributes. 53 + * @trap: Immutable packet trap attributes. 54 + * @group_item: Associated group item. 55 + * @list: trap_list member. 56 + * @action: Trap action. 57 + * @stats: Trap statistics. 58 + * @priv: Driver private information. 59 + * 60 + * Describes both mutable and immutable packet trap attributes. Created by 61 + * devlink during trap registration and used for all trap related operations. 62 + */ 63 + struct devlink_trap_item { 64 + const struct devlink_trap *trap; 65 + struct devlink_trap_group_item *group_item; 66 + struct list_head list; 67 + enum devlink_trap_action action; 68 + struct devlink_stats __percpu *stats; 69 + void *priv; 70 + }; 71 + 72 + static struct devlink_trap_policer_item * 73 + devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id) 74 + { 75 + struct devlink_trap_policer_item *policer_item; 76 + 77 + list_for_each_entry(policer_item, &devlink->trap_policer_list, list) { 78 + if (policer_item->policer->id == id) 79 + return policer_item; 80 + } 81 + 82 + return NULL; 83 + } 84 + 85 + static struct devlink_trap_item * 86 + devlink_trap_item_lookup(struct devlink *devlink, const char *name) 87 + { 88 + struct devlink_trap_item *trap_item; 89 + 90 + list_for_each_entry(trap_item, &devlink->trap_list, list) { 91 + if (!strcmp(trap_item->trap->name, name)) 92 + return trap_item; 93 + } 94 + 95 + return NULL; 96 + } 97 + 98 + static struct devlink_trap_item * 99 + devlink_trap_item_get_from_info(struct devlink *devlink, 100 + struct genl_info *info) 101 + { 102 + struct nlattr *attr; 103 + 104 + if (!info->attrs[DEVLINK_ATTR_TRAP_NAME]) 105 + return NULL; 106 + attr = info->attrs[DEVLINK_ATTR_TRAP_NAME]; 107 + 108 + return devlink_trap_item_lookup(devlink, nla_data(attr)); 109 + } 110 + 111 + static int 112 + devlink_trap_action_get_from_info(struct genl_info *info, 113 + enum devlink_trap_action *p_trap_action) 114 + { 115 + u8 val; 116 + 117 + val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]); 118 + switch (val) { 119 + case DEVLINK_TRAP_ACTION_DROP: 120 + case DEVLINK_TRAP_ACTION_TRAP: 121 + case DEVLINK_TRAP_ACTION_MIRROR: 122 + *p_trap_action = val; 123 + break; 124 + default: 125 + return -EINVAL; 126 + } 127 + 128 + return 0; 129 + } 130 + 131 + static int devlink_trap_metadata_put(struct sk_buff *msg, 132 + const struct devlink_trap *trap) 133 + { 134 + struct nlattr *attr; 135 + 136 + attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA); 137 + if (!attr) 138 + return -EMSGSIZE; 139 + 140 + if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) && 141 + nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT)) 142 + goto nla_put_failure; 143 + if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) && 144 + nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE)) 145 + goto nla_put_failure; 146 + 147 + nla_nest_end(msg, attr); 148 + 149 + return 0; 150 + 151 + nla_put_failure: 152 + nla_nest_cancel(msg, attr); 153 + return -EMSGSIZE; 154 + } 155 + 156 + static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats, 157 + struct devlink_stats *stats) 158 + { 159 + int i; 160 + 161 + memset(stats, 0, sizeof(*stats)); 162 + for_each_possible_cpu(i) { 163 + struct devlink_stats *cpu_stats; 164 + u64 rx_packets, rx_bytes; 165 + unsigned int start; 166 + 167 + cpu_stats = per_cpu_ptr(trap_stats, i); 168 + do { 169 + start = u64_stats_fetch_begin(&cpu_stats->syncp); 170 + rx_packets = u64_stats_read(&cpu_stats->rx_packets); 171 + rx_bytes = u64_stats_read(&cpu_stats->rx_bytes); 172 + } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); 173 + 174 + u64_stats_add(&stats->rx_packets, rx_packets); 175 + u64_stats_add(&stats->rx_bytes, rx_bytes); 176 + } 177 + } 178 + 179 + static int 180 + devlink_trap_group_stats_put(struct sk_buff *msg, 181 + struct devlink_stats __percpu *trap_stats) 182 + { 183 + struct devlink_stats stats; 184 + struct nlattr *attr; 185 + 186 + devlink_trap_stats_read(trap_stats, &stats); 187 + 188 + attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 189 + if (!attr) 190 + return -EMSGSIZE; 191 + 192 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS, 193 + u64_stats_read(&stats.rx_packets), 194 + DEVLINK_ATTR_PAD)) 195 + goto nla_put_failure; 196 + 197 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES, 198 + u64_stats_read(&stats.rx_bytes), 199 + DEVLINK_ATTR_PAD)) 200 + goto nla_put_failure; 201 + 202 + nla_nest_end(msg, attr); 203 + 204 + return 0; 205 + 206 + nla_put_failure: 207 + nla_nest_cancel(msg, attr); 208 + return -EMSGSIZE; 209 + } 210 + 211 + static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink, 212 + const struct devlink_trap_item *trap_item) 213 + { 214 + struct devlink_stats stats; 215 + struct nlattr *attr; 216 + u64 drops = 0; 217 + int err; 218 + 219 + if (devlink->ops->trap_drop_counter_get) { 220 + err = devlink->ops->trap_drop_counter_get(devlink, 221 + trap_item->trap, 222 + &drops); 223 + if (err) 224 + return err; 225 + } 226 + 227 + devlink_trap_stats_read(trap_item->stats, &stats); 228 + 229 + attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 230 + if (!attr) 231 + return -EMSGSIZE; 232 + 233 + if (devlink->ops->trap_drop_counter_get && 234 + nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops, 235 + DEVLINK_ATTR_PAD)) 236 + goto nla_put_failure; 237 + 238 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS, 239 + u64_stats_read(&stats.rx_packets), 240 + DEVLINK_ATTR_PAD)) 241 + goto nla_put_failure; 242 + 243 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES, 244 + u64_stats_read(&stats.rx_bytes), 245 + DEVLINK_ATTR_PAD)) 246 + goto nla_put_failure; 247 + 248 + nla_nest_end(msg, attr); 249 + 250 + return 0; 251 + 252 + nla_put_failure: 253 + nla_nest_cancel(msg, attr); 254 + return -EMSGSIZE; 255 + } 256 + 257 + static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink, 258 + const struct devlink_trap_item *trap_item, 259 + enum devlink_command cmd, u32 portid, u32 seq, 260 + int flags) 261 + { 262 + struct devlink_trap_group_item *group_item = trap_item->group_item; 263 + void *hdr; 264 + int err; 265 + 266 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 267 + if (!hdr) 268 + return -EMSGSIZE; 269 + 270 + if (devlink_nl_put_handle(msg, devlink)) 271 + goto nla_put_failure; 272 + 273 + if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 274 + group_item->group->name)) 275 + goto nla_put_failure; 276 + 277 + if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name)) 278 + goto nla_put_failure; 279 + 280 + if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type)) 281 + goto nla_put_failure; 282 + 283 + if (trap_item->trap->generic && 284 + nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 285 + goto nla_put_failure; 286 + 287 + if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action)) 288 + goto nla_put_failure; 289 + 290 + err = devlink_trap_metadata_put(msg, trap_item->trap); 291 + if (err) 292 + goto nla_put_failure; 293 + 294 + err = devlink_trap_stats_put(msg, devlink, trap_item); 295 + if (err) 296 + goto nla_put_failure; 297 + 298 + genlmsg_end(msg, hdr); 299 + 300 + return 0; 301 + 302 + nla_put_failure: 303 + genlmsg_cancel(msg, hdr); 304 + return -EMSGSIZE; 305 + } 306 + 307 + int devlink_nl_trap_get_doit(struct sk_buff *skb, struct genl_info *info) 308 + { 309 + struct netlink_ext_ack *extack = info->extack; 310 + struct devlink *devlink = info->user_ptr[0]; 311 + struct devlink_trap_item *trap_item; 312 + struct sk_buff *msg; 313 + int err; 314 + 315 + if (list_empty(&devlink->trap_list)) 316 + return -EOPNOTSUPP; 317 + 318 + trap_item = devlink_trap_item_get_from_info(devlink, info); 319 + if (!trap_item) { 320 + NL_SET_ERR_MSG(extack, "Device did not register this trap"); 321 + return -ENOENT; 322 + } 323 + 324 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 325 + if (!msg) 326 + return -ENOMEM; 327 + 328 + err = devlink_nl_trap_fill(msg, devlink, trap_item, 329 + DEVLINK_CMD_TRAP_NEW, info->snd_portid, 330 + info->snd_seq, 0); 331 + if (err) 332 + goto err_trap_fill; 333 + 334 + return genlmsg_reply(msg, info); 335 + 336 + err_trap_fill: 337 + nlmsg_free(msg); 338 + return err; 339 + } 340 + 341 + static int devlink_nl_trap_get_dump_one(struct sk_buff *msg, 342 + struct devlink *devlink, 343 + struct netlink_callback *cb, int flags) 344 + { 345 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 346 + struct devlink_trap_item *trap_item; 347 + int idx = 0; 348 + int err = 0; 349 + 350 + list_for_each_entry(trap_item, &devlink->trap_list, list) { 351 + if (idx < state->idx) { 352 + idx++; 353 + continue; 354 + } 355 + err = devlink_nl_trap_fill(msg, devlink, trap_item, 356 + DEVLINK_CMD_TRAP_NEW, 357 + NETLINK_CB(cb->skb).portid, 358 + cb->nlh->nlmsg_seq, flags); 359 + if (err) { 360 + state->idx = idx; 361 + break; 362 + } 363 + idx++; 364 + } 365 + 366 + return err; 367 + } 368 + 369 + int devlink_nl_trap_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 370 + { 371 + return devlink_nl_dumpit(skb, cb, devlink_nl_trap_get_dump_one); 372 + } 373 + 374 + static int __devlink_trap_action_set(struct devlink *devlink, 375 + struct devlink_trap_item *trap_item, 376 + enum devlink_trap_action trap_action, 377 + struct netlink_ext_ack *extack) 378 + { 379 + int err; 380 + 381 + if (trap_item->action != trap_action && 382 + trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) { 383 + NL_SET_ERR_MSG(extack, "Cannot change action of non-drop traps. Skipping"); 384 + return 0; 385 + } 386 + 387 + err = devlink->ops->trap_action_set(devlink, trap_item->trap, 388 + trap_action, extack); 389 + if (err) 390 + return err; 391 + 392 + trap_item->action = trap_action; 393 + 394 + return 0; 395 + } 396 + 397 + static int devlink_trap_action_set(struct devlink *devlink, 398 + struct devlink_trap_item *trap_item, 399 + struct genl_info *info) 400 + { 401 + enum devlink_trap_action trap_action; 402 + int err; 403 + 404 + if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 405 + return 0; 406 + 407 + err = devlink_trap_action_get_from_info(info, &trap_action); 408 + if (err) { 409 + NL_SET_ERR_MSG(info->extack, "Invalid trap action"); 410 + return -EINVAL; 411 + } 412 + 413 + return __devlink_trap_action_set(devlink, trap_item, trap_action, 414 + info->extack); 415 + } 416 + 417 + int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb, struct genl_info *info) 418 + { 419 + struct netlink_ext_ack *extack = info->extack; 420 + struct devlink *devlink = info->user_ptr[0]; 421 + struct devlink_trap_item *trap_item; 422 + 423 + if (list_empty(&devlink->trap_list)) 424 + return -EOPNOTSUPP; 425 + 426 + trap_item = devlink_trap_item_get_from_info(devlink, info); 427 + if (!trap_item) { 428 + NL_SET_ERR_MSG(extack, "Device did not register this trap"); 429 + return -ENOENT; 430 + } 431 + 432 + return devlink_trap_action_set(devlink, trap_item, info); 433 + } 434 + 435 + static struct devlink_trap_group_item * 436 + devlink_trap_group_item_lookup(struct devlink *devlink, const char *name) 437 + { 438 + struct devlink_trap_group_item *group_item; 439 + 440 + list_for_each_entry(group_item, &devlink->trap_group_list, list) { 441 + if (!strcmp(group_item->group->name, name)) 442 + return group_item; 443 + } 444 + 445 + return NULL; 446 + } 447 + 448 + static struct devlink_trap_group_item * 449 + devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id) 450 + { 451 + struct devlink_trap_group_item *group_item; 452 + 453 + list_for_each_entry(group_item, &devlink->trap_group_list, list) { 454 + if (group_item->group->id == id) 455 + return group_item; 456 + } 457 + 458 + return NULL; 459 + } 460 + 461 + static struct devlink_trap_group_item * 462 + devlink_trap_group_item_get_from_info(struct devlink *devlink, 463 + struct genl_info *info) 464 + { 465 + char *name; 466 + 467 + if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]) 468 + return NULL; 469 + name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]); 470 + 471 + return devlink_trap_group_item_lookup(devlink, name); 472 + } 473 + 474 + static int 475 + devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink, 476 + const struct devlink_trap_group_item *group_item, 477 + enum devlink_command cmd, u32 portid, u32 seq, 478 + int flags) 479 + { 480 + void *hdr; 481 + int err; 482 + 483 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 484 + if (!hdr) 485 + return -EMSGSIZE; 486 + 487 + if (devlink_nl_put_handle(msg, devlink)) 488 + goto nla_put_failure; 489 + 490 + if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 491 + group_item->group->name)) 492 + goto nla_put_failure; 493 + 494 + if (group_item->group->generic && 495 + nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 496 + goto nla_put_failure; 497 + 498 + if (group_item->policer_item && 499 + nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 500 + group_item->policer_item->policer->id)) 501 + goto nla_put_failure; 502 + 503 + err = devlink_trap_group_stats_put(msg, group_item->stats); 504 + if (err) 505 + goto nla_put_failure; 506 + 507 + genlmsg_end(msg, hdr); 508 + 509 + return 0; 510 + 511 + nla_put_failure: 512 + genlmsg_cancel(msg, hdr); 513 + return -EMSGSIZE; 514 + } 515 + 516 + int devlink_nl_trap_group_get_doit(struct sk_buff *skb, struct genl_info *info) 517 + { 518 + struct netlink_ext_ack *extack = info->extack; 519 + struct devlink *devlink = info->user_ptr[0]; 520 + struct devlink_trap_group_item *group_item; 521 + struct sk_buff *msg; 522 + int err; 523 + 524 + if (list_empty(&devlink->trap_group_list)) 525 + return -EOPNOTSUPP; 526 + 527 + group_item = devlink_trap_group_item_get_from_info(devlink, info); 528 + if (!group_item) { 529 + NL_SET_ERR_MSG(extack, "Device did not register this trap group"); 530 + return -ENOENT; 531 + } 532 + 533 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 534 + if (!msg) 535 + return -ENOMEM; 536 + 537 + err = devlink_nl_trap_group_fill(msg, devlink, group_item, 538 + DEVLINK_CMD_TRAP_GROUP_NEW, 539 + info->snd_portid, info->snd_seq, 0); 540 + if (err) 541 + goto err_trap_group_fill; 542 + 543 + return genlmsg_reply(msg, info); 544 + 545 + err_trap_group_fill: 546 + nlmsg_free(msg); 547 + return err; 548 + } 549 + 550 + static int devlink_nl_trap_group_get_dump_one(struct sk_buff *msg, 551 + struct devlink *devlink, 552 + struct netlink_callback *cb, 553 + int flags) 554 + { 555 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 556 + struct devlink_trap_group_item *group_item; 557 + int idx = 0; 558 + int err = 0; 559 + 560 + list_for_each_entry(group_item, &devlink->trap_group_list, list) { 561 + if (idx < state->idx) { 562 + idx++; 563 + continue; 564 + } 565 + err = devlink_nl_trap_group_fill(msg, devlink, group_item, 566 + DEVLINK_CMD_TRAP_GROUP_NEW, 567 + NETLINK_CB(cb->skb).portid, 568 + cb->nlh->nlmsg_seq, flags); 569 + if (err) { 570 + state->idx = idx; 571 + break; 572 + } 573 + idx++; 574 + } 575 + 576 + return err; 577 + } 578 + 579 + int devlink_nl_trap_group_get_dumpit(struct sk_buff *skb, 580 + struct netlink_callback *cb) 581 + { 582 + return devlink_nl_dumpit(skb, cb, devlink_nl_trap_group_get_dump_one); 583 + } 584 + 585 + static int 586 + __devlink_trap_group_action_set(struct devlink *devlink, 587 + struct devlink_trap_group_item *group_item, 588 + enum devlink_trap_action trap_action, 589 + struct netlink_ext_ack *extack) 590 + { 591 + const char *group_name = group_item->group->name; 592 + struct devlink_trap_item *trap_item; 593 + int err; 594 + 595 + if (devlink->ops->trap_group_action_set) { 596 + err = devlink->ops->trap_group_action_set(devlink, group_item->group, 597 + trap_action, extack); 598 + if (err) 599 + return err; 600 + 601 + list_for_each_entry(trap_item, &devlink->trap_list, list) { 602 + if (strcmp(trap_item->group_item->group->name, group_name)) 603 + continue; 604 + if (trap_item->action != trap_action && 605 + trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) 606 + continue; 607 + trap_item->action = trap_action; 608 + } 609 + 610 + return 0; 611 + } 612 + 613 + list_for_each_entry(trap_item, &devlink->trap_list, list) { 614 + if (strcmp(trap_item->group_item->group->name, group_name)) 615 + continue; 616 + err = __devlink_trap_action_set(devlink, trap_item, 617 + trap_action, extack); 618 + if (err) 619 + return err; 620 + } 621 + 622 + return 0; 623 + } 624 + 625 + static int 626 + devlink_trap_group_action_set(struct devlink *devlink, 627 + struct devlink_trap_group_item *group_item, 628 + struct genl_info *info, bool *p_modified) 629 + { 630 + enum devlink_trap_action trap_action; 631 + int err; 632 + 633 + if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 634 + return 0; 635 + 636 + err = devlink_trap_action_get_from_info(info, &trap_action); 637 + if (err) { 638 + NL_SET_ERR_MSG(info->extack, "Invalid trap action"); 639 + return -EINVAL; 640 + } 641 + 642 + err = __devlink_trap_group_action_set(devlink, group_item, trap_action, 643 + info->extack); 644 + if (err) 645 + return err; 646 + 647 + *p_modified = true; 648 + 649 + return 0; 650 + } 651 + 652 + static int devlink_trap_group_set(struct devlink *devlink, 653 + struct devlink_trap_group_item *group_item, 654 + struct genl_info *info) 655 + { 656 + struct devlink_trap_policer_item *policer_item; 657 + struct netlink_ext_ack *extack = info->extack; 658 + const struct devlink_trap_policer *policer; 659 + struct nlattr **attrs = info->attrs; 660 + u32 policer_id; 661 + int err; 662 + 663 + if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 664 + return 0; 665 + 666 + if (!devlink->ops->trap_group_set) 667 + return -EOPNOTSUPP; 668 + 669 + policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 670 + policer_item = devlink_trap_policer_item_lookup(devlink, policer_id); 671 + if (policer_id && !policer_item) { 672 + NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 673 + return -ENOENT; 674 + } 675 + policer = policer_item ? policer_item->policer : NULL; 676 + 677 + err = devlink->ops->trap_group_set(devlink, group_item->group, policer, 678 + extack); 679 + if (err) 680 + return err; 681 + 682 + group_item->policer_item = policer_item; 683 + 684 + return 0; 685 + } 686 + 687 + int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb, 688 + struct genl_info *info) 689 + { 690 + struct netlink_ext_ack *extack = info->extack; 691 + struct devlink *devlink = info->user_ptr[0]; 692 + struct devlink_trap_group_item *group_item; 693 + bool modified = false; 694 + int err; 695 + 696 + if (list_empty(&devlink->trap_group_list)) 697 + return -EOPNOTSUPP; 698 + 699 + group_item = devlink_trap_group_item_get_from_info(devlink, info); 700 + if (!group_item) { 701 + NL_SET_ERR_MSG(extack, "Device did not register this trap group"); 702 + return -ENOENT; 703 + } 704 + 705 + err = devlink_trap_group_action_set(devlink, group_item, info, 706 + &modified); 707 + if (err) 708 + return err; 709 + 710 + err = devlink_trap_group_set(devlink, group_item, info); 711 + if (err) 712 + goto err_trap_group_set; 713 + 714 + return 0; 715 + 716 + err_trap_group_set: 717 + if (modified) 718 + NL_SET_ERR_MSG(extack, "Trap group set failed, but some changes were committed already"); 719 + return err; 720 + } 721 + 722 + static struct devlink_trap_policer_item * 723 + devlink_trap_policer_item_get_from_info(struct devlink *devlink, 724 + struct genl_info *info) 725 + { 726 + u32 id; 727 + 728 + if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 729 + return NULL; 730 + id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 731 + 732 + return devlink_trap_policer_item_lookup(devlink, id); 733 + } 734 + 735 + static int 736 + devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink, 737 + const struct devlink_trap_policer *policer) 738 + { 739 + struct nlattr *attr; 740 + u64 drops; 741 + int err; 742 + 743 + if (!devlink->ops->trap_policer_counter_get) 744 + return 0; 745 + 746 + err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops); 747 + if (err) 748 + return err; 749 + 750 + attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 751 + if (!attr) 752 + return -EMSGSIZE; 753 + 754 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops, 755 + DEVLINK_ATTR_PAD)) 756 + goto nla_put_failure; 757 + 758 + nla_nest_end(msg, attr); 759 + 760 + return 0; 761 + 762 + nla_put_failure: 763 + nla_nest_cancel(msg, attr); 764 + return -EMSGSIZE; 765 + } 766 + 767 + static int 768 + devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink, 769 + const struct devlink_trap_policer_item *policer_item, 770 + enum devlink_command cmd, u32 portid, u32 seq, 771 + int flags) 772 + { 773 + void *hdr; 774 + int err; 775 + 776 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 777 + if (!hdr) 778 + return -EMSGSIZE; 779 + 780 + if (devlink_nl_put_handle(msg, devlink)) 781 + goto nla_put_failure; 782 + 783 + if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 784 + policer_item->policer->id)) 785 + goto nla_put_failure; 786 + 787 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE, 788 + policer_item->rate, DEVLINK_ATTR_PAD)) 789 + goto nla_put_failure; 790 + 791 + if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST, 792 + policer_item->burst, DEVLINK_ATTR_PAD)) 793 + goto nla_put_failure; 794 + 795 + err = devlink_trap_policer_stats_put(msg, devlink, 796 + policer_item->policer); 797 + if (err) 798 + goto nla_put_failure; 799 + 800 + genlmsg_end(msg, hdr); 801 + 802 + return 0; 803 + 804 + nla_put_failure: 805 + genlmsg_cancel(msg, hdr); 806 + return -EMSGSIZE; 807 + } 808 + 809 + int devlink_nl_trap_policer_get_doit(struct sk_buff *skb, 810 + struct genl_info *info) 811 + { 812 + struct devlink_trap_policer_item *policer_item; 813 + struct netlink_ext_ack *extack = info->extack; 814 + struct devlink *devlink = info->user_ptr[0]; 815 + struct sk_buff *msg; 816 + int err; 817 + 818 + if (list_empty(&devlink->trap_policer_list)) 819 + return -EOPNOTSUPP; 820 + 821 + policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 822 + if (!policer_item) { 823 + NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 824 + return -ENOENT; 825 + } 826 + 827 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 828 + if (!msg) 829 + return -ENOMEM; 830 + 831 + err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, 832 + DEVLINK_CMD_TRAP_POLICER_NEW, 833 + info->snd_portid, info->snd_seq, 0); 834 + if (err) 835 + goto err_trap_policer_fill; 836 + 837 + return genlmsg_reply(msg, info); 838 + 839 + err_trap_policer_fill: 840 + nlmsg_free(msg); 841 + return err; 842 + } 843 + 844 + static int devlink_nl_trap_policer_get_dump_one(struct sk_buff *msg, 845 + struct devlink *devlink, 846 + struct netlink_callback *cb, 847 + int flags) 848 + { 849 + struct devlink_nl_dump_state *state = devlink_dump_state(cb); 850 + struct devlink_trap_policer_item *policer_item; 851 + int idx = 0; 852 + int err = 0; 853 + 854 + list_for_each_entry(policer_item, &devlink->trap_policer_list, list) { 855 + if (idx < state->idx) { 856 + idx++; 857 + continue; 858 + } 859 + err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, 860 + DEVLINK_CMD_TRAP_POLICER_NEW, 861 + NETLINK_CB(cb->skb).portid, 862 + cb->nlh->nlmsg_seq, flags); 863 + if (err) { 864 + state->idx = idx; 865 + break; 866 + } 867 + idx++; 868 + } 869 + 870 + return err; 871 + } 872 + 873 + int devlink_nl_trap_policer_get_dumpit(struct sk_buff *skb, 874 + struct netlink_callback *cb) 875 + { 876 + return devlink_nl_dumpit(skb, cb, devlink_nl_trap_policer_get_dump_one); 877 + } 878 + 879 + static int 880 + devlink_trap_policer_set(struct devlink *devlink, 881 + struct devlink_trap_policer_item *policer_item, 882 + struct genl_info *info) 883 + { 884 + struct netlink_ext_ack *extack = info->extack; 885 + struct nlattr **attrs = info->attrs; 886 + u64 rate, burst; 887 + int err; 888 + 889 + rate = policer_item->rate; 890 + burst = policer_item->burst; 891 + 892 + if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]) 893 + rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]); 894 + 895 + if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]) 896 + burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]); 897 + 898 + if (rate < policer_item->policer->min_rate) { 899 + NL_SET_ERR_MSG(extack, "Policer rate lower than limit"); 900 + return -EINVAL; 901 + } 902 + 903 + if (rate > policer_item->policer->max_rate) { 904 + NL_SET_ERR_MSG(extack, "Policer rate higher than limit"); 905 + return -EINVAL; 906 + } 907 + 908 + if (burst < policer_item->policer->min_burst) { 909 + NL_SET_ERR_MSG(extack, "Policer burst size lower than limit"); 910 + return -EINVAL; 911 + } 912 + 913 + if (burst > policer_item->policer->max_burst) { 914 + NL_SET_ERR_MSG(extack, "Policer burst size higher than limit"); 915 + return -EINVAL; 916 + } 917 + 918 + err = devlink->ops->trap_policer_set(devlink, policer_item->policer, 919 + rate, burst, info->extack); 920 + if (err) 921 + return err; 922 + 923 + policer_item->rate = rate; 924 + policer_item->burst = burst; 925 + 926 + return 0; 927 + } 928 + 929 + int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb, 930 + struct genl_info *info) 931 + { 932 + struct devlink_trap_policer_item *policer_item; 933 + struct netlink_ext_ack *extack = info->extack; 934 + struct devlink *devlink = info->user_ptr[0]; 935 + 936 + if (list_empty(&devlink->trap_policer_list)) 937 + return -EOPNOTSUPP; 938 + 939 + if (!devlink->ops->trap_policer_set) 940 + return -EOPNOTSUPP; 941 + 942 + policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 943 + if (!policer_item) { 944 + NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 945 + return -ENOENT; 946 + } 947 + 948 + return devlink_trap_policer_set(devlink, policer_item, info); 949 + } 950 + 951 + #define DEVLINK_TRAP(_id, _type) \ 952 + { \ 953 + .type = DEVLINK_TRAP_TYPE_##_type, \ 954 + .id = DEVLINK_TRAP_GENERIC_ID_##_id, \ 955 + .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \ 956 + } 957 + 958 + static const struct devlink_trap devlink_trap_generic[] = { 959 + DEVLINK_TRAP(SMAC_MC, DROP), 960 + DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP), 961 + DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP), 962 + DEVLINK_TRAP(INGRESS_STP_FILTER, DROP), 963 + DEVLINK_TRAP(EMPTY_TX_LIST, DROP), 964 + DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP), 965 + DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP), 966 + DEVLINK_TRAP(TTL_ERROR, EXCEPTION), 967 + DEVLINK_TRAP(TAIL_DROP, DROP), 968 + DEVLINK_TRAP(NON_IP_PACKET, DROP), 969 + DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP), 970 + DEVLINK_TRAP(DIP_LB, DROP), 971 + DEVLINK_TRAP(SIP_MC, DROP), 972 + DEVLINK_TRAP(SIP_LB, DROP), 973 + DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP), 974 + DEVLINK_TRAP(IPV4_SIP_BC, DROP), 975 + DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP), 976 + DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP), 977 + DEVLINK_TRAP(MTU_ERROR, EXCEPTION), 978 + DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION), 979 + DEVLINK_TRAP(RPF, EXCEPTION), 980 + DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION), 981 + DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION), 982 + DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION), 983 + DEVLINK_TRAP(NON_ROUTABLE, DROP), 984 + DEVLINK_TRAP(DECAP_ERROR, EXCEPTION), 985 + DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP), 986 + DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP), 987 + DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP), 988 + DEVLINK_TRAP(STP, CONTROL), 989 + DEVLINK_TRAP(LACP, CONTROL), 990 + DEVLINK_TRAP(LLDP, CONTROL), 991 + DEVLINK_TRAP(IGMP_QUERY, CONTROL), 992 + DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL), 993 + DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL), 994 + DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL), 995 + DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL), 996 + DEVLINK_TRAP(MLD_QUERY, CONTROL), 997 + DEVLINK_TRAP(MLD_V1_REPORT, CONTROL), 998 + DEVLINK_TRAP(MLD_V2_REPORT, CONTROL), 999 + DEVLINK_TRAP(MLD_V1_DONE, CONTROL), 1000 + DEVLINK_TRAP(IPV4_DHCP, CONTROL), 1001 + DEVLINK_TRAP(IPV6_DHCP, CONTROL), 1002 + DEVLINK_TRAP(ARP_REQUEST, CONTROL), 1003 + DEVLINK_TRAP(ARP_RESPONSE, CONTROL), 1004 + DEVLINK_TRAP(ARP_OVERLAY, CONTROL), 1005 + DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL), 1006 + DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL), 1007 + DEVLINK_TRAP(IPV4_BFD, CONTROL), 1008 + DEVLINK_TRAP(IPV6_BFD, CONTROL), 1009 + DEVLINK_TRAP(IPV4_OSPF, CONTROL), 1010 + DEVLINK_TRAP(IPV6_OSPF, CONTROL), 1011 + DEVLINK_TRAP(IPV4_BGP, CONTROL), 1012 + DEVLINK_TRAP(IPV6_BGP, CONTROL), 1013 + DEVLINK_TRAP(IPV4_VRRP, CONTROL), 1014 + DEVLINK_TRAP(IPV6_VRRP, CONTROL), 1015 + DEVLINK_TRAP(IPV4_PIM, CONTROL), 1016 + DEVLINK_TRAP(IPV6_PIM, CONTROL), 1017 + DEVLINK_TRAP(UC_LB, CONTROL), 1018 + DEVLINK_TRAP(LOCAL_ROUTE, CONTROL), 1019 + DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL), 1020 + DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL), 1021 + DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL), 1022 + DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL), 1023 + DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL), 1024 + DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL), 1025 + DEVLINK_TRAP(IPV6_REDIRECT, CONTROL), 1026 + DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL), 1027 + DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL), 1028 + DEVLINK_TRAP(PTP_EVENT, CONTROL), 1029 + DEVLINK_TRAP(PTP_GENERAL, CONTROL), 1030 + DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL), 1031 + DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL), 1032 + DEVLINK_TRAP(EARLY_DROP, DROP), 1033 + DEVLINK_TRAP(VXLAN_PARSING, DROP), 1034 + DEVLINK_TRAP(LLC_SNAP_PARSING, DROP), 1035 + DEVLINK_TRAP(VLAN_PARSING, DROP), 1036 + DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP), 1037 + DEVLINK_TRAP(MPLS_PARSING, DROP), 1038 + DEVLINK_TRAP(ARP_PARSING, DROP), 1039 + DEVLINK_TRAP(IP_1_PARSING, DROP), 1040 + DEVLINK_TRAP(IP_N_PARSING, DROP), 1041 + DEVLINK_TRAP(GRE_PARSING, DROP), 1042 + DEVLINK_TRAP(UDP_PARSING, DROP), 1043 + DEVLINK_TRAP(TCP_PARSING, DROP), 1044 + DEVLINK_TRAP(IPSEC_PARSING, DROP), 1045 + DEVLINK_TRAP(SCTP_PARSING, DROP), 1046 + DEVLINK_TRAP(DCCP_PARSING, DROP), 1047 + DEVLINK_TRAP(GTP_PARSING, DROP), 1048 + DEVLINK_TRAP(ESP_PARSING, DROP), 1049 + DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP), 1050 + DEVLINK_TRAP(DMAC_FILTER, DROP), 1051 + DEVLINK_TRAP(EAPOL, CONTROL), 1052 + DEVLINK_TRAP(LOCKED_PORT, DROP), 1053 + }; 1054 + 1055 + #define DEVLINK_TRAP_GROUP(_id) \ 1056 + { \ 1057 + .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \ 1058 + .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \ 1059 + } 1060 + 1061 + static const struct devlink_trap_group devlink_trap_group_generic[] = { 1062 + DEVLINK_TRAP_GROUP(L2_DROPS), 1063 + DEVLINK_TRAP_GROUP(L3_DROPS), 1064 + DEVLINK_TRAP_GROUP(L3_EXCEPTIONS), 1065 + DEVLINK_TRAP_GROUP(BUFFER_DROPS), 1066 + DEVLINK_TRAP_GROUP(TUNNEL_DROPS), 1067 + DEVLINK_TRAP_GROUP(ACL_DROPS), 1068 + DEVLINK_TRAP_GROUP(STP), 1069 + DEVLINK_TRAP_GROUP(LACP), 1070 + DEVLINK_TRAP_GROUP(LLDP), 1071 + DEVLINK_TRAP_GROUP(MC_SNOOPING), 1072 + DEVLINK_TRAP_GROUP(DHCP), 1073 + DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY), 1074 + DEVLINK_TRAP_GROUP(BFD), 1075 + DEVLINK_TRAP_GROUP(OSPF), 1076 + DEVLINK_TRAP_GROUP(BGP), 1077 + DEVLINK_TRAP_GROUP(VRRP), 1078 + DEVLINK_TRAP_GROUP(PIM), 1079 + DEVLINK_TRAP_GROUP(UC_LB), 1080 + DEVLINK_TRAP_GROUP(LOCAL_DELIVERY), 1081 + DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY), 1082 + DEVLINK_TRAP_GROUP(IPV6), 1083 + DEVLINK_TRAP_GROUP(PTP_EVENT), 1084 + DEVLINK_TRAP_GROUP(PTP_GENERAL), 1085 + DEVLINK_TRAP_GROUP(ACL_SAMPLE), 1086 + DEVLINK_TRAP_GROUP(ACL_TRAP), 1087 + DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS), 1088 + DEVLINK_TRAP_GROUP(EAPOL), 1089 + }; 1090 + 1091 + static int devlink_trap_generic_verify(const struct devlink_trap *trap) 1092 + { 1093 + if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX) 1094 + return -EINVAL; 1095 + 1096 + if (strcmp(trap->name, devlink_trap_generic[trap->id].name)) 1097 + return -EINVAL; 1098 + 1099 + if (trap->type != devlink_trap_generic[trap->id].type) 1100 + return -EINVAL; 1101 + 1102 + return 0; 1103 + } 1104 + 1105 + static int devlink_trap_driver_verify(const struct devlink_trap *trap) 1106 + { 1107 + int i; 1108 + 1109 + if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX) 1110 + return -EINVAL; 1111 + 1112 + for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) { 1113 + if (!strcmp(trap->name, devlink_trap_generic[i].name)) 1114 + return -EEXIST; 1115 + } 1116 + 1117 + return 0; 1118 + } 1119 + 1120 + static int devlink_trap_verify(const struct devlink_trap *trap) 1121 + { 1122 + if (!trap || !trap->name) 1123 + return -EINVAL; 1124 + 1125 + if (trap->generic) 1126 + return devlink_trap_generic_verify(trap); 1127 + else 1128 + return devlink_trap_driver_verify(trap); 1129 + } 1130 + 1131 + static int 1132 + devlink_trap_group_generic_verify(const struct devlink_trap_group *group) 1133 + { 1134 + if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 1135 + return -EINVAL; 1136 + 1137 + if (strcmp(group->name, devlink_trap_group_generic[group->id].name)) 1138 + return -EINVAL; 1139 + 1140 + return 0; 1141 + } 1142 + 1143 + static int 1144 + devlink_trap_group_driver_verify(const struct devlink_trap_group *group) 1145 + { 1146 + int i; 1147 + 1148 + if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 1149 + return -EINVAL; 1150 + 1151 + for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) { 1152 + if (!strcmp(group->name, devlink_trap_group_generic[i].name)) 1153 + return -EEXIST; 1154 + } 1155 + 1156 + return 0; 1157 + } 1158 + 1159 + static int devlink_trap_group_verify(const struct devlink_trap_group *group) 1160 + { 1161 + if (group->generic) 1162 + return devlink_trap_group_generic_verify(group); 1163 + else 1164 + return devlink_trap_group_driver_verify(group); 1165 + } 1166 + 1167 + static void 1168 + devlink_trap_group_notify(struct devlink *devlink, 1169 + const struct devlink_trap_group_item *group_item, 1170 + enum devlink_command cmd) 1171 + { 1172 + struct sk_buff *msg; 1173 + int err; 1174 + 1175 + WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW && 1176 + cmd != DEVLINK_CMD_TRAP_GROUP_DEL); 1177 + if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 1178 + return; 1179 + 1180 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1181 + if (!msg) 1182 + return; 1183 + 1184 + err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0, 1185 + 0); 1186 + if (err) { 1187 + nlmsg_free(msg); 1188 + return; 1189 + } 1190 + 1191 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 1192 + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 1193 + } 1194 + 1195 + void devlink_trap_groups_notify_register(struct devlink *devlink) 1196 + { 1197 + struct devlink_trap_group_item *group_item; 1198 + 1199 + list_for_each_entry(group_item, &devlink->trap_group_list, list) 1200 + devlink_trap_group_notify(devlink, group_item, 1201 + DEVLINK_CMD_TRAP_GROUP_NEW); 1202 + } 1203 + 1204 + void devlink_trap_groups_notify_unregister(struct devlink *devlink) 1205 + { 1206 + struct devlink_trap_group_item *group_item; 1207 + 1208 + list_for_each_entry_reverse(group_item, &devlink->trap_group_list, list) 1209 + devlink_trap_group_notify(devlink, group_item, 1210 + DEVLINK_CMD_TRAP_GROUP_DEL); 1211 + } 1212 + 1213 + static int 1214 + devlink_trap_item_group_link(struct devlink *devlink, 1215 + struct devlink_trap_item *trap_item) 1216 + { 1217 + u16 group_id = trap_item->trap->init_group_id; 1218 + struct devlink_trap_group_item *group_item; 1219 + 1220 + group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id); 1221 + if (WARN_ON_ONCE(!group_item)) 1222 + return -EINVAL; 1223 + 1224 + trap_item->group_item = group_item; 1225 + 1226 + return 0; 1227 + } 1228 + 1229 + static void devlink_trap_notify(struct devlink *devlink, 1230 + const struct devlink_trap_item *trap_item, 1231 + enum devlink_command cmd) 1232 + { 1233 + struct sk_buff *msg; 1234 + int err; 1235 + 1236 + WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW && 1237 + cmd != DEVLINK_CMD_TRAP_DEL); 1238 + if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 1239 + return; 1240 + 1241 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1242 + if (!msg) 1243 + return; 1244 + 1245 + err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0); 1246 + if (err) { 1247 + nlmsg_free(msg); 1248 + return; 1249 + } 1250 + 1251 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 1252 + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 1253 + } 1254 + 1255 + void devlink_traps_notify_register(struct devlink *devlink) 1256 + { 1257 + struct devlink_trap_item *trap_item; 1258 + 1259 + list_for_each_entry(trap_item, &devlink->trap_list, list) 1260 + devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW); 1261 + } 1262 + 1263 + void devlink_traps_notify_unregister(struct devlink *devlink) 1264 + { 1265 + struct devlink_trap_item *trap_item; 1266 + 1267 + list_for_each_entry_reverse(trap_item, &devlink->trap_list, list) 1268 + devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL); 1269 + } 1270 + 1271 + static int 1272 + devlink_trap_register(struct devlink *devlink, 1273 + const struct devlink_trap *trap, void *priv) 1274 + { 1275 + struct devlink_trap_item *trap_item; 1276 + int err; 1277 + 1278 + if (devlink_trap_item_lookup(devlink, trap->name)) 1279 + return -EEXIST; 1280 + 1281 + trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL); 1282 + if (!trap_item) 1283 + return -ENOMEM; 1284 + 1285 + trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 1286 + if (!trap_item->stats) { 1287 + err = -ENOMEM; 1288 + goto err_stats_alloc; 1289 + } 1290 + 1291 + trap_item->trap = trap; 1292 + trap_item->action = trap->init_action; 1293 + trap_item->priv = priv; 1294 + 1295 + err = devlink_trap_item_group_link(devlink, trap_item); 1296 + if (err) 1297 + goto err_group_link; 1298 + 1299 + err = devlink->ops->trap_init(devlink, trap, trap_item); 1300 + if (err) 1301 + goto err_trap_init; 1302 + 1303 + list_add_tail(&trap_item->list, &devlink->trap_list); 1304 + devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW); 1305 + 1306 + return 0; 1307 + 1308 + err_trap_init: 1309 + err_group_link: 1310 + free_percpu(trap_item->stats); 1311 + err_stats_alloc: 1312 + kfree(trap_item); 1313 + return err; 1314 + } 1315 + 1316 + static void devlink_trap_unregister(struct devlink *devlink, 1317 + const struct devlink_trap *trap) 1318 + { 1319 + struct devlink_trap_item *trap_item; 1320 + 1321 + trap_item = devlink_trap_item_lookup(devlink, trap->name); 1322 + if (WARN_ON_ONCE(!trap_item)) 1323 + return; 1324 + 1325 + devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL); 1326 + list_del(&trap_item->list); 1327 + if (devlink->ops->trap_fini) 1328 + devlink->ops->trap_fini(devlink, trap, trap_item); 1329 + free_percpu(trap_item->stats); 1330 + kfree(trap_item); 1331 + } 1332 + 1333 + static void devlink_trap_disable(struct devlink *devlink, 1334 + const struct devlink_trap *trap) 1335 + { 1336 + struct devlink_trap_item *trap_item; 1337 + 1338 + trap_item = devlink_trap_item_lookup(devlink, trap->name); 1339 + if (WARN_ON_ONCE(!trap_item)) 1340 + return; 1341 + 1342 + devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP, 1343 + NULL); 1344 + trap_item->action = DEVLINK_TRAP_ACTION_DROP; 1345 + } 1346 + 1347 + /** 1348 + * devl_traps_register - Register packet traps with devlink. 1349 + * @devlink: devlink. 1350 + * @traps: Packet traps. 1351 + * @traps_count: Count of provided packet traps. 1352 + * @priv: Driver private information. 1353 + * 1354 + * Return: Non-zero value on failure. 1355 + */ 1356 + int devl_traps_register(struct devlink *devlink, 1357 + const struct devlink_trap *traps, 1358 + size_t traps_count, void *priv) 1359 + { 1360 + int i, err; 1361 + 1362 + if (!devlink->ops->trap_init || !devlink->ops->trap_action_set) 1363 + return -EINVAL; 1364 + 1365 + devl_assert_locked(devlink); 1366 + for (i = 0; i < traps_count; i++) { 1367 + const struct devlink_trap *trap = &traps[i]; 1368 + 1369 + err = devlink_trap_verify(trap); 1370 + if (err) 1371 + goto err_trap_verify; 1372 + 1373 + err = devlink_trap_register(devlink, trap, priv); 1374 + if (err) 1375 + goto err_trap_register; 1376 + } 1377 + 1378 + return 0; 1379 + 1380 + err_trap_register: 1381 + err_trap_verify: 1382 + for (i--; i >= 0; i--) 1383 + devlink_trap_unregister(devlink, &traps[i]); 1384 + return err; 1385 + } 1386 + EXPORT_SYMBOL_GPL(devl_traps_register); 1387 + 1388 + /** 1389 + * devlink_traps_register - Register packet traps with devlink. 1390 + * @devlink: devlink. 1391 + * @traps: Packet traps. 1392 + * @traps_count: Count of provided packet traps. 1393 + * @priv: Driver private information. 1394 + * 1395 + * Context: Takes and release devlink->lock <mutex>. 1396 + * 1397 + * Return: Non-zero value on failure. 1398 + */ 1399 + int devlink_traps_register(struct devlink *devlink, 1400 + const struct devlink_trap *traps, 1401 + size_t traps_count, void *priv) 1402 + { 1403 + int err; 1404 + 1405 + devl_lock(devlink); 1406 + err = devl_traps_register(devlink, traps, traps_count, priv); 1407 + devl_unlock(devlink); 1408 + return err; 1409 + } 1410 + EXPORT_SYMBOL_GPL(devlink_traps_register); 1411 + 1412 + /** 1413 + * devl_traps_unregister - Unregister packet traps from devlink. 1414 + * @devlink: devlink. 1415 + * @traps: Packet traps. 1416 + * @traps_count: Count of provided packet traps. 1417 + */ 1418 + void devl_traps_unregister(struct devlink *devlink, 1419 + const struct devlink_trap *traps, 1420 + size_t traps_count) 1421 + { 1422 + int i; 1423 + 1424 + devl_assert_locked(devlink); 1425 + /* Make sure we do not have any packets in-flight while unregistering 1426 + * traps by disabling all of them and waiting for a grace period. 1427 + */ 1428 + for (i = traps_count - 1; i >= 0; i--) 1429 + devlink_trap_disable(devlink, &traps[i]); 1430 + synchronize_rcu(); 1431 + for (i = traps_count - 1; i >= 0; i--) 1432 + devlink_trap_unregister(devlink, &traps[i]); 1433 + } 1434 + EXPORT_SYMBOL_GPL(devl_traps_unregister); 1435 + 1436 + /** 1437 + * devlink_traps_unregister - Unregister packet traps from devlink. 1438 + * @devlink: devlink. 1439 + * @traps: Packet traps. 1440 + * @traps_count: Count of provided packet traps. 1441 + * 1442 + * Context: Takes and release devlink->lock <mutex>. 1443 + */ 1444 + void devlink_traps_unregister(struct devlink *devlink, 1445 + const struct devlink_trap *traps, 1446 + size_t traps_count) 1447 + { 1448 + devl_lock(devlink); 1449 + devl_traps_unregister(devlink, traps, traps_count); 1450 + devl_unlock(devlink); 1451 + } 1452 + EXPORT_SYMBOL_GPL(devlink_traps_unregister); 1453 + 1454 + static void 1455 + devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats, 1456 + size_t skb_len) 1457 + { 1458 + struct devlink_stats *stats; 1459 + 1460 + stats = this_cpu_ptr(trap_stats); 1461 + u64_stats_update_begin(&stats->syncp); 1462 + u64_stats_add(&stats->rx_bytes, skb_len); 1463 + u64_stats_inc(&stats->rx_packets); 1464 + u64_stats_update_end(&stats->syncp); 1465 + } 1466 + 1467 + static void 1468 + devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata, 1469 + const struct devlink_trap_item *trap_item, 1470 + struct devlink_port *in_devlink_port, 1471 + const struct flow_action_cookie *fa_cookie) 1472 + { 1473 + metadata->trap_name = trap_item->trap->name; 1474 + metadata->trap_group_name = trap_item->group_item->group->name; 1475 + metadata->fa_cookie = fa_cookie; 1476 + metadata->trap_type = trap_item->trap->type; 1477 + 1478 + spin_lock(&in_devlink_port->type_lock); 1479 + if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH) 1480 + metadata->input_dev = in_devlink_port->type_eth.netdev; 1481 + spin_unlock(&in_devlink_port->type_lock); 1482 + } 1483 + 1484 + /** 1485 + * devlink_trap_report - Report trapped packet to drop monitor. 1486 + * @devlink: devlink. 1487 + * @skb: Trapped packet. 1488 + * @trap_ctx: Trap context. 1489 + * @in_devlink_port: Input devlink port. 1490 + * @fa_cookie: Flow action cookie. Could be NULL. 1491 + */ 1492 + void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb, 1493 + void *trap_ctx, struct devlink_port *in_devlink_port, 1494 + const struct flow_action_cookie *fa_cookie) 1495 + 1496 + { 1497 + struct devlink_trap_item *trap_item = trap_ctx; 1498 + 1499 + devlink_trap_stats_update(trap_item->stats, skb->len); 1500 + devlink_trap_stats_update(trap_item->group_item->stats, skb->len); 1501 + 1502 + if (tracepoint_enabled(devlink_trap_report)) { 1503 + struct devlink_trap_metadata metadata = {}; 1504 + 1505 + devlink_trap_report_metadata_set(&metadata, trap_item, 1506 + in_devlink_port, fa_cookie); 1507 + trace_devlink_trap_report(devlink, skb, &metadata); 1508 + } 1509 + } 1510 + EXPORT_SYMBOL_GPL(devlink_trap_report); 1511 + 1512 + /** 1513 + * devlink_trap_ctx_priv - Trap context to driver private information. 1514 + * @trap_ctx: Trap context. 1515 + * 1516 + * Return: Driver private information passed during registration. 1517 + */ 1518 + void *devlink_trap_ctx_priv(void *trap_ctx) 1519 + { 1520 + struct devlink_trap_item *trap_item = trap_ctx; 1521 + 1522 + return trap_item->priv; 1523 + } 1524 + EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv); 1525 + 1526 + static int 1527 + devlink_trap_group_item_policer_link(struct devlink *devlink, 1528 + struct devlink_trap_group_item *group_item) 1529 + { 1530 + u32 policer_id = group_item->group->init_policer_id; 1531 + struct devlink_trap_policer_item *policer_item; 1532 + 1533 + if (policer_id == 0) 1534 + return 0; 1535 + 1536 + policer_item = devlink_trap_policer_item_lookup(devlink, policer_id); 1537 + if (WARN_ON_ONCE(!policer_item)) 1538 + return -EINVAL; 1539 + 1540 + group_item->policer_item = policer_item; 1541 + 1542 + return 0; 1543 + } 1544 + 1545 + static int 1546 + devlink_trap_group_register(struct devlink *devlink, 1547 + const struct devlink_trap_group *group) 1548 + { 1549 + struct devlink_trap_group_item *group_item; 1550 + int err; 1551 + 1552 + if (devlink_trap_group_item_lookup(devlink, group->name)) 1553 + return -EEXIST; 1554 + 1555 + group_item = kzalloc(sizeof(*group_item), GFP_KERNEL); 1556 + if (!group_item) 1557 + return -ENOMEM; 1558 + 1559 + group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 1560 + if (!group_item->stats) { 1561 + err = -ENOMEM; 1562 + goto err_stats_alloc; 1563 + } 1564 + 1565 + group_item->group = group; 1566 + 1567 + err = devlink_trap_group_item_policer_link(devlink, group_item); 1568 + if (err) 1569 + goto err_policer_link; 1570 + 1571 + if (devlink->ops->trap_group_init) { 1572 + err = devlink->ops->trap_group_init(devlink, group); 1573 + if (err) 1574 + goto err_group_init; 1575 + } 1576 + 1577 + list_add_tail(&group_item->list, &devlink->trap_group_list); 1578 + devlink_trap_group_notify(devlink, group_item, 1579 + DEVLINK_CMD_TRAP_GROUP_NEW); 1580 + 1581 + return 0; 1582 + 1583 + err_group_init: 1584 + err_policer_link: 1585 + free_percpu(group_item->stats); 1586 + err_stats_alloc: 1587 + kfree(group_item); 1588 + return err; 1589 + } 1590 + 1591 + static void 1592 + devlink_trap_group_unregister(struct devlink *devlink, 1593 + const struct devlink_trap_group *group) 1594 + { 1595 + struct devlink_trap_group_item *group_item; 1596 + 1597 + group_item = devlink_trap_group_item_lookup(devlink, group->name); 1598 + if (WARN_ON_ONCE(!group_item)) 1599 + return; 1600 + 1601 + devlink_trap_group_notify(devlink, group_item, 1602 + DEVLINK_CMD_TRAP_GROUP_DEL); 1603 + list_del(&group_item->list); 1604 + free_percpu(group_item->stats); 1605 + kfree(group_item); 1606 + } 1607 + 1608 + /** 1609 + * devl_trap_groups_register - Register packet trap groups with devlink. 1610 + * @devlink: devlink. 1611 + * @groups: Packet trap groups. 1612 + * @groups_count: Count of provided packet trap groups. 1613 + * 1614 + * Return: Non-zero value on failure. 1615 + */ 1616 + int devl_trap_groups_register(struct devlink *devlink, 1617 + const struct devlink_trap_group *groups, 1618 + size_t groups_count) 1619 + { 1620 + int i, err; 1621 + 1622 + devl_assert_locked(devlink); 1623 + for (i = 0; i < groups_count; i++) { 1624 + const struct devlink_trap_group *group = &groups[i]; 1625 + 1626 + err = devlink_trap_group_verify(group); 1627 + if (err) 1628 + goto err_trap_group_verify; 1629 + 1630 + err = devlink_trap_group_register(devlink, group); 1631 + if (err) 1632 + goto err_trap_group_register; 1633 + } 1634 + 1635 + return 0; 1636 + 1637 + err_trap_group_register: 1638 + err_trap_group_verify: 1639 + for (i--; i >= 0; i--) 1640 + devlink_trap_group_unregister(devlink, &groups[i]); 1641 + return err; 1642 + } 1643 + EXPORT_SYMBOL_GPL(devl_trap_groups_register); 1644 + 1645 + /** 1646 + * devlink_trap_groups_register - Register packet trap groups with devlink. 1647 + * @devlink: devlink. 1648 + * @groups: Packet trap groups. 1649 + * @groups_count: Count of provided packet trap groups. 1650 + * 1651 + * Context: Takes and release devlink->lock <mutex>. 1652 + * 1653 + * Return: Non-zero value on failure. 1654 + */ 1655 + int devlink_trap_groups_register(struct devlink *devlink, 1656 + const struct devlink_trap_group *groups, 1657 + size_t groups_count) 1658 + { 1659 + int err; 1660 + 1661 + devl_lock(devlink); 1662 + err = devl_trap_groups_register(devlink, groups, groups_count); 1663 + devl_unlock(devlink); 1664 + return err; 1665 + } 1666 + EXPORT_SYMBOL_GPL(devlink_trap_groups_register); 1667 + 1668 + /** 1669 + * devl_trap_groups_unregister - Unregister packet trap groups from devlink. 1670 + * @devlink: devlink. 1671 + * @groups: Packet trap groups. 1672 + * @groups_count: Count of provided packet trap groups. 1673 + */ 1674 + void devl_trap_groups_unregister(struct devlink *devlink, 1675 + const struct devlink_trap_group *groups, 1676 + size_t groups_count) 1677 + { 1678 + int i; 1679 + 1680 + devl_assert_locked(devlink); 1681 + for (i = groups_count - 1; i >= 0; i--) 1682 + devlink_trap_group_unregister(devlink, &groups[i]); 1683 + } 1684 + EXPORT_SYMBOL_GPL(devl_trap_groups_unregister); 1685 + 1686 + /** 1687 + * devlink_trap_groups_unregister - Unregister packet trap groups from devlink. 1688 + * @devlink: devlink. 1689 + * @groups: Packet trap groups. 1690 + * @groups_count: Count of provided packet trap groups. 1691 + * 1692 + * Context: Takes and release devlink->lock <mutex>. 1693 + */ 1694 + void devlink_trap_groups_unregister(struct devlink *devlink, 1695 + const struct devlink_trap_group *groups, 1696 + size_t groups_count) 1697 + { 1698 + devl_lock(devlink); 1699 + devl_trap_groups_unregister(devlink, groups, groups_count); 1700 + devl_unlock(devlink); 1701 + } 1702 + EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister); 1703 + 1704 + static void 1705 + devlink_trap_policer_notify(struct devlink *devlink, 1706 + const struct devlink_trap_policer_item *policer_item, 1707 + enum devlink_command cmd) 1708 + { 1709 + struct sk_buff *msg; 1710 + int err; 1711 + 1712 + WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW && 1713 + cmd != DEVLINK_CMD_TRAP_POLICER_DEL); 1714 + if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 1715 + return; 1716 + 1717 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1718 + if (!msg) 1719 + return; 1720 + 1721 + err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0, 1722 + 0, 0); 1723 + if (err) { 1724 + nlmsg_free(msg); 1725 + return; 1726 + } 1727 + 1728 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 1729 + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 1730 + } 1731 + 1732 + void devlink_trap_policers_notify_register(struct devlink *devlink) 1733 + { 1734 + struct devlink_trap_policer_item *policer_item; 1735 + 1736 + list_for_each_entry(policer_item, &devlink->trap_policer_list, list) 1737 + devlink_trap_policer_notify(devlink, policer_item, 1738 + DEVLINK_CMD_TRAP_POLICER_NEW); 1739 + } 1740 + 1741 + void devlink_trap_policers_notify_unregister(struct devlink *devlink) 1742 + { 1743 + struct devlink_trap_policer_item *policer_item; 1744 + 1745 + list_for_each_entry_reverse(policer_item, &devlink->trap_policer_list, 1746 + list) 1747 + devlink_trap_policer_notify(devlink, policer_item, 1748 + DEVLINK_CMD_TRAP_POLICER_DEL); 1749 + } 1750 + 1751 + static int 1752 + devlink_trap_policer_register(struct devlink *devlink, 1753 + const struct devlink_trap_policer *policer) 1754 + { 1755 + struct devlink_trap_policer_item *policer_item; 1756 + int err; 1757 + 1758 + if (devlink_trap_policer_item_lookup(devlink, policer->id)) 1759 + return -EEXIST; 1760 + 1761 + policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL); 1762 + if (!policer_item) 1763 + return -ENOMEM; 1764 + 1765 + policer_item->policer = policer; 1766 + policer_item->rate = policer->init_rate; 1767 + policer_item->burst = policer->init_burst; 1768 + 1769 + if (devlink->ops->trap_policer_init) { 1770 + err = devlink->ops->trap_policer_init(devlink, policer); 1771 + if (err) 1772 + goto err_policer_init; 1773 + } 1774 + 1775 + list_add_tail(&policer_item->list, &devlink->trap_policer_list); 1776 + devlink_trap_policer_notify(devlink, policer_item, 1777 + DEVLINK_CMD_TRAP_POLICER_NEW); 1778 + 1779 + return 0; 1780 + 1781 + err_policer_init: 1782 + kfree(policer_item); 1783 + return err; 1784 + } 1785 + 1786 + static void 1787 + devlink_trap_policer_unregister(struct devlink *devlink, 1788 + const struct devlink_trap_policer *policer) 1789 + { 1790 + struct devlink_trap_policer_item *policer_item; 1791 + 1792 + policer_item = devlink_trap_policer_item_lookup(devlink, policer->id); 1793 + if (WARN_ON_ONCE(!policer_item)) 1794 + return; 1795 + 1796 + devlink_trap_policer_notify(devlink, policer_item, 1797 + DEVLINK_CMD_TRAP_POLICER_DEL); 1798 + list_del(&policer_item->list); 1799 + if (devlink->ops->trap_policer_fini) 1800 + devlink->ops->trap_policer_fini(devlink, policer); 1801 + kfree(policer_item); 1802 + } 1803 + 1804 + /** 1805 + * devl_trap_policers_register - Register packet trap policers with devlink. 1806 + * @devlink: devlink. 1807 + * @policers: Packet trap policers. 1808 + * @policers_count: Count of provided packet trap policers. 1809 + * 1810 + * Return: Non-zero value on failure. 1811 + */ 1812 + int 1813 + devl_trap_policers_register(struct devlink *devlink, 1814 + const struct devlink_trap_policer *policers, 1815 + size_t policers_count) 1816 + { 1817 + int i, err; 1818 + 1819 + devl_assert_locked(devlink); 1820 + for (i = 0; i < policers_count; i++) { 1821 + const struct devlink_trap_policer *policer = &policers[i]; 1822 + 1823 + if (WARN_ON(policer->id == 0 || 1824 + policer->max_rate < policer->min_rate || 1825 + policer->max_burst < policer->min_burst)) { 1826 + err = -EINVAL; 1827 + goto err_trap_policer_verify; 1828 + } 1829 + 1830 + err = devlink_trap_policer_register(devlink, policer); 1831 + if (err) 1832 + goto err_trap_policer_register; 1833 + } 1834 + return 0; 1835 + 1836 + err_trap_policer_register: 1837 + err_trap_policer_verify: 1838 + for (i--; i >= 0; i--) 1839 + devlink_trap_policer_unregister(devlink, &policers[i]); 1840 + return err; 1841 + } 1842 + EXPORT_SYMBOL_GPL(devl_trap_policers_register); 1843 + 1844 + /** 1845 + * devl_trap_policers_unregister - Unregister packet trap policers from devlink. 1846 + * @devlink: devlink. 1847 + * @policers: Packet trap policers. 1848 + * @policers_count: Count of provided packet trap policers. 1849 + */ 1850 + void 1851 + devl_trap_policers_unregister(struct devlink *devlink, 1852 + const struct devlink_trap_policer *policers, 1853 + size_t policers_count) 1854 + { 1855 + int i; 1856 + 1857 + devl_assert_locked(devlink); 1858 + for (i = policers_count - 1; i >= 0; i--) 1859 + devlink_trap_policer_unregister(devlink, &policers[i]); 1860 + } 1861 + EXPORT_SYMBOL_GPL(devl_trap_policers_unregister);