git: bf8c4eaee6ad - main - ixl: fix big-endian hardware interface handling
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 28 Sep 2026 14:09:11 UTC
The branch main has been updated by mchoo:
URL: https://cgit.FreeBSD.org/src/commit/?id=bf8c4eaee6ad85e647c3026116f58332c89e3794
commit bf8c4eaee6ad85e647c3026116f58332c89e3794
Author: Minsoo Choo <mchoo@FreeBSD.org>
AuthorDate: 2026-09-05 00:29:35 +0000
Commit: Minsoo Choo <mchoo@FreeBSD.org>
CommitDate: 2026-09-28 14:09:04 +0000
ixl: fix big-endian hardware interface handling
Correct the byte order at the driver interfaces that do not operate in
host order. Encode little-endian Admin Queue VSI and MAC/VLAN fields,
and decode firmware-provided queue handles, statistics indices, and
event parameters before using them.
Decode transmit descriptor writeback before examining it, and construct
VLAN descriptor fields in host order for the final descriptor
conversion. Store paged HMC descriptors in little-endian form and retain
the selected field bits when reading HMC contexts.
Keep MMIO values in host order for bus-space accessors and remove the
obsolete le16_to_cpu no-op macro. In particular, retain the atomic
bus_space_read_8() used for 64-bit registers.
On big-endian systems, the unconverted perfect-match filter flag is
presented to firmware as 0x0100 instead of 0x0001. Firmware rejects that
command with EINVAL, leaving receive traffic functional only in
promiscuous mode.
Reviewed by: kbowling
Approved by: olce (mentor)
MFC after: 2 weeks
Sponsored by: FreeBSD Foundation, Reliable Computer Systems Lab
Pull Request: https://github.com/freebsd/freebsd-src/pull/2408
---
sys/dev/ixl/i40e_hmc.c | 2 +-
sys/dev/ixl/i40e_lan_hmc.c | 8 ++++----
sys/dev/ixl/i40e_osdep.h | 2 --
sys/dev/ixl/if_ixl.c | 5 +++--
sys/dev/ixl/ixl_iw.c | 2 +-
sys/dev/ixl/ixl_pf_iflib.c | 18 ++++++++++--------
sys/dev/ixl/ixl_pf_iov.c | 8 ++++----
sys/dev/ixl/ixl_pf_main.c | 13 +++++++------
sys/dev/ixl/ixl_txrx.c | 7 +++++--
9 files changed, 35 insertions(+), 30 deletions(-)
diff --git a/sys/dev/ixl/i40e_hmc.c b/sys/dev/ixl/i40e_hmc.c
index a3f93b79f597..7f3f04427d30 100644
--- a/sys/dev/ixl/i40e_hmc.c
+++ b/sys/dev/ixl/i40e_hmc.c
@@ -187,7 +187,7 @@ enum i40e_status_code i40e_add_pd_table_entry(struct i40e_hw *hw,
pd_entry->bp.sd_pd_index = pd_index;
pd_entry->bp.entry_type = I40E_SD_TYPE_PAGED;
/* Set page address and valid bit */
- page_desc = page->pa | 0x1;
+ page_desc = CPU_TO_LE64(page->pa | 0x1);
pd_addr = (u64 *)pd_table->pd_page_addr.va;
pd_addr += rel_pd_idx;
diff --git a/sys/dev/ixl/i40e_lan_hmc.c b/sys/dev/ixl/i40e_lan_hmc.c
index afb5ad3e228d..a5e6212b52df 100644
--- a/sys/dev/ixl/i40e_lan_hmc.c
+++ b/sys/dev/ixl/i40e_lan_hmc.c
@@ -969,7 +969,7 @@ static void i40e_read_byte(u8 *hmc_bits,
i40e_memcpy(&dest_byte, src, sizeof(dest_byte), I40E_DMA_TO_NONDMA);
- dest_byte &= ~(mask);
+ dest_byte &= mask;
dest_byte >>= shift_width;
@@ -1010,7 +1010,7 @@ static void i40e_read_word(u8 *hmc_bits,
/* the data in the memory is stored as little endian so mask it
* correctly
*/
- src_word &= ~(CPU_TO_LE16(mask));
+ src_word &= CPU_TO_LE16(mask);
/* get the data back into host order before shifting */
dest_word = LE16_TO_CPU(src_word);
@@ -1062,7 +1062,7 @@ static void i40e_read_dword(u8 *hmc_bits,
/* the data in the memory is stored as little endian so mask it
* correctly
*/
- src_dword &= ~(CPU_TO_LE32(mask));
+ src_dword &= CPU_TO_LE32(mask);
/* get the data back into host order before shifting */
dest_dword = LE32_TO_CPU(src_dword);
@@ -1115,7 +1115,7 @@ static void i40e_read_qword(u8 *hmc_bits,
/* the data in the memory is stored as little endian so mask it
* correctly
*/
- src_qword &= ~(CPU_TO_LE64(mask));
+ src_qword &= CPU_TO_LE64(mask);
/* get the data back into host order before shifting */
dest_qword = LE64_TO_CPU(src_qword);
diff --git a/sys/dev/ixl/i40e_osdep.h b/sys/dev/ixl/i40e_osdep.h
index 82418aca9aa2..dc5f68fbea4c 100644
--- a/sys/dev/ixl/i40e_osdep.h
+++ b/sys/dev/ixl/i40e_osdep.h
@@ -133,8 +133,6 @@ struct i40e_spinlock {
struct mtx mutex;
};
-#define le16_to_cpu
-
#if defined(__amd64__) || defined(i386)
static __inline
void prefetch(void *x)
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index 723126c0dfd9..3822f4b5ace2 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -1483,9 +1483,10 @@ ixl_handle_lan_overflow_event(struct ixl_pf *pf, struct i40e_arq_event_info *e)
device_t dev = pf->dev;
u32 rxq_idx, qtx_ctl;
- rxq_idx = (e->desc.params.external.param0 & I40E_PRTDCB_RUPTQ_RXQNUM_MASK) >>
+ rxq_idx = (le32toh(e->desc.params.external.param0) &
+ I40E_PRTDCB_RUPTQ_RXQNUM_MASK) >>
I40E_PRTDCB_RUPTQ_RXQNUM_SHIFT;
- qtx_ctl = e->desc.params.external.param1;
+ qtx_ctl = le32toh(e->desc.params.external.param1);
device_printf(dev, "LAN overflow event: global rxq_idx %d\n", rxq_idx);
device_printf(dev, "LAN overflow event: QTX_CTL 0x%08x\n", qtx_ctl);
diff --git a/sys/dev/ixl/ixl_iw.c b/sys/dev/ixl/ixl_iw.c
index 237217da2a90..554a1defc546 100644
--- a/sys/dev/ixl/ixl_iw.c
+++ b/sys/dev/ixl/ixl_iw.c
@@ -170,7 +170,7 @@ ixl_iw_pf_init(struct ixl_pf *pf)
pf_info->iw_msix.base = IXL_IW_VEC_BASE(pf);
for (int i = 0; i < IXL_IW_MAX_USER_PRIORITY; i++)
- pf_info->qs_handle[i] = le16_to_cpu(pf->vsi.info.qs_handle[0]);
+ pf_info->qs_handle[i] = le16toh(pf->vsi.info.qs_handle[0]);
pf_entry->state.pf = IXL_IW_PF_STATE_ON;
if (ixl_iw.registered) {
diff --git a/sys/dev/ixl/ixl_pf_iflib.c b/sys/dev/ixl/ixl_pf_iflib.c
index 17802e28d613..b6283855e794 100644
--- a/sys/dev/ixl/ixl_pf_iflib.c
+++ b/sys/dev/ixl/ixl_pf_iflib.c
@@ -463,14 +463,15 @@ ixl_initialize_vsi(struct ixl_vsi *vsi)
ctxt.uplink_seid, ctxt.vsi_number,
ctxt.vsis_allocated, ctxt.vsis_unallocated,
ctxt.flags, ctxt.pf_num, ctxt.vf_num,
- ctxt.info.stat_counter_idx, ctxt.info.up_enable_bits);
+ le16toh(ctxt.info.stat_counter_idx), ctxt.info.up_enable_bits);
/*
** Set the queue and traffic class bits
** - when multiple traffic classes are supported
** this will need to be more robust.
*/
- ctxt.info.valid_sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
- ctxt.info.mapping_flags |= I40E_AQ_VSI_QUE_MAP_CONTIG;
+ ctxt.info.valid_sections =
+ htole16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+ ctxt.info.mapping_flags = htole16(I40E_AQ_VSI_QUE_MAP_CONTIG);
/* In contig mode, que_mapping[0] is first queue index used by this VSI */
ctxt.info.queue_mapping[0] = 0;
/*
@@ -479,13 +480,14 @@ ixl_initialize_vsi(struct ixl_vsi *vsi)
* the driver may not use all of them).
*/
tc_queues = fls(pf->qtag.num_allocated) - 1;
- ctxt.info.tc_mapping[0] = ((pf->qtag.first_qidx << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT)
+ ctxt.info.tc_mapping[0] = htole16(
+ ((pf->qtag.first_qidx << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT)
& I40E_AQ_VSI_TC_QUE_OFFSET_MASK) |
((tc_queues << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)
- & I40E_AQ_VSI_TC_QUE_NUMBER_MASK);
+ & I40E_AQ_VSI_TC_QUE_NUMBER_MASK));
/* Set VLAN receive stripping mode */
- ctxt.info.valid_sections |= I40E_AQ_VSI_PROP_VLAN_VALID;
+ ctxt.info.valid_sections |= htole16(I40E_AQ_VSI_PROP_VLAN_VALID);
ctxt.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL;
if (if_getcapenable(vsi->ifp) & IFCAP_VLAN_HWTAGGING)
ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH;
@@ -510,7 +512,7 @@ ixl_initialize_vsi(struct ixl_vsi *vsi)
vsi->vsi_num = ctxt.vsi_number;
bcopy(&ctxt.info, &vsi->info, sizeof(vsi->info));
- ctxt.flags = htole16(I40E_AQ_VSI_TYPE_PF);
+ ctxt.flags = I40E_AQ_VSI_TYPE_PF;
err = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
if (err) {
@@ -534,7 +536,7 @@ ixl_initialize_vsi(struct ixl_vsi *vsi)
* This value needs to pulled from the VSI that this queue
* is assigned to. Index into array is traffic class.
*/
- tctx.rdylist = vsi->info.qs_handle[0];
+ tctx.rdylist = le16toh(vsi->info.qs_handle[0]);
/*
* Set these to enable Head Writeback
* - Address is last entry in TX ring (reserved for HWB index)
diff --git a/sys/dev/ixl/ixl_pf_iov.c b/sys/dev/ixl/ixl_pf_iov.c
index 8c985d622cfe..f3f71ebfb637 100644
--- a/sys/dev/ixl/ixl_pf_iov.c
+++ b/sys/dev/ixl/ixl_pf_iov.c
@@ -181,7 +181,7 @@ ixl_vf_alloc_vsi(struct ixl_pf *pf, struct ixl_vf *vf)
/* XXX: Only scattered allocation is supported for VFs right now */
for (i = 0; i < vf->qtag.num_active; i++)
- vsi_ctx.info.queue_mapping[i] = vf->qtag.qidx[i];
+ vsi_ctx.info.queue_mapping[i] = htole16(vf->qtag.qidx[i]);
for (; i < nitems(vsi_ctx.info.queue_mapping); i++)
vsi_ctx.info.queue_mapping[i] = htole16(I40E_AQ_VSI_QUEUE_MASK);
@@ -660,7 +660,7 @@ ixl_vf_config_tx_queue(struct ixl_pf *pf, struct ixl_vf *vf,
txq.head_wb_ena = info->headwb_enabled;
txq.head_wb_addr = info->dma_headwb_addr;
txq.qlen = info->ring_len;
- txq.rdylist = le16_to_cpu(vf->vsi.info.qs_handle[0]);
+ txq.rdylist = le16toh(vf->vsi.info.qs_handle[0]);
txq.rdylist_act = 0;
status = i40e_set_lan_tx_queue_context(hw, global_queue_num, &txq);
@@ -876,11 +876,11 @@ ixl_vf_set_qctl(struct ixl_pf *pf,
itr_indx = vector->txitr_idx;
}
- qctl = htole32((vector->vector_id << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
+ qctl = (vector->vector_id << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
(*last_type << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
(*last_queue << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
I40E_QINT_RQCTL_CAUSE_ENA_MASK |
- (itr_indx << I40E_QINT_RQCTL_ITR_INDX_SHIFT));
+ (itr_indx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
wr32(&pf->hw, offset, qctl);
diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c
index 838e2178a110..d2a2fb74fe69 100644
--- a/sys/dev/ixl/ixl_pf_main.c
+++ b/sys/dev/ixl/ixl_pf_main.c
@@ -1524,12 +1524,13 @@ ixl_add_hw_filters(struct ixl_vsi *vsi, struct ixl_ftl_head *to_add, int cnt)
bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN);
if (f->vlan == IXL_VLAN_ANY) {
b->vlan_tag = 0;
- b->flags = I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
+ b->flags =
+ htole16(I40E_AQC_MACVLAN_ADD_IGNORE_VLAN);
} else {
- b->vlan_tag = f->vlan;
+ b->vlan_tag = htole16(f->vlan);
b->flags = 0;
}
- b->flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
+ b->flags |= htole16(I40E_AQC_MACVLAN_ADD_PERFECT_MATCH);
/* Some FW versions do not set match method
* when adding filters fails. Initialize it with
* expected error value to allow detection which
@@ -1622,7 +1623,7 @@ ixl_del_hw_filters(struct ixl_vsi *vsi, struct ixl_ftl_head *to_del, int cnt)
e->vlan_tag = 0;
e->flags |= I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
} else {
- e->vlan_tag = f->vlan;
+ e->vlan_tag = htole16(f->vlan);
}
ixl_dbg_filter(pf, "DEL: " MAC_FORMAT "\n",
@@ -1654,7 +1655,7 @@ ixl_del_hw_filters(struct ixl_vsi *vsi, struct ixl_ftl_head *to_del, int cnt)
device_printf(dev,
"%s Filter does not exist " MAC_FORMAT " VTAG: %d\n",
__func__, MAC_FORMAT_ARGS(d[i].mac_addr),
- d[i].vlan_tag);
+ le16toh(d[i].vlan_tag));
}
}
@@ -2278,7 +2279,7 @@ ixl_update_eth_stats(struct ixl_vsi *vsi)
struct i40e_hw *hw = &pf->hw;
struct i40e_eth_stats *es;
struct i40e_eth_stats *oes;
- u16 stat_idx = vsi->info.stat_counter_idx;
+ u16 stat_idx = le16toh(vsi->info.stat_counter_idx);
es = &vsi->eth_stats;
oes = &vsi->eth_stats_offsets;
diff --git a/sys/dev/ixl/ixl_txrx.c b/sys/dev/ixl/ixl_txrx.c
index 047bb468254b..7ce1c24c814a 100644
--- a/sys/dev/ixl/ixl_txrx.c
+++ b/sys/dev/ixl/ixl_txrx.c
@@ -131,7 +131,10 @@ ixl_debug_core(device_t dev, u32 enabled_mask, u32 mask, char *fmt, ...)
static bool
ixl_is_tx_desc_done(struct tx_ring *txr, int idx)
{
- return (((txr->tx_base[idx].cmd_type_offset_bsz >> I40E_TXD_QW1_DTYPE_SHIFT)
+ u64 descriptor;
+
+ descriptor = le64toh(txr->tx_base[idx].cmd_type_offset_bsz);
+ return (((descriptor >> I40E_TXD_QW1_DTYPE_SHIFT)
& I40E_TXD_QW1_DTYPE_MASK) == I40E_TX_DESC_DTYPE_DESC_DONE);
}
@@ -373,7 +376,7 @@ ixl_isc_txd_encap(void *arg, if_pkt_info_t pi)
| ((u64)cmd << I40E_TXD_QW1_CMD_SHIFT)
| ((u64)off << I40E_TXD_QW1_OFFSET_SHIFT)
| ((u64)seglen << I40E_TXD_QW1_TX_BUF_SZ_SHIFT)
- | ((u64)htole16(pi->ipi_vtag) << I40E_TXD_QW1_L2TAG1_SHIFT));
+ | ((u64)pi->ipi_vtag << I40E_TXD_QW1_L2TAG1_SHIFT));
txr->tx_bytes += seglen;
pidx_last = i;