Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ice/ice_sched.c
Context not available. | |||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req, | ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req, | ||||
struct ice_aqc_get_elem *buf, u16 buf_size, | struct ice_aqc_txsched_elem_data *buf, u16 buf_size, | ||||
u16 *elems_ret, struct ice_sq_cd *cd) | u16 *elems_ret, struct ice_sq_cd *cd) | ||||
{ | { | ||||
return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_get_sched_elems, | return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_get_sched_elems, | ||||
Context not available. | |||||
ice_sched_add_node(struct ice_port_info *pi, u8 layer, | 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_aqc_txsched_elem_data elem; | |||||
struct ice_sched_node *parent; | struct ice_sched_node *parent; | ||||
struct ice_aqc_get_elem elem; | |||||
struct ice_sched_node *node; | struct ice_sched_node *node; | ||||
enum ice_status status; | enum ice_status status; | ||||
struct ice_hw *hw; | struct ice_hw *hw; | ||||
Context not available. | |||||
parent = ice_sched_find_node_by_teid(pi->root, | parent = ice_sched_find_node_by_teid(pi->root, | ||||
LE32_TO_CPU(info->parent_teid)); | LE32_TO_CPU(info->parent_teid)); | ||||
if (!parent) { | if (!parent) { | ||||
ice_debug(hw, ICE_DBG_SCHED, | ice_debug(hw, ICE_DBG_SCHED, "Parent Node not found for parent_teid=0x%x\n", | ||||
"Parent Node not found for parent_teid=0x%x\n", | |||||
LE32_TO_CPU(info->parent_teid)); | LE32_TO_CPU(info->parent_teid)); | ||||
return ICE_ERR_PARAM; | return ICE_ERR_PARAM; | ||||
} | } | ||||
/* query the current node information from FW before additing it | /* query the current node information from FW before adding it | ||||
* to the SW DB | * to the SW DB | ||||
*/ | */ | ||||
status = ice_sched_query_elem(hw, LE32_TO_CPU(info->node_teid), &elem); | status = ice_sched_query_elem(hw, LE32_TO_CPU(info->node_teid), &elem); | ||||
Context not available. | |||||
node->parent = parent; | node->parent = parent; | ||||
node->tx_sched_layer = layer; | node->tx_sched_layer = layer; | ||||
parent->children[parent->num_children++] = node; | parent->children[parent->num_children++] = node; | ||||
node->info = elem.generic[0]; | node->info = elem; | ||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
Context not available. | |||||
enum ice_status status; | enum ice_status status; | ||||
u16 buf_size; | u16 buf_size; | ||||
buf_size = sizeof(*buf) + sizeof(u32) * (num_nodes - 1); | buf_size = ice_struct_size(buf, teid, num_nodes); | ||||
buf = (struct ice_aqc_delete_elem *)ice_malloc(hw, buf_size); | buf = (struct ice_aqc_delete_elem *)ice_malloc(hw, buf_size); | ||||
if (!buf) | if (!buf) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
Context not available. | |||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_aq_cfg_sched_elems(struct ice_hw *hw, u16 elems_req, | ice_aq_cfg_sched_elems(struct ice_hw *hw, u16 elems_req, | ||||
struct ice_aqc_conf_elem *buf, u16 buf_size, | struct ice_aqc_txsched_elem_data *buf, u16 buf_size, | ||||
u16 *elems_cfgd, struct ice_sq_cd *cd) | u16 *elems_cfgd, struct ice_sq_cd *cd) | ||||
{ | { | ||||
return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_cfg_sched_elems, | return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_cfg_sched_elems, | ||||
Context not available. | |||||
* Suspend scheduling elements (0x0409) | * Suspend scheduling elements (0x0409) | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_aq_suspend_sched_elems(struct ice_hw *hw, u16 elems_req, | ice_aq_suspend_sched_elems(struct ice_hw *hw, u16 elems_req, __le32 *buf, | ||||
struct ice_aqc_suspend_resume_elem *buf, | |||||
u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd) | u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd) | ||||
{ | { | ||||
return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_suspend_sched_elems, | return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_suspend_sched_elems, | ||||
Context not available. | |||||
* resume scheduling elements (0x040A) | * resume scheduling elements (0x040A) | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_aq_resume_sched_elems(struct ice_hw *hw, u16 elems_req, | ice_aq_resume_sched_elems(struct ice_hw *hw, u16 elems_req, __le32 *buf, | ||||
struct ice_aqc_suspend_resume_elem *buf, | |||||
u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd) | u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd) | ||||
{ | { | ||||
return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_resume_sched_elems, | return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_resume_sched_elems, | ||||
Context not available. | |||||
ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids, | ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids, | ||||
bool suspend) | bool suspend) | ||||
{ | { | ||||
struct ice_aqc_suspend_resume_elem *buf; | |||||
u16 i, buf_size, num_elem_ret = 0; | u16 i, buf_size, num_elem_ret = 0; | ||||
enum ice_status status; | enum ice_status status; | ||||
__le32 *buf; | |||||
buf_size = sizeof(*buf) * num_nodes; | buf_size = sizeof(*buf) * num_nodes; | ||||
buf = (struct ice_aqc_suspend_resume_elem *) | buf = (__le32 *)ice_malloc(hw, buf_size); | ||||
ice_malloc(hw, buf_size); | |||||
if (!buf) | if (!buf) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
for (i = 0; i < num_nodes; i++) | for (i = 0; i < num_nodes; i++) | ||||
buf->teid[i] = CPU_TO_LE32(node_teids[i]); | buf[i] = CPU_TO_LE32(node_teids[i]); | ||||
if (suspend) | if (suspend) | ||||
status = ice_aq_suspend_sched_elems(hw, num_nodes, buf, | status = ice_aq_suspend_sched_elems(hw, num_nodes, buf, | ||||
Context not available. | |||||
/** | /** | ||||
* ice_aq_rl_profile - performs a rate limiting task | * ice_aq_rl_profile - performs a rate limiting task | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @opcode:opcode for add, query, or remove profile(s) | * @opcode: opcode for add, query, or remove profile(s) | ||||
* @num_profiles: the number of profiles | * @num_profiles: the number of profiles | ||||
* @buf: pointer to buffer | * @buf: pointer to buffer | ||||
* @buf_size: buffer size in bytes | * @buf_size: buffer size in bytes | ||||
* @num_processed: number of processed add or remove profile(s) to return | * @num_processed: number of processed add or remove profile(s) to return | ||||
* @cd: pointer to command details structure | * @cd: pointer to command details structure | ||||
* | * | ||||
* Rl profile function to add, query, or remove profile(s) | * RL profile function to add, query, or remove profile(s) | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_aq_rl_profile(struct ice_hw *hw, enum ice_adminq_opc opcode, | ice_aq_rl_profile(struct ice_hw *hw, enum ice_adminq_opc opcode, | ||||
u16 num_profiles, struct ice_aqc_rl_profile_generic_elem *buf, | u16 num_profiles, struct ice_aqc_rl_profile_elem *buf, | ||||
u16 buf_size, u16 *num_processed, struct ice_sq_cd *cd) | u16 buf_size, u16 *num_processed, struct ice_sq_cd *cd) | ||||
{ | { | ||||
struct ice_aqc_rl_profile *cmd; | struct ice_aqc_rl_profile *cmd; | ||||
Context not available. | |||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_aq_add_rl_profile(struct ice_hw *hw, u16 num_profiles, | ice_aq_add_rl_profile(struct ice_hw *hw, u16 num_profiles, | ||||
struct ice_aqc_rl_profile_generic_elem *buf, | struct ice_aqc_rl_profile_elem *buf, u16 buf_size, | ||||
u16 buf_size, u16 *num_profiles_added, | u16 *num_profiles_added, struct ice_sq_cd *cd) | ||||
struct ice_sq_cd *cd) | |||||
{ | { | ||||
return ice_aq_rl_profile(hw, ice_aqc_opc_add_rl_profiles, | return ice_aq_rl_profile(hw, ice_aqc_opc_add_rl_profiles, num_profiles, | ||||
num_profiles, buf, | buf, buf_size, num_profiles_added, cd); | ||||
buf_size, num_profiles_added, cd); | |||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_aq_query_rl_profile(struct ice_hw *hw, u16 num_profiles, | ice_aq_query_rl_profile(struct ice_hw *hw, u16 num_profiles, | ||||
struct ice_aqc_rl_profile_generic_elem *buf, | struct ice_aqc_rl_profile_elem *buf, u16 buf_size, | ||||
u16 buf_size, struct ice_sq_cd *cd) | struct ice_sq_cd *cd) | ||||
{ | { | ||||
return ice_aq_rl_profile(hw, ice_aqc_opc_query_rl_profiles, | return ice_aq_rl_profile(hw, ice_aqc_opc_query_rl_profiles, | ||||
num_profiles, buf, buf_size, NULL, cd); | num_profiles, buf, buf_size, NULL, cd); | ||||
Context not available. | |||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_aq_remove_rl_profile(struct ice_hw *hw, u16 num_profiles, | ice_aq_remove_rl_profile(struct ice_hw *hw, u16 num_profiles, | ||||
struct ice_aqc_rl_profile_generic_elem *buf, | struct ice_aqc_rl_profile_elem *buf, u16 buf_size, | ||||
u16 buf_size, u16 *num_profiles_removed, | u16 *num_profiles_removed, struct ice_sq_cd *cd) | ||||
struct ice_sq_cd *cd) | |||||
{ | { | ||||
return ice_aq_rl_profile(hw, ice_aqc_opc_remove_rl_profiles, | return ice_aq_rl_profile(hw, ice_aqc_opc_remove_rl_profiles, | ||||
num_profiles, buf, | num_profiles, buf, buf_size, | ||||
buf_size, num_profiles_removed, cd); | num_profiles_removed, cd); | ||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
ice_sched_del_rl_profile(struct ice_hw *hw, | ice_sched_del_rl_profile(struct ice_hw *hw, | ||||
struct ice_aqc_rl_profile_info *rl_info) | struct ice_aqc_rl_profile_info *rl_info) | ||||
{ | { | ||||
struct ice_aqc_rl_profile_generic_elem *buf; | struct ice_aqc_rl_profile_elem *buf; | ||||
u16 num_profiles_removed; | u16 num_profiles_removed; | ||||
enum ice_status status; | enum ice_status status; | ||||
u16 num_profiles = 1; | u16 num_profiles = 1; | ||||
Context not available. | |||||
return ICE_ERR_IN_USE; | return ICE_ERR_IN_USE; | ||||
/* Safe to remove profile ID */ | /* Safe to remove profile ID */ | ||||
buf = (struct ice_aqc_rl_profile_generic_elem *) | buf = &rl_info->profile; | ||||
&rl_info->profile; | |||||
status = ice_aq_remove_rl_profile(hw, num_profiles, buf, sizeof(*buf), | status = ice_aq_remove_rl_profile(hw, num_profiles, buf, sizeof(*buf), | ||||
&num_profiles_removed, NULL); | &num_profiles_removed, NULL); | ||||
if (status || num_profiles_removed != num_profiles) | if (status || num_profiles_removed != num_profiles) | ||||
Context not available. | |||||
rl_prof_elem->prof_id_ref = 0; | rl_prof_elem->prof_id_ref = 0; | ||||
status = ice_sched_del_rl_profile(hw, rl_prof_elem); | status = ice_sched_del_rl_profile(hw, rl_prof_elem); | ||||
if (status) { | if (status) { | ||||
ice_debug(hw, ICE_DBG_SCHED, | ice_debug(hw, ICE_DBG_SCHED, "Remove rl profile failed\n"); | ||||
"Remove rl profile failed\n"); | |||||
/* On error, free mem required */ | /* On error, free mem required */ | ||||
LIST_DEL(&rl_prof_elem->list_entry); | LIST_DEL(&rl_prof_elem->list_entry); | ||||
ice_free(hw, rl_prof_elem); | ice_free(hw, rl_prof_elem); | ||||
Context not available. | |||||
} | } | ||||
/** | /** | ||||
* ice_sched_clear_tx_topo - clears the schduler tree nodes | * ice_sched_clear_tx_topo - clears the scheduler tree nodes | ||||
* @pi: port information structure | * @pi: port information structure | ||||
* | * | ||||
* This function removes all the nodes from HW as well as from SW DB. | * This function removes all the nodes from HW as well as from SW DB. | ||||
Context not available. | |||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_aq_cfg_l2_node_cgd(struct ice_hw *hw, u16 num_l2_nodes, | ice_aq_cfg_l2_node_cgd(struct ice_hw *hw, u16 num_l2_nodes, | ||||
struct ice_aqc_cfg_l2_node_cgd_data *buf, | struct ice_aqc_cfg_l2_node_cgd_elem *buf, | ||||
u16 buf_size, struct ice_sq_cd *cd) | u16 buf_size, struct ice_sq_cd *cd) | ||||
{ | { | ||||
struct ice_aqc_cfg_l2_node_cgd *cmd; | struct ice_aqc_cfg_l2_node_cgd *cmd; | ||||
Context not available. | |||||
u16 buf_size; | u16 buf_size; | ||||
u32 teid; | u32 teid; | ||||
buf_size = ice_struct_size(buf, generic, num_nodes - 1); | buf_size = ice_struct_size(buf, generic, num_nodes); | ||||
buf = (struct ice_aqc_add_elem *)ice_malloc(hw, buf_size); | buf = (struct ice_aqc_add_elem *)ice_malloc(hw, buf_size); | ||||
if (!buf) | if (!buf) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
Context not available. | |||||
for (i = 0; i < num_nodes; i++) { | for (i = 0; i < num_nodes; i++) { | ||||
status = ice_sched_add_node(pi, layer, &buf->generic[i]); | status = ice_sched_add_node(pi, layer, &buf->generic[i]); | ||||
if (status != ICE_SUCCESS) { | if (status != ICE_SUCCESS) { | ||||
ice_debug(hw, ICE_DBG_SCHED, | ice_debug(hw, ICE_DBG_SCHED, "add nodes in SW DB failed status =%d\n", | ||||
"add nodes in SW DB failed status =%d\n", | |||||
status); | status); | ||||
break; | break; | ||||
} | } | ||||
Context not available. | |||||
teid = LE32_TO_CPU(buf->generic[i].node_teid); | teid = LE32_TO_CPU(buf->generic[i].node_teid); | ||||
new_node = ice_sched_find_node_by_teid(parent, teid); | new_node = ice_sched_find_node_by_teid(parent, teid); | ||||
if (!new_node) { | if (!new_node) { | ||||
ice_debug(hw, ICE_DBG_SCHED, | ice_debug(hw, ICE_DBG_SCHED, "Node is missing for teid =%d\n", teid); | ||||
"Node is missing for teid =%d\n", teid); | |||||
break; | break; | ||||
} | } | ||||
Context not available. | |||||
ice_release_lock(&pi->sched_lock); | ice_release_lock(&pi->sched_lock); | ||||
if (!node) | if (!node) | ||||
ice_debug(pi->hw, ICE_DBG_SCHED, | ice_debug(pi->hw, ICE_DBG_SCHED, "Node not found for teid=0x%x\n", teid); | ||||
"Node not found for teid=0x%x\n", teid); | |||||
return node; | return node; | ||||
} | } | ||||
Context not available. | |||||
return false; | return false; | ||||
} | } | ||||
/** | |||||
* ice_sched_get_free_qgrp - Scan all queue group siblings and find a free node | |||||
* @pi: port information structure | |||||
* @vsi_node: software VSI handle | |||||
* @qgrp_node: first queue group node identified for scanning | |||||
* @owner: LAN or RDMA | |||||
* | |||||
* This function retrieves a free LAN or RDMA queue group node by scanning | |||||
* qgrp_node and its siblings for the queue group with the fewest number | |||||
* of queues currently assigned. | |||||
*/ | |||||
static struct ice_sched_node * | |||||
ice_sched_get_free_qgrp(struct ice_port_info *pi, | |||||
struct ice_sched_node *vsi_node, | |||||
struct ice_sched_node *qgrp_node, u8 owner) | |||||
{ | |||||
struct ice_sched_node *min_qgrp; | |||||
u8 min_children; | |||||
if (!qgrp_node) | |||||
return qgrp_node; | |||||
min_children = qgrp_node->num_children; | |||||
if (!min_children) | |||||
return qgrp_node; | |||||
min_qgrp = qgrp_node; | |||||
/* scan all queue groups until find a node which has less than the | |||||
* minimum number of children. This way all queue group nodes get | |||||
* equal number of shares and active. The bandwidth will be equally | |||||
* distributed across all queues. | |||||
*/ | |||||
while (qgrp_node) { | |||||
/* make sure the qgroup node is part of the VSI subtree */ | |||||
if (ice_sched_find_node_in_subtree(pi->hw, vsi_node, qgrp_node)) | |||||
if (qgrp_node->num_children < min_children && | |||||
qgrp_node->owner == owner) { | |||||
/* replace the new min queue group node */ | |||||
min_qgrp = qgrp_node; | |||||
min_children = min_qgrp->num_children; | |||||
/* break if it has no children, */ | |||||
if (!min_children) | |||||
break; | |||||
} | |||||
qgrp_node = qgrp_node->sibling; | |||||
} | |||||
return min_qgrp; | |||||
} | |||||
/** | /** | ||||
* ice_sched_get_free_qparent - Get a free LAN or RDMA queue group node | * ice_sched_get_free_qparent - Get a free LAN or RDMA queue group node | ||||
* @pi: port information structure | * @pi: port information structure | ||||
Context not available. | |||||
ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_handle, u8 tc, | ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_handle, u8 tc, | ||||
u8 owner) | u8 owner) | ||||
{ | { | ||||
struct ice_sched_node *vsi_node, *qgrp_node = NULL; | struct ice_sched_node *vsi_node, *qgrp_node; | ||||
struct ice_vsi_ctx *vsi_ctx; | struct ice_vsi_ctx *vsi_ctx; | ||||
u16 max_children; | u16 max_children; | ||||
u8 qgrp_layer; | u8 qgrp_layer; | ||||
Context not available. | |||||
vsi_node = vsi_ctx->sched.vsi_node[tc]; | vsi_node = vsi_ctx->sched.vsi_node[tc]; | ||||
/* validate invalid VSI ID */ | /* validate invalid VSI ID */ | ||||
if (!vsi_node) | if (!vsi_node) | ||||
goto lan_q_exit; | return NULL; | ||||
/* get the first queue group node from VSI sub-tree */ | /* get the first queue group node from VSI sub-tree */ | ||||
qgrp_node = ice_sched_get_first_node(pi, vsi_node, qgrp_layer); | qgrp_node = ice_sched_get_first_node(pi, vsi_node, qgrp_layer); | ||||
Context not available. | |||||
qgrp_node = qgrp_node->sibling; | qgrp_node = qgrp_node->sibling; | ||||
} | } | ||||
lan_q_exit: | /* Select the best queue group */ | ||||
return qgrp_node; | return ice_sched_get_free_qgrp(pi, vsi_node, qgrp_node, owner); | ||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
*/ | */ | ||||
static bool ice_sched_check_node(struct ice_hw *hw, struct ice_sched_node *node) | static bool ice_sched_check_node(struct ice_hw *hw, struct ice_sched_node *node) | ||||
{ | { | ||||
struct ice_aqc_get_elem buf; | struct ice_aqc_txsched_elem_data buf; | ||||
enum ice_status status; | enum ice_status status; | ||||
u32 node_teid; | u32 node_teid; | ||||
Context not available. | |||||
if (status != ICE_SUCCESS) | if (status != ICE_SUCCESS) | ||||
return false; | return false; | ||||
if (memcmp(buf.generic, &node->info, sizeof(*buf.generic))) { | if (memcmp(&buf, &node->info, sizeof(buf))) { | ||||
ice_debug(hw, ICE_DBG_SCHED, "Node mismatch for teid=0x%x\n", | ice_debug(hw, ICE_DBG_SCHED, "Node mismatch for teid=0x%x\n", | ||||
node_teid); | node_teid); | ||||
return false; | return false; | ||||
Context not available. | |||||
* This function removes single aggregator VSI info entry from | * This function removes single aggregator VSI info entry from | ||||
* aggregator list. | * aggregator list. | ||||
*/ | */ | ||||
static void | static void ice_sched_rm_agg_vsi_info(struct ice_port_info *pi, u16 vsi_handle) | ||||
ice_sched_rm_agg_vsi_info(struct ice_port_info *pi, u16 vsi_handle) | |||||
{ | { | ||||
struct ice_sched_agg_info *agg_info; | struct ice_sched_agg_info *agg_info; | ||||
struct ice_sched_agg_info *atmp; | struct ice_sched_agg_info *atmp; | ||||
Context not available. | |||||
continue; | continue; | ||||
if (ice_sched_is_leaf_node_present(vsi_node)) { | if (ice_sched_is_leaf_node_present(vsi_node)) { | ||||
ice_debug(pi->hw, ICE_DBG_SCHED, | ice_debug(pi->hw, ICE_DBG_SCHED, "VSI has leaf nodes in TC %d\n", i); | ||||
"VSI has leaf nodes in TC %d\n", i); | |||||
status = ICE_ERR_IN_USE; | status = ICE_ERR_IN_USE; | ||||
goto exit_sched_rm_vsi_cfg; | goto exit_sched_rm_vsi_cfg; | ||||
} | } | ||||
Context not available. | |||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_aq_query_node_to_root(struct ice_hw *hw, u32 node_teid, | ice_aq_query_node_to_root(struct ice_hw *hw, u32 node_teid, | ||||
struct ice_aqc_get_elem *buf, u16 buf_size, | struct ice_aqc_txsched_elem_data *buf, u16 buf_size, | ||||
struct ice_sq_cd *cd) | struct ice_sq_cd *cd) | ||||
{ | { | ||||
struct ice_aqc_query_node_to_root *cmd; | struct ice_aqc_query_node_to_root *cmd; | ||||
Context not available. | |||||
* This function validates aggregator ID. The function returns info if | * This function validates aggregator ID. The function returns info if | ||||
* aggregator ID is present in list otherwise it returns null. | * aggregator ID is present in list otherwise it returns null. | ||||
*/ | */ | ||||
static struct ice_sched_agg_info* | static struct ice_sched_agg_info * | ||||
ice_get_agg_info(struct ice_hw *hw, u32 agg_id) | ice_get_agg_info(struct ice_hw *hw, u32 agg_id) | ||||
{ | { | ||||
struct ice_sched_agg_info *agg_info; | struct ice_sched_agg_info *agg_info; | ||||
Context not available. | |||||
struct ice_sched_node *node; | struct ice_sched_node *node; | ||||
u16 i, grps_movd = 0; | u16 i, grps_movd = 0; | ||||
struct ice_hw *hw; | struct ice_hw *hw; | ||||
u16 buf_len; | |||||
hw = pi->hw; | hw = pi->hw; | ||||
Context not available. | |||||
return ICE_ERR_PARAM; | return ICE_ERR_PARAM; | ||||
/* Does parent have enough space */ | /* Does parent have enough space */ | ||||
if (parent->num_children + num_items >= | if (parent->num_children + num_items > | ||||
hw->max_children[parent->tx_sched_layer]) | hw->max_children[parent->tx_sched_layer]) | ||||
return ICE_ERR_AQ_FULL; | return ICE_ERR_AQ_FULL; | ||||
buf = (struct ice_aqc_move_elem *)ice_malloc(hw, sizeof(*buf)); | buf_len = ice_struct_size(buf, teid, 1); | ||||
buf = (struct ice_aqc_move_elem *)ice_malloc(hw, buf_len); | |||||
if (!buf) | if (!buf) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
Context not available. | |||||
buf->hdr.dest_parent_teid = parent->info.node_teid; | buf->hdr.dest_parent_teid = parent->info.node_teid; | ||||
buf->teid[0] = node->info.node_teid; | buf->teid[0] = node->info.node_teid; | ||||
buf->hdr.num_elems = CPU_TO_LE16(1); | buf->hdr.num_elems = CPU_TO_LE16(1); | ||||
status = ice_aq_move_sched_elems(hw, 1, buf, sizeof(*buf), | status = ice_aq_move_sched_elems(hw, 1, buf, buf_len, | ||||
&grps_movd, NULL); | &grps_movd, NULL); | ||||
if (status && grps_movd != 1) { | if (status && grps_movd != 1) { | ||||
status = ICE_ERR_CFG; | status = ICE_ERR_CFG; | ||||
Context not available. | |||||
if (!vsi_node) | if (!vsi_node) | ||||
return ICE_ERR_DOES_NOT_EXIST; | return ICE_ERR_DOES_NOT_EXIST; | ||||
/* Is this VSI already part of given aggregator? */ | |||||
if (ice_sched_find_node_in_subtree(pi->hw, agg_node, vsi_node)) | |||||
return ICE_SUCCESS; | |||||
aggl = ice_sched_get_agg_layer(pi->hw); | aggl = ice_sched_get_agg_layer(pi->hw); | ||||
vsil = ice_sched_get_vsi_layer(pi->hw); | vsil = ice_sched_get_vsi_layer(pi->hw); | ||||
Context not available. | |||||
* The function returns aggregator VSI info based on VSI handle. This function | * The function returns aggregator VSI info based on VSI handle. This function | ||||
* needs to be called with scheduler lock held. | * needs to be called with scheduler lock held. | ||||
*/ | */ | ||||
static struct ice_sched_agg_vsi_info* | static struct ice_sched_agg_vsi_info * | ||||
ice_get_agg_vsi_info(struct ice_sched_agg_info *agg_info, u16 vsi_handle) | ice_get_agg_vsi_info(struct ice_sched_agg_info *agg_info, u16 vsi_handle) | ||||
{ | { | ||||
struct ice_sched_agg_vsi_info *agg_vsi_info; | struct ice_sched_agg_vsi_info *agg_vsi_info; | ||||
Context not available. | |||||
* VSI has in this case a different aggregator than the default one. This | * VSI has in this case a different aggregator than the default one. This | ||||
* function needs to be called with scheduler lock held. | * function needs to be called with scheduler lock held. | ||||
*/ | */ | ||||
static struct ice_sched_agg_info* | static struct ice_sched_agg_info * | ||||
ice_get_vsi_agg_info(struct ice_hw *hw, u16 vsi_handle) | ice_get_vsi_agg_info(struct ice_hw *hw, u16 vsi_handle) | ||||
{ | { | ||||
struct ice_sched_agg_info *agg_info; | struct ice_sched_agg_info *agg_info; | ||||
Context not available. | |||||
&pi->rl_prof_list[ln], | &pi->rl_prof_list[ln], | ||||
ice_aqc_rl_profile_info, list_entry) { | ice_aqc_rl_profile_info, list_entry) { | ||||
if (!ice_sched_del_rl_profile(pi->hw, rl_prof_elem)) | if (!ice_sched_del_rl_profile(pi->hw, rl_prof_elem)) | ||||
ice_debug(pi->hw, ICE_DBG_SCHED, | ice_debug(pi->hw, ICE_DBG_SCHED, "Removed rl profile\n"); | ||||
"Removed rl profile\n"); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
* @node: pointer to node | * @node: pointer to node | ||||
* @info: node info to update | * @info: node info to update | ||||
* | * | ||||
* It updates the HW DB, and local SW DB of node. It updates the scheduling | * Update the HW DB, and local SW DB of node. Update the scheduling | ||||
* parameters of node from argument info data buffer (Info->data buf) and | * parameters of node from argument info data buffer (Info->data buf) and | ||||
* returns success or error on config sched element failure. The caller | * returns success or error on config sched element failure. The caller | ||||
* needs to hold scheduler lock. | * needs to hold scheduler lock. | ||||
Context not available. | |||||
ice_sched_update_elem(struct ice_hw *hw, struct ice_sched_node *node, | ice_sched_update_elem(struct ice_hw *hw, struct ice_sched_node *node, | ||||
struct ice_aqc_txsched_elem_data *info) | struct ice_aqc_txsched_elem_data *info) | ||||
{ | { | ||||
struct ice_aqc_conf_elem buf; | struct ice_aqc_txsched_elem_data buf; | ||||
enum ice_status status; | enum ice_status status; | ||||
u16 elem_cfgd = 0; | u16 elem_cfgd = 0; | ||||
u16 num_elems = 1; | u16 num_elems = 1; | ||||
buf.generic[0] = *info; | buf = *info; | ||||
/* Parent TEID is reserved field in this aq call */ | /* Parent TEID is reserved field in this aq call */ | ||||
buf.generic[0].parent_teid = 0; | buf.parent_teid = 0; | ||||
/* Element type is reserved field in this aq call */ | /* Element type is reserved field in this aq call */ | ||||
buf.generic[0].data.elem_type = 0; | buf.data.elem_type = 0; | ||||
/* Flags is reserved field in this aq call */ | /* Flags is reserved field in this aq call */ | ||||
buf.generic[0].data.flags = 0; | buf.data.flags = 0; | ||||
/* Update HW DB */ | /* Update HW DB */ | ||||
/* Configure element node */ | /* Configure element node */ | ||||
Context not available. | |||||
* | * | ||||
* Save or clear CIR bandwidth (BW) in the passed param bw_t_info. | * Save or clear CIR bandwidth (BW) in the passed param bw_t_info. | ||||
*/ | */ | ||||
static void | static void ice_set_clear_cir_bw(struct ice_bw_type_info *bw_t_info, u32 bw) | ||||
ice_set_clear_cir_bw(struct ice_bw_type_info *bw_t_info, u32 bw) | |||||
{ | { | ||||
if (bw == ICE_SCHED_DFLT_BW) { | if (bw == ICE_SCHED_DFLT_BW) { | ||||
ice_clear_bit(ICE_BW_TYPE_CIR, bw_t_info->bw_t_bitmap); | ice_clear_bit(ICE_BW_TYPE_CIR, bw_t_info->bw_t_bitmap); | ||||
Context not available. | |||||
* | * | ||||
* Save or clear EIR bandwidth (BW) in the passed param bw_t_info. | * Save or clear EIR bandwidth (BW) in the passed param bw_t_info. | ||||
*/ | */ | ||||
static void | static void ice_set_clear_eir_bw(struct ice_bw_type_info *bw_t_info, u32 bw) | ||||
ice_set_clear_eir_bw(struct ice_bw_type_info *bw_t_info, u32 bw) | |||||
{ | { | ||||
if (bw == ICE_SCHED_DFLT_BW) { | if (bw == ICE_SCHED_DFLT_BW) { | ||||
ice_clear_bit(ICE_BW_TYPE_EIR, bw_t_info->bw_t_bitmap); | ice_clear_bit(ICE_BW_TYPE_EIR, bw_t_info->bw_t_bitmap); | ||||
Context not available. | |||||
* | * | ||||
* Save or clear shared bandwidth (BW) in the passed param bw_t_info. | * Save or clear shared bandwidth (BW) in the passed param bw_t_info. | ||||
*/ | */ | ||||
static void | static void ice_set_clear_shared_bw(struct ice_bw_type_info *bw_t_info, u32 bw) | ||||
ice_set_clear_shared_bw(struct ice_bw_type_info *bw_t_info, u32 bw) | |||||
{ | { | ||||
if (bw == ICE_SCHED_DFLT_BW) { | if (bw == ICE_SCHED_DFLT_BW) { | ||||
ice_clear_bit(ICE_BW_TYPE_SHARED, bw_t_info->bw_t_bitmap); | ice_clear_bit(ICE_BW_TYPE_SHARED, bw_t_info->bw_t_bitmap); | ||||
Context not available. | |||||
* | * | ||||
* Save or clear priority (prio) in the passed param bw_t_info. | * Save or clear priority (prio) in the passed param bw_t_info. | ||||
*/ | */ | ||||
static void | static void ice_set_clear_prio(struct ice_bw_type_info *bw_t_info, u8 prio) | ||||
ice_set_clear_prio(struct ice_bw_type_info *bw_t_info, u8 prio) | |||||
{ | { | ||||
bw_t_info->generic = prio; | bw_t_info->generic = prio; | ||||
if (bw_t_info->generic) | if (bw_t_info->generic) | ||||
Context not available. | |||||
* @pi: port information structure | * @pi: port information structure | ||||
* @num_qs: number of VSI queues | * @num_qs: number of VSI queues | ||||
* @q_ids: queue IDs array | * @q_ids: queue IDs array | ||||
* @q_ids: queue IDs array | |||||
* @q_prio: queue priority array | * @q_prio: queue priority array | ||||
* | * | ||||
* This function configures the queue node priority (Sibling Priority) of the | * This function configures the queue node priority (Sibling Priority) of the | ||||
Context not available. | |||||
ice_sched_add_rl_profile(struct ice_port_info *pi, | ice_sched_add_rl_profile(struct ice_port_info *pi, | ||||
enum ice_rl_type rl_type, u32 bw, u8 layer_num) | enum ice_rl_type rl_type, u32 bw, u8 layer_num) | ||||
{ | { | ||||
struct ice_aqc_rl_profile_generic_elem *buf; | |||||
struct ice_aqc_rl_profile_info *rl_prof_elem; | struct ice_aqc_rl_profile_info *rl_prof_elem; | ||||
u16 profiles_added = 0, num_profiles = 1; | u16 profiles_added = 0, num_profiles = 1; | ||||
struct ice_aqc_rl_profile_elem *buf; | |||||
enum ice_status status; | enum ice_status status; | ||||
struct ice_hw *hw; | struct ice_hw *hw; | ||||
u8 profile_type; | u8 profile_type; | ||||
Context not available. | |||||
hw = pi->hw; | hw = pi->hw; | ||||
LIST_FOR_EACH_ENTRY(rl_prof_elem, &pi->rl_prof_list[layer_num], | LIST_FOR_EACH_ENTRY(rl_prof_elem, &pi->rl_prof_list[layer_num], | ||||
ice_aqc_rl_profile_info, list_entry) | ice_aqc_rl_profile_info, list_entry) | ||||
if (rl_prof_elem->profile.flags == profile_type && | if ((rl_prof_elem->profile.flags & ICE_AQC_RL_PROFILE_TYPE_M) == | ||||
rl_prof_elem->bw == bw) | profile_type && rl_prof_elem->bw == bw) | ||||
/* Return existing profile ID info */ | /* Return existing profile ID info */ | ||||
return rl_prof_elem; | return rl_prof_elem; | ||||
Context not available. | |||||
rl_prof_elem->profile.max_burst_size = CPU_TO_LE16(hw->max_burst_size); | rl_prof_elem->profile.max_burst_size = CPU_TO_LE16(hw->max_burst_size); | ||||
/* Create new entry in HW DB */ | /* Create new entry in HW DB */ | ||||
buf = (struct ice_aqc_rl_profile_generic_elem *) | buf = &rl_prof_elem->profile; | ||||
&rl_prof_elem->profile; | |||||
status = ice_aq_add_rl_profile(hw, num_profiles, buf, sizeof(*buf), | status = ice_aq_add_rl_profile(hw, num_profiles, buf, sizeof(*buf), | ||||
&profiles_added, NULL); | &profiles_added, NULL); | ||||
if (status || profiles_added != num_profiles) | if (status || profiles_added != num_profiles) | ||||
Context not available. | |||||
/* Check the existing list for RL profile */ | /* 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, &pi->rl_prof_list[layer_num], | ||||
ice_aqc_rl_profile_info, list_entry) | ice_aqc_rl_profile_info, list_entry) | ||||
if (rl_prof_elem->profile.flags == profile_type && | if ((rl_prof_elem->profile.flags & ICE_AQC_RL_PROFILE_TYPE_M) == | ||||
profile_type && | |||||
LE16_TO_CPU(rl_prof_elem->profile.profile_id) == | LE16_TO_CPU(rl_prof_elem->profile.profile_id) == | ||||
profile_id) { | profile_id) { | ||||
if (rl_prof_elem->prof_id_ref) | if (rl_prof_elem->prof_id_ref) | ||||
Context not available. | |||||
/* Remove old profile ID from database */ | /* Remove old profile ID from database */ | ||||
status = ice_sched_del_rl_profile(pi->hw, rl_prof_elem); | status = ice_sched_del_rl_profile(pi->hw, rl_prof_elem); | ||||
if (status && status != ICE_ERR_IN_USE) | if (status && status != ICE_ERR_IN_USE) | ||||
ice_debug(pi->hw, ICE_DBG_SCHED, | ice_debug(pi->hw, ICE_DBG_SCHED, "Remove rl profile failed\n"); | ||||
"Remove rl profile failed\n"); | |||||
break; | break; | ||||
} | } | ||||
if (status == ICE_ERR_IN_USE) | if (status == ICE_ERR_IN_USE) | ||||
Context not available. | |||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
return ice_sched_rm_rl_profile(pi, layer_num, | return ice_sched_rm_rl_profile(pi, layer_num, | ||||
rl_prof_info->profile.flags, | rl_prof_info->profile.flags & | ||||
old_id); | ICE_AQC_RL_PROFILE_TYPE_M, old_id); | ||||
} | } | ||||
/** | /** | ||||
Context not available. | |||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/* | /** | ||||
* ice_sched_replay_node_prio - re-configure node priority | * ice_sched_replay_node_prio - re-configure node priority | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @node: sched node to configure | * @node: sched node to configure | ||||
Context not available. | |||||
ice_acquire_lock(&pi->sched_lock); | ice_acquire_lock(&pi->sched_lock); | ||||
LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info, | LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info, | ||||
list_entry) { | list_entry) | ||||
/* replay aggregator (re-create aggregator node) */ | /* replay aggregator (re-create aggregator node) */ | ||||
if (!ice_cmp_bitmap(agg_info->tc_bitmap, | if (!ice_cmp_bitmap(agg_info->tc_bitmap, | ||||
agg_info->replay_tc_bitmap, | agg_info->replay_tc_bitmap, | ||||
Context not available. | |||||
ice_info(hw, "Replay agg bw [id=%d] failed\n", | ice_info(hw, "Replay agg bw [id=%d] failed\n", | ||||
agg_info->agg_id); | agg_info->agg_id); | ||||
} | } | ||||
} | |||||
ice_release_lock(&pi->sched_lock); | ice_release_lock(&pi->sched_lock); | ||||
} | } | ||||
Context not available. | |||||
ice_release_lock(&pi->sched_lock); | ice_release_lock(&pi->sched_lock); | ||||
} | } | ||||
/** | |||||
* ice_sched_replay_root_node_bw - replay root node BW | |||||
* @pi: port information structure | |||||
* | |||||
* Replay root node BW settings. | |||||
*/ | |||||
enum ice_status ice_sched_replay_root_node_bw(struct ice_port_info *pi) | |||||
{ | |||||
enum ice_status status = ICE_SUCCESS; | |||||
if (!pi->hw) | |||||
return ICE_ERR_PARAM; | |||||
ice_acquire_lock(&pi->sched_lock); | |||||
status = ice_sched_replay_node_bw(pi->hw, pi->root, | |||||
&pi->root_node_bw_t_info); | |||||
ice_release_lock(&pi->sched_lock); | |||||
return status; | |||||
} | |||||
/** | /** | ||||
* ice_sched_replay_tc_node_bw - replay TC node(s) BW | * ice_sched_replay_tc_node_bw - replay TC node(s) BW | ||||
* @pi: port information structure | * @pi: port information structure | ||||
* | * | ||||
* This function replay TC nodes. | * This function replay TC nodes. | ||||
*/ | */ | ||||
enum ice_status | enum ice_status ice_sched_replay_tc_node_bw(struct ice_port_info *pi) | ||||
ice_sched_replay_tc_node_bw(struct ice_port_info *pi) | |||||
{ | { | ||||
enum ice_status status = ICE_SUCCESS; | enum ice_status status = ICE_SUCCESS; | ||||
u8 tc; | u8 tc; | ||||
Context not available. | |||||
* This function replays association of VSI to aggregator type nodes, and | * This function replays association of VSI to aggregator type nodes, and | ||||
* node bandwidth information. | * node bandwidth information. | ||||
*/ | */ | ||||
enum ice_status | enum ice_status ice_replay_vsi_agg(struct ice_hw *hw, u16 vsi_handle) | ||||
ice_replay_vsi_agg(struct ice_hw *hw, u16 vsi_handle) | |||||
{ | { | ||||
struct ice_port_info *pi = hw->port_info; | struct ice_port_info *pi = hw->port_info; | ||||
enum ice_status status; | enum ice_status status; | ||||
Context not available. |