/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2020 Intel Corporation
+ * Copyright(c) 2001-2021 Intel Corporation
*/
#include "ice_sched.h"
static void ice_sched_clear_rl_prof(struct ice_port_info *pi)
{
u16 ln;
+ struct ice_hw *hw = pi->hw;
- for (ln = 0; ln < pi->hw->num_tx_sched_layers; ln++) {
+ for (ln = 0; ln < hw->num_tx_sched_layers; ln++) {
struct ice_aqc_rl_profile_info *rl_prof_elem;
struct ice_aqc_rl_profile_info *rl_prof_tmp;
LIST_FOR_EACH_ENTRY_SAFE(rl_prof_elem, rl_prof_tmp,
- &pi->rl_prof_list[ln],
+ &hw->rl_prof_list[ln],
ice_aqc_rl_profile_info, list_entry) {
- struct ice_hw *hw = pi->hw;
enum ice_status status;
rl_prof_elem->prof_id_ref = 0;
}
/**
- * ice_sched_add_nodes_to_layer - Add nodes to a given layer
+ * ice_sched_add_nodes_to_hw_layer - Add nodes to hw layer
* @pi: port information structure
* @tc_node: pointer to TC node
* @parent: pointer to parent node
* @first_node_teid: pointer to the first node TEID
* @num_nodes_added: pointer to number of nodes added
*
- * This function add nodes to a given layer.
+ * Add nodes into specific hw layer.
*/
static enum ice_status
-ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
- struct ice_sched_node *tc_node,
- struct ice_sched_node *parent, u8 layer,
- u16 num_nodes, u32 *first_node_teid,
- u16 *num_nodes_added)
+ice_sched_add_nodes_to_hw_layer(struct ice_port_info *pi,
+ struct ice_sched_node *tc_node,
+ struct ice_sched_node *parent, u8 layer,
+ u16 num_nodes, u32 *first_node_teid,
+ u16 *num_nodes_added)
{
- u32 *first_teid_ptr = first_node_teid;
- u16 new_num_nodes, max_child_nodes;
- enum ice_status status = ICE_SUCCESS;
- struct ice_hw *hw = pi->hw;
- u16 num_added = 0;
- u32 temp;
+ u16 max_child_nodes;
*num_nodes_added = 0;
if (!num_nodes)
- return status;
+ return ICE_SUCCESS;
- if (!parent || layer < hw->sw_entry_point_layer)
+ if (!parent || layer < pi->hw->sw_entry_point_layer)
return ICE_ERR_PARAM;
/* max children per node per layer */
- max_child_nodes = hw->max_children[parent->tx_sched_layer];
+ max_child_nodes = pi->hw->max_children[parent->tx_sched_layer];
- /* current number of children + required nodes exceed max children ? */
+ /* current number of children + required nodes exceed max children */
if ((parent->num_children + num_nodes) > max_child_nodes) {
/* Fail if the parent is a TC node */
if (parent == tc_node)
return ICE_ERR_CFG;
+ return ICE_ERR_MAX_LIMIT;
+ }
+
+ return ice_sched_add_elems(pi, tc_node, parent, layer, num_nodes,
+ num_nodes_added, first_node_teid);
+}
+
+/**
+ * ice_sched_add_nodes_to_layer - Add nodes to a given layer
+ * @pi: port information structure
+ * @tc_node: pointer to TC node
+ * @parent: pointer to parent node
+ * @layer: layer number to add nodes
+ * @num_nodes: number of nodes to be added
+ * @first_node_teid: pointer to the first node TEID
+ * @num_nodes_added: pointer to number of nodes added
+ *
+ * This function add nodes to a given layer.
+ */
+static enum ice_status
+ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
+ struct ice_sched_node *tc_node,
+ struct ice_sched_node *parent, u8 layer,
+ u16 num_nodes, u32 *first_node_teid,
+ u16 *num_nodes_added)
+{
+ u32 *first_teid_ptr = first_node_teid;
+ u16 new_num_nodes = num_nodes;
+ enum ice_status status = ICE_SUCCESS;
+ *num_nodes_added = 0;
+ while (*num_nodes_added < num_nodes) {
+ u16 max_child_nodes, num_added = 0;
+ u32 temp;
+
+ status = ice_sched_add_nodes_to_hw_layer(pi, tc_node, parent,
+ layer, new_num_nodes,
+ first_teid_ptr,
+ &num_added);
+ if (status == ICE_SUCCESS)
+ *num_nodes_added += num_added;
+ /* added more nodes than requested ? */
+ if (*num_nodes_added > num_nodes) {
+ ice_debug(pi->hw, ICE_DBG_SCHED, "added extra nodes %d %d\n", num_nodes,
+ *num_nodes_added);
+ status = ICE_ERR_CFG;
+ break;
+ }
+ /* break if all the nodes are added successfully */
+ if (status == ICE_SUCCESS && (*num_nodes_added == num_nodes))
+ break;
+ /* break if the error is not max limit */
+ if (status != ICE_SUCCESS && status != ICE_ERR_MAX_LIMIT)
+ break;
+ /* Exceeded the max children */
+ max_child_nodes = pi->hw->max_children[parent->tx_sched_layer];
/* utilize all the spaces if the parent is not full */
if (parent->num_children < max_child_nodes) {
new_num_nodes = max_child_nodes - parent->num_children;
- /* this recursion is intentional, and wouldn't
- * go more than 2 calls
+ } else {
+ /* This parent is full, try the next sibling */
+ parent = parent->sibling;
+ /* Don't modify the first node TEID memory if the
+ * first node was added already in the above call.
+ * Instead send some temp memory for all other
+ * recursive calls.
*/
- status = ice_sched_add_nodes_to_layer(pi, tc_node,
- parent, layer,
- new_num_nodes,
- first_node_teid,
- &num_added);
- if (status != ICE_SUCCESS)
- return status;
+ if (num_added)
+ first_teid_ptr = &temp;
- *num_nodes_added += num_added;
+ new_num_nodes = num_nodes - *num_nodes_added;
}
- /* Don't modify the first node TEID memory if the first node was
- * added already in the above call. Instead send some temp
- * memory for all other recursive calls.
- */
- if (num_added)
- first_teid_ptr = &temp;
-
- new_num_nodes = num_nodes - num_added;
-
- /* This parent is full, try the next sibling */
- parent = parent->sibling;
-
- /* this recursion is intentional, for 1024 queues
- * per VSI, it goes max of 16 iterations.
- * 1024 / 8 = 128 layer 8 nodes
- * 128 /8 = 16 (add 8 nodes per iteration)
- */
- status = ice_sched_add_nodes_to_layer(pi, tc_node, parent,
- layer, new_num_nodes,
- first_teid_ptr,
- &num_added);
- *num_nodes_added += num_added;
- return status;
}
-
- status = ice_sched_add_elems(pi, tc_node, parent, layer, num_nodes,
- num_nodes_added, first_node_teid);
return status;
}
pi->port_state = ICE_SCHED_PORT_STATE_READY;
ice_init_lock(&pi->sched_lock);
for (i = 0; i < ICE_AQC_TOPO_MAX_LEVEL_NUM; i++)
- INIT_LIST_HEAD(&pi->rl_prof_list[i]);
+ INIT_LIST_HEAD(&hw->rl_prof_list[i]);
err_init_port:
if (status && pi->root) {
ice_memdup(hw, buf->layer_props,
(hw->num_tx_sched_layers *
sizeof(*hw->layer_info)),
- ICE_DMA_TO_DMA);
+ ICE_NONDMA_TO_NONDMA);
if (!hw->layer_info) {
status = ICE_ERR_NO_MEMORY;
goto sched_query_out;
}
/**
- * ice_sched_rm_agg_vsi_entry - remove aggregator related VSI info entry
+ * ice_sched_rm_agg_vsi_info - remove aggregator related VSI info entry
* @pi: port information structure
* @vsi_handle: software VSI handle
*
/* Create new entry for new aggregator ID */
agg_info = (struct ice_sched_agg_info *)
ice_malloc(hw, sizeof(*agg_info));
- if (!agg_info) {
- status = ICE_ERR_NO_MEMORY;
- goto exit_reg_agg;
- }
+ if (!agg_info)
+ return ICE_ERR_NO_MEMORY;
+
agg_info->agg_id = agg_id;
agg_info->agg_type = agg_type;
agg_info->tc_bitmap[0] = 0;
/* Save aggregator node's TC information */
ice_set_bit(tc, agg_info->tc_bitmap);
}
-exit_reg_agg:
+
return status;
}
ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,
u16 vsi_handle, ice_bitmap_t *tc_bitmap)
{
- struct ice_sched_agg_vsi_info *agg_vsi_info;
- struct ice_sched_agg_info *agg_info;
+ struct ice_sched_agg_vsi_info *agg_vsi_info, *old_agg_vsi_info = NULL;
+ struct ice_sched_agg_info *agg_info, *old_agg_info;
enum ice_status status = ICE_SUCCESS;
struct ice_hw *hw = pi->hw;
u8 tc;
agg_info = ice_get_agg_info(hw, agg_id);
if (!agg_info)
return ICE_ERR_PARAM;
+ /* If the vsi is already part of another aggregator then update
+ * its vsi info list
+ */
+ old_agg_info = ice_get_vsi_agg_info(hw, vsi_handle);
+ if (old_agg_info && old_agg_info != agg_info) {
+ struct ice_sched_agg_vsi_info *vtmp;
+
+ LIST_FOR_EACH_ENTRY_SAFE(old_agg_vsi_info, vtmp,
+ &old_agg_info->agg_vsi_list,
+ ice_sched_agg_vsi_info, list_entry)
+ if (old_agg_vsi_info->vsi_handle == vsi_handle)
+ break;
+ }
+
/* check if entry already exist */
agg_vsi_info = ice_get_agg_vsi_info(agg_info, vsi_handle);
if (!agg_vsi_info) {
if (status)
break;
- if (agg_id != ICE_DFLT_AGG_ID)
- ice_set_bit(tc, agg_vsi_info->tc_bitmap);
- else
- ice_clear_bit(tc, agg_vsi_info->tc_bitmap);
+ ice_set_bit(tc, agg_vsi_info->tc_bitmap);
+ if (old_agg_vsi_info)
+ ice_clear_bit(tc, old_agg_vsi_info->tc_bitmap);
}
- /* If VSI moved back to default aggregator, delete agg_vsi_info. */
- if (!ice_is_any_bit_set(agg_vsi_info->tc_bitmap,
- ICE_MAX_TRAFFIC_CLASS)) {
- LIST_DEL(&agg_vsi_info->list_entry);
- ice_free(hw, agg_vsi_info);
+ if (old_agg_vsi_info && !old_agg_vsi_info->tc_bitmap[0]) {
+ LIST_DEL(&old_agg_vsi_info->list_entry);
+ ice_free(pi->hw, old_agg_vsi_info);
}
return status;
}
/**
* ice_sched_rm_unused_rl_prof - remove unused RL profile
- * @pi: port information structure
+ * @hw: pointer to the hardware structure
*
* This function removes unused rate limit profiles from the HW and
* SW DB. The caller needs to hold scheduler lock.
*/
-static void ice_sched_rm_unused_rl_prof(struct ice_port_info *pi)
+static void ice_sched_rm_unused_rl_prof(struct ice_hw *hw)
{
u16 ln;
- for (ln = 0; ln < pi->hw->num_tx_sched_layers; ln++) {
+ for (ln = 0; ln < hw->num_tx_sched_layers; ln++) {
struct ice_aqc_rl_profile_info *rl_prof_elem;
struct ice_aqc_rl_profile_info *rl_prof_tmp;
LIST_FOR_EACH_ENTRY_SAFE(rl_prof_elem, rl_prof_tmp,
- &pi->rl_prof_list[ln],
+ &hw->rl_prof_list[ln],
ice_aqc_rl_profile_info, list_entry) {
- if (!ice_sched_del_rl_profile(pi->hw, rl_prof_elem))
- ice_debug(pi->hw, ICE_DBG_SCHED, "Removed rl profile\n");
+ if (!ice_sched_del_rl_profile(hw, rl_prof_elem))
+ ice_debug(hw, ICE_DBG_SCHED, "Removed rl profile\n");
}
}
}
u16 num_elems = 1;
buf = *info;
+ /* For TC nodes, CIR config is not supported */
+ if (node->info.data.elem_type == ICE_AQC_ELEM_TYPE_TC)
+ buf.data.valid_sections &= ~ICE_AQC_ELEM_VALID_CIR;
/* Parent TEID is reserved field in this aq call */
buf.parent_teid = 0;
/* Element type is reserved field in this aq call */
ice_free(pi->hw, agg_info);
/* Remove unused RL profile IDs from HW and SW DB */
- ice_sched_rm_unused_rl_prof(pi);
+ ice_sched_rm_unused_rl_prof(pi->hw);
exit_ice_rm_agg_cfg:
ice_release_lock(&pi->sched_lock);
ice_clear_bit(ICE_BW_TYPE_EIR, bw_t_info->bw_t_bitmap);
bw_t_info->eir_bw.bw = 0;
} else {
- /* EIR BW and Shared BW profiles are mutually exclusive and
- * hence only one of them may be set for any given element.
- * First clear earlier saved shared BW information.
- */
- ice_clear_bit(ICE_BW_TYPE_SHARED, bw_t_info->bw_t_bitmap);
- bw_t_info->shared_bw = 0;
/* save EIR BW information */
ice_set_bit(ICE_BW_TYPE_EIR, bw_t_info->bw_t_bitmap);
bw_t_info->eir_bw.bw = bw;
ice_clear_bit(ICE_BW_TYPE_SHARED, bw_t_info->bw_t_bitmap);
bw_t_info->shared_bw = 0;
} else {
- /* EIR BW and Shared BW profiles are mutually exclusive and
- * hence only one of them may be set for any given element.
- * First clear earlier saved EIR BW information.
- */
- ice_clear_bit(ICE_BW_TYPE_EIR, bw_t_info->bw_t_bitmap);
- bw_t_info->eir_bw.bw = 0;
/* save shared BW information */
ice_set_bit(ICE_BW_TYPE_SHARED, bw_t_info->bw_t_bitmap);
bw_t_info->shared_bw = bw;
}
/**
- * ice_cfg_dflt_vsi_bw_lmt_per_tc - configure default VSI BW limit per TC
+ * ice_cfg_vsi_bw_dflt_lmt_per_tc - configure default VSI BW limit per TC
* @pi: port information structure
* @vsi_handle: software VSI handle
* @tc: traffic class
* ice_cfg_vsi_bw_shared_lmt - configure VSI BW shared limit
* @pi: port information structure
* @vsi_handle: software VSI handle
- * @bw: bandwidth in Kbps
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
*
- * This function Configures shared rate limiter(SRL) of all VSI type nodes
- * across all traffic classes for VSI matching handle.
+ * Configure shared rate limiter(SRL) of all VSI type nodes across all traffic
+ * classes for VSI matching handle.
*/
enum ice_status
-ice_cfg_vsi_bw_shared_lmt(struct ice_port_info *pi, u16 vsi_handle, u32 bw)
+ice_cfg_vsi_bw_shared_lmt(struct ice_port_info *pi, u16 vsi_handle, u32 min_bw,
+ u32 max_bw, u32 shared_bw)
{
- return ice_sched_set_vsi_bw_shared_lmt(pi, vsi_handle, bw);
+ return ice_sched_set_vsi_bw_shared_lmt(pi, vsi_handle, min_bw, max_bw,
+ shared_bw);
}
/**
ice_cfg_vsi_bw_no_shared_lmt(struct ice_port_info *pi, u16 vsi_handle)
{
return ice_sched_set_vsi_bw_shared_lmt(pi, vsi_handle,
+ ICE_SCHED_DFLT_BW,
+ ICE_SCHED_DFLT_BW,
ICE_SCHED_DFLT_BW);
}
* ice_cfg_agg_bw_shared_lmt - configure aggregator BW shared limit
* @pi: port information structure
* @agg_id: aggregator ID
- * @bw: bandwidth in Kbps
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
*
* This function configures the shared rate limiter(SRL) of all aggregator type
* nodes across all traffic classes for aggregator matching agg_id.
*/
enum ice_status
-ice_cfg_agg_bw_shared_lmt(struct ice_port_info *pi, u32 agg_id, u32 bw)
+ice_cfg_agg_bw_shared_lmt(struct ice_port_info *pi, u32 agg_id, u32 min_bw,
+ u32 max_bw, u32 shared_bw)
{
- return ice_sched_set_agg_bw_shared_lmt(pi, agg_id, bw);
+ return ice_sched_set_agg_bw_shared_lmt(pi, agg_id, min_bw, max_bw,
+ shared_bw);
}
/**
enum ice_status
ice_cfg_agg_bw_no_shared_lmt(struct ice_port_info *pi, u32 agg_id)
{
- return ice_sched_set_agg_bw_shared_lmt(pi, agg_id, ICE_SCHED_DFLT_BW);
+ return ice_sched_set_agg_bw_shared_lmt(pi, agg_id, ICE_SCHED_DFLT_BW,
+ ICE_SCHED_DFLT_BW,
+ ICE_SCHED_DFLT_BW);
+}
+
+/**
+ * ice_cfg_agg_bw_shared_lmt_per_tc - config aggregator BW shared limit per tc
+ * @pi: port information structure
+ * @agg_id: aggregator ID
+ * @tc: traffic class
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
+ *
+ * This function configures the shared rate limiter(SRL) of all aggregator type
+ * nodes across all traffic classes for aggregator matching agg_id.
+ */
+enum ice_status
+ice_cfg_agg_bw_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc,
+ u32 min_bw, u32 max_bw, u32 shared_bw)
+{
+ return ice_sched_set_agg_bw_shared_lmt_per_tc(pi, agg_id, tc, min_bw,
+ max_bw, shared_bw);
+}
+
+/**
+ * ice_cfg_agg_bw_no_shared_lmt_per_tc - cfg aggregator BW shared limit per tc
+ * @pi: port information structure
+ * @agg_id: aggregator ID
+ * @tc: traffic class
+ *
+ * This function configures the shared rate limiter(SRL) of all aggregator type
+ * nodes across all traffic classes for aggregator matching agg_id.
+ */
+enum ice_status
+ice_cfg_agg_bw_no_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc)
+{
+ return ice_sched_set_agg_bw_shared_lmt_per_tc(pi, agg_id, tc,
+ ICE_SCHED_DFLT_BW,
+ ICE_SCHED_DFLT_BW,
+ ICE_SCHED_DFLT_BW);
}
/**
- * ice_config_vsi_queue_priority - config VSI queue priority of node
+ * ice_cfg_vsi_q_priority - config VSI queue priority of node
* @pi: port information structure
* @num_qs: number of VSI queues
* @q_ids: queue IDs array
return status;
}
+/**
+ * ice_sched_cfg_sibl_node_prio_lock - config priority of node
+ * @pi: port information structure
+ * @node: sched node to configure
+ * @priority: sibling priority
+ *
+ * This function configures node element's sibling priority only.
+ */
+enum ice_status
+ice_sched_cfg_sibl_node_prio_lock(struct ice_port_info *pi,
+ struct ice_sched_node *node,
+ u8 priority)
+{
+ enum ice_status status;
+
+ ice_acquire_lock(&pi->sched_lock);
+ status = ice_sched_cfg_sibl_node_prio(pi, node, priority);
+ ice_release_lock(&pi->sched_lock);
+
+ return status;
+}
+
+/**
+ * ice_sched_save_q_bw_alloc - save queue node's BW allocation information
+ * @q_ctx: queue context structure
+ * @rl_type: rate limit type min, max, or shared
+ * @bw_alloc: BW weight/allocation
+ *
+ * Save BW information of queue type node for post replay use.
+ */
+static enum ice_status
+ice_sched_save_q_bw_alloc(struct ice_q_ctx *q_ctx, enum ice_rl_type rl_type,
+ u32 bw_alloc)
+{
+ switch (rl_type) {
+ case ICE_MIN_BW:
+ ice_set_clear_cir_bw_alloc(&q_ctx->bw_t_info, bw_alloc);
+ break;
+ case ICE_MAX_BW:
+ ice_set_clear_eir_bw_alloc(&q_ctx->bw_t_info, bw_alloc);
+ break;
+ default:
+ return ICE_ERR_PARAM;
+ }
+ return ICE_SUCCESS;
+}
+
+/**
+ * ice_cfg_q_bw_alloc - configure queue BW weight/alloc params
+ * @pi: port information structure
+ * @vsi_handle: sw VSI handle
+ * @tc: traffic class
+ * @q_handle: software queue handle
+ * @rl_type: min, max, or shared
+ * @bw_alloc: BW weight/allocation
+ *
+ * This function configures BW allocation of queue scheduling node.
+ */
+enum ice_status
+ice_cfg_q_bw_alloc(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
+ u16 q_handle, enum ice_rl_type rl_type, u32 bw_alloc)
+{
+ enum ice_status status = ICE_ERR_PARAM;
+ struct ice_sched_node *node;
+ struct ice_q_ctx *q_ctx;
+
+ ice_acquire_lock(&pi->sched_lock);
+ q_ctx = ice_get_lan_q_ctx(pi->hw, vsi_handle, tc, q_handle);
+ if (!q_ctx)
+ goto exit_q_bw_alloc;
+
+ node = ice_sched_find_node_by_teid(pi->root, q_ctx->q_teid);
+ if (!node) {
+ ice_debug(pi->hw, ICE_DBG_SCHED, "Wrong q_teid\n");
+ goto exit_q_bw_alloc;
+ }
+
+ status = ice_sched_cfg_node_bw_alloc(pi->hw, node, rl_type, bw_alloc);
+ if (!status)
+ status = ice_sched_save_q_bw_alloc(q_ctx, rl_type, bw_alloc);
+
+exit_q_bw_alloc:
+ ice_release_lock(&pi->sched_lock);
+ return status;
+}
+
/**
* ice_cfg_agg_vsi_priority_per_tc - config aggregator's VSI priority per TC
* @pi: port information structure
LIST_FOR_EACH_ENTRY(agg_vsi_info, &agg_info->agg_vsi_list,
ice_sched_agg_vsi_info, list_entry)
if (agg_vsi_info->vsi_handle == vsi_handle) {
- /* cppcheck-suppress unreadVariable */
vsi_handle_valid = true;
break;
}
/**
* ice_sched_add_rl_profile - add RL profile
- * @pi: port information structure
+ * @hw: pointer to the hardware structure
* @rl_type: type of rate limit BW - min, max, or shared
* @bw: bandwidth in Kbps - Kilo bits per sec
* @layer_num: specifies in which layer to create profile
* The caller needs to hold the scheduler lock.
*/
static struct ice_aqc_rl_profile_info *
-ice_sched_add_rl_profile(struct ice_port_info *pi,
- enum ice_rl_type rl_type, u32 bw, u8 layer_num)
+ice_sched_add_rl_profile(struct ice_hw *hw, enum ice_rl_type rl_type,
+ u32 bw, u8 layer_num)
{
struct ice_aqc_rl_profile_info *rl_prof_elem;
u16 profiles_added = 0, num_profiles = 1;
struct ice_aqc_rl_profile_elem *buf;
enum ice_status status;
- struct ice_hw *hw;
u8 profile_type;
if (layer_num >= ICE_AQC_TOPO_MAX_LEVEL_NUM)
return NULL;
}
- if (!pi)
+ if (!hw)
return NULL;
- hw = pi->hw;
- LIST_FOR_EACH_ENTRY(rl_prof_elem, &pi->rl_prof_list[layer_num],
+ LIST_FOR_EACH_ENTRY(rl_prof_elem, &hw->rl_prof_list[layer_num],
ice_aqc_rl_profile_info, list_entry)
if ((rl_prof_elem->profile.flags & ICE_AQC_RL_PROFILE_TYPE_M) ==
profile_type && rl_prof_elem->bw == bw)
/* Good entry - add in the list */
rl_prof_elem->prof_id_ref = 0;
- LIST_ADD(&rl_prof_elem->list_entry, &pi->rl_prof_list[layer_num]);
+ LIST_ADD(&rl_prof_elem->list_entry, &hw->rl_prof_list[layer_num]);
return rl_prof_elem;
exit_add_rl_prof:
data->cir_bw.bw_profile_idx = CPU_TO_LE16(rl_prof_id);
break;
case ICE_MAX_BW:
- /* EIR BW and Shared BW profiles are mutually exclusive and
- * hence only one of them may be set for any given element
- */
- if (data->valid_sections & ICE_AQC_ELEM_VALID_SHARED)
- return ICE_ERR_CFG;
data->valid_sections |= ICE_AQC_ELEM_VALID_EIR;
data->eir_bw.bw_profile_idx = CPU_TO_LE16(rl_prof_id);
break;
case ICE_SHARED_BW:
- /* Check for removing shared BW */
- if (rl_prof_id == ICE_SCHED_NO_SHARED_RL_PROF_ID) {
- /* remove shared profile */
- data->valid_sections &= ~ICE_AQC_ELEM_VALID_SHARED;
- data->srl_id = 0; /* clear SRL field */
-
- /* enable back EIR to default profile */
- data->valid_sections |= ICE_AQC_ELEM_VALID_EIR;
- data->eir_bw.bw_profile_idx =
- CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
- break;
- }
- /* EIR BW and Shared BW profiles are mutually exclusive and
- * hence only one of them may be set for any given element
- */
- if ((data->valid_sections & ICE_AQC_ELEM_VALID_EIR) &&
- (LE16_TO_CPU(data->eir_bw.bw_profile_idx) !=
- ICE_SCHED_DFLT_RL_PROF_ID))
- return ICE_ERR_CFG;
- /* EIR BW is set to default, disable it */
- data->valid_sections &= ~ICE_AQC_ELEM_VALID_EIR;
- /* Okay to enable shared BW now */
data->valid_sections |= ICE_AQC_ELEM_VALID_SHARED;
data->srl_id = CPU_TO_LE16(rl_prof_id);
break;
/**
* ice_sched_rm_rl_profile - remove RL profile ID
- * @pi: port information structure
+ * @hw: pointer to the hardware structure
* @layer_num: layer number where profiles are saved
* @profile_type: profile type like EIR, CIR, or SRL
* @profile_id: profile ID to remove
* scheduler lock.
*/
static enum ice_status
-ice_sched_rm_rl_profile(struct ice_port_info *pi, u8 layer_num, u8 profile_type,
+ice_sched_rm_rl_profile(struct ice_hw *hw, u8 layer_num, u8 profile_type,
u16 profile_id)
{
struct ice_aqc_rl_profile_info *rl_prof_elem;
if (layer_num >= ICE_AQC_TOPO_MAX_LEVEL_NUM)
return ICE_ERR_PARAM;
/* Check the existing list for RL profile */
- LIST_FOR_EACH_ENTRY(rl_prof_elem, &pi->rl_prof_list[layer_num],
+ LIST_FOR_EACH_ENTRY(rl_prof_elem, &hw->rl_prof_list[layer_num],
ice_aqc_rl_profile_info, list_entry)
if ((rl_prof_elem->profile.flags & ICE_AQC_RL_PROFILE_TYPE_M) ==
profile_type &&
rl_prof_elem->prof_id_ref--;
/* Remove old profile ID from database */
- status = ice_sched_del_rl_profile(pi->hw, rl_prof_elem);
+ status = ice_sched_del_rl_profile(hw, rl_prof_elem);
if (status && status != ICE_ERR_IN_USE)
- ice_debug(pi->hw, ICE_DBG_SCHED, "Remove rl profile failed\n");
+ ice_debug(hw, ICE_DBG_SCHED, "Remove rl profile failed\n");
break;
}
if (status == ICE_ERR_IN_USE)
old_id == ICE_SCHED_INVAL_PROF_ID)
return ICE_SUCCESS;
- return ice_sched_rm_rl_profile(pi, layer_num, profile_type, old_id);
-}
-
-/**
- * ice_sched_set_eir_srl_excl - set EIR/SRL exclusiveness
- * @pi: port information structure
- * @node: pointer to node structure
- * @layer_num: layer number where rate limit profiles are saved
- * @rl_type: rate limit type min, max, or shared
- * @bw: bandwidth value
- *
- * This function prepares node element's bandwidth to SRL or EIR exclusively.
- * EIR BW and Shared BW profiles are mutually exclusive and hence only one of
- * them may be set for any given element. This function needs to be called
- * with the scheduler lock held.
- */
-static enum ice_status
-ice_sched_set_eir_srl_excl(struct ice_port_info *pi,
- struct ice_sched_node *node,
- u8 layer_num, enum ice_rl_type rl_type, u32 bw)
-{
- if (rl_type == ICE_SHARED_BW) {
- /* SRL node passed in this case, it may be different node */
- if (bw == ICE_SCHED_DFLT_BW)
- /* SRL being removed, ice_sched_cfg_node_bw_lmt()
- * enables EIR to default. EIR is not set in this
- * case, so no additional action is required.
- */
- return ICE_SUCCESS;
-
- /* SRL being configured, set EIR to default here.
- * ice_sched_cfg_node_bw_lmt() disables EIR when it
- * configures SRL
- */
- return ice_sched_set_node_bw_dflt(pi, node, ICE_MAX_BW,
- layer_num);
- } else if (rl_type == ICE_MAX_BW &&
- node->info.data.valid_sections & ICE_AQC_ELEM_VALID_SHARED) {
- /* Remove Shared profile. Set default shared BW call
- * removes shared profile for a node.
- */
- return ice_sched_set_node_bw_dflt(pi, node,
- ICE_SHARED_BW,
- layer_num);
- }
- return ICE_SUCCESS;
+ return ice_sched_rm_rl_profile(hw, layer_num, profile_type, old_id);
}
/**
struct ice_hw *hw = pi->hw;
u16 old_id, rl_prof_id;
- rl_prof_info = ice_sched_add_rl_profile(pi, rl_type, bw, layer_num);
+ rl_prof_info = ice_sched_add_rl_profile(hw, rl_type, bw, layer_num);
if (!rl_prof_info)
return status;
old_id == ICE_SCHED_INVAL_PROF_ID || old_id == rl_prof_id)
return ICE_SUCCESS;
- return ice_sched_rm_rl_profile(pi, layer_num,
+ return ice_sched_rm_rl_profile(hw, layer_num,
rl_prof_info->profile.flags &
ICE_AQC_RL_PROFILE_TYPE_M, old_id);
}
*
* 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.
+ *
+ * NOTE: Caller provides the correct SRL node in case of shared profile
+ * settings.
*/
static enum ice_status
ice_sched_set_node_bw_lmt(struct ice_port_info *pi, struct ice_sched_node *node,
enum ice_rl_type rl_type, u32 bw)
{
- struct ice_sched_node *cfg_node = node;
- enum ice_status status;
-
struct ice_hw *hw;
u8 layer_num;
return ICE_ERR_PARAM;
hw = pi->hw;
/* Remove unused RL profile IDs from HW and SW DB */
- ice_sched_rm_unused_rl_prof(pi);
+ ice_sched_rm_unused_rl_prof(hw);
+
layer_num = ice_sched_get_rl_prof_layer(pi, rl_type,
node->tx_sched_layer);
if (layer_num >= hw->num_tx_sched_layers)
return ICE_ERR_PARAM;
- if (rl_type == ICE_SHARED_BW) {
- /* SRL node may be different */
- cfg_node = ice_sched_get_srl_node(node, layer_num);
- if (!cfg_node)
- return ICE_ERR_CFG;
- }
- /* EIR BW and Shared BW profiles are mutually exclusive and
- * hence only one of them may be set for any given element
- */
- status = ice_sched_set_eir_srl_excl(pi, cfg_node, layer_num, rl_type,
- bw);
- if (status)
- return status;
if (bw == ICE_SCHED_DFLT_BW)
- return ice_sched_set_node_bw_dflt(pi, cfg_node, rl_type,
- layer_num);
- return ice_sched_set_node_bw(pi, cfg_node, rl_type, bw, layer_num);
+ return ice_sched_set_node_bw_dflt(pi, node, rl_type, layer_num);
+ return ice_sched_set_node_bw(pi, node, rl_type, bw, layer_num);
}
/**
case ICE_AGG_TYPE_Q:
/* The current implementation allows single queue to modify */
- node = ice_sched_get_node(pi, id);
+ node = ice_sched_find_node_by_teid(pi->root, id);
break;
case ICE_AGG_TYPE_QG:
/* The current implementation allows single qg to modify */
- child_node = ice_sched_get_node(pi, id);
+ child_node = ice_sched_find_node_by_teid(pi->root, id);
if (!child_node)
break;
node = child_node->parent;
return ICE_SUCCESS;
}
+/**
+ * ice_sched_set_save_vsi_srl_node_bw - set VSI shared limit values
+ * @pi: port information structure
+ * @vsi_handle: software VSI handle
+ * @tc: traffic class
+ * @srl_node: sched node to configure
+ * @rl_type: rate limit type minimum, maximum, or shared
+ * @bw: minimum, maximum, or shared bandwidth in Kbps
+ *
+ * Configure shared rate limiter(SRL) of VSI type nodes across given traffic
+ * class, and saves those value for later use for replaying purposes. The
+ * caller holds the scheduler lock.
+ */
+static enum ice_status
+ice_sched_set_save_vsi_srl_node_bw(struct ice_port_info *pi, u16 vsi_handle,
+ u8 tc, struct ice_sched_node *srl_node,
+ enum ice_rl_type rl_type, u32 bw)
+{
+ enum ice_status status;
+
+ if (bw == ICE_SCHED_DFLT_BW) {
+ status = ice_sched_set_node_bw_dflt_lmt(pi, srl_node, rl_type);
+ } else {
+ status = ice_sched_set_node_bw_lmt(pi, srl_node, rl_type, bw);
+ if (status)
+ return status;
+ status = ice_sched_save_vsi_bw(pi, vsi_handle, tc, rl_type, bw);
+ }
+ return status;
+}
+
+/**
+ * ice_sched_set_vsi_node_srl_per_tc - set VSI node BW shared limit for tc
+ * @pi: port information structure
+ * @vsi_handle: software VSI handle
+ * @tc: traffic class
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
+ *
+ * Configure shared rate limiter(SRL) of VSI type nodes across requested
+ * traffic class for VSI matching handle. When BW value of ICE_SCHED_DFLT_BW
+ * is passed, it removes the corresponding bw from the node. The caller
+ * holds scheduler lock.
+ */
+static enum ice_status
+ice_sched_set_vsi_node_srl_per_tc(struct ice_port_info *pi, u16 vsi_handle,
+ u8 tc, u32 min_bw, u32 max_bw, u32 shared_bw)
+{
+ struct ice_sched_node *tc_node, *vsi_node, *cfg_node;
+ enum ice_status status;
+ u8 layer_num;
+
+ tc_node = ice_sched_get_tc_node(pi, tc);
+ if (!tc_node)
+ return ICE_ERR_CFG;
+
+ vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
+ if (!vsi_node)
+ return ICE_ERR_CFG;
+
+ layer_num = ice_sched_get_rl_prof_layer(pi, ICE_SHARED_BW,
+ vsi_node->tx_sched_layer);
+ if (layer_num >= pi->hw->num_tx_sched_layers)
+ return ICE_ERR_PARAM;
+
+ /* SRL node may be different */
+ cfg_node = ice_sched_get_srl_node(vsi_node, layer_num);
+ if (!cfg_node)
+ return ICE_ERR_CFG;
+
+ status = ice_sched_set_save_vsi_srl_node_bw(pi, vsi_handle, tc,
+ cfg_node, ICE_MIN_BW,
+ min_bw);
+ if (status)
+ return status;
+
+ status = ice_sched_set_save_vsi_srl_node_bw(pi, vsi_handle, tc,
+ cfg_node, ICE_MAX_BW,
+ max_bw);
+ if (status)
+ return status;
+
+ return ice_sched_set_save_vsi_srl_node_bw(pi, vsi_handle, tc, cfg_node,
+ ICE_SHARED_BW, shared_bw);
+}
+
/**
* ice_sched_set_vsi_bw_shared_lmt - set VSI BW shared limit
* @pi: port information structure
* @vsi_handle: software VSI handle
- * @bw: bandwidth in Kbps
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
*
- * This function Configures shared rate limiter(SRL) of all VSI type nodes
- * across all traffic classes for VSI matching handle. When BW value of
- * ICE_SCHED_DFLT_BW is passed, it removes the SRL from the node.
+ * Configure shared rate limiter(SRL) of all VSI type nodes across all traffic
+ * classes for VSI matching handle. When BW value of ICE_SCHED_DFLT_BW is
+ * passed, it removes those value(s) from the node.
*/
enum ice_status
ice_sched_set_vsi_bw_shared_lmt(struct ice_port_info *pi, u16 vsi_handle,
- u32 bw)
+ u32 min_bw, u32 max_bw, u32 shared_bw)
{
enum ice_status status = ICE_SUCCESS;
u8 tc;
/* Return success if no nodes are present across TC */
ice_for_each_traffic_class(tc) {
struct ice_sched_node *tc_node, *vsi_node;
- enum ice_rl_type rl_type = ICE_SHARED_BW;
tc_node = ice_sched_get_tc_node(pi, tc);
if (!tc_node)
if (!vsi_node)
continue;
- if (bw == ICE_SCHED_DFLT_BW)
- /* It removes existing SRL from the node */
- status = ice_sched_set_node_bw_dflt_lmt(pi, vsi_node,
- rl_type);
- else
- status = ice_sched_set_node_bw_lmt(pi, vsi_node,
- rl_type, bw);
- if (status)
- break;
- status = ice_sched_save_vsi_bw(pi, vsi_handle, tc, rl_type, bw);
+ status = ice_sched_set_vsi_node_srl_per_tc(pi, vsi_handle, tc,
+ min_bw, max_bw,
+ shared_bw);
if (status)
break;
}
}
/**
- * ice_sched_set_agg_bw_shared_lmt - set aggregator BW shared limit
+ * ice_sched_validate_agg_id - Validate aggregator id
* @pi: port information structure
* @agg_id: aggregator ID
- * @bw: bandwidth in Kbps
*
- * This function configures the shared rate limiter(SRL) of all aggregator type
- * nodes across all traffic classes for aggregator matching agg_id. When
- * BW value of ICE_SCHED_DFLT_BW is passed, it removes SRL from the
- * node(s).
+ * This function validates aggregator id. Caller holds the scheduler lock.
*/
-enum ice_status
-ice_sched_set_agg_bw_shared_lmt(struct ice_port_info *pi, u32 agg_id, u32 bw)
+static enum ice_status
+ice_sched_validate_agg_id(struct ice_port_info *pi, u32 agg_id)
{
struct ice_sched_agg_info *agg_info;
struct ice_sched_agg_info *tmp;
bool agg_id_present = false;
- enum ice_status status = ICE_SUCCESS;
- u8 tc;
-
- if (!pi)
- return ICE_ERR_PARAM;
+ enum ice_status status;
- ice_acquire_lock(&pi->sched_lock);
status = ice_sched_validate_agg_srl_node(pi, agg_id);
if (status)
- goto exit_agg_bw_shared_lmt;
+ return status;
LIST_FOR_EACH_ENTRY_SAFE(agg_info, tmp, &pi->hw->agg_list,
ice_sched_agg_info, list_entry)
break;
}
- if (!agg_id_present) {
- status = ICE_ERR_PARAM;
- goto exit_agg_bw_shared_lmt;
+ if (!agg_id_present)
+ return ICE_ERR_PARAM;
+
+ return ICE_SUCCESS;
+}
+
+/**
+ * ice_sched_set_save_agg_srl_node_bw - set aggregator shared limit values
+ * @pi: port information structure
+ * @agg_id: aggregator ID
+ * @tc: traffic class
+ * @srl_node: sched node to configure
+ * @rl_type: rate limit type minimum, maximum, or shared
+ * @bw: minimum, maximum, or shared bandwidth in Kbps
+ *
+ * Configure shared rate limiter(SRL) of aggregator type nodes across
+ * requested traffic class, and saves those value for later use for
+ * replaying purposes. The caller holds the scheduler lock.
+ */
+static enum ice_status
+ice_sched_set_save_agg_srl_node_bw(struct ice_port_info *pi, u32 agg_id, u8 tc,
+ struct ice_sched_node *srl_node,
+ enum ice_rl_type rl_type, u32 bw)
+{
+ enum ice_status status;
+
+ if (bw == ICE_SCHED_DFLT_BW) {
+ status = ice_sched_set_node_bw_dflt_lmt(pi, srl_node, rl_type);
+ } else {
+ status = ice_sched_set_node_bw_lmt(pi, srl_node, rl_type, bw);
+ if (status)
+ return status;
+ status = ice_sched_save_agg_bw(pi, agg_id, tc, rl_type, bw);
}
+ return status;
+}
+
+/**
+ * ice_sched_set_agg_node_srl_per_tc - set aggregator SRL per tc
+ * @pi: port information structure
+ * @agg_id: aggregator ID
+ * @tc: traffic class
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
+ *
+ * This function configures the shared rate limiter(SRL) of aggregator type
+ * node for a given traffic class for aggregator matching agg_id. When BW
+ * value of ICE_SCHED_DFLT_BW is passed, it removes SRL from the node. Caller
+ * holds the scheduler lock.
+ */
+static enum ice_status
+ice_sched_set_agg_node_srl_per_tc(struct ice_port_info *pi, u32 agg_id,
+ u8 tc, u32 min_bw, u32 max_bw, u32 shared_bw)
+{
+ struct ice_sched_node *tc_node, *agg_node, *cfg_node;
+ enum ice_rl_type rl_type = ICE_SHARED_BW;
+ enum ice_status status = ICE_ERR_CFG;
+ u8 layer_num;
+
+ tc_node = ice_sched_get_tc_node(pi, tc);
+ if (!tc_node)
+ return ICE_ERR_CFG;
+
+ agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
+ if (!agg_node)
+ return ICE_ERR_CFG;
+
+ layer_num = ice_sched_get_rl_prof_layer(pi, rl_type,
+ agg_node->tx_sched_layer);
+ if (layer_num >= pi->hw->num_tx_sched_layers)
+ return ICE_ERR_PARAM;
+
+ /* SRL node may be different */
+ cfg_node = ice_sched_get_srl_node(agg_node, layer_num);
+ if (!cfg_node)
+ return ICE_ERR_CFG;
+
+ status = ice_sched_set_save_agg_srl_node_bw(pi, agg_id, tc, cfg_node,
+ ICE_MIN_BW, min_bw);
+ if (status)
+ return status;
+
+ status = ice_sched_set_save_agg_srl_node_bw(pi, agg_id, tc, cfg_node,
+ ICE_MAX_BW, max_bw);
+ if (status)
+ return status;
+
+ status = ice_sched_set_save_agg_srl_node_bw(pi, agg_id, tc, cfg_node,
+ ICE_SHARED_BW, shared_bw);
+ return status;
+}
+
+/**
+ * ice_sched_set_agg_bw_shared_lmt - set aggregator BW shared limit
+ * @pi: port information structure
+ * @agg_id: aggregator ID
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
+ *
+ * This function configures the shared rate limiter(SRL) of all aggregator type
+ * nodes across all traffic classes for aggregator matching agg_id. When
+ * BW value of ICE_SCHED_DFLT_BW is passed, it removes SRL from the
+ * node(s).
+ */
+enum ice_status
+ice_sched_set_agg_bw_shared_lmt(struct ice_port_info *pi, u32 agg_id,
+ u32 min_bw, u32 max_bw, u32 shared_bw)
+{
+ enum ice_status status;
+ u8 tc;
+
+ if (!pi)
+ return ICE_ERR_PARAM;
+
+ ice_acquire_lock(&pi->sched_lock);
+ status = ice_sched_validate_agg_id(pi, agg_id);
+ if (status)
+ goto exit_agg_bw_shared_lmt;
/* Return success if no nodes are present across TC */
ice_for_each_traffic_class(tc) {
- enum ice_rl_type rl_type = ICE_SHARED_BW;
struct ice_sched_node *tc_node, *agg_node;
tc_node = ice_sched_get_tc_node(pi, tc);
if (!agg_node)
continue;
- if (bw == ICE_SCHED_DFLT_BW)
- /* It removes existing SRL from the node */
- status = ice_sched_set_node_bw_dflt_lmt(pi, agg_node,
- rl_type);
- else
- status = ice_sched_set_node_bw_lmt(pi, agg_node,
- rl_type, bw);
- if (status)
- break;
- status = ice_sched_save_agg_bw(pi, agg_id, tc, rl_type, bw);
+ status = ice_sched_set_agg_node_srl_per_tc(pi, agg_id, tc,
+ min_bw, max_bw,
+ shared_bw);
if (status)
break;
}
return status;
}
+/**
+ * ice_sched_set_agg_bw_shared_lmt_per_tc - set aggregator BW shared lmt per tc
+ * @pi: port information structure
+ * @agg_id: aggregator ID
+ * @tc: traffic class
+ * @min_bw: minimum bandwidth in Kbps
+ * @max_bw: maximum bandwidth in Kbps
+ * @shared_bw: shared bandwidth in Kbps
+ *
+ * This function configures the shared rate limiter(SRL) of aggregator type
+ * node for a given traffic class for aggregator matching agg_id. When BW
+ * value of ICE_SCHED_DFLT_BW is passed, it removes SRL from the node.
+ */
+enum ice_status
+ice_sched_set_agg_bw_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id,
+ u8 tc, u32 min_bw, u32 max_bw,
+ u32 shared_bw)
+{
+ enum ice_status status;
+
+ if (!pi)
+ return ICE_ERR_PARAM;
+ ice_acquire_lock(&pi->sched_lock);
+ status = ice_sched_validate_agg_id(pi, agg_id);
+ if (status)
+ goto exit_agg_bw_shared_lmt_per_tc;
+
+ status = ice_sched_set_agg_node_srl_per_tc(pi, agg_id, tc, min_bw,
+ max_bw, shared_bw);
+
+exit_agg_bw_shared_lmt_per_tc:
+ ice_release_lock(&pi->sched_lock);
+ return status;
+}
+
/**
* ice_sched_cfg_sibl_node_prio - configure node sibling priority
* @pi: port information structure