Skip to content

Commit 9f32975

Browse files
shifty91anguy11
authored andcommitted
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 <[email protected]> Reviewed-by: Wojciech Drewek <[email protected]> Acked-by: Vinicius Costa Gomes <[email protected]> Reviewed-by: Simon Horman <[email protected]> Tested-by: Mor Bar-Gabay <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent fbdaffe commit 9f32975

File tree

6 files changed

+161
-2
lines changed

6 files changed

+161
-2
lines changed

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ struct igc_adapter {
259259
*/
260260
spinlock_t qbv_tx_lock;
261261

262+
bool strict_priority_enable;
263+
u8 num_tc;
264+
u16 queue_per_tc[IGC_MAX_TX_QUEUES];
265+
262266
/* OS defined structs */
263267
struct pci_dev *pdev;
264268
/* lock for statistics */
@@ -382,9 +386,11 @@ extern char igc_driver_name[];
382386
#define IGC_FLAG_RX_LEGACY BIT(16)
383387
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
384388
#define IGC_FLAG_TSN_QAV_ENABLED BIT(18)
389+
#define IGC_FLAG_TSN_LEGACY_ENABLED BIT(19)
385390

386-
#define IGC_FLAG_TSN_ANY_ENABLED \
387-
(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED)
391+
#define IGC_FLAG_TSN_ANY_ENABLED \
392+
(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED | \
393+
IGC_FLAG_TSN_LEGACY_ENABLED)
388394

389395
#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
390396
#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)

drivers/net/ethernet/intel/igc/igc_defines.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#ifndef _IGC_DEFINES_H_
55
#define _IGC_DEFINES_H_
66

7+
#include <linux/bitfield.h>
8+
79
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
810
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
911
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
@@ -553,6 +555,15 @@
553555

554556
#define IGC_MAX_SR_QUEUES 2
555557

558+
#define IGC_TXARB_TXQ_PRIO_0_MASK GENMASK(1, 0)
559+
#define IGC_TXARB_TXQ_PRIO_1_MASK GENMASK(3, 2)
560+
#define IGC_TXARB_TXQ_PRIO_2_MASK GENMASK(5, 4)
561+
#define IGC_TXARB_TXQ_PRIO_3_MASK GENMASK(7, 6)
562+
#define IGC_TXARB_TXQ_PRIO_0(x) FIELD_PREP(IGC_TXARB_TXQ_PRIO_0_MASK, (x))
563+
#define IGC_TXARB_TXQ_PRIO_1(x) FIELD_PREP(IGC_TXARB_TXQ_PRIO_1_MASK, (x))
564+
#define IGC_TXARB_TXQ_PRIO_2(x) FIELD_PREP(IGC_TXARB_TXQ_PRIO_2_MASK, (x))
565+
#define IGC_TXARB_TXQ_PRIO_3(x) FIELD_PREP(IGC_TXARB_TXQ_PRIO_3_MASK, (x))
566+
556567
/* Receive Checksum Control */
557568
#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
558569
#define IGC_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */

drivers/net/ethernet/intel/igc/igc_ethtool.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,10 @@ static int igc_ethtool_set_channels(struct net_device *netdev,
15401540
if (ch->other_count != NON_Q_VECTORS)
15411541
return -EINVAL;
15421542

1543+
/* Do not allow channel reconfiguration when mqprio is enabled */
1544+
if (adapter->strict_priority_enable)
1545+
return -EINVAL;
1546+
15431547
/* Verify the number of channels doesn't exceed hw limits */
15441548
max_combined = igc_get_max_rss_queues(adapter);
15451549
if (count > max_combined)

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6515,6 +6515,13 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,
65156515
struct igc_hw *hw = &adapter->hw;
65166516

65176517
switch (base->type) {
6518+
case TC_SETUP_QDISC_MQPRIO: {
6519+
struct tc_mqprio_caps *caps = base->caps;
6520+
6521+
caps->validate_queue_counts = true;
6522+
6523+
return 0;
6524+
}
65186525
case TC_SETUP_QDISC_TAPRIO: {
65196526
struct tc_taprio_caps *caps = base->caps;
65206527

@@ -6532,6 +6539,65 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,
65326539
}
65336540
}
65346541

6542+
static void igc_save_mqprio_params(struct igc_adapter *adapter, u8 num_tc,
6543+
u16 *offset)
6544+
{
6545+
int i;
6546+
6547+
adapter->strict_priority_enable = true;
6548+
adapter->num_tc = num_tc;
6549+
6550+
for (i = 0; i < num_tc; i++)
6551+
adapter->queue_per_tc[i] = offset[i];
6552+
}
6553+
6554+
static int igc_tsn_enable_mqprio(struct igc_adapter *adapter,
6555+
struct tc_mqprio_qopt_offload *mqprio)
6556+
{
6557+
struct igc_hw *hw = &adapter->hw;
6558+
int i;
6559+
6560+
if (hw->mac.type != igc_i225)
6561+
return -EOPNOTSUPP;
6562+
6563+
if (!mqprio->qopt.num_tc) {
6564+
adapter->strict_priority_enable = false;
6565+
goto apply;
6566+
}
6567+
6568+
/* There are as many TCs as Tx queues. */
6569+
if (mqprio->qopt.num_tc != adapter->num_tx_queues) {
6570+
NL_SET_ERR_MSG_FMT_MOD(mqprio->extack,
6571+
"Only %d traffic classes supported",
6572+
adapter->num_tx_queues);
6573+
return -EOPNOTSUPP;
6574+
}
6575+
6576+
/* Only one queue per TC is supported. */
6577+
for (i = 0; i < mqprio->qopt.num_tc; i++) {
6578+
if (mqprio->qopt.count[i] != 1) {
6579+
NL_SET_ERR_MSG_MOD(mqprio->extack,
6580+
"Only one queue per TC supported");
6581+
return -EOPNOTSUPP;
6582+
}
6583+
}
6584+
6585+
/* Preemption is not supported yet. */
6586+
if (mqprio->preemptible_tcs) {
6587+
NL_SET_ERR_MSG_MOD(mqprio->extack,
6588+
"Preemption is not supported yet");
6589+
return -EOPNOTSUPP;
6590+
}
6591+
6592+
igc_save_mqprio_params(adapter, mqprio->qopt.num_tc,
6593+
mqprio->qopt.offset);
6594+
6595+
mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;
6596+
6597+
apply:
6598+
return igc_tsn_offload_apply(adapter);
6599+
}
6600+
65356601
static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
65366602
void *type_data)
65376603
{
@@ -6551,6 +6617,9 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
65516617
case TC_SETUP_QDISC_CBS:
65526618
return igc_tsn_enable_cbs(adapter, type_data);
65536619

6620+
case TC_SETUP_QDISC_MQPRIO:
6621+
return igc_tsn_enable_mqprio(adapter, type_data);
6622+
65546623
default:
65556624
return -EOPNOTSUPP;
65566625
}

drivers/net/ethernet/intel/igc/igc_regs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@
238238
#define IGC_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
239239
#define IGC_TQAVHC(_n) (0x300C + ((_n) * 0x40))
240240

241+
#define IGC_TXARB 0x3354 /* Tx Arbitration Control TxARB - RW */
242+
241243
/* System Time Registers */
242244
#define IGC_SYSTIML 0x0B600 /* System time register Low - RO */
243245
#define IGC_SYSTIMH 0x0B604 /* System time register High - RO */

drivers/net/ethernet/intel/igc/igc_tsn.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
4646
if (is_cbs_enabled(adapter))
4747
new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
4848

49+
if (adapter->strict_priority_enable)
50+
new_flags |= IGC_FLAG_TSN_LEGACY_ENABLED;
51+
4952
return new_flags;
5053
}
5154

@@ -102,11 +105,32 @@ bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter)
102105
adapter->taprio_offload_enable;
103106
}
104107

108+
static void igc_tsn_tx_arb(struct igc_adapter *adapter, u16 *queue_per_tc)
109+
{
110+
struct igc_hw *hw = &adapter->hw;
111+
u32 txarb;
112+
113+
txarb = rd32(IGC_TXARB);
114+
115+
txarb &= ~(IGC_TXARB_TXQ_PRIO_0_MASK |
116+
IGC_TXARB_TXQ_PRIO_1_MASK |
117+
IGC_TXARB_TXQ_PRIO_2_MASK |
118+
IGC_TXARB_TXQ_PRIO_3_MASK);
119+
120+
txarb |= IGC_TXARB_TXQ_PRIO_0(queue_per_tc[3]);
121+
txarb |= IGC_TXARB_TXQ_PRIO_1(queue_per_tc[2]);
122+
txarb |= IGC_TXARB_TXQ_PRIO_2(queue_per_tc[1]);
123+
txarb |= IGC_TXARB_TXQ_PRIO_3(queue_per_tc[0]);
124+
125+
wr32(IGC_TXARB, txarb);
126+
}
127+
105128
/* Returns the TSN specific registers to their default values after
106129
* the adapter is reset.
107130
*/
108131
static int igc_tsn_disable_offload(struct igc_adapter *adapter)
109132
{
133+
u16 queue_per_tc[4] = { 3, 2, 1, 0 };
110134
struct igc_hw *hw = &adapter->hw;
111135
u32 tqavctrl;
112136
int i;
@@ -133,7 +157,16 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
133157
wr32(IGC_QBVCYCLET_S, 0);
134158
wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
135159

160+
/* Reset mqprio TC configuration. */
161+
netdev_reset_tc(adapter->netdev);
162+
163+
/* Restore the default Tx arbitration: Priority 0 has the highest
164+
* priority and is assigned to queue 0 and so on and so forth.
165+
*/
166+
igc_tsn_tx_arb(adapter, queue_per_tc);
167+
136168
adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
169+
adapter->flags &= ~IGC_FLAG_TSN_LEGACY_ENABLED;
137170

138171
return 0;
139172
}
@@ -172,6 +205,40 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
172205
if (igc_is_device_id_i226(hw))
173206
igc_tsn_set_retx_qbvfullthreshold(adapter);
174207

208+
if (adapter->strict_priority_enable) {
209+
int err;
210+
211+
err = netdev_set_num_tc(adapter->netdev, adapter->num_tc);
212+
if (err)
213+
return err;
214+
215+
for (i = 0; i < adapter->num_tc; i++) {
216+
err = netdev_set_tc_queue(adapter->netdev, i, 1,
217+
adapter->queue_per_tc[i]);
218+
if (err)
219+
return err;
220+
}
221+
222+
/* In case the card is configured with less than four queues. */
223+
for (; i < IGC_MAX_TX_QUEUES; i++)
224+
adapter->queue_per_tc[i] = i;
225+
226+
/* Configure queue priorities according to the user provided
227+
* mapping.
228+
*/
229+
igc_tsn_tx_arb(adapter, adapter->queue_per_tc);
230+
231+
/* Enable legacy TSN mode which will do strict priority without
232+
* any other TSN features.
233+
*/
234+
tqavctrl = rd32(IGC_TQAVCTRL);
235+
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN;
236+
tqavctrl &= ~IGC_TQAVCTRL_ENHANCED_QAV;
237+
wr32(IGC_TQAVCTRL, tqavctrl);
238+
239+
return 0;
240+
}
241+
175242
for (i = 0; i < adapter->num_tx_queues; i++) {
176243
struct igc_ring *ring = adapter->tx_ring[i];
177244
u32 txqctl = 0;

0 commit comments

Comments
 (0)