This source file includes following definitions.
- devlink_net
- devlink_net_set
- devlink_get_from_attrs
- devlink_get_from_info
- devlink_port_get_by_index
- devlink_port_index_exists
- devlink_port_get_from_attrs
- devlink_port_get_from_info
- devlink_sb_pool_count
- devlink_sb_get_by_index
- devlink_sb_index_exists
- devlink_sb_get_from_attrs
- devlink_sb_get_from_info
- devlink_sb_pool_index_get_from_attrs
- devlink_sb_pool_index_get_from_info
- devlink_sb_pool_type_get_from_attrs
- devlink_sb_pool_type_get_from_info
- devlink_sb_th_type_get_from_attrs
- devlink_sb_th_type_get_from_info
- devlink_sb_tc_index_get_from_attrs
- devlink_sb_tc_index_get_from_info
- devlink_region_get_by_name
- devlink_region_snapshot_get_by_id
- devlink_nl_pre_doit
- devlink_nl_post_doit
- devlink_nl_put_handle
- devlink_nl_fill
- devlink_notify
- devlink_nl_port_attrs_put
- devlink_nl_port_fill
- devlink_port_notify
- devlink_nl_cmd_get_doit
- devlink_nl_cmd_get_dumpit
- devlink_nl_cmd_port_get_doit
- devlink_nl_cmd_port_get_dumpit
- devlink_port_type_set
- devlink_nl_cmd_port_set_doit
- devlink_port_split
- devlink_nl_cmd_port_split_doit
- devlink_port_unsplit
- devlink_nl_cmd_port_unsplit_doit
- devlink_nl_sb_fill
- devlink_nl_cmd_sb_get_doit
- devlink_nl_cmd_sb_get_dumpit
- devlink_nl_sb_pool_fill
- devlink_nl_cmd_sb_pool_get_doit
- __sb_pool_get_dumpit
- devlink_nl_cmd_sb_pool_get_dumpit
- devlink_sb_pool_set
- devlink_nl_cmd_sb_pool_set_doit
- devlink_nl_sb_port_pool_fill
- devlink_nl_cmd_sb_port_pool_get_doit
- __sb_port_pool_get_dumpit
- devlink_nl_cmd_sb_port_pool_get_dumpit
- devlink_sb_port_pool_set
- devlink_nl_cmd_sb_port_pool_set_doit
- devlink_nl_sb_tc_pool_bind_fill
- devlink_nl_cmd_sb_tc_pool_bind_get_doit
- __sb_tc_pool_bind_get_dumpit
- devlink_nl_cmd_sb_tc_pool_bind_get_dumpit
- devlink_sb_tc_pool_bind_set
- devlink_nl_cmd_sb_tc_pool_bind_set_doit
- devlink_nl_cmd_sb_occ_snapshot_doit
- devlink_nl_cmd_sb_occ_max_clear_doit
- devlink_nl_eswitch_fill
- devlink_nl_cmd_eswitch_get_doit
- devlink_nl_cmd_eswitch_set_doit
- devlink_dpipe_match_put
- devlink_dpipe_matches_put
- devlink_dpipe_action_put
- devlink_dpipe_actions_put
- devlink_dpipe_table_put
- devlink_dpipe_send_and_alloc_skb
- devlink_dpipe_tables_fill
- devlink_nl_cmd_dpipe_table_get
- devlink_dpipe_value_put
- devlink_dpipe_action_value_put
- devlink_dpipe_action_values_put
- devlink_dpipe_match_value_put
- devlink_dpipe_match_values_put
- devlink_dpipe_entry_put
- devlink_dpipe_table_find
- devlink_dpipe_entry_ctx_prepare
- devlink_dpipe_entry_ctx_append
- devlink_dpipe_entry_ctx_close
- devlink_dpipe_entry_clear
- devlink_dpipe_entries_fill
- devlink_nl_cmd_dpipe_entries_get
- devlink_dpipe_fields_put
- devlink_dpipe_header_put
- devlink_dpipe_headers_fill
- devlink_nl_cmd_dpipe_headers_get
- devlink_dpipe_table_counters_set
- devlink_nl_cmd_dpipe_table_counters_set
- devlink_resource_find
- devlink_resource_validate_children
- devlink_resource_validate_size
- devlink_nl_cmd_resource_set
- devlink_resource_size_params_put
- devlink_resource_occ_put
- devlink_resource_put
- devlink_resource_fill
- devlink_nl_cmd_resource_dump
- devlink_resources_validate
- devlink_reload_supported
- devlink_reload_failed_set
- devlink_is_reload_failed
- devlink_nl_cmd_reload
- devlink_nl_flash_update_fill
- __devlink_flash_update_notify
- devlink_flash_update_begin_notify
- devlink_flash_update_end_notify
- devlink_flash_update_status_notify
- devlink_nl_cmd_flash_update
- devlink_param_generic_verify
- devlink_param_driver_verify
- devlink_param_find_by_name
- devlink_param_find_by_id
- devlink_param_cmode_is_supported
- devlink_param_get
- devlink_param_set
- devlink_param_type_to_nla_type
- devlink_nl_param_value_fill_one
- devlink_nl_param_fill
- devlink_param_notify
- devlink_nl_cmd_param_get_dumpit
- devlink_param_type_get_from_info
- devlink_param_value_get_from_info
- devlink_param_get_from_info
- devlink_nl_cmd_param_get_doit
- __devlink_nl_cmd_param_set_doit
- devlink_nl_cmd_param_set_doit
- devlink_param_register_one
- devlink_param_unregister_one
- devlink_nl_cmd_port_param_get_dumpit
- devlink_nl_cmd_port_param_get_doit
- devlink_nl_cmd_port_param_set_doit
- devlink_nl_region_snapshot_id_put
- devlink_nl_region_snapshots_id_put
- devlink_nl_region_fill
- devlink_nl_region_notify
- devlink_region_snapshot_del
- devlink_nl_cmd_region_get_doit
- devlink_nl_cmd_region_get_dumpit
- devlink_nl_cmd_region_del
- devlink_nl_cmd_region_read_chunk_fill
- devlink_nl_region_read_snapshot_fill
- devlink_nl_cmd_region_read_dumpit
- devlink_info_driver_name_put
- devlink_info_serial_number_put
- devlink_info_version_put
- devlink_info_version_fixed_put
- devlink_info_version_stored_put
- devlink_info_version_running_put
- devlink_nl_info_fill
- devlink_nl_cmd_info_get_doit
- devlink_nl_cmd_info_get_dumpit
- devlink_fmsg_alloc
- devlink_fmsg_free
- devlink_fmsg_nest_common
- devlink_fmsg_obj_nest_start
- devlink_fmsg_nest_end
- devlink_fmsg_obj_nest_end
- devlink_fmsg_put_name
- devlink_fmsg_pair_nest_start
- devlink_fmsg_pair_nest_end
- devlink_fmsg_arr_pair_nest_start
- devlink_fmsg_arr_pair_nest_end
- devlink_fmsg_put_value
- devlink_fmsg_bool_put
- devlink_fmsg_u8_put
- devlink_fmsg_u32_put
- devlink_fmsg_u64_put
- devlink_fmsg_string_put
- devlink_fmsg_binary_put
- devlink_fmsg_bool_pair_put
- devlink_fmsg_u8_pair_put
- devlink_fmsg_u32_pair_put
- devlink_fmsg_u64_pair_put
- devlink_fmsg_string_pair_put
- devlink_fmsg_binary_pair_put
- devlink_fmsg_item_fill_type
- devlink_fmsg_item_fill_data
- devlink_fmsg_prepare_skb
- devlink_fmsg_snd
- devlink_fmsg_dumpit
- devlink_health_reporter_priv
- devlink_health_reporter_find_by_name
- devlink_health_reporter_create
- devlink_health_reporter_destroy
- devlink_health_reporter_state_update
- devlink_health_reporter_recover
- devlink_health_dump_clear
- devlink_health_do_dump
- devlink_health_report
- devlink_health_reporter_get_from_attrs
- devlink_health_reporter_get_from_info
- devlink_health_reporter_get_from_cb
- devlink_health_reporter_put
- devlink_nl_health_reporter_fill
- devlink_nl_cmd_health_reporter_get_doit
- devlink_nl_cmd_health_reporter_get_dumpit
- devlink_nl_cmd_health_reporter_set_doit
- devlink_nl_cmd_health_reporter_recover_doit
- devlink_nl_cmd_health_reporter_diagnose_doit
- devlink_nl_cmd_health_reporter_dump_get_dumpit
- devlink_nl_cmd_health_reporter_dump_clear_doit
- devlink_trap_item_lookup
- devlink_trap_item_get_from_info
- devlink_trap_action_get_from_info
- devlink_trap_metadata_put
- devlink_trap_stats_read
- devlink_trap_stats_put
- devlink_nl_trap_fill
- devlink_nl_cmd_trap_get_doit
- devlink_nl_cmd_trap_get_dumpit
- __devlink_trap_action_set
- devlink_trap_action_set
- devlink_nl_cmd_trap_set_doit
- devlink_trap_group_item_lookup
- devlink_trap_group_item_get_from_info
- devlink_nl_trap_group_fill
- devlink_nl_cmd_trap_group_get_doit
- devlink_nl_cmd_trap_group_get_dumpit
- __devlink_trap_group_action_set
- devlink_trap_group_action_set
- devlink_nl_cmd_trap_group_set_doit
- devlink_alloc
- devlink_register
- devlink_unregister
- devlink_reload_enable
- devlink_reload_disable
- devlink_free
- devlink_port_type_warn
- devlink_port_type_should_warn
- devlink_port_type_warn_schedule
- devlink_port_type_warn_cancel
- devlink_port_register
- devlink_port_unregister
- __devlink_port_type_set
- devlink_port_type_eth_set
- devlink_port_type_ib_set
- devlink_port_type_clear
- __devlink_port_attrs_set
- devlink_port_attrs_set
- devlink_port_attrs_pci_pf_set
- devlink_port_attrs_pci_vf_set
- __devlink_port_phys_port_name_get
- devlink_sb_register
- devlink_sb_unregister
- devlink_dpipe_headers_register
- devlink_dpipe_headers_unregister
- devlink_dpipe_table_counter_enabled
- devlink_dpipe_table_register
- devlink_dpipe_table_unregister
- devlink_resource_register
- devlink_resources_unregister
- devlink_resource_size_get
- devlink_dpipe_table_resource_set
- devlink_resource_occ_get_register
- devlink_resource_occ_get_unregister
- devlink_param_verify
- __devlink_params_register
- __devlink_params_unregister
- devlink_params_register
- devlink_params_unregister
- devlink_params_publish
- devlink_params_unpublish
- devlink_port_params_register
- devlink_port_params_unregister
- __devlink_param_driverinit_value_get
- __devlink_param_driverinit_value_set
- devlink_param_driverinit_value_get
- devlink_param_driverinit_value_set
- devlink_port_param_driverinit_value_get
- devlink_port_param_driverinit_value_set
- devlink_param_value_changed
- devlink_port_param_value_changed
- devlink_param_value_str_fill
- devlink_region_create
- devlink_region_destroy
- devlink_region_shapshot_id_get
- devlink_region_snapshot_create
- devlink_trap_generic_verify
- devlink_trap_driver_verify
- devlink_trap_verify
- devlink_trap_group_generic_verify
- devlink_trap_group_driver_verify
- devlink_trap_group_verify
- devlink_trap_group_notify
- devlink_trap_group_item_create
- devlink_trap_group_item_destroy
- devlink_trap_group_item_get
- devlink_trap_group_item_put
- devlink_trap_item_group_link
- devlink_trap_item_group_unlink
- devlink_trap_notify
- devlink_trap_register
- devlink_trap_unregister
- devlink_trap_disable
- devlink_traps_register
- devlink_traps_unregister
- devlink_trap_stats_update
- devlink_trap_report_metadata_fill
- devlink_trap_report
- devlink_trap_ctx_priv
- __devlink_compat_running_version
- devlink_compat_running_version
- devlink_compat_flash_update
- devlink_compat_phys_port_name_get
- devlink_compat_switch_id_get
- devlink_init
1
2
3
4
5
6
7
8
9
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/types.h>
13 #include <linux/slab.h>
14 #include <linux/gfp.h>
15 #include <linux/device.h>
16 #include <linux/list.h>
17 #include <linux/netdevice.h>
18 #include <linux/spinlock.h>
19 #include <linux/refcount.h>
20 #include <linux/workqueue.h>
21 #include <linux/u64_stats_sync.h>
22 #include <linux/timekeeping.h>
23 #include <rdma/ib_verbs.h>
24 #include <net/netlink.h>
25 #include <net/genetlink.h>
26 #include <net/rtnetlink.h>
27 #include <net/net_namespace.h>
28 #include <net/sock.h>
29 #include <net/devlink.h>
30 #include <net/drop_monitor.h>
31 #define CREATE_TRACE_POINTS
32 #include <trace/events/devlink.h>
33
34 static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
35 {
36 .name = "destination mac",
37 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
38 .bitwidth = 48,
39 },
40 };
41
42 struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
43 .name = "ethernet",
44 .id = DEVLINK_DPIPE_HEADER_ETHERNET,
45 .fields = devlink_dpipe_fields_ethernet,
46 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
47 .global = true,
48 };
49 EXPORT_SYMBOL(devlink_dpipe_header_ethernet);
50
51 static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
52 {
53 .name = "destination ip",
54 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
55 .bitwidth = 32,
56 },
57 };
58
59 struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
60 .name = "ipv4",
61 .id = DEVLINK_DPIPE_HEADER_IPV4,
62 .fields = devlink_dpipe_fields_ipv4,
63 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
64 .global = true,
65 };
66 EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
67
68 static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
69 {
70 .name = "destination ip",
71 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
72 .bitwidth = 128,
73 },
74 };
75
76 struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
77 .name = "ipv6",
78 .id = DEVLINK_DPIPE_HEADER_IPV6,
79 .fields = devlink_dpipe_fields_ipv6,
80 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
81 .global = true,
82 };
83 EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
84
85 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
86 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr);
87
88 static LIST_HEAD(devlink_list);
89
90
91
92
93
94
95
96 static DEFINE_MUTEX(devlink_mutex);
97
98 static struct net *devlink_net(const struct devlink *devlink)
99 {
100 return read_pnet(&devlink->_net);
101 }
102
103 static void devlink_net_set(struct devlink *devlink, struct net *net)
104 {
105 write_pnet(&devlink->_net, net);
106 }
107
108 static struct devlink *devlink_get_from_attrs(struct net *net,
109 struct nlattr **attrs)
110 {
111 struct devlink *devlink;
112 char *busname;
113 char *devname;
114
115 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
116 return ERR_PTR(-EINVAL);
117
118 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
119 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
120
121 lockdep_assert_held(&devlink_mutex);
122
123 list_for_each_entry(devlink, &devlink_list, list) {
124 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
125 strcmp(dev_name(devlink->dev), devname) == 0 &&
126 net_eq(devlink_net(devlink), net))
127 return devlink;
128 }
129
130 return ERR_PTR(-ENODEV);
131 }
132
133 static struct devlink *devlink_get_from_info(struct genl_info *info)
134 {
135 return devlink_get_from_attrs(genl_info_net(info), info->attrs);
136 }
137
138 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
139 unsigned int port_index)
140 {
141 struct devlink_port *devlink_port;
142
143 list_for_each_entry(devlink_port, &devlink->port_list, list) {
144 if (devlink_port->index == port_index)
145 return devlink_port;
146 }
147 return NULL;
148 }
149
150 static bool devlink_port_index_exists(struct devlink *devlink,
151 unsigned int port_index)
152 {
153 return devlink_port_get_by_index(devlink, port_index);
154 }
155
156 static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
157 struct nlattr **attrs)
158 {
159 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
160 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
161 struct devlink_port *devlink_port;
162
163 devlink_port = devlink_port_get_by_index(devlink, port_index);
164 if (!devlink_port)
165 return ERR_PTR(-ENODEV);
166 return devlink_port;
167 }
168 return ERR_PTR(-EINVAL);
169 }
170
171 static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
172 struct genl_info *info)
173 {
174 return devlink_port_get_from_attrs(devlink, info->attrs);
175 }
176
177 struct devlink_sb {
178 struct list_head list;
179 unsigned int index;
180 u32 size;
181 u16 ingress_pools_count;
182 u16 egress_pools_count;
183 u16 ingress_tc_count;
184 u16 egress_tc_count;
185 };
186
187 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
188 {
189 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
190 }
191
192 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
193 unsigned int sb_index)
194 {
195 struct devlink_sb *devlink_sb;
196
197 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
198 if (devlink_sb->index == sb_index)
199 return devlink_sb;
200 }
201 return NULL;
202 }
203
204 static bool devlink_sb_index_exists(struct devlink *devlink,
205 unsigned int sb_index)
206 {
207 return devlink_sb_get_by_index(devlink, sb_index);
208 }
209
210 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
211 struct nlattr **attrs)
212 {
213 if (attrs[DEVLINK_ATTR_SB_INDEX]) {
214 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
215 struct devlink_sb *devlink_sb;
216
217 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
218 if (!devlink_sb)
219 return ERR_PTR(-ENODEV);
220 return devlink_sb;
221 }
222 return ERR_PTR(-EINVAL);
223 }
224
225 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
226 struct genl_info *info)
227 {
228 return devlink_sb_get_from_attrs(devlink, info->attrs);
229 }
230
231 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
232 struct nlattr **attrs,
233 u16 *p_pool_index)
234 {
235 u16 val;
236
237 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
238 return -EINVAL;
239
240 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
241 if (val >= devlink_sb_pool_count(devlink_sb))
242 return -EINVAL;
243 *p_pool_index = val;
244 return 0;
245 }
246
247 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
248 struct genl_info *info,
249 u16 *p_pool_index)
250 {
251 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
252 p_pool_index);
253 }
254
255 static int
256 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
257 enum devlink_sb_pool_type *p_pool_type)
258 {
259 u8 val;
260
261 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
262 return -EINVAL;
263
264 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
265 if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
266 val != DEVLINK_SB_POOL_TYPE_EGRESS)
267 return -EINVAL;
268 *p_pool_type = val;
269 return 0;
270 }
271
272 static int
273 devlink_sb_pool_type_get_from_info(struct genl_info *info,
274 enum devlink_sb_pool_type *p_pool_type)
275 {
276 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
277 }
278
279 static int
280 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
281 enum devlink_sb_threshold_type *p_th_type)
282 {
283 u8 val;
284
285 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
286 return -EINVAL;
287
288 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
289 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
290 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
291 return -EINVAL;
292 *p_th_type = val;
293 return 0;
294 }
295
296 static int
297 devlink_sb_th_type_get_from_info(struct genl_info *info,
298 enum devlink_sb_threshold_type *p_th_type)
299 {
300 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
301 }
302
303 static int
304 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
305 struct nlattr **attrs,
306 enum devlink_sb_pool_type pool_type,
307 u16 *p_tc_index)
308 {
309 u16 val;
310
311 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
312 return -EINVAL;
313
314 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
315 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
316 val >= devlink_sb->ingress_tc_count)
317 return -EINVAL;
318 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
319 val >= devlink_sb->egress_tc_count)
320 return -EINVAL;
321 *p_tc_index = val;
322 return 0;
323 }
324
325 static int
326 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
327 struct genl_info *info,
328 enum devlink_sb_pool_type pool_type,
329 u16 *p_tc_index)
330 {
331 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
332 pool_type, p_tc_index);
333 }
334
335 struct devlink_region {
336 struct devlink *devlink;
337 struct list_head list;
338 const char *name;
339 struct list_head snapshot_list;
340 u32 max_snapshots;
341 u32 cur_snapshots;
342 u64 size;
343 };
344
345 struct devlink_snapshot {
346 struct list_head list;
347 struct devlink_region *region;
348 devlink_snapshot_data_dest_t *data_destructor;
349 u8 *data;
350 u32 id;
351 };
352
353 static struct devlink_region *
354 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
355 {
356 struct devlink_region *region;
357
358 list_for_each_entry(region, &devlink->region_list, list)
359 if (!strcmp(region->name, region_name))
360 return region;
361
362 return NULL;
363 }
364
365 static struct devlink_snapshot *
366 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
367 {
368 struct devlink_snapshot *snapshot;
369
370 list_for_each_entry(snapshot, ®ion->snapshot_list, list)
371 if (snapshot->id == id)
372 return snapshot;
373
374 return NULL;
375 }
376
377 #define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
378 #define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
379 #define DEVLINK_NL_FLAG_NEED_SB BIT(2)
380
381
382
383
384
385 #define DEVLINK_NL_FLAG_NO_LOCK BIT(3)
386
387 static int devlink_nl_pre_doit(const struct genl_ops *ops,
388 struct sk_buff *skb, struct genl_info *info)
389 {
390 struct devlink *devlink;
391 int err;
392
393 mutex_lock(&devlink_mutex);
394 devlink = devlink_get_from_info(info);
395 if (IS_ERR(devlink)) {
396 mutex_unlock(&devlink_mutex);
397 return PTR_ERR(devlink);
398 }
399 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
400 mutex_lock(&devlink->lock);
401 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
402 info->user_ptr[0] = devlink;
403 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
404 struct devlink_port *devlink_port;
405
406 devlink_port = devlink_port_get_from_info(devlink, info);
407 if (IS_ERR(devlink_port)) {
408 err = PTR_ERR(devlink_port);
409 goto unlock;
410 }
411 info->user_ptr[0] = devlink_port;
412 }
413 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
414 struct devlink_sb *devlink_sb;
415
416 devlink_sb = devlink_sb_get_from_info(devlink, info);
417 if (IS_ERR(devlink_sb)) {
418 err = PTR_ERR(devlink_sb);
419 goto unlock;
420 }
421 info->user_ptr[1] = devlink_sb;
422 }
423 return 0;
424
425 unlock:
426 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
427 mutex_unlock(&devlink->lock);
428 mutex_unlock(&devlink_mutex);
429 return err;
430 }
431
432 static void devlink_nl_post_doit(const struct genl_ops *ops,
433 struct sk_buff *skb, struct genl_info *info)
434 {
435 struct devlink *devlink;
436
437 devlink = devlink_get_from_info(info);
438 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
439 mutex_unlock(&devlink->lock);
440 mutex_unlock(&devlink_mutex);
441 }
442
443 static struct genl_family devlink_nl_family;
444
445 enum devlink_multicast_groups {
446 DEVLINK_MCGRP_CONFIG,
447 };
448
449 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
450 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
451 };
452
453 static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
454 {
455 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
456 return -EMSGSIZE;
457 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
458 return -EMSGSIZE;
459 return 0;
460 }
461
462 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
463 enum devlink_command cmd, u32 portid,
464 u32 seq, int flags)
465 {
466 void *hdr;
467
468 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
469 if (!hdr)
470 return -EMSGSIZE;
471
472 if (devlink_nl_put_handle(msg, devlink))
473 goto nla_put_failure;
474 if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
475 goto nla_put_failure;
476
477 genlmsg_end(msg, hdr);
478 return 0;
479
480 nla_put_failure:
481 genlmsg_cancel(msg, hdr);
482 return -EMSGSIZE;
483 }
484
485 static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
486 {
487 struct sk_buff *msg;
488 int err;
489
490 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
491
492 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
493 if (!msg)
494 return;
495
496 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
497 if (err) {
498 nlmsg_free(msg);
499 return;
500 }
501
502 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
503 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
504 }
505
506 static int devlink_nl_port_attrs_put(struct sk_buff *msg,
507 struct devlink_port *devlink_port)
508 {
509 struct devlink_port_attrs *attrs = &devlink_port->attrs;
510
511 if (!attrs->set)
512 return 0;
513 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
514 return -EMSGSIZE;
515 switch (devlink_port->attrs.flavour) {
516 case DEVLINK_PORT_FLAVOUR_PCI_PF:
517 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
518 attrs->pci_pf.pf))
519 return -EMSGSIZE;
520 break;
521 case DEVLINK_PORT_FLAVOUR_PCI_VF:
522 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
523 attrs->pci_vf.pf) ||
524 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER,
525 attrs->pci_vf.vf))
526 return -EMSGSIZE;
527 break;
528 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
529 case DEVLINK_PORT_FLAVOUR_CPU:
530 case DEVLINK_PORT_FLAVOUR_DSA:
531 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER,
532 attrs->phys.port_number))
533 return -EMSGSIZE;
534 if (!attrs->split)
535 return 0;
536 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
537 attrs->phys.port_number))
538 return -EMSGSIZE;
539 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
540 attrs->phys.split_subport_number))
541 return -EMSGSIZE;
542 break;
543 default:
544 break;
545 }
546 return 0;
547 }
548
549 static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
550 struct devlink_port *devlink_port,
551 enum devlink_command cmd, u32 portid,
552 u32 seq, int flags)
553 {
554 void *hdr;
555
556 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
557 if (!hdr)
558 return -EMSGSIZE;
559
560 if (devlink_nl_put_handle(msg, devlink))
561 goto nla_put_failure;
562 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
563 goto nla_put_failure;
564
565 spin_lock_bh(&devlink_port->type_lock);
566 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
567 goto nla_put_failure_type_locked;
568 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
569 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
570 devlink_port->desired_type))
571 goto nla_put_failure_type_locked;
572 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
573 struct net_device *netdev = devlink_port->type_dev;
574
575 if (netdev &&
576 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
577 netdev->ifindex) ||
578 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
579 netdev->name)))
580 goto nla_put_failure_type_locked;
581 }
582 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
583 struct ib_device *ibdev = devlink_port->type_dev;
584
585 if (ibdev &&
586 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
587 ibdev->name))
588 goto nla_put_failure_type_locked;
589 }
590 spin_unlock_bh(&devlink_port->type_lock);
591 if (devlink_nl_port_attrs_put(msg, devlink_port))
592 goto nla_put_failure;
593
594 genlmsg_end(msg, hdr);
595 return 0;
596
597 nla_put_failure_type_locked:
598 spin_unlock_bh(&devlink_port->type_lock);
599 nla_put_failure:
600 genlmsg_cancel(msg, hdr);
601 return -EMSGSIZE;
602 }
603
604 static void devlink_port_notify(struct devlink_port *devlink_port,
605 enum devlink_command cmd)
606 {
607 struct devlink *devlink = devlink_port->devlink;
608 struct sk_buff *msg;
609 int err;
610
611 if (!devlink_port->registered)
612 return;
613
614 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
615
616 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
617 if (!msg)
618 return;
619
620 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
621 if (err) {
622 nlmsg_free(msg);
623 return;
624 }
625
626 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
627 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
628 }
629
630 static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
631 {
632 struct devlink *devlink = info->user_ptr[0];
633 struct sk_buff *msg;
634 int err;
635
636 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
637 if (!msg)
638 return -ENOMEM;
639
640 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
641 info->snd_portid, info->snd_seq, 0);
642 if (err) {
643 nlmsg_free(msg);
644 return err;
645 }
646
647 return genlmsg_reply(msg, info);
648 }
649
650 static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
651 struct netlink_callback *cb)
652 {
653 struct devlink *devlink;
654 int start = cb->args[0];
655 int idx = 0;
656 int err;
657
658 mutex_lock(&devlink_mutex);
659 list_for_each_entry(devlink, &devlink_list, list) {
660 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
661 continue;
662 if (idx < start) {
663 idx++;
664 continue;
665 }
666 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
667 NETLINK_CB(cb->skb).portid,
668 cb->nlh->nlmsg_seq, NLM_F_MULTI);
669 if (err)
670 goto out;
671 idx++;
672 }
673 out:
674 mutex_unlock(&devlink_mutex);
675
676 cb->args[0] = idx;
677 return msg->len;
678 }
679
680 static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
681 struct genl_info *info)
682 {
683 struct devlink_port *devlink_port = info->user_ptr[0];
684 struct devlink *devlink = devlink_port->devlink;
685 struct sk_buff *msg;
686 int err;
687
688 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
689 if (!msg)
690 return -ENOMEM;
691
692 err = devlink_nl_port_fill(msg, devlink, devlink_port,
693 DEVLINK_CMD_PORT_NEW,
694 info->snd_portid, info->snd_seq, 0);
695 if (err) {
696 nlmsg_free(msg);
697 return err;
698 }
699
700 return genlmsg_reply(msg, info);
701 }
702
703 static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
704 struct netlink_callback *cb)
705 {
706 struct devlink *devlink;
707 struct devlink_port *devlink_port;
708 int start = cb->args[0];
709 int idx = 0;
710 int err;
711
712 mutex_lock(&devlink_mutex);
713 list_for_each_entry(devlink, &devlink_list, list) {
714 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
715 continue;
716 mutex_lock(&devlink->lock);
717 list_for_each_entry(devlink_port, &devlink->port_list, list) {
718 if (idx < start) {
719 idx++;
720 continue;
721 }
722 err = devlink_nl_port_fill(msg, devlink, devlink_port,
723 DEVLINK_CMD_NEW,
724 NETLINK_CB(cb->skb).portid,
725 cb->nlh->nlmsg_seq,
726 NLM_F_MULTI);
727 if (err) {
728 mutex_unlock(&devlink->lock);
729 goto out;
730 }
731 idx++;
732 }
733 mutex_unlock(&devlink->lock);
734 }
735 out:
736 mutex_unlock(&devlink_mutex);
737
738 cb->args[0] = idx;
739 return msg->len;
740 }
741
742 static int devlink_port_type_set(struct devlink *devlink,
743 struct devlink_port *devlink_port,
744 enum devlink_port_type port_type)
745
746 {
747 int err;
748
749 if (devlink->ops->port_type_set) {
750 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
751 return -EINVAL;
752 if (port_type == devlink_port->type)
753 return 0;
754 err = devlink->ops->port_type_set(devlink_port, port_type);
755 if (err)
756 return err;
757 devlink_port->desired_type = port_type;
758 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
759 return 0;
760 }
761 return -EOPNOTSUPP;
762 }
763
764 static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
765 struct genl_info *info)
766 {
767 struct devlink_port *devlink_port = info->user_ptr[0];
768 struct devlink *devlink = devlink_port->devlink;
769 int err;
770
771 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
772 enum devlink_port_type port_type;
773
774 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
775 err = devlink_port_type_set(devlink, devlink_port, port_type);
776 if (err)
777 return err;
778 }
779 return 0;
780 }
781
782 static int devlink_port_split(struct devlink *devlink, u32 port_index,
783 u32 count, struct netlink_ext_ack *extack)
784
785 {
786 if (devlink->ops->port_split)
787 return devlink->ops->port_split(devlink, port_index, count,
788 extack);
789 return -EOPNOTSUPP;
790 }
791
792 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
793 struct genl_info *info)
794 {
795 struct devlink *devlink = info->user_ptr[0];
796 u32 port_index;
797 u32 count;
798
799 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
800 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
801 return -EINVAL;
802
803 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
804 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
805 return devlink_port_split(devlink, port_index, count, info->extack);
806 }
807
808 static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
809 struct netlink_ext_ack *extack)
810
811 {
812 if (devlink->ops->port_unsplit)
813 return devlink->ops->port_unsplit(devlink, port_index, extack);
814 return -EOPNOTSUPP;
815 }
816
817 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
818 struct genl_info *info)
819 {
820 struct devlink *devlink = info->user_ptr[0];
821 u32 port_index;
822
823 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
824 return -EINVAL;
825
826 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
827 return devlink_port_unsplit(devlink, port_index, info->extack);
828 }
829
830 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
831 struct devlink_sb *devlink_sb,
832 enum devlink_command cmd, u32 portid,
833 u32 seq, int flags)
834 {
835 void *hdr;
836
837 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
838 if (!hdr)
839 return -EMSGSIZE;
840
841 if (devlink_nl_put_handle(msg, devlink))
842 goto nla_put_failure;
843 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
844 goto nla_put_failure;
845 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
846 goto nla_put_failure;
847 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
848 devlink_sb->ingress_pools_count))
849 goto nla_put_failure;
850 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
851 devlink_sb->egress_pools_count))
852 goto nla_put_failure;
853 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
854 devlink_sb->ingress_tc_count))
855 goto nla_put_failure;
856 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
857 devlink_sb->egress_tc_count))
858 goto nla_put_failure;
859
860 genlmsg_end(msg, hdr);
861 return 0;
862
863 nla_put_failure:
864 genlmsg_cancel(msg, hdr);
865 return -EMSGSIZE;
866 }
867
868 static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
869 struct genl_info *info)
870 {
871 struct devlink *devlink = info->user_ptr[0];
872 struct devlink_sb *devlink_sb = info->user_ptr[1];
873 struct sk_buff *msg;
874 int err;
875
876 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
877 if (!msg)
878 return -ENOMEM;
879
880 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
881 DEVLINK_CMD_SB_NEW,
882 info->snd_portid, info->snd_seq, 0);
883 if (err) {
884 nlmsg_free(msg);
885 return err;
886 }
887
888 return genlmsg_reply(msg, info);
889 }
890
891 static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
892 struct netlink_callback *cb)
893 {
894 struct devlink *devlink;
895 struct devlink_sb *devlink_sb;
896 int start = cb->args[0];
897 int idx = 0;
898 int err;
899
900 mutex_lock(&devlink_mutex);
901 list_for_each_entry(devlink, &devlink_list, list) {
902 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
903 continue;
904 mutex_lock(&devlink->lock);
905 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
906 if (idx < start) {
907 idx++;
908 continue;
909 }
910 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
911 DEVLINK_CMD_SB_NEW,
912 NETLINK_CB(cb->skb).portid,
913 cb->nlh->nlmsg_seq,
914 NLM_F_MULTI);
915 if (err) {
916 mutex_unlock(&devlink->lock);
917 goto out;
918 }
919 idx++;
920 }
921 mutex_unlock(&devlink->lock);
922 }
923 out:
924 mutex_unlock(&devlink_mutex);
925
926 cb->args[0] = idx;
927 return msg->len;
928 }
929
930 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
931 struct devlink_sb *devlink_sb,
932 u16 pool_index, enum devlink_command cmd,
933 u32 portid, u32 seq, int flags)
934 {
935 struct devlink_sb_pool_info pool_info;
936 void *hdr;
937 int err;
938
939 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
940 pool_index, &pool_info);
941 if (err)
942 return err;
943
944 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
945 if (!hdr)
946 return -EMSGSIZE;
947
948 if (devlink_nl_put_handle(msg, devlink))
949 goto nla_put_failure;
950 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
951 goto nla_put_failure;
952 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
953 goto nla_put_failure;
954 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
955 goto nla_put_failure;
956 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
957 goto nla_put_failure;
958 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
959 pool_info.threshold_type))
960 goto nla_put_failure;
961 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
962 pool_info.cell_size))
963 goto nla_put_failure;
964
965 genlmsg_end(msg, hdr);
966 return 0;
967
968 nla_put_failure:
969 genlmsg_cancel(msg, hdr);
970 return -EMSGSIZE;
971 }
972
973 static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
974 struct genl_info *info)
975 {
976 struct devlink *devlink = info->user_ptr[0];
977 struct devlink_sb *devlink_sb = info->user_ptr[1];
978 struct sk_buff *msg;
979 u16 pool_index;
980 int err;
981
982 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
983 &pool_index);
984 if (err)
985 return err;
986
987 if (!devlink->ops->sb_pool_get)
988 return -EOPNOTSUPP;
989
990 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
991 if (!msg)
992 return -ENOMEM;
993
994 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
995 DEVLINK_CMD_SB_POOL_NEW,
996 info->snd_portid, info->snd_seq, 0);
997 if (err) {
998 nlmsg_free(msg);
999 return err;
1000 }
1001
1002 return genlmsg_reply(msg, info);
1003 }
1004
1005 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1006 struct devlink *devlink,
1007 struct devlink_sb *devlink_sb,
1008 u32 portid, u32 seq)
1009 {
1010 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1011 u16 pool_index;
1012 int err;
1013
1014 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1015 if (*p_idx < start) {
1016 (*p_idx)++;
1017 continue;
1018 }
1019 err = devlink_nl_sb_pool_fill(msg, devlink,
1020 devlink_sb,
1021 pool_index,
1022 DEVLINK_CMD_SB_POOL_NEW,
1023 portid, seq, NLM_F_MULTI);
1024 if (err)
1025 return err;
1026 (*p_idx)++;
1027 }
1028 return 0;
1029 }
1030
1031 static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
1032 struct netlink_callback *cb)
1033 {
1034 struct devlink *devlink;
1035 struct devlink_sb *devlink_sb;
1036 int start = cb->args[0];
1037 int idx = 0;
1038 int err;
1039
1040 mutex_lock(&devlink_mutex);
1041 list_for_each_entry(devlink, &devlink_list, list) {
1042 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1043 !devlink->ops->sb_pool_get)
1044 continue;
1045 mutex_lock(&devlink->lock);
1046 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1047 err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
1048 devlink_sb,
1049 NETLINK_CB(cb->skb).portid,
1050 cb->nlh->nlmsg_seq);
1051 if (err && err != -EOPNOTSUPP) {
1052 mutex_unlock(&devlink->lock);
1053 goto out;
1054 }
1055 }
1056 mutex_unlock(&devlink->lock);
1057 }
1058 out:
1059 mutex_unlock(&devlink_mutex);
1060
1061 cb->args[0] = idx;
1062 return msg->len;
1063 }
1064
1065 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
1066 u16 pool_index, u32 size,
1067 enum devlink_sb_threshold_type threshold_type,
1068 struct netlink_ext_ack *extack)
1069
1070 {
1071 const struct devlink_ops *ops = devlink->ops;
1072
1073 if (ops->sb_pool_set)
1074 return ops->sb_pool_set(devlink, sb_index, pool_index,
1075 size, threshold_type, extack);
1076 return -EOPNOTSUPP;
1077 }
1078
1079 static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
1080 struct genl_info *info)
1081 {
1082 struct devlink *devlink = info->user_ptr[0];
1083 struct devlink_sb *devlink_sb = info->user_ptr[1];
1084 enum devlink_sb_threshold_type threshold_type;
1085 u16 pool_index;
1086 u32 size;
1087 int err;
1088
1089 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1090 &pool_index);
1091 if (err)
1092 return err;
1093
1094 err = devlink_sb_th_type_get_from_info(info, &threshold_type);
1095 if (err)
1096 return err;
1097
1098 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
1099 return -EINVAL;
1100
1101 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
1102 return devlink_sb_pool_set(devlink, devlink_sb->index,
1103 pool_index, size, threshold_type,
1104 info->extack);
1105 }
1106
1107 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
1108 struct devlink *devlink,
1109 struct devlink_port *devlink_port,
1110 struct devlink_sb *devlink_sb,
1111 u16 pool_index,
1112 enum devlink_command cmd,
1113 u32 portid, u32 seq, int flags)
1114 {
1115 const struct devlink_ops *ops = devlink->ops;
1116 u32 threshold;
1117 void *hdr;
1118 int err;
1119
1120 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
1121 pool_index, &threshold);
1122 if (err)
1123 return err;
1124
1125 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1126 if (!hdr)
1127 return -EMSGSIZE;
1128
1129 if (devlink_nl_put_handle(msg, devlink))
1130 goto nla_put_failure;
1131 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1132 goto nla_put_failure;
1133 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1134 goto nla_put_failure;
1135 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1136 goto nla_put_failure;
1137 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1138 goto nla_put_failure;
1139
1140 if (ops->sb_occ_port_pool_get) {
1141 u32 cur;
1142 u32 max;
1143
1144 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
1145 pool_index, &cur, &max);
1146 if (err && err != -EOPNOTSUPP)
1147 return err;
1148 if (!err) {
1149 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1150 goto nla_put_failure;
1151 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1152 goto nla_put_failure;
1153 }
1154 }
1155
1156 genlmsg_end(msg, hdr);
1157 return 0;
1158
1159 nla_put_failure:
1160 genlmsg_cancel(msg, hdr);
1161 return -EMSGSIZE;
1162 }
1163
1164 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1165 struct genl_info *info)
1166 {
1167 struct devlink_port *devlink_port = info->user_ptr[0];
1168 struct devlink *devlink = devlink_port->devlink;
1169 struct devlink_sb *devlink_sb = info->user_ptr[1];
1170 struct sk_buff *msg;
1171 u16 pool_index;
1172 int err;
1173
1174 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1175 &pool_index);
1176 if (err)
1177 return err;
1178
1179 if (!devlink->ops->sb_port_pool_get)
1180 return -EOPNOTSUPP;
1181
1182 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1183 if (!msg)
1184 return -ENOMEM;
1185
1186 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1187 devlink_sb, pool_index,
1188 DEVLINK_CMD_SB_PORT_POOL_NEW,
1189 info->snd_portid, info->snd_seq, 0);
1190 if (err) {
1191 nlmsg_free(msg);
1192 return err;
1193 }
1194
1195 return genlmsg_reply(msg, info);
1196 }
1197
1198 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1199 struct devlink *devlink,
1200 struct devlink_sb *devlink_sb,
1201 u32 portid, u32 seq)
1202 {
1203 struct devlink_port *devlink_port;
1204 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1205 u16 pool_index;
1206 int err;
1207
1208 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1209 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1210 if (*p_idx < start) {
1211 (*p_idx)++;
1212 continue;
1213 }
1214 err = devlink_nl_sb_port_pool_fill(msg, devlink,
1215 devlink_port,
1216 devlink_sb,
1217 pool_index,
1218 DEVLINK_CMD_SB_PORT_POOL_NEW,
1219 portid, seq,
1220 NLM_F_MULTI);
1221 if (err)
1222 return err;
1223 (*p_idx)++;
1224 }
1225 }
1226 return 0;
1227 }
1228
1229 static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1230 struct netlink_callback *cb)
1231 {
1232 struct devlink *devlink;
1233 struct devlink_sb *devlink_sb;
1234 int start = cb->args[0];
1235 int idx = 0;
1236 int err;
1237
1238 mutex_lock(&devlink_mutex);
1239 list_for_each_entry(devlink, &devlink_list, list) {
1240 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1241 !devlink->ops->sb_port_pool_get)
1242 continue;
1243 mutex_lock(&devlink->lock);
1244 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1245 err = __sb_port_pool_get_dumpit(msg, start, &idx,
1246 devlink, devlink_sb,
1247 NETLINK_CB(cb->skb).portid,
1248 cb->nlh->nlmsg_seq);
1249 if (err && err != -EOPNOTSUPP) {
1250 mutex_unlock(&devlink->lock);
1251 goto out;
1252 }
1253 }
1254 mutex_unlock(&devlink->lock);
1255 }
1256 out:
1257 mutex_unlock(&devlink_mutex);
1258
1259 cb->args[0] = idx;
1260 return msg->len;
1261 }
1262
1263 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1264 unsigned int sb_index, u16 pool_index,
1265 u32 threshold,
1266 struct netlink_ext_ack *extack)
1267
1268 {
1269 const struct devlink_ops *ops = devlink_port->devlink->ops;
1270
1271 if (ops->sb_port_pool_set)
1272 return ops->sb_port_pool_set(devlink_port, sb_index,
1273 pool_index, threshold, extack);
1274 return -EOPNOTSUPP;
1275 }
1276
1277 static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1278 struct genl_info *info)
1279 {
1280 struct devlink_port *devlink_port = info->user_ptr[0];
1281 struct devlink_sb *devlink_sb = info->user_ptr[1];
1282 u16 pool_index;
1283 u32 threshold;
1284 int err;
1285
1286 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1287 &pool_index);
1288 if (err)
1289 return err;
1290
1291 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1292 return -EINVAL;
1293
1294 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1295 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1296 pool_index, threshold, info->extack);
1297 }
1298
1299 static int
1300 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1301 struct devlink_port *devlink_port,
1302 struct devlink_sb *devlink_sb, u16 tc_index,
1303 enum devlink_sb_pool_type pool_type,
1304 enum devlink_command cmd,
1305 u32 portid, u32 seq, int flags)
1306 {
1307 const struct devlink_ops *ops = devlink->ops;
1308 u16 pool_index;
1309 u32 threshold;
1310 void *hdr;
1311 int err;
1312
1313 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1314 tc_index, pool_type,
1315 &pool_index, &threshold);
1316 if (err)
1317 return err;
1318
1319 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1320 if (!hdr)
1321 return -EMSGSIZE;
1322
1323 if (devlink_nl_put_handle(msg, devlink))
1324 goto nla_put_failure;
1325 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1326 goto nla_put_failure;
1327 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1328 goto nla_put_failure;
1329 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1330 goto nla_put_failure;
1331 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1332 goto nla_put_failure;
1333 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1334 goto nla_put_failure;
1335 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1336 goto nla_put_failure;
1337
1338 if (ops->sb_occ_tc_port_bind_get) {
1339 u32 cur;
1340 u32 max;
1341
1342 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1343 devlink_sb->index,
1344 tc_index, pool_type,
1345 &cur, &max);
1346 if (err && err != -EOPNOTSUPP)
1347 return err;
1348 if (!err) {
1349 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1350 goto nla_put_failure;
1351 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1352 goto nla_put_failure;
1353 }
1354 }
1355
1356 genlmsg_end(msg, hdr);
1357 return 0;
1358
1359 nla_put_failure:
1360 genlmsg_cancel(msg, hdr);
1361 return -EMSGSIZE;
1362 }
1363
1364 static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1365 struct genl_info *info)
1366 {
1367 struct devlink_port *devlink_port = info->user_ptr[0];
1368 struct devlink *devlink = devlink_port->devlink;
1369 struct devlink_sb *devlink_sb = info->user_ptr[1];
1370 struct sk_buff *msg;
1371 enum devlink_sb_pool_type pool_type;
1372 u16 tc_index;
1373 int err;
1374
1375 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1376 if (err)
1377 return err;
1378
1379 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1380 pool_type, &tc_index);
1381 if (err)
1382 return err;
1383
1384 if (!devlink->ops->sb_tc_pool_bind_get)
1385 return -EOPNOTSUPP;
1386
1387 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1388 if (!msg)
1389 return -ENOMEM;
1390
1391 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1392 devlink_sb, tc_index, pool_type,
1393 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1394 info->snd_portid,
1395 info->snd_seq, 0);
1396 if (err) {
1397 nlmsg_free(msg);
1398 return err;
1399 }
1400
1401 return genlmsg_reply(msg, info);
1402 }
1403
1404 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1405 int start, int *p_idx,
1406 struct devlink *devlink,
1407 struct devlink_sb *devlink_sb,
1408 u32 portid, u32 seq)
1409 {
1410 struct devlink_port *devlink_port;
1411 u16 tc_index;
1412 int err;
1413
1414 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1415 for (tc_index = 0;
1416 tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1417 if (*p_idx < start) {
1418 (*p_idx)++;
1419 continue;
1420 }
1421 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1422 devlink_port,
1423 devlink_sb,
1424 tc_index,
1425 DEVLINK_SB_POOL_TYPE_INGRESS,
1426 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1427 portid, seq,
1428 NLM_F_MULTI);
1429 if (err)
1430 return err;
1431 (*p_idx)++;
1432 }
1433 for (tc_index = 0;
1434 tc_index < devlink_sb->egress_tc_count; tc_index++) {
1435 if (*p_idx < start) {
1436 (*p_idx)++;
1437 continue;
1438 }
1439 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1440 devlink_port,
1441 devlink_sb,
1442 tc_index,
1443 DEVLINK_SB_POOL_TYPE_EGRESS,
1444 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1445 portid, seq,
1446 NLM_F_MULTI);
1447 if (err)
1448 return err;
1449 (*p_idx)++;
1450 }
1451 }
1452 return 0;
1453 }
1454
1455 static int
1456 devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1457 struct netlink_callback *cb)
1458 {
1459 struct devlink *devlink;
1460 struct devlink_sb *devlink_sb;
1461 int start = cb->args[0];
1462 int idx = 0;
1463 int err;
1464
1465 mutex_lock(&devlink_mutex);
1466 list_for_each_entry(devlink, &devlink_list, list) {
1467 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1468 !devlink->ops->sb_tc_pool_bind_get)
1469 continue;
1470
1471 mutex_lock(&devlink->lock);
1472 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1473 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1474 devlink,
1475 devlink_sb,
1476 NETLINK_CB(cb->skb).portid,
1477 cb->nlh->nlmsg_seq);
1478 if (err && err != -EOPNOTSUPP) {
1479 mutex_unlock(&devlink->lock);
1480 goto out;
1481 }
1482 }
1483 mutex_unlock(&devlink->lock);
1484 }
1485 out:
1486 mutex_unlock(&devlink_mutex);
1487
1488 cb->args[0] = idx;
1489 return msg->len;
1490 }
1491
1492 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1493 unsigned int sb_index, u16 tc_index,
1494 enum devlink_sb_pool_type pool_type,
1495 u16 pool_index, u32 threshold,
1496 struct netlink_ext_ack *extack)
1497
1498 {
1499 const struct devlink_ops *ops = devlink_port->devlink->ops;
1500
1501 if (ops->sb_tc_pool_bind_set)
1502 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1503 tc_index, pool_type,
1504 pool_index, threshold, extack);
1505 return -EOPNOTSUPP;
1506 }
1507
1508 static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1509 struct genl_info *info)
1510 {
1511 struct devlink_port *devlink_port = info->user_ptr[0];
1512 struct devlink_sb *devlink_sb = info->user_ptr[1];
1513 enum devlink_sb_pool_type pool_type;
1514 u16 tc_index;
1515 u16 pool_index;
1516 u32 threshold;
1517 int err;
1518
1519 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1520 if (err)
1521 return err;
1522
1523 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1524 pool_type, &tc_index);
1525 if (err)
1526 return err;
1527
1528 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1529 &pool_index);
1530 if (err)
1531 return err;
1532
1533 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1534 return -EINVAL;
1535
1536 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1537 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1538 tc_index, pool_type,
1539 pool_index, threshold, info->extack);
1540 }
1541
1542 static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1543 struct genl_info *info)
1544 {
1545 struct devlink *devlink = info->user_ptr[0];
1546 struct devlink_sb *devlink_sb = info->user_ptr[1];
1547 const struct devlink_ops *ops = devlink->ops;
1548
1549 if (ops->sb_occ_snapshot)
1550 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1551 return -EOPNOTSUPP;
1552 }
1553
1554 static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1555 struct genl_info *info)
1556 {
1557 struct devlink *devlink = info->user_ptr[0];
1558 struct devlink_sb *devlink_sb = info->user_ptr[1];
1559 const struct devlink_ops *ops = devlink->ops;
1560
1561 if (ops->sb_occ_max_clear)
1562 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1563 return -EOPNOTSUPP;
1564 }
1565
1566 static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1567 enum devlink_command cmd, u32 portid,
1568 u32 seq, int flags)
1569 {
1570 const struct devlink_ops *ops = devlink->ops;
1571 enum devlink_eswitch_encap_mode encap_mode;
1572 u8 inline_mode;
1573 void *hdr;
1574 int err = 0;
1575 u16 mode;
1576
1577 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1578 if (!hdr)
1579 return -EMSGSIZE;
1580
1581 err = devlink_nl_put_handle(msg, devlink);
1582 if (err)
1583 goto nla_put_failure;
1584
1585 if (ops->eswitch_mode_get) {
1586 err = ops->eswitch_mode_get(devlink, &mode);
1587 if (err)
1588 goto nla_put_failure;
1589 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
1590 if (err)
1591 goto nla_put_failure;
1592 }
1593
1594 if (ops->eswitch_inline_mode_get) {
1595 err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
1596 if (err)
1597 goto nla_put_failure;
1598 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
1599 inline_mode);
1600 if (err)
1601 goto nla_put_failure;
1602 }
1603
1604 if (ops->eswitch_encap_mode_get) {
1605 err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
1606 if (err)
1607 goto nla_put_failure;
1608 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
1609 if (err)
1610 goto nla_put_failure;
1611 }
1612
1613 genlmsg_end(msg, hdr);
1614 return 0;
1615
1616 nla_put_failure:
1617 genlmsg_cancel(msg, hdr);
1618 return err;
1619 }
1620
1621 static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
1622 struct genl_info *info)
1623 {
1624 struct devlink *devlink = info->user_ptr[0];
1625 struct sk_buff *msg;
1626 int err;
1627
1628 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1629 if (!msg)
1630 return -ENOMEM;
1631
1632 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
1633 info->snd_portid, info->snd_seq, 0);
1634
1635 if (err) {
1636 nlmsg_free(msg);
1637 return err;
1638 }
1639
1640 return genlmsg_reply(msg, info);
1641 }
1642
1643 static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
1644 struct genl_info *info)
1645 {
1646 struct devlink *devlink = info->user_ptr[0];
1647 const struct devlink_ops *ops = devlink->ops;
1648 enum devlink_eswitch_encap_mode encap_mode;
1649 u8 inline_mode;
1650 int err = 0;
1651 u16 mode;
1652
1653 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
1654 if (!ops->eswitch_mode_set)
1655 return -EOPNOTSUPP;
1656 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1657 err = ops->eswitch_mode_set(devlink, mode, info->extack);
1658 if (err)
1659 return err;
1660 }
1661
1662 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
1663 if (!ops->eswitch_inline_mode_set)
1664 return -EOPNOTSUPP;
1665 inline_mode = nla_get_u8(
1666 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
1667 err = ops->eswitch_inline_mode_set(devlink, inline_mode,
1668 info->extack);
1669 if (err)
1670 return err;
1671 }
1672
1673 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
1674 if (!ops->eswitch_encap_mode_set)
1675 return -EOPNOTSUPP;
1676 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
1677 err = ops->eswitch_encap_mode_set(devlink, encap_mode,
1678 info->extack);
1679 if (err)
1680 return err;
1681 }
1682
1683 return 0;
1684 }
1685
1686 int devlink_dpipe_match_put(struct sk_buff *skb,
1687 struct devlink_dpipe_match *match)
1688 {
1689 struct devlink_dpipe_header *header = match->header;
1690 struct devlink_dpipe_field *field = &header->fields[match->field_id];
1691 struct nlattr *match_attr;
1692
1693 match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH);
1694 if (!match_attr)
1695 return -EMSGSIZE;
1696
1697 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
1698 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
1699 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1700 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1701 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1702 goto nla_put_failure;
1703
1704 nla_nest_end(skb, match_attr);
1705 return 0;
1706
1707 nla_put_failure:
1708 nla_nest_cancel(skb, match_attr);
1709 return -EMSGSIZE;
1710 }
1711 EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
1712
1713 static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
1714 struct sk_buff *skb)
1715 {
1716 struct nlattr *matches_attr;
1717
1718 matches_attr = nla_nest_start_noflag(skb,
1719 DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
1720 if (!matches_attr)
1721 return -EMSGSIZE;
1722
1723 if (table->table_ops->matches_dump(table->priv, skb))
1724 goto nla_put_failure;
1725
1726 nla_nest_end(skb, matches_attr);
1727 return 0;
1728
1729 nla_put_failure:
1730 nla_nest_cancel(skb, matches_attr);
1731 return -EMSGSIZE;
1732 }
1733
1734 int devlink_dpipe_action_put(struct sk_buff *skb,
1735 struct devlink_dpipe_action *action)
1736 {
1737 struct devlink_dpipe_header *header = action->header;
1738 struct devlink_dpipe_field *field = &header->fields[action->field_id];
1739 struct nlattr *action_attr;
1740
1741 action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION);
1742 if (!action_attr)
1743 return -EMSGSIZE;
1744
1745 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
1746 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
1747 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1748 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1749 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1750 goto nla_put_failure;
1751
1752 nla_nest_end(skb, action_attr);
1753 return 0;
1754
1755 nla_put_failure:
1756 nla_nest_cancel(skb, action_attr);
1757 return -EMSGSIZE;
1758 }
1759 EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
1760
1761 static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
1762 struct sk_buff *skb)
1763 {
1764 struct nlattr *actions_attr;
1765
1766 actions_attr = nla_nest_start_noflag(skb,
1767 DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
1768 if (!actions_attr)
1769 return -EMSGSIZE;
1770
1771 if (table->table_ops->actions_dump(table->priv, skb))
1772 goto nla_put_failure;
1773
1774 nla_nest_end(skb, actions_attr);
1775 return 0;
1776
1777 nla_put_failure:
1778 nla_nest_cancel(skb, actions_attr);
1779 return -EMSGSIZE;
1780 }
1781
1782 static int devlink_dpipe_table_put(struct sk_buff *skb,
1783 struct devlink_dpipe_table *table)
1784 {
1785 struct nlattr *table_attr;
1786 u64 table_size;
1787
1788 table_size = table->table_ops->size_get(table->priv);
1789 table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE);
1790 if (!table_attr)
1791 return -EMSGSIZE;
1792
1793 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
1794 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
1795 DEVLINK_ATTR_PAD))
1796 goto nla_put_failure;
1797 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
1798 table->counters_enabled))
1799 goto nla_put_failure;
1800
1801 if (table->resource_valid) {
1802 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
1803 table->resource_id, DEVLINK_ATTR_PAD) ||
1804 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
1805 table->resource_units, DEVLINK_ATTR_PAD))
1806 goto nla_put_failure;
1807 }
1808 if (devlink_dpipe_matches_put(table, skb))
1809 goto nla_put_failure;
1810
1811 if (devlink_dpipe_actions_put(table, skb))
1812 goto nla_put_failure;
1813
1814 nla_nest_end(skb, table_attr);
1815 return 0;
1816
1817 nla_put_failure:
1818 nla_nest_cancel(skb, table_attr);
1819 return -EMSGSIZE;
1820 }
1821
1822 static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
1823 struct genl_info *info)
1824 {
1825 int err;
1826
1827 if (*pskb) {
1828 err = genlmsg_reply(*pskb, info);
1829 if (err)
1830 return err;
1831 }
1832 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1833 if (!*pskb)
1834 return -ENOMEM;
1835 return 0;
1836 }
1837
1838 static int devlink_dpipe_tables_fill(struct genl_info *info,
1839 enum devlink_command cmd, int flags,
1840 struct list_head *dpipe_tables,
1841 const char *table_name)
1842 {
1843 struct devlink *devlink = info->user_ptr[0];
1844 struct devlink_dpipe_table *table;
1845 struct nlattr *tables_attr;
1846 struct sk_buff *skb = NULL;
1847 struct nlmsghdr *nlh;
1848 bool incomplete;
1849 void *hdr;
1850 int i;
1851 int err;
1852
1853 table = list_first_entry(dpipe_tables,
1854 struct devlink_dpipe_table, list);
1855 start_again:
1856 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1857 if (err)
1858 return err;
1859
1860 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
1861 &devlink_nl_family, NLM_F_MULTI, cmd);
1862 if (!hdr) {
1863 nlmsg_free(skb);
1864 return -EMSGSIZE;
1865 }
1866
1867 if (devlink_nl_put_handle(skb, devlink))
1868 goto nla_put_failure;
1869 tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES);
1870 if (!tables_attr)
1871 goto nla_put_failure;
1872
1873 i = 0;
1874 incomplete = false;
1875 list_for_each_entry_from(table, dpipe_tables, list) {
1876 if (!table_name) {
1877 err = devlink_dpipe_table_put(skb, table);
1878 if (err) {
1879 if (!i)
1880 goto err_table_put;
1881 incomplete = true;
1882 break;
1883 }
1884 } else {
1885 if (!strcmp(table->name, table_name)) {
1886 err = devlink_dpipe_table_put(skb, table);
1887 if (err)
1888 break;
1889 }
1890 }
1891 i++;
1892 }
1893
1894 nla_nest_end(skb, tables_attr);
1895 genlmsg_end(skb, hdr);
1896 if (incomplete)
1897 goto start_again;
1898
1899 send_done:
1900 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
1901 NLMSG_DONE, 0, flags | NLM_F_MULTI);
1902 if (!nlh) {
1903 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1904 if (err)
1905 return err;
1906 goto send_done;
1907 }
1908
1909 return genlmsg_reply(skb, info);
1910
1911 nla_put_failure:
1912 err = -EMSGSIZE;
1913 err_table_put:
1914 nlmsg_free(skb);
1915 return err;
1916 }
1917
1918 static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
1919 struct genl_info *info)
1920 {
1921 struct devlink *devlink = info->user_ptr[0];
1922 const char *table_name = NULL;
1923
1924 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
1925 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
1926
1927 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
1928 &devlink->dpipe_table_list,
1929 table_name);
1930 }
1931
1932 static int devlink_dpipe_value_put(struct sk_buff *skb,
1933 struct devlink_dpipe_value *value)
1934 {
1935 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
1936 value->value_size, value->value))
1937 return -EMSGSIZE;
1938 if (value->mask)
1939 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
1940 value->value_size, value->mask))
1941 return -EMSGSIZE;
1942 if (value->mapping_valid)
1943 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
1944 value->mapping_value))
1945 return -EMSGSIZE;
1946 return 0;
1947 }
1948
1949 static int devlink_dpipe_action_value_put(struct sk_buff *skb,
1950 struct devlink_dpipe_value *value)
1951 {
1952 if (!value->action)
1953 return -EINVAL;
1954 if (devlink_dpipe_action_put(skb, value->action))
1955 return -EMSGSIZE;
1956 if (devlink_dpipe_value_put(skb, value))
1957 return -EMSGSIZE;
1958 return 0;
1959 }
1960
1961 static int devlink_dpipe_action_values_put(struct sk_buff *skb,
1962 struct devlink_dpipe_value *values,
1963 unsigned int values_count)
1964 {
1965 struct nlattr *action_attr;
1966 int i;
1967 int err;
1968
1969 for (i = 0; i < values_count; i++) {
1970 action_attr = nla_nest_start_noflag(skb,
1971 DEVLINK_ATTR_DPIPE_ACTION_VALUE);
1972 if (!action_attr)
1973 return -EMSGSIZE;
1974 err = devlink_dpipe_action_value_put(skb, &values[i]);
1975 if (err)
1976 goto err_action_value_put;
1977 nla_nest_end(skb, action_attr);
1978 }
1979 return 0;
1980
1981 err_action_value_put:
1982 nla_nest_cancel(skb, action_attr);
1983 return err;
1984 }
1985
1986 static int devlink_dpipe_match_value_put(struct sk_buff *skb,
1987 struct devlink_dpipe_value *value)
1988 {
1989 if (!value->match)
1990 return -EINVAL;
1991 if (devlink_dpipe_match_put(skb, value->match))
1992 return -EMSGSIZE;
1993 if (devlink_dpipe_value_put(skb, value))
1994 return -EMSGSIZE;
1995 return 0;
1996 }
1997
1998 static int devlink_dpipe_match_values_put(struct sk_buff *skb,
1999 struct devlink_dpipe_value *values,
2000 unsigned int values_count)
2001 {
2002 struct nlattr *match_attr;
2003 int i;
2004 int err;
2005
2006 for (i = 0; i < values_count; i++) {
2007 match_attr = nla_nest_start_noflag(skb,
2008 DEVLINK_ATTR_DPIPE_MATCH_VALUE);
2009 if (!match_attr)
2010 return -EMSGSIZE;
2011 err = devlink_dpipe_match_value_put(skb, &values[i]);
2012 if (err)
2013 goto err_match_value_put;
2014 nla_nest_end(skb, match_attr);
2015 }
2016 return 0;
2017
2018 err_match_value_put:
2019 nla_nest_cancel(skb, match_attr);
2020 return err;
2021 }
2022
2023 static int devlink_dpipe_entry_put(struct sk_buff *skb,
2024 struct devlink_dpipe_entry *entry)
2025 {
2026 struct nlattr *entry_attr, *matches_attr, *actions_attr;
2027 int err;
2028
2029 entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY);
2030 if (!entry_attr)
2031 return -EMSGSIZE;
2032
2033 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
2034 DEVLINK_ATTR_PAD))
2035 goto nla_put_failure;
2036 if (entry->counter_valid)
2037 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
2038 entry->counter, DEVLINK_ATTR_PAD))
2039 goto nla_put_failure;
2040
2041 matches_attr = nla_nest_start_noflag(skb,
2042 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
2043 if (!matches_attr)
2044 goto nla_put_failure;
2045
2046 err = devlink_dpipe_match_values_put(skb, entry->match_values,
2047 entry->match_values_count);
2048 if (err) {
2049 nla_nest_cancel(skb, matches_attr);
2050 goto err_match_values_put;
2051 }
2052 nla_nest_end(skb, matches_attr);
2053
2054 actions_attr = nla_nest_start_noflag(skb,
2055 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
2056 if (!actions_attr)
2057 goto nla_put_failure;
2058
2059 err = devlink_dpipe_action_values_put(skb, entry->action_values,
2060 entry->action_values_count);
2061 if (err) {
2062 nla_nest_cancel(skb, actions_attr);
2063 goto err_action_values_put;
2064 }
2065 nla_nest_end(skb, actions_attr);
2066
2067 nla_nest_end(skb, entry_attr);
2068 return 0;
2069
2070 nla_put_failure:
2071 err = -EMSGSIZE;
2072 err_match_values_put:
2073 err_action_values_put:
2074 nla_nest_cancel(skb, entry_attr);
2075 return err;
2076 }
2077
2078 static struct devlink_dpipe_table *
2079 devlink_dpipe_table_find(struct list_head *dpipe_tables,
2080 const char *table_name)
2081 {
2082 struct devlink_dpipe_table *table;
2083
2084 list_for_each_entry_rcu(table, dpipe_tables, list) {
2085 if (!strcmp(table->name, table_name))
2086 return table;
2087 }
2088 return NULL;
2089 }
2090
2091 int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
2092 {
2093 struct devlink *devlink;
2094 int err;
2095
2096 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
2097 dump_ctx->info);
2098 if (err)
2099 return err;
2100
2101 dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
2102 dump_ctx->info->snd_portid,
2103 dump_ctx->info->snd_seq,
2104 &devlink_nl_family, NLM_F_MULTI,
2105 dump_ctx->cmd);
2106 if (!dump_ctx->hdr)
2107 goto nla_put_failure;
2108
2109 devlink = dump_ctx->info->user_ptr[0];
2110 if (devlink_nl_put_handle(dump_ctx->skb, devlink))
2111 goto nla_put_failure;
2112 dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb,
2113 DEVLINK_ATTR_DPIPE_ENTRIES);
2114 if (!dump_ctx->nest)
2115 goto nla_put_failure;
2116 return 0;
2117
2118 nla_put_failure:
2119 nlmsg_free(dump_ctx->skb);
2120 return -EMSGSIZE;
2121 }
2122 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
2123
2124 int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
2125 struct devlink_dpipe_entry *entry)
2126 {
2127 return devlink_dpipe_entry_put(dump_ctx->skb, entry);
2128 }
2129 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
2130
2131 int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
2132 {
2133 nla_nest_end(dump_ctx->skb, dump_ctx->nest);
2134 genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
2135 return 0;
2136 }
2137 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
2138
2139 void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
2140
2141 {
2142 unsigned int value_count, value_index;
2143 struct devlink_dpipe_value *value;
2144
2145 value = entry->action_values;
2146 value_count = entry->action_values_count;
2147 for (value_index = 0; value_index < value_count; value_index++) {
2148 kfree(value[value_index].value);
2149 kfree(value[value_index].mask);
2150 }
2151
2152 value = entry->match_values;
2153 value_count = entry->match_values_count;
2154 for (value_index = 0; value_index < value_count; value_index++) {
2155 kfree(value[value_index].value);
2156 kfree(value[value_index].mask);
2157 }
2158 }
2159 EXPORT_SYMBOL(devlink_dpipe_entry_clear);
2160
2161 static int devlink_dpipe_entries_fill(struct genl_info *info,
2162 enum devlink_command cmd, int flags,
2163 struct devlink_dpipe_table *table)
2164 {
2165 struct devlink_dpipe_dump_ctx dump_ctx;
2166 struct nlmsghdr *nlh;
2167 int err;
2168
2169 dump_ctx.skb = NULL;
2170 dump_ctx.cmd = cmd;
2171 dump_ctx.info = info;
2172
2173 err = table->table_ops->entries_dump(table->priv,
2174 table->counters_enabled,
2175 &dump_ctx);
2176 if (err)
2177 return err;
2178
2179 send_done:
2180 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
2181 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2182 if (!nlh) {
2183 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
2184 if (err)
2185 return err;
2186 goto send_done;
2187 }
2188 return genlmsg_reply(dump_ctx.skb, info);
2189 }
2190
2191 static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
2192 struct genl_info *info)
2193 {
2194 struct devlink *devlink = info->user_ptr[0];
2195 struct devlink_dpipe_table *table;
2196 const char *table_name;
2197
2198 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
2199 return -EINVAL;
2200
2201 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2202 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2203 table_name);
2204 if (!table)
2205 return -EINVAL;
2206
2207 if (!table->table_ops->entries_dump)
2208 return -EINVAL;
2209
2210 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
2211 0, table);
2212 }
2213
2214 static int devlink_dpipe_fields_put(struct sk_buff *skb,
2215 const struct devlink_dpipe_header *header)
2216 {
2217 struct devlink_dpipe_field *field;
2218 struct nlattr *field_attr;
2219 int i;
2220
2221 for (i = 0; i < header->fields_count; i++) {
2222 field = &header->fields[i];
2223 field_attr = nla_nest_start_noflag(skb,
2224 DEVLINK_ATTR_DPIPE_FIELD);
2225 if (!field_attr)
2226 return -EMSGSIZE;
2227 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
2228 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
2229 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
2230 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
2231 goto nla_put_failure;
2232 nla_nest_end(skb, field_attr);
2233 }
2234 return 0;
2235
2236 nla_put_failure:
2237 nla_nest_cancel(skb, field_attr);
2238 return -EMSGSIZE;
2239 }
2240
2241 static int devlink_dpipe_header_put(struct sk_buff *skb,
2242 struct devlink_dpipe_header *header)
2243 {
2244 struct nlattr *fields_attr, *header_attr;
2245 int err;
2246
2247 header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER);
2248 if (!header_attr)
2249 return -EMSGSIZE;
2250
2251 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
2252 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
2253 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
2254 goto nla_put_failure;
2255
2256 fields_attr = nla_nest_start_noflag(skb,
2257 DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
2258 if (!fields_attr)
2259 goto nla_put_failure;
2260
2261 err = devlink_dpipe_fields_put(skb, header);
2262 if (err) {
2263 nla_nest_cancel(skb, fields_attr);
2264 goto nla_put_failure;
2265 }
2266 nla_nest_end(skb, fields_attr);
2267 nla_nest_end(skb, header_attr);
2268 return 0;
2269
2270 nla_put_failure:
2271 err = -EMSGSIZE;
2272 nla_nest_cancel(skb, header_attr);
2273 return err;
2274 }
2275
2276 static int devlink_dpipe_headers_fill(struct genl_info *info,
2277 enum devlink_command cmd, int flags,
2278 struct devlink_dpipe_headers *
2279 dpipe_headers)
2280 {
2281 struct devlink *devlink = info->user_ptr[0];
2282 struct nlattr *headers_attr;
2283 struct sk_buff *skb = NULL;
2284 struct nlmsghdr *nlh;
2285 void *hdr;
2286 int i, j;
2287 int err;
2288
2289 i = 0;
2290 start_again:
2291 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2292 if (err)
2293 return err;
2294
2295 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2296 &devlink_nl_family, NLM_F_MULTI, cmd);
2297 if (!hdr) {
2298 nlmsg_free(skb);
2299 return -EMSGSIZE;
2300 }
2301
2302 if (devlink_nl_put_handle(skb, devlink))
2303 goto nla_put_failure;
2304 headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS);
2305 if (!headers_attr)
2306 goto nla_put_failure;
2307
2308 j = 0;
2309 for (; i < dpipe_headers->headers_count; i++) {
2310 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
2311 if (err) {
2312 if (!j)
2313 goto err_table_put;
2314 break;
2315 }
2316 j++;
2317 }
2318 nla_nest_end(skb, headers_attr);
2319 genlmsg_end(skb, hdr);
2320 if (i != dpipe_headers->headers_count)
2321 goto start_again;
2322
2323 send_done:
2324 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2325 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2326 if (!nlh) {
2327 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2328 if (err)
2329 return err;
2330 goto send_done;
2331 }
2332 return genlmsg_reply(skb, info);
2333
2334 nla_put_failure:
2335 err = -EMSGSIZE;
2336 err_table_put:
2337 nlmsg_free(skb);
2338 return err;
2339 }
2340
2341 static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
2342 struct genl_info *info)
2343 {
2344 struct devlink *devlink = info->user_ptr[0];
2345
2346 if (!devlink->dpipe_headers)
2347 return -EOPNOTSUPP;
2348 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
2349 0, devlink->dpipe_headers);
2350 }
2351
2352 static int devlink_dpipe_table_counters_set(struct devlink *devlink,
2353 const char *table_name,
2354 bool enable)
2355 {
2356 struct devlink_dpipe_table *table;
2357
2358 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2359 table_name);
2360 if (!table)
2361 return -EINVAL;
2362
2363 if (table->counter_control_extern)
2364 return -EOPNOTSUPP;
2365
2366 if (!(table->counters_enabled ^ enable))
2367 return 0;
2368
2369 table->counters_enabled = enable;
2370 if (table->table_ops->counters_set_update)
2371 table->table_ops->counters_set_update(table->priv, enable);
2372 return 0;
2373 }
2374
2375 static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
2376 struct genl_info *info)
2377 {
2378 struct devlink *devlink = info->user_ptr[0];
2379 const char *table_name;
2380 bool counters_enable;
2381
2382 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
2383 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
2384 return -EINVAL;
2385
2386 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2387 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
2388
2389 return devlink_dpipe_table_counters_set(devlink, table_name,
2390 counters_enable);
2391 }
2392
2393 static struct devlink_resource *
2394 devlink_resource_find(struct devlink *devlink,
2395 struct devlink_resource *resource, u64 resource_id)
2396 {
2397 struct list_head *resource_list;
2398
2399 if (resource)
2400 resource_list = &resource->resource_list;
2401 else
2402 resource_list = &devlink->resource_list;
2403
2404 list_for_each_entry(resource, resource_list, list) {
2405 struct devlink_resource *child_resource;
2406
2407 if (resource->id == resource_id)
2408 return resource;
2409
2410 child_resource = devlink_resource_find(devlink, resource,
2411 resource_id);
2412 if (child_resource)
2413 return child_resource;
2414 }
2415 return NULL;
2416 }
2417
2418 static void
2419 devlink_resource_validate_children(struct devlink_resource *resource)
2420 {
2421 struct devlink_resource *child_resource;
2422 bool size_valid = true;
2423 u64 parts_size = 0;
2424
2425 if (list_empty(&resource->resource_list))
2426 goto out;
2427
2428 list_for_each_entry(child_resource, &resource->resource_list, list)
2429 parts_size += child_resource->size_new;
2430
2431 if (parts_size > resource->size_new)
2432 size_valid = false;
2433 out:
2434 resource->size_valid = size_valid;
2435 }
2436
2437 static int
2438 devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2439 struct netlink_ext_ack *extack)
2440 {
2441 u64 reminder;
2442 int err = 0;
2443
2444 if (size > resource->size_params.size_max) {
2445 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2446 err = -EINVAL;
2447 }
2448
2449 if (size < resource->size_params.size_min) {
2450 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2451 err = -EINVAL;
2452 }
2453
2454 div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
2455 if (reminder) {
2456 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2457 err = -EINVAL;
2458 }
2459
2460 return err;
2461 }
2462
2463 static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2464 struct genl_info *info)
2465 {
2466 struct devlink *devlink = info->user_ptr[0];
2467 struct devlink_resource *resource;
2468 u64 resource_id;
2469 u64 size;
2470 int err;
2471
2472 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
2473 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
2474 return -EINVAL;
2475 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
2476
2477 resource = devlink_resource_find(devlink, NULL, resource_id);
2478 if (!resource)
2479 return -EINVAL;
2480
2481 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2482 err = devlink_resource_validate_size(resource, size, info->extack);
2483 if (err)
2484 return err;
2485
2486 resource->size_new = size;
2487 devlink_resource_validate_children(resource);
2488 if (resource->parent)
2489 devlink_resource_validate_children(resource->parent);
2490 return 0;
2491 }
2492
2493 static int
2494 devlink_resource_size_params_put(struct devlink_resource *resource,
2495 struct sk_buff *skb)
2496 {
2497 struct devlink_resource_size_params *size_params;
2498
2499 size_params = &resource->size_params;
2500 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
2501 size_params->size_granularity, DEVLINK_ATTR_PAD) ||
2502 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
2503 size_params->size_max, DEVLINK_ATTR_PAD) ||
2504 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
2505 size_params->size_min, DEVLINK_ATTR_PAD) ||
2506 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
2507 return -EMSGSIZE;
2508 return 0;
2509 }
2510
2511 static int devlink_resource_occ_put(struct devlink_resource *resource,
2512 struct sk_buff *skb)
2513 {
2514 if (!resource->occ_get)
2515 return 0;
2516 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
2517 resource->occ_get(resource->occ_get_priv),
2518 DEVLINK_ATTR_PAD);
2519 }
2520
2521 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
2522 struct devlink_resource *resource)
2523 {
2524 struct devlink_resource *child_resource;
2525 struct nlattr *child_resource_attr;
2526 struct nlattr *resource_attr;
2527
2528 resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
2529 if (!resource_attr)
2530 return -EMSGSIZE;
2531
2532 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
2533 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
2534 DEVLINK_ATTR_PAD) ||
2535 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
2536 DEVLINK_ATTR_PAD))
2537 goto nla_put_failure;
2538 if (resource->size != resource->size_new)
2539 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
2540 resource->size_new, DEVLINK_ATTR_PAD);
2541 if (devlink_resource_occ_put(resource, skb))
2542 goto nla_put_failure;
2543 if (devlink_resource_size_params_put(resource, skb))
2544 goto nla_put_failure;
2545 if (list_empty(&resource->resource_list))
2546 goto out;
2547
2548 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
2549 resource->size_valid))
2550 goto nla_put_failure;
2551
2552 child_resource_attr = nla_nest_start_noflag(skb,
2553 DEVLINK_ATTR_RESOURCE_LIST);
2554 if (!child_resource_attr)
2555 goto nla_put_failure;
2556
2557 list_for_each_entry(child_resource, &resource->resource_list, list) {
2558 if (devlink_resource_put(devlink, skb, child_resource))
2559 goto resource_put_failure;
2560 }
2561
2562 nla_nest_end(skb, child_resource_attr);
2563 out:
2564 nla_nest_end(skb, resource_attr);
2565 return 0;
2566
2567 resource_put_failure:
2568 nla_nest_cancel(skb, child_resource_attr);
2569 nla_put_failure:
2570 nla_nest_cancel(skb, resource_attr);
2571 return -EMSGSIZE;
2572 }
2573
2574 static int devlink_resource_fill(struct genl_info *info,
2575 enum devlink_command cmd, int flags)
2576 {
2577 struct devlink *devlink = info->user_ptr[0];
2578 struct devlink_resource *resource;
2579 struct nlattr *resources_attr;
2580 struct sk_buff *skb = NULL;
2581 struct nlmsghdr *nlh;
2582 bool incomplete;
2583 void *hdr;
2584 int i;
2585 int err;
2586
2587 resource = list_first_entry(&devlink->resource_list,
2588 struct devlink_resource, list);
2589 start_again:
2590 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2591 if (err)
2592 return err;
2593
2594 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2595 &devlink_nl_family, NLM_F_MULTI, cmd);
2596 if (!hdr) {
2597 nlmsg_free(skb);
2598 return -EMSGSIZE;
2599 }
2600
2601 if (devlink_nl_put_handle(skb, devlink))
2602 goto nla_put_failure;
2603
2604 resources_attr = nla_nest_start_noflag(skb,
2605 DEVLINK_ATTR_RESOURCE_LIST);
2606 if (!resources_attr)
2607 goto nla_put_failure;
2608
2609 incomplete = false;
2610 i = 0;
2611 list_for_each_entry_from(resource, &devlink->resource_list, list) {
2612 err = devlink_resource_put(devlink, skb, resource);
2613 if (err) {
2614 if (!i)
2615 goto err_resource_put;
2616 incomplete = true;
2617 break;
2618 }
2619 i++;
2620 }
2621 nla_nest_end(skb, resources_attr);
2622 genlmsg_end(skb, hdr);
2623 if (incomplete)
2624 goto start_again;
2625 send_done:
2626 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2627 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2628 if (!nlh) {
2629 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2630 if (err)
2631 return err;
2632 goto send_done;
2633 }
2634 return genlmsg_reply(skb, info);
2635
2636 nla_put_failure:
2637 err = -EMSGSIZE;
2638 err_resource_put:
2639 nlmsg_free(skb);
2640 return err;
2641 }
2642
2643 static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
2644 struct genl_info *info)
2645 {
2646 struct devlink *devlink = info->user_ptr[0];
2647
2648 if (list_empty(&devlink->resource_list))
2649 return -EOPNOTSUPP;
2650
2651 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
2652 }
2653
2654 static int
2655 devlink_resources_validate(struct devlink *devlink,
2656 struct devlink_resource *resource,
2657 struct genl_info *info)
2658 {
2659 struct list_head *resource_list;
2660 int err = 0;
2661
2662 if (resource)
2663 resource_list = &resource->resource_list;
2664 else
2665 resource_list = &devlink->resource_list;
2666
2667 list_for_each_entry(resource, resource_list, list) {
2668 if (!resource->size_valid)
2669 return -EINVAL;
2670 err = devlink_resources_validate(devlink, resource, info);
2671 if (err)
2672 return err;
2673 }
2674 return err;
2675 }
2676
2677 static bool devlink_reload_supported(struct devlink *devlink)
2678 {
2679 return devlink->ops->reload_down && devlink->ops->reload_up;
2680 }
2681
2682 static void devlink_reload_failed_set(struct devlink *devlink,
2683 bool reload_failed)
2684 {
2685 if (devlink->reload_failed == reload_failed)
2686 return;
2687 devlink->reload_failed = reload_failed;
2688 devlink_notify(devlink, DEVLINK_CMD_NEW);
2689 }
2690
2691 bool devlink_is_reload_failed(const struct devlink *devlink)
2692 {
2693 return devlink->reload_failed;
2694 }
2695 EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
2696
2697 static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2698 {
2699 struct devlink *devlink = info->user_ptr[0];
2700 int err;
2701
2702 if (!devlink_reload_supported(devlink) || !devlink->reload_enabled)
2703 return -EOPNOTSUPP;
2704
2705 err = devlink_resources_validate(devlink, NULL, info);
2706 if (err) {
2707 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
2708 return err;
2709 }
2710 err = devlink->ops->reload_down(devlink, info->extack);
2711 if (err)
2712 return err;
2713 err = devlink->ops->reload_up(devlink, info->extack);
2714 devlink_reload_failed_set(devlink, !!err);
2715 return err;
2716 }
2717
2718 static int devlink_nl_flash_update_fill(struct sk_buff *msg,
2719 struct devlink *devlink,
2720 enum devlink_command cmd,
2721 const char *status_msg,
2722 const char *component,
2723 unsigned long done, unsigned long total)
2724 {
2725 void *hdr;
2726
2727 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
2728 if (!hdr)
2729 return -EMSGSIZE;
2730
2731 if (devlink_nl_put_handle(msg, devlink))
2732 goto nla_put_failure;
2733
2734 if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
2735 goto out;
2736
2737 if (status_msg &&
2738 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
2739 status_msg))
2740 goto nla_put_failure;
2741 if (component &&
2742 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
2743 component))
2744 goto nla_put_failure;
2745 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
2746 done, DEVLINK_ATTR_PAD))
2747 goto nla_put_failure;
2748 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
2749 total, DEVLINK_ATTR_PAD))
2750 goto nla_put_failure;
2751
2752 out:
2753 genlmsg_end(msg, hdr);
2754 return 0;
2755
2756 nla_put_failure:
2757 genlmsg_cancel(msg, hdr);
2758 return -EMSGSIZE;
2759 }
2760
2761 static void __devlink_flash_update_notify(struct devlink *devlink,
2762 enum devlink_command cmd,
2763 const char *status_msg,
2764 const char *component,
2765 unsigned long done,
2766 unsigned long total)
2767 {
2768 struct sk_buff *msg;
2769 int err;
2770
2771 WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
2772 cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
2773 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
2774
2775 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2776 if (!msg)
2777 return;
2778
2779 err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg,
2780 component, done, total);
2781 if (err)
2782 goto out_free_msg;
2783
2784 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2785 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2786 return;
2787
2788 out_free_msg:
2789 nlmsg_free(msg);
2790 }
2791
2792 void devlink_flash_update_begin_notify(struct devlink *devlink)
2793 {
2794 __devlink_flash_update_notify(devlink,
2795 DEVLINK_CMD_FLASH_UPDATE,
2796 NULL, NULL, 0, 0);
2797 }
2798 EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify);
2799
2800 void devlink_flash_update_end_notify(struct devlink *devlink)
2801 {
2802 __devlink_flash_update_notify(devlink,
2803 DEVLINK_CMD_FLASH_UPDATE_END,
2804 NULL, NULL, 0, 0);
2805 }
2806 EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify);
2807
2808 void devlink_flash_update_status_notify(struct devlink *devlink,
2809 const char *status_msg,
2810 const char *component,
2811 unsigned long done,
2812 unsigned long total)
2813 {
2814 __devlink_flash_update_notify(devlink,
2815 DEVLINK_CMD_FLASH_UPDATE_STATUS,
2816 status_msg, component, done, total);
2817 }
2818 EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
2819
2820 static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
2821 struct genl_info *info)
2822 {
2823 struct devlink *devlink = info->user_ptr[0];
2824 const char *file_name, *component;
2825 struct nlattr *nla_component;
2826
2827 if (!devlink->ops->flash_update)
2828 return -EOPNOTSUPP;
2829
2830 if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME])
2831 return -EINVAL;
2832 file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]);
2833
2834 nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
2835 component = nla_component ? nla_data(nla_component) : NULL;
2836
2837 return devlink->ops->flash_update(devlink, file_name, component,
2838 info->extack);
2839 }
2840
2841 static const struct devlink_param devlink_param_generic[] = {
2842 {
2843 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
2844 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
2845 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
2846 },
2847 {
2848 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
2849 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
2850 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
2851 },
2852 {
2853 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
2854 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
2855 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
2856 },
2857 {
2858 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
2859 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
2860 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
2861 },
2862 {
2863 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
2864 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
2865 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
2866 },
2867 {
2868 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
2869 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
2870 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
2871 },
2872 {
2873 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
2874 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
2875 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
2876 },
2877 {
2878 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
2879 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
2880 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
2881 },
2882 {
2883 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
2884 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
2885 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
2886 },
2887 };
2888
2889 static int devlink_param_generic_verify(const struct devlink_param *param)
2890 {
2891
2892 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
2893 return -EINVAL;
2894 if (strcmp(param->name, devlink_param_generic[param->id].name))
2895 return -ENOENT;
2896
2897 WARN_ON(param->type != devlink_param_generic[param->id].type);
2898
2899 return 0;
2900 }
2901
2902 static int devlink_param_driver_verify(const struct devlink_param *param)
2903 {
2904 int i;
2905
2906 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
2907 return -EINVAL;
2908
2909 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
2910 if (!strcmp(param->name, devlink_param_generic[i].name))
2911 return -EEXIST;
2912
2913 return 0;
2914 }
2915
2916 static struct devlink_param_item *
2917 devlink_param_find_by_name(struct list_head *param_list,
2918 const char *param_name)
2919 {
2920 struct devlink_param_item *param_item;
2921
2922 list_for_each_entry(param_item, param_list, list)
2923 if (!strcmp(param_item->param->name, param_name))
2924 return param_item;
2925 return NULL;
2926 }
2927
2928 static struct devlink_param_item *
2929 devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
2930 {
2931 struct devlink_param_item *param_item;
2932
2933 list_for_each_entry(param_item, param_list, list)
2934 if (param_item->param->id == param_id)
2935 return param_item;
2936 return NULL;
2937 }
2938
2939 static bool
2940 devlink_param_cmode_is_supported(const struct devlink_param *param,
2941 enum devlink_param_cmode cmode)
2942 {
2943 return test_bit(cmode, ¶m->supported_cmodes);
2944 }
2945
2946 static int devlink_param_get(struct devlink *devlink,
2947 const struct devlink_param *param,
2948 struct devlink_param_gset_ctx *ctx)
2949 {
2950 if (!param->get)
2951 return -EOPNOTSUPP;
2952 return param->get(devlink, param->id, ctx);
2953 }
2954
2955 static int devlink_param_set(struct devlink *devlink,
2956 const struct devlink_param *param,
2957 struct devlink_param_gset_ctx *ctx)
2958 {
2959 if (!param->set)
2960 return -EOPNOTSUPP;
2961 return param->set(devlink, param->id, ctx);
2962 }
2963
2964 static int
2965 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
2966 {
2967 switch (param_type) {
2968 case DEVLINK_PARAM_TYPE_U8:
2969 return NLA_U8;
2970 case DEVLINK_PARAM_TYPE_U16:
2971 return NLA_U16;
2972 case DEVLINK_PARAM_TYPE_U32:
2973 return NLA_U32;
2974 case DEVLINK_PARAM_TYPE_STRING:
2975 return NLA_STRING;
2976 case DEVLINK_PARAM_TYPE_BOOL:
2977 return NLA_FLAG;
2978 default:
2979 return -EINVAL;
2980 }
2981 }
2982
2983 static int
2984 devlink_nl_param_value_fill_one(struct sk_buff *msg,
2985 enum devlink_param_type type,
2986 enum devlink_param_cmode cmode,
2987 union devlink_param_value val)
2988 {
2989 struct nlattr *param_value_attr;
2990
2991 param_value_attr = nla_nest_start_noflag(msg,
2992 DEVLINK_ATTR_PARAM_VALUE);
2993 if (!param_value_attr)
2994 goto nla_put_failure;
2995
2996 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
2997 goto value_nest_cancel;
2998
2999 switch (type) {
3000 case DEVLINK_PARAM_TYPE_U8:
3001 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
3002 goto value_nest_cancel;
3003 break;
3004 case DEVLINK_PARAM_TYPE_U16:
3005 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
3006 goto value_nest_cancel;
3007 break;
3008 case DEVLINK_PARAM_TYPE_U32:
3009 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
3010 goto value_nest_cancel;
3011 break;
3012 case DEVLINK_PARAM_TYPE_STRING:
3013 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
3014 val.vstr))
3015 goto value_nest_cancel;
3016 break;
3017 case DEVLINK_PARAM_TYPE_BOOL:
3018 if (val.vbool &&
3019 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
3020 goto value_nest_cancel;
3021 break;
3022 }
3023
3024 nla_nest_end(msg, param_value_attr);
3025 return 0;
3026
3027 value_nest_cancel:
3028 nla_nest_cancel(msg, param_value_attr);
3029 nla_put_failure:
3030 return -EMSGSIZE;
3031 }
3032
3033 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
3034 unsigned int port_index,
3035 struct devlink_param_item *param_item,
3036 enum devlink_command cmd,
3037 u32 portid, u32 seq, int flags)
3038 {
3039 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
3040 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
3041 const struct devlink_param *param = param_item->param;
3042 struct devlink_param_gset_ctx ctx;
3043 struct nlattr *param_values_list;
3044 struct nlattr *param_attr;
3045 int nla_type;
3046 void *hdr;
3047 int err;
3048 int i;
3049
3050
3051 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3052 if (!devlink_param_cmode_is_supported(param, i))
3053 continue;
3054 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3055 if (!param_item->driverinit_value_valid)
3056 return -EOPNOTSUPP;
3057 param_value[i] = param_item->driverinit_value;
3058 } else {
3059 if (!param_item->published)
3060 continue;
3061 ctx.cmode = i;
3062 err = devlink_param_get(devlink, param, &ctx);
3063 if (err)
3064 return err;
3065 param_value[i] = ctx.val;
3066 }
3067 param_value_set[i] = true;
3068 }
3069
3070 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3071 if (!hdr)
3072 return -EMSGSIZE;
3073
3074 if (devlink_nl_put_handle(msg, devlink))
3075 goto genlmsg_cancel;
3076
3077 if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
3078 cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
3079 cmd == DEVLINK_CMD_PORT_PARAM_DEL)
3080 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
3081 goto genlmsg_cancel;
3082
3083 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
3084 if (!param_attr)
3085 goto genlmsg_cancel;
3086 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
3087 goto param_nest_cancel;
3088 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
3089 goto param_nest_cancel;
3090
3091 nla_type = devlink_param_type_to_nla_type(param->type);
3092 if (nla_type < 0)
3093 goto param_nest_cancel;
3094 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
3095 goto param_nest_cancel;
3096
3097 param_values_list = nla_nest_start_noflag(msg,
3098 DEVLINK_ATTR_PARAM_VALUES_LIST);
3099 if (!param_values_list)
3100 goto param_nest_cancel;
3101
3102 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3103 if (!param_value_set[i])
3104 continue;
3105 err = devlink_nl_param_value_fill_one(msg, param->type,
3106 i, param_value[i]);
3107 if (err)
3108 goto values_list_nest_cancel;
3109 }
3110
3111 nla_nest_end(msg, param_values_list);
3112 nla_nest_end(msg, param_attr);
3113 genlmsg_end(msg, hdr);
3114 return 0;
3115
3116 values_list_nest_cancel:
3117 nla_nest_end(msg, param_values_list);
3118 param_nest_cancel:
3119 nla_nest_cancel(msg, param_attr);
3120 genlmsg_cancel:
3121 genlmsg_cancel(msg, hdr);
3122 return -EMSGSIZE;
3123 }
3124
3125 static void devlink_param_notify(struct devlink *devlink,
3126 unsigned int port_index,
3127 struct devlink_param_item *param_item,
3128 enum devlink_command cmd)
3129 {
3130 struct sk_buff *msg;
3131 int err;
3132
3133 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
3134 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
3135 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
3136
3137 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3138 if (!msg)
3139 return;
3140 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
3141 0, 0, 0);
3142 if (err) {
3143 nlmsg_free(msg);
3144 return;
3145 }
3146
3147 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3148 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3149 }
3150
3151 static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
3152 struct netlink_callback *cb)
3153 {
3154 struct devlink_param_item *param_item;
3155 struct devlink *devlink;
3156 int start = cb->args[0];
3157 int idx = 0;
3158 int err;
3159
3160 mutex_lock(&devlink_mutex);
3161 list_for_each_entry(devlink, &devlink_list, list) {
3162 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3163 continue;
3164 mutex_lock(&devlink->lock);
3165 list_for_each_entry(param_item, &devlink->param_list, list) {
3166 if (idx < start) {
3167 idx++;
3168 continue;
3169 }
3170 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3171 DEVLINK_CMD_PARAM_GET,
3172 NETLINK_CB(cb->skb).portid,
3173 cb->nlh->nlmsg_seq,
3174 NLM_F_MULTI);
3175 if (err && err != -EOPNOTSUPP) {
3176 mutex_unlock(&devlink->lock);
3177 goto out;
3178 }
3179 idx++;
3180 }
3181 mutex_unlock(&devlink->lock);
3182 }
3183 out:
3184 mutex_unlock(&devlink_mutex);
3185
3186 cb->args[0] = idx;
3187 return msg->len;
3188 }
3189
3190 static int
3191 devlink_param_type_get_from_info(struct genl_info *info,
3192 enum devlink_param_type *param_type)
3193 {
3194 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
3195 return -EINVAL;
3196
3197 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
3198 case NLA_U8:
3199 *param_type = DEVLINK_PARAM_TYPE_U8;
3200 break;
3201 case NLA_U16:
3202 *param_type = DEVLINK_PARAM_TYPE_U16;
3203 break;
3204 case NLA_U32:
3205 *param_type = DEVLINK_PARAM_TYPE_U32;
3206 break;
3207 case NLA_STRING:
3208 *param_type = DEVLINK_PARAM_TYPE_STRING;
3209 break;
3210 case NLA_FLAG:
3211 *param_type = DEVLINK_PARAM_TYPE_BOOL;
3212 break;
3213 default:
3214 return -EINVAL;
3215 }
3216
3217 return 0;
3218 }
3219
3220 static int
3221 devlink_param_value_get_from_info(const struct devlink_param *param,
3222 struct genl_info *info,
3223 union devlink_param_value *value)
3224 {
3225 struct nlattr *param_data;
3226 int len;
3227
3228 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
3229
3230 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
3231 return -EINVAL;
3232
3233 switch (param->type) {
3234 case DEVLINK_PARAM_TYPE_U8:
3235 if (nla_len(param_data) != sizeof(u8))
3236 return -EINVAL;
3237 value->vu8 = nla_get_u8(param_data);
3238 break;
3239 case DEVLINK_PARAM_TYPE_U16:
3240 if (nla_len(param_data) != sizeof(u16))
3241 return -EINVAL;
3242 value->vu16 = nla_get_u16(param_data);
3243 break;
3244 case DEVLINK_PARAM_TYPE_U32:
3245 if (nla_len(param_data) != sizeof(u32))
3246 return -EINVAL;
3247 value->vu32 = nla_get_u32(param_data);
3248 break;
3249 case DEVLINK_PARAM_TYPE_STRING:
3250 len = strnlen(nla_data(param_data), nla_len(param_data));
3251 if (len == nla_len(param_data) ||
3252 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3253 return -EINVAL;
3254 strcpy(value->vstr, nla_data(param_data));
3255 break;
3256 case DEVLINK_PARAM_TYPE_BOOL:
3257 if (param_data && nla_len(param_data))
3258 return -EINVAL;
3259 value->vbool = nla_get_flag(param_data);
3260 break;
3261 }
3262 return 0;
3263 }
3264
3265 static struct devlink_param_item *
3266 devlink_param_get_from_info(struct list_head *param_list,
3267 struct genl_info *info)
3268 {
3269 char *param_name;
3270
3271 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3272 return NULL;
3273
3274 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
3275 return devlink_param_find_by_name(param_list, param_name);
3276 }
3277
3278 static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3279 struct genl_info *info)
3280 {
3281 struct devlink *devlink = info->user_ptr[0];
3282 struct devlink_param_item *param_item;
3283 struct sk_buff *msg;
3284 int err;
3285
3286 param_item = devlink_param_get_from_info(&devlink->param_list, info);
3287 if (!param_item)
3288 return -EINVAL;
3289
3290 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3291 if (!msg)
3292 return -ENOMEM;
3293
3294 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3295 DEVLINK_CMD_PARAM_GET,
3296 info->snd_portid, info->snd_seq, 0);
3297 if (err) {
3298 nlmsg_free(msg);
3299 return err;
3300 }
3301
3302 return genlmsg_reply(msg, info);
3303 }
3304
3305 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
3306 unsigned int port_index,
3307 struct list_head *param_list,
3308 struct genl_info *info,
3309 enum devlink_command cmd)
3310 {
3311 enum devlink_param_type param_type;
3312 struct devlink_param_gset_ctx ctx;
3313 enum devlink_param_cmode cmode;
3314 struct devlink_param_item *param_item;
3315 const struct devlink_param *param;
3316 union devlink_param_value value;
3317 int err = 0;
3318
3319 param_item = devlink_param_get_from_info(param_list, info);
3320 if (!param_item)
3321 return -EINVAL;
3322 param = param_item->param;
3323 err = devlink_param_type_get_from_info(info, ¶m_type);
3324 if (err)
3325 return err;
3326 if (param_type != param->type)
3327 return -EINVAL;
3328 err = devlink_param_value_get_from_info(param, info, &value);
3329 if (err)
3330 return err;
3331 if (param->validate) {
3332 err = param->validate(devlink, param->id, value, info->extack);
3333 if (err)
3334 return err;
3335 }
3336
3337 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3338 return -EINVAL;
3339 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3340 if (!devlink_param_cmode_is_supported(param, cmode))
3341 return -EOPNOTSUPP;
3342
3343 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3344 if (param->type == DEVLINK_PARAM_TYPE_STRING)
3345 strcpy(param_item->driverinit_value.vstr, value.vstr);
3346 else
3347 param_item->driverinit_value = value;
3348 param_item->driverinit_value_valid = true;
3349 } else {
3350 if (!param->set)
3351 return -EOPNOTSUPP;
3352 ctx.val = value;
3353 ctx.cmode = cmode;
3354 err = devlink_param_set(devlink, param, &ctx);
3355 if (err)
3356 return err;
3357 }
3358
3359 devlink_param_notify(devlink, port_index, param_item, cmd);
3360 return 0;
3361 }
3362
3363 static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3364 struct genl_info *info)
3365 {
3366 struct devlink *devlink = info->user_ptr[0];
3367
3368 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
3369 info, DEVLINK_CMD_PARAM_NEW);
3370 }
3371
3372 static int devlink_param_register_one(struct devlink *devlink,
3373 unsigned int port_index,
3374 struct list_head *param_list,
3375 const struct devlink_param *param,
3376 enum devlink_command cmd)
3377 {
3378 struct devlink_param_item *param_item;
3379
3380 if (devlink_param_find_by_name(param_list, param->name))
3381 return -EEXIST;
3382
3383 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
3384 WARN_ON(param->get || param->set);
3385 else
3386 WARN_ON(!param->get || !param->set);
3387
3388 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
3389 if (!param_item)
3390 return -ENOMEM;
3391 param_item->param = param;
3392
3393 list_add_tail(¶m_item->list, param_list);
3394 devlink_param_notify(devlink, port_index, param_item, cmd);
3395 return 0;
3396 }
3397
3398 static void devlink_param_unregister_one(struct devlink *devlink,
3399 unsigned int port_index,
3400 struct list_head *param_list,
3401 const struct devlink_param *param,
3402 enum devlink_command cmd)
3403 {
3404 struct devlink_param_item *param_item;
3405
3406 param_item = devlink_param_find_by_name(param_list, param->name);
3407 WARN_ON(!param_item);
3408 devlink_param_notify(devlink, port_index, param_item, cmd);
3409 list_del(¶m_item->list);
3410 kfree(param_item);
3411 }
3412
3413 static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
3414 struct netlink_callback *cb)
3415 {
3416 struct devlink_param_item *param_item;
3417 struct devlink_port *devlink_port;
3418 struct devlink *devlink;
3419 int start = cb->args[0];
3420 int idx = 0;
3421 int err;
3422
3423 mutex_lock(&devlink_mutex);
3424 list_for_each_entry(devlink, &devlink_list, list) {
3425 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3426 continue;
3427 mutex_lock(&devlink->lock);
3428 list_for_each_entry(devlink_port, &devlink->port_list, list) {
3429 list_for_each_entry(param_item,
3430 &devlink_port->param_list, list) {
3431 if (idx < start) {
3432 idx++;
3433 continue;
3434 }
3435 err = devlink_nl_param_fill(msg,
3436 devlink_port->devlink,
3437 devlink_port->index, param_item,
3438 DEVLINK_CMD_PORT_PARAM_GET,
3439 NETLINK_CB(cb->skb).portid,
3440 cb->nlh->nlmsg_seq,
3441 NLM_F_MULTI);
3442 if (err && err != -EOPNOTSUPP) {
3443 mutex_unlock(&devlink->lock);
3444 goto out;
3445 }
3446 idx++;
3447 }
3448 }
3449 mutex_unlock(&devlink->lock);
3450 }
3451 out:
3452 mutex_unlock(&devlink_mutex);
3453
3454 cb->args[0] = idx;
3455 return msg->len;
3456 }
3457
3458 static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
3459 struct genl_info *info)
3460 {
3461 struct devlink_port *devlink_port = info->user_ptr[0];
3462 struct devlink_param_item *param_item;
3463 struct sk_buff *msg;
3464 int err;
3465
3466 param_item = devlink_param_get_from_info(&devlink_port->param_list,
3467 info);
3468 if (!param_item)
3469 return -EINVAL;
3470
3471 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3472 if (!msg)
3473 return -ENOMEM;
3474
3475 err = devlink_nl_param_fill(msg, devlink_port->devlink,
3476 devlink_port->index, param_item,
3477 DEVLINK_CMD_PORT_PARAM_GET,
3478 info->snd_portid, info->snd_seq, 0);
3479 if (err) {
3480 nlmsg_free(msg);
3481 return err;
3482 }
3483
3484 return genlmsg_reply(msg, info);
3485 }
3486
3487 static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
3488 struct genl_info *info)
3489 {
3490 struct devlink_port *devlink_port = info->user_ptr[0];
3491
3492 return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
3493 devlink_port->index,
3494 &devlink_port->param_list, info,
3495 DEVLINK_CMD_PORT_PARAM_NEW);
3496 }
3497
3498 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
3499 struct devlink *devlink,
3500 struct devlink_snapshot *snapshot)
3501 {
3502 struct nlattr *snap_attr;
3503 int err;
3504
3505 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
3506 if (!snap_attr)
3507 return -EINVAL;
3508
3509 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
3510 if (err)
3511 goto nla_put_failure;
3512
3513 nla_nest_end(msg, snap_attr);
3514 return 0;
3515
3516 nla_put_failure:
3517 nla_nest_cancel(msg, snap_attr);
3518 return err;
3519 }
3520
3521 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
3522 struct devlink *devlink,
3523 struct devlink_region *region)
3524 {
3525 struct devlink_snapshot *snapshot;
3526 struct nlattr *snapshots_attr;
3527 int err;
3528
3529 snapshots_attr = nla_nest_start_noflag(msg,
3530 DEVLINK_ATTR_REGION_SNAPSHOTS);
3531 if (!snapshots_attr)
3532 return -EINVAL;
3533
3534 list_for_each_entry(snapshot, ®ion->snapshot_list, list) {
3535 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
3536 if (err)
3537 goto nla_put_failure;
3538 }
3539
3540 nla_nest_end(msg, snapshots_attr);
3541 return 0;
3542
3543 nla_put_failure:
3544 nla_nest_cancel(msg, snapshots_attr);
3545 return err;
3546 }
3547
3548 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
3549 enum devlink_command cmd, u32 portid,
3550 u32 seq, int flags,
3551 struct devlink_region *region)
3552 {
3553 void *hdr;
3554 int err;
3555
3556 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3557 if (!hdr)
3558 return -EMSGSIZE;
3559
3560 err = devlink_nl_put_handle(msg, devlink);
3561 if (err)
3562 goto nla_put_failure;
3563
3564 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name);
3565 if (err)
3566 goto nla_put_failure;
3567
3568 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3569 region->size,
3570 DEVLINK_ATTR_PAD);
3571 if (err)
3572 goto nla_put_failure;
3573
3574 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
3575 if (err)
3576 goto nla_put_failure;
3577
3578 genlmsg_end(msg, hdr);
3579 return 0;
3580
3581 nla_put_failure:
3582 genlmsg_cancel(msg, hdr);
3583 return err;
3584 }
3585
3586 static void devlink_nl_region_notify(struct devlink_region *region,
3587 struct devlink_snapshot *snapshot,
3588 enum devlink_command cmd)
3589 {
3590 struct devlink *devlink = region->devlink;
3591 struct sk_buff *msg;
3592 void *hdr;
3593 int err;
3594
3595 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
3596
3597 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3598 if (!msg)
3599 return;
3600
3601 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
3602 if (!hdr)
3603 goto out_free_msg;
3604
3605 err = devlink_nl_put_handle(msg, devlink);
3606 if (err)
3607 goto out_cancel_msg;
3608
3609 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
3610 region->name);
3611 if (err)
3612 goto out_cancel_msg;
3613
3614 if (snapshot) {
3615 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
3616 snapshot->id);
3617 if (err)
3618 goto out_cancel_msg;
3619 } else {
3620 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3621 region->size, DEVLINK_ATTR_PAD);
3622 if (err)
3623 goto out_cancel_msg;
3624 }
3625 genlmsg_end(msg, hdr);
3626
3627 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3628 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3629
3630 return;
3631
3632 out_cancel_msg:
3633 genlmsg_cancel(msg, hdr);
3634 out_free_msg:
3635 nlmsg_free(msg);
3636 }
3637
3638 static void devlink_region_snapshot_del(struct devlink_region *region,
3639 struct devlink_snapshot *snapshot)
3640 {
3641 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
3642 region->cur_snapshots--;
3643 list_del(&snapshot->list);
3644 (*snapshot->data_destructor)(snapshot->data);
3645 kfree(snapshot);
3646 }
3647
3648 static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
3649 struct genl_info *info)
3650 {
3651 struct devlink *devlink = info->user_ptr[0];
3652 struct devlink_region *region;
3653 const char *region_name;
3654 struct sk_buff *msg;
3655 int err;
3656
3657 if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
3658 return -EINVAL;
3659
3660 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3661 region = devlink_region_get_by_name(devlink, region_name);
3662 if (!region)
3663 return -EINVAL;
3664
3665 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3666 if (!msg)
3667 return -ENOMEM;
3668
3669 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
3670 info->snd_portid, info->snd_seq, 0,
3671 region);
3672 if (err) {
3673 nlmsg_free(msg);
3674 return err;
3675 }
3676
3677 return genlmsg_reply(msg, info);
3678 }
3679
3680 static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
3681 struct netlink_callback *cb)
3682 {
3683 struct devlink_region *region;
3684 struct devlink *devlink;
3685 int start = cb->args[0];
3686 int idx = 0;
3687 int err;
3688
3689 mutex_lock(&devlink_mutex);
3690 list_for_each_entry(devlink, &devlink_list, list) {
3691 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3692 continue;
3693
3694 mutex_lock(&devlink->lock);
3695 list_for_each_entry(region, &devlink->region_list, list) {
3696 if (idx < start) {
3697 idx++;
3698 continue;
3699 }
3700 err = devlink_nl_region_fill(msg, devlink,
3701 DEVLINK_CMD_REGION_GET,
3702 NETLINK_CB(cb->skb).portid,
3703 cb->nlh->nlmsg_seq,
3704 NLM_F_MULTI, region);
3705 if (err) {
3706 mutex_unlock(&devlink->lock);
3707 goto out;
3708 }
3709 idx++;
3710 }
3711 mutex_unlock(&devlink->lock);
3712 }
3713 out:
3714 mutex_unlock(&devlink_mutex);
3715 cb->args[0] = idx;
3716 return msg->len;
3717 }
3718
3719 static int devlink_nl_cmd_region_del(struct sk_buff *skb,
3720 struct genl_info *info)
3721 {
3722 struct devlink *devlink = info->user_ptr[0];
3723 struct devlink_snapshot *snapshot;
3724 struct devlink_region *region;
3725 const char *region_name;
3726 u32 snapshot_id;
3727
3728 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
3729 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
3730 return -EINVAL;
3731
3732 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3733 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3734
3735 region = devlink_region_get_by_name(devlink, region_name);
3736 if (!region)
3737 return -EINVAL;
3738
3739 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3740 if (!snapshot)
3741 return -EINVAL;
3742
3743 devlink_region_snapshot_del(region, snapshot);
3744 return 0;
3745 }
3746
3747 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
3748 struct devlink *devlink,
3749 u8 *chunk, u32 chunk_size,
3750 u64 addr)
3751 {
3752 struct nlattr *chunk_attr;
3753 int err;
3754
3755 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
3756 if (!chunk_attr)
3757 return -EINVAL;
3758
3759 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
3760 if (err)
3761 goto nla_put_failure;
3762
3763 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
3764 DEVLINK_ATTR_PAD);
3765 if (err)
3766 goto nla_put_failure;
3767
3768 nla_nest_end(msg, chunk_attr);
3769 return 0;
3770
3771 nla_put_failure:
3772 nla_nest_cancel(msg, chunk_attr);
3773 return err;
3774 }
3775
3776 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
3777
3778 static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
3779 struct devlink *devlink,
3780 struct devlink_region *region,
3781 struct nlattr **attrs,
3782 u64 start_offset,
3783 u64 end_offset,
3784 bool dump,
3785 u64 *new_offset)
3786 {
3787 struct devlink_snapshot *snapshot;
3788 u64 curr_offset = start_offset;
3789 u32 snapshot_id;
3790 int err = 0;
3791
3792 *new_offset = start_offset;
3793
3794 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3795 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3796 if (!snapshot)
3797 return -EINVAL;
3798
3799 if (end_offset > region->size || dump)
3800 end_offset = region->size;
3801
3802 while (curr_offset < end_offset) {
3803 u32 data_size;
3804 u8 *data;
3805
3806 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
3807 data_size = end_offset - curr_offset;
3808 else
3809 data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
3810
3811 data = &snapshot->data[curr_offset];
3812 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
3813 data, data_size,
3814 curr_offset);
3815 if (err)
3816 break;
3817
3818 curr_offset += data_size;
3819 }
3820 *new_offset = curr_offset;
3821
3822 return err;
3823 }
3824
3825 static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
3826 struct netlink_callback *cb)
3827 {
3828 u64 ret_offset, start_offset, end_offset = 0;
3829 struct devlink_region *region;
3830 struct nlattr *chunks_attr;
3831 const char *region_name;
3832 struct devlink *devlink;
3833 struct nlattr **attrs;
3834 bool dump = true;
3835 void *hdr;
3836 int err;
3837
3838 start_offset = *((u64 *)&cb->args[0]);
3839
3840 attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
3841 if (!attrs)
3842 return -ENOMEM;
3843
3844 err = nlmsg_parse_deprecated(cb->nlh,
3845 GENL_HDRLEN + devlink_nl_family.hdrsize,
3846 attrs, DEVLINK_ATTR_MAX,
3847 devlink_nl_family.policy, cb->extack);
3848 if (err)
3849 goto out_free;
3850
3851 mutex_lock(&devlink_mutex);
3852 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
3853 if (IS_ERR(devlink)) {
3854 err = PTR_ERR(devlink);
3855 goto out_dev;
3856 }
3857
3858 mutex_lock(&devlink->lock);
3859
3860 if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
3861 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
3862 err = -EINVAL;
3863 goto out_unlock;
3864 }
3865
3866 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
3867 region = devlink_region_get_by_name(devlink, region_name);
3868 if (!region) {
3869 err = -EINVAL;
3870 goto out_unlock;
3871 }
3872
3873
3874 if (start_offset >= region->size) {
3875 err = 0;
3876 goto out_unlock;
3877 }
3878
3879 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
3880 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
3881 DEVLINK_CMD_REGION_READ);
3882 if (!hdr) {
3883 err = -EMSGSIZE;
3884 goto out_unlock;
3885 }
3886
3887 err = devlink_nl_put_handle(skb, devlink);
3888 if (err)
3889 goto nla_put_failure;
3890
3891 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
3892 if (err)
3893 goto nla_put_failure;
3894
3895 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
3896 if (!chunks_attr) {
3897 err = -EMSGSIZE;
3898 goto nla_put_failure;
3899 }
3900
3901 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
3902 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
3903 if (!start_offset)
3904 start_offset =
3905 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3906
3907 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3908 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
3909 dump = false;
3910
3911 if (start_offset == end_offset) {
3912 err = 0;
3913 goto nla_put_failure;
3914 }
3915 }
3916
3917 err = devlink_nl_region_read_snapshot_fill(skb, devlink,
3918 region, attrs,
3919 start_offset,
3920 end_offset, dump,
3921 &ret_offset);
3922
3923 if (err && err != -EMSGSIZE)
3924 goto nla_put_failure;
3925
3926
3927 if (ret_offset == start_offset) {
3928 err = -EINVAL;
3929 goto nla_put_failure;
3930 }
3931
3932 *((u64 *)&cb->args[0]) = ret_offset;
3933
3934 nla_nest_end(skb, chunks_attr);
3935 genlmsg_end(skb, hdr);
3936 mutex_unlock(&devlink->lock);
3937 mutex_unlock(&devlink_mutex);
3938 kfree(attrs);
3939
3940 return skb->len;
3941
3942 nla_put_failure:
3943 genlmsg_cancel(skb, hdr);
3944 out_unlock:
3945 mutex_unlock(&devlink->lock);
3946 out_dev:
3947 mutex_unlock(&devlink_mutex);
3948 out_free:
3949 kfree(attrs);
3950 return err;
3951 }
3952
3953 struct devlink_info_req {
3954 struct sk_buff *msg;
3955 };
3956
3957 int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
3958 {
3959 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
3960 }
3961 EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
3962
3963 int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
3964 {
3965 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
3966 }
3967 EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
3968
3969 static int devlink_info_version_put(struct devlink_info_req *req, int attr,
3970 const char *version_name,
3971 const char *version_value)
3972 {
3973 struct nlattr *nest;
3974 int err;
3975
3976 nest = nla_nest_start_noflag(req->msg, attr);
3977 if (!nest)
3978 return -EMSGSIZE;
3979
3980 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
3981 version_name);
3982 if (err)
3983 goto nla_put_failure;
3984
3985 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
3986 version_value);
3987 if (err)
3988 goto nla_put_failure;
3989
3990 nla_nest_end(req->msg, nest);
3991
3992 return 0;
3993
3994 nla_put_failure:
3995 nla_nest_cancel(req->msg, nest);
3996 return err;
3997 }
3998
3999 int devlink_info_version_fixed_put(struct devlink_info_req *req,
4000 const char *version_name,
4001 const char *version_value)
4002 {
4003 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
4004 version_name, version_value);
4005 }
4006 EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
4007
4008 int devlink_info_version_stored_put(struct devlink_info_req *req,
4009 const char *version_name,
4010 const char *version_value)
4011 {
4012 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
4013 version_name, version_value);
4014 }
4015 EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
4016
4017 int devlink_info_version_running_put(struct devlink_info_req *req,
4018 const char *version_name,
4019 const char *version_value)
4020 {
4021 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
4022 version_name, version_value);
4023 }
4024 EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
4025
4026 static int
4027 devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
4028 enum devlink_command cmd, u32 portid,
4029 u32 seq, int flags, struct netlink_ext_ack *extack)
4030 {
4031 struct devlink_info_req req;
4032 void *hdr;
4033 int err;
4034
4035 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4036 if (!hdr)
4037 return -EMSGSIZE;
4038
4039 err = -EMSGSIZE;
4040 if (devlink_nl_put_handle(msg, devlink))
4041 goto err_cancel_msg;
4042
4043 req.msg = msg;
4044 err = devlink->ops->info_get(devlink, &req, extack);
4045 if (err)
4046 goto err_cancel_msg;
4047
4048 genlmsg_end(msg, hdr);
4049 return 0;
4050
4051 err_cancel_msg:
4052 genlmsg_cancel(msg, hdr);
4053 return err;
4054 }
4055
4056 static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
4057 struct genl_info *info)
4058 {
4059 struct devlink *devlink = info->user_ptr[0];
4060 struct sk_buff *msg;
4061 int err;
4062
4063 if (!devlink->ops->info_get)
4064 return -EOPNOTSUPP;
4065
4066 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4067 if (!msg)
4068 return -ENOMEM;
4069
4070 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4071 info->snd_portid, info->snd_seq, 0,
4072 info->extack);
4073 if (err) {
4074 nlmsg_free(msg);
4075 return err;
4076 }
4077
4078 return genlmsg_reply(msg, info);
4079 }
4080
4081 static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
4082 struct netlink_callback *cb)
4083 {
4084 struct devlink *devlink;
4085 int start = cb->args[0];
4086 int idx = 0;
4087 int err;
4088
4089 mutex_lock(&devlink_mutex);
4090 list_for_each_entry(devlink, &devlink_list, list) {
4091 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4092 continue;
4093 if (idx < start) {
4094 idx++;
4095 continue;
4096 }
4097
4098 if (!devlink->ops->info_get) {
4099 idx++;
4100 continue;
4101 }
4102
4103 mutex_lock(&devlink->lock);
4104 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4105 NETLINK_CB(cb->skb).portid,
4106 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4107 cb->extack);
4108 mutex_unlock(&devlink->lock);
4109 if (err && err != -EOPNOTSUPP)
4110 break;
4111 idx++;
4112 }
4113 mutex_unlock(&devlink_mutex);
4114
4115 cb->args[0] = idx;
4116 return msg->len;
4117 }
4118
4119 struct devlink_fmsg_item {
4120 struct list_head list;
4121 int attrtype;
4122 u8 nla_type;
4123 u16 len;
4124 int value[0];
4125 };
4126
4127 struct devlink_fmsg {
4128 struct list_head item_list;
4129 };
4130
4131 static struct devlink_fmsg *devlink_fmsg_alloc(void)
4132 {
4133 struct devlink_fmsg *fmsg;
4134
4135 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
4136 if (!fmsg)
4137 return NULL;
4138
4139 INIT_LIST_HEAD(&fmsg->item_list);
4140
4141 return fmsg;
4142 }
4143
4144 static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
4145 {
4146 struct devlink_fmsg_item *item, *tmp;
4147
4148 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
4149 list_del(&item->list);
4150 kfree(item);
4151 }
4152 kfree(fmsg);
4153 }
4154
4155 static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
4156 int attrtype)
4157 {
4158 struct devlink_fmsg_item *item;
4159
4160 item = kzalloc(sizeof(*item), GFP_KERNEL);
4161 if (!item)
4162 return -ENOMEM;
4163
4164 item->attrtype = attrtype;
4165 list_add_tail(&item->list, &fmsg->item_list);
4166
4167 return 0;
4168 }
4169
4170 int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
4171 {
4172 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
4173 }
4174 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
4175
4176 static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
4177 {
4178 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
4179 }
4180
4181 int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
4182 {
4183 return devlink_fmsg_nest_end(fmsg);
4184 }
4185 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
4186
4187 #define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
4188
4189 static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
4190 {
4191 struct devlink_fmsg_item *item;
4192
4193 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
4194 return -EMSGSIZE;
4195
4196 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
4197 if (!item)
4198 return -ENOMEM;
4199
4200 item->nla_type = NLA_NUL_STRING;
4201 item->len = strlen(name) + 1;
4202 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
4203 memcpy(&item->value, name, item->len);
4204 list_add_tail(&item->list, &fmsg->item_list);
4205
4206 return 0;
4207 }
4208
4209 int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
4210 {
4211 int err;
4212
4213 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
4214 if (err)
4215 return err;
4216
4217 err = devlink_fmsg_put_name(fmsg, name);
4218 if (err)
4219 return err;
4220
4221 return 0;
4222 }
4223 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
4224
4225 int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
4226 {
4227 return devlink_fmsg_nest_end(fmsg);
4228 }
4229 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
4230
4231 int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
4232 const char *name)
4233 {
4234 int err;
4235
4236 err = devlink_fmsg_pair_nest_start(fmsg, name);
4237 if (err)
4238 return err;
4239
4240 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
4241 if (err)
4242 return err;
4243
4244 return 0;
4245 }
4246 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
4247
4248 int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
4249 {
4250 int err;
4251
4252 err = devlink_fmsg_nest_end(fmsg);
4253 if (err)
4254 return err;
4255
4256 err = devlink_fmsg_nest_end(fmsg);
4257 if (err)
4258 return err;
4259
4260 return 0;
4261 }
4262 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
4263
4264 static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
4265 const void *value, u16 value_len,
4266 u8 value_nla_type)
4267 {
4268 struct devlink_fmsg_item *item;
4269
4270 if (value_len > DEVLINK_FMSG_MAX_SIZE)
4271 return -EMSGSIZE;
4272
4273 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
4274 if (!item)
4275 return -ENOMEM;
4276
4277 item->nla_type = value_nla_type;
4278 item->len = value_len;
4279 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4280 memcpy(&item->value, value, item->len);
4281 list_add_tail(&item->list, &fmsg->item_list);
4282
4283 return 0;
4284 }
4285
4286 int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
4287 {
4288 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
4289 }
4290 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put);
4291
4292 int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
4293 {
4294 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
4295 }
4296 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put);
4297
4298 int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
4299 {
4300 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
4301 }
4302 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
4303
4304 int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
4305 {
4306 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
4307 }
4308 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put);
4309
4310 int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
4311 {
4312 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
4313 NLA_NUL_STRING);
4314 }
4315 EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
4316
4317 int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
4318 u16 value_len)
4319 {
4320 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
4321 }
4322 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
4323
4324 int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
4325 bool value)
4326 {
4327 int err;
4328
4329 err = devlink_fmsg_pair_nest_start(fmsg, name);
4330 if (err)
4331 return err;
4332
4333 err = devlink_fmsg_bool_put(fmsg, value);
4334 if (err)
4335 return err;
4336
4337 err = devlink_fmsg_pair_nest_end(fmsg);
4338 if (err)
4339 return err;
4340
4341 return 0;
4342 }
4343 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
4344
4345 int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
4346 u8 value)
4347 {
4348 int err;
4349
4350 err = devlink_fmsg_pair_nest_start(fmsg, name);
4351 if (err)
4352 return err;
4353
4354 err = devlink_fmsg_u8_put(fmsg, value);
4355 if (err)
4356 return err;
4357
4358 err = devlink_fmsg_pair_nest_end(fmsg);
4359 if (err)
4360 return err;
4361
4362 return 0;
4363 }
4364 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
4365
4366 int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
4367 u32 value)
4368 {
4369 int err;
4370
4371 err = devlink_fmsg_pair_nest_start(fmsg, name);
4372 if (err)
4373 return err;
4374
4375 err = devlink_fmsg_u32_put(fmsg, value);
4376 if (err)
4377 return err;
4378
4379 err = devlink_fmsg_pair_nest_end(fmsg);
4380 if (err)
4381 return err;
4382
4383 return 0;
4384 }
4385 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
4386
4387 int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
4388 u64 value)
4389 {
4390 int err;
4391
4392 err = devlink_fmsg_pair_nest_start(fmsg, name);
4393 if (err)
4394 return err;
4395
4396 err = devlink_fmsg_u64_put(fmsg, value);
4397 if (err)
4398 return err;
4399
4400 err = devlink_fmsg_pair_nest_end(fmsg);
4401 if (err)
4402 return err;
4403
4404 return 0;
4405 }
4406 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
4407
4408 int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
4409 const char *value)
4410 {
4411 int err;
4412
4413 err = devlink_fmsg_pair_nest_start(fmsg, name);
4414 if (err)
4415 return err;
4416
4417 err = devlink_fmsg_string_put(fmsg, value);
4418 if (err)
4419 return err;
4420
4421 err = devlink_fmsg_pair_nest_end(fmsg);
4422 if (err)
4423 return err;
4424
4425 return 0;
4426 }
4427 EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
4428
4429 int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
4430 const void *value, u16 value_len)
4431 {
4432 int err;
4433
4434 err = devlink_fmsg_pair_nest_start(fmsg, name);
4435 if (err)
4436 return err;
4437
4438 err = devlink_fmsg_binary_put(fmsg, value, value_len);
4439 if (err)
4440 return err;
4441
4442 err = devlink_fmsg_pair_nest_end(fmsg);
4443 if (err)
4444 return err;
4445
4446 return 0;
4447 }
4448 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
4449
4450 static int
4451 devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4452 {
4453 switch (msg->nla_type) {
4454 case NLA_FLAG:
4455 case NLA_U8:
4456 case NLA_U32:
4457 case NLA_U64:
4458 case NLA_NUL_STRING:
4459 case NLA_BINARY:
4460 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
4461 msg->nla_type);
4462 default:
4463 return -EINVAL;
4464 }
4465 }
4466
4467 static int
4468 devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4469 {
4470 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4471 u8 tmp;
4472
4473 switch (msg->nla_type) {
4474 case NLA_FLAG:
4475
4476 tmp = *(bool *) msg->value;
4477
4478 return nla_put_u8(skb, attrtype, tmp);
4479 case NLA_U8:
4480 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
4481 case NLA_U32:
4482 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
4483 case NLA_U64:
4484 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
4485 DEVLINK_ATTR_PAD);
4486 case NLA_NUL_STRING:
4487 return nla_put_string(skb, attrtype, (char *) &msg->value);
4488 case NLA_BINARY:
4489 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
4490 default:
4491 return -EINVAL;
4492 }
4493 }
4494
4495 static int
4496 devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4497 int *start)
4498 {
4499 struct devlink_fmsg_item *item;
4500 struct nlattr *fmsg_nlattr;
4501 int i = 0;
4502 int err;
4503
4504 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
4505 if (!fmsg_nlattr)
4506 return -EMSGSIZE;
4507
4508 list_for_each_entry(item, &fmsg->item_list, list) {
4509 if (i < *start) {
4510 i++;
4511 continue;
4512 }
4513
4514 switch (item->attrtype) {
4515 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
4516 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
4517 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
4518 case DEVLINK_ATTR_FMSG_NEST_END:
4519 err = nla_put_flag(skb, item->attrtype);
4520 break;
4521 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
4522 err = devlink_fmsg_item_fill_type(item, skb);
4523 if (err)
4524 break;
4525 err = devlink_fmsg_item_fill_data(item, skb);
4526 break;
4527 case DEVLINK_ATTR_FMSG_OBJ_NAME:
4528 err = nla_put_string(skb, item->attrtype,
4529 (char *) &item->value);
4530 break;
4531 default:
4532 err = -EINVAL;
4533 break;
4534 }
4535 if (!err)
4536 *start = ++i;
4537 else
4538 break;
4539 }
4540
4541 nla_nest_end(skb, fmsg_nlattr);
4542 return err;
4543 }
4544
4545 static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
4546 struct genl_info *info,
4547 enum devlink_command cmd, int flags)
4548 {
4549 struct nlmsghdr *nlh;
4550 struct sk_buff *skb;
4551 bool last = false;
4552 int index = 0;
4553 void *hdr;
4554 int err;
4555
4556 while (!last) {
4557 int tmp_index = index;
4558
4559 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4560 if (!skb)
4561 return -ENOMEM;
4562
4563 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
4564 &devlink_nl_family, flags | NLM_F_MULTI, cmd);
4565 if (!hdr) {
4566 err = -EMSGSIZE;
4567 goto nla_put_failure;
4568 }
4569
4570 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4571 if (!err)
4572 last = true;
4573 else if (err != -EMSGSIZE || tmp_index == index)
4574 goto nla_put_failure;
4575
4576 genlmsg_end(skb, hdr);
4577 err = genlmsg_reply(skb, info);
4578 if (err)
4579 return err;
4580 }
4581
4582 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4583 if (!skb)
4584 return -ENOMEM;
4585 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
4586 NLMSG_DONE, 0, flags | NLM_F_MULTI);
4587 if (!nlh) {
4588 err = -EMSGSIZE;
4589 goto nla_put_failure;
4590 }
4591
4592 return genlmsg_reply(skb, info);
4593
4594 nla_put_failure:
4595 nlmsg_free(skb);
4596 return err;
4597 }
4598
4599 static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4600 struct netlink_callback *cb,
4601 enum devlink_command cmd)
4602 {
4603 int index = cb->args[0];
4604 int tmp_index = index;
4605 void *hdr;
4606 int err;
4607
4608 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
4609 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
4610 if (!hdr) {
4611 err = -EMSGSIZE;
4612 goto nla_put_failure;
4613 }
4614
4615 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4616 if ((err && err != -EMSGSIZE) || tmp_index == index)
4617 goto nla_put_failure;
4618
4619 cb->args[0] = index;
4620 genlmsg_end(skb, hdr);
4621 return skb->len;
4622
4623 nla_put_failure:
4624 genlmsg_cancel(skb, hdr);
4625 return err;
4626 }
4627
4628 struct devlink_health_reporter {
4629 struct list_head list;
4630 void *priv;
4631 const struct devlink_health_reporter_ops *ops;
4632 struct devlink *devlink;
4633 struct devlink_fmsg *dump_fmsg;
4634 struct mutex dump_lock;
4635 u64 graceful_period;
4636 bool auto_recover;
4637 u8 health_state;
4638 u64 dump_ts;
4639 u64 dump_real_ts;
4640 u64 error_count;
4641 u64 recovery_count;
4642 u64 last_recovery_ts;
4643 refcount_t refcount;
4644 };
4645
4646 void *
4647 devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
4648 {
4649 return reporter->priv;
4650 }
4651 EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
4652
4653 static struct devlink_health_reporter *
4654 devlink_health_reporter_find_by_name(struct devlink *devlink,
4655 const char *reporter_name)
4656 {
4657 struct devlink_health_reporter *reporter;
4658
4659 lockdep_assert_held(&devlink->reporters_lock);
4660 list_for_each_entry(reporter, &devlink->reporter_list, list)
4661 if (!strcmp(reporter->ops->name, reporter_name))
4662 return reporter;
4663 return NULL;
4664 }
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675 struct devlink_health_reporter *
4676 devlink_health_reporter_create(struct devlink *devlink,
4677 const struct devlink_health_reporter_ops *ops,
4678 u64 graceful_period, bool auto_recover,
4679 void *priv)
4680 {
4681 struct devlink_health_reporter *reporter;
4682
4683 mutex_lock(&devlink->reporters_lock);
4684 if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
4685 reporter = ERR_PTR(-EEXIST);
4686 goto unlock;
4687 }
4688
4689 if (WARN_ON(auto_recover && !ops->recover) ||
4690 WARN_ON(graceful_period && !ops->recover)) {
4691 reporter = ERR_PTR(-EINVAL);
4692 goto unlock;
4693 }
4694
4695 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
4696 if (!reporter) {
4697 reporter = ERR_PTR(-ENOMEM);
4698 goto unlock;
4699 }
4700
4701 reporter->priv = priv;
4702 reporter->ops = ops;
4703 reporter->devlink = devlink;
4704 reporter->graceful_period = graceful_period;
4705 reporter->auto_recover = auto_recover;
4706 mutex_init(&reporter->dump_lock);
4707 refcount_set(&reporter->refcount, 1);
4708 list_add_tail(&reporter->list, &devlink->reporter_list);
4709 unlock:
4710 mutex_unlock(&devlink->reporters_lock);
4711 return reporter;
4712 }
4713 EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
4714
4715
4716
4717
4718
4719
4720 void
4721 devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
4722 {
4723 mutex_lock(&reporter->devlink->reporters_lock);
4724 list_del(&reporter->list);
4725 mutex_unlock(&reporter->devlink->reporters_lock);
4726 while (refcount_read(&reporter->refcount) > 1)
4727 msleep(100);
4728 mutex_destroy(&reporter->dump_lock);
4729 if (reporter->dump_fmsg)
4730 devlink_fmsg_free(reporter->dump_fmsg);
4731 kfree(reporter);
4732 }
4733 EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
4734
4735 void
4736 devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
4737 enum devlink_health_reporter_state state)
4738 {
4739 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
4740 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
4741 return;
4742
4743 if (reporter->health_state == state)
4744 return;
4745
4746 reporter->health_state = state;
4747 trace_devlink_health_reporter_state_update(reporter->devlink,
4748 reporter->ops->name, state);
4749 }
4750 EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
4751
4752 static int
4753 devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
4754 void *priv_ctx)
4755 {
4756 int err;
4757
4758 if (!reporter->ops->recover)
4759 return -EOPNOTSUPP;
4760
4761 err = reporter->ops->recover(reporter, priv_ctx);
4762 if (err)
4763 return err;
4764
4765 reporter->recovery_count++;
4766 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
4767 reporter->last_recovery_ts = jiffies;
4768
4769 return 0;
4770 }
4771
4772 static void
4773 devlink_health_dump_clear(struct devlink_health_reporter *reporter)
4774 {
4775 if (!reporter->dump_fmsg)
4776 return;
4777 devlink_fmsg_free(reporter->dump_fmsg);
4778 reporter->dump_fmsg = NULL;
4779 }
4780
4781 static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
4782 void *priv_ctx)
4783 {
4784 int err;
4785
4786 if (!reporter->ops->dump)
4787 return 0;
4788
4789 if (reporter->dump_fmsg)
4790 return 0;
4791
4792 reporter->dump_fmsg = devlink_fmsg_alloc();
4793 if (!reporter->dump_fmsg) {
4794 err = -ENOMEM;
4795 return err;
4796 }
4797
4798 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
4799 if (err)
4800 goto dump_err;
4801
4802 err = reporter->ops->dump(reporter, reporter->dump_fmsg,
4803 priv_ctx);
4804 if (err)
4805 goto dump_err;
4806
4807 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
4808 if (err)
4809 goto dump_err;
4810
4811 reporter->dump_ts = jiffies;
4812 reporter->dump_real_ts = ktime_get_real_ns();
4813
4814 return 0;
4815
4816 dump_err:
4817 devlink_health_dump_clear(reporter);
4818 return err;
4819 }
4820
4821 int devlink_health_report(struct devlink_health_reporter *reporter,
4822 const char *msg, void *priv_ctx)
4823 {
4824 enum devlink_health_reporter_state prev_health_state;
4825 struct devlink *devlink = reporter->devlink;
4826
4827
4828 WARN_ON(!msg);
4829 trace_devlink_health_report(devlink, reporter->ops->name, msg);
4830 reporter->error_count++;
4831 prev_health_state = reporter->health_state;
4832 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4833
4834
4835 if (reporter->auto_recover &&
4836 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
4837 jiffies - reporter->last_recovery_ts <
4838 msecs_to_jiffies(reporter->graceful_period))) {
4839 trace_devlink_health_recover_aborted(devlink,
4840 reporter->ops->name,
4841 reporter->health_state,
4842 jiffies -
4843 reporter->last_recovery_ts);
4844 return -ECANCELED;
4845 }
4846
4847 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4848
4849 mutex_lock(&reporter->dump_lock);
4850
4851 devlink_health_do_dump(reporter, priv_ctx);
4852 mutex_unlock(&reporter->dump_lock);
4853
4854 if (reporter->auto_recover)
4855 return devlink_health_reporter_recover(reporter, priv_ctx);
4856
4857 return 0;
4858 }
4859 EXPORT_SYMBOL_GPL(devlink_health_report);
4860
4861 static struct devlink_health_reporter *
4862 devlink_health_reporter_get_from_attrs(struct devlink *devlink,
4863 struct nlattr **attrs)
4864 {
4865 struct devlink_health_reporter *reporter;
4866 char *reporter_name;
4867
4868 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
4869 return NULL;
4870
4871 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
4872 mutex_lock(&devlink->reporters_lock);
4873 reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
4874 if (reporter)
4875 refcount_inc(&reporter->refcount);
4876 mutex_unlock(&devlink->reporters_lock);
4877 return reporter;
4878 }
4879
4880 static struct devlink_health_reporter *
4881 devlink_health_reporter_get_from_info(struct devlink *devlink,
4882 struct genl_info *info)
4883 {
4884 return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
4885 }
4886
4887 static struct devlink_health_reporter *
4888 devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
4889 {
4890 struct devlink_health_reporter *reporter;
4891 struct devlink *devlink;
4892 struct nlattr **attrs;
4893 int err;
4894
4895 attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
4896 if (!attrs)
4897 return NULL;
4898
4899 err = nlmsg_parse_deprecated(cb->nlh,
4900 GENL_HDRLEN + devlink_nl_family.hdrsize,
4901 attrs, DEVLINK_ATTR_MAX,
4902 devlink_nl_family.policy, cb->extack);
4903 if (err)
4904 goto free;
4905
4906 mutex_lock(&devlink_mutex);
4907 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
4908 if (IS_ERR(devlink))
4909 goto unlock;
4910
4911 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
4912 mutex_unlock(&devlink_mutex);
4913 kfree(attrs);
4914 return reporter;
4915 unlock:
4916 mutex_unlock(&devlink_mutex);
4917 free:
4918 kfree(attrs);
4919 return NULL;
4920 }
4921
4922 static void
4923 devlink_health_reporter_put(struct devlink_health_reporter *reporter)
4924 {
4925 refcount_dec(&reporter->refcount);
4926 }
4927
4928 static int
4929 devlink_nl_health_reporter_fill(struct sk_buff *msg,
4930 struct devlink *devlink,
4931 struct devlink_health_reporter *reporter,
4932 enum devlink_command cmd, u32 portid,
4933 u32 seq, int flags)
4934 {
4935 struct nlattr *reporter_attr;
4936 void *hdr;
4937
4938 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4939 if (!hdr)
4940 return -EMSGSIZE;
4941
4942 if (devlink_nl_put_handle(msg, devlink))
4943 goto genlmsg_cancel;
4944
4945 reporter_attr = nla_nest_start_noflag(msg,
4946 DEVLINK_ATTR_HEALTH_REPORTER);
4947 if (!reporter_attr)
4948 goto genlmsg_cancel;
4949 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
4950 reporter->ops->name))
4951 goto reporter_nest_cancel;
4952 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
4953 reporter->health_state))
4954 goto reporter_nest_cancel;
4955 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
4956 reporter->error_count, DEVLINK_ATTR_PAD))
4957 goto reporter_nest_cancel;
4958 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
4959 reporter->recovery_count, DEVLINK_ATTR_PAD))
4960 goto reporter_nest_cancel;
4961 if (reporter->ops->recover &&
4962 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
4963 reporter->graceful_period,
4964 DEVLINK_ATTR_PAD))
4965 goto reporter_nest_cancel;
4966 if (reporter->ops->recover &&
4967 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
4968 reporter->auto_recover))
4969 goto reporter_nest_cancel;
4970 if (reporter->dump_fmsg &&
4971 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
4972 jiffies_to_msecs(reporter->dump_ts),
4973 DEVLINK_ATTR_PAD))
4974 goto reporter_nest_cancel;
4975 if (reporter->dump_fmsg &&
4976 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
4977 reporter->dump_real_ts, DEVLINK_ATTR_PAD))
4978 goto reporter_nest_cancel;
4979
4980 nla_nest_end(msg, reporter_attr);
4981 genlmsg_end(msg, hdr);
4982 return 0;
4983
4984 reporter_nest_cancel:
4985 nla_nest_end(msg, reporter_attr);
4986 genlmsg_cancel:
4987 genlmsg_cancel(msg, hdr);
4988 return -EMSGSIZE;
4989 }
4990
4991 static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
4992 struct genl_info *info)
4993 {
4994 struct devlink *devlink = info->user_ptr[0];
4995 struct devlink_health_reporter *reporter;
4996 struct sk_buff *msg;
4997 int err;
4998
4999 reporter = devlink_health_reporter_get_from_info(devlink, info);
5000 if (!reporter)
5001 return -EINVAL;
5002
5003 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5004 if (!msg) {
5005 err = -ENOMEM;
5006 goto out;
5007 }
5008
5009 err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
5010 DEVLINK_CMD_HEALTH_REPORTER_GET,
5011 info->snd_portid, info->snd_seq,
5012 0);
5013 if (err) {
5014 nlmsg_free(msg);
5015 goto out;
5016 }
5017
5018 err = genlmsg_reply(msg, info);
5019 out:
5020 devlink_health_reporter_put(reporter);
5021 return err;
5022 }
5023
5024 static int
5025 devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
5026 struct netlink_callback *cb)
5027 {
5028 struct devlink_health_reporter *reporter;
5029 struct devlink *devlink;
5030 int start = cb->args[0];
5031 int idx = 0;
5032 int err;
5033
5034 mutex_lock(&devlink_mutex);
5035 list_for_each_entry(devlink, &devlink_list, list) {
5036 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5037 continue;
5038 mutex_lock(&devlink->reporters_lock);
5039 list_for_each_entry(reporter, &devlink->reporter_list,
5040 list) {
5041 if (idx < start) {
5042 idx++;
5043 continue;
5044 }
5045 err = devlink_nl_health_reporter_fill(msg, devlink,
5046 reporter,
5047 DEVLINK_CMD_HEALTH_REPORTER_GET,
5048 NETLINK_CB(cb->skb).portid,
5049 cb->nlh->nlmsg_seq,
5050 NLM_F_MULTI);
5051 if (err) {
5052 mutex_unlock(&devlink->reporters_lock);
5053 goto out;
5054 }
5055 idx++;
5056 }
5057 mutex_unlock(&devlink->reporters_lock);
5058 }
5059 out:
5060 mutex_unlock(&devlink_mutex);
5061
5062 cb->args[0] = idx;
5063 return msg->len;
5064 }
5065
5066 static int
5067 devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
5068 struct genl_info *info)
5069 {
5070 struct devlink *devlink = info->user_ptr[0];
5071 struct devlink_health_reporter *reporter;
5072 int err;
5073
5074 reporter = devlink_health_reporter_get_from_info(devlink, info);
5075 if (!reporter)
5076 return -EINVAL;
5077
5078 if (!reporter->ops->recover &&
5079 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
5080 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
5081 err = -EOPNOTSUPP;
5082 goto out;
5083 }
5084
5085 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
5086 reporter->graceful_period =
5087 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
5088
5089 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
5090 reporter->auto_recover =
5091 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
5092
5093 devlink_health_reporter_put(reporter);
5094 return 0;
5095 out:
5096 devlink_health_reporter_put(reporter);
5097 return err;
5098 }
5099
5100 static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
5101 struct genl_info *info)
5102 {
5103 struct devlink *devlink = info->user_ptr[0];
5104 struct devlink_health_reporter *reporter;
5105 int err;
5106
5107 reporter = devlink_health_reporter_get_from_info(devlink, info);
5108 if (!reporter)
5109 return -EINVAL;
5110
5111 err = devlink_health_reporter_recover(reporter, NULL);
5112
5113 devlink_health_reporter_put(reporter);
5114 return err;
5115 }
5116
5117 static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
5118 struct genl_info *info)
5119 {
5120 struct devlink *devlink = info->user_ptr[0];
5121 struct devlink_health_reporter *reporter;
5122 struct devlink_fmsg *fmsg;
5123 int err;
5124
5125 reporter = devlink_health_reporter_get_from_info(devlink, info);
5126 if (!reporter)
5127 return -EINVAL;
5128
5129 if (!reporter->ops->diagnose) {
5130 devlink_health_reporter_put(reporter);
5131 return -EOPNOTSUPP;
5132 }
5133
5134 fmsg = devlink_fmsg_alloc();
5135 if (!fmsg) {
5136 devlink_health_reporter_put(reporter);
5137 return -ENOMEM;
5138 }
5139
5140 err = devlink_fmsg_obj_nest_start(fmsg);
5141 if (err)
5142 goto out;
5143
5144 err = reporter->ops->diagnose(reporter, fmsg);
5145 if (err)
5146 goto out;
5147
5148 err = devlink_fmsg_obj_nest_end(fmsg);
5149 if (err)
5150 goto out;
5151
5152 err = devlink_fmsg_snd(fmsg, info,
5153 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
5154
5155 out:
5156 devlink_fmsg_free(fmsg);
5157 devlink_health_reporter_put(reporter);
5158 return err;
5159 }
5160
5161 static int
5162 devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
5163 struct netlink_callback *cb)
5164 {
5165 struct devlink_health_reporter *reporter;
5166 u64 start = cb->args[0];
5167 int err;
5168
5169 reporter = devlink_health_reporter_get_from_cb(cb);
5170 if (!reporter)
5171 return -EINVAL;
5172
5173 if (!reporter->ops->dump) {
5174 err = -EOPNOTSUPP;
5175 goto out;
5176 }
5177 mutex_lock(&reporter->dump_lock);
5178 if (!start) {
5179 err = devlink_health_do_dump(reporter, NULL);
5180 if (err)
5181 goto unlock;
5182 cb->args[1] = reporter->dump_ts;
5183 }
5184 if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) {
5185 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
5186 err = -EAGAIN;
5187 goto unlock;
5188 }
5189
5190 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
5191 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
5192 unlock:
5193 mutex_unlock(&reporter->dump_lock);
5194 out:
5195 devlink_health_reporter_put(reporter);
5196 return err;
5197 }
5198
5199 static int
5200 devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
5201 struct genl_info *info)
5202 {
5203 struct devlink *devlink = info->user_ptr[0];
5204 struct devlink_health_reporter *reporter;
5205
5206 reporter = devlink_health_reporter_get_from_info(devlink, info);
5207 if (!reporter)
5208 return -EINVAL;
5209
5210 if (!reporter->ops->dump) {
5211 devlink_health_reporter_put(reporter);
5212 return -EOPNOTSUPP;
5213 }
5214
5215 mutex_lock(&reporter->dump_lock);
5216 devlink_health_dump_clear(reporter);
5217 mutex_unlock(&reporter->dump_lock);
5218 devlink_health_reporter_put(reporter);
5219 return 0;
5220 }
5221
5222 struct devlink_stats {
5223 u64 rx_bytes;
5224 u64 rx_packets;
5225 struct u64_stats_sync syncp;
5226 };
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238 struct devlink_trap_group_item {
5239 const struct devlink_trap_group *group;
5240 refcount_t refcount;
5241 struct list_head list;
5242 struct devlink_stats __percpu *stats;
5243 };
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257 struct devlink_trap_item {
5258 const struct devlink_trap *trap;
5259 struct devlink_trap_group_item *group_item;
5260 struct list_head list;
5261 enum devlink_trap_action action;
5262 struct devlink_stats __percpu *stats;
5263 void *priv;
5264 };
5265
5266 static struct devlink_trap_item *
5267 devlink_trap_item_lookup(struct devlink *devlink, const char *name)
5268 {
5269 struct devlink_trap_item *trap_item;
5270
5271 list_for_each_entry(trap_item, &devlink->trap_list, list) {
5272 if (!strcmp(trap_item->trap->name, name))
5273 return trap_item;
5274 }
5275
5276 return NULL;
5277 }
5278
5279 static struct devlink_trap_item *
5280 devlink_trap_item_get_from_info(struct devlink *devlink,
5281 struct genl_info *info)
5282 {
5283 struct nlattr *attr;
5284
5285 if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
5286 return NULL;
5287 attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
5288
5289 return devlink_trap_item_lookup(devlink, nla_data(attr));
5290 }
5291
5292 static int
5293 devlink_trap_action_get_from_info(struct genl_info *info,
5294 enum devlink_trap_action *p_trap_action)
5295 {
5296 u8 val;
5297
5298 val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
5299 switch (val) {
5300 case DEVLINK_TRAP_ACTION_DROP:
5301 case DEVLINK_TRAP_ACTION_TRAP:
5302 *p_trap_action = val;
5303 break;
5304 default:
5305 return -EINVAL;
5306 }
5307
5308 return 0;
5309 }
5310
5311 static int devlink_trap_metadata_put(struct sk_buff *msg,
5312 const struct devlink_trap *trap)
5313 {
5314 struct nlattr *attr;
5315
5316 attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
5317 if (!attr)
5318 return -EMSGSIZE;
5319
5320 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
5321 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
5322 goto nla_put_failure;
5323
5324 nla_nest_end(msg, attr);
5325
5326 return 0;
5327
5328 nla_put_failure:
5329 nla_nest_cancel(msg, attr);
5330 return -EMSGSIZE;
5331 }
5332
5333 static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
5334 struct devlink_stats *stats)
5335 {
5336 int i;
5337
5338 memset(stats, 0, sizeof(*stats));
5339 for_each_possible_cpu(i) {
5340 struct devlink_stats *cpu_stats;
5341 u64 rx_packets, rx_bytes;
5342 unsigned int start;
5343
5344 cpu_stats = per_cpu_ptr(trap_stats, i);
5345 do {
5346 start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
5347 rx_packets = cpu_stats->rx_packets;
5348 rx_bytes = cpu_stats->rx_bytes;
5349 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
5350
5351 stats->rx_packets += rx_packets;
5352 stats->rx_bytes += rx_bytes;
5353 }
5354 }
5355
5356 static int devlink_trap_stats_put(struct sk_buff *msg,
5357 struct devlink_stats __percpu *trap_stats)
5358 {
5359 struct devlink_stats stats;
5360 struct nlattr *attr;
5361
5362 devlink_trap_stats_read(trap_stats, &stats);
5363
5364 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
5365 if (!attr)
5366 return -EMSGSIZE;
5367
5368 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
5369 stats.rx_packets, DEVLINK_ATTR_PAD))
5370 goto nla_put_failure;
5371
5372 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
5373 stats.rx_bytes, DEVLINK_ATTR_PAD))
5374 goto nla_put_failure;
5375
5376 nla_nest_end(msg, attr);
5377
5378 return 0;
5379
5380 nla_put_failure:
5381 nla_nest_cancel(msg, attr);
5382 return -EMSGSIZE;
5383 }
5384
5385 static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
5386 const struct devlink_trap_item *trap_item,
5387 enum devlink_command cmd, u32 portid, u32 seq,
5388 int flags)
5389 {
5390 struct devlink_trap_group_item *group_item = trap_item->group_item;
5391 void *hdr;
5392 int err;
5393
5394 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5395 if (!hdr)
5396 return -EMSGSIZE;
5397
5398 if (devlink_nl_put_handle(msg, devlink))
5399 goto nla_put_failure;
5400
5401 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
5402 group_item->group->name))
5403 goto nla_put_failure;
5404
5405 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
5406 goto nla_put_failure;
5407
5408 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
5409 goto nla_put_failure;
5410
5411 if (trap_item->trap->generic &&
5412 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
5413 goto nla_put_failure;
5414
5415 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
5416 goto nla_put_failure;
5417
5418 err = devlink_trap_metadata_put(msg, trap_item->trap);
5419 if (err)
5420 goto nla_put_failure;
5421
5422 err = devlink_trap_stats_put(msg, trap_item->stats);
5423 if (err)
5424 goto nla_put_failure;
5425
5426 genlmsg_end(msg, hdr);
5427
5428 return 0;
5429
5430 nla_put_failure:
5431 genlmsg_cancel(msg, hdr);
5432 return -EMSGSIZE;
5433 }
5434
5435 static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb,
5436 struct genl_info *info)
5437 {
5438 struct netlink_ext_ack *extack = info->extack;
5439 struct devlink *devlink = info->user_ptr[0];
5440 struct devlink_trap_item *trap_item;
5441 struct sk_buff *msg;
5442 int err;
5443
5444 if (list_empty(&devlink->trap_list))
5445 return -EOPNOTSUPP;
5446
5447 trap_item = devlink_trap_item_get_from_info(devlink, info);
5448 if (!trap_item) {
5449 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
5450 return -ENOENT;
5451 }
5452
5453 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5454 if (!msg)
5455 return -ENOMEM;
5456
5457 err = devlink_nl_trap_fill(msg, devlink, trap_item,
5458 DEVLINK_CMD_TRAP_NEW, info->snd_portid,
5459 info->snd_seq, 0);
5460 if (err)
5461 goto err_trap_fill;
5462
5463 return genlmsg_reply(msg, info);
5464
5465 err_trap_fill:
5466 nlmsg_free(msg);
5467 return err;
5468 }
5469
5470 static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg,
5471 struct netlink_callback *cb)
5472 {
5473 struct devlink_trap_item *trap_item;
5474 struct devlink *devlink;
5475 int start = cb->args[0];
5476 int idx = 0;
5477 int err;
5478
5479 mutex_lock(&devlink_mutex);
5480 list_for_each_entry(devlink, &devlink_list, list) {
5481 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5482 continue;
5483 mutex_lock(&devlink->lock);
5484 list_for_each_entry(trap_item, &devlink->trap_list, list) {
5485 if (idx < start) {
5486 idx++;
5487 continue;
5488 }
5489 err = devlink_nl_trap_fill(msg, devlink, trap_item,
5490 DEVLINK_CMD_TRAP_NEW,
5491 NETLINK_CB(cb->skb).portid,
5492 cb->nlh->nlmsg_seq,
5493 NLM_F_MULTI);
5494 if (err) {
5495 mutex_unlock(&devlink->lock);
5496 goto out;
5497 }
5498 idx++;
5499 }
5500 mutex_unlock(&devlink->lock);
5501 }
5502 out:
5503 mutex_unlock(&devlink_mutex);
5504
5505 cb->args[0] = idx;
5506 return msg->len;
5507 }
5508
5509 static int __devlink_trap_action_set(struct devlink *devlink,
5510 struct devlink_trap_item *trap_item,
5511 enum devlink_trap_action trap_action,
5512 struct netlink_ext_ack *extack)
5513 {
5514 int err;
5515
5516 if (trap_item->action != trap_action &&
5517 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
5518 NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping");
5519 return 0;
5520 }
5521
5522 err = devlink->ops->trap_action_set(devlink, trap_item->trap,
5523 trap_action);
5524 if (err)
5525 return err;
5526
5527 trap_item->action = trap_action;
5528
5529 return 0;
5530 }
5531
5532 static int devlink_trap_action_set(struct devlink *devlink,
5533 struct devlink_trap_item *trap_item,
5534 struct genl_info *info)
5535 {
5536 enum devlink_trap_action trap_action;
5537 int err;
5538
5539 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
5540 return 0;
5541
5542 err = devlink_trap_action_get_from_info(info, &trap_action);
5543 if (err) {
5544 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
5545 return -EINVAL;
5546 }
5547
5548 return __devlink_trap_action_set(devlink, trap_item, trap_action,
5549 info->extack);
5550 }
5551
5552 static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb,
5553 struct genl_info *info)
5554 {
5555 struct netlink_ext_ack *extack = info->extack;
5556 struct devlink *devlink = info->user_ptr[0];
5557 struct devlink_trap_item *trap_item;
5558 int err;
5559
5560 if (list_empty(&devlink->trap_list))
5561 return -EOPNOTSUPP;
5562
5563 trap_item = devlink_trap_item_get_from_info(devlink, info);
5564 if (!trap_item) {
5565 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
5566 return -ENOENT;
5567 }
5568
5569 err = devlink_trap_action_set(devlink, trap_item, info);
5570 if (err)
5571 return err;
5572
5573 return 0;
5574 }
5575
5576 static struct devlink_trap_group_item *
5577 devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
5578 {
5579 struct devlink_trap_group_item *group_item;
5580
5581 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
5582 if (!strcmp(group_item->group->name, name))
5583 return group_item;
5584 }
5585
5586 return NULL;
5587 }
5588
5589 static struct devlink_trap_group_item *
5590 devlink_trap_group_item_get_from_info(struct devlink *devlink,
5591 struct genl_info *info)
5592 {
5593 char *name;
5594
5595 if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
5596 return NULL;
5597 name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
5598
5599 return devlink_trap_group_item_lookup(devlink, name);
5600 }
5601
5602 static int
5603 devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
5604 const struct devlink_trap_group_item *group_item,
5605 enum devlink_command cmd, u32 portid, u32 seq,
5606 int flags)
5607 {
5608 void *hdr;
5609 int err;
5610
5611 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5612 if (!hdr)
5613 return -EMSGSIZE;
5614
5615 if (devlink_nl_put_handle(msg, devlink))
5616 goto nla_put_failure;
5617
5618 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
5619 group_item->group->name))
5620 goto nla_put_failure;
5621
5622 if (group_item->group->generic &&
5623 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
5624 goto nla_put_failure;
5625
5626 err = devlink_trap_stats_put(msg, group_item->stats);
5627 if (err)
5628 goto nla_put_failure;
5629
5630 genlmsg_end(msg, hdr);
5631
5632 return 0;
5633
5634 nla_put_failure:
5635 genlmsg_cancel(msg, hdr);
5636 return -EMSGSIZE;
5637 }
5638
5639 static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb,
5640 struct genl_info *info)
5641 {
5642 struct netlink_ext_ack *extack = info->extack;
5643 struct devlink *devlink = info->user_ptr[0];
5644 struct devlink_trap_group_item *group_item;
5645 struct sk_buff *msg;
5646 int err;
5647
5648 if (list_empty(&devlink->trap_group_list))
5649 return -EOPNOTSUPP;
5650
5651 group_item = devlink_trap_group_item_get_from_info(devlink, info);
5652 if (!group_item) {
5653 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
5654 return -ENOENT;
5655 }
5656
5657 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5658 if (!msg)
5659 return -ENOMEM;
5660
5661 err = devlink_nl_trap_group_fill(msg, devlink, group_item,
5662 DEVLINK_CMD_TRAP_GROUP_NEW,
5663 info->snd_portid, info->snd_seq, 0);
5664 if (err)
5665 goto err_trap_group_fill;
5666
5667 return genlmsg_reply(msg, info);
5668
5669 err_trap_group_fill:
5670 nlmsg_free(msg);
5671 return err;
5672 }
5673
5674 static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg,
5675 struct netlink_callback *cb)
5676 {
5677 enum devlink_command cmd = DEVLINK_CMD_TRAP_GROUP_NEW;
5678 struct devlink_trap_group_item *group_item;
5679 u32 portid = NETLINK_CB(cb->skb).portid;
5680 struct devlink *devlink;
5681 int start = cb->args[0];
5682 int idx = 0;
5683 int err;
5684
5685 mutex_lock(&devlink_mutex);
5686 list_for_each_entry(devlink, &devlink_list, list) {
5687 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5688 continue;
5689 mutex_lock(&devlink->lock);
5690 list_for_each_entry(group_item, &devlink->trap_group_list,
5691 list) {
5692 if (idx < start) {
5693 idx++;
5694 continue;
5695 }
5696 err = devlink_nl_trap_group_fill(msg, devlink,
5697 group_item, cmd,
5698 portid,
5699 cb->nlh->nlmsg_seq,
5700 NLM_F_MULTI);
5701 if (err) {
5702 mutex_unlock(&devlink->lock);
5703 goto out;
5704 }
5705 idx++;
5706 }
5707 mutex_unlock(&devlink->lock);
5708 }
5709 out:
5710 mutex_unlock(&devlink_mutex);
5711
5712 cb->args[0] = idx;
5713 return msg->len;
5714 }
5715
5716 static int
5717 __devlink_trap_group_action_set(struct devlink *devlink,
5718 struct devlink_trap_group_item *group_item,
5719 enum devlink_trap_action trap_action,
5720 struct netlink_ext_ack *extack)
5721 {
5722 const char *group_name = group_item->group->name;
5723 struct devlink_trap_item *trap_item;
5724 int err;
5725
5726 list_for_each_entry(trap_item, &devlink->trap_list, list) {
5727 if (strcmp(trap_item->trap->group.name, group_name))
5728 continue;
5729 err = __devlink_trap_action_set(devlink, trap_item,
5730 trap_action, extack);
5731 if (err)
5732 return err;
5733 }
5734
5735 return 0;
5736 }
5737
5738 static int
5739 devlink_trap_group_action_set(struct devlink *devlink,
5740 struct devlink_trap_group_item *group_item,
5741 struct genl_info *info)
5742 {
5743 enum devlink_trap_action trap_action;
5744 int err;
5745
5746 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
5747 return 0;
5748
5749 err = devlink_trap_action_get_from_info(info, &trap_action);
5750 if (err) {
5751 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
5752 return -EINVAL;
5753 }
5754
5755 err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
5756 info->extack);
5757 if (err)
5758 return err;
5759
5760 return 0;
5761 }
5762
5763 static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
5764 struct genl_info *info)
5765 {
5766 struct netlink_ext_ack *extack = info->extack;
5767 struct devlink *devlink = info->user_ptr[0];
5768 struct devlink_trap_group_item *group_item;
5769 int err;
5770
5771 if (list_empty(&devlink->trap_group_list))
5772 return -EOPNOTSUPP;
5773
5774 group_item = devlink_trap_group_item_get_from_info(devlink, info);
5775 if (!group_item) {
5776 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
5777 return -ENOENT;
5778 }
5779
5780 err = devlink_trap_group_action_set(devlink, group_item, info);
5781 if (err)
5782 return err;
5783
5784 return 0;
5785 }
5786
5787 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
5788 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
5789 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
5790 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
5791 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
5792 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
5793 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
5794 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
5795 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
5796 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
5797 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
5798 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
5799 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
5800 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
5801 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
5802 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
5803 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
5804 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
5805 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
5806 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
5807 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
5808 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
5809 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
5810 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
5811 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
5812 [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 },
5813 [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 },
5814 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
5815 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
5816 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
5817 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
5818 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
5819 [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING },
5820 [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 },
5821 [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },
5822 };
5823
5824 static const struct genl_ops devlink_nl_ops[] = {
5825 {
5826 .cmd = DEVLINK_CMD_GET,
5827 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5828 .doit = devlink_nl_cmd_get_doit,
5829 .dumpit = devlink_nl_cmd_get_dumpit,
5830 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5831
5832 },
5833 {
5834 .cmd = DEVLINK_CMD_PORT_GET,
5835 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5836 .doit = devlink_nl_cmd_port_get_doit,
5837 .dumpit = devlink_nl_cmd_port_get_dumpit,
5838 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5839
5840 },
5841 {
5842 .cmd = DEVLINK_CMD_PORT_SET,
5843 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5844 .doit = devlink_nl_cmd_port_set_doit,
5845 .flags = GENL_ADMIN_PERM,
5846 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5847 },
5848 {
5849 .cmd = DEVLINK_CMD_PORT_SPLIT,
5850 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5851 .doit = devlink_nl_cmd_port_split_doit,
5852 .flags = GENL_ADMIN_PERM,
5853 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5854 DEVLINK_NL_FLAG_NO_LOCK,
5855 },
5856 {
5857 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
5858 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5859 .doit = devlink_nl_cmd_port_unsplit_doit,
5860 .flags = GENL_ADMIN_PERM,
5861 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5862 DEVLINK_NL_FLAG_NO_LOCK,
5863 },
5864 {
5865 .cmd = DEVLINK_CMD_SB_GET,
5866 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5867 .doit = devlink_nl_cmd_sb_get_doit,
5868 .dumpit = devlink_nl_cmd_sb_get_dumpit,
5869 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5870 DEVLINK_NL_FLAG_NEED_SB,
5871
5872 },
5873 {
5874 .cmd = DEVLINK_CMD_SB_POOL_GET,
5875 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5876 .doit = devlink_nl_cmd_sb_pool_get_doit,
5877 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
5878 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5879 DEVLINK_NL_FLAG_NEED_SB,
5880
5881 },
5882 {
5883 .cmd = DEVLINK_CMD_SB_POOL_SET,
5884 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5885 .doit = devlink_nl_cmd_sb_pool_set_doit,
5886 .flags = GENL_ADMIN_PERM,
5887 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5888 DEVLINK_NL_FLAG_NEED_SB,
5889 },
5890 {
5891 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
5892 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5893 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
5894 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
5895 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5896 DEVLINK_NL_FLAG_NEED_SB,
5897
5898 },
5899 {
5900 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
5901 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5902 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
5903 .flags = GENL_ADMIN_PERM,
5904 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5905 DEVLINK_NL_FLAG_NEED_SB,
5906 },
5907 {
5908 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
5909 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5910 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
5911 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
5912 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5913 DEVLINK_NL_FLAG_NEED_SB,
5914
5915 },
5916 {
5917 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
5918 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5919 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
5920 .flags = GENL_ADMIN_PERM,
5921 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5922 DEVLINK_NL_FLAG_NEED_SB,
5923 },
5924 {
5925 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
5926 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5927 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
5928 .flags = GENL_ADMIN_PERM,
5929 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5930 DEVLINK_NL_FLAG_NEED_SB,
5931 },
5932 {
5933 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
5934 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5935 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
5936 .flags = GENL_ADMIN_PERM,
5937 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5938 DEVLINK_NL_FLAG_NEED_SB,
5939 },
5940 {
5941 .cmd = DEVLINK_CMD_ESWITCH_GET,
5942 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5943 .doit = devlink_nl_cmd_eswitch_get_doit,
5944 .flags = GENL_ADMIN_PERM,
5945 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5946 },
5947 {
5948 .cmd = DEVLINK_CMD_ESWITCH_SET,
5949 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5950 .doit = devlink_nl_cmd_eswitch_set_doit,
5951 .flags = GENL_ADMIN_PERM,
5952 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5953 DEVLINK_NL_FLAG_NO_LOCK,
5954 },
5955 {
5956 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
5957 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5958 .doit = devlink_nl_cmd_dpipe_table_get,
5959 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5960
5961 },
5962 {
5963 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
5964 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5965 .doit = devlink_nl_cmd_dpipe_entries_get,
5966 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5967
5968 },
5969 {
5970 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
5971 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5972 .doit = devlink_nl_cmd_dpipe_headers_get,
5973 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5974
5975 },
5976 {
5977 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
5978 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5979 .doit = devlink_nl_cmd_dpipe_table_counters_set,
5980 .flags = GENL_ADMIN_PERM,
5981 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5982 },
5983 {
5984 .cmd = DEVLINK_CMD_RESOURCE_SET,
5985 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5986 .doit = devlink_nl_cmd_resource_set,
5987 .flags = GENL_ADMIN_PERM,
5988 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5989 },
5990 {
5991 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
5992 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5993 .doit = devlink_nl_cmd_resource_dump,
5994 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5995
5996 },
5997 {
5998 .cmd = DEVLINK_CMD_RELOAD,
5999 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6000 .doit = devlink_nl_cmd_reload,
6001 .flags = GENL_ADMIN_PERM,
6002 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6003 DEVLINK_NL_FLAG_NO_LOCK,
6004 },
6005 {
6006 .cmd = DEVLINK_CMD_PARAM_GET,
6007 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6008 .doit = devlink_nl_cmd_param_get_doit,
6009 .dumpit = devlink_nl_cmd_param_get_dumpit,
6010 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6011
6012 },
6013 {
6014 .cmd = DEVLINK_CMD_PARAM_SET,
6015 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6016 .doit = devlink_nl_cmd_param_set_doit,
6017 .flags = GENL_ADMIN_PERM,
6018 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6019 },
6020 {
6021 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
6022 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6023 .doit = devlink_nl_cmd_port_param_get_doit,
6024 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
6025 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6026
6027 },
6028 {
6029 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
6030 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6031 .doit = devlink_nl_cmd_port_param_set_doit,
6032 .flags = GENL_ADMIN_PERM,
6033 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6034 },
6035 {
6036 .cmd = DEVLINK_CMD_REGION_GET,
6037 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6038 .doit = devlink_nl_cmd_region_get_doit,
6039 .dumpit = devlink_nl_cmd_region_get_dumpit,
6040 .flags = GENL_ADMIN_PERM,
6041 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6042 },
6043 {
6044 .cmd = DEVLINK_CMD_REGION_DEL,
6045 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6046 .doit = devlink_nl_cmd_region_del,
6047 .flags = GENL_ADMIN_PERM,
6048 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6049 },
6050 {
6051 .cmd = DEVLINK_CMD_REGION_READ,
6052 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6053 .dumpit = devlink_nl_cmd_region_read_dumpit,
6054 .flags = GENL_ADMIN_PERM,
6055 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6056 },
6057 {
6058 .cmd = DEVLINK_CMD_INFO_GET,
6059 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6060 .doit = devlink_nl_cmd_info_get_doit,
6061 .dumpit = devlink_nl_cmd_info_get_dumpit,
6062 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6063
6064 },
6065 {
6066 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
6067 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6068 .doit = devlink_nl_cmd_health_reporter_get_doit,
6069 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
6070 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6071 DEVLINK_NL_FLAG_NO_LOCK,
6072
6073 },
6074 {
6075 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
6076 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6077 .doit = devlink_nl_cmd_health_reporter_set_doit,
6078 .flags = GENL_ADMIN_PERM,
6079 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6080 DEVLINK_NL_FLAG_NO_LOCK,
6081 },
6082 {
6083 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
6084 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6085 .doit = devlink_nl_cmd_health_reporter_recover_doit,
6086 .flags = GENL_ADMIN_PERM,
6087 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6088 DEVLINK_NL_FLAG_NO_LOCK,
6089 },
6090 {
6091 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
6092 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6093 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
6094 .flags = GENL_ADMIN_PERM,
6095 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6096 DEVLINK_NL_FLAG_NO_LOCK,
6097 },
6098 {
6099 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
6100 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6101 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
6102 .flags = GENL_ADMIN_PERM,
6103 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6104 DEVLINK_NL_FLAG_NO_LOCK,
6105 },
6106 {
6107 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
6108 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6109 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
6110 .flags = GENL_ADMIN_PERM,
6111 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6112 DEVLINK_NL_FLAG_NO_LOCK,
6113 },
6114 {
6115 .cmd = DEVLINK_CMD_FLASH_UPDATE,
6116 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6117 .doit = devlink_nl_cmd_flash_update,
6118 .flags = GENL_ADMIN_PERM,
6119 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6120 },
6121 {
6122 .cmd = DEVLINK_CMD_TRAP_GET,
6123 .doit = devlink_nl_cmd_trap_get_doit,
6124 .dumpit = devlink_nl_cmd_trap_get_dumpit,
6125 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6126
6127 },
6128 {
6129 .cmd = DEVLINK_CMD_TRAP_SET,
6130 .doit = devlink_nl_cmd_trap_set_doit,
6131 .flags = GENL_ADMIN_PERM,
6132 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6133 },
6134 {
6135 .cmd = DEVLINK_CMD_TRAP_GROUP_GET,
6136 .doit = devlink_nl_cmd_trap_group_get_doit,
6137 .dumpit = devlink_nl_cmd_trap_group_get_dumpit,
6138 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6139
6140 },
6141 {
6142 .cmd = DEVLINK_CMD_TRAP_GROUP_SET,
6143 .doit = devlink_nl_cmd_trap_group_set_doit,
6144 .flags = GENL_ADMIN_PERM,
6145 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6146 },
6147 };
6148
6149 static struct genl_family devlink_nl_family __ro_after_init = {
6150 .name = DEVLINK_GENL_NAME,
6151 .version = DEVLINK_GENL_VERSION,
6152 .maxattr = DEVLINK_ATTR_MAX,
6153 .policy = devlink_nl_policy,
6154 .netnsok = true,
6155 .pre_doit = devlink_nl_pre_doit,
6156 .post_doit = devlink_nl_post_doit,
6157 .module = THIS_MODULE,
6158 .ops = devlink_nl_ops,
6159 .n_ops = ARRAY_SIZE(devlink_nl_ops),
6160 .mcgrps = devlink_nl_mcgrps,
6161 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps),
6162 };
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173 struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
6174 {
6175 struct devlink *devlink;
6176
6177 if (WARN_ON(!ops))
6178 return NULL;
6179
6180 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
6181 if (!devlink)
6182 return NULL;
6183 devlink->ops = ops;
6184 devlink_net_set(devlink, &init_net);
6185 INIT_LIST_HEAD(&devlink->port_list);
6186 INIT_LIST_HEAD(&devlink->sb_list);
6187 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
6188 INIT_LIST_HEAD(&devlink->resource_list);
6189 INIT_LIST_HEAD(&devlink->param_list);
6190 INIT_LIST_HEAD(&devlink->region_list);
6191 INIT_LIST_HEAD(&devlink->reporter_list);
6192 INIT_LIST_HEAD(&devlink->trap_list);
6193 INIT_LIST_HEAD(&devlink->trap_group_list);
6194 mutex_init(&devlink->lock);
6195 mutex_init(&devlink->reporters_lock);
6196 return devlink;
6197 }
6198 EXPORT_SYMBOL_GPL(devlink_alloc);
6199
6200
6201
6202
6203
6204
6205
6206 int devlink_register(struct devlink *devlink, struct device *dev)
6207 {
6208 mutex_lock(&devlink_mutex);
6209 devlink->dev = dev;
6210 list_add_tail(&devlink->list, &devlink_list);
6211 devlink_notify(devlink, DEVLINK_CMD_NEW);
6212 mutex_unlock(&devlink_mutex);
6213 return 0;
6214 }
6215 EXPORT_SYMBOL_GPL(devlink_register);
6216
6217
6218
6219
6220
6221
6222 void devlink_unregister(struct devlink *devlink)
6223 {
6224 mutex_lock(&devlink_mutex);
6225 WARN_ON(devlink_reload_supported(devlink) &&
6226 devlink->reload_enabled);
6227 devlink_notify(devlink, DEVLINK_CMD_DEL);
6228 list_del(&devlink->list);
6229 mutex_unlock(&devlink_mutex);
6230 }
6231 EXPORT_SYMBOL_GPL(devlink_unregister);
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241 void devlink_reload_enable(struct devlink *devlink)
6242 {
6243 mutex_lock(&devlink_mutex);
6244 devlink->reload_enabled = true;
6245 mutex_unlock(&devlink_mutex);
6246 }
6247 EXPORT_SYMBOL_GPL(devlink_reload_enable);
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257 void devlink_reload_disable(struct devlink *devlink)
6258 {
6259 mutex_lock(&devlink_mutex);
6260
6261
6262
6263 devlink->reload_enabled = false;
6264 mutex_unlock(&devlink_mutex);
6265 }
6266 EXPORT_SYMBOL_GPL(devlink_reload_disable);
6267
6268
6269
6270
6271
6272
6273 void devlink_free(struct devlink *devlink)
6274 {
6275 mutex_destroy(&devlink->reporters_lock);
6276 mutex_destroy(&devlink->lock);
6277 WARN_ON(!list_empty(&devlink->trap_group_list));
6278 WARN_ON(!list_empty(&devlink->trap_list));
6279 WARN_ON(!list_empty(&devlink->reporter_list));
6280 WARN_ON(!list_empty(&devlink->region_list));
6281 WARN_ON(!list_empty(&devlink->param_list));
6282 WARN_ON(!list_empty(&devlink->resource_list));
6283 WARN_ON(!list_empty(&devlink->dpipe_table_list));
6284 WARN_ON(!list_empty(&devlink->sb_list));
6285 WARN_ON(!list_empty(&devlink->port_list));
6286
6287 kfree(devlink);
6288 }
6289 EXPORT_SYMBOL_GPL(devlink_free);
6290
6291 static void devlink_port_type_warn(struct work_struct *work)
6292 {
6293 WARN(true, "Type was not set for devlink port.");
6294 }
6295
6296 static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
6297 {
6298
6299 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
6300 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA;
6301 }
6302
6303 #define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
6304
6305 static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
6306 {
6307 if (!devlink_port_type_should_warn(devlink_port))
6308 return;
6309
6310
6311
6312 schedule_delayed_work(&devlink_port->type_warn_dw,
6313 DEVLINK_PORT_TYPE_WARN_TIMEOUT);
6314 }
6315
6316 static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
6317 {
6318 if (!devlink_port_type_should_warn(devlink_port))
6319 return;
6320 cancel_delayed_work_sync(&devlink_port->type_warn_dw);
6321 }
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336 int devlink_port_register(struct devlink *devlink,
6337 struct devlink_port *devlink_port,
6338 unsigned int port_index)
6339 {
6340 mutex_lock(&devlink->lock);
6341 if (devlink_port_index_exists(devlink, port_index)) {
6342 mutex_unlock(&devlink->lock);
6343 return -EEXIST;
6344 }
6345 devlink_port->devlink = devlink;
6346 devlink_port->index = port_index;
6347 devlink_port->registered = true;
6348 spin_lock_init(&devlink_port->type_lock);
6349 list_add_tail(&devlink_port->list, &devlink->port_list);
6350 INIT_LIST_HEAD(&devlink_port->param_list);
6351 mutex_unlock(&devlink->lock);
6352 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
6353 devlink_port_type_warn_schedule(devlink_port);
6354 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
6355 return 0;
6356 }
6357 EXPORT_SYMBOL_GPL(devlink_port_register);
6358
6359
6360
6361
6362
6363
6364 void devlink_port_unregister(struct devlink_port *devlink_port)
6365 {
6366 struct devlink *devlink = devlink_port->devlink;
6367
6368 devlink_port_type_warn_cancel(devlink_port);
6369 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
6370 mutex_lock(&devlink->lock);
6371 list_del(&devlink_port->list);
6372 mutex_unlock(&devlink->lock);
6373 }
6374 EXPORT_SYMBOL_GPL(devlink_port_unregister);
6375
6376 static void __devlink_port_type_set(struct devlink_port *devlink_port,
6377 enum devlink_port_type type,
6378 void *type_dev)
6379 {
6380 if (WARN_ON(!devlink_port->registered))
6381 return;
6382 devlink_port_type_warn_cancel(devlink_port);
6383 spin_lock_bh(&devlink_port->type_lock);
6384 devlink_port->type = type;
6385 devlink_port->type_dev = type_dev;
6386 spin_unlock_bh(&devlink_port->type_lock);
6387 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
6388 }
6389
6390
6391
6392
6393
6394
6395
6396 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
6397 struct net_device *netdev)
6398 {
6399 const struct net_device_ops *ops = netdev->netdev_ops;
6400
6401
6402
6403
6404
6405 if (ops->ndo_get_phys_port_name) {
6406
6407
6408
6409
6410
6411
6412 char name[IFNAMSIZ];
6413 int err;
6414
6415 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
6416 WARN_ON(err != -EOPNOTSUPP);
6417 }
6418 if (ops->ndo_get_port_parent_id) {
6419
6420
6421
6422
6423
6424
6425 struct netdev_phys_item_id ppid;
6426 int err;
6427
6428 err = ops->ndo_get_port_parent_id(netdev, &ppid);
6429 WARN_ON(err != -EOPNOTSUPP);
6430 }
6431 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
6432 }
6433 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
6434
6435
6436
6437
6438
6439
6440
6441 void devlink_port_type_ib_set(struct devlink_port *devlink_port,
6442 struct ib_device *ibdev)
6443 {
6444 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
6445 }
6446 EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
6447
6448
6449
6450
6451
6452
6453 void devlink_port_type_clear(struct devlink_port *devlink_port)
6454 {
6455 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
6456 devlink_port_type_warn_schedule(devlink_port);
6457 }
6458 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
6459
6460 static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
6461 enum devlink_port_flavour flavour,
6462 const unsigned char *switch_id,
6463 unsigned char switch_id_len)
6464 {
6465 struct devlink_port_attrs *attrs = &devlink_port->attrs;
6466
6467 if (WARN_ON(devlink_port->registered))
6468 return -EEXIST;
6469 attrs->set = true;
6470 attrs->flavour = flavour;
6471 if (switch_id) {
6472 attrs->switch_port = true;
6473 if (WARN_ON(switch_id_len > MAX_PHYS_ITEM_ID_LEN))
6474 switch_id_len = MAX_PHYS_ITEM_ID_LEN;
6475 memcpy(attrs->switch_id.id, switch_id, switch_id_len);
6476 attrs->switch_id.id_len = switch_id_len;
6477 } else {
6478 attrs->switch_port = false;
6479 }
6480 return 0;
6481 }
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497 void devlink_port_attrs_set(struct devlink_port *devlink_port,
6498 enum devlink_port_flavour flavour,
6499 u32 port_number, bool split,
6500 u32 split_subport_number,
6501 const unsigned char *switch_id,
6502 unsigned char switch_id_len)
6503 {
6504 struct devlink_port_attrs *attrs = &devlink_port->attrs;
6505 int ret;
6506
6507 ret = __devlink_port_attrs_set(devlink_port, flavour,
6508 switch_id, switch_id_len);
6509 if (ret)
6510 return;
6511 attrs->split = split;
6512 attrs->phys.port_number = port_number;
6513 attrs->phys.split_subport_number = split_subport_number;
6514 }
6515 EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526 void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port,
6527 const unsigned char *switch_id,
6528 unsigned char switch_id_len, u16 pf)
6529 {
6530 struct devlink_port_attrs *attrs = &devlink_port->attrs;
6531 int ret;
6532
6533 ret = __devlink_port_attrs_set(devlink_port,
6534 DEVLINK_PORT_FLAVOUR_PCI_PF,
6535 switch_id, switch_id_len);
6536 if (ret)
6537 return;
6538
6539 attrs->pci_pf.pf = pf;
6540 }
6541 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553 void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
6554 const unsigned char *switch_id,
6555 unsigned char switch_id_len,
6556 u16 pf, u16 vf)
6557 {
6558 struct devlink_port_attrs *attrs = &devlink_port->attrs;
6559 int ret;
6560
6561 ret = __devlink_port_attrs_set(devlink_port,
6562 DEVLINK_PORT_FLAVOUR_PCI_VF,
6563 switch_id, switch_id_len);
6564 if (ret)
6565 return;
6566 attrs->pci_vf.pf = pf;
6567 attrs->pci_vf.vf = vf;
6568 }
6569 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
6570
6571 static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
6572 char *name, size_t len)
6573 {
6574 struct devlink_port_attrs *attrs = &devlink_port->attrs;
6575 int n = 0;
6576
6577 if (!attrs->set)
6578 return -EOPNOTSUPP;
6579
6580 switch (attrs->flavour) {
6581 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
6582 if (!attrs->split)
6583 n = snprintf(name, len, "p%u", attrs->phys.port_number);
6584 else
6585 n = snprintf(name, len, "p%us%u",
6586 attrs->phys.port_number,
6587 attrs->phys.split_subport_number);
6588 break;
6589 case DEVLINK_PORT_FLAVOUR_CPU:
6590 case DEVLINK_PORT_FLAVOUR_DSA:
6591
6592
6593
6594 WARN_ON(1);
6595 return -EINVAL;
6596 case DEVLINK_PORT_FLAVOUR_PCI_PF:
6597 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
6598 break;
6599 case DEVLINK_PORT_FLAVOUR_PCI_VF:
6600 n = snprintf(name, len, "pf%uvf%u",
6601 attrs->pci_vf.pf, attrs->pci_vf.vf);
6602 break;
6603 }
6604
6605 if (n >= len)
6606 return -EINVAL;
6607
6608 return 0;
6609 }
6610
6611 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
6612 u32 size, u16 ingress_pools_count,
6613 u16 egress_pools_count, u16 ingress_tc_count,
6614 u16 egress_tc_count)
6615 {
6616 struct devlink_sb *devlink_sb;
6617 int err = 0;
6618
6619 mutex_lock(&devlink->lock);
6620 if (devlink_sb_index_exists(devlink, sb_index)) {
6621 err = -EEXIST;
6622 goto unlock;
6623 }
6624
6625 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
6626 if (!devlink_sb) {
6627 err = -ENOMEM;
6628 goto unlock;
6629 }
6630 devlink_sb->index = sb_index;
6631 devlink_sb->size = size;
6632 devlink_sb->ingress_pools_count = ingress_pools_count;
6633 devlink_sb->egress_pools_count = egress_pools_count;
6634 devlink_sb->ingress_tc_count = ingress_tc_count;
6635 devlink_sb->egress_tc_count = egress_tc_count;
6636 list_add_tail(&devlink_sb->list, &devlink->sb_list);
6637 unlock:
6638 mutex_unlock(&devlink->lock);
6639 return err;
6640 }
6641 EXPORT_SYMBOL_GPL(devlink_sb_register);
6642
6643 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
6644 {
6645 struct devlink_sb *devlink_sb;
6646
6647 mutex_lock(&devlink->lock);
6648 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
6649 WARN_ON(!devlink_sb);
6650 list_del(&devlink_sb->list);
6651 mutex_unlock(&devlink->lock);
6652 kfree(devlink_sb);
6653 }
6654 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664 int devlink_dpipe_headers_register(struct devlink *devlink,
6665 struct devlink_dpipe_headers *dpipe_headers)
6666 {
6667 mutex_lock(&devlink->lock);
6668 devlink->dpipe_headers = dpipe_headers;
6669 mutex_unlock(&devlink->lock);
6670 return 0;
6671 }
6672 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
6673
6674
6675
6676
6677
6678
6679
6680
6681 void devlink_dpipe_headers_unregister(struct devlink *devlink)
6682 {
6683 mutex_lock(&devlink->lock);
6684 devlink->dpipe_headers = NULL;
6685 mutex_unlock(&devlink->lock);
6686 }
6687 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703 bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
6704 const char *table_name)
6705 {
6706 struct devlink_dpipe_table *table;
6707 bool enabled;
6708
6709 rcu_read_lock();
6710 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6711 table_name);
6712 enabled = false;
6713 if (table)
6714 enabled = table->counters_enabled;
6715 rcu_read_unlock();
6716 return enabled;
6717 }
6718 EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729 int devlink_dpipe_table_register(struct devlink *devlink,
6730 const char *table_name,
6731 struct devlink_dpipe_table_ops *table_ops,
6732 void *priv, bool counter_control_extern)
6733 {
6734 struct devlink_dpipe_table *table;
6735
6736 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
6737 return -EEXIST;
6738
6739 if (WARN_ON(!table_ops->size_get))
6740 return -EINVAL;
6741
6742 table = kzalloc(sizeof(*table), GFP_KERNEL);
6743 if (!table)
6744 return -ENOMEM;
6745
6746 table->name = table_name;
6747 table->table_ops = table_ops;
6748 table->priv = priv;
6749 table->counter_control_extern = counter_control_extern;
6750
6751 mutex_lock(&devlink->lock);
6752 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
6753 mutex_unlock(&devlink->lock);
6754 return 0;
6755 }
6756 EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
6757
6758
6759
6760
6761
6762
6763
6764 void devlink_dpipe_table_unregister(struct devlink *devlink,
6765 const char *table_name)
6766 {
6767 struct devlink_dpipe_table *table;
6768
6769 mutex_lock(&devlink->lock);
6770 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6771 table_name);
6772 if (!table)
6773 goto unlock;
6774 list_del_rcu(&table->list);
6775 mutex_unlock(&devlink->lock);
6776 kfree_rcu(table, rcu);
6777 return;
6778 unlock:
6779 mutex_unlock(&devlink->lock);
6780 }
6781 EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793 int devlink_resource_register(struct devlink *devlink,
6794 const char *resource_name,
6795 u64 resource_size,
6796 u64 resource_id,
6797 u64 parent_resource_id,
6798 const struct devlink_resource_size_params *size_params)
6799 {
6800 struct devlink_resource *resource;
6801 struct list_head *resource_list;
6802 bool top_hierarchy;
6803 int err = 0;
6804
6805 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
6806
6807 mutex_lock(&devlink->lock);
6808 resource = devlink_resource_find(devlink, NULL, resource_id);
6809 if (resource) {
6810 err = -EINVAL;
6811 goto out;
6812 }
6813
6814 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
6815 if (!resource) {
6816 err = -ENOMEM;
6817 goto out;
6818 }
6819
6820 if (top_hierarchy) {
6821 resource_list = &devlink->resource_list;
6822 } else {
6823 struct devlink_resource *parent_resource;
6824
6825 parent_resource = devlink_resource_find(devlink, NULL,
6826 parent_resource_id);
6827 if (parent_resource) {
6828 resource_list = &parent_resource->resource_list;
6829 resource->parent = parent_resource;
6830 } else {
6831 kfree(resource);
6832 err = -EINVAL;
6833 goto out;
6834 }
6835 }
6836
6837 resource->name = resource_name;
6838 resource->size = resource_size;
6839 resource->size_new = resource_size;
6840 resource->id = resource_id;
6841 resource->size_valid = true;
6842 memcpy(&resource->size_params, size_params,
6843 sizeof(resource->size_params));
6844 INIT_LIST_HEAD(&resource->resource_list);
6845 list_add_tail(&resource->list, resource_list);
6846 out:
6847 mutex_unlock(&devlink->lock);
6848 return err;
6849 }
6850 EXPORT_SYMBOL_GPL(devlink_resource_register);
6851
6852
6853
6854
6855
6856
6857
6858 void devlink_resources_unregister(struct devlink *devlink,
6859 struct devlink_resource *resource)
6860 {
6861 struct devlink_resource *tmp, *child_resource;
6862 struct list_head *resource_list;
6863
6864 if (resource)
6865 resource_list = &resource->resource_list;
6866 else
6867 resource_list = &devlink->resource_list;
6868
6869 if (!resource)
6870 mutex_lock(&devlink->lock);
6871
6872 list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
6873 devlink_resources_unregister(devlink, child_resource);
6874 list_del(&child_resource->list);
6875 kfree(child_resource);
6876 }
6877
6878 if (!resource)
6879 mutex_unlock(&devlink->lock);
6880 }
6881 EXPORT_SYMBOL_GPL(devlink_resources_unregister);
6882
6883
6884
6885
6886
6887
6888
6889
6890 int devlink_resource_size_get(struct devlink *devlink,
6891 u64 resource_id,
6892 u64 *p_resource_size)
6893 {
6894 struct devlink_resource *resource;
6895 int err = 0;
6896
6897 mutex_lock(&devlink->lock);
6898 resource = devlink_resource_find(devlink, NULL, resource_id);
6899 if (!resource) {
6900 err = -EINVAL;
6901 goto out;
6902 }
6903 *p_resource_size = resource->size_new;
6904 resource->size = resource->size_new;
6905 out:
6906 mutex_unlock(&devlink->lock);
6907 return err;
6908 }
6909 EXPORT_SYMBOL_GPL(devlink_resource_size_get);
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919 int devlink_dpipe_table_resource_set(struct devlink *devlink,
6920 const char *table_name, u64 resource_id,
6921 u64 resource_units)
6922 {
6923 struct devlink_dpipe_table *table;
6924 int err = 0;
6925
6926 mutex_lock(&devlink->lock);
6927 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6928 table_name);
6929 if (!table) {
6930 err = -EINVAL;
6931 goto out;
6932 }
6933 table->resource_id = resource_id;
6934 table->resource_units = resource_units;
6935 table->resource_valid = true;
6936 out:
6937 mutex_unlock(&devlink->lock);
6938 return err;
6939 }
6940 EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950 void devlink_resource_occ_get_register(struct devlink *devlink,
6951 u64 resource_id,
6952 devlink_resource_occ_get_t *occ_get,
6953 void *occ_get_priv)
6954 {
6955 struct devlink_resource *resource;
6956
6957 mutex_lock(&devlink->lock);
6958 resource = devlink_resource_find(devlink, NULL, resource_id);
6959 if (WARN_ON(!resource))
6960 goto out;
6961 WARN_ON(resource->occ_get);
6962
6963 resource->occ_get = occ_get;
6964 resource->occ_get_priv = occ_get_priv;
6965 out:
6966 mutex_unlock(&devlink->lock);
6967 }
6968 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
6969
6970
6971
6972
6973
6974
6975
6976 void devlink_resource_occ_get_unregister(struct devlink *devlink,
6977 u64 resource_id)
6978 {
6979 struct devlink_resource *resource;
6980
6981 mutex_lock(&devlink->lock);
6982 resource = devlink_resource_find(devlink, NULL, resource_id);
6983 if (WARN_ON(!resource))
6984 goto out;
6985 WARN_ON(!resource->occ_get);
6986
6987 resource->occ_get = NULL;
6988 resource->occ_get_priv = NULL;
6989 out:
6990 mutex_unlock(&devlink->lock);
6991 }
6992 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
6993
6994 static int devlink_param_verify(const struct devlink_param *param)
6995 {
6996 if (!param || !param->name || !param->supported_cmodes)
6997 return -EINVAL;
6998 if (param->generic)
6999 return devlink_param_generic_verify(param);
7000 else
7001 return devlink_param_driver_verify(param);
7002 }
7003
7004 static int __devlink_params_register(struct devlink *devlink,
7005 unsigned int port_index,
7006 struct list_head *param_list,
7007 const struct devlink_param *params,
7008 size_t params_count,
7009 enum devlink_command reg_cmd,
7010 enum devlink_command unreg_cmd)
7011 {
7012 const struct devlink_param *param = params;
7013 int i;
7014 int err;
7015
7016 mutex_lock(&devlink->lock);
7017 for (i = 0; i < params_count; i++, param++) {
7018 err = devlink_param_verify(param);
7019 if (err)
7020 goto rollback;
7021
7022 err = devlink_param_register_one(devlink, port_index,
7023 param_list, param, reg_cmd);
7024 if (err)
7025 goto rollback;
7026 }
7027
7028 mutex_unlock(&devlink->lock);
7029 return 0;
7030
7031 rollback:
7032 if (!i)
7033 goto unlock;
7034 for (param--; i > 0; i--, param--)
7035 devlink_param_unregister_one(devlink, port_index, param_list,
7036 param, unreg_cmd);
7037 unlock:
7038 mutex_unlock(&devlink->lock);
7039 return err;
7040 }
7041
7042 static void __devlink_params_unregister(struct devlink *devlink,
7043 unsigned int port_index,
7044 struct list_head *param_list,
7045 const struct devlink_param *params,
7046 size_t params_count,
7047 enum devlink_command cmd)
7048 {
7049 const struct devlink_param *param = params;
7050 int i;
7051
7052 mutex_lock(&devlink->lock);
7053 for (i = 0; i < params_count; i++, param++)
7054 devlink_param_unregister_one(devlink, 0, param_list, param,
7055 cmd);
7056 mutex_unlock(&devlink->lock);
7057 }
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068 int devlink_params_register(struct devlink *devlink,
7069 const struct devlink_param *params,
7070 size_t params_count)
7071 {
7072 return __devlink_params_register(devlink, 0, &devlink->param_list,
7073 params, params_count,
7074 DEVLINK_CMD_PARAM_NEW,
7075 DEVLINK_CMD_PARAM_DEL);
7076 }
7077 EXPORT_SYMBOL_GPL(devlink_params_register);
7078
7079
7080
7081
7082
7083
7084
7085 void devlink_params_unregister(struct devlink *devlink,
7086 const struct devlink_param *params,
7087 size_t params_count)
7088 {
7089 return __devlink_params_unregister(devlink, 0, &devlink->param_list,
7090 params, params_count,
7091 DEVLINK_CMD_PARAM_DEL);
7092 }
7093 EXPORT_SYMBOL_GPL(devlink_params_unregister);
7094
7095
7096
7097
7098
7099
7100
7101
7102 void devlink_params_publish(struct devlink *devlink)
7103 {
7104 struct devlink_param_item *param_item;
7105
7106 list_for_each_entry(param_item, &devlink->param_list, list) {
7107 if (param_item->published)
7108 continue;
7109 param_item->published = true;
7110 devlink_param_notify(devlink, 0, param_item,
7111 DEVLINK_CMD_PARAM_NEW);
7112 }
7113 }
7114 EXPORT_SYMBOL_GPL(devlink_params_publish);
7115
7116
7117
7118
7119
7120
7121
7122
7123 void devlink_params_unpublish(struct devlink *devlink)
7124 {
7125 struct devlink_param_item *param_item;
7126
7127 list_for_each_entry(param_item, &devlink->param_list, list) {
7128 if (!param_item->published)
7129 continue;
7130 param_item->published = false;
7131 devlink_param_notify(devlink, 0, param_item,
7132 DEVLINK_CMD_PARAM_DEL);
7133 }
7134 }
7135 EXPORT_SYMBOL_GPL(devlink_params_unpublish);
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146 int devlink_port_params_register(struct devlink_port *devlink_port,
7147 const struct devlink_param *params,
7148 size_t params_count)
7149 {
7150 return __devlink_params_register(devlink_port->devlink,
7151 devlink_port->index,
7152 &devlink_port->param_list, params,
7153 params_count,
7154 DEVLINK_CMD_PORT_PARAM_NEW,
7155 DEVLINK_CMD_PORT_PARAM_DEL);
7156 }
7157 EXPORT_SYMBOL_GPL(devlink_port_params_register);
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167 void devlink_port_params_unregister(struct devlink_port *devlink_port,
7168 const struct devlink_param *params,
7169 size_t params_count)
7170 {
7171 return __devlink_params_unregister(devlink_port->devlink,
7172 devlink_port->index,
7173 &devlink_port->param_list,
7174 params, params_count,
7175 DEVLINK_CMD_PORT_PARAM_DEL);
7176 }
7177 EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
7178
7179 static int
7180 __devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id,
7181 union devlink_param_value *init_val)
7182 {
7183 struct devlink_param_item *param_item;
7184
7185 param_item = devlink_param_find_by_id(param_list, param_id);
7186 if (!param_item)
7187 return -EINVAL;
7188
7189 if (!param_item->driverinit_value_valid ||
7190 !devlink_param_cmode_is_supported(param_item->param,
7191 DEVLINK_PARAM_CMODE_DRIVERINIT))
7192 return -EOPNOTSUPP;
7193
7194 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
7195 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
7196 else
7197 *init_val = param_item->driverinit_value;
7198
7199 return 0;
7200 }
7201
7202 static int
7203 __devlink_param_driverinit_value_set(struct devlink *devlink,
7204 unsigned int port_index,
7205 struct list_head *param_list, u32 param_id,
7206 union devlink_param_value init_val,
7207 enum devlink_command cmd)
7208 {
7209 struct devlink_param_item *param_item;
7210
7211 param_item = devlink_param_find_by_id(param_list, param_id);
7212 if (!param_item)
7213 return -EINVAL;
7214
7215 if (!devlink_param_cmode_is_supported(param_item->param,
7216 DEVLINK_PARAM_CMODE_DRIVERINIT))
7217 return -EOPNOTSUPP;
7218
7219 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
7220 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
7221 else
7222 param_item->driverinit_value = init_val;
7223 param_item->driverinit_value_valid = true;
7224
7225 devlink_param_notify(devlink, port_index, param_item, cmd);
7226 return 0;
7227 }
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240 int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
7241 union devlink_param_value *init_val)
7242 {
7243 if (!devlink_reload_supported(devlink))
7244 return -EOPNOTSUPP;
7245
7246 return __devlink_param_driverinit_value_get(&devlink->param_list,
7247 param_id, init_val);
7248 }
7249 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263 int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
7264 union devlink_param_value init_val)
7265 {
7266 return __devlink_param_driverinit_value_set(devlink, 0,
7267 &devlink->param_list,
7268 param_id, init_val,
7269 DEVLINK_CMD_PARAM_NEW);
7270 }
7271 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284 int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
7285 u32 param_id,
7286 union devlink_param_value *init_val)
7287 {
7288 struct devlink *devlink = devlink_port->devlink;
7289
7290 if (!devlink_reload_supported(devlink))
7291 return -EOPNOTSUPP;
7292
7293 return __devlink_param_driverinit_value_get(&devlink_port->param_list,
7294 param_id, init_val);
7295 }
7296 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get);
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310 int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port,
7311 u32 param_id,
7312 union devlink_param_value init_val)
7313 {
7314 return __devlink_param_driverinit_value_set(devlink_port->devlink,
7315 devlink_port->index,
7316 &devlink_port->param_list,
7317 param_id, init_val,
7318 DEVLINK_CMD_PORT_PARAM_NEW);
7319 }
7320 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set);
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334 void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
7335 {
7336 struct devlink_param_item *param_item;
7337
7338 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
7339 WARN_ON(!param_item);
7340
7341 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
7342 }
7343 EXPORT_SYMBOL_GPL(devlink_param_value_changed);
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358 void devlink_port_param_value_changed(struct devlink_port *devlink_port,
7359 u32 param_id)
7360 {
7361 struct devlink_param_item *param_item;
7362
7363 param_item = devlink_param_find_by_id(&devlink_port->param_list,
7364 param_id);
7365 WARN_ON(!param_item);
7366
7367 devlink_param_notify(devlink_port->devlink, devlink_port->index,
7368 param_item, DEVLINK_CMD_PORT_PARAM_NEW);
7369 }
7370 EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
7371
7372
7373
7374
7375
7376
7377
7378
7379 void devlink_param_value_str_fill(union devlink_param_value *dst_val,
7380 const char *src)
7381 {
7382 size_t len;
7383
7384 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
7385 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
7386 }
7387 EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397 struct devlink_region *devlink_region_create(struct devlink *devlink,
7398 const char *region_name,
7399 u32 region_max_snapshots,
7400 u64 region_size)
7401 {
7402 struct devlink_region *region;
7403 int err = 0;
7404
7405 mutex_lock(&devlink->lock);
7406
7407 if (devlink_region_get_by_name(devlink, region_name)) {
7408 err = -EEXIST;
7409 goto unlock;
7410 }
7411
7412 region = kzalloc(sizeof(*region), GFP_KERNEL);
7413 if (!region) {
7414 err = -ENOMEM;
7415 goto unlock;
7416 }
7417
7418 region->devlink = devlink;
7419 region->max_snapshots = region_max_snapshots;
7420 region->name = region_name;
7421 region->size = region_size;
7422 INIT_LIST_HEAD(®ion->snapshot_list);
7423 list_add_tail(®ion->list, &devlink->region_list);
7424 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
7425
7426 mutex_unlock(&devlink->lock);
7427 return region;
7428
7429 unlock:
7430 mutex_unlock(&devlink->lock);
7431 return ERR_PTR(err);
7432 }
7433 EXPORT_SYMBOL_GPL(devlink_region_create);
7434
7435
7436
7437
7438
7439
7440 void devlink_region_destroy(struct devlink_region *region)
7441 {
7442 struct devlink *devlink = region->devlink;
7443 struct devlink_snapshot *snapshot, *ts;
7444
7445 mutex_lock(&devlink->lock);
7446
7447
7448 list_for_each_entry_safe(snapshot, ts, ®ion->snapshot_list, list)
7449 devlink_region_snapshot_del(region, snapshot);
7450
7451 list_del(®ion->list);
7452
7453 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
7454 mutex_unlock(&devlink->lock);
7455 kfree(region);
7456 }
7457 EXPORT_SYMBOL_GPL(devlink_region_destroy);
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468 u32 devlink_region_shapshot_id_get(struct devlink *devlink)
7469 {
7470 u32 id;
7471
7472 mutex_lock(&devlink->lock);
7473 id = ++devlink->snapshot_id;
7474 mutex_unlock(&devlink->lock);
7475
7476 return id;
7477 }
7478 EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get);
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493 int devlink_region_snapshot_create(struct devlink_region *region,
7494 u8 *data, u32 snapshot_id,
7495 devlink_snapshot_data_dest_t *data_destructor)
7496 {
7497 struct devlink *devlink = region->devlink;
7498 struct devlink_snapshot *snapshot;
7499 int err;
7500
7501 mutex_lock(&devlink->lock);
7502
7503
7504 if (region->cur_snapshots == region->max_snapshots) {
7505 err = -ENOMEM;
7506 goto unlock;
7507 }
7508
7509 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
7510 err = -EEXIST;
7511 goto unlock;
7512 }
7513
7514 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
7515 if (!snapshot) {
7516 err = -ENOMEM;
7517 goto unlock;
7518 }
7519
7520 snapshot->id = snapshot_id;
7521 snapshot->region = region;
7522 snapshot->data = data;
7523 snapshot->data_destructor = data_destructor;
7524
7525 list_add_tail(&snapshot->list, ®ion->snapshot_list);
7526
7527 region->cur_snapshots++;
7528
7529 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
7530 mutex_unlock(&devlink->lock);
7531 return 0;
7532
7533 unlock:
7534 mutex_unlock(&devlink->lock);
7535 return err;
7536 }
7537 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
7538
7539 #define DEVLINK_TRAP(_id, _type) \
7540 { \
7541 .type = DEVLINK_TRAP_TYPE_##_type, \
7542 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \
7543 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \
7544 }
7545
7546 static const struct devlink_trap devlink_trap_generic[] = {
7547 DEVLINK_TRAP(SMAC_MC, DROP),
7548 DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
7549 DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
7550 DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
7551 DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
7552 DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
7553 DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
7554 DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
7555 DEVLINK_TRAP(TAIL_DROP, DROP),
7556 };
7557
7558 #define DEVLINK_TRAP_GROUP(_id) \
7559 { \
7560 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \
7561 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \
7562 }
7563
7564 static const struct devlink_trap_group devlink_trap_group_generic[] = {
7565 DEVLINK_TRAP_GROUP(L2_DROPS),
7566 DEVLINK_TRAP_GROUP(L3_DROPS),
7567 DEVLINK_TRAP_GROUP(BUFFER_DROPS),
7568 };
7569
7570 static int devlink_trap_generic_verify(const struct devlink_trap *trap)
7571 {
7572 if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
7573 return -EINVAL;
7574
7575 if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
7576 return -EINVAL;
7577
7578 if (trap->type != devlink_trap_generic[trap->id].type)
7579 return -EINVAL;
7580
7581 return 0;
7582 }
7583
7584 static int devlink_trap_driver_verify(const struct devlink_trap *trap)
7585 {
7586 int i;
7587
7588 if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
7589 return -EINVAL;
7590
7591 for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
7592 if (!strcmp(trap->name, devlink_trap_generic[i].name))
7593 return -EEXIST;
7594 }
7595
7596 return 0;
7597 }
7598
7599 static int devlink_trap_verify(const struct devlink_trap *trap)
7600 {
7601 if (!trap || !trap->name || !trap->group.name)
7602 return -EINVAL;
7603
7604 if (trap->generic)
7605 return devlink_trap_generic_verify(trap);
7606 else
7607 return devlink_trap_driver_verify(trap);
7608 }
7609
7610 static int
7611 devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
7612 {
7613 if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
7614 return -EINVAL;
7615
7616 if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
7617 return -EINVAL;
7618
7619 return 0;
7620 }
7621
7622 static int
7623 devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
7624 {
7625 int i;
7626
7627 if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
7628 return -EINVAL;
7629
7630 for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
7631 if (!strcmp(group->name, devlink_trap_group_generic[i].name))
7632 return -EEXIST;
7633 }
7634
7635 return 0;
7636 }
7637
7638 static int devlink_trap_group_verify(const struct devlink_trap_group *group)
7639 {
7640 if (group->generic)
7641 return devlink_trap_group_generic_verify(group);
7642 else
7643 return devlink_trap_group_driver_verify(group);
7644 }
7645
7646 static void
7647 devlink_trap_group_notify(struct devlink *devlink,
7648 const struct devlink_trap_group_item *group_item,
7649 enum devlink_command cmd)
7650 {
7651 struct sk_buff *msg;
7652 int err;
7653
7654 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
7655 cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
7656
7657 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7658 if (!msg)
7659 return;
7660
7661 err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
7662 0);
7663 if (err) {
7664 nlmsg_free(msg);
7665 return;
7666 }
7667
7668 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
7669 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
7670 }
7671
7672 static struct devlink_trap_group_item *
7673 devlink_trap_group_item_create(struct devlink *devlink,
7674 const struct devlink_trap_group *group)
7675 {
7676 struct devlink_trap_group_item *group_item;
7677 int err;
7678
7679 err = devlink_trap_group_verify(group);
7680 if (err)
7681 return ERR_PTR(err);
7682
7683 group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
7684 if (!group_item)
7685 return ERR_PTR(-ENOMEM);
7686
7687 group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
7688 if (!group_item->stats) {
7689 err = -ENOMEM;
7690 goto err_stats_alloc;
7691 }
7692
7693 group_item->group = group;
7694 refcount_set(&group_item->refcount, 1);
7695
7696 if (devlink->ops->trap_group_init) {
7697 err = devlink->ops->trap_group_init(devlink, group);
7698 if (err)
7699 goto err_group_init;
7700 }
7701
7702 list_add_tail(&group_item->list, &devlink->trap_group_list);
7703 devlink_trap_group_notify(devlink, group_item,
7704 DEVLINK_CMD_TRAP_GROUP_NEW);
7705
7706 return group_item;
7707
7708 err_group_init:
7709 free_percpu(group_item->stats);
7710 err_stats_alloc:
7711 kfree(group_item);
7712 return ERR_PTR(err);
7713 }
7714
7715 static void
7716 devlink_trap_group_item_destroy(struct devlink *devlink,
7717 struct devlink_trap_group_item *group_item)
7718 {
7719 devlink_trap_group_notify(devlink, group_item,
7720 DEVLINK_CMD_TRAP_GROUP_DEL);
7721 list_del(&group_item->list);
7722 free_percpu(group_item->stats);
7723 kfree(group_item);
7724 }
7725
7726 static struct devlink_trap_group_item *
7727 devlink_trap_group_item_get(struct devlink *devlink,
7728 const struct devlink_trap_group *group)
7729 {
7730 struct devlink_trap_group_item *group_item;
7731
7732 group_item = devlink_trap_group_item_lookup(devlink, group->name);
7733 if (group_item) {
7734 refcount_inc(&group_item->refcount);
7735 return group_item;
7736 }
7737
7738 return devlink_trap_group_item_create(devlink, group);
7739 }
7740
7741 static void
7742 devlink_trap_group_item_put(struct devlink *devlink,
7743 struct devlink_trap_group_item *group_item)
7744 {
7745 if (!refcount_dec_and_test(&group_item->refcount))
7746 return;
7747
7748 devlink_trap_group_item_destroy(devlink, group_item);
7749 }
7750
7751 static int
7752 devlink_trap_item_group_link(struct devlink *devlink,
7753 struct devlink_trap_item *trap_item)
7754 {
7755 struct devlink_trap_group_item *group_item;
7756
7757 group_item = devlink_trap_group_item_get(devlink,
7758 &trap_item->trap->group);
7759 if (IS_ERR(group_item))
7760 return PTR_ERR(group_item);
7761
7762 trap_item->group_item = group_item;
7763
7764 return 0;
7765 }
7766
7767 static void
7768 devlink_trap_item_group_unlink(struct devlink *devlink,
7769 struct devlink_trap_item *trap_item)
7770 {
7771 devlink_trap_group_item_put(devlink, trap_item->group_item);
7772 }
7773
7774 static void devlink_trap_notify(struct devlink *devlink,
7775 const struct devlink_trap_item *trap_item,
7776 enum devlink_command cmd)
7777 {
7778 struct sk_buff *msg;
7779 int err;
7780
7781 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
7782 cmd != DEVLINK_CMD_TRAP_DEL);
7783
7784 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7785 if (!msg)
7786 return;
7787
7788 err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
7789 if (err) {
7790 nlmsg_free(msg);
7791 return;
7792 }
7793
7794 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
7795 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
7796 }
7797
7798 static int
7799 devlink_trap_register(struct devlink *devlink,
7800 const struct devlink_trap *trap, void *priv)
7801 {
7802 struct devlink_trap_item *trap_item;
7803 int err;
7804
7805 if (devlink_trap_item_lookup(devlink, trap->name))
7806 return -EEXIST;
7807
7808 trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
7809 if (!trap_item)
7810 return -ENOMEM;
7811
7812 trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
7813 if (!trap_item->stats) {
7814 err = -ENOMEM;
7815 goto err_stats_alloc;
7816 }
7817
7818 trap_item->trap = trap;
7819 trap_item->action = trap->init_action;
7820 trap_item->priv = priv;
7821
7822 err = devlink_trap_item_group_link(devlink, trap_item);
7823 if (err)
7824 goto err_group_link;
7825
7826 err = devlink->ops->trap_init(devlink, trap, trap_item);
7827 if (err)
7828 goto err_trap_init;
7829
7830 list_add_tail(&trap_item->list, &devlink->trap_list);
7831 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
7832
7833 return 0;
7834
7835 err_trap_init:
7836 devlink_trap_item_group_unlink(devlink, trap_item);
7837 err_group_link:
7838 free_percpu(trap_item->stats);
7839 err_stats_alloc:
7840 kfree(trap_item);
7841 return err;
7842 }
7843
7844 static void devlink_trap_unregister(struct devlink *devlink,
7845 const struct devlink_trap *trap)
7846 {
7847 struct devlink_trap_item *trap_item;
7848
7849 trap_item = devlink_trap_item_lookup(devlink, trap->name);
7850 if (WARN_ON_ONCE(!trap_item))
7851 return;
7852
7853 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
7854 list_del(&trap_item->list);
7855 if (devlink->ops->trap_fini)
7856 devlink->ops->trap_fini(devlink, trap, trap_item);
7857 devlink_trap_item_group_unlink(devlink, trap_item);
7858 free_percpu(trap_item->stats);
7859 kfree(trap_item);
7860 }
7861
7862 static void devlink_trap_disable(struct devlink *devlink,
7863 const struct devlink_trap *trap)
7864 {
7865 struct devlink_trap_item *trap_item;
7866
7867 trap_item = devlink_trap_item_lookup(devlink, trap->name);
7868 if (WARN_ON_ONCE(!trap_item))
7869 return;
7870
7871 devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP);
7872 trap_item->action = DEVLINK_TRAP_ACTION_DROP;
7873 }
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884 int devlink_traps_register(struct devlink *devlink,
7885 const struct devlink_trap *traps,
7886 size_t traps_count, void *priv)
7887 {
7888 int i, err;
7889
7890 if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
7891 return -EINVAL;
7892
7893 mutex_lock(&devlink->lock);
7894 for (i = 0; i < traps_count; i++) {
7895 const struct devlink_trap *trap = &traps[i];
7896
7897 err = devlink_trap_verify(trap);
7898 if (err)
7899 goto err_trap_verify;
7900
7901 err = devlink_trap_register(devlink, trap, priv);
7902 if (err)
7903 goto err_trap_register;
7904 }
7905 mutex_unlock(&devlink->lock);
7906
7907 return 0;
7908
7909 err_trap_register:
7910 err_trap_verify:
7911 for (i--; i >= 0; i--)
7912 devlink_trap_unregister(devlink, &traps[i]);
7913 mutex_unlock(&devlink->lock);
7914 return err;
7915 }
7916 EXPORT_SYMBOL_GPL(devlink_traps_register);
7917
7918
7919
7920
7921
7922
7923
7924 void devlink_traps_unregister(struct devlink *devlink,
7925 const struct devlink_trap *traps,
7926 size_t traps_count)
7927 {
7928 int i;
7929
7930 mutex_lock(&devlink->lock);
7931
7932
7933
7934 for (i = traps_count - 1; i >= 0; i--)
7935 devlink_trap_disable(devlink, &traps[i]);
7936 synchronize_rcu();
7937 for (i = traps_count - 1; i >= 0; i--)
7938 devlink_trap_unregister(devlink, &traps[i]);
7939 mutex_unlock(&devlink->lock);
7940 }
7941 EXPORT_SYMBOL_GPL(devlink_traps_unregister);
7942
7943 static void
7944 devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
7945 size_t skb_len)
7946 {
7947 struct devlink_stats *stats;
7948
7949 stats = this_cpu_ptr(trap_stats);
7950 u64_stats_update_begin(&stats->syncp);
7951 stats->rx_bytes += skb_len;
7952 stats->rx_packets++;
7953 u64_stats_update_end(&stats->syncp);
7954 }
7955
7956 static void
7957 devlink_trap_report_metadata_fill(struct net_dm_hw_metadata *hw_metadata,
7958 const struct devlink_trap_item *trap_item,
7959 struct devlink_port *in_devlink_port)
7960 {
7961 struct devlink_trap_group_item *group_item = trap_item->group_item;
7962
7963 hw_metadata->trap_group_name = group_item->group->name;
7964 hw_metadata->trap_name = trap_item->trap->name;
7965
7966 spin_lock(&in_devlink_port->type_lock);
7967 if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
7968 hw_metadata->input_dev = in_devlink_port->type_dev;
7969 spin_unlock(&in_devlink_port->type_lock);
7970 }
7971
7972
7973
7974
7975
7976
7977
7978
7979 void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
7980 void *trap_ctx, struct devlink_port *in_devlink_port)
7981 {
7982 struct devlink_trap_item *trap_item = trap_ctx;
7983 struct net_dm_hw_metadata hw_metadata = {};
7984
7985 devlink_trap_stats_update(trap_item->stats, skb->len);
7986 devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
7987
7988 devlink_trap_report_metadata_fill(&hw_metadata, trap_item,
7989 in_devlink_port);
7990 net_dm_hw_report(skb, &hw_metadata);
7991 }
7992 EXPORT_SYMBOL_GPL(devlink_trap_report);
7993
7994
7995
7996
7997
7998
7999
8000 void *devlink_trap_ctx_priv(void *trap_ctx)
8001 {
8002 struct devlink_trap_item *trap_item = trap_ctx;
8003
8004 return trap_item->priv;
8005 }
8006 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
8007
8008 static void __devlink_compat_running_version(struct devlink *devlink,
8009 char *buf, size_t len)
8010 {
8011 const struct nlattr *nlattr;
8012 struct devlink_info_req req;
8013 struct sk_buff *msg;
8014 int rem, err;
8015
8016 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8017 if (!msg)
8018 return;
8019
8020 req.msg = msg;
8021 err = devlink->ops->info_get(devlink, &req, NULL);
8022 if (err)
8023 goto free_msg;
8024
8025 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
8026 const struct nlattr *kv;
8027 int rem_kv;
8028
8029 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
8030 continue;
8031
8032 nla_for_each_nested(kv, nlattr, rem_kv) {
8033 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
8034 continue;
8035
8036 strlcat(buf, nla_data(kv), len);
8037 strlcat(buf, " ", len);
8038 }
8039 }
8040 free_msg:
8041 nlmsg_free(msg);
8042 }
8043
8044 void devlink_compat_running_version(struct net_device *dev,
8045 char *buf, size_t len)
8046 {
8047 struct devlink *devlink;
8048
8049 dev_hold(dev);
8050 rtnl_unlock();
8051
8052 devlink = netdev_to_devlink(dev);
8053 if (!devlink || !devlink->ops->info_get)
8054 goto out;
8055
8056 mutex_lock(&devlink->lock);
8057 __devlink_compat_running_version(devlink, buf, len);
8058 mutex_unlock(&devlink->lock);
8059
8060 out:
8061 rtnl_lock();
8062 dev_put(dev);
8063 }
8064
8065 int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
8066 {
8067 struct devlink *devlink;
8068 int ret;
8069
8070 dev_hold(dev);
8071 rtnl_unlock();
8072
8073 devlink = netdev_to_devlink(dev);
8074 if (!devlink || !devlink->ops->flash_update) {
8075 ret = -EOPNOTSUPP;
8076 goto out;
8077 }
8078
8079 mutex_lock(&devlink->lock);
8080 ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL);
8081 mutex_unlock(&devlink->lock);
8082
8083 out:
8084 rtnl_lock();
8085 dev_put(dev);
8086
8087 return ret;
8088 }
8089
8090 int devlink_compat_phys_port_name_get(struct net_device *dev,
8091 char *name, size_t len)
8092 {
8093 struct devlink_port *devlink_port;
8094
8095
8096
8097
8098
8099 ASSERT_RTNL();
8100
8101 devlink_port = netdev_to_devlink_port(dev);
8102 if (!devlink_port)
8103 return -EOPNOTSUPP;
8104
8105 return __devlink_port_phys_port_name_get(devlink_port, name, len);
8106 }
8107
8108 int devlink_compat_switch_id_get(struct net_device *dev,
8109 struct netdev_phys_item_id *ppid)
8110 {
8111 struct devlink_port *devlink_port;
8112
8113
8114
8115
8116
8117 devlink_port = netdev_to_devlink_port(dev);
8118 if (!devlink_port || !devlink_port->attrs.switch_port)
8119 return -EOPNOTSUPP;
8120
8121 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
8122
8123 return 0;
8124 }
8125
8126 static int __init devlink_init(void)
8127 {
8128 return genl_register_family(&devlink_nl_family);
8129 }
8130
8131 subsys_initcall(devlink_init);