File Index
Files and directories
Sign in
FILE

devlink.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2025, Intel Corporation. */
  3
  4#include "ixgbe.h"
  5#include "devlink.h"
  6#include "ixgbe_fw_update.h"
  7
  8struct ixgbe_info_ctx {
  9	char buf[128];
 10	struct ixgbe_orom_info pending_orom;
 11	struct ixgbe_nvm_info pending_nvm;
 12	struct ixgbe_netlist_info pending_netlist;
 13	struct ixgbe_hw_dev_caps dev_caps;
 14};
 15
 16enum ixgbe_devlink_version_type {
 17	IXGBE_DL_VERSION_RUNNING,
 18	IXGBE_DL_VERSION_STORED
 19};
 20
 21static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter,
 22			       struct ixgbe_info_ctx *ctx)
 23{
 24	u8 dsn[8];
 25
 26	/* Copy the DSN into an array in Big Endian format */
 27	put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn);
 28
 29	snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
 30}
 31
 32static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter,
 33				struct ixgbe_info_ctx *ctx,
 34				enum ixgbe_devlink_version_type type)
 35{
 36	struct ixgbe_hw *hw = &adapter->hw;
 37	struct ixgbe_nvm_version nvm_ver;
 38
 39	ctx->buf[0] = '\0';
 40
 41	if (hw->mac.type == ixgbe_mac_e610) {
 42		struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
 43
 44		if (type == IXGBE_DL_VERSION_STORED &&
 45		    ctx->dev_caps.common_cap.nvm_update_pending_orom)
 46			orom = &ctx->pending_orom;
 47
 48		snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
 49			 orom->major, orom->build, orom->patch);
 50		return;
 51	}
 52
 53	ixgbe_get_oem_prod_version(hw, &nvm_ver);
 54	if (nvm_ver.oem_valid) {
 55		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x",
 56			 nvm_ver.oem_major, nvm_ver.oem_minor,
 57			 nvm_ver.oem_release);
 58
 59		return;
 60	}
 61
 62	ixgbe_get_orom_version(hw, &nvm_ver);
 63	if (nvm_ver.or_valid)
 64		snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d",
 65			 nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch);
 66}
 67
 68static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
 69			       struct ixgbe_info_ctx *ctx,
 70			       enum ixgbe_devlink_version_type type)
 71{
 72	struct ixgbe_hw *hw = &adapter->hw;
 73	struct ixgbe_nvm_version nvm_ver;
 74
 75	if (hw->mac.type == ixgbe_mac_e610) {
 76		u32 eetrack = hw->flash.nvm.eetrack;
 77
 78		if (type == IXGBE_DL_VERSION_STORED &&
 79		    ctx->dev_caps.common_cap.nvm_update_pending_nvm)
 80			eetrack = ctx->pending_nvm.eetrack;
 81
 82		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", eetrack);
 83		return;
 84	}
 85
 86	ixgbe_get_oem_prod_version(hw, &nvm_ver);
 87
 88	/* No ETRACK version for OEM */
 89	if (nvm_ver.oem_valid) {
 90		ctx->buf[0] = '\0';
 91		return;
 92	}
 93
 94	ixgbe_get_etk_id(hw, &nvm_ver);
 95	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
 96}
 97
 98static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter,
 99			      struct ixgbe_info_ctx *ctx)
