Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
ixgbe: Add basic devlink support

Jedrzej Jagielski says:

Create devlink specific directory for more convenient future feature
development.

Flashing and reloading are supported only by E610 devices.

Introduce basic FW/NVM validation since devlink reload introduces
possibility of runtime NVM update. Check FW API version, FW recovery
mode and FW rollback mode. Introduce minimal recovery probe to let
user to reload the faulty FW when recovery mode is detected.

* '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  ixgbe: add support for FW rollback mode
  ixgbe: add E610 implementation of FW recovery mode
  ixgbe: add FW API version check
  ixgbe: add support for devlink reload
  ixgbe: add device flash update via devlink
  ixgbe: extend .info_get() with stored versions
  ixgbe: add E610 functions getting PBA and FW ver info
  ixgbe: add .info_get extension specific for E610 devices
  ixgbe: read the netlist version information
  ixgbe: read the OROM version information
  ixgbe: add E610 functions for acquiring flash data
  ixgbe: add handler for devlink .info_get()
  ixgbe: add initial devlink support
  ixgbe: wrap netdev_priv() usage
  devlink: add value check to devlink_info_version_put()
====================

Link: https://patch.msgid.link/20250415221301.1633933-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2025-04-16 19:05:20 -07:00
27 changed files with 3249 additions and 142 deletions

View File

@@ -86,6 +86,10 @@ In case software/firmware components are loaded from the disk (e.g.
``/lib/firmware``) only the running version should be reported via
the kernel API.
Please note that any security versions reported via devlink are purely
informational. Devlink does not use a secure channel to communicate with
the device.
Generic Versions
================

View File

@@ -84,6 +84,7 @@ parameters, info versions, and other features it supports.
i40e
ionic
ice
ixgbe
mlx4
mlx5
mlxsw

View File

