diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 103 | 
1 files changed, 63 insertions, 40 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 4fea8716ab6..dce48bf64d9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -346,6 +346,10 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter)  static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,  			     u32 vf)  { +	/* VLAN 0 is a special case, don't allow it to be removed */ +	if (!vid && !add) +		return 0; +  	return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);  } @@ -414,6 +418,7 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)  				  VLAN_PRIO_SHIFT)), vf);  		ixgbe_set_vmolr(hw, vf, false);  	} else { +		ixgbe_set_vf_vlan(adapter, true, 0, vf);  		ixgbe_set_vmvir(adapter, 0, vf);  		ixgbe_set_vmolr(hw, vf, true);  	} @@ -810,9 +815,9 @@ out:         return err;  } -static int ixgbe_link_mbps(int internal_link_speed) +static int ixgbe_link_mbps(struct ixgbe_adapter *adapter)  { -	switch (internal_link_speed) { +	switch (adapter->link_speed) {  	case IXGBE_LINK_SPEED_100_FULL:  		return 100;  	case IXGBE_LINK_SPEED_1GB_FULL: @@ -824,27 +829,30 @@ static int ixgbe_link_mbps(int internal_link_speed)  	}  } -static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate, -				    int link_speed) +static void ixgbe_set_vf_rate_limit(struct ixgbe_adapter *adapter, int vf)  { -	int rf_dec, rf_int; -	u32 bcnrc_val; +	struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; +	struct ixgbe_hw *hw = &adapter->hw; +	u32 bcnrc_val = 0; +	u16 queue, queues_per_pool; +	u16 tx_rate = adapter->vfinfo[vf].tx_rate; + +	if (tx_rate) { +		/* start with base link speed value */ +		bcnrc_val = adapter->vf_rate_link_speed; -	if (tx_rate != 0) {  		/* Calculate the rate factor values to set */ -		rf_int = link_speed / tx_rate; -		rf_dec = (link_speed - (rf_int * tx_rate)); -		rf_dec = (rf_dec * (1<<IXGBE_RTTBCNRC_RF_INT_SHIFT)) / tx_rate; +		bcnrc_val <<= IXGBE_RTTBCNRC_RF_INT_SHIFT; +		bcnrc_val /= tx_rate; -		bcnrc_val = IXGBE_RTTBCNRC_RS_ENA; -		bcnrc_val |= ((rf_int<<IXGBE_RTTBCNRC_RF_INT_SHIFT) & -		               IXGBE_RTTBCNRC_RF_INT_MASK); -		bcnrc_val |= (rf_dec & IXGBE_RTTBCNRC_RF_DEC_MASK); -	} else { -		bcnrc_val = 0; +		/* clear everything but the rate factor */ +		bcnrc_val &= IXGBE_RTTBCNRC_RF_INT_MASK | +			     IXGBE_RTTBCNRC_RF_DEC_MASK; + +		/* enable the rate scheduler */ +		bcnrc_val |= IXGBE_RTTBCNRC_RS_ENA;  	} -	IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, 2*vf); /* vf Y uses queue 2*Y */  	/*  	 * Set global transmit compensation time to the MMW_SIZE in RTTBCNRM  	 * register. Typically MMW_SIZE=0x014 if 9728-byte jumbo is supported @@ -861,53 +869,68 @@ static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate,  		break;  	} -	IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val); +	/* determine how many queues per pool based on VMDq mask */ +	queues_per_pool = __ALIGN_MASK(1, ~vmdq->mask); + +	/* write value for all Tx queues belonging to VF */ +	for (queue = 0; queue < queues_per_pool; queue++) { +		unsigned int reg_idx = (vf * queues_per_pool) + queue; + +		IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, reg_idx); +		IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val); +	}  }  void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter)  { -	int actual_link_speed, i; -	bool reset_rate = false; +	int i;  	/* VF Tx rate limit was not set */ -	if (adapter->vf_rate_link_speed == 0) +	if (!adapter->vf_rate_link_speed)  		return; -	actual_link_speed = ixgbe_link_mbps(adapter->link_speed); -	if (actual_link_speed != adapter->vf_rate_link_speed) { -		reset_rate = true; +	if (ixgbe_link_mbps(adapter) != adapter->vf_rate_link_speed) {  		adapter->vf_rate_link_speed = 0;  		dev_info(&adapter->pdev->dev, -		         "Link speed has been changed. VF Transmit rate " -		         "is disabled\n"); +			 "Link speed has been changed. VF Transmit rate is disabled\n");  	}  	for (i = 0; i < adapter->num_vfs; i++) { -		if (reset_rate) +		if (!adapter->vf_rate_link_speed)  			adapter->vfinfo[i].tx_rate = 0; -		ixgbe_set_vf_rate_limit(&adapter->hw, i, -					adapter->vfinfo[i].tx_rate, -					actual_link_speed); +		ixgbe_set_vf_rate_limit(adapter, i);  	}  }  int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)  {  	struct ixgbe_adapter *adapter = netdev_priv(netdev); -	struct ixgbe_hw *hw = &adapter->hw; -	int actual_link_speed; +	int link_speed; -	actual_link_speed = ixgbe_link_mbps(adapter->link_speed); -	if ((vf >= adapter->num_vfs) || (!adapter->link_up) || -	    (tx_rate > actual_link_speed) || (actual_link_speed != 10000) || -	    ((tx_rate != 0) && (tx_rate <= 10))) -	    /* rate limit cannot be set to 10Mb or less in 10Gb adapters */ +	/* verify VF is active */ +	if (vf >= adapter->num_vfs)  		return -EINVAL; -	adapter->vf_rate_link_speed = actual_link_speed; -	adapter->vfinfo[vf].tx_rate = (u16)tx_rate; -	ixgbe_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed); +	/* verify link is up */ +	if (!adapter->link_up) +		return -EINVAL; + +	/* verify we are linked at 10Gbps */ +	link_speed = ixgbe_link_mbps(adapter); +	if (link_speed != 10000) +		return -EINVAL; + +	/* rate limit cannot be less than 10Mbs or greater than link speed */ +	if (tx_rate && ((tx_rate <= 10) || (tx_rate > link_speed))) +		return -EINVAL; + +	/* store values */ +	adapter->vf_rate_link_speed = link_speed; +	adapter->vfinfo[vf].tx_rate = tx_rate; + +	/* update hardware configuration */ +	ixgbe_set_vf_rate_limit(adapter, vf);  	return 0;  }  |