Two bugs in the same loop in ixgbe_validate_rtr(): 1. The 3-bit traffic-class field was extracted by shifting a u32 and assigning the result directly to a u8. For user priority 0 this is harmless; for UP[5..7] the shift leaves bits [15..21] in the u32 which are then silently truncated when stored in u8. Mask with IXGBE_RTRUP2TC_UP_MASK before the assignment so only the intended 3 bits are kept. 2. When clearing an out-of-bounds entry the mask was always shifted by the fixed constant IXGBE_RTRUP2TC_UP_SHIFT (== 3), regardless of which loop iteration was being processed. This means only UP1 (bit position 3) was ever cleared; UP0,2..7 (positions 0, 6, 9, ..., 21) were left unreset, so invalid TC mappings persisted in hardware and could mis-steer received packets to the wrong traffic class. Use i * IXGBE_RTRUP2TC_UP_SHIFT to target the correct 3-bit field for each iteration. Swap the operand order in the mask expression to place the constant on the right per kernel coding style (noted by David Laight). Fixes: 8b1c0b24d9af ("ixgbe: configure minimal packet buffers to support TC") Cc: stable@vger.kernel.org Reviewed-by: Simon Horman Signed-off-by: Aleksandr Loktionov --- v2 -> v3: - Correct Fixes: tag to 8b1c0b24d9af ("ixgbe: configure minimal packet buffers to support TC") -- the previously used e7589eab9291 predates the buggy code path (Simon Horman); add Reviewed-by: Simon Horman. v1 -> v2: - Add Fixes: tag; reroute to iwl-net (wrong bit positions cause packet mis-steering); swap to (reg >> ...) & MASK operand order per David Laight. drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 210c7b9..c9e4f12 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9772,11 +9772,12 @@ static void ixgbe_validate_rtr(struct ixgbe_adapter *adapter, u8 tc) rsave = reg; for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { - u8 up2tc = reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT); + u8 up2tc = (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)) & + IXGBE_RTRUP2TC_UP_MASK; /* If up2tc is out of bounds default to zero */ if (up2tc > tc) - reg &= ~(0x7 << IXGBE_RTRUP2TC_UP_SHIFT); + reg &= ~(IXGBE_RTRUP2TC_UP_MASK << (i * IXGBE_RTRUP2TC_UP_SHIFT)); } if (reg != rsave) -- 2.52.0