Commit 1f47510e authored by David S. Miller's avatar David S. Miller
Browse files
Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2023-01-03 (igc)

Muhammad Husaini Zulkifli says:

Improvements to the Time-Sensitive Networking (TSN) Qbv Scheduling
capabilities were included in this patch series for I226 SKU.

An overview of each patch series is given below:

Patch 1: To enable basetime scheduling in the future, remove the existing
restriction for i226 stepping while maintain the restriction for i225.
Patch 2: Remove the restriction which require a controller reset when
setting the basetime register for new i226 steps and enable the second
GCL configuration.
Patch 3: Remove the power reset adapter during disabling the tsn config.
---
Patches remaining from initial PR:
https://lore.kernel.org/netdev/20221205212414.3197525-1-anthony.l.nguyen@intel.com/

after sending net patches:
https://lore.kernel.org/netdev/20221215230758.3595578-1-anthony.l.nguyen@intel.com/



Note: patch 3 is an additional patch from the initial PR.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c183e6c3 1d1b4c63
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -396,6 +396,35 @@ void igc_rx_fifo_flush_base(struct igc_hw *hw)
	rd32(IGC_MPC);
}

bool igc_is_device_id_i225(struct igc_hw *hw)
{
	switch (hw->device_id) {
	case IGC_DEV_ID_I225_LM:
	case IGC_DEV_ID_I225_V:
	case IGC_DEV_ID_I225_I:
	case IGC_DEV_ID_I225_K:
	case IGC_DEV_ID_I225_K2:
	case IGC_DEV_ID_I225_LMVP:
	case IGC_DEV_ID_I225_IT:
		return true;
	default:
		return false;
	}
}

bool igc_is_device_id_i226(struct igc_hw *hw)
{
	switch (hw->device_id) {
	case IGC_DEV_ID_I226_LM:
	case IGC_DEV_ID_I226_V:
	case IGC_DEV_ID_I226_K:
	case IGC_DEV_ID_I226_IT:
		return true;
	default:
		return false;
	}
}

static struct igc_mac_operations igc_mac_ops_base = {
	.init_hw		= igc_init_hw_base,
	.check_for_link		= igc_check_for_copper_link,
+2 −0
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@
/* forward declaration */
void igc_rx_fifo_flush_base(struct igc_hw *hw);
void igc_power_down_phy_copper_base(struct igc_hw *hw);
bool igc_is_device_id_i225(struct igc_hw *hw);
bool igc_is_device_id_i226(struct igc_hw *hw);

/* Transmit Descriptor - Advanced */
union igc_adv_tx_desc {
+1 −0
Original line number Diff line number Diff line
@@ -522,6 +522,7 @@
/* Transmit Scheduling */
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN	0x00000001
#define IGC_TQAVCTRL_ENHANCED_QAV	0x00000008
#define IGC_TQAVCTRL_FUTSCDDIS		0x00000080

#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT	0x00000001
#define IGC_TXQCTL_STRICT_CYCLE		0x00000002
+6 −2
Original line number Diff line number Diff line
@@ -5958,6 +5958,7 @@ static bool validate_schedule(struct igc_adapter *adapter,
			      const struct tc_taprio_qopt_offload *qopt)
{
	int queue_uses[IGC_MAX_TX_QUEUES] = { };
	struct igc_hw *hw = &adapter->hw;
	struct timespec64 now;
	size_t n;

@@ -5970,8 +5971,10 @@ static bool validate_schedule(struct igc_adapter *adapter,
	 * in the future, it will hold all the packets until that
	 * time, causing a lot of TX Hangs, so to avoid that, we
	 * reject schedules that would start in the future.
	 * Note: Limitation above is no longer in i226.
	 */
	if (!is_base_time_past(qopt->base_time, &now))
	if (!is_base_time_past(qopt->base_time, &now) &&
	    igc_is_device_id_i225(hw))
		return false;

	for (n = 0; n < qopt->num_entries; n++) {
@@ -6041,6 +6044,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
				 struct tc_taprio_qopt_offload *qopt)
{
	bool queue_configured[IGC_MAX_TX_QUEUES] = { };
	struct igc_hw *hw = &adapter->hw;
	u32 start_time = 0, end_time = 0;
	size_t n;
	int i;
@@ -6053,7 +6057,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
	if (qopt->base_time < 0)
		return -ERANGE;

	if (adapter->base_time)
	if (igc_is_device_id_i225(hw) && adapter->base_time)
		return -EALREADY;

	if (!validate_schedule(adapter, qopt))
+35 −21
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
/* Copyright (c)  2019 Intel Corporation */

#include "igc.h"
#include "igc_hw.h"
#include "igc_tsn.h"

static bool is_any_launchtime(struct igc_adapter *adapter)
@@ -92,7 +93,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_FUTSCDDIS);

	wr32(IGC_TQAVCTRL, tqavctrl);

	for (i = 0; i < adapter->num_tx_queues; i++) {
@@ -117,20 +119,10 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
	ktime_t base_time, systim;
	int i;

	cycle = adapter->cycle_time;
	base_time = adapter->base_time;

	wr32(IGC_TSAUXC, 0);
	wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
	wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);

	tqavctrl = rd32(IGC_TQAVCTRL);
	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
	wr32(IGC_TQAVCTRL, tqavctrl);

	wr32(IGC_QBVCYCLET_S, cycle);
	wr32(IGC_QBVCYCLET, cycle);

	for (i = 0; i < adapter->num_tx_queues; i++) {
		struct igc_ring *ring = adapter->tx_ring[i];
		u32 txqctl = 0;
@@ -233,21 +225,46 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
		wr32(IGC_TXQCTL(i), txqctl);
	}

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

	cycle = adapter->cycle_time;
	base_time = adapter->base_time;

	nsec = rd32(IGC_SYSTIML);
	sec = rd32(IGC_SYSTIMH);

	systim = ktime_set(sec, nsec);

	if (ktime_compare(systim, base_time) > 0) {
		s64 n;
		s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);

		n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
		base_time = ktime_add_ns(base_time, (n + 1) * cycle);
	} else {
		/* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
		 * has to be configured before the cycle time and base time.
		 * Tx won't hang if there is a GCL is already running,
		 * so in this case we don't need to set FutScdDis.
		 */
		if (igc_is_device_id_i226(hw) &&
		    !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
			tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
	}

	baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
	wr32(IGC_TQAVCTRL, tqavctrl);

	wr32(IGC_QBVCYCLET_S, cycle);
	wr32(IGC_QBVCYCLET, cycle);

	baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
	wr32(IGC_BASET_H, baset_h);

	/* In i226, Future base time is only supported when FutScdDis bit
	 * is enabled and only active for re-configuration.
	 * In this case, initialize the base time with zero to create
	 * "re-configuration" scenario then only set the desired base time.
	 */
	if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS)
		wr32(IGC_BASET_L, 0);
	wr32(IGC_BASET_L, baset_l);

	return 0;
@@ -274,17 +291,14 @@ int igc_tsn_reset(struct igc_adapter *adapter)

int igc_tsn_offload_apply(struct igc_adapter *adapter)
{
	int err;
	struct igc_hw *hw = &adapter->hw;

	if (netif_running(adapter->netdev)) {
	if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
		schedule_work(&adapter->reset_task);
		return 0;
	}

	err = igc_tsn_enable_offload(adapter);
	if (err < 0)
		return err;
	igc_tsn_reset(adapter);

	adapter->flags = igc_tsn_new_flags(adapter);
	return 0;
}