1*0545cc86SMichal Swiatkowski // SPDX-License-Identifier: GPL-2.0
2*0545cc86SMichal Swiatkowski /* Copyright (c) 2020, Intel Corporation. */
3*0545cc86SMichal Swiatkowski 
4*0545cc86SMichal Swiatkowski #include <linux/vmalloc.h>
5*0545cc86SMichal Swiatkowski 
6*0545cc86SMichal Swiatkowski #include "ice.h"
7*0545cc86SMichal Swiatkowski #include "ice_lib.h"
8*0545cc86SMichal Swiatkowski #include "devlink.h"
9*0545cc86SMichal Swiatkowski #include "ice_eswitch.h"
10*0545cc86SMichal Swiatkowski #include "ice_fw_update.h"
11*0545cc86SMichal Swiatkowski #include "ice_dcb_lib.h"
12*0545cc86SMichal Swiatkowski 
13*0545cc86SMichal Swiatkowski static int ice_active_port_option = -1;
14*0545cc86SMichal Swiatkowski 
15*0545cc86SMichal Swiatkowski /* context for devlink info version reporting */
16*0545cc86SMichal Swiatkowski struct ice_info_ctx {
17*0545cc86SMichal Swiatkowski 	char buf[128];
18*0545cc86SMichal Swiatkowski 	struct ice_orom_info pending_orom;
19*0545cc86SMichal Swiatkowski 	struct ice_nvm_info pending_nvm;
20*0545cc86SMichal Swiatkowski 	struct ice_netlist_info pending_netlist;
21*0545cc86SMichal Swiatkowski 	struct ice_hw_dev_caps dev_caps;
22*0545cc86SMichal Swiatkowski };
23*0545cc86SMichal Swiatkowski 
24*0545cc86SMichal Swiatkowski /* The following functions are used to format specific strings for various
25*0545cc86SMichal Swiatkowski  * devlink info versions. The ctx parameter is used to provide the storage
26*0545cc86SMichal Swiatkowski  * buffer, as well as any ancillary information calculated when the info
27*0545cc86SMichal Swiatkowski  * request was made.
28*0545cc86SMichal Swiatkowski  *
29*0545cc86SMichal Swiatkowski  * If a version does not exist, for example when attempting to get the
30*0545cc86SMichal Swiatkowski  * inactive version of flash when there is no pending update, the function
31*0545cc86SMichal Swiatkowski  * should leave the buffer in the ctx structure empty.
32*0545cc86SMichal Swiatkowski  */
33*0545cc86SMichal Swiatkowski 
34*0545cc86SMichal Swiatkowski static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx)
35*0545cc86SMichal Swiatkowski {
36*0545cc86SMichal Swiatkowski 	u8 dsn[8];
37*0545cc86SMichal Swiatkowski 
38*0545cc86SMichal Swiatkowski 	/* Copy the DSN into an array in Big Endian format */
39*0545cc86SMichal Swiatkowski 	put_unaligned_be64(pci_get_dsn(pf->pdev), dsn);
40*0545cc86SMichal Swiatkowski 
41*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
42*0545cc86SMichal Swiatkowski }
43*0545cc86SMichal Swiatkowski 
44*0545cc86SMichal Swiatkowski static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx)
45*0545cc86SMichal Swiatkowski {
46*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
47*0545cc86SMichal Swiatkowski 	int status;
48*0545cc86SMichal Swiatkowski 
49*0545cc86SMichal Swiatkowski 	status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf));
50*0545cc86SMichal Swiatkowski 	if (status)
51*0545cc86SMichal Swiatkowski 		/* We failed to locate the PBA, so just skip this entry */
52*0545cc86SMichal Swiatkowski 		dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n",
53*0545cc86SMichal Swiatkowski 			status);
54*0545cc86SMichal Swiatkowski }
55*0545cc86SMichal Swiatkowski 
56*0545cc86SMichal Swiatkowski static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx)
57*0545cc86SMichal Swiatkowski {
58*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
59*0545cc86SMichal Swiatkowski 
60*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
61*0545cc86SMichal Swiatkowski 		 hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch);
62*0545cc86SMichal Swiatkowski }
63*0545cc86SMichal Swiatkowski 
64*0545cc86SMichal Swiatkowski static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx)
65*0545cc86SMichal Swiatkowski {
66*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
67*0545cc86SMichal Swiatkowski 
68*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver,
69*0545cc86SMichal Swiatkowski 		 hw->api_min_ver, hw->api_patch);
70*0545cc86SMichal Swiatkowski }
71*0545cc86SMichal Swiatkowski 
72*0545cc86SMichal Swiatkowski static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
73*0545cc86SMichal Swiatkowski {
74*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
75*0545cc86SMichal Swiatkowski 
76*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
77*0545cc86SMichal Swiatkowski }
78*0545cc86SMichal Swiatkowski 
79*0545cc86SMichal Swiatkowski static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
80*0545cc86SMichal Swiatkowski {
81*0545cc86SMichal Swiatkowski 	struct ice_orom_info *orom = &pf->hw.flash.orom;
82*0545cc86SMichal Swiatkowski 
83*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
84*0545cc86SMichal Swiatkowski 		 orom->major, orom->build, orom->patch);
85*0545cc86SMichal Swiatkowski }
86*0545cc86SMichal Swiatkowski 
87*0545cc86SMichal Swiatkowski static void
88*0545cc86SMichal Swiatkowski ice_info_pending_orom_ver(struct ice_pf __always_unused *pf,
89*0545cc86SMichal Swiatkowski 			  struct ice_info_ctx *ctx)
90*0545cc86SMichal Swiatkowski {
91*0545cc86SMichal Swiatkowski 	struct ice_orom_info *orom = &ctx->pending_orom;
92*0545cc86SMichal Swiatkowski 
93*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_orom)
94*0545cc86SMichal Swiatkowski 		snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
95*0545cc86SMichal Swiatkowski 			 orom->major, orom->build, orom->patch);
96*0545cc86SMichal Swiatkowski }
97*0545cc86SMichal Swiatkowski 
98*0545cc86SMichal Swiatkowski static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
99*0545cc86SMichal Swiatkowski {
100*0545cc86SMichal Swiatkowski 	struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
101*0545cc86SMichal Swiatkowski 
102*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
103*0545cc86SMichal Swiatkowski }
104*0545cc86SMichal Swiatkowski 
105*0545cc86SMichal Swiatkowski static void
106*0545cc86SMichal Swiatkowski ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf,
107*0545cc86SMichal Swiatkowski 			 struct ice_info_ctx *ctx)
108*0545cc86SMichal Swiatkowski {
109*0545cc86SMichal Swiatkowski 	struct ice_nvm_info *nvm = &ctx->pending_nvm;
110*0545cc86SMichal Swiatkowski 
111*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
112*0545cc86SMichal Swiatkowski 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x",
113*0545cc86SMichal Swiatkowski 			 nvm->major, nvm->minor);
114*0545cc86SMichal Swiatkowski }
115*0545cc86SMichal Swiatkowski 
116*0545cc86SMichal Swiatkowski static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
117*0545cc86SMichal Swiatkowski {
118*0545cc86SMichal Swiatkowski 	struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
119*0545cc86SMichal Swiatkowski 
120*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
121*0545cc86SMichal Swiatkowski }
122*0545cc86SMichal Swiatkowski 
123*0545cc86SMichal Swiatkowski static void
124*0545cc86SMichal Swiatkowski ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
125*0545cc86SMichal Swiatkowski {
126*0545cc86SMichal Swiatkowski 	struct ice_nvm_info *nvm = &ctx->pending_nvm;
127*0545cc86SMichal Swiatkowski 
128*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
129*0545cc86SMichal Swiatkowski 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
130*0545cc86SMichal Swiatkowski }
131*0545cc86SMichal Swiatkowski 
132*0545cc86SMichal Swiatkowski static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx)
133*0545cc86SMichal Swiatkowski {
134*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
135*0545cc86SMichal Swiatkowski 
136*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name);
137*0545cc86SMichal Swiatkowski }
138*0545cc86SMichal Swiatkowski 
139*0545cc86SMichal Swiatkowski static void
140*0545cc86SMichal Swiatkowski ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx)
141*0545cc86SMichal Swiatkowski {
142*0545cc86SMichal Swiatkowski 	struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver;
143*0545cc86SMichal Swiatkowski 
144*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u",
145*0545cc86SMichal Swiatkowski 		 pkg->major, pkg->minor, pkg->update, pkg->draft);
146*0545cc86SMichal Swiatkowski }
147*0545cc86SMichal Swiatkowski 
148*0545cc86SMichal Swiatkowski static void
149*0545cc86SMichal Swiatkowski ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx)
150*0545cc86SMichal Swiatkowski {
151*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id);
152*0545cc86SMichal Swiatkowski }
153*0545cc86SMichal Swiatkowski 
154*0545cc86SMichal Swiatkowski static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
155*0545cc86SMichal Swiatkowski {
156*0545cc86SMichal Swiatkowski 	struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
157*0545cc86SMichal Swiatkowski 
158*0545cc86SMichal Swiatkowski 	/* The netlist version fields are BCD formatted */
159*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
160*0545cc86SMichal Swiatkowski 		 netlist->major, netlist->minor,
161*0545cc86SMichal Swiatkowski 		 netlist->type >> 16, netlist->type & 0xFFFF,
162*0545cc86SMichal Swiatkowski 		 netlist->rev, netlist->cust_ver);
163*0545cc86SMichal Swiatkowski }
164*0545cc86SMichal Swiatkowski 
165*0545cc86SMichal Swiatkowski static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
166*0545cc86SMichal Swiatkowski {
167*0545cc86SMichal Swiatkowski 	struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
168*0545cc86SMichal Swiatkowski 
169*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
170*0545cc86SMichal Swiatkowski }
171*0545cc86SMichal Swiatkowski 
172*0545cc86SMichal Swiatkowski static void
173*0545cc86SMichal Swiatkowski ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf,
174*0545cc86SMichal Swiatkowski 			     struct ice_info_ctx *ctx)
175*0545cc86SMichal Swiatkowski {
176*0545cc86SMichal Swiatkowski 	struct ice_netlist_info *netlist = &ctx->pending_netlist;
177*0545cc86SMichal Swiatkowski 
178*0545cc86SMichal Swiatkowski 	/* The netlist version fields are BCD formatted */
179*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
180*0545cc86SMichal Swiatkowski 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
181*0545cc86SMichal Swiatkowski 			 netlist->major, netlist->minor,
182*0545cc86SMichal Swiatkowski 			 netlist->type >> 16, netlist->type & 0xFFFF,
183*0545cc86SMichal Swiatkowski 			 netlist->rev, netlist->cust_ver);
184*0545cc86SMichal Swiatkowski }
185*0545cc86SMichal Swiatkowski 
186*0545cc86SMichal Swiatkowski static void
187*0545cc86SMichal Swiatkowski ice_info_pending_netlist_build(struct ice_pf __always_unused *pf,
188*0545cc86SMichal Swiatkowski 			       struct ice_info_ctx *ctx)
189*0545cc86SMichal Swiatkowski {
190*0545cc86SMichal Swiatkowski 	struct ice_netlist_info *netlist = &ctx->pending_netlist;
191*0545cc86SMichal Swiatkowski 
192*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
193*0545cc86SMichal Swiatkowski 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
194*0545cc86SMichal Swiatkowski }
195*0545cc86SMichal Swiatkowski 
196*0545cc86SMichal Swiatkowski static void ice_info_cgu_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
197*0545cc86SMichal Swiatkowski {
198*0545cc86SMichal Swiatkowski 	u32 id, cfg_ver, fw_ver;
199*0545cc86SMichal Swiatkowski 
200*0545cc86SMichal Swiatkowski 	if (!ice_is_feature_supported(pf, ICE_F_CGU))
201*0545cc86SMichal Swiatkowski 		return;
202*0545cc86SMichal Swiatkowski 	if (ice_aq_get_cgu_info(&pf->hw, &id, &cfg_ver, &fw_ver))
203*0545cc86SMichal Swiatkowski 		return;
204*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", id, cfg_ver, fw_ver);
205*0545cc86SMichal Swiatkowski }
206*0545cc86SMichal Swiatkowski 
207*0545cc86SMichal Swiatkowski static void ice_info_cgu_id(struct ice_pf *pf, struct ice_info_ctx *ctx)
208*0545cc86SMichal Swiatkowski {
209*0545cc86SMichal Swiatkowski 	if (!ice_is_feature_supported(pf, ICE_F_CGU))
210*0545cc86SMichal Swiatkowski 		return;
211*0545cc86SMichal Swiatkowski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u", pf->hw.cgu_part_number);
212*0545cc86SMichal Swiatkowski }
213*0545cc86SMichal Swiatkowski 
214*0545cc86SMichal Swiatkowski #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL }
215*0545cc86SMichal Swiatkowski #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL }
216*0545cc86SMichal Swiatkowski #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback }
217*0545cc86SMichal Swiatkowski 
218*0545cc86SMichal Swiatkowski /* The combined() macro inserts both the running entry as well as a stored
219*0545cc86SMichal Swiatkowski  * entry. The running entry will always report the version from the active
220*0545cc86SMichal Swiatkowski  * handler. The stored entry will first try the pending handler, and fallback
221*0545cc86SMichal Swiatkowski  * to the active handler if the pending function does not report a version.
222*0545cc86SMichal Swiatkowski  * The pending handler should check the status of a pending update for the
223*0545cc86SMichal Swiatkowski  * relevant flash component. It should only fill in the buffer in the case
224*0545cc86SMichal Swiatkowski  * where a valid pending version is available. This ensures that the related
225*0545cc86SMichal Swiatkowski  * stored and running versions remain in sync, and that stored versions are
226*0545cc86SMichal Swiatkowski  * correctly reported as expected.
227*0545cc86SMichal Swiatkowski  */
228*0545cc86SMichal Swiatkowski #define combined(key, active, pending) \
229*0545cc86SMichal Swiatkowski 	running(key, active), \
230*0545cc86SMichal Swiatkowski 	stored(key, pending, active)
231*0545cc86SMichal Swiatkowski 
232*0545cc86SMichal Swiatkowski enum ice_version_type {
233*0545cc86SMichal Swiatkowski 	ICE_VERSION_FIXED,
234*0545cc86SMichal Swiatkowski 	ICE_VERSION_RUNNING,
235*0545cc86SMichal Swiatkowski 	ICE_VERSION_STORED,
236*0545cc86SMichal Swiatkowski };
237*0545cc86SMichal Swiatkowski 
238*0545cc86SMichal Swiatkowski static const struct ice_devlink_version {
239*0545cc86SMichal Swiatkowski 	enum ice_version_type type;
240*0545cc86SMichal Swiatkowski 	const char *key;
241*0545cc86SMichal Swiatkowski 	void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx);
242*0545cc86SMichal Swiatkowski 	void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx);
243*0545cc86SMichal Swiatkowski } ice_devlink_versions[] = {
244*0545cc86SMichal Swiatkowski 	fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba),
245*0545cc86SMichal Swiatkowski 	running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt),
246*0545cc86SMichal Swiatkowski 	running("fw.mgmt.api", ice_info_fw_api),
247*0545cc86SMichal Swiatkowski 	running("fw.mgmt.build", ice_info_fw_build),
248*0545cc86SMichal Swiatkowski 	combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver),
249*0545cc86SMichal Swiatkowski 	combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver),
250*0545cc86SMichal Swiatkowski 	combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack),
251*0545cc86SMichal Swiatkowski 	running("fw.app.name", ice_info_ddp_pkg_name),
252*0545cc86SMichal Swiatkowski 	running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version),
253*0545cc86SMichal Swiatkowski 	running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id),
254*0545cc86SMichal Swiatkowski 	combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver),
255*0545cc86SMichal Swiatkowski 	combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build),
256*0545cc86SMichal Swiatkowski 	fixed("cgu.id", ice_info_cgu_id),
257*0545cc86SMichal Swiatkowski 	running("fw.cgu", ice_info_cgu_fw_build),
258*0545cc86SMichal Swiatkowski };
259*0545cc86SMichal Swiatkowski 
260*0545cc86SMichal Swiatkowski /**
261*0545cc86SMichal Swiatkowski  * ice_devlink_info_get - .info_get devlink handler
262*0545cc86SMichal Swiatkowski  * @devlink: devlink instance structure
263*0545cc86SMichal Swiatkowski  * @req: the devlink info request
264*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
265*0545cc86SMichal Swiatkowski  *
266*0545cc86SMichal Swiatkowski  * Callback for the devlink .info_get operation. Reports information about the
267*0545cc86SMichal Swiatkowski  * device.
268*0545cc86SMichal Swiatkowski  *
269*0545cc86SMichal Swiatkowski  * Return: zero on success or an error code on failure.
270*0545cc86SMichal Swiatkowski  */
271*0545cc86SMichal Swiatkowski static int ice_devlink_info_get(struct devlink *devlink,
272*0545cc86SMichal Swiatkowski 				struct devlink_info_req *req,
273*0545cc86SMichal Swiatkowski 				struct netlink_ext_ack *extack)
274*0545cc86SMichal Swiatkowski {
275*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
276*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
277*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
278*0545cc86SMichal Swiatkowski 	struct ice_info_ctx *ctx;
279*0545cc86SMichal Swiatkowski 	size_t i;
280*0545cc86SMichal Swiatkowski 	int err;
281*0545cc86SMichal Swiatkowski 
282*0545cc86SMichal Swiatkowski 	err = ice_wait_for_reset(pf, 10 * HZ);
283*0545cc86SMichal Swiatkowski 	if (err) {
284*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting");
285*0545cc86SMichal Swiatkowski 		return err;
286*0545cc86SMichal Swiatkowski 	}
287*0545cc86SMichal Swiatkowski 
288*0545cc86SMichal Swiatkowski 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
289*0545cc86SMichal Swiatkowski 	if (!ctx)
290*0545cc86SMichal Swiatkowski 		return -ENOMEM;
291*0545cc86SMichal Swiatkowski 
292*0545cc86SMichal Swiatkowski 	/* discover capabilities first */
293*0545cc86SMichal Swiatkowski 	err = ice_discover_dev_caps(hw, &ctx->dev_caps);
294*0545cc86SMichal Swiatkowski 	if (err) {
295*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n",
296*0545cc86SMichal Swiatkowski 			err, ice_aq_str(hw->adminq.sq_last_status));
297*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities");
298*0545cc86SMichal Swiatkowski 		goto out_free_ctx;
299*0545cc86SMichal Swiatkowski 	}
300*0545cc86SMichal Swiatkowski 
301*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_orom) {
302*0545cc86SMichal Swiatkowski 		err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom);
303*0545cc86SMichal Swiatkowski 		if (err) {
304*0545cc86SMichal Swiatkowski 			dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n",
305*0545cc86SMichal Swiatkowski 				err, ice_aq_str(hw->adminq.sq_last_status));
306*0545cc86SMichal Swiatkowski 
307*0545cc86SMichal Swiatkowski 			/* disable display of pending Option ROM */
308*0545cc86SMichal Swiatkowski 			ctx->dev_caps.common_cap.nvm_update_pending_orom = false;
309*0545cc86SMichal Swiatkowski 		}
310*0545cc86SMichal Swiatkowski 	}
311*0545cc86SMichal Swiatkowski 
312*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) {
313*0545cc86SMichal Swiatkowski 		err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
314*0545cc86SMichal Swiatkowski 		if (err) {
315*0545cc86SMichal Swiatkowski 			dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n",
316*0545cc86SMichal Swiatkowski 				err, ice_aq_str(hw->adminq.sq_last_status));
317*0545cc86SMichal Swiatkowski 
318*0545cc86SMichal Swiatkowski 			/* disable display of pending Option ROM */
319*0545cc86SMichal Swiatkowski 			ctx->dev_caps.common_cap.nvm_update_pending_nvm = false;
320*0545cc86SMichal Swiatkowski 		}
321*0545cc86SMichal Swiatkowski 	}
322*0545cc86SMichal Swiatkowski 
323*0545cc86SMichal Swiatkowski 	if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) {
324*0545cc86SMichal Swiatkowski 		err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
325*0545cc86SMichal Swiatkowski 		if (err) {
326*0545cc86SMichal Swiatkowski 			dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n",
327*0545cc86SMichal Swiatkowski 				err, ice_aq_str(hw->adminq.sq_last_status));
328*0545cc86SMichal Swiatkowski 
329*0545cc86SMichal Swiatkowski 			/* disable display of pending Option ROM */
330*0545cc86SMichal Swiatkowski 			ctx->dev_caps.common_cap.nvm_update_pending_netlist = false;
331*0545cc86SMichal Swiatkowski 		}
332*0545cc86SMichal Swiatkowski 	}
333*0545cc86SMichal Swiatkowski 
334*0545cc86SMichal Swiatkowski 	ice_info_get_dsn(pf, ctx);
335*0545cc86SMichal Swiatkowski 
336*0545cc86SMichal Swiatkowski 	err = devlink_info_serial_number_put(req, ctx->buf);
337*0545cc86SMichal Swiatkowski 	if (err) {
338*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number");
339*0545cc86SMichal Swiatkowski 		goto out_free_ctx;
340*0545cc86SMichal Swiatkowski 	}
341*0545cc86SMichal Swiatkowski 
342*0545cc86SMichal Swiatkowski 	for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) {
343*0545cc86SMichal Swiatkowski 		enum ice_version_type type = ice_devlink_versions[i].type;
344*0545cc86SMichal Swiatkowski 		const char *key = ice_devlink_versions[i].key;
345*0545cc86SMichal Swiatkowski 
346*0545cc86SMichal Swiatkowski 		memset(ctx->buf, 0, sizeof(ctx->buf));
347*0545cc86SMichal Swiatkowski 
348*0545cc86SMichal Swiatkowski 		ice_devlink_versions[i].getter(pf, ctx);
349*0545cc86SMichal Swiatkowski 
350*0545cc86SMichal Swiatkowski 		/* If the default getter doesn't report a version, use the
351*0545cc86SMichal Swiatkowski 		 * fallback function. This is primarily useful in the case of
352*0545cc86SMichal Swiatkowski 		 * "stored" versions that want to report the same value as the
353*0545cc86SMichal Swiatkowski 		 * running version in the normal case of no pending update.
354*0545cc86SMichal Swiatkowski 		 */
355*0545cc86SMichal Swiatkowski 		if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback)
356*0545cc86SMichal Swiatkowski 			ice_devlink_versions[i].fallback(pf, ctx);
357*0545cc86SMichal Swiatkowski 
358*0545cc86SMichal Swiatkowski 		/* Do not report missing versions */
359*0545cc86SMichal Swiatkowski 		if (ctx->buf[0] == '\0')
360*0545cc86SMichal Swiatkowski 			continue;
361*0545cc86SMichal Swiatkowski 
362*0545cc86SMichal Swiatkowski 		switch (type) {
363*0545cc86SMichal Swiatkowski 		case ICE_VERSION_FIXED:
364*0545cc86SMichal Swiatkowski 			err = devlink_info_version_fixed_put(req, key, ctx->buf);
365*0545cc86SMichal Swiatkowski 			if (err) {
366*0545cc86SMichal Swiatkowski 				NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version");
367*0545cc86SMichal Swiatkowski 				goto out_free_ctx;
368*0545cc86SMichal Swiatkowski 			}
369*0545cc86SMichal Swiatkowski 			break;
370*0545cc86SMichal Swiatkowski 		case ICE_VERSION_RUNNING:
371*0545cc86SMichal Swiatkowski 			err = devlink_info_version_running_put(req, key, ctx->buf);
372*0545cc86SMichal Swiatkowski 			if (err) {
373*0545cc86SMichal Swiatkowski 				NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
374*0545cc86SMichal Swiatkowski 				goto out_free_ctx;
375*0545cc86SMichal Swiatkowski 			}
376*0545cc86SMichal Swiatkowski 			break;
377*0545cc86SMichal Swiatkowski 		case ICE_VERSION_STORED:
378*0545cc86SMichal Swiatkowski 			err = devlink_info_version_stored_put(req, key, ctx->buf);
379*0545cc86SMichal Swiatkowski 			if (err) {
380*0545cc86SMichal Swiatkowski 				NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
381*0545cc86SMichal Swiatkowski 				goto out_free_ctx;
382*0545cc86SMichal Swiatkowski 			}
383*0545cc86SMichal Swiatkowski 			break;
384*0545cc86SMichal Swiatkowski 		}
385*0545cc86SMichal Swiatkowski 	}
386*0545cc86SMichal Swiatkowski 
387*0545cc86SMichal Swiatkowski out_free_ctx:
388*0545cc86SMichal Swiatkowski 	kfree(ctx);
389*0545cc86SMichal Swiatkowski 	return err;
390*0545cc86SMichal Swiatkowski }
391*0545cc86SMichal Swiatkowski 
392*0545cc86SMichal Swiatkowski /**
393*0545cc86SMichal Swiatkowski  * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware
394*0545cc86SMichal Swiatkowski  * @pf: pointer to the pf instance
395*0545cc86SMichal Swiatkowski  * @extack: netlink extended ACK structure
396*0545cc86SMichal Swiatkowski  *
397*0545cc86SMichal Swiatkowski  * Allow user to activate new Embedded Management Processor firmware by
398*0545cc86SMichal Swiatkowski  * issuing device specific EMP reset. Called in response to
399*0545cc86SMichal Swiatkowski  * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE.
400*0545cc86SMichal Swiatkowski  *
401*0545cc86SMichal Swiatkowski  * Note that teardown and rebuild of the driver state happens automatically as
402*0545cc86SMichal Swiatkowski  * part of an interrupt and watchdog task. This is because all physical
403*0545cc86SMichal Swiatkowski  * functions on the device must be able to reset when an EMP reset occurs from
404*0545cc86SMichal Swiatkowski  * any source.
405*0545cc86SMichal Swiatkowski  */
406*0545cc86SMichal Swiatkowski static int
407*0545cc86SMichal Swiatkowski ice_devlink_reload_empr_start(struct ice_pf *pf,
408*0545cc86SMichal Swiatkowski 			      struct netlink_ext_ack *extack)
409*0545cc86SMichal Swiatkowski {
410*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
411*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
412*0545cc86SMichal Swiatkowski 	u8 pending;
413*0545cc86SMichal Swiatkowski 	int err;
414*0545cc86SMichal Swiatkowski 
415*0545cc86SMichal Swiatkowski 	err = ice_get_pending_updates(pf, &pending, extack);
416*0545cc86SMichal Swiatkowski 	if (err)
417*0545cc86SMichal Swiatkowski 		return err;
418*0545cc86SMichal Swiatkowski 
419*0545cc86SMichal Swiatkowski 	/* pending is a bitmask of which flash banks have a pending update,
420*0545cc86SMichal Swiatkowski 	 * including the main NVM bank, the Option ROM bank, and the netlist
421*0545cc86SMichal Swiatkowski 	 * bank. If any of these bits are set, then there is a pending update
422*0545cc86SMichal Swiatkowski 	 * waiting to be activated.
423*0545cc86SMichal Swiatkowski 	 */
424*0545cc86SMichal Swiatkowski 	if (!pending) {
425*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "No pending firmware update");
426*0545cc86SMichal Swiatkowski 		return -ECANCELED;
427*0545cc86SMichal Swiatkowski 	}
428*0545cc86SMichal Swiatkowski 
429*0545cc86SMichal Swiatkowski 	if (pf->fw_emp_reset_disabled) {
430*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed");
431*0545cc86SMichal Swiatkowski 		return -ECANCELED;
432*0545cc86SMichal Swiatkowski 	}
433*0545cc86SMichal Swiatkowski 
434*0545cc86SMichal Swiatkowski 	dev_dbg(dev, "Issuing device EMP reset to activate firmware\n");
435*0545cc86SMichal Swiatkowski 
436*0545cc86SMichal Swiatkowski 	err = ice_aq_nvm_update_empr(hw);
437*0545cc86SMichal Swiatkowski 	if (err) {
438*0545cc86SMichal Swiatkowski 		dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n",
439*0545cc86SMichal Swiatkowski 			err, ice_aq_str(hw->adminq.sq_last_status));
440*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware");
441*0545cc86SMichal Swiatkowski 		return err;
442*0545cc86SMichal Swiatkowski 	}
443*0545cc86SMichal Swiatkowski 
444*0545cc86SMichal Swiatkowski 	return 0;
445*0545cc86SMichal Swiatkowski }
446*0545cc86SMichal Swiatkowski 
447*0545cc86SMichal Swiatkowski /**
448*0545cc86SMichal Swiatkowski  * ice_devlink_reinit_down - unload given PF
449*0545cc86SMichal Swiatkowski  * @pf: pointer to the PF struct
450*0545cc86SMichal Swiatkowski  */
451*0545cc86SMichal Swiatkowski static void ice_devlink_reinit_down(struct ice_pf *pf)
452*0545cc86SMichal Swiatkowski {
453*0545cc86SMichal Swiatkowski 	/* No need to take devl_lock, it's already taken by devlink API */
454*0545cc86SMichal Swiatkowski 	ice_unload(pf);
455*0545cc86SMichal Swiatkowski 	rtnl_lock();
456*0545cc86SMichal Swiatkowski 	ice_vsi_decfg(ice_get_main_vsi(pf));
457*0545cc86SMichal Swiatkowski 	rtnl_unlock();
458*0545cc86SMichal Swiatkowski 	ice_deinit_dev(pf);
459*0545cc86SMichal Swiatkowski }
460*0545cc86SMichal Swiatkowski 
461*0545cc86SMichal Swiatkowski /**
462*0545cc86SMichal Swiatkowski  * ice_devlink_reload_down - prepare for reload
463*0545cc86SMichal Swiatkowski  * @devlink: pointer to the devlink instance to reload
464*0545cc86SMichal Swiatkowski  * @netns_change: if true, the network namespace is changing
465*0545cc86SMichal Swiatkowski  * @action: the action to perform
466*0545cc86SMichal Swiatkowski  * @limit: limits on what reload should do, such as not resetting
467*0545cc86SMichal Swiatkowski  * @extack: netlink extended ACK structure
468*0545cc86SMichal Swiatkowski  */
469*0545cc86SMichal Swiatkowski static int
470*0545cc86SMichal Swiatkowski ice_devlink_reload_down(struct devlink *devlink, bool netns_change,
471*0545cc86SMichal Swiatkowski 			enum devlink_reload_action action,
472*0545cc86SMichal Swiatkowski 			enum devlink_reload_limit limit,
473*0545cc86SMichal Swiatkowski 			struct netlink_ext_ack *extack)
474*0545cc86SMichal Swiatkowski {
475*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
476*0545cc86SMichal Swiatkowski 
477*0545cc86SMichal Swiatkowski 	switch (action) {
478*0545cc86SMichal Swiatkowski 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
479*0545cc86SMichal Swiatkowski 		if (ice_is_eswitch_mode_switchdev(pf)) {
480*0545cc86SMichal Swiatkowski 			NL_SET_ERR_MSG_MOD(extack,
481*0545cc86SMichal Swiatkowski 					   "Go to legacy mode before doing reinit");
482*0545cc86SMichal Swiatkowski 			return -EOPNOTSUPP;
483*0545cc86SMichal Swiatkowski 		}
484*0545cc86SMichal Swiatkowski 		if (ice_is_adq_active(pf)) {
485*0545cc86SMichal Swiatkowski 			NL_SET_ERR_MSG_MOD(extack,
486*0545cc86SMichal Swiatkowski 					   "Turn off ADQ before doing reinit");
487*0545cc86SMichal Swiatkowski 			return -EOPNOTSUPP;
488*0545cc86SMichal Swiatkowski 		}
489*0545cc86SMichal Swiatkowski 		if (ice_has_vfs(pf)) {
490*0545cc86SMichal Swiatkowski 			NL_SET_ERR_MSG_MOD(extack,
491*0545cc86SMichal Swiatkowski 					   "Remove all VFs before doing reinit");
492*0545cc86SMichal Swiatkowski 			return -EOPNOTSUPP;
493*0545cc86SMichal Swiatkowski 		}
494*0545cc86SMichal Swiatkowski 		ice_devlink_reinit_down(pf);
495*0545cc86SMichal Swiatkowski 		return 0;
496*0545cc86SMichal Swiatkowski 	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
497*0545cc86SMichal Swiatkowski 		return ice_devlink_reload_empr_start(pf, extack);
498*0545cc86SMichal Swiatkowski 	default:
499*0545cc86SMichal Swiatkowski 		WARN_ON(1);
500*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
501*0545cc86SMichal Swiatkowski 	}
502*0545cc86SMichal Swiatkowski }
503*0545cc86SMichal Swiatkowski 
504*0545cc86SMichal Swiatkowski /**
505*0545cc86SMichal Swiatkowski  * ice_devlink_reload_empr_finish - Wait for EMP reset to finish
506*0545cc86SMichal Swiatkowski  * @pf: pointer to the pf instance
507*0545cc86SMichal Swiatkowski  * @extack: netlink extended ACK structure
508*0545cc86SMichal Swiatkowski  *
509*0545cc86SMichal Swiatkowski  * Wait for driver to finish rebuilding after EMP reset is completed. This
510*0545cc86SMichal Swiatkowski  * includes time to wait for both the actual device reset as well as the time
511*0545cc86SMichal Swiatkowski  * for the driver's rebuild to complete.
512*0545cc86SMichal Swiatkowski  */
513*0545cc86SMichal Swiatkowski static int
514*0545cc86SMichal Swiatkowski ice_devlink_reload_empr_finish(struct ice_pf *pf,
515*0545cc86SMichal Swiatkowski 			       struct netlink_ext_ack *extack)
516*0545cc86SMichal Swiatkowski {
517*0545cc86SMichal Swiatkowski 	int err;
518*0545cc86SMichal Swiatkowski 
519*0545cc86SMichal Swiatkowski 	err = ice_wait_for_reset(pf, 60 * HZ);
520*0545cc86SMichal Swiatkowski 	if (err) {
521*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute");
522*0545cc86SMichal Swiatkowski 		return err;
523*0545cc86SMichal Swiatkowski 	}
524*0545cc86SMichal Swiatkowski 
525*0545cc86SMichal Swiatkowski 	return 0;
526*0545cc86SMichal Swiatkowski }
527*0545cc86SMichal Swiatkowski 
528*0545cc86SMichal Swiatkowski /**
529*0545cc86SMichal Swiatkowski  * ice_devlink_port_opt_speed_str - convert speed to a string
530*0545cc86SMichal Swiatkowski  * @speed: speed value
531*0545cc86SMichal Swiatkowski  */
532*0545cc86SMichal Swiatkowski static const char *ice_devlink_port_opt_speed_str(u8 speed)
533*0545cc86SMichal Swiatkowski {
534*0545cc86SMichal Swiatkowski 	switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) {
535*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_100M:
536*0545cc86SMichal Swiatkowski 		return "0.1";
537*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_1G:
538*0545cc86SMichal Swiatkowski 		return "1";
539*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_2500M:
540*0545cc86SMichal Swiatkowski 		return "2.5";
541*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_5G:
542*0545cc86SMichal Swiatkowski 		return "5";
543*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_10G:
544*0545cc86SMichal Swiatkowski 		return "10";
545*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_25G:
546*0545cc86SMichal Swiatkowski 		return "25";
547*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_50G:
548*0545cc86SMichal Swiatkowski 		return "50";
549*0545cc86SMichal Swiatkowski 	case ICE_AQC_PORT_OPT_MAX_LANE_100G:
550*0545cc86SMichal Swiatkowski 		return "100";
551*0545cc86SMichal Swiatkowski 	}
552*0545cc86SMichal Swiatkowski 
553*0545cc86SMichal Swiatkowski 	return "-";
554*0545cc86SMichal Swiatkowski }
555*0545cc86SMichal Swiatkowski 
556*0545cc86SMichal Swiatkowski #define ICE_PORT_OPT_DESC_LEN	50
557*0545cc86SMichal Swiatkowski /**
558*0545cc86SMichal Swiatkowski  * ice_devlink_port_options_print - Print available port split options
559*0545cc86SMichal Swiatkowski  * @pf: the PF to print split port options
560*0545cc86SMichal Swiatkowski  *
561*0545cc86SMichal Swiatkowski  * Prints a table with available port split options and max port speeds
562*0545cc86SMichal Swiatkowski  */
563*0545cc86SMichal Swiatkowski static void ice_devlink_port_options_print(struct ice_pf *pf)
564*0545cc86SMichal Swiatkowski {
565*0545cc86SMichal Swiatkowski 	u8 i, j, options_count, cnt, speed, pending_idx, active_idx;
566*0545cc86SMichal Swiatkowski 	struct ice_aqc_get_port_options_elem *options, *opt;
567*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
568*0545cc86SMichal Swiatkowski 	bool active_valid, pending_valid;
569*0545cc86SMichal Swiatkowski 	char desc[ICE_PORT_OPT_DESC_LEN];
570*0545cc86SMichal Swiatkowski 	const char *str;
571*0545cc86SMichal Swiatkowski 	int status;
572*0545cc86SMichal Swiatkowski 
573*0545cc86SMichal Swiatkowski 	options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV,
574*0545cc86SMichal Swiatkowski 			  sizeof(*options), GFP_KERNEL);
575*0545cc86SMichal Swiatkowski 	if (!options)
576*0545cc86SMichal Swiatkowski 		return;
577*0545cc86SMichal Swiatkowski 
578*0545cc86SMichal Swiatkowski 	for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) {
579*0545cc86SMichal Swiatkowski 		opt = options + i * ICE_AQC_PORT_OPT_MAX;
580*0545cc86SMichal Swiatkowski 		options_count = ICE_AQC_PORT_OPT_MAX;
581*0545cc86SMichal Swiatkowski 		active_valid = 0;
582*0545cc86SMichal Swiatkowski 
583*0545cc86SMichal Swiatkowski 		status = ice_aq_get_port_options(&pf->hw, opt, &options_count,
584*0545cc86SMichal Swiatkowski 						 i, true, &active_idx,
585*0545cc86SMichal Swiatkowski 						 &active_valid, &pending_idx,
586*0545cc86SMichal Swiatkowski 						 &pending_valid);
587*0545cc86SMichal Swiatkowski 		if (status) {
588*0545cc86SMichal Swiatkowski 			dev_dbg(dev, "Couldn't read port option for port %d, err %d\n",
589*0545cc86SMichal Swiatkowski 				i, status);
590*0545cc86SMichal Swiatkowski 			goto err;
591*0545cc86SMichal Swiatkowski 		}
592*0545cc86SMichal Swiatkowski 	}
593*0545cc86SMichal Swiatkowski 
594*0545cc86SMichal Swiatkowski 	dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n");
595*0545cc86SMichal Swiatkowski 	dev_dbg(dev, "Status  Split      Quad 0          Quad 1\n");
596*0545cc86SMichal Swiatkowski 	dev_dbg(dev, "        count  L0  L1  L2  L3  L4  L5  L6  L7\n");
597*0545cc86SMichal Swiatkowski 
598*0545cc86SMichal Swiatkowski 	for (i = 0; i < options_count; i++) {
599*0545cc86SMichal Swiatkowski 		cnt = 0;
600*0545cc86SMichal Swiatkowski 
601*0545cc86SMichal Swiatkowski 		if (i == ice_active_port_option)
602*0545cc86SMichal Swiatkowski 			str = "Active";
603*0545cc86SMichal Swiatkowski 		else if ((i == pending_idx) && pending_valid)
604*0545cc86SMichal Swiatkowski 			str = "Pending";
605*0545cc86SMichal Swiatkowski 		else
606*0545cc86SMichal Swiatkowski 			str = "";
607*0545cc86SMichal Swiatkowski 
608*0545cc86SMichal Swiatkowski 		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
609*0545cc86SMichal Swiatkowski 				"%-8s", str);
610*0545cc86SMichal Swiatkowski 
611*0545cc86SMichal Swiatkowski 		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
612*0545cc86SMichal Swiatkowski 				"%-6u", options[i].pmd);
613*0545cc86SMichal Swiatkowski 
614*0545cc86SMichal Swiatkowski 		for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) {
615*0545cc86SMichal Swiatkowski 			speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed;
616*0545cc86SMichal Swiatkowski 			str = ice_devlink_port_opt_speed_str(speed);
617*0545cc86SMichal Swiatkowski 			cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
618*0545cc86SMichal Swiatkowski 					"%3s ", str);
619*0545cc86SMichal Swiatkowski 		}
620*0545cc86SMichal Swiatkowski 
621*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "%s\n", desc);
622*0545cc86SMichal Swiatkowski 	}
623*0545cc86SMichal Swiatkowski 
624*0545cc86SMichal Swiatkowski err:
625*0545cc86SMichal Swiatkowski 	kfree(options);
626*0545cc86SMichal Swiatkowski }
627*0545cc86SMichal Swiatkowski 
628*0545cc86SMichal Swiatkowski /**
629*0545cc86SMichal Swiatkowski  * ice_devlink_aq_set_port_option - Send set port option admin queue command
630*0545cc86SMichal Swiatkowski  * @pf: the PF to print split port options
631*0545cc86SMichal Swiatkowski  * @option_idx: selected port option
632*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
633*0545cc86SMichal Swiatkowski  *
634*0545cc86SMichal Swiatkowski  * Sends set port option admin queue command with selected port option and
635*0545cc86SMichal Swiatkowski  * calls NVM write activate.
636*0545cc86SMichal Swiatkowski  */
637*0545cc86SMichal Swiatkowski static int
638*0545cc86SMichal Swiatkowski ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx,
639*0545cc86SMichal Swiatkowski 			       struct netlink_ext_ack *extack)
640*0545cc86SMichal Swiatkowski {
641*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
642*0545cc86SMichal Swiatkowski 	int status;
643*0545cc86SMichal Swiatkowski 
644*0545cc86SMichal Swiatkowski 	status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx);
645*0545cc86SMichal Swiatkowski 	if (status) {
646*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n",
647*0545cc86SMichal Swiatkowski 			status, pf->hw.adminq.sq_last_status);
648*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Port split request failed");
649*0545cc86SMichal Swiatkowski 		return -EIO;
650*0545cc86SMichal Swiatkowski 	}
651*0545cc86SMichal Swiatkowski 
652*0545cc86SMichal Swiatkowski 	status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE);
653*0545cc86SMichal Swiatkowski 	if (status) {
654*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
655*0545cc86SMichal Swiatkowski 			status, pf->hw.adminq.sq_last_status);
656*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
657*0545cc86SMichal Swiatkowski 		return -EIO;
658*0545cc86SMichal Swiatkowski 	}
659*0545cc86SMichal Swiatkowski 
660*0545cc86SMichal Swiatkowski 	status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL);
661*0545cc86SMichal Swiatkowski 	if (status) {
662*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n",
663*0545cc86SMichal Swiatkowski 			status, pf->hw.adminq.sq_last_status);
664*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data");
665*0545cc86SMichal Swiatkowski 		ice_release_nvm(&pf->hw);
666*0545cc86SMichal Swiatkowski 		return -EIO;
667*0545cc86SMichal Swiatkowski 	}
668*0545cc86SMichal Swiatkowski 
669*0545cc86SMichal Swiatkowski 	ice_release_nvm(&pf->hw);
670*0545cc86SMichal Swiatkowski 
671*0545cc86SMichal Swiatkowski 	NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split");
672*0545cc86SMichal Swiatkowski 	return 0;
673*0545cc86SMichal Swiatkowski }
674*0545cc86SMichal Swiatkowski 
675*0545cc86SMichal Swiatkowski /**
676*0545cc86SMichal Swiatkowski  * ice_devlink_port_split - .port_split devlink handler
677*0545cc86SMichal Swiatkowski  * @devlink: devlink instance structure
678*0545cc86SMichal Swiatkowski  * @port: devlink port structure
679*0545cc86SMichal Swiatkowski  * @count: number of ports to split to
680*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
681*0545cc86SMichal Swiatkowski  *
682*0545cc86SMichal Swiatkowski  * Callback for the devlink .port_split operation.
683*0545cc86SMichal Swiatkowski  *
684*0545cc86SMichal Swiatkowski  * Unfortunately, the devlink expression of available options is limited
685*0545cc86SMichal Swiatkowski  * to just a number, so search for an FW port option which supports
686*0545cc86SMichal Swiatkowski  * the specified number. As there could be multiple FW port options with
687*0545cc86SMichal Swiatkowski  * the same port split count, allow switching between them. When the same
688*0545cc86SMichal Swiatkowski  * port split count request is issued again, switch to the next FW port
689*0545cc86SMichal Swiatkowski  * option with the same port split count.
690*0545cc86SMichal Swiatkowski  *
691*0545cc86SMichal Swiatkowski  * Return: zero on success or an error code on failure.
692*0545cc86SMichal Swiatkowski  */
693*0545cc86SMichal Swiatkowski static int
694*0545cc86SMichal Swiatkowski ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port,
695*0545cc86SMichal Swiatkowski 		       unsigned int count, struct netlink_ext_ack *extack)
696*0545cc86SMichal Swiatkowski {
697*0545cc86SMichal Swiatkowski 	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
698*0545cc86SMichal Swiatkowski 	u8 i, j, active_idx, pending_idx, new_option;
699*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
700*0545cc86SMichal Swiatkowski 	u8 option_count = ICE_AQC_PORT_OPT_MAX;
701*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
702*0545cc86SMichal Swiatkowski 	bool active_valid, pending_valid;
703*0545cc86SMichal Swiatkowski 	int status;
704*0545cc86SMichal Swiatkowski 
705*0545cc86SMichal Swiatkowski 	status = ice_aq_get_port_options(&pf->hw, options, &option_count,
706*0545cc86SMichal Swiatkowski 					 0, true, &active_idx, &active_valid,
707*0545cc86SMichal Swiatkowski 					 &pending_idx, &pending_valid);
708*0545cc86SMichal Swiatkowski 	if (status) {
709*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "Couldn't read port split options, err = %d\n",
710*0545cc86SMichal Swiatkowski 			status);
711*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options");
712*0545cc86SMichal Swiatkowski 		return -EIO;
713*0545cc86SMichal Swiatkowski 	}
714*0545cc86SMichal Swiatkowski 
715*0545cc86SMichal Swiatkowski 	new_option = ICE_AQC_PORT_OPT_MAX;
716*0545cc86SMichal Swiatkowski 	active_idx = pending_valid ? pending_idx : active_idx;
717*0545cc86SMichal Swiatkowski 	for (i = 1; i <= option_count; i++) {
718*0545cc86SMichal Swiatkowski 		/* In order to allow switching between FW port options with
719*0545cc86SMichal Swiatkowski 		 * the same port split count, search for a new option starting
720*0545cc86SMichal Swiatkowski 		 * from the active/pending option (with array wrap around).
721*0545cc86SMichal Swiatkowski 		 */
722*0545cc86SMichal Swiatkowski 		j = (active_idx + i) % option_count;
723*0545cc86SMichal Swiatkowski 
724*0545cc86SMichal Swiatkowski 		if (count == options[j].pmd) {
725*0545cc86SMichal Swiatkowski 			new_option = j;
726*0545cc86SMichal Swiatkowski 			break;
727*0545cc86SMichal Swiatkowski 		}
728*0545cc86SMichal Swiatkowski 	}
729*0545cc86SMichal Swiatkowski 
730*0545cc86SMichal Swiatkowski 	if (new_option == active_idx) {
731*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n",
732*0545cc86SMichal Swiatkowski 			count);
733*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set");
734*0545cc86SMichal Swiatkowski 		ice_devlink_port_options_print(pf);
735*0545cc86SMichal Swiatkowski 		return -EINVAL;
736*0545cc86SMichal Swiatkowski 	}
737*0545cc86SMichal Swiatkowski 
738*0545cc86SMichal Swiatkowski 	if (new_option == ICE_AQC_PORT_OPT_MAX) {
739*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "request to split: count: %u not found\n", count);
740*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config");
741*0545cc86SMichal Swiatkowski 		ice_devlink_port_options_print(pf);
742*0545cc86SMichal Swiatkowski 		return -EINVAL;
743*0545cc86SMichal Swiatkowski 	}
744*0545cc86SMichal Swiatkowski 
745*0545cc86SMichal Swiatkowski 	status = ice_devlink_aq_set_port_option(pf, new_option, extack);
746*0545cc86SMichal Swiatkowski 	if (status)
747*0545cc86SMichal Swiatkowski 		return status;
748*0545cc86SMichal Swiatkowski 
749*0545cc86SMichal Swiatkowski 	ice_devlink_port_options_print(pf);
750*0545cc86SMichal Swiatkowski 
751*0545cc86SMichal Swiatkowski 	return 0;
752*0545cc86SMichal Swiatkowski }
753*0545cc86SMichal Swiatkowski 
754*0545cc86SMichal Swiatkowski /**
755*0545cc86SMichal Swiatkowski  * ice_devlink_port_unsplit - .port_unsplit devlink handler
756*0545cc86SMichal Swiatkowski  * @devlink: devlink instance structure
757*0545cc86SMichal Swiatkowski  * @port: devlink port structure
758*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
759*0545cc86SMichal Swiatkowski  *
760*0545cc86SMichal Swiatkowski  * Callback for the devlink .port_unsplit operation.
761*0545cc86SMichal Swiatkowski  * Calls ice_devlink_port_split with split count set to 1.
762*0545cc86SMichal Swiatkowski  * There could be no FW option available with split count 1.
763*0545cc86SMichal Swiatkowski  *
764*0545cc86SMichal Swiatkowski  * Return: zero on success or an error code on failure.
765*0545cc86SMichal Swiatkowski  */
766*0545cc86SMichal Swiatkowski static int
767*0545cc86SMichal Swiatkowski ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,
768*0545cc86SMichal Swiatkowski 			 struct netlink_ext_ack *extack)
769*0545cc86SMichal Swiatkowski {
770*0545cc86SMichal Swiatkowski 	return ice_devlink_port_split(devlink, port, 1, extack);
771*0545cc86SMichal Swiatkowski }
772*0545cc86SMichal Swiatkowski 
773*0545cc86SMichal Swiatkowski /**
774*0545cc86SMichal Swiatkowski  * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree
775*0545cc86SMichal Swiatkowski  * @pf: pf struct
776*0545cc86SMichal Swiatkowski  *
777*0545cc86SMichal Swiatkowski  * This function tears down tree exported during VF's creation.
778*0545cc86SMichal Swiatkowski  */
779*0545cc86SMichal Swiatkowski void ice_tear_down_devlink_rate_tree(struct ice_pf *pf)
780*0545cc86SMichal Swiatkowski {
781*0545cc86SMichal Swiatkowski 	struct devlink *devlink;
782*0545cc86SMichal Swiatkowski 	struct ice_vf *vf;
783*0545cc86SMichal Swiatkowski 	unsigned int bkt;
784*0545cc86SMichal Swiatkowski 
785*0545cc86SMichal Swiatkowski 	devlink = priv_to_devlink(pf);
786*0545cc86SMichal Swiatkowski 
787*0545cc86SMichal Swiatkowski 	devl_lock(devlink);
788*0545cc86SMichal Swiatkowski 	mutex_lock(&pf->vfs.table_lock);
789*0545cc86SMichal Swiatkowski 	ice_for_each_vf(pf, bkt, vf) {
790*0545cc86SMichal Swiatkowski 		if (vf->devlink_port.devlink_rate)
791*0545cc86SMichal Swiatkowski 			devl_rate_leaf_destroy(&vf->devlink_port);
792*0545cc86SMichal Swiatkowski 	}
793*0545cc86SMichal Swiatkowski 	mutex_unlock(&pf->vfs.table_lock);
794*0545cc86SMichal Swiatkowski 
795*0545cc86SMichal Swiatkowski 	devl_rate_nodes_destroy(devlink);
796*0545cc86SMichal Swiatkowski 	devl_unlock(devlink);
797*0545cc86SMichal Swiatkowski }
798*0545cc86SMichal Swiatkowski 
799*0545cc86SMichal Swiatkowski /**
800*0545cc86SMichal Swiatkowski  * ice_enable_custom_tx - try to enable custom Tx feature
801*0545cc86SMichal Swiatkowski  * @pf: pf struct
802*0545cc86SMichal Swiatkowski  *
803*0545cc86SMichal Swiatkowski  * This function tries to enable custom Tx feature,
804*0545cc86SMichal Swiatkowski  * it's not possible to enable it, if DCB or ADQ is active.
805*0545cc86SMichal Swiatkowski  */
806*0545cc86SMichal Swiatkowski static bool ice_enable_custom_tx(struct ice_pf *pf)
807*0545cc86SMichal Swiatkowski {
808*0545cc86SMichal Swiatkowski 	struct ice_port_info *pi = ice_get_main_vsi(pf)->port_info;
809*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
810*0545cc86SMichal Swiatkowski 
811*0545cc86SMichal Swiatkowski 	if (pi->is_custom_tx_enabled)
812*0545cc86SMichal Swiatkowski 		/* already enabled, return true */
813*0545cc86SMichal Swiatkowski 		return true;
814*0545cc86SMichal Swiatkowski 
815*0545cc86SMichal Swiatkowski 	if (ice_is_adq_active(pf)) {
816*0545cc86SMichal Swiatkowski 		dev_err(dev, "ADQ active, can't modify Tx scheduler tree\n");
817*0545cc86SMichal Swiatkowski 		return false;
818*0545cc86SMichal Swiatkowski 	}
819*0545cc86SMichal Swiatkowski 
820*0545cc86SMichal Swiatkowski 	if (ice_is_dcb_active(pf)) {
821*0545cc86SMichal Swiatkowski 		dev_err(dev, "DCB active, can't modify Tx scheduler tree\n");
822*0545cc86SMichal Swiatkowski 		return false;
823*0545cc86SMichal Swiatkowski 	}
824*0545cc86SMichal Swiatkowski 
825*0545cc86SMichal Swiatkowski 	pi->is_custom_tx_enabled = true;
826*0545cc86SMichal Swiatkowski 
827*0545cc86SMichal Swiatkowski 	return true;
828*0545cc86SMichal Swiatkowski }
829*0545cc86SMichal Swiatkowski 
830*0545cc86SMichal Swiatkowski /**
831*0545cc86SMichal Swiatkowski  * ice_traverse_tx_tree - traverse Tx scheduler tree
832*0545cc86SMichal Swiatkowski  * @devlink: devlink struct
833*0545cc86SMichal Swiatkowski  * @node: current node, used for recursion
834*0545cc86SMichal Swiatkowski  * @tc_node: tc_node struct, that is treated as a root
835*0545cc86SMichal Swiatkowski  * @pf: pf struct
836*0545cc86SMichal Swiatkowski  *
837*0545cc86SMichal Swiatkowski  * This function traverses Tx scheduler tree and exports
838*0545cc86SMichal Swiatkowski  * entire structure to the devlink-rate.
839*0545cc86SMichal Swiatkowski  */
840*0545cc86SMichal Swiatkowski static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node *node,
841*0545cc86SMichal Swiatkowski 				 struct ice_sched_node *tc_node, struct ice_pf *pf)
842*0545cc86SMichal Swiatkowski {
843*0545cc86SMichal Swiatkowski 	struct devlink_rate *rate_node = NULL;
844*0545cc86SMichal Swiatkowski 	struct ice_vf *vf;
845*0545cc86SMichal Swiatkowski 	int i;
846*0545cc86SMichal Swiatkowski 
847*0545cc86SMichal Swiatkowski 	if (node->rate_node)
848*0545cc86SMichal Swiatkowski 		/* already added, skip to the next */
849*0545cc86SMichal Swiatkowski 		goto traverse_children;
850*0545cc86SMichal Swiatkowski 
851*0545cc86SMichal Swiatkowski 	if (node->parent == tc_node) {
852*0545cc86SMichal Swiatkowski 		/* create root node */
853*0545cc86SMichal Swiatkowski 		rate_node = devl_rate_node_create(devlink, node, node->name, NULL);
854*0545cc86SMichal Swiatkowski 	} else if (node->vsi_handle &&
855*0545cc86SMichal Swiatkowski 		   pf->vsi[node->vsi_handle]->vf) {
856*0545cc86SMichal Swiatkowski 		vf = pf->vsi[node->vsi_handle]->vf;
857*0545cc86SMichal Swiatkowski 		if (!vf->devlink_port.devlink_rate)
858*0545cc86SMichal Swiatkowski 			/* leaf nodes doesn't have children
859*0545cc86SMichal Swiatkowski 			 * so we don't set rate_node
860*0545cc86SMichal Swiatkowski 			 */
861*0545cc86SMichal Swiatkowski 			devl_rate_leaf_create(&vf->devlink_port, node,
862*0545cc86SMichal Swiatkowski 					      node->parent->rate_node);
863*0545cc86SMichal Swiatkowski 	} else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF &&
864*0545cc86SMichal Swiatkowski 		   node->parent->rate_node) {
865*0545cc86SMichal Swiatkowski 		rate_node = devl_rate_node_create(devlink, node, node->name,
866*0545cc86SMichal Swiatkowski 						  node->parent->rate_node);
867*0545cc86SMichal Swiatkowski 	}
868*0545cc86SMichal Swiatkowski 
869*0545cc86SMichal Swiatkowski 	if (rate_node && !IS_ERR(rate_node))
870*0545cc86SMichal Swiatkowski 		node->rate_node = rate_node;
871*0545cc86SMichal Swiatkowski 
872*0545cc86SMichal Swiatkowski traverse_children:
873*0545cc86SMichal Swiatkowski 	for (i = 0; i < node->num_children; i++)
874*0545cc86SMichal Swiatkowski 		ice_traverse_tx_tree(devlink, node->children[i], tc_node, pf);
875*0545cc86SMichal Swiatkowski }
876*0545cc86SMichal Swiatkowski 
877*0545cc86SMichal Swiatkowski /**
878*0545cc86SMichal Swiatkowski  * ice_devlink_rate_init_tx_topology - export Tx scheduler tree to devlink rate
879*0545cc86SMichal Swiatkowski  * @devlink: devlink struct
880*0545cc86SMichal Swiatkowski  * @vsi: main vsi struct
881*0545cc86SMichal Swiatkowski  *
882*0545cc86SMichal Swiatkowski  * This function finds a root node, then calls ice_traverse_tx tree, which
883*0545cc86SMichal Swiatkowski  * traverses the tree and exports it's contents to devlink rate.
884*0545cc86SMichal Swiatkowski  */
885*0545cc86SMichal Swiatkowski int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *vsi)
886*0545cc86SMichal Swiatkowski {
887*0545cc86SMichal Swiatkowski 	struct ice_port_info *pi = vsi->port_info;
888*0545cc86SMichal Swiatkowski 	struct ice_sched_node *tc_node;
889*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = vsi->back;
890*0545cc86SMichal Swiatkowski 	int i;
891*0545cc86SMichal Swiatkowski 
892*0545cc86SMichal Swiatkowski 	tc_node = pi->root->children[0];
893*0545cc86SMichal Swiatkowski 	mutex_lock(&pi->sched_lock);
894*0545cc86SMichal Swiatkowski 	devl_lock(devlink);
895*0545cc86SMichal Swiatkowski 	for (i = 0; i < tc_node->num_children; i++)
896*0545cc86SMichal Swiatkowski 		ice_traverse_tx_tree(devlink, tc_node->children[i], tc_node, pf);
897*0545cc86SMichal Swiatkowski 	devl_unlock(devlink);
898*0545cc86SMichal Swiatkowski 	mutex_unlock(&pi->sched_lock);
899*0545cc86SMichal Swiatkowski 
900*0545cc86SMichal Swiatkowski 	return 0;
901*0545cc86SMichal Swiatkowski }
902*0545cc86SMichal Swiatkowski 
903*0545cc86SMichal Swiatkowski static void ice_clear_rate_nodes(struct ice_sched_node *node)
904*0545cc86SMichal Swiatkowski {
905*0545cc86SMichal Swiatkowski 	node->rate_node = NULL;
906*0545cc86SMichal Swiatkowski 
907*0545cc86SMichal Swiatkowski 	for (int i = 0; i < node->num_children; i++)
908*0545cc86SMichal Swiatkowski 		ice_clear_rate_nodes(node->children[i]);
909*0545cc86SMichal Swiatkowski }
910*0545cc86SMichal Swiatkowski 
911*0545cc86SMichal Swiatkowski /**
912*0545cc86SMichal Swiatkowski  * ice_devlink_rate_clear_tx_topology - clear node->rate_node
913*0545cc86SMichal Swiatkowski  * @vsi: main vsi struct
914*0545cc86SMichal Swiatkowski  *
915*0545cc86SMichal Swiatkowski  * Clear rate_node to cleanup creation of Tx topology.
916*0545cc86SMichal Swiatkowski  *
917*0545cc86SMichal Swiatkowski  */
918*0545cc86SMichal Swiatkowski void ice_devlink_rate_clear_tx_topology(struct ice_vsi *vsi)
919*0545cc86SMichal Swiatkowski {
920*0545cc86SMichal Swiatkowski 	struct ice_port_info *pi = vsi->port_info;
921*0545cc86SMichal Swiatkowski 
922*0545cc86SMichal Swiatkowski 	mutex_lock(&pi->sched_lock);
923*0545cc86SMichal Swiatkowski 	ice_clear_rate_nodes(pi->root->children[0]);
924*0545cc86SMichal Swiatkowski 	mutex_unlock(&pi->sched_lock);
925*0545cc86SMichal Swiatkowski }
926*0545cc86SMichal Swiatkowski 
927*0545cc86SMichal Swiatkowski /**
928*0545cc86SMichal Swiatkowski  * ice_set_object_tx_share - sets node scheduling parameter
929*0545cc86SMichal Swiatkowski  * @pi: devlink struct instance
930*0545cc86SMichal Swiatkowski  * @node: node struct instance
931*0545cc86SMichal Swiatkowski  * @bw: bandwidth in bytes per second
932*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
933*0545cc86SMichal Swiatkowski  *
934*0545cc86SMichal Swiatkowski  * This function sets ICE_MIN_BW scheduling BW limit.
935*0545cc86SMichal Swiatkowski  */
936*0545cc86SMichal Swiatkowski static int ice_set_object_tx_share(struct ice_port_info *pi, struct ice_sched_node *node,
937*0545cc86SMichal Swiatkowski 				   u64 bw, struct netlink_ext_ack *extack)
938*0545cc86SMichal Swiatkowski {
939*0545cc86SMichal Swiatkowski 	int status;
940*0545cc86SMichal Swiatkowski 
941*0545cc86SMichal Swiatkowski 	mutex_lock(&pi->sched_lock);
942*0545cc86SMichal Swiatkowski 	/* converts bytes per second to kilo bits per second */
943*0545cc86SMichal Swiatkowski 	node->tx_share = div_u64(bw, 125);
944*0545cc86SMichal Swiatkowski 	status = ice_sched_set_node_bw_lmt(pi, node, ICE_MIN_BW, node->tx_share);
945*0545cc86SMichal Swiatkowski 	mutex_unlock(&pi->sched_lock);
946*0545cc86SMichal Swiatkowski 
947*0545cc86SMichal Swiatkowski 	if (status)
948*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_share");
949*0545cc86SMichal Swiatkowski 
950*0545cc86SMichal Swiatkowski 	return status;
951*0545cc86SMichal Swiatkowski }
952*0545cc86SMichal Swiatkowski 
953*0545cc86SMichal Swiatkowski /**
954*0545cc86SMichal Swiatkowski  * ice_set_object_tx_max - sets node scheduling parameter
955*0545cc86SMichal Swiatkowski  * @pi: devlink struct instance
956*0545cc86SMichal Swiatkowski  * @node: node struct instance
957*0545cc86SMichal Swiatkowski  * @bw: bandwidth in bytes per second
958*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
959*0545cc86SMichal Swiatkowski  *
960*0545cc86SMichal Swiatkowski  * This function sets ICE_MAX_BW scheduling BW limit.
961*0545cc86SMichal Swiatkowski  */
962*0545cc86SMichal Swiatkowski static int ice_set_object_tx_max(struct ice_port_info *pi, struct ice_sched_node *node,
963*0545cc86SMichal Swiatkowski 				 u64 bw, struct netlink_ext_ack *extack)
964*0545cc86SMichal Swiatkowski {
965*0545cc86SMichal Swiatkowski 	int status;
966*0545cc86SMichal Swiatkowski 
967*0545cc86SMichal Swiatkowski 	mutex_lock(&pi->sched_lock);
968*0545cc86SMichal Swiatkowski 	/* converts bytes per second value to kilo bits per second */
969*0545cc86SMichal Swiatkowski 	node->tx_max = div_u64(bw, 125);
970*0545cc86SMichal Swiatkowski 	status = ice_sched_set_node_bw_lmt(pi, node, ICE_MAX_BW, node->tx_max);
971*0545cc86SMichal Swiatkowski 	mutex_unlock(&pi->sched_lock);
972*0545cc86SMichal Swiatkowski 
973*0545cc86SMichal Swiatkowski 	if (status)
974*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_max");
975*0545cc86SMichal Swiatkowski 
976*0545cc86SMichal Swiatkowski 	return status;
977*0545cc86SMichal Swiatkowski }
978*0545cc86SMichal Swiatkowski 
979*0545cc86SMichal Swiatkowski /**
980*0545cc86SMichal Swiatkowski  * ice_set_object_tx_priority - sets node scheduling parameter
981*0545cc86SMichal Swiatkowski  * @pi: devlink struct instance
982*0545cc86SMichal Swiatkowski  * @node: node struct instance
983*0545cc86SMichal Swiatkowski  * @priority: value representing priority for strict priority arbitration
984*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
985*0545cc86SMichal Swiatkowski  *
986*0545cc86SMichal Swiatkowski  * This function sets priority of node among siblings.
987*0545cc86SMichal Swiatkowski  */
988*0545cc86SMichal Swiatkowski static int ice_set_object_tx_priority(struct ice_port_info *pi, struct ice_sched_node *node,
989*0545cc86SMichal Swiatkowski 				      u32 priority, struct netlink_ext_ack *extack)
990*0545cc86SMichal Swiatkowski {
991*0545cc86SMichal Swiatkowski 	int status;
992*0545cc86SMichal Swiatkowski 
993*0545cc86SMichal Swiatkowski 	if (priority >= 8) {
994*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Priority should be less than 8");
995*0545cc86SMichal Swiatkowski 		return -EINVAL;
996*0545cc86SMichal Swiatkowski 	}
997*0545cc86SMichal Swiatkowski 
998*0545cc86SMichal Swiatkowski 	mutex_lock(&pi->sched_lock);
999*0545cc86SMichal Swiatkowski 	node->tx_priority = priority;
1000*0545cc86SMichal Swiatkowski 	status = ice_sched_set_node_priority(pi, node, node->tx_priority);
1001*0545cc86SMichal Swiatkowski 	mutex_unlock(&pi->sched_lock);
1002*0545cc86SMichal Swiatkowski 
1003*0545cc86SMichal Swiatkowski 	if (status)
1004*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_priority");
1005*0545cc86SMichal Swiatkowski 
1006*0545cc86SMichal Swiatkowski 	return status;
1007*0545cc86SMichal Swiatkowski }
1008*0545cc86SMichal Swiatkowski 
1009*0545cc86SMichal Swiatkowski /**
1010*0545cc86SMichal Swiatkowski  * ice_set_object_tx_weight - sets node scheduling parameter
1011*0545cc86SMichal Swiatkowski  * @pi: devlink struct instance
1012*0545cc86SMichal Swiatkowski  * @node: node struct instance
1013*0545cc86SMichal Swiatkowski  * @weight: value represeting relative weight for WFQ arbitration
1014*0545cc86SMichal Swiatkowski  * @extack: extended netdev ack structure
1015*0545cc86SMichal Swiatkowski  *
1016*0545cc86SMichal Swiatkowski  * This function sets node weight for WFQ algorithm.
1017*0545cc86SMichal Swiatkowski  */
1018*0545cc86SMichal Swiatkowski static int ice_set_object_tx_weight(struct ice_port_info *pi, struct ice_sched_node *node,
1019*0545cc86SMichal Swiatkowski 				    u32 weight, struct netlink_ext_ack *extack)
1020*0545cc86SMichal Swiatkowski {
1021*0545cc86SMichal Swiatkowski 	int status;
1022*0545cc86SMichal Swiatkowski 
1023*0545cc86SMichal Swiatkowski 	if (weight > 200 || weight < 1) {
1024*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Weight must be between 1 and 200");
1025*0545cc86SMichal Swiatkowski 		return -EINVAL;
1026*0545cc86SMichal Swiatkowski 	}
1027*0545cc86SMichal Swiatkowski 
1028*0545cc86SMichal Swiatkowski 	mutex_lock(&pi->sched_lock);
1029*0545cc86SMichal Swiatkowski 	node->tx_weight = weight;
1030*0545cc86SMichal Swiatkowski 	status = ice_sched_set_node_weight(pi, node, node->tx_weight);
1031*0545cc86SMichal Swiatkowski 	mutex_unlock(&pi->sched_lock);
1032*0545cc86SMichal Swiatkowski 
1033*0545cc86SMichal Swiatkowski 	if (status)
1034*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_weight");
1035*0545cc86SMichal Swiatkowski 
1036*0545cc86SMichal Swiatkowski 	return status;
1037*0545cc86SMichal Swiatkowski }
1038*0545cc86SMichal Swiatkowski 
1039*0545cc86SMichal Swiatkowski /**
1040*0545cc86SMichal Swiatkowski  * ice_get_pi_from_dev_rate - get port info from devlink_rate
1041*0545cc86SMichal Swiatkowski  * @rate_node: devlink struct instance
1042*0545cc86SMichal Swiatkowski  *
1043*0545cc86SMichal Swiatkowski  * This function returns corresponding port_info struct of devlink_rate
1044*0545cc86SMichal Swiatkowski  */
1045*0545cc86SMichal Swiatkowski static struct ice_port_info *ice_get_pi_from_dev_rate(struct devlink_rate *rate_node)
1046*0545cc86SMichal Swiatkowski {
1047*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(rate_node->devlink);
1048*0545cc86SMichal Swiatkowski 
1049*0545cc86SMichal Swiatkowski 	return ice_get_main_vsi(pf)->port_info;
1050*0545cc86SMichal Swiatkowski }
1051*0545cc86SMichal Swiatkowski 
1052*0545cc86SMichal Swiatkowski static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
1053*0545cc86SMichal Swiatkowski 				     struct netlink_ext_ack *extack)
1054*0545cc86SMichal Swiatkowski {
1055*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node;
1056*0545cc86SMichal Swiatkowski 	struct ice_port_info *pi;
1057*0545cc86SMichal Swiatkowski 
1058*0545cc86SMichal Swiatkowski 	pi = ice_get_pi_from_dev_rate(rate_node);
1059*0545cc86SMichal Swiatkowski 
1060*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink)))
1061*0545cc86SMichal Swiatkowski 		return -EBUSY;
1062*0545cc86SMichal Swiatkowski 
1063*0545cc86SMichal Swiatkowski 	/* preallocate memory for ice_sched_node */
1064*0545cc86SMichal Swiatkowski 	node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL);
1065*0545cc86SMichal Swiatkowski 	*priv = node;
1066*0545cc86SMichal Swiatkowski 
1067*0545cc86SMichal Swiatkowski 	return 0;
1068*0545cc86SMichal Swiatkowski }
1069*0545cc86SMichal Swiatkowski 
1070*0545cc86SMichal Swiatkowski static int ice_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv,
1071*0545cc86SMichal Swiatkowski 				     struct netlink_ext_ack *extack)
1072*0545cc86SMichal Swiatkowski {
1073*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node, *tc_node;
1074*0545cc86SMichal Swiatkowski 	struct ice_port_info *pi;
1075*0545cc86SMichal Swiatkowski 
1076*0545cc86SMichal Swiatkowski 	pi = ice_get_pi_from_dev_rate(rate_node);
1077*0545cc86SMichal Swiatkowski 	tc_node = pi->root->children[0];
1078*0545cc86SMichal Swiatkowski 	node = priv;
1079*0545cc86SMichal Swiatkowski 
1080*0545cc86SMichal Swiatkowski 	if (!rate_node->parent || !node || tc_node == node || !extack)
1081*0545cc86SMichal Swiatkowski 		return 0;
1082*0545cc86SMichal Swiatkowski 
1083*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink)))
1084*0545cc86SMichal Swiatkowski 		return -EBUSY;
1085*0545cc86SMichal Swiatkowski 
1086*0545cc86SMichal Swiatkowski 	/* can't allow to delete a node with children */
1087*0545cc86SMichal Swiatkowski 	if (node->num_children)
1088*0545cc86SMichal Swiatkowski 		return -EINVAL;
1089*0545cc86SMichal Swiatkowski 
1090*0545cc86SMichal Swiatkowski 	mutex_lock(&pi->sched_lock);
1091*0545cc86SMichal Swiatkowski 	ice_free_sched_node(pi, node);
1092*0545cc86SMichal Swiatkowski 	mutex_unlock(&pi->sched_lock);
1093*0545cc86SMichal Swiatkowski 
1094*0545cc86SMichal Swiatkowski 	return 0;
1095*0545cc86SMichal Swiatkowski }
1096*0545cc86SMichal Swiatkowski 
1097*0545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv,
1098*0545cc86SMichal Swiatkowski 					    u64 tx_max, struct netlink_ext_ack *extack)
1099*0545cc86SMichal Swiatkowski {
1100*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1101*0545cc86SMichal Swiatkowski 
1102*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink)))
1103*0545cc86SMichal Swiatkowski 		return -EBUSY;
1104*0545cc86SMichal Swiatkowski 
1105*0545cc86SMichal Swiatkowski 	if (!node)
1106*0545cc86SMichal Swiatkowski 		return 0;
1107*0545cc86SMichal Swiatkowski 
1108*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_leaf),
1109*0545cc86SMichal Swiatkowski 				     node, tx_max, extack);
1110*0545cc86SMichal Swiatkowski }
1111*0545cc86SMichal Swiatkowski 
1112*0545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv,
1113*0545cc86SMichal Swiatkowski 					      u64 tx_share, struct netlink_ext_ack *extack)
1114*0545cc86SMichal Swiatkowski {
1115*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1116*0545cc86SMichal Swiatkowski 
1117*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink)))
1118*0545cc86SMichal Swiatkowski 		return -EBUSY;
1119*0545cc86SMichal Swiatkowski 
1120*0545cc86SMichal Swiatkowski 	if (!node)
1121*0545cc86SMichal Swiatkowski 		return 0;
1122*0545cc86SMichal Swiatkowski 
1123*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_leaf), node,
1124*0545cc86SMichal Swiatkowski 				       tx_share, extack);
1125*0545cc86SMichal Swiatkowski }
1126*0545cc86SMichal Swiatkowski 
1127*0545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_priority_set(struct devlink_rate *rate_leaf, void *priv,
1128*0545cc86SMichal Swiatkowski 						 u32 tx_priority, struct netlink_ext_ack *extack)
1129*0545cc86SMichal Swiatkowski {
1130*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1131*0545cc86SMichal Swiatkowski 
1132*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink)))
1133*0545cc86SMichal Swiatkowski 		return -EBUSY;
1134*0545cc86SMichal Swiatkowski 
1135*0545cc86SMichal Swiatkowski 	if (!node)
1136*0545cc86SMichal Swiatkowski 		return 0;
1137*0545cc86SMichal Swiatkowski 
1138*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_leaf), node,
1139*0545cc86SMichal Swiatkowski 					  tx_priority, extack);
1140*0545cc86SMichal Swiatkowski }
1141*0545cc86SMichal Swiatkowski 
1142*0545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_weight_set(struct devlink_rate *rate_leaf, void *priv,
1143*0545cc86SMichal Swiatkowski 					       u32 tx_weight, struct netlink_ext_ack *extack)
1144*0545cc86SMichal Swiatkowski {
1145*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1146*0545cc86SMichal Swiatkowski 
1147*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink)))
1148*0545cc86SMichal Swiatkowski 		return -EBUSY;
1149*0545cc86SMichal Swiatkowski 
1150*0545cc86SMichal Swiatkowski 	if (!node)
1151*0545cc86SMichal Swiatkowski 		return 0;
1152*0545cc86SMichal Swiatkowski 
1153*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_leaf), node,
1154*0545cc86SMichal Swiatkowski 					tx_weight, extack);
1155*0545cc86SMichal Swiatkowski }
1156*0545cc86SMichal Swiatkowski 
1157*0545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv,
1158*0545cc86SMichal Swiatkowski 					    u64 tx_max, struct netlink_ext_ack *extack)
1159*0545cc86SMichal Swiatkowski {
1160*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1161*0545cc86SMichal Swiatkowski 
1162*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink)))
1163*0545cc86SMichal Swiatkowski 		return -EBUSY;
1164*0545cc86SMichal Swiatkowski 
1165*0545cc86SMichal Swiatkowski 	if (!node)
1166*0545cc86SMichal Swiatkowski 		return 0;
1167*0545cc86SMichal Swiatkowski 
1168*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_node),
1169*0545cc86SMichal Swiatkowski 				     node, tx_max, extack);
1170*0545cc86SMichal Swiatkowski }
1171*0545cc86SMichal Swiatkowski 
1172*0545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv,
1173*0545cc86SMichal Swiatkowski 					      u64 tx_share, struct netlink_ext_ack *extack)
1174*0545cc86SMichal Swiatkowski {
1175*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1176*0545cc86SMichal Swiatkowski 
1177*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink)))
1178*0545cc86SMichal Swiatkowski 		return -EBUSY;
1179*0545cc86SMichal Swiatkowski 
1180*0545cc86SMichal Swiatkowski 	if (!node)
1181*0545cc86SMichal Swiatkowski 		return 0;
1182*0545cc86SMichal Swiatkowski 
1183*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_node),
1184*0545cc86SMichal Swiatkowski 				       node, tx_share, extack);
1185*0545cc86SMichal Swiatkowski }
1186*0545cc86SMichal Swiatkowski 
1187*0545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_priority_set(struct devlink_rate *rate_node, void *priv,
1188*0545cc86SMichal Swiatkowski 						 u32 tx_priority, struct netlink_ext_ack *extack)
1189*0545cc86SMichal Swiatkowski {
1190*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1191*0545cc86SMichal Swiatkowski 
1192*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink)))
1193*0545cc86SMichal Swiatkowski 		return -EBUSY;
1194*0545cc86SMichal Swiatkowski 
1195*0545cc86SMichal Swiatkowski 	if (!node)
1196*0545cc86SMichal Swiatkowski 		return 0;
1197*0545cc86SMichal Swiatkowski 
1198*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_node),
1199*0545cc86SMichal Swiatkowski 					  node, tx_priority, extack);
1200*0545cc86SMichal Swiatkowski }
1201*0545cc86SMichal Swiatkowski 
1202*0545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_weight_set(struct devlink_rate *rate_node, void *priv,
1203*0545cc86SMichal Swiatkowski 					       u32 tx_weight, struct netlink_ext_ack *extack)
1204*0545cc86SMichal Swiatkowski {
1205*0545cc86SMichal Swiatkowski 	struct ice_sched_node *node = priv;
1206*0545cc86SMichal Swiatkowski 
1207*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink)))
1208*0545cc86SMichal Swiatkowski 		return -EBUSY;
1209*0545cc86SMichal Swiatkowski 
1210*0545cc86SMichal Swiatkowski 	if (!node)
1211*0545cc86SMichal Swiatkowski 		return 0;
1212*0545cc86SMichal Swiatkowski 
1213*0545cc86SMichal Swiatkowski 	return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_node),
1214*0545cc86SMichal Swiatkowski 					node, tx_weight, extack);
1215*0545cc86SMichal Swiatkowski }
1216*0545cc86SMichal Swiatkowski 
1217*0545cc86SMichal Swiatkowski static int ice_devlink_set_parent(struct devlink_rate *devlink_rate,
1218*0545cc86SMichal Swiatkowski 				  struct devlink_rate *parent,
1219*0545cc86SMichal Swiatkowski 				  void *priv, void *parent_priv,
1220*0545cc86SMichal Swiatkowski 				  struct netlink_ext_ack *extack)
1221*0545cc86SMichal Swiatkowski {
1222*0545cc86SMichal Swiatkowski 	struct ice_port_info *pi = ice_get_pi_from_dev_rate(devlink_rate);
1223*0545cc86SMichal Swiatkowski 	struct ice_sched_node *tc_node, *node, *parent_node;
1224*0545cc86SMichal Swiatkowski 	u16 num_nodes_added;
1225*0545cc86SMichal Swiatkowski 	u32 first_node_teid;
1226*0545cc86SMichal Swiatkowski 	u32 node_teid;
1227*0545cc86SMichal Swiatkowski 	int status;
1228*0545cc86SMichal Swiatkowski 
1229*0545cc86SMichal Swiatkowski 	tc_node = pi->root->children[0];
1230*0545cc86SMichal Swiatkowski 	node = priv;
1231*0545cc86SMichal Swiatkowski 
1232*0545cc86SMichal Swiatkowski 	if (!extack)
1233*0545cc86SMichal Swiatkowski 		return 0;
1234*0545cc86SMichal Swiatkowski 
1235*0545cc86SMichal Swiatkowski 	if (!ice_enable_custom_tx(devlink_priv(devlink_rate->devlink)))
1236*0545cc86SMichal Swiatkowski 		return -EBUSY;
1237*0545cc86SMichal Swiatkowski 
1238*0545cc86SMichal Swiatkowski 	if (!parent) {
1239*0545cc86SMichal Swiatkowski 		if (!node || tc_node == node || node->num_children)
1240*0545cc86SMichal Swiatkowski 			return -EINVAL;
1241*0545cc86SMichal Swiatkowski 
1242*0545cc86SMichal Swiatkowski 		mutex_lock(&pi->sched_lock);
1243*0545cc86SMichal Swiatkowski 		ice_free_sched_node(pi, node);
1244*0545cc86SMichal Swiatkowski 		mutex_unlock(&pi->sched_lock);
1245*0545cc86SMichal Swiatkowski 
1246*0545cc86SMichal Swiatkowski 		return 0;
1247*0545cc86SMichal Swiatkowski 	}
1248*0545cc86SMichal Swiatkowski 
1249*0545cc86SMichal Swiatkowski 	parent_node = parent_priv;
1250*0545cc86SMichal Swiatkowski 
1251*0545cc86SMichal Swiatkowski 	/* if the node doesn't exist, create it */
1252*0545cc86SMichal Swiatkowski 	if (!node->parent) {
1253*0545cc86SMichal Swiatkowski 		mutex_lock(&pi->sched_lock);
1254*0545cc86SMichal Swiatkowski 		status = ice_sched_add_elems(pi, tc_node, parent_node,
1255*0545cc86SMichal Swiatkowski 					     parent_node->tx_sched_layer + 1,
1256*0545cc86SMichal Swiatkowski 					     1, &num_nodes_added, &first_node_teid,
1257*0545cc86SMichal Swiatkowski 					     &node);
1258*0545cc86SMichal Swiatkowski 		mutex_unlock(&pi->sched_lock);
1259*0545cc86SMichal Swiatkowski 
1260*0545cc86SMichal Swiatkowski 		if (status) {
1261*0545cc86SMichal Swiatkowski 			NL_SET_ERR_MSG_MOD(extack, "Can't add a new node");
1262*0545cc86SMichal Swiatkowski 			return status;
1263*0545cc86SMichal Swiatkowski 		}
1264*0545cc86SMichal Swiatkowski 
1265*0545cc86SMichal Swiatkowski 		if (devlink_rate->tx_share)
1266*0545cc86SMichal Swiatkowski 			ice_set_object_tx_share(pi, node, devlink_rate->tx_share, extack);
1267*0545cc86SMichal Swiatkowski 		if (devlink_rate->tx_max)
1268*0545cc86SMichal Swiatkowski 			ice_set_object_tx_max(pi, node, devlink_rate->tx_max, extack);
1269*0545cc86SMichal Swiatkowski 		if (devlink_rate->tx_priority)
1270*0545cc86SMichal Swiatkowski 			ice_set_object_tx_priority(pi, node, devlink_rate->tx_priority, extack);
1271*0545cc86SMichal Swiatkowski 		if (devlink_rate->tx_weight)
1272*0545cc86SMichal Swiatkowski 			ice_set_object_tx_weight(pi, node, devlink_rate->tx_weight, extack);
1273*0545cc86SMichal Swiatkowski 	} else {
1274*0545cc86SMichal Swiatkowski 		node_teid = le32_to_cpu(node->info.node_teid);
1275*0545cc86SMichal Swiatkowski 		mutex_lock(&pi->sched_lock);
1276*0545cc86SMichal Swiatkowski 		status = ice_sched_move_nodes(pi, parent_node, 1, &node_teid);
1277*0545cc86SMichal Swiatkowski 		mutex_unlock(&pi->sched_lock);
1278*0545cc86SMichal Swiatkowski 
1279*0545cc86SMichal Swiatkowski 		if (status)
1280*0545cc86SMichal Swiatkowski 			NL_SET_ERR_MSG_MOD(extack, "Can't move existing node to a new parent");
1281*0545cc86SMichal Swiatkowski 	}
1282*0545cc86SMichal Swiatkowski 
1283*0545cc86SMichal Swiatkowski 	return status;
1284*0545cc86SMichal Swiatkowski }
1285*0545cc86SMichal Swiatkowski 
1286*0545cc86SMichal Swiatkowski /**
1287*0545cc86SMichal Swiatkowski  * ice_devlink_reinit_up - do reinit of the given PF
1288*0545cc86SMichal Swiatkowski  * @pf: pointer to the PF struct
1289*0545cc86SMichal Swiatkowski  */
1290*0545cc86SMichal Swiatkowski static int ice_devlink_reinit_up(struct ice_pf *pf)
1291*0545cc86SMichal Swiatkowski {
1292*0545cc86SMichal Swiatkowski 	struct ice_vsi *vsi = ice_get_main_vsi(pf);
1293*0545cc86SMichal Swiatkowski 	struct ice_vsi_cfg_params params;
1294*0545cc86SMichal Swiatkowski 	int err;
1295*0545cc86SMichal Swiatkowski 
1296*0545cc86SMichal Swiatkowski 	err = ice_init_dev(pf);
1297*0545cc86SMichal Swiatkowski 	if (err)
1298*0545cc86SMichal Swiatkowski 		return err;
1299*0545cc86SMichal Swiatkowski 
1300*0545cc86SMichal Swiatkowski 	params = ice_vsi_to_params(vsi);
1301*0545cc86SMichal Swiatkowski 	params.flags = ICE_VSI_FLAG_INIT;
1302*0545cc86SMichal Swiatkowski 
1303*0545cc86SMichal Swiatkowski 	rtnl_lock();
1304*0545cc86SMichal Swiatkowski 	err = ice_vsi_cfg(vsi, &params);
1305*0545cc86SMichal Swiatkowski 	rtnl_unlock();
1306*0545cc86SMichal Swiatkowski 	if (err)
1307*0545cc86SMichal Swiatkowski 		goto err_vsi_cfg;
1308*0545cc86SMichal Swiatkowski 
1309*0545cc86SMichal Swiatkowski 	/* No need to take devl_lock, it's already taken by devlink API */
1310*0545cc86SMichal Swiatkowski 	err = ice_load(pf);
1311*0545cc86SMichal Swiatkowski 	if (err)
1312*0545cc86SMichal Swiatkowski 		goto err_load;
1313*0545cc86SMichal Swiatkowski 
1314*0545cc86SMichal Swiatkowski 	return 0;
1315*0545cc86SMichal Swiatkowski 
1316*0545cc86SMichal Swiatkowski err_load:
1317*0545cc86SMichal Swiatkowski 	rtnl_lock();
1318*0545cc86SMichal Swiatkowski 	ice_vsi_decfg(vsi);
1319*0545cc86SMichal Swiatkowski 	rtnl_unlock();
1320*0545cc86SMichal Swiatkowski err_vsi_cfg:
1321*0545cc86SMichal Swiatkowski 	ice_deinit_dev(pf);
1322*0545cc86SMichal Swiatkowski 	return err;
1323*0545cc86SMichal Swiatkowski }
1324*0545cc86SMichal Swiatkowski 
1325*0545cc86SMichal Swiatkowski /**
1326*0545cc86SMichal Swiatkowski  * ice_devlink_reload_up - do reload up after reinit
1327*0545cc86SMichal Swiatkowski  * @devlink: pointer to the devlink instance reloading
1328*0545cc86SMichal Swiatkowski  * @action: the action requested
1329*0545cc86SMichal Swiatkowski  * @limit: limits imposed by userspace, such as not resetting
1330*0545cc86SMichal Swiatkowski  * @actions_performed: on return, indicate what actions actually performed
1331*0545cc86SMichal Swiatkowski  * @extack: netlink extended ACK structure
1332*0545cc86SMichal Swiatkowski  */
1333*0545cc86SMichal Swiatkowski static int
1334*0545cc86SMichal Swiatkowski ice_devlink_reload_up(struct devlink *devlink,
1335*0545cc86SMichal Swiatkowski 		      enum devlink_reload_action action,
1336*0545cc86SMichal Swiatkowski 		      enum devlink_reload_limit limit,
1337*0545cc86SMichal Swiatkowski 		      u32 *actions_performed,
1338*0545cc86SMichal Swiatkowski 		      struct netlink_ext_ack *extack)
1339*0545cc86SMichal Swiatkowski {
1340*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1341*0545cc86SMichal Swiatkowski 
1342*0545cc86SMichal Swiatkowski 	switch (action) {
1343*0545cc86SMichal Swiatkowski 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
1344*0545cc86SMichal Swiatkowski 		*actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
1345*0545cc86SMichal Swiatkowski 		return ice_devlink_reinit_up(pf);
1346*0545cc86SMichal Swiatkowski 	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
1347*0545cc86SMichal Swiatkowski 		*actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
1348*0545cc86SMichal Swiatkowski 		return ice_devlink_reload_empr_finish(pf, extack);
1349*0545cc86SMichal Swiatkowski 	default:
1350*0545cc86SMichal Swiatkowski 		WARN_ON(1);
1351*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
1352*0545cc86SMichal Swiatkowski 	}
1353*0545cc86SMichal Swiatkowski }
1354*0545cc86SMichal Swiatkowski 
1355*0545cc86SMichal Swiatkowski static const struct devlink_ops ice_devlink_ops = {
1356*0545cc86SMichal Swiatkowski 	.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
1357*0545cc86SMichal Swiatkowski 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
1358*0545cc86SMichal Swiatkowski 			  BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
1359*0545cc86SMichal Swiatkowski 	.reload_down = ice_devlink_reload_down,
1360*0545cc86SMichal Swiatkowski 	.reload_up = ice_devlink_reload_up,
1361*0545cc86SMichal Swiatkowski 	.eswitch_mode_get = ice_eswitch_mode_get,
1362*0545cc86SMichal Swiatkowski 	.eswitch_mode_set = ice_eswitch_mode_set,
1363*0545cc86SMichal Swiatkowski 	.info_get = ice_devlink_info_get,
1364*0545cc86SMichal Swiatkowski 	.flash_update = ice_devlink_flash_update,
1365*0545cc86SMichal Swiatkowski 
1366*0545cc86SMichal Swiatkowski 	.rate_node_new = ice_devlink_rate_node_new,
1367*0545cc86SMichal Swiatkowski 	.rate_node_del = ice_devlink_rate_node_del,
1368*0545cc86SMichal Swiatkowski 
1369*0545cc86SMichal Swiatkowski 	.rate_leaf_tx_max_set = ice_devlink_rate_leaf_tx_max_set,
1370*0545cc86SMichal Swiatkowski 	.rate_leaf_tx_share_set = ice_devlink_rate_leaf_tx_share_set,
1371*0545cc86SMichal Swiatkowski 	.rate_leaf_tx_priority_set = ice_devlink_rate_leaf_tx_priority_set,
1372*0545cc86SMichal Swiatkowski 	.rate_leaf_tx_weight_set = ice_devlink_rate_leaf_tx_weight_set,
1373*0545cc86SMichal Swiatkowski 
1374*0545cc86SMichal Swiatkowski 	.rate_node_tx_max_set = ice_devlink_rate_node_tx_max_set,
1375*0545cc86SMichal Swiatkowski 	.rate_node_tx_share_set = ice_devlink_rate_node_tx_share_set,
1376*0545cc86SMichal Swiatkowski 	.rate_node_tx_priority_set = ice_devlink_rate_node_tx_priority_set,
1377*0545cc86SMichal Swiatkowski 	.rate_node_tx_weight_set = ice_devlink_rate_node_tx_weight_set,
1378*0545cc86SMichal Swiatkowski 
1379*0545cc86SMichal Swiatkowski 	.rate_leaf_parent_set = ice_devlink_set_parent,
1380*0545cc86SMichal Swiatkowski 	.rate_node_parent_set = ice_devlink_set_parent,
1381*0545cc86SMichal Swiatkowski };
1382*0545cc86SMichal Swiatkowski 
1383*0545cc86SMichal Swiatkowski static int
1384*0545cc86SMichal Swiatkowski ice_devlink_enable_roce_get(struct devlink *devlink, u32 id,
1385*0545cc86SMichal Swiatkowski 			    struct devlink_param_gset_ctx *ctx)
1386*0545cc86SMichal Swiatkowski {
1387*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1388*0545cc86SMichal Swiatkowski 
1389*0545cc86SMichal Swiatkowski 	ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false;
1390*0545cc86SMichal Swiatkowski 
1391*0545cc86SMichal Swiatkowski 	return 0;
1392*0545cc86SMichal Swiatkowski }
1393*0545cc86SMichal Swiatkowski 
1394*0545cc86SMichal Swiatkowski static int
1395*0545cc86SMichal Swiatkowski ice_devlink_enable_roce_set(struct devlink *devlink, u32 id,
1396*0545cc86SMichal Swiatkowski 			    struct devlink_param_gset_ctx *ctx)
1397*0545cc86SMichal Swiatkowski {
1398*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1399*0545cc86SMichal Swiatkowski 	bool roce_ena = ctx->val.vbool;
1400*0545cc86SMichal Swiatkowski 	int ret;
1401*0545cc86SMichal Swiatkowski 
1402*0545cc86SMichal Swiatkowski 	if (!roce_ena) {
1403*0545cc86SMichal Swiatkowski 		ice_unplug_aux_dev(pf);
1404*0545cc86SMichal Swiatkowski 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2;
1405*0545cc86SMichal Swiatkowski 		return 0;
1406*0545cc86SMichal Swiatkowski 	}
1407*0545cc86SMichal Swiatkowski 
1408*0545cc86SMichal Swiatkowski 	pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2;
1409*0545cc86SMichal Swiatkowski 	ret = ice_plug_aux_dev(pf);
1410*0545cc86SMichal Swiatkowski 	if (ret)
1411*0545cc86SMichal Swiatkowski 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2;
1412*0545cc86SMichal Swiatkowski 
1413*0545cc86SMichal Swiatkowski 	return ret;
1414*0545cc86SMichal Swiatkowski }
1415*0545cc86SMichal Swiatkowski 
1416*0545cc86SMichal Swiatkowski static int
1417*0545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
1418*0545cc86SMichal Swiatkowski 				 union devlink_param_value val,
1419*0545cc86SMichal Swiatkowski 				 struct netlink_ext_ack *extack)
1420*0545cc86SMichal Swiatkowski {
1421*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1422*0545cc86SMichal Swiatkowski 
1423*0545cc86SMichal Swiatkowski 	if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
1424*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
1425*0545cc86SMichal Swiatkowski 
1426*0545cc86SMichal Swiatkowski 	if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) {
1427*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously");
1428*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
1429*0545cc86SMichal Swiatkowski 	}
1430*0545cc86SMichal Swiatkowski 
1431*0545cc86SMichal Swiatkowski 	return 0;
1432*0545cc86SMichal Swiatkowski }
1433*0545cc86SMichal Swiatkowski 
1434*0545cc86SMichal Swiatkowski static int
1435*0545cc86SMichal Swiatkowski ice_devlink_enable_iw_get(struct devlink *devlink, u32 id,
1436*0545cc86SMichal Swiatkowski 			  struct devlink_param_gset_ctx *ctx)
1437*0545cc86SMichal Swiatkowski {
1438*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1439*0545cc86SMichal Swiatkowski 
1440*0545cc86SMichal Swiatkowski 	ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP;
1441*0545cc86SMichal Swiatkowski 
1442*0545cc86SMichal Swiatkowski 	return 0;
1443*0545cc86SMichal Swiatkowski }
1444*0545cc86SMichal Swiatkowski 
1445*0545cc86SMichal Swiatkowski static int
1446*0545cc86SMichal Swiatkowski ice_devlink_enable_iw_set(struct devlink *devlink, u32 id,
1447*0545cc86SMichal Swiatkowski 			  struct devlink_param_gset_ctx *ctx)
1448*0545cc86SMichal Swiatkowski {
1449*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1450*0545cc86SMichal Swiatkowski 	bool iw_ena = ctx->val.vbool;
1451*0545cc86SMichal Swiatkowski 	int ret;
1452*0545cc86SMichal Swiatkowski 
1453*0545cc86SMichal Swiatkowski 	if (!iw_ena) {
1454*0545cc86SMichal Swiatkowski 		ice_unplug_aux_dev(pf);
1455*0545cc86SMichal Swiatkowski 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP;
1456*0545cc86SMichal Swiatkowski 		return 0;
1457*0545cc86SMichal Swiatkowski 	}
1458*0545cc86SMichal Swiatkowski 
1459*0545cc86SMichal Swiatkowski 	pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP;
1460*0545cc86SMichal Swiatkowski 	ret = ice_plug_aux_dev(pf);
1461*0545cc86SMichal Swiatkowski 	if (ret)
1462*0545cc86SMichal Swiatkowski 		pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP;
1463*0545cc86SMichal Swiatkowski 
1464*0545cc86SMichal Swiatkowski 	return ret;
1465*0545cc86SMichal Swiatkowski }
1466*0545cc86SMichal Swiatkowski 
1467*0545cc86SMichal Swiatkowski static int
1468*0545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id,
1469*0545cc86SMichal Swiatkowski 			       union devlink_param_value val,
1470*0545cc86SMichal Swiatkowski 			       struct netlink_ext_ack *extack)
1471*0545cc86SMichal Swiatkowski {
1472*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1473*0545cc86SMichal Swiatkowski 
1474*0545cc86SMichal Swiatkowski 	if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
1475*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
1476*0545cc86SMichal Swiatkowski 
1477*0545cc86SMichal Swiatkowski 	if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) {
1478*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously");
1479*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
1480*0545cc86SMichal Swiatkowski 	}
1481*0545cc86SMichal Swiatkowski 
1482*0545cc86SMichal Swiatkowski 	return 0;
1483*0545cc86SMichal Swiatkowski }
1484*0545cc86SMichal Swiatkowski 
1485*0545cc86SMichal Swiatkowski static const struct devlink_param ice_devlink_params[] = {
1486*0545cc86SMichal Swiatkowski 	DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
1487*0545cc86SMichal Swiatkowski 			      ice_devlink_enable_roce_get,
1488*0545cc86SMichal Swiatkowski 			      ice_devlink_enable_roce_set,
1489*0545cc86SMichal Swiatkowski 			      ice_devlink_enable_roce_validate),
1490*0545cc86SMichal Swiatkowski 	DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
1491*0545cc86SMichal Swiatkowski 			      ice_devlink_enable_iw_get,
1492*0545cc86SMichal Swiatkowski 			      ice_devlink_enable_iw_set,
1493*0545cc86SMichal Swiatkowski 			      ice_devlink_enable_iw_validate),
1494*0545cc86SMichal Swiatkowski 
1495*0545cc86SMichal Swiatkowski };
1496*0545cc86SMichal Swiatkowski 
1497*0545cc86SMichal Swiatkowski static void ice_devlink_free(void *devlink_ptr)
1498*0545cc86SMichal Swiatkowski {
1499*0545cc86SMichal Swiatkowski 	devlink_free((struct devlink *)devlink_ptr);
1500*0545cc86SMichal Swiatkowski }
1501*0545cc86SMichal Swiatkowski 
1502*0545cc86SMichal Swiatkowski /**
1503*0545cc86SMichal Swiatkowski  * ice_allocate_pf - Allocate devlink and return PF structure pointer
1504*0545cc86SMichal Swiatkowski  * @dev: the device to allocate for
1505*0545cc86SMichal Swiatkowski  *
1506*0545cc86SMichal Swiatkowski  * Allocate a devlink instance for this device and return the private area as
1507*0545cc86SMichal Swiatkowski  * the PF structure. The devlink memory is kept track of through devres by
1508*0545cc86SMichal Swiatkowski  * adding an action to remove it when unwinding.
1509*0545cc86SMichal Swiatkowski  */
1510*0545cc86SMichal Swiatkowski struct ice_pf *ice_allocate_pf(struct device *dev)
1511*0545cc86SMichal Swiatkowski {
1512*0545cc86SMichal Swiatkowski 	struct devlink *devlink;
1513*0545cc86SMichal Swiatkowski 
1514*0545cc86SMichal Swiatkowski 	devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev);
1515*0545cc86SMichal Swiatkowski 	if (!devlink)
1516*0545cc86SMichal Swiatkowski 		return NULL;
1517*0545cc86SMichal Swiatkowski 
1518*0545cc86SMichal Swiatkowski 	/* Add an action to teardown the devlink when unwinding the driver */
1519*0545cc86SMichal Swiatkowski 	if (devm_add_action_or_reset(dev, ice_devlink_free, devlink))
1520*0545cc86SMichal Swiatkowski 		return NULL;
1521*0545cc86SMichal Swiatkowski 
1522*0545cc86SMichal Swiatkowski 	return devlink_priv(devlink);
1523*0545cc86SMichal Swiatkowski }
1524*0545cc86SMichal Swiatkowski 
1525*0545cc86SMichal Swiatkowski /**
1526*0545cc86SMichal Swiatkowski  * ice_devlink_register - Register devlink interface for this PF
1527*0545cc86SMichal Swiatkowski  * @pf: the PF to register the devlink for.
1528*0545cc86SMichal Swiatkowski  *
1529*0545cc86SMichal Swiatkowski  * Register the devlink instance associated with this physical function.
1530*0545cc86SMichal Swiatkowski  *
1531*0545cc86SMichal Swiatkowski  * Return: zero on success or an error code on failure.
1532*0545cc86SMichal Swiatkowski  */
1533*0545cc86SMichal Swiatkowski void ice_devlink_register(struct ice_pf *pf)
1534*0545cc86SMichal Swiatkowski {
1535*0545cc86SMichal Swiatkowski 	struct devlink *devlink = priv_to_devlink(pf);
1536*0545cc86SMichal Swiatkowski 
1537*0545cc86SMichal Swiatkowski 	devlink_register(devlink);
1538*0545cc86SMichal Swiatkowski }
1539*0545cc86SMichal Swiatkowski 
1540*0545cc86SMichal Swiatkowski /**
1541*0545cc86SMichal Swiatkowski  * ice_devlink_unregister - Unregister devlink resources for this PF.
1542*0545cc86SMichal Swiatkowski  * @pf: the PF structure to cleanup
1543*0545cc86SMichal Swiatkowski  *
1544*0545cc86SMichal Swiatkowski  * Releases resources used by devlink and cleans up associated memory.
1545*0545cc86SMichal Swiatkowski  */
1546*0545cc86SMichal Swiatkowski void ice_devlink_unregister(struct ice_pf *pf)
1547*0545cc86SMichal Swiatkowski {
1548*0545cc86SMichal Swiatkowski 	devlink_unregister(priv_to_devlink(pf));
1549*0545cc86SMichal Swiatkowski }
1550*0545cc86SMichal Swiatkowski 
1551*0545cc86SMichal Swiatkowski /**
1552*0545cc86SMichal Swiatkowski  * ice_devlink_set_switch_id - Set unique switch id based on pci dsn
1553*0545cc86SMichal Swiatkowski  * @pf: the PF to create a devlink port for
1554*0545cc86SMichal Swiatkowski  * @ppid: struct with switch id information
1555*0545cc86SMichal Swiatkowski  */
1556*0545cc86SMichal Swiatkowski static void
1557*0545cc86SMichal Swiatkowski ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid)
1558*0545cc86SMichal Swiatkowski {
1559*0545cc86SMichal Swiatkowski 	struct pci_dev *pdev = pf->pdev;
1560*0545cc86SMichal Swiatkowski 	u64 id;
1561*0545cc86SMichal Swiatkowski 
1562*0545cc86SMichal Swiatkowski 	id = pci_get_dsn(pdev);
1563*0545cc86SMichal Swiatkowski 
1564*0545cc86SMichal Swiatkowski 	ppid->id_len = sizeof(id);
1565*0545cc86SMichal Swiatkowski 	put_unaligned_be64(id, &ppid->id);
1566*0545cc86SMichal Swiatkowski }
1567*0545cc86SMichal Swiatkowski 
1568*0545cc86SMichal Swiatkowski int ice_devlink_register_params(struct ice_pf *pf)
1569*0545cc86SMichal Swiatkowski {
1570*0545cc86SMichal Swiatkowski 	struct devlink *devlink = priv_to_devlink(pf);
1571*0545cc86SMichal Swiatkowski 
1572*0545cc86SMichal Swiatkowski 	return devlink_params_register(devlink, ice_devlink_params,
1573*0545cc86SMichal Swiatkowski 				       ARRAY_SIZE(ice_devlink_params));
1574*0545cc86SMichal Swiatkowski }
1575*0545cc86SMichal Swiatkowski 
1576*0545cc86SMichal Swiatkowski void ice_devlink_unregister_params(struct ice_pf *pf)
1577*0545cc86SMichal Swiatkowski {
1578*0545cc86SMichal Swiatkowski 	devlink_params_unregister(priv_to_devlink(pf), ice_devlink_params,
1579*0545cc86SMichal Swiatkowski 				  ARRAY_SIZE(ice_devlink_params));
1580*0545cc86SMichal Swiatkowski }
1581*0545cc86SMichal Swiatkowski 
1582*0545cc86SMichal Swiatkowski /**
1583*0545cc86SMichal Swiatkowski  * ice_devlink_set_port_split_options - Set port split options
1584*0545cc86SMichal Swiatkowski  * @pf: the PF to set port split options
1585*0545cc86SMichal Swiatkowski  * @attrs: devlink attributes
1586*0545cc86SMichal Swiatkowski  *
1587*0545cc86SMichal Swiatkowski  * Sets devlink port split options based on available FW port options
1588*0545cc86SMichal Swiatkowski  */
1589*0545cc86SMichal Swiatkowski static void
1590*0545cc86SMichal Swiatkowski ice_devlink_set_port_split_options(struct ice_pf *pf,
1591*0545cc86SMichal Swiatkowski 				   struct devlink_port_attrs *attrs)
1592*0545cc86SMichal Swiatkowski {
1593*0545cc86SMichal Swiatkowski 	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
1594*0545cc86SMichal Swiatkowski 	u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX;
1595*0545cc86SMichal Swiatkowski 	bool active_valid, pending_valid;
1596*0545cc86SMichal Swiatkowski 	int status;
1597*0545cc86SMichal Swiatkowski 
1598*0545cc86SMichal Swiatkowski 	status = ice_aq_get_port_options(&pf->hw, options, &option_count,
1599*0545cc86SMichal Swiatkowski 					 0, true, &active_idx, &active_valid,
1600*0545cc86SMichal Swiatkowski 					 &pending_idx, &pending_valid);
1601*0545cc86SMichal Swiatkowski 	if (status) {
1602*0545cc86SMichal Swiatkowski 		dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n",
1603*0545cc86SMichal Swiatkowski 			status);
1604*0545cc86SMichal Swiatkowski 		return;
1605*0545cc86SMichal Swiatkowski 	}
1606*0545cc86SMichal Swiatkowski 
1607*0545cc86SMichal Swiatkowski 	/* find the biggest available port split count */
1608*0545cc86SMichal Swiatkowski 	for (i = 0; i < option_count; i++)
1609*0545cc86SMichal Swiatkowski 		attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);
1610*0545cc86SMichal Swiatkowski 
1611*0545cc86SMichal Swiatkowski 	attrs->splittable = attrs->lanes ? 1 : 0;
1612*0545cc86SMichal Swiatkowski 	ice_active_port_option = active_idx;
1613*0545cc86SMichal Swiatkowski }
1614*0545cc86SMichal Swiatkowski 
1615*0545cc86SMichal Swiatkowski static const struct devlink_port_ops ice_devlink_port_ops = {
1616*0545cc86SMichal Swiatkowski 	.port_split = ice_devlink_port_split,
1617*0545cc86SMichal Swiatkowski 	.port_unsplit = ice_devlink_port_unsplit,
1618*0545cc86SMichal Swiatkowski };
1619*0545cc86SMichal Swiatkowski 
1620*0545cc86SMichal Swiatkowski /**
1621*0545cc86SMichal Swiatkowski  * ice_devlink_create_pf_port - Create a devlink port for this PF
1622*0545cc86SMichal Swiatkowski  * @pf: the PF to create a devlink port for
1623*0545cc86SMichal Swiatkowski  *
1624*0545cc86SMichal Swiatkowski  * Create and register a devlink_port for this PF.
1625*0545cc86SMichal Swiatkowski  * This function has to be called under devl_lock.
1626*0545cc86SMichal Swiatkowski  *
1627*0545cc86SMichal Swiatkowski  * Return: zero on success or an error code on failure.
1628*0545cc86SMichal Swiatkowski  */
1629*0545cc86SMichal Swiatkowski int ice_devlink_create_pf_port(struct ice_pf *pf)
1630*0545cc86SMichal Swiatkowski {
1631*0545cc86SMichal Swiatkowski 	struct devlink_port_attrs attrs = {};
1632*0545cc86SMichal Swiatkowski 	struct devlink_port *devlink_port;
1633*0545cc86SMichal Swiatkowski 	struct devlink *devlink;
1634*0545cc86SMichal Swiatkowski 	struct ice_vsi *vsi;
1635*0545cc86SMichal Swiatkowski 	struct device *dev;
1636*0545cc86SMichal Swiatkowski 	int err;
1637*0545cc86SMichal Swiatkowski 
1638*0545cc86SMichal Swiatkowski 	devlink = priv_to_devlink(pf);
1639*0545cc86SMichal Swiatkowski 
1640*0545cc86SMichal Swiatkowski 	dev = ice_pf_to_dev(pf);
1641*0545cc86SMichal Swiatkowski 
1642*0545cc86SMichal Swiatkowski 	devlink_port = &pf->devlink_port;
1643*0545cc86SMichal Swiatkowski 
1644*0545cc86SMichal Swiatkowski 	vsi = ice_get_main_vsi(pf);
1645*0545cc86SMichal Swiatkowski 	if (!vsi)
1646*0545cc86SMichal Swiatkowski 		return -EIO;
1647*0545cc86SMichal Swiatkowski 
1648*0545cc86SMichal Swiatkowski 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
1649*0545cc86SMichal Swiatkowski 	attrs.phys.port_number = pf->hw.bus.func;
1650*0545cc86SMichal Swiatkowski 
1651*0545cc86SMichal Swiatkowski 	/* As FW supports only port split options for whole device,
1652*0545cc86SMichal Swiatkowski 	 * set port split options only for first PF.
1653*0545cc86SMichal Swiatkowski 	 */
1654*0545cc86SMichal Swiatkowski 	if (pf->hw.pf_id == 0)
1655*0545cc86SMichal Swiatkowski 		ice_devlink_set_port_split_options(pf, &attrs);
1656*0545cc86SMichal Swiatkowski 
1657*0545cc86SMichal Swiatkowski 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
1658*0545cc86SMichal Swiatkowski 
1659*0545cc86SMichal Swiatkowski 	devlink_port_attrs_set(devlink_port, &attrs);
1660*0545cc86SMichal Swiatkowski 
1661*0545cc86SMichal Swiatkowski 	err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
1662*0545cc86SMichal Swiatkowski 					  &ice_devlink_port_ops);
1663*0545cc86SMichal Swiatkowski 	if (err) {
1664*0545cc86SMichal Swiatkowski 		dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
1665*0545cc86SMichal Swiatkowski 			pf->hw.pf_id, err);
1666*0545cc86SMichal Swiatkowski 		return err;
1667*0545cc86SMichal Swiatkowski 	}
1668*0545cc86SMichal Swiatkowski 
1669*0545cc86SMichal Swiatkowski 	return 0;
1670*0545cc86SMichal Swiatkowski }
1671*0545cc86SMichal Swiatkowski 
1672*0545cc86SMichal Swiatkowski /**
1673*0545cc86SMichal Swiatkowski  * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
1674*0545cc86SMichal Swiatkowski  * @pf: the PF to cleanup
1675*0545cc86SMichal Swiatkowski  *
1676*0545cc86SMichal Swiatkowski  * Unregisters the devlink_port structure associated with this PF.
1677*0545cc86SMichal Swiatkowski  * This function has to be called under devl_lock.
1678*0545cc86SMichal Swiatkowski  */
1679*0545cc86SMichal Swiatkowski void ice_devlink_destroy_pf_port(struct ice_pf *pf)
1680*0545cc86SMichal Swiatkowski {
1681*0545cc86SMichal Swiatkowski 	devl_port_unregister(&pf->devlink_port);
1682*0545cc86SMichal Swiatkowski }
1683*0545cc86SMichal Swiatkowski 
1684*0545cc86SMichal Swiatkowski /**
1685*0545cc86SMichal Swiatkowski  * ice_devlink_create_vf_port - Create a devlink port for this VF
1686*0545cc86SMichal Swiatkowski  * @vf: the VF to create a port for
1687*0545cc86SMichal Swiatkowski  *
1688*0545cc86SMichal Swiatkowski  * Create and register a devlink_port for this VF.
1689*0545cc86SMichal Swiatkowski  *
1690*0545cc86SMichal Swiatkowski  * Return: zero on success or an error code on failure.
1691*0545cc86SMichal Swiatkowski  */
1692*0545cc86SMichal Swiatkowski int ice_devlink_create_vf_port(struct ice_vf *vf)
1693*0545cc86SMichal Swiatkowski {
1694*0545cc86SMichal Swiatkowski 	struct devlink_port_attrs attrs = {};
1695*0545cc86SMichal Swiatkowski 	struct devlink_port *devlink_port;
1696*0545cc86SMichal Swiatkowski 	struct devlink *devlink;
1697*0545cc86SMichal Swiatkowski 	struct ice_vsi *vsi;
1698*0545cc86SMichal Swiatkowski 	struct device *dev;
1699*0545cc86SMichal Swiatkowski 	struct ice_pf *pf;
1700*0545cc86SMichal Swiatkowski 	int err;
1701*0545cc86SMichal Swiatkowski 
1702*0545cc86SMichal Swiatkowski 	pf = vf->pf;
1703*0545cc86SMichal Swiatkowski 	dev = ice_pf_to_dev(pf);
1704*0545cc86SMichal Swiatkowski 	devlink_port = &vf->devlink_port;
1705*0545cc86SMichal Swiatkowski 
1706*0545cc86SMichal Swiatkowski 	vsi = ice_get_vf_vsi(vf);
1707*0545cc86SMichal Swiatkowski 	if (!vsi)
1708*0545cc86SMichal Swiatkowski 		return -EINVAL;
1709*0545cc86SMichal Swiatkowski 
1710*0545cc86SMichal Swiatkowski 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
1711*0545cc86SMichal Swiatkowski 	attrs.pci_vf.pf = pf->hw.bus.func;
1712*0545cc86SMichal Swiatkowski 	attrs.pci_vf.vf = vf->vf_id;
1713*0545cc86SMichal Swiatkowski 
1714*0545cc86SMichal Swiatkowski 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
1715*0545cc86SMichal Swiatkowski 
1716*0545cc86SMichal Swiatkowski 	devlink_port_attrs_set(devlink_port, &attrs);
1717*0545cc86SMichal Swiatkowski 	devlink = priv_to_devlink(pf);
1718*0545cc86SMichal Swiatkowski 
1719*0545cc86SMichal Swiatkowski 	err = devlink_port_register(devlink, devlink_port, vsi->idx);
1720*0545cc86SMichal Swiatkowski 	if (err) {
1721*0545cc86SMichal Swiatkowski 		dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
1722*0545cc86SMichal Swiatkowski 			vf->vf_id, err);
1723*0545cc86SMichal Swiatkowski 		return err;
1724*0545cc86SMichal Swiatkowski 	}
1725*0545cc86SMichal Swiatkowski 
1726*0545cc86SMichal Swiatkowski 	return 0;
1727*0545cc86SMichal Swiatkowski }
1728*0545cc86SMichal Swiatkowski 
1729*0545cc86SMichal Swiatkowski /**
1730*0545cc86SMichal Swiatkowski  * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
1731*0545cc86SMichal Swiatkowski  * @vf: the VF to cleanup
1732*0545cc86SMichal Swiatkowski  *
1733*0545cc86SMichal Swiatkowski  * Unregisters the devlink_port structure associated with this VF.
1734*0545cc86SMichal Swiatkowski  */
1735*0545cc86SMichal Swiatkowski void ice_devlink_destroy_vf_port(struct ice_vf *vf)
1736*0545cc86SMichal Swiatkowski {
1737*0545cc86SMichal Swiatkowski 	devl_rate_leaf_destroy(&vf->devlink_port);
1738*0545cc86SMichal Swiatkowski 	devlink_port_unregister(&vf->devlink_port);
1739*0545cc86SMichal Swiatkowski }
1740*0545cc86SMichal Swiatkowski 
1741*0545cc86SMichal Swiatkowski #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024)
1742*0545cc86SMichal Swiatkowski 
1743*0545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops;
1744*0545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops;
1745*0545cc86SMichal Swiatkowski 
1746*0545cc86SMichal Swiatkowski /**
1747*0545cc86SMichal Swiatkowski  * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents
1748*0545cc86SMichal Swiatkowski  * @devlink: the devlink instance
1749*0545cc86SMichal Swiatkowski  * @ops: the devlink region to snapshot
1750*0545cc86SMichal Swiatkowski  * @extack: extended ACK response structure
1751*0545cc86SMichal Swiatkowski  * @data: on exit points to snapshot data buffer
1752*0545cc86SMichal Swiatkowski  *
1753*0545cc86SMichal Swiatkowski  * This function is called in response to a DEVLINK_CMD_REGION_NEW for either
1754*0545cc86SMichal Swiatkowski  * the nvm-flash or shadow-ram region.
1755*0545cc86SMichal Swiatkowski  *
1756*0545cc86SMichal Swiatkowski  * It captures a snapshot of the NVM or Shadow RAM flash contents. This
1757*0545cc86SMichal Swiatkowski  * snapshot can then later be viewed via the DEVLINK_CMD_REGION_READ netlink
1758*0545cc86SMichal Swiatkowski  * interface.
1759*0545cc86SMichal Swiatkowski  *
1760*0545cc86SMichal Swiatkowski  * @returns zero on success, and updates the data pointer. Returns a non-zero
1761*0545cc86SMichal Swiatkowski  * error code on failure.
1762*0545cc86SMichal Swiatkowski  */
1763*0545cc86SMichal Swiatkowski static int ice_devlink_nvm_snapshot(struct devlink *devlink,
1764*0545cc86SMichal Swiatkowski 				    const struct devlink_region_ops *ops,
1765*0545cc86SMichal Swiatkowski 				    struct netlink_ext_ack *extack, u8 **data)
1766*0545cc86SMichal Swiatkowski {
1767*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1768*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
1769*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
1770*0545cc86SMichal Swiatkowski 	bool read_shadow_ram;
1771*0545cc86SMichal Swiatkowski 	u8 *nvm_data, *tmp, i;
1772*0545cc86SMichal Swiatkowski 	u32 nvm_size, left;
1773*0545cc86SMichal Swiatkowski 	s8 num_blks;
1774*0545cc86SMichal Swiatkowski 	int status;
1775*0545cc86SMichal Swiatkowski 
1776*0545cc86SMichal Swiatkowski 	if (ops == &ice_nvm_region_ops) {
1777*0545cc86SMichal Swiatkowski 		read_shadow_ram = false;
1778*0545cc86SMichal Swiatkowski 		nvm_size = hw->flash.flash_size;
1779*0545cc86SMichal Swiatkowski 	} else if (ops == &ice_sram_region_ops) {
1780*0545cc86SMichal Swiatkowski 		read_shadow_ram = true;
1781*0545cc86SMichal Swiatkowski 		nvm_size = hw->flash.sr_words * 2u;
1782*0545cc86SMichal Swiatkowski 	} else {
1783*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function");
1784*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
1785*0545cc86SMichal Swiatkowski 	}
1786*0545cc86SMichal Swiatkowski 
1787*0545cc86SMichal Swiatkowski 	nvm_data = vzalloc(nvm_size);
1788*0545cc86SMichal Swiatkowski 	if (!nvm_data)
1789*0545cc86SMichal Swiatkowski 		return -ENOMEM;
1790*0545cc86SMichal Swiatkowski 
1791*0545cc86SMichal Swiatkowski 	num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE);
1792*0545cc86SMichal Swiatkowski 	tmp = nvm_data;
1793*0545cc86SMichal Swiatkowski 	left = nvm_size;
1794*0545cc86SMichal Swiatkowski 
1795*0545cc86SMichal Swiatkowski 	/* Some systems take longer to read the NVM than others which causes the
1796*0545cc86SMichal Swiatkowski 	 * FW to reclaim the NVM lock before the entire NVM has been read. Fix
1797*0545cc86SMichal Swiatkowski 	 * this by breaking the reads of the NVM into smaller chunks that will
1798*0545cc86SMichal Swiatkowski 	 * probably not take as long. This has some overhead since we are
1799*0545cc86SMichal Swiatkowski 	 * increasing the number of AQ commands, but it should always work
1800*0545cc86SMichal Swiatkowski 	 */
1801*0545cc86SMichal Swiatkowski 	for (i = 0; i < num_blks; i++) {
1802*0545cc86SMichal Swiatkowski 		u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left);
1803*0545cc86SMichal Swiatkowski 
1804*0545cc86SMichal Swiatkowski 		status = ice_acquire_nvm(hw, ICE_RES_READ);
1805*0545cc86SMichal Swiatkowski 		if (status) {
1806*0545cc86SMichal Swiatkowski 			dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
1807*0545cc86SMichal Swiatkowski 				status, hw->adminq.sq_last_status);
1808*0545cc86SMichal Swiatkowski 			NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
1809*0545cc86SMichal Swiatkowski 			vfree(nvm_data);
1810*0545cc86SMichal Swiatkowski 			return -EIO;
1811*0545cc86SMichal Swiatkowski 		}
1812*0545cc86SMichal Swiatkowski 
1813*0545cc86SMichal Swiatkowski 		status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE,
1814*0545cc86SMichal Swiatkowski 					   &read_sz, tmp, read_shadow_ram);
1815*0545cc86SMichal Swiatkowski 		if (status) {
1816*0545cc86SMichal Swiatkowski 			dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
1817*0545cc86SMichal Swiatkowski 				read_sz, status, hw->adminq.sq_last_status);
1818*0545cc86SMichal Swiatkowski 			NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
1819*0545cc86SMichal Swiatkowski 			ice_release_nvm(hw);
1820*0545cc86SMichal Swiatkowski 			vfree(nvm_data);
1821*0545cc86SMichal Swiatkowski 			return -EIO;
1822*0545cc86SMichal Swiatkowski 		}
1823*0545cc86SMichal Swiatkowski 		ice_release_nvm(hw);
1824*0545cc86SMichal Swiatkowski 
1825*0545cc86SMichal Swiatkowski 		tmp += read_sz;
1826*0545cc86SMichal Swiatkowski 		left -= read_sz;
1827*0545cc86SMichal Swiatkowski 	}
1828*0545cc86SMichal Swiatkowski 
1829*0545cc86SMichal Swiatkowski 	*data = nvm_data;
1830*0545cc86SMichal Swiatkowski 
1831*0545cc86SMichal Swiatkowski 	return 0;
1832*0545cc86SMichal Swiatkowski }
1833*0545cc86SMichal Swiatkowski 
1834*0545cc86SMichal Swiatkowski /**
1835*0545cc86SMichal Swiatkowski  * ice_devlink_nvm_read - Read a portion of NVM flash contents
1836*0545cc86SMichal Swiatkowski  * @devlink: the devlink instance
1837*0545cc86SMichal Swiatkowski  * @ops: the devlink region to snapshot
1838*0545cc86SMichal Swiatkowski  * @extack: extended ACK response structure
1839*0545cc86SMichal Swiatkowski  * @offset: the offset to start at
1840*0545cc86SMichal Swiatkowski  * @size: the amount to read
1841*0545cc86SMichal Swiatkowski  * @data: the data buffer to read into
1842*0545cc86SMichal Swiatkowski  *
1843*0545cc86SMichal Swiatkowski  * This function is called in response to DEVLINK_CMD_REGION_READ to directly
1844*0545cc86SMichal Swiatkowski  * read a section of the NVM contents.
1845*0545cc86SMichal Swiatkowski  *
1846*0545cc86SMichal Swiatkowski  * It reads from either the nvm-flash or shadow-ram region contents.
1847*0545cc86SMichal Swiatkowski  *
1848*0545cc86SMichal Swiatkowski  * @returns zero on success, and updates the data pointer. Returns a non-zero
1849*0545cc86SMichal Swiatkowski  * error code on failure.
1850*0545cc86SMichal Swiatkowski  */
1851*0545cc86SMichal Swiatkowski static int ice_devlink_nvm_read(struct devlink *devlink,
1852*0545cc86SMichal Swiatkowski 				const struct devlink_region_ops *ops,
1853*0545cc86SMichal Swiatkowski 				struct netlink_ext_ack *extack,
1854*0545cc86SMichal Swiatkowski 				u64 offset, u32 size, u8 *data)
1855*0545cc86SMichal Swiatkowski {
1856*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1857*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
1858*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
1859*0545cc86SMichal Swiatkowski 	bool read_shadow_ram;
1860*0545cc86SMichal Swiatkowski 	u64 nvm_size;
1861*0545cc86SMichal Swiatkowski 	int status;
1862*0545cc86SMichal Swiatkowski 
1863*0545cc86SMichal Swiatkowski 	if (ops == &ice_nvm_region_ops) {
1864*0545cc86SMichal Swiatkowski 		read_shadow_ram = false;
1865*0545cc86SMichal Swiatkowski 		nvm_size = hw->flash.flash_size;
1866*0545cc86SMichal Swiatkowski 	} else if (ops == &ice_sram_region_ops) {
1867*0545cc86SMichal Swiatkowski 		read_shadow_ram = true;
1868*0545cc86SMichal Swiatkowski 		nvm_size = hw->flash.sr_words * 2u;
1869*0545cc86SMichal Swiatkowski 	} else {
1870*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function");
1871*0545cc86SMichal Swiatkowski 		return -EOPNOTSUPP;
1872*0545cc86SMichal Swiatkowski 	}
1873*0545cc86SMichal Swiatkowski 
1874*0545cc86SMichal Swiatkowski 	if (offset + size >= nvm_size) {
1875*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size");
1876*0545cc86SMichal Swiatkowski 		return -ERANGE;
1877*0545cc86SMichal Swiatkowski 	}
1878*0545cc86SMichal Swiatkowski 
1879*0545cc86SMichal Swiatkowski 	status = ice_acquire_nvm(hw, ICE_RES_READ);
1880*0545cc86SMichal Swiatkowski 	if (status) {
1881*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
1882*0545cc86SMichal Swiatkowski 			status, hw->adminq.sq_last_status);
1883*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
1884*0545cc86SMichal Swiatkowski 		return -EIO;
1885*0545cc86SMichal Swiatkowski 	}
1886*0545cc86SMichal Swiatkowski 
1887*0545cc86SMichal Swiatkowski 	status = ice_read_flat_nvm(hw, (u32)offset, &size, data,
1888*0545cc86SMichal Swiatkowski 				   read_shadow_ram);
1889*0545cc86SMichal Swiatkowski 	if (status) {
1890*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
1891*0545cc86SMichal Swiatkowski 			size, status, hw->adminq.sq_last_status);
1892*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
1893*0545cc86SMichal Swiatkowski 		ice_release_nvm(hw);
1894*0545cc86SMichal Swiatkowski 		return -EIO;
1895*0545cc86SMichal Swiatkowski 	}
1896*0545cc86SMichal Swiatkowski 	ice_release_nvm(hw);
1897*0545cc86SMichal Swiatkowski 
1898*0545cc86SMichal Swiatkowski 	return 0;
1899*0545cc86SMichal Swiatkowski }
1900*0545cc86SMichal Swiatkowski 
1901*0545cc86SMichal Swiatkowski /**
1902*0545cc86SMichal Swiatkowski  * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities
1903*0545cc86SMichal Swiatkowski  * @devlink: the devlink instance
1904*0545cc86SMichal Swiatkowski  * @ops: the devlink region being snapshotted
1905*0545cc86SMichal Swiatkowski  * @extack: extended ACK response structure
1906*0545cc86SMichal Swiatkowski  * @data: on exit points to snapshot data buffer
1907*0545cc86SMichal Swiatkowski  *
1908*0545cc86SMichal Swiatkowski  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
1909*0545cc86SMichal Swiatkowski  * the device-caps devlink region. It captures a snapshot of the device
1910*0545cc86SMichal Swiatkowski  * capabilities reported by firmware.
1911*0545cc86SMichal Swiatkowski  *
1912*0545cc86SMichal Swiatkowski  * @returns zero on success, and updates the data pointer. Returns a non-zero
1913*0545cc86SMichal Swiatkowski  * error code on failure.
1914*0545cc86SMichal Swiatkowski  */
1915*0545cc86SMichal Swiatkowski static int
1916*0545cc86SMichal Swiatkowski ice_devlink_devcaps_snapshot(struct devlink *devlink,
1917*0545cc86SMichal Swiatkowski 			     const struct devlink_region_ops *ops,
1918*0545cc86SMichal Swiatkowski 			     struct netlink_ext_ack *extack, u8 **data)
1919*0545cc86SMichal Swiatkowski {
1920*0545cc86SMichal Swiatkowski 	struct ice_pf *pf = devlink_priv(devlink);
1921*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
1922*0545cc86SMichal Swiatkowski 	struct ice_hw *hw = &pf->hw;
1923*0545cc86SMichal Swiatkowski 	void *devcaps;
1924*0545cc86SMichal Swiatkowski 	int status;
1925*0545cc86SMichal Swiatkowski 
1926*0545cc86SMichal Swiatkowski 	devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN);
1927*0545cc86SMichal Swiatkowski 	if (!devcaps)
1928*0545cc86SMichal Swiatkowski 		return -ENOMEM;
1929*0545cc86SMichal Swiatkowski 
1930*0545cc86SMichal Swiatkowski 	status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL,
1931*0545cc86SMichal Swiatkowski 				  ice_aqc_opc_list_dev_caps, NULL);
1932*0545cc86SMichal Swiatkowski 	if (status) {
1933*0545cc86SMichal Swiatkowski 		dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n",
1934*0545cc86SMichal Swiatkowski 			status, hw->adminq.sq_last_status);
1935*0545cc86SMichal Swiatkowski 		NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities");
1936*0545cc86SMichal Swiatkowski 		vfree(devcaps);
1937*0545cc86SMichal Swiatkowski 		return status;
1938*0545cc86SMichal Swiatkowski 	}
1939*0545cc86SMichal Swiatkowski 
1940*0545cc86SMichal Swiatkowski 	*data = (u8 *)devcaps;
1941*0545cc86SMichal Swiatkowski 
1942*0545cc86SMichal Swiatkowski 	return 0;
1943*0545cc86SMichal Swiatkowski }
1944*0545cc86SMichal Swiatkowski 
1945*0545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops = {
1946*0545cc86SMichal Swiatkowski 	.name = "nvm-flash",
1947*0545cc86SMichal Swiatkowski 	.destructor = vfree,
1948*0545cc86SMichal Swiatkowski 	.snapshot = ice_devlink_nvm_snapshot,
1949*0545cc86SMichal Swiatkowski 	.read = ice_devlink_nvm_read,
1950*0545cc86SMichal Swiatkowski };
1951*0545cc86SMichal Swiatkowski 
1952*0545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops = {
1953*0545cc86SMichal Swiatkowski 	.name = "shadow-ram",
1954*0545cc86SMichal Swiatkowski 	.destructor = vfree,
1955*0545cc86SMichal Swiatkowski 	.snapshot = ice_devlink_nvm_snapshot,
1956*0545cc86SMichal Swiatkowski 	.read = ice_devlink_nvm_read,
1957*0545cc86SMichal Swiatkowski };
1958*0545cc86SMichal Swiatkowski 
1959*0545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_devcaps_region_ops = {
1960*0545cc86SMichal Swiatkowski 	.name = "device-caps",
1961*0545cc86SMichal Swiatkowski 	.destructor = vfree,
1962*0545cc86SMichal Swiatkowski 	.snapshot = ice_devlink_devcaps_snapshot,
1963*0545cc86SMichal Swiatkowski };
1964*0545cc86SMichal Swiatkowski 
1965*0545cc86SMichal Swiatkowski /**
1966*0545cc86SMichal Swiatkowski  * ice_devlink_init_regions - Initialize devlink regions
1967*0545cc86SMichal Swiatkowski  * @pf: the PF device structure
1968*0545cc86SMichal Swiatkowski  *
1969*0545cc86SMichal Swiatkowski  * Create devlink regions used to enable access to dump the contents of the
1970*0545cc86SMichal Swiatkowski  * flash memory on the device.
1971*0545cc86SMichal Swiatkowski  */
1972*0545cc86SMichal Swiatkowski void ice_devlink_init_regions(struct ice_pf *pf)
1973*0545cc86SMichal Swiatkowski {
1974*0545cc86SMichal Swiatkowski 	struct devlink *devlink = priv_to_devlink(pf);
1975*0545cc86SMichal Swiatkowski 	struct device *dev = ice_pf_to_dev(pf);
1976*0545cc86SMichal Swiatkowski 	u64 nvm_size, sram_size;
1977*0545cc86SMichal Swiatkowski 
1978*0545cc86SMichal Swiatkowski 	nvm_size = pf->hw.flash.flash_size;
1979*0545cc86SMichal Swiatkowski 	pf->nvm_region = devlink_region_create(devlink, &ice_nvm_region_ops, 1,
1980*0545cc86SMichal Swiatkowski 					       nvm_size);
1981*0545cc86SMichal Swiatkowski 	if (IS_ERR(pf->nvm_region)) {
1982*0545cc86SMichal Swiatkowski 		dev_err(dev, "failed to create NVM devlink region, err %ld\n",
1983*0545cc86SMichal Swiatkowski 			PTR_ERR(pf->nvm_region));
1984*0545cc86SMichal Swiatkowski 		pf->nvm_region = NULL;
1985*0545cc86SMichal Swiatkowski 	}
1986*0545cc86SMichal Swiatkowski 
1987*0545cc86SMichal Swiatkowski 	sram_size = pf->hw.flash.sr_words * 2u;
1988*0545cc86SMichal Swiatkowski 	pf->sram_region = devlink_region_create(devlink, &ice_sram_region_ops,
1989*0545cc86SMichal Swiatkowski 						1, sram_size);
1990*0545cc86SMichal Swiatkowski 	if (IS_ERR(pf->sram_region)) {
1991*0545cc86SMichal Swiatkowski 		dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n",
1992*0545cc86SMichal Swiatkowski 			PTR_ERR(pf->sram_region));
1993*0545cc86SMichal Swiatkowski 		pf->sram_region = NULL;
1994*0545cc86SMichal Swiatkowski 	}
1995*0545cc86SMichal Swiatkowski 
1996*0545cc86SMichal Swiatkowski 	pf->devcaps_region = devlink_region_create(devlink,
1997*0545cc86SMichal Swiatkowski 						   &ice_devcaps_region_ops, 10,
1998*0545cc86SMichal Swiatkowski 						   ICE_AQ_MAX_BUF_LEN);
1999*0545cc86SMichal Swiatkowski 	if (IS_ERR(pf->devcaps_region)) {
2000*0545cc86SMichal Swiatkowski 		dev_err(dev, "failed to create device-caps devlink region, err %ld\n",
2001*0545cc86SMichal Swiatkowski 			PTR_ERR(pf->devcaps_region));
2002*0545cc86SMichal Swiatkowski 		pf->devcaps_region = NULL;
2003*0545cc86SMichal Swiatkowski 	}
2004*0545cc86SMichal Swiatkowski }
2005*0545cc86SMichal Swiatkowski 
2006*0545cc86SMichal Swiatkowski /**
2007*0545cc86SMichal Swiatkowski  * ice_devlink_destroy_regions - Destroy devlink regions
2008*0545cc86SMichal Swiatkowski  * @pf: the PF device structure
2009*0545cc86SMichal Swiatkowski  *
2010*0545cc86SMichal Swiatkowski  * Remove previously created regions for this PF.
2011*0545cc86SMichal Swiatkowski  */
2012*0545cc86SMichal Swiatkowski void ice_devlink_destroy_regions(struct ice_pf *pf)
2013*0545cc86SMichal Swiatkowski {
2014*0545cc86SMichal Swiatkowski 	if (pf->nvm_region)
2015*0545cc86SMichal Swiatkowski 		devlink_region_destroy(pf->nvm_region);
2016*0545cc86SMichal Swiatkowski 
2017*0545cc86SMichal Swiatkowski 	if (pf->sram_region)
2018*0545cc86SMichal Swiatkowski 		devlink_region_destroy(pf->sram_region);
2019*0545cc86SMichal Swiatkowski 
2020*0545cc86SMichal Swiatkowski 	if (pf->devcaps_region)
2021*0545cc86SMichal Swiatkowski 		devlink_region_destroy(pf->devcaps_region);
2022*0545cc86SMichal Swiatkowski }
2023