summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/igc/igc_main.c
diff options
context:
space:
mode:
authorKurt Kanzenbach <kurt@linutronix.de>2024-06-21 09:25:55 +0200
committerTony Nguyen <anthony.l.nguyen@intel.com>2024-08-30 07:33:46 -0700
commit9f3297511dae19b28b333134cbf7e8746722d6a5 (patch)
treeed7831a7e2a08ca0fc20eb4c37cf0a1c6704c1df /drivers/net/ethernet/intel/igc/igc_main.c
parentfbdaffe41adca26cb9566e92060b97cd6dd87b60 (diff)
igc: Add MQPRIO offload support
Add support for offloading MQPRIO. The hardware has four priorities as well as four queues. Each queue must be a assigned with a unique priority. However, the priorities are only considered in TSN Tx mode. There are two TSN Tx modes. In case of MQPRIO the Qbv capability is not required. Therefore, use the legacy TSN Tx mode, which performs strict priority arbitration. Example for mqprio with hardware offload: |tc qdisc replace dev ${INTERFACE} handle 100 parent root mqprio num_tc 4 \ | map 0 0 0 0 0 1 2 3 0 0 0 0 0 0 0 0 \ | queues 1@0 1@1 1@2 1@3 \ | hw 1 The mqprio Qdisc also allows to configure the `preemptible_tcs'. However, frame preemption is not supported yet. Tested on Intel i225 and implemented by following data sheet section 7.5.2, Transmit Scheduling. Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com> Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Tested-by: Mor Bar-Gabay <morx.bar.gabay@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igc/igc_main.c')
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index dfd6c00b4205..96b2f2a37bc3 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6515,6 +6515,13 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,
struct igc_hw *hw = &adapter->hw;
switch (base->type) {
+ case TC_SETUP_QDISC_MQPRIO: {
+ struct tc_mqprio_caps *caps = base->caps;
+
+ caps->validate_queue_counts = true;
+
+ return 0;
+ }
case TC_SETUP_QDISC_TAPRIO: {
struct tc_taprio_caps *caps = base->caps;
@@ -6532,6 +6539,65 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,
}
}
+static void igc_save_mqprio_params(struct igc_adapter *adapter, u8 num_tc,
+ u16 *offset)
+{
+ int i;
+
+ adapter->strict_priority_enable = true;
+ adapter->num_tc = num_tc;
+
+ for (i = 0; i < num_tc; i++)
+ adapter->queue_per_tc[i] = offset[i];
+}
+
+static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,
+ struct tc_mqprio_qopt_offload *mqprio)
+{
+ struct igc_hw *hw = &adapter->hw;
+ int i;
+
+ if (hw->mac.type != igc_i225)
+ return -EOPNOTSUPP;
+
+ if (!mqprio->qopt.num_tc) {
+ adapter->strict_priority_enable = false;
+ goto apply;
+ }
+
+ /* There are as many TCs as Tx queues. */
+ if (mqprio->qopt.num_tc != adapter->num_tx_queues) {
+ NL_SET_ERR_MSG_FMT_MOD(mqprio->extack,
+ "Only %d traffic classes supported",
+ adapter->num_tx_queues);
+ return -EOPNOTSUPP;
+ }
+
+ /* Only one queue per TC is supported. */
+ for (i = 0; i < mqprio->qopt.num_tc; i++) {
+ if (mqprio->qopt.count[i] != 1) {
+ NL_SET_ERR_MSG_MOD(mqprio->extack,
+ "Only one queue per TC supported");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ /* Preemption is not supported yet. */
+ if (mqprio->preemptible_tcs) {
+ NL_SET_ERR_MSG_MOD(mqprio->extack,
+ "Preemption is not supported yet");
+ return -EOPNOTSUPP;
+ }
+
+ igc_save_mqprio_params(adapter, mqprio->qopt.num_tc,
+ mqprio->qopt.offset);
+
+ mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;
+
+apply:
+ return igc_tsn_offload_apply(adapter);
+}
+
static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -6551,6 +6617,9 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
case TC_SETUP_QDISC_CBS:
return igc_tsn_enable_cbs(adapter, type_data);
+ case TC_SETUP_QDISC_MQPRIO:
+ return igc_tsn_enable_mqprio(adapter, type_data);
+
default:
return -EOPNOTSUPP;
}