diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igc')
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc.h | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_base.h | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_defines.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_ethtool.c | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_hw.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_i225.c | 19 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 79 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_regs.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_tsn.c | 12 | 
9 files changed, 74 insertions, 57 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index df3e26c0cf01..34aebf00a512 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -99,6 +99,7 @@ struct igc_ring {  	u32 start_time;  	u32 end_time; +	u32 max_sdu;  	/* CBS parameters */  	bool cbs_enable;                /* indicates if CBS is enabled */ @@ -185,6 +186,7 @@ struct igc_adapter {  	ktime_t base_time;  	ktime_t cycle_time;  	bool qbv_enable; +	u32 qbv_config_change_errors;  	/* OS defined structs */  	struct pci_dev *pdev; @@ -292,8 +294,6 @@ extern char igc_driver_name[];  #define IGC_FLAG_PTP			BIT(8)  #define IGC_FLAG_WOL_SUPPORTED		BIT(8)  #define IGC_FLAG_NEED_LINK_UPDATE	BIT(9) -#define IGC_FLAG_MEDIA_RESET		BIT(10) -#define IGC_FLAG_MAS_ENABLE		BIT(12)  #define IGC_FLAG_HAS_MSIX		BIT(13)  #define IGC_FLAG_EEE			BIT(14)  #define IGC_FLAG_VLAN_PROMISC		BIT(15) diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h index 7a992befca24..9f3827eda157 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.h +++ b/drivers/net/ethernet/intel/igc/igc_base.h @@ -87,8 +87,13 @@ union igc_adv_rx_desc {  #define IGC_RXDCTL_SWFLUSH		0x04000000 /* Receive Software Flush */  /* SRRCTL bit definitions */ -#define IGC_SRRCTL_BSIZEPKT_SHIFT		10 /* Shift _right_ */ -#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT		2  /* Shift _left_ */ -#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF	0x02000000 +#define IGC_SRRCTL_BSIZEPKT_MASK	GENMASK(6, 0) +#define IGC_SRRCTL_BSIZEPKT(x)		FIELD_PREP(IGC_SRRCTL_BSIZEPKT_MASK, \ +					(x) / 1024) /* in 1 KB resolution */ +#define IGC_SRRCTL_BSIZEHDR_MASK	GENMASK(13, 8) +#define IGC_SRRCTL_BSIZEHDR(x)		FIELD_PREP(IGC_SRRCTL_BSIZEHDR_MASK, \ +					(x) / 64) /* in 64 bytes resolution */ +#define IGC_SRRCTL_DESCTYPE_MASK	GENMASK(27, 25) +#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF	FIELD_PREP(IGC_SRRCTL_DESCTYPE_MASK, 1)  #endif /* _IGC_BASE_H */ diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 9dec3563ce3a..44a507029946 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -662,9 +662,6 @@   */  #define IGC_TW_SYSTEM_100_MASK		0x0000FF00  #define IGC_TW_SYSTEM_100_SHIFT		8 -#define IGC_DMACR_DMAC_EN		0x80000000 /* Enable DMA Coalescing */ -#define IGC_DMACR_DMACTHR_MASK		0x00FF0000 -#define IGC_DMACR_DMACTHR_SHIFT		16  /* Reg val to set scale to 1024 nsec */  #define IGC_LTRMINV_SCALE_1024		2  /* Reg val to set scale to 32768 nsec */ diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index 5a26a7805ef8..0e2cb00622d1 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -67,6 +67,7 @@ static const struct igc_stats igc_gstrings_stats[] = {  	IGC_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),  	IGC_STAT("tx_lpi_counter", stats.tlpic),  	IGC_STAT("rx_lpi_counter", stats.rlpic), +	IGC_STAT("qbv_config_change_errors", qbv_config_change_errors),  };  #define IGC_NETDEV_STAT(_net_stat) { \ diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h index 88680e3d613d..e1c572e0d4ef 100644 --- a/drivers/net/ethernet/intel/igc/igc_hw.h +++ b/drivers/net/ethernet/intel/igc/igc_hw.h @@ -273,6 +273,7 @@ struct igc_hw_stats {  	u64 o2bspc;  	u64 b2ospc;  	u64 b2ogprc; +	u64 txdrop;  };  struct net_device *igc_get_hw_dev(struct igc_hw *hw); diff --git a/drivers/net/ethernet/intel/igc/igc_i225.c b/drivers/net/ethernet/intel/igc/igc_i225.c index 59d5c467ea6e..17546a035ab1 100644 --- a/drivers/net/ethernet/intel/igc/igc_i225.c +++ b/drivers/net/ethernet/intel/igc/igc_i225.c @@ -593,20 +593,11 @@ s32 igc_set_ltr_i225(struct igc_hw *hw, bool link)  		size = rd32(IGC_RXPBS) &  		       IGC_RXPBS_SIZE_I225_MASK; -		/* Calculations vary based on DMAC settings. */ -		if (rd32(IGC_DMACR) & IGC_DMACR_DMAC_EN) { -			size -= (rd32(IGC_DMACR) & -				 IGC_DMACR_DMACTHR_MASK) >> -				 IGC_DMACR_DMACTHR_SHIFT; -			/* Convert size to bits. */ -			size *= 1024 * 8; -		} else { -			/* Convert size to bytes, subtract the MTU, and then -			 * convert the size to bits. -			 */ -			size *= 1024; -			size *= 8; -		} +		/* Convert size to bytes, subtract the MTU, and then +		 * convert the size to bits. +		 */ +		size *= 1024; +		size *= 8;  		if (size < 0) {  			hw_dbg("Invalid effective Rx buffer size %d\n", diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 2928a6c73692..1c4676882082 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -4,7 +4,6 @@  #include <linux/module.h>  #include <linux/types.h>  #include <linux/if_vlan.h> -#include <linux/aer.h>  #include <linux/tcp.h>  #include <linux/udp.h>  #include <linux/ip.h> @@ -641,8 +640,11 @@ static void igc_configure_rx_ring(struct igc_adapter *adapter,  	else  		buf_size = IGC_RXBUFFER_2048; -	srrctl = IGC_RX_HDR_LEN << IGC_SRRCTL_BSIZEHDRSIZE_SHIFT; -	srrctl |= buf_size >> IGC_SRRCTL_BSIZEPKT_SHIFT; +	srrctl = rd32(IGC_SRRCTL(reg_idx)); +	srrctl &= ~(IGC_SRRCTL_BSIZEPKT_MASK | IGC_SRRCTL_BSIZEHDR_MASK | +		    IGC_SRRCTL_DESCTYPE_MASK); +	srrctl |= IGC_SRRCTL_BSIZEHDR(IGC_RX_HDR_LEN); +	srrctl |= IGC_SRRCTL_BSIZEPKT(buf_size);  	srrctl |= IGC_SRRCTL_DESCTYPE_ADV_ONEBUF;  	wr32(IGC_SRRCTL(reg_idx), srrctl); @@ -1501,6 +1503,7 @@ static int igc_tso(struct igc_ring *tx_ring,  static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,  				       struct igc_ring *tx_ring)  { +	struct igc_adapter *adapter = netdev_priv(tx_ring->netdev);  	bool first_flag = false, insert_empty = false;  	u16 count = TXD_USE_COUNT(skb_headlen(skb));  	__be16 protocol = vlan_get_protocol(skb); @@ -1563,9 +1566,19 @@ done:  	first->bytecount = skb->len;  	first->gso_segs = 1; -	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { -		struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); +	if (tx_ring->max_sdu > 0) { +		u32 max_sdu = 0; + +		max_sdu = tx_ring->max_sdu + +			  (skb_vlan_tagged(first->skb) ? VLAN_HLEN : 0); + +		if (first->bytecount > max_sdu) { +			adapter->stats.txdrop++; +			goto out_drop; +		} +	} +	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {  		/* FIXME: add support for retrieving timestamps from  		 * the other timer registers before skipping the  		 * timestamping request. @@ -4920,7 +4933,8 @@ void igc_update_stats(struct igc_adapter *adapter)  	net_stats->tx_window_errors = adapter->stats.latecol;  	net_stats->tx_carrier_errors = adapter->stats.tncrs; -	/* Tx Dropped needs to be maintained elsewhere */ +	/* Tx Dropped */ +	net_stats->tx_dropped = adapter->stats.txdrop;  	/* Management Stats */  	adapter->stats.mgptc += rd32(IGC_MGTPTC); @@ -5566,25 +5580,8 @@ no_wait:  				mod_timer(&adapter->phy_info_timer,  					  round_jiffies(jiffies + 2 * HZ)); -			/* link is down, time to check for alternate media */ -			if (adapter->flags & IGC_FLAG_MAS_ENABLE) { -				if (adapter->flags & IGC_FLAG_MEDIA_RESET) { -					schedule_work(&adapter->reset_task); -					/* return immediately */ -					return; -				} -			}  			pm_schedule_suspend(netdev->dev.parent,  					    MSEC_PER_SEC * 5); - -		/* also check for alternate media here */ -		} else if (!netif_carrier_ok(netdev) && -			   (adapter->flags & IGC_FLAG_MAS_ENABLE)) { -			if (adapter->flags & IGC_FLAG_MEDIA_RESET) { -				schedule_work(&adapter->reset_task); -				/* return immediately */ -				return; -			}  		}  	} @@ -6010,18 +6007,18 @@ static bool validate_schedule(struct igc_adapter *adapter,  		if (e->command != TC_TAPRIO_CMD_SET_GATES)  			return false; -		for (i = 0; i < adapter->num_tx_queues; i++) { -			if (e->gate_mask & BIT(i)) +		for (i = 0; i < adapter->num_tx_queues; i++) +			if (e->gate_mask & BIT(i)) {  				queue_uses[i]++; -			/* There are limitations: A single queue cannot be -			 * opened and closed multiple times per cycle unless the -			 * gate stays open. Check for it. -			 */ -			if (queue_uses[i] > 1 && -			    !(prev->gate_mask & BIT(i))) -				return false; -		} +				/* There are limitations: A single queue cannot +				 * be opened and closed multiple times per cycle +				 * unless the gate stays open. Check for it. +				 */ +				if (queue_uses[i] > 1 && +				    !(prev->gate_mask & BIT(i))) +					return false; +			}  	}  	return true; @@ -6049,12 +6046,14 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)  	adapter->base_time = 0;  	adapter->cycle_time = NSEC_PER_SEC; +	adapter->qbv_config_change_errors = 0;  	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_SEC; +		ring->max_sdu = 0;  	}  	return 0; @@ -6138,6 +6137,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,  		}  	} +	for (i = 0; i < adapter->num_tx_queues; i++) { +		struct igc_ring *ring = adapter->tx_ring[i]; +		struct net_device *dev = adapter->netdev; + +		if (qopt->max_sdu[i]) +			ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len; +		else +			ring->max_sdu = 0; +	} +  	return 0;  } @@ -6236,8 +6245,10 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,  		caps->broken_mqprio = true; -		if (hw->mac.type == igc_i225) +		if (hw->mac.type == igc_i225) { +			caps->supports_queue_max_sdu = true;  			caps->gate_mask_per_txq = true; +		}  		return 0;  	} diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h index 01c86d36856d..dba5a5759b1c 100644 --- a/drivers/net/ethernet/intel/igc/igc_regs.h +++ b/drivers/net/ethernet/intel/igc/igc_regs.h @@ -292,7 +292,6 @@  /* LTR registers */  #define IGC_LTRC	0x01A0 /* Latency Tolerance Reporting Control */ -#define IGC_DMACR	0x02508 /* DMA Coalescing Control Register */  #define IGC_LTRMINV	0x5BB0 /* LTR Minimum Value */  #define IGC_LTRMAXV	0x5BB4 /* LTR Maximum Value */ diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c index a386c8d61dbf..94a2b0dfb54d 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.c +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c @@ -114,6 +114,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)  static int igc_tsn_enable_offload(struct igc_adapter *adapter)  {  	struct igc_hw *hw = &adapter->hw; +	bool tsn_mode_reconfig = false;  	u32 tqavctrl, baset_l, baset_h;  	u32 sec, nsec, cycle;  	ktime_t base_time, systim; @@ -226,6 +227,10 @@ skip_cbs:  	}  	tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS; + +	if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN) +		tsn_mode_reconfig = true; +  	tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;  	cycle = adapter->cycle_time; @@ -239,6 +244,13 @@ skip_cbs:  		s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);  		base_time = ktime_add_ns(base_time, (n + 1) * cycle); + +		/* Increase the counter if scheduling into the past while +		 * Gate Control List (GCL) is running. +		 */ +		if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && +		    tsn_mode_reconfig) +			adapter->qbv_config_change_errors++;  	} else {  		/* According to datasheet section 7.5.2.9.3.3, FutScdDis bit  		 * has to be configured before the cycle time and base time.  |