diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igc')
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_tsn.c | 35 |
2 files changed, 42 insertions, 13 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index f3a312c9413b..1322a2db6dba 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6724,6 +6724,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) { @@ -6756,6 +6770,12 @@ static int igc_tsn_enable_mqprio(struct igc_adapter *adapter, } } + if (!igc_tsn_is_tc_to_queue_priority_ordered(mqprio)) { + NL_SET_ERR_MSG_MOD(mqprio->extack, + "tc to queue mapping must preserve increasing priority (higher tc -> higher queue)"); + return -EOPNOTSUPP; + } + /* Preemption is not supported yet. */ if (mqprio->preemptible_tcs) { NL_SET_ERR_MSG_MOD(mqprio->extack, diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c index f22cc4d4f459..78a4a9cf5f96 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.c +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c @@ -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, @@ -238,7 +245,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 +257,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 +300,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; @@ -319,7 +332,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,12 +398,8 @@ 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) + igc_tsn_tx_arb(adapter, true); for (i = 0; i < adapter->num_tx_queues; i++) { struct igc_ring *ring = adapter->tx_ring[i]; |