Commit 2ec56385 authored by Paul M Stillwell Jr's avatar Paul M Stillwell Jr Committed by Tony Nguyen

ice: handle increasing Tx or Rx ring sizes

There is an issue when the Tx or Rx ring size increases using
'ethtool -L ...' where the new rings don't get the correct ITR
values because when we rebuild the VSI we don't know that some
of the rings may be new.

Fix this by looking at the original number of rings and
determining if the rings in ice_vsi_rebuild_set_coalesce()
were not present in the original rings received in
ice_vsi_rebuild_get_coalesce().

Also change the code to return an error if we can't allocate
memory for the coalesce data in ice_vsi_rebuild().
Signed-off-by: default avatarPaul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Tested-by: default avatarTony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent a05983c3
...@@ -2866,38 +2866,46 @@ int ice_vsi_release(struct ice_vsi *vsi) ...@@ -2866,38 +2866,46 @@ int ice_vsi_release(struct ice_vsi *vsi)
} }
/** /**
* ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector * ice_vsi_rebuild_update_coalesce_intrl - set interrupt rate limit for a q_vector
* @q_vector: pointer to q_vector which is being updated * @q_vector: pointer to q_vector which is being updated
* @coalesce: pointer to array of struct with stored coalesce * @stored_intrl_setting: original INTRL setting
* *
* Set coalesce param in q_vector and update these parameters in HW. * Set coalesce param in q_vector and update these parameters in HW.
*/ */
static void static void
ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector, ice_vsi_rebuild_update_coalesce_intrl(struct ice_q_vector *q_vector,
struct ice_coalesce_stored *coalesce) u16 stored_intrl_setting)
{ {
struct ice_ring_container *rx_rc = &q_vector->rx;
struct ice_ring_container *tx_rc = &q_vector->tx;
struct ice_hw *hw = &q_vector->vsi->back->hw; struct ice_hw *hw = &q_vector->vsi->back->hw;
tx_rc->itr_setting = coalesce->itr_tx; q_vector->intrl = stored_intrl_setting;
rx_rc->itr_setting = coalesce->itr_rx;
/* dynamic ITR values will be updated during Tx/Rx */
if (!ITR_IS_DYNAMIC(tx_rc->itr_setting))
wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx),
ITR_REG_ALIGN(tx_rc->itr_setting) >>
ICE_ITR_GRAN_S);
if (!ITR_IS_DYNAMIC(rx_rc->itr_setting))
wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx),
ITR_REG_ALIGN(rx_rc->itr_setting) >>
ICE_ITR_GRAN_S);
q_vector->intrl = coalesce->intrl;
wr32(hw, GLINT_RATE(q_vector->reg_idx), wr32(hw, GLINT_RATE(q_vector->reg_idx),
ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
} }
/**
* ice_vsi_rebuild_update_coalesce_itr - set coalesce for a q_vector
* @q_vector: pointer to q_vector which is being updated
* @rc: pointer to ring container
* @stored_itr_setting: original ITR setting
*
* Set coalesce param in q_vector and update these parameters in HW.
*/
static void
ice_vsi_rebuild_update_coalesce_itr(struct ice_q_vector *q_vector,
struct ice_ring_container *rc,
u16 stored_itr_setting)
{
struct ice_hw *hw = &q_vector->vsi->back->hw;
rc->itr_setting = stored_itr_setting;
/* dynamic ITR values will be updated during Tx/Rx */
if (!ITR_IS_DYNAMIC(rc->itr_setting))
wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx),
ITR_REG_ALIGN(rc->itr_setting) >> ICE_ITR_GRAN_S);
}
/** /**
* ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors
* @vsi: VSI connected with q_vectors * @vsi: VSI connected with q_vectors
...@@ -2917,6 +2925,11 @@ ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi, ...@@ -2917,6 +2925,11 @@ ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
coalesce[i].itr_tx = q_vector->tx.itr_setting; coalesce[i].itr_tx = q_vector->tx.itr_setting;
coalesce[i].itr_rx = q_vector->rx.itr_setting; coalesce[i].itr_rx = q_vector->rx.itr_setting;
coalesce[i].intrl = q_vector->intrl; coalesce[i].intrl = q_vector->intrl;
if (i < vsi->num_txq)
coalesce[i].tx_valid = true;
if (i < vsi->num_rxq)
coalesce[i].rx_valid = true;
} }
return vsi->num_q_vectors; return vsi->num_q_vectors;
...@@ -2941,17 +2954,59 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi, ...@@ -2941,17 +2954,59 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
if ((size && !coalesce) || !vsi) if ((size && !coalesce) || !vsi)
return; return;
for (i = 0; i < size && i < vsi->num_q_vectors; i++) /* There are a couple of cases that have to be handled here:
ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], * 1. The case where the number of queue vectors stays the same, but
&coalesce[i]); * the number of Tx or Rx rings changes (the first for loop)
* 2. The case where the number of queue vectors increased (the
/* number of q_vectors increased, so assume coalesce settings were * second for loop)
* changed globally (i.e. ethtool -C eth0 instead of per-queue) and use
* the previous settings from q_vector 0 for all of the new q_vectors
*/ */
for (; i < vsi->num_q_vectors; i++) for (i = 0; i < size && i < vsi->num_q_vectors; i++) {
ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], /* There are 2 cases to handle here and they are the same for
&coalesce[0]); * both Tx and Rx:
* if the entry was valid previously (coalesce[i].[tr]x_valid
* and the loop variable is less than the number of rings
* allocated, then write the previous values
*
* if the entry was not valid previously, but the number of
* rings is less than are allocated (this means the number of
* rings increased from previously), then write out the
* values in the first element
*/
if (i < vsi->alloc_rxq && coalesce[i].rx_valid)
ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
&vsi->q_vectors[i]->rx,
coalesce[i].itr_rx);
else if (i < vsi->alloc_rxq)
ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
&vsi->q_vectors[i]->rx,
coalesce[0].itr_rx);
if (i < vsi->alloc_txq && coalesce[i].tx_valid)
ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
&vsi->q_vectors[i]->tx,
coalesce[i].itr_tx);
else if (i < vsi->alloc_txq)
ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
&vsi->q_vectors[i]->tx,
coalesce[0].itr_tx);
ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i],
coalesce[i].intrl);
}
/* the number of queue vectors increased so write whatever is in
* the first element
*/
for (; i < vsi->num_q_vectors; i++) {
ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
&vsi->q_vectors[i]->tx,
coalesce[0].itr_tx);
ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
&vsi->q_vectors[i]->rx,
coalesce[0].itr_rx);
ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i],
coalesce[0].intrl);
}
} }
/** /**
...@@ -2980,9 +3035,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) ...@@ -2980,9 +3035,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
coalesce = kcalloc(vsi->num_q_vectors, coalesce = kcalloc(vsi->num_q_vectors,
sizeof(struct ice_coalesce_stored), GFP_KERNEL); sizeof(struct ice_coalesce_stored), GFP_KERNEL);
if (coalesce) if (!coalesce)
prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, return -ENOMEM;
coalesce);
prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce);
ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
ice_vsi_free_q_vectors(vsi); ice_vsi_free_q_vectors(vsi);
......
...@@ -357,6 +357,8 @@ struct ice_coalesce_stored { ...@@ -357,6 +357,8 @@ struct ice_coalesce_stored {
u16 itr_tx; u16 itr_tx;
u16 itr_rx; u16 itr_rx;
u8 intrl; u8 intrl;
u8 tx_valid;
u8 rx_valid;
}; };
/* iterator for handling rings in ring container */ /* iterator for handling rings in ring container */
......
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