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 
12*26d1c571SAnatolii Gerasymenko static int ice_active_port_option = -1;
13*26d1c571SAnatolii Gerasymenko 
1474789085SJacob Keller /* context for devlink info version reporting */
1574789085SJacob Keller struct ice_info_ctx {
1674789085SJacob Keller 	char buf[128];
17e67fbcfbSJacob Keller 	struct ice_orom_info pending_orom;
182c4fe41dSJacob Keller 	struct ice_nvm_info pending_nvm;
19e120a9abSJacob Keller 	struct ice_netlist_info pending_netlist;
202c4fe41dSJacob Keller 	struct ice_hw_dev_caps dev_caps;
2174789085SJacob Keller };
2274789085SJacob Keller 
2374789085SJacob Keller /* The following functions are used to format specific strings for various
2474789085SJacob Keller  * devlink info versions. The ctx parameter is used to provide the storage
2574789085SJacob Keller  * buffer, as well as any ancillary information calculated when the info
2674789085SJacob Keller  * request was made.
2774789085SJacob Keller  *
2874789085SJacob Keller  * If a version does not exist, for example when attempting to get the
2974789085SJacob Keller  * inactive version of flash when there is no pending update, the function
300128cc6eSJacob Keller  * should leave the buffer in the ctx structure empty.
3174789085SJacob Keller  */
3274789085SJacob Keller 
3374789085SJacob Keller static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx)
34ff2e5c70SJacob Keller {
35ff2e5c70SJacob Keller 	u8 dsn[8];
36ff2e5c70SJacob Keller 
37ff2e5c70SJacob Keller 	/* Copy the DSN into an array in Big Endian format */
38ff2e5c70SJacob Keller 	put_unaligned_be64(pci_get_dsn(pf->pdev), dsn);
39ff2e5c70SJacob Keller 
4074789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
41ff2e5c70SJacob Keller }
42ff2e5c70SJacob Keller 
430128cc6eSJacob Keller static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx)
44e961b679SJacob Keller {
45e961b679SJacob Keller 	struct ice_hw *hw = &pf->hw;
465e24d598STony Nguyen 	int status;
47e961b679SJacob Keller 
4874789085SJacob Keller 	status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf));
49e961b679SJacob Keller 	if (status)
50a8f89fa2SJacob Keller 		/* We failed to locate the PBA, so just skip this entry */
515f87ec48STony Nguyen 		dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n",
525f87ec48STony Nguyen 			status);
53e961b679SJacob Keller }
54e961b679SJacob Keller 
550128cc6eSJacob Keller static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx)
56ff2e5c70SJacob Keller {
57ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
58ff2e5c70SJacob Keller 
590128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
600128cc6eSJacob Keller 		 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch);
61ff2e5c70SJacob Keller }
62ff2e5c70SJacob Keller 
630128cc6eSJacob Keller static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx)
64ff2e5c70SJacob Keller {
65ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
66ff2e5c70SJacob Keller 
67b726ddf9SBrett Creeley 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver,
68b726ddf9SBrett Creeley 		 hw->api_min_ver, hw->api_patch);
69ff2e5c70SJacob Keller }
70ff2e5c70SJacob Keller 
710128cc6eSJacob Keller static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
72ff2e5c70SJacob Keller {
73ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
74ff2e5c70SJacob Keller 
7574789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
76ff2e5c70SJacob Keller }
77ff2e5c70SJacob Keller 
780128cc6eSJacob Keller static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
79ff2e5c70SJacob Keller {
809af368faSJacob Keller 	struct ice_orom_info *orom = &pf->hw.flash.orom;
81ff2e5c70SJacob Keller 
820128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
830128cc6eSJacob Keller 		 orom->major, orom->build, orom->patch);
84ff2e5c70SJacob Keller }
85ff2e5c70SJacob Keller 
860128cc6eSJacob Keller static void
870128cc6eSJacob Keller ice_info_pending_orom_ver(struct ice_pf __always_unused *pf,
880128cc6eSJacob Keller 			  struct ice_info_ctx *ctx)
89e67fbcfbSJacob Keller {
90e67fbcfbSJacob Keller 	struct ice_orom_info *orom = &ctx->pending_orom;
91e67fbcfbSJacob Keller 
92e67fbcfbSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_orom)
93e67fbcfbSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
94e67fbcfbSJacob Keller 			 orom->major, orom->build, orom->patch);
95e67fbcfbSJacob Keller }
96e67fbcfbSJacob Keller 
970128cc6eSJacob Keller static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
98ff2e5c70SJacob Keller {
999af368faSJacob Keller 	struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
100ff2e5c70SJacob Keller 
10174789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
102ff2e5c70SJacob Keller }
103ff2e5c70SJacob Keller 
1040128cc6eSJacob Keller static void
1050128cc6eSJacob Keller ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf,
1060128cc6eSJacob Keller 			 struct ice_info_ctx *ctx)
1072c4fe41dSJacob Keller {
1082c4fe41dSJacob Keller 	struct ice_nvm_info *nvm = &ctx->pending_nvm;
1092c4fe41dSJacob Keller 
1102c4fe41dSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
1110128cc6eSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x",
1120128cc6eSJacob Keller 			 nvm->major, nvm->minor);
1132c4fe41dSJacob Keller }
1142c4fe41dSJacob Keller 
1150128cc6eSJacob Keller static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
116ff2e5c70SJacob Keller {
1179af368faSJacob Keller 	struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
118ff2e5c70SJacob Keller 
11974789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
120ff2e5c70SJacob Keller }
121ff2e5c70SJacob Keller 
1220128cc6eSJacob Keller static void
1230128cc6eSJacob Keller ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
1242c4fe41dSJacob Keller {
1252c4fe41dSJacob Keller 	struct ice_nvm_info *nvm = &ctx->pending_nvm;
1262c4fe41dSJacob Keller 
1272c4fe41dSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
1282c4fe41dSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
1292c4fe41dSJacob Keller }
1302c4fe41dSJacob Keller 
1310128cc6eSJacob Keller static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx)
132ff2e5c70SJacob Keller {
133ff2e5c70SJacob Keller 	struct ice_hw *hw = &pf->hw;
134ff2e5c70SJacob Keller 
13574789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name);
136ff2e5c70SJacob Keller }
137ff2e5c70SJacob Keller 
1380128cc6eSJacob Keller static void
1390128cc6eSJacob Keller ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx)
140ff2e5c70SJacob Keller {
141ff2e5c70SJacob Keller 	struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver;
142ff2e5c70SJacob Keller 
1430128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u",
1440128cc6eSJacob Keller 		 pkg->major, pkg->minor, pkg->update, pkg->draft);
145ff2e5c70SJacob Keller }
146ff2e5c70SJacob Keller 
1470128cc6eSJacob Keller static void
1480128cc6eSJacob Keller ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx)
149410d0687SJacob Keller {
15074789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id);
151410d0687SJacob Keller }
152410d0687SJacob Keller 
1530128cc6eSJacob Keller static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
154f45a645fSJacob Keller {
1559af368faSJacob Keller 	struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
156f45a645fSJacob Keller 
157f45a645fSJacob Keller 	/* The netlist version fields are BCD formatted */
1580128cc6eSJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
1590128cc6eSJacob Keller 		 netlist->major, netlist->minor,
1600128cc6eSJacob Keller 		 netlist->type >> 16, netlist->type & 0xFFFF,
1610128cc6eSJacob Keller 		 netlist->rev, netlist->cust_ver);
162f45a645fSJacob Keller }
163f45a645fSJacob Keller 
1640128cc6eSJacob Keller static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
165f45a645fSJacob Keller {
1669af368faSJacob Keller 	struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
167f45a645fSJacob Keller 
16874789085SJacob Keller 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
169f45a645fSJacob Keller }
170f45a645fSJacob Keller 
1710128cc6eSJacob Keller static void
1720128cc6eSJacob Keller ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf,
1730128cc6eSJacob Keller 			     struct ice_info_ctx *ctx)
174e120a9abSJacob Keller {
175e120a9abSJacob Keller 	struct ice_netlist_info *netlist = &ctx->pending_netlist;
176e120a9abSJacob Keller 
177e120a9abSJacob Keller 	/* The netlist version fields are BCD formatted */
178e120a9abSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
179e120a9abSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
180e120a9abSJacob Keller 			 netlist->major, netlist->minor,
1810128cc6eSJacob Keller 			 netlist->type >> 16, netlist->type & 0xFFFF,
1820128cc6eSJacob Keller 			 netlist->rev, netlist->cust_ver);
183e120a9abSJacob Keller }
184e120a9abSJacob Keller 
1850128cc6eSJacob Keller static void
1860128cc6eSJacob Keller ice_info_pending_netlist_build(struct ice_pf __always_unused *pf,
1870128cc6eSJacob Keller 			       struct ice_info_ctx *ctx)
188e120a9abSJacob Keller {
189e120a9abSJacob Keller 	struct ice_netlist_info *netlist = &ctx->pending_netlist;
190e120a9abSJacob Keller 
191e120a9abSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
192e120a9abSJacob Keller 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
193e120a9abSJacob Keller }
194e120a9abSJacob Keller 
1952c4fe41dSJacob Keller #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL }
1962c4fe41dSJacob Keller #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL }
1972c4fe41dSJacob Keller #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback }
1982c4fe41dSJacob Keller 
1992c4fe41dSJacob Keller /* The combined() macro inserts both the running entry as well as a stored
2002c4fe41dSJacob Keller  * entry. The running entry will always report the version from the active
2012c4fe41dSJacob Keller  * handler. The stored entry will first try the pending handler, and fallback
2022c4fe41dSJacob Keller  * to the active handler if the pending function does not report a version.
2032c4fe41dSJacob Keller  * The pending handler should check the status of a pending update for the
2042c4fe41dSJacob Keller  * relevant flash component. It should only fill in the buffer in the case
2052c4fe41dSJacob Keller  * where a valid pending version is available. This ensures that the related
2062c4fe41dSJacob Keller  * stored and running versions remain in sync, and that stored versions are
2072c4fe41dSJacob Keller  * correctly reported as expected.
2082c4fe41dSJacob Keller  */
2092c4fe41dSJacob Keller #define combined(key, active, pending) \
2102c4fe41dSJacob Keller 	running(key, active), \
2112c4fe41dSJacob Keller 	stored(key, pending, active)
212ff2e5c70SJacob Keller 
213ff2e5c70SJacob Keller enum ice_version_type {
214ff2e5c70SJacob Keller 	ICE_VERSION_FIXED,
215ff2e5c70SJacob Keller 	ICE_VERSION_RUNNING,
216ff2e5c70SJacob Keller 	ICE_VERSION_STORED,
217ff2e5c70SJacob Keller };
218ff2e5c70SJacob Keller 
219ff2e5c70SJacob Keller static const struct ice_devlink_version {
220ff2e5c70SJacob Keller 	enum ice_version_type type;
221ff2e5c70SJacob Keller 	const char *key;
2220128cc6eSJacob Keller 	void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx);
2230128cc6eSJacob Keller 	void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx);
224ff2e5c70SJacob Keller } ice_devlink_versions[] = {
225e961b679SJacob Keller 	fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba),
226ff2e5c70SJacob Keller 	running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt),
227ff2e5c70SJacob Keller 	running("fw.mgmt.api", ice_info_fw_api),
228ff2e5c70SJacob Keller 	running("fw.mgmt.build", ice_info_fw_build),
229e67fbcfbSJacob Keller 	combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver),
2302c4fe41dSJacob Keller 	combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver),
2312c4fe41dSJacob Keller 	combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack),
232ff2e5c70SJacob Keller 	running("fw.app.name", ice_info_ddp_pkg_name),
233ff2e5c70SJacob Keller 	running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version),
234410d0687SJacob Keller 	running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id),
235e120a9abSJacob Keller 	combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver),
236e120a9abSJacob Keller 	combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build),
237ff2e5c70SJacob Keller };
238ff2e5c70SJacob Keller 
239ff2e5c70SJacob Keller /**
240ff2e5c70SJacob Keller  * ice_devlink_info_get - .info_get devlink handler
241ff2e5c70SJacob Keller  * @devlink: devlink instance structure
242ff2e5c70SJacob Keller  * @req: the devlink info request
243ff2e5c70SJacob Keller  * @extack: extended netdev ack structure
244ff2e5c70SJacob Keller  *
245ff2e5c70SJacob Keller  * Callback for the devlink .info_get operation. Reports information about the
246ff2e5c70SJacob Keller  * device.
247ff2e5c70SJacob Keller  *
248e961b679SJacob Keller  * Return: zero on success or an error code on failure.
249ff2e5c70SJacob Keller  */
250ff2e5c70SJacob Keller static int ice_devlink_info_get(struct devlink *devlink,
251ff2e5c70SJacob Keller 				struct devlink_info_req *req,
252ff2e5c70SJacob Keller 				struct netlink_ext_ack *extack)
253ff2e5c70SJacob Keller {
254ff2e5c70SJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
2552c4fe41dSJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
2562c4fe41dSJacob Keller 	struct ice_hw *hw = &pf->hw;
25774789085SJacob Keller 	struct ice_info_ctx *ctx;
258ff2e5c70SJacob Keller 	size_t i;
259ff2e5c70SJacob Keller 	int err;
260ff2e5c70SJacob Keller 
2611c08052eSJacob Keller 	err = ice_wait_for_reset(pf, 10 * HZ);
2621c08052eSJacob Keller 	if (err) {
2631c08052eSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting");
2641c08052eSJacob Keller 		return err;
2651c08052eSJacob Keller 	}
2661c08052eSJacob Keller 
26774789085SJacob Keller 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
26874789085SJacob Keller 	if (!ctx)
26974789085SJacob Keller 		return -ENOMEM;
27074789085SJacob Keller 
2712c4fe41dSJacob Keller 	/* discover capabilities first */
2722ccc1c1cSTony Nguyen 	err = ice_discover_dev_caps(hw, &ctx->dev_caps);
2732ccc1c1cSTony Nguyen 	if (err) {
2745f87ec48STony Nguyen 		dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n",
2752ccc1c1cSTony Nguyen 			err, ice_aq_str(hw->adminq.sq_last_status));
276d5f84ae9SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities");
2772c4fe41dSJacob Keller 		goto out_free_ctx;
2782c4fe41dSJacob Keller 	}
2792c4fe41dSJacob Keller 
280e67fbcfbSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_orom) {
2812ccc1c1cSTony Nguyen 		err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom);
2822ccc1c1cSTony Nguyen 		if (err) {
2835f87ec48STony Nguyen 			dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n",
2842ccc1c1cSTony Nguyen 				err, ice_aq_str(hw->adminq.sq_last_status));
285e67fbcfbSJacob Keller 
286e67fbcfbSJacob Keller 			/* disable display of pending Option ROM */
287e67fbcfbSJacob Keller 			ctx->dev_caps.common_cap.nvm_update_pending_orom = false;
288e67fbcfbSJacob Keller 		}
289e67fbcfbSJacob Keller 	}
290e67fbcfbSJacob Keller 
2912c4fe41dSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) {
2922ccc1c1cSTony Nguyen 		err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
2932ccc1c1cSTony Nguyen 		if (err) {
2945f87ec48STony Nguyen 			dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n",
2952ccc1c1cSTony Nguyen 				err, ice_aq_str(hw->adminq.sq_last_status));
2962c4fe41dSJacob Keller 
2972c4fe41dSJacob Keller 			/* disable display of pending Option ROM */
2982c4fe41dSJacob Keller 			ctx->dev_caps.common_cap.nvm_update_pending_nvm = false;
2992c4fe41dSJacob Keller 		}
3002c4fe41dSJacob Keller 	}
3012c4fe41dSJacob Keller 
302e120a9abSJacob Keller 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) {
3032ccc1c1cSTony Nguyen 		err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
3042ccc1c1cSTony Nguyen 		if (err) {
3055f87ec48STony Nguyen 			dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n",
3062ccc1c1cSTony Nguyen 				err, ice_aq_str(hw->adminq.sq_last_status));
307e120a9abSJacob Keller 
308e120a9abSJacob Keller 			/* disable display of pending Option ROM */
309e120a9abSJacob Keller 			ctx->dev_caps.common_cap.nvm_update_pending_netlist = false;
310e120a9abSJacob Keller 		}
311e120a9abSJacob Keller 	}
312e120a9abSJacob Keller 
313ff2e5c70SJacob Keller 	err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
314ff2e5c70SJacob Keller 	if (err) {
315ff2e5c70SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name");
31674789085SJacob Keller 		goto out_free_ctx;
317ff2e5c70SJacob Keller 	}
318ff2e5c70SJacob Keller 
31974789085SJacob Keller 	ice_info_get_dsn(pf, ctx);
320ff2e5c70SJacob Keller 
32174789085SJacob Keller 	err = devlink_info_serial_number_put(req, ctx->buf);
322ff2e5c70SJacob Keller 	if (err) {
323ff2e5c70SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number");
32474789085SJacob Keller 		goto out_free_ctx;
325ff2e5c70SJacob Keller 	}
326ff2e5c70SJacob Keller 
327ff2e5c70SJacob Keller 	for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) {
328ff2e5c70SJacob Keller 		enum ice_version_type type = ice_devlink_versions[i].type;
329ff2e5c70SJacob Keller 		const char *key = ice_devlink_versions[i].key;
330ff2e5c70SJacob Keller 
33174789085SJacob Keller 		memset(ctx->buf, 0, sizeof(ctx->buf));
33274789085SJacob Keller 
3330128cc6eSJacob Keller 		ice_devlink_versions[i].getter(pf, ctx);
334ff2e5c70SJacob Keller 
3352c4fe41dSJacob Keller 		/* If the default getter doesn't report a version, use the
3362c4fe41dSJacob Keller 		 * fallback function. This is primarily useful in the case of
3372c4fe41dSJacob Keller 		 * "stored" versions that want to report the same value as the
3382c4fe41dSJacob Keller 		 * running version in the normal case of no pending update.
3392c4fe41dSJacob Keller 		 */
3400128cc6eSJacob Keller 		if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback)
3410128cc6eSJacob Keller 			ice_devlink_versions[i].fallback(pf, ctx);
3422c4fe41dSJacob Keller 
34374789085SJacob Keller 		/* Do not report missing versions */
34474789085SJacob Keller 		if (ctx->buf[0] == '\0')
34574789085SJacob Keller 			continue;
34674789085SJacob Keller 
347ff2e5c70SJacob Keller 		switch (type) {
348ff2e5c70SJacob Keller 		case ICE_VERSION_FIXED:
34974789085SJacob Keller 			err = devlink_info_version_fixed_put(req, key, ctx->buf);
350ff2e5c70SJacob Keller 			if (err) {
351ff2e5c70SJacob Keller 				NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version");
35274789085SJacob Keller 				goto out_free_ctx;
353ff2e5c70SJacob Keller 			}
354ff2e5c70SJacob Keller 			break;
355ff2e5c70SJacob Keller 		case ICE_VERSION_RUNNING:
35674789085SJacob Keller 			err = devlink_info_version_running_put(req, key, ctx->buf);
357ff2e5c70SJacob Keller 			if (err) {
358ff2e5c70SJacob Keller 				NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
35974789085SJacob Keller 				goto out_free_ctx;
360ff2e5c70SJacob Keller 			}
361ff2e5c70SJacob Keller 			break;
362ff2e5c70SJacob Keller 		case ICE_VERSION_STORED:
36374789085SJacob Keller 			err = devlink_info_version_stored_put(req, key, ctx->buf);
364ff2e5c70SJacob Keller 			if (err) {
365ff2e5c70SJacob Keller 				NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
36674789085SJacob Keller 				goto out_free_ctx;
367ff2e5c70SJacob Keller 			}
368ff2e5c70SJacob Keller 			break;
369ff2e5c70SJacob Keller 		}
370ff2e5c70SJacob Keller 	}
371ff2e5c70SJacob Keller 
37274789085SJacob Keller out_free_ctx:
37374789085SJacob Keller 	kfree(ctx);
37474789085SJacob Keller 	return err;
375ff2e5c70SJacob Keller }
376ff2e5c70SJacob Keller 
377399e27dbSJacob Keller /**
378399e27dbSJacob Keller  * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware
379399e27dbSJacob Keller  * @devlink: pointer to the devlink instance to reload
380399e27dbSJacob Keller  * @netns_change: if true, the network namespace is changing
381399e27dbSJacob Keller  * @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE
382399e27dbSJacob Keller  * @limit: limits on what reload should do, such as not resetting
383399e27dbSJacob Keller  * @extack: netlink extended ACK structure
384399e27dbSJacob Keller  *
385399e27dbSJacob Keller  * Allow user to activate new Embedded Management Processor firmware by
386399e27dbSJacob Keller  * issuing device specific EMP reset. Called in response to
387399e27dbSJacob Keller  * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE.
388399e27dbSJacob Keller  *
389399e27dbSJacob Keller  * Note that teardown and rebuild of the driver state happens automatically as
390399e27dbSJacob Keller  * part of an interrupt and watchdog task. This is because all physical
391399e27dbSJacob Keller  * functions on the device must be able to reset when an EMP reset occurs from
392399e27dbSJacob Keller  * any source.
393399e27dbSJacob Keller  */
394399e27dbSJacob Keller static int
395399e27dbSJacob Keller ice_devlink_reload_empr_start(struct devlink *devlink, bool netns_change,
396399e27dbSJacob Keller 			      enum devlink_reload_action action,
397399e27dbSJacob Keller 			      enum devlink_reload_limit limit,
398399e27dbSJacob Keller 			      struct netlink_ext_ack *extack)
399399e27dbSJacob Keller {
400399e27dbSJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
401399e27dbSJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
402399e27dbSJacob Keller 	struct ice_hw *hw = &pf->hw;
403399e27dbSJacob Keller 	u8 pending;
404399e27dbSJacob Keller 	int err;
405399e27dbSJacob Keller 
406399e27dbSJacob Keller 	err = ice_get_pending_updates(pf, &pending, extack);
407399e27dbSJacob Keller 	if (err)
408399e27dbSJacob Keller 		return err;
409399e27dbSJacob Keller 
410399e27dbSJacob Keller 	/* pending is a bitmask of which flash banks have a pending update,
411399e27dbSJacob Keller 	 * including the main NVM bank, the Option ROM bank, and the netlist
412399e27dbSJacob Keller 	 * bank. If any of these bits are set, then there is a pending update
413399e27dbSJacob Keller 	 * waiting to be activated.
414399e27dbSJacob Keller 	 */
415399e27dbSJacob Keller 	if (!pending) {
416399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "No pending firmware update");
417399e27dbSJacob Keller 		return -ECANCELED;
418399e27dbSJacob Keller 	}
419399e27dbSJacob Keller 
420399e27dbSJacob Keller 	if (pf->fw_emp_reset_disabled) {
421399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed");
422399e27dbSJacob Keller 		return -ECANCELED;
423399e27dbSJacob Keller 	}
424399e27dbSJacob Keller 
425399e27dbSJacob Keller 	dev_dbg(dev, "Issuing device EMP reset to activate firmware\n");
426399e27dbSJacob Keller 
427399e27dbSJacob Keller 	err = ice_aq_nvm_update_empr(hw);
428399e27dbSJacob Keller 	if (err) {
429399e27dbSJacob Keller 		dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n",
430399e27dbSJacob Keller 			err, ice_aq_str(hw->adminq.sq_last_status));
431399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware");
432399e27dbSJacob Keller 		return err;
433399e27dbSJacob Keller 	}
434399e27dbSJacob Keller 
435399e27dbSJacob Keller 	return 0;
436399e27dbSJacob Keller }
437399e27dbSJacob Keller 
438399e27dbSJacob Keller /**
439399e27dbSJacob Keller  * ice_devlink_reload_empr_finish - Wait for EMP reset to finish
440399e27dbSJacob Keller  * @devlink: pointer to the devlink instance reloading
441399e27dbSJacob Keller  * @action: the action requested
442399e27dbSJacob Keller  * @limit: limits imposed by userspace, such as not resetting
443399e27dbSJacob Keller  * @actions_performed: on return, indicate what actions actually performed
444399e27dbSJacob Keller  * @extack: netlink extended ACK structure
445399e27dbSJacob Keller  *
446399e27dbSJacob Keller  * Wait for driver to finish rebuilding after EMP reset is completed. This
447399e27dbSJacob Keller  * includes time to wait for both the actual device reset as well as the time
448399e27dbSJacob Keller  * for the driver's rebuild to complete.
449399e27dbSJacob Keller  */
450399e27dbSJacob Keller static int
451399e27dbSJacob Keller ice_devlink_reload_empr_finish(struct devlink *devlink,
452399e27dbSJacob Keller 			       enum devlink_reload_action action,
453399e27dbSJacob Keller 			       enum devlink_reload_limit limit,
454399e27dbSJacob Keller 			       u32 *actions_performed,
455399e27dbSJacob Keller 			       struct netlink_ext_ack *extack)
456399e27dbSJacob Keller {
457399e27dbSJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
458399e27dbSJacob Keller 	int err;
459399e27dbSJacob Keller 
460399e27dbSJacob Keller 	*actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
461399e27dbSJacob Keller 
462399e27dbSJacob Keller 	err = ice_wait_for_reset(pf, 60 * HZ);
463399e27dbSJacob Keller 	if (err) {
464399e27dbSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute");
465399e27dbSJacob Keller 		return err;
466399e27dbSJacob Keller 	}
467399e27dbSJacob Keller 
468399e27dbSJacob Keller 	return 0;
469399e27dbSJacob Keller }
470399e27dbSJacob Keller 
471*26d1c571SAnatolii Gerasymenko /**
472*26d1c571SAnatolii Gerasymenko  * ice_devlink_port_opt_speed_str - convert speed to a string
473*26d1c571SAnatolii Gerasymenko  * @speed: speed value
474*26d1c571SAnatolii Gerasymenko  */
475*26d1c571SAnatolii Gerasymenko static const char *ice_devlink_port_opt_speed_str(u8 speed)
476*26d1c571SAnatolii Gerasymenko {
477*26d1c571SAnatolii Gerasymenko 	switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) {
478*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_100M:
479*26d1c571SAnatolii Gerasymenko 		return "0.1";
480*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_1G:
481*26d1c571SAnatolii Gerasymenko 		return "1";
482*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_2500M:
483*26d1c571SAnatolii Gerasymenko 		return "2.5";
484*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_5G:
485*26d1c571SAnatolii Gerasymenko 		return "5";
486*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_10G:
487*26d1c571SAnatolii Gerasymenko 		return "10";
488*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_25G:
489*26d1c571SAnatolii Gerasymenko 		return "25";
490*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_50G:
491*26d1c571SAnatolii Gerasymenko 		return "50";
492*26d1c571SAnatolii Gerasymenko 	case ICE_AQC_PORT_OPT_MAX_LANE_100G:
493*26d1c571SAnatolii Gerasymenko 		return "100";
494*26d1c571SAnatolii Gerasymenko 	}
495*26d1c571SAnatolii Gerasymenko 
496*26d1c571SAnatolii Gerasymenko 	return "-";
497*26d1c571SAnatolii Gerasymenko }
498*26d1c571SAnatolii Gerasymenko 
499*26d1c571SAnatolii Gerasymenko #define ICE_PORT_OPT_DESC_LEN	50
500*26d1c571SAnatolii Gerasymenko /**
501*26d1c571SAnatolii Gerasymenko  * ice_devlink_port_options_print - Print available port split options
502*26d1c571SAnatolii Gerasymenko  * @pf: the PF to print split port options
503*26d1c571SAnatolii Gerasymenko  *
504*26d1c571SAnatolii Gerasymenko  * Prints a table with available port split options and max port speeds
505*26d1c571SAnatolii Gerasymenko  */
506*26d1c571SAnatolii Gerasymenko static void ice_devlink_port_options_print(struct ice_pf *pf)
507*26d1c571SAnatolii Gerasymenko {
508*26d1c571SAnatolii Gerasymenko 	u8 i, j, options_count, cnt, speed, pending_idx, active_idx;
509*26d1c571SAnatolii Gerasymenko 	struct ice_aqc_get_port_options_elem *options, *opt;
510*26d1c571SAnatolii Gerasymenko 	struct device *dev = ice_pf_to_dev(pf);
511*26d1c571SAnatolii Gerasymenko 	bool active_valid, pending_valid;
512*26d1c571SAnatolii Gerasymenko 	char desc[ICE_PORT_OPT_DESC_LEN];
513*26d1c571SAnatolii Gerasymenko 	const char *str;
514*26d1c571SAnatolii Gerasymenko 	int status;
515*26d1c571SAnatolii Gerasymenko 
516*26d1c571SAnatolii Gerasymenko 	options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV,
517*26d1c571SAnatolii Gerasymenko 			  sizeof(*options), GFP_KERNEL);
518*26d1c571SAnatolii Gerasymenko 	if (!options)
519*26d1c571SAnatolii Gerasymenko 		return;
520*26d1c571SAnatolii Gerasymenko 
521*26d1c571SAnatolii Gerasymenko 	for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) {
522*26d1c571SAnatolii Gerasymenko 		opt = options + i * ICE_AQC_PORT_OPT_MAX;
523*26d1c571SAnatolii Gerasymenko 		options_count = ICE_AQC_PORT_OPT_MAX;
524*26d1c571SAnatolii Gerasymenko 		active_valid = 0;
525*26d1c571SAnatolii Gerasymenko 
526*26d1c571SAnatolii Gerasymenko 		status = ice_aq_get_port_options(&pf->hw, opt, &options_count,
527*26d1c571SAnatolii Gerasymenko 						 i, true, &active_idx,
528*26d1c571SAnatolii Gerasymenko 						 &active_valid, &pending_idx,
529*26d1c571SAnatolii Gerasymenko 						 &pending_valid);
530*26d1c571SAnatolii Gerasymenko 		if (status) {
531*26d1c571SAnatolii Gerasymenko 			dev_dbg(dev, "Couldn't read port option for port %d, err %d\n",
532*26d1c571SAnatolii Gerasymenko 				i, status);
533*26d1c571SAnatolii Gerasymenko 			goto err;
534*26d1c571SAnatolii Gerasymenko 		}
535*26d1c571SAnatolii Gerasymenko 	}
536*26d1c571SAnatolii Gerasymenko 
537*26d1c571SAnatolii Gerasymenko 	dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n");
538*26d1c571SAnatolii Gerasymenko 	dev_dbg(dev, "Status  Split      Quad 0          Quad 1\n");
539*26d1c571SAnatolii Gerasymenko 	dev_dbg(dev, "        count  L0  L1  L2  L3  L4  L5  L6  L7\n");
540*26d1c571SAnatolii Gerasymenko 
541*26d1c571SAnatolii Gerasymenko 	for (i = 0; i < options_count; i++) {
542*26d1c571SAnatolii Gerasymenko 		cnt = 0;
543*26d1c571SAnatolii Gerasymenko 
544*26d1c571SAnatolii Gerasymenko 		if (i == ice_active_port_option)
545*26d1c571SAnatolii Gerasymenko 			str = "Active";
546*26d1c571SAnatolii Gerasymenko 		else if ((i == pending_idx) && pending_valid)
547*26d1c571SAnatolii Gerasymenko 			str = "Pending";
548*26d1c571SAnatolii Gerasymenko 		else
549*26d1c571SAnatolii Gerasymenko 			str = "";
550*26d1c571SAnatolii Gerasymenko 
551*26d1c571SAnatolii Gerasymenko 		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
552*26d1c571SAnatolii Gerasymenko 				"%-8s", str);
553*26d1c571SAnatolii Gerasymenko 
554*26d1c571SAnatolii Gerasymenko 		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
555*26d1c571SAnatolii Gerasymenko 				"%-6u", options[i].pmd);
556*26d1c571SAnatolii Gerasymenko 
557*26d1c571SAnatolii Gerasymenko 		for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) {
558*26d1c571SAnatolii Gerasymenko 			speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed;
559*26d1c571SAnatolii Gerasymenko 			str = ice_devlink_port_opt_speed_str(speed);
560*26d1c571SAnatolii Gerasymenko 			cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
561*26d1c571SAnatolii Gerasymenko 					"%3s ", str);
562*26d1c571SAnatolii Gerasymenko 		}
563*26d1c571SAnatolii Gerasymenko 
564*26d1c571SAnatolii Gerasymenko 		dev_dbg(dev, "%s\n", desc);
565*26d1c571SAnatolii Gerasymenko 	}
566*26d1c571SAnatolii Gerasymenko 
567*26d1c571SAnatolii Gerasymenko err:
568*26d1c571SAnatolii Gerasymenko 	kfree(options);
569*26d1c571SAnatolii Gerasymenko }
570*26d1c571SAnatolii Gerasymenko 
571*26d1c571SAnatolii Gerasymenko /**
572*26d1c571SAnatolii Gerasymenko  * ice_devlink_aq_set_port_option - Send set port option admin queue command
573*26d1c571SAnatolii Gerasymenko  * @pf: the PF to print split port options
574*26d1c571SAnatolii Gerasymenko  * @option_idx: selected port option
575*26d1c571SAnatolii Gerasymenko  * @extack: extended netdev ack structure
576*26d1c571SAnatolii Gerasymenko  *
577*26d1c571SAnatolii Gerasymenko  * Sends set port option admin queue command with selected port option and
578*26d1c571SAnatolii Gerasymenko  * calls NVM write activate.
579*26d1c571SAnatolii Gerasymenko  */
580*26d1c571SAnatolii Gerasymenko static int
581*26d1c571SAnatolii Gerasymenko ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx,
582*26d1c571SAnatolii Gerasymenko 			       struct netlink_ext_ack *extack)
583*26d1c571SAnatolii Gerasymenko {
584*26d1c571SAnatolii Gerasymenko 	struct device *dev = ice_pf_to_dev(pf);
585*26d1c571SAnatolii Gerasymenko 	int status;
586*26d1c571SAnatolii Gerasymenko 
587*26d1c571SAnatolii Gerasymenko 	status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx);
588*26d1c571SAnatolii Gerasymenko 	if (status) {
589*26d1c571SAnatolii Gerasymenko 		dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n",
590*26d1c571SAnatolii Gerasymenko 			status, pf->hw.adminq.sq_last_status);
591*26d1c571SAnatolii Gerasymenko 		NL_SET_ERR_MSG_MOD(extack, "Port split request failed");
592*26d1c571SAnatolii Gerasymenko 		return -EIO;
593*26d1c571SAnatolii Gerasymenko 	}
594*26d1c571SAnatolii Gerasymenko 
595*26d1c571SAnatolii Gerasymenko 	status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE);
596*26d1c571SAnatolii Gerasymenko 	if (status) {
597*26d1c571SAnatolii Gerasymenko 		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
598*26d1c571SAnatolii Gerasymenko 			status, pf->hw.adminq.sq_last_status);
599*26d1c571SAnatolii Gerasymenko 		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
600*26d1c571SAnatolii Gerasymenko 		return -EIO;
601*26d1c571SAnatolii Gerasymenko 	}
602*26d1c571SAnatolii Gerasymenko 
603*26d1c571SAnatolii Gerasymenko 	status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL);
604*26d1c571SAnatolii Gerasymenko 	if (status) {
605*26d1c571SAnatolii Gerasymenko 		dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n",
606*26d1c571SAnatolii Gerasymenko 			status, pf->hw.adminq.sq_last_status);
607*26d1c571SAnatolii Gerasymenko 		NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data");
608*26d1c571SAnatolii Gerasymenko 		ice_release_nvm(&pf->hw);
609*26d1c571SAnatolii Gerasymenko 		return -EIO;
610*26d1c571SAnatolii Gerasymenko 	}
611*26d1c571SAnatolii Gerasymenko 
612*26d1c571SAnatolii Gerasymenko 	ice_release_nvm(&pf->hw);
613*26d1c571SAnatolii Gerasymenko 
614*26d1c571SAnatolii Gerasymenko 	NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split");
615*26d1c571SAnatolii Gerasymenko 	return 0;
616*26d1c571SAnatolii Gerasymenko }
617*26d1c571SAnatolii Gerasymenko 
618*26d1c571SAnatolii Gerasymenko /**
619*26d1c571SAnatolii Gerasymenko  * ice_devlink_port_split - .port_split devlink handler
620*26d1c571SAnatolii Gerasymenko  * @devlink: devlink instance structure
621*26d1c571SAnatolii Gerasymenko  * @port: devlink port structure
622*26d1c571SAnatolii Gerasymenko  * @count: number of ports to split to
623*26d1c571SAnatolii Gerasymenko  * @extack: extended netdev ack structure
624*26d1c571SAnatolii Gerasymenko  *
625*26d1c571SAnatolii Gerasymenko  * Callback for the devlink .port_split operation.
626*26d1c571SAnatolii Gerasymenko  *
627*26d1c571SAnatolii Gerasymenko  * Unfortunately, the devlink expression of available options is limited
628*26d1c571SAnatolii Gerasymenko  * to just a number, so search for an FW port option which supports
629*26d1c571SAnatolii Gerasymenko  * the specified number. As there could be multiple FW port options with
630*26d1c571SAnatolii Gerasymenko  * the same port split count, allow switching between them. When the same
631*26d1c571SAnatolii Gerasymenko  * port split count request is issued again, switch to the next FW port
632*26d1c571SAnatolii Gerasymenko  * option with the same port split count.
633*26d1c571SAnatolii Gerasymenko  *
634*26d1c571SAnatolii Gerasymenko  * Return: zero on success or an error code on failure.
635*26d1c571SAnatolii Gerasymenko  */
636*26d1c571SAnatolii Gerasymenko static int
637*26d1c571SAnatolii Gerasymenko ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port,
638*26d1c571SAnatolii Gerasymenko 		       unsigned int count, struct netlink_ext_ack *extack)
639*26d1c571SAnatolii Gerasymenko {
640*26d1c571SAnatolii Gerasymenko 	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
641*26d1c571SAnatolii Gerasymenko 	u8 i, j, active_idx, pending_idx, new_option;
642*26d1c571SAnatolii Gerasymenko 	struct ice_pf *pf = devlink_priv(devlink);
643*26d1c571SAnatolii Gerasymenko 	u8 option_count = ICE_AQC_PORT_OPT_MAX;
644*26d1c571SAnatolii Gerasymenko 	struct device *dev = ice_pf_to_dev(pf);
645*26d1c571SAnatolii Gerasymenko 	bool active_valid, pending_valid;
646*26d1c571SAnatolii Gerasymenko 	int status;
647*26d1c571SAnatolii Gerasymenko 
648*26d1c571SAnatolii Gerasymenko 	status = ice_aq_get_port_options(&pf->hw, options, &option_count,
649*26d1c571SAnatolii Gerasymenko 					 0, true, &active_idx, &active_valid,
650*26d1c571SAnatolii Gerasymenko 					 &pending_idx, &pending_valid);
651*26d1c571SAnatolii Gerasymenko 	if (status) {
652*26d1c571SAnatolii Gerasymenko 		dev_dbg(dev, "Couldn't read port split options, err = %d\n",
653*26d1c571SAnatolii Gerasymenko 			status);
654*26d1c571SAnatolii Gerasymenko 		NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options");
655*26d1c571SAnatolii Gerasymenko 		return -EIO;
656*26d1c571SAnatolii Gerasymenko 	}
657*26d1c571SAnatolii Gerasymenko 
658*26d1c571SAnatolii Gerasymenko 	new_option = ICE_AQC_PORT_OPT_MAX;
659*26d1c571SAnatolii Gerasymenko 	active_idx = pending_valid ? pending_idx : active_idx;
660*26d1c571SAnatolii Gerasymenko 	for (i = 1; i <= option_count; i++) {
661*26d1c571SAnatolii Gerasymenko 		/* In order to allow switching between FW port options with
662*26d1c571SAnatolii Gerasymenko 		 * the same port split count, search for a new option starting
663*26d1c571SAnatolii Gerasymenko 		 * from the active/pending option (with array wrap around).
664*26d1c571SAnatolii Gerasymenko 		 */
665*26d1c571SAnatolii Gerasymenko 		j = (active_idx + i) % option_count;
666*26d1c571SAnatolii Gerasymenko 
667*26d1c571SAnatolii Gerasymenko 		if (count == options[j].pmd) {
668*26d1c571SAnatolii Gerasymenko 			new_option = j;
669*26d1c571SAnatolii Gerasymenko 			break;
670*26d1c571SAnatolii Gerasymenko 		}
671*26d1c571SAnatolii Gerasymenko 	}
672*26d1c571SAnatolii Gerasymenko 
673*26d1c571SAnatolii Gerasymenko 	if (new_option == active_idx) {
674*26d1c571SAnatolii Gerasymenko 		dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n",
675*26d1c571SAnatolii Gerasymenko 			count);
676*26d1c571SAnatolii Gerasymenko 		NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set");
677*26d1c571SAnatolii Gerasymenko 		ice_devlink_port_options_print(pf);
678*26d1c571SAnatolii Gerasymenko 		return -EINVAL;
679*26d1c571SAnatolii Gerasymenko 	}
680*26d1c571SAnatolii Gerasymenko 
681*26d1c571SAnatolii Gerasymenko 	if (new_option == ICE_AQC_PORT_OPT_MAX) {
682*26d1c571SAnatolii Gerasymenko 		dev_dbg(dev, "request to split: count: %u not found\n", count);
683*26d1c571SAnatolii Gerasymenko 		NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config");
684*26d1c571SAnatolii Gerasymenko 		ice_devlink_port_options_print(pf);
685*26d1c571SAnatolii Gerasymenko 		return -EINVAL;
686*26d1c571SAnatolii Gerasymenko 	}
687*26d1c571SAnatolii Gerasymenko 
688*26d1c571SAnatolii Gerasymenko 	status = ice_devlink_aq_set_port_option(pf, new_option, extack);
689*26d1c571SAnatolii Gerasymenko 	if (status)
690*26d1c571SAnatolii Gerasymenko 		return status;
691*26d1c571SAnatolii Gerasymenko 
692*26d1c571SAnatolii Gerasymenko 	ice_devlink_port_options_print(pf);
693*26d1c571SAnatolii Gerasymenko 
694*26d1c571SAnatolii Gerasymenko 	return 0;
695*26d1c571SAnatolii Gerasymenko }
696*26d1c571SAnatolii Gerasymenko 
697*26d1c571SAnatolii Gerasymenko /**
698*26d1c571SAnatolii Gerasymenko  * ice_devlink_port_unsplit - .port_unsplit devlink handler
699*26d1c571SAnatolii Gerasymenko  * @devlink: devlink instance structure
700*26d1c571SAnatolii Gerasymenko  * @port: devlink port structure
701*26d1c571SAnatolii Gerasymenko  * @extack: extended netdev ack structure
702*26d1c571SAnatolii Gerasymenko  *
703*26d1c571SAnatolii Gerasymenko  * Callback for the devlink .port_unsplit operation.
704*26d1c571SAnatolii Gerasymenko  * Calls ice_devlink_port_split with split count set to 1.
705*26d1c571SAnatolii Gerasymenko  * There could be no FW option available with split count 1.
706*26d1c571SAnatolii Gerasymenko  *
707*26d1c571SAnatolii Gerasymenko  * Return: zero on success or an error code on failure.
708*26d1c571SAnatolii Gerasymenko  */
709*26d1c571SAnatolii Gerasymenko static int
710*26d1c571SAnatolii Gerasymenko ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,
711*26d1c571SAnatolii Gerasymenko 			 struct netlink_ext_ack *extack)
712*26d1c571SAnatolii Gerasymenko {
713*26d1c571SAnatolii Gerasymenko 	return ice_devlink_port_split(devlink, port, 1, extack);
714*26d1c571SAnatolii Gerasymenko }
715*26d1c571SAnatolii Gerasymenko 
7161adf7eadSJacob Keller static const struct devlink_ops ice_devlink_ops = {
71750db1bcaSJacob Keller 	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
718399e27dbSJacob Keller 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
719399e27dbSJacob Keller 	/* The ice driver currently does not support driver reinit */
720399e27dbSJacob Keller 	.reload_down = ice_devlink_reload_empr_start,
721399e27dbSJacob Keller 	.reload_up = ice_devlink_reload_empr_finish,
722*26d1c571SAnatolii Gerasymenko 	.port_split = ice_devlink_port_split,
723*26d1c571SAnatolii Gerasymenko 	.port_unsplit = ice_devlink_port_unsplit,
7243ea9bd5dSMichal Swiatkowski 	.eswitch_mode_get = ice_eswitch_mode_get,
7253ea9bd5dSMichal Swiatkowski 	.eswitch_mode_set = ice_eswitch_mode_set,
726ff2e5c70SJacob Keller 	.info_get = ice_devlink_info_get,
727d69ea414SJacob Keller 	.flash_update = ice_devlink_flash_update,
7281adf7eadSJacob Keller };
7291adf7eadSJacob Keller 
730e523af4eSShiraz Saleem static int
731e523af4eSShiraz Saleem ice_devlink_enable_roce_get(struct devlink *devlink, u32 id,
732e523af4eSShiraz Saleem 			    struct devlink_param_gset_ctx *ctx)
733e523af4eSShiraz Saleem {
734e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
735e523af4eSShiraz Saleem 
7367b62483fSShiraz Saleem 	ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false;
737e523af4eSShiraz Saleem 
738e523af4eSShiraz Saleem 	return 0;
739e523af4eSShiraz Saleem }
740e523af4eSShiraz Saleem 
741e523af4eSShiraz Saleem static int
742e523af4eSShiraz Saleem ice_devlink_enable_roce_set(struct devlink *devlink, u32 id,
743e523af4eSShiraz Saleem 			    struct devlink_param_gset_ctx *ctx)
744e523af4eSShiraz Saleem {
745e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
746e523af4eSShiraz Saleem 	bool roce_ena = ctx->val.vbool;
747e523af4eSShiraz Saleem 	int ret;
748e523af4eSShiraz Saleem 
749e523af4eSShiraz Saleem 	if (!roce_ena) {
750e523af4eSShiraz Saleem 		ice_unplug_aux_dev(pf);
751e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2;
752e523af4eSShiraz Saleem 		return 0;
753e523af4eSShiraz Saleem 	}
754e523af4eSShiraz Saleem 
755e523af4eSShiraz Saleem 	pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2;
756e523af4eSShiraz Saleem 	ret = ice_plug_aux_dev(pf);
757e523af4eSShiraz Saleem 	if (ret)
758e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2;
759e523af4eSShiraz Saleem 
760e523af4eSShiraz Saleem 	return ret;
761e523af4eSShiraz Saleem }
762e523af4eSShiraz Saleem 
763e523af4eSShiraz Saleem static int
764e523af4eSShiraz Saleem ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
765e523af4eSShiraz Saleem 				 union devlink_param_value val,
766e523af4eSShiraz Saleem 				 struct netlink_ext_ack *extack)
767e523af4eSShiraz Saleem {
768e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
769e523af4eSShiraz Saleem 
770e523af4eSShiraz Saleem 	if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
771e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
772e523af4eSShiraz Saleem 
773e523af4eSShiraz Saleem 	if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) {
774e523af4eSShiraz Saleem 		NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously");
775e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
776e523af4eSShiraz Saleem 	}
777e523af4eSShiraz Saleem 
778e523af4eSShiraz Saleem 	return 0;
779e523af4eSShiraz Saleem }
780e523af4eSShiraz Saleem 
781e523af4eSShiraz Saleem static int
782e523af4eSShiraz Saleem ice_devlink_enable_iw_get(struct devlink *devlink, u32 id,
783e523af4eSShiraz Saleem 			  struct devlink_param_gset_ctx *ctx)
784e523af4eSShiraz Saleem {
785e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
786e523af4eSShiraz Saleem 
787e523af4eSShiraz Saleem 	ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP;
788e523af4eSShiraz Saleem 
789e523af4eSShiraz Saleem 	return 0;
790e523af4eSShiraz Saleem }
791e523af4eSShiraz Saleem 
792e523af4eSShiraz Saleem static int
793e523af4eSShiraz Saleem ice_devlink_enable_iw_set(struct devlink *devlink, u32 id,
794e523af4eSShiraz Saleem 			  struct devlink_param_gset_ctx *ctx)
795e523af4eSShiraz Saleem {
796e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
797e523af4eSShiraz Saleem 	bool iw_ena = ctx->val.vbool;
798e523af4eSShiraz Saleem 	int ret;
799e523af4eSShiraz Saleem 
800e523af4eSShiraz Saleem 	if (!iw_ena) {
801e523af4eSShiraz Saleem 		ice_unplug_aux_dev(pf);
802e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP;
803e523af4eSShiraz Saleem 		return 0;
804e523af4eSShiraz Saleem 	}
805e523af4eSShiraz Saleem 
806e523af4eSShiraz Saleem 	pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP;
807e523af4eSShiraz Saleem 	ret = ice_plug_aux_dev(pf);
808e523af4eSShiraz Saleem 	if (ret)
809e523af4eSShiraz Saleem 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP;
810e523af4eSShiraz Saleem 
811e523af4eSShiraz Saleem 	return ret;
812e523af4eSShiraz Saleem }
813e523af4eSShiraz Saleem 
814e523af4eSShiraz Saleem static int
815e523af4eSShiraz Saleem ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id,
816e523af4eSShiraz Saleem 			       union devlink_param_value val,
817e523af4eSShiraz Saleem 			       struct netlink_ext_ack *extack)
818e523af4eSShiraz Saleem {
819e523af4eSShiraz Saleem 	struct ice_pf *pf = devlink_priv(devlink);
820e523af4eSShiraz Saleem 
821e523af4eSShiraz Saleem 	if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
822e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
823e523af4eSShiraz Saleem 
824e523af4eSShiraz Saleem 	if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) {
825e523af4eSShiraz Saleem 		NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously");
826e523af4eSShiraz Saleem 		return -EOPNOTSUPP;
827e523af4eSShiraz Saleem 	}
828e523af4eSShiraz Saleem 
829e523af4eSShiraz Saleem 	return 0;
830e523af4eSShiraz Saleem }
831e523af4eSShiraz Saleem 
832e523af4eSShiraz Saleem static const struct devlink_param ice_devlink_params[] = {
833e523af4eSShiraz Saleem 	DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
834e523af4eSShiraz Saleem 			      ice_devlink_enable_roce_get,
835e523af4eSShiraz Saleem 			      ice_devlink_enable_roce_set,
836e523af4eSShiraz Saleem 			      ice_devlink_enable_roce_validate),
837e523af4eSShiraz Saleem 	DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
838e523af4eSShiraz Saleem 			      ice_devlink_enable_iw_get,
839e523af4eSShiraz Saleem 			      ice_devlink_enable_iw_set,
840e523af4eSShiraz Saleem 			      ice_devlink_enable_iw_validate),
841e523af4eSShiraz Saleem 
842e523af4eSShiraz Saleem };
843e523af4eSShiraz Saleem 
8441adf7eadSJacob Keller static void ice_devlink_free(void *devlink_ptr)
8451adf7eadSJacob Keller {
8461adf7eadSJacob Keller 	devlink_free((struct devlink *)devlink_ptr);
8471adf7eadSJacob Keller }
8481adf7eadSJacob Keller 
8491adf7eadSJacob Keller /**
8501adf7eadSJacob Keller  * ice_allocate_pf - Allocate devlink and return PF structure pointer
8511adf7eadSJacob Keller  * @dev: the device to allocate for
8521adf7eadSJacob Keller  *
8531adf7eadSJacob Keller  * Allocate a devlink instance for this device and return the private area as
8541adf7eadSJacob Keller  * the PF structure. The devlink memory is kept track of through devres by
8551adf7eadSJacob Keller  * adding an action to remove it when unwinding.
8561adf7eadSJacob Keller  */
8571adf7eadSJacob Keller struct ice_pf *ice_allocate_pf(struct device *dev)
8581adf7eadSJacob Keller {
8591adf7eadSJacob Keller 	struct devlink *devlink;
8601adf7eadSJacob Keller 
861919d13a7SLeon Romanovsky 	devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev);
8621adf7eadSJacob Keller 	if (!devlink)
8631adf7eadSJacob Keller 		return NULL;
8641adf7eadSJacob Keller 
8651adf7eadSJacob Keller 	/* Add an action to teardown the devlink when unwinding the driver */
8667c1b694aSCai Huoqing 	if (devm_add_action_or_reset(dev, ice_devlink_free, devlink))
8671adf7eadSJacob Keller 		return NULL;
8681adf7eadSJacob Keller 
8691adf7eadSJacob Keller 	return devlink_priv(devlink);
8701adf7eadSJacob Keller }
8711adf7eadSJacob Keller 
8721adf7eadSJacob Keller /**
8731adf7eadSJacob Keller  * ice_devlink_register - Register devlink interface for this PF
8741adf7eadSJacob Keller  * @pf: the PF to register the devlink for.
8751adf7eadSJacob Keller  *
8761adf7eadSJacob Keller  * Register the devlink instance associated with this physical function.
8771adf7eadSJacob Keller  *
8781adf7eadSJacob Keller  * Return: zero on success or an error code on failure.
8791adf7eadSJacob Keller  */
880db4278c5SLeon Romanovsky void ice_devlink_register(struct ice_pf *pf)
8811adf7eadSJacob Keller {
8821adf7eadSJacob Keller 	struct devlink *devlink = priv_to_devlink(pf);
8831adf7eadSJacob Keller 
884399e27dbSJacob Keller 	devlink_set_features(devlink, DEVLINK_F_RELOAD);
885db4278c5SLeon Romanovsky 	devlink_register(devlink);
8861adf7eadSJacob Keller }
8871adf7eadSJacob Keller 
8881adf7eadSJacob Keller /**
8891adf7eadSJacob Keller  * ice_devlink_unregister - Unregister devlink resources for this PF.
8901adf7eadSJacob Keller  * @pf: the PF structure to cleanup
8911adf7eadSJacob Keller  *
8921adf7eadSJacob Keller  * Releases resources used by devlink and cleans up associated memory.
8931adf7eadSJacob Keller  */
8941adf7eadSJacob Keller void ice_devlink_unregister(struct ice_pf *pf)
8951adf7eadSJacob Keller {
8961adf7eadSJacob Keller 	devlink_unregister(priv_to_devlink(pf));
8971adf7eadSJacob Keller }
8981adf7eadSJacob Keller 
8994b889474SMichal Swiatkowski /**
9004b889474SMichal Swiatkowski  * ice_devlink_set_switch_id - Set unique switch id based on pci dsn
9014b889474SMichal Swiatkowski  * @pf: the PF to create a devlink port for
9024b889474SMichal Swiatkowski  * @ppid: struct with switch id information
9034b889474SMichal Swiatkowski  */
9044b889474SMichal Swiatkowski static void
9054b889474SMichal Swiatkowski ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid)
9064b889474SMichal Swiatkowski {
9074b889474SMichal Swiatkowski 	struct pci_dev *pdev = pf->pdev;
9084b889474SMichal Swiatkowski 	u64 id;
9094b889474SMichal Swiatkowski 
9104b889474SMichal Swiatkowski 	id = pci_get_dsn(pdev);
9114b889474SMichal Swiatkowski 
9124b889474SMichal Swiatkowski 	ppid->id_len = sizeof(id);
9134b889474SMichal Swiatkowski 	put_unaligned_be64(id, &ppid->id);
9144b889474SMichal Swiatkowski }
9154b889474SMichal Swiatkowski 
916e523af4eSShiraz Saleem int ice_devlink_register_params(struct ice_pf *pf)
917e523af4eSShiraz Saleem {
918e523af4eSShiraz Saleem 	struct devlink *devlink = priv_to_devlink(pf);
919e523af4eSShiraz Saleem 	union devlink_param_value value;
920e523af4eSShiraz Saleem 	int err;
921e523af4eSShiraz Saleem 
922e523af4eSShiraz Saleem 	err = devlink_params_register(devlink, ice_devlink_params,
923e523af4eSShiraz Saleem 				      ARRAY_SIZE(ice_devlink_params));
924e523af4eSShiraz Saleem 	if (err)
925e523af4eSShiraz Saleem 		return err;
926e523af4eSShiraz Saleem 
927e523af4eSShiraz Saleem 	value.vbool = false;
928e523af4eSShiraz Saleem 	devlink_param_driverinit_value_set(devlink,
929e523af4eSShiraz Saleem 					   DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP,
930e523af4eSShiraz Saleem 					   value);
931e523af4eSShiraz Saleem 
932e523af4eSShiraz Saleem 	value.vbool = test_bit(ICE_FLAG_RDMA_ENA, pf->flags) ? true : false;
933e523af4eSShiraz Saleem 	devlink_param_driverinit_value_set(devlink,
934e523af4eSShiraz Saleem 					   DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
935e523af4eSShiraz Saleem 					   value);
936e523af4eSShiraz Saleem 
937e523af4eSShiraz Saleem 	return 0;
938e523af4eSShiraz Saleem }
939e523af4eSShiraz Saleem 
940e523af4eSShiraz Saleem void ice_devlink_unregister_params(struct ice_pf *pf)
941e523af4eSShiraz Saleem {
942e523af4eSShiraz Saleem 	devlink_params_unregister(priv_to_devlink(pf), ice_devlink_params,
943e523af4eSShiraz Saleem 				  ARRAY_SIZE(ice_devlink_params));
944e523af4eSShiraz Saleem }
945e523af4eSShiraz Saleem 
9461adf7eadSJacob Keller /**
947*26d1c571SAnatolii Gerasymenko  * ice_devlink_set_port_split_options - Set port split options
948*26d1c571SAnatolii Gerasymenko  * @pf: the PF to set port split options
949*26d1c571SAnatolii Gerasymenko  * @attrs: devlink attributes
950*26d1c571SAnatolii Gerasymenko  *
951*26d1c571SAnatolii Gerasymenko  * Sets devlink port split options based on available FW port options
952*26d1c571SAnatolii Gerasymenko  */
953*26d1c571SAnatolii Gerasymenko static void
954*26d1c571SAnatolii Gerasymenko ice_devlink_set_port_split_options(struct ice_pf *pf,
955*26d1c571SAnatolii Gerasymenko 				   struct devlink_port_attrs *attrs)
956*26d1c571SAnatolii Gerasymenko {
957*26d1c571SAnatolii Gerasymenko 	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
958*26d1c571SAnatolii Gerasymenko 	u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX;
959*26d1c571SAnatolii Gerasymenko 	bool active_valid, pending_valid;
960*26d1c571SAnatolii Gerasymenko 	int status;
961*26d1c571SAnatolii Gerasymenko 
962*26d1c571SAnatolii Gerasymenko 	status = ice_aq_get_port_options(&pf->hw, options, &option_count,
963*26d1c571SAnatolii Gerasymenko 					 0, true, &active_idx, &active_valid,
964*26d1c571SAnatolii Gerasymenko 					 &pending_idx, &pending_valid);
965*26d1c571SAnatolii Gerasymenko 	if (status) {
966*26d1c571SAnatolii Gerasymenko 		dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n",
967*26d1c571SAnatolii Gerasymenko 			status);
968*26d1c571SAnatolii Gerasymenko 		return;
969*26d1c571SAnatolii Gerasymenko 	}
970*26d1c571SAnatolii Gerasymenko 
971*26d1c571SAnatolii Gerasymenko 	/* find the biggest available port split count */
972*26d1c571SAnatolii Gerasymenko 	for (i = 0; i < option_count; i++)
973*26d1c571SAnatolii Gerasymenko 		attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);
974*26d1c571SAnatolii Gerasymenko 
975*26d1c571SAnatolii Gerasymenko 	attrs->splittable = attrs->lanes ? 1 : 0;
976*26d1c571SAnatolii Gerasymenko 	ice_active_port_option = active_idx;
977*26d1c571SAnatolii Gerasymenko }
978*26d1c571SAnatolii Gerasymenko 
979*26d1c571SAnatolii Gerasymenko /**
9802ae0aa47SWojciech Drewek  * ice_devlink_create_pf_port - Create a devlink port for this PF
9812ae0aa47SWojciech Drewek  * @pf: the PF to create a devlink port for
9821adf7eadSJacob Keller  *
9832ae0aa47SWojciech Drewek  * Create and register a devlink_port for this PF.
9841adf7eadSJacob Keller  *
9851adf7eadSJacob Keller  * Return: zero on success or an error code on failure.
9861adf7eadSJacob Keller  */
9872ae0aa47SWojciech Drewek int ice_devlink_create_pf_port(struct ice_pf *pf)
9881adf7eadSJacob Keller {
98971ad8d55SDanielle Ratson 	struct devlink_port_attrs attrs = {};
9902ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
99148d40025SJacob Keller 	struct devlink *devlink;
9922ae0aa47SWojciech Drewek 	struct ice_vsi *vsi;
99348d40025SJacob Keller 	struct device *dev;
9941adf7eadSJacob Keller 	int err;
9951adf7eadSJacob Keller 
99648d40025SJacob Keller 	dev = ice_pf_to_dev(pf);
9972ae0aa47SWojciech Drewek 
9982ae0aa47SWojciech Drewek 	devlink_port = &pf->devlink_port;
9992ae0aa47SWojciech Drewek 
10002ae0aa47SWojciech Drewek 	vsi = ice_get_main_vsi(pf);
10012ae0aa47SWojciech Drewek 	if (!vsi)
10022ae0aa47SWojciech Drewek 		return -EIO;
10031adf7eadSJacob Keller 
100471ad8d55SDanielle Ratson 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
10052ae0aa47SWojciech Drewek 	attrs.phys.port_number = pf->hw.bus.func;
10064b889474SMichal Swiatkowski 
1007*26d1c571SAnatolii Gerasymenko 	/* As FW supports only port split options for whole device,
1008*26d1c571SAnatolii Gerasymenko 	 * set port split options only for first PF.
1009*26d1c571SAnatolii Gerasymenko 	 */
1010*26d1c571SAnatolii Gerasymenko 	if (pf->hw.pf_id == 0)
1011*26d1c571SAnatolii Gerasymenko 		ice_devlink_set_port_split_options(pf, &attrs);
1012*26d1c571SAnatolii Gerasymenko 
10134b889474SMichal Swiatkowski 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
10144b889474SMichal Swiatkowski 
10152ae0aa47SWojciech Drewek 	devlink_port_attrs_set(devlink_port, &attrs);
10162ae0aa47SWojciech Drewek 	devlink = priv_to_devlink(pf);
10172ae0aa47SWojciech Drewek 
10182ae0aa47SWojciech Drewek 	err = devlink_port_register(devlink, devlink_port, vsi->idx);
10191adf7eadSJacob Keller 	if (err) {
10202ae0aa47SWojciech Drewek 		dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
10212ae0aa47SWojciech Drewek 			pf->hw.pf_id, err);
10221adf7eadSJacob Keller 		return err;
10231adf7eadSJacob Keller 	}
10241adf7eadSJacob Keller 
10251adf7eadSJacob Keller 	return 0;
10261adf7eadSJacob Keller }
10271adf7eadSJacob Keller 
10281adf7eadSJacob Keller /**
10292ae0aa47SWojciech Drewek  * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
10302ae0aa47SWojciech Drewek  * @pf: the PF to cleanup
10311adf7eadSJacob Keller  *
10322ae0aa47SWojciech Drewek  * Unregisters the devlink_port structure associated with this PF.
10331adf7eadSJacob Keller  */
10342ae0aa47SWojciech Drewek void ice_devlink_destroy_pf_port(struct ice_pf *pf)
10351adf7eadSJacob Keller {
10362ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
103748d40025SJacob Keller 
10382ae0aa47SWojciech Drewek 	devlink_port = &pf->devlink_port;
103948d40025SJacob Keller 
10402ae0aa47SWojciech Drewek 	devlink_port_type_clear(devlink_port);
10412ae0aa47SWojciech Drewek 	devlink_port_unregister(devlink_port);
10422ae0aa47SWojciech Drewek }
10432ae0aa47SWojciech Drewek 
10442ae0aa47SWojciech Drewek /**
10452ae0aa47SWojciech Drewek  * ice_devlink_create_vf_port - Create a devlink port for this VF
10462ae0aa47SWojciech Drewek  * @vf: the VF to create a port for
10472ae0aa47SWojciech Drewek  *
10482ae0aa47SWojciech Drewek  * Create and register a devlink_port for this VF.
10492ae0aa47SWojciech Drewek  *
10502ae0aa47SWojciech Drewek  * Return: zero on success or an error code on failure.
10512ae0aa47SWojciech Drewek  */
10522ae0aa47SWojciech Drewek int ice_devlink_create_vf_port(struct ice_vf *vf)
10532ae0aa47SWojciech Drewek {
10542ae0aa47SWojciech Drewek 	struct devlink_port_attrs attrs = {};
10552ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
10562ae0aa47SWojciech Drewek 	struct devlink *devlink;
10572ae0aa47SWojciech Drewek 	struct ice_vsi *vsi;
10582ae0aa47SWojciech Drewek 	struct device *dev;
10592ae0aa47SWojciech Drewek 	struct ice_pf *pf;
10602ae0aa47SWojciech Drewek 	int err;
10612ae0aa47SWojciech Drewek 
10622ae0aa47SWojciech Drewek 	pf = vf->pf;
10632ae0aa47SWojciech Drewek 	dev = ice_pf_to_dev(pf);
10642ae0aa47SWojciech Drewek 	devlink_port = &vf->devlink_port;
10652ae0aa47SWojciech Drewek 
1066baeb705fSJacob Keller 	vsi = ice_get_vf_vsi(vf);
1067baeb705fSJacob Keller 	if (!vsi)
1068baeb705fSJacob Keller 		return -EINVAL;
1069baeb705fSJacob Keller 
10702ae0aa47SWojciech Drewek 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
10712ae0aa47SWojciech Drewek 	attrs.pci_vf.pf = pf->hw.bus.func;
10722ae0aa47SWojciech Drewek 	attrs.pci_vf.vf = vf->vf_id;
10732ae0aa47SWojciech Drewek 
10744b889474SMichal Swiatkowski 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
10754b889474SMichal Swiatkowski 
10762ae0aa47SWojciech Drewek 	devlink_port_attrs_set(devlink_port, &attrs);
10772ae0aa47SWojciech Drewek 	devlink = priv_to_devlink(pf);
10782ae0aa47SWojciech Drewek 
10792ae0aa47SWojciech Drewek 	err = devlink_port_register(devlink, devlink_port, vsi->idx);
10802ae0aa47SWojciech Drewek 	if (err) {
10812ae0aa47SWojciech Drewek 		dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
10822ae0aa47SWojciech Drewek 			vf->vf_id, err);
10832ae0aa47SWojciech Drewek 		return err;
10842ae0aa47SWojciech Drewek 	}
10852ae0aa47SWojciech Drewek 
10862ae0aa47SWojciech Drewek 	return 0;
10872ae0aa47SWojciech Drewek }
10882ae0aa47SWojciech Drewek 
10892ae0aa47SWojciech Drewek /**
10902ae0aa47SWojciech Drewek  * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
10912ae0aa47SWojciech Drewek  * @vf: the VF to cleanup
10922ae0aa47SWojciech Drewek  *
10932ae0aa47SWojciech Drewek  * Unregisters the devlink_port structure associated with this VF.
10942ae0aa47SWojciech Drewek  */
10952ae0aa47SWojciech Drewek void ice_devlink_destroy_vf_port(struct ice_vf *vf)
10962ae0aa47SWojciech Drewek {
10972ae0aa47SWojciech Drewek 	struct devlink_port *devlink_port;
10982ae0aa47SWojciech Drewek 
10992ae0aa47SWojciech Drewek 	devlink_port = &vf->devlink_port;
11002ae0aa47SWojciech Drewek 
11012ae0aa47SWojciech Drewek 	devlink_port_type_clear(devlink_port);
11022ae0aa47SWojciech Drewek 	devlink_port_unregister(devlink_port);
11031adf7eadSJacob Keller }
1104dce730f1SJacob Keller 
11057b6f9462SPaul M Stillwell Jr #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024)
11067b6f9462SPaul M Stillwell Jr 
1107dce730f1SJacob Keller /**
110878ad87daSJacob Keller  * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents
1109dce730f1SJacob Keller  * @devlink: the devlink instance
1110d4602a9fSAndrew Lunn  * @ops: the devlink region being snapshotted
1111dce730f1SJacob Keller  * @extack: extended ACK response structure
1112dce730f1SJacob Keller  * @data: on exit points to snapshot data buffer
1113dce730f1SJacob Keller  *
1114dce730f1SJacob Keller  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
111578ad87daSJacob Keller  * the nvm-flash devlink region. It captures a snapshot of the full NVM flash
111678ad87daSJacob Keller  * contents, including both banks of flash. This snapshot can later be viewed
111778ad87daSJacob Keller  * via the devlink-region interface.
111878ad87daSJacob Keller  *
111978ad87daSJacob Keller  * It captures the flash using the FLASH_ONLY bit set when reading via
112078ad87daSJacob Keller  * firmware, so it does not read the current Shadow RAM contents. For that,
112178ad87daSJacob Keller  * use the shadow-ram region.
1122dce730f1SJacob Keller  *
1123dce730f1SJacob Keller  * @returns zero on success, and updates the data pointer. Returns a non-zero
1124dce730f1SJacob Keller  * error code on failure.
1125dce730f1SJacob Keller  */
1126dce730f1SJacob Keller static int ice_devlink_nvm_snapshot(struct devlink *devlink,
1127d4602a9fSAndrew Lunn 				    const struct devlink_region_ops *ops,
1128dce730f1SJacob Keller 				    struct netlink_ext_ack *extack, u8 **data)
1129dce730f1SJacob Keller {
1130dce730f1SJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
1131dce730f1SJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
1132dce730f1SJacob Keller 	struct ice_hw *hw = &pf->hw;
11337b6f9462SPaul M Stillwell Jr 	u8 *nvm_data, *tmp, i;
11347b6f9462SPaul M Stillwell Jr 	u32 nvm_size, left;
11357b6f9462SPaul M Stillwell Jr 	s8 num_blks;
11365518ac2aSTony Nguyen 	int status;
1137dce730f1SJacob Keller 
11389af368faSJacob Keller 	nvm_size = hw->flash.flash_size;
1139dce730f1SJacob Keller 	nvm_data = vzalloc(nvm_size);
1140dce730f1SJacob Keller 	if (!nvm_data)
1141dce730f1SJacob Keller 		return -ENOMEM;
1142dce730f1SJacob Keller 
11437b6f9462SPaul M Stillwell Jr 
11447b6f9462SPaul M Stillwell Jr 	num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE);
11457b6f9462SPaul M Stillwell Jr 	tmp = nvm_data;
11467b6f9462SPaul M Stillwell Jr 	left = nvm_size;
11477b6f9462SPaul M Stillwell Jr 
11487b6f9462SPaul M Stillwell Jr 	/* Some systems take longer to read the NVM than others which causes the
11497b6f9462SPaul M Stillwell Jr 	 * FW to reclaim the NVM lock before the entire NVM has been read. Fix
11507b6f9462SPaul M Stillwell Jr 	 * this by breaking the reads of the NVM into smaller chunks that will
11517b6f9462SPaul M Stillwell Jr 	 * probably not take as long. This has some overhead since we are
11527b6f9462SPaul M Stillwell Jr 	 * increasing the number of AQ commands, but it should always work
11537b6f9462SPaul M Stillwell Jr 	 */
11547b6f9462SPaul M Stillwell Jr 	for (i = 0; i < num_blks; i++) {
11557b6f9462SPaul M Stillwell Jr 		u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left);
11567b6f9462SPaul M Stillwell Jr 
1157dce730f1SJacob Keller 		status = ice_acquire_nvm(hw, ICE_RES_READ);
1158dce730f1SJacob Keller 		if (status) {
1159dce730f1SJacob Keller 			dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
1160dce730f1SJacob Keller 				status, hw->adminq.sq_last_status);
1161dce730f1SJacob Keller 			NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
1162dce730f1SJacob Keller 			vfree(nvm_data);
11637b6f9462SPaul M Stillwell Jr 			return -EIO;
1164dce730f1SJacob Keller 		}
1165dce730f1SJacob Keller 
11667b6f9462SPaul M Stillwell Jr 		status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE,
11677b6f9462SPaul M Stillwell Jr 					   &read_sz, tmp, false);
1168dce730f1SJacob Keller 		if (status) {
1169dce730f1SJacob Keller 			dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
11707b6f9462SPaul M Stillwell Jr 				read_sz, status, hw->adminq.sq_last_status);
1171dce730f1SJacob Keller 			NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
1172dce730f1SJacob Keller 			ice_release_nvm(hw);
1173dce730f1SJacob Keller 			vfree(nvm_data);
11747b6f9462SPaul M Stillwell Jr 			return -EIO;
1175dce730f1SJacob Keller 		}
1176dce730f1SJacob Keller 		ice_release_nvm(hw);
1177dce730f1SJacob Keller 
11787b6f9462SPaul M Stillwell Jr 		tmp += read_sz;
11797b6f9462SPaul M Stillwell Jr 		left -= read_sz;
11807b6f9462SPaul M Stillwell Jr 	}
11817b6f9462SPaul M Stillwell Jr 
1182dce730f1SJacob Keller 	*data = nvm_data;
1183dce730f1SJacob Keller 
1184dce730f1SJacob Keller 	return 0;
1185dce730f1SJacob Keller }
1186dce730f1SJacob Keller 
11878d7aab35SJacob Keller /**
118878ad87daSJacob Keller  * ice_devlink_sram_snapshot - Capture a snapshot of the Shadow RAM contents
118978ad87daSJacob Keller  * @devlink: the devlink instance
119078ad87daSJacob Keller  * @ops: the devlink region being snapshotted
119178ad87daSJacob Keller  * @extack: extended ACK response structure
119278ad87daSJacob Keller  * @data: on exit points to snapshot data buffer
119378ad87daSJacob Keller  *
119478ad87daSJacob Keller  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
119578ad87daSJacob Keller  * the shadow-ram devlink region. It captures a snapshot of the shadow ram
119678ad87daSJacob Keller  * contents. This snapshot can later be viewed via the devlink-region
119778ad87daSJacob Keller  * interface.
119878ad87daSJacob Keller  *
119978ad87daSJacob Keller  * @returns zero on success, and updates the data pointer. Returns a non-zero
120078ad87daSJacob Keller  * error code on failure.
120178ad87daSJacob Keller  */
120278ad87daSJacob Keller static int
120378ad87daSJacob Keller ice_devlink_sram_snapshot(struct devlink *devlink,
120478ad87daSJacob Keller 			  const struct devlink_region_ops __always_unused *ops,
120578ad87daSJacob Keller 			  struct netlink_ext_ack *extack, u8 **data)
120678ad87daSJacob Keller {
120778ad87daSJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
120878ad87daSJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
120978ad87daSJacob Keller 	struct ice_hw *hw = &pf->hw;
121078ad87daSJacob Keller 	u8 *sram_data;
121178ad87daSJacob Keller 	u32 sram_size;
121278ad87daSJacob Keller 	int err;
121378ad87daSJacob Keller 
121478ad87daSJacob Keller 	sram_size = hw->flash.sr_words * 2u;
121578ad87daSJacob Keller 	sram_data = vzalloc(sram_size);
121678ad87daSJacob Keller 	if (!sram_data)
121778ad87daSJacob Keller 		return -ENOMEM;
121878ad87daSJacob Keller 
121978ad87daSJacob Keller 	err = ice_acquire_nvm(hw, ICE_RES_READ);
122078ad87daSJacob Keller 	if (err) {
122178ad87daSJacob Keller 		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
122278ad87daSJacob Keller 			err, hw->adminq.sq_last_status);
122378ad87daSJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
122478ad87daSJacob Keller 		vfree(sram_data);
122578ad87daSJacob Keller 		return err;
122678ad87daSJacob Keller 	}
122778ad87daSJacob Keller 
122878ad87daSJacob Keller 	/* Read from the Shadow RAM, rather than directly from NVM */
122978ad87daSJacob Keller 	err = ice_read_flat_nvm(hw, 0, &sram_size, sram_data, true);
123078ad87daSJacob Keller 	if (err) {
123178ad87daSJacob Keller 		dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
123278ad87daSJacob Keller 			sram_size, err, hw->adminq.sq_last_status);
123378ad87daSJacob Keller 		NL_SET_ERR_MSG_MOD(extack,
123478ad87daSJacob Keller 				   "Failed to read Shadow RAM contents");
123578ad87daSJacob Keller 		ice_release_nvm(hw);
123678ad87daSJacob Keller 		vfree(sram_data);
123778ad87daSJacob Keller 		return err;
123878ad87daSJacob Keller 	}
123978ad87daSJacob Keller 
124078ad87daSJacob Keller 	ice_release_nvm(hw);
124178ad87daSJacob Keller 
124278ad87daSJacob Keller 	*data = sram_data;
124378ad87daSJacob Keller 
124478ad87daSJacob Keller 	return 0;
124578ad87daSJacob Keller }
124678ad87daSJacob Keller 
124778ad87daSJacob Keller /**
12488d7aab35SJacob Keller  * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities
12498d7aab35SJacob Keller  * @devlink: the devlink instance
1250d4602a9fSAndrew Lunn  * @ops: the devlink region being snapshotted
12518d7aab35SJacob Keller  * @extack: extended ACK response structure
12528d7aab35SJacob Keller  * @data: on exit points to snapshot data buffer
12538d7aab35SJacob Keller  *
12548d7aab35SJacob Keller  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
12558d7aab35SJacob Keller  * the device-caps devlink region. It captures a snapshot of the device
12568d7aab35SJacob Keller  * capabilities reported by firmware.
12578d7aab35SJacob Keller  *
12588d7aab35SJacob Keller  * @returns zero on success, and updates the data pointer. Returns a non-zero
12598d7aab35SJacob Keller  * error code on failure.
12608d7aab35SJacob Keller  */
12618d7aab35SJacob Keller static int
12628d7aab35SJacob Keller ice_devlink_devcaps_snapshot(struct devlink *devlink,
1263d4602a9fSAndrew Lunn 			     const struct devlink_region_ops *ops,
12648d7aab35SJacob Keller 			     struct netlink_ext_ack *extack, u8 **data)
12658d7aab35SJacob Keller {
12668d7aab35SJacob Keller 	struct ice_pf *pf = devlink_priv(devlink);
12678d7aab35SJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
12688d7aab35SJacob Keller 	struct ice_hw *hw = &pf->hw;
12698d7aab35SJacob Keller 	void *devcaps;
12705518ac2aSTony Nguyen 	int status;
12718d7aab35SJacob Keller 
12728d7aab35SJacob Keller 	devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN);
12738d7aab35SJacob Keller 	if (!devcaps)
12748d7aab35SJacob Keller 		return -ENOMEM;
12758d7aab35SJacob Keller 
12768d7aab35SJacob Keller 	status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL,
12778d7aab35SJacob Keller 				  ice_aqc_opc_list_dev_caps, NULL);
12788d7aab35SJacob Keller 	if (status) {
12798d7aab35SJacob Keller 		dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n",
12808d7aab35SJacob Keller 			status, hw->adminq.sq_last_status);
12818d7aab35SJacob Keller 		NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities");
12828d7aab35SJacob Keller 		vfree(devcaps);
1283c1484691STony Nguyen 		return status;
12848d7aab35SJacob Keller 	}
12858d7aab35SJacob Keller 
12868d7aab35SJacob Keller 	*data = (u8 *)devcaps;
12878d7aab35SJacob Keller 
12888d7aab35SJacob Keller 	return 0;
12898d7aab35SJacob Keller }
12908d7aab35SJacob Keller 
1291dce730f1SJacob Keller static const struct devlink_region_ops ice_nvm_region_ops = {
1292dce730f1SJacob Keller 	.name = "nvm-flash",
1293dce730f1SJacob Keller 	.destructor = vfree,
1294dce730f1SJacob Keller 	.snapshot = ice_devlink_nvm_snapshot,
1295dce730f1SJacob Keller };
1296dce730f1SJacob Keller 
129778ad87daSJacob Keller static const struct devlink_region_ops ice_sram_region_ops = {
129878ad87daSJacob Keller 	.name = "shadow-ram",
129978ad87daSJacob Keller 	.destructor = vfree,
130078ad87daSJacob Keller 	.snapshot = ice_devlink_sram_snapshot,
130178ad87daSJacob Keller };
130278ad87daSJacob Keller 
13038d7aab35SJacob Keller static const struct devlink_region_ops ice_devcaps_region_ops = {
13048d7aab35SJacob Keller 	.name = "device-caps",
13058d7aab35SJacob Keller 	.destructor = vfree,
13068d7aab35SJacob Keller 	.snapshot = ice_devlink_devcaps_snapshot,
13078d7aab35SJacob Keller };
13088d7aab35SJacob Keller 
1309dce730f1SJacob Keller /**
1310dce730f1SJacob Keller  * ice_devlink_init_regions - Initialize devlink regions
1311dce730f1SJacob Keller  * @pf: the PF device structure
1312dce730f1SJacob Keller  *
1313dce730f1SJacob Keller  * Create devlink regions used to enable access to dump the contents of the
1314dce730f1SJacob Keller  * flash memory on the device.
1315dce730f1SJacob Keller  */
1316dce730f1SJacob Keller void ice_devlink_init_regions(struct ice_pf *pf)
1317dce730f1SJacob Keller {
1318dce730f1SJacob Keller 	struct devlink *devlink = priv_to_devlink(pf);
1319dce730f1SJacob Keller 	struct device *dev = ice_pf_to_dev(pf);
132078ad87daSJacob Keller 	u64 nvm_size, sram_size;
1321dce730f1SJacob Keller 
13229af368faSJacob Keller 	nvm_size = pf->hw.flash.flash_size;
1323dce730f1SJacob Keller 	pf->nvm_region = devlink_region_create(devlink, &ice_nvm_region_ops, 1,
1324dce730f1SJacob Keller 					       nvm_size);
1325dce730f1SJacob Keller 	if (IS_ERR(pf->nvm_region)) {
1326dce730f1SJacob Keller 		dev_err(dev, "failed to create NVM devlink region, err %ld\n",
1327dce730f1SJacob Keller 			PTR_ERR(pf->nvm_region));
1328dce730f1SJacob Keller 		pf->nvm_region = NULL;
1329dce730f1SJacob Keller 	}
13308d7aab35SJacob Keller 
133178ad87daSJacob Keller 	sram_size = pf->hw.flash.sr_words * 2u;
133278ad87daSJacob Keller 	pf->sram_region = devlink_region_create(devlink, &ice_sram_region_ops,
133378ad87daSJacob Keller 						1, sram_size);
133478ad87daSJacob Keller 	if (IS_ERR(pf->sram_region)) {
133578ad87daSJacob Keller 		dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n",
133678ad87daSJacob Keller 			PTR_ERR(pf->sram_region));
133778ad87daSJacob Keller 		pf->sram_region = NULL;
133878ad87daSJacob Keller 	}
133978ad87daSJacob Keller 
13408d7aab35SJacob Keller 	pf->devcaps_region = devlink_region_create(devlink,
13418d7aab35SJacob Keller 						   &ice_devcaps_region_ops, 10,
13428d7aab35SJacob Keller 						   ICE_AQ_MAX_BUF_LEN);
13438d7aab35SJacob Keller 	if (IS_ERR(pf->devcaps_region)) {
13448d7aab35SJacob Keller 		dev_err(dev, "failed to create device-caps devlink region, err %ld\n",
13458d7aab35SJacob Keller 			PTR_ERR(pf->devcaps_region));
13468d7aab35SJacob Keller 		pf->devcaps_region = NULL;
13478d7aab35SJacob Keller 	}
1348dce730f1SJacob Keller }
1349dce730f1SJacob Keller 
1350dce730f1SJacob Keller /**
1351dce730f1SJacob Keller  * ice_devlink_destroy_regions - Destroy devlink regions
1352dce730f1SJacob Keller  * @pf: the PF device structure
1353dce730f1SJacob Keller  *
1354dce730f1SJacob Keller  * Remove previously created regions for this PF.
1355dce730f1SJacob Keller  */
1356dce730f1SJacob Keller void ice_devlink_destroy_regions(struct ice_pf *pf)
1357dce730f1SJacob Keller {
1358dce730f1SJacob Keller 	if (pf->nvm_region)
1359dce730f1SJacob Keller 		devlink_region_destroy(pf->nvm_region);
136078ad87daSJacob Keller 
136178ad87daSJacob Keller 	if (pf->sram_region)
136278ad87daSJacob Keller 		devlink_region_destroy(pf->sram_region);
136378ad87daSJacob Keller 
13648d7aab35SJacob Keller 	if (pf->devcaps_region)
13658d7aab35SJacob Keller 		devlink_region_destroy(pf->devcaps_region);
1366dce730f1SJacob Keller }
1367