net: Don't include filter.h from net/sock.h
[linux-block.git] / drivers / net / ethernet / broadcom / bnxt / bnxt_devlink.c
CommitLineData
3c467bf3
SL
1/* Broadcom NetXtreme-C/E network driver.
2 *
3 * Copyright (c) 2017 Broadcom Limited
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation.
8 */
9
10#include <linux/pci.h>
11#include <linux/netdevice.h>
b6459415 12#include <linux/vmalloc.h>
477edb78 13#include <net/devlink.h>
3c467bf3
SL
14#include "bnxt_hsi.h"
15#include "bnxt.h"
3c8c20db 16#include "bnxt_hwrm.h"
3c467bf3
SL
17#include "bnxt_vfr.h"
18#include "bnxt_devlink.h"
d168f328 19#include "bnxt_ethtool.h"
228ea8c1
EP
20#include "bnxt_ulp.h"
21#include "bnxt_ptp.h"
188876db 22#include "bnxt_coredump.h"
d168f328 23
aadb0b1a
EP
24static void __bnxt_fw_recover(struct bnxt *bp)
25{
26 if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) ||
27 test_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state))
28 bnxt_fw_reset(bp);
29 else
30 bnxt_fw_exception(bp);
31}
32
d168f328 33static int
bc75c054
JK
34bnxt_dl_flash_update(struct devlink *dl,
35 struct devlink_flash_update_params *params,
36 struct netlink_ext_ack *extack)
d168f328
VV
37{
38 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
8159cbe3 39 int rc;
d168f328 40
d168f328
VV
41 if (!BNXT_PF(bp)) {
42 NL_SET_ERR_MSG_MOD(extack,
43 "flash update not supported from a VF");
44 return -EPERM;
45 }
46
22ec3d23 47 devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0);
b44cfd4f 48 rc = bnxt_flash_package_from_fw_obj(bp->dev, params->fw, 0);
8159cbe3 49 if (!rc)
22ec3d23 50 devlink_flash_update_status_notify(dl, "Flashing done", NULL, 0, 0);
8159cbe3 51 else
22ec3d23 52 devlink_flash_update_status_notify(dl, "Flashing failed", NULL, 0, 0);
8159cbe3 53 return rc;
d168f328 54}
3c467bf3 55
892a662f
EP
56static int bnxt_hwrm_remote_dev_reset_set(struct bnxt *bp, bool remote_reset)
57{
58 struct hwrm_func_cfg_input *req;
59 int rc;
60
61 if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
62 return -EOPNOTSUPP;
63
64 rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
65 if (rc)
66 return rc;
67
68 req->fid = cpu_to_le16(0xffff);
69 req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_HOT_RESET_IF_SUPPORT);
70 if (remote_reset)
71 req->flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_HOT_RESET_IF_EN_DIS);
72
73 return hwrm_req_send(bp, req);
74}
75
8cc95ceb
EP
76static char *bnxt_health_severity_str(enum bnxt_health_severity severity)
77{
78 switch (severity) {
79 case SEVERITY_NORMAL: return "normal";
80 case SEVERITY_WARNING: return "warning";
81 case SEVERITY_RECOVERABLE: return "recoverable";
82 case SEVERITY_FATAL: return "fatal";
83 default: return "unknown";
84 }
85}
86
87static char *bnxt_health_remedy_str(enum bnxt_health_remedy remedy)
88{
89 switch (remedy) {
90 case REMEDY_DEVLINK_RECOVER: return "devlink recover";
91 case REMEDY_POWER_CYCLE_DEVICE: return "device power cycle";
92 case REMEDY_POWER_CYCLE_HOST: return "host power cycle";
93 case REMEDY_FW_UPDATE: return "update firmware";
94 case REMEDY_HW_REPLACE: return "replace hardware";
95 default: return "unknown";
96 }
97}
98
2bb21b8d
EP
99static int bnxt_fw_diagnose(struct devlink_health_reporter *reporter,
100 struct devlink_fmsg *fmsg,
101 struct netlink_ext_ack *extack)
6763c779
VV
102{
103 struct bnxt *bp = devlink_health_reporter_priv(reporter);
8cc95ceb
EP
104 struct bnxt_fw_health *h = bp->fw_health;
105 u32 fw_status, fw_resets;
6763c779
VV
106 int rc;
107
0797c10d 108 if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
8cc95ceb 109 return devlink_fmsg_string_pair_put(fmsg, "Status", "recovering");
6763c779 110
8cc95ceb
EP
111 if (!h->status_reliable)
112 return devlink_fmsg_string_pair_put(fmsg, "Status", "unknown");
6763c779 113
8cc95ceb
EP
114 mutex_lock(&h->lock);
115 fw_status = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
116 if (BNXT_FW_IS_BOOTING(fw_status)) {
117 rc = devlink_fmsg_string_pair_put(fmsg, "Status", "initializing");
6763c779 118 if (rc)
8cc95ceb
EP
119 goto unlock;
120 } else if (h->severity || fw_status != BNXT_FW_STATUS_HEALTHY) {
121 if (!h->severity) {
122 h->severity = SEVERITY_FATAL;
123 h->remedy = REMEDY_POWER_CYCLE_DEVICE;
124 h->diagnoses++;
125 devlink_health_report(h->fw_reporter,
126 "FW error diagnosed", h);
127 }
128 rc = devlink_fmsg_string_pair_put(fmsg, "Status", "error");
6763c779 129 if (rc)
8cc95ceb
EP
130 goto unlock;
131 rc = devlink_fmsg_u32_pair_put(fmsg, "Syndrome", fw_status);
132 if (rc)
133 goto unlock;
134 } else {
135 rc = devlink_fmsg_string_pair_put(fmsg, "Status", "healthy");
136 if (rc)
137 goto unlock;
6763c779
VV
138 }
139
8cc95ceb
EP
140 rc = devlink_fmsg_string_pair_put(fmsg, "Severity",
141 bnxt_health_severity_str(h->severity));
142 if (rc)
143 goto unlock;
144
145 if (h->severity) {
146 rc = devlink_fmsg_string_pair_put(fmsg, "Remedy",
147 bnxt_health_remedy_str(h->remedy));
6763c779 148 if (rc)
8cc95ceb
EP
149 goto unlock;
150 if (h->remedy == REMEDY_DEVLINK_RECOVER) {
151 rc = devlink_fmsg_string_pair_put(fmsg, "Impact",
152 "traffic+ntuple_cfg");
153 if (rc)
154 goto unlock;
155 }
6763c779
VV
156 }
157
8cc95ceb
EP
158unlock:
159 mutex_unlock(&h->lock);
160 if (rc || !h->resets_reliable)
6763c779
VV
161 return rc;
162
8cc95ceb
EP
163 fw_resets = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
164 rc = devlink_fmsg_u32_pair_put(fmsg, "Resets", fw_resets);
165 if (rc)
166 return rc;
167 rc = devlink_fmsg_u32_pair_put(fmsg, "Arrests", h->arrests);
168 if (rc)
169 return rc;
170 rc = devlink_fmsg_u32_pair_put(fmsg, "Survivals", h->survivals);
171 if (rc)
172 return rc;
173 rc = devlink_fmsg_u32_pair_put(fmsg, "Discoveries", h->discoveries);
174 if (rc)
175 return rc;
176 rc = devlink_fmsg_u32_pair_put(fmsg, "Fatalities", h->fatalities);
177 if (rc)
178 return rc;
179 return devlink_fmsg_u32_pair_put(fmsg, "Diagnoses", h->diagnoses);
6763c779
VV
180}
181
188876db
EP
182static int bnxt_fw_dump(struct devlink_health_reporter *reporter,
183 struct devlink_fmsg *fmsg, void *priv_ctx,
184 struct netlink_ext_ack *extack)
185{
186 struct bnxt *bp = devlink_health_reporter_priv(reporter);
187 u32 dump_len;
188 void *data;
189 int rc;
190
191 /* TODO: no firmware dump support in devlink_health_report() context */
192 if (priv_ctx)
193 return -EOPNOTSUPP;
194
195 dump_len = bnxt_get_coredump_length(bp, BNXT_DUMP_LIVE);
196 if (!dump_len)
197 return -EIO;
198
199 data = vmalloc(dump_len);
200 if (!data)
201 return -ENOMEM;
202
203 rc = bnxt_get_coredump(bp, BNXT_DUMP_LIVE, data, &dump_len);
204 if (!rc) {
205 rc = devlink_fmsg_pair_nest_start(fmsg, "core");
206 if (rc)
207 goto exit;
208 rc = devlink_fmsg_binary_pair_put(fmsg, "data", data, dump_len);
209 if (rc)
210 goto exit;
211 rc = devlink_fmsg_u32_pair_put(fmsg, "size", dump_len);
212 if (rc)
213 goto exit;
214 rc = devlink_fmsg_pair_nest_end(fmsg);
215 }
216
217exit:
218 vfree(data);
219 return rc;
220}
221
2bb21b8d
EP
222static int bnxt_fw_recover(struct devlink_health_reporter *reporter,
223 void *priv_ctx,
224 struct netlink_ext_ack *extack)
acfb50e4
VV
225{
226 struct bnxt *bp = devlink_health_reporter_priv(reporter);
acfb50e4 227
8cc95ceb
EP
228 if (bp->fw_health->severity == SEVERITY_FATAL)
229 return -ENODEV;
230
aadb0b1a
EP
231 set_bit(BNXT_STATE_RECOVER, &bp->state);
232 __bnxt_fw_recover(bp);
acfb50e4 233
737d7a6c 234 return -EINPROGRESS;
acfb50e4
VV
235}
236
2bb21b8d
EP
237static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = {
238 .name = "fw",
239 .diagnose = bnxt_fw_diagnose,
188876db 240 .dump = bnxt_fw_dump,
2bb21b8d 241 .recover = bnxt_fw_recover,
acfb50e4
VV
242};
243
937f188c 244void bnxt_dl_fw_reporters_create(struct bnxt *bp)
6763c779
VV
245{
246 struct bnxt_fw_health *health = bp->fw_health;
247
2bb21b8d 248 if (!health || health->fw_reporter)
6763c779
VV
249 return;
250
2bb21b8d
EP
251 health->fw_reporter =
252 devlink_health_reporter_create(bp->dl, &bnxt_dl_fw_reporter_ops,
ba7d16c7 253 0, bp);
2bb21b8d
EP
254 if (IS_ERR(health->fw_reporter)) {
255 netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
256 PTR_ERR(health->fw_reporter));
257 health->fw_reporter = NULL;
937f188c 258 bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
acfb50e4 259 }
6763c779
VV
260}
261
937f188c 262void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
6763c779
VV
263{
264 struct bnxt_fw_health *health = bp->fw_health;
265
e624c70e 266 if (!health)
6763c779
VV
267 return;
268
937f188c
VV
269 if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && !all)
270 return;
271
272 if (health->fw_reporter) {
273 devlink_health_reporter_destroy(health->fw_reporter);
274 health->fw_reporter = NULL;
275 }
657a33c8
VV
276}
277
aadb0b1a 278void bnxt_devlink_health_fw_report(struct bnxt *bp)
657a33c8
VV
279{
280 struct bnxt_fw_health *fw_health = bp->fw_health;
8cc95ceb 281 int rc;
657a33c8 282
aadb0b1a 283 if (!fw_health)
657a33c8 284 return;
acfb50e4 285
2bb21b8d 286 if (!fw_health->fw_reporter) {
aadb0b1a 287 __bnxt_fw_recover(bp);
acfb50e4 288 return;
657a33c8 289 }
aadb0b1a 290
8cc95ceb
EP
291 mutex_lock(&fw_health->lock);
292 fw_health->severity = SEVERITY_RECOVERABLE;
293 fw_health->remedy = REMEDY_DEVLINK_RECOVER;
294 mutex_unlock(&fw_health->lock);
295 rc = devlink_health_report(fw_health->fw_reporter, "FW error reported",
296 fw_health);
297 if (rc == -ECANCELED)
298 __bnxt_fw_recover(bp);
6763c779
VV
299}
300
aadb0b1a 301void bnxt_dl_health_fw_status_update(struct bnxt *bp, bool healthy)
e4e38237 302{
8cc95ceb 303 struct bnxt_fw_health *fw_health = bp->fw_health;
e4e38237
VV
304 u8 state;
305
8cc95ceb
EP
306 mutex_lock(&fw_health->lock);
307 if (healthy) {
308 fw_health->severity = SEVERITY_NORMAL;
e4e38237 309 state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
8cc95ceb
EP
310 } else {
311 fw_health->severity = SEVERITY_FATAL;
312 fw_health->remedy = REMEDY_POWER_CYCLE_DEVICE;
e4e38237 313 state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
8cc95ceb
EP
314 }
315 mutex_unlock(&fw_health->lock);
316 devlink_health_reporter_state_update(fw_health->fw_reporter, state);
e4e38237
VV
317}
318
aadb0b1a 319void bnxt_dl_health_fw_recovery_done(struct bnxt *bp)
737d7a6c 320{
892a662f 321 struct bnxt_dl *dl = devlink_priv(bp->dl);
737d7a6c 322
2bb21b8d 323 devlink_health_reporter_recovery_done(bp->fw_health->fw_reporter);
892a662f 324 bnxt_hwrm_remote_dev_reset_set(bp, dl->remote_reset);
737d7a6c
VG
325}
326
9599e036
VV
327static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
328 struct netlink_ext_ack *extack);
329
3c415339
EP
330static void
331bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack,
332 struct hwrm_fw_livepatch_output *resp)
333{
334 int err = ((struct hwrm_err_output *)resp)->cmd_err;
335
336 switch (err) {
337 case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_OPCODE:
338 netdev_err(bp->dev, "Illegal live patch opcode");
339 NL_SET_ERR_MSG_MOD(extack, "Invalid opcode");
340 break;
341 case FW_LIVEPATCH_CMD_ERR_CODE_NOT_SUPPORTED:
342 NL_SET_ERR_MSG_MOD(extack, "Live patch operation not supported");
343 break;
344 case FW_LIVEPATCH_CMD_ERR_CODE_NOT_INSTALLED:
345 NL_SET_ERR_MSG_MOD(extack, "Live patch not found");
346 break;
347 case FW_LIVEPATCH_CMD_ERR_CODE_NOT_PATCHED:
348 NL_SET_ERR_MSG_MOD(extack,
349 "Live patch deactivation failed. Firmware not patched.");
350 break;
351 case FW_LIVEPATCH_CMD_ERR_CODE_AUTH_FAIL:
352 NL_SET_ERR_MSG_MOD(extack, "Live patch not authenticated");
353 break;
354 case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_HEADER:
355 NL_SET_ERR_MSG_MOD(extack, "Incompatible live patch");
356 break;
357 case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_SIZE:
358 NL_SET_ERR_MSG_MOD(extack, "Live patch has invalid size");
359 break;
360 case FW_LIVEPATCH_CMD_ERR_CODE_ALREADY_PATCHED:
361 NL_SET_ERR_MSG_MOD(extack, "Live patch already applied");
362 break;
363 default:
b68a1a93 364 netdev_err(bp->dev, "Unexpected live patch error: %d\n", err);
3c415339
EP
365 NL_SET_ERR_MSG_MOD(extack, "Failed to activate live patch");
366 break;
367 }
368}
369
370static int
371bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
372{
373 struct hwrm_fw_livepatch_query_output *query_resp;
374 struct hwrm_fw_livepatch_query_input *query_req;
375 struct hwrm_fw_livepatch_output *patch_resp;
376 struct hwrm_fw_livepatch_input *patch_req;
377 u32 installed = 0;
378 u16 flags;
379 u8 target;
380 int rc;
381
382 if (~bp->fw_cap & BNXT_FW_CAP_LIVEPATCH) {
383 NL_SET_ERR_MSG_MOD(extack, "Device does not support live patch");
384 return -EOPNOTSUPP;
385 }
386
387 rc = hwrm_req_init(bp, query_req, HWRM_FW_LIVEPATCH_QUERY);
388 if (rc)
389 return rc;
390 query_resp = hwrm_req_hold(bp, query_req);
391
392 rc = hwrm_req_init(bp, patch_req, HWRM_FW_LIVEPATCH);
393 if (rc) {
394 hwrm_req_drop(bp, query_req);
395 return rc;
396 }
397 patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE;
398 patch_req->loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL;
399 patch_resp = hwrm_req_hold(bp, patch_req);
400
401 for (target = 1; target <= FW_LIVEPATCH_REQ_FW_TARGET_LAST; target++) {
402 query_req->fw_target = target;
403 rc = hwrm_req_send(bp, query_req);
404 if (rc) {
405 NL_SET_ERR_MSG_MOD(extack, "Failed to query packages");
406 break;
407 }
408
409 flags = le16_to_cpu(query_resp->status_flags);
410 if (~flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL)
411 continue;
412 if ((flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE) &&
413 !strncmp(query_resp->active_ver, query_resp->install_ver,
414 sizeof(query_resp->active_ver)))
415 continue;
416
417 patch_req->fw_target = target;
418 rc = hwrm_req_send(bp, patch_req);
419 if (rc) {
420 bnxt_dl_livepatch_report_err(bp, extack, patch_resp);
421 break;
422 }
423 installed++;
424 }
425
426 if (!rc && !installed) {
427 NL_SET_ERR_MSG_MOD(extack, "No live patches found");
428 rc = -ENOENT;
429 }
430 hwrm_req_drop(bp, query_req);
431 hwrm_req_drop(bp, patch_req);
432 return rc;
433}
434
228ea8c1
EP
435static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
436 enum devlink_reload_action action,
437 enum devlink_reload_limit limit,
438 struct netlink_ext_ack *extack)
439{
440 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
441 int rc = 0;
442
443 switch (action) {
444 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: {
46d08f55 445 rtnl_lock();
9f536391 446 if (bnxt_sriov_cfg(bp)) {
228ea8c1 447 NL_SET_ERR_MSG_MOD(extack,
46d08f55
EP
448 "reload is unsupported while VFs are allocated or being configured");
449 rtnl_unlock();
228ea8c1
EP
450 return -EOPNOTSUPP;
451 }
228ea8c1
EP
452 if (bp->dev->reg_state == NETREG_UNREGISTERED) {
453 rtnl_unlock();
454 return -ENODEV;
455 }
456 bnxt_ulp_stop(bp);
457 if (netif_running(bp->dev)) {
458 rc = bnxt_close_nic(bp, true, true);
459 if (rc) {
460 NL_SET_ERR_MSG_MOD(extack, "Failed to close");
461 dev_close(bp->dev);
462 rtnl_unlock();
463 break;
464 }
465 }
466 bnxt_vf_reps_free(bp);
467 rc = bnxt_hwrm_func_drv_unrgtr(bp);
468 if (rc) {
469 NL_SET_ERR_MSG_MOD(extack, "Failed to deregister");
470 if (netif_running(bp->dev))
471 dev_close(bp->dev);
472 rtnl_unlock();
473 break;
474 }
475 bnxt_cancel_reservations(bp, false);
476 bnxt_free_ctx_mem(bp);
477 kfree(bp->ctx);
478 bp->ctx = NULL;
479 break;
480 }
8f6c5e4d 481 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: {
3c415339
EP
482 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
483 return bnxt_dl_livepatch_activate(bp, extack);
8f6c5e4d
EP
484 if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET) {
485 NL_SET_ERR_MSG_MOD(extack, "Device not capable, requires reboot");
486 return -EOPNOTSUPP;
487 }
892a662f
EP
488 if (!bnxt_hwrm_reset_permitted(bp)) {
489 NL_SET_ERR_MSG_MOD(extack,
490 "Reset denied by firmware, it may be inhibited by remote driver");
491 return -EPERM;
492 }
8f6c5e4d
EP
493 rtnl_lock();
494 if (bp->dev->reg_state == NETREG_UNREGISTERED) {
495 rtnl_unlock();
496 return -ENODEV;
497 }
498 if (netif_running(bp->dev))
499 set_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
500 rc = bnxt_hwrm_firmware_reset(bp->dev,
501 FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIP,
502 FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP,
503 FW_RESET_REQ_FLAGS_RESET_GRACEFUL |
504 FW_RESET_REQ_FLAGS_FW_ACTIVATION);
505 if (rc) {
506 NL_SET_ERR_MSG_MOD(extack, "Failed to activate firmware");
507 clear_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
508 rtnl_unlock();
509 }
510 break;
511 }
228ea8c1
EP
512 default:
513 rc = -EOPNOTSUPP;
514 }
515
516 return rc;
517}
518
519static int bnxt_dl_reload_up(struct devlink *dl, enum devlink_reload_action action,
520 enum devlink_reload_limit limit, u32 *actions_performed,
521 struct netlink_ext_ack *extack)
522{
523 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
524 int rc = 0;
525
526 *actions_performed = 0;
527 switch (action) {
528 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: {
529 bnxt_fw_init_one(bp);
530 bnxt_vf_reps_alloc(bp);
531 if (netif_running(bp->dev))
532 rc = bnxt_open_nic(bp, true, true);
533 bnxt_ulp_start(bp, rc);
534 if (!rc) {
535 bnxt_reenable_sriov(bp);
536 bnxt_ptp_reapply_pps(bp);
537 }
538 break;
539 }
8f6c5e4d
EP
540 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: {
541 unsigned long start = jiffies;
542 unsigned long timeout = start + BNXT_DFLT_FW_RST_MAX_DSECS * HZ / 10;
543
3c415339
EP
544 if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
545 break;
8f6c5e4d
EP
546 if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
547 timeout = start + bp->fw_health->normal_func_wait_dsecs * HZ / 10;
548 if (!netif_running(bp->dev))
549 NL_SET_ERR_MSG_MOD(extack,
550 "Device is closed, not waiting for reset notice that will never come");
551 rtnl_unlock();
552 while (test_bit(BNXT_STATE_FW_ACTIVATE, &bp->state)) {
553 if (time_after(jiffies, timeout)) {
554 NL_SET_ERR_MSG_MOD(extack, "Activation incomplete");
555 rc = -ETIMEDOUT;
556 break;
557 }
558 if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) {
559 NL_SET_ERR_MSG_MOD(extack, "Activation aborted");
560 rc = -ENODEV;
561 break;
562 }
563 msleep(50);
564 }
565 rtnl_lock();
566 if (!rc)
567 *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
568 clear_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
569 break;
570 }
228ea8c1
EP
571 default:
572 return -EOPNOTSUPP;
573 }
574
575 if (!rc) {
576 bnxt_print_device_info(bp);
577 if (netif_running(bp->dev)) {
578 mutex_lock(&bp->link_lock);
579 bnxt_report_link(bp);
580 mutex_unlock(&bp->link_lock);
581 }
582 *actions_performed |= BIT(action);
583 } else if (netif_running(bp->dev)) {
584 dev_close(bp->dev);
585 }
586 rtnl_unlock();
587 return rc;
588}
589
3c467bf3
SL
590static const struct devlink_ops bnxt_dl_ops = {
591#ifdef CONFIG_BNXT_SRIOV
592 .eswitch_mode_set = bnxt_dl_eswitch_mode_set,
593 .eswitch_mode_get = bnxt_dl_eswitch_mode_get,
594#endif /* CONFIG_BNXT_SRIOV */
9599e036 595 .info_get = bnxt_dl_info_get,
d168f328 596 .flash_update = bnxt_dl_flash_update,
8f6c5e4d
EP
597 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
598 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
3c415339 599 .reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET),
228ea8c1
EP
600 .reload_down = bnxt_dl_reload_down,
601 .reload_up = bnxt_dl_reload_up,
3c467bf3
SL
602};
603
7e334fc8
VV
604static const struct devlink_ops bnxt_vf_dl_ops;
605
2dc0865e
VV
606enum bnxt_dl_param_id {
607 BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
608 BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
609};
610
6354b95e
VV
611static const struct bnxt_dl_nvm_param nvm_params[] = {
612 {DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV,
c329230c 613 BNXT_NVM_SHARED_CFG, 1, 1},
7d859234 614 {DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI,
c329230c 615 BNXT_NVM_SHARED_CFG, 1, 1},
f399e849 616 {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
c329230c 617 NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4},
f399e849 618 {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
c329230c 619 NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4},
2dc0865e 620 {BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK,
c329230c 621 BNXT_NVM_SHARED_CFG, 1, 1},
6354b95e
VV
622};
623
83a46a82
MC
624union bnxt_nvm_data {
625 u8 val8;
626 __le32 val32;
627};
628
629static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst,
630 union devlink_param_value *src,
631 int nvm_num_bits, int dl_num_bytes)
632{
633 u32 val32 = 0;
634
635 if (nvm_num_bits == 1) {
636 dst->val8 = src->vbool;
637 return;
638 }
639 if (dl_num_bytes == 4)
640 val32 = src->vu32;
641 else if (dl_num_bytes == 2)
642 val32 = (u32)src->vu16;
643 else if (dl_num_bytes == 1)
644 val32 = (u32)src->vu8;
645 dst->val32 = cpu_to_le32(val32);
646}
647
648static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
649 union bnxt_nvm_data *src,
650 int nvm_num_bits, int dl_num_bytes)
651{
652 u32 val32;
653
654 if (nvm_num_bits == 1) {
655 dst->vbool = src->val8;
656 return;
657 }
658 val32 = le32_to_cpu(src->val32);
659 if (dl_num_bytes == 4)
660 dst->vu32 = val32;
661 else if (dl_num_bytes == 2)
662 dst->vu16 = (u16)val32;
663 else if (dl_num_bytes == 1)
664 dst->vu8 = (u8)val32;
665}
666
beb55fcf 667static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp, u32 *nvm_cfg_ver)
9599e036 668{
bbf33d1d 669 struct hwrm_nvm_get_variable_input *req;
beb55fcf
EP
670 u16 bytes = BNXT_NVM_CFG_VER_BYTES;
671 u16 bits = BNXT_NVM_CFG_VER_BITS;
672 union devlink_param_value ver;
9599e036
VV
673 union bnxt_nvm_data *data;
674 dma_addr_t data_dma_addr;
beb55fcf
EP
675 int rc, i = 2;
676 u16 dim = 1;
9599e036 677
bbf33d1d
EP
678 rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE);
679 if (rc)
680 return rc;
681
682 data = hwrm_req_dma_slice(bp, req, sizeof(*data), &data_dma_addr);
683 if (!data) {
684 rc = -ENOMEM;
685 goto exit;
686 }
9599e036 687
beb55fcf
EP
688 /* earlier devices present as an array of raw bytes */
689 if (!BNXT_CHIP_P5(bp)) {
690 dim = 0;
691 i = 0;
692 bits *= 3; /* array of 3 version components */
693 bytes *= 4; /* copy whole word */
694 }
695
bbf33d1d
EP
696 hwrm_req_hold(bp, req);
697 req->dest_data_addr = cpu_to_le64(data_dma_addr);
beb55fcf 698 req->data_len = cpu_to_le16(bits);
bbf33d1d 699 req->option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER);
beb55fcf 700 req->dimensions = cpu_to_le16(dim);
9599e036 701
beb55fcf
EP
702 while (i >= 0) {
703 req->index_0 = cpu_to_le16(i--);
704 rc = hwrm_req_send_silent(bp, req);
705 if (rc)
706 goto exit;
707 bnxt_copy_from_nvm_data(&ver, data, bits, bytes);
708
709 if (BNXT_CHIP_P5(bp)) {
710 *nvm_cfg_ver <<= 8;
711 *nvm_cfg_ver |= ver.vu8;
712 } else {
713 *nvm_cfg_ver = ver.vu32;
714 }
715 }
9599e036 716
bbf33d1d
EP
717exit:
718 hwrm_req_drop(bp, req);
9599e036
VV
719 return rc;
720}
721
7154917a
VV
722static int bnxt_dl_info_put(struct bnxt *bp, struct devlink_info_req *req,
723 enum bnxt_dl_version_type type, const char *key,
724 char *buf)
725{
726 if (!strlen(buf))
727 return 0;
728
729 if ((bp->flags & BNXT_FLAG_CHIP_P5) &&
730 (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
731 !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE)))
732 return 0;
733
734 switch (type) {
735 case BNXT_VERSION_FIXED:
736 return devlink_info_version_fixed_put(req, key, buf);
737 case BNXT_VERSION_RUNNING:
738 return devlink_info_version_running_put(req, key, buf);
739 case BNXT_VERSION_STORED:
740 return devlink_info_version_stored_put(req, key, buf);
741 }
742 return 0;
743}
744
3c415339
EP
745#define BNXT_FW_SRT_PATCH "fw.srt.patch"
746#define BNXT_FW_CRT_PATCH "fw.crt.patch"
747
748static int bnxt_dl_livepatch_info_put(struct bnxt *bp,
749 struct devlink_info_req *req,
750 const char *key)
751{
752 struct hwrm_fw_livepatch_query_input *query;
753 struct hwrm_fw_livepatch_query_output *resp;
754 u16 flags;
755 int rc;
756
757 if (~bp->fw_cap & BNXT_FW_CAP_LIVEPATCH)
758 return 0;
759
760 rc = hwrm_req_init(bp, query, HWRM_FW_LIVEPATCH_QUERY);
761 if (rc)
762 return rc;
763
764 if (!strcmp(key, BNXT_FW_SRT_PATCH))
765 query->fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_SECURE_FW;
766 else if (!strcmp(key, BNXT_FW_CRT_PATCH))
767 query->fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_COMMON_FW;
768 else
769 goto exit;
770
771 resp = hwrm_req_hold(bp, query);
772 rc = hwrm_req_send(bp, query);
773 if (rc)
774 goto exit;
775
776 flags = le16_to_cpu(resp->status_flags);
777 if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE) {
778 resp->active_ver[sizeof(resp->active_ver) - 1] = '\0';
779 rc = devlink_info_version_running_put(req, key, resp->active_ver);
780 if (rc)
781 goto exit;
782 }
783
784 if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL) {
785 resp->install_ver[sizeof(resp->install_ver) - 1] = '\0';
786 rc = devlink_info_version_stored_put(req, key, resp->install_ver);
787 if (rc)
788 goto exit;
789 }
790
791exit:
792 hwrm_req_drop(bp, query);
793 return rc;
794}
795
7154917a
VV
796#define HWRM_FW_VER_STR_LEN 16
797
9599e036
VV
798static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
799 struct netlink_ext_ack *extack)
800{
1388875b 801 struct hwrm_nvm_get_dev_info_output nvm_dev_info;
9599e036 802 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
9599e036
VV
803 struct hwrm_ver_get_output *ver_resp;
804 char mgmt_ver[FW_VER_STR_LEN];
805 char roce_ver[FW_VER_STR_LEN];
7154917a 806 char ncsi_ver[FW_VER_STR_LEN];
9599e036 807 char buf[32];
beb55fcf 808 u32 ver = 0;
9599e036
VV
809 int rc;
810
811 rc = devlink_info_driver_name_put(req, DRV_MODULE_NAME);
812 if (rc)
813 return rc;
814
7154917a
VV
815 if (BNXT_PF(bp) && (bp->flags & BNXT_FLAG_DSN_VALID)) {
816 sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
817 bp->dsn[7], bp->dsn[6], bp->dsn[5], bp->dsn[4],
818 bp->dsn[3], bp->dsn[2], bp->dsn[1], bp->dsn[0]);
819 rc = devlink_info_serial_number_put(req, buf);
56d69c78
VV
820 if (rc)
821 return rc;
822 }
823
9bf88b9f
VV
824 if (strlen(bp->board_serialno)) {
825 rc = devlink_info_board_serial_number_put(req, bp->board_serialno);
826 if (rc)
827 return rc;
828 }
829
7154917a
VV
830 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
831 DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
832 bp->board_partno);
833 if (rc)
834 return rc;
835
9599e036 836 sprintf(buf, "%X", bp->chip_num);
7154917a
VV
837 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
838 DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
9599e036
VV
839 if (rc)
840 return rc;
841
842 ver_resp = &bp->ver_resp;
6fdab8a3 843 sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
7154917a
VV
844 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
845 DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
9599e036
VV
846 if (rc)
847 return rc;
848
1388875b
VV
849 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
850 DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
851 bp->nvm_cfg_ver);
852 if (rc)
853 return rc;
854
7154917a
VV
855 buf[0] = 0;
856 strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
857 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
858 DEVLINK_INFO_VERSION_GENERIC_FW, buf);
859 if (rc)
860 return rc;
9599e036 861
beb55fcf 862 if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &ver)) {
1656db67
EP
863 sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xff, (ver >> 8) & 0xff,
864 ver & 0xff);
1388875b 865 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
7154917a
VV
866 DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
867 buf);
9599e036
VV
868 if (rc)
869 return rc;
870 }
871
872 if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
7154917a 873 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
9599e036
VV
874 ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
875 ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
876
7154917a 877 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
9599e036
VV
878 ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
879 ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
880
881 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
882 ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
883 ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
884 } else {
7154917a 885 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
9599e036
VV
886 ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
887 ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
888
7154917a 889 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
9599e036
VV
890 ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
891 ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
892
893 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
894 ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
895 ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
896 }
7154917a
VV
897 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
898 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
9599e036
VV
899 if (rc)
900 return rc;
901
7154917a
VV
902 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
903 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
904 bp->hwrm_ver_supp);
b7a444f0
VV
905 if (rc)
906 return rc;
907
7154917a
VV
908 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
909 DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
910 if (rc)
911 return rc;
9599e036 912
1388875b
VV
913 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
914 DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
915 if (rc)
916 return rc;
917
918 rc = bnxt_hwrm_nvm_get_dev_info(bp, &nvm_dev_info);
919 if (rc ||
63185eb3
VG
920 !(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID)) {
921 if (!bnxt_get_pkginfo(bp->dev, buf, sizeof(buf)))
922 return bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
923 DEVLINK_INFO_VERSION_GENERIC_FW,
924 buf);
1388875b 925 return 0;
63185eb3 926 }
1388875b
VV
927
928 buf[0] = 0;
929 strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
930 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
931 DEVLINK_INFO_VERSION_GENERIC_FW, buf);
932 if (rc)
933 return rc;
934
935 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
936 nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
937 nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
938 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
939 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
940 if (rc)
941 return rc;
942
943 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
944 nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
945 nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
946 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
947 DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
948 if (rc)
949 return rc;
950
951 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
952 nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
953 nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
3c415339
EP
954 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
955 DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
956 if (rc)
957 return rc;
958
959 rc = bnxt_dl_livepatch_info_put(bp, req, BNXT_FW_SRT_PATCH);
960 if (rc)
961 return rc;
962 return bnxt_dl_livepatch_info_put(bp, req, BNXT_FW_CRT_PATCH);
963
9599e036
VV
964}
965
6354b95e 966static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
bbf33d1d 967 union devlink_param_value *val)
6354b95e 968{
6fc92c33 969 struct hwrm_nvm_get_variable_input *req = msg;
6354b95e 970 struct bnxt_dl_nvm_param nvm_param;
bbf33d1d 971 struct hwrm_err_output *resp;
83a46a82 972 union bnxt_nvm_data *data;
6354b95e 973 dma_addr_t data_dma_addr;
c329230c 974 int idx = 0, rc, i;
6354b95e
VV
975
976 /* Get/Set NVM CFG parameter is supported only on PFs */
bbf33d1d
EP
977 if (BNXT_VF(bp)) {
978 hwrm_req_drop(bp, req);
6354b95e 979 return -EPERM;
bbf33d1d 980 }
6354b95e
VV
981
982 for (i = 0; i < ARRAY_SIZE(nvm_params); i++) {
983 if (nvm_params[i].id == param_id) {
984 nvm_param = nvm_params[i];
985 break;
986 }
987 }
988
bbf33d1d
EP
989 if (i == ARRAY_SIZE(nvm_params)) {
990 hwrm_req_drop(bp, req);
65fac4fe 991 return -EOPNOTSUPP;
bbf33d1d 992 }
65fac4fe 993
6354b95e
VV
994 if (nvm_param.dir_type == BNXT_NVM_PORT_CFG)
995 idx = bp->pf.port_id;
996 else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
997 idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
998
bbf33d1d
EP
999 data = hwrm_req_dma_slice(bp, req, sizeof(*data), &data_dma_addr);
1000
1001 if (!data) {
1002 hwrm_req_drop(bp, req);
6354b95e 1003 return -ENOMEM;
bbf33d1d 1004 }
6354b95e 1005
6fc92c33 1006 req->dest_data_addr = cpu_to_le64(data_dma_addr);
c329230c 1007 req->data_len = cpu_to_le16(nvm_param.nvm_num_bits);
6354b95e
VV
1008 req->option_num = cpu_to_le16(nvm_param.offset);
1009 req->index_0 = cpu_to_le16(idx);
1010 if (idx)
1011 req->dimensions = cpu_to_le16(1);
1012
bbf33d1d 1013 resp = hwrm_req_hold(bp, req);
b703ba75 1014 if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
83a46a82
MC
1015 bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits,
1016 nvm_param.dl_num_bytes);
bbf33d1d 1017 rc = hwrm_req_send(bp, msg);
b703ba75 1018 } else {
bbf33d1d 1019 rc = hwrm_req_send_silent(bp, msg);
05069dd4 1020 if (!rc) {
83a46a82
MC
1021 bnxt_copy_from_nvm_data(val, data,
1022 nvm_param.nvm_num_bits,
1023 nvm_param.dl_num_bytes);
05069dd4 1024 } else {
05069dd4
VV
1025 if (resp->cmd_err ==
1026 NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST)
1027 rc = -EOPNOTSUPP;
1028 }
b703ba75 1029 }
bbf33d1d 1030 hwrm_req_drop(bp, req);
d4f1420d 1031 if (rc == -EACCES)
3a1d52a5 1032 netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n");
d4f1420d 1033 return rc;
6354b95e
VV
1034}
1035
1036static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
1037 struct devlink_param_gset_ctx *ctx)
1038{
6354b95e 1039 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
bbf33d1d 1040 struct hwrm_nvm_get_variable_input *req;
2dc0865e 1041 int rc;
6354b95e 1042
bbf33d1d
EP
1043 rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE);
1044 if (rc)
1045 return rc;
1046
1047 rc = bnxt_hwrm_nvm_req(bp, id, req, &ctx->val);
1048 if (!rc && id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
1049 ctx->val.vbool = !ctx->val.vbool;
2dc0865e
VV
1050
1051 return rc;
6354b95e
VV
1052}
1053
1054static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
1055 struct devlink_param_gset_ctx *ctx)
1056{
6354b95e 1057 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
bbf33d1d
EP
1058 struct hwrm_nvm_set_variable_input *req;
1059 int rc;
6354b95e 1060
bbf33d1d
EP
1061 rc = hwrm_req_init(bp, req, HWRM_NVM_SET_VARIABLE);
1062 if (rc)
1063 return rc;
2dc0865e
VV
1064
1065 if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
1066 ctx->val.vbool = !ctx->val.vbool;
1067
bbf33d1d 1068 return bnxt_hwrm_nvm_req(bp, id, req, &ctx->val);
6354b95e
VV
1069}
1070
f399e849
VV
1071static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
1072 union devlink_param_value val,
1073 struct netlink_ext_ack *extack)
1074{
5fc7c12f 1075 int max_val = -1;
f399e849
VV
1076
1077 if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX)
1078 max_val = BNXT_MSIX_VEC_MAX;
1079
1080 if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN)
1081 max_val = BNXT_MSIX_VEC_MIN_MAX;
1082
5fc7c12f 1083 if (val.vu32 > max_val) {
f399e849
VV
1084 NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range");
1085 return -EINVAL;
1086 }
1087
1088 return 0;
1089}
1090
892a662f
EP
1091static int bnxt_remote_dev_reset_get(struct devlink *dl, u32 id,
1092 struct devlink_param_gset_ctx *ctx)
1093{
1094 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
1095
1096 if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
1097 return -EOPNOTSUPP;
1098
1099 ctx->val.vbool = bnxt_dl_get_remote_reset(dl);
1100 return 0;
1101}
1102
1103static int bnxt_remote_dev_reset_set(struct devlink *dl, u32 id,
1104 struct devlink_param_gset_ctx *ctx)
1105{
1106 struct bnxt *bp = bnxt_get_bp_from_dl(dl);
1107 int rc;
1108
1109 rc = bnxt_hwrm_remote_dev_reset_set(bp, ctx->val.vbool);
1110 if (rc)
1111 return rc;
1112
1113 bnxt_dl_set_remote_reset(dl, ctx->val.vbool);
1114 return rc;
1115}
1116
6354b95e
VV
1117static const struct devlink_param bnxt_dl_params[] = {
1118 DEVLINK_PARAM_GENERIC(ENABLE_SRIOV,
1119 BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1120 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1121 NULL),
7d859234
VV
1122 DEVLINK_PARAM_GENERIC(IGNORE_ARI,
1123 BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1124 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1125 NULL),
f399e849
VV
1126 DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX,
1127 BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1128 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1129 bnxt_dl_msix_validate),
1130 DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN,
1131 BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1132 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1133 bnxt_dl_msix_validate),
2dc0865e
VV
1134 DEVLINK_PARAM_DRIVER(BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
1135 "gre_ver_check", DEVLINK_PARAM_TYPE_BOOL,
1136 BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1137 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1138 NULL),
892a662f
EP
1139 /* keep REMOTE_DEV_RESET last, it is excluded based on caps */
1140 DEVLINK_PARAM_GENERIC(ENABLE_REMOTE_DEV_RESET,
1141 BIT(DEVLINK_PARAM_CMODE_RUNTIME),
1142 bnxt_remote_dev_reset_get,
1143 bnxt_remote_dev_reset_set, NULL),
6354b95e
VV
1144};
1145
d6292ade
VV
1146static int bnxt_dl_params_register(struct bnxt *bp)
1147{
892a662f 1148 int num_params = ARRAY_SIZE(bnxt_dl_params);
d6292ade
VV
1149 int rc;
1150
002870eb
VV
1151 if (bp->hwrm_spec_code < 0x10600)
1152 return 0;
1153
892a662f
EP
1154 if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
1155 num_params--;
1156
1157 rc = devlink_params_register(bp->dl, bnxt_dl_params, num_params);
5df290e7 1158 if (rc)
9a005c38 1159 netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n",
d6292ade 1160 rc);
5df290e7 1161 return rc;
d6292ade
VV
1162}
1163
1164static void bnxt_dl_params_unregister(struct bnxt *bp)
1165{
892a662f
EP
1166 int num_params = ARRAY_SIZE(bnxt_dl_params);
1167
002870eb
VV
1168 if (bp->hwrm_spec_code < 0x10600)
1169 return;
1170
892a662f
EP
1171 if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
1172 num_params--;
1173
1174 devlink_params_unregister(bp->dl, bnxt_dl_params, num_params);
d6292ade
VV
1175}
1176
3c467bf3
SL
1177int bnxt_dl_register(struct bnxt *bp)
1178{
919d13a7 1179 const struct devlink_ops *devlink_ops;
71ad8d55 1180 struct devlink_port_attrs attrs = {};
e624c70e 1181 struct bnxt_dl *bp_dl;
3c467bf3
SL
1182 struct devlink *dl;
1183 int rc;
1184
7e334fc8 1185 if (BNXT_PF(bp))
919d13a7 1186 devlink_ops = &bnxt_dl_ops;
7e334fc8 1187 else
919d13a7
LR
1188 devlink_ops = &bnxt_vf_dl_ops;
1189
1190 dl = devlink_alloc(devlink_ops, sizeof(struct bnxt_dl), &bp->pdev->dev);
3c467bf3 1191 if (!dl) {
9a005c38 1192 netdev_warn(bp->dev, "devlink_alloc failed\n");
3c467bf3
SL
1193 return -ENOMEM;
1194 }
1195
e624c70e
LR
1196 bp->dl = dl;
1197 bp_dl = devlink_priv(dl);
1198 bp_dl->bp = bp;
892a662f 1199 bnxt_dl_set_remote_reset(dl, true);
6354b95e
VV
1200
1201 /* Add switchdev eswitch mode setting, if SRIOV supported */
1202 if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) &&
1203 bp->hwrm_spec_code > 0x10803)
1204 bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
1205
7e334fc8 1206 if (!BNXT_PF(bp))
5df290e7 1207 goto out;
7e334fc8 1208
71ad8d55
DR
1209 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
1210 attrs.phys.port_number = bp->pf.port_id;
1211 memcpy(attrs.switch_id.id, bp->dsn, sizeof(bp->dsn));
1212 attrs.switch_id.id_len = sizeof(bp->dsn);
1213 devlink_port_attrs_set(&bp->dl_port, &attrs);
782a624d
VV
1214 rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
1215 if (rc) {
9a005c38 1216 netdev_err(bp->dev, "devlink_port_register failed\n");
db4278c5 1217 goto err_dl_free;
782a624d 1218 }
782a624d 1219
d6292ade
VV
1220 rc = bnxt_dl_params_register(bp);
1221 if (rc)
782a624d 1222 goto err_dl_port_unreg;
7c62cfb8 1223
5df290e7
LR
1224out:
1225 devlink_register(dl);
3c467bf3 1226 return 0;
6354b95e 1227
782a624d
VV
1228err_dl_port_unreg:
1229 devlink_port_unregister(&bp->dl_port);
6354b95e 1230err_dl_free:
6354b95e
VV
1231 devlink_free(dl);
1232 return rc;
3c467bf3
SL
1233}
1234
1235void bnxt_dl_unregister(struct bnxt *bp)
1236{
1237 struct devlink *dl = bp->dl;
1238
5df290e7 1239 devlink_unregister(dl);
7e334fc8 1240 if (BNXT_PF(bp)) {
d6292ade 1241 bnxt_dl_params_unregister(bp);
7e334fc8 1242 devlink_port_unregister(&bp->dl_port);
7e334fc8 1243 }
3c467bf3
SL
1244 devlink_free(dl);
1245}