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.4
  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
 18static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
 19				     struct devlink_fmsg *fmsg)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 20{
 21	struct bnxt *bp = devlink_health_reporter_priv(reporter);
 22	struct bnxt_fw_health *health = bp->fw_health;
 23	u32 val, health_status;
 24	int rc;
 25
 26	if (!health || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
 
 27		return 0;
 
 28
 29	val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
 30	health_status = val & 0xffff;
 
 
 31
 32	if (health_status < BNXT_FW_STATUS_HEALTHY) {
 33		rc = devlink_fmsg_string_pair_put(fmsg, "Description",
 34						  "Not yet completed initialization");
 35		if (rc)
 36			return rc;
 37	} else if (health_status > BNXT_FW_STATUS_HEALTHY) {
 38		rc = devlink_fmsg_string_pair_put(fmsg, "Description",
 39						  "Encountered fatal error and cannot recover");
 40		if (rc)
 41			return rc;
 
 
 
 
 
 
 42	}
 43
 44	if (val >> 16) {
 45		rc = devlink_fmsg_u32_pair_put(fmsg, "Error code", val >> 16);
 46		if (rc)
 47			return rc;
 
 
 
 
 
 48	}
 49
 50	val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
 51	rc = devlink_fmsg_u32_pair_put(fmsg, "Reset count", val);
 52	if (rc)
 53		return rc;
 54
 
 
 
 
 
 
 
 55	return 0;
 56}
 57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 58static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = {
 59	.name = "fw",
 60	.diagnose = bnxt_fw_reporter_diagnose,
 
 
 61};
 62
 63static int bnxt_fw_reset_recover(struct devlink_health_reporter *reporter,
 64				 void *priv_ctx)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 65{
 66	struct bnxt *bp = devlink_health_reporter_priv(reporter);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 67
 68	if (!priv_ctx)
 69		return -EOPNOTSUPP;
 
 
 70
 71	bnxt_fw_reset(bp);
 72	return 0;
 
 
 
 
 
 
 73}
 74
 75static const
 76struct devlink_health_reporter_ops bnxt_dl_fw_reset_reporter_ops = {
 77	.name = "fw_reset",
 78	.recover = bnxt_fw_reset_recover,
 79};
 
 
 
 
 
 
 
 
 
 
 
 
 80
 81static int bnxt_fw_fatal_recover(struct devlink_health_reporter *reporter,
 82				 void *priv_ctx)
 83{
 84	struct bnxt *bp = devlink_health_reporter_priv(reporter);
 85	struct bnxt_fw_reporter_ctx *fw_reporter_ctx = priv_ctx;
 86	unsigned long event;
 
 
 87
 88	if (!priv_ctx)
 89		return -EOPNOTSUPP;
 90
 91	event = fw_reporter_ctx->sp_event;
 92	if (event == BNXT_FW_RESET_NOTIFY_SP_EVENT)
 93		bnxt_fw_reset(bp);
 94	else if (event == BNXT_FW_EXCEPTION_SP_EVENT)
 95		bnxt_fw_exception(bp);
 96
 97	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 98}
 99
100static const
101struct devlink_health_reporter_ops bnxt_dl_fw_fatal_reporter_ops = {
102	.name = "fw_fatal",
103	.recover = bnxt_fw_fatal_recover,
104};
 
 
 
 
105
106static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
 
107{
108	struct bnxt_fw_health *health = bp->fw_health;
 
 
 
 
 
 
 
 
 
 
 
 
 
109
110	if (!health)
111		return;
 
 
112
113	health->fw_reporter =
114		devlink_health_reporter_create(bp->dl, &bnxt_dl_fw_reporter_ops,
115					       0, false, bp);
116	if (IS_ERR(health->fw_reporter)) {
117		netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
118			    PTR_ERR(health->fw_reporter));
119		health->fw_reporter = NULL;
120	}
 
 
 
 
 
 
 
 
 
 
121
122	health->fw_reset_reporter =
123		devlink_health_reporter_create(bp->dl,
124					       &bnxt_dl_fw_reset_reporter_ops,
125					       0, true, bp);
126	if (IS_ERR(health->fw_reset_reporter)) {
127		netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
128			    PTR_ERR(health->fw_reset_reporter));
129		health->fw_reset_reporter = NULL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130	}
131
132	health->fw_fatal_reporter =
133		devlink_health_reporter_create(bp->dl,
134					       &bnxt_dl_fw_fatal_reporter_ops,
135					       0, true, bp);
136	if (IS_ERR(health->fw_fatal_reporter)) {
137		netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
138			    PTR_ERR(health->fw_fatal_reporter));
139		health->fw_fatal_reporter = NULL;
140	}
 
 
 
