mirror of
https://github.com/torvalds/linux.git
synced 2026-06-05 13:06:59 +02:00
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>
This commit is contained in:
commit
2c68d5eacc
|
|
@ -2251,7 +2251,7 @@ void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
|
|||
/* there are some rare cases when trying to release the resource
|
||||
* results in an admin queue timeout, so handle them correctly
|
||||
*/
|
||||
timeout = jiffies + 10 * ICE_CTL_Q_SQ_CMD_TIMEOUT;
|
||||
timeout = jiffies + 10 * usecs_to_jiffies(ICE_CTL_Q_SQ_CMD_TIMEOUT);
|
||||
do {
|
||||
status = ice_aq_release_res(hw, res, 0, NULL);
|
||||
if (status != -EIO)
|
||||
|
|
|
|||
|
|
@ -398,6 +398,8 @@ static int ice_vsi_alloc_ring_stats(struct ice_vsi *vsi)
|
|||
if (!ring_stats)
|
||||
goto err_out;
|
||||
|
||||
u64_stats_init(&ring_stats->syncp);
|
||||
|
||||
WRITE_ONCE(tx_ring_stats[i], ring_stats);
|
||||
}
|
||||
|
||||
|
|
@ -417,6 +419,8 @@ static int ice_vsi_alloc_ring_stats(struct ice_vsi *vsi)
|
|||
if (!ring_stats)
|
||||
goto err_out;
|
||||
|
||||
u64_stats_init(&ring_stats->syncp);
|
||||
|
||||
WRITE_ONCE(rx_ring_stats[i], ring_stats);
|
||||
}
|
||||
|
||||
|
|
@ -3805,22 +3809,31 @@ int ice_vsi_add_vlan_zero(struct ice_vsi *vsi)
|
|||
int ice_vsi_del_vlan_zero(struct ice_vsi *vsi)
|
||||
{
|
||||
struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
|
||||
struct ice_pf *pf = vsi->back;
|
||||
struct ice_vlan vlan;
|
||||
int err;
|
||||
|
||||
vlan = ICE_VLAN(0, 0, 0);
|
||||
err = vlan_ops->del_vlan(vsi, &vlan);
|
||||
if (err && err != -EEXIST)
|
||||
return err;
|
||||
if (pf->lag && pf->lag->primary) {
|
||||
dev_dbg(ice_pf_to_dev(pf), "Interface is primary in aggregate - not deleting prune list\n");
|
||||
} else {
|
||||
vlan = ICE_VLAN(0, 0, 0);
|
||||
err = vlan_ops->del_vlan(vsi, &vlan);
|
||||
if (err && err != -EEXIST)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* in SVM both VLAN 0 filters are identical */
|
||||
if (!ice_is_dvm_ena(&vsi->back->hw))
|
||||
return 0;
|
||||
|
||||
vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
|
||||
err = vlan_ops->del_vlan(vsi, &vlan);
|
||||
if (err && err != -EEXIST)
|
||||
return err;
|
||||
if (pf->lag && pf->lag->primary) {
|
||||
dev_dbg(ice_pf_to_dev(pf), "Interface is primary in aggregate - not deleting QinQ prune list\n");
|
||||
} else {
|
||||
vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
|
||||
err = vlan_ops->del_vlan(vsi, &vlan);
|
||||
if (err && err != -EEXIST)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* when deleting the last VLAN filter, make sure to disable the VLAN
|
||||
* promisc mode so the filter isn't left by accident
|
||||
|
|
|
|||
|
|
@ -443,9 +443,10 @@
|
|||
#define IGC_TXPBSIZE_DEFAULT ( \
|
||||
IGC_TXPB0SIZE(20) | IGC_TXPB1SIZE(0) | IGC_TXPB2SIZE(0) | \
|
||||
IGC_TXPB3SIZE(0) | IGC_OS2BMCPBSIZE(4))
|
||||
/* TSN value following I225/I226 SW User Manual Section 7.5.4 */
|
||||
#define IGC_TXPBSIZE_TSN ( \
|
||||
IGC_TXPB0SIZE(7) | IGC_TXPB1SIZE(7) | IGC_TXPB2SIZE(7) | \
|
||||
IGC_TXPB3SIZE(7) | IGC_OS2BMCPBSIZE(4))
|
||||
IGC_TXPB0SIZE(5) | IGC_TXPB1SIZE(5) | IGC_TXPB2SIZE(5) | \
|
||||
IGC_TXPB3SIZE(5) | IGC_OS2BMCPBSIZE(4))
|
||||
|
||||
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
|
||||
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
|
||||
|
|
|
|||
|
|
@ -1565,8 +1565,8 @@ static int igc_ethtool_set_channels(struct net_device *netdev,
|
|||
if (ch->other_count != NON_Q_VECTORS)
|
||||
return -EINVAL;
|
||||
|
||||
/* Do not allow channel reconfiguration when mqprio is enabled */
|
||||
if (adapter->strict_priority_enable)
|
||||
/* Do not allow channel reconfiguration when any TSN qdisc is enabled */
|
||||
if (adapter->flags & IGC_FLAG_TSN_ANY_ENABLED)
|
||||
return -EINVAL;
|
||||
|
||||
/* Verify the number of channels doesn't exceed hw limits */
|
||||
|
|
|
|||
|
|
@ -7759,6 +7759,11 @@ int igc_reinit_queues(struct igc_adapter *adapter)
|
|||
if (netif_running(netdev))
|
||||
err = igc_open(netdev);
|
||||
|
||||
if (!err) {
|
||||
/* Restore default IEEE 802.1Qbv schedule after queue reinit */
|
||||
igc_tsn_clear_schedule(adapter);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -774,36 +774,43 @@ static void igc_ptp_tx_reg_to_stamp(struct igc_adapter *adapter,
|
|||
static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 txstmpl_old;
|
||||
u64 regval;
|
||||
u32 mask;
|
||||
int i;
|
||||
|
||||
/* Establish baseline of TXSTMPL_0 before checking TXTT_0.
|
||||
* This baseline is used to detect if a new timestamp arrives in
|
||||
* register 0 during the hardware bug workaround below.
|
||||
*/
|
||||
txstmpl_old = rd32(IGC_TXSTMPL);
|
||||
|
||||
mask = rd32(IGC_TSYNCTXCTL) & IGC_TSYNCTXCTL_TXTT_ANY;
|
||||
if (mask & IGC_TSYNCTXCTL_TXTT_0) {
|
||||
regval = rd32(IGC_TXSTMPL);
|
||||
regval |= (u64)rd32(IGC_TXSTMPH) << 32;
|
||||
} else {
|
||||
/* There's a bug in the hardware that could cause
|
||||
* missing interrupts for TX timestamping. The issue
|
||||
* is that for new interrupts to be triggered, the
|
||||
* IGC_TXSTMPH_0 register must be read.
|
||||
/* TXTT_0 not set - register 0 has no new timestamp initially.
|
||||
*
|
||||
* To avoid discarding a valid timestamp that just
|
||||
* happened at the "wrong" time, we need to confirm
|
||||
* that there was no timestamp captured, we do that by
|
||||
* assuming that no two timestamps in sequence have
|
||||
* the same nanosecond value.
|
||||
* Hardware bug: Future timestamp interrupts won't fire unless
|
||||
* TXSTMPH_0 is read, even if the timestamp was captured in
|
||||
* registers 1-3.
|
||||
*
|
||||
* So, we read the "low" register, read the "high"
|
||||
* register (to latch a new timestamp) and read the
|
||||
* "low" register again, if "old" and "new" versions
|
||||
* of the "low" register are different, a valid
|
||||
* timestamp was captured, we can read the "high"
|
||||
* register again.
|
||||
* Workaround: Read TXSTMPH_0 here to enable future interrupts.
|
||||
* However, this read clears TXTT_0. If a timestamp arrives in
|
||||
* register 0 after checking TXTT_0 but before this read, it
|
||||
* would be lost.
|
||||
*
|
||||
* To detect this race: We saved a baseline read of TXSTMPL_0
|
||||
* before TXTT_0 check. After performing the workaround read of
|
||||
* TXSTMPH_0, we read TXSTMPL_0 again. Since consecutive
|
||||
* timestamps never share the same nanosecond value, a change
|
||||
* between the baseline and new TXSTMPL_0 indicates a timestamp
|
||||
* arrived during the race window. If so, read the complete
|
||||
* timestamp.
|
||||
*/
|
||||
u32 txstmpl_old, txstmpl_new;
|
||||
u32 txstmpl_new;
|
||||
|
||||
txstmpl_old = rd32(IGC_TXSTMPL);
|
||||
rd32(IGC_TXSTMPH);
|
||||
txstmpl_new = rd32(IGC_TXSTMPL);
|
||||
|
||||
|
|
@ -818,7 +825,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
|
|||
|
||||
done:
|
||||
/* Now that the problematic first register was handled, we can
|
||||
* use retrieve the timestamps from the other registers
|
||||
* retrieve the timestamps from the other registers
|
||||
* (starting from '1') with less complications.
|
||||
*/
|
||||
for (i = 1; i < IGC_MAX_TX_TSTAMP_REGS; i++) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user