forked from mirrors/linux
		
	ice: Restore interrupt throttle settings after VSI rebuild
After each rebuild driver deallocates q_vectors, so the interrupt throttle rate (ITR) settings get lost. Create a function to save and restore ITR for each queue. If a user increases the number of queues, restore all the previous queue settings for each existing queue, and the additional queues will get the default setting. Signed-off-by: Michal Swiatkowski <michal.swiatkowski@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
		
							parent
							
								
									118e0e1002
								
							
						
					
					
						commit
						61dc79ced7
					
				
					 2 changed files with 108 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -2403,6 +2403,97 @@ int ice_vsi_release(struct ice_vsi *vsi)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector
 | 
			
		||||
 * @q_vector: pointer to q_vector which is being updated
 | 
			
		||||
 * @coalesce: pointer to array of struct with stored coalesce
 | 
			
		||||
 *
 | 
			
		||||
 * Set coalesce param in q_vector and update these parameters in HW.
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector,
 | 
			
		||||
				struct ice_coalesce_stored *coalesce)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	tx_rc->itr_setting = coalesce->itr_tx;
 | 
			
		||||
	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),
 | 
			
		||||
	     ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors
 | 
			
		||||
 * @vsi: VSI connected with q_vectors
 | 
			
		||||
 * @coalesce: array of struct with stored coalesce
 | 
			
		||||
 *
 | 
			
		||||
 * Returns array size.
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
 | 
			
		||||
			     struct ice_coalesce_stored *coalesce)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	ice_for_each_q_vector(vsi, i) {
 | 
			
		||||
		struct ice_q_vector *q_vector = vsi->q_vectors[i];
 | 
			
		||||
 | 
			
		||||
		coalesce[i].itr_tx = q_vector->tx.itr_setting;
 | 
			
		||||
		coalesce[i].itr_rx = q_vector->rx.itr_setting;
 | 
			
		||||
		coalesce[i].intrl = q_vector->intrl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vsi->num_q_vectors;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays
 | 
			
		||||
 * @vsi: VSI connected with q_vectors
 | 
			
		||||
 * @coalesce: pointer to array of struct with stored coalesce
 | 
			
		||||
 * @size: size of coalesce array
 | 
			
		||||
 *
 | 
			
		||||
 * Before this function, ice_vsi_rebuild_get_coalesce should be called to save
 | 
			
		||||
 * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce
 | 
			
		||||
 * to default value.
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
 | 
			
		||||
			     struct ice_coalesce_stored *coalesce, int size)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if ((size && !coalesce) || !vsi)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < size && i < vsi->num_q_vectors; i++)
 | 
			
		||||
		ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
 | 
			
		||||
						&coalesce[i]);
 | 
			
		||||
 | 
			
		||||
	for (; i < vsi->num_q_vectors; i++) {
 | 
			
		||||
		struct ice_coalesce_stored coalesce_dflt = {
 | 
			
		||||
			.itr_tx = ICE_DFLT_TX_ITR,
 | 
			
		||||
			.itr_rx = ICE_DFLT_RX_ITR,
 | 
			
		||||
			.intrl = 0
 | 
			
		||||
		};
 | 
			
		||||
		ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
 | 
			
		||||
						&coalesce_dflt);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ice_vsi_rebuild - Rebuild VSI after reset
 | 
			
		||||
 * @vsi: VSI to be rebuild
 | 
			
		||||
| 
						 | 
				
			
			@ -2413,6 +2504,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
 | 
			
		|||
int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
 | 
			
		||||
{
 | 
			
		||||
	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
 | 
			
		||||
	struct ice_coalesce_stored *coalesce;
 | 
			
		||||
	int prev_num_q_vectors = 0;
 | 
			
		||||
	struct ice_vf *vf = NULL;
 | 
			
		||||
	enum ice_status status;
 | 
			
		||||
	struct ice_pf *pf;
 | 
			
		||||
| 
						 | 
				
			
			@ -2425,6 +2518,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
 | 
			
		|||
	if (vsi->type == ICE_VSI_VF)
 | 
			
		||||
		vf = &pf->vf[vsi->vf_id];
 | 
			
		||||
 | 
			
		||||
	coalesce = kcalloc(vsi->num_q_vectors,
 | 
			
		||||
			   sizeof(struct ice_coalesce_stored), GFP_KERNEL);
 | 
			
		||||
	if (coalesce)
 | 
			
		||||
		prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi,
 | 
			
		||||
								  coalesce);
 | 
			
		||||
	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
 | 
			
		||||
	ice_vsi_free_q_vectors(vsi);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2537,6 +2635,9 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
 | 
			
		|||
			return ice_schedule_reset(pf, ICE_RESET_PFR);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors);
 | 
			
		||||
	kfree(coalesce);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
err_vectors:
 | 
			
		||||
| 
						 | 
				
			
			@ -2551,6 +2652,7 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
 | 
			
		|||
err_vsi:
 | 
			
		||||
	ice_vsi_clear(vsi);
 | 
			
		||||
	set_bit(__ICE_RESET_FAILED, pf->state);
 | 
			
		||||
	kfree(coalesce);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -341,6 +341,12 @@ struct ice_ring_container {
 | 
			
		|||
	u16 itr_setting;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ice_coalesce_stored {
 | 
			
		||||
	u16 itr_tx;
 | 
			
		||||
	u16 itr_rx;
 | 
			
		||||
	u8 intrl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* iterator for handling rings in ring container */
 | 
			
		||||
#define ice_for_each_ring(pos, head) \
 | 
			
		||||
	for (pos = (head).ring; pos; pos = pos->next)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue