Linux Audio

Check our new training course

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