2020-03-12 09:58:15 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/* Copyright (c) 2020, Intel Corporation. */
|
|
|
|
|
|
|
|
#include "ice.h"
|
2020-03-12 09:58:17 +08:00
|
|
|
#include "ice_lib.h"
|
2020-03-12 09:58:15 +08:00
|
|
|
#include "ice_devlink.h"
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
#include "ice_fw_update.h"
|
2020-03-12 09:58:15 +08:00
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
/* context for devlink info version reporting */
|
|
|
|
struct ice_info_ctx {
|
|
|
|
char buf[128];
|
2020-11-12 08:43:30 +08:00
|
|
|
struct ice_orom_info pending_orom;
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
struct ice_nvm_info pending_nvm;
|
2020-11-12 08:43:29 +08:00
|
|
|
struct ice_netlist_info pending_netlist;
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
struct ice_hw_dev_caps dev_caps;
|
2020-11-12 08:43:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* The following functions are used to format specific strings for various
|
|
|
|
* devlink info versions. The ctx parameter is used to provide the storage
|
|
|
|
* buffer, as well as any ancillary information calculated when the info
|
|
|
|
* request was made.
|
|
|
|
*
|
|
|
|
* If a version does not exist, for example when attempting to get the
|
|
|
|
* inactive version of flash when there is no pending update, the function
|
|
|
|
* should leave the buffer in the ctx structure empty and return 0.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
|
|
|
u8 dsn[8];
|
|
|
|
|
|
|
|
/* Copy the DSN into an array in Big Endian format */
|
|
|
|
put_unaligned_be64(pci_get_dsn(pf->pdev), dsn);
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:18 +08:00
|
|
|
{
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
enum ice_status status;
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf));
|
2020-03-12 09:58:18 +08:00
|
|
|
if (status)
|
2021-08-20 06:34:51 +08:00
|
|
|
/* We failed to locate the PBA, so just skip this entry */
|
|
|
|
dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %s\n",
|
|
|
|
ice_stat_str(status));
|
2020-03-12 09:58:18 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver,
|
2020-03-12 09:58:17 +08:00
|
|
|
hw->fw_patch);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u", hw->api_maj_ver, hw->api_min_ver);
|
2020-03-12 09:58:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
|
2020-03-12 09:58:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
2020-10-02 01:31:41 +08:00
|
|
|
struct ice_orom_info *orom = &pf->hw.flash.orom;
|
2020-03-12 09:58:17 +08:00
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", orom->major, orom->build, orom->patch);
|
2020-03-12 09:58:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:30 +08:00
|
|
|
static int
|
|
|
|
ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx)
|
|
|
|
{
|
|
|
|
struct ice_orom_info *orom = &ctx->pending_orom;
|
|
|
|
|
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_orom)
|
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
|
|
|
|
orom->major, orom->build, orom->patch);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
2020-10-02 01:31:41 +08:00
|
|
|
struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
|
2020-03-12 09:58:17 +08:00
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
|
2020-03-12 09:58:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
static int
|
|
|
|
ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx)
|
|
|
|
{
|
|
|
|
struct ice_nvm_info *nvm = &ctx->pending_nvm;
|
|
|
|
|
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
|
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
2020-10-02 01:31:41 +08:00
|
|
|
struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
|
2020-03-12 09:58:17 +08:00
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
|
2020-03-12 09:58:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
static int
|
|
|
|
ice_info_pending_eetrack(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx)
|
|
|
|
{
|
|
|
|
struct ice_nvm_info *nvm = &ctx->pending_nvm;
|
|
|
|
|
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
|
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name);
|
2020-03-12 09:58:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-03-12 09:58:17 +08:00
|
|
|
{
|
|
|
|
struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver;
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", pkg->major, pkg->minor, pkg->update,
|
2020-03-12 09:58:17 +08:00
|
|
|
pkg->draft);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-10-08 01:54:43 +08:00
|
|
|
{
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id);
|
2020-10-08 01:54:43 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-05-06 06:55:37 +08:00
|
|
|
{
|
2020-10-02 01:31:41 +08:00
|
|
|
struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
|
2020-05-06 06:55:37 +08:00
|
|
|
|
|
|
|
/* The netlist version fields are BCD formatted */
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", netlist->major, netlist->minor,
|
2020-05-06 06:55:37 +08:00
|
|
|
netlist->type >> 16, netlist->type & 0xFFFF, netlist->rev,
|
|
|
|
netlist->cust_ver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
static int ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
|
2020-05-06 06:55:37 +08:00
|
|
|
{
|
2020-10-02 01:31:41 +08:00
|
|
|
struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
|
2020-05-06 06:55:37 +08:00
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
|
2020-05-06 06:55:37 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:29 +08:00
|
|
|
static int
|
|
|
|
ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx)
|
|
|
|
{
|
|
|
|
struct ice_netlist_info *netlist = &ctx->pending_netlist;
|
|
|
|
|
|
|
|
/* The netlist version fields are BCD formatted */
|
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
|
|
|
|
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);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx)
|
|
|
|
{
|
|
|
|
struct ice_netlist_info *netlist = &ctx->pending_netlist;
|
|
|
|
|
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
|
|
|
|
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
#define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL }
|
|
|
|
#define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL }
|
|
|
|
#define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback }
|
|
|
|
|
|
|
|
/* The combined() macro inserts both the running entry as well as a stored
|
|
|
|
* entry. The running entry will always report the version from the active
|
|
|
|
* handler. The stored entry will first try the pending handler, and fallback
|
|
|
|
* to the active handler if the pending function does not report a version.
|
|
|
|
* The pending handler should check the status of a pending update for the
|
|
|
|
* relevant flash component. It should only fill in the buffer in the case
|
|
|
|
* where a valid pending version is available. This ensures that the related
|
|
|
|
* stored and running versions remain in sync, and that stored versions are
|
|
|
|
* correctly reported as expected.
|
|
|
|
*/
|
|
|
|
#define combined(key, active, pending) \
|
|
|
|
running(key, active), \
|
|
|
|
stored(key, pending, active)
|
2020-03-12 09:58:17 +08:00
|
|
|
|
|
|
|
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;
|
2020-11-12 08:43:24 +08:00
|
|
|
int (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx);
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
int (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx);
|
2020-03-12 09:58:17 +08:00
|
|
|
} ice_devlink_versions[] = {
|
2020-03-12 09:58:18 +08:00
|
|
|
fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba),
|
2020-03-12 09:58:17 +08:00
|
|
|
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),
|
2020-11-12 08:43:30 +08:00
|
|
|
combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver),
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver),
|
|
|
|
combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack),
|
2020-03-12 09:58:17 +08:00
|
|
|
running("fw.app.name", ice_info_ddp_pkg_name),
|
|
|
|
running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version),
|
2020-10-08 01:54:43 +08:00
|
|
|
running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id),
|
2020-11-12 08:43:29 +08:00
|
|
|
combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver),
|
|
|
|
combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build),
|
2020-03-12 09:58:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
2020-03-12 09:58:18 +08:00
|
|
|
* Return: zero on success or an error code on failure.
|
2020-03-12 09:58:17 +08:00
|
|
|
*/
|
|
|
|
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);
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
struct device *dev = ice_pf_to_dev(pf);
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
2020-11-12 08:43:24 +08:00
|
|
|
struct ice_info_ctx *ctx;
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
enum ice_status status;
|
2020-03-12 09:58:17 +08:00
|
|
|
size_t i;
|
|
|
|
int err;
|
|
|
|
|
2021-05-06 23:39:59 +08:00
|
|
|
err = ice_wait_for_reset(pf, 10 * HZ);
|
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting");
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
|
|
|
if (!ctx)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
/* discover capabilities first */
|
|
|
|
status = ice_discover_dev_caps(hw, &ctx->dev_caps);
|
|
|
|
if (status) {
|
2021-05-06 23:39:57 +08:00
|
|
|
dev_dbg(dev, "Failed to discover device capabilities, status %s aq_err %s\n",
|
|
|
|
ice_stat_str(status), ice_aq_str(hw->adminq.sq_last_status));
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities");
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
err = -EIO;
|
|
|
|
goto out_free_ctx;
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:30 +08:00
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_orom) {
|
|
|
|
status = ice_get_inactive_orom_ver(hw, &ctx->pending_orom);
|
|
|
|
if (status) {
|
|
|
|
dev_dbg(dev, "Unable to read inactive Option ROM version data, status %s aq_err %s\n",
|
|
|
|
ice_stat_str(status), ice_aq_str(hw->adminq.sq_last_status));
|
|
|
|
|
|
|
|
/* disable display of pending Option ROM */
|
|
|
|
ctx->dev_caps.common_cap.nvm_update_pending_orom = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) {
|
|
|
|
status = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
|
|
|
|
if (status) {
|
|
|
|
dev_dbg(dev, "Unable to read inactive NVM version data, status %s aq_err %s\n",
|
|
|
|
ice_stat_str(status), ice_aq_str(hw->adminq.sq_last_status));
|
|
|
|
|
|
|
|
/* disable display of pending Option ROM */
|
|
|
|
ctx->dev_caps.common_cap.nvm_update_pending_nvm = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:29 +08:00
|
|
|
if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) {
|
|
|
|
status = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
|
|
|
|
if (status) {
|
|
|
|
dev_dbg(dev, "Unable to read inactive Netlist version data, status %s aq_err %s\n",
|
|
|
|
ice_stat_str(status), ice_aq_str(hw->adminq.sq_last_status));
|
|
|
|
|
|
|
|
/* disable display of pending Option ROM */
|
|
|
|
ctx->dev_caps.common_cap.nvm_update_pending_netlist = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-12 09:58:17 +08:00
|
|
|
err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
|
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name");
|
2020-11-12 08:43:24 +08:00
|
|
|
goto out_free_ctx;
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
ice_info_get_dsn(pf, ctx);
|
2020-03-12 09:58:17 +08:00
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
err = devlink_info_serial_number_put(req, ctx->buf);
|
2020-03-12 09:58:17 +08:00
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number");
|
2020-11-12 08:43:24 +08:00
|
|
|
goto out_free_ctx;
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
memset(ctx->buf, 0, sizeof(ctx->buf));
|
|
|
|
|
|
|
|
err = ice_devlink_versions[i].getter(pf, ctx);
|
2020-03-12 09:58:17 +08:00
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info");
|
2020-11-12 08:43:24 +08:00
|
|
|
goto out_free_ctx;
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
|
ice: display some stored NVM versions via devlink info
The devlink info interface supports drivers reporting "stored" versions.
These versions indicate the version of an update that has been
downloaded to the device, but is not yet active.
The code for extracting the NVM version recently changed to enable
support for reading from either the active or the inactive bank. Use
this to implement ice_get_inactive_nvm_ver, which will read the NVM
version data from the inactive section of flash.
When reporting the versions via devlink info, first read the device
capabilities. Determine if there is a pending flash update, and if so,
extract relevant version information from the inactive flash. Store
these within the info context structure.
When reporting "stored" firmware versions, devlink documentation
indicates that we ought to always report a stored value, even if there
is no pending update. In this common case, the stored version should
match the running version. This means that each stored version should by
default fallback to the same value as reported by the running handler.
To support this, modify the version structure to have both a "getter"
and a "fallback". Modify the control loop so that it will use the
"fallback" function if the "getter" function does not report a version.
To report versions for which we can read the stored value, use a new
"stored()" macro. This macro will insert two entries into the version
list. The first entry is the traditional running version. The second is
the stored version, implemented with a fallback to the active version.
This is a little tricky, but reduces the overall duplication of elements
in the entry list, and ensures that running and stored values remain
consistent.
To avoid some duplication, add a combined() macro that will insert both
the running and stored versions into the version entry list.
Using this new support, add pending version reporter functions for
"fw.psid.api" and "fw.bundle_id". This enables reporting the stored
values for some of versions in the NVM module of the flash.
Reporting management versions is not implemented by this patch. The
active management version is reported to the driver via the AdminQ
mailbox during load. Although the version must be in the firmware binary
somewhere, accessing this from the inactive firmware is not trivial and
has not been implemented in this change.
Future changes will introduce support for reading the UNDI Option ROM
version and the version associated with the Netlist module.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2020-11-12 08:43:28 +08:00
|
|
|
/* If the default getter doesn't report a version, use the
|
|
|
|
* fallback function. This is primarily useful in the case of
|
|
|
|
* "stored" versions that want to report the same value as the
|
|
|
|
* running version in the normal case of no pending update.
|
|
|
|
*/
|
|
|
|
if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) {
|
|
|
|
err = ice_devlink_versions[i].fallback(pf, ctx);
|
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info");
|
|
|
|
goto out_free_ctx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
/* Do not report missing versions */
|
|
|
|
if (ctx->buf[0] == '\0')
|
|
|
|
continue;
|
|
|
|
|
2020-03-12 09:58:17 +08:00
|
|
|
switch (type) {
|
|
|
|
case ICE_VERSION_FIXED:
|
2020-11-12 08:43:24 +08:00
|
|
|
err = devlink_info_version_fixed_put(req, key, ctx->buf);
|
2020-03-12 09:58:17 +08:00
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version");
|
2020-11-12 08:43:24 +08:00
|
|
|
goto out_free_ctx;
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ICE_VERSION_RUNNING:
|
2020-11-12 08:43:24 +08:00
|
|
|
err = devlink_info_version_running_put(req, key, ctx->buf);
|
2020-03-12 09:58:17 +08:00
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
|
2020-11-12 08:43:24 +08:00
|
|
|
goto out_free_ctx;
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ICE_VERSION_STORED:
|
2020-11-12 08:43:24 +08:00
|
|
|
err = devlink_info_version_stored_put(req, key, ctx->buf);
|
2020-03-12 09:58:17 +08:00
|
|
|
if (err) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
|
2020-11-12 08:43:24 +08:00
|
|
|
goto out_free_ctx;
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 08:43:24 +08:00
|
|
|
out_free_ctx:
|
|
|
|
kfree(ctx);
|
|
|
|
return err;
|
2020-03-12 09:58:17 +08:00
|
|
|
}
|
|
|
|
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
/**
|
|
|
|
* ice_devlink_flash_update - Update firmware stored in flash on the device
|
|
|
|
* @devlink: pointer to devlink associated with device to update
|
2020-09-26 04:46:06 +08:00
|
|
|
* @params: flash update parameters
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
* @extack: netlink extended ACK structure
|
|
|
|
*
|
|
|
|
* Perform a device flash update. The bulk of the update logic is contained
|
|
|
|
* within the ice_flash_pldm_image function.
|
|
|
|
*
|
|
|
|
* Returns: zero on success, or an error code on failure.
|
|
|
|
*/
|
|
|
|
static int
|
2020-09-26 04:46:06 +08:00
|
|
|
ice_devlink_flash_update(struct devlink *devlink,
|
|
|
|
struct devlink_flash_update_params *params,
|
|
|
|
struct netlink_ext_ack *extack)
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
{
|
|
|
|
struct ice_pf *pf = devlink_priv(devlink);
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
2020-09-26 04:46:09 +08:00
|
|
|
u8 preservation;
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
int err;
|
|
|
|
|
2020-09-26 04:46:09 +08:00
|
|
|
if (!params->overwrite_mask) {
|
|
|
|
/* preserve all settings and identifiers */
|
|
|
|
preservation = ICE_AQC_NVM_PRESERVE_ALL;
|
|
|
|
} else if (params->overwrite_mask == DEVLINK_FLASH_OVERWRITE_SETTINGS) {
|
|
|
|
/* overwrite settings, but preserve the vital device identifiers */
|
|
|
|
preservation = ICE_AQC_NVM_PRESERVE_SELECTED;
|
|
|
|
} else if (params->overwrite_mask == (DEVLINK_FLASH_OVERWRITE_SETTINGS |
|
|
|
|
DEVLINK_FLASH_OVERWRITE_IDENTIFIERS)) {
|
|
|
|
/* overwrite both settings and identifiers, preserve nothing */
|
|
|
|
preservation = ICE_AQC_NVM_NO_PRESERVATION;
|
|
|
|
} else {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Requested overwrite mask is not supported");
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
if (!hw->dev_caps.common_cap.nvm_unified_update) {
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update");
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
2020-09-26 04:46:05 +08:00
|
|
|
err = ice_check_for_pending_update(pf, NULL, extack);
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2020-09-26 04:46:05 +08:00
|
|
|
devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
|
2020-11-19 03:06:36 +08:00
|
|
|
return ice_flash_pldm_image(pf, params->fw, preservation, extack);
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
}
|
|
|
|
|
2020-03-12 09:58:15 +08:00
|
|
|
static const struct devlink_ops ice_devlink_ops = {
|
2020-09-26 04:46:09 +08:00
|
|
|
.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
|
2020-03-12 09:58:17 +08:00
|
|
|
.info_get = ice_devlink_info_get,
|
ice: implement device flash update via devlink
Use the newly added pldmfw library to implement device flash update for
the Intel ice networking device driver. This support uses the devlink
flash update interface.
The main parts of the flash include the Option ROM, the netlist module,
and the main NVM data. The PLDM firmware file contains modules for each
of these components.
Using the pldmfw library, the provided firmware file will be scanned for
the three major components, "fw.undi" for the Option ROM, "fw.mgmt" for
the main NVM module containing the primary device firmware, and
"fw.netlist" containing the netlist module.
The flash is separated into two banks, the active bank containing the
running firmware, and the inactive bank which we use for update. Each
module is updated in a staged process. First, the inactive bank is
erased, preparing the device for update. Second, the contents of the
component are copied to the inactive portion of the flash. After all
components are updated, the driver signals the device to switch the
active bank during the next EMP reset (which would usually occur during
the next reboot).
Although the firmware AdminQ interface does report an immediate status
for each command, the NVM erase and NVM write commands receive status
asynchronously. The driver must not continue writing until previous
erase and write commands have finished. The real status of the NVM
commands is returned over the receive AdminQ. Implement a simple
interface that uses a wait queue so that the main update thread can
sleep until the completion status is reported by firmware. For erasing
the inactive banks, this can take quite a while in practice.
To help visualize the process to the devlink application and other
applications based on the devlink netlink interface, status is reported
via the devlink_flash_update_status_notify. While we do report status
after each 4k block when writing, there is no real status we can report
during erasing. We simply must wait for the complete module erasure to
finish.
With this implementation, basic flash update for the ice hardware is
supported.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-24 08:22:03 +08:00
|
|
|
.flash_update = ice_devlink_flash_update,
|
2020-03-12 09:58:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2021-08-09 02:57:43 +08:00
|
|
|
devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev);
|
2020-03-12 09:58:15 +08:00
|
|
|
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;
|
|
|
|
|
2021-08-09 02:57:43 +08:00
|
|
|
err = devlink_register(devlink);
|
2020-03-12 09:58:15 +08:00
|
|
|
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: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
* ice_devlink_create_port - Create a devlink port for this VSI
|
|
|
|
* @vsi: the VSI to create a port for
|
2020-03-12 09:58:15 +08:00
|
|
|
*
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
* Create and register a devlink_port for this VSI.
|
2020-03-12 09:58:15 +08:00
|
|
|
*
|
|
|
|
* Return: zero on success or an error code on failure.
|
|
|
|
*/
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
int ice_devlink_create_port(struct ice_vsi *vsi)
|
2020-03-12 09:58:15 +08:00
|
|
|
{
|
2020-07-09 21:18:16 +08:00
|
|
|
struct devlink_port_attrs attrs = {};
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
struct ice_port_info *pi;
|
|
|
|
struct devlink *devlink;
|
|
|
|
struct device *dev;
|
|
|
|
struct ice_pf *pf;
|
2020-03-12 09:58:15 +08:00
|
|
|
int err;
|
|
|
|
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
/* Currently we only create devlink_port instances for PF VSIs */
|
|
|
|
if (vsi->type != ICE_VSI_PF)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
pf = vsi->back;
|
|
|
|
devlink = priv_to_devlink(pf);
|
|
|
|
dev = ice_pf_to_dev(pf);
|
|
|
|
pi = pf->hw.port_info;
|
2020-03-12 09:58:15 +08:00
|
|
|
|
2020-07-09 21:18:16 +08:00
|
|
|
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
attrs.phys.port_number = pi->lport;
|
|
|
|
devlink_port_attrs_set(&vsi->devlink_port, &attrs);
|
|
|
|
err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx);
|
2020-03-12 09:58:15 +08:00
|
|
|
if (err) {
|
|
|
|
dev_err(dev, "devlink_port_register failed: %d\n", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
vsi->devlink_port_registered = true;
|
|
|
|
|
2020-03-12 09:58:15 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
* ice_devlink_destroy_port - Destroy the devlink_port for this VSI
|
|
|
|
* @vsi: the VSI to cleanup
|
2020-03-12 09:58:15 +08:00
|
|
|
*
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
* Unregisters the devlink_port structure associated with this VSI.
|
2020-03-12 09:58:15 +08:00
|
|
|
*/
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
void ice_devlink_destroy_port(struct ice_vsi *vsi)
|
2020-03-12 09:58:15 +08:00
|
|
|
{
|
ice: refactor devlink_port to be per-VSI
Currently, the devlink_port structure is stored within the ice_pf. This
made sense because we create a single devlink_port for each PF. This
setup does not mesh with the abstractions in the driver very well, and
led to a flow where we accidentally call devlink_port_unregister twice
during error cleanup.
In particular, if devlink_port_register or devlink_port_unregister are
called twice, this leads to a kernel panic. This appears to occur during
some possible flows while cleaning up from a failure during driver
probe.
If register_netdev fails, then we will call devlink_port_unregister in
ice_cfg_netdev as it cleans up. Later, we again call
devlink_port_unregister since we assume that we must cleanup the port
that is associated with the PF structure.
This occurs because we cleanup the devlink_port for the main PF even
though it was not allocated. We allocated the port within a per-VSI
function for managing the main netdev, but did not release the port when
cleaning up that VSI, the allocation and destruction are not aligned.
Instead of attempting to manage the devlink_port as part of the PF
structure, manage it as part of the PF VSI. Doing this has advantages,
as we can match the de-allocation of the devlink_port with the
unregister_netdev associated with the main PF VSI.
Moving the port to the VSI is preferable as it paves the way for
handling devlink ports allocated for other purposes such as SR-IOV VFs.
Since we're changing up how we allocate the devlink_port, also change
the indexing. Originally, we indexed the port using the PF id number.
This came from an old goal of sharing a devlink for each physical
function. Managing devlink instances across multiple function drivers is
not workable. Instead, lets set the port number to the logical port
number returned by firmware and set the index using the VSI index
(sometimes referred to as VSI handle).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-10-08 01:54:44 +08:00
|
|
|
if (!vsi->devlink_port_registered)
|
|
|
|
return;
|
|
|
|
|
|
|
|
devlink_port_type_clear(&vsi->devlink_port);
|
|
|
|
devlink_port_unregister(&vsi->devlink_port);
|
|
|
|
|
|
|
|
vsi->devlink_port_registered = false;
|
2020-03-12 09:58:15 +08:00
|
|
|
}
|
2020-03-27 02:37:18 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ice_devlink_nvm_snapshot - Capture a snapshot of the Shadow RAM contents
|
|
|
|
* @devlink: the devlink instance
|
2020-09-19 03:11:02 +08:00
|
|
|
* @ops: the devlink region being snapshotted
|
2020-03-27 02:37:18 +08:00
|
|
|
* @extack: extended ACK response structure
|
|
|
|
* @data: on exit points to snapshot data buffer
|
|
|
|
*
|
|
|
|
* This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
|
|
|
|
* the shadow-ram devlink region. It captures a snapshot of the shadow ram
|
|
|
|
* contents. This snapshot can later be viewed via the devlink-region
|
|
|
|
* interface.
|
|
|
|
*
|
|
|
|
* @returns zero on success, and updates the data pointer. Returns a non-zero
|
|
|
|
* error code on failure.
|
|
|
|
*/
|
|
|
|
static int ice_devlink_nvm_snapshot(struct devlink *devlink,
|
2020-09-19 03:11:02 +08:00
|
|
|
const struct devlink_region_ops *ops,
|
2020-03-27 02:37:18 +08:00
|
|
|
struct netlink_ext_ack *extack, u8 **data)
|
|
|
|
{
|
|
|
|
struct ice_pf *pf = devlink_priv(devlink);
|
|
|
|
struct device *dev = ice_pf_to_dev(pf);
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
enum ice_status status;
|
|
|
|
void *nvm_data;
|
|
|
|
u32 nvm_size;
|
|
|
|
|
2020-10-02 01:31:41 +08:00
|
|
|
nvm_size = hw->flash.flash_size;
|
2020-03-27 02:37:18 +08:00
|
|
|
nvm_data = vzalloc(nvm_size);
|
|
|
|
if (!nvm_data)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
status = ice_acquire_nvm(hw, ICE_RES_READ);
|
|
|
|
if (status) {
|
|
|
|
dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
|
|
|
|
status, hw->adminq.sq_last_status);
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
|
|
|
|
vfree(nvm_data);
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = ice_read_flat_nvm(hw, 0, &nvm_size, nvm_data, false);
|
|
|
|
if (status) {
|
|
|
|
dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
|
|
|
|
nvm_size, status, hw->adminq.sq_last_status);
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
|
|
|
|
ice_release_nvm(hw);
|
|
|
|
vfree(nvm_data);
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
ice_release_nvm(hw);
|
|
|
|
|
|
|
|
*data = nvm_data;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-06-19 02:46:11 +08:00
|
|
|
/**
|
|
|
|
* ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities
|
|
|
|
* @devlink: the devlink instance
|
2020-09-19 03:11:02 +08:00
|
|
|
* @ops: the devlink region being snapshotted
|
2020-06-19 02:46:11 +08:00
|
|
|
* @extack: extended ACK response structure
|
|
|
|
* @data: on exit points to snapshot data buffer
|
|
|
|
*
|
|
|
|
* This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
|
|
|
|
* the device-caps devlink region. It captures a snapshot of the device
|
|
|
|
* capabilities reported by firmware.
|
|
|
|
*
|
|
|
|
* @returns zero on success, and updates the data pointer. Returns a non-zero
|
|
|
|
* error code on failure.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ice_devlink_devcaps_snapshot(struct devlink *devlink,
|
2020-09-19 03:11:02 +08:00
|
|
|
const struct devlink_region_ops *ops,
|
2020-06-19 02:46:11 +08:00
|
|
|
struct netlink_ext_ack *extack, u8 **data)
|
|
|
|
{
|
|
|
|
struct ice_pf *pf = devlink_priv(devlink);
|
|
|
|
struct device *dev = ice_pf_to_dev(pf);
|
|
|
|
struct ice_hw *hw = &pf->hw;
|
|
|
|
enum ice_status status;
|
|
|
|
void *devcaps;
|
|
|
|
|
|
|
|
devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN);
|
|
|
|
if (!devcaps)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL,
|
|
|
|
ice_aqc_opc_list_dev_caps, NULL);
|
|
|
|
if (status) {
|
|
|
|
dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n",
|
|
|
|
status, hw->adminq.sq_last_status);
|
|
|
|
NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities");
|
|
|
|
vfree(devcaps);
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
*data = (u8 *)devcaps;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-27 02:37:18 +08:00
|
|
|
static const struct devlink_region_ops ice_nvm_region_ops = {
|
|
|
|
.name = "nvm-flash",
|
|
|
|
.destructor = vfree,
|
|
|
|
.snapshot = ice_devlink_nvm_snapshot,
|
|
|
|
};
|
|
|
|
|
2020-06-19 02:46:11 +08:00
|
|
|
static const struct devlink_region_ops ice_devcaps_region_ops = {
|
|
|
|
.name = "device-caps",
|
|
|
|
.destructor = vfree,
|
|
|
|
.snapshot = ice_devlink_devcaps_snapshot,
|
|
|
|
};
|
|
|
|
|
2020-03-27 02:37:18 +08:00
|
|
|
/**
|
|
|
|
* ice_devlink_init_regions - Initialize devlink regions
|
|
|
|
* @pf: the PF device structure
|
|
|
|
*
|
|
|
|
* Create devlink regions used to enable access to dump the contents of the
|
|
|
|
* flash memory on the device.
|
|
|
|
*/
|
|
|
|
void ice_devlink_init_regions(struct ice_pf *pf)
|
|
|
|
{
|
|
|
|
struct devlink *devlink = priv_to_devlink(pf);
|
|
|
|
struct device *dev = ice_pf_to_dev(pf);
|
|
|
|
u64 nvm_size;
|
|
|
|
|
2020-10-02 01:31:41 +08:00
|
|
|
nvm_size = pf->hw.flash.flash_size;
|
2020-03-27 02:37:18 +08:00
|
|
|
pf->nvm_region = devlink_region_create(devlink, &ice_nvm_region_ops, 1,
|
|
|
|
nvm_size);
|
|
|
|
if (IS_ERR(pf->nvm_region)) {
|
|
|
|
dev_err(dev, "failed to create NVM devlink region, err %ld\n",
|
|
|
|
PTR_ERR(pf->nvm_region));
|
|
|
|
pf->nvm_region = NULL;
|
|
|
|
}
|
2020-06-19 02:46:11 +08:00
|
|
|
|
|
|
|
pf->devcaps_region = devlink_region_create(devlink,
|
|
|
|
&ice_devcaps_region_ops, 10,
|
|
|
|
ICE_AQ_MAX_BUF_LEN);
|
|
|
|
if (IS_ERR(pf->devcaps_region)) {
|
|
|
|
dev_err(dev, "failed to create device-caps devlink region, err %ld\n",
|
|
|
|
PTR_ERR(pf->devcaps_region));
|
|
|
|
pf->devcaps_region = NULL;
|
|
|
|
}
|
2020-03-27 02:37:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ice_devlink_destroy_regions - Destroy devlink regions
|
|
|
|
* @pf: the PF device structure
|
|
|
|
*
|
|
|
|
* Remove previously created regions for this PF.
|
|
|
|
*/
|
|
|
|
void ice_devlink_destroy_regions(struct ice_pf *pf)
|
|
|
|
{
|
|
|
|
if (pf->nvm_region)
|
|
|
|
devlink_region_destroy(pf->nvm_region);
|
2020-06-19 02:46:11 +08:00
|
|
|
if (pf->devcaps_region)
|
|
|
|
devlink_region_destroy(pf->devcaps_region);
|
2020-03-27 02:37:18 +08:00
|
|
|
}
|