brintos

brintos / linux-shallow public Read only

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