Skip to content

Commit a0f4567

Browse files
jjagielskanguy11
authored andcommitted
ixgbe: add device flash update via devlink
Use the pldmfw library to implement device flash update for the Intel ixgbe networking device driver specifically for E610 devices. This support uses the devlink flash update interface. 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. With this implementation, basic flash update for the E610 hardware is supported. Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Bharath R <bharath.r@intel.com> Co-developed-by: Slawomir Mrozowicz <slawomirx.mrozowicz@intel.com> Signed-off-by: Slawomir Mrozowicz <slawomirx.mrozowicz@intel.com> Co-developed-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com> Signed-off-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com> Co-developed-by: Stefan Wegrzyn <stefan.wegrzyn@intel.com> Signed-off-by: Stefan Wegrzyn <stefan.wegrzyn@intel.com> Signed-off-by: Jedrzej Jagielski <jedrzej.jagielski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent 6eae2ae commit a0f4567

9 files changed

Lines changed: 997 additions & 1 deletion

File tree

Documentation/networking/devlink/ixgbe.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,30 @@ The ``ixgbe`` driver reports the following versions
7676
- running
7777
- 0xee16ced7
7878
- The first 4 bytes of the hash of the netlist module contents.
79+
80+
Flash Update
81+
============
82+
83+
The ``ixgbe`` driver implements support for flash update using the
84+
``devlink-flash`` interface. It supports updating the device flash using a
85+
combined flash image that contains the ``fw.mgmt``, ``fw.undi``, and
86+
``fw.netlist`` components.
87+
88+
.. list-table:: List of supported overwrite modes
89+
:widths: 5 95
90+
91+
* - Bits
92+
- Behavior
93+
* - ``DEVLINK_FLASH_OVERWRITE_SETTINGS``
94+
- Do not preserve settings stored in the flash components being
95+
updated. This includes overwriting the port configuration that
96+
determines the number of physical functions the device will
97+
initialize with.
98+
* - ``DEVLINK_FLASH_OVERWRITE_SETTINGS`` and ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS``
99+
- Do not preserve either settings or identifiers. Overwrite everything
100+
in the flash with the contents from the provided image, without
101+
performing any preservation. This includes overwriting device
102+
identifying fields such as the MAC address, Vital product Data (VPD) area,
103+
and device serial number. It is expected that this combination be used with an
104+
image customized for the specific device.
105+

drivers/net/ethernet/intel/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ config IXGBE
148148
depends on PTP_1588_CLOCK_OPTIONAL
149149
select MDIO
150150
select NET_DEVLINK
151+
select PLDMFW
151152
select PHYLIB
152153
help
153154
This driver supports Intel(R) 10GbE PCI Express family of

drivers/net/ethernet/intel/ixgbe/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
1010
ixgbe-y := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
1111
ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
1212
ixgbe_mbx.o ixgbe_x540.o ixgbe_x550.o ixgbe_lib.o ixgbe_ptp.o \
13-
ixgbe_xsk.o ixgbe_e610.o devlink/devlink.o
13+
ixgbe_xsk.o ixgbe_e610.o devlink/devlink.o ixgbe_fw_update.o
1414

1515
ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \
1616
ixgbe_dcb_82599.o ixgbe_dcb_nl.o

drivers/net/ethernet/intel/ixgbe/devlink/devlink.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "ixgbe.h"
55
#include "devlink.h"
6+
#include "ixgbe_fw_update.h"
67

78
struct ixgbe_info_ctx {
89
char buf[128];
@@ -366,6 +367,9 @@ static int ixgbe_devlink_info_get(struct devlink *devlink,
366367

367368
static const struct devlink_ops ixgbe_devlink_ops = {
368369
.info_get = ixgbe_devlink_info_get,
370+
.supported_flash_update_params =
371+
DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
372+
.flash_update = ixgbe_flash_pldm_image,
369373
};
370374

371375
/**

drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,11 @@ static bool ixgbe_parse_e610_caps(struct ixgbe_hw *hw,
597597
case IXGBE_ACI_CAPS_PENDING_NET_VER:
598598
caps->nvm_update_pending_netlist = true;
599599
break;
600+
case IXGBE_ACI_CAPS_NVM_MGMT:
601+
caps->nvm_unified_update =
602+
(number & IXGBE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
603+
true : false;
604+
break;
600605
case IXGBE_ACI_CAPS_MAX_MTU:
601606
caps->max_mtu = number;
602607
break;
@@ -2294,6 +2299,131 @@ int ixgbe_aci_read_nvm(struct ixgbe_hw *hw, u16 module_typeid, u32 offset,
22942299
return ixgbe_aci_send_cmd(hw, &desc, data, length);
22952300
}
22962301

2302+
/**
2303+
* ixgbe_aci_erase_nvm - erase NVM sector
2304+
* @hw: pointer to the HW struct
2305+
* @module_typeid: module pointer location in words from the NVM beginning
2306+
*
2307+
* Erase the NVM sector using the ACI command (0x0702).
2308+
*
2309+
* Return: the exit code of the operation.
2310+
*/
2311+
int ixgbe_aci_erase_nvm(struct ixgbe_hw *hw, u16 module_typeid)
2312+
{
2313+
struct ixgbe_aci_cmd_nvm *cmd;
2314+
struct ixgbe_aci_desc desc;
2315+
__le16 len;
2316+
int err;
2317+
2318+
/* Read a length value from SR, so module_typeid is equal to 0,
2319+
* calculate offset where module size is placed from bytes to words
2320+
* set last command and read from SR values to true.
2321+
*/
2322+
err = ixgbe_aci_read_nvm(hw, 0, 2 * module_typeid + 2, 2, &len, true,
2323+
true);
2324+
if (err)
2325+
return err;
2326+
2327+
cmd = &desc.params.nvm;
2328+
2329+
ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_erase);
2330+
2331+
cmd->module_typeid = cpu_to_le16(module_typeid);
2332+
cmd->length = len;
2333+
cmd->offset_low = 0;
2334+
cmd->offset_high = 0;
2335+
2336+
return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2337+
}
2338+
2339+
/**
2340+
* ixgbe_aci_update_nvm - update NVM
2341+
* @hw: pointer to the HW struct
2342+
* @module_typeid: module pointer location in words from the NVM beginning
2343+
* @offset: byte offset from the module beginning
2344+
* @length: length of the section to be written (in bytes from the offset)
2345+
* @data: command buffer (size [bytes] = length)
2346+
* @last_command: tells if this is the last command in a series
2347+
* @command_flags: command parameters
2348+
*
2349+
* Update the NVM using the ACI command (0x0703).
2350+
*
2351+
* Return: the exit code of the operation.
2352+
*/
2353+
int ixgbe_aci_update_nvm(struct ixgbe_hw *hw, u16 module_typeid,
2354+
u32 offset, u16 length, void *data,
2355+
bool last_command, u8 command_flags)
2356+
{
2357+
struct ixgbe_aci_cmd_nvm *cmd;
2358+
struct ixgbe_aci_desc desc;
2359+
2360+
cmd = &desc.params.nvm;
2361+
2362+
/* In offset the highest byte must be zeroed. */
2363+
if (offset & 0xFF000000)
2364+
return -EINVAL;
2365+
2366+
ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_write);
2367+
2368+
cmd->cmd_flags |= command_flags;
2369+
2370+
/* If this is the last command in a series, set the proper flag. */
2371+
if (last_command)
2372+
cmd->cmd_flags |= IXGBE_ACI_NVM_LAST_CMD;
2373+
cmd->module_typeid = cpu_to_le16(module_typeid);
2374+
cmd->offset_low = cpu_to_le16(offset & 0xFFFF);
2375+
cmd->offset_high = FIELD_GET(IXGBE_ACI_NVM_OFFSET_HI_U_MASK, offset);
2376+
cmd->length = cpu_to_le16(length);
2377+
2378+
desc.flags |= cpu_to_le16(IXGBE_ACI_FLAG_RD);
2379+
2380+
return ixgbe_aci_send_cmd(hw, &desc, data, length);
2381+
}
2382+
2383+
/**
2384+
* ixgbe_nvm_write_activate - NVM activate write
2385+
* @hw: pointer to the HW struct
2386+
* @cmd_flags: flags for write activate command
2387+
* @response_flags: response indicators from firmware
2388+
*
2389+
* Update the control word with the required banks' validity bits
2390+
* and dumps the Shadow RAM to flash using ACI command (0x0707).
2391+
*
2392+
* cmd_flags controls which banks to activate, the preservation level to use
2393+
* when activating the NVM bank, and whether an EMP reset is required for
2394+
* activation.
2395+
*
2396+
* Note that the 16bit cmd_flags value is split between two separate 1 byte
2397+
* flag values in the descriptor.
2398+
*
2399+
* On successful return of the firmware command, the response_flags variable
2400+
* is updated with the flags reported by firmware indicating certain status,
2401+
* such as whether EMP reset is enabled.
2402+
*
2403+
* Return: the exit code of the operation.
2404+
*/
2405+
int ixgbe_nvm_write_activate(struct ixgbe_hw *hw, u16 cmd_flags,
2406+
u8 *response_flags)
2407+
{
2408+
struct ixgbe_aci_cmd_nvm *cmd;
2409+
struct ixgbe_aci_desc desc;
2410+
s32 err;
2411+
2412+
cmd = &desc.params.nvm;
2413+
ixgbe_fill_dflt_direct_cmd_desc(&desc,
2414+
ixgbe_aci_opc_nvm_write_activate);
2415+
2416+
cmd->cmd_flags = (u8)(cmd_flags & 0xFF);
2417+
cmd->offset_high = (u8)FIELD_GET(IXGBE_ACI_NVM_OFFSET_HI_A_MASK,
2418+
cmd_flags);
2419+
2420+
err = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
2421+
if (!err && response_flags)
2422+
*response_flags = cmd->cmd_flags;
2423+
2424+
return err;
2425+
}
2426+
22972427
/**
22982428
* ixgbe_nvm_validate_checksum - validate checksum
22992429
* @hw: pointer to the HW struct
@@ -3171,6 +3301,85 @@ int ixgbe_get_flash_data(struct ixgbe_hw *hw)
31713301
return err;
31723302
}
31733303

3304+
/* ixgbe_nvm_set_pkg_data - NVM set package data
3305+
* @hw: pointer to the HW struct
3306+
* @del_pkg_data_flag: If is set then the current pkg_data store by FW
3307+
* is deleted.
3308+
* If bit is set to 1, then buffer should be size 0.
3309+
* @data: pointer to buffer
3310+
* @length: length of the buffer
3311+
*
3312+
* Set package data using ACI command (0x070A).
3313+
* This command is equivalent to the reception of
3314+
* a PLDM FW Update GetPackageData cmd. This command should be sent
3315+
* as part of the NVM update as the first cmd in the flow.
3316+
*
3317+
* Return: the exit code of the operation.
3318+
*/
3319+
int ixgbe_nvm_set_pkg_data(struct ixgbe_hw *hw, bool del_pkg_data_flag,
3320+
u8 *data, u16 length)
3321+
{
3322+
struct ixgbe_aci_cmd_nvm_pkg_data *cmd;
3323+
struct ixgbe_aci_desc desc;
3324+
3325+
if (length != 0 && !data)
3326+
return -EINVAL;
3327+
3328+
cmd = &desc.params.pkg_data;
3329+
3330+
ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_pkg_data);
3331+
desc.flags |= cpu_to_le16(IXGBE_ACI_FLAG_RD);
3332+
3333+
if (del_pkg_data_flag)
3334+
cmd->cmd_flags |= IXGBE_ACI_NVM_PKG_DELETE;
3335+
3336+
return ixgbe_aci_send_cmd(hw, &desc, data, length);
3337+
}
3338+
3339+
/* ixgbe_nvm_pass_component_tbl - NVM pass component table
3340+
* @hw: pointer to the HW struct
3341+
* @data: pointer to buffer
3342+
* @length: length of the buffer
3343+
* @transfer_flag: parameter for determining stage of the update
3344+
* @comp_response: a pointer to the response from the 0x070B ACI.
3345+
* @comp_response_code: a pointer to the response code from the 0x070B ACI.
3346+
*
3347+
* Pass component table using ACI command (0x070B). This command is equivalent
3348+
* to the reception of a PLDM FW Update PassComponentTable cmd.
3349+
* This command should be sent once per component. It can be only sent after
3350+
* Set Package Data cmd and before actual update. FW will assume these
3351+
* commands are going to be sent until the TransferFlag is set to End or
3352+
* StartAndEnd.
3353+
*
3354+
* Return: the exit code of the operation.
3355+
*/
3356+
int ixgbe_nvm_pass_component_tbl(struct ixgbe_hw *hw, u8 *data, u16 length,
3357+
u8 transfer_flag, u8 *comp_response,
3358+
u8 *comp_response_code)
3359+
{
3360+
struct ixgbe_aci_cmd_nvm_pass_comp_tbl *cmd;
3361+
struct ixgbe_aci_desc desc;
3362+
int err;
3363+
3364+
if (!data || !comp_response || !comp_response_code)
3365+
return -EINVAL;
3366+
3367+
cmd = &desc.params.pass_comp_tbl;
3368+
3369+
ixgbe_fill_dflt_direct_cmd_desc(&desc,
3370+
ixgbe_aci_opc_nvm_pass_component_tbl);
3371+
desc.flags |= cpu_to_le16(IXGBE_ACI_FLAG_RD);
3372+
3373+
cmd->transfer_flag = transfer_flag;
3374+
err = ixgbe_aci_send_cmd(hw, &desc, data, length);
3375+
if (!err) {
3376+
*comp_response = cmd->component_response;
3377+
*comp_response_code = cmd->component_response_code;
3378+
}
3379+
3380+
return err;
3381+
}
3382+
31743383
/**
31753384
* ixgbe_read_sr_word_aci - Reads Shadow RAM via ACI
31763385
* @hw: pointer to the HW structure

drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,16 @@ int ixgbe_read_ee_aci_buffer_e610(struct ixgbe_hw *hw, u16 offset,
8383
int ixgbe_validate_eeprom_checksum_e610(struct ixgbe_hw *hw, u16 *checksum_val);
8484
int ixgbe_reset_hw_e610(struct ixgbe_hw *hw);
8585
int ixgbe_get_flash_data(struct ixgbe_hw *hw);
86+
int ixgbe_nvm_set_pkg_data(struct ixgbe_hw *hw, bool del_pkg_data_flag,
87+
u8 *data, u16 length);
88+
int ixgbe_nvm_pass_component_tbl(struct ixgbe_hw *hw, u8 *data, u16 length,
89+
u8 transfer_flag, u8 *comp_response,
90+
u8 *comp_response_code);
91+
int ixgbe_aci_erase_nvm(struct ixgbe_hw *hw, u16 module_typeid);
92+
int ixgbe_aci_update_nvm(struct ixgbe_hw *hw, u16 module_typeid,
93+
u32 offset, u16 length, void *data,
94+
bool last_command, u8 command_flags);
95+
int ixgbe_nvm_write_activate(struct ixgbe_hw *hw, u16 cmd_flags,
96+
u8 *response_flags);
8697

8798
#endif /* _IXGBE_E610_H_ */

0 commit comments

Comments
 (0)