Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2026-01-13 (ice, igc)

For ice:
Jake adds missing initialization calls to u64_stats_init().

Dave stops deletion of VLAN 0 from prune list when device is primary
LAG interface.

Ding Hui adds a missed unit conversion function for proper timeout
value.

For igc:
Kurt Kanzenbach adds a call to re-set default Qbv schedule when number
of channels changes.

Chwee-Lin Choong reworks Tx timestamp detection logic to resolve a race
condition and reverts changes to TSN packet buffer size causing Tx
hangs under heavy load.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue:
igc: Reduce TSN TX packet buffer from 7KB to 5KB per queue
igc: fix race condition in TX timestamp read for register 0
igc: Restore default Qbv schedule when changing channels
ice: Fix incorrect timeout ice_release_res()
ice: Avoid detrimental cleanup for bond during interface stop
ice: initialize ring_stats->syncp
====================

Link: https://patch.msgid.link/20260113220220.1034638-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+57 -31
+1 -1
drivers/net/ethernet/intel/ice/ice_common.c
··· 2251 2251 /* there are some rare cases when trying to release the resource 2252 2252 * results in an admin queue timeout, so handle them correctly 2253 2253 */ 2254 - timeout = jiffies + 10 * ICE_CTL_Q_SQ_CMD_TIMEOUT; 2254 + timeout = jiffies + 10 * usecs_to_jiffies(ICE_CTL_Q_SQ_CMD_TIMEOUT); 2255 2255 do { 2256 2256 status = ice_aq_release_res(hw, res, 0, NULL); 2257 2257 if (status != -EIO)
+21 -8
drivers/net/ethernet/intel/ice/ice_lib.c
··· 398 398 if (!ring_stats) 399 399 goto err_out; 400 400 401 + u64_stats_init(&ring_stats->syncp); 402 + 401 403 WRITE_ONCE(tx_ring_stats[i], ring_stats); 402 404 } 403 405 ··· 418 416 ring_stats = kzalloc(sizeof(*ring_stats), GFP_KERNEL); 419 417 if (!ring_stats) 420 418 goto err_out; 419 + 420 + u64_stats_init(&ring_stats->syncp); 421 421 422 422 WRITE_ONCE(rx_ring_stats[i], ring_stats); 423 423 } ··· 3809 3805 int ice_vsi_del_vlan_zero(struct ice_vsi *vsi) 3810 3806 { 3811 3807 struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); 3808 + struct ice_pf *pf = vsi->back; 3812 3809 struct ice_vlan vlan; 3813 3810 int err; 3814 3811 3815 - vlan = ICE_VLAN(0, 0, 0); 3816 - err = vlan_ops->del_vlan(vsi, &vlan); 3817 - if (err && err != -EEXIST) 3818 - return err; 3812 + if (pf->lag && pf->lag->primary) { 3813 + dev_dbg(ice_pf_to_dev(pf), "Interface is primary in aggregate - not deleting prune list\n"); 3814 + } else { 3815 + vlan = ICE_VLAN(0, 0, 0); 3816 + err = vlan_ops->del_vlan(vsi, &vlan); 3817 + if (err && err != -EEXIST) 3818 + return err; 3819 + } 3819 3820 3820 3821 /* in SVM both VLAN 0 filters are identical */ 3821 3822 if (!ice_is_dvm_ena(&vsi->back->hw)) 3822 3823 return 0; 3823 3824 3824 - vlan = ICE_VLAN(ETH_P_8021Q, 0, 0); 3825 - err = vlan_ops->del_vlan(vsi, &vlan); 3826 - if (err && err != -EEXIST) 3827 - return err; 3825 + if (pf->lag && pf->lag->primary) { 3826 + dev_dbg(ice_pf_to_dev(pf), "Interface is primary in aggregate - not deleting QinQ prune list\n"); 3827 + } else { 3828 + vlan = ICE_VLAN(ETH_P_8021Q, 0, 0); 3829 + err = vlan_ops->del_vlan(vsi, &vlan); 3830 + if (err && err != -EEXIST) 3831 + return err; 3832 + } 3828 3833 3829 3834 /* when deleting the last VLAN filter, make sure to disable the VLAN 3830 3835 * promisc mode so the filter isn't left by accident
+3 -2
drivers/net/ethernet/intel/igc/igc_defines.h
··· 443 443 #define IGC_TXPBSIZE_DEFAULT ( \ 444 444 IGC_TXPB0SIZE(20) | IGC_TXPB1SIZE(0) | IGC_TXPB2SIZE(0) | \ 445 445 IGC_TXPB3SIZE(0) | IGC_OS2BMCPBSIZE(4)) 446 + /* TSN value following I225/I226 SW User Manual Section 7.5.4 */ 446 447 #define IGC_TXPBSIZE_TSN ( \ 447 - IGC_TXPB0SIZE(7) | IGC_TXPB1SIZE(7) | IGC_TXPB2SIZE(7) | \ 448 - IGC_TXPB3SIZE(7) | IGC_OS2BMCPBSIZE(4)) 448 + IGC_TXPB0SIZE(5) | IGC_TXPB1SIZE(5) | IGC_TXPB2SIZE(5) | \ 449 + IGC_TXPB3SIZE(5) | IGC_OS2BMCPBSIZE(4)) 449 450 450 451 #define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */ 451 452 #define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
+2 -2
drivers/net/ethernet/intel/igc/igc_ethtool.c
··· 1565 1565 if (ch->other_count != NON_Q_VECTORS) 1566 1566 return -EINVAL; 1567 1567 1568 - /* Do not allow channel reconfiguration when mqprio is enabled */ 1569 - if (adapter->strict_priority_enable) 1568 + /* Do not allow channel reconfiguration when any TSN qdisc is enabled */ 1569 + if (adapter->flags & IGC_FLAG_TSN_ANY_ENABLED) 1570 1570 return -EINVAL; 1571 1571 1572 1572 /* Verify the number of channels doesn't exceed hw limits */
+5
drivers/net/ethernet/intel/igc/igc_main.c
··· 7759 7759 if (netif_running(netdev)) 7760 7760 err = igc_open(netdev); 7761 7761 7762 + if (!err) { 7763 + /* Restore default IEEE 802.1Qbv schedule after queue reinit */ 7764 + igc_tsn_clear_schedule(adapter); 7765 + } 7766 + 7762 7767 return err; 7763 7768 } 7764 7769
+25 -18
drivers/net/ethernet/intel/igc/igc_ptp.c
··· 774 774 static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) 775 775 { 776 776 struct igc_hw *hw = &adapter->hw; 777 + u32 txstmpl_old; 777 778 u64 regval; 778 779 u32 mask; 779 780 int i; 781 + 782 + /* Establish baseline of TXSTMPL_0 before checking TXTT_0. 783 + * This baseline is used to detect if a new timestamp arrives in 784 + * register 0 during the hardware bug workaround below. 785 + */ 786 + txstmpl_old = rd32(IGC_TXSTMPL); 780 787 781 788 mask = rd32(IGC_TSYNCTXCTL) & IGC_TSYNCTXCTL_TXTT_ANY; 782 789 if (mask & IGC_TSYNCTXCTL_TXTT_0) { 783 790 regval = rd32(IGC_TXSTMPL); 784 791 regval |= (u64)rd32(IGC_TXSTMPH) << 32; 785 792 } else { 786 - /* There's a bug in the hardware that could cause 787 - * missing interrupts for TX timestamping. The issue 788 - * is that for new interrupts to be triggered, the 789 - * IGC_TXSTMPH_0 register must be read. 793 + /* TXTT_0 not set - register 0 has no new timestamp initially. 790 794 * 791 - * To avoid discarding a valid timestamp that just 792 - * happened at the "wrong" time, we need to confirm 793 - * that there was no timestamp captured, we do that by 794 - * assuming that no two timestamps in sequence have 795 - * the same nanosecond value. 795 + * Hardware bug: Future timestamp interrupts won't fire unless 796 + * TXSTMPH_0 is read, even if the timestamp was captured in 797 + * registers 1-3. 796 798 * 797 - * So, we read the "low" register, read the "high" 798 - * register (to latch a new timestamp) and read the 799 - * "low" register again, if "old" and "new" versions 800 - * of the "low" register are different, a valid 801 - * timestamp was captured, we can read the "high" 802 - * register again. 799 + * Workaround: Read TXSTMPH_0 here to enable future interrupts. 800 + * However, this read clears TXTT_0. If a timestamp arrives in 801 + * register 0 after checking TXTT_0 but before this read, it 802 + * would be lost. 803 + * 804 + * To detect this race: We saved a baseline read of TXSTMPL_0 805 + * before TXTT_0 check. After performing the workaround read of 806 + * TXSTMPH_0, we read TXSTMPL_0 again. Since consecutive 807 + * timestamps never share the same nanosecond value, a change 808 + * between the baseline and new TXSTMPL_0 indicates a timestamp 809 + * arrived during the race window. If so, read the complete 810 + * timestamp. 803 811 */ 804 - u32 txstmpl_old, txstmpl_new; 812 + u32 txstmpl_new; 805 813 806 - txstmpl_old = rd32(IGC_TXSTMPL); 807 814 rd32(IGC_TXSTMPH); 808 815 txstmpl_new = rd32(IGC_TXSTMPL); 809 816 ··· 825 818 826 819 done: 827 820 /* Now that the problematic first register was handled, we can 828 - * use retrieve the timestamps from the other registers 821 + * retrieve the timestamps from the other registers 829 822 * (starting from '1') with less complications. 830 823 */ 831 824 for (i = 1; i < IGC_MAX_TX_TSTAMP_REGS; i++) {