@@ -0,0 +1,122 @@
.. SPDX-License-Identifier: GPL-2.0
=====================
ixgbe devlink support
=====================
This document describes the devlink features implemented by the ``ixgbe``
device driver.
Info versions
=============
Any of the versions dealing with the security presented by ``devlink-info``
is purely informational. Devlink does not use a secure channel to communicate
with the device.
The ``ixgbe`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 5 5 5 90
* - Name
- Type
- Example
- Description
* - ``board.id``
- fixed
- H49289-000
- The Product Board Assembly (PBA) identifier of the board.
* - ``fw.undi``
- running
- 1.1937.0
- Version of the Option ROM containing the UEFI driver. The version is
reported in ``major.minor.patch`` format. The major version is
incremented whenever a major breaking change occurs, or when the
minor version would overflow. The minor version is incremented for
non-breaking changes and reset to 1 when the major version is
incremented. The patch version is normally 0 but is incremented when
a fix is delivered as a patch against an older base Option ROM.
* - ``fw.undi.srev``
- running
- 4
- Number indicating the security revision of the Option ROM.
* - ``fw.bundle_id``
- running
- 0x80000d0d
- Unique identifier of the firmware image file that was loaded onto
the device. Also referred to as the EETRACK identifier of the NVM.
* - ``fw.mgmt.api``
- running
- 1.5.1
- 3-digit version number (major.minor.patch) of the API exported over
the AdminQ by the management firmware. Used by the driver to
identify what commands are supported. Historical versions of the
kernel only displayed a 2-digit version number (major.minor).
* - ``fw.mgmt.build``
- running
- 0x305d955f
- Unique identifier of the source for the management firmware.
* - ``fw.mgmt.srev``
- running
- 3
- Number indicating the security revision of the firmware.
* - ``fw.psid.api``
- running
- 0.80
- Version defining the format of the flash contents.
* - ``fw.netlist``
- running
- 1.1.2000-6.7.0
- The version of the netlist module. This module defines the device's
Ethernet capabilities and default settings, and is used by the
management firmware as part of managing link and device
connectivity.
* - ``fw.netlist.build``
- running
- 0xee16ced7
- The first 4 bytes of the hash of the netlist module contents.
Flash Update
============
The ``ixgbe`` driver implements support for flash update using the
``devlink-flash`` interface. It supports updating the device flash using a
combined flash image that contains the ``fw.mgmt``, ``fw.undi``, and
``fw.netlist`` components.
.. list-table:: List of supported overwrite modes
:widths: 5 95
* - Bits
- Behavior
* - ``DEVLINK_FLASH_OVERWRITE_SETTINGS``
- Do not preserve settings stored in the flash components being
updated. This includes overwriting the port configuration that
determines the number of physical functions the device will
initialize with.
* - ``DEVLINK_FLASH_OVERWRITE_SETTINGS`` and ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS``
- Do not preserve either settings or identifiers. Overwrite everything
in the flash with the contents from the provided image, without
performing any preservation. This includes overwriting device
identifying fields such as the MAC address, Vital product Data (VPD) area,
and device serial number. It is expected that this combination be used with an
image customized for the specific device.
Reload
======
The ``ixgbe`` driver supports activating new firmware after a flash update
using ``DEVLINK_CMD_RELOAD`` with the ``DEVLINK_RELOAD_ACTION_FW_ACTIVATE``
action.
.. code:: shell
$ devlink dev reload pci/0000:01:00.0 reload action fw_activate
The new firmware is activated by issuing a device specific Embedded
Management Processor reset which requests the device to reset and reload the
EMP firmware image.
The driver does not currently support reloading the driver via
``DEVLINK_RELOAD_ACTION_DRIVER_REINIT``.

View File

@@ -147,6 +147,8 @@ config IXGBE
depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL
select MDIO
select NET_DEVLINK
select PLDMFW
select PHYLIB
help
This driver supports Intel(R) 10GbE PCI Express family of

View File

@@ -4,12 +4,13 @@
# Makefile for the Intel(R) 10GbE PCI Express ethernet driver
#
subdir-ccflags-y += -I$(src)
obj-$(CONFIG_IXGBE) += ixgbe.o
ixgbe-y := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
ixgbe_mbx.o ixgbe_x540.o ixgbe_x550.o ixgbe_lib.o ixgbe_ptp.o \
ixgbe_xsk.o ixgbe_e610.o
ixgbe_xsk.o ixgbe_e610.o devlink/devlink.o ixgbe_fw_update.o
ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \
ixgbe_dcb_82599.o ixgbe_dcb_nl.o

View File

@@ -0,0 +1,557 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2025, Intel Corporation. */
#include "ixgbe.h"
#include "devlink.h"
#include "ixgbe_fw_update.h"
struct ixgbe_info_ctx {
char buf[128];
struct ixgbe_orom_info pending_orom;
struct ixgbe_nvm_info pending_nvm;
struct ixgbe_netlist_info pending_netlist;
struct ixgbe_hw_dev_caps dev_caps;
};
enum ixgbe_devlink_version_type {
IXGBE_DL_VERSION_RUNNING,
IXGBE_DL_VERSION_STORED
};
static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
u8 dsn[8];
/* Copy the DSN into an array in Big Endian format */
put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn);
snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
}
static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx,
enum ixgbe_devlink_version_type type)
{
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_nvm_version nvm_ver;
ctx->buf[0] = '\0';
if (hw->mac.type == ixgbe_mac_e610) {
struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
if (type == IXGBE_DL_VERSION_STORED &&
ctx->dev_caps.common_cap.nvm_update_pending_orom)
orom = &ctx->pending_orom;
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
orom->major, orom->build, orom->patch);
return;
}
ixgbe_get_oem_prod_version(hw, &nvm_ver);
if (nvm_ver.oem_valid) {
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x",
nvm_ver.oem_major, nvm_ver.oem_minor,
nvm_ver.oem_release);
return;
}
ixgbe_get_orom_version(hw, &nvm_ver);
if (nvm_ver.or_valid)
snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d",
nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch);
}
static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx,
enum ixgbe_devlink_version_type type)
{
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_nvm_version nvm_ver;
if (hw->mac.type == ixgbe_mac_e610) {
u32 eetrack = hw->flash.nvm.eetrack;
if (type == IXGBE_DL_VERSION_STORED &&
ctx->dev_caps.common_cap.nvm_update_pending_nvm)
eetrack = ctx->pending_nvm.eetrack;
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", eetrack);
return;
}
ixgbe_get_oem_prod_version(hw, &nvm_ver);
/* No ETRACK version for OEM */
if (nvm_ver.oem_valid) {
ctx->buf[0] = '\0';
return;
}
ixgbe_get_etk_id(hw, &nvm_ver);
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
}
static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
struct ixgbe_hw *hw = &adapter->hw;
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
hw->api_maj_ver, hw->api_min_ver, hw->api_patch);
}
static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
struct ixgbe_hw *hw = &adapter->hw;
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
}
static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx,
enum ixgbe_devlink_version_type type)
{
struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
if (type == IXGBE_DL_VERSION_STORED &&
ctx->dev_caps.common_cap.nvm_update_pending_nvm)
nvm = &ctx->pending_nvm;
snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
}
static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx,
enum ixgbe_devlink_version_type type)
{
struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
if (type == IXGBE_DL_VERSION_STORED &&
ctx->dev_caps.common_cap.nvm_update_pending_orom)
orom = &ctx->pending_orom;
snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
}
static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx,
enum ixgbe_devlink_version_type type)
{
struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
if (type == IXGBE_DL_VERSION_STORED &&
ctx->dev_caps.common_cap.nvm_update_pending_nvm)
nvm = &ctx->pending_nvm;
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
}
static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx,
enum ixgbe_devlink_version_type type)
{
struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
if (type == IXGBE_DL_VERSION_STORED &&
ctx->dev_caps.common_cap.nvm_update_pending_netlist)
netlist = &ctx->pending_netlist;
/* The netlist version fields are BCD formatted */
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
netlist->major, netlist->minor,
netlist->type >> 16, netlist->type & 0xFFFF,
netlist->rev, netlist->cust_ver);
}
static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx,
enum ixgbe_devlink_version_type type)
{
struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
if (type == IXGBE_DL_VERSION_STORED &&
ctx->dev_caps.common_cap.nvm_update_pending_netlist)
netlist = &ctx->pending_netlist;
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
}
static int ixgbe_set_ctx_dev_caps(struct ixgbe_hw *hw,
struct ixgbe_info_ctx *ctx,
struct netlink_ext_ack *extack)
{
bool *pending_orom, *pending_nvm, *pending_netlist;
int err;
err = ixgbe_discover_dev_caps(hw, &ctx->dev_caps);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Unable to discover device capabilities");
return err;
}
pending_orom = &ctx->dev_caps.common_cap.nvm_update_pending_orom;
pending_nvm = &ctx->dev_caps.common_cap.nvm_update_pending_nvm;
pending_netlist = &ctx->dev_caps.common_cap.nvm_update_pending_netlist;
if (*pending_orom) {
err = ixgbe_get_inactive_orom_ver(hw, &ctx->pending_orom);
if (err)
*pending_orom = false;
}
if (*pending_nvm) {
err = ixgbe_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
if (err)
*pending_nvm = false;
}
if (*pending_netlist) {
err = ixgbe_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
if (err)
*pending_netlist = false;
}
return 0;
}
static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter,
struct devlink_info_req *req,
struct ixgbe_info_ctx *ctx)
{
int err;
ixgbe_info_fw_api(adapter, ctx);
err = devlink_info_version_running_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
ctx->buf);
if (err)
return err;
ixgbe_info_fw_build(adapter, ctx);
err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf);
if (err)
return err;
ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf);
if (err)
return err;
ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf);
if (err)
return err;
ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf);
if (err)
return err;
ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf);
if (err)
return err;
ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
return devlink_info_version_running_put(req, "fw.netlist.build",
ctx->buf);
}
static int
ixgbe_devlink_pending_info_get_e610(struct ixgbe_adapter *adapter,
struct devlink_info_req *req,
struct ixgbe_info_ctx *ctx)
{
int err;
ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
err = devlink_info_version_stored_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
ctx->buf);
if (err)
return err;
ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_STORED);
err = devlink_info_version_stored_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
ctx->buf);
if (err)
return err;
ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
err = devlink_info_version_stored_put(req, "fw.mgmt.srev", ctx->buf);
if (err)
return err;
ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
err = devlink_info_version_stored_put(req, "fw.undi.srev", ctx->buf);
if (err)
return err;
ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
err = devlink_info_version_stored_put(req, "fw.psid.api", ctx->buf);
if (err)
return err;
ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
err = devlink_info_version_stored_put(req, "fw.netlist", ctx->buf);
if (err)
return err;
ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_STORED);
return devlink_info_version_stored_put(req, "fw.netlist.build",
ctx->buf);
}
static int ixgbe_devlink_info_get(struct devlink *devlink,
struct devlink_info_req *req,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = devlink_priv(devlink);
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_info_ctx *ctx;
int err;
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
if (hw->mac.type == ixgbe_mac_e610)
ixgbe_refresh_fw_version(adapter);
ixgbe_info_get_dsn(adapter, ctx);
err = devlink_info_serial_number_put(req, ctx->buf);
if (err)
goto free_ctx;
err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf));
if (err)
goto free_ctx;
err = devlink_info_version_fixed_put(req,
DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
ctx->buf);
if (err)
goto free_ctx;
ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
err = devlink_info_version_running_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
ctx->buf);
if (err)
goto free_ctx;
ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
err = devlink_info_version_running_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
ctx->buf);
if (err || hw->mac.type != ixgbe_mac_e610)
goto free_ctx;
err = ixgbe_set_ctx_dev_caps(hw, ctx, extack);
if (err)
goto free_ctx;
err = ixgbe_devlink_info_get_e610(adapter, req, ctx);
if (err)
goto free_ctx;
err = ixgbe_devlink_pending_info_get_e610(adapter, req, ctx);
free_ctx:
kfree(ctx);
return err;
}
/**
* ixgbe_devlink_reload_empr_start - Start EMP reset to activate new firmware
* @devlink: pointer to the devlink instance to reload
* @netns_change: if true, the network namespace is changing
* @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE
* @limit: limits on what reload should do, such as not resetting
* @extack: netlink extended ACK structure
*
* Allow user to activate new Embedded Management Processor firmware by
* issuing device specific EMP reset. Called in response to
* a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE.
*
* Note that teardown and rebuild of the driver state happens automatically as
* part of an interrupt and watchdog task. This is because all physical
* functions on the device must be able to reset when an EMP reset occurs from
* any source.
*
* Return: the exit code of the operation.
*/
static int ixgbe_devlink_reload_empr_start(struct devlink *devlink,
bool netns_change,
enum devlink_reload_action action,
enum devlink_reload_limit limit,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = devlink_priv(devlink);
struct ixgbe_hw *hw = &adapter->hw;
u8 pending;
int err;
if (hw->mac.type != ixgbe_mac_e610)
return -EOPNOTSUPP;
err = ixgbe_get_pending_updates(adapter, &pending, extack);
if (err)
return err;
/* Pending is a bitmask of which flash banks have a pending update,
* including the main NVM bank, the Option ROM bank, and the netlist
* bank. If any of these bits are set, then there is a pending update
* waiting to be activated.
*/
if (!pending) {
NL_SET_ERR_MSG_MOD(extack, "No pending firmware update");
return -ECANCELED;
}
if (adapter->fw_emp_reset_disabled) {
NL_SET_ERR_MSG_MOD(extack,
"EMP reset is not available. To activate firmware, a reboot or power cycle is needed");
return -ECANCELED;
}
err = ixgbe_aci_nvm_update_empr(hw);
if (err)
NL_SET_ERR_MSG_MOD(extack,
"Failed to trigger EMP device reset to reload firmware");
return err;
}
/*Wait for 10 sec with 0.5 sec tic. EMPR takes no less than half of a sec */
#define IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC 20
/**
* ixgbe_devlink_reload_empr_finish - finishes EMP reset
* @devlink: pointer to the devlink instance
* @action: the action to perform.
* @limit: limits on what reload should do
* @actions_performed: actions performed
* @extack: netlink extended ACK structure
*
* Wait for new NVM to be loaded during EMP reset.
*
* Return: -ETIME when timer is exceeded, 0 on success.
*/
static int ixgbe_devlink_reload_empr_finish(struct devlink *devlink,
enum devlink_reload_action action,
enum devlink_reload_limit limit,
u32 *actions_performed,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = devlink_priv(devlink);
struct ixgbe_hw *hw = &adapter->hw;
int i = 0;
u32 fwsm;
do {
/* Just right away after triggering EMP reset the FWSM register
* may be not cleared yet, so begin the loop with the delay
* in order to not check the not updated register.
*/
mdelay(500);
fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
if (i++ >= IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC)
return -ETIME;
} while (!(fwsm & IXGBE_FWSM_FW_VAL_BIT));
*actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
adapter->flags2 &= ~(IXGBE_FLAG2_API_MISMATCH |
IXGBE_FLAG2_FW_ROLLBACK);
return 0;
}
static const struct devlink_ops ixgbe_devlink_ops = {
.info_get = ixgbe_devlink_info_get,
.supported_flash_update_params =
DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
.flash_update = ixgbe_flash_pldm_image,
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
.reload_down = ixgbe_devlink_reload_empr_start,
.reload_up = ixgbe_devlink_reload_empr_finish,
};
/**
* ixgbe_allocate_devlink - Allocate devlink instance
* @dev: device to allocate devlink for
*
* Allocate a devlink instance for this physical function.
*
* Return: pointer to the device adapter structure on success,
* ERR_PTR(-ENOMEM) when allocation failed.
*/
struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev)
{
struct ixgbe_adapter *adapter;
struct devlink *devlink;
devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev);
if (!devlink)
return ERR_PTR(-ENOMEM);
adapter = devlink_priv(devlink);
adapter->devlink = devlink;
return adapter;
}
/**
* ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN
* @adapter: pointer to the device adapter structure
* @ppid: struct with switch id information
*/
static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter,
struct netdev_phys_item_id *ppid)
{
u64 id = pci_get_dsn(adapter->pdev);
ppid->id_len = sizeof(id);
put_unaligned_be64(id, &ppid->id);
}
/**
* ixgbe_devlink_register_port - Register devlink port
* @adapter: pointer to the device adapter structure
*
* Create and register a devlink_port for this physical function.
*
* Return: 0 on success, error code on failure.
*/
int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter)
{
struct devlink_port *devlink_port = &adapter->devlink_port;
struct devlink *devlink = adapter->devlink;
struct device *dev = &adapter->pdev->dev;
struct devlink_port_attrs attrs = {};
int err;
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = adapter->hw.bus.func;
ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id);
devlink_port_attrs_set(devlink_port, &attrs);
err = devl_port_register(devlink, devlink_port, 0);
if (err) {
dev_err(dev,
"devlink port registration failed, err %d\n", err);
}
return err;
}

View File

@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025, Intel Corporation. */
#ifndef _IXGBE_DEVLINK_H_
#define _IXGBE_DEVLINK_H_
struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev);
int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter);
#endif /* _IXGBE_DEVLINK_H_ */

View File

@@ -17,6 +17,8 @@
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#include <net/devlink.h>
#include "ixgbe_type.h"
#include "ixgbe_common.h"
#include "ixgbe_dcb.h"
@@ -612,6 +614,8 @@ struct ixgbe_adapter {
struct bpf_prog *xdp_prog;
struct pci_dev *pdev;
struct mii_bus *mii_bus;
struct devlink *devlink;
struct devlink_port devlink_port;
unsigned long state;
@@ -667,6 +671,8 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_PHY_FW_LOAD_FAILED BIT(20)
#define IXGBE_FLAG2_NO_MEDIA BIT(21)
#define IXGBE_FLAG2_MOD_POWER_UNSUPPORTED BIT(22)
#define IXGBE_FLAG2_API_MISMATCH BIT(23)
#define IXGBE_FLAG2_FW_ROLLBACK BIT(24)
/* Tx fast path data */
int num_tx_queues;
@@ -755,6 +761,8 @@ struct ixgbe_adapter {
u32 atr_sample_rate;
spinlock_t fdir_perfect_lock;
bool fw_emp_reset_disabled;
#ifdef IXGBE_FCOE
struct ixgbe_fcoe fcoe;
#endif /* IXGBE_FCOE */
@@ -830,6 +838,17 @@ struct ixgbe_adapter {
spinlock_t vfs_lock;
};
struct ixgbe_netdevice_priv {
struct ixgbe_adapter *adapter;
};
static inline struct ixgbe_adapter *ixgbe_from_netdev(struct net_device *netdev)
{
struct ixgbe_netdevice_priv *priv = netdev_priv(netdev);
return priv->adapter;
}
static inline int ixgbe_determine_xdp_q_idx(int cpu)
{
if (static_key_enabled(&ixgbe_xdp_locking_key))
@@ -945,6 +964,8 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter);
int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
u16 subdevice_id);
void ixgbe_set_fw_version_e610(struct ixgbe_adapter *adapter);
void ixgbe_refresh_fw_version(struct ixgbe_adapter *adapter);
#ifdef CONFIG_PCI_IOV
void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter);
#endif

View File

@@ -1169,6 +1169,7 @@ static const struct ixgbe_eeprom_operations eeprom_ops_82598 = {
.calc_checksum = &ixgbe_calc_eeprom_checksum_generic,
.validate_checksum = &ixgbe_validate_eeprom_checksum_generic,
.update_checksum = &ixgbe_update_eeprom_checksum_generic,
.read_pba_string = &ixgbe_read_pba_string_generic,
};
static const struct ixgbe_phy_operations phy_ops_82598 = {

View File

@@ -2230,6 +2230,7 @@ static const struct ixgbe_eeprom_operations eeprom_ops_82599 = {
.calc_checksum = &ixgbe_calc_eeprom_checksum_generic,
.validate_checksum = &ixgbe_validate_eeprom_checksum_generic,
.update_checksum = &ixgbe_update_eeprom_checksum_generic,
.read_pba_string = &ixgbe_read_pba_string_generic,
};
static const struct ixgbe_phy_operations phy_ops_82599 = {

View File

@@ -332,6 +332,7 @@ int ixgbe_start_hw_generic(struct ixgbe_hw *hw)
* Devices in the second generation:
* 82599
* X540
* E610
**/
int ixgbe_start_hw_gen2(struct ixgbe_hw *hw)
{

View File

@@ -118,14 +118,14 @@ static int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max)
static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
}
static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
/* Fail command if not in CEE mode */
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
@@ -142,7 +142,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
u8 *perm_addr)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
int i, j;
memset(perm_addr, 0xff, MAX_ADDR_LEN);
@@ -167,7 +167,7 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
u8 prio, u8 bwg_id, u8 bw_pct,
u8 up_map)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (prio != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
@@ -184,7 +184,7 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
u8 bw_pct)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
}
@@ -193,7 +193,7 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
u8 prio, u8 bwg_id, u8 bw_pct,
u8 up_map)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (prio != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
@@ -210,7 +210,7 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
u8 bw_pct)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
}
@@ -219,7 +219,7 @@ static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
u8 *prio, u8 *bwg_id, u8 *bw_pct,
u8 *up_map)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
*prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type;
*bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id;
@@ -230,7 +230,7 @@ static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
u8 *bw_pct)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
*bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id];
}
@@ -239,7 +239,7 @@ static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
u8 *prio, u8 *bwg_id, u8 *bw_pct,
u8 *up_map)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
*prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type;
*bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id;
@@ -250,7 +250,7 @@ static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
u8 *bw_pct)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
*bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id];
}
@@ -258,7 +258,7 @@ static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
u8 setting)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
@@ -269,14 +269,14 @@ static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
u8 *setting)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
*setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc;
}
static void ixgbe_dcbnl_devreset(struct net_device *dev)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
usleep_range(1000, 2000);
@@ -295,7 +295,7 @@ static void ixgbe_dcbnl_devreset(struct net_device *dev)
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_dcb_config *dcb_cfg = &adapter->dcb_cfg;
struct ixgbe_hw *hw = &adapter->hw;
int ret = DCB_NO_HW_CHG;
@@ -383,7 +383,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
switch (capid) {
case DCB_CAP_ATTR_PG:
@@ -420,7 +420,7 @@ static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
static int ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
switch (tcid) {
@@ -447,14 +447,14 @@ static int ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
return adapter->dcb_cfg.pfc_mode_enable;
}
static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
adapter->temp_dcb_cfg.pfc_mode_enable = state;
}
@@ -471,7 +471,7 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
*/
static int ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct dcb_app app = {
.selector = idtype,
.protocol = id,
@@ -486,7 +486,7 @@ static int ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
struct ieee_ets *ets)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets;
ets->ets_cap = adapter->dcb_cfg.num_tcs.pg_tcs;
@@ -506,7 +506,7 @@ static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
struct ieee_ets *ets)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
int i, err;
__u8 max_tc = 0;
@@ -559,7 +559,7 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
struct ieee_pfc *pfc)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc;
int i;
@@ -584,7 +584,7 @@ static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
struct ieee_pfc *pfc)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_hw *hw = &adapter->hw;
u8 *prio_tc;
int err;
@@ -616,7 +616,7 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
struct dcb_app *app)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
int err;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
@@ -661,7 +661,7 @@ static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
struct dcb_app *app)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
int err;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
@@ -705,13 +705,13 @@ static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
return adapter->dcbx_cap;
}
static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ieee_ets ets = {0};
struct ieee_pfc pfc = {0};
int err = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -67,6 +67,11 @@ int ixgbe_aci_read_nvm(struct ixgbe_hw *hw, u16 module_typeid, u32 offset,
u16 length, void *data, bool last_command,
bool read_shadow_ram);
int ixgbe_nvm_validate_checksum(struct ixgbe_hw *hw);
int ixgbe_get_inactive_orom_ver(struct ixgbe_hw *hw,
struct ixgbe_orom_info *orom);
int ixgbe_get_inactive_nvm_ver(struct ixgbe_hw *hw, struct ixgbe_nvm_info *nvm);
int ixgbe_get_inactive_netlist_ver(struct ixgbe_hw *hw,
struct ixgbe_netlist_info *netlist);
int ixgbe_read_sr_word_aci(struct ixgbe_hw *hw, u16 offset, u16 *data);
int ixgbe_read_flat_nvm(struct ixgbe_hw *hw, u32 offset, u32 *length,
u8 *data, bool read_shadow_ram);
@@ -77,5 +82,18 @@ int ixgbe_read_ee_aci_buffer_e610(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
int ixgbe_validate_eeprom_checksum_e610(struct ixgbe_hw *hw, u16 *checksum_val);
int ixgbe_reset_hw_e610(struct ixgbe_hw *hw);
int ixgbe_get_flash_data(struct ixgbe_hw *hw);
int ixgbe_aci_nvm_update_empr(struct ixgbe_hw *hw);
int ixgbe_nvm_set_pkg_data(struct ixgbe_hw *hw, bool del_pkg_data_flag,
u8 *data, u16 length);
int ixgbe_nvm_pass_component_tbl(struct ixgbe_hw *hw, u8 *data, u16 length,
u8 transfer_flag, u8 *comp_response,
u8 *comp_response_code);
int ixgbe_aci_erase_nvm(struct ixgbe_hw *hw, u16 module_typeid);
int ixgbe_aci_update_nvm(struct ixgbe_hw *hw, u16 module_typeid,
u32 offset, u16 length, void *data,
bool last_command, u8 command_flags);
int ixgbe_nvm_write_activate(struct ixgbe_hw *hw, u16 cmd_flags,
u8 *response_flags);
#endif /* _IXGBE_E610_H_ */

View File

@@ -213,7 +213,7 @@ static void ixgbe_set_advertising_10gtypes(struct ixgbe_hw *hw,
static int ixgbe_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
ixgbe_link_speed supported_link;
bool autoneg = false;
@@ -458,7 +458,7 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
static int ixgbe_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u32 advertised, old;
int err = 0;
@@ -535,7 +535,7 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev,
static void ixgbe_get_pause_stats(struct net_device *netdev,
struct ethtool_pause_stats *stats)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw_stats *hwstats = &adapter->stats;
stats->tx_pause_frames = hwstats->lxontxc + hwstats->lxofftxc;
@@ -545,7 +545,7 @@ static void ixgbe_get_pause_stats(struct net_device *netdev,
static void ixgbe_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
if (ixgbe_device_supports_autoneg_fc(hw) &&
@@ -567,7 +567,7 @@ static void ixgbe_get_pauseparam(struct net_device *netdev,
static int ixgbe_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_fc_info fc = hw->fc;
@@ -606,13 +606,13 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
static u32 ixgbe_get_msglevel(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
return adapter->msg_enable;
}
static void ixgbe_set_msglevel(struct net_device *netdev, u32 data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
adapter->msg_enable = data;
}
@@ -627,7 +627,7 @@ static int ixgbe_get_regs_len(struct net_device *netdev)
static void ixgbe_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u32 *regs_buff = p;
u8 i;
@@ -994,14 +994,14 @@ static void ixgbe_get_regs(struct net_device *netdev,
static int ixgbe_get_eeprom_len(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
return adapter->hw.eeprom.word_size * 2;
}
static int ixgbe_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u16 *eeprom_buff;
int first_word, last_word, eeprom_len;
@@ -1037,7 +1037,7 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
static int ixgbe_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u16 *eeprom_buff;
void *ptr;
@@ -1104,10 +1104,22 @@ static int ixgbe_set_eeprom(struct net_device *netdev,
return ret_val;
}
void ixgbe_refresh_fw_version(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
ixgbe_get_flash_data(hw);
ixgbe_set_fw_version_e610(adapter);
}
static void ixgbe_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
/* need to refresh info for e610 in case fw reloads in runtime */
if (adapter->hw.mac.type == ixgbe_mac_e610)
ixgbe_refresh_fw_version(adapter);
strscpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
@@ -1161,7 +1173,7 @@ static void ixgbe_get_ringparam(struct net_device *netdev,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
struct ixgbe_ring *rx_ring = adapter->rx_ring[0];
@@ -1176,7 +1188,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_ring *temp_ring;
int i, j, err = 0;
u32 new_rx_count, new_tx_count;
@@ -1336,7 +1348,7 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset)
static void ixgbe_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct rtnl_link_stats64 temp;
const struct rtnl_link_stats64 *net_stats;
unsigned int start;
@@ -1710,7 +1722,7 @@ static int ixgbe_eeprom_test(struct ixgbe_adapter *adapter, u64 *data)
static irqreturn_t ixgbe_test_intr(int irq, void *data)
{
struct net_device *netdev = (struct net_device *) data;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
adapter->test_icr |= IXGBE_READ_REG(&adapter->hw, IXGBE_EICR);
@@ -2183,7 +2195,7 @@ static int ixgbe_loopback_test(struct ixgbe_adapter *adapter, u64 *data)
static void ixgbe_diag_test(struct net_device *netdev,
struct ethtool_test *eth_test, u64 *data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
bool if_running = netif_running(netdev);
if (ixgbe_removed(adapter->hw.hw_addr)) {
@@ -2306,7 +2318,7 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter,
static void ixgbe_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
wol->supported = WAKE_UCAST | WAKE_MCAST |
WAKE_BCAST | WAKE_MAGIC;
@@ -2328,7 +2340,7 @@ static void ixgbe_get_wol(struct net_device *netdev,
static int ixgbe_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE |
WAKE_FILTER))
@@ -2355,7 +2367,7 @@ static int ixgbe_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
static int ixgbe_nway_reset(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (netif_running(netdev))
ixgbe_reinit_locked(adapter);
@@ -2366,7 +2378,7 @@ static int ixgbe_nway_reset(struct net_device *netdev)
static int ixgbe_set_phys_id(struct net_device *netdev,
enum ethtool_phys_id_state state)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
if (!hw->mac.ops.led_on || !hw->mac.ops.led_off)
@@ -2399,7 +2411,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
/* only valid if in constant ITR mode */
if (adapter->rx_itr_setting <= 1)
@@ -2455,7 +2467,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_q_vector *q_vector;
int i;
u16 tx_itr_param, rx_itr_param, tx_itr_prev;
@@ -2681,7 +2693,7 @@ static int ixgbe_rss_indir_tbl_max(struct ixgbe_adapter *adapter)
static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
int ret = -EOPNOTSUPP;
switch (cmd->cmd) {
@@ -3069,7 +3081,7 @@ static int ixgbe_set_rss_hash_opt(struct ixgbe_adapter *adapter,
static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
int ret = -EOPNOTSUPP;
switch (cmd->cmd) {
@@ -3096,7 +3108,7 @@ static u32 ixgbe_get_rxfh_key_size(struct net_device *netdev)
static u32 ixgbe_rss_indir_size(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
return ixgbe_rss_indir_tbl_entries(adapter);
}
@@ -3116,7 +3128,7 @@ static void ixgbe_get_reta(struct ixgbe_adapter *adapter, u32 *indir)
static int ixgbe_get_rxfh(struct net_device *netdev,
struct ethtool_rxfh_param *rxfh)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
rxfh->hfunc = ETH_RSS_HASH_TOP;
@@ -3134,7 +3146,7 @@ static int ixgbe_set_rxfh(struct net_device *netdev,
struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
int i;
u32 reta_entries = ixgbe_rss_indir_tbl_entries(adapter);
@@ -3176,7 +3188,7 @@ static int ixgbe_set_rxfh(struct net_device *netdev,
static int ixgbe_get_ts_info(struct net_device *dev,
struct kernel_ethtool_ts_info *info)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
/* we always support timestamping disabled */
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
@@ -3252,7 +3264,7 @@ static unsigned int ixgbe_max_channels(struct ixgbe_adapter *adapter)
static void ixgbe_get_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
/* report maximum channels */
ch->max_combined = ixgbe_max_channels(adapter);
@@ -3289,7 +3301,7 @@ static void ixgbe_get_channels(struct net_device *dev,
static int ixgbe_set_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
unsigned int count = ch->combined_count;
u8 max_rss_indices = ixgbe_max_rss_indices(adapter);
@@ -3327,7 +3339,7 @@ static int ixgbe_set_channels(struct net_device *dev,
static int ixgbe_get_module_info(struct net_device *dev,
struct ethtool_modinfo *modinfo)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_hw *hw = &adapter->hw;
u8 sff8472_rev, addr_mode;
bool page_swap = false;
@@ -3373,7 +3385,7 @@ static int ixgbe_get_module_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee,
u8 *data)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_hw *hw = &adapter->hw;
int status = -EFAULT;
u8 databyte = 0xFF;
@@ -3469,7 +3481,7 @@ ixgbe_get_eee_fw(struct ixgbe_adapter *adapter, struct ethtool_keee *edata)
static int ixgbe_get_eee(struct net_device *netdev, struct ethtool_keee *edata)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
if (!(adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE))
@@ -3483,7 +3495,7 @@ static int ixgbe_get_eee(struct net_device *netdev, struct ethtool_keee *edata)
static int ixgbe_set_eee(struct net_device *netdev, struct ethtool_keee *edata)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
struct ethtool_keee eee_data;
int ret_val;
@@ -3538,7 +3550,7 @@ static int ixgbe_set_eee(struct net_device *netdev, struct ethtool_keee *edata)
static u32 ixgbe_get_priv_flags(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
u32 priv_flags = 0;
if (adapter->flags2 & IXGBE_FLAG2_RX_LEGACY)
@@ -3555,7 +3567,7 @@ static u32 ixgbe_get_priv_flags(struct net_device *netdev)
static int ixgbe_set_priv_flags(struct net_device *netdev, u32 priv_flags)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
unsigned int flags2 = adapter->flags2;
unsigned int i;

View File

@@ -56,7 +56,7 @@ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
if (xid >= netdev->fcoe_ddp_xid)
return 0;
adapter = netdev_priv(netdev);
adapter = ixgbe_from_netdev(netdev);
fcoe = &adapter->fcoe;
ddp = &fcoe->ddp[xid];
if (!ddp->udl)
@@ -153,7 +153,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
if (!netdev || !sgl)
return 0;
adapter = netdev_priv(netdev);
adapter = ixgbe_from_netdev(netdev);
if (xid >= netdev->fcoe_ddp_xid) {
e_warn(drv, "xid=0x%x out-of-range\n", xid);
return 0;
@@ -834,7 +834,7 @@ static void ixgbe_fcoe_ddp_disable(struct ixgbe_adapter *adapter)
*/
int ixgbe_fcoe_enable(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_fcoe *fcoe = &adapter->fcoe;
atomic_inc(&fcoe->refcnt);
@@ -881,7 +881,7 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
*/
int ixgbe_fcoe_disable(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (!atomic_dec_and_test(&adapter->fcoe.refcnt))
return -EINVAL;
@@ -927,7 +927,7 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
{
u16 prefix = 0xffff;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_mac_info *mac = &adapter->hw.mac;
switch (type) {
@@ -967,7 +967,7 @@ int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
int ixgbe_fcoe_get_hbainfo(struct net_device *netdev,
struct netdev_fcoe_hbainfo *info)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u64 dsn;

View File

@@ -0,0 +1,707 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2025 Intel Corporation. */
#include <linux/crc32.h>
#include <linux/pldmfw.h>
#include <linux/uuid.h>
#include "ixgbe.h"
#include "ixgbe_fw_update.h"
struct ixgbe_fwu_priv {
struct pldmfw context;
struct ixgbe_adapter *adapter;
struct netlink_ext_ack *extack;
/* Track which NVM banks to activate at the end of the update */
u8 activate_flags;
bool emp_reset_available;
};
/**
* ixgbe_send_package_data - Send record package data to firmware
* @context: PLDM fw update structure
* @data: pointer to the package data
* @length: length of the package data
*
* Send a copy of the package data associated with the PLDM record matching
* this device to the firmware.
*
* Note that this function sends an AdminQ command that will fail unless the
* NVM resource has been acquired.
*
* Return: zero on success, or a negative error code on failure.
*/
static int ixgbe_send_package_data(struct pldmfw *context,
const u8 *data, u16 length)
{
struct ixgbe_fwu_priv *priv = container_of(context,
struct ixgbe_fwu_priv,
context);
struct ixgbe_adapter *adapter = priv->adapter;
struct ixgbe_hw *hw = &adapter->hw;
u8 *package_data;
int err;
package_data = kmemdup(data, length, GFP_KERNEL);
if (!package_data)
return -ENOMEM;
err = ixgbe_nvm_set_pkg_data(hw, false, package_data, length);
kfree(package_data);
return err;
}
/**
* ixgbe_check_component_response - Report firmware response to a component
* @adapter: device private data structure
* @response: indicates whether this component can be updated
* @code: code indicating reason for response
* @extack: netlink extended ACK structure
*
* Check whether firmware indicates if this component can be updated. Report
* a suitable error message over the netlink extended ACK if the component
* cannot be updated.
*
* Return: 0 if the component can be updated, or -ECANCELED if the
* firmware indicates the component cannot be updated.
*/
static int ixgbe_check_component_response(struct ixgbe_adapter *adapter,
u8 response, u8 code,
struct netlink_ext_ack *extack)
{
struct ixgbe_hw *hw = &adapter->hw;
switch (response) {
case IXGBE_ACI_NVM_PASS_COMP_CAN_BE_UPDATED:
/* Firmware indicated this update is good to proceed. */
return 0;
case IXGBE_ACI_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE:
NL_SET_ERR_MSG_MOD(extack,
"Firmware recommends not updating, as it may result in a downgrade. Continuing anyways");
return 0;
case IXGBE_ACI_NVM_PASS_COMP_CAN_NOT_BE_UPDATED:
NL_SET_ERR_MSG_MOD(extack, "Firmware has rejected updating.");
break;
case IXGBE_ACI_NVM_PASS_COMP_PARTIAL_CHECK:
if (hw->mac.ops.fw_recovery_mode &&
hw->mac.ops.fw_recovery_mode(hw))
return 0;
break;
}
switch (code) {
case IXGBE_ACI_NVM_PASS_COMP_STAMP_IDENTICAL_CODE:
NL_SET_ERR_MSG_MOD(extack,
"Component comparison stamp is identical to running image");
break;
case IXGBE_ACI_NVM_PASS_COMP_STAMP_LOWER:
NL_SET_ERR_MSG_MOD(extack,
"Component comparison stamp is lower than running image");
break;
case IXGBE_ACI_NVM_PASS_COMP_INVALID_STAMP_CODE:
NL_SET_ERR_MSG_MOD(extack,
"Component comparison stamp is invalid");
break;
case IXGBE_ACI_NVM_PASS_COMP_CONFLICT_CODE:
NL_SET_ERR_MSG_MOD(extack,
"Component table conflict occurred");
break;
case IXGBE_ACI_NVM_PASS_COMP_PRE_REQ_NOT_MET_CODE:
NL_SET_ERR_MSG_MOD(extack, "Component pre-requisites not met");
break;
case IXGBE_ACI_NVM_PASS_COMP_NOT_SUPPORTED_CODE:
NL_SET_ERR_MSG_MOD(extack, "Component not supported");
break;
case IXGBE_ACI_NVM_PASS_COMP_CANNOT_DOWNGRADE_CODE:
NL_SET_ERR_MSG_MOD(extack, "Component cannot be downgraded");
break;
case IXGBE_ACI_NVM_PASS_COMP_INCOMPLETE_IMAGE_CODE:
NL_SET_ERR_MSG_MOD(extack, "Incomplete component image");
break;
case IXGBE_ACI_NVM_PASS_COMP_VER_STR_IDENTICAL_CODE:
NL_SET_ERR_MSG_MOD(extack,
"Component version is identical to running image");
break;
case IXGBE_ACI_NVM_PASS_COMP_VER_STR_LOWER_CODE:
NL_SET_ERR_MSG_MOD(extack,
"Component version is lower than the running image");
break;
default:
NL_SET_ERR_MSG_MOD(extack,
"Received unexpected response code from firmware");
break;
}
return -ECANCELED;
}
/**
* ixgbe_send_component_table - Send PLDM component table to firmware
* @context: PLDM fw update structure
* @component: the component to process
* @transfer_flag: relative transfer order of this component
*
* Read relevant data from the component and forward it to the device
* firmware. Check the response to determine if the firmware indicates that
* the update can proceed.
*
* This function sends ACI commands related to the NVM, and assumes that
* the NVM resource has been acquired.
*
* Return: 0 on success, or a negative error code on failure.
*/
static int ixgbe_send_component_table(struct pldmfw *context,
struct pldmfw_component *component,
u8 transfer_flag)
{
struct ixgbe_fwu_priv *priv = container_of(context,
struct ixgbe_fwu_priv,
context);
struct ixgbe_adapter *adapter = priv->adapter;
struct netlink_ext_ack *extack = priv->extack;
struct ixgbe_aci_cmd_nvm_comp_tbl *comp_tbl;
u8 comp_response, comp_response_code;
struct ixgbe_hw *hw = &adapter->hw;
size_t length;
int err;
switch (component->identifier) {
case NVM_COMP_ID_OROM:
case NVM_COMP_ID_NVM:
case NVM_COMP_ID_NETLIST:
break;
default:
NL_SET_ERR_MSG_MOD(extack,
"Unable to update due to unknown firmware component");
return -EOPNOTSUPP;
}
length = struct_size(comp_tbl, cvs, component->version_len);
comp_tbl = kzalloc(length, GFP_KERNEL);
if (!comp_tbl)
return -ENOMEM;
comp_tbl->comp_class = cpu_to_le16(component->classification);
comp_tbl->comp_id = cpu_to_le16(component->identifier);
comp_tbl->comp_class_idx = FWU_COMP_CLASS_IDX_NOT_USE;
comp_tbl->comp_cmp_stamp = cpu_to_le32(component->comparison_stamp);
comp_tbl->cvs_type = component->version_type;
comp_tbl->cvs_len = component->version_len;
memcpy(comp_tbl->cvs, component->version_string,
component->version_len);
err = ixgbe_nvm_pass_component_tbl(hw, (u8 *)comp_tbl, length,
transfer_flag, &comp_response,
&comp_response_code);
kfree(comp_tbl);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to transfer component table to firmware");
return -EIO;
}
return ixgbe_check_component_response(adapter,
comp_response,
comp_response_code, extack);
}
/**
* ixgbe_write_one_nvm_block - Write an NVM block and await completion response
* @adapter: the PF data structure
* @module: the module to write to
* @offset: offset in bytes
* @block_size: size of the block to write, up to 4k
* @block: pointer to block of data to write
* @last_cmd: whether this is the last command
* @extack: netlink extended ACK structure
*
* Write a block of data to a flash module, and await for the completion
* response message from firmware.
*
* Note this function assumes the caller has acquired the NVM resource.
*
* On successful return, reset level indicates the device reset required to
* complete the update.
*
* 0 - IXGBE_ACI_NVM_POR_FLAG - A full power on is required
* 1 - IXGBE_ACI_NVM_PERST_FLAG - A cold PCIe reset is required
* 2 - IXGBE_ACI_NVM_EMPR_FLAG - An EMP reset is required
*
* Return: 0 on success, or a negative error code on failure.
*/
static int ixgbe_write_one_nvm_block(struct ixgbe_adapter *adapter,
u16 module, u32 offset,
u16 block_size, u8 *block, bool last_cmd,
struct netlink_ext_ack *extack)
{
struct ixgbe_hw *hw = &adapter->hw;
return ixgbe_aci_update_nvm(hw, module, offset, block_size, block,
last_cmd, 0);
}
/**
* ixgbe_write_nvm_module - Write data to an NVM module
* @adapter: the PF driver structure
* @module: the module id to program
* @component: the name of the component being updated
* @image: buffer of image data to write to the NVM
* @length: length of the buffer
* @extack: netlink extended ACK structure
*
* Loop over the data for a given NVM module and program it in 4 Kb
* blocks. Notify devlink core of progress after each block is programmed.
* Loops over a block of data and programs the NVM in 4k block chunks.
*
* Note this function assumes the caller has acquired the NVM resource.
*
* Return: 0 on success, or a negative error code on failure.
*/
static int ixgbe_write_nvm_module(struct ixgbe_adapter *adapter, u16 module,
const char *component, const u8 *image,
u32 length,
struct netlink_ext_ack *extack)
{
struct devlink *devlink = adapter->devlink;
u32 offset = 0;
bool last_cmd;
u8 *block;
int err;
devlink_flash_update_status_notify(devlink, "Flashing",
component, 0, length);
block = kzalloc(IXGBE_ACI_MAX_BUFFER_SIZE, GFP_KERNEL);
if (!block)
return -ENOMEM;
do {
u32 block_size;
block_size = min_t(u32, IXGBE_ACI_MAX_BUFFER_SIZE,
length - offset);
last_cmd = !(offset + block_size < length);
memcpy(block, image + offset, block_size);
err = ixgbe_write_one_nvm_block(adapter, module, offset,
block_size, block, last_cmd,
extack);
if (err)
break;
offset += block_size;
devlink_flash_update_status_notify(devlink, "Flashing",
component, offset, length);
} while (!last_cmd);
if (err)
devlink_flash_update_status_notify(devlink, "Flashing failed",
component, length, length);
else
devlink_flash_update_status_notify(devlink, "Flashing done",
component, length, length);
kfree(block);
return err;
}
/* Length in seconds to wait before timing out when erasing a flash module.
* Yes, erasing really can take minutes to complete.
*/
#define IXGBE_FW_ERASE_TIMEOUT 300
/**
* ixgbe_erase_nvm_module - Erase an NVM module and await firmware completion
* @adapter: the PF data structure
* @module: the module to erase
* @component: name of the component being updated
* @extack: netlink extended ACK structure
*
* Erase the inactive NVM bank associated with this module, and await for
* a completion response message from firmware.
*
* Note this function assumes the caller has acquired the NVM resource.
*
* Return: 0 on success, or a negative error code on failure.
*/
static int ixgbe_erase_nvm_module(struct ixgbe_adapter *adapter, u16 module,
const char *component,
struct netlink_ext_ack *extack)
{
struct devlink *devlink = adapter->devlink;
struct ixgbe_hw *hw = &adapter->hw;
int err;
devlink_flash_update_timeout_notify(devlink, "Erasing", component,
IXGBE_FW_ERASE_TIMEOUT);
err = ixgbe_aci_erase_nvm(hw, module);
if (err)
devlink_flash_update_status_notify(devlink, "Erasing failed",
component, 0, 0);
else
devlink_flash_update_status_notify(devlink, "Erasing done",
component, 0, 0);
return err;
}
/**
* ixgbe_switch_flash_banks - Tell firmware to switch NVM banks
* @adapter: Pointer to the PF data structure
* @activate_flags: flags used for the activation command
* @emp_reset_available: on return, indicates if EMP reset is available
* @extack: netlink extended ACK structure
*
* Notify firmware to activate the newly written flash banks, and wait for the
* firmware response.
*
* Return: 0 on success or an error code on failure.
*/
static int ixgbe_switch_flash_banks(struct ixgbe_adapter *adapter,
u8 activate_flags,
bool *emp_reset_available,
struct netlink_ext_ack *extack)
{
struct ixgbe_hw *hw = &adapter->hw;
u8 response_flags;
int err;
err = ixgbe_nvm_write_activate(hw, activate_flags, &response_flags);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to switch active flash banks");
return err;
}
if (emp_reset_available) {
if (hw->dev_caps.common_cap.reset_restrict_support)
*emp_reset_available =
response_flags & IXGBE_ACI_NVM_EMPR_ENA;
else
*emp_reset_available = true;
}
return 0;
}
/**
* ixgbe_flash_component - Flash a component of the NVM
* @context: PLDM fw update structure
* @component: the component table to program
*
* Program the flash contents for a given component. First, determine the
* module id. Then, erase the secondary bank for this module. Finally, write
* the contents of the component to the NVM.
*
* Note this function assumes the caller has acquired the NVM resource.
*
* Return: 0 on success, or a negative error code on failure.
*/
static int ixgbe_flash_component(struct pldmfw *context,
struct pldmfw_component *component)
{
struct ixgbe_fwu_priv *priv = container_of(context,
struct ixgbe_fwu_priv,
context);
struct netlink_ext_ack *extack = priv->extack;
struct ixgbe_adapter *adapter = priv->adapter;
const char *name;
u16 module;
int err;
u8 flag;
switch (component->identifier) {
case NVM_COMP_ID_OROM:
module = IXGBE_E610_SR_1ST_OROM_BANK_PTR;
flag = IXGBE_ACI_NVM_ACTIV_SEL_OROM;
name = "fw.undi";
break;
case NVM_COMP_ID_NVM:
module = IXGBE_E610_SR_1ST_NVM_BANK_PTR;
flag = IXGBE_ACI_NVM_ACTIV_SEL_NVM;
name = "fw.mgmt";
break;
case NVM_COMP_ID_NETLIST:
module = IXGBE_E610_SR_NETLIST_BANK_PTR;
flag = IXGBE_ACI_NVM_ACTIV_SEL_NETLIST;
name = "fw.netlist";
break;
default:
return -EOPNOTSUPP;
}
/* Mark this component for activating at the end. */
priv->activate_flags |= flag;
err = ixgbe_erase_nvm_module(adapter, module, name, extack);
if (err)
return err;
return ixgbe_write_nvm_module(adapter, module, name,
component->component_data,
component->component_size, extack);
}
/**
* ixgbe_finalize_update - Perform last steps to complete device update
* @context: PLDM fw update structure
*
* Called as the last step of the update process. Complete the update by
* telling the firmware to switch active banks, and perform a reset of
* configured.
*
* Return: 0 on success, or an error code on failure.
*/
static int ixgbe_finalize_update(struct pldmfw *context)
{
struct ixgbe_fwu_priv *priv = container_of(context,
struct ixgbe_fwu_priv,
context);
struct ixgbe_adapter *adapter = priv->adapter;
struct netlink_ext_ack *extack = priv->extack;
struct devlink *devlink = adapter->devlink;
int err;
/* Finally, notify firmware to activate the written NVM banks */
err = ixgbe_switch_flash_banks(adapter, priv->activate_flags,
&priv->emp_reset_available, extack);
if (err)
return err;
adapter->fw_emp_reset_disabled = !priv->emp_reset_available;
if (!adapter->fw_emp_reset_disabled)
devlink_flash_update_status_notify(devlink,
"Suggested is to activate new firmware by devlink reload, if it doesn't work then a power cycle is required",
NULL, 0, 0);
return 0;
}
static const struct pldmfw_ops ixgbe_fwu_ops_e610 = {
.match_record = &pldmfw_op_pci_match_record,
.send_package_data = &ixgbe_send_package_data,
.send_component_table = &ixgbe_send_component_table,
.flash_component = &ixgbe_flash_component,
.finalize_update = &ixgbe_finalize_update,
};
/**
* ixgbe_get_pending_updates - Check if the component has a pending update
* @adapter: the PF driver structure
* @pending: on return, bitmap of updates pending
* @extack: Netlink extended ACK
*
* Check if the device has any pending updates on any flash components.
*
* Return: 0 on success, or a negative error code on failure. Update
* pending with the bitmap of pending updates.
*/
int ixgbe_get_pending_updates(struct ixgbe_adapter *adapter, u8 *pending,
struct netlink_ext_ack *extack)
{
struct ixgbe_hw_dev_caps *dev_caps;
struct ixgbe_hw *hw = &adapter->hw;
int err;
dev_caps = kzalloc(sizeof(*dev_caps), GFP_KERNEL);
if (!dev_caps)
return -ENOMEM;
err = ixgbe_discover_dev_caps(hw, dev_caps);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Unable to read device capabilities");
kfree(dev_caps);
return -EIO;
}
*pending = 0;
if (dev_caps->common_cap.nvm_update_pending_nvm)
*pending |= IXGBE_ACI_NVM_ACTIV_SEL_NVM;
if (dev_caps->common_cap.nvm_update_pending_orom)
*pending |= IXGBE_ACI_NVM_ACTIV_SEL_OROM;
if (dev_caps->common_cap.nvm_update_pending_netlist)
*pending |= IXGBE_ACI_NVM_ACTIV_SEL_NETLIST;
kfree(dev_caps);
return 0;
}
/**
* ixgbe_cancel_pending_update - Cancel any pending update for a component
* @adapter: the PF driver structure
* @component: if not NULL, the name of the component being updated
* @extack: Netlink extended ACK structure
*
* Cancel any pending update for the specified component. If component is
* NULL, all device updates will be canceled.
*
* Return: 0 on success, or a negative error code on failure.
*/
static int ixgbe_cancel_pending_update(struct ixgbe_adapter *adapter,
const char *component,
struct netlink_ext_ack *extack)
{
struct devlink *devlink = adapter->devlink;
struct ixgbe_hw *hw = &adapter->hw;
u8 pending;
int err;
err = ixgbe_get_pending_updates(adapter, &pending, extack);
if (err)
return err;
/* If the flash_update request is for a specific component, ignore all
* of the other components.
*/
if (component) {
if (strcmp(component, "fw.mgmt") == 0)
pending &= IXGBE_ACI_NVM_ACTIV_SEL_NVM;
else if (strcmp(component, "fw.undi") == 0)
pending &= IXGBE_ACI_NVM_ACTIV_SEL_OROM;
else if (strcmp(component, "fw.netlist") == 0)
pending &= IXGBE_ACI_NVM_ACTIV_SEL_NETLIST;
else
return -EINVAL;
}
/* There is no previous pending update, so this request may continue */
if (!pending)
return 0;
/* In order to allow overwriting a previous pending update, notify
* firmware to cancel that update by issuing the appropriate command.
*/
devlink_flash_update_status_notify(devlink,
"Canceling previous pending update",
component, 0, 0);
err = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to acquire device flash lock");
return -EIO;
}
pending |= IXGBE_ACI_NVM_REVERT_LAST_ACTIV;
err = ixgbe_switch_flash_banks(adapter, pending, NULL, extack);
ixgbe_release_nvm(hw);
return err;
}
/**
* ixgbe_flash_pldm_image - Write a PLDM-formatted firmware image to the device
* @devlink: pointer to devlink associated with the device to update
* @params: devlink flash update parameters
* @extack: netlink extended ACK structure
*
* Parse the data for a given firmware file, verifying that it is a valid PLDM
* formatted image that matches this device.
*
* Extract the device record Package Data and Component Tables and send them
* to the firmware. Extract and write the flash data for each of the three
* main flash components, "fw.mgmt", "fw.undi", and "fw.netlist". Notify
* firmware once the data is written to the inactive banks.
*
* Return: 0 on success or a negative error code on failure.
*/
int ixgbe_flash_pldm_image(struct devlink *devlink,
struct devlink_flash_update_params *params,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = devlink_priv(devlink);
struct device *dev = &adapter->pdev->dev;
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_fwu_priv priv;
u8 preservation;
int err;
if (hw->mac.type != ixgbe_mac_e610)
return -EOPNOTSUPP;
switch (params->overwrite_mask) {
case 0:
/* preserve all settings and identifiers */
preservation = IXGBE_ACI_NVM_PRESERVE_ALL;
break;
case DEVLINK_FLASH_OVERWRITE_SETTINGS:
/* Overwrite settings, but preserve vital information such as
* device identifiers.
*/
preservation = IXGBE_ACI_NVM_PRESERVE_SELECTED;
break;
case (DEVLINK_FLASH_OVERWRITE_SETTINGS |
DEVLINK_FLASH_OVERWRITE_IDENTIFIERS):
/* overwrite both settings and identifiers, preserve nothing */
preservation = IXGBE_ACI_NVM_NO_PRESERVATION;
break;
default:
NL_SET_ERR_MSG_MOD(extack,
"Requested overwrite mask is not supported");
return -EOPNOTSUPP;
}
/* Cannot get caps in recovery mode, so lack of nvm_unified_update bit
* cannot lead to error
*/
if (!hw->dev_caps.common_cap.nvm_unified_update &&
(hw->mac.ops.fw_recovery_mode &&
!hw->mac.ops.fw_recovery_mode(hw))) {
NL_SET_ERR_MSG_MOD(extack,
"Current firmware does not support unified update");
return -EOPNOTSUPP;
}
memset(&priv, 0, sizeof(priv));
priv.context.ops = &ixgbe_fwu_ops_e610;
priv.context.dev = dev;
priv.extack = extack;
priv.adapter = adapter;
priv.activate_flags = preservation;
devlink_flash_update_status_notify(devlink,
"Preparing to flash", NULL, 0, 0);
err = ixgbe_cancel_pending_update(adapter, NULL, extack);
if (err)
return err;
err = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to acquire device flash lock");
return -EIO;
}
err = pldmfw_flash_image(&priv.context, params->fw);
if (err == -ENOENT) {
NL_SET_ERR_MSG_MOD(extack,
"Firmware image has no record matching this device");
} else if (err) {
NL_SET_ERR_MSG_MOD(extack, "Failed to flash PLDM image");
}
ixgbe_release_nvm(hw);
return err;
}

View File

@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2025 Intel Corporation. */
#ifndef _IXGBE_FW_UPDATE_H_
#define _IXGBE_FW_UPDATE_H_
int ixgbe_flash_pldm_image(struct devlink *devlink,
struct devlink_flash_update_params *params,
struct netlink_ext_ack *extack);
int ixgbe_get_pending_updates(struct ixgbe_adapter *adapter, u8 *pending,
struct netlink_ext_ack *extack);
#endif

View File

@@ -478,7 +478,7 @@ static int ixgbe_ipsec_parse_proto_keys(struct xfrm_state *xs,
static int ixgbe_ipsec_check_mgmt_ip(struct xfrm_state *xs)
{
struct net_device *dev = xs->xso.real_dev;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_hw *hw = &adapter->hw;
u32 mfval, manc, reg;
int num_filters = 4;
@@ -563,7 +563,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
struct netlink_ext_ack *extack)
{
struct net_device *dev = xs->xso.real_dev;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_ipsec *ipsec = adapter->ipsec;
struct ixgbe_hw *hw = &adapter->hw;
int checked, match, first;
@@ -757,7 +757,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
static void ixgbe_ipsec_del_sa(struct xfrm_state *xs)
{
struct net_device *dev = xs->xso.real_dev;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_ipsec *ipsec = adapter->ipsec;
struct ixgbe_hw *hw = &adapter->hw;
u32 zerobuf[4] = {0, 0, 0, 0};
@@ -1052,7 +1052,7 @@ int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring,
struct ixgbe_tx_buffer *first,
struct ixgbe_ipsec_tx_data *itd)
{
struct ixgbe_adapter *adapter = netdev_priv(tx_ring->netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(tx_ring->netdev);
struct ixgbe_ipsec *ipsec = adapter->ipsec;
struct xfrm_state *xs;
struct sec_path *sp;
@@ -1142,7 +1142,7 @@ void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
struct ixgbe_adapter *adapter = netdev_priv(rx_ring->netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(rx_ring->netdev);
__le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
__le16 ipsec_pkt_types = cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPSEC_AH |
IXGBE_RXDADV_PKTTYPE_IPSEC_ESP);

View File

@@ -49,6 +49,7 @@
#include "ixgbe_sriov.h"
#include "ixgbe_model.h"
#include "ixgbe_txrx_common.h"
#include "devlink/devlink.h"
char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
@@ -1095,7 +1096,7 @@ static void ixgbe_tx_timeout_reset(struct ixgbe_adapter *adapter)
static int ixgbe_tx_maxrate(struct net_device *netdev,
int queue_index, u32 maxrate)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u32 bcnrc_val = ixgbe_link_mbps(adapter);
@@ -4678,7 +4679,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
static int ixgbe_vlan_rx_add_vid(struct net_device *netdev,
__be16 proto, u16 vid)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
/* add VID to filter table */
@@ -4737,7 +4738,7 @@ void ixgbe_update_pf_promisc_vlvf(struct ixgbe_adapter *adapter, u32 vid)
static int ixgbe_vlan_rx_kill_vid(struct net_device *netdev,
__be16 proto, u16 vid)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
/* remove VID from filter table */
@@ -4962,7 +4963,7 @@ static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
**/
static int ixgbe_write_mc_addr_list(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
if (!netif_running(netdev))
@@ -5138,7 +5139,7 @@ int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter,
static int ixgbe_uc_sync(struct net_device *netdev, const unsigned char *addr)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
int ret;
ret = ixgbe_add_mac_filter(adapter, addr, VMDQ_P(0));
@@ -5148,7 +5149,7 @@ static int ixgbe_uc_sync(struct net_device *netdev, const unsigned char *addr)
static int ixgbe_uc_unsync(struct net_device *netdev, const unsigned char *addr)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
ixgbe_del_mac_filter(adapter, addr, VMDQ_P(0));
@@ -5166,7 +5167,7 @@ static int ixgbe_uc_unsync(struct net_device *netdev, const unsigned char *addr)
**/
void ixgbe_set_rx_mode(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u32 fctrl, vmolr = IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE;
netdev_features_t features = netdev->features;
@@ -5268,7 +5269,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
static int ixgbe_udp_tunnel_sync(struct net_device *dev, unsigned int table)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_hw *hw = &adapter->hw;
struct udp_tunnel_info ti;
@@ -6600,7 +6601,7 @@ static void ixgbe_set_eee_capable(struct ixgbe_adapter *adapter)
**/
static void ixgbe_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
/* Do the reset outside of interrupt context */
ixgbe_tx_timeout_reset(adapter);
@@ -6849,7 +6850,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
adapter->tx_work_limit = IXGBE_DEFAULT_TX_WORK;
/* initialize eeprom parameters */
if (ixgbe_init_eeprom_params_generic(hw)) {
if (hw->eeprom.ops.init_params(hw)) {
e_dev_err("EEPROM initialization failed\n");
return -EIO;
}
@@ -7165,7 +7166,7 @@ static int ixgbe_max_xdp_frame_size(struct ixgbe_adapter *adapter)
**/
static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (ixgbe_enabled_xdp_adapter(adapter)) {
int new_frame_size = new_mtu + IXGBE_PKT_HDR_PAD;
@@ -7212,7 +7213,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
**/
int ixgbe_open(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
int err, queues;
@@ -7316,7 +7317,7 @@ static void ixgbe_close_suspend(struct ixgbe_adapter *adapter)
**/
int ixgbe_close(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
ixgbe_ptp_stop(adapter);
@@ -8364,6 +8365,34 @@ static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
rtnl_unlock();
}
static int ixgbe_check_fw_api_mismatch(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
if (hw->mac.type != ixgbe_mac_e610)
return 0;
if (hw->mac.ops.get_fw_ver && hw->mac.ops.get_fw_ver(hw))
return 0;
if (hw->api_maj_ver > IXGBE_FW_API_VER_MAJOR) {
e_dev_err("The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n");
adapter->flags2 |= IXGBE_FLAG2_API_MISMATCH;
return -EOPNOTSUPP;
} else if (hw->api_maj_ver == IXGBE_FW_API_VER_MAJOR &&
hw->api_min_ver > IXGBE_FW_API_VER_MINOR + IXGBE_FW_API_VER_DIFF_ALLOWED) {
e_dev_info("The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n");
adapter->flags2 |= IXGBE_FLAG2_API_MISMATCH;
} else if (hw->api_maj_ver < IXGBE_FW_API_VER_MAJOR ||
hw->api_min_ver < IXGBE_FW_API_VER_MINOR - IXGBE_FW_API_VER_DIFF_ALLOWED) {
e_dev_info("The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
adapter->flags2 |= IXGBE_FLAG2_API_MISMATCH;
}
return 0;
}
/**
* ixgbe_check_fw_error - Check firmware for errors
* @adapter: the adapter private structure
@@ -8374,12 +8403,14 @@ static bool ixgbe_check_fw_error(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 fwsm;
int err;
/* read fwsm.ext_err_ind register and log errors */
fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
/* skip if E610's FW is reloading, warning in that case may be misleading */
if (fwsm & IXGBE_FWSM_EXT_ERR_IND_MASK ||
!(fwsm & IXGBE_FWSM_FW_VAL_BIT))
(!(fwsm & IXGBE_FWSM_FW_VAL_BIT) && !(hw->mac.type == ixgbe_mac_e610)))
e_dev_warn("Warning firmware error detected FWSM: 0x%08X\n",
fwsm);
@@ -8387,10 +8418,53 @@ static bool ixgbe_check_fw_error(struct ixgbe_adapter *adapter)
e_dev_err("Firmware recovery mode detected. Limiting functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n");
return true;
}
if (!(adapter->flags2 & IXGBE_FLAG2_API_MISMATCH)) {
err = ixgbe_check_fw_api_mismatch(adapter);
if (err)
return true;
}
/* return here if FW rollback mode has been already detected */
if (adapter->flags2 & IXGBE_FLAG2_FW_ROLLBACK)
return false;
if (hw->mac.ops.fw_rollback_mode && hw->mac.ops.fw_rollback_mode(hw)) {
struct ixgbe_nvm_info *nvm_info = &adapter->hw.flash.nvm;
char ver_buff[64] = "";
if (hw->mac.ops.get_fw_ver && hw->mac.ops.get_fw_ver(hw))
goto no_version;
if (hw->mac.ops.get_nvm_ver &&
hw->mac.ops.get_nvm_ver(hw, nvm_info))
goto no_version;
snprintf(ver_buff, sizeof(ver_buff),
"Current version is NVM:%x.%x.%x, FW:%d.%d. ",
nvm_info->major, nvm_info->minor, nvm_info->eetrack,
hw->fw_maj_ver, hw->fw_maj_ver);
no_version:
e_dev_warn("Firmware rollback mode detected. %sDevice may exhibit limited functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware rollback mode.",
ver_buff);
adapter->flags2 |= IXGBE_FLAG2_FW_ROLLBACK;
}
return false;
}
static void ixgbe_recovery_service_task(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work,
struct ixgbe_adapter,
service_task);
ixgbe_handle_fw_event(adapter);
ixgbe_service_event_complete(adapter);
mod_timer(&adapter->service_timer, jiffies + msecs_to_jiffies(100));
}
/**
* ixgbe_service_task - manages and runs subtasks
* @work: pointer to work_struct containing our data
@@ -8410,8 +8484,13 @@ static void ixgbe_service_task(struct work_struct *work)
return;
}
if (ixgbe_check_fw_error(adapter)) {
if (!test_bit(__IXGBE_DOWN, &adapter->state))
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
if (adapter->mii_bus) {
mdiobus_unregister(adapter->mii_bus);
adapter->mii_bus = NULL;
}
unregister_netdev(adapter->netdev);
}
ixgbe_service_event_complete(adapter);
return;
}
@@ -9001,7 +9080,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
switch (vlan_get_protocol(skb)) {
case htons(ETH_P_FCOE):
case htons(ETH_P_FIP):
adapter = netdev_priv(dev);
adapter = ixgbe_from_netdev(dev);
if (!sb_dev && (adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
break;
@@ -9260,7 +9339,7 @@ static netdev_tx_t __ixgbe_xmit_frame(struct sk_buff *skb,
struct net_device *netdev,
struct ixgbe_ring *ring)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_ring *tx_ring;
/*
@@ -9292,7 +9371,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
**/
static int ixgbe_set_mac(struct net_device *netdev, void *p)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
struct sockaddr *addr = p;
@@ -9310,7 +9389,7 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p)
static int
ixgbe_mdio_read(struct net_device *netdev, int prtad, int devad, u16 addr)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
u16 value;
int rc;
@@ -9336,7 +9415,7 @@ ixgbe_mdio_read(struct net_device *netdev, int prtad, int devad, u16 addr)
static int ixgbe_mdio_write(struct net_device *netdev, int prtad, int devad,
u16 addr, u16 value)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
if (adapter->mii_bus) {
@@ -9356,7 +9435,7 @@ static int ixgbe_mdio_write(struct net_device *netdev, int prtad, int devad,
static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
switch (cmd) {
case SIOCSHWTSTAMP:
@@ -9382,7 +9461,7 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
static int ixgbe_add_sanmac_netdev(struct net_device *dev)
{
int err = 0;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_hw *hw = &adapter->hw;
if (is_valid_ether_addr(hw->mac.san_addr)) {
@@ -9406,7 +9485,7 @@ static int ixgbe_add_sanmac_netdev(struct net_device *dev)
static int ixgbe_del_sanmac_netdev(struct net_device *dev)
{
int err = 0;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_mac_info *mac = &adapter->hw.mac;
if (is_valid_ether_addr(mac->san_addr)) {
@@ -9437,7 +9516,7 @@ static void ixgbe_get_ring_stats64(struct rtnl_link_stats64 *stats,
static void ixgbe_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
int i;
rcu_read_lock();
@@ -9480,7 +9559,7 @@ static void ixgbe_get_stats64(struct net_device *netdev,
static int ixgbe_ndo_get_vf_stats(struct net_device *netdev, int vf,
struct ifla_vf_stats *vf_stats)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (vf < 0 || vf >= adapter->num_vfs)
return -EINVAL;
@@ -9597,7 +9676,7 @@ static int ixgbe_reassign_macvlan_pool(struct net_device *vdev,
static void ixgbe_defrag_macvlan_pools(struct net_device *dev)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct netdev_nested_priv priv = {
.data = (void *)adapter,
};
@@ -9618,7 +9697,7 @@ static void ixgbe_defrag_macvlan_pools(struct net_device *dev)
*/
int ixgbe_setup_tc(struct net_device *dev, u8 tc)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_hw *hw = &adapter->hw;
/* Hardware supports up to 8 traffic classes */
@@ -10176,7 +10255,7 @@ static LIST_HEAD(ixgbe_block_cb_list);
static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
switch (type) {
case TC_SETUP_BLOCK:
@@ -10204,7 +10283,7 @@ void ixgbe_sriov_reinit(struct ixgbe_adapter *adapter)
#endif
void ixgbe_do_reset(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (netif_running(netdev))
ixgbe_reinit_locked(adapter);
@@ -10215,7 +10294,7 @@ void ixgbe_do_reset(struct net_device *netdev)
static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
netdev_features_t features)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
/* If Rx checksum is disabled, then RSC/LRO should also be disabled */
if (!(features & NETIF_F_RXCSUM))
@@ -10252,7 +10331,7 @@ static void ixgbe_reset_l2fw_offload(struct ixgbe_adapter *adapter)
static int ixgbe_set_features(struct net_device *netdev,
netdev_features_t features)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
netdev_features_t changed = netdev->features ^ features;
bool need_reset = false;
@@ -10328,7 +10407,7 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
{
/* guarantee we can provide a unique filter for the unicast address */
if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) {
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
u16 pool = VMDQ_P(0);
if (netdev_uc_count(dev) >= ixgbe_available_rars(adapter, pool))
@@ -10416,7 +10495,7 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
struct nlmsghdr *nlh, u16 flags,
struct netlink_ext_ack *extack)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct nlattr *attr, *br_spec;
int rem;
@@ -10444,7 +10523,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev,
u32 filter_mask, int nlflags)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
return 0;
@@ -10456,7 +10535,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
{
struct ixgbe_adapter *adapter = netdev_priv(pdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(pdev);
struct ixgbe_fwd_adapter *accel;
int tcs = adapter->hw_tcs ? : 1;
int pool, err;
@@ -10553,7 +10632,7 @@ static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
{
struct ixgbe_fwd_adapter *accel = priv;
struct ixgbe_adapter *adapter = netdev_priv(pdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(pdev);
unsigned int rxbase = accel->rx_base_queue;
unsigned int i;
@@ -10631,7 +10710,7 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
{
int i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct bpf_prog *old_prog;
bool need_reset;
int num_queues;
@@ -10703,7 +10782,7 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
static int ixgbe_xdp(struct net_device *dev, struct netdev_bpf *xdp)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
switch (xdp->command) {
case XDP_SETUP_PROG:
@@ -10738,7 +10817,7 @@ void ixgbe_xdp_ring_update_tail_locked(struct ixgbe_ring *ring)
static int ixgbe_xdp_xmit(struct net_device *dev, int n,
struct xdp_frame **frames, u32 flags)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_ring *ring;
int nxmit = 0;
int i;
@@ -11146,7 +11225,7 @@ bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
* format to display. The FW version is taken from the EEPROM/NVM.
*
*/
static void ixgbe_set_fw_version_e610(struct ixgbe_adapter *adapter)
void ixgbe_set_fw_version_e610(struct ixgbe_adapter *adapter)
{
struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
@@ -11196,6 +11275,65 @@ static void ixgbe_set_fw_version(struct ixgbe_adapter *adapter)
"0x%08x", nvm_ver.etk_id);
}
/**
* ixgbe_recovery_probe - Handle FW recovery mode during probe
* @adapter: the adapter private structure
*
* Perform limited driver initialization when FW error is detected.
*
* Return: 0 on successful probe for E610, -EIO if recovery mode is detected
* for non-E610 adapter, error status code on any other case.
*/
static int ixgbe_recovery_probe(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct ixgbe_hw *hw = &adapter->hw;
bool disable_dev;
int err = -EIO;
if (hw->mac.type != ixgbe_mac_e610)
goto clean_up_probe;
ixgbe_get_hw_control(adapter);
mutex_init(&hw->aci.lock);
err = ixgbe_get_flash_data(&adapter->hw);
if (err)
goto shutdown_aci;
timer_setup(&adapter->service_timer, ixgbe_service_timer, 0);
INIT_WORK(&adapter->service_task, ixgbe_recovery_service_task);
set_bit(__IXGBE_SERVICE_INITED, &adapter->state);
clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state);
if (hw->mac.ops.get_bus_info)
hw->mac.ops.get_bus_info(hw);
pci_set_drvdata(pdev, adapter);
/* We are creating devlink interface so NIC can be managed,
* e.g. new NVM image loaded
*/
devl_lock(adapter->devlink);
ixgbe_devlink_register_port(adapter);
SET_NETDEV_DEVLINK_PORT(adapter->netdev,
&adapter->devlink_port);
devl_register(adapter->devlink);
devl_unlock(adapter->devlink);
return 0;
shutdown_aci:
mutex_destroy(&adapter->hw.aci.lock);
ixgbe_release_hw_control(adapter);
devlink_free(adapter->devlink);
clean_up_probe:
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
free_netdev(netdev);
pci_release_mem_regions(pdev);
if (disable_dev)
pci_disable_device(pdev);
return err;
}
/**
* ixgbe_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -11210,6 +11348,7 @@ static void ixgbe_set_fw_version(struct ixgbe_adapter *adapter)
static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct ixgbe_netdevice_priv *netdev_priv_wrapper;
struct ixgbe_adapter *adapter = NULL;
struct ixgbe_hw *hw;
const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
@@ -11263,7 +11402,13 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
indices = IXGBE_MAX_RSS_INDICES_X550;
}
netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), indices);
adapter = ixgbe_allocate_devlink(&pdev->dev);
if (IS_ERR(adapter)) {
err = PTR_ERR(adapter);
goto err_devlink;
}
netdev = alloc_etherdev_mq(sizeof(*netdev_priv_wrapper), indices);
if (!netdev) {
err = -ENOMEM;
goto err_alloc_etherdev;
@@ -11271,7 +11416,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_NETDEV_DEV(netdev, &pdev->dev);
adapter = netdev_priv(netdev);
netdev_priv_wrapper = netdev_priv(netdev);
netdev_priv_wrapper->adapter = adapter;
adapter->netdev = netdev;
adapter->pdev = pdev;
@@ -11326,10 +11472,21 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_sw_init;
/* Make sure the SWFW semaphore is in a valid state */
if (hw->mac.ops.init_swfw_sync)
hw->mac.ops.init_swfw_sync(hw);
if (ixgbe_check_fw_error(adapter))
return ixgbe_recovery_probe(adapter);
if (adapter->hw.mac.type == ixgbe_mac_e610) {
err = ixgbe_get_caps(&adapter->hw);
if (err)
dev_err(&pdev->dev, "ixgbe_get_caps failed %d\n", err);
err = ixgbe_get_flash_data(&adapter->hw);
if (err)
goto err_sw_init;
}
if (adapter->hw.mac.type == ixgbe_mac_82599EB)
@@ -11348,10 +11505,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
/* Make sure the SWFW semaphore is in a valid state */
if (hw->mac.ops.init_swfw_sync)
hw->mac.ops.init_swfw_sync(hw);
/* Make it possible the adapter to be woken up via WOL */
switch (adapter->hw.mac.type) {
case ixgbe_mac_82599EB:
@@ -11504,11 +11657,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
netdev->features |= NETIF_F_LRO;
if (ixgbe_check_fw_error(adapter)) {
err = -EIO;
goto err_sw_init;
}
/* make sure the EEPROM is good */
if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) {
e_dev_err("The EEPROM Checksum Is Not Valid\n");
@@ -11591,7 +11739,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (expected_gts > 0)
ixgbe_check_minimum_link(adapter, expected_gts);
err = ixgbe_read_pba_string_generic(hw, part_str, sizeof(part_str));
err = hw->eeprom.ops.read_pba_string(hw, part_str, sizeof(part_str));
if (err)
strscpy(part_str, "Unknown", sizeof(part_str));
if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
@@ -11617,6 +11765,11 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
strcpy(netdev->name, "eth%d");
pci_set_drvdata(pdev, adapter);
devl_lock(adapter->devlink);
ixgbe_devlink_register_port(adapter);
SET_NETDEV_DEVLINK_PORT(adapter->netdev, &adapter->devlink_port);
err = register_netdev(netdev);
if (err)
goto err_register;
@@ -11671,11 +11824,15 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_netdev;
devl_register(adapter->devlink);
devl_unlock(adapter->devlink);
return 0;
err_netdev:
unregister_netdev(netdev);
err_register:
devl_port_unregister(&adapter->devlink_port);
devl_unlock(adapter->devlink);
ixgbe_release_hw_control(adapter);
ixgbe_clear_interrupt_scheme(adapter);
if (hw->mac.type == ixgbe_mac_e610)
@@ -11692,7 +11849,9 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
free_netdev(netdev);
err_alloc_etherdev:
devlink_free(adapter->devlink);
pci_release_mem_regions(pdev);
err_devlink:
err_pci_reg:
err_dma:
if (!adapter || disable_dev)
@@ -11721,6 +11880,8 @@ static void ixgbe_remove(struct pci_dev *pdev)
return;
netdev = adapter->netdev;
devl_lock(adapter->devlink);
devl_unregister(adapter->devlink);
ixgbe_dbg_adapter_exit(adapter);
set_bit(__IXGBE_REMOVING, &adapter->state);
@@ -11756,6 +11917,10 @@ static void ixgbe_remove(struct pci_dev *pdev)
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
devl_port_unregister(&adapter->devlink_port);
devl_unlock(adapter->devlink);
devlink_free(adapter->devlink);
ixgbe_stop_ipsec_offload(adapter);
ixgbe_clear_interrupt_scheme(adapter);

View File

@@ -1418,7 +1418,7 @@ void ixgbe_set_all_vfs(struct ixgbe_adapter *adapter)
int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
int retval;
if (vf >= adapter->num_vfs)
@@ -1526,7 +1526,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
u8 qos, __be16 vlan_proto)
{
int err = 0;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7))
return -EINVAL;
@@ -1644,7 +1644,7 @@ void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter)
int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate,
int max_tx_rate)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
int link_speed;
/* verify VF is active */
@@ -1679,7 +1679,7 @@ int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate,
int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
struct ixgbe_hw *hw = &adapter->hw;
if (vf >= adapter->num_vfs)
@@ -1757,7 +1757,7 @@ void ixgbe_set_vf_link_state(struct ixgbe_adapter *adapter, int vf, int state)
**/
int ixgbe_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
int ret = 0;
if (vf < 0 || vf >= adapter->num_vfs) {
@@ -1794,7 +1794,7 @@ int ixgbe_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state)
int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf,
bool setting)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
/* This operation is currently supported only for 82599 and x540
* devices.
@@ -1813,7 +1813,7 @@ int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf,
int ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (vf >= adapter->num_vfs)
return -EINVAL;
@@ -1836,7 +1836,7 @@ int ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
if (vf >= adapter->num_vfs)
return -EINVAL;
ivi->vf = vf;

View File

@@ -3446,6 +3446,8 @@ struct ixgbe_eeprom_operations {
int (*validate_checksum)(struct ixgbe_hw *, u16 *);
int (*update_checksum)(struct ixgbe_hw *);
int (*calc_checksum)(struct ixgbe_hw *);
int (*read_pba_string)(struct ixgbe_hw *hw, u8 *pba_num,
u32 pba_num_size);
};
struct ixgbe_mac_operations {
@@ -3454,6 +3456,7 @@ struct ixgbe_mac_operations {
int (*start_hw)(struct ixgbe_hw *);
int (*clear_hw_cntrs)(struct ixgbe_hw *);
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
int (*get_fw_ver)(struct ixgbe_hw *hw);
int (*get_mac_addr)(struct ixgbe_hw *, u8 *);
int (*get_san_mac_addr)(struct ixgbe_hw *, u8 *);
int (*get_device_caps)(struct ixgbe_hw *, u16 *);
@@ -3522,6 +3525,8 @@ struct ixgbe_mac_operations {
int (*get_thermal_sensor_data)(struct ixgbe_hw *);
int (*init_thermal_sensor_thresh)(struct ixgbe_hw *hw);
bool (*fw_recovery_mode)(struct ixgbe_hw *hw);
bool (*fw_rollback_mode)(struct ixgbe_hw *hw);
int (*get_nvm_ver)(struct ixgbe_hw *hw, struct ixgbe_nvm_info *nvm);
void (*disable_rx)(struct ixgbe_hw *hw);
void (*enable_rx)(struct ixgbe_hw *hw);
void (*set_source_address_pruning)(struct ixgbe_hw *, bool,

View File

@@ -10,11 +10,75 @@
#define IXGBE_MAX_VSI 768
/* Checksum and Shadow RAM pointers */
#define E610_SR_SW_CHECKSUM_WORD 0x3F
#define IXGBE_E610_SR_NVM_CTRL_WORD 0x00
#define IXGBE_E610_SR_PBA_BLOCK_PTR 0x16
#define IXGBE_E610_SR_PBA_BLOCK_MASK GENMASK(15, 8)
#define IXGBE_E610_SR_NVM_DEV_STARTER_VER 0x18
#define IXGBE_E610_SR_NVM_EETRACK_LO 0x2D
#define IXGBE_E610_SR_NVM_EETRACK_HI 0x2E
#define IXGBE_E610_NVM_VER_LO_MASK GENMASK(7, 0)
#define IXGBE_E610_NVM_VER_HI_MASK GENMASK(15, 12)
#define IXGBE_E610_SR_SW_CHECKSUM_WORD 0x3F
#define IXGBE_E610_SR_PFA_PTR 0x40
#define IXGBE_E610_SR_1ST_NVM_BANK_PTR 0x42
#define IXGBE_E610_SR_NVM_BANK_SIZE 0x43
#define IXGBE_E610_SR_1ST_OROM_BANK_PTR 0x44
#define IXGBE_E610_SR_OROM_BANK_SIZE 0x45
#define IXGBE_E610_SR_NETLIST_BANK_PTR 0x46
#define IXGBE_E610_SR_NETLIST_BANK_SIZE 0x47
/* The OROM version topology */
#define IXGBE_OROM_VER_PATCH_MASK GENMASK_ULL(7, 0)
#define IXGBE_OROM_VER_BUILD_MASK GENMASK_ULL(23, 8)
#define IXGBE_OROM_VER_MASK GENMASK_ULL(31, 24)
/* CSS Header words */
#define IXGBE_NVM_CSS_HDR_LEN_L 0x02
#define IXGBE_NVM_CSS_HDR_LEN_H 0x03
#define IXGBE_NVM_CSS_SREV_L 0x14
#define IXGBE_NVM_CSS_SREV_H 0x15
#define IXGBE_HDR_LEN_ROUNDUP 32
/* Length of Authentication header section in words */
#define IXGBE_NVM_AUTH_HEADER_LEN 0x08
/* Shadow RAM related */
#define IXGBE_SR_WORDS_IN_1KB 512
/* The Netlist ID Block is located after all of the Link Topology nodes. */
#define IXGBE_NETLIST_ID_BLK_SIZE 0x30
#define IXGBE_NETLIST_ID_BLK_OFFSET(n) IXGBE_NETLIST_LINK_TOPO_OFFSET(0x0004 + 2 * (n))
/* netlist ID block field offsets (word offsets) */
#define IXGBE_NETLIST_ID_BLK_MAJOR_VER_LOW 0x02
#define IXGBE_NETLIST_ID_BLK_MAJOR_VER_HIGH 0x03
#define IXGBE_NETLIST_ID_BLK_MINOR_VER_LOW 0x04
#define IXGBE_NETLIST_ID_BLK_MINOR_VER_HIGH 0x05
#define IXGBE_NETLIST_ID_BLK_TYPE_LOW 0x06
#define IXGBE_NETLIST_ID_BLK_TYPE_HIGH 0x07
#define IXGBE_NETLIST_ID_BLK_REV_LOW 0x08
#define IXGBE_NETLIST_ID_BLK_REV_HIGH 0x09
#define IXGBE_NETLIST_ID_BLK_SHA_HASH_WORD(n) (0x0A + (n))
#define IXGBE_NETLIST_ID_BLK_CUST_VER 0x2F
/* The Link Topology Netlist section is stored as a series of words. It is
* stored in the NVM as a TLV, with the first two words containing the type
* and length.
*/
#define IXGBE_NETLIST_LINK_TOPO_MOD_ID 0x011B
#define IXGBE_NETLIST_TYPE_OFFSET 0x0000
#define IXGBE_NETLIST_LEN_OFFSET 0x0001
/* The Link Topology section follows the TLV header. When reading the netlist
* using ixgbe_read_netlist_module, we need to account for the 2-word TLV
* header.
*/
#define IXGBE_NETLIST_LINK_TOPO_OFFSET(n) ((n) + 2)
#define IXGBE_LINK_TOPO_MODULE_LEN IXGBE_NETLIST_LINK_TOPO_OFFSET(0x0000)
#define IXGBE_LINK_TOPO_NODE_COUNT IXGBE_NETLIST_LINK_TOPO_OFFSET(0x0001)
#define IXGBE_LINK_TOPO_NODE_COUNT_M GENMASK_ULL(9, 0)
/* Firmware Status Register (GL_FWSTS) */
#define GL_FWSTS 0x00083048 /* Reset Source: POR */
#define GL_FWSTS_EP_PF0 BIT(24)
@@ -24,11 +88,23 @@
#define GLNVM_GENS 0x000B6100 /* Reset Source: POR */
#define GLNVM_GENS_SR_SIZE_M GENMASK(7, 5)
#define IXGBE_GL_MNG_FWSM 0x000B6134 /* Reset Source: POR */
#define IXGBE_GL_MNG_FWSM_RECOVERY_M BIT(1)
#define IXGBE_GL_MNG_FWSM_ROLLBACK_M BIT(2)
/* Flash Access Register */
#define IXGBE_GLNVM_FLA 0x000B6108 /* Reset Source: POR */
#define IXGBE_GLNVM_FLA_LOCKED_S 6
#define IXGBE_GLNVM_FLA_LOCKED_M BIT(6)
/* Auxiliary field, mask and shift definition for Shadow RAM and NVM Flash */
#define IXGBE_SR_CTRL_WORD_1_M GENMASK(7, 6)
#define IXGBE_SR_CTRL_WORD_VALID BIT(0)
#define IXGBE_SR_CTRL_WORD_OROM_BANK BIT(3)
#define IXGBE_SR_CTRL_WORD_NETLIST_BANK BIT(4)
#define IXGBE_SR_CTRL_WORD_NVM_BANK BIT(5)
#define IXGBE_SR_NVM_PTR_4KB_UNITS BIT(15)
/* Admin Command Interface (ACI) registers */
#define IXGBE_PF_HIDA(_i) (0x00085000 + ((_i) * 4))
#define IXGBE_PF_HIDA_2(_i) (0x00085020 + ((_i) * 4))
@@ -40,6 +116,10 @@
#define IXGBE_PF_HICR_SV BIT(2)
#define IXGBE_PF_HICR_EV BIT(3)
#define IXGBE_FW_API_VER_MAJOR 0x01
#define IXGBE_FW_API_VER_MINOR 0x07
#define IXGBE_FW_API_VER_DIFF_ALLOWED 0x02
#define IXGBE_ACI_DESC_SIZE 32
#define IXGBE_ACI_DESC_SIZE_IN_DWORDS (IXGBE_ACI_DESC_SIZE / BYTES_PER_DWORD)
@@ -761,6 +841,8 @@ struct ixgbe_aci_cmd_nvm {
#define IXGBE_ACI_NVM_MAX_OFFSET 0xFFFFFF
__le16 offset_low;
u8 offset_high; /* For Write Activate offset_high is used as flags2 */
#define IXGBE_ACI_NVM_OFFSET_HI_A_MASK GENMASK(15, 8)
#define IXGBE_ACI_NVM_OFFSET_HI_U_MASK GENMASK(23, 16)
u8 cmd_flags;
#define IXGBE_ACI_NVM_LAST_CMD BIT(0)
#define IXGBE_ACI_NVM_PCIR_REQ BIT(0) /* Used by NVM Write reply */
@@ -776,6 +858,9 @@ struct ixgbe_aci_cmd_nvm {
#define IXGBE_ACI_NVM_PERST_FLAG 1
#define IXGBE_ACI_NVM_EMPR_FLAG 2
#define IXGBE_ACI_NVM_EMPR_ENA BIT(0) /* Write Activate reply only */
#define IXGBE_ACI_NVM_NO_PRESERVATION 0x0
#define IXGBE_ACI_NVM_PRESERVE_SELECTED 0x6
/* For Write Activate, several flags are sent as part of a separate
* flags2 field using a separate byte. For simplicity of the software
* interface, we pass the flags as a 16 bit value so these flags are
@@ -805,6 +890,63 @@ struct ixgbe_aci_cmd_nvm_checksum {
u8 rsvd2[12];
};
/* Used for NVM Set Package Data command - 0x070A */
struct ixgbe_aci_cmd_nvm_pkg_data {
u8 reserved[3];
u8 cmd_flags;
#define IXGBE_ACI_NVM_PKG_DELETE BIT(0) /* used for command call */
u32 reserved1;
__le32 addr_high;
__le32 addr_low;
};
/* Used for Pass Component Table command - 0x070B */
struct ixgbe_aci_cmd_nvm_pass_comp_tbl {
u8 component_response; /* Response only */
#define IXGBE_ACI_NVM_PASS_COMP_CAN_BE_UPDATED 0x0
#define IXGBE_ACI_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE 0x1
#define IXGBE_ACI_NVM_PASS_COMP_CAN_NOT_BE_UPDATED 0x2
#define IXGBE_ACI_NVM_PASS_COMP_PARTIAL_CHECK 0x3
u8 component_response_code; /* Response only */
#define IXGBE_ACI_NVM_PASS_COMP_CAN_BE_UPDATED_CODE 0x0
#define IXGBE_ACI_NVM_PASS_COMP_STAMP_IDENTICAL_CODE 0x1
#define IXGBE_ACI_NVM_PASS_COMP_STAMP_LOWER 0x2
#define IXGBE_ACI_NVM_PASS_COMP_INVALID_STAMP_CODE 0x3
#define IXGBE_ACI_NVM_PASS_COMP_CONFLICT_CODE 0x4
#define IXGBE_ACI_NVM_PASS_COMP_PRE_REQ_NOT_MET_CODE 0x5
#define IXGBE_ACI_NVM_PASS_COMP_NOT_SUPPORTED_CODE 0x6
#define IXGBE_ACI_NVM_PASS_COMP_CANNOT_DOWNGRADE_CODE 0x7
#define IXGBE_ACI_NVM_PASS_COMP_INCOMPLETE_IMAGE_CODE 0x8
#define IXGBE_ACI_NVM_PASS_COMP_VER_STR_IDENTICAL_CODE 0xA
#define IXGBE_ACI_NVM_PASS_COMP_VER_STR_LOWER_CODE 0xB
u8 reserved;
u8 transfer_flag;
__le32 reserved1;
__le32 addr_high;
__le32 addr_low;
};
struct ixgbe_aci_cmd_nvm_comp_tbl {
__le16 comp_class;
#define NVM_COMP_CLASS_ALL_FW 0x000A
__le16 comp_id;
#define NVM_COMP_ID_OROM 0x5
#define NVM_COMP_ID_NVM 0x6
#define NVM_COMP_ID_NETLIST 0x8
u8 comp_class_idx;
#define FWU_COMP_CLASS_IDX_NOT_USE 0x0
__le32 comp_cmp_stamp;
u8 cvs_type;
#define NVM_CVS_TYPE_ASCII 0x1
u8 cvs_len;
u8 cvs[]; /* Component Version String */
} __packed;
/**
* struct ixgbe_aci_desc - Admin Command (AC) descriptor
* @flags: IXGBE_ACI_FLAG_* flags
@@ -848,6 +990,8 @@ struct ixgbe_aci_desc {
struct ixgbe_aci_cmd_sff_eeprom read_write_sff_param;
struct ixgbe_aci_cmd_nvm nvm;
struct ixgbe_aci_cmd_nvm_checksum nvm_checksum;
struct ixgbe_aci_cmd_nvm_pkg_data pkg_data;
struct ixgbe_aci_cmd_nvm_pass_comp_tbl pass_comp_tbl;
} params;
};
@@ -984,6 +1128,16 @@ struct ixgbe_hw_caps {
#define IXGBE_EXT_TOPO_DEV_IMG_PROG_EN BIT(1)
} __packed;
#define IXGBE_OROM_CIV_SIGNATURE "$CIV"
struct ixgbe_orom_civd_info {
u8 signature[4]; /* Must match ASCII '$CIV' characters */
u8 checksum; /* Simple modulo 256 sum of all structure bytes must equal 0 */
__le32 combo_ver; /* Combo Image Version number */
u8 combo_name_len; /* Length of the unicode combo image version string, max of 32 */
__le16 combo_name[32]; /* Unicode string representing the Combo Image version */
};
/* Function specific capabilities */
struct ixgbe_hw_func_caps {
u32 num_allocd_vfs; /* Number of allocated VFs */
@@ -1015,6 +1169,11 @@ struct ixgbe_aci_info {
enum ixgbe_aci_err last_status; /* last status of sent admin command */
};
enum ixgbe_bank_select {
IXGBE_ACTIVE_FLASH_BANK,
IXGBE_INACTIVE_FLASH_BANK,
};
/* Option ROM version information */
struct ixgbe_orom_info {
u8 major; /* Major version of OROM */

View File

@@ -894,6 +894,7 @@ static const struct ixgbe_eeprom_operations eeprom_ops_X540 = {
.calc_checksum = &ixgbe_calc_eeprom_checksum_X540,
.validate_checksum = &ixgbe_validate_eeprom_checksum_X540,
.update_checksum = &ixgbe_update_eeprom_checksum_X540,
.read_pba_string = &ixgbe_read_pba_string_generic,
};
static const struct ixgbe_phy_operations phy_ops_X540 = {

View File

@@ -3959,6 +3959,7 @@ static const struct ixgbe_mac_operations mac_ops_x550em_a_fw = {
.validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \
.update_checksum = &ixgbe_update_eeprom_checksum_X550, \
.calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \
.read_pba_string = &ixgbe_read_pba_string_generic, \
static const struct ixgbe_eeprom_operations eeprom_ops_X550 = {
X550_COMMON_EEP

View File

@@ -508,7 +508,7 @@ bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
int ixgbe_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
struct ixgbe_ring *ring;
if (test_bit(__IXGBE_DOWN, &adapter->state))

View File

@@ -775,7 +775,7 @@ static int devlink_info_version_put(struct devlink_info_req *req, int attr,
req->version_cb(version_name, version_type,
req->version_cb_priv);
if (!req->msg)
if (!req->msg || !*version_value)
return 0;
nest = nla_nest_start_noflag(req->msg, attr);