mirror of
https://github.com/torvalds/linux.git
synced 2026-05-22 22:22:08 +02:00
Merge branch 'intel-next-queue-1GbE'
Tony Nguyen says: ==================== Faizal Rahim says: MAC Merge support for frame preemption was previously added for igc: https://lore.kernel.org/netdev/20250418163822.3519810-1-anthony.l.nguyen@intel.com/ This series builds on that work and adds support for: - Harmonizing taprio and mqprio queue priority behavior, based on past discussions and suggestions: https://lore.kernel.org/all/20250214102206.25dqgut5tbak2rkz@skbuf/ - Enabling preemptible queue support for both taprio and mqprio, with priority harmonization as a prerequisite. Patch organization: - Patches 1-3: Preparation work for patches 6 and 7 - Patches 4-5: Queue priority harmonization - Patches 6-7: Add preemptible queue support ==================== Link: https://patch.msgid.link/20250611180314.2059166-1-anthony.l.nguyen@intel.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
9149a63288
|
|
@ -43,6 +43,7 @@ void igc_ethtool_set_ops(struct net_device *);
|
|||
struct igc_fpe_t {
|
||||
struct ethtool_mmsv mmsv;
|
||||
u32 tx_min_frag_size;
|
||||
bool tx_enabled;
|
||||
};
|
||||
|
||||
enum igc_mac_filter_type {
|
||||
|
|
@ -163,6 +164,7 @@ struct igc_ring {
|
|||
bool launchtime_enable; /* true if LaunchTime is enabled */
|
||||
ktime_t last_tx_cycle; /* end of the cycle with a launchtime transmission */
|
||||
ktime_t last_ff_cycle; /* Last cycle with an active first flag */
|
||||
bool preemptible; /* True if preemptible queue, false if express queue */
|
||||
|
||||
u32 start_time;
|
||||
u32 end_time;
|
||||
|
|
@ -395,6 +397,7 @@ extern char igc_driver_name[];
|
|||
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
|
||||
#define IGC_FLAG_TSN_QAV_ENABLED BIT(18)
|
||||
#define IGC_FLAG_TSN_PREEMPT_ENABLED BIT(19)
|
||||
#define IGC_FLAG_TSN_REVERSE_TXQ_PRIO BIT(20)
|
||||
|
||||
#define IGC_FLAG_TSN_ANY_ENABLED \
|
||||
(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED | \
|
||||
|
|
@ -485,12 +488,30 @@ static inline u32 igc_rss_type(const union igc_adv_rx_desc *rx_desc)
|
|||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGC_RX_PTHRESH 8
|
||||
#define IGC_RX_HTHRESH 8
|
||||
#define IGC_TX_PTHRESH 8
|
||||
#define IGC_TX_HTHRESH 1
|
||||
#define IGC_RX_WTHRESH 4
|
||||
#define IGC_TX_WTHRESH 16
|
||||
#define IGC_RXDCTL_PTHRESH 8
|
||||
#define IGC_RXDCTL_HTHRESH 8
|
||||
#define IGC_RXDCTL_WTHRESH 4
|
||||
/* Ena specific Rx Queue */
|
||||
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000
|
||||
/* Receive Software Flush */
|
||||
#define IGC_RXDCTL_SWFLUSH 0x04000000
|
||||
|
||||
#define IGC_TXDCTL_PTHRESH_MASK GENMASK(4, 0)
|
||||
#define IGC_TXDCTL_HTHRESH_MASK GENMASK(12, 8)
|
||||
#define IGC_TXDCTL_WTHRESH_MASK GENMASK(20, 16)
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE_MASK GENMASK(25, 25)
|
||||
#define IGC_TXDCTL_SWFLUSH_MASK GENMASK(26, 26)
|
||||
#define IGC_TXDCTL_PRIORITY_MASK GENMASK(27, 27)
|
||||
|
||||
#define IGC_TXDCTL_PTHRESH(x) FIELD_PREP(IGC_TXDCTL_PTHRESH_MASK, (x))
|
||||
#define IGC_TXDCTL_HTHRESH(x) FIELD_PREP(IGC_TXDCTL_HTHRESH_MASK, (x))
|
||||
#define IGC_TXDCTL_WTHRESH(x) FIELD_PREP(IGC_TXDCTL_WTHRESH_MASK, (x))
|
||||
/* Ena specific Tx Queue */
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE FIELD_PREP(IGC_TXDCTL_QUEUE_ENABLE_MASK, 1)
|
||||
/* Transmit Software Flush */
|
||||
#define IGC_TXDCTL_SWFLUSH FIELD_PREP(IGC_TXDCTL_SWFLUSH_MASK, 1)
|
||||
#define IGC_TXDCTL_PRIORITY(x) FIELD_PREP(IGC_TXDCTL_PRIORITY_MASK, (x))
|
||||
#define IGC_TXDCTL_PRIORITY_HIGH IGC_TXDCTL_PRIORITY(1)
|
||||
|
||||
#define IGC_RX_DMA_ATTR \
|
||||
(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
|
||||
|
|
|
|||
|
|
@ -86,14 +86,6 @@ union igc_adv_rx_desc {
|
|||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
|
||||
#define IGC_TXDCTL_SWFLUSH 0x04000000 /* Transmit Software Flush */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
|
||||
#define IGC_RXDCTL_SWFLUSH 0x04000000 /* Receive Software Flush */
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define IGC_SRRCTL_BSIZEPKT_MASK GENMASK(6, 0)
|
||||
#define IGC_SRRCTL_BSIZEPKT(x) FIELD_PREP(IGC_SRRCTL_BSIZEPKT_MASK, \
|
||||
|
|
|
|||
|
|
@ -588,6 +588,7 @@
|
|||
#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
|
||||
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002
|
||||
#define IGC_TXQCTL_STRICT_END 0x00000004
|
||||
#define IGC_TXQCTL_PREEMPTIBLE 0x00000008
|
||||
#define IGC_TXQCTL_QAV_SEL_MASK 0x000000C0
|
||||
#define IGC_TXQCTL_QAV_SEL_CBS0 0x00000080
|
||||
#define IGC_TXQCTL_QAV_SEL_CBS1 0x000000C0
|
||||
|
|
|
|||
|
|
@ -122,9 +122,11 @@ static const char igc_gstrings_test[][ETH_GSTRING_LEN] = {
|
|||
#define IGC_STATS_LEN \
|
||||
(IGC_GLOBAL_STATS_LEN + IGC_NETDEV_STATS_LEN + IGC_QUEUE_STATS_LEN)
|
||||
|
||||
#define IGC_PRIV_FLAGS_LEGACY_RX BIT(0)
|
||||
#define IGC_PRIV_FLAGS_REVERSE_TSN_TXQ_PRIO BIT(1)
|
||||
static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = {
|
||||
#define IGC_PRIV_FLAGS_LEGACY_RX BIT(0)
|
||||
"legacy-rx",
|
||||
"reverse-tsn-txq-prio",
|
||||
};
|
||||
|
||||
#define IGC_PRIV_FLAGS_STR_LEN ARRAY_SIZE(igc_priv_flags_strings)
|
||||
|
|
@ -1600,6 +1602,9 @@ static u32 igc_ethtool_get_priv_flags(struct net_device *netdev)
|
|||
if (adapter->flags & IGC_FLAG_RX_LEGACY)
|
||||
priv_flags |= IGC_PRIV_FLAGS_LEGACY_RX;
|
||||
|
||||
if (adapter->flags & IGC_FLAG_TSN_REVERSE_TXQ_PRIO)
|
||||
priv_flags |= IGC_PRIV_FLAGS_REVERSE_TSN_TXQ_PRIO;
|
||||
|
||||
return priv_flags;
|
||||
}
|
||||
|
||||
|
|
@ -1608,10 +1613,13 @@ static int igc_ethtool_set_priv_flags(struct net_device *netdev, u32 priv_flags)
|
|||
struct igc_adapter *adapter = netdev_priv(netdev);
|
||||
unsigned int flags = adapter->flags;
|
||||
|
||||
flags &= ~IGC_FLAG_RX_LEGACY;
|
||||
flags &= ~(IGC_FLAG_RX_LEGACY | IGC_FLAG_TSN_REVERSE_TXQ_PRIO);
|
||||
if (priv_flags & IGC_PRIV_FLAGS_LEGACY_RX)
|
||||
flags |= IGC_FLAG_RX_LEGACY;
|
||||
|
||||
if (priv_flags & IGC_PRIV_FLAGS_REVERSE_TSN_TXQ_PRIO)
|
||||
flags |= IGC_FLAG_TSN_REVERSE_TXQ_PRIO;
|
||||
|
||||
if (flags != adapter->flags) {
|
||||
adapter->flags = flags;
|
||||
|
||||
|
|
|
|||
|
|
@ -683,9 +683,9 @@ static void igc_configure_rx_ring(struct igc_adapter *adapter,
|
|||
|
||||
wr32(IGC_SRRCTL(reg_idx), srrctl);
|
||||
|
||||
rxdctl |= IGC_RX_PTHRESH;
|
||||
rxdctl |= IGC_RX_HTHRESH << 8;
|
||||
rxdctl |= IGC_RX_WTHRESH << 16;
|
||||
rxdctl |= IGC_RXDCTL_PTHRESH;
|
||||
rxdctl |= IGC_RXDCTL_HTHRESH << 8;
|
||||
rxdctl |= IGC_RXDCTL_WTHRESH << 16;
|
||||
|
||||
/* initialize rx_buffer_info */
|
||||
memset(ring->rx_buffer_info, 0,
|
||||
|
|
@ -749,11 +749,9 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter,
|
|||
wr32(IGC_TDH(reg_idx), 0);
|
||||
writel(0, ring->tail);
|
||||
|
||||
txdctl |= IGC_TX_PTHRESH;
|
||||
txdctl |= IGC_TX_HTHRESH << 8;
|
||||
txdctl |= IGC_TX_WTHRESH << 16;
|
||||
txdctl |= IGC_TXDCTL_PTHRESH(8) | IGC_TXDCTL_HTHRESH(1) |
|
||||
IGC_TXDCTL_WTHRESH(16) | IGC_TXDCTL_QUEUE_ENABLE;
|
||||
|
||||
txdctl |= IGC_TXDCTL_QUEUE_ENABLE;
|
||||
wr32(IGC_TXDCTL(reg_idx), txdctl);
|
||||
}
|
||||
|
||||
|
|
@ -1687,6 +1685,15 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
|
|||
first->tx_flags = tx_flags;
|
||||
first->protocol = protocol;
|
||||
|
||||
/* For preemptible queue, manually pad the skb so that HW includes
|
||||
* padding bytes in mCRC calculation
|
||||
*/
|
||||
if (tx_ring->preemptible && skb->len < ETH_ZLEN) {
|
||||
if (skb_padto(skb, ETH_ZLEN))
|
||||
goto out_drop;
|
||||
skb_put(skb, ETH_ZLEN - skb->len);
|
||||
}
|
||||
|
||||
tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len);
|
||||
if (tso < 0)
|
||||
goto out_drop;
|
||||
|
|
@ -6423,6 +6430,7 @@ static int igc_qbv_clear_schedule(struct igc_adapter *adapter)
|
|||
ring->start_time = 0;
|
||||
ring->end_time = NSEC_PER_SEC;
|
||||
ring->max_sdu = 0;
|
||||
ring->preemptible = false;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
|
||||
|
|
@ -6488,9 +6496,12 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
|
|||
if (!validate_schedule(adapter, qopt))
|
||||
return -EINVAL;
|
||||
|
||||
/* preemptible isn't supported yet */
|
||||
if (qopt->mqprio.preemptible_tcs)
|
||||
return -EOPNOTSUPP;
|
||||
if (qopt->mqprio.preemptible_tcs &&
|
||||
!(adapter->flags & IGC_FLAG_TSN_REVERSE_TXQ_PRIO)) {
|
||||
NL_SET_ERR_MSG_MOD(qopt->extack,
|
||||
"reverse-tsn-txq-prio private flag must be enabled before setting preemptible tc");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
igc_ptp_read(adapter, &now);
|
||||
|
||||
|
|
@ -6583,6 +6594,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
|
|||
ring->max_sdu = 0;
|
||||
}
|
||||
|
||||
igc_fpe_save_preempt_queue(adapter, &qopt->mqprio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -6702,7 +6715,8 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,
|
|||
case TC_SETUP_QDISC_TAPRIO: {
|
||||
struct tc_taprio_caps *caps = base->caps;
|
||||
|
||||
caps->broken_mqprio = true;
|
||||
if (!(adapter->flags & IGC_FLAG_TSN_REVERSE_TXQ_PRIO))
|
||||
caps->broken_mqprio = true;
|
||||
|
||||
if (hw->mac.type == igc_i225) {
|
||||
caps->supports_queue_max_sdu = true;
|
||||
|
|
@ -6728,6 +6742,20 @@ static void igc_save_mqprio_params(struct igc_adapter *adapter, u8 num_tc,
|
|||
adapter->queue_per_tc[i] = offset[i];
|
||||
}
|
||||
|
||||
static bool
|
||||
igc_tsn_is_tc_to_queue_priority_ordered(struct tc_mqprio_qopt_offload *mqprio)
|
||||
{
|
||||
int num_tc = mqprio->qopt.num_tc;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < num_tc; i++) {
|
||||
if (mqprio->qopt.offset[i - 1] > mqprio->qopt.offset[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,
|
||||
struct tc_mqprio_qopt_offload *mqprio)
|
||||
{
|
||||
|
|
@ -6739,6 +6767,7 @@ static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,
|
|||
|
||||
if (!mqprio->qopt.num_tc) {
|
||||
adapter->strict_priority_enable = false;
|
||||
igc_fpe_clear_preempt_queue(adapter);
|
||||
netdev_reset_tc(adapter->netdev);
|
||||
goto apply;
|
||||
}
|
||||
|
|
@ -6760,10 +6789,9 @@ static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,
|
|||
}
|
||||
}
|
||||
|
||||
/* Preemption is not supported yet. */
|
||||
if (mqprio->preemptible_tcs) {
|
||||
if (!igc_tsn_is_tc_to_queue_priority_ordered(mqprio)) {
|
||||
NL_SET_ERR_MSG_MOD(mqprio->extack,
|
||||
"Preemption is not supported yet");
|
||||
"tc to queue mapping must preserve increasing priority (higher tc -> higher queue)");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
|
@ -6786,6 +6814,7 @@ static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,
|
|||
adapter->queue_per_tc[i] = i;
|
||||
|
||||
mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
igc_fpe_save_preempt_queue(adapter, mqprio);
|
||||
|
||||
apply:
|
||||
return igc_tsn_offload_apply(adapter);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@
|
|||
#define TX_MAX_FRAG_SIZE (TX_MIN_FRAG_SIZE * \
|
||||
(MAX_MULTPLIER_TX_MIN_FRAG + 1))
|
||||
|
||||
enum tx_queue {
|
||||
TX_QUEUE_0 = 0,
|
||||
TX_QUEUE_1,
|
||||
TX_QUEUE_2,
|
||||
TX_QUEUE_3,
|
||||
};
|
||||
|
||||
DEFINE_STATIC_KEY_FALSE(igc_fpe_enabled);
|
||||
|
||||
static int igc_fpe_init_smd_frame(struct igc_ring *ring,
|
||||
|
|
@ -109,6 +116,18 @@ static int igc_fpe_xmit_smd_frame(struct igc_adapter *adapter,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void igc_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable)
|
||||
{
|
||||
struct igc_fpe_t *fpe = container_of(mmsv, struct igc_fpe_t, mmsv);
|
||||
struct igc_adapter *adapter;
|
||||
|
||||
adapter = container_of(fpe, struct igc_adapter, fpe);
|
||||
adapter->fpe.tx_enabled = tx_enable;
|
||||
|
||||
/* Update config since tx_enabled affects preemptible queue configuration */
|
||||
igc_tsn_offload_apply(adapter);
|
||||
}
|
||||
|
||||
static void igc_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
|
||||
enum ethtool_mpacket type)
|
||||
{
|
||||
|
|
@ -130,15 +149,59 @@ static void igc_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
|
|||
}
|
||||
|
||||
static const struct ethtool_mmsv_ops igc_mmsv_ops = {
|
||||
.configure_tx = igc_fpe_configure_tx,
|
||||
.send_mpacket = igc_fpe_send_mpacket,
|
||||
};
|
||||
|
||||
void igc_fpe_init(struct igc_adapter *adapter)
|
||||
{
|
||||
adapter->fpe.tx_min_frag_size = TX_MIN_FRAG_SIZE;
|
||||
adapter->fpe.tx_enabled = false;
|
||||
ethtool_mmsv_init(&adapter->fpe.mmsv, adapter->netdev, &igc_mmsv_ops);
|
||||
}
|
||||
|
||||
void igc_fpe_clear_preempt_queue(struct igc_adapter *adapter)
|
||||
{
|
||||
for (int i = 0; i < adapter->num_tx_queues; i++) {
|
||||
struct igc_ring *tx_ring = adapter->tx_ring[i];
|
||||
|
||||
tx_ring->preemptible = false;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 igc_fpe_map_preempt_tc_to_queue(const struct igc_adapter *adapter,
|
||||
unsigned long preemptible_tcs)
|
||||
{
|
||||
struct net_device *dev = adapter->netdev;
|
||||
u32 i, queue = 0;
|
||||
|
||||
for (i = 0; i < dev->num_tc; i++) {
|
||||
u32 offset, count;
|
||||
|
||||
if (!(preemptible_tcs & BIT(i)))
|
||||
continue;
|
||||
|
||||
offset = dev->tc_to_txq[i].offset;
|
||||
count = dev->tc_to_txq[i].count;
|
||||
queue |= GENMASK(offset + count - 1, offset);
|
||||
}
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
void igc_fpe_save_preempt_queue(struct igc_adapter *adapter,
|
||||
const struct tc_mqprio_qopt_offload *mqprio)
|
||||
{
|
||||
u32 preemptible_queue = igc_fpe_map_preempt_tc_to_queue(adapter,
|
||||
mqprio->preemptible_tcs);
|
||||
|
||||
for (int i = 0; i < adapter->num_tx_queues; i++) {
|
||||
struct igc_ring *tx_ring = adapter->tx_ring[i];
|
||||
|
||||
tx_ring->preemptible = !!(preemptible_queue & BIT(i));
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_any_launchtime(struct igc_adapter *adapter)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -238,7 +301,7 @@ bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter)
|
|||
adapter->taprio_offload_enable;
|
||||
}
|
||||
|
||||
static void igc_tsn_tx_arb(struct igc_adapter *adapter, u16 *queue_per_tc)
|
||||
static void igc_tsn_tx_arb(struct igc_adapter *adapter, bool reverse_prio)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 txarb;
|
||||
|
|
@ -250,10 +313,17 @@ static void igc_tsn_tx_arb(struct igc_adapter *adapter, u16 *queue_per_tc)
|
|||
IGC_TXARB_TXQ_PRIO_2_MASK |
|
||||
IGC_TXARB_TXQ_PRIO_3_MASK);
|
||||
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_0(queue_per_tc[3]);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_1(queue_per_tc[2]);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_2(queue_per_tc[1]);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_3(queue_per_tc[0]);
|
||||
if (reverse_prio) {
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_0(TX_QUEUE_3);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_1(TX_QUEUE_2);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_2(TX_QUEUE_1);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_3(TX_QUEUE_0);
|
||||
} else {
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_0(TX_QUEUE_0);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_1(TX_QUEUE_1);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_2(TX_QUEUE_2);
|
||||
txarb |= IGC_TXARB_TXQ_PRIO_3(TX_QUEUE_3);
|
||||
}
|
||||
|
||||
wr32(IGC_TXARB, txarb);
|
||||
}
|
||||
|
|
@ -286,7 +356,6 @@ static void igc_tsn_set_rxpbsize(struct igc_adapter *adapter,
|
|||
*/
|
||||
static int igc_tsn_disable_offload(struct igc_adapter *adapter)
|
||||
{
|
||||
u16 queue_per_tc[4] = { 3, 2, 1, 0 };
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 tqavctrl;
|
||||
int i;
|
||||
|
|
@ -308,9 +377,16 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
|
|||
wr32(IGC_TQAVCTRL, tqavctrl);
|
||||
|
||||
for (i = 0; i < adapter->num_tx_queues; i++) {
|
||||
int reg_idx = adapter->tx_ring[i]->reg_idx;
|
||||
u32 txdctl;
|
||||
|
||||
wr32(IGC_TXQCTL(i), 0);
|
||||
wr32(IGC_STQT(i), 0);
|
||||
wr32(IGC_ENDQT(i), NSEC_PER_SEC);
|
||||
|
||||
txdctl = rd32(IGC_TXDCTL(reg_idx));
|
||||
txdctl &= ~IGC_TXDCTL_PRIORITY_HIGH;
|
||||
wr32(IGC_TXDCTL(reg_idx), txdctl);
|
||||
}
|
||||
|
||||
wr32(IGC_QBVCYCLET_S, 0);
|
||||
|
|
@ -319,7 +395,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
|
|||
/* Restore the default Tx arbitration: Priority 0 has the highest
|
||||
* priority and is assigned to queue 0 and so on and so forth.
|
||||
*/
|
||||
igc_tsn_tx_arb(adapter, queue_per_tc);
|
||||
igc_tsn_tx_arb(adapter, false);
|
||||
|
||||
adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
|
||||
|
||||
|
|
@ -385,15 +461,13 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
|
|||
if (igc_is_device_id_i226(hw))
|
||||
igc_tsn_set_retx_qbvfullthreshold(adapter);
|
||||
|
||||
if (adapter->strict_priority_enable) {
|
||||
/* Configure queue priorities according to the user provided
|
||||
* mapping.
|
||||
*/
|
||||
igc_tsn_tx_arb(adapter, adapter->queue_per_tc);
|
||||
}
|
||||
if (adapter->strict_priority_enable ||
|
||||
adapter->flags & IGC_FLAG_TSN_REVERSE_TXQ_PRIO)
|
||||
igc_tsn_tx_arb(adapter, true);
|
||||
|
||||
for (i = 0; i < adapter->num_tx_queues; i++) {
|
||||
struct igc_ring *ring = adapter->tx_ring[i];
|
||||
u32 txdctl = rd32(IGC_TXDCTL(ring->reg_idx));
|
||||
u32 txqctl = 0;
|
||||
u16 cbs_value;
|
||||
u32 tqavcc;
|
||||
|
|
@ -427,6 +501,22 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
|
|||
if (ring->launchtime_enable)
|
||||
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
|
||||
|
||||
if (!adapter->fpe.tx_enabled) {
|
||||
/* fpe inactive: clear both flags */
|
||||
txqctl &= ~IGC_TXQCTL_PREEMPTIBLE;
|
||||
txdctl &= ~IGC_TXDCTL_PRIORITY_HIGH;
|
||||
} else if (ring->preemptible) {
|
||||
/* fpe active + preemptible: enable preemptible queue + set low priority */
|
||||
txqctl |= IGC_TXQCTL_PREEMPTIBLE;
|
||||
txdctl &= ~IGC_TXDCTL_PRIORITY_HIGH;
|
||||
} else {
|
||||
/* fpe active + express: enable express queue + set high priority */
|
||||
txqctl &= ~IGC_TXQCTL_PREEMPTIBLE;
|
||||
txdctl |= IGC_TXDCTL_PRIORITY_HIGH;
|
||||
}
|
||||
|
||||
wr32(IGC_TXDCTL(ring->reg_idx), txdctl);
|
||||
|
||||
/* Skip configuring CBS for Q2 and Q3 */
|
||||
if (i > 1)
|
||||
goto skip_cbs;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#ifndef _IGC_TSN_H_
|
||||
#define _IGC_TSN_H_
|
||||
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
#define IGC_RX_MIN_FRAG_SIZE 60
|
||||
#define SMD_FRAME_SIZE 60
|
||||
|
||||
|
|
@ -15,6 +17,9 @@ enum igc_txd_popts_type {
|
|||
DECLARE_STATIC_KEY_FALSE(igc_fpe_enabled);
|
||||
|
||||
void igc_fpe_init(struct igc_adapter *adapter);
|
||||
void igc_fpe_clear_preempt_queue(struct igc_adapter *adapter);
|
||||
void igc_fpe_save_preempt_queue(struct igc_adapter *adapter,
|
||||
const struct tc_mqprio_qopt_offload *mqprio);
|
||||
u32 igc_fpe_get_supported_frag_size(u32 frag_size);
|
||||
int igc_tsn_offload_apply(struct igc_adapter *adapter);
|
||||
int igc_tsn_reset(struct igc_adapter *adapter);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user