Commit 9f66d3ee authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher

ixgbe: Fix VF rate limiting to correctly account for more queues per VF

This change fixes the assumptions of the rate limiting code that previously
assumed that each VF would only ever have 2 queues.  This update makes it
so that we now use a queues per pool value that is determined based on the
VMDq feature mask.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Acked-By: default avatarJohn Fastabend <john.r.fastabend@intel.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Tested-by: default avatarRobert Garrett <RobertX.Garrett@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent b35d4d42
...@@ -815,9 +815,9 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) ...@@ -815,9 +815,9 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
return err; 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: case IXGBE_LINK_SPEED_100_FULL:
return 100; return 100;
case IXGBE_LINK_SPEED_1GB_FULL: case IXGBE_LINK_SPEED_1GB_FULL:
...@@ -829,27 +829,30 @@ static int ixgbe_link_mbps(int internal_link_speed) ...@@ -829,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, static void ixgbe_set_vf_rate_limit(struct ixgbe_adapter *adapter, int vf)
int link_speed)
{ {
int rf_dec, rf_int; struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
u32 bcnrc_val; 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 */ /* Calculate the rate factor values to set */
rf_int = link_speed / tx_rate; bcnrc_val <<= IXGBE_RTTBCNRC_RF_INT_SHIFT;
rf_dec = (link_speed - (rf_int * tx_rate)); bcnrc_val /= tx_rate;
rf_dec = (rf_dec * (1<<IXGBE_RTTBCNRC_RF_INT_SHIFT)) / tx_rate;
/* clear everything but the rate factor */
bcnrc_val = IXGBE_RTTBCNRC_RS_ENA; bcnrc_val &= IXGBE_RTTBCNRC_RF_INT_MASK |
bcnrc_val |= ((rf_int<<IXGBE_RTTBCNRC_RF_INT_SHIFT) & IXGBE_RTTBCNRC_RF_DEC_MASK;
IXGBE_RTTBCNRC_RF_INT_MASK);
bcnrc_val |= (rf_dec & IXGBE_RTTBCNRC_RF_DEC_MASK); /* enable the rate scheduler */
} else { bcnrc_val |= IXGBE_RTTBCNRC_RS_ENA;
bcnrc_val = 0;
} }
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 * Set global transmit compensation time to the MMW_SIZE in RTTBCNRM
* register. Typically MMW_SIZE=0x014 if 9728-byte jumbo is supported * register. Typically MMW_SIZE=0x014 if 9728-byte jumbo is supported
...@@ -866,53 +869,68 @@ static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate, ...@@ -866,53 +869,68 @@ static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate,
break; 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) void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter)
{ {
int actual_link_speed, i; int i;
bool reset_rate = false;
/* VF Tx rate limit was not set */ /* VF Tx rate limit was not set */
if (adapter->vf_rate_link_speed == 0) if (!adapter->vf_rate_link_speed)
return; return;
actual_link_speed = ixgbe_link_mbps(adapter->link_speed); if (ixgbe_link_mbps(adapter) != adapter->vf_rate_link_speed) {
if (actual_link_speed != adapter->vf_rate_link_speed) {
reset_rate = true;
adapter->vf_rate_link_speed = 0; adapter->vf_rate_link_speed = 0;
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"Link speed has been changed. VF Transmit rate " "Link speed has been changed. VF Transmit rate is disabled\n");
"is disabled\n");
} }
for (i = 0; i < adapter->num_vfs; i++) { for (i = 0; i < adapter->num_vfs; i++) {
if (reset_rate) if (!adapter->vf_rate_link_speed)
adapter->vfinfo[i].tx_rate = 0; adapter->vfinfo[i].tx_rate = 0;
ixgbe_set_vf_rate_limit(&adapter->hw, i, ixgbe_set_vf_rate_limit(adapter, i);
adapter->vfinfo[i].tx_rate,
actual_link_speed);
} }
} }
int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw; int link_speed;
int actual_link_speed;
actual_link_speed = ixgbe_link_mbps(adapter->link_speed); /* verify VF is active */
if ((vf >= adapter->num_vfs) || (!adapter->link_up) || if (vf >= adapter->num_vfs)
(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 */
return -EINVAL; return -EINVAL;
adapter->vf_rate_link_speed = actual_link_speed; /* verify link is up */
adapter->vfinfo[vf].tx_rate = (u16)tx_rate; if (!adapter->link_up)
ixgbe_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed); 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment