Skip to content

Commit 503f1c7

Browse files
jacob-kelleranguy11
authored andcommitted
i40e: fix Jumbo Frame support after iPXE boot
The i40e hardware has multiple hardware settings which define the Maximum Frame Size (MFS) of the physical port. The firmware has an AdminQ command (0x0603) to configure the MFS, but the i40e Linux driver never issues this command. In most cases this is no problem, as the NVM default value has the device configured for its maximum value of 9728. Unfortunately, recent versions of the iPXE intelxl driver now issue the 0x0603 Set Mac Config command, modifying the MFS and reducing it from its default value of 9728. This occurred as part of iPXE commit 6871a7de705b ("[intelxl] Use admin queue to set port MAC address and maximum frame size"), a prerequisite change for supporting the E800 series hardware in iPXE. Both the E700 and E800 firmware support the AdminQ command, and the iPXE code shares much of the logic between the two device drivers. The ice E800 Linux driver already issues the 0x0603 Set Mac Config command early during probe, and is thus unaffected by the iPXE change. Since commit 3a2c6ce ("i40e: Add a check to see if MFS is set"), the i40e driver does check the I40E_PRTGL_SAH register, but it only logs a warning message if its value is below the 9728 default. This register also only covers received packets and not transmitted packets. A warning can inform system administrators, but does not correct the issue. No interactions from userspace cause the driver to write to PRTGL_SAH or issue the 0x0603 AdminQ command. Only a GLOBR reset will restore the value to its default value. There is no obvious method to trigger a GLOBR reset from user space. To fix this, introduce the i40e_aq_set_mac_config() function, similar to the one from the ice driver. Call this during early probe to ensure that the device configuration matches driver expectation. Unlike E800, the E700 firmware also has a bit to control whether the MAC should append CRC data. It is on by default, but setting a 0 to this bit would disable CRC. The i40e implementation must set this bit to ensure CRC will be appended by the MAC. In addition to the AQ command, instead of just checking the I40E_PRTGL_SAH register, update its value to the 9728 default and write it back. This ensures that the hardware is in the expected state, regardless of whether the iPXE (or any other early boot driver) has modified this state. This is a better user experience, as we now fix the issues with larger MTU instead of merely warning. It also aligns with the way the ice E800 series driver works. A final note: The Fixes tag provided here is not strictly accurate. The issue occurs as a result of an external entity (the iPXE intelxl driver), and this is not a regression specifically caused by the mentioned change. However, I believe the original change to just warn about PRTGL_SAH being too low was an insufficient fix. Fixes: 3a2c6ce ("i40e: Add a check to see if MFS is set") Link: ipxe/ipxe@6871a7d Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> Reviewed-by: Michal Schmidt <mschmidt@redhat.com> Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent 915470e commit 503f1c7

File tree

4 files changed

+47
-6
lines changed

4 files changed

+47
-6
lines changed

drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
15611561
struct i40e_aq_set_mac_config {
15621562
__le16 max_frame_size;
15631563
u8 params;
1564+
#define I40E_AQ_SET_MAC_CONFIG_CRC_EN BIT(2)
15641565
u8 tx_timer_priority; /* bitmap */
15651566
__le16 tx_timer_value;
15661567
__le16 fc_refresh_threshold;

drivers/net/ethernet/intel/i40e/i40e_common.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,40 @@ int i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
11891189
return status;
11901190
}
11911191

1192+
/**
1193+
* i40e_aq_set_mac_config - Configure MAC settings
1194+
* @hw: pointer to the hw struct
1195+
* @max_frame_size: Maximum Frame Size to be supported by the port
1196+
* @cmd_details: pointer to command details structure or NULL
1197+
*
1198+
* Set MAC configuration (0x0603). Note that max_frame_size must be greater
1199+
* than zero.
1200+
*
1201+
* Return: 0 on success, or a negative error code on failure.
1202+
*/
1203+
int i40e_aq_set_mac_config(struct i40e_hw *hw, u16 max_frame_size,
1204+
struct i40e_asq_cmd_details *cmd_details)
1205+
{
1206+
struct i40e_aq_set_mac_config *cmd;
1207+
struct libie_aq_desc desc;
1208+
1209+
cmd = libie_aq_raw(&desc);
1210+
1211+
if (max_frame_size == 0)
1212+
return -EINVAL;
1213+
1214+
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_mac_config);
1215+
1216+
cmd->max_frame_size = cpu_to_le16(max_frame_size);
1217+
cmd->params = I40E_AQ_SET_MAC_CONFIG_CRC_EN;
1218+
1219+
#define I40E_AQ_SET_MAC_CONFIG_FC_DEFAULT_THRESHOLD 0x7FFF
1220+
cmd->fc_refresh_threshold =
1221+
cpu_to_le16(I40E_AQ_SET_MAC_CONFIG_FC_DEFAULT_THRESHOLD);
1222+
1223+
return i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
1224+
}
1225+
11921226
/**
11931227
* i40e_aq_clear_pxe_mode
11941228
* @hw: pointer to the hw struct

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16045,13 +16045,17 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1604516045
dev_dbg(&pf->pdev->dev, "get supported phy types ret = %pe last_status = %s\n",
1604616046
ERR_PTR(err), libie_aq_str(pf->hw.aq.asq_last_status));
1604716047

16048-
/* make sure the MFS hasn't been set lower than the default */
1604916048
#define MAX_FRAME_SIZE_DEFAULT 0x2600
16050-
val = FIELD_GET(I40E_PRTGL_SAH_MFS_MASK,
16051-
rd32(&pf->hw, I40E_PRTGL_SAH));
16052-
if (val < MAX_FRAME_SIZE_DEFAULT)
16053-
dev_warn(&pdev->dev, "MFS for port %x (%d) has been set below the default (%d)\n",
16054-
pf->hw.port, val, MAX_FRAME_SIZE_DEFAULT);
16049+
16050+
err = i40e_aq_set_mac_config(hw, MAX_FRAME_SIZE_DEFAULT, NULL);
16051+
if (err)
16052+
dev_warn(&pdev->dev, "set mac config ret = %pe last_status = %s\n",
16053+
ERR_PTR(err), libie_aq_str(pf->hw.aq.asq_last_status));
16054+
16055+
/* Make sure the MFS is set to the expected value */
16056+
val = rd32(hw, I40E_PRTGL_SAH);
16057+
FIELD_MODIFY(I40E_PRTGL_SAH_MFS_MASK, &val, MAX_FRAME_SIZE_DEFAULT);
16058+
wr32(hw, I40E_PRTGL_SAH, val);
1605516059

1605616060
/* Add a filter to drop all Flow control frames from any VSI from being
1605716061
* transmitted. By doing so we stop a malicious VF from sending out

drivers/net/ethernet/intel/i40e/i40e_prototype.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ int i40e_aq_set_mac_loopback(struct i40e_hw *hw,
9898
struct i40e_asq_cmd_details *cmd_details);
9999
int i40e_aq_set_phy_int_mask(struct i40e_hw *hw, u16 mask,
100100
struct i40e_asq_cmd_details *cmd_details);
101+
int i40e_aq_set_mac_config(struct i40e_hw *hw, u16 max_frame_size,
102+
struct i40e_asq_cmd_details *cmd_details);
101103
int i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
102104
struct i40e_asq_cmd_details *cmd_details);
103105
int i40e_aq_set_link_restart_an(struct i40e_hw *hw,

0 commit comments

Comments
 (0)