Commit 3fec58f5 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Tony Nguyen says:

====================
igc: Add support for Frame Preemption

Faizal Rahim says:

Introduce support for the FPE feature in the IGC driver.

The patches aligns with the upstream FPE API:
https://patchwork.kernel.org/project/netdevbpf/cover/20230220122343.1156614-1-vladimir.oltean@nxp.com/
https://patchwork.kernel.org/project/netdevbpf/cover/20230119122705.73054-1-vladimir.oltean@nxp.com/

It builds upon earlier work:
https://patchwork.kernel.org/project/netdevbpf/cover/20220520011538.1098888-1-vinicius.gomes@intel.com/

The patch series adds the following functionalities to the IGC driver:
a) Configure FPE using `ethtool --set-mm`.
b) Display FPE settings via `ethtool --show-mm`.
c) View FPE statistics using `ethtool --include-statistics --show-mm'.
e) Block setting preemptible tc in taprio since it is not supported yet.
   Existing code already blocks it in mqprio.

Tested:
Enabled CONFIG_PROVE_LOCKING, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_DMA_API_DEBUG, and CONFIG_KASAN
1) selftests
2) netdev down/up cycles
3) suspend/resume cycles
4) fpe verification

No bugs or unusual dmesg logs were observed.
Ran 1), 2) and 3) with and without the patch series, compared dmesg and selftest logs - no differences found.

* '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  igc: add support to get frame preemption statistics via ethtool
  igc: add support to get MAC Merge data via ethtool
  igc: block setting preemptible traffic class in taprio
  igc: add support to set tx-min-frag-size
  igc: add support for frame preemption verification
  igc: set the RX packet buffer size for TSN mode
  igc: use FIELD_PREP and GENMASK for existing RX packet buffer size
  igc: optimize TX packet buffer utilization for TSN mode
  igc: use FIELD_PREP and GENMASK for existing TX packet buffer size
  igc: rename I225_RXPBSIZE_DEFAULT and I225_TXPBSIZE_DEFAULT
  igc: rename xdp_get_tx_ring() for non-xdp usage
  net: ethtool: mm: reset verification status when link is down
  net: ethtool: mm: extract stmmac verification logic into common library
  net: stmmac: move frag_size handling out of spin_lock
====================

Link: https://patch.msgid.link/20250418163822.3519810-1-anthony.l.nguyen@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents a484fe88 f05ce73c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -369,6 +369,7 @@ config IGC
	default n
	depends on PCI
	depends on PTP_1588_CLOCK_OPTIONAL
	depends on ETHTOOL_NETLINK
	help
	  This driver supports Intel(R) Ethernet Controller I225-LM/I225-V
	  family of adapters.
+13 −2
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ void igc_ethtool_set_ops(struct net_device *);

#define IGC_MAX_TX_TSTAMP_REGS		4

struct igc_fpe_t {
	struct ethtool_mmsv mmsv;
	u32 tx_min_frag_size;
};

enum igc_mac_filter_type {
	IGC_MAC_FILTER_TYPE_DST = 0,
	IGC_MAC_FILTER_TYPE_SRC
@@ -333,6 +338,8 @@ struct igc_adapter {
		struct timespec64 period;
	} perout[IGC_N_PEROUT];

	struct igc_fpe_t fpe;

	/* LEDs */
	struct mutex led_mutex;
	struct igc_led_classdev *leds;
@@ -388,10 +395,11 @@ extern char igc_driver_name[];
#define IGC_FLAG_TSN_QBV_ENABLED	BIT(17)
#define IGC_FLAG_TSN_QAV_ENABLED	BIT(18)
#define IGC_FLAG_TSN_LEGACY_ENABLED	BIT(19)
#define IGC_FLAG_TSN_PREEMPT_ENABLED	BIT(20)

#define IGC_FLAG_TSN_ANY_ENABLED				\
	(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED |	\
	 IGC_FLAG_TSN_LEGACY_ENABLED)
	 IGC_FLAG_TSN_LEGACY_ENABLED | IGC_FLAG_TSN_PREEMPT_ENABLED)

#define IGC_FLAG_RSS_FIELD_IPV4_UDP	BIT(6)
#define IGC_FLAG_RSS_FIELD_IPV6_UDP	BIT(7)
@@ -736,7 +744,10 @@ struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
				      u32 location);
int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);

void igc_disable_empty_addr_recv(struct igc_adapter *adapter);
int igc_enable_empty_addr_recv(struct igc_adapter *adapter);
struct igc_ring *igc_get_tx_ring(struct igc_adapter *adapter, int cpu);
void igc_flush_tx_descriptors(struct igc_ring *ring);
void igc_ptp_init(struct igc_adapter *adapter);
void igc_ptp_reset(struct igc_adapter *adapter);
void igc_ptp_suspend(struct igc_adapter *adapter);
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct igc_adv_tx_context_desc {
#define IGC_ADVTXD_DCMD_DEXT	0x20000000 /* Descriptor extension (1=Adv) */
#define IGC_ADVTXD_DCMD_VLE	0x40000000 /* VLAN pkt enable */
#define IGC_ADVTXD_DCMD_TSE	0x80000000 /* TCP Seg enable */
#define IGC_ADVTXD_PAYLEN_MASK	0XFFFFC000 /* Adv desc PAYLEN mask */
#define IGC_ADVTXD_PAYLEN_SHIFT	14 /* Adv desc PAYLEN shift */

#define IGC_RAR_ENTRIES		16
+49 −6
Original line number Diff line number Diff line
@@ -308,6 +308,8 @@
#define IGC_TXD_DTYP_C		0x00000000 /* Context Descriptor */
#define IGC_TXD_POPTS_IXSM	0x01       /* Insert IP checksum */
#define IGC_TXD_POPTS_TXSM	0x02       /* Insert TCP/UDP checksum */
#define IGC_TXD_POPTS_SMD_MASK	0x3000     /* Indicates whether it's SMD-V or SMD-R */

#define IGC_TXD_CMD_EOP		0x01000000 /* End of Packet */
#define IGC_TXD_CMD_IC		0x04000000 /* Insert Checksum */
#define IGC_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */
@@ -363,6 +365,8 @@
#define IGC_SRRCTL_TIMER0SEL(timer)	(((timer) & 0x3) << 17)

/* Receive Descriptor bit definitions */
#define IGC_RXD_STAT_SMD_TYPE_V	0x01	/* SMD-V Packet */
#define IGC_RXD_STAT_SMD_TYPE_R	0x02	/* SMD-R Packet */
#define IGC_RXD_STAT_EOP	0x02	/* End of Packet */
#define IGC_RXD_STAT_IXSM	0x04	/* Ignore checksum */
#define IGC_RXD_STAT_UDPCS	0x10	/* UDP xsum calculated */
@@ -372,6 +376,7 @@
#define IGC_RXDEXT_STATERR_LB	0x00040000

/* Advanced Receive Descriptor bit definitions */
#define IGC_RXDADV_STAT_SMD_TYPE_MASK	0x06000
#define IGC_RXDADV_STAT_TSIP		0x08000 /* timestamp in packet */

#define IGC_RXDEXT_STATERR_L4E		0x20000000
@@ -396,11 +401,47 @@
#define IGC_RCTL_PMCF		0x00800000 /* pass MAC control frames */
#define IGC_RCTL_SECRC		0x04000000 /* Strip Ethernet CRC */

#define I225_RXPBSIZE_DEFAULT	0x000000A2 /* RXPBSIZE default */
#define I225_TXPBSIZE_DEFAULT	0x04000014 /* TXPBSIZE default */
#define IGC_RXPBS_CFG_TS_EN	0x80000000 /* Timestamp in Rx buffer */

#define IGC_TXPBSIZE_TSN	0x04145145 /* 5k bytes buffer for each queue */
/* Mask for RX packet buffer size */
#define IGC_RXPBSIZE_EXP_MASK		GENMASK(5, 0)
#define IGC_BMC2OSPBSIZE_MASK		GENMASK(11, 6)
#define IGC_RXPBSIZE_BE_MASK		GENMASK(17, 12)
/* Mask for timestamp in RX buffer */
#define IGC_RXPBS_CFG_TS_EN_MASK	GENMASK(31, 31)
/* High-priority RX packet buffer size (KB). Used for Express traffic when preemption is enabled */
#define IGC_RXPBSIZE_EXP(x)		FIELD_PREP(IGC_RXPBSIZE_EXP_MASK, (x))
/* BMC to OS packet buffer size in KB */
#define IGC_BMC2OSPBSIZE(x)		FIELD_PREP(IGC_BMC2OSPBSIZE_MASK, (x))
/* Low-priority RX packet buffer size (KB). Used for BE traffic when preemption is enabled */
#define IGC_RXPBSIZE_BE(x)		FIELD_PREP(IGC_RXPBSIZE_BE_MASK, (x))
/* Enable RX packet buffer for timestamp descriptor, saving 16 bytes per packet if set */
#define IGC_RXPBS_CFG_TS_EN		FIELD_PREP(IGC_RXPBS_CFG_TS_EN_MASK, 1)
/* Default value following I225/I226 SW User Manual Section 8.3.1 */
#define IGC_RXPBSIZE_EXP_BMC_DEFAULT ( \
	IGC_RXPBSIZE_EXP(34) | IGC_BMC2OSPBSIZE(2))
#define IGC_RXPBSIZE_EXP_BMC_BE_TSN ( \
	IGC_RXPBSIZE_EXP(15) | IGC_BMC2OSPBSIZE(2) | IGC_RXPBSIZE_BE(15))

/* Mask for TX packet buffer size */
#define IGC_TXPB0SIZE_MASK		GENMASK(5, 0)
#define IGC_TXPB1SIZE_MASK		GENMASK(11, 6)
#define IGC_TXPB2SIZE_MASK		GENMASK(17, 12)
#define IGC_TXPB3SIZE_MASK		GENMASK(23, 18)
/* Mask for OS to BMC packet buffer size */
#define IGC_OS2BMCPBSIZE_MASK		GENMASK(29, 24)
/* TX Packet buffer size in KB */
#define IGC_TXPB0SIZE(x)		FIELD_PREP(IGC_TXPB0SIZE_MASK, (x))
#define IGC_TXPB1SIZE(x)		FIELD_PREP(IGC_TXPB1SIZE_MASK, (x))
#define IGC_TXPB2SIZE(x)		FIELD_PREP(IGC_TXPB2SIZE_MASK, (x))
#define IGC_TXPB3SIZE(x)		FIELD_PREP(IGC_TXPB3SIZE_MASK, (x))
/* OS to BMC packet buffer size in KB */
#define IGC_OS2BMCPBSIZE(x)		FIELD_PREP(IGC_OS2BMCPBSIZE_MASK, (x))
/* Default value following I225/I226 SW User Manual Section 8.3.2 */
#define IGC_TXPBSIZE_DEFAULT ( \
	IGC_TXPB0SIZE(20) | IGC_TXPB1SIZE(0) | IGC_TXPB2SIZE(0) | \
	IGC_TXPB3SIZE(0) | IGC_OS2BMCPBSIZE(4))
#define IGC_TXPBSIZE_TSN ( \
	IGC_TXPB0SIZE(7) | IGC_TXPB1SIZE(7) | IGC_TXPB2SIZE(7) | \
	IGC_TXPB3SIZE(7) | IGC_OS2BMCPBSIZE(4))

#define IGC_DTXMXPKTSZ_TSN	0x19 /* 1600 bytes of max TX DMA packet size */
#define IGC_DTXMXPKTSZ_DEFAULT	0x98 /* 9728-byte Jumbo frames */
@@ -539,8 +580,10 @@

/* Transmit Scheduling */
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN	0x00000001
#define IGC_TQAVCTRL_PREEMPT_ENA	0x00000002
#define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
#define IGC_TQAVCTRL_FUTSCDDIS		0x00000080
#define IGC_TQAVCTRL_MIN_FRAG_MASK	0x0000C000

#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT	0x00000001
#define IGC_TXQCTL_STRICT_CYCLE		0x00000002
+81 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

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

/* forward declaration */
struct igc_stats {
@@ -1781,6 +1782,83 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
	return 0;
}

static int igc_ethtool_get_mm(struct net_device *netdev,
			      struct ethtool_mm_state *cmd)
{
	struct igc_adapter *adapter = netdev_priv(netdev);
	struct igc_fpe_t *fpe = &adapter->fpe;

	ethtool_mmsv_get_mm(&fpe->mmsv, cmd);
	cmd->tx_min_frag_size = fpe->tx_min_frag_size;
	cmd->rx_min_frag_size = IGC_RX_MIN_FRAG_SIZE;

	return 0;
}

static int igc_ethtool_set_mm(struct net_device *netdev,
			      struct ethtool_mm_cfg *cmd,
			      struct netlink_ext_ack *extack)
{
	struct igc_adapter *adapter = netdev_priv(netdev);
	struct igc_fpe_t *fpe = &adapter->fpe;

	fpe->tx_min_frag_size = igc_fpe_get_supported_frag_size(cmd->tx_min_frag_size);
	if (fpe->tx_min_frag_size != cmd->tx_min_frag_size)
		NL_SET_ERR_MSG_MOD(extack,
				   "tx-min-frag-size value set is unsupported. Rounded up to supported value (64, 128, 192, 256)");

	if (fpe->mmsv.pmac_enabled != cmd->pmac_enabled) {
		if (cmd->pmac_enabled)
			static_branch_inc(&igc_fpe_enabled);
		else
			static_branch_dec(&igc_fpe_enabled);
	}

	ethtool_mmsv_set_mm(&fpe->mmsv, cmd);

	return igc_tsn_offload_apply(adapter);
}

/**
 * igc_ethtool_get_frame_ass_error - Get the frame assembly error count.
 * @reg_value: Register value for IGC_PRMEXCPRCNT
 * Return: The count of frame assembly errors.
 */
static u64 igc_ethtool_get_frame_ass_error(u32 reg_value)
{
	/* Out of order statistics */
	u32 ooo_frame_cnt, ooo_frag_cnt;
	u32 miss_frame_frag_cnt;

	ooo_frame_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAME_CNT, reg_value);
	ooo_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_OOO_FRAG_CNT, reg_value);
	miss_frame_frag_cnt = FIELD_GET(IGC_PRMEXCPRCNT_MISS_FRAME_FRAG_CNT,
					reg_value);

	return ooo_frame_cnt + ooo_frag_cnt + miss_frame_frag_cnt;
}

static u64 igc_ethtool_get_frame_smd_error(u32 reg_value)
{
	return FIELD_GET(IGC_PRMEXCPRCNT_OOO_SMDC, reg_value);
}

static void igc_ethtool_get_mm_stats(struct net_device *dev,
				     struct ethtool_mm_stats *stats)
{
	struct igc_adapter *adapter = netdev_priv(dev);
	struct igc_hw *hw = &adapter->hw;
	u32 reg_value;

	reg_value = rd32(IGC_PRMEXCPRCNT);

	stats->MACMergeFrameAssErrorCount = igc_ethtool_get_frame_ass_error(reg_value);
	stats->MACMergeFrameSmdErrorCount = igc_ethtool_get_frame_smd_error(reg_value);
	stats->MACMergeFrameAssOkCount = rd32(IGC_PRMPTDRCNT);
	stats->MACMergeFragCountRx = rd32(IGC_PRMEVNTRCNT);
	stats->MACMergeFragCountTx = rd32(IGC_PRMEVNTTCNT);
}

static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
					  struct ethtool_link_ksettings *cmd)
{
@@ -2076,6 +2154,9 @@ static const struct ethtool_ops igc_ethtool_ops = {
	.get_link_ksettings	= igc_ethtool_get_link_ksettings,
	.set_link_ksettings	= igc_ethtool_set_link_ksettings,
	.self_test		= igc_ethtool_diag_test,
	.get_mm			= igc_ethtool_get_mm,
	.get_mm_stats		= igc_ethtool_get_mm_stats,
	.set_mm			= igc_ethtool_set_mm,
};

void igc_ethtool_set_ops(struct net_device *netdev)
Loading