From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [next-queue RFC 3/4] igc: Add support for configuring frame preemption
Date: Fri, 15 May 2020 18:29:47 -0700 [thread overview]
Message-ID: <20200516012948.3173993-4-vinicius.gomes@intel.com> (raw)
In-Reply-To: <20200516012948.3173993-1-vinicius.gomes@intel.com>
WIP
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
drivers/net/ethernet/intel/igc/igc.h | 3 +
drivers/net/ethernet/intel/igc/igc_defines.h | 6 ++
drivers/net/ethernet/intel/igc/igc_ethtool.c | 68 ++++++++++++++++++++
drivers/net/ethernet/intel/igc/igc_tsn.c | 46 +++++++++++--
4 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 5dbc5a1..963ac98 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -87,6 +87,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;
@@ -162,6 +163,8 @@ struct igc_adapter {
ktime_t base_time;
ktime_t cycle_time;
+ bool frame_preemption_active;
+ u32 min_frag_size; /* Frame preemption minimum fragment size */
/* OS defined structs */
struct pci_dev *pdev;
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 80b664e..fa823c3 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -364,6 +364,8 @@
#define IGC_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */
#define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */
+#define IGC_RXPBSIZE_TSN 0x00010090 /* 16KB for EXP + 16KB for BE + 2KB for BMC */
+#define IGC_RXPBSIZE_SIZE_MASK 0x0001FFFF
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
@@ -422,10 +424,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 */
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 2214a5d..48d5d18 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -7,6 +7,7 @@
#include "igc.h"
#include "igc_diag.h"
+#include "igc_tsn.h"
/* forward declaration */
struct igc_stats {
@@ -1549,6 +1550,71 @@ static int igc_ethtool_set_priv_flags(struct net_device *netdev, u32 priv_flags)
return 0;
}
+static int igc_ethtool_get_preempt(struct net_device *netdev,
+ struct ethtool_fp *fpcmd)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ fpcmd->fp_supported = 1;
+ fpcmd->fp_enabled = adapter->frame_preemption_active;
+ fpcmd->min_frag_size = adapter->min_frag_size;
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *ring = adapter->tx_ring[i];
+
+ fpcmd->supported_queues_mask |= BIT(i);
+
+ if (ring->preemptible)
+ fpcmd->preemptible_queues_mask |= BIT(i);
+ }
+
+ return 0;
+}
+
+static int igc_ethtool_set_preempt(struct net_device *netdev,
+ struct ethtool_fp *fpcmd)
+{
+ struct igc_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ /* The formula is (Section 8.12.4 of the datasheet):
+ * MIN_FRAG_SIZE = 4 + (1 + MIN_FRAG)*64
+ * MIN_FRAG is represented by two bits, so we can only have
+ * min_frag_size between 68 and 260.
+ */
+ if (fpcmd->min_frag_size < 68 || fpcmd->min_frag_size > 260)
+ return -EINVAL;
+
+ fpcmd->fp_supported = 1;
+
+ adapter->frame_preemption_active = fpcmd->fp_enabled;
+ adapter->min_frag_size = fpcmd->min_frag_size;
+
+ /* We need to setup a dummy Qbv cycle for frame preemption to
+ * work, but we only need to set it up if none is set. This
+ * same check below exists for the same purpose.
+ */
+ if (!adapter->base_time)
+ adapter->cycle_time = NSEC_PER_SEC;
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *ring = adapter->tx_ring[i];
+ bool preemptible = fpcmd->preemptible_queues_mask & BIT(i);
+
+ fpcmd->fp_supported |= BIT(i);
+ ring->preemptible = preemptible;
+
+ if (adapter->base_time)
+ continue;
+
+ ring->start_time = 0;
+ ring->end_time = NSEC_PER_SEC;
+ }
+
+ return igc_tsn_offload_apply(adapter);
+}
+
static int igc_ethtool_begin(struct net_device *netdev)
{
struct igc_adapter *adapter = netdev_priv(netdev);
@@ -1828,6 +1894,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,
.begin = igc_ethtool_begin,
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 174103c..1bebe1c 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -18,26 +18,45 @@ static bool is_any_launchtime(struct igc_adapter *adapter)
return false;
}
+static u32 igc_min_frag_size_to_tqavctrl(u32 min_frag)
+{
+ u32 tqavctrl;
+
+ tqavctrl = DIV_ROUND_UP((min_frag - 4), 64);
+ tqavctrl -= 1;
+
+ tqavctrl <<= IGC_TQAVCTRL_MIN_FRAG_SHIFT;
+
+ return tqavctrl;
+}
+
/* Returns the TSN specific registers to their default values after
* TSN offloading is disabled.
*/
static int igc_tsn_disable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
- u32 tqavctrl;
+ u32 tqavctrl, rxpbs;
int i;
if (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED))
return 0;
adapter->cycle_time = 0;
+ adapter->frame_preemption_active = false;
+ adapter->min_frag_size = 68;
wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
+ rxpbs = rd32(IGC_RXPBS) & ~IGC_RXPBSIZE_SIZE_MASK;
+ rxpbs |= I225_RXPBSIZE_DEFAULT;
+
+ wr32(IGC_RXPBS, rxpbs);
+
tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
- IGC_TQAVCTRL_ENHANCED_QAV);
+ IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_PREEMPT_ENA);
wr32(IGC_TQAVCTRL, tqavctrl);
for (i = 0; i < adapter->num_tx_queues; i++) {
@@ -46,6 +65,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);
@@ -64,7 +84,7 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 tqavctrl, baset_l, baset_h;
- u32 sec, nsec, cycle;
+ u32 sec, nsec, cycle, rxpbs;
ktime_t base_time, systim;
int i;
@@ -78,8 +98,20 @@ 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;
+
+ tqavctrl |= igc_min_frag_size_to_tqavctrl(adapter->min_frag_size);
+
wr32(IGC_TQAVCTRL, tqavctrl);
wr32(IGC_QBVCYCLET_S, cycle);
@@ -105,6 +137,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);
}
@@ -132,7 +167,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;
--
2.26.2
next prev parent reply other threads:[~2020-05-16 1:29 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-16 1:29 [Intel-wired-lan] [next-queue RFC 0/4] ethtool: Add support for frame preemption Vinicius Costa Gomes
2020-05-16 1:29 ` [Intel-wired-lan] [next-queue RFC 1/4] ethtool: Add support for configuring " Vinicius Costa Gomes
2020-05-19 15:27 ` Murali Karicheri
2020-05-16 1:29 ` [Intel-wired-lan] [next-queue RFC 2/4] ethtool: Add support for configuring frame preemption via netlink Vinicius Costa Gomes
2020-05-16 1:29 ` Vinicius Costa Gomes [this message]
2020-05-19 16:36 ` [Intel-wired-lan] [next-queue RFC 3/4] igc: Add support for configuring frame preemption Murali Karicheri
2020-05-16 1:29 ` [Intel-wired-lan] [next-queue RFC 4/4] igc: Add support for exposing frame preemption stats registers Vinicius Costa Gomes
2020-05-20 12:50 ` Murali Karicheri
2020-05-16 9:33 ` [Intel-wired-lan] [next-queue RFC 0/4] ethtool: Add support for frame preemption Michal Kubecek
2020-05-18 19:34 ` Vinicius Costa Gomes
2020-05-19 22:40 ` Andre Guedes
2020-05-19 22:53 ` Vinicius Costa Gomes
2020-05-16 20:37 ` David Miller
2020-05-16 21:03 ` Vladimir Oltean
2020-05-16 22:19 ` David Miller
2020-05-17 10:51 ` Vladimir Oltean
2020-05-17 18:45 ` Andrew Lunn
2020-05-17 19:04 ` Vladimir Oltean
2020-05-18 19:05 ` Vinicius Costa Gomes
2020-05-18 20:56 ` Jakub Kicinski
2020-05-18 22:06 ` Vinicius Costa Gomes
2020-05-18 22:22 ` Jakub Kicinski
2020-05-18 23:05 ` Vinicius Costa Gomes
2020-05-18 23:09 ` Jakub Kicinski
2020-05-20 21:42 ` Andre Guedes
2020-05-20 22:35 ` Vinicius Costa Gomes
2020-05-19 16:34 ` Murali Karicheri
2020-05-19 17:49 ` Vinicius Costa Gomes
2020-05-19 14:53 ` Murali Karicheri
2020-05-19 15:32 ` Vinicius Costa Gomes
2020-05-19 16:11 ` Murali Karicheri
2020-05-19 22:39 ` Andre Guedes
2020-05-19 23:37 ` Vinicius Costa Gomes
2020-05-20 12:47 ` Murali Karicheri
2020-05-20 12:52 ` Joergen Andreasen
2020-05-20 21:32 ` Vinicius Costa Gomes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200516012948.3173993-4-vinicius.gomes@intel.com \
--to=vinicius.gomes@intel.com \
--cc=intel-wired-lan@osuosl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox