diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igb')
| -rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_defines.h | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_hw.h | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_mac.c | 27 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_mbx.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_phy.c | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb.h | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ethtool.c | 41 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 58 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ptp.c | 32 | 
9 files changed, 111 insertions, 68 deletions
| diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index d2e2c50ce257..ca5429774994 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -340,10 +340,10 @@  #define I210_RXPBSIZE_PB_32KB		0x00000020  #define I210_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */  #define I210_TXPBSIZE_MASK		0xC0FFFFFF -#define I210_TXPBSIZE_PB0_8KB		(8 << 0) -#define I210_TXPBSIZE_PB1_8KB		(8 << 6) -#define I210_TXPBSIZE_PB2_4KB		(4 << 12) -#define I210_TXPBSIZE_PB3_4KB		(4 << 18) +#define I210_TXPBSIZE_PB0_6KB		(6 << 0) +#define I210_TXPBSIZE_PB1_6KB		(6 << 6) +#define I210_TXPBSIZE_PB2_6KB		(6 << 12) +#define I210_TXPBSIZE_PB3_6KB		(6 << 18)  #define I210_DTXMXPKTSZ_DEFAULT		0x00000098 diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h index 5d87957b2627..44111f65afc7 100644 --- a/drivers/net/ethernet/intel/igb/e1000_hw.h +++ b/drivers/net/ethernet/intel/igb/e1000_hw.h @@ -1,8 +1,8 @@  /* SPDX-License-Identifier: GPL-2.0 */  /* Copyright(c) 2007 - 2018 Intel Corporation. */ -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ +#ifndef _E1000_IGB_HW_H_ +#define _E1000_IGB_HW_H_  #include <linux/types.h>  #include <linux/delay.h> @@ -551,4 +551,4 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);  void igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);  void igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); -#endif /* _E1000_HW_H_ */ +#endif /* _E1000_IGB_HW_H_ */ diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index fd8eb2f9ab9d..e63ee3cca5ea 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -484,6 +484,31 @@ static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)  }  /** + * igb_i21x_hw_doublecheck - double checks potential HW issue in i21X + * @hw: pointer to the HW structure + * + * Checks if multicast array is wrote correctly + * If not then rewrites again to register + **/ +static void igb_i21x_hw_doublecheck(struct e1000_hw *hw) +{ +	bool is_failed; +	int i; + +	do { +		is_failed = false; +		for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) { +			if (array_rd32(E1000_MTA, i) != hw->mac.mta_shadow[i]) { +				is_failed = true; +				array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]); +				wrfl(); +				break; +			} +		} +	} while (is_failed); +} + +/**   *  igb_update_mc_addr_list - Update Multicast addresses   *  @hw: pointer to the HW structure   *  @mc_addr_list: array of multicast addresses to program @@ -516,6 +541,8 @@ void igb_update_mc_addr_list(struct e1000_hw *hw,  	for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)  		array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);  	wrfl(); +	if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) +		igb_i21x_hw_doublecheck(hw);  }  /** diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.c b/drivers/net/ethernet/intel/igb/e1000_mbx.c index 33cceb77e960..29383112bc19 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mbx.c +++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c @@ -441,7 +441,7 @@ out_no_read:  }  /** - *  e1000_init_mbx_params_pf - set initial values for pf mailbox + *  igb_init_mbx_params_pf - set initial values for pf mailbox   *  @hw: pointer to the HW structure   *   *  Initializes the hw->mbx struct to correct values for pf mailbox diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index 8c8eb82e6272..a018000f7db9 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c @@ -836,6 +836,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw)  			break;  		case e1000_ms_auto:  			data &= ~CR_1000T_MS_ENABLE; +			break;  		default:  			break;  		} diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index aaa954aae574..7bda8c5edea5 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -748,8 +748,8 @@ void igb_ptp_suspend(struct igb_adapter *adapter);  void igb_ptp_rx_hang(struct igb_adapter *adapter);  void igb_ptp_tx_hang(struct igb_adapter *adapter);  void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb); -void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, -			 struct sk_buff *skb); +int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, +			struct sk_buff *skb);  int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);  int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);  void igb_set_flag_queue_pairs(struct igb_adapter *, const u32); diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 28baf203459a..7545da216d8b 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -2347,35 +2347,23 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)  			IGB_TEST_LEN*ETH_GSTRING_LEN);  		break;  	case ETH_SS_STATS: -		for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { -			memcpy(p, igb_gstrings_stats[i].stat_string, -			       ETH_GSTRING_LEN); -			p += ETH_GSTRING_LEN; -		} -		for (i = 0; i < IGB_NETDEV_STATS_LEN; i++) { -			memcpy(p, igb_gstrings_net_stats[i].stat_string, -			       ETH_GSTRING_LEN); -			p += ETH_GSTRING_LEN; -		} +		for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) +			ethtool_sprintf(&p, +					igb_gstrings_stats[i].stat_string); +		for (i = 0; i < IGB_NETDEV_STATS_LEN; i++) +			ethtool_sprintf(&p, +					igb_gstrings_net_stats[i].stat_string);  		for (i = 0; i < adapter->num_tx_queues; i++) { -			sprintf(p, "tx_queue_%u_packets", i); -			p += ETH_GSTRING_LEN; -			sprintf(p, "tx_queue_%u_bytes", i); -			p += ETH_GSTRING_LEN; -			sprintf(p, "tx_queue_%u_restart", i); -			p += ETH_GSTRING_LEN; +			ethtool_sprintf(&p, "tx_queue_%u_packets", i); +			ethtool_sprintf(&p, "tx_queue_%u_bytes", i); +			ethtool_sprintf(&p, "tx_queue_%u_restart", i);  		}  		for (i = 0; i < adapter->num_rx_queues; i++) { -			sprintf(p, "rx_queue_%u_packets", i); -			p += ETH_GSTRING_LEN; -			sprintf(p, "rx_queue_%u_bytes", i); -			p += ETH_GSTRING_LEN; -			sprintf(p, "rx_queue_%u_drops", i); -			p += ETH_GSTRING_LEN; -			sprintf(p, "rx_queue_%u_csum_err", i); -			p += ETH_GSTRING_LEN; -			sprintf(p, "rx_queue_%u_alloc_failed", i); -			p += ETH_GSTRING_LEN; +			ethtool_sprintf(&p, "rx_queue_%u_packets", i); +			ethtool_sprintf(&p, "rx_queue_%u_bytes", i); +			ethtool_sprintf(&p, "rx_queue_%u_drops", i); +			ethtool_sprintf(&p, "rx_queue_%u_csum_err", i); +			ethtool_sprintf(&p, "rx_queue_%u_alloc_failed", i);  		}  		/* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */  		break; @@ -3022,6 +3010,7 @@ static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)  		break;  	case ETHTOOL_SRXCLSRLDEL:  		ret = igb_del_ethtool_nfc_entry(adapter, cmd); +		break;  	default:  		break;  	} diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 878b31d534ec..038a9fd1af44 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -1921,8 +1921,8 @@ static void igb_setup_tx_mode(struct igb_adapter *adapter)  		 */  		val = rd32(E1000_TXPBS);  		val &= ~I210_TXPBSIZE_MASK; -		val |= I210_TXPBSIZE_PB0_8KB | I210_TXPBSIZE_PB1_8KB | -			I210_TXPBSIZE_PB2_4KB | I210_TXPBSIZE_PB3_4KB; +		val |= I210_TXPBSIZE_PB0_6KB | I210_TXPBSIZE_PB1_6KB | +			I210_TXPBSIZE_PB2_6KB | I210_TXPBSIZE_PB3_6KB;  		wr32(E1000_TXPBS, val);  		val = rd32(E1000_RXPBS); @@ -2037,7 +2037,7 @@ static void igb_power_down_link(struct igb_adapter *adapter)  }  /** - * Detect and switch function for Media Auto Sense + * igb_check_swap_media -  Detect and switch function for Media Auto Sense   * @adapter: address of the board private structure   **/  static void igb_check_swap_media(struct igb_adapter *adapter) @@ -2934,7 +2934,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,  	int cpu = smp_processor_id();  	struct igb_ring *tx_ring;  	struct netdev_queue *nq; -	int drops = 0; +	int nxmit = 0;  	int i;  	if (unlikely(test_bit(__IGB_DOWN, &adapter->state))) @@ -2961,10 +2961,9 @@ static int igb_xdp_xmit(struct net_device *dev, int n,  		int err;  		err = igb_xmit_xdp_ring(adapter, tx_ring, xdpf); -		if (err != IGB_XDP_TX) { -			xdp_return_frame_rx_napi(xdpf); -			drops++; -		} +		if (err != IGB_XDP_TX) +			break; +		nxmit++;  	}  	__netif_tx_unlock(nq); @@ -2972,7 +2971,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,  	if (unlikely(flags & XDP_XMIT_FLUSH))  		igb_xdp_ring_update_tail(tx_ring); -	return n - drops; +	return nxmit;  }  static const struct net_device_ops igb_netdev_ops = { @@ -3115,7 +3114,7 @@ static s32 igb_init_i2c(struct igb_adapter *adapter)  		return 0;  	/* Initialize the i2c bus which is controlled by the registers. -	 * This bus will use the i2c_algo_bit structue that implements +	 * This bus will use the i2c_algo_bit structure that implements  	 * the protocol through toggling of the 4 bits in the register.  	 */  	adapter->i2c_adap.owner = THIS_MODULE; @@ -4020,7 +4019,7 @@ static int igb_sw_init(struct igb_adapter *adapter)  }  /** - *  igb_open - Called when a network interface is made active + *  __igb_open - Called when a network interface is made active   *  @netdev: network interface device structure   *  @resuming: indicates whether we are in a resume call   * @@ -4138,7 +4137,7 @@ int igb_open(struct net_device *netdev)  }  /** - *  igb_close - Disables a network interface + *  __igb_close - Disables a network interface   *  @netdev: network interface device structure   *  @suspending: indicates we are in a suspend call   * @@ -5856,7 +5855,7 @@ static void igb_tx_ctxtdesc(struct igb_ring *tx_ring,  	 */  	if (tx_ring->launchtime_enable) {  		ts = ktime_to_timespec64(first->skb->tstamp); -		first->skb->tstamp = ktime_set(0, 0); +		skb_txtime_consumed(first->skb);  		context_desc->seqnum_seed = cpu_to_le32(ts.tv_nsec / 32);  	} else {  		context_desc->seqnum_seed = 0; @@ -8214,7 +8213,8 @@ static void igb_reuse_rx_page(struct igb_ring *rx_ring,  	new_buff->pagecnt_bias	= old_buff->pagecnt_bias;  } -static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer) +static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer, +				  int rx_buf_pgcnt)  {  	unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;  	struct page *page = rx_buffer->page; @@ -8225,7 +8225,7 @@ static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer)  #if (PAGE_SIZE < 8192)  	/* if we are only owner of page we can reuse it */ -	if (unlikely((page_ref_count(page) - pagecnt_bias) > 1)) +	if (unlikely((rx_buf_pgcnt - pagecnt_bias) > 1))  		return false;  #else  #define IGB_LAST_OFFSET \ @@ -8301,9 +8301,10 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,  		return NULL;  	if (unlikely(igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))) { -		igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb); -		xdp->data += IGB_TS_HDR_LEN; -		size -= IGB_TS_HDR_LEN; +		if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb)) { +			xdp->data += IGB_TS_HDR_LEN; +			size -= IGB_TS_HDR_LEN; +		}  	}  	/* Determine available headroom for copy */ @@ -8364,8 +8365,8 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,  	/* pull timestamp out of packet data */  	if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { -		igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb); -		__skb_pull(skb, IGB_TS_HDR_LEN); +		if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb)) +			__skb_pull(skb, IGB_TS_HDR_LEN);  	}  	/* update buffer offset */ @@ -8614,11 +8615,17 @@ static unsigned int igb_rx_offset(struct igb_ring *rx_ring)  }  static struct igb_rx_buffer *igb_get_rx_buffer(struct igb_ring *rx_ring, -					       const unsigned int size) +					       const unsigned int size, int *rx_buf_pgcnt)  {  	struct igb_rx_buffer *rx_buffer;  	rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; +	*rx_buf_pgcnt = +#if (PAGE_SIZE < 8192) +		page_count(rx_buffer->page); +#else +		0; +#endif  	prefetchw(rx_buffer->page);  	/* we are reusing so sync this buffer for CPU use */ @@ -8634,9 +8641,9 @@ static struct igb_rx_buffer *igb_get_rx_buffer(struct igb_ring *rx_ring,  }  static void igb_put_rx_buffer(struct igb_ring *rx_ring, -			      struct igb_rx_buffer *rx_buffer) +			      struct igb_rx_buffer *rx_buffer, int rx_buf_pgcnt)  { -	if (igb_can_reuse_rx_page(rx_buffer)) { +	if (igb_can_reuse_rx_page(rx_buffer, rx_buf_pgcnt)) {  		/* hand second half of page back to the ring */  		igb_reuse_rx_page(rx_ring, rx_buffer);  	} else { @@ -8664,6 +8671,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)  	unsigned int xdp_xmit = 0;  	struct xdp_buff xdp;  	u32 frame_sz = 0; +	int rx_buf_pgcnt;  	/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */  #if (PAGE_SIZE < 8192) @@ -8693,7 +8701,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)  		 */  		dma_rmb(); -		rx_buffer = igb_get_rx_buffer(rx_ring, size); +		rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt);  		/* retrieve a buffer from the ring */  		if (!skb) { @@ -8736,7 +8744,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)  			break;  		} -		igb_put_rx_buffer(rx_ring, rx_buffer); +		igb_put_rx_buffer(rx_ring, rx_buffer, rx_buf_pgcnt);  		cleaned_count++;  		/* fetch next buffer in frame if non-eop */ diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 7cc5428c3b3d..ba61fe9bfaf4 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -856,6 +856,9 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)  	dev_kfree_skb_any(skb);  } +#define IGB_RET_PTP_DISABLED 1 +#define IGB_RET_PTP_INVALID 2 +  /**   * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp   * @q_vector: Pointer to interrupt specific structure @@ -864,19 +867,29 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)   *   * This function is meant to retrieve a timestamp from the first buffer of an   * incoming frame.  The value is stored in little endian format starting on - * byte 8. + * byte 8 + * + * Returns: 0 if success, nonzero if failure   **/ -void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, -			 struct sk_buff *skb) +int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, +			struct sk_buff *skb)  { -	__le64 *regval = (__le64 *)va;  	struct igb_adapter *adapter = q_vector->adapter; +	__le64 *regval = (__le64 *)va;  	int adjust = 0; +	if (!(adapter->ptp_flags & IGB_PTP_ENABLED)) +		return IGB_RET_PTP_DISABLED; +  	/* The timestamp is recorded in little endian format.  	 * DWORD: 0        1        2        3  	 * Field: Reserved Reserved SYSTIML  SYSTIMH  	 */ + +	/* check reserved dwords are zero, be/le doesn't matter for zero */ +	if (regval[0]) +		return IGB_RET_PTP_INVALID; +  	igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb),  				   le64_to_cpu(regval[1])); @@ -896,6 +909,8 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,  	}  	skb_hwtstamps(skb)->hwtstamp =  		ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); + +	return 0;  }  /** @@ -906,13 +921,15 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,   * This function is meant to retrieve a timestamp from the internal registers   * of the adapter and store it in the skb.   **/ -void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, -			 struct sk_buff *skb) +void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb)  {  	struct igb_adapter *adapter = q_vector->adapter;  	struct e1000_hw *hw = &adapter->hw; -	u64 regval;  	int adjust = 0; +	u64 regval; + +	if (!(adapter->ptp_flags & IGB_PTP_ENABLED)) +		return;  	/* If this bit is set, then the RX registers contain the time stamp. No  	 * other packet will be time stamped until we read these registers, so @@ -1008,6 +1025,7 @@ static int igb_ptp_set_timestamp_mode(struct igb_adapter *adapter,  	switch (config->tx_type) {  	case HWTSTAMP_TX_OFF:  		tsync_tx_ctl = 0; +		break;  	case HWTSTAMP_TX_ON:  		break;  	default: | 
