1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2020, Intel Corporation. */ |
3 | |
4 | #include <linux/vmalloc.h> |
5 | |
6 | #include "ice.h" |
7 | #include "ice_lib.h" |
8 | #include "ice_devlink.h" |
9 | #include "ice_eswitch.h" |
10 | #include "ice_fw_update.h" |
11 | #include "ice_dcb_lib.h" |
12 | |
13 | static int ice_active_port_option = -1; |
14 | |
15 | /* context for devlink info version reporting */ |
16 | struct ice_info_ctx { |
17 | char buf[128]; |
18 | struct ice_orom_info pending_orom; |
19 | struct ice_nvm_info pending_nvm; |
20 | struct ice_netlist_info pending_netlist; |
21 | struct ice_hw_dev_caps dev_caps; |
22 | }; |
23 | |
24 | /* The following functions are used to format specific strings for various |
25 | * devlink info versions. The ctx parameter is used to provide the storage |
26 | * buffer, as well as any ancillary information calculated when the info |
27 | * request was made. |
28 | * |
29 | * If a version does not exist, for example when attempting to get the |
30 | * inactive version of flash when there is no pending update, the function |
31 | * should leave the buffer in the ctx structure empty. |
32 | */ |
33 | |
34 | static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) |
35 | { |
36 | u8 dsn[8]; |
37 | |
38 | /* Copy the DSN into an array in Big Endian format */ |
39 | put_unaligned_be64(val: pci_get_dsn(dev: pf->pdev), p: dsn); |
40 | |
41 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%8phD" , dsn); |
42 | } |
43 | |
44 | static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) |
45 | { |
46 | struct ice_hw *hw = &pf->hw; |
47 | int status; |
48 | |
49 | status = ice_read_pba_string(hw, pba_num: (u8 *)ctx->buf, pba_num_size: sizeof(ctx->buf)); |
50 | if (status) |
51 | /* We failed to locate the PBA, so just skip this entry */ |
52 | dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n" , |
53 | status); |
54 | } |
55 | |
56 | static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) |
57 | { |
58 | struct ice_hw *hw = &pf->hw; |
59 | |
60 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%u.%u.%u" , |
61 | hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); |
62 | } |
63 | |
64 | static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) |
65 | { |
66 | struct ice_hw *hw = &pf->hw; |
67 | |
68 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%u.%u.%u" , hw->api_maj_ver, |
69 | hw->api_min_ver, hw->api_patch); |
70 | } |
71 | |
72 | static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) |
73 | { |
74 | struct ice_hw *hw = &pf->hw; |
75 | |
76 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "0x%08x" , hw->fw_build); |
77 | } |
78 | |
79 | static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) |
80 | { |
81 | struct ice_orom_info *orom = &pf->hw.flash.orom; |
82 | |
83 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%u.%u.%u" , |
84 | orom->major, orom->build, orom->patch); |
85 | } |
86 | |
87 | static void |
88 | ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, |
89 | struct ice_info_ctx *ctx) |
90 | { |
91 | struct ice_orom_info *orom = &ctx->pending_orom; |
92 | |
93 | if (ctx->dev_caps.common_cap.nvm_update_pending_orom) |
94 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%u.%u.%u" , |
95 | orom->major, orom->build, orom->patch); |
96 | } |
97 | |
98 | static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) |
99 | { |
100 | struct ice_nvm_info *nvm = &pf->hw.flash.nvm; |
101 | |
102 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%x.%02x" , nvm->major, nvm->minor); |
103 | } |
104 | |
105 | static void |
106 | ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, |
107 | struct ice_info_ctx *ctx) |
108 | { |
109 | struct ice_nvm_info *nvm = &ctx->pending_nvm; |
110 | |
111 | if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) |
112 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%x.%02x" , |
113 | nvm->major, nvm->minor); |
114 | } |
115 | |
116 | static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) |
117 | { |
118 | struct ice_nvm_info *nvm = &pf->hw.flash.nvm; |
119 | |
120 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "0x%08x" , nvm->eetrack); |
121 | } |
122 | |
123 | static void |
124 | ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) |
125 | { |
126 | struct ice_nvm_info *nvm = &ctx->pending_nvm; |
127 | |
128 | if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) |
129 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "0x%08x" , nvm->eetrack); |
130 | } |
131 | |
132 | static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) |
133 | { |
134 | struct ice_hw *hw = &pf->hw; |
135 | |
136 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%s" , hw->active_pkg_name); |
137 | } |
138 | |
139 | static void |
140 | ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) |
141 | { |
142 | struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; |
143 | |
144 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%u.%u.%u.%u" , |
145 | pkg->major, pkg->minor, pkg->update, pkg->draft); |
146 | } |
147 | |
148 | static void |
149 | ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) |
150 | { |
151 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "0x%08x" , pf->hw.active_track_id); |
152 | } |
153 | |
154 | static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) |
155 | { |
156 | struct ice_netlist_info *netlist = &pf->hw.flash.netlist; |
157 | |
158 | /* The netlist version fields are BCD formatted */ |
159 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%x.%x.%x-%x.%x.%x" , |
160 | netlist->major, netlist->minor, |
161 | netlist->type >> 16, netlist->type & 0xFFFF, |
162 | netlist->rev, netlist->cust_ver); |
163 | } |
164 | |
165 | static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) |
166 | { |
167 | struct ice_netlist_info *netlist = &pf->hw.flash.netlist; |
168 | |
169 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "0x%08x" , netlist->hash); |
170 | } |
171 | |
172 | static void |
173 | ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, |
174 | struct ice_info_ctx *ctx) |
175 | { |
176 | struct ice_netlist_info *netlist = &ctx->pending_netlist; |
177 | |
178 | /* The netlist version fields are BCD formatted */ |
179 | if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) |
180 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%x.%x.%x-%x.%x.%x" , |
181 | netlist->major, netlist->minor, |
182 | netlist->type >> 16, netlist->type & 0xFFFF, |
183 | netlist->rev, netlist->cust_ver); |
184 | } |
185 | |
186 | static void |
187 | ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, |
188 | struct ice_info_ctx *ctx) |
189 | { |
190 | struct ice_netlist_info *netlist = &ctx->pending_netlist; |
191 | |
192 | if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) |
193 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "0x%08x" , netlist->hash); |
194 | } |
195 | |
196 | static void ice_info_cgu_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) |
197 | { |
198 | u32 id, cfg_ver, fw_ver; |
199 | |
200 | if (!ice_is_feature_supported(pf, f: ICE_F_CGU)) |
201 | return; |
202 | if (ice_aq_get_cgu_info(hw: &pf->hw, cgu_id: &id, cgu_cfg_ver: &cfg_ver, cgu_fw_ver: &fw_ver)) |
203 | return; |
204 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%u.%u.%u" , id, cfg_ver, fw_ver); |
205 | } |
206 | |
207 | static void ice_info_cgu_id(struct ice_pf *pf, struct ice_info_ctx *ctx) |
208 | { |
209 | if (!ice_is_feature_supported(pf, f: ICE_F_CGU)) |
210 | return; |
211 | snprintf(buf: ctx->buf, size: sizeof(ctx->buf), fmt: "%u" , pf->hw.cgu_part_number); |
212 | } |
213 | |
214 | #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } |
215 | #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL } |
216 | #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback } |
217 | |
218 | /* The combined() macro inserts both the running entry as well as a stored |
219 | * entry. The running entry will always report the version from the active |
220 | * handler. The stored entry will first try the pending handler, and fallback |
221 | * to the active handler if the pending function does not report a version. |
222 | * The pending handler should check the status of a pending update for the |
223 | * relevant flash component. It should only fill in the buffer in the case |
224 | * where a valid pending version is available. This ensures that the related |
225 | * stored and running versions remain in sync, and that stored versions are |
226 | * correctly reported as expected. |
227 | */ |
228 | #define combined(key, active, pending) \ |
229 | running(key, active), \ |
230 | stored(key, pending, active) |
231 | |
232 | enum ice_version_type { |
233 | ICE_VERSION_FIXED, |
234 | ICE_VERSION_RUNNING, |
235 | ICE_VERSION_STORED, |
236 | }; |
237 | |
238 | static const struct ice_devlink_version { |
239 | enum ice_version_type type; |
240 | const char *key; |
241 | void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); |
242 | void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); |
243 | } ice_devlink_versions[] = { |
244 | fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), |
245 | running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), |
246 | running("fw.mgmt.api" , ice_info_fw_api), |
247 | running("fw.mgmt.build" , ice_info_fw_build), |
248 | combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver), |
249 | combined("fw.psid.api" , ice_info_nvm_ver, ice_info_pending_nvm_ver), |
250 | combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack), |
251 | running("fw.app.name" , ice_info_ddp_pkg_name), |
252 | running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version), |
253 | running("fw.app.bundle_id" , ice_info_ddp_pkg_bundle_id), |
254 | combined("fw.netlist" , ice_info_netlist_ver, ice_info_pending_netlist_ver), |
255 | combined("fw.netlist.build" , ice_info_netlist_build, ice_info_pending_netlist_build), |
256 | fixed("cgu.id" , ice_info_cgu_id), |
257 | running("fw.cgu" , ice_info_cgu_fw_build), |
258 | }; |
259 | |
260 | /** |
261 | * ice_devlink_info_get - .info_get devlink handler |
262 | * @devlink: devlink instance structure |
263 | * @req: the devlink info request |
264 | * @extack: extended netdev ack structure |
265 | * |
266 | * Callback for the devlink .info_get operation. Reports information about the |
267 | * device. |
268 | * |
269 | * Return: zero on success or an error code on failure. |
270 | */ |
271 | static int ice_devlink_info_get(struct devlink *devlink, |
272 | struct devlink_info_req *req, |
273 | struct netlink_ext_ack *extack) |
274 | { |
275 | struct ice_pf *pf = devlink_priv(devlink); |
276 | struct device *dev = ice_pf_to_dev(pf); |
277 | struct ice_hw *hw = &pf->hw; |
278 | struct ice_info_ctx *ctx; |
279 | size_t i; |
280 | int err; |
281 | |
282 | err = ice_wait_for_reset(pf, timeout: 10 * HZ); |
283 | if (err) { |
284 | NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting" ); |
285 | return err; |
286 | } |
287 | |
288 | ctx = kzalloc(size: sizeof(*ctx), GFP_KERNEL); |
289 | if (!ctx) |
290 | return -ENOMEM; |
291 | |
292 | /* discover capabilities first */ |
293 | err = ice_discover_dev_caps(hw, dev_caps: &ctx->dev_caps); |
294 | if (err) { |
295 | dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n" , |
296 | err, ice_aq_str(hw->adminq.sq_last_status)); |
297 | NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities" ); |
298 | goto out_free_ctx; |
299 | } |
300 | |
301 | if (ctx->dev_caps.common_cap.nvm_update_pending_orom) { |
302 | err = ice_get_inactive_orom_ver(hw, orom: &ctx->pending_orom); |
303 | if (err) { |
304 | dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n" , |
305 | err, ice_aq_str(hw->adminq.sq_last_status)); |
306 | |
307 | /* disable display of pending Option ROM */ |
308 | ctx->dev_caps.common_cap.nvm_update_pending_orom = false; |
309 | } |
310 | } |
311 | |
312 | if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) { |
313 | err = ice_get_inactive_nvm_ver(hw, nvm: &ctx->pending_nvm); |
314 | if (err) { |
315 | dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n" , |
316 | err, ice_aq_str(hw->adminq.sq_last_status)); |
317 | |
318 | /* disable display of pending Option ROM */ |
319 | ctx->dev_caps.common_cap.nvm_update_pending_nvm = false; |
320 | } |
321 | } |
322 | |
323 | if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) { |
324 | err = ice_get_inactive_netlist_ver(hw, netlist: &ctx->pending_netlist); |
325 | if (err) { |
326 | dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n" , |
327 | err, ice_aq_str(hw->adminq.sq_last_status)); |
328 | |
329 | /* disable display of pending Option ROM */ |
330 | ctx->dev_caps.common_cap.nvm_update_pending_netlist = false; |
331 | } |
332 | } |
333 | |
334 | ice_info_get_dsn(pf, ctx); |
335 | |
336 | err = devlink_info_serial_number_put(req, sn: ctx->buf); |
337 | if (err) { |
338 | NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number" ); |
339 | goto out_free_ctx; |
340 | } |
341 | |
342 | for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) { |
343 | enum ice_version_type type = ice_devlink_versions[i].type; |
344 | const char *key = ice_devlink_versions[i].key; |
345 | |
346 | memset(ctx->buf, 0, sizeof(ctx->buf)); |
347 | |
348 | ice_devlink_versions[i].getter(pf, ctx); |
349 | |
350 | /* If the default getter doesn't report a version, use the |
351 | * fallback function. This is primarily useful in the case of |
352 | * "stored" versions that want to report the same value as the |
353 | * running version in the normal case of no pending update. |
354 | */ |
355 | if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) |
356 | ice_devlink_versions[i].fallback(pf, ctx); |
357 | |
358 | /* Do not report missing versions */ |
359 | if (ctx->buf[0] == '\0') |
360 | continue; |
361 | |
362 | switch (type) { |
363 | case ICE_VERSION_FIXED: |
364 | err = devlink_info_version_fixed_put(req, version_name: key, version_value: ctx->buf); |
365 | if (err) { |
366 | NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version" ); |
367 | goto out_free_ctx; |
368 | } |
369 | break; |
370 | case ICE_VERSION_RUNNING: |
371 | err = devlink_info_version_running_put(req, version_name: key, version_value: ctx->buf); |
372 | if (err) { |
373 | NL_SET_ERR_MSG_MOD(extack, "Unable to set running version" ); |
374 | goto out_free_ctx; |
375 | } |
376 | break; |
377 | case ICE_VERSION_STORED: |
378 | err = devlink_info_version_stored_put(req, version_name: key, version_value: ctx->buf); |
379 | if (err) { |
380 | NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version" ); |
381 | goto out_free_ctx; |
382 | } |
383 | break; |
384 | } |
385 | } |
386 | |
387 | out_free_ctx: |
388 | kfree(objp: ctx); |
389 | return err; |
390 | } |
391 | |
392 | /** |
393 | * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware |
394 | * @pf: pointer to the pf instance |
395 | * @extack: netlink extended ACK structure |
396 | * |
397 | * Allow user to activate new Embedded Management Processor firmware by |
398 | * issuing device specific EMP reset. Called in response to |
399 | * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. |
400 | * |
401 | * Note that teardown and rebuild of the driver state happens automatically as |
402 | * part of an interrupt and watchdog task. This is because all physical |
403 | * functions on the device must be able to reset when an EMP reset occurs from |
404 | * any source. |
405 | */ |
406 | static int |
407 | ice_devlink_reload_empr_start(struct ice_pf *pf, |
408 | struct netlink_ext_ack *extack) |
409 | { |
410 | struct device *dev = ice_pf_to_dev(pf); |
411 | struct ice_hw *hw = &pf->hw; |
412 | u8 pending; |
413 | int err; |
414 | |
415 | err = ice_get_pending_updates(pf, pending: &pending, extack); |
416 | if (err) |
417 | return err; |
418 | |
419 | /* pending is a bitmask of which flash banks have a pending update, |
420 | * including the main NVM bank, the Option ROM bank, and the netlist |
421 | * bank. If any of these bits are set, then there is a pending update |
422 | * waiting to be activated. |
423 | */ |
424 | if (!pending) { |
425 | NL_SET_ERR_MSG_MOD(extack, "No pending firmware update" ); |
426 | return -ECANCELED; |
427 | } |
428 | |
429 | if (pf->fw_emp_reset_disabled) { |
430 | NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed" ); |
431 | return -ECANCELED; |
432 | } |
433 | |
434 | dev_dbg(dev, "Issuing device EMP reset to activate firmware\n" ); |
435 | |
436 | err = ice_aq_nvm_update_empr(hw); |
437 | if (err) { |
438 | dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n" , |
439 | err, ice_aq_str(hw->adminq.sq_last_status)); |
440 | NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware" ); |
441 | return err; |
442 | } |
443 | |
444 | return 0; |
445 | } |
446 | |
447 | /** |
448 | * ice_devlink_reinit_down - unload given PF |
449 | * @pf: pointer to the PF struct |
450 | */ |
451 | static void ice_devlink_reinit_down(struct ice_pf *pf) |
452 | { |
453 | /* No need to take devl_lock, it's already taken by devlink API */ |
454 | ice_unload(pf); |
455 | rtnl_lock(); |
456 | ice_vsi_decfg(vsi: ice_get_main_vsi(pf)); |
457 | rtnl_unlock(); |
458 | ice_deinit_dev(pf); |
459 | } |
460 | |
461 | /** |
462 | * ice_devlink_reload_down - prepare for reload |
463 | * @devlink: pointer to the devlink instance to reload |
464 | * @netns_change: if true, the network namespace is changing |
465 | * @action: the action to perform |
466 | * @limit: limits on what reload should do, such as not resetting |
467 | * @extack: netlink extended ACK structure |
468 | */ |
469 | static int |
470 | ice_devlink_reload_down(struct devlink *devlink, bool netns_change, |
471 | enum devlink_reload_action action, |
472 | enum devlink_reload_limit limit, |
473 | struct netlink_ext_ack *extack) |
474 | { |
475 | struct ice_pf *pf = devlink_priv(devlink); |
476 | |
477 | switch (action) { |
478 | case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: |
479 | if (ice_is_eswitch_mode_switchdev(pf)) { |
480 | NL_SET_ERR_MSG_MOD(extack, |
481 | "Go to legacy mode before doing reinit\n" ); |
482 | return -EOPNOTSUPP; |
483 | } |
484 | if (ice_is_adq_active(pf)) { |
485 | NL_SET_ERR_MSG_MOD(extack, |
486 | "Turn off ADQ before doing reinit\n" ); |
487 | return -EOPNOTSUPP; |
488 | } |
489 | if (ice_has_vfs(pf)) { |
490 | NL_SET_ERR_MSG_MOD(extack, |
491 | "Remove all VFs before doing reinit\n" ); |
492 | return -EOPNOTSUPP; |
493 | } |
494 | ice_devlink_reinit_down(pf); |
495 | return 0; |
496 | case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: |
497 | return ice_devlink_reload_empr_start(pf, extack); |
498 | default: |
499 | WARN_ON(1); |
500 | return -EOPNOTSUPP; |
501 | } |
502 | } |
503 | |
504 | /** |
505 | * ice_devlink_reload_empr_finish - Wait for EMP reset to finish |
506 | * @pf: pointer to the pf instance |
507 | * @extack: netlink extended ACK structure |
508 | * |
509 | * Wait for driver to finish rebuilding after EMP reset is completed. This |
510 | * includes time to wait for both the actual device reset as well as the time |
511 | * for the driver's rebuild to complete. |
512 | */ |
513 | static int |
514 | ice_devlink_reload_empr_finish(struct ice_pf *pf, |
515 | struct netlink_ext_ack *extack) |
516 | { |
517 | int err; |
518 | |
519 | err = ice_wait_for_reset(pf, timeout: 60 * HZ); |
520 | if (err) { |
521 | NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute" ); |
522 | return err; |
523 | } |
524 | |
525 | return 0; |
526 | } |
527 | |
528 | /** |
529 | * ice_devlink_port_opt_speed_str - convert speed to a string |
530 | * @speed: speed value |
531 | */ |
532 | static const char *ice_devlink_port_opt_speed_str(u8 speed) |
533 | { |
534 | switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) { |
535 | case ICE_AQC_PORT_OPT_MAX_LANE_100M: |
536 | return "0.1" ; |
537 | case ICE_AQC_PORT_OPT_MAX_LANE_1G: |
538 | return "1" ; |
539 | case ICE_AQC_PORT_OPT_MAX_LANE_2500M: |
540 | return "2.5" ; |
541 | case ICE_AQC_PORT_OPT_MAX_LANE_5G: |
542 | return "5" ; |
543 | case ICE_AQC_PORT_OPT_MAX_LANE_10G: |
544 | return "10" ; |
545 | case ICE_AQC_PORT_OPT_MAX_LANE_25G: |
546 | return "25" ; |
547 | case ICE_AQC_PORT_OPT_MAX_LANE_50G: |
548 | return "50" ; |
549 | case ICE_AQC_PORT_OPT_MAX_LANE_100G: |
550 | return "100" ; |
551 | } |
552 | |
553 | return "-" ; |
554 | } |
555 | |
556 | #define ICE_PORT_OPT_DESC_LEN 50 |
557 | /** |
558 | * ice_devlink_port_options_print - Print available port split options |
559 | * @pf: the PF to print split port options |
560 | * |
561 | * Prints a table with available port split options and max port speeds |
562 | */ |
563 | static void ice_devlink_port_options_print(struct ice_pf *pf) |
564 | { |
565 | u8 i, j, options_count, cnt, speed, pending_idx, active_idx; |
566 | struct ice_aqc_get_port_options_elem *options, *opt; |
567 | struct device *dev = ice_pf_to_dev(pf); |
568 | bool active_valid, pending_valid; |
569 | char desc[ICE_PORT_OPT_DESC_LEN]; |
570 | const char *str; |
571 | int status; |
572 | |
573 | options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV, |
574 | size: sizeof(*options), GFP_KERNEL); |
575 | if (!options) |
576 | return; |
577 | |
578 | for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) { |
579 | opt = options + i * ICE_AQC_PORT_OPT_MAX; |
580 | options_count = ICE_AQC_PORT_OPT_MAX; |
581 | active_valid = 0; |
582 | |
583 | status = ice_aq_get_port_options(hw: &pf->hw, options: opt, option_count: &options_count, |
584 | lport: i, lport_valid: true, active_option_idx: &active_idx, |
585 | active_option_valid: &active_valid, pending_option_idx: &pending_idx, |
586 | pending_option_valid: &pending_valid); |
587 | if (status) { |
588 | dev_dbg(dev, "Couldn't read port option for port %d, err %d\n" , |
589 | i, status); |
590 | goto err; |
591 | } |
592 | } |
593 | |
594 | dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n" ); |
595 | dev_dbg(dev, "Status Split Quad 0 Quad 1\n" ); |
596 | dev_dbg(dev, " count L0 L1 L2 L3 L4 L5 L6 L7\n" ); |
597 | |
598 | for (i = 0; i < options_count; i++) { |
599 | cnt = 0; |
600 | |
601 | if (i == ice_active_port_option) |
602 | str = "Active" ; |
603 | else if ((i == pending_idx) && pending_valid) |
604 | str = "Pending" ; |
605 | else |
606 | str = "" ; |
607 | |
608 | cnt += snprintf(buf: &desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt, |
609 | fmt: "%-8s" , str); |
610 | |
611 | cnt += snprintf(buf: &desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt, |
612 | fmt: "%-6u" , options[i].pmd); |
613 | |
614 | for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) { |
615 | speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed; |
616 | str = ice_devlink_port_opt_speed_str(speed); |
617 | cnt += snprintf(buf: &desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt, |
618 | fmt: "%3s " , str); |
619 | } |
620 | |
621 | dev_dbg(dev, "%s\n" , desc); |
622 | } |
623 | |
624 | err: |
625 | kfree(objp: options); |
626 | } |
627 | |
628 | /** |
629 | * ice_devlink_aq_set_port_option - Send set port option admin queue command |
630 | * @pf: the PF to print split port options |
631 | * @option_idx: selected port option |
632 | * @extack: extended netdev ack structure |
633 | * |
634 | * Sends set port option admin queue command with selected port option and |
635 | * calls NVM write activate. |
636 | */ |
637 | static int |
638 | ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx, |
639 | struct netlink_ext_ack *extack) |
640 | { |
641 | struct device *dev = ice_pf_to_dev(pf); |
642 | int status; |
643 | |
644 | status = ice_aq_set_port_option(hw: &pf->hw, lport: 0, lport_valid: true, new_option: option_idx); |
645 | if (status) { |
646 | dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n" , |
647 | status, pf->hw.adminq.sq_last_status); |
648 | NL_SET_ERR_MSG_MOD(extack, "Port split request failed" ); |
649 | return -EIO; |
650 | } |
651 | |
652 | status = ice_acquire_nvm(hw: &pf->hw, access: ICE_RES_WRITE); |
653 | if (status) { |
654 | dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n" , |
655 | status, pf->hw.adminq.sq_last_status); |
656 | NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore" ); |
657 | return -EIO; |
658 | } |
659 | |
660 | status = ice_nvm_write_activate(hw: &pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL); |
661 | if (status) { |
662 | dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n" , |
663 | status, pf->hw.adminq.sq_last_status); |
664 | NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data" ); |
665 | ice_release_nvm(hw: &pf->hw); |
666 | return -EIO; |
667 | } |
668 | |
669 | ice_release_nvm(hw: &pf->hw); |
670 | |
671 | NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split" ); |
672 | return 0; |
673 | } |
674 | |
675 | /** |
676 | * ice_devlink_port_split - .port_split devlink handler |
677 | * @devlink: devlink instance structure |
678 | * @port: devlink port structure |
679 | * @count: number of ports to split to |
680 | * @extack: extended netdev ack structure |
681 | * |
682 | * Callback for the devlink .port_split operation. |
683 | * |
684 | * Unfortunately, the devlink expression of available options is limited |
685 | * to just a number, so search for an FW port option which supports |
686 | * the specified number. As there could be multiple FW port options with |
687 | * the same port split count, allow switching between them. When the same |
688 | * port split count request is issued again, switch to the next FW port |
689 | * option with the same port split count. |
690 | * |
691 | * Return: zero on success or an error code on failure. |
692 | */ |
693 | static int |
694 | ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port, |
695 | unsigned int count, struct netlink_ext_ack *extack) |
696 | { |
697 | struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX]; |
698 | u8 i, j, active_idx, pending_idx, new_option; |
699 | struct ice_pf *pf = devlink_priv(devlink); |
700 | u8 option_count = ICE_AQC_PORT_OPT_MAX; |
701 | struct device *dev = ice_pf_to_dev(pf); |
702 | bool active_valid, pending_valid; |
703 | int status; |
704 | |
705 | status = ice_aq_get_port_options(hw: &pf->hw, options, option_count: &option_count, |
706 | lport: 0, lport_valid: true, active_option_idx: &active_idx, active_option_valid: &active_valid, |
707 | pending_option_idx: &pending_idx, pending_option_valid: &pending_valid); |
708 | if (status) { |
709 | dev_dbg(dev, "Couldn't read port split options, err = %d\n" , |
710 | status); |
711 | NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options" ); |
712 | return -EIO; |
713 | } |
714 | |
715 | new_option = ICE_AQC_PORT_OPT_MAX; |
716 | active_idx = pending_valid ? pending_idx : active_idx; |
717 | for (i = 1; i <= option_count; i++) { |
718 | /* In order to allow switching between FW port options with |
719 | * the same port split count, search for a new option starting |
720 | * from the active/pending option (with array wrap around). |
721 | */ |
722 | j = (active_idx + i) % option_count; |
723 | |
724 | if (count == options[j].pmd) { |
725 | new_option = j; |
726 | break; |
727 | } |
728 | } |
729 | |
730 | if (new_option == active_idx) { |
731 | dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n" , |
732 | count); |
733 | NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set" ); |
734 | ice_devlink_port_options_print(pf); |
735 | return -EINVAL; |
736 | } |
737 | |
738 | if (new_option == ICE_AQC_PORT_OPT_MAX) { |
739 | dev_dbg(dev, "request to split: count: %u not found\n" , count); |
740 | NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config" ); |
741 | ice_devlink_port_options_print(pf); |
742 | return -EINVAL; |
743 | } |
744 | |
745 | status = ice_devlink_aq_set_port_option(pf, option_idx: new_option, extack); |
746 | if (status) |
747 | return status; |
748 | |
749 | ice_devlink_port_options_print(pf); |
750 | |
751 | return 0; |
752 | } |
753 | |
754 | /** |
755 | * ice_devlink_port_unsplit - .port_unsplit devlink handler |
756 | * @devlink: devlink instance structure |
757 | * @port: devlink port structure |
758 | * @extack: extended netdev ack structure |
759 | * |
760 | * Callback for the devlink .port_unsplit operation. |
761 | * Calls ice_devlink_port_split with split count set to 1. |
762 | * There could be no FW option available with split count 1. |
763 | * |
764 | * Return: zero on success or an error code on failure. |
765 | */ |
766 | static int |
767 | ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port, |
768 | struct netlink_ext_ack *extack) |
769 | { |
770 | return ice_devlink_port_split(devlink, port, count: 1, extack); |
771 | } |
772 | |
773 | /** |
774 | * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree |
775 | * @pf: pf struct |
776 | * |
777 | * This function tears down tree exported during VF's creation. |
778 | */ |
779 | void ice_tear_down_devlink_rate_tree(struct ice_pf *pf) |
780 | { |
781 | struct devlink *devlink; |
782 | struct ice_vf *vf; |
783 | unsigned int bkt; |
784 | |
785 | devlink = priv_to_devlink(priv: pf); |
786 | |
787 | devl_lock(devlink); |
788 | mutex_lock(&pf->vfs.table_lock); |
789 | ice_for_each_vf(pf, bkt, vf) { |
790 | if (vf->devlink_port.devlink_rate) |
791 | devl_rate_leaf_destroy(devlink_port: &vf->devlink_port); |
792 | } |
793 | mutex_unlock(lock: &pf->vfs.table_lock); |
794 | |
795 | devl_rate_nodes_destroy(devlink); |
796 | devl_unlock(devlink); |
797 | } |
798 | |
799 | /** |
800 | * ice_enable_custom_tx - try to enable custom Tx feature |
801 | * @pf: pf struct |
802 | * |
803 | * This function tries to enable custom Tx feature, |
804 | * it's not possible to enable it, if DCB or ADQ is active. |
805 | */ |
806 | static bool ice_enable_custom_tx(struct ice_pf *pf) |
807 | { |
808 | struct ice_port_info *pi = ice_get_main_vsi(pf)->port_info; |
809 | struct device *dev = ice_pf_to_dev(pf); |
810 | |
811 | if (pi->is_custom_tx_enabled) |
812 | /* already enabled, return true */ |
813 | return true; |
814 | |
815 | if (ice_is_adq_active(pf)) { |
816 | dev_err(dev, "ADQ active, can't modify Tx scheduler tree\n" ); |
817 | return false; |
818 | } |
819 | |
820 | if (ice_is_dcb_active(pf)) { |
821 | dev_err(dev, "DCB active, can't modify Tx scheduler tree\n" ); |
822 | return false; |
823 | } |
824 | |
825 | pi->is_custom_tx_enabled = true; |
826 | |
827 | return true; |
828 | } |
829 | |
830 | /** |
831 | * ice_traverse_tx_tree - traverse Tx scheduler tree |
832 | * @devlink: devlink struct |
833 | * @node: current node, used for recursion |
834 | * @tc_node: tc_node struct, that is treated as a root |
835 | * @pf: pf struct |
836 | * |
837 | * This function traverses Tx scheduler tree and exports |
838 | * entire structure to the devlink-rate. |
839 | */ |
840 | static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node *node, |
841 | struct ice_sched_node *tc_node, struct ice_pf *pf) |
842 | { |
843 | struct devlink_rate *rate_node = NULL; |
844 | struct ice_vf *vf; |
845 | int i; |
846 | |
847 | if (node->rate_node) |
848 | /* already added, skip to the next */ |
849 | goto traverse_children; |
850 | |
851 | if (node->parent == tc_node) { |
852 | /* create root node */ |
853 | rate_node = devl_rate_node_create(devlink, priv: node, node_name: node->name, NULL); |
854 | } else if (node->vsi_handle && |
855 | pf->vsi[node->vsi_handle]->vf) { |
856 | vf = pf->vsi[node->vsi_handle]->vf; |
857 | if (!vf->devlink_port.devlink_rate) |
858 | /* leaf nodes doesn't have children |
859 | * so we don't set rate_node |
860 | */ |
861 | devl_rate_leaf_create(devlink_port: &vf->devlink_port, priv: node, |
862 | parent: node->parent->rate_node); |
863 | } else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF && |
864 | node->parent->rate_node) { |
865 | rate_node = devl_rate_node_create(devlink, priv: node, node_name: node->name, |
866 | parent: node->parent->rate_node); |
867 | } |
868 | |
869 | if (rate_node && !IS_ERR(ptr: rate_node)) |
870 | node->rate_node = rate_node; |
871 | |
872 | traverse_children: |
873 | for (i = 0; i < node->num_children; i++) |
874 | ice_traverse_tx_tree(devlink, node: node->children[i], tc_node, pf); |
875 | } |
876 | |
877 | /** |
878 | * ice_devlink_rate_init_tx_topology - export Tx scheduler tree to devlink rate |
879 | * @devlink: devlink struct |
880 | * @vsi: main vsi struct |
881 | * |
882 | * This function finds a root node, then calls ice_traverse_tx tree, which |
883 | * traverses the tree and exports it's contents to devlink rate. |
884 | */ |
885 | int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *vsi) |
886 | { |
887 | struct ice_port_info *pi = vsi->port_info; |
888 | struct ice_sched_node *tc_node; |
889 | struct ice_pf *pf = vsi->back; |
890 | int i; |
891 | |
892 | tc_node = pi->root->children[0]; |
893 | mutex_lock(&pi->sched_lock); |
894 | devl_lock(devlink); |
895 | for (i = 0; i < tc_node->num_children; i++) |
896 | ice_traverse_tx_tree(devlink, node: tc_node->children[i], tc_node, pf); |
897 | devl_unlock(devlink); |
898 | mutex_unlock(lock: &pi->sched_lock); |
899 | |
900 | return 0; |
901 | } |
902 | |
903 | static void ice_clear_rate_nodes(struct ice_sched_node *node) |
904 | { |
905 | node->rate_node = NULL; |
906 | |
907 | for (int i = 0; i < node->num_children; i++) |
908 | ice_clear_rate_nodes(node: node->children[i]); |
909 | } |
910 | |
911 | /** |
912 | * ice_devlink_rate_clear_tx_topology - clear node->rate_node |
913 | * @vsi: main vsi struct |
914 | * |
915 | * Clear rate_node to cleanup creation of Tx topology. |
916 | * |
917 | */ |
918 | void ice_devlink_rate_clear_tx_topology(struct ice_vsi *vsi) |
919 | { |
920 | struct ice_port_info *pi = vsi->port_info; |
921 | |
922 | mutex_lock(&pi->sched_lock); |
923 | ice_clear_rate_nodes(node: pi->root->children[0]); |
924 | mutex_unlock(lock: &pi->sched_lock); |
925 | } |
926 | |
927 | /** |
928 | * ice_set_object_tx_share - sets node scheduling parameter |
929 | * @pi: devlink struct instance |
930 | * @node: node struct instance |
931 | * @bw: bandwidth in bytes per second |
932 | * @extack: extended netdev ack structure |
933 | * |
934 | * This function sets ICE_MIN_BW scheduling BW limit. |
935 | */ |
936 | static int ice_set_object_tx_share(struct ice_port_info *pi, struct ice_sched_node *node, |
937 | u64 bw, struct netlink_ext_ack *extack) |
938 | { |
939 | int status; |
940 | |
941 | mutex_lock(&pi->sched_lock); |
942 | /* converts bytes per second to kilo bits per second */ |
943 | node->tx_share = div_u64(dividend: bw, divisor: 125); |
944 | status = ice_sched_set_node_bw_lmt(pi, node, rl_type: ICE_MIN_BW, bw: node->tx_share); |
945 | mutex_unlock(lock: &pi->sched_lock); |
946 | |
947 | if (status) |
948 | NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_share" ); |
949 | |
950 | return status; |
951 | } |
952 | |
953 | /** |
954 | * ice_set_object_tx_max - sets node scheduling parameter |
955 | * @pi: devlink struct instance |
956 | * @node: node struct instance |
957 | * @bw: bandwidth in bytes per second |
958 | * @extack: extended netdev ack structure |
959 | * |
960 | * This function sets ICE_MAX_BW scheduling BW limit. |
961 | */ |
962 | static int ice_set_object_tx_max(struct ice_port_info *pi, struct ice_sched_node *node, |
963 | u64 bw, struct netlink_ext_ack *extack) |
964 | { |
965 | int status; |
966 | |
967 | mutex_lock(&pi->sched_lock); |
968 | /* converts bytes per second value to kilo bits per second */ |
969 | node->tx_max = div_u64(dividend: bw, divisor: 125); |
970 | status = ice_sched_set_node_bw_lmt(pi, node, rl_type: ICE_MAX_BW, bw: node->tx_max); |
971 | mutex_unlock(lock: &pi->sched_lock); |
972 | |
973 | if (status) |
974 | NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_max" ); |
975 | |
976 | return status; |
977 | } |
978 | |
979 | /** |
980 | * ice_set_object_tx_priority - sets node scheduling parameter |
981 | * @pi: devlink struct instance |
982 | * @node: node struct instance |
983 | * @priority: value representing priority for strict priority arbitration |
984 | * @extack: extended netdev ack structure |
985 | * |
986 | * This function sets priority of node among siblings. |
987 | */ |
988 | static int ice_set_object_tx_priority(struct ice_port_info *pi, struct ice_sched_node *node, |
989 | u32 priority, struct netlink_ext_ack *extack) |
990 | { |
991 | int status; |
992 | |
993 | if (priority >= 8) { |
994 | NL_SET_ERR_MSG_MOD(extack, "Priority should be less than 8" ); |
995 | return -EINVAL; |
996 | } |
997 | |
998 | mutex_lock(&pi->sched_lock); |
999 | node->tx_priority = priority; |
1000 | status = ice_sched_set_node_priority(pi, node, priority: node->tx_priority); |
1001 | mutex_unlock(lock: &pi->sched_lock); |
1002 | |
1003 | if (status) |
1004 | NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_priority" ); |
1005 | |
1006 | return status; |
1007 | } |
1008 | |
1009 | /** |
1010 | * ice_set_object_tx_weight - sets node scheduling parameter |
1011 | * @pi: devlink struct instance |
1012 | * @node: node struct instance |
1013 | * @weight: value represeting relative weight for WFQ arbitration |
1014 | * @extack: extended netdev ack structure |
1015 | * |
1016 | * This function sets node weight for WFQ algorithm. |
1017 | */ |
1018 | static int ice_set_object_tx_weight(struct ice_port_info *pi, struct ice_sched_node *node, |
1019 | u32 weight, struct netlink_ext_ack *extack) |
1020 | { |
1021 | int status; |
1022 | |
1023 | if (weight > 200 || weight < 1) { |
1024 | NL_SET_ERR_MSG_MOD(extack, "Weight must be between 1 and 200" ); |
1025 | return -EINVAL; |
1026 | } |
1027 | |
1028 | mutex_lock(&pi->sched_lock); |
1029 | node->tx_weight = weight; |
1030 | status = ice_sched_set_node_weight(pi, node, weight: node->tx_weight); |
1031 | mutex_unlock(lock: &pi->sched_lock); |
1032 | |
1033 | if (status) |
1034 | NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_weight" ); |
1035 | |
1036 | return status; |
1037 | } |
1038 | |
1039 | /** |
1040 | * ice_get_pi_from_dev_rate - get port info from devlink_rate |
1041 | * @rate_node: devlink struct instance |
1042 | * |
1043 | * This function returns corresponding port_info struct of devlink_rate |
1044 | */ |
1045 | static struct ice_port_info *ice_get_pi_from_dev_rate(struct devlink_rate *rate_node) |
1046 | { |
1047 | struct ice_pf *pf = devlink_priv(devlink: rate_node->devlink); |
1048 | |
1049 | return ice_get_main_vsi(pf)->port_info; |
1050 | } |
1051 | |
1052 | static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv, |
1053 | struct netlink_ext_ack *extack) |
1054 | { |
1055 | struct ice_sched_node *node; |
1056 | struct ice_port_info *pi; |
1057 | |
1058 | pi = ice_get_pi_from_dev_rate(rate_node); |
1059 | |
1060 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_node->devlink))) |
1061 | return -EBUSY; |
1062 | |
1063 | /* preallocate memory for ice_sched_node */ |
1064 | node = devm_kzalloc(dev: ice_hw_to_dev(hw: pi->hw), size: sizeof(*node), GFP_KERNEL); |
1065 | *priv = node; |
1066 | |
1067 | return 0; |
1068 | } |
1069 | |
1070 | static int ice_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv, |
1071 | struct netlink_ext_ack *extack) |
1072 | { |
1073 | struct ice_sched_node *node, *tc_node; |
1074 | struct ice_port_info *pi; |
1075 | |
1076 | pi = ice_get_pi_from_dev_rate(rate_node); |
1077 | tc_node = pi->root->children[0]; |
1078 | node = priv; |
1079 | |
1080 | if (!rate_node->parent || !node || tc_node == node || !extack) |
1081 | return 0; |
1082 | |
1083 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_node->devlink))) |
1084 | return -EBUSY; |
1085 | |
1086 | /* can't allow to delete a node with children */ |
1087 | if (node->num_children) |
1088 | return -EINVAL; |
1089 | |
1090 | mutex_lock(&pi->sched_lock); |
1091 | ice_free_sched_node(pi, node); |
1092 | mutex_unlock(lock: &pi->sched_lock); |
1093 | |
1094 | return 0; |
1095 | } |
1096 | |
1097 | static int ice_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv, |
1098 | u64 tx_max, struct netlink_ext_ack *extack) |
1099 | { |
1100 | struct ice_sched_node *node = priv; |
1101 | |
1102 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_leaf->devlink))) |
1103 | return -EBUSY; |
1104 | |
1105 | if (!node) |
1106 | return 0; |
1107 | |
1108 | return ice_set_object_tx_max(pi: ice_get_pi_from_dev_rate(rate_node: rate_leaf), |
1109 | node, bw: tx_max, extack); |
1110 | } |
1111 | |
1112 | static int ice_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, |
1113 | u64 tx_share, struct netlink_ext_ack *extack) |
1114 | { |
1115 | struct ice_sched_node *node = priv; |
1116 | |
1117 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_leaf->devlink))) |
1118 | return -EBUSY; |
1119 | |
1120 | if (!node) |
1121 | return 0; |
1122 | |
1123 | return ice_set_object_tx_share(pi: ice_get_pi_from_dev_rate(rate_node: rate_leaf), node, |
1124 | bw: tx_share, extack); |
1125 | } |
1126 | |
1127 | static int ice_devlink_rate_leaf_tx_priority_set(struct devlink_rate *rate_leaf, void *priv, |
1128 | u32 tx_priority, struct netlink_ext_ack *extack) |
1129 | { |
1130 | struct ice_sched_node *node = priv; |
1131 | |
1132 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_leaf->devlink))) |
1133 | return -EBUSY; |
1134 | |
1135 | if (!node) |
1136 | return 0; |
1137 | |
1138 | return ice_set_object_tx_priority(pi: ice_get_pi_from_dev_rate(rate_node: rate_leaf), node, |
1139 | priority: tx_priority, extack); |
1140 | } |
1141 | |
1142 | static int ice_devlink_rate_leaf_tx_weight_set(struct devlink_rate *rate_leaf, void *priv, |
1143 | u32 tx_weight, struct netlink_ext_ack *extack) |
1144 | { |
1145 | struct ice_sched_node *node = priv; |
1146 | |
1147 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_leaf->devlink))) |
1148 | return -EBUSY; |
1149 | |
1150 | if (!node) |
1151 | return 0; |
1152 | |
1153 | return ice_set_object_tx_weight(pi: ice_get_pi_from_dev_rate(rate_node: rate_leaf), node, |
1154 | weight: tx_weight, extack); |
1155 | } |
1156 | |
1157 | static int ice_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv, |
1158 | u64 tx_max, struct netlink_ext_ack *extack) |
1159 | { |
1160 | struct ice_sched_node *node = priv; |
1161 | |
1162 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_node->devlink))) |
1163 | return -EBUSY; |
1164 | |
1165 | if (!node) |
1166 | return 0; |
1167 | |
1168 | return ice_set_object_tx_max(pi: ice_get_pi_from_dev_rate(rate_node), |
1169 | node, bw: tx_max, extack); |
1170 | } |
1171 | |
1172 | static int ice_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv, |
1173 | u64 tx_share, struct netlink_ext_ack *extack) |
1174 | { |
1175 | struct ice_sched_node *node = priv; |
1176 | |
1177 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_node->devlink))) |
1178 | return -EBUSY; |
1179 | |
1180 | if (!node) |
1181 | return 0; |
1182 | |
1183 | return ice_set_object_tx_share(pi: ice_get_pi_from_dev_rate(rate_node), |
1184 | node, bw: tx_share, extack); |
1185 | } |
1186 | |
1187 | static int ice_devlink_rate_node_tx_priority_set(struct devlink_rate *rate_node, void *priv, |
1188 | u32 tx_priority, struct netlink_ext_ack *extack) |
1189 | { |
1190 | struct ice_sched_node *node = priv; |
1191 | |
1192 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_node->devlink))) |
1193 | return -EBUSY; |
1194 | |
1195 | if (!node) |
1196 | return 0; |
1197 | |
1198 | return ice_set_object_tx_priority(pi: ice_get_pi_from_dev_rate(rate_node), |
1199 | node, priority: tx_priority, extack); |
1200 | } |
1201 | |
1202 | static int ice_devlink_rate_node_tx_weight_set(struct devlink_rate *rate_node, void *priv, |
1203 | u32 tx_weight, struct netlink_ext_ack *extack) |
1204 | { |
1205 | struct ice_sched_node *node = priv; |
1206 | |
1207 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: rate_node->devlink))) |
1208 | return -EBUSY; |
1209 | |
1210 | if (!node) |
1211 | return 0; |
1212 | |
1213 | return ice_set_object_tx_weight(pi: ice_get_pi_from_dev_rate(rate_node), |
1214 | node, weight: tx_weight, extack); |
1215 | } |
1216 | |
1217 | static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, |
1218 | struct devlink_rate *parent, |
1219 | void *priv, void *parent_priv, |
1220 | struct netlink_ext_ack *extack) |
1221 | { |
1222 | struct ice_port_info *pi = ice_get_pi_from_dev_rate(rate_node: devlink_rate); |
1223 | struct ice_sched_node *tc_node, *node, *parent_node; |
1224 | u16 num_nodes_added; |
1225 | u32 first_node_teid; |
1226 | u32 node_teid; |
1227 | int status; |
1228 | |
1229 | tc_node = pi->root->children[0]; |
1230 | node = priv; |
1231 | |
1232 | if (!extack) |
1233 | return 0; |
1234 | |
1235 | if (!ice_enable_custom_tx(pf: devlink_priv(devlink: devlink_rate->devlink))) |
1236 | return -EBUSY; |
1237 | |
1238 | if (!parent) { |
1239 | if (!node || tc_node == node || node->num_children) |
1240 | return -EINVAL; |
1241 | |
1242 | mutex_lock(&pi->sched_lock); |
1243 | ice_free_sched_node(pi, node); |
1244 | mutex_unlock(lock: &pi->sched_lock); |
1245 | |
1246 | return 0; |
1247 | } |
1248 | |
1249 | parent_node = parent_priv; |
1250 | |
1251 | /* if the node doesn't exist, create it */ |
1252 | if (!node->parent) { |
1253 | mutex_lock(&pi->sched_lock); |
1254 | status = ice_sched_add_elems(pi, tc_node, parent: parent_node, |
1255 | layer: parent_node->tx_sched_layer + 1, |
1256 | num_nodes: 1, num_nodes_added: &num_nodes_added, first_node_teid: &first_node_teid, |
1257 | prealloc_node: &node); |
1258 | mutex_unlock(lock: &pi->sched_lock); |
1259 | |
1260 | if (status) { |
1261 | NL_SET_ERR_MSG_MOD(extack, "Can't add a new node" ); |
1262 | return status; |
1263 | } |
1264 | |
1265 | if (devlink_rate->tx_share) |
1266 | ice_set_object_tx_share(pi, node, bw: devlink_rate->tx_share, extack); |
1267 | if (devlink_rate->tx_max) |
1268 | ice_set_object_tx_max(pi, node, bw: devlink_rate->tx_max, extack); |
1269 | if (devlink_rate->tx_priority) |
1270 | ice_set_object_tx_priority(pi, node, priority: devlink_rate->tx_priority, extack); |
1271 | if (devlink_rate->tx_weight) |
1272 | ice_set_object_tx_weight(pi, node, weight: devlink_rate->tx_weight, extack); |
1273 | } else { |
1274 | node_teid = le32_to_cpu(node->info.node_teid); |
1275 | mutex_lock(&pi->sched_lock); |
1276 | status = ice_sched_move_nodes(pi, parent: parent_node, num_items: 1, list: &node_teid); |
1277 | mutex_unlock(lock: &pi->sched_lock); |
1278 | |
1279 | if (status) |
1280 | NL_SET_ERR_MSG_MOD(extack, "Can't move existing node to a new parent" ); |
1281 | } |
1282 | |
1283 | return status; |
1284 | } |
1285 | |
1286 | /** |
1287 | * ice_devlink_reinit_up - do reinit of the given PF |
1288 | * @pf: pointer to the PF struct |
1289 | */ |
1290 | static int ice_devlink_reinit_up(struct ice_pf *pf) |
1291 | { |
1292 | struct ice_vsi *vsi = ice_get_main_vsi(pf); |
1293 | struct ice_vsi_cfg_params params; |
1294 | int err; |
1295 | |
1296 | err = ice_init_dev(pf); |
1297 | if (err) |
1298 | return err; |
1299 | |
1300 | params = ice_vsi_to_params(vsi); |
1301 | params.flags = ICE_VSI_FLAG_INIT; |
1302 | |
1303 | rtnl_lock(); |
1304 | err = ice_vsi_cfg(vsi, params: ¶ms); |
1305 | rtnl_unlock(); |
1306 | if (err) |
1307 | goto err_vsi_cfg; |
1308 | |
1309 | /* No need to take devl_lock, it's already taken by devlink API */ |
1310 | err = ice_load(pf); |
1311 | if (err) |
1312 | goto err_load; |
1313 | |
1314 | return 0; |
1315 | |
1316 | err_load: |
1317 | rtnl_lock(); |
1318 | ice_vsi_decfg(vsi); |
1319 | rtnl_unlock(); |
1320 | err_vsi_cfg: |
1321 | ice_deinit_dev(pf); |
1322 | return err; |
1323 | } |
1324 | |
1325 | /** |
1326 | * ice_devlink_reload_up - do reload up after reinit |
1327 | * @devlink: pointer to the devlink instance reloading |
1328 | * @action: the action requested |
1329 | * @limit: limits imposed by userspace, such as not resetting |
1330 | * @actions_performed: on return, indicate what actions actually performed |
1331 | * @extack: netlink extended ACK structure |
1332 | */ |
1333 | static int |
1334 | ice_devlink_reload_up(struct devlink *devlink, |
1335 | enum devlink_reload_action action, |
1336 | enum devlink_reload_limit limit, |
1337 | u32 *actions_performed, |
1338 | struct netlink_ext_ack *extack) |
1339 | { |
1340 | struct ice_pf *pf = devlink_priv(devlink); |
1341 | |
1342 | switch (action) { |
1343 | case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: |
1344 | *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); |
1345 | return ice_devlink_reinit_up(pf); |
1346 | case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: |
1347 | *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); |
1348 | return ice_devlink_reload_empr_finish(pf, extack); |
1349 | default: |
1350 | WARN_ON(1); |
1351 | return -EOPNOTSUPP; |
1352 | } |
1353 | } |
1354 | |
1355 | static const struct devlink_ops ice_devlink_ops = { |
1356 | .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, |
1357 | .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | |
1358 | BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), |
1359 | .reload_down = ice_devlink_reload_down, |
1360 | .reload_up = ice_devlink_reload_up, |
1361 | .eswitch_mode_get = ice_eswitch_mode_get, |
1362 | .eswitch_mode_set = ice_eswitch_mode_set, |
1363 | .info_get = ice_devlink_info_get, |
1364 | .flash_update = ice_devlink_flash_update, |
1365 | |
1366 | .rate_node_new = ice_devlink_rate_node_new, |
1367 | .rate_node_del = ice_devlink_rate_node_del, |
1368 | |
1369 | .rate_leaf_tx_max_set = ice_devlink_rate_leaf_tx_max_set, |
1370 | .rate_leaf_tx_share_set = ice_devlink_rate_leaf_tx_share_set, |
1371 | .rate_leaf_tx_priority_set = ice_devlink_rate_leaf_tx_priority_set, |
1372 | .rate_leaf_tx_weight_set = ice_devlink_rate_leaf_tx_weight_set, |
1373 | |
1374 | .rate_node_tx_max_set = ice_devlink_rate_node_tx_max_set, |
1375 | .rate_node_tx_share_set = ice_devlink_rate_node_tx_share_set, |
1376 | .rate_node_tx_priority_set = ice_devlink_rate_node_tx_priority_set, |
1377 | .rate_node_tx_weight_set = ice_devlink_rate_node_tx_weight_set, |
1378 | |
1379 | .rate_leaf_parent_set = ice_devlink_set_parent, |
1380 | .rate_node_parent_set = ice_devlink_set_parent, |
1381 | }; |
1382 | |
1383 | static int |
1384 | ice_devlink_enable_roce_get(struct devlink *devlink, u32 id, |
1385 | struct devlink_param_gset_ctx *ctx) |
1386 | { |
1387 | struct ice_pf *pf = devlink_priv(devlink); |
1388 | |
1389 | ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false; |
1390 | |
1391 | return 0; |
1392 | } |
1393 | |
1394 | static int |
1395 | ice_devlink_enable_roce_set(struct devlink *devlink, u32 id, |
1396 | struct devlink_param_gset_ctx *ctx) |
1397 | { |
1398 | struct ice_pf *pf = devlink_priv(devlink); |
1399 | bool roce_ena = ctx->val.vbool; |
1400 | int ret; |
1401 | |
1402 | if (!roce_ena) { |
1403 | ice_unplug_aux_dev(pf); |
1404 | pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; |
1405 | return 0; |
1406 | } |
1407 | |
1408 | pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; |
1409 | ret = ice_plug_aux_dev(pf); |
1410 | if (ret) |
1411 | pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; |
1412 | |
1413 | return ret; |
1414 | } |
1415 | |
1416 | static int |
1417 | ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id, |
1418 | union devlink_param_value val, |
1419 | struct netlink_ext_ack *extack) |
1420 | { |
1421 | struct ice_pf *pf = devlink_priv(devlink); |
1422 | |
1423 | if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) |
1424 | return -EOPNOTSUPP; |
1425 | |
1426 | if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) { |
1427 | NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously" ); |
1428 | return -EOPNOTSUPP; |
1429 | } |
1430 | |
1431 | return 0; |
1432 | } |
1433 | |
1434 | static int |
1435 | ice_devlink_enable_iw_get(struct devlink *devlink, u32 id, |
1436 | struct devlink_param_gset_ctx *ctx) |
1437 | { |
1438 | struct ice_pf *pf = devlink_priv(devlink); |
1439 | |
1440 | ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP; |
1441 | |
1442 | return 0; |
1443 | } |
1444 | |
1445 | static int |
1446 | ice_devlink_enable_iw_set(struct devlink *devlink, u32 id, |
1447 | struct devlink_param_gset_ctx *ctx) |
1448 | { |
1449 | struct ice_pf *pf = devlink_priv(devlink); |
1450 | bool iw_ena = ctx->val.vbool; |
1451 | int ret; |
1452 | |
1453 | if (!iw_ena) { |
1454 | ice_unplug_aux_dev(pf); |
1455 | pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; |
1456 | return 0; |
1457 | } |
1458 | |
1459 | pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP; |
1460 | ret = ice_plug_aux_dev(pf); |
1461 | if (ret) |
1462 | pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; |
1463 | |
1464 | return ret; |
1465 | } |
1466 | |
1467 | static int |
1468 | ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id, |
1469 | union devlink_param_value val, |
1470 | struct netlink_ext_ack *extack) |
1471 | { |
1472 | struct ice_pf *pf = devlink_priv(devlink); |
1473 | |
1474 | if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) |
1475 | return -EOPNOTSUPP; |
1476 | |
1477 | if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) { |
1478 | NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously" ); |
1479 | return -EOPNOTSUPP; |
1480 | } |
1481 | |
1482 | return 0; |
1483 | } |
1484 | |
1485 | static const struct devlink_param ice_devlink_params[] = { |
1486 | DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), |
1487 | ice_devlink_enable_roce_get, |
1488 | ice_devlink_enable_roce_set, |
1489 | ice_devlink_enable_roce_validate), |
1490 | DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME), |
1491 | ice_devlink_enable_iw_get, |
1492 | ice_devlink_enable_iw_set, |
1493 | ice_devlink_enable_iw_validate), |
1494 | |
1495 | }; |
1496 | |
1497 | static void ice_devlink_free(void *devlink_ptr) |
1498 | { |
1499 | devlink_free(devlink: (struct devlink *)devlink_ptr); |
1500 | } |
1501 | |
1502 | /** |
1503 | * ice_allocate_pf - Allocate devlink and return PF structure pointer |
1504 | * @dev: the device to allocate for |
1505 | * |
1506 | * Allocate a devlink instance for this device and return the private area as |
1507 | * the PF structure. The devlink memory is kept track of through devres by |
1508 | * adding an action to remove it when unwinding. |
1509 | */ |
1510 | struct ice_pf *ice_allocate_pf(struct device *dev) |
1511 | { |
1512 | struct devlink *devlink; |
1513 | |
1514 | devlink = devlink_alloc(ops: &ice_devlink_ops, priv_size: sizeof(struct ice_pf), dev); |
1515 | if (!devlink) |
1516 | return NULL; |
1517 | |
1518 | /* Add an action to teardown the devlink when unwinding the driver */ |
1519 | if (devm_add_action_or_reset(dev, ice_devlink_free, devlink)) |
1520 | return NULL; |
1521 | |
1522 | return devlink_priv(devlink); |
1523 | } |
1524 | |
1525 | /** |
1526 | * ice_devlink_register - Register devlink interface for this PF |
1527 | * @pf: the PF to register the devlink for. |
1528 | * |
1529 | * Register the devlink instance associated with this physical function. |
1530 | * |
1531 | * Return: zero on success or an error code on failure. |
1532 | */ |
1533 | void ice_devlink_register(struct ice_pf *pf) |
1534 | { |
1535 | struct devlink *devlink = priv_to_devlink(priv: pf); |
1536 | |
1537 | devlink_register(devlink); |
1538 | } |
1539 | |
1540 | /** |
1541 | * ice_devlink_unregister - Unregister devlink resources for this PF. |
1542 | * @pf: the PF structure to cleanup |
1543 | * |
1544 | * Releases resources used by devlink and cleans up associated memory. |
1545 | */ |
1546 | void ice_devlink_unregister(struct ice_pf *pf) |
1547 | { |
1548 | devlink_unregister(devlink: priv_to_devlink(priv: pf)); |
1549 | } |
1550 | |
1551 | /** |
1552 | * ice_devlink_set_switch_id - Set unique switch id based on pci dsn |
1553 | * @pf: the PF to create a devlink port for |
1554 | * @ppid: struct with switch id information |
1555 | */ |
1556 | static void |
1557 | ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid) |
1558 | { |
1559 | struct pci_dev *pdev = pf->pdev; |
1560 | u64 id; |
1561 | |
1562 | id = pci_get_dsn(dev: pdev); |
1563 | |
1564 | ppid->id_len = sizeof(id); |
1565 | put_unaligned_be64(val: id, p: &ppid->id); |
1566 | } |
1567 | |
1568 | int ice_devlink_register_params(struct ice_pf *pf) |
1569 | { |
1570 | struct devlink *devlink = priv_to_devlink(priv: pf); |
1571 | |
1572 | return devlink_params_register(devlink, params: ice_devlink_params, |
1573 | ARRAY_SIZE(ice_devlink_params)); |
1574 | } |
1575 | |
1576 | void ice_devlink_unregister_params(struct ice_pf *pf) |
1577 | { |
1578 | devlink_params_unregister(devlink: priv_to_devlink(priv: pf), params: ice_devlink_params, |
1579 | ARRAY_SIZE(ice_devlink_params)); |
1580 | } |
1581 | |
1582 | /** |
1583 | * ice_devlink_set_port_split_options - Set port split options |
1584 | * @pf: the PF to set port split options |
1585 | * @attrs: devlink attributes |
1586 | * |
1587 | * Sets devlink port split options based on available FW port options |
1588 | */ |
1589 | static void |
1590 | ice_devlink_set_port_split_options(struct ice_pf *pf, |
1591 | struct devlink_port_attrs *attrs) |
1592 | { |
1593 | struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX]; |
1594 | u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX; |
1595 | bool active_valid, pending_valid; |
1596 | int status; |
1597 | |
1598 | status = ice_aq_get_port_options(hw: &pf->hw, options, option_count: &option_count, |
1599 | lport: 0, lport_valid: true, active_option_idx: &active_idx, active_option_valid: &active_valid, |
1600 | pending_option_idx: &pending_idx, pending_option_valid: &pending_valid); |
1601 | if (status) { |
1602 | dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n" , |
1603 | status); |
1604 | return; |
1605 | } |
1606 | |
1607 | /* find the biggest available port split count */ |
1608 | for (i = 0; i < option_count; i++) |
1609 | attrs->lanes = max_t(int, attrs->lanes, options[i].pmd); |
1610 | |
1611 | attrs->splittable = attrs->lanes ? 1 : 0; |
1612 | ice_active_port_option = active_idx; |
1613 | } |
1614 | |
1615 | static const struct devlink_port_ops ice_devlink_port_ops = { |
1616 | .port_split = ice_devlink_port_split, |
1617 | .port_unsplit = ice_devlink_port_unsplit, |
1618 | }; |
1619 | |
1620 | /** |
1621 | * ice_devlink_create_pf_port - Create a devlink port for this PF |
1622 | * @pf: the PF to create a devlink port for |
1623 | * |
1624 | * Create and register a devlink_port for this PF. |
1625 | * This function has to be called under devl_lock. |
1626 | * |
1627 | * Return: zero on success or an error code on failure. |
1628 | */ |
1629 | int ice_devlink_create_pf_port(struct ice_pf *pf) |
1630 | { |
1631 | struct devlink_port_attrs attrs = {}; |
1632 | struct devlink_port *devlink_port; |
1633 | struct devlink *devlink; |
1634 | struct ice_vsi *vsi; |
1635 | struct device *dev; |
1636 | int err; |
1637 | |
1638 | devlink = priv_to_devlink(priv: pf); |
1639 | |
1640 | dev = ice_pf_to_dev(pf); |
1641 | |
1642 | devlink_port = &pf->devlink_port; |
1643 | |
1644 | vsi = ice_get_main_vsi(pf); |
1645 | if (!vsi) |
1646 | return -EIO; |
1647 | |
1648 | attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; |
1649 | attrs.phys.port_number = pf->hw.bus.func; |
1650 | |
1651 | /* As FW supports only port split options for whole device, |
1652 | * set port split options only for first PF. |
1653 | */ |
1654 | if (pf->hw.pf_id == 0) |
1655 | ice_devlink_set_port_split_options(pf, attrs: &attrs); |
1656 | |
1657 | ice_devlink_set_switch_id(pf, ppid: &attrs.switch_id); |
1658 | |
1659 | devlink_port_attrs_set(devlink_port, devlink_port_attrs: &attrs); |
1660 | |
1661 | err = devl_port_register_with_ops(devlink, devlink_port, port_index: vsi->idx, |
1662 | ops: &ice_devlink_port_ops); |
1663 | if (err) { |
1664 | dev_err(dev, "Failed to create devlink port for PF %d, error %d\n" , |
1665 | pf->hw.pf_id, err); |
1666 | return err; |
1667 | } |
1668 | |
1669 | return 0; |
1670 | } |
1671 | |
1672 | /** |
1673 | * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF |
1674 | * @pf: the PF to cleanup |
1675 | * |
1676 | * Unregisters the devlink_port structure associated with this PF. |
1677 | * This function has to be called under devl_lock. |
1678 | */ |
1679 | void ice_devlink_destroy_pf_port(struct ice_pf *pf) |
1680 | { |
1681 | devl_port_unregister(devlink_port: &pf->devlink_port); |
1682 | } |
1683 | |
1684 | /** |
1685 | * ice_devlink_create_vf_port - Create a devlink port for this VF |
1686 | * @vf: the VF to create a port for |
1687 | * |
1688 | * Create and register a devlink_port for this VF. |
1689 | * |
1690 | * Return: zero on success or an error code on failure. |
1691 | */ |
1692 | int ice_devlink_create_vf_port(struct ice_vf *vf) |
1693 | { |
1694 | struct devlink_port_attrs attrs = {}; |
1695 | struct devlink_port *devlink_port; |
1696 | struct devlink *devlink; |
1697 | struct ice_vsi *vsi; |
1698 | struct device *dev; |
1699 | struct ice_pf *pf; |
1700 | int err; |
1701 | |
1702 | pf = vf->pf; |
1703 | dev = ice_pf_to_dev(pf); |
1704 | devlink_port = &vf->devlink_port; |
1705 | |
1706 | vsi = ice_get_vf_vsi(vf); |
1707 | if (!vsi) |
1708 | return -EINVAL; |
1709 | |
1710 | attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; |
1711 | attrs.pci_vf.pf = pf->hw.bus.func; |
1712 | attrs.pci_vf.vf = vf->vf_id; |
1713 | |
1714 | ice_devlink_set_switch_id(pf, ppid: &attrs.switch_id); |
1715 | |
1716 | devlink_port_attrs_set(devlink_port, devlink_port_attrs: &attrs); |
1717 | devlink = priv_to_devlink(priv: pf); |
1718 | |
1719 | err = devlink_port_register(devlink, devlink_port, port_index: vsi->idx); |
1720 | if (err) { |
1721 | dev_err(dev, "Failed to create devlink port for VF %d, error %d\n" , |
1722 | vf->vf_id, err); |
1723 | return err; |
1724 | } |
1725 | |
1726 | return 0; |
1727 | } |
1728 | |
1729 | /** |
1730 | * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF |
1731 | * @vf: the VF to cleanup |
1732 | * |
1733 | * Unregisters the devlink_port structure associated with this VF. |
1734 | */ |
1735 | void ice_devlink_destroy_vf_port(struct ice_vf *vf) |
1736 | { |
1737 | devl_rate_leaf_destroy(devlink_port: &vf->devlink_port); |
1738 | devlink_port_unregister(devlink_port: &vf->devlink_port); |
1739 | } |
1740 | |
1741 | #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) |
1742 | |
1743 | static const struct devlink_region_ops ice_nvm_region_ops; |
1744 | static const struct devlink_region_ops ice_sram_region_ops; |
1745 | |
1746 | /** |
1747 | * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents |
1748 | * @devlink: the devlink instance |
1749 | * @ops: the devlink region to snapshot |
1750 | * @extack: extended ACK response structure |
1751 | * @data: on exit points to snapshot data buffer |
1752 | * |
1753 | * This function is called in response to a DEVLINK_CMD_REGION_NEW for either |
1754 | * the nvm-flash or shadow-ram region. |
1755 | * |
1756 | * It captures a snapshot of the NVM or Shadow RAM flash contents. This |
1757 | * snapshot can then later be viewed via the DEVLINK_CMD_REGION_READ netlink |
1758 | * interface. |
1759 | * |
1760 | * @returns zero on success, and updates the data pointer. Returns a non-zero |
1761 | * error code on failure. |
1762 | */ |
1763 | static int ice_devlink_nvm_snapshot(struct devlink *devlink, |
1764 | const struct devlink_region_ops *ops, |
1765 | struct netlink_ext_ack *extack, u8 **data) |
1766 | { |
1767 | struct ice_pf *pf = devlink_priv(devlink); |
1768 | struct device *dev = ice_pf_to_dev(pf); |
1769 | struct ice_hw *hw = &pf->hw; |
1770 | bool read_shadow_ram; |
1771 | u8 *nvm_data, *tmp, i; |
1772 | u32 nvm_size, left; |
1773 | s8 num_blks; |
1774 | int status; |
1775 | |
1776 | if (ops == &ice_nvm_region_ops) { |
1777 | read_shadow_ram = false; |
1778 | nvm_size = hw->flash.flash_size; |
1779 | } else if (ops == &ice_sram_region_ops) { |
1780 | read_shadow_ram = true; |
1781 | nvm_size = hw->flash.sr_words * 2u; |
1782 | } else { |
1783 | NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function" ); |
1784 | return -EOPNOTSUPP; |
1785 | } |
1786 | |
1787 | nvm_data = vzalloc(size: nvm_size); |
1788 | if (!nvm_data) |
1789 | return -ENOMEM; |
1790 | |
1791 | num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE); |
1792 | tmp = nvm_data; |
1793 | left = nvm_size; |
1794 | |
1795 | /* Some systems take longer to read the NVM than others which causes the |
1796 | * FW to reclaim the NVM lock before the entire NVM has been read. Fix |
1797 | * this by breaking the reads of the NVM into smaller chunks that will |
1798 | * probably not take as long. This has some overhead since we are |
1799 | * increasing the number of AQ commands, but it should always work |
1800 | */ |
1801 | for (i = 0; i < num_blks; i++) { |
1802 | u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left); |
1803 | |
1804 | status = ice_acquire_nvm(hw, access: ICE_RES_READ); |
1805 | if (status) { |
1806 | dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n" , |
1807 | status, hw->adminq.sq_last_status); |
1808 | NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore" ); |
1809 | vfree(addr: nvm_data); |
1810 | return -EIO; |
1811 | } |
1812 | |
1813 | status = ice_read_flat_nvm(hw, offset: i * ICE_DEVLINK_READ_BLK_SIZE, |
1814 | length: &read_sz, data: tmp, read_shadow_ram); |
1815 | if (status) { |
1816 | dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n" , |
1817 | read_sz, status, hw->adminq.sq_last_status); |
1818 | NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents" ); |
1819 | ice_release_nvm(hw); |
1820 | vfree(addr: nvm_data); |
1821 | return -EIO; |
1822 | } |
1823 | ice_release_nvm(hw); |
1824 | |
1825 | tmp += read_sz; |
1826 | left -= read_sz; |
1827 | } |
1828 | |
1829 | *data = nvm_data; |
1830 | |
1831 | return 0; |
1832 | } |
1833 | |
1834 | /** |
1835 | * ice_devlink_nvm_read - Read a portion of NVM flash contents |
1836 | * @devlink: the devlink instance |
1837 | * @ops: the devlink region to snapshot |
1838 | * @extack: extended ACK response structure |
1839 | * @offset: the offset to start at |
1840 | * @size: the amount to read |
1841 | * @data: the data buffer to read into |
1842 | * |
1843 | * This function is called in response to DEVLINK_CMD_REGION_READ to directly |
1844 | * read a section of the NVM contents. |
1845 | * |
1846 | * It reads from either the nvm-flash or shadow-ram region contents. |
1847 | * |
1848 | * @returns zero on success, and updates the data pointer. Returns a non-zero |
1849 | * error code on failure. |
1850 | */ |
1851 | static int ice_devlink_nvm_read(struct devlink *devlink, |
1852 | const struct devlink_region_ops *ops, |
1853 | struct netlink_ext_ack *extack, |
1854 | u64 offset, u32 size, u8 *data) |
1855 | { |
1856 | struct ice_pf *pf = devlink_priv(devlink); |
1857 | struct device *dev = ice_pf_to_dev(pf); |
1858 | struct ice_hw *hw = &pf->hw; |
1859 | bool read_shadow_ram; |
1860 | u64 nvm_size; |
1861 | int status; |
1862 | |
1863 | if (ops == &ice_nvm_region_ops) { |
1864 | read_shadow_ram = false; |
1865 | nvm_size = hw->flash.flash_size; |
1866 | } else if (ops == &ice_sram_region_ops) { |
1867 | read_shadow_ram = true; |
1868 | nvm_size = hw->flash.sr_words * 2u; |
1869 | } else { |
1870 | NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function" ); |
1871 | return -EOPNOTSUPP; |
1872 | } |
1873 | |
1874 | if (offset + size >= nvm_size) { |
1875 | NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size" ); |
1876 | return -ERANGE; |
1877 | } |
1878 | |
1879 | status = ice_acquire_nvm(hw, access: ICE_RES_READ); |
1880 | if (status) { |
1881 | dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n" , |
1882 | status, hw->adminq.sq_last_status); |
1883 | NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore" ); |
1884 | return -EIO; |
1885 | } |
1886 | |
1887 | status = ice_read_flat_nvm(hw, offset: (u32)offset, length: &size, data, |
1888 | read_shadow_ram); |
1889 | if (status) { |
1890 | dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n" , |
1891 | size, status, hw->adminq.sq_last_status); |
1892 | NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents" ); |
1893 | ice_release_nvm(hw); |
1894 | return -EIO; |
1895 | } |
1896 | ice_release_nvm(hw); |
1897 | |
1898 | return 0; |
1899 | } |
1900 | |
1901 | /** |
1902 | * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities |
1903 | * @devlink: the devlink instance |
1904 | * @ops: the devlink region being snapshotted |
1905 | * @extack: extended ACK response structure |
1906 | * @data: on exit points to snapshot data buffer |
1907 | * |
1908 | * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for |
1909 | * the device-caps devlink region. It captures a snapshot of the device |
1910 | * capabilities reported by firmware. |
1911 | * |
1912 | * @returns zero on success, and updates the data pointer. Returns a non-zero |
1913 | * error code on failure. |
1914 | */ |
1915 | static int |
1916 | ice_devlink_devcaps_snapshot(struct devlink *devlink, |
1917 | const struct devlink_region_ops *ops, |
1918 | struct netlink_ext_ack *extack, u8 **data) |
1919 | { |
1920 | struct ice_pf *pf = devlink_priv(devlink); |
1921 | struct device *dev = ice_pf_to_dev(pf); |
1922 | struct ice_hw *hw = &pf->hw; |
1923 | void *devcaps; |
1924 | int status; |
1925 | |
1926 | devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); |
1927 | if (!devcaps) |
1928 | return -ENOMEM; |
1929 | |
1930 | status = ice_aq_list_caps(hw, buf: devcaps, ICE_AQ_MAX_BUF_LEN, NULL, |
1931 | opc: ice_aqc_opc_list_dev_caps, NULL); |
1932 | if (status) { |
1933 | dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n" , |
1934 | status, hw->adminq.sq_last_status); |
1935 | NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities" ); |
1936 | vfree(addr: devcaps); |
1937 | return status; |
1938 | } |
1939 | |
1940 | *data = (u8 *)devcaps; |
1941 | |
1942 | return 0; |
1943 | } |
1944 | |
1945 | static const struct devlink_region_ops ice_nvm_region_ops = { |
1946 | .name = "nvm-flash" , |
1947 | .destructor = vfree, |
1948 | .snapshot = ice_devlink_nvm_snapshot, |
1949 | .read = ice_devlink_nvm_read, |
1950 | }; |
1951 | |
1952 | static const struct devlink_region_ops ice_sram_region_ops = { |
1953 | .name = "shadow-ram" , |
1954 | .destructor = vfree, |
1955 | .snapshot = ice_devlink_nvm_snapshot, |
1956 | .read = ice_devlink_nvm_read, |
1957 | }; |
1958 | |
1959 | static const struct devlink_region_ops ice_devcaps_region_ops = { |
1960 | .name = "device-caps" , |
1961 | .destructor = vfree, |
1962 | .snapshot = ice_devlink_devcaps_snapshot, |
1963 | }; |
1964 | |
1965 | /** |
1966 | * ice_devlink_init_regions - Initialize devlink regions |
1967 | * @pf: the PF device structure |
1968 | * |
1969 | * Create devlink regions used to enable access to dump the contents of the |
1970 | * flash memory on the device. |
1971 | */ |
1972 | void ice_devlink_init_regions(struct ice_pf *pf) |
1973 | { |
1974 | struct devlink *devlink = priv_to_devlink(priv: pf); |
1975 | struct device *dev = ice_pf_to_dev(pf); |
1976 | u64 nvm_size, sram_size; |
1977 | |
1978 | nvm_size = pf->hw.flash.flash_size; |
1979 | pf->nvm_region = devlink_region_create(devlink, ops: &ice_nvm_region_ops, region_max_snapshots: 1, |
1980 | region_size: nvm_size); |
1981 | if (IS_ERR(ptr: pf->nvm_region)) { |
1982 | dev_err(dev, "failed to create NVM devlink region, err %ld\n" , |
1983 | PTR_ERR(pf->nvm_region)); |
1984 | pf->nvm_region = NULL; |
1985 | } |
1986 | |
1987 | sram_size = pf->hw.flash.sr_words * 2u; |
1988 | pf->sram_region = devlink_region_create(devlink, ops: &ice_sram_region_ops, |
1989 | region_max_snapshots: 1, region_size: sram_size); |
1990 | if (IS_ERR(ptr: pf->sram_region)) { |
1991 | dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n" , |
1992 | PTR_ERR(pf->sram_region)); |
1993 | pf->sram_region = NULL; |
1994 | } |
1995 | |
1996 | pf->devcaps_region = devlink_region_create(devlink, |
1997 | ops: &ice_devcaps_region_ops, region_max_snapshots: 10, |
1998 | ICE_AQ_MAX_BUF_LEN); |
1999 | if (IS_ERR(ptr: pf->devcaps_region)) { |
2000 | dev_err(dev, "failed to create device-caps devlink region, err %ld\n" , |
2001 | PTR_ERR(pf->devcaps_region)); |
2002 | pf->devcaps_region = NULL; |
2003 | } |
2004 | } |
2005 | |
2006 | /** |
2007 | * ice_devlink_destroy_regions - Destroy devlink regions |
2008 | * @pf: the PF device structure |
2009 | * |
2010 | * Remove previously created regions for this PF. |
2011 | */ |
2012 | void ice_devlink_destroy_regions(struct ice_pf *pf) |
2013 | { |
2014 | if (pf->nvm_region) |
2015 | devlink_region_destroy(region: pf->nvm_region); |
2016 | |
2017 | if (pf->sram_region) |
2018 | devlink_region_destroy(region: pf->sram_region); |
2019 | |
2020 | if (pf->devcaps_region) |
2021 | devlink_region_destroy(region: pf->devcaps_region); |
2022 | } |
2023 | |