1429c3944STomasz Duszynski /* SPDX-License-Identifier: BSD-3-Clause 2429c3944STomasz Duszynski * Copyright(c) 2018 Marvell International Ltd. 3429c3944STomasz Duszynski * Copyright(c) 2018 Semihalf. 4429c3944STomasz Duszynski * All rights reserved. 5429c3944STomasz Duszynski */ 6429c3944STomasz Duszynski 7429c3944STomasz Duszynski #include <rte_malloc.h> 8429c3944STomasz Duszynski 9429c3944STomasz Duszynski #include <linux/ethtool.h> 10429c3944STomasz Duszynski #include <linux/sockios.h> 11429c3944STomasz Duszynski #include <net/if.h> 12429c3944STomasz Duszynski #include <sys/ioctl.h> 13429c3944STomasz Duszynski 14429c3944STomasz Duszynski #include "mrvl_tm.h" 15429c3944STomasz Duszynski 16429c3944STomasz Duszynski /** Minimum rate value in Bytes/s */ 17429c3944STomasz Duszynski #define MRVL_RATE_MIN (PP2_PPIO_MIN_CIR * 1000 / 8) 18429c3944STomasz Duszynski 19429c3944STomasz Duszynski /** Minimum burst size in Bytes */ 20429c3944STomasz Duszynski #define MRVL_BURST_MIN (PP2_PPIO_MIN_CBS * 1000) 21429c3944STomasz Duszynski 22429c3944STomasz Duszynski /** Maximum burst size in Bytes */ 23429c3944STomasz Duszynski #define MRVL_BURST_MAX 256000000 24429c3944STomasz Duszynski 25429c3944STomasz Duszynski /** Maximum WRR weight */ 26429c3944STomasz Duszynski #define MRVL_WEIGHT_MAX 255 27429c3944STomasz Duszynski 28429c3944STomasz Duszynski /** 29429c3944STomasz Duszynski * Get maximum port rate in Bytes/s. 30429c3944STomasz Duszynski * 31429c3944STomasz Duszynski * @param dev Pointer to the device. 32429c3944STomasz Duszynski * @param rate Pointer to the rate. 33429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 34429c3944STomasz Duszynski */ 35429c3944STomasz Duszynski static int 36429c3944STomasz Duszynski mrvl_get_max_rate(struct rte_eth_dev *dev, uint64_t *rate) 37429c3944STomasz Duszynski { 38429c3944STomasz Duszynski struct ethtool_cmd edata; 39429c3944STomasz Duszynski struct ifreq req; 40429c3944STomasz Duszynski int ret, fd; 41429c3944STomasz Duszynski 42429c3944STomasz Duszynski memset(&edata, 0, sizeof(edata)); 43429c3944STomasz Duszynski memset(&req, 0, sizeof(req)); 44429c3944STomasz Duszynski edata.cmd = ETHTOOL_GSET; 45429c3944STomasz Duszynski strcpy(req.ifr_name, dev->data->name); 46429c3944STomasz Duszynski req.ifr_data = (void *)&edata; 47429c3944STomasz Duszynski 48429c3944STomasz Duszynski fd = socket(AF_INET, SOCK_DGRAM, 0); 49429c3944STomasz Duszynski if (fd == -1) 50429c3944STomasz Duszynski return -1; 51429c3944STomasz Duszynski 52429c3944STomasz Duszynski ret = ioctl(fd, SIOCETHTOOL, &req); 53429c3944STomasz Duszynski if (ret == -1) { 54429c3944STomasz Duszynski close(fd); 55429c3944STomasz Duszynski return -1; 56429c3944STomasz Duszynski } 57429c3944STomasz Duszynski 58429c3944STomasz Duszynski close(fd); 59429c3944STomasz Duszynski 608fa07a68SDana Vardi *rate = (uint64_t)ethtool_cmd_speed(&edata) * 1000 * 1000 / 8; 61429c3944STomasz Duszynski 62429c3944STomasz Duszynski return 0; 63429c3944STomasz Duszynski } 64429c3944STomasz Duszynski 65429c3944STomasz Duszynski /** 66429c3944STomasz Duszynski * Initialize traffic manager related data. 67429c3944STomasz Duszynski * 68429c3944STomasz Duszynski * @param dev Pointer to the device. 69429c3944STomasz Duszynski * @returns 0 on success, failure otherwise. 70429c3944STomasz Duszynski */ 71429c3944STomasz Duszynski int 72429c3944STomasz Duszynski mrvl_tm_init(struct rte_eth_dev *dev) 73429c3944STomasz Duszynski { 74429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 75429c3944STomasz Duszynski 76429c3944STomasz Duszynski LIST_INIT(&priv->shaper_profiles); 77429c3944STomasz Duszynski LIST_INIT(&priv->nodes); 78429c3944STomasz Duszynski 79429c3944STomasz Duszynski if (priv->rate_max) 80429c3944STomasz Duszynski return 0; 81429c3944STomasz Duszynski 82429c3944STomasz Duszynski return mrvl_get_max_rate(dev, &priv->rate_max); 83429c3944STomasz Duszynski } 84429c3944STomasz Duszynski 85429c3944STomasz Duszynski /** 86429c3944STomasz Duszynski * Cleanup traffic manager related data. 87429c3944STomasz Duszynski * 88429c3944STomasz Duszynski * @param dev Pointer to the device. 89429c3944STomasz Duszynski */ 90429c3944STomasz Duszynski void mrvl_tm_deinit(struct rte_eth_dev *dev) 91429c3944STomasz Duszynski { 92429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 93429c3944STomasz Duszynski struct mrvl_tm_shaper_profile *profile = 94429c3944STomasz Duszynski LIST_FIRST(&priv->shaper_profiles); 95429c3944STomasz Duszynski struct mrvl_tm_node *node = LIST_FIRST(&priv->nodes); 96429c3944STomasz Duszynski 97429c3944STomasz Duszynski while (profile) { 98429c3944STomasz Duszynski struct mrvl_tm_shaper_profile *next = LIST_NEXT(profile, next); 99429c3944STomasz Duszynski 100429c3944STomasz Duszynski LIST_REMOVE(profile, next); 101429c3944STomasz Duszynski rte_free(profile); 102429c3944STomasz Duszynski profile = next; 103429c3944STomasz Duszynski } 104429c3944STomasz Duszynski 105429c3944STomasz Duszynski while (node) { 106429c3944STomasz Duszynski struct mrvl_tm_node *next = LIST_NEXT(node, next); 107429c3944STomasz Duszynski 108429c3944STomasz Duszynski LIST_REMOVE(node, next); 109429c3944STomasz Duszynski rte_free(node); 110429c3944STomasz Duszynski node = next; 111429c3944STomasz Duszynski } 112429c3944STomasz Duszynski } 113429c3944STomasz Duszynski 114429c3944STomasz Duszynski /** 115429c3944STomasz Duszynski * Get node using its id. 116429c3944STomasz Duszynski * 117429c3944STomasz Duszynski * @param priv Pointer to the port's private data. 118429c3944STomasz Duszynski * @param node_id Id used by this node. 119429c3944STomasz Duszynski * @returns Pointer to the node if exists, NULL otherwise. 120429c3944STomasz Duszynski */ 121429c3944STomasz Duszynski static struct mrvl_tm_node * 122429c3944STomasz Duszynski mrvl_node_from_id(struct mrvl_priv *priv, uint32_t node_id) 123429c3944STomasz Duszynski { 124429c3944STomasz Duszynski struct mrvl_tm_node *node; 125429c3944STomasz Duszynski 126429c3944STomasz Duszynski LIST_FOREACH(node, &priv->nodes, next) 127429c3944STomasz Duszynski if (node->id == node_id) 128429c3944STomasz Duszynski return node; 129429c3944STomasz Duszynski 130429c3944STomasz Duszynski return NULL; 131429c3944STomasz Duszynski } 132429c3944STomasz Duszynski 133429c3944STomasz Duszynski /** 134429c3944STomasz Duszynski * Check whether node is leaf or root. 135429c3944STomasz Duszynski * 136429c3944STomasz Duszynski * @param dev Pointer to the device. 137429c3944STomasz Duszynski * @param node_id Id used by this node. 138429c3944STomasz Duszynski * @param is_leaf Pointer to flag indicating whether node is a leaf. 139429c3944STomasz Duszynski * @param error Pointer to the error. 140429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 141429c3944STomasz Duszynski */ 142429c3944STomasz Duszynski static int 143429c3944STomasz Duszynski mrvl_node_type_get(struct rte_eth_dev *dev, uint32_t node_id, int *is_leaf, 144429c3944STomasz Duszynski struct rte_tm_error *error) 145429c3944STomasz Duszynski { 146429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 147429c3944STomasz Duszynski struct mrvl_tm_node *node; 148429c3944STomasz Duszynski 149e622c1a8SDana Vardi if (!priv->configured) 150e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 151e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 152e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 153e622c1a8SDana Vardi 154429c3944STomasz Duszynski if (!is_leaf) 155429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 156429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 157429c3944STomasz Duszynski NULL, NULL); 158429c3944STomasz Duszynski 159429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 160429c3944STomasz Duszynski if (!node) 161429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 162429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 163429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 164429c3944STomasz Duszynski 165429c3944STomasz Duszynski *is_leaf = node->type == MRVL_NODE_QUEUE ? 1 : 0; 166429c3944STomasz Duszynski 167429c3944STomasz Duszynski return 0; 168429c3944STomasz Duszynski } 169429c3944STomasz Duszynski 170429c3944STomasz Duszynski /** 171429c3944STomasz Duszynski * Get traffic manager capabilities. 172429c3944STomasz Duszynski * 173429c3944STomasz Duszynski * @param dev Pointer to the device (unused). 174429c3944STomasz Duszynski * @param cap Pointer to the capabilities. 175429c3944STomasz Duszynski * @param error Pointer to the error. 176429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 177429c3944STomasz Duszynski */ 178429c3944STomasz Duszynski static int 179429c3944STomasz Duszynski mrvl_capabilities_get(struct rte_eth_dev *dev, 180429c3944STomasz Duszynski struct rte_tm_capabilities *cap, 181429c3944STomasz Duszynski struct rte_tm_error *error) 182429c3944STomasz Duszynski { 183429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 184429c3944STomasz Duszynski 185e622c1a8SDana Vardi if (!priv->configured) 186e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 187e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 188e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 189e622c1a8SDana Vardi 190429c3944STomasz Duszynski if (!cap) 191429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 192429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 193429c3944STomasz Duszynski NULL, "Capabilities are missing\n"); 194429c3944STomasz Duszynski 195429c3944STomasz Duszynski memset(cap, 0, sizeof(*cap)); 196429c3944STomasz Duszynski 197429c3944STomasz Duszynski cap->n_nodes_max = 1 + dev->data->nb_tx_queues; /* port + txqs number */ 198429c3944STomasz Duszynski cap->n_levels_max = 2; /* port level + txqs level */ 199429c3944STomasz Duszynski cap->non_leaf_nodes_identical = 1; 200429c3944STomasz Duszynski cap->leaf_nodes_identical = 1; 201429c3944STomasz Duszynski 202429c3944STomasz Duszynski cap->shaper_n_max = cap->n_nodes_max; 203429c3944STomasz Duszynski cap->shaper_private_n_max = cap->shaper_n_max; 204429c3944STomasz Duszynski cap->shaper_private_rate_min = MRVL_RATE_MIN; 205429c3944STomasz Duszynski cap->shaper_private_rate_max = priv->rate_max; 20657fc9e47SNithin Dabilpuram cap->shaper_private_packet_mode_supported = 0; 20757fc9e47SNithin Dabilpuram cap->shaper_private_byte_mode_supported = 1; 208429c3944STomasz Duszynski 209429c3944STomasz Duszynski cap->sched_n_children_max = dev->data->nb_tx_queues; 210429c3944STomasz Duszynski cap->sched_sp_n_priorities_max = dev->data->nb_tx_queues; 211429c3944STomasz Duszynski cap->sched_wfq_n_children_per_group_max = dev->data->nb_tx_queues; 212429c3944STomasz Duszynski cap->sched_wfq_n_groups_max = 1; 213429c3944STomasz Duszynski cap->sched_wfq_weight_max = MRVL_WEIGHT_MAX; 21457fc9e47SNithin Dabilpuram cap->sched_wfq_packet_mode_supported = 0; 21557fc9e47SNithin Dabilpuram cap->sched_wfq_byte_mode_supported = 1; 216429c3944STomasz Duszynski 217429c3944STomasz Duszynski cap->dynamic_update_mask = RTE_TM_UPDATE_NODE_SUSPEND_RESUME | 218429c3944STomasz Duszynski RTE_TM_UPDATE_NODE_STATS; 219429c3944STomasz Duszynski cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES; 220429c3944STomasz Duszynski 221429c3944STomasz Duszynski return 0; 222429c3944STomasz Duszynski } 223429c3944STomasz Duszynski 224429c3944STomasz Duszynski /** 225429c3944STomasz Duszynski * Get traffic manager hierarchy level capabilities. 226429c3944STomasz Duszynski * 227429c3944STomasz Duszynski * @param dev Pointer to the device. 228429c3944STomasz Duszynski * @param level_id Id of the level. 229429c3944STomasz Duszynski * @param cap Pointer to the level capabilities. 230429c3944STomasz Duszynski * @param error Pointer to the error. 231429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 232429c3944STomasz Duszynski */ 233429c3944STomasz Duszynski static int 234429c3944STomasz Duszynski mrvl_level_capabilities_get(struct rte_eth_dev *dev, 235429c3944STomasz Duszynski uint32_t level_id, 236429c3944STomasz Duszynski struct rte_tm_level_capabilities *cap, 237429c3944STomasz Duszynski struct rte_tm_error *error) 238429c3944STomasz Duszynski { 239429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 240429c3944STomasz Duszynski 241e622c1a8SDana Vardi if (!priv->configured) 242e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 243e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 244e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 245e622c1a8SDana Vardi 246429c3944STomasz Duszynski if (!cap) 247429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 248429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 249429c3944STomasz Duszynski NULL, NULL); 250429c3944STomasz Duszynski 251429c3944STomasz Duszynski memset(cap, 0, sizeof(*cap)); 252429c3944STomasz Duszynski 253429c3944STomasz Duszynski if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE) 254429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 255429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_LEVEL_ID, 256429c3944STomasz Duszynski NULL, "Wrong level id\n"); 257429c3944STomasz Duszynski 258429c3944STomasz Duszynski if (level_id == MRVL_NODE_PORT) { 259429c3944STomasz Duszynski cap->n_nodes_max = 1; 260429c3944STomasz Duszynski cap->n_nodes_nonleaf_max = 1; 261429c3944STomasz Duszynski cap->non_leaf_nodes_identical = 1; 262429c3944STomasz Duszynski 263429c3944STomasz Duszynski cap->nonleaf.shaper_private_supported = 1; 264429c3944STomasz Duszynski cap->nonleaf.shaper_private_rate_min = MRVL_RATE_MIN; 265429c3944STomasz Duszynski cap->nonleaf.shaper_private_rate_max = priv->rate_max; 26657fc9e47SNithin Dabilpuram cap->nonleaf.shaper_private_packet_mode_supported = 0; 26757fc9e47SNithin Dabilpuram cap->nonleaf.shaper_private_byte_mode_supported = 1; 268429c3944STomasz Duszynski 269429c3944STomasz Duszynski cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues; 270429c3944STomasz Duszynski cap->nonleaf.sched_sp_n_priorities_max = 1; 271429c3944STomasz Duszynski cap->nonleaf.sched_wfq_n_children_per_group_max = 272429c3944STomasz Duszynski dev->data->nb_tx_queues; 273429c3944STomasz Duszynski cap->nonleaf.sched_wfq_n_groups_max = 1; 274429c3944STomasz Duszynski cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX; 27557fc9e47SNithin Dabilpuram cap->nonleaf.sched_wfq_packet_mode_supported = 0; 27657fc9e47SNithin Dabilpuram cap->nonleaf.sched_wfq_byte_mode_supported = 1; 277429c3944STomasz Duszynski cap->nonleaf.stats_mask = RTE_TM_STATS_N_PKTS | 278429c3944STomasz Duszynski RTE_TM_STATS_N_BYTES; 279429c3944STomasz Duszynski } else { /* level_id == MRVL_NODE_QUEUE */ 280429c3944STomasz Duszynski cap->n_nodes_max = dev->data->nb_tx_queues; 281429c3944STomasz Duszynski cap->n_nodes_leaf_max = dev->data->nb_tx_queues; 282429c3944STomasz Duszynski cap->leaf_nodes_identical = 1; 283429c3944STomasz Duszynski 284429c3944STomasz Duszynski cap->leaf.shaper_private_supported = 1; 285429c3944STomasz Duszynski cap->leaf.shaper_private_rate_min = MRVL_RATE_MIN; 286429c3944STomasz Duszynski cap->leaf.shaper_private_rate_max = priv->rate_max; 28757fc9e47SNithin Dabilpuram cap->leaf.shaper_private_packet_mode_supported = 0; 28857fc9e47SNithin Dabilpuram cap->leaf.shaper_private_byte_mode_supported = 1; 289429c3944STomasz Duszynski cap->leaf.stats_mask = RTE_TM_STATS_N_PKTS; 290429c3944STomasz Duszynski } 291429c3944STomasz Duszynski 292429c3944STomasz Duszynski return 0; 293429c3944STomasz Duszynski } 294429c3944STomasz Duszynski 295429c3944STomasz Duszynski /** 296429c3944STomasz Duszynski * Get node capabilities. 297429c3944STomasz Duszynski * 298429c3944STomasz Duszynski * @param dev Pointer to the device. 299429c3944STomasz Duszynski * @param node_id Id of the node. 300429c3944STomasz Duszynski * @param cap Pointer to the capabilities. 301429c3944STomasz Duszynski * @param error Pointer to the error. 302429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 303429c3944STomasz Duszynski */ 304429c3944STomasz Duszynski static int 305429c3944STomasz Duszynski mrvl_node_capabilities_get(struct rte_eth_dev *dev, uint32_t node_id, 306429c3944STomasz Duszynski struct rte_tm_node_capabilities *cap, 307429c3944STomasz Duszynski struct rte_tm_error *error) 308429c3944STomasz Duszynski { 309429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 310429c3944STomasz Duszynski struct mrvl_tm_node *node; 311429c3944STomasz Duszynski 312e622c1a8SDana Vardi if (!priv->configured) 313e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 314e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 315e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 316e622c1a8SDana Vardi 317429c3944STomasz Duszynski if (!cap) 318429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 319429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 320429c3944STomasz Duszynski NULL, NULL); 321429c3944STomasz Duszynski 322429c3944STomasz Duszynski memset(cap, 0, sizeof(*cap)); 323429c3944STomasz Duszynski 324429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 325429c3944STomasz Duszynski if (!node) 326429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 327429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 328429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 329429c3944STomasz Duszynski 330429c3944STomasz Duszynski cap->shaper_private_supported = 1; 331429c3944STomasz Duszynski cap->shaper_private_rate_min = MRVL_RATE_MIN; 332429c3944STomasz Duszynski cap->shaper_private_rate_max = priv->rate_max; 33357fc9e47SNithin Dabilpuram cap->shaper_private_packet_mode_supported = 0; 33457fc9e47SNithin Dabilpuram cap->shaper_private_byte_mode_supported = 1; 335429c3944STomasz Duszynski 336429c3944STomasz Duszynski if (node->type == MRVL_NODE_PORT) { 337429c3944STomasz Duszynski cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues; 338429c3944STomasz Duszynski cap->nonleaf.sched_sp_n_priorities_max = 1; 339429c3944STomasz Duszynski cap->nonleaf.sched_wfq_n_children_per_group_max = 340429c3944STomasz Duszynski dev->data->nb_tx_queues; 341429c3944STomasz Duszynski cap->nonleaf.sched_wfq_n_groups_max = 1; 342429c3944STomasz Duszynski cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX; 34357fc9e47SNithin Dabilpuram cap->nonleaf.sched_wfq_packet_mode_supported = 0; 34457fc9e47SNithin Dabilpuram cap->nonleaf.sched_wfq_byte_mode_supported = 1; 345429c3944STomasz Duszynski cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES; 346429c3944STomasz Duszynski } else { 347429c3944STomasz Duszynski cap->stats_mask = RTE_TM_STATS_N_PKTS; 348429c3944STomasz Duszynski } 349429c3944STomasz Duszynski 350429c3944STomasz Duszynski return 0; 351429c3944STomasz Duszynski } 352429c3944STomasz Duszynski 353429c3944STomasz Duszynski /** 354429c3944STomasz Duszynski * Get shaper profile using its id. 355429c3944STomasz Duszynski * 356429c3944STomasz Duszynski * @param priv Pointer to the port's private data. 357429c3944STomasz Duszynski * @param shaper_profile_id Id used by the shaper. 358429c3944STomasz Duszynski * @returns Pointer to the shaper profile if exists, NULL otherwise. 359429c3944STomasz Duszynski */ 360429c3944STomasz Duszynski static struct mrvl_tm_shaper_profile * 361429c3944STomasz Duszynski mrvl_shaper_profile_from_id(struct mrvl_priv *priv, uint32_t shaper_profile_id) 362429c3944STomasz Duszynski { 363429c3944STomasz Duszynski struct mrvl_tm_shaper_profile *profile; 364429c3944STomasz Duszynski 365429c3944STomasz Duszynski LIST_FOREACH(profile, &priv->shaper_profiles, next) 366429c3944STomasz Duszynski if (profile->id == shaper_profile_id) 367429c3944STomasz Duszynski return profile; 368429c3944STomasz Duszynski 369429c3944STomasz Duszynski return NULL; 370429c3944STomasz Duszynski } 371429c3944STomasz Duszynski 372429c3944STomasz Duszynski /** 373429c3944STomasz Duszynski * Add a new shaper profile. 374429c3944STomasz Duszynski * 375429c3944STomasz Duszynski * @param dev Pointer to the device. 376429c3944STomasz Duszynski * @param shaper_profile_id Id of the new profile. 377429c3944STomasz Duszynski * @param params Pointer to the shaper profile parameters. 378429c3944STomasz Duszynski * @param error Pointer to the error. 379429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 380429c3944STomasz Duszynski */ 381429c3944STomasz Duszynski static int 382429c3944STomasz Duszynski mrvl_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, 383*39533238SBruce Richardson const struct rte_tm_shaper_params *params, 384429c3944STomasz Duszynski struct rte_tm_error *error) 385429c3944STomasz Duszynski { 386429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 387429c3944STomasz Duszynski struct mrvl_tm_shaper_profile *profile; 388429c3944STomasz Duszynski 389e622c1a8SDana Vardi if (!priv->configured) 390e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 391e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 392e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 393e622c1a8SDana Vardi 394429c3944STomasz Duszynski if (!params) 395429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 396429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 397429c3944STomasz Duszynski NULL, NULL); 398429c3944STomasz Duszynski 399429c3944STomasz Duszynski if (params->committed.rate) 400429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 401429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE, 402429c3944STomasz Duszynski NULL, "Committed rate not supported\n"); 403429c3944STomasz Duszynski 404429c3944STomasz Duszynski if (params->committed.size) 405429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 406429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE, 407429c3944STomasz Duszynski NULL, "Committed bucket size not supported\n"); 408429c3944STomasz Duszynski 409429c3944STomasz Duszynski if (params->peak.rate < MRVL_RATE_MIN || 410429c3944STomasz Duszynski params->peak.rate > priv->rate_max) 411429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 412429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, 413429c3944STomasz Duszynski NULL, "Peak rate is out of range\n"); 414429c3944STomasz Duszynski 415429c3944STomasz Duszynski if (params->peak.size < MRVL_BURST_MIN || 416429c3944STomasz Duszynski params->peak.size > MRVL_BURST_MAX) 417429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 418429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, 419429c3944STomasz Duszynski NULL, "Peak size is out of range\n"); 420429c3944STomasz Duszynski 421429c3944STomasz Duszynski if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE) 422429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 423429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID, 424429c3944STomasz Duszynski NULL, "Wrong shaper profile id\n"); 425429c3944STomasz Duszynski 426429c3944STomasz Duszynski profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id); 427429c3944STomasz Duszynski if (profile) 428429c3944STomasz Duszynski return -rte_tm_error_set(error, EEXIST, 429429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID, 430429c3944STomasz Duszynski NULL, "Profile id already exists\n"); 431429c3944STomasz Duszynski 432429c3944STomasz Duszynski profile = rte_zmalloc_socket(NULL, sizeof(*profile), 0, 433429c3944STomasz Duszynski rte_socket_id()); 434429c3944STomasz Duszynski if (!profile) 435429c3944STomasz Duszynski return -rte_tm_error_set(error, ENOMEM, 436429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 437429c3944STomasz Duszynski NULL, NULL); 438429c3944STomasz Duszynski 439429c3944STomasz Duszynski profile->id = shaper_profile_id; 440429c3944STomasz Duszynski rte_memcpy(&profile->params, params, sizeof(profile->params)); 441429c3944STomasz Duszynski 442429c3944STomasz Duszynski LIST_INSERT_HEAD(&priv->shaper_profiles, profile, next); 443429c3944STomasz Duszynski 444429c3944STomasz Duszynski return 0; 445429c3944STomasz Duszynski } 446429c3944STomasz Duszynski 447429c3944STomasz Duszynski /** 448429c3944STomasz Duszynski * Remove a shaper profile. 449429c3944STomasz Duszynski * 450429c3944STomasz Duszynski * @param dev Pointer to the device. 451429c3944STomasz Duszynski * @param shaper_profile_id Id of the shaper profile. 452429c3944STomasz Duszynski * @param error Pointer to the error. 453429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 454429c3944STomasz Duszynski */ 455429c3944STomasz Duszynski static int 456429c3944STomasz Duszynski mrvl_shaper_profile_delete(struct rte_eth_dev *dev, uint32_t shaper_profile_id, 457429c3944STomasz Duszynski struct rte_tm_error *error) 458429c3944STomasz Duszynski { 459429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 460429c3944STomasz Duszynski struct mrvl_tm_shaper_profile *profile; 461429c3944STomasz Duszynski 462e622c1a8SDana Vardi if (!priv->configured) 463e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 464e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 465e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 466e622c1a8SDana Vardi 467429c3944STomasz Duszynski profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id); 468429c3944STomasz Duszynski if (!profile) 469429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 470429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID, 471429c3944STomasz Duszynski NULL, "Profile id does not exist\n"); 472429c3944STomasz Duszynski 473429c3944STomasz Duszynski if (profile->refcnt) 474429c3944STomasz Duszynski return -rte_tm_error_set(error, EPERM, 475429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID, 476429c3944STomasz Duszynski NULL, "Profile is used\n"); 477429c3944STomasz Duszynski 478429c3944STomasz Duszynski LIST_REMOVE(profile, next); 479429c3944STomasz Duszynski rte_free(profile); 480429c3944STomasz Duszynski 481429c3944STomasz Duszynski return 0; 482429c3944STomasz Duszynski } 483429c3944STomasz Duszynski 484429c3944STomasz Duszynski /** 485429c3944STomasz Duszynski * Check node parameters. 486429c3944STomasz Duszynski * 487429c3944STomasz Duszynski * @param dev Pointer to the device. 488429c3944STomasz Duszynski * @param node_id Id used by the node. 489429c3944STomasz Duszynski * @param priority Priority value. 490429c3944STomasz Duszynski * @param weight Weight value. 491429c3944STomasz Duszynski * @param level_id Id of the level. 492429c3944STomasz Duszynski * @param params Pointer to the node parameters. 493429c3944STomasz Duszynski * @param error Pointer to the error. 494429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 495429c3944STomasz Duszynski */ 496429c3944STomasz Duszynski static int 497429c3944STomasz Duszynski mrvl_node_check_params(struct rte_eth_dev *dev, uint32_t node_id, 498429c3944STomasz Duszynski uint32_t priority, uint32_t weight, uint32_t level_id, 4995d49af62SBruce Richardson const struct rte_tm_node_params *params, 500429c3944STomasz Duszynski struct rte_tm_error *error) 501429c3944STomasz Duszynski { 502429c3944STomasz Duszynski if (node_id == RTE_TM_NODE_ID_NULL) 503429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, RTE_TM_NODE_ID_NULL, 504429c3944STomasz Duszynski NULL, "Node id is invalid\n"); 505429c3944STomasz Duszynski 506429c3944STomasz Duszynski if (priority) 507429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 508429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PRIORITY, 509429c3944STomasz Duszynski NULL, "Priority should be 0\n"); 510429c3944STomasz Duszynski 511429c3944STomasz Duszynski if (weight > MRVL_WEIGHT_MAX) 512429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 513429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_WEIGHT, 514429c3944STomasz Duszynski NULL, "Weight is out of range\n"); 515429c3944STomasz Duszynski 516429c3944STomasz Duszynski if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE) 517429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 518429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_LEVEL_ID, 519429c3944STomasz Duszynski NULL, "Wrong level id\n"); 520429c3944STomasz Duszynski 521429c3944STomasz Duszynski if (!params) 522429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 523429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 524429c3944STomasz Duszynski NULL, NULL); 525429c3944STomasz Duszynski 526429c3944STomasz Duszynski if (params->shared_shaper_id) 527429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 528429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID, 529429c3944STomasz Duszynski NULL, "Shared shaper is not supported\n"); 530429c3944STomasz Duszynski 531429c3944STomasz Duszynski if (params->n_shared_shapers) 532429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 533429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS, 534429c3944STomasz Duszynski NULL, "Shared shaper is not supported\n"); 535429c3944STomasz Duszynski 536429c3944STomasz Duszynski /* verify port (root node) settings */ 537429c3944STomasz Duszynski if (node_id >= dev->data->nb_tx_queues) { 538429c3944STomasz Duszynski if (params->nonleaf.wfq_weight_mode) 539429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 540429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE, 541429c3944STomasz Duszynski NULL, "WFQ is not supported\n"); 542429c3944STomasz Duszynski 543429c3944STomasz Duszynski if (params->nonleaf.n_sp_priorities != 1) 544429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 545429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES, 546429c3944STomasz Duszynski NULL, "SP is not supported\n"); 547429c3944STomasz Duszynski 548429c3944STomasz Duszynski if (params->stats_mask & ~(RTE_TM_STATS_N_PKTS | 549429c3944STomasz Duszynski RTE_TM_STATS_N_BYTES)) 550429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 551429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS, 552429c3944STomasz Duszynski NULL, 553429c3944STomasz Duszynski "Requested port stats are not supported\n"); 554429c3944STomasz Duszynski 555429c3944STomasz Duszynski return 0; 556429c3944STomasz Duszynski } 557429c3944STomasz Duszynski 558429c3944STomasz Duszynski /* verify txq (leaf node) settings */ 559429c3944STomasz Duszynski if (params->leaf.cman) 560429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 561429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN, 562429c3944STomasz Duszynski NULL, 563429c3944STomasz Duszynski "Congestion mngmt is not supported\n"); 564429c3944STomasz Duszynski 565429c3944STomasz Duszynski if (params->leaf.wred.wred_profile_id) 566429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 567429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID, 568429c3944STomasz Duszynski NULL, "WRED is not supported\n"); 569429c3944STomasz Duszynski 570429c3944STomasz Duszynski if (params->leaf.wred.shared_wred_context_id) 571429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 572429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID, 573429c3944STomasz Duszynski NULL, "WRED is not supported\n"); 574429c3944STomasz Duszynski 575429c3944STomasz Duszynski if (params->leaf.wred.n_shared_wred_contexts) 576429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 577429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS, 578429c3944STomasz Duszynski NULL, "WRED is not supported\n"); 579429c3944STomasz Duszynski 580429c3944STomasz Duszynski if (params->stats_mask & ~RTE_TM_STATS_N_PKTS) 581429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 582429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS, 583429c3944STomasz Duszynski NULL, 584429c3944STomasz Duszynski "Requested txq stats are not supported\n"); 585429c3944STomasz Duszynski 586429c3944STomasz Duszynski return 0; 587429c3944STomasz Duszynski } 588429c3944STomasz Duszynski 589429c3944STomasz Duszynski /** 590429c3944STomasz Duszynski * Add a new node. 591429c3944STomasz Duszynski * 592429c3944STomasz Duszynski * @param dev Pointer to the device. 593429c3944STomasz Duszynski * @param node_id Id of the node. 594429c3944STomasz Duszynski * @param parent_node_id Id of the parent node. 595429c3944STomasz Duszynski * @param priority Priority value. 596429c3944STomasz Duszynski * @param weight Weight value. 597429c3944STomasz Duszynski * @param level_id Id of the level. 598429c3944STomasz Duszynski * @param params Pointer to the node parameters. 599429c3944STomasz Duszynski * @param error Pointer to the error. 600429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 601429c3944STomasz Duszynski */ 602429c3944STomasz Duszynski static int 603429c3944STomasz Duszynski mrvl_node_add(struct rte_eth_dev *dev, uint32_t node_id, 604429c3944STomasz Duszynski uint32_t parent_node_id, uint32_t priority, uint32_t weight, 6055d49af62SBruce Richardson uint32_t level_id, const struct rte_tm_node_params *params, 606429c3944STomasz Duszynski struct rte_tm_error *error) 607429c3944STomasz Duszynski { 608429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 609429c3944STomasz Duszynski struct mrvl_tm_shaper_profile *profile = NULL; 610429c3944STomasz Duszynski struct mrvl_tm_node *node, *parent = NULL; 611429c3944STomasz Duszynski int ret; 612429c3944STomasz Duszynski 613e622c1a8SDana Vardi if (!priv->configured) 614e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 615e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 616e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 617e622c1a8SDana Vardi 618429c3944STomasz Duszynski if (priv->ppio) 619429c3944STomasz Duszynski return -rte_tm_error_set(error, EPERM, 620429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 621429c3944STomasz Duszynski NULL, "Port is already started\n"); 622429c3944STomasz Duszynski 623429c3944STomasz Duszynski ret = mrvl_node_check_params(dev, node_id, priority, weight, level_id, 624429c3944STomasz Duszynski params, error); 625429c3944STomasz Duszynski if (ret) 626429c3944STomasz Duszynski return ret; 627429c3944STomasz Duszynski 628429c3944STomasz Duszynski if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) { 629429c3944STomasz Duszynski profile = mrvl_shaper_profile_from_id(priv, 630429c3944STomasz Duszynski params->shaper_profile_id); 631429c3944STomasz Duszynski if (!profile) 632429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 633429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID, 634429c3944STomasz Duszynski NULL, "Shaper id does not exist\n"); 635429c3944STomasz Duszynski } 636429c3944STomasz Duszynski 637429c3944STomasz Duszynski if (parent_node_id == RTE_TM_NODE_ID_NULL) { 638429c3944STomasz Duszynski LIST_FOREACH(node, &priv->nodes, next) { 639429c3944STomasz Duszynski if (node->type != MRVL_NODE_PORT) 640429c3944STomasz Duszynski continue; 641429c3944STomasz Duszynski 642429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 643429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 644429c3944STomasz Duszynski NULL, "Root node exists\n"); 645429c3944STomasz Duszynski } 646429c3944STomasz Duszynski } else { 647429c3944STomasz Duszynski parent = mrvl_node_from_id(priv, parent_node_id); 648429c3944STomasz Duszynski if (!parent) 649429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 650429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID, 651429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 652429c3944STomasz Duszynski } 653429c3944STomasz Duszynski 654429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 655429c3944STomasz Duszynski if (node) 656429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 657429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 658429c3944STomasz Duszynski NULL, "Node id already exists\n"); 659429c3944STomasz Duszynski 660429c3944STomasz Duszynski node = rte_zmalloc_socket(NULL, sizeof(*node), 0, rte_socket_id()); 661429c3944STomasz Duszynski if (!node) 662429c3944STomasz Duszynski return -rte_tm_error_set(error, ENOMEM, 663429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 664429c3944STomasz Duszynski NULL, NULL); 665429c3944STomasz Duszynski 666429c3944STomasz Duszynski node->id = node_id; 667429c3944STomasz Duszynski node->type = parent_node_id == RTE_TM_NODE_ID_NULL ? MRVL_NODE_PORT : 668429c3944STomasz Duszynski MRVL_NODE_QUEUE; 669429c3944STomasz Duszynski 670429c3944STomasz Duszynski if (parent) { 671429c3944STomasz Duszynski node->parent = parent; 672429c3944STomasz Duszynski parent->refcnt++; 673429c3944STomasz Duszynski } 674429c3944STomasz Duszynski 675429c3944STomasz Duszynski if (profile) { 676429c3944STomasz Duszynski node->profile = profile; 677429c3944STomasz Duszynski profile->refcnt++; 678429c3944STomasz Duszynski } 679429c3944STomasz Duszynski 680429c3944STomasz Duszynski node->weight = weight; 681429c3944STomasz Duszynski node->stats_mask = params->stats_mask; 682429c3944STomasz Duszynski 683429c3944STomasz Duszynski LIST_INSERT_HEAD(&priv->nodes, node, next); 684429c3944STomasz Duszynski 685429c3944STomasz Duszynski return 0; 686429c3944STomasz Duszynski } 687429c3944STomasz Duszynski 688429c3944STomasz Duszynski /** 689429c3944STomasz Duszynski * Delete a node. 690429c3944STomasz Duszynski * 691429c3944STomasz Duszynski * @param dev Pointer to the device. 692429c3944STomasz Duszynski * @param node_id Id of the node. 693429c3944STomasz Duszynski * @param error Pointer to the error. 694429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 695429c3944STomasz Duszynski */ 696429c3944STomasz Duszynski static int 697429c3944STomasz Duszynski mrvl_node_delete(struct rte_eth_dev *dev, uint32_t node_id, 698429c3944STomasz Duszynski struct rte_tm_error *error) 699429c3944STomasz Duszynski { 700429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 701429c3944STomasz Duszynski struct mrvl_tm_node *node; 702429c3944STomasz Duszynski 703e622c1a8SDana Vardi if (!priv->configured) 704e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 705e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 706e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 707e622c1a8SDana Vardi 708429c3944STomasz Duszynski if (priv->ppio) { 709429c3944STomasz Duszynski return -rte_tm_error_set(error, EPERM, 710429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 711429c3944STomasz Duszynski NULL, "Port is already started\n"); 712429c3944STomasz Duszynski } 713429c3944STomasz Duszynski 714429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 715429c3944STomasz Duszynski if (!node) 716429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 717429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 718429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 719429c3944STomasz Duszynski 720429c3944STomasz Duszynski if (node->refcnt) 721429c3944STomasz Duszynski return -rte_tm_error_set(error, EPERM, 722429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 723429c3944STomasz Duszynski NULL, "Node id is used\n"); 724429c3944STomasz Duszynski 725429c3944STomasz Duszynski if (node->parent) 726429c3944STomasz Duszynski node->parent->refcnt--; 727429c3944STomasz Duszynski 728429c3944STomasz Duszynski if (node->profile) 729429c3944STomasz Duszynski node->profile->refcnt--; 730429c3944STomasz Duszynski 731429c3944STomasz Duszynski LIST_REMOVE(node, next); 732429c3944STomasz Duszynski rte_free(node); 733429c3944STomasz Duszynski 734429c3944STomasz Duszynski return 0; 735429c3944STomasz Duszynski } 736429c3944STomasz Duszynski 737429c3944STomasz Duszynski /** 738429c3944STomasz Duszynski * Helper for suspending specific tx queue. 739429c3944STomasz Duszynski * 740429c3944STomasz Duszynski * @param dev Pointer to the device. 741429c3944STomasz Duszynski * @param node_id Id used by this node. 742429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 743429c3944STomasz Duszynski */ 744429c3944STomasz Duszynski static int mrvl_node_suspend_one(struct rte_eth_dev *dev, uint32_t node_id, 745429c3944STomasz Duszynski struct rte_tm_error *error) 746429c3944STomasz Duszynski { 747429c3944STomasz Duszynski int ret = dev->dev_ops->tx_queue_stop(dev, node_id); 748429c3944STomasz Duszynski if (ret) 749429c3944STomasz Duszynski return -rte_tm_error_set(error, ret, 750429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 751429c3944STomasz Duszynski NULL, "Failed to suspend a txq\n"); 752429c3944STomasz Duszynski 753429c3944STomasz Duszynski return 0; 754429c3944STomasz Duszynski } 755429c3944STomasz Duszynski 756429c3944STomasz Duszynski /** 757429c3944STomasz Duszynski * Suspend a node. 758429c3944STomasz Duszynski * 759429c3944STomasz Duszynski * @param dev Pointer to the device. 760429c3944STomasz Duszynski * @param node_id Id of the node. 761429c3944STomasz Duszynski * @param error Pointer to the error. 762429c3944STomasz Duszynski * returns 0 on success, negative value otherwise. 763429c3944STomasz Duszynski */ 764429c3944STomasz Duszynski static int 765429c3944STomasz Duszynski mrvl_node_suspend(struct rte_eth_dev *dev, uint32_t node_id, 766429c3944STomasz Duszynski struct rte_tm_error *error) 767429c3944STomasz Duszynski { 768429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 769429c3944STomasz Duszynski struct mrvl_tm_node *node, *tmp; 770429c3944STomasz Duszynski int ret; 771429c3944STomasz Duszynski 772e622c1a8SDana Vardi if (!priv->configured) 773e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 774e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 775e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 776e622c1a8SDana Vardi 777429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 778429c3944STomasz Duszynski if (!node) 779429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 780429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 781429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 782429c3944STomasz Duszynski 783429c3944STomasz Duszynski if (!node->parent) { 784429c3944STomasz Duszynski LIST_FOREACH(tmp, &priv->nodes, next) { 785429c3944STomasz Duszynski if (!tmp->parent) 786429c3944STomasz Duszynski continue; 787429c3944STomasz Duszynski 788429c3944STomasz Duszynski if (node != tmp->parent) 789429c3944STomasz Duszynski continue; 790429c3944STomasz Duszynski 791429c3944STomasz Duszynski ret = mrvl_node_suspend_one(dev, tmp->id, error); 792429c3944STomasz Duszynski if (ret) 793429c3944STomasz Duszynski return ret; 794429c3944STomasz Duszynski } 795429c3944STomasz Duszynski 796429c3944STomasz Duszynski return 0; 797429c3944STomasz Duszynski } 798429c3944STomasz Duszynski 799429c3944STomasz Duszynski return mrvl_node_suspend_one(dev, node_id, error); 800429c3944STomasz Duszynski } 801429c3944STomasz Duszynski 802429c3944STomasz Duszynski /** 803429c3944STomasz Duszynski * Resume a node. 804429c3944STomasz Duszynski * 805429c3944STomasz Duszynski * @param dev Pointer to the device. 806429c3944STomasz Duszynski * @param node_id Id of the node. 807429c3944STomasz Duszynski * @param error Pointer to the error. 808429c3944STomasz Duszynski * returns 0 on success, negative value otherwise. 809429c3944STomasz Duszynski */ 810429c3944STomasz Duszynski static int 811429c3944STomasz Duszynski mrvl_node_resume(struct rte_eth_dev *dev, uint32_t node_id, 812429c3944STomasz Duszynski struct rte_tm_error *error) 813429c3944STomasz Duszynski { 814429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 815429c3944STomasz Duszynski struct mrvl_tm_node *node; 816429c3944STomasz Duszynski int ret; 817429c3944STomasz Duszynski 818e622c1a8SDana Vardi if (!priv->configured) 819e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 820e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 821e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 822e622c1a8SDana Vardi 823429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 824429c3944STomasz Duszynski if (!node) 825429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 826429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 827429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 828429c3944STomasz Duszynski 829429c3944STomasz Duszynski 830429c3944STomasz Duszynski if (!node->parent) 831429c3944STomasz Duszynski return -rte_tm_error_set(error, EPERM, 832429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 833429c3944STomasz Duszynski NULL, "Cannot suspend a port\n"); 834429c3944STomasz Duszynski 835429c3944STomasz Duszynski ret = dev->dev_ops->tx_queue_start(dev, node_id); 836429c3944STomasz Duszynski if (ret) 837429c3944STomasz Duszynski return -rte_tm_error_set(error, ret, 838429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 839429c3944STomasz Duszynski NULL, "Failed to resume a txq\n"); 840429c3944STomasz Duszynski return 0; 841429c3944STomasz Duszynski } 842429c3944STomasz Duszynski 843429c3944STomasz Duszynski /** 844429c3944STomasz Duszynski * Apply traffic manager hierarchy. 845429c3944STomasz Duszynski * 846429c3944STomasz Duszynski * @param dev Pointer to the device. 847429c3944STomasz Duszynski * @param clear_on_fail Flag indicating whether to do cleanup on the failure. 848429c3944STomasz Duszynski * @param error Pointer to the error. 849429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 850429c3944STomasz Duszynski */ 851429c3944STomasz Duszynski static int 852429c3944STomasz Duszynski mrvl_hierarchy_commit(struct rte_eth_dev *dev, int clear_on_fail, 853429c3944STomasz Duszynski struct rte_tm_error *error) 854429c3944STomasz Duszynski { 855429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 856429c3944STomasz Duszynski struct mrvl_tm_node *node; 857429c3944STomasz Duszynski int ret; 858429c3944STomasz Duszynski 859e622c1a8SDana Vardi if (!priv->configured) 860e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 861e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 862e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 863e622c1a8SDana Vardi 864429c3944STomasz Duszynski if (priv->ppio) { 865429c3944STomasz Duszynski ret = -rte_tm_error_set(error, EPERM, 866429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 867429c3944STomasz Duszynski NULL, "Port is already started\n"); 868429c3944STomasz Duszynski goto out; 869429c3944STomasz Duszynski } 870429c3944STomasz Duszynski 871429c3944STomasz Duszynski LIST_FOREACH(node, &priv->nodes, next) { 872429c3944STomasz Duszynski struct pp2_ppio_outq_params *p; 873429c3944STomasz Duszynski 874429c3944STomasz Duszynski if (node->type == MRVL_NODE_PORT) { 875429c3944STomasz Duszynski if (!node->profile) 876429c3944STomasz Duszynski continue; 877429c3944STomasz Duszynski 878429c3944STomasz Duszynski priv->ppio_params.rate_limit_enable = 1; 879429c3944STomasz Duszynski priv->ppio_params.rate_limit_params.cir = 880429c3944STomasz Duszynski node->profile->params.peak.rate * 8 / 1000; 881429c3944STomasz Duszynski priv->ppio_params.rate_limit_params.cbs = 882429c3944STomasz Duszynski node->profile->params.peak.size / 1000; 883429c3944STomasz Duszynski 884429c3944STomasz Duszynski MRVL_LOG(INFO, 885429c3944STomasz Duszynski "Port rate limit overrides txqs rate limit"); 886429c3944STomasz Duszynski 887429c3944STomasz Duszynski continue; 888429c3944STomasz Duszynski } 889429c3944STomasz Duszynski 890429c3944STomasz Duszynski if (node->id >= dev->data->nb_tx_queues) { 891429c3944STomasz Duszynski ret = -rte_tm_error_set(error, EINVAL, 892429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, NULL, 893429c3944STomasz Duszynski "Not enough txqs are configured\n"); 894429c3944STomasz Duszynski goto out; 895429c3944STomasz Duszynski } 896429c3944STomasz Duszynski 897429c3944STomasz Duszynski p = &priv->ppio_params.outqs_params.outqs_params[node->id]; 898429c3944STomasz Duszynski 899429c3944STomasz Duszynski if (node->weight) { 900429c3944STomasz Duszynski p->sched_mode = PP2_PPIO_SCHED_M_WRR; 901429c3944STomasz Duszynski p->weight = node->weight; 902429c3944STomasz Duszynski } else { 903429c3944STomasz Duszynski p->sched_mode = PP2_PPIO_SCHED_M_SP; 904429c3944STomasz Duszynski p->weight = 0; 905429c3944STomasz Duszynski } 906429c3944STomasz Duszynski 907429c3944STomasz Duszynski if (node->profile) { 908429c3944STomasz Duszynski p->rate_limit_enable = 1; 909429c3944STomasz Duszynski /* convert Bytes/s to kilo bits/s */ 910429c3944STomasz Duszynski p->rate_limit_params.cir = 911429c3944STomasz Duszynski node->profile->params.peak.rate * 8 / 1000; 912429c3944STomasz Duszynski /* convert bits to kilo bits */ 913429c3944STomasz Duszynski p->rate_limit_params.cbs = 914429c3944STomasz Duszynski node->profile->params.peak.size / 1000; 915429c3944STomasz Duszynski } else { 916429c3944STomasz Duszynski p->rate_limit_enable = 0; 917429c3944STomasz Duszynski p->rate_limit_params.cir = 0; 918429c3944STomasz Duszynski p->rate_limit_params.cbs = 0; 919429c3944STomasz Duszynski } 920429c3944STomasz Duszynski } 921429c3944STomasz Duszynski 922429c3944STomasz Duszynski /* reset to defaults in case applied tm hierarchy is empty */ 923429c3944STomasz Duszynski if (LIST_EMPTY(&priv->nodes)) { 924429c3944STomasz Duszynski int i; 925429c3944STomasz Duszynski 926429c3944STomasz Duszynski for (i = 0; i < priv->ppio_params.outqs_params.num_outqs; i++) { 927429c3944STomasz Duszynski struct pp2_ppio_outq_params *p = 928429c3944STomasz Duszynski &priv->ppio_params.outqs_params.outqs_params[i]; 929429c3944STomasz Duszynski 930429c3944STomasz Duszynski p->sched_mode = PP2_PPIO_SCHED_M_WRR; 931429c3944STomasz Duszynski p->weight = 0; 932429c3944STomasz Duszynski p->rate_limit_enable = 0; 933429c3944STomasz Duszynski p->rate_limit_params.cir = 0; 934429c3944STomasz Duszynski p->rate_limit_params.cbs = 0; 935429c3944STomasz Duszynski } 936429c3944STomasz Duszynski } 937429c3944STomasz Duszynski 938429c3944STomasz Duszynski return 0; 939429c3944STomasz Duszynski out: 940429c3944STomasz Duszynski if (clear_on_fail) { 941429c3944STomasz Duszynski mrvl_tm_deinit(dev); 942429c3944STomasz Duszynski mrvl_tm_init(dev); 943429c3944STomasz Duszynski } 944429c3944STomasz Duszynski 945429c3944STomasz Duszynski return ret; 946429c3944STomasz Duszynski } 947429c3944STomasz Duszynski 948429c3944STomasz Duszynski /** 949429c3944STomasz Duszynski * Read statistics counters for current node. 950429c3944STomasz Duszynski * 951429c3944STomasz Duszynski * @param dev Pointer to the device. 952429c3944STomasz Duszynski * @param node_id Id of the node. 953429c3944STomasz Duszynski * @param stats Pointer to the statistics counters. 954429c3944STomasz Duszynski * @param stats_mask Pointer to mask of enabled statistics counters 955429c3944STomasz Duszynski * that are retrieved. 956429c3944STomasz Duszynski * @param clear Flag indicating whether to clear statistics. 957429c3944STomasz Duszynski * Non-zero value clears statistics. 958429c3944STomasz Duszynski * @param error Pointer to the error. 959429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 960429c3944STomasz Duszynski */ 961429c3944STomasz Duszynski static int 962429c3944STomasz Duszynski mrvl_node_stats_read(struct rte_eth_dev *dev, uint32_t node_id, 963429c3944STomasz Duszynski struct rte_tm_node_stats *stats, uint64_t *stats_mask, 964429c3944STomasz Duszynski int clear, struct rte_tm_error *error) 965429c3944STomasz Duszynski { 966429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 967429c3944STomasz Duszynski struct mrvl_tm_node *node; 968429c3944STomasz Duszynski int ret; 969429c3944STomasz Duszynski 970e622c1a8SDana Vardi if (!priv->configured) 971e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 972e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 973e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 974e622c1a8SDana Vardi 975429c3944STomasz Duszynski if (!priv->ppio) { 976429c3944STomasz Duszynski return -rte_tm_error_set(error, EPERM, 977429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, 978429c3944STomasz Duszynski NULL, "Port is not started\n"); 979429c3944STomasz Duszynski } 980429c3944STomasz Duszynski 981429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 982429c3944STomasz Duszynski if (!node) 983429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 984429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 985429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 986429c3944STomasz Duszynski 987429c3944STomasz Duszynski if (stats_mask) 988429c3944STomasz Duszynski *stats_mask = node->stats_mask; 989429c3944STomasz Duszynski 990429c3944STomasz Duszynski if (!stats) 991429c3944STomasz Duszynski return 0; 992429c3944STomasz Duszynski 993429c3944STomasz Duszynski memset(stats, 0, sizeof(*stats)); 994429c3944STomasz Duszynski 995429c3944STomasz Duszynski if (!node->parent) { 996429c3944STomasz Duszynski struct pp2_ppio_statistics s; 997429c3944STomasz Duszynski 998429c3944STomasz Duszynski memset(&s, 0, sizeof(s)); 999429c3944STomasz Duszynski ret = pp2_ppio_get_statistics(priv->ppio, &s, clear); 1000429c3944STomasz Duszynski if (ret) 1001429c3944STomasz Duszynski return -rte_tm_error_set(error, -ret, 1002429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL, 1003429c3944STomasz Duszynski "Failed to read port statistics\n"); 1004429c3944STomasz Duszynski 1005429c3944STomasz Duszynski if (node->stats_mask & RTE_TM_STATS_N_PKTS) 1006429c3944STomasz Duszynski stats->n_pkts = s.tx_packets; 1007429c3944STomasz Duszynski 1008429c3944STomasz Duszynski if (node->stats_mask & RTE_TM_STATS_N_BYTES) 1009429c3944STomasz Duszynski stats->n_bytes = s.tx_bytes; 1010429c3944STomasz Duszynski } else { 1011429c3944STomasz Duszynski struct pp2_ppio_outq_statistics s; 1012429c3944STomasz Duszynski 1013429c3944STomasz Duszynski memset(&s, 0, sizeof(s)); 1014429c3944STomasz Duszynski ret = pp2_ppio_outq_get_statistics(priv->ppio, node_id, &s, 1015429c3944STomasz Duszynski clear); 1016429c3944STomasz Duszynski if (ret) 1017429c3944STomasz Duszynski return -rte_tm_error_set(error, -ret, 1018429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL, 1019429c3944STomasz Duszynski "Failed to read txq statistics\n"); 1020429c3944STomasz Duszynski 1021429c3944STomasz Duszynski if (node->stats_mask & RTE_TM_STATS_N_PKTS) 1022429c3944STomasz Duszynski stats->n_pkts = s.deq_desc; 1023429c3944STomasz Duszynski } 1024429c3944STomasz Duszynski 1025429c3944STomasz Duszynski return 0; 1026429c3944STomasz Duszynski } 1027429c3944STomasz Duszynski 1028429c3944STomasz Duszynski /** 1029429c3944STomasz Duszynski * Update node statistics. 1030429c3944STomasz Duszynski * 1031429c3944STomasz Duszynski * @param dev Pointer to the device. 1032429c3944STomasz Duszynski * @param node_id Id of the node. 1033429c3944STomasz Duszynski * @param stats_mask Bitmask of statistics counters to be enabled. 1034429c3944STomasz Duszynski * @param error Pointer to the error. 1035429c3944STomasz Duszynski * @returns 0 on success, negative value otherwise. 1036429c3944STomasz Duszynski */ 1037429c3944STomasz Duszynski static int 1038429c3944STomasz Duszynski mrvl_node_stats_update(struct rte_eth_dev *dev, uint32_t node_id, 1039429c3944STomasz Duszynski uint64_t stats_mask, struct rte_tm_error *error) 1040429c3944STomasz Duszynski { 1041429c3944STomasz Duszynski struct mrvl_priv *priv = dev->data->dev_private; 1042429c3944STomasz Duszynski struct mrvl_tm_node *node; 1043429c3944STomasz Duszynski 1044e622c1a8SDana Vardi if (!priv->configured) 1045e622c1a8SDana Vardi return -rte_tm_error_set(error, ENODEV, 1046e622c1a8SDana Vardi RTE_TM_ERROR_TYPE_UNSPECIFIED, 1047e622c1a8SDana Vardi NULL, "Port didn't configured\n"); 1048e622c1a8SDana Vardi 1049429c3944STomasz Duszynski node = mrvl_node_from_id(priv, node_id); 1050429c3944STomasz Duszynski if (!node) 1051429c3944STomasz Duszynski return -rte_tm_error_set(error, ENODEV, 1052429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_ID, 1053429c3944STomasz Duszynski NULL, "Node id does not exist\n"); 1054429c3944STomasz Duszynski 1055429c3944STomasz Duszynski if (!node->parent) { 1056429c3944STomasz Duszynski if (stats_mask & ~(RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES)) 1057429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 1058429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS, 1059429c3944STomasz Duszynski NULL, 1060429c3944STomasz Duszynski "Requested port stats are not supported\n"); 1061429c3944STomasz Duszynski } else { 1062429c3944STomasz Duszynski if (stats_mask & ~RTE_TM_STATS_N_PKTS) 1063429c3944STomasz Duszynski return -rte_tm_error_set(error, EINVAL, 1064429c3944STomasz Duszynski RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS, 1065429c3944STomasz Duszynski NULL, 1066429c3944STomasz Duszynski "Requested txq stats are not supported\n"); 1067429c3944STomasz Duszynski } 1068429c3944STomasz Duszynski 1069429c3944STomasz Duszynski node->stats_mask = stats_mask; 1070429c3944STomasz Duszynski 1071429c3944STomasz Duszynski return 0; 1072429c3944STomasz Duszynski } 1073429c3944STomasz Duszynski 1074429c3944STomasz Duszynski const struct rte_tm_ops mrvl_tm_ops = { 1075429c3944STomasz Duszynski .node_type_get = mrvl_node_type_get, 1076429c3944STomasz Duszynski .capabilities_get = mrvl_capabilities_get, 1077429c3944STomasz Duszynski .level_capabilities_get = mrvl_level_capabilities_get, 1078429c3944STomasz Duszynski .node_capabilities_get = mrvl_node_capabilities_get, 1079429c3944STomasz Duszynski .shaper_profile_add = mrvl_shaper_profile_add, 1080429c3944STomasz Duszynski .shaper_profile_delete = mrvl_shaper_profile_delete, 1081429c3944STomasz Duszynski .node_add = mrvl_node_add, 1082429c3944STomasz Duszynski .node_delete = mrvl_node_delete, 1083429c3944STomasz Duszynski .node_suspend = mrvl_node_suspend, 1084429c3944STomasz Duszynski .node_resume = mrvl_node_resume, 1085429c3944STomasz Duszynski .hierarchy_commit = mrvl_hierarchy_commit, 1086429c3944STomasz Duszynski .node_stats_update = mrvl_node_stats_update, 1087429c3944STomasz Duszynski .node_stats_read = mrvl_node_stats_read, 1088429c3944STomasz Duszynski }; 1089