141}
142
143static void bnxt_dl_fw_reporters_destroy(struct bnxt *bp)
 
 
 
144{
145	struct bnxt_fw_health *health = bp->fw_health;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
147	if (!health)
148		return;
 
 
 
 
149
150	if (health->fw_reporter)
151		devlink_health_reporter_destroy(health->fw_reporter);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
153	if (health->fw_reset_reporter)
154		devlink_health_reporter_destroy(health->fw_reset_reporter);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
156	if (health->fw_fatal_reporter)
157		devlink_health_reporter_destroy(health->fw_fatal_reporter);
 
 
 
 
 
 
 
 
 
 
 
158}
159
160void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
161{
162	struct bnxt_fw_health *fw_health = bp->fw_health;
163	struct bnxt_fw_reporter_ctx fw_reporter_ctx;
 
 
 
 
 
 
 
 
 
164
165	if (!fw_health)
166		return;
 
 
 
167
168	fw_reporter_ctx.sp_event = event;
169	switch (event) {
170	case BNXT_FW_RESET_NOTIFY_SP_EVENT:
171		if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) {
172			if (!fw_health->fw_fatal_reporter)
173				return;
174
175			devlink_health_report(fw_health->fw_fatal_reporter,
176					      "FW fatal async event received",
177					      &fw_reporter_ctx);
178			return;
179		}
180		if (!fw_health->fw_reset_reporter)
181			return;
182
183		devlink_health_report(fw_health->fw_reset_reporter,
184				      "FW non-fatal reset event received",
185				      &fw_reporter_ctx);
186		return;
187
188	case BNXT_FW_EXCEPTION_SP_EVENT:
189		if (!fw_health->fw_fatal_reporter)
190			return;
191
192		devlink_health_report(fw_health->fw_fatal_reporter,
193				      "FW fatal error reported",
194				      &fw_reporter_ctx);
195		return;
196	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197}
198
199static const struct devlink_ops bnxt_dl_ops = {
200#ifdef CONFIG_BNXT_SRIOV
201	.eswitch_mode_set = bnxt_dl_eswitch_mode_set,
202	.eswitch_mode_get = bnxt_dl_eswitch_mode_get,
203#endif /* CONFIG_BNXT_SRIOV */
 
 
 
 
 
 
 
 
 
204};
205
 
 
206enum bnxt_dl_param_id {
207	BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
208	BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
209};
210
211static const struct bnxt_dl_nvm_param nvm_params[] = {
212	{DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV,
213	 BNXT_NVM_SHARED_CFG, 1, 1},
214	{DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI,
215	 BNXT_NVM_SHARED_CFG, 1, 1},
216	{DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
217	 NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4},
218	{DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
219	 NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4},
220	{BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK,
221	 BNXT_NVM_SHARED_CFG, 1, 1},
222};
223
224union bnxt_nvm_data {
225	u8	val8;
226	__le32	val32;
227};
228
229static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst,
230				  union devlink_param_value *src,
231				  int nvm_num_bits, int dl_num_bytes)
232{
233	u32 val32 = 0;
234
235	if (nvm_num_bits == 1) {
236		dst->val8 = src->vbool;
237		return;
238	}
239	if (dl_num_bytes == 4)
240		val32 = src->vu32;
241	else if (dl_num_bytes == 2)
242		val32 = (u32)src->vu16;
243	else if (dl_num_bytes == 1)
244		val32 = (u32)src->vu8;
245	dst->val32 = cpu_to_le32(val32);
246}
247
248static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
249				    union bnxt_nvm_data *src,
250				    int nvm_num_bits, int dl_num_bytes)
251{
252	u32 val32;
253
254	if (nvm_num_bits == 1) {
255		dst->vbool = src->val8;
256		return;
257	}
258	val32 = le32_to_cpu(src->val32);
259	if (dl_num_bytes == 4)
260		dst->vu32 = val32;
261	else if (dl_num_bytes == 2)
262		dst->vu16 = (u16)val32;
263	else if (dl_num_bytes == 1)
264		dst->vu8 = (u8)val32;
265}
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
268			     int msg_len, union devlink_param_value *val)
269{
270	struct hwrm_nvm_get_variable_input *req = msg;
271	struct bnxt_dl_nvm_param nvm_param;
 
272	union bnxt_nvm_data *data;
273	dma_addr_t data_dma_addr;
274	int idx = 0, rc, i;
275
276	/* Get/Set NVM CFG parameter is supported only on PFs */
277	if (BNXT_VF(bp))
 
278		return -EPERM;
 
279
280	for (i = 0; i < ARRAY_SIZE(nvm_params); i++) {
281		if (nvm_params[i].id == param_id) {
282			nvm_param = nvm_params[i];
283			break;
284		}
285	}
286
287	if (i == ARRAY_SIZE(nvm_params))
 
288		return -EOPNOTSUPP;
 
289
290	if (nvm_param.dir_type == BNXT_NVM_PORT_CFG)
291		idx = bp->pf.port_id;
292	else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
293		idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
294
295	data = dma_alloc_coherent(&bp->pdev->dev, sizeof(*data),
296				  &data_dma_addr, GFP_KERNEL);
297	if (!data)
 
298		return -ENOMEM;
 
299
300	req->dest_data_addr = cpu_to_le64(data_dma_addr);
301	req->data_len = cpu_to_le16(nvm_param.nvm_num_bits);
302	req->option_num = cpu_to_le16(nvm_param.offset);
303	req->index_0 = cpu_to_le16(idx);
304	if (idx)
305		req->dimensions = cpu_to_le16(1);
306
 
307	if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
308		bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits,
309				      nvm_param.dl_num_bytes);
310		rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
311	} else {
312		rc = hwrm_send_message_silent(bp, msg, msg_len,
313					      HWRM_CMD_TIMEOUT);
314		if (!rc)
315			bnxt_copy_from_nvm_data(val, data,
316						nvm_param.nvm_num_bits,
317						nvm_param.dl_num_bytes);
 
 
 
 
 
318	}
319	dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
320	if (rc == -EACCES)
321		netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n");
322	return rc;
323}
324
325static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
326				 struct devlink_param_gset_ctx *ctx)
327{
328	struct hwrm_nvm_get_variable_input req = {0};
329	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
 
330	int rc;
331
332	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
333	rc = bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
334	if (!rc)
335		if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
336			ctx->val.vbool = !ctx->val.vbool;
 
 
337
338	return rc;
339}
340
341static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
342				 struct devlink_param_gset_ctx *ctx)
343{
344	struct hwrm_nvm_set_variable_input req = {0};
345	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
 
 
346
347	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_SET_VARIABLE, -1, -1);
 
 
348
349	if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
350		ctx->val.vbool = !ctx->val.vbool;
351
352	return bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
353}
354
355static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
356				 union devlink_param_value val,
357				 struct netlink_ext_ack *extack)
358{
359	int max_val = -1;
360
361	if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX)
362		max_val = BNXT_MSIX_VEC_MAX;
363
364	if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN)
365		max_val = BNXT_MSIX_VEC_MIN_MAX;
366
367	if (val.vu32 > max_val) {
368		NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range");
369		return -EINVAL;
370	}
371
372	return 0;
373}
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375static const struct devlink_param bnxt_dl_params[] = {
376	DEVLINK_PARAM_GENERIC(ENABLE_SRIOV,
377			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
378			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
379			      NULL),
380	DEVLINK_PARAM_GENERIC(IGNORE_ARI,
381			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
382			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
383			      NULL),
384	DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX,
385			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
386			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
387			      bnxt_dl_msix_validate),
388	DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN,
389			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
390			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
391			      bnxt_dl_msix_validate),
392	DEVLINK_PARAM_DRIVER(BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
393			     "gre_ver_check", DEVLINK_PARAM_TYPE_BOOL,
394			     BIT(DEVLINK_PARAM_CMODE_PERMANENT),
395			     bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
396			     NULL),
 
 
 
 
 