100{
101	struct ixgbe_hw *hw = &adapter->hw;
102
103	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
104		 hw->api_maj_ver, hw->api_min_ver, hw->api_patch);
105}
106
107static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter,
108				struct ixgbe_info_ctx *ctx)
109{
110	struct ixgbe_hw *hw = &adapter->hw;
111
112	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
113}
114
115static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter,
116			       struct ixgbe_info_ctx *ctx,
117			       enum ixgbe_devlink_version_type type)
118{
119	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
120
121	if (type == IXGBE_DL_VERSION_STORED &&
122	    ctx->dev_caps.common_cap.nvm_update_pending_nvm)
123		nvm = &ctx->pending_nvm;
124
125	snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
126}
127
128static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
129				 struct ixgbe_info_ctx *ctx,
130				 enum ixgbe_devlink_version_type type)
131{
132	struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
133
134	if (type == IXGBE_DL_VERSION_STORED &&
135	    ctx->dev_caps.common_cap.nvm_update_pending_orom)
136		orom = &ctx->pending_orom;
137
138	snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
139}
140
141static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
142			       struct ixgbe_info_ctx *ctx,
143			       enum ixgbe_devlink_version_type type)
144{
145	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
146
147	if (type == IXGBE_DL_VERSION_STORED &&
148	    ctx->dev_caps.common_cap.nvm_update_pending_nvm)
149		nvm = &ctx->pending_nvm;
150
151	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
152}
153
154static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
155				   struct ixgbe_info_ctx *ctx,
156				   enum ixgbe_devlink_version_type type)
157{
158	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
159
160	if (type == IXGBE_DL_VERSION_STORED &&
161	    ctx->dev_caps.common_cap.nvm_update_pending_netlist)
162		netlist = &ctx->pending_netlist;
163
164	/* The netlist version fields are BCD formatted */
165	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
166		 netlist->major, netlist->minor,
167		 netlist->type >> 16, netlist->type & 0xFFFF,
168		 netlist->rev, netlist->cust_ver);
169}
170
171static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
172				     struct ixgbe_info_ctx *ctx,
173				     enum ixgbe_devlink_version_type type)
174{
175	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
176
177	if (type == IXGBE_DL_VERSION_STORED &&
178	    ctx->dev_caps.common_cap.nvm_update_pending_netlist)
179		netlist = &ctx->pending_netlist;
180
181	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
182}
183
184static int ixgbe_set_ctx_dev_caps(struct ixgbe_hw *hw,
185				  struct ixgbe_info_ctx *ctx,
186				  struct netlink_ext_ack *extack)
187{
188	bool *pending_orom, *pending_nvm, *pending_netlist;
189	int err;
190
191	err = ixgbe_discover_dev_caps(hw, &ctx->dev_caps);
192	if (err) {
193		NL_SET_ERR_MSG_MOD(extack,
194				   "Unable to discover device capabilities");
195		return err;
196	}
197
198	pending_orom = &ctx->dev_caps.common_cap.nvm_update_pending_orom;
199	pending_nvm = &ctx->dev_caps.common_cap.nvm_update_pending_nvm;
200	pending_netlist = &ctx->dev_caps.common_cap.nvm_update_pending_netlist;
201
202	if (*pending_orom) {
203		err = ixgbe_get_inactive_orom_ver(hw, &ctx->pending_orom);
204		if (err)
205			*pending_orom = false;
206	}
207
208	if (*pending_nvm) {
209		err = ixgbe_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
210		if (err)
211			*pending_nvm = false;
212	}
213
214	if (*pending_netlist) {
215		err = ixgbe_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
216		if (err)
217			*pending_netlist = false;
218	}
219
220	return 0;
221}
222
223static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter,
224				       struct devlink_info_req *req,
225				       struct ixgbe_info_ctx *ctx)
226{
227	int err;
228
229	ixgbe_info_fw_api(adapter, ctx);
230	err = devlink_info_version_running_put(req,
231					       DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
232					       ctx->buf);
233	if (err)
234		return err;
235
236	ixgbe_info_fw_build(adapter, ctx);
237	err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf);
238	if (err)
239		return err;
240
241	ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
242	err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf);
243	if (err)
244		return err;
245
246	ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
247	err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf);
248	if (err)
249		return err;
250
251	ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
252	err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf);
253	if (err)
254		return err;
255
256	ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
257	err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf);
258	if (err)
259		return err;
260
261	ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
262	return devlink_info_version_running_put(req, "fw.netlist.build",
263						ctx->buf);
264}
265
266static int
267ixgbe_devlink_pending_info_get_e610(struct ixgbe_adapter *adapter,
268				    struct devlink_info_req *req,
269				    struct ixgbe_info_ctx *ctx)
270{
271	int err;
272
273	ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
274	err = devlink_info_version_stored_put(req,
275					      DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
276					      ctx->buf);
277	if (err)
278		return err;
279
280	ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_STORED);
281	err = devlink_info_version_stored_put(req,
282					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
283					      ctx->buf);
284	if (err)
285		return err;
286
287	ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
288	err = devlink_info_version_stored_put(req, "fw.mgmt.srev", ctx->buf);
289	if (err)
290		return err;
291
292	ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
293	err = devlink_info_version_stored_put(req, "fw.undi.srev", ctx->buf);
294	if (err)
295		return err;
296
297	ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
298	err = devlink_info_version_stored_put(req, "fw.psid.api", ctx->buf);
299	if (err)
300		return err;
301
302	ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
303	err = devlink_info_version_stored_put(req, "fw.netlist", ctx->buf);
304	if (err)
305		return err;
306
307	ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_STORED);
308	return devlink_info_version_stored_put(req, "fw.netlist.build",
309					       ctx->buf);
310}
311
312static int ixgbe_devlink_info_get(struct devlink *devlink,
313				  struct devlink_info_req *req,
314				  struct netlink_ext_ack *extack)
315{
316	struct ixgbe_adapter *adapter = devlink_priv(devlink);
317	struct ixgbe_hw *hw = &adapter->hw;
318	struct ixgbe_info_ctx *ctx;
319	int err;
320
321	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
322	if (!ctx)
323		return -ENOMEM;
324
325	if (hw->mac.type == ixgbe_mac_e610)
326		ixgbe_refresh_fw_version(adapter);
327
328	ixgbe_info_get_dsn(adapter, ctx);
329	err = devlink_info_serial_number_put(req, ctx->buf);
330	if (err)
331		goto free_ctx;
332
333	err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf));
334	if (err)
335		goto free_ctx;
336
337	err = devlink_info_version_fixed_put(req,
338					     DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
339					     ctx->buf);
340	if (err)
341		goto free_ctx;
342
343	ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
344	err = devlink_info_version_running_put(req,
345					       DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
346					       ctx->buf);
347	if (err)
348		goto free_ctx;
349
350	ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
351	err = devlink_info_version_running_put(req,
352					       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
353					       ctx->buf);
354	if (err || hw->mac.type != ixgbe_mac_e610)
355		goto free_ctx;
356
357	err = ixgbe_set_ctx_dev_caps(hw, ctx, extack);
358	if (err)
359		goto free_ctx;
360
361	err = ixgbe_devlink_info_get_e610(adapter, req, ctx);
362	if (err)
363		goto free_ctx;
364
365	err = ixgbe_devlink_pending_info_get_e610(adapter, req, ctx);
366free_ctx:
367	kfree(ctx);
368	return err;
369}
370
371/**
372 * ixgbe_devlink_reload_empr_start - Start EMP reset to activate new firmware
373 * @devlink: pointer to the devlink instance to reload
374 * @netns_change: if true, the network namespace is changing
375 * @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE
376 * @limit: limits on what reload should do, such as not resetting
377 * @extack: netlink extended ACK structure
378 *
379 * Allow user to activate new Embedded Management Processor firmware by
380 * issuing device specific EMP reset. Called in response to
381 * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE.
382 *
383 * Note that teardown and rebuild of the driver state happens automatically as
384 * part of an interrupt and watchdog task. This is because all physical
385 * functions on the device must be able to reset when an EMP reset occurs from
386 * any source.
387 *
388 * Return: the exit code of the operation.
389 */
390static int ixgbe_devlink_reload_empr_start(struct devlink *devlink,
391					   bool netns_change,
392					   enum devlink_reload_action action,
393					   enum devlink_reload_limit limit,
394					   struct netlink_ext_ack *extack)
395{
396	struct ixgbe_adapter *adapter = devlink_priv(devlink);
397	struct ixgbe_hw *hw = &adapter->hw;
398	u8 pending;
399	int err;
400
401	if (hw->mac.type != ixgbe_mac_e610)
402		return -EOPNOTSUPP;
403
404	err = ixgbe_get_pending_updates(adapter, &pending, extack);
405	if (err)
406		return err;
407
408	/* Pending is a bitmask of which flash banks have a pending update,
409	 * including the main NVM bank, the Option ROM bank, and the netlist
410	 * bank. If any of these bits are set, then there is a pending update
411	 * waiting to be activated.
412	 */
413	if (!pending) {
414		NL_SET_ERR_MSG_MOD(extack, "No pending firmware update");
415		return -ECANCELED;
416	}
417
418	if (adapter->fw_emp_reset_disabled) {
419		NL_SET_ERR_MSG_MOD(extack,
420				   "EMP reset is not available. To activate firmware, a reboot or power cycle is needed");
421		return -ECANCELED;
422	}
423
424	err = ixgbe_aci_nvm_update_empr(hw);
425	if (err)
426		NL_SET_ERR_MSG_MOD(extack,
427				   "Failed to trigger EMP device reset to reload firmware");
428
429	return err;
430}
431
432/*Wait for 10 sec with 0.5 sec tic. EMPR takes no less than half of a sec */
433#define IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC	20
434
435/**
436 * ixgbe_devlink_reload_empr_finish - finishes EMP reset
437 * @devlink: pointer to the devlink instance
438 * @action: the action to perform.
439 * @limit: limits on what reload should do
440 * @actions_performed: actions performed
441 * @extack: netlink extended ACK structure
442 *
443 * Wait for new NVM to be loaded during EMP reset.
444 *
445 * Return: -ETIME when timer is exceeded, 0 on success.
446 */
447static int ixgbe_devlink_reload_empr_finish(struct devlink *devlink,
448					    enum devlink_reload_action action,
449					    enum devlink_reload_limit limit,
450					    u32 *actions_performed,
451					    struct netlink_ext_ack *extack)
452{
453	struct ixgbe_adapter *adapter = devlink_priv(devlink);
454	struct ixgbe_hw *hw = &adapter->hw;
455	int i = 0;
456	u32 fwsm;
457
458	do {
459		/* Just right away after triggering EMP reset the FWSM register
460		 * may be not cleared yet, so begin the loop with the delay
461		 * in order to not check the not updated register.
462		 */
463		mdelay(500);
464
465		fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
466
467		if (i++ >= IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC)
468			return -ETIME;
469
470	} while (!(fwsm & IXGBE_FWSM_FW_VAL_BIT));
471
472	*actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
473
474	adapter->flags2 &= ~(IXGBE_FLAG2_API_MISMATCH |
475			     IXGBE_FLAG2_FW_ROLLBACK);
476
477	return ixgbe_refresh_fw_version(adapter);
478}
479
480static const struct devlink_ops ixgbe_devlink_ops = {
481	.info_get = ixgbe_devlink_info_get,
482	.supported_flash_update_params =
483		DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
484	.flash_update = ixgbe_flash_pldm_image,
485	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
486	.reload_down = ixgbe_devlink_reload_empr_start,
487	.reload_up = ixgbe_devlink_reload_empr_finish,
488};
489
490/**
491 * ixgbe_allocate_devlink - Allocate devlink instance
492 * @dev: device to allocate devlink for
493 *
494 * Allocate a devlink instance for this physical function.
495 *
496 * Return: pointer to the device adapter structure on success,
497 * ERR_PTR(-ENOMEM) when allocation failed.
498 */
499struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev)
500{
501	struct ixgbe_adapter *adapter;
502	struct devlink *devlink;
503
504	devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev);
505	if (!devlink)
506		return ERR_PTR(-ENOMEM);
507
508	adapter = devlink_priv(devlink);
509	adapter->devlink = devlink;
510
511	return adapter;
512}
513
514/**
515 * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN
516 * @adapter: pointer to the device adapter structure
517 * @ppid: struct with switch id information
518 */
519static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter,
520					struct netdev_phys_item_id *ppid)
521{
522	u64 id = pci_get_dsn(adapter->pdev);
523
524	ppid->id_len = sizeof(id);
525	put_unaligned_be64(id, &ppid->id);
526}
527
528/**
529 * ixgbe_devlink_register_port - Register devlink port
530 * @adapter: pointer to the device adapter structure
531 *
532 * Create and register a devlink_port for this physical function.
533 *
534 * Return: 0 on success, error code on failure.
535 */
536int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter)
537{
538	struct devlink_port *devlink_port = &adapter->devlink_port;
539	struct devlink *devlink = adapter->devlink;
540	struct device *dev = &adapter->pdev->dev;
541	struct devlink_port_attrs attrs = {};
542	int err;
543
544	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
545	attrs.phys.port_number = adapter->hw.bus.func;
546	attrs.no_phys_port_name = 1;
547	ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id);
548
549	devlink_port_attrs_set(devlink_port, &attrs);
550
551	err = devl_port_register(devlink, devlink_port, 0);
552	if (err) {
553		dev_err(dev,
554			"devlink port registration failed, err %d\n", err);
555	}
556
557	return err;
558}
~/ Read-only file preview.