[Intel-wired-lan] [next PATCH 03/11] igb: Allow asymmetric configuration of MTU versus Rx frame size

Hisashi T Fujinaka htodd at twofifty.com
Tue Jan 12 18:03:33 UTC 2016


Hey Alex, I have a question.

On Wed, 6 Jan 2016, Alexander Duyck wrote:

> Since the igb driver is using page based receive there is no point in
> limiting the Rx capabilities of the device.  The driver can receive 9K
> jumbo frames at all times.  The only changes needed due to MTU changes are
> updates for the FIFO sizes and flow-control watermarks.
>
> Update the maximum frame size to reflect the 9.5K limitation of the
> hardware, and replace all instances of max_frame_size with
> MAX_JUMBO_FRAME_SIZE when referring to an Rx FIFO or frame.
>
> Signed-off-by: Alexander Duyck <aduyck at mirantis.com>
> ---
> drivers/net/ethernet/intel/igb/e1000_defines.h |    3 -
> drivers/net/ethernet/intel/igb/igb_main.c      |  107 +++++++++---------------
> 2 files changed, 42 insertions(+), 68 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
> index e28f06e56f37..3e4181a4b177 100644
> --- a/drivers/net/ethernet/intel/igb/e1000_defines.h
> +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
> @@ -357,7 +357,8 @@
> /* Ethertype field values */
> #define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
>
> -#define MAX_JUMBO_FRAME_SIZE    0x3F00
> +/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
> +#define MAX_JUMBO_FRAME_SIZE    0x2600
>
> /* PBA constants */
> #define E1000_PBA_32K 0x0020
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index 3b6d4e10d095..5b200c9f7658 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -1891,7 +1891,7 @@ void igb_reset(struct igb_adapter *adapter)
> 	struct e1000_hw *hw = &adapter->hw;
> 	struct e1000_mac_info *mac = &hw->mac;
> 	struct e1000_fc_info *fc = &hw->fc;
> -	u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm;
> +	u32 pba, hwm;
>
> 	/* Repartition Pba for greater than 9k mtu
> 	 * To take effect CTRL.RST is required.
> @@ -1917,9 +1917,10 @@ void igb_reset(struct igb_adapter *adapter)
> 		break;
> 	}
>
> -	if ((adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) &&
> -	    (mac->type < e1000_82576)) {
> -		/* adjust PBA for jumbo frames */
> +	if (mac->type == e1000_82575) {
> +		u32 min_rx_space, min_tx_space, needed_tx_space;
> +
> +		/* write Rx PBA so that hardware can report correct Tx PBA */
> 		wr32(E1000_PBA, pba);

Aren't you writing a random pba here? Shouldn't it still be "pba = 0"  a
few lines up?

> 		/* To maintain wire speed transmits, the Tx FIFO should be
> @@ -1929,31 +1930,26 @@ void igb_reset(struct igb_adapter *adapter)
> 		 * one full receive packet and is similarly rounded up and
> 		 * expressed in KB.
> 		 */
> -		pba = rd32(E1000_PBA);
> -		/* upper 16 bits has Tx packet buffer allocation size in KB */
> -		tx_space = pba >> 16;
> -		/* lower 16 bits has Rx packet buffer allocation size in KB */
> -		pba &= 0xffff;
> -		/* the Tx fifo also stores 16 bytes of information about the Tx
> -		 * but don't include ethernet FCS because hardware appends it
> +		min_rx_space = DIV_ROUND_UP(MAX_JUMBO_FRAME_SIZE, 1024);
> +
> +		/* The Tx FIFO also stores 16 bytes of information about the Tx
> +		 * but don't include Ethernet FCS because hardware appends it.
> +		 * We only need to round down to the nearest 512 byte block count
> +		 * since the value we care about is 2 frames, not 1.
> 		 */
> -		min_tx_space = (adapter->max_frame_size +
> -				sizeof(union e1000_adv_tx_desc) -
> -				ETH_FCS_LEN) * 2;
> -		min_tx_space = ALIGN(min_tx_space, 1024);
> -		min_tx_space >>= 10;
> -		/* software strips receive CRC, so leave room for it */
> -		min_rx_space = adapter->max_frame_size;
> -		min_rx_space = ALIGN(min_rx_space, 1024);
> -		min_rx_space >>= 10;
> +		min_tx_space = adapter->max_frame_size;
> +		min_tx_space += sizeof(union e1000_adv_tx_desc) - ETH_FCS_LEN;
> +		min_tx_space = DIV_ROUND_UP(min_tx_space, 512);
> +
> +		/* upper 16 bits has Tx packet buffer allocation size in KB */
> +		needed_tx_space = min_tx_space - (rd32(E1000_PBA) >> 16);
>
> 		/* If current Tx allocation is less than the min Tx FIFO size,
> 		 * and the min Tx FIFO size is less than the current Rx FIFO
> -		 * allocation, take space away from current Rx allocation
> +		 * allocation, take space away from current Rx allocation.
> 		 */
> -		if (tx_space < min_tx_space &&
> -		    ((min_tx_space - tx_space) < pba)) {
> -			pba = pba - (min_tx_space - tx_space);
> +		if (needed_tx_space < pba) {
> +			pba -= needed_tx_space;
>
> 			/* if short on Rx space, Rx wins and must trump Tx
> 			 * adjustment
> @@ -1961,18 +1957,20 @@ void igb_reset(struct igb_adapter *adapter)
> 			if (pba < min_rx_space)
> 				pba = min_rx_space;
> 		}
> +
> +		/* adjust PBA for jumbo frames */
> 		wr32(E1000_PBA, pba);
> 	}
>
> -	/* flow control settings */
> -	/* The high water mark must be low enough to fit one full frame
> -	 * (or the size used for early receive) above it in the Rx FIFO.
> -	 * Set it to the lower of:
> -	 * - 90% of the Rx FIFO size, or
> -	 * - the full Rx FIFO size minus one full frame
> +	/* flow control settings
> +	 * The high water mark must be low enough to fit one full frame
> +	 * after transmitting the pause frame.  As such we must have enough
> +	 * space to allow for us to complete our current transmit and then
> +	 * receive the frame that is in progress from the link partner.
> +	 * Set it to:
> +	 * - the full Rx FIFO size minus one full Tx plus one full Rx frame
> 	 */
> -	hwm = min(((pba << 10) * 9 / 10),
> -			((pba << 10) - 2 * adapter->max_frame_size));
> +	hwm = (pba << 10) - (adapter->max_frame_size + MAX_JUMBO_FRAME_SIZE);
>
> 	fc->high_water = hwm & 0xFFFFFFF0;	/* 16-byte granularity */
> 	fc->low_water = fc->high_water - 16;
> @@ -3612,7 +3610,7 @@ void igb_setup_rctl(struct igb_adapter *adapter)
> 	/* disable store bad packets and clear size bits. */
> 	rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256);
>
> -	/* enable LPE to prevent packets larger than max_frame_size */
> +	/* enable LPE to allow for reception of jumbo frames */
> 	rctl |= E1000_RCTL_LPE;
>
> 	/* disable queue 0 to prevent tail write w/o re-config */
> @@ -3668,32 +3666,6 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
> 	return 0;
> }
>
> -/**
> - *  igb_rlpml_set - set maximum receive packet size
> - *  @adapter: board private structure
> - *
> - *  Configure maximum receivable packet size.
> - **/
> -static void igb_rlpml_set(struct igb_adapter *adapter)
> -{
> -	u32 max_frame_size = adapter->max_frame_size;
> -	struct e1000_hw *hw = &adapter->hw;
> -	u16 pf_id = adapter->vfs_allocated_count;
> -
> -	if (pf_id) {
> -		igb_set_vf_rlpml(adapter, max_frame_size, pf_id);
> -		/* If we're in VMDQ or SR-IOV mode, then set global RLPML
> -		 * to our max jumbo frame size, in case we need to enable
> -		 * jumbo frames on one of the rings later.
> -		 * This will not pass over-length frames into the default
> -		 * queue because it's gated by the VMOLR.RLPML.
> -		 */
> -		max_frame_size = MAX_JUMBO_FRAME_SIZE;
> -	}
> -
> -	wr32(E1000_RLPML, max_frame_size);
> -}
> -
> static inline void igb_set_vmolr(struct igb_adapter *adapter,
> 				 int vfn, bool aupe)
> {
> @@ -4191,7 +4163,14 @@ static void igb_set_rx_mode(struct net_device *netdev)
>
> 	vmolr |= rd32(E1000_VMOLR(vfn)) &
> 		 ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE);
> +
> +	/* enable Rx jumbo frames, no need for restriction */
> +	vmolr &= ~E1000_VMOLR_RLPML_MASK;
> +	vmolr |= MAX_JUMBO_FRAME_SIZE | E1000_VMOLR_LPE;
> +
> 	wr32(E1000_VMOLR(vfn), vmolr);
> +	wr32(E1000_RLPML, MAX_JUMBO_FRAME_SIZE);
> +
> 	igb_restore_vf_multicasts(adapter);
> }
>
> @@ -7331,8 +7310,6 @@ static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features)
> 		ctrl &= ~E1000_CTRL_VME;
> 		wr32(E1000_CTRL, ctrl);
> 	}
> -
> -	igb_rlpml_set(adapter);
> }
>
> static int igb_vlan_rx_add_vid(struct net_device *netdev,
> @@ -8088,9 +8065,7 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
> 			 * than the Rx threshold. Set hwm to PBA - max frame
> 			 * size in 16B units, capping it at PBA - 6KB.
> 			 */
> -			hwm = 64 * pba - adapter->max_frame_size / 16;
> -			if (hwm < 64 * (pba - 6))
> -				hwm = 64 * (pba - 6);
> +			hwm = 64 * (pba - 6);
> 			reg = rd32(E1000_FCRTC);
> 			reg &= ~E1000_FCRTC_RTH_COAL_MASK;
> 			reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT)
> @@ -8100,9 +8075,7 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
> 			/* Set the DMA Coalescing Rx threshold to PBA - 2 * max
> 			 * frame size, capping it at PBA - 10KB.
> 			 */
> -			dmac_thr = pba - adapter->max_frame_size / 512;
> -			if (dmac_thr < pba - 10)
> -				dmac_thr = pba - 10;
> +			dmac_thr = pba - 10;
> 			reg = rd32(E1000_DMACR);
> 			reg &= ~E1000_DMACR_DMACTHR_MASK;
> 			reg |= ((dmac_thr << E1000_DMACR_DMACTHR_SHIFT)
>
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan at lists.osuosl.org
> http://lists.osuosl.org/mailman/listinfo/intel-wired-lan
>


More information about the Intel-wired-lan mailing list