net/ice/base: add sibling head to parse nodes
authorLeyi Rong <leyi.rong@intel.com>
Wed, 19 Jun 2019 15:17:57 +0000 (23:17 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 28 Jun 2019 18:31:48 +0000 (20:31 +0200)
There was a bug in the previous code which never traverses all the
children to get the first node of the requested layer.

Added a sibling head pointer to point the first node of each layer
per TC. This helps the traverse easy and quicker and also removed the
recursive, complexity of the code.

Signed-off-by: Victor Raj <victor.raj@intel.com>
Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Signed-off-by: Leyi Rong <leyi.rong@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
drivers/net/ice/base/ice_sched.c
drivers/net/ice/base/ice_type.h

index 855e384..0c1c18b 100644 (file)
@@ -260,33 +260,17 @@ ice_sched_remove_elems(struct ice_hw *hw, struct ice_sched_node *parent,
 
 /**
  * ice_sched_get_first_node - get the first node of the given layer
- * @hw: pointer to the HW struct
+ * @pi: port information structure
  * @parent: pointer the base node of the subtree
  * @layer: layer number
  *
  * This function retrieves the first node of the given layer from the subtree
  */
 static struct ice_sched_node *
-ice_sched_get_first_node(struct ice_hw *hw, struct ice_sched_node *parent,
-                        u8 layer)
+ice_sched_get_first_node(struct ice_port_info *pi,
+                        struct ice_sched_node *parent, u8 layer)
 {
-       u8 i;
-
-       if (layer < hw->sw_entry_point_layer)
-               return NULL;
-       for (i = 0; i < parent->num_children; i++) {
-               struct ice_sched_node *node = parent->children[i];
-
-               if (node) {
-                       if (node->tx_sched_layer == layer)
-                               return node;
-                       /* this recursion is intentional, and wouldn't
-                        * go more than 9 calls
-                        */
-                       return ice_sched_get_first_node(hw, node, layer);
-               }
-       }
-       return NULL;
+       return pi->sib_head[parent->tc_num][layer];
 }
 
 /**
@@ -342,7 +326,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
        parent = node->parent;
        /* root has no parent */
        if (parent) {
-               struct ice_sched_node *p, *tc_node;
+               struct ice_sched_node *p;
 
                /* update the parent */
                for (i = 0; i < parent->num_children; i++)
@@ -354,16 +338,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
                                break;
                        }
 
-               /* search for previous sibling that points to this node and
-                * remove the reference
-                */
-               tc_node = ice_sched_get_tc_node(pi, node->tc_num);
-               if (!tc_node) {
-                       ice_debug(hw, ICE_DBG_SCHED,
-                                 "Invalid TC number %d\n", node->tc_num);
-                       goto err_exit;
-               }
-               p = ice_sched_get_first_node(hw, tc_node, node->tx_sched_layer);
+               p = ice_sched_get_first_node(pi, node, node->tx_sched_layer);
                while (p) {
                        if (p->sibling == node) {
                                p->sibling = node->sibling;
@@ -371,8 +346,13 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
                        }
                        p = p->sibling;
                }
+
+               /* update the sibling head if head is getting removed */
+               if (pi->sib_head[node->tc_num][node->tx_sched_layer] == node)
+                       pi->sib_head[node->tc_num][node->tx_sched_layer] =
+                               node->sibling;
        }
-err_exit:
+
        /* leaf nodes have no children */
        if (node->children)
                ice_free(hw, node->children);
@@ -979,13 +959,17 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
 
                /* add it to previous node sibling pointer */
                /* Note: siblings are not linked across branches */
-               prev = ice_sched_get_first_node(hw, tc_node, layer);
+               prev = ice_sched_get_first_node(pi, tc_node, layer);
                if (prev && prev != new_node) {
                        while (prev->sibling)
                                prev = prev->sibling;
                        prev->sibling = new_node;
                }
 
+               /* initialize the sibling head */
+               if (!pi->sib_head[tc_node->tc_num][layer])
+                       pi->sib_head[tc_node->tc_num][layer] = new_node;
+
                if (i == 0)
                        *first_node_teid = teid;
        }
@@ -1451,7 +1435,7 @@ ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
                goto lan_q_exit;
 
        /* get the first queue group node from VSI sub-tree */
-       qgrp_node = ice_sched_get_first_node(pi->hw, vsi_node, qgrp_layer);
+       qgrp_node = ice_sched_get_first_node(pi, vsi_node, qgrp_layer);
        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))
@@ -1482,7 +1466,7 @@ ice_sched_get_vsi_node(struct ice_hw *hw, struct ice_sched_node *tc_node,
        u8 vsi_layer;
 
        vsi_layer = ice_sched_get_vsi_layer(hw);
-       node = ice_sched_get_first_node(hw, tc_node, vsi_layer);
+       node = ice_sched_get_first_node(hw->port_info, tc_node, vsi_layer);
 
        /* Check whether it already exists */
        while (node) {
@@ -1511,7 +1495,7 @@ ice_sched_get_agg_node(struct ice_hw *hw, struct ice_sched_node *tc_node,
        u8 agg_layer;
 
        agg_layer = ice_sched_get_agg_layer(hw);
-       node = ice_sched_get_first_node(hw, tc_node, agg_layer);
+       node = ice_sched_get_first_node(hw->port_info, tc_node, agg_layer);
 
        /* Check whether it already exists */
        while (node) {
@@ -1663,7 +1647,8 @@ ice_sched_calc_vsi_support_nodes(struct ice_hw *hw,
                        /* If intermediate nodes are reached max children
                         * then add a new one.
                         */
-                       node = ice_sched_get_first_node(hw, tc_node, (u8)i);
+                       node = ice_sched_get_first_node(hw->port_info, tc_node,
+                                                       (u8)i);
                        /* scan all the siblings */
                        while (node) {
                                if (node->num_children < hw->max_children[i])
@@ -2528,7 +2513,7 @@ ice_sched_add_agg_cfg(struct ice_port_info *pi, u32 agg_id, u8 tc)
         * intermediate node on those layers
         */
        for (i = hw->sw_entry_point_layer; i < aggl; i++) {
-               parent = ice_sched_get_first_node(hw, tc_node, i);
+               parent = ice_sched_get_first_node(pi, tc_node, i);
 
                /* scan all the siblings */
                while (parent) {
index bc1ba60..0f033bb 100644 (file)
@@ -667,6 +667,8 @@ struct ice_port_info {
        struct ice_mac_info mac;
        struct ice_phy_info phy;
        struct ice_lock sched_lock;     /* protect access to TXSched tree */
+       struct ice_sched_node *
+               sib_head[ICE_MAX_TRAFFIC_CLASS][ICE_AQC_TOPO_MAX_LEVEL_NUM];
        /* List contain profile ID(s) and other params per layer */
        struct LIST_HEAD_TYPE rl_prof_list[ICE_AQC_TOPO_MAX_LEVEL_NUM];
        struct ice_dcbx_cfg local_dcbx_cfg;     /* Oper/Local Cfg */