Skip to content

Commit

Permalink
igc: Add support for tuning frame preemption via ethtool
Browse files Browse the repository at this point in the history
The tc subsystem sets which queues are marked as preemptible, it's the
role of ethtool to control more hardware specific parameters. These
parameters include:

 - enabling the frame preemption hardware: As enabling frame
 preemption may have other requirements before it can be enabled, it's
 exposed via the ethtool API;

 - mininum fragment size multiplier: expressed in usually in the form
 of (1 + N)*64, this number indicates what's the size of the minimum
 fragment that can be preempted.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: Malli C <mallikarjuna.chilakala@intel.com>
  • Loading branch information
mrchilak authored and zhoufuro committed Feb 23, 2021
1 parent 63d162a commit eab3a2c
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 3 deletions.
12 changes: 12 additions & 0 deletions drivers/net/ethernet/intel/igc/igc.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct igc_ring {
u8 queue_index; /* logical index of the ring*/
u8 reg_idx; /* physical index of the ring */
bool launchtime_enable; /* true if LaunchTime is enabled */
bool preemptible; /* true if not express */

u32 start_time;
u32 end_time;
Expand Down Expand Up @@ -166,6 +167,8 @@ struct igc_adapter {

ktime_t base_time;
ktime_t cycle_time;
bool frame_preemption_active;
u8 add_frag_size;

/* OS defined structs */
struct pci_dev *pdev;
Expand Down Expand Up @@ -274,6 +277,10 @@ extern char igc_driver_version[];
#define IGC_FLAG_VLAN_PROMISC BIT(15)
#define IGC_FLAG_RX_LEGACY BIT(16)
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
#define IGC_FLAG_TSN_PREEMPT_ENABLED BIT(18)

#define IGC_FLAG_TSN_ANY_ENABLED \
(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_PREEMPT_ENABLED)

#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
Expand Down Expand Up @@ -322,6 +329,11 @@ extern char igc_driver_version[];
#define IGC_I225_RX_LATENCY_1000 300
#define IGC_I225_RX_LATENCY_2500 1485

/* From the datasheet section 8.12.4 Tx Qav Control TQAVCTRL,
* MIN_FRAG initial value.
*/
#define IGC_I225_MIN_FRAG_SIZE_DEFAULT 68

/* RX and TX descriptor control thresholds.
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
* descriptors available in its onboard memory.
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/igc/igc_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,10 +410,14 @@
/* Transmit Scheduling */
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001
#define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008
#define IGC_TQAVCTRL_PREEMPT_ENA 0x00000002
#define IGC_TQAVCTRL_MIN_FRAG_MASK 0x0000C000
#define IGC_TQAVCTRL_MIN_FRAG_SHIFT 14

#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002
#define IGC_TXQCTL_STRICT_END 0x00000004
#define IGC_TXQCTL_PREEMPTABLE 0x00000008

/* Receive Checksum Control */
#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
Expand Down
53 changes: 53 additions & 0 deletions drivers/net/ethernet/intel/igc/igc_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "igc.h"
#include "igc_diag.h"
#include "igc_tsn.h"

/* forward declaration */
struct igc_stats {
Expand Down Expand Up @@ -1647,6 +1648,56 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
return 0;
}

static int igc_ethtool_get_preempt(struct net_device *netdev,
struct ethtool_fp *fpcmd)
{
struct igc_adapter *adapter = netdev_priv(netdev);

fpcmd->enabled = adapter->frame_preemption_active;
fpcmd->add_frag_size = adapter->add_frag_size;

return 0;
}

static int igc_ethtool_set_preempt(struct net_device *netdev,
struct ethtool_fp *fpcmd,
struct netlink_ext_ack *extack)
{
struct igc_adapter *adapter = netdev_priv(netdev);
int i;

if (fpcmd->add_frag_size < 68 || fpcmd->add_frag_size > 260) {
NL_SET_ERR_MSG_MOD(extack, "Invalid value for add-frag-size");
return -EINVAL;
}

adapter->frame_preemption_active = fpcmd->enabled;
adapter->add_frag_size = fpcmd->add_frag_size;

if (!adapter->frame_preemption_active)
goto done;

/* Enabling frame preemption requires TSN mode to be enabled,
* which requires a schedule to be active. So, if there isn't
* a schedule already configured, configure a simple one, with
* all queues open, with 1ms cycle time.
*/
if (adapter->base_time)
goto done;

adapter->cycle_time = NSEC_PER_MSEC;

for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];

ring->start_time = 0;
ring->end_time = NSEC_PER_MSEC;
}

done:
return igc_tsn_offload_apply(adapter);
}

