Commit adbea1a5 authored by David S. Miller's avatar David S. Miller

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

Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2020-03-21

Implement basic support for the devlink interface in the ice driver.
Additionally pave some necessary changes for adding a devlink region that
exposes the NVM contents.

This series first contains 5 patches for enabling and implementing full NVM
read access via the ETHTOOL_GEEPROM interface. This includes some cleanup of
endian-types, a new function for reading from the NVM and Shadow RAM as a flat
addressable space, a function to calculate the available flash size during
load, and a change to how some of the NVM version fields are stored in the
ice_nvm_info structure.

Following this is 3 patches for implementing devlink support. First, one patch
which implements the basic framework and introduces the ice_devlink.c file.
Second, a patch to implement basic .info_get support. Finally, a patch which
reads the device PBA identifier and reports it as the `board.id` value in the
.info_get response.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 08e8b91c e961b679
...@@ -98,3 +98,8 @@ fw.roce ...@@ -98,3 +98,8 @@ fw.roce
RoCE firmware version which is responsible for handling roce RoCE firmware version which is responsible for handling roce
management. management.
fw.bundle_id
------------
Unique identifier of the entire firmware bundle.
.. SPDX-License-Identifier: GPL-2.0
===================
ice devlink support
===================
This document describes the devlink features implemented by the ``ice``
device driver.
Info versions
=============
The ``ice`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 5 5 5 90
* - Name
- Type
- Example
- Description
* - ``board.id``
- fixed
- K65390-000
- The Product Board Assembly (PBA) identifier of the board.
* - ``fw.mgmt``
- running
- 2.1.7
- 3-digit version number of the management firmware that controls the
PHY, link, etc.
* - ``fw.mgmt.api``
- running
- 1.5
- 2-digit version number of the API exported over the AdminQ by the
management firmware. Used by the driver to identify what commands
are supported.
* - ``fw.mgmt.build``
- running
- 0x305d955f
- Unique identifier of the source for the management firmware.
* - ``fw.undi``
- running
- 1.2581.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.psid.api``
- running
- 0.80
- Version defining the format of the flash contents.
* - ``fw.bundle_id``
- running
- 0x80002ec0
- Unique identifier of the firmware image file that was loaded onto
the device. Also referred to as the EETRACK identifier of the NVM.
* - ``fw.app.name``
- running
- ICE OS Default Package
- The name of the DDP package that is active in the device. The DDP
package is loaded by the driver during initialization. Each varation
of DDP package shall have a unique name.
* - ``fw.app``
- running
- 1.3.1.0
- The version of the DDP package that is active in the device. Note
that both the name (as reported by ``fw.app.name``) and version are
required to uniquely identify the package.
...@@ -32,6 +32,7 @@ parameters, info versions, and other features it supports. ...@@ -32,6 +32,7 @@ parameters, info versions, and other features it supports.
bnxt bnxt
ionic ionic
ice
mlx4 mlx4
mlx5 mlx5
mlxsw mlxsw
......
...@@ -294,6 +294,7 @@ config ICE ...@@ -294,6 +294,7 @@ config ICE
tristate "Intel(R) Ethernet Connection E800 Series Support" tristate "Intel(R) Ethernet Connection E800 Series Support"
default n default n
depends on PCI_MSI depends on PCI_MSI
select NET_DEVLINK
---help--- ---help---
This driver supports Intel(R) Ethernet Connection E800 Series of This driver supports Intel(R) Ethernet Connection E800 Series of
devices. For more information on how to identify your adapter, go devices. For more information on how to identify your adapter, go
......
...@@ -19,6 +19,7 @@ ice-y := ice_main.o \ ...@@ -19,6 +19,7 @@ ice-y := ice_main.o \
ice_txrx.o \ ice_txrx.o \
ice_flex_pipe.o \ ice_flex_pipe.o \
ice_flow.o \ ice_flow.o \
ice_devlink.o \
ice_ethtool.o ice_ethtool.o
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o
ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/avf/virtchnl.h> #include <linux/avf/virtchnl.h>
#include <net/devlink.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/xdp_sock.h> #include <net/xdp_sock.h>
#include "ice_devids.h" #include "ice_devids.h"
...@@ -347,6 +348,9 @@ enum ice_pf_flags { ...@@ -347,6 +348,9 @@ enum ice_pf_flags {
struct ice_pf { struct ice_pf {
struct pci_dev *pdev; struct pci_dev *pdev;
/* devlink port data */
struct devlink_port devlink_port;
/* OS reserved IRQ details */ /* OS reserved IRQ details */
struct msix_entry *msix_entries; struct msix_entry *msix_entries;
struct ice_res_tracker *irq_tracker; struct ice_res_tracker *irq_tracker;
......
...@@ -1232,6 +1232,7 @@ struct ice_aqc_sff_eeprom { ...@@ -1232,6 +1232,7 @@ struct ice_aqc_sff_eeprom {
* NVM Update commands (indirect 0x0703) * NVM Update commands (indirect 0x0703)
*/ */
struct ice_aqc_nvm { struct ice_aqc_nvm {
#define ICE_AQC_NVM_MAX_OFFSET 0xFFFFFF
__le16 offset_low; __le16 offset_low;
u8 offset_high; u8 offset_high;
u8 cmd_flags; u8 cmd_flags;
...@@ -1250,6 +1251,8 @@ struct ice_aqc_nvm { ...@@ -1250,6 +1251,8 @@ struct ice_aqc_nvm {
__le32 addr_low; __le32 addr_low;
}; };
#define ICE_AQC_NVM_START_POINT 0
/* NVM Checksum Command (direct, 0x0706) */ /* NVM Checksum Command (direct, 0x0706) */
struct ice_aqc_nvm_checksum { struct ice_aqc_nvm_checksum {
u8 flags; u8 flags;
...@@ -1764,6 +1767,7 @@ enum ice_aq_err { ...@@ -1764,6 +1767,7 @@ enum ice_aq_err {
ICE_AQ_RC_ENOMEM = 9, /* Out of memory */ ICE_AQ_RC_ENOMEM = 9, /* Out of memory */
ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */ ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */
ICE_AQ_RC_EEXIST = 13, /* Object already exists */ ICE_AQ_RC_EEXIST = 13, /* Object already exists */
ICE_AQ_RC_EINVAL = 14, /* Invalid argument */
ICE_AQ_RC_ENOSPC = 16, /* No space left or allocation failure */ ICE_AQ_RC_ENOSPC = 16, /* No space left or allocation failure */
ICE_AQ_RC_ENOSYS = 17, /* Function not implemented */ ICE_AQ_RC_ENOSYS = 17, /* Function not implemented */
ICE_AQ_RC_ENOSEC = 24, /* Missing security manifest */ ICE_AQ_RC_ENOSEC = 24, /* Missing security manifest */
......
...@@ -614,29 +614,6 @@ static void ice_get_itr_intrl_gran(struct ice_hw *hw) ...@@ -614,29 +614,6 @@ static void ice_get_itr_intrl_gran(struct ice_hw *hw)
} }
} }
/**
* ice_get_nvm_version - get cached NVM version data
* @hw: pointer to the hardware structure
* @oem_ver: 8 bit NVM version
* @oem_build: 16 bit NVM build number
* @oem_patch: 8 NVM patch number
* @ver_hi: high 8 bits of the NVM version
* @ver_lo: low 8 bits of the NVM version
*/
void
ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build,
u8 *oem_patch, u8 *ver_hi, u8 *ver_lo)
{
struct ice_nvm_info *nvm = &hw->nvm;
*oem_ver = (u8)((nvm->oem_ver & ICE_OEM_VER_MASK) >> ICE_OEM_VER_SHIFT);
*oem_patch = (u8)(nvm->oem_ver & ICE_OEM_VER_PATCH_MASK);
*oem_build = (u16)((nvm->oem_ver & ICE_OEM_VER_BUILD_MASK) >>
ICE_OEM_VER_BUILD_SHIFT);
*ver_hi = (nvm->ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT;
*ver_lo = (nvm->ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT;
}
/** /**
* ice_init_hw - main hardware initialization routine * ice_init_hw - main hardware initialization routine
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
...@@ -957,72 +934,6 @@ enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req) ...@@ -957,72 +934,6 @@ enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
return ice_check_reset(hw); return ice_check_reset(hw);
} }
/**
* ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA
* @hw: pointer to hardware structure
* @module_tlv: pointer to module TLV to return
* @module_tlv_len: pointer to module TLV length to return
* @module_type: module type requested
*
* Finds the requested sub module TLV type from the Preserved Field
* Area (PFA) and returns the TLV pointer and length. The caller can
* use these to read the variable length TLV value.
*/
enum ice_status
ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
u16 module_type)
{
enum ice_status status;
u16 pfa_len, pfa_ptr;
u16 next_tlv;
status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Preserved Field Array pointer.\n");
return status;
}
status = ice_read_sr_word(hw, pfa_ptr, &pfa_len);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n");
return status;
}
/* Starting with first TLV after PFA length, iterate through the list
* of TLVs to find the requested one.
*/
next_tlv = pfa_ptr + 1;
while (next_tlv < pfa_ptr + pfa_len) {
u16 tlv_sub_module_type;
u16 tlv_len;
/* Read TLV type */
status = ice_read_sr_word(hw, next_tlv, &tlv_sub_module_type);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV type.\n");
break;
}
/* Read TLV length */
status = ice_read_sr_word(hw, next_tlv + 1, &tlv_len);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n");
break;
}
if (tlv_sub_module_type == module_type) {
if (tlv_len) {
*module_tlv = next_tlv;
*module_tlv_len = tlv_len;
return 0;
}
return ICE_ERR_INVAL_SIZE;
}
/* Check next TLV, i.e. current TLV pointer + length + 2 words
* (for current TLV's type and length)
*/
next_tlv = next_tlv + tlv_len + 2;
}
/* Module does not exist */
return ICE_ERR_DOES_NOT_EXIST;
}
/** /**
* ice_copy_rxq_ctx_to_hw * ice_copy_rxq_ctx_to_hw
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
......
...@@ -15,9 +15,6 @@ enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw); ...@@ -15,9 +15,6 @@ enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw);
enum ice_status ice_init_hw(struct ice_hw *hw); enum ice_status ice_init_hw(struct ice_hw *hw);
void ice_deinit_hw(struct ice_hw *hw); void ice_deinit_hw(struct ice_hw *hw);
enum ice_status
ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
u16 module_type);
enum ice_status ice_check_reset(struct ice_hw *hw); enum ice_status ice_check_reset(struct ice_hw *hw);
enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req); enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req);
enum ice_status ice_create_all_ctrlq(struct ice_hw *hw); enum ice_status ice_create_all_ctrlq(struct ice_hw *hw);
...@@ -38,9 +35,6 @@ enum ice_status ...@@ -38,9 +35,6 @@ enum ice_status
ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res); ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res);
enum ice_status enum ice_status
ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res); ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res);
enum ice_status ice_init_nvm(struct ice_hw *hw);
enum ice_status
ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data);
enum ice_status enum ice_status
ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
...@@ -153,9 +147,6 @@ ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, ...@@ -153,9 +147,6 @@ ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
void void
ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
u64 *prev_stat, u64 *cur_stat); u64 *prev_stat, u64 *cur_stat);
void
ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build,
u8 *oem_patch, u8 *ver_hi, u8 *ver_lo);
enum ice_status enum ice_status
ice_sched_query_elem(struct ice_hw *hw, u32 node_teid, ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
struct ice_aqc_get_elem *buf); struct ice_aqc_get_elem *buf);
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020, Intel Corporation. */
#include "ice.h"
#include "ice_lib.h"
#include "ice_devlink.h"
static int ice_info_get_dsn(struct ice_pf *pf, char *buf, size_t len)
{
u8 dsn[8];
/* Copy the DSN into an array in Big Endian format */
put_unaligned_be64(pci_get_dsn(pf->pdev), dsn);
snprintf(buf, len, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
dsn[0], dsn[1], dsn[2], dsn[3],
dsn[4], dsn[5], dsn[6], dsn[7]);
return 0;
}
static int ice_info_pba(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_hw *hw = &pf->hw;
enum ice_status status;
status = ice_read_pba_string(hw, (u8 *)buf, len);
if (status)
return -EIO;
return 0;
}
static int ice_info_fw_mgmt(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_hw *hw = &pf->hw;
snprintf(buf, len, "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver,
hw->fw_patch);
return 0;
}
static int ice_info_fw_api(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_hw *hw = &pf->hw;
snprintf(buf, len, "%u.%u", hw->api_maj_ver, hw->api_min_ver);
return 0;
}
static int ice_info_fw_build(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_hw *hw = &pf->hw;
snprintf(buf, len, "0x%08x", hw->fw_build);
return 0;
}
static int ice_info_orom_ver(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_orom_info *orom = &pf->hw.nvm.orom;
snprintf(buf, len, "%u.%u.%u", orom->major, orom->build, orom->patch);
return 0;
}
static int ice_info_nvm_ver(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_nvm_info *nvm = &pf->hw.nvm;
snprintf(buf, len, "%x.%02x", nvm->major_ver, nvm->minor_ver);
return 0;
}
static int ice_info_eetrack(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_nvm_info *nvm = &pf->hw.nvm;
snprintf(buf, len, "0x%08x", nvm->eetrack);
return 0;
}
static int ice_info_ddp_pkg_name(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_hw *hw = &pf->hw;
snprintf(buf, len, "%s", hw->active_pkg_name);
return 0;
}
static int ice_info_ddp_pkg_version(struct ice_pf *pf, char *buf, size_t len)
{
struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver;
snprintf(buf, len, "%u.%u.%u.%u", pkg->major, pkg->minor, pkg->update,
pkg->draft);
return 0;
}
#define fixed(key, getter) { ICE_VERSION_FIXED, key, getter }
#define running(key, getter) { ICE_VERSION_RUNNING, key, getter }
enum ice_version_type {
ICE_VERSION_FIXED,
ICE_VERSION_RUNNING,
ICE_VERSION_STORED,
};
static const struct ice_devlink_version {
enum ice_version_type type;
const char *key;
int (*getter)(struct ice_pf *pf, char *buf, size_t len);
} ice_devlink_versions[] = {
fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba),
running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt),
running("fw.mgmt.api", ice_info_fw_api),
running("fw.mgmt.build", ice_info_fw_build),
running(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver),
running("fw.psid.api", ice_info_nvm_ver),
running(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack),
running("fw.app.name", ice_info_ddp_pkg_name),
running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version),
};
/**
* ice_devlink_info_get - .info_get devlink handler
* @devlink: devlink instance structure
* @req: the devlink info request
* @extack: extended netdev ack structure
*
* Callback for the devlink .info_get operation. Reports information about the
* device.
*
* Return: zero on success or an error code on failure.
*/
static int ice_devlink_info_get(struct devlink *devlink,
struct devlink_info_req *req,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
char buf[100];
size_t i;
int err;
err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name");
return err;
}
err = ice_info_get_dsn(pf, buf, sizeof(buf));
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to obtain serial number");
return err;
}
err = devlink_info_serial_number_put(req, buf);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number");
return err;
}
for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) {
enum ice_version_type type = ice_devlink_versions[i].type;
const char *key = ice_devlink_versions[i].key;
err = ice_devlink_versions[i].getter(pf, buf, sizeof(buf));
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info");
return err;
}
switch (type) {
case ICE_VERSION_FIXED:
err = devlink_info_version_fixed_put(req, key, buf);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version");
return err;
}
break;
case ICE_VERSION_RUNNING:
err = devlink_info_version_running_put(req, key, buf);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
return err;
}
break;
case ICE_VERSION_STORED:
err = devlink_info_version_stored_put(req, key, buf);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
return err;
}
break;
}
}
return 0;
}
static const struct devlink_ops ice_devlink_ops = {
.info_get = ice_devlink_info_get,
};
static void ice_devlink_free(void *devlink_ptr)
{
devlink_free((struct devlink *)devlink_ptr);
}
/**
* ice_allocate_pf - Allocate devlink and return PF structure pointer
* @dev: the device to allocate for
*
* Allocate a devlink instance for this device and return the private area as
* the PF structure. The devlink memory is kept track of through devres by
* adding an action to remove it when unwinding.
*/
struct ice_pf *ice_allocate_pf(struct device *dev)
{
struct devlink *devlink;
devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf));
if (!devlink)
return NULL;
/* Add an action to teardown the devlink when unwinding the driver */
if (devm_add_action(dev, ice_devlink_free, devlink)) {
devlink_free(devlink);
return NULL;
}
return devlink_priv(devlink);
}
/**
* ice_devlink_register - Register devlink interface for this PF
* @pf: the PF to register the devlink for.
*
* Register the devlink instance associated with this physical function.
*
* Return: zero on success or an error code on failure.
*/
int ice_devlink_register(struct ice_pf *pf)
{
struct devlink *devlink = priv_to_devlink(pf);
struct device *dev = ice_pf_to_dev(pf);
int err;
err = devlink_register(devlink, dev);
if (err) {
dev_err(dev, "devlink registration failed: %d\n", err);
return err;
}
return 0;
}
/**
* ice_devlink_unregister - Unregister devlink resources for this PF.
* @pf: the PF structure to cleanup
*
* Releases resources used by devlink and cleans up associated memory.
*/
void ice_devlink_unregister(struct ice_pf *pf)
{
devlink_unregister(priv_to_devlink(pf));
}
/**
* ice_devlink_create_port - Create a devlink port for this PF
* @pf: the PF to create a port for
*
* Create and register a devlink_port for this PF. Note that although each
* physical function is connected to a separate devlink instance, the port
* will still be numbered according to the physical function id.
*
* Return: zero on success or an error code on failure.
*/
int ice_devlink_create_port(struct ice_pf *pf)
{
struct devlink *devlink = priv_to_devlink(pf);
struct ice_vsi *vsi = ice_get_main_vsi(pf);
struct device *dev = ice_pf_to_dev(pf);
int err;
if (!vsi) {
dev_err(dev, "%s: unable to find main VSI\n", __func__);
return -EIO;
}
devlink_port_attrs_set(&pf->devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
pf->hw.pf_id, false, 0, NULL, 0);
err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id);
if (err) {
dev_err(dev, "devlink_port_register failed: %d\n", err);
return err;
}
return 0;
}
/**
* ice_devlink_destroy_port - Destroy the devlink_port for this PF
* @pf: the PF to cleanup
*
* Unregisters the devlink_port structure associated with this PF.
*/
void ice_devlink_destroy_port(struct ice_pf *pf)
{
devlink_port_type_clear(&pf->devlink_port);
devlink_port_unregister(&pf->devlink_port);
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019, Intel Corporation. */
#ifndef _ICE_DEVLINK_H_
#define _ICE_DEVLINK_H_
struct ice_pf *ice_allocate_pf(struct device *dev);
int ice_devlink_register(struct ice_pf *pf);
void ice_devlink_unregister(struct ice_pf *pf);
int ice_devlink_create_port(struct ice_pf *pf);
void ice_devlink_destroy_port(struct ice_pf *pf);
#endif /* _ICE_DEVLINK_H_ */
...@@ -167,11 +167,14 @@ static void ...@@ -167,11 +167,14 @@ static void
ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
{ {
struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_netdev_priv *np = netdev_priv(netdev);
u8 oem_ver, oem_patch, nvm_ver_hi, nvm_ver_lo;
struct ice_vsi *vsi = np->vsi; struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
u16 oem_build; struct ice_orom_info *orom;
struct ice_nvm_info *nvm;
nvm = &hw->nvm;
orom = &nvm->orom;
strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
strscpy(drvinfo->version, ice_drv_ver, sizeof(drvinfo->version)); strscpy(drvinfo->version, ice_drv_ver, sizeof(drvinfo->version));
...@@ -179,11 +182,9 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) ...@@ -179,11 +182,9 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
/* Display NVM version (from which the firmware version can be /* Display NVM version (from which the firmware version can be
* determined) which contains more pertinent information. * determined) which contains more pertinent information.
*/ */
ice_get_nvm_version(hw, &oem_ver, &oem_build, &oem_patch,
&nvm_ver_hi, &nvm_ver_lo);
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
"%x.%02x 0x%x %d.%d.%d", nvm_ver_hi, nvm_ver_lo, "%x.%02x 0x%x %d.%d.%d", nvm->major_ver, nvm->minor_ver,
hw->nvm.eetrack, oem_ver, oem_build, oem_patch); nvm->eetrack, orom->major, orom->build, orom->patch);
strscpy(drvinfo->bus_info, pci_name(pf->pdev), strscpy(drvinfo->bus_info, pci_name(pf->pdev),
sizeof(drvinfo->bus_info)); sizeof(drvinfo->bus_info));
...@@ -244,7 +245,7 @@ static int ice_get_eeprom_len(struct net_device *netdev) ...@@ -244,7 +245,7 @@ static int ice_get_eeprom_len(struct net_device *netdev)
struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_pf *pf = np->vsi->back; struct ice_pf *pf = np->vsi->back;
return (int)(pf->hw.nvm.sr_words * sizeof(u16)); return (int)pf->hw.nvm.flash_size;
} }
static int static int
...@@ -252,39 +253,46 @@ ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, ...@@ -252,39 +253,46 @@ ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
u8 *bytes) u8 *bytes)
{ {
struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_netdev_priv *np = netdev_priv(netdev);
u16 first_word, last_word, nwords;
struct ice_vsi *vsi = np->vsi; struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
enum ice_status status; enum ice_status status;
struct device *dev; struct device *dev;
int ret = 0; int ret = 0;
u16 *buf; u8 *buf;
dev = ice_pf_to_dev(pf); dev = ice_pf_to_dev(pf);
eeprom->magic = hw->vendor_id | (hw->device_id << 16); eeprom->magic = hw->vendor_id | (hw->device_id << 16);
netdev_dbg(netdev, "GEEPROM cmd 0x%08x, offset 0x%08x, len 0x%08x\n",
eeprom->cmd, eeprom->offset, eeprom->len);
first_word = eeprom->offset >> 1; buf = kzalloc(eeprom->len, GFP_KERNEL);
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
nwords = last_word - first_word + 1;
buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL);
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
status = ice_read_sr_buf(hw, first_word, &nwords, buf); status = ice_acquire_nvm(hw, ICE_RES_READ);
if (status) { if (status) {
dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n", dev_err(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
status, hw->adminq.sq_last_status); status, hw->adminq.sq_last_status);
eeprom->len = sizeof(u16) * nwords;
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len); status = ice_read_flat_nvm(hw, eeprom->offset, &eeprom->len, buf,
false);
if (status) {
dev_err(dev, "ice_read_flat_nvm failed, err %d aq_err %d\n",
status, hw->adminq.sq_last_status);
ret = -EIO;
goto release;
}
memcpy(bytes, buf, eeprom->len);
release:
ice_release_nvm(hw);
out: out:
devm_kfree(dev, buf); kfree(buf);
return ret; return ret;
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ice_lib.h" #include "ice_lib.h"
#include "ice_dcb_lib.h" #include "ice_dcb_lib.h"
#include "ice_dcb_nl.h" #include "ice_dcb_nl.h"
#include "ice_devlink.h"
#define DRV_VERSION_MAJOR 0 #define DRV_VERSION_MAJOR 0
#define DRV_VERSION_MINOR 8 #define DRV_VERSION_MINOR 8
...@@ -2371,10 +2372,16 @@ static int ice_cfg_netdev(struct ice_vsi *vsi) ...@@ -2371,10 +2372,16 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
int err; int err;
err = ice_devlink_create_port(pf);
if (err)
return err;
netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq, netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
vsi->alloc_rxq); vsi->alloc_rxq);
if (!netdev) if (!netdev) {
return -ENOMEM; err = -ENOMEM;
goto err_destroy_devlink_port;
}
vsi->netdev = netdev; vsi->netdev = netdev;
np = netdev_priv(netdev); np = netdev_priv(netdev);
...@@ -2404,7 +2411,9 @@ static int ice_cfg_netdev(struct ice_vsi *vsi) ...@@ -2404,7 +2411,9 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
err = register_netdev(vsi->netdev); err = register_netdev(vsi->netdev);
if (err) if (err)
return err; goto err_destroy_devlink_port;
devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev);
netif_carrier_off(vsi->netdev); netif_carrier_off(vsi->netdev);
...@@ -2412,6 +2421,11 @@ static int ice_cfg_netdev(struct ice_vsi *vsi) ...@@ -2412,6 +2421,11 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
netif_tx_stop_all_queues(vsi->netdev); netif_tx_stop_all_queues(vsi->netdev);
return 0; return 0;
err_destroy_devlink_port:
ice_devlink_destroy_port(pf);
return err;
} }
/** /**
...@@ -3184,7 +3198,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) ...@@ -3184,7 +3198,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
return err; return err;
} }
pf = devm_kzalloc(dev, sizeof(*pf), GFP_KERNEL); pf = ice_allocate_pf(dev);
if (!pf) if (!pf)
return -ENOMEM; return -ENOMEM;
...@@ -3222,6 +3236,12 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) ...@@ -3222,6 +3236,12 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M); pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);
err = ice_devlink_register(pf);
if (err) {
dev_err(dev, "ice_devlink_register failed: %d\n", err);
goto err_exit_unroll;
}
#ifndef CONFIG_DYNAMIC_DEBUG #ifndef CONFIG_DYNAMIC_DEBUG
if (debug < -1) if (debug < -1)
hw->debug_mask = debug; hw->debug_mask = debug;
...@@ -3354,6 +3374,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) ...@@ -3354,6 +3374,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
return 0; return 0;
err_alloc_sw_unroll: err_alloc_sw_unroll:
ice_devlink_destroy_port(pf);
set_bit(__ICE_SERVICE_DIS, pf->state); set_bit(__ICE_SERVICE_DIS, pf->state);
set_bit(__ICE_DOWN, pf->state); set_bit(__ICE_DOWN, pf->state);
devm_kfree(dev, pf->first_sw); devm_kfree(dev, pf->first_sw);
...@@ -3366,6 +3387,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) ...@@ -3366,6 +3387,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
ice_deinit_pf(pf); ice_deinit_pf(pf);
ice_deinit_hw(hw); ice_deinit_hw(hw);
err_exit_unroll: err_exit_unroll:
ice_devlink_unregister(pf);
pci_disable_pcie_error_reporting(pdev); pci_disable_pcie_error_reporting(pdev);
return err; return err;
} }
...@@ -3396,6 +3418,7 @@ static void ice_remove(struct pci_dev *pdev) ...@@ -3396,6 +3418,7 @@ static void ice_remove(struct pci_dev *pdev)
set_bit(__ICE_DOWN, pf->state); set_bit(__ICE_DOWN, pf->state);
ice_service_task_stop(pf); ice_service_task_stop(pf);
ice_devlink_destroy_port(pf);
ice_vsi_release_all(pf); ice_vsi_release_all(pf);
ice_free_irq_msix_misc(pf); ice_free_irq_msix_misc(pf);
ice_for_each_vsi(pf, i) { ice_for_each_vsi(pf, i) {
...@@ -3405,6 +3428,8 @@ static void ice_remove(struct pci_dev *pdev) ...@@ -3405,6 +3428,8 @@ static void ice_remove(struct pci_dev *pdev)
} }
ice_deinit_pf(pf); ice_deinit_pf(pf);
ice_deinit_hw(&pf->hw); ice_deinit_hw(&pf->hw);
ice_devlink_unregister(pf);
/* Issue a PFR as part of the prescribed driver unload flow. Do not /* Issue a PFR as part of the prescribed driver unload flow. Do not
* do it via ice_schedule_reset() since there is no need to rebuild * do it via ice_schedule_reset() since there is no need to rebuild
* and the service task is already stopped. * and the service task is already stopped.
......
This diff is collapsed.
...@@ -4,5 +4,17 @@ ...@@ -4,5 +4,17 @@
#ifndef _ICE_NVM_H_ #ifndef _ICE_NVM_H_
#define _ICE_NVM_H_ #define _ICE_NVM_H_
enum ice_status
ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access);
void ice_release_nvm(struct ice_hw *hw);
enum ice_status
ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
bool read_shadow_ram);
enum ice_status
ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
u16 module_type);
enum ice_status
ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size);
enum ice_status ice_init_nvm(struct ice_hw *hw);
enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data); enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data);
#endif /* _ICE_NVM_H_ */ #endif /* _ICE_NVM_H_ */
...@@ -239,12 +239,21 @@ struct ice_fc_info { ...@@ -239,12 +239,21 @@ struct ice_fc_info {
enum ice_fc_mode req_mode; /* FC mode requested by caller */ enum ice_fc_mode req_mode; /* FC mode requested by caller */
}; };
/* Option ROM version information */
struct ice_orom_info {
u8 major; /* Major version of OROM */
u8 patch; /* Patch version of OROM */
u16 build; /* Build version of OROM */
};
/* NVM Information */ /* NVM Information */
struct ice_nvm_info { struct ice_nvm_info {
u32 eetrack; /* NVM data version */ struct ice_orom_info orom; /* Option ROM version info */
u32 oem_ver; /* OEM version info */ u32 eetrack; /* NVM data version */
u16 sr_words; /* Shadow RAM size in words */ u16 sr_words; /* Shadow RAM size in words */
u16 ver; /* NVM package version */ u32 flash_size; /* Size of available flash in bytes */
u8 major_ver; /* major version of NVM package */
u8 minor_ver; /* minor version of dev starter */
u8 blank_nvm_mode; /* is NVM empty (no FW present) */ u8 blank_nvm_mode; /* is NVM empty (no FW present) */
}; };
...@@ -626,7 +635,8 @@ struct ice_hw_port_stats { ...@@ -626,7 +635,8 @@ struct ice_hw_port_stats {
/* Checksum and Shadow RAM pointers */ /* Checksum and Shadow RAM pointers */
#define ICE_SR_BOOT_CFG_PTR 0x132 #define ICE_SR_BOOT_CFG_PTR 0x132
#define ICE_NVM_OEM_VER_OFF 0x02 #define ICE_NVM_OROM_VER_OFF 0x02
#define ICE_SR_PBA_BLOCK_PTR 0x16
#define ICE_SR_NVM_DEV_STARTER_VER 0x18 #define ICE_SR_NVM_DEV_STARTER_VER 0x18
#define ICE_SR_NVM_EETRACK_LO 0x2D #define ICE_SR_NVM_EETRACK_LO 0x2D
#define ICE_SR_NVM_EETRACK_HI 0x2E #define ICE_SR_NVM_EETRACK_HI 0x2E
...@@ -634,12 +644,12 @@ struct ice_hw_port_stats { ...@@ -634,12 +644,12 @@ struct ice_hw_port_stats {
#define ICE_NVM_VER_LO_MASK (0xff << ICE_NVM_VER_LO_SHIFT) #define ICE_NVM_VER_LO_MASK (0xff << ICE_NVM_VER_LO_SHIFT)
#define ICE_NVM_VER_HI_SHIFT 12 #define ICE_NVM_VER_HI_SHIFT 12
#define ICE_NVM_VER_HI_MASK (0xf << ICE_NVM_VER_HI_SHIFT) #define ICE_NVM_VER_HI_MASK (0xf << ICE_NVM_VER_HI_SHIFT)
#define ICE_OEM_VER_PATCH_SHIFT 0 #define ICE_OROM_VER_PATCH_SHIFT 0
#define ICE_OEM_VER_PATCH_MASK (0xff << ICE_OEM_VER_PATCH_SHIFT) #define ICE_OROM_VER_PATCH_MASK (0xff << ICE_OROM_VER_PATCH_SHIFT)
#define ICE_OEM_VER_BUILD_SHIFT 8 #define ICE_OROM_VER_BUILD_SHIFT 8
#define ICE_OEM_VER_BUILD_MASK (0xffff << ICE_OEM_VER_BUILD_SHIFT) #define ICE_OROM_VER_BUILD_MASK (0xffff << ICE_OROM_VER_BUILD_SHIFT)
#define ICE_OEM_VER_SHIFT 24 #define ICE_OROM_VER_SHIFT 24
#define ICE_OEM_VER_MASK (0xff << ICE_OEM_VER_SHIFT) #define ICE_OROM_VER_MASK (0xff << ICE_OROM_VER_SHIFT)
#define ICE_SR_PFA_PTR 0x40 #define ICE_SR_PFA_PTR 0x40
#define ICE_SR_SECTOR_SIZE_IN_WORDS 0x800 #define ICE_SR_SECTOR_SIZE_IN_WORDS 0x800
#define ICE_SR_WORDS_IN_1KB 512 #define ICE_SR_WORDS_IN_1KB 512
......
...@@ -211,7 +211,7 @@ static const struct nfp_devlink_versions { ...@@ -211,7 +211,7 @@ static const struct nfp_devlink_versions {
enum nfp_nsp_versions id; enum nfp_nsp_versions id;
const char *key; const char *key;
} nfp_devlink_versions_nsp[] = { } nfp_devlink_versions_nsp[] = {
{ NFP_VERSIONS_BUNDLE, "fw.bundle_id", }, { NFP_VERSIONS_BUNDLE, DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, },
{ NFP_VERSIONS_BSP, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, }, { NFP_VERSIONS_BSP, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, },
{ NFP_VERSIONS_CPLD, "fw.cpld", }, { NFP_VERSIONS_CPLD, "fw.cpld", },
{ NFP_VERSIONS_APP, DEVLINK_INFO_VERSION_GENERIC_FW_APP, }, { NFP_VERSIONS_APP, DEVLINK_INFO_VERSION_GENERIC_FW_APP, },
......
...@@ -490,6 +490,8 @@ enum devlink_param_generic_id { ...@@ -490,6 +490,8 @@ enum devlink_param_generic_id {
#define DEVLINK_INFO_VERSION_GENERIC_FW_PSID "fw.psid" #define DEVLINK_INFO_VERSION_GENERIC_FW_PSID "fw.psid"
/* RoCE FW version */ /* RoCE FW version */
#define DEVLINK_INFO_VERSION_GENERIC_FW_ROCE "fw.roce" #define DEVLINK_INFO_VERSION_GENERIC_FW_ROCE "fw.roce"
/* Firmware bundle identifier */
#define DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID "fw.bundle_id"
struct devlink_region; struct devlink_region;
struct devlink_info_req; struct devlink_info_req;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment