11adf7eadSJacob Keller // SPDX-License-Identifier: GPL-2.0
21adf7eadSJacob Keller /* Copyright (c) 2020, Intel Corporation. */
31adf7eadSJacob Keller 
4b6459415SJakub Kicinski #include <linux/vmalloc.h>
5b6459415SJakub Kicinski 
61adf7eadSJacob Keller #include "ice.h"
7ff2e5c70SJacob Keller #include "ice_lib.h"
81adf7eadSJacob Keller #include "ice_devlink.h"
93ea9bd5dSMichal Swiatkowski #include "ice_eswitch.h"
10d69ea414SJacob Keller #include "ice_fw_update.h"
111adf7eadSJacob Keller 
1274789085SJacob Keller /* context for devlink info version reporting */
1374789085SJacob Keller struct ice_info_ctx {
1474789085SJacob Keller 	char buf[128];
15e67fbcfbSJacob Keller 	struct ice_orom_info pending_orom;
162c4fe41dSJacob Keller 	struct ice_nvm_info pending_nvm;
17e120a9abSJacob Keller 	struct ice_netlist_info pending_netlist;
182c4fe41dSJacob Keller 	struct ice_hw_dev_caps dev_caps;
1974789085SJacob Keller };
2074789085SJacob Keller 
2174789085SJacob Keller /* The following functions are used to format specific strings for various
2274789085SJacob Keller  * devlink info versions. The ctx parameter is used to provide the storage
2374789085SJacob Keller  * buffer, as well as any ancillary information calculated when the info
2474789085SJacob Keller  * request was made.
2574789085SJacob Keller  *
2674789085SJacob Keller  * If a version does not exist, for example when attempting to get the
2774789085SJacob Keller  * inactive version of flash when there is no pending update, the function
280128cc6eSJacob Keller  * should leave the buffer in the ctx structure empty.
2974789085SJacob Keller  */
3074789085SJacob Keller 
3174789085SJacob Keller static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx)
32ff2e5c70SJacob Keller {
33ff2e5c70SJacob Keller 	u8 dsn[8];
34ff2e5c70SJacob Keller 
35ff2e5c70SJacob Keller 	/* Copy the DSN into an array in Big Endian format */
36ff2e5c70SJacob Keller 	put_unaligned_be64(pci_get_dsn(pf->pdev), dsn);
37ff2e5c70SJacob Keller 
3874789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
39ff2e5c70SJacob Keller }
40ff2e5c70SJacob Keller 
410128cc6eSJacob Keller static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx)
42e961b679SJacob Keller {
43e961b679SJacob Keller 	struct ice_hw *hw = &pf->hw;
445e24d598STony Nguyen 	int status;
45e961b679SJacob Keller 
4674789085SJacob Keller 	status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf));
47e961b679SJacob Keller 	if (status)
48a8f89fa2SJacob Keller 		/* We failed to locate the PBA, so just skip this entry */
495f87ec48STony Nguyen 		dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n",
505f87ec48STony Nguyen 			status);
51e961b679SJacob Keller }
52e961b679SJacob Keller 
530128cc6eSJacob Keller static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx)
54ff2e5c70SJacob Keller {
55ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
56ff2e5c70SJacob Keller 
570128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
580128cc6eSJacob Keller 		 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch);
59ff2e5c70SJacob Keller }
60ff2e5c70SJacob Keller 
610128cc6eSJacob Keller static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx)
62ff2e5c70SJacob Keller {
63ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
64ff2e5c70SJacob Keller 
65b726ddf9SBrett Creeley 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver,
66b726ddf9SBrett Creeley 		 hw->api_min_ver, hw->api_patch);
67ff2e5c70SJacob Keller }
68ff2e5c70SJacob Keller 
690128cc6eSJacob Keller static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
70ff2e5c70SJacob Keller {
71ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
72ff2e5c70SJacob Keller 
7374789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
74ff2e5c70SJacob Keller }
75ff2e5c70SJacob Keller 
760128cc6eSJacob Keller static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
77ff2e5c70SJacob Keller {
789af368faSJacob Keller 	struct ice_orom_info *orom = &pf->hw.flash.orom;
79ff2e5c70SJacob Keller 
800128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
810128cc6eSJacob Keller 		 orom->major, orom->build, orom->patch);
82ff2e5c70SJacob Keller }
83ff2e5c70SJacob Keller 
840128cc6eSJacob Keller static void
850128cc6eSJacob Keller ice_info_pending_orom_ver(struct ice_pf __always_unused *pf,
860128cc6eSJacob Keller 			  struct ice_info_ctx *ctx)
87e67fbcfbSJacob Keller {
88e67fbcfbSJacob Keller 	struct ice_orom_info *orom = &ctx->pending_orom;
89e67fbcfbSJacob Keller 
90e67fbcfbSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_orom)
91e67fbcfbSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
92e67fbcfbSJacob Keller 			 orom->major, orom->build, orom->patch);
93e67fbcfbSJacob Keller }
94e67fbcfbSJacob Keller 
950128cc6eSJacob Keller static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
96ff2e5c70SJacob Keller {
979af368faSJacob Keller 	struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
98ff2e5c70SJacob Keller 
9974789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
100ff2e5c70SJacob Keller }
101ff2e5c70SJacob Keller 
1020128cc6eSJacob Keller static void
1030128cc6eSJacob Keller ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf,
1040128cc6eSJacob Keller 			 struct ice_info_ctx *ctx)
1052c4fe41dSJacob Keller {
1062c4fe41dSJacob Keller 	struct ice_nvm_info *nvm = &ctx->pending_nvm;
1072c4fe41dSJacob Keller 
1082c4fe41dSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
1090128cc6eSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x",
1100128cc6eSJacob Keller 			 nvm->major, nvm->minor);
1112c4fe41dSJacob Keller }
1122c4fe41dSJacob Keller 
1130128cc6eSJacob Keller static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
114ff2e5c70SJacob Keller {
1159af368faSJacob Keller 	struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
116ff2e5c70SJacob Keller 
11774789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
118ff2e5c70SJacob Keller }
119ff2e5c70SJacob Keller 
1200128cc6eSJacob Keller static void
1210128cc6eSJacob Keller ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
1222c4fe41dSJacob Keller {
1232c4fe41dSJacob Keller 	struct ice_nvm_info *nvm = &ctx->pending_nvm;
1242c4fe41dSJacob Keller 
1252c4fe41dSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
1262c4fe41dSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
1272c4fe41dSJacob Keller }
1282c4fe41dSJacob Keller 
1290128cc6eSJacob Keller static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx)
130ff2e5c70SJacob Keller {
131ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
132ff2e5c70SJacob Keller 
13374789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name);
134ff2e5c70SJacob Keller }
135ff2e5c70SJacob Keller 
1360128cc6eSJacob Keller static void
1370128cc6eSJacob Keller ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx)
138ff2e5c70SJacob Keller {
139ff2e5c70SJacob Keller 	struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver;
140ff2e5c70SJacob Keller 
1410128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u",
1420128cc6eSJacob Keller 		 pkg->major, pkg->minor, pkg->update, pkg->draft);
143ff2e5c70SJacob Keller }
144ff2e5c70SJacob Keller 
1450128cc6eSJacob Keller static void
1460128cc6eSJacob Keller ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx)
147410d0687SJacob Keller {
14874789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id);
149410d0687SJacob Keller }
150410d0687SJacob Keller 
1510128cc6eSJacob Keller static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
152f45a645fSJacob Keller {
1539af368faSJacob Keller 	struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
154f45a645fSJacob Keller 
155f45a645fSJacob Keller 	/* The netlist version fields are BCD formatted */
1560128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
1570128cc6eSJacob Keller 		 netlist->major, netlist->minor,
1580128cc6eSJacob Keller 		 netlist->type >> 16, netlist->type & 0xFFFF,
1590128cc6eSJacob Keller 		 netlist->rev, netlist->cust_ver);
160f45a645fSJacob Keller }
161f45a645fSJacob Keller 
1620128cc6eSJacob Keller static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
163f45a645fSJacob Keller {
1649af368faSJacob Keller 	struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
165f45a645fSJacob Keller 
16674789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
167f45a645fSJacob Keller }
168f45a645fSJacob Keller 
1690128cc6eSJacob Keller static void
1700128cc6eSJacob Keller ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf,
1710128cc6eSJacob Keller 			     struct ice_info_ctx *ctx)
172e120a9abSJacob Keller {
173e120a9abSJacob Keller 	struct ice_netlist_info *netlist = &ctx->pending_netlist;
174e120a9abSJacob Keller 
175e120a9abSJacob Keller 	/* The netlist version fields are BCD formatted */
176e120a9abSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
177e120a9abSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
178e120a9abSJacob Keller 			 netlist->major, netlist->minor,
1790128cc6eSJacob Keller 			 netlist->type >> 16, netlist->type & 0xFFFF,
1800128cc6eSJacob Keller 			 netlist->rev, netlist->cust_ver);
181e120a9abSJacob Keller }
182e120a9abSJacob Keller 
1830128cc6eSJacob Keller static void
1840128cc6eSJacob Keller ice_info_pending_netlist_build(struct ice_pf __always_unused *pf,
1850128cc6eSJacob Keller 			       struct ice_info_ctx *ctx)
186e120a9abSJacob Keller {
187e120a9abSJacob Keller 	struct ice_netlist_info *netlist = &ctx->pending_netlist;
188e120a9abSJacob Keller 
189e120a9abSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
190e120a9abSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
191e120a9abSJacob Keller }
192e120a9abSJacob Keller 
1932c4fe41dSJacob Keller #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL }
1942c4fe41dSJacob Keller #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL }
1952c4fe41dSJacob Keller #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback }
1962c4fe41dSJacob Keller 
1972c4fe41dSJacob Keller /* The combined() macro inserts both the running entry as well as a stored
1982c4fe41dSJacob Keller  * entry. The running entry will always report the version from the active
1992c4fe41dSJacob Keller  * handler. The stored entry will first try the pending handler, and fallback
2002c4fe41dSJacob Keller  * to the active handler if the pending function does not report a version.
2012c4fe41dSJacob Keller  * The pending handler should check the status of a pending update for the
2022c4fe41dSJacob Keller  * relevant flash component. It should only fill in the buffer in the case
2032c4fe41dSJacob Keller  * where a valid pending version is available. This ensures that the related
2042c4fe41dSJacob Keller  * stored and running versions remain in sync, and that stored versions are
2052c4fe41dSJacob Keller  * correctly reported as expected.
2062c4fe41dSJacob Keller  */
2072c4fe41dSJacob Keller #define combined(key, active, pending) \
2082c4fe41dSJacob Keller 	running(key, active), \
2092c4fe41dSJacob Keller 	stored(key, pending, active)
210ff2e5c70SJacob Keller 
211ff2e5c70SJacob Keller enum ice_version_type {
212ff2e5c70SJacob Keller 	ICE_VERSION_FIXED,
213ff2e5c70SJacob Keller 	ICE_VERSION_RUNNING,
214ff2e5c70SJacob Keller 	ICE_VERSION_STORED,
215ff2e5c70SJacob Keller };
216ff2e5c70SJacob Keller 
217ff2e5c70SJacob Keller static const struct ice_devlink_version {
218ff2e5c70SJacob Keller 	enum ice_version_type type;
219ff2e5c70SJacob Keller 	const char *key;
2200128cc6eSJacob Keller 	void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx);
2210128cc6eSJacob Keller 	void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx);
222ff2e5c70SJacob Keller } ice_devlink_versions[] = {
223e961b679SJacob Keller 	fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba),
224ff2e5c70SJacob Keller 	running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt),
225ff2e5c70SJacob Keller 	running("fw.mgmt.api", ice_info_fw_api),
226ff2e5c70SJacob Keller 	running("fw.mgmt.build", ice_info_fw_build),
227e67fbcfbSJacob Keller 	combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver),
2282c4fe41dSJacob Keller 	combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver),
2292c4fe41dSJacob Keller 	combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack),
230ff2e5c70SJacob Keller 	running("fw.app.name", ice_info_ddp_pkg_name),
231ff2e5c70SJacob Keller 	running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version),
232410d0687SJacob Keller 	running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id),
233e120a9abSJacob Keller 	combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver),
234e120a9abSJacob Keller 	combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build),
235ff2e5c70SJacob Keller };
236ff2e5c70SJacob Keller 
237ff2e5c70SJacob Keller /**
238ff2e5c70SJacob Keller  * ice_devlink_info_get - .info_get devlink handler
239ff2e5c70SJacob Keller  * @devlink: devlink instance structure
240ff2e5c70SJacob Keller  * @req: the devlink info request
241ff2e5c70SJacob Keller  * @extack: extended netdev ack structure
242ff2e5c70SJacob Keller  *
243ff2e5c70SJacob Keller  * Callback for the devlink .info_get operation. Reports information about the
244ff2e5c70SJacob Keller  * device.
245ff2e5c70SJacob Keller  *
246e961b679SJacob Keller  * Return: zero on success or an error code on failure.
247ff2e5c70SJacob Keller  */
248ff2e5c70SJacob Keller static int ice_devlink_info_get(struct devlink *devlink,
249ff2e5c70SJacob Keller 				struct devlink_info_req *req,
250ff2e5c70SJacob Keller 				struct netlink_ext_ack *extack)
251ff2e5c70SJacob Keller {
252ff2e5c70SJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
2532c4fe41dSJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
2542c4fe41dSJacob Keller 	struct ice_hw *hw = &pf->hw;
25574789085SJacob Keller 	struct ice_info_ctx *ctx;
256ff2e5c70SJacob Keller 	size_t i;
257ff2e5c70SJacob Keller 	int err;
258ff2e5c70SJacob Keller 
2591c08052eSJacob Keller 	err = ice_wait_for_reset(pf, 10 * HZ);
2601c08052eSJacob Keller 	if (err) {
2611c08052eSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting");
2621c08052eSJacob Keller 		return err;
2631c08052eSJacob Keller 	}
2641c08052eSJacob Keller 
26574789085SJacob Keller 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
26674789085SJacob Keller 	if (!ctx)
26774789085SJacob Keller 		return -ENOMEM;
26874789085SJacob Keller 
2692c4fe41dSJacob Keller 	/* discover capabilities first */
2702ccc1c1cSTony Nguyen 	err = ice_discover_dev_caps(hw, &ctx->dev_caps);
2712ccc1c1cSTony Nguyen 	if (err) {
2725f87ec48STony Nguyen 		dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n",
2732ccc1c1cSTony Nguyen 			err, ice_aq_str(hw->adminq.sq_last_status));
274d5f84ae9SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities");
2752c4fe41dSJacob Keller 		goto out_free_ctx;
2762c4fe41dSJacob Keller 	}
2772c4fe41dSJacob Keller 
278e67fbcfbSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_orom) {
2792ccc1c1cSTony Nguyen 		err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom);
2802ccc1c1cSTony Nguyen 		if (err) {
2815f87ec48STony Nguyen 			dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n",
2822ccc1c1cSTony Nguyen 				err, ice_aq_str(hw->adminq.sq_last_status));
283e67fbcfbSJacob Keller 
284e67fbcfbSJacob Keller 			/* disable display of pending Option ROM */
285e67fbcfbSJacob Keller 			ctx->dev_caps.common_cap.nvm_update_pending_orom = false;
286e67fbcfbSJacob Keller 		}
287e67fbcfbSJacob Keller 	}
288e67fbcfbSJacob Keller 
2892c4fe41dSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) {
2902ccc1c1cSTony Nguyen 		err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
2912ccc1c1cSTony Nguyen 		if (err) {
2925f87ec48STony Nguyen 			dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n",
2932ccc1c1cSTony Nguyen 				err, ice_aq_str(hw->adminq.sq_last_status));
2942c4fe41dSJacob Keller 
2952c4fe41dSJacob Keller 			/* disable display of pending Option ROM */
2962c4fe41dSJacob Keller 			ctx->dev_caps.common_cap.nvm_update_pending_nvm = false;
2972c4fe41dSJacob Keller 		}
2982c4fe41dSJacob Keller 	}
2992c4fe41dSJacob Keller 
300e120a9abSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) {
3012ccc1c1cSTony Nguyen 		err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
3022ccc1c1cSTony Nguyen 		if (err) {
3035f87ec48STony Nguyen 			dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n",
3042ccc1c1cSTony Nguyen 				err, ice_aq_str(hw->adminq.sq_last_status));
305e120a9abSJacob Keller 
306e120a9abSJacob Keller 			/* disable display of pending Option ROM */
307e120a9abSJacob Keller 			ctx->dev_caps.common_cap.nvm_update_pending_netlist = false;
308e120a9abSJacob Keller 		}
309e120a9abSJacob Keller 	}
310e120a9abSJacob Keller 
311ff2e5c70SJacob Keller 	err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
312ff2e5c70SJacob Keller 	if (err) {
313ff2e5c70SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name");
31474789085SJacob Keller 		goto out_free_ctx;
315ff2e5c70SJacob Keller 	}
316ff2e5c70SJacob Keller 
31774789085SJacob Keller 	ice_info_get_dsn(pf, ctx);
318ff2e5c70SJacob Keller 
31974789085SJacob Keller 	err = devlink_info_serial_number_put(req, ctx->buf);
320ff2e5c70SJacob Keller 	if (err) {
321ff2e5c70SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number");
32274789085SJacob Keller 		goto out_free_ctx;
323ff2e5c70SJacob Keller 	}
324ff2e5c70SJacob Keller 
325ff2e5c70SJacob Keller 	for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) {
326ff2e5c70SJacob Keller 		enum ice_version_type type = ice_devlink_versions[i].type;
327ff2e5c70SJacob Keller 		const char *key = ice_devlink_versions[i].key;
328ff2e5c70SJacob Keller 
32974789085SJacob Keller 		memset(ctx->buf, 0, sizeof(ctx->buf));
33074789085SJacob Keller 
3310128cc6eSJacob Keller 		ice_devlink_versions[i].getter(pf, ctx);
332ff2e5c70SJacob Keller 
3332c4fe41dSJacob Keller 		/* If the default getter doesn't report a version, use the
3342c4fe41dSJacob Keller 		 * fallback function. This is primarily useful in the case of
3352c4fe41dSJacob Keller 		 * "stored" versions that want to report the same value as the
3362c4fe41dSJacob Keller 		 * running version in the normal case of no pending update.
3372c4fe41dSJacob Keller 		 */
3380128cc6eSJacob Keller 		if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback)
3390128cc6eSJacob Keller 			ice_devlink_versions[i].fallback(pf, ctx);
3402c4fe41dSJacob Keller 
34174789085SJacob Keller 		/* Do not report missing versions */
34274789085SJacob Keller 		if (ctx->buf[0] == '\0')
34374789085SJacob Keller 			continue;
34474789085SJacob Keller 
345ff2e5c70SJacob Keller 		switch (type) {
346ff2e5c70SJacob Keller 		case ICE_VERSION_FIXED:
34774789085SJacob Keller 			err = devlink_info_version_fixed_put(req, key, ctx->buf);
348ff2e5c70SJacob Keller 			if (err) {
349ff2e5c70SJacob Keller 				NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version");
35074789085SJacob Keller 				goto out_free_ctx;
351ff2e5c70SJacob Keller 			}
352ff2e5c70SJacob Keller 			break;
353ff2e5c70SJacob Keller 		case ICE_VERSION_RUNNING:
35474789085SJacob Keller 			err = devlink_info_version_running_put(req, key, ctx->buf);
355ff2e5c70SJacob Keller 			if (err) {
356ff2e5c70SJacob Keller 				NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
35774789085SJacob Keller 				goto out_free_ctx;
358ff2e5c70SJacob Keller 			}
359ff2e5c70SJacob Keller 			break;
360ff2e5c70SJacob Keller 		case ICE_VERSION_STORED:
36174789085SJacob Keller 			err = devlink_info_version_stored_put(req, key, ctx->buf);
362ff2e5c70SJacob Keller 			if (err) {
363ff2e5c70SJacob Keller 				NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
36474789085SJacob Keller 				goto out_free_ctx;
365ff2e5c70SJacob Keller 			}
366ff2e5c70SJacob Keller 			break;
367ff2e5c70SJacob Keller 		}
368ff2e5c70SJacob Keller 	}
369ff2e5c70SJacob Keller 
37074789085SJacob Keller out_free_ctx:
37174789085SJacob Keller 	kfree(ctx);
37274789085SJacob Keller 	return err;
373ff2e5c70SJacob Keller }
374ff2e5c70SJacob Keller 
375399e27dbSJacob Keller /**
376399e27dbSJacob Keller  * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware
377399e27dbSJacob Keller  * @devlink: pointer to the devlink instance to reload
378399e27dbSJacob Keller  * @netns_change: if true, the network namespace is changing
379399e27dbSJacob Keller  * @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE
380399e27dbSJacob Keller  * @limit: limits on what reload should do, such as not resetting
381399e27dbSJacob Keller  * @extack: netlink extended ACK structure
382399e27dbSJacob Keller  *
383399e27dbSJacob Keller  * Allow user to activate new Embedded Management Processor firmware by
384399e27dbSJacob Keller  * issuing device specific EMP reset. Called in response to
385399e27dbSJacob Keller  * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE.
386399e27dbSJacob Keller  *
387399e27dbSJacob Keller  * Note that teardown and rebuild of the driver state happens automatically as
388399e27dbSJacob Keller  * part of an interrupt and watchdog task. This is because all physical
389399e27dbSJacob Keller  * functions on the device must be able to reset when an EMP reset occurs from
390399e27dbSJacob Keller  * any source.
391399e27dbSJacob Keller  */
392399e27dbSJacob Keller static int
393399e27dbSJacob Keller ice_devlink_reload_empr_start(struct devlink *devlink, bool netns_change,
394399e27dbSJacob Keller 			      enum devlink_reload_action action,
395399e27dbSJacob Keller 			      enum devlink_reload_limit limit,
396399e27dbSJacob Keller 			      struct netlink_ext_ack *extack)
397399e27dbSJacob Keller {
398399e27dbSJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
399399e27dbSJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
400399e27dbSJacob Keller 	struct ice_hw *hw = &pf->hw;
401399e27dbSJacob Keller 	u8 pending;
402399e27dbSJacob Keller 	int err;
403399e27dbSJacob Keller 
404399e27dbSJacob Keller 	err = ice_get_pending_updates(pf, &pending, extack);
405399e27dbSJacob Keller 	if (err)
406399e27dbSJacob Keller 		return err;
407399e27dbSJacob Keller 
408399e27dbSJacob Keller 	/* pending is a bitmask of which flash banks have a pending update,
409399e27dbSJacob Keller 	 * including the main NVM bank, the Option ROM bank, and the netlist
410399e27dbSJacob Keller 	 * bank. If any of these bits are set, then there is a pending update
411399e27dbSJacob Keller 	 * waiting to be activated.
412399e27dbSJacob Keller 	 */
413399e27dbSJacob Keller 	if (!pending) {
414399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "No pending firmware update");
415399e27dbSJacob Keller 		return -ECANCELED;
416399e27dbSJacob Keller 	}
417399e27dbSJacob Keller 
418399e27dbSJacob Keller 	if (pf->fw_emp_reset_disabled) {
419399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed");
420399e27dbSJacob Keller 		return -ECANCELED;
421399e27dbSJacob Keller 	}
422399e27dbSJacob Keller 
423399e27dbSJacob Keller 	dev_dbg(dev, "Issuing device EMP reset to activate firmware\n");
424399e27dbSJacob Keller 
425399e27dbSJacob Keller 	err = ice_aq_nvm_update_empr(hw);
426399e27dbSJacob Keller 	if (err) {
427399e27dbSJacob Keller 		dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n",
428399e27dbSJacob Keller 			err, ice_aq_str(hw->adminq.sq_last_status));
429399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware");
430399e27dbSJacob Keller 		return err;
431399e27dbSJacob Keller 	}
432399e27dbSJacob Keller 
433399e27dbSJacob Keller 	return 0;
434399e27dbSJacob Keller }
435399e27dbSJacob Keller 
436399e27dbSJacob Keller /**
437399e27dbSJacob Keller  * ice_devlink_reload_empr_finish - Wait for EMP reset to finish
438399e27dbSJacob Keller  * @devlink: pointer to the devlink instance reloading
439399e27dbSJacob Keller  * @action: the action requested
440399e27dbSJacob Keller  * @limit: limits imposed by userspace, such as not resetting
441399e27dbSJacob Keller  * @actions_performed: on return, indicate what actions actually performed
442399e27dbSJacob Keller  * @extack: netlink extended ACK structure
443399e27dbSJacob Keller  *
444399e27dbSJacob Keller  * Wait for driver to finish rebuilding after EMP reset is completed. This
445399e27dbSJacob Keller  * includes time to wait for both the actual device reset as well as the time
446399e27dbSJacob Keller  * for the driver's rebuild to complete.
447399e27dbSJacob Keller  */
448399e27dbSJacob Keller static int
449399e27dbSJacob Keller ice_devlink_reload_empr_finish(struct devlink *devlink,
450399e27dbSJacob Keller 			       enum devlink_reload_action action,
451399e27dbSJacob Keller 			       enum devlink_reload_limit limit,
452399e27dbSJacob Keller 			       u32 *actions_performed,
453399e27dbSJacob Keller 			       struct netlink_ext_ack *extack)
454399e27dbSJacob Keller {
455399e27dbSJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
456399e27dbSJacob Keller 	int err;
457399e27dbSJacob Keller 
458399e27dbSJacob Keller 	*actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
459399e27dbSJacob Keller 
460399e27dbSJacob Keller 	err = ice_wait_for_reset(pf, 60 * HZ);
461399e27dbSJacob Keller 	if (err) {
462399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute");
463399e27dbSJacob Keller 		return err;
464399e27dbSJacob Keller 	}
465399e27dbSJacob Keller 
466399e27dbSJacob Keller 	return 0;
467399e27dbSJacob Keller }
468399e27dbSJacob Keller 
4691adf7eadSJacob Keller static const struct devlink_ops ice_devlink_ops = {
47050db1bcaSJacob Keller 	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
471399e27dbSJacob Keller 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
472399e27dbSJacob Keller 	/* The ice driver currently does not support driver reinit */
473399e27dbSJacob Keller 	.reload_down = ice_devlink_reload_empr_start,
474399e27dbSJacob Keller 	.reload_up = ice_devlink_reload_empr_finish,
4753ea9bd5dSMichal Swiatkowski 	.eswitch_mode_get = ice_eswitch_mode_get,
4763ea9bd5dSMichal Swiatkowski 	.eswitch_mode_set = ice_eswitch_mode_set,
477ff2e5c70SJacob Keller 	.info_get = ice_devlink_info_get,
478d69ea414SJacob Keller 	.flash_update = ice_devlink_flash_update,
4791adf7eadSJacob Keller };
4801adf7eadSJacob Keller 
481e523af4eSShiraz Saleem static int
482e523af4eSShiraz Saleem ice_devlink_enable_roce_get(struct devlink *devlink, u32 id,
483e523af4eSShiraz Saleem 			    struct devlink_param_gset_ctx *ctx)
484e523af4eSShiraz Saleem {
485e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
486e523af4eSShiraz Saleem 
4877b62483fSShiraz Saleem 	ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false;
488e523af4eSShiraz Saleem 
489e523af4eSShiraz Saleem 	return 0;
490e523af4eSShiraz Saleem }
491e523af4eSShiraz Saleem 
492e523af4eSShiraz Saleem static int
493e523af4eSShiraz Saleem ice_devlink_enable_roce_set(struct devlink *devlink, u32 id,
494e523af4eSShiraz Saleem 			    struct devlink_param_gset_ctx *ctx)
495e523af4eSShiraz Saleem {
496e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
497e523af4eSShiraz Saleem 	bool roce_ena = ctx->val.vbool;
498e523af4eSShiraz Saleem 	int ret;
499e523af4eSShiraz Saleem 
500e523af4eSShiraz Saleem 	if (!roce_ena) {
501e523af4eSShiraz Saleem 		ice_unplug_aux_dev(pf);
502e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2;
503e523af4eSShiraz Saleem 		return 0;
504e523af4eSShiraz Saleem 	}
505e523af4eSShiraz Saleem 
506e523af4eSShiraz Saleem 	pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2;
507e523af4eSShiraz Saleem 	ret = ice_plug_aux_dev(pf);
508e523af4eSShiraz Saleem 	if (ret)
509e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2;
510e523af4eSShiraz Saleem 
511e523af4eSShiraz Saleem 	return ret;
512e523af4eSShiraz Saleem }
513e523af4eSShiraz Saleem 
514e523af4eSShiraz Saleem static int
515e523af4eSShiraz Saleem ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
516e523af4eSShiraz Saleem 				 union devlink_param_value val,
517e523af4eSShiraz Saleem 				 struct netlink_ext_ack *extack)
518e523af4eSShiraz Saleem {
519e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
520e523af4eSShiraz Saleem 
521e523af4eSShiraz Saleem 	if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
522e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
523e523af4eSShiraz Saleem 
524e523af4eSShiraz Saleem 	if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) {
525e523af4eSShiraz Saleem 		NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously");
526e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
527e523af4eSShiraz Saleem 	}
528e523af4eSShiraz Saleem 
529e523af4eSShiraz Saleem 	return 0;
530e523af4eSShiraz Saleem }
531e523af4eSShiraz Saleem 
532e523af4eSShiraz Saleem static int
533e523af4eSShiraz Saleem ice_devlink_enable_iw_get(struct devlink *devlink, u32 id,
534e523af4eSShiraz Saleem 			  struct devlink_param_gset_ctx *ctx)
535e523af4eSShiraz Saleem {
536e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
537e523af4eSShiraz Saleem 
538e523af4eSShiraz Saleem 	ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP;
539e523af4eSShiraz Saleem 
540e523af4eSShiraz Saleem 	return 0;
541e523af4eSShiraz Saleem }
542e523af4eSShiraz Saleem 
543e523af4eSShiraz Saleem static int
544e523af4eSShiraz Saleem ice_devlink_enable_iw_set(struct devlink *devlink, u32 id,
545e523af4eSShiraz Saleem 			  struct devlink_param_gset_ctx *ctx)
546e523af4eSShiraz Saleem {
547e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
548e523af4eSShiraz Saleem 	bool iw_ena = ctx->val.vbool;
549e523af4eSShiraz Saleem 	int ret;
550e523af4eSShiraz Saleem 
551e523af4eSShiraz Saleem 	if (!iw_ena) {
552e523af4eSShiraz Saleem 		ice_unplug_aux_dev(pf);
553e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP;
554e523af4eSShiraz Saleem 		return 0;
555e523af4eSShiraz Saleem 	}
556e523af4eSShiraz Saleem 
557e523af4eSShiraz Saleem 	pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP;
558e523af4eSShiraz Saleem 	ret = ice_plug_aux_dev(pf);
559e523af4eSShiraz Saleem 	if (ret)
560e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP;
561e523af4eSShiraz Saleem 
562e523af4eSShiraz Saleem 	return ret;
563e523af4eSShiraz Saleem }
564e523af4eSShiraz Saleem 
565e523af4eSShiraz Saleem static int
566e523af4eSShiraz Saleem ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id,
567e523af4eSShiraz Saleem 			       union devlink_param_value val,
568e523af4eSShiraz Saleem 			       struct netlink_ext_ack *extack)
569e523af4eSShiraz Saleem {
570e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
571e523af4eSShiraz Saleem 
572e523af4eSShiraz Saleem 	if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
573e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
574e523af4eSShiraz Saleem 
575e523af4eSShiraz Saleem 	if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) {
576e523af4eSShiraz Saleem 		NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously");
577e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
578e523af4eSShiraz Saleem 	}
579e523af4eSShiraz Saleem 
580e523af4eSShiraz Saleem 	return 0;
581e523af4eSShiraz Saleem }
582e523af4eSShiraz Saleem 
583e523af4eSShiraz Saleem static const struct devlink_param ice_devlink_params[] = {
584e523af4eSShiraz Saleem 	DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
585e523af4eSShiraz Saleem 			      ice_devlink_enable_roce_get,
586e523af4eSShiraz Saleem 			      ice_devlink_enable_roce_set,
587e523af4eSShiraz Saleem 			      ice_devlink_enable_roce_validate),
588e523af4eSShiraz Saleem 	DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
589e523af4eSShiraz Saleem 			      ice_devlink_enable_iw_get,
590e523af4eSShiraz Saleem 			      ice_devlink_enable_iw_set,
591e523af4eSShiraz Saleem 			      ice_devlink_enable_iw_validate),
592e523af4eSShiraz Saleem 
593e523af4eSShiraz Saleem };
594e523af4eSShiraz Saleem 
5951adf7eadSJacob Keller static void ice_devlink_free(void *devlink_ptr)
5961adf7eadSJacob Keller {
5971adf7eadSJacob Keller 	devlink_free((struct devlink *)devlink_ptr);
5981adf7eadSJacob Keller }
5991adf7eadSJacob Keller 
6001adf7eadSJacob Keller /**
6011adf7eadSJacob Keller  * ice_allocate_pf - Allocate devlink and return PF structure pointer
6021adf7eadSJacob Keller  * @dev: the device to allocate for
6031adf7eadSJacob Keller  *
6041adf7eadSJacob Keller  * Allocate a devlink instance for this device and return the private area as
6051adf7eadSJacob Keller  * the PF structure. The devlink memory is kept track of through devres by
6061adf7eadSJacob Keller  * adding an action to remove it when unwinding.
6071adf7eadSJacob Keller  */
6081adf7eadSJacob Keller struct ice_pf *ice_allocate_pf(struct device *dev)
6091adf7eadSJacob Keller {
6101adf7eadSJacob Keller 	struct devlink *devlink;
6111adf7eadSJacob Keller 
612919d13a7SLeon Romanovsky 	devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev);
6131adf7eadSJacob Keller 	if (!devlink)
6141adf7eadSJacob Keller 		return NULL;
6151adf7eadSJacob Keller 
6161adf7eadSJacob Keller 	/* Add an action to teardown the devlink when unwinding the driver */
6177c1b694aSCai Huoqing 	if (devm_add_action_or_reset(dev, ice_devlink_free, devlink))
6181adf7eadSJacob Keller 		return NULL;
6191adf7eadSJacob Keller 
6201adf7eadSJacob Keller 	return devlink_priv(devlink);
6211adf7eadSJacob Keller }
6221adf7eadSJacob Keller 
6231adf7eadSJacob Keller /**
6241adf7eadSJacob Keller  * ice_devlink_register - Register devlink interface for this PF
6251adf7eadSJacob Keller  * @pf: the PF to register the devlink for.
6261adf7eadSJacob Keller  *
6271adf7eadSJacob Keller  * Register the devlink instance associated with this physical function.
6281adf7eadSJacob Keller  *
6291adf7eadSJacob Keller  * Return: zero on success or an error code on failure.
6301adf7eadSJacob Keller  */
631db4278c5SLeon Romanovsky void ice_devlink_register(struct ice_pf *pf)
6321adf7eadSJacob Keller {
6331adf7eadSJacob Keller 	struct devlink *devlink = priv_to_devlink(pf);
6341adf7eadSJacob Keller 
635399e27dbSJacob Keller 	devlink_set_features(devlink, DEVLINK_F_RELOAD);
636db4278c5SLeon Romanovsky 	devlink_register(devlink);
6371adf7eadSJacob Keller }
6381adf7eadSJacob Keller 
6391adf7eadSJacob Keller /**
6401adf7eadSJacob Keller  * ice_devlink_unregister - Unregister devlink resources for this PF.
6411adf7eadSJacob Keller  * @pf: the PF structure to cleanup
6421adf7eadSJacob Keller  *
6431adf7eadSJacob Keller  * Releases resources used by devlink and cleans up associated memory.
6441adf7eadSJacob Keller  */
6451adf7eadSJacob Keller void ice_devlink_unregister(struct ice_pf *pf)
6461adf7eadSJacob Keller {
6471adf7eadSJacob Keller 	devlink_unregister(priv_to_devlink(pf));
6481adf7eadSJacob Keller }
6491adf7eadSJacob Keller 
650*4b889474SMichal Swiatkowski /**
651*4b889474SMichal Swiatkowski  * ice_devlink_set_switch_id - Set unique switch id based on pci dsn
652*4b889474SMichal Swiatkowski  * @pf: the PF to create a devlink port for
653*4b889474SMichal Swiatkowski  * @ppid: struct with switch id information
654*4b889474SMichal Swiatkowski  */
655*4b889474SMichal Swiatkowski static void
656*4b889474SMichal Swiatkowski ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid)
657*4b889474SMichal Swiatkowski {
658*4b889474SMichal Swiatkowski 	struct pci_dev *pdev = pf->pdev;
659*4b889474SMichal Swiatkowski 	u64 id;
660*4b889474SMichal Swiatkowski 
661*4b889474SMichal Swiatkowski 	id = pci_get_dsn(pdev);
662*4b889474SMichal Swiatkowski 
663*4b889474SMichal Swiatkowski 	ppid->id_len = sizeof(id);
664*4b889474SMichal Swiatkowski 	put_unaligned_be64(id, &ppid->id);
665*4b889474SMichal Swiatkowski }
666*4b889474SMichal Swiatkowski 
667e523af4eSShiraz Saleem int ice_devlink_register_params(struct ice_pf *pf)
668e523af4eSShiraz Saleem {
669e523af4eSShiraz Saleem 	struct devlink *devlink = priv_to_devlink(pf);
670e523af4eSShiraz Saleem 	union devlink_param_value value;
671e523af4eSShiraz Saleem 	int err;
672e523af4eSShiraz Saleem 
673e523af4eSShiraz Saleem 	err = devlink_params_register(devlink, ice_devlink_params,
674e523af4eSShiraz Saleem 				      ARRAY_SIZE(ice_devlink_params));
675e523af4eSShiraz Saleem 	if (err)
676e523af4eSShiraz Saleem 		return err;
677e523af4eSShiraz Saleem 
678e523af4eSShiraz Saleem 	value.vbool = false;
679e523af4eSShiraz Saleem 	devlink_param_driverinit_value_set(devlink,
680e523af4eSShiraz Saleem 					   DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP,
681e523af4eSShiraz Saleem 					   value);
682e523af4eSShiraz Saleem 
683e523af4eSShiraz Saleem 	value.vbool = test_bit(ICE_FLAG_RDMA_ENA, pf->flags) ? true : false;
684e523af4eSShiraz Saleem 	devlink_param_driverinit_value_set(devlink,
685e523af4eSShiraz Saleem 					   DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
686e523af4eSShiraz Saleem 					   value);
687e523af4eSShiraz Saleem 
688e523af4eSShiraz Saleem 	return 0;
689e523af4eSShiraz Saleem }
690e523af4eSShiraz Saleem 
691e523af4eSShiraz Saleem void ice_devlink_unregister_params(struct ice_pf *pf)
692e523af4eSShiraz Saleem {
693e523af4eSShiraz Saleem 	devlink_params_unregister(priv_to_devlink(pf), ice_devlink_params,
694e523af4eSShiraz Saleem 				  ARRAY_SIZE(ice_devlink_params));
695e523af4eSShiraz Saleem }
696e523af4eSShiraz Saleem 
6971adf7eadSJacob Keller /**
6982ae0aa47SWojciech Drewek  * ice_devlink_create_pf_port - Create a devlink port for this PF
6992ae0aa47SWojciech Drewek  * @pf: the PF to create a devlink port for
7001adf7eadSJacob Keller  *
7012ae0aa47SWojciech Drewek  * Create and register a devlink_port for this PF.
7021adf7eadSJacob Keller  *
7031adf7eadSJacob Keller  * Return: zero on success or an error code on failure.
7041adf7eadSJacob Keller  */
7052ae0aa47SWojciech Drewek int ice_devlink_create_pf_port(struct ice_pf *pf)
7061adf7eadSJacob Keller {
70771ad8d55SDanielle Ratson 	struct devlink_port_attrs attrs = {};
7082ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
70948d40025SJacob Keller 	struct devlink *devlink;
7102ae0aa47SWojciech Drewek 	struct ice_vsi *vsi;
71148d40025SJacob Keller 	struct device *dev;
7121adf7eadSJacob Keller 	int err;
7131adf7eadSJacob Keller 
71448d40025SJacob Keller 	dev = ice_pf_to_dev(pf);
7152ae0aa47SWojciech Drewek 
7162ae0aa47SWojciech Drewek 	devlink_port = &pf->devlink_port;
7172ae0aa47SWojciech Drewek 
7182ae0aa47SWojciech Drewek 	vsi = ice_get_main_vsi(pf);
7192ae0aa47SWojciech Drewek 	if (!vsi)
7202ae0aa47SWojciech Drewek 		return -EIO;
7211adf7eadSJacob Keller 
72271ad8d55SDanielle Ratson 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
7232ae0aa47SWojciech Drewek 	attrs.phys.port_number = pf->hw.bus.func;
724*4b889474SMichal Swiatkowski 
725*4b889474SMichal Swiatkowski 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
726*4b889474SMichal Swiatkowski 
7272ae0aa47SWojciech Drewek 	devlink_port_attrs_set(devlink_port, &attrs);
7282ae0aa47SWojciech Drewek 	devlink = priv_to_devlink(pf);
7292ae0aa47SWojciech Drewek 
7302ae0aa47SWojciech Drewek 	err = devlink_port_register(devlink, devlink_port, vsi->idx);
7311adf7eadSJacob Keller 	if (err) {
7322ae0aa47SWojciech Drewek 		dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
7332ae0aa47SWojciech Drewek 			pf->hw.pf_id, err);
7341adf7eadSJacob Keller 		return err;
7351adf7eadSJacob Keller 	}
7361adf7eadSJacob Keller 
7371adf7eadSJacob Keller 	return 0;
7381adf7eadSJacob Keller }
7391adf7eadSJacob Keller 
7401adf7eadSJacob Keller /**
7412ae0aa47SWojciech Drewek  * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
7422ae0aa47SWojciech Drewek  * @pf: the PF to cleanup
7431adf7eadSJacob Keller  *
7442ae0aa47SWojciech Drewek  * Unregisters the devlink_port structure associated with this PF.
7451adf7eadSJacob Keller  */
7462ae0aa47SWojciech Drewek void ice_devlink_destroy_pf_port(struct ice_pf *pf)
7471adf7eadSJacob Keller {
7482ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
74948d40025SJacob Keller 
7502ae0aa47SWojciech Drewek 	devlink_port = &pf->devlink_port;
75148d40025SJacob Keller 
7522ae0aa47SWojciech Drewek 	devlink_port_type_clear(devlink_port);
7532ae0aa47SWojciech Drewek 	devlink_port_unregister(devlink_port);
7542ae0aa47SWojciech Drewek }
7552ae0aa47SWojciech Drewek 
7562ae0aa47SWojciech Drewek /**
7572ae0aa47SWojciech Drewek  * ice_devlink_create_vf_port - Create a devlink port for this VF
7582ae0aa47SWojciech Drewek  * @vf: the VF to create a port for
7592ae0aa47SWojciech Drewek  *
7602ae0aa47SWojciech Drewek  * Create and register a devlink_port for this VF.
7612ae0aa47SWojciech Drewek  *
7622ae0aa47SWojciech Drewek  * Return: zero on success or an error code on failure.
7632ae0aa47SWojciech Drewek  */
7642ae0aa47SWojciech Drewek int ice_devlink_create_vf_port(struct ice_vf *vf)
7652ae0aa47SWojciech Drewek {
7662ae0aa47SWojciech Drewek 	struct devlink_port_attrs attrs = {};
7672ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
7682ae0aa47SWojciech Drewek 	struct devlink *devlink;
7692ae0aa47SWojciech Drewek 	struct ice_vsi *vsi;
7702ae0aa47SWojciech Drewek 	struct device *dev;
7712ae0aa47SWojciech Drewek 	struct ice_pf *pf;
7722ae0aa47SWojciech Drewek 	int err;
7732ae0aa47SWojciech Drewek 
7742ae0aa47SWojciech Drewek 	pf = vf->pf;
7752ae0aa47SWojciech Drewek 	dev = ice_pf_to_dev(pf);
7762ae0aa47SWojciech Drewek 	vsi = ice_get_vf_vsi(vf);
7772ae0aa47SWojciech Drewek 	devlink_port = &vf->devlink_port;
7782ae0aa47SWojciech Drewek 
7792ae0aa47SWojciech Drewek 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
7802ae0aa47SWojciech Drewek 	attrs.pci_vf.pf = pf->hw.bus.func;
7812ae0aa47SWojciech Drewek 	attrs.pci_vf.vf = vf->vf_id;
7822ae0aa47SWojciech Drewek 
783*4b889474SMichal Swiatkowski 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
784*4b889474SMichal Swiatkowski 
7852ae0aa47SWojciech Drewek 	devlink_port_attrs_set(devlink_port, &attrs);
7862ae0aa47SWojciech Drewek 	devlink = priv_to_devlink(pf);
7872ae0aa47SWojciech Drewek 
7882ae0aa47SWojciech Drewek 	err = devlink_port_register(devlink, devlink_port, vsi->idx);
7892ae0aa47SWojciech Drewek 	if (err) {
7902ae0aa47SWojciech Drewek 		dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
7912ae0aa47SWojciech Drewek 			vf->vf_id, err);
7922ae0aa47SWojciech Drewek 		return err;
7932ae0aa47SWojciech Drewek 	}
7942ae0aa47SWojciech Drewek 
7952ae0aa47SWojciech Drewek 	return 0;
7962ae0aa47SWojciech Drewek }
7972ae0aa47SWojciech Drewek 
7982ae0aa47SWojciech Drewek /**
7992ae0aa47SWojciech Drewek  * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
8002ae0aa47SWojciech Drewek  * @vf: the VF to cleanup
8012ae0aa47SWojciech Drewek  *
8022ae0aa47SWojciech Drewek  * Unregisters the devlink_port structure associated with this VF.
8032ae0aa47SWojciech Drewek  */
8042ae0aa47SWojciech Drewek void ice_devlink_destroy_vf_port(struct ice_vf *vf)
8052ae0aa47SWojciech Drewek {
8062ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
8072ae0aa47SWojciech Drewek 
8082ae0aa47SWojciech Drewek 	devlink_port = &vf->devlink_port;
8092ae0aa47SWojciech Drewek 
8102ae0aa47SWojciech Drewek 	devlink_port_type_clear(devlink_port);
8112ae0aa47SWojciech Drewek 	devlink_port_unregister(devlink_port);
8121adf7eadSJacob Keller }
813dce730f1SJacob Keller 
814dce730f1SJacob Keller /**
81578ad87daSJacob Keller  * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents
816dce730f1SJacob Keller  * @devlink: the devlink instance
817d4602a9fSAndrew Lunn  * @ops: the devlink region being snapshotted
818dce730f1SJacob Keller  * @extack: extended ACK response structure
819dce730f1SJacob Keller  * @data: on exit points to snapshot data buffer
820dce730f1SJacob Keller  *
821dce730f1SJacob Keller  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
82278ad87daSJacob Keller  * the nvm-flash devlink region. It captures a snapshot of the full NVM flash
82378ad87daSJacob Keller  * contents, including both banks of flash. This snapshot can later be viewed
82478ad87daSJacob Keller  * via the devlink-region interface.
82578ad87daSJacob Keller  *
82678ad87daSJacob Keller  * It captures the flash using the FLASH_ONLY bit set when reading via
82778ad87daSJacob Keller  * firmware, so it does not read the current Shadow RAM contents. For that,
82878ad87daSJacob Keller  * use the shadow-ram region.
829dce730f1SJacob Keller  *
830dce730f1SJacob Keller  * @returns zero on success, and updates the data pointer. Returns a non-zero
831dce730f1SJacob Keller  * error code on failure.
832dce730f1SJacob Keller  */
833dce730f1SJacob Keller static int ice_devlink_nvm_snapshot(struct devlink *devlink,
834d4602a9fSAndrew Lunn 				    const struct devlink_region_ops *ops,
835dce730f1SJacob Keller 				    struct netlink_ext_ack *extack, u8 **data)
836dce730f1SJacob Keller {
837dce730f1SJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
838dce730f1SJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
839dce730f1SJacob Keller 	struct ice_hw *hw = &pf->hw;
840dce730f1SJacob Keller 	void *nvm_data;
841dce730f1SJacob Keller 	u32 nvm_size;
8425518ac2aSTony Nguyen 	int status;
843dce730f1SJacob Keller 
8449af368faSJacob Keller 	nvm_size = hw->flash.flash_size;
845dce730f1SJacob Keller 	nvm_data = vzalloc(nvm_size);
846dce730f1SJacob Keller 	if (!nvm_data)
847dce730f1SJacob Keller 		return -ENOMEM;
848dce730f1SJacob Keller 
849dce730f1SJacob Keller 	status = ice_acquire_nvm(hw, ICE_RES_READ);
850dce730f1SJacob Keller 	if (status) {
851dce730f1SJacob Keller 		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
852dce730f1SJacob Keller 			status, hw->adminq.sq_last_status);
853dce730f1SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
854dce730f1SJacob Keller 		vfree(nvm_data);
855c1484691STony Nguyen 		return status;
856dce730f1SJacob Keller 	}
857dce730f1SJacob Keller 
858dce730f1SJacob Keller 	status = ice_read_flat_nvm(hw, 0, &nvm_size, nvm_data, false);
859dce730f1SJacob Keller 	if (status) {
860dce730f1SJacob Keller 		dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
861dce730f1SJacob Keller 			nvm_size, status, hw->adminq.sq_last_status);
862dce730f1SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
863dce730f1SJacob Keller 		ice_release_nvm(hw);
864dce730f1SJacob Keller 		vfree(nvm_data);
865c1484691STony Nguyen 		return status;
866dce730f1SJacob Keller 	}
867dce730f1SJacob Keller 
868dce730f1SJacob Keller 	ice_release_nvm(hw);
869dce730f1SJacob Keller 
870dce730f1SJacob Keller 	*data = nvm_data;
871dce730f1SJacob Keller 
872dce730f1SJacob Keller 	return 0;
873dce730f1SJacob Keller }
874dce730f1SJacob Keller 
8758d7aab35SJacob Keller /**
87678ad87daSJacob Keller  * ice_devlink_sram_snapshot - Capture a snapshot of the Shadow RAM contents
87778ad87daSJacob Keller  * @devlink: the devlink instance
87878ad87daSJacob Keller  * @ops: the devlink region being snapshotted
87978ad87daSJacob Keller  * @extack: extended ACK response structure
88078ad87daSJacob Keller  * @data: on exit points to snapshot data buffer
88178ad87daSJacob Keller  *
88278ad87daSJacob Keller  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
88378ad87daSJacob Keller  * the shadow-ram devlink region. It captures a snapshot of the shadow ram
88478ad87daSJacob Keller  * contents. This snapshot can later be viewed via the devlink-region
88578ad87daSJacob Keller  * interface.
88678ad87daSJacob Keller  *
88778ad87daSJacob Keller  * @returns zero on success, and updates the data pointer. Returns a non-zero
88878ad87daSJacob Keller  * error code on failure.
88978ad87daSJacob Keller  */
89078ad87daSJacob Keller static int
89178ad87daSJacob Keller ice_devlink_sram_snapshot(struct devlink *devlink,
89278ad87daSJacob Keller 			  const struct devlink_region_ops __always_unused *ops,
89378ad87daSJacob Keller 			  struct netlink_ext_ack *extack, u8 **data)
89478ad87daSJacob Keller {
89578ad87daSJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
89678ad87daSJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
89778ad87daSJacob Keller 	struct ice_hw *hw = &pf->hw;
89878ad87daSJacob Keller 	u8 *sram_data;
89978ad87daSJacob Keller 	u32 sram_size;
90078ad87daSJacob Keller 	int err;
90178ad87daSJacob Keller 
90278ad87daSJacob Keller 	sram_size = hw->flash.sr_words * 2u;
90378ad87daSJacob Keller 	sram_data = vzalloc(sram_size);
90478ad87daSJacob Keller 	if (!sram_data)
90578ad87daSJacob Keller 		return -ENOMEM;
90678ad87daSJacob Keller 
90778ad87daSJacob Keller 	err = ice_acquire_nvm(hw, ICE_RES_READ);
90878ad87daSJacob Keller 	if (err) {
90978ad87daSJacob Keller 		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
91078ad87daSJacob Keller 			err, hw->adminq.sq_last_status);
91178ad87daSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
91278ad87daSJacob Keller 		vfree(sram_data);
91378ad87daSJacob Keller 		return err;
91478ad87daSJacob Keller 	}
91578ad87daSJacob Keller 
91678ad87daSJacob Keller 	/* Read from the Shadow RAM, rather than directly from NVM */
91778ad87daSJacob Keller 	err = ice_read_flat_nvm(hw, 0, &sram_size, sram_data, true);
91878ad87daSJacob Keller 	if (err) {
91978ad87daSJacob Keller 		dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
92078ad87daSJacob Keller 			sram_size, err, hw->adminq.sq_last_status);
92178ad87daSJacob Keller 		NL_SET_ERR_MSG_MOD(extack,
92278ad87daSJacob Keller 				   "Failed to read Shadow RAM contents");
92378ad87daSJacob Keller 		ice_release_nvm(hw);
92478ad87daSJacob Keller 		vfree(sram_data);
92578ad87daSJacob Keller 		return err;
92678ad87daSJacob Keller 	}
92778ad87daSJacob Keller 
92878ad87daSJacob Keller 	ice_release_nvm(hw);
92978ad87daSJacob Keller 
93078ad87daSJacob Keller 	*data = sram_data;
93178ad87daSJacob Keller 
93278ad87daSJacob Keller 	return 0;
93378ad87daSJacob Keller }
93478ad87daSJacob Keller 
93578ad87daSJacob Keller /**
9368d7aab35SJacob Keller  * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities
9378d7aab35SJacob Keller  * @devlink: the devlink instance
938d4602a9fSAndrew Lunn  * @ops: the devlink region being snapshotted
9398d7aab35SJacob Keller  * @extack: extended ACK response structure
9408d7aab35SJacob Keller  * @data: on exit points to snapshot data buffer
9418d7aab35SJacob Keller  *
9428d7aab35SJacob Keller  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
9438d7aab35SJacob Keller  * the device-caps devlink region. It captures a snapshot of the device
9448d7aab35SJacob Keller  * capabilities reported by firmware.
9458d7aab35SJacob Keller  *
9468d7aab35SJacob Keller  * @returns zero on success, and updates the data pointer. Returns a non-zero
9478d7aab35SJacob Keller  * error code on failure.
9488d7aab35SJacob Keller  */
9498d7aab35SJacob Keller static int
9508d7aab35SJacob Keller ice_devlink_devcaps_snapshot(struct devlink *devlink,
951d4602a9fSAndrew Lunn 			     const struct devlink_region_ops *ops,
9528d7aab35SJacob Keller 			     struct netlink_ext_ack *extack, u8 **data)
9538d7aab35SJacob Keller {
9548d7aab35SJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
9558d7aab35SJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
9568d7aab35SJacob Keller 	struct ice_hw *hw = &pf->hw;
9578d7aab35SJacob Keller 	void *devcaps;
9585518ac2aSTony Nguyen 	int status;
9598d7aab35SJacob Keller 
9608d7aab35SJacob Keller 	devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN);
9618d7aab35SJacob Keller 	if (!devcaps)
9628d7aab35SJacob Keller 		return -ENOMEM;
9638d7aab35SJacob Keller 
9648d7aab35SJacob Keller 	status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL,
9658d7aab35SJacob Keller 				  ice_aqc_opc_list_dev_caps, NULL);
9668d7aab35SJacob Keller 	if (status) {
9678d7aab35SJacob Keller 		dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n",
9688d7aab35SJacob Keller 			status, hw->adminq.sq_last_status);
9698d7aab35SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities");
9708d7aab35SJacob Keller 		vfree(devcaps);
971c1484691STony Nguyen 		return status;
9728d7aab35SJacob Keller 	}
9738d7aab35SJacob Keller 
9748d7aab35SJacob Keller 	*data = (u8 *)devcaps;
9758d7aab35SJacob Keller 
9768d7aab35SJacob Keller 	return 0;
9778d7aab35SJacob Keller }
9788d7aab35SJacob Keller 
979dce730f1SJacob Keller static const struct devlink_region_ops ice_nvm_region_ops = {
980dce730f1SJacob Keller 	.name = "nvm-flash",
981dce730f1SJacob Keller 	.destructor = vfree,
982dce730f1SJacob Keller 	.snapshot = ice_devlink_nvm_snapshot,
983dce730f1SJacob Keller };
984dce730f1SJacob Keller 
98578ad87daSJacob Keller static const struct devlink_region_ops ice_sram_region_ops = {
98678ad87daSJacob Keller 	.name = "shadow-ram",
98778ad87daSJacob Keller 	.destructor = vfree,
98878ad87daSJacob Keller 	.snapshot = ice_devlink_sram_snapshot,
98978ad87daSJacob Keller };
99078ad87daSJacob Keller 
9918d7aab35SJacob Keller static const struct devlink_region_ops ice_devcaps_region_ops = {
9928d7aab35SJacob Keller 	.name = "device-caps",
9938d7aab35SJacob Keller 	.destructor = vfree,
9948d7aab35SJacob Keller 	.snapshot = ice_devlink_devcaps_snapshot,
9958d7aab35SJacob Keller };
9968d7aab35SJacob Keller 
997dce730f1SJacob Keller /**
998dce730f1SJacob Keller  * ice_devlink_init_regions - Initialize devlink regions
999dce730f1SJacob Keller  * @pf: the PF device structure
1000dce730f1SJacob Keller  *
1001dce730f1SJacob Keller  * Create devlink regions used to enable access to dump the contents of the
1002dce730f1SJacob Keller  * flash memory on the device.
1003dce730f1SJacob Keller  */
1004dce730f1SJacob Keller void ice_devlink_init_regions(struct ice_pf *pf)
1005dce730f1SJacob Keller {
1006dce730f1SJacob Keller 	struct devlink *devlink = priv_to_devlink(pf);
1007dce730f1SJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
100878ad87daSJacob Keller 	u64 nvm_size, sram_size;
1009dce730f1SJacob Keller 
10109af368faSJacob Keller 	nvm_size = pf->hw.flash.flash_size;
1011dce730f1SJacob Keller 	pf->nvm_region = devlink_region_create(devlink, &ice_nvm_region_ops, 1,
1012dce730f1SJacob Keller 					       nvm_size);
1013dce730f1SJacob Keller 	if (IS_ERR(pf->nvm_region)) {
1014dce730f1SJacob Keller 		dev_err(dev, "failed to create NVM devlink region, err %ld\n",
1015dce730f1SJacob Keller 			PTR_ERR(pf->nvm_region));
1016dce730f1SJacob Keller 		pf->nvm_region = NULL;
1017dce730f1SJacob Keller 	}
10188d7aab35SJacob Keller 
101978ad87daSJacob Keller 	sram_size = pf->hw.flash.sr_words * 2u;
102078ad87daSJacob Keller 	pf->sram_region = devlink_region_create(devlink, &ice_sram_region_ops,
102178ad87daSJacob Keller 						1, sram_size);
102278ad87daSJacob Keller 	if (IS_ERR(pf->sram_region)) {
102378ad87daSJacob Keller 		dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n",
102478ad87daSJacob Keller 			PTR_ERR(pf->sram_region));
102578ad87daSJacob Keller 		pf->sram_region = NULL;
102678ad87daSJacob Keller 	}
102778ad87daSJacob Keller 
10288d7aab35SJacob Keller 	pf->devcaps_region = devlink_region_create(devlink,
10298d7aab35SJacob Keller 						   &ice_devcaps_region_ops, 10,
10308d7aab35SJacob Keller 						   ICE_AQ_MAX_BUF_LEN);
10318d7aab35SJacob Keller 	if (IS_ERR(pf->devcaps_region)) {
10328d7aab35SJacob Keller 		dev_err(dev, "failed to create device-caps devlink region, err %ld\n",
10338d7aab35SJacob Keller 			PTR_ERR(pf->devcaps_region));
10348d7aab35SJacob Keller 		pf->devcaps_region = NULL;
10358d7aab35SJacob Keller 	}
1036dce730f1SJacob Keller }
1037dce730f1SJacob Keller 
1038dce730f1SJacob Keller /**
1039dce730f1SJacob Keller  * ice_devlink_destroy_regions - Destroy devlink regions
1040dce730f1SJacob Keller  * @pf: the PF device structure
1041dce730f1SJacob Keller  *
1042dce730f1SJacob Keller  * Remove previously created regions for this PF.
1043dce730f1SJacob Keller  */
1044dce730f1SJacob Keller void ice_devlink_destroy_regions(struct ice_pf *pf)
1045dce730f1SJacob Keller {
1046dce730f1SJacob Keller 	if (pf->nvm_region)
1047dce730f1SJacob Keller 		devlink_region_destroy(pf->nvm_region);
104878ad87daSJacob Keller 
104978ad87daSJacob Keller 	if (pf->sram_region)
105078ad87daSJacob Keller 		devlink_region_destroy(pf->sram_region);
105178ad87daSJacob Keller 
10528d7aab35SJacob Keller 	if (pf->devcaps_region)
10538d7aab35SJacob Keller 		devlink_region_destroy(pf->devcaps_region);
1054dce730f1SJacob Keller }
1055