397};
398
399static const struct devlink_param bnxt_dl_port_params[] = {
400};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
402int bnxt_dl_register(struct bnxt *bp)
403{
 
 
 
404	struct devlink *dl;
405	int rc;
406
407	if (bp->hwrm_spec_code < 0x10600) {
408		netdev_warn(bp->dev, "Firmware does not support NVM params");
409		return -ENOTSUPP;
410	}
411
412	dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
413	if (!dl) {
414		netdev_warn(bp->dev, "devlink_alloc failed");
415		return -ENOMEM;
416	}
417
418	bnxt_link_bp_to_dl(bp, dl);
 
 
 
419
420	/* Add switchdev eswitch mode setting, if SRIOV supported */
421	if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) &&
422	    bp->hwrm_spec_code > 0x10803)
423		bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
424
425	rc = devlink_register(dl, &bp->pdev->dev);
426	if (rc) {
427		netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
428		goto err_dl_free;
429	}
430
431	rc = devlink_params_register(dl, bnxt_dl_params,
432				     ARRAY_SIZE(bnxt_dl_params));
433	if (rc) {
434		netdev_warn(bp->dev, "devlink_params_register failed. rc=%d",
435			    rc);
436		goto err_dl_unreg;
437	}
438
439	devlink_port_attrs_set(&bp->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
440			       bp->pf.port_id, false, 0,
441			       bp->switch_id, sizeof(bp->switch_id));
 
 
442	rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
443	if (rc) {
444		netdev_err(bp->dev, "devlink_port_register failed");
445		goto err_dl_param_unreg;
446	}
447	devlink_port_type_eth_set(&bp->dl_port, bp->dev);
448
449	rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
450					  ARRAY_SIZE(bnxt_dl_port_params));
451	if (rc) {
452		netdev_err(bp->dev, "devlink_port_params_register failed");
453		goto err_dl_port_unreg;
454	}
455
456	devlink_params_publish(dl);
457
458	bnxt_dl_fw_reporters_create(bp);
459
 
 
460	return 0;
461
462err_dl_port_unreg:
463	devlink_port_unregister(&bp->dl_port);
464err_dl_param_unreg:
465	devlink_params_unregister(dl, bnxt_dl_params,
466				  ARRAY_SIZE(bnxt_dl_params));
467err_dl_unreg:
468	devlink_unregister(dl);
469err_dl_free:
470	bnxt_link_bp_to_dl(bp, NULL);
471	devlink_free(dl);
472	return rc;
473}
474
475void bnxt_dl_unregister(struct bnxt *bp)
476{
477	struct devlink *dl = bp->dl;
478
479	if (!dl)
480		return;
481
482	bnxt_dl_fw_reporters_destroy(bp);
483	devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params,
484				       ARRAY_SIZE(bnxt_dl_port_params));
485	devlink_port_unregister(&bp->dl_port);
486	devlink_params_unregister(dl, bnxt_dl_params,
487				  ARRAY_SIZE(bnxt_dl_params));
488	devlink_unregister(dl);
 
 
 
 
489	devlink_free(dl);
490}