diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_sched.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_sched.c | 111 | 
1 files changed, 97 insertions, 14 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index 118595763bba..4eca8d195ef0 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -1,6 +1,7 @@  // SPDX-License-Identifier: GPL-2.0  /* Copyright (c) 2018, Intel Corporation. */ +#include <net/devlink.h>  #include "ice_sched.h"  /** @@ -142,12 +143,14 @@ ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req,   * @pi: port information structure   * @layer: Scheduler layer of the node   * @info: Scheduler element information from firmware + * @prealloc_node: preallocated ice_sched_node struct for SW DB   *   * This function inserts a scheduler node to the SW DB.   */  int  ice_sched_add_node(struct ice_port_info *pi, u8 layer, -		   struct ice_aqc_txsched_elem_data *info) +		   struct ice_aqc_txsched_elem_data *info, +		   struct ice_sched_node *prealloc_node)  {  	struct ice_aqc_txsched_elem_data elem;  	struct ice_sched_node *parent; @@ -176,7 +179,10 @@ ice_sched_add_node(struct ice_port_info *pi, u8 layer,  	if (status)  		return status; -	node = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*node), GFP_KERNEL); +	if (prealloc_node) +		node = prealloc_node; +	else +		node = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*node), GFP_KERNEL);  	if (!node)  		return -ENOMEM;  	if (hw->max_children[layer]) { @@ -355,6 +361,9 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)  	/* leaf nodes have no children */  	if (node->children)  		devm_kfree(ice_hw_to_dev(hw), node->children); + +	kfree(node->name); +	xa_erase(&pi->sched_node_ids, node->id);  	devm_kfree(ice_hw_to_dev(hw), node);  } @@ -872,13 +881,15 @@ void ice_sched_cleanup_all(struct ice_hw *hw)   * @num_nodes: number of nodes   * @num_nodes_added: pointer to num nodes added   * @first_node_teid: if new nodes are added then return the TEID of first node + * @prealloc_nodes: preallocated nodes struct for software DB   *   * This function add nodes to HW as well as to SW DB for a given layer   */ -static int +int  ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,  		    struct ice_sched_node *parent, u8 layer, u16 num_nodes, -		    u16 *num_nodes_added, u32 *first_node_teid) +		    u16 *num_nodes_added, u32 *first_node_teid, +		    struct ice_sched_node **prealloc_nodes)  {  	struct ice_sched_node *prev, *new_node;  	struct ice_aqc_add_elem *buf; @@ -924,7 +935,11 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,  	*num_nodes_added = num_nodes;  	/* add nodes to the SW DB */  	for (i = 0; i < num_nodes; i++) { -		status = ice_sched_add_node(pi, layer, &buf->generic[i]); +		if (prealloc_nodes) +			status = ice_sched_add_node(pi, layer, &buf->generic[i], prealloc_nodes[i]); +		else +			status = ice_sched_add_node(pi, layer, &buf->generic[i], NULL); +  		if (status) {  			ice_debug(hw, ICE_DBG_SCHED, "add nodes in SW DB failed status =%d\n",  				  status); @@ -940,6 +955,22 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,  		new_node->sibling = NULL;  		new_node->tc_num = tc_node->tc_num; +		new_node->tx_weight = ICE_SCHED_DFLT_BW_WT; +		new_node->tx_share = ICE_SCHED_DFLT_BW; +		new_node->tx_max = ICE_SCHED_DFLT_BW; +		new_node->name = kzalloc(SCHED_NODE_NAME_MAX_LEN, GFP_KERNEL); +		if (!new_node->name) +			return -ENOMEM; + +		status = xa_alloc(&pi->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX), +				  GFP_KERNEL); +		if (status) { +			ice_debug(hw, ICE_DBG_SCHED, "xa_alloc failed for sched node status =%d\n", +				  status); +			break; +		} + +		snprintf(new_node->name, SCHED_NODE_NAME_MAX_LEN, "node_%u", new_node->id);  		/* add it to previous node sibling pointer */  		/* Note: siblings are not linked across branches */ @@ -1003,7 +1034,7 @@ ice_sched_add_nodes_to_hw_layer(struct ice_port_info *pi,  	}  	return ice_sched_add_elems(pi, tc_node, parent, layer, num_nodes, -				   num_nodes_added, first_node_teid); +				   num_nodes_added, first_node_teid, NULL);  }  /** @@ -1032,7 +1063,6 @@ ice_sched_add_nodes_to_layer(struct ice_port_info *pi,  	*num_nodes_added = 0;  	while (*num_nodes_added < num_nodes) {  		u16 max_child_nodes, num_added = 0; -		/* cppcheck-suppress unusedVariable */  		u32 temp;  		status = ice_sched_add_nodes_to_hw_layer(pi, tc_node, parent, @@ -1268,7 +1298,7 @@ int ice_sched_init_port(struct ice_port_info *pi)  			    ICE_AQC_ELEM_TYPE_ENTRY_POINT)  				hw->sw_entry_point_layer = j; -			status = ice_sched_add_node(pi, j, &buf[i].generic[j]); +			status = ice_sched_add_node(pi, j, &buf[i].generic[j], NULL);  			if (status)  				goto err_init_port;  		} @@ -1624,12 +1654,13 @@ ice_sched_add_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_handle,  	u32 first_node_teid;  	u16 num_added = 0;  	u8 i, qgl, vsil; -	int status;  	qgl = ice_sched_get_qgrp_layer(hw);  	vsil = ice_sched_get_vsi_layer(hw);  	parent = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);  	for (i = vsil + 1; i <= qgl; i++) { +		int status; +  		if (!parent)  			return -EIO; @@ -1725,13 +1756,14 @@ ice_sched_add_vsi_support_nodes(struct ice_port_info *pi, u16 vsi_handle,  	u32 first_node_teid;  	u16 num_added = 0;  	u8 i, vsil; -	int status;  	if (!pi)  		return -EINVAL;  	vsil = ice_sched_get_vsi_layer(pi->hw);  	for (i = pi->hw->sw_entry_point_layer; i <= vsil; i++) { +		int status; +  		status = ice_sched_add_nodes_to_layer(pi, tc_node, parent,  						      i, num_nodes[i],  						      &first_node_teid, @@ -2154,7 +2186,7 @@ ice_sched_get_free_vsi_parent(struct ice_hw *hw, struct ice_sched_node *node,   * This function removes the child from the old parent and adds it to a new   * parent   */ -static void +void  ice_sched_update_parent(struct ice_sched_node *new_parent,  			struct ice_sched_node *node)  { @@ -2188,7 +2220,7 @@ ice_sched_update_parent(struct ice_sched_node *new_parent,   *   * This function move the child nodes to a given parent.   */ -static int +int  ice_sched_move_nodes(struct ice_port_info *pi, struct ice_sched_node *parent,  		     u16 num_items, u32 *list)  { @@ -3560,7 +3592,7 @@ ice_sched_set_eir_srl_excl(struct ice_port_info *pi,   * node's RL profile ID of type CIR, EIR, or SRL, and removes old profile   * ID from local database. The caller needs to hold scheduler lock.   */ -static int +int  ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,  		      enum ice_rl_type rl_type, u32 bw, u8 layer_num)  { @@ -3597,6 +3629,57 @@ ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,  }  /** + * ice_sched_set_node_priority - set node's priority + * @pi: port information structure + * @node: tree node + * @priority: number 0-7 representing priority among siblings + * + * This function sets priority of a node among it's siblings. + */ +int +ice_sched_set_node_priority(struct ice_port_info *pi, struct ice_sched_node *node, +			    u16 priority) +{ +	struct ice_aqc_txsched_elem_data buf; +	struct ice_aqc_txsched_elem *data; + +	buf = node->info; +	data = &buf.data; + +	data->valid_sections |= ICE_AQC_ELEM_VALID_GENERIC; +	data->generic |= FIELD_PREP(ICE_AQC_ELEM_GENERIC_PRIO_M, priority); + +	return ice_sched_update_elem(pi->hw, node, &buf); +} + +/** + * ice_sched_set_node_weight - set node's weight + * @pi: port information structure + * @node: tree node + * @weight: number 1-200 representing weight for WFQ + * + * This function sets weight of the node for WFQ algorithm. + */ +int +ice_sched_set_node_weight(struct ice_port_info *pi, struct ice_sched_node *node, u16 weight) +{ +	struct ice_aqc_txsched_elem_data buf; +	struct ice_aqc_txsched_elem *data; + +	buf = node->info; +	data = &buf.data; + +	data->valid_sections = ICE_AQC_ELEM_VALID_CIR | ICE_AQC_ELEM_VALID_EIR | +			       ICE_AQC_ELEM_VALID_GENERIC; +	data->cir_bw.bw_alloc = cpu_to_le16(weight); +	data->eir_bw.bw_alloc = cpu_to_le16(weight); + +	data->generic |= FIELD_PREP(ICE_AQC_ELEM_GENERIC_SP_M, 0x0); + +	return ice_sched_update_elem(pi->hw, node, &buf); +} + +/**   * ice_sched_set_node_bw_lmt - set node's BW limit   * @pi: port information structure   * @node: tree node @@ -3606,7 +3689,7 @@ ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,   * It updates node's BW limit parameters like BW RL profile ID of type CIR,   * EIR, or SRL. The caller needs to hold scheduler lock.   */ -static int +int  ice_sched_set_node_bw_lmt(struct ice_port_info *pi, struct ice_sched_node *node,  			  enum ice_rl_type rl_type, u32 bw)  {  |