static int igc_ethtool_begin(struct net_device *netdev)
{
struct igc_adapter *adapter = netdev_priv(netdev);
Expand Down Expand Up @@ -1940,6 +1991,8 @@ static const struct ethtool_ops igc_ethtool_ops = {
.get_ts_info = igc_ethtool_get_ts_info,
.get_channels = igc_ethtool_get_channels,
.set_channels = igc_ethtool_set_channels,
.get_preempt = igc_ethtool_get_preempt,
.set_preempt = igc_ethtool_set_preempt,
.get_priv_flags = igc_ethtool_get_priv_flags,
.set_priv_flags = igc_ethtool_set_priv_flags,
.get_eee = igc_ethtool_get_eee,
Expand Down
25 changes: 22 additions & 3 deletions drivers/net/ethernet/intel/igc/igc_tsn.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
if (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED))
return 0;

adapter->base_time = 0;
adapter->cycle_time = 0;
adapter->frame_preemption_active = false;
adapter->add_frag_size = IGC_I225_MIN_FRAG_SIZE_DEFAULT;

wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
Expand All @@ -42,7 +45,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)

tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
IGC_TQAVCTRL_ENHANCED_QAV);
IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_PREEMPT_ENA |
IGC_TQAVCTRL_MIN_FRAG_MASK);
wr32(IGC_TQAVCTRL, tqavctrl);

for (i = 0; i < adapter->num_tx_queues; i++) {
Expand All @@ -51,6 +55,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
ring->start_time = 0;
ring->end_time = 0;
ring->launchtime_enable = false;
ring->preemptible = false;

wr32(IGC_TXQCTL(i), 0);
wr32(IGC_STQT(i), 0);
Expand All @@ -71,6 +76,7 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
u32 tqavctrl, baset_l, baset_h;
u32 sec, nsec, cycle, rxpbs;
ktime_t base_time, systim;
u8 frag_size_mult;
int i;

if (adapter->flags & IGC_FLAG_TSN_QBV_ENABLED)
Expand All @@ -83,13 +89,22 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);

tqavctrl = rd32(IGC_TQAVCTRL);
rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK;
rxpbs |= IGC_RXPBSIZE_TSN;

wr32(IGC_RXPBS, rxpbs);

tqavctrl = rd32(IGC_TQAVCTRL) &
~(IGC_TQAVCTRL_MIN_FRAG_MASK | IGC_TQAVCTRL_PREEMPT_ENA);
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;

if (adapter->frame_preemption_active)
tqavctrl |= IGC_TQAVCTRL_PREEMPT_ENA;

frag_size_mult = ethtool_frag_size_to_mult(adapter->add_frag_size);

tqavctrl |= frag_size_mult << IGC_TQAVCTRL_MIN_FRAG_SHIFT;

wr32(IGC_TQAVCTRL, tqavctrl);

wr32(IGC_QBVCYCLET_S, cycle);
Expand All @@ -115,6 +130,9 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
if (ring->launchtime_enable)
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;

if (ring->preemptible)
txqctl |= IGC_TXQCTL_PREEMPTABLE;

wr32(IGC_TXQCTL(i), txqctl);
}

Expand Down Expand Up @@ -142,7 +160,8 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)

int igc_tsn_offload_apply(struct igc_adapter *adapter)
{
bool is_any_enabled = adapter->base_time || is_any_launchtime(adapter);
bool is_any_enabled = adapter->base_time ||
is_any_launchtime(adapter) || adapter->frame_preemption_active;

if (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED) && !is_any_enabled)
return 0;
Expand Down

0 comments on commit eab3a2c

Please sign in to comment.