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