LCOV - code coverage report
Current view: top level - lib/ethdev - ethdev_private.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 140 197 71.1 %
Date: 2025-05-01 17:49:45 Functions: 14 18 77.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 86 150 57.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Gaƫtan Rivet
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <eal_export.h>
       6                 :            : #include <rte_debug.h>
       7                 :            : 
       8                 :            : #include "rte_ethdev.h"
       9                 :            : #include "rte_ethdev_trace_fp.h"
      10                 :            : #include "ethdev_driver.h"
      11                 :            : #include "ethdev_private.h"
      12                 :            : 
      13                 :            : static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data";
      14                 :            : 
      15                 :            : static const struct rte_memzone *eth_dev_shared_mz;
      16                 :            : struct eth_dev_shared *eth_dev_shared_data;
      17                 :            : 
      18                 :            : /* spinlock for eth device callbacks */
      19                 :            : rte_spinlock_t eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER;
      20                 :            : 
      21                 :            : uint16_t
      22                 :          0 : eth_dev_to_id(const struct rte_eth_dev *dev)
      23                 :            : {
      24         [ #  # ]:          0 :         if (dev == NULL)
      25                 :            :                 return RTE_MAX_ETHPORTS;
      26                 :          0 :         return dev - rte_eth_devices;
      27                 :            : }
      28                 :            : 
      29                 :            : struct rte_eth_dev *
      30                 :          0 : eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
      31                 :            :                 const void *data)
      32                 :            : {
      33                 :            :         struct rte_eth_dev *edev;
      34                 :            :         ptrdiff_t idx;
      35                 :            : 
      36                 :            :         /* Avoid Undefined Behaviour */
      37   [ #  #  #  # ]:          0 :         if (start != NULL &&
      38         [ #  # ]:          0 :             (start < &rte_eth_devices[0] ||
      39                 :            :              start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
      40                 :            :                 return NULL;
      41         [ #  # ]:          0 :         if (start != NULL)
      42                 :          0 :                 idx = eth_dev_to_id(start) + 1;
      43                 :            :         else
      44                 :            :                 idx = 0;
      45         [ #  # ]:          0 :         for (; idx < RTE_MAX_ETHPORTS; idx++) {
      46                 :          0 :                 edev = &rte_eth_devices[idx];
      47         [ #  # ]:          0 :                 if (cmp(edev, data) == 0)
      48                 :          0 :                         return edev;
      49                 :            :         }
      50                 :            :         return NULL;
      51                 :            : }
      52                 :            : 
      53                 :            : /* Put new value into list. */
      54                 :            : static int
      55                 :            : rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list,
      56                 :            :                        const uint16_t max_list, uint16_t val)
      57                 :            : {
      58                 :            :         uint16_t i;
      59                 :            : 
      60   [ +  +  +  + ]:        200 :         for (i = 0; i < *len_list; i++) {
      61   [ +  -  +  - ]:         66 :                 if (list[i] == val)
      62                 :            :                         return 0;
      63                 :            :         }
      64   [ +  -  +  - ]:        134 :         if (*len_list >= max_list)
      65                 :            :                 return -1;
      66                 :        134 :         list[(*len_list)++] = val;
      67                 :            :         return 0;
      68                 :            : }
      69                 :            : 
      70                 :            : /* Parse and enlist a range expression of "min-max" or a single value. */
      71                 :            : static char *
      72                 :        106 : rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list,
      73                 :            :         const uint16_t max_list)
      74                 :            : {
      75                 :            :         uint16_t lo, hi, val;
      76                 :        106 :         int result, n = 0;
      77                 :            :         char *pos = str;
      78                 :            : 
      79                 :        106 :         result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n);
      80         [ +  + ]:        106 :         if (result == 1) {
      81                 :         78 :                 if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0)
      82                 :            :                         return NULL;
      83         [ +  + ]:         28 :         } else if (result == 2) {
      84         [ +  - ]:         26 :                 if (lo > hi)
      85                 :            :                         return NULL;
      86         [ +  + ]:         82 :                 for (val = lo; val <= hi; val++) {
      87                 :            :                         if (rte_eth_devargs_enlist(list, len_list, max_list,
      88                 :            :                                                    val) != 0)
      89                 :            :                                 return NULL;
      90                 :            :                 }
      91                 :            :         } else
      92                 :            :                 return NULL;
      93                 :        104 :         return pos + n;
      94                 :            : }
      95                 :            : 
      96                 :            : /*
      97                 :            :  * Parse list of values separated by ",".
      98                 :            :  * Each value could be a range [min-max] or single number.
      99                 :            :  * Examples:
     100                 :            :  *  2               - single
     101                 :            :  *  [1,2,3]         - single list
     102                 :            :  *  [1,3-5,7,9-11]  - list with singles and ranges
     103                 :            :  */
     104                 :            : static char *
     105                 :         90 : rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list,
     106                 :            :         const uint16_t max_list)
     107                 :            : {
     108                 :            :         char *pos = str;
     109                 :            : 
     110         [ +  + ]:         90 :         if (*pos == '[')
     111                 :         46 :                 pos++;
     112                 :            :         while (1) {
     113                 :        106 :                 pos = rte_eth_devargs_process_range(pos, list, len_list,
     114                 :            :                                                     max_list);
     115         [ +  + ]:        106 :                 if (pos == NULL)
     116                 :            :                         return NULL;
     117         [ +  + ]:        104 :                 if (*pos != ',') /* end of list */
     118                 :            :                         break;
     119                 :         16 :                 pos++;
     120                 :            :         }
     121   [ +  +  +  + ]:         88 :         if (*str == '[' && *pos != ']')
     122                 :            :                 return NULL;
     123         [ +  + ]:         87 :         if (*pos == ']')
     124                 :         44 :                 pos++;
     125                 :            :         return pos;
     126                 :            : }
     127                 :            : 
     128                 :            : /*
     129                 :            :  * Parse representor ports from a single value or lists.
     130                 :            :  *
     131                 :            :  * Representor format:
     132                 :            :  *   #: range or single number of VF representor - legacy
     133                 :            :  *   [[c#]pf#]vf#: VF port representor/s
     134                 :            :  *   [[c#]pf#]sf#: SF port representor/s
     135                 :            :  *   [c#]pf#:      PF port representor/s
     136                 :            :  *
     137                 :            :  * Examples of #:
     138                 :            :  *  2               - single
     139                 :            :  *  [1,2,3]         - single list
     140                 :            :  *  [1,3-5,7,9-11]  - list with singles and ranges
     141                 :            :  */
     142                 :            : int
     143                 :         73 : rte_eth_devargs_parse_representor_ports(char *str, void *data)
     144                 :            : {
     145                 :            :         struct rte_eth_devargs *eth_da = data;
     146                 :            : 
     147         [ +  + ]:         73 :         if (str[0] == 'c') {
     148                 :          9 :                 str += 1;
     149                 :          9 :                 str = rte_eth_devargs_process_list(str, eth_da->mh_controllers,
     150                 :            :                                 &eth_da->nb_mh_controllers,
     151                 :            :                                 RTE_DIM(eth_da->mh_controllers));
     152         [ -  + ]:          9 :                 if (str == NULL)
     153                 :          0 :                         goto done;
     154                 :            :         }
     155   [ +  +  +  - ]:         73 :         if (str[0] == 'p' && str[1] == 'f') {
     156                 :         26 :                 eth_da->type = RTE_ETH_REPRESENTOR_PF;
     157                 :         26 :                 str += 2;
     158                 :         26 :                 str = rte_eth_devargs_process_list(str, eth_da->ports,
     159                 :            :                                 &eth_da->nb_ports, RTE_DIM(eth_da->ports));
     160   [ +  +  +  + ]:         26 :                 if (str == NULL || str[0] == '\0')
     161                 :         12 :                         goto done;
     162         [ +  + ]:         47 :         } else if (eth_da->nb_mh_controllers > 0) {
     163                 :            :                 /* 'c' must followed by 'pf'. */
     164                 :            :                 str = NULL;
     165                 :          5 :                 goto done;
     166                 :            :         }
     167   [ +  +  +  - ]:         56 :         if (str[0] == 'v' && str[1] == 'f') {
     168                 :         38 :                 eth_da->type = RTE_ETH_REPRESENTOR_VF;
     169                 :         38 :                 str += 2;
     170   [ +  +  +  - ]:         18 :         } else if (str[0] == 's' && str[1] == 'f') {
     171                 :          3 :                 eth_da->type = RTE_ETH_REPRESENTOR_SF;
     172                 :          3 :                 str += 2;
     173                 :            :         } else {
     174                 :            :                 /* 'pf' must followed by 'vf' or 'sf'. */
     175         [ +  + ]:         15 :                 if (eth_da->type == RTE_ETH_REPRESENTOR_PF) {
     176                 :            :                         str = NULL;
     177                 :          1 :                         goto done;
     178                 :            :                 }
     179                 :         14 :                 eth_da->type = RTE_ETH_REPRESENTOR_VF;
     180                 :            :         }
     181                 :         55 :         str = rte_eth_devargs_process_list(str, eth_da->representor_ports,
     182                 :            :                 &eth_da->nb_representor_ports,
     183                 :            :                 RTE_DIM(eth_da->representor_ports));
     184                 :         67 : done:
     185         [ +  + ]:         67 :         if (str == NULL)
     186                 :          9 :                 RTE_ETHDEV_LOG_LINE(ERR, "wrong representor format: %s", str);
     187         [ +  + ]:         73 :         return str == NULL ? -1 : 0;
     188                 :            : }
     189                 :            : 
     190                 :            : struct dummy_queue {
     191                 :            :         bool rx_warn_once;
     192                 :            :         bool tx_warn_once;
     193                 :            : };
     194                 :            : static struct dummy_queue *dummy_queues_array[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
     195                 :            : static struct dummy_queue per_port_queues[RTE_MAX_ETHPORTS];
     196                 :        252 : RTE_INIT(dummy_queue_init)
     197                 :            : {
     198                 :            :         uint16_t port_id;
     199                 :            : 
     200         [ +  + ]:       8316 :         for (port_id = 0; port_id < RTE_DIM(per_port_queues); port_id++) {
     201                 :            :                 unsigned int q;
     202                 :            : 
     203         [ +  + ]:    8265600 :                 for (q = 0; q < RTE_DIM(dummy_queues_array[port_id]); q++)
     204                 :    8257536 :                         dummy_queues_array[port_id][q] = &per_port_queues[port_id];
     205                 :            :         }
     206                 :        252 : }
     207                 :            : 
     208                 :            : static uint16_t
     209                 :          0 : dummy_eth_rx_burst(void *rxq,
     210                 :            :                 __rte_unused struct rte_mbuf **rx_pkts,
     211                 :            :                 __rte_unused uint16_t nb_pkts)
     212                 :            : {
     213                 :            :         struct dummy_queue *queue = rxq;
     214                 :            :         uintptr_t port_id;
     215                 :            : 
     216                 :          0 :         port_id = queue - per_port_queues;
     217   [ #  #  #  # ]:          0 :         if (port_id < RTE_DIM(per_port_queues) && !queue->rx_warn_once) {
     218                 :          0 :                 RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIuPTR,
     219                 :            :                         rte_lcore_id(), port_id);
     220                 :          0 :                 rte_dump_stack();
     221                 :          0 :                 queue->rx_warn_once = true;
     222                 :            :         }
     223                 :          0 :         rte_errno = ENOTSUP;
     224                 :          0 :         return 0;
     225                 :            : }
     226                 :            : 
     227                 :            : static uint16_t
     228                 :          0 : dummy_eth_tx_burst(void *txq,
     229                 :            :                 __rte_unused struct rte_mbuf **tx_pkts,
     230                 :            :                 __rte_unused uint16_t nb_pkts)
     231                 :            : {
     232                 :            :         struct dummy_queue *queue = txq;
     233                 :            :         uintptr_t port_id;
     234                 :            : 
     235                 :          0 :         port_id = queue - per_port_queues;
     236   [ #  #  #  # ]:          0 :         if (port_id < RTE_DIM(per_port_queues) && !queue->tx_warn_once) {
     237                 :          0 :                 RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIuPTR,
     238                 :            :                         rte_lcore_id(), port_id);
     239                 :          0 :                 rte_dump_stack();
     240                 :          0 :                 queue->tx_warn_once = true;
     241                 :            :         }
     242                 :          0 :         rte_errno = ENOTSUP;
     243                 :          0 :         return 0;
     244                 :            : }
     245                 :            : 
     246                 :            : void
     247                 :       8092 : eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo)
     248                 :            : {
     249                 :            :         static RTE_ATOMIC(void *) dummy_data[RTE_MAX_QUEUES_PER_PORT];
     250                 :       8092 :         uintptr_t port_id = fpo - rte_eth_fp_ops;
     251                 :            : 
     252                 :       8092 :         per_port_queues[port_id].rx_warn_once = false;
     253                 :       8092 :         per_port_queues[port_id].tx_warn_once = false;
     254                 :       8092 :         *fpo = (struct rte_eth_fp_ops) {
     255                 :            :                 .rx_pkt_burst = dummy_eth_rx_burst,
     256                 :            :                 .tx_pkt_burst = dummy_eth_tx_burst,
     257                 :            :                 .rxq = {
     258                 :       8092 :                         .data = (void **)&dummy_queues_array[port_id],
     259                 :            :                         .clbk = dummy_data,
     260                 :            :                 },
     261                 :            :                 .txq = {
     262                 :            :                         .data = (void **)&dummy_queues_array[port_id],
     263                 :            :                         .clbk = dummy_data,
     264                 :            :                 },
     265                 :            :         };
     266                 :       8092 : }
     267                 :            : 
     268                 :            : void
     269                 :         10 : eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo,
     270                 :            :                 const struct rte_eth_dev *dev)
     271                 :            : {
     272                 :         10 :         fpo->rx_pkt_burst = dev->rx_pkt_burst;
     273                 :         10 :         fpo->tx_pkt_burst = dev->tx_pkt_burst;
     274                 :         10 :         fpo->tx_pkt_prepare = dev->tx_pkt_prepare;
     275                 :         10 :         fpo->rx_queue_count = dev->rx_queue_count;
     276                 :         10 :         fpo->rx_descriptor_status = dev->rx_descriptor_status;
     277                 :         10 :         fpo->tx_queue_count = dev->tx_queue_count;
     278                 :         10 :         fpo->tx_descriptor_status = dev->tx_descriptor_status;
     279                 :         10 :         fpo->recycle_tx_mbufs_reuse = dev->recycle_tx_mbufs_reuse;
     280                 :         10 :         fpo->recycle_rx_descriptors_refill = dev->recycle_rx_descriptors_refill;
     281                 :            : 
     282                 :         10 :         fpo->rxq.data = dev->data->rx_queues;
     283                 :         10 :         fpo->rxq.clbk = (void * __rte_atomic *)(uintptr_t)dev->post_rx_burst_cbs;
     284                 :            : 
     285                 :         10 :         fpo->txq.data = dev->data->tx_queues;
     286                 :         10 :         fpo->txq.clbk = (void * __rte_atomic *)(uintptr_t)dev->pre_tx_burst_cbs;
     287                 :         10 : }
     288                 :            : 
     289                 :            : RTE_EXPORT_SYMBOL(rte_eth_call_rx_callbacks)
     290                 :            : uint16_t
     291                 :          1 : rte_eth_call_rx_callbacks(uint16_t port_id, uint16_t queue_id,
     292                 :            :         struct rte_mbuf **rx_pkts, uint16_t nb_rx, uint16_t nb_pkts,
     293                 :            :         void *opaque)
     294                 :            : {
     295                 :            :         const struct rte_eth_rxtx_callback *cb = opaque;
     296                 :            : 
     297         [ +  + ]:          2 :         while (cb != NULL) {
     298                 :          1 :                 nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
     299                 :          1 :                                 nb_pkts, cb->param);
     300                 :          1 :                 cb = cb->next;
     301                 :            :         }
     302                 :            : 
     303                 :            :         if (unlikely(nb_rx))
     304                 :            :                 rte_eth_trace_call_rx_callbacks_nonempty(port_id, queue_id, (void **)rx_pkts,
     305                 :            :                                                 nb_rx, nb_pkts);
     306                 :            :         else
     307                 :            :                 rte_eth_trace_call_rx_callbacks_empty(port_id, queue_id, (void **)rx_pkts,
     308                 :            :                                                 nb_pkts);
     309                 :            : 
     310                 :          1 :         return nb_rx;
     311                 :            : }
     312                 :            : 
     313                 :            : RTE_EXPORT_SYMBOL(rte_eth_call_tx_callbacks)
     314                 :            : uint16_t
     315                 :          1 : rte_eth_call_tx_callbacks(uint16_t port_id, uint16_t queue_id,
     316                 :            :         struct rte_mbuf **tx_pkts, uint16_t nb_pkts, void *opaque)
     317                 :            : {
     318                 :            :         const struct rte_eth_rxtx_callback *cb = opaque;
     319                 :            : 
     320         [ +  + ]:          2 :         while (cb != NULL) {
     321                 :          1 :                 nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts,
     322                 :          1 :                                 cb->param);
     323                 :          1 :                 cb = cb->next;
     324                 :            :         }
     325                 :            : 
     326                 :            :         rte_eth_trace_call_tx_callbacks(port_id, queue_id, (void **)tx_pkts,
     327                 :            :                                         nb_pkts);
     328                 :            : 
     329                 :          1 :         return nb_pkts;
     330                 :            : }
     331                 :            : 
     332                 :            : void *
     333                 :         56 : eth_dev_shared_data_prepare(void)
     334                 :            : {
     335                 :            :         const struct rte_memzone *mz;
     336                 :            : 
     337         [ +  - ]:         56 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
     338                 :            :                 const unsigned int flags = 0;
     339                 :            : 
     340         [ +  + ]:         56 :                 if (eth_dev_shared_mz != NULL)
     341                 :         45 :                         goto out;
     342                 :            : 
     343                 :            :                 /* Allocate port data and ownership shared memory. */
     344                 :         11 :                 mz = rte_memzone_reserve(MZ_RTE_ETH_DEV_DATA,
     345                 :            :                                 sizeof(*eth_dev_shared_data),
     346                 :         11 :                                 rte_socket_id(), flags);
     347         [ -  + ]:         11 :                 if (mz == NULL) {
     348                 :          0 :                         RTE_ETHDEV_LOG_LINE(ERR, "Cannot allocate ethdev shared data");
     349                 :          0 :                         goto out;
     350                 :            :                 }
     351                 :            : 
     352                 :         11 :                 eth_dev_shared_mz = mz;
     353                 :         11 :                 eth_dev_shared_data = mz->addr;
     354                 :         11 :                 eth_dev_shared_data->allocated_owners = 0;
     355                 :         11 :                 eth_dev_shared_data->next_owner_id =
     356                 :            :                         RTE_ETH_DEV_NO_OWNER + 1;
     357                 :         11 :                 eth_dev_shared_data->allocated_ports = 0;
     358                 :         11 :                 memset(eth_dev_shared_data->data, 0,
     359                 :            :                        sizeof(eth_dev_shared_data->data));
     360                 :            :         } else {
     361                 :          0 :                 mz = rte_memzone_lookup(MZ_RTE_ETH_DEV_DATA);
     362         [ #  # ]:          0 :                 if (mz == NULL) {
     363                 :            :                         /* Clean remaining any traces of a previous shared mem */
     364                 :          0 :                         eth_dev_shared_mz = NULL;
     365                 :          0 :                         eth_dev_shared_data = NULL;
     366                 :          0 :                         RTE_ETHDEV_LOG_LINE(ERR, "Cannot lookup ethdev shared data");
     367                 :          0 :                         goto out;
     368                 :            :                 }
     369   [ #  #  #  # ]:          0 :                 if (mz == eth_dev_shared_mz && mz->addr == eth_dev_shared_data)
     370                 :          0 :                         goto out;
     371                 :            : 
     372                 :            :                 /* Shared mem changed in primary process, refresh pointers */
     373                 :          0 :                 eth_dev_shared_mz = mz;
     374                 :          0 :                 eth_dev_shared_data = mz->addr;
     375                 :            :         }
     376                 :         56 : out:
     377                 :         56 :         return eth_dev_shared_data;
     378                 :            : }
     379                 :            : 
     380                 :            : void
     381                 :         18 : eth_dev_shared_data_release(void)
     382                 :            : {
     383                 :            :         RTE_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
     384                 :            : 
     385         [ +  + ]:         18 :         if (eth_dev_shared_data->allocated_ports != 0)
     386                 :            :                 return;
     387         [ +  - ]:         10 :         if (eth_dev_shared_data->allocated_owners != 0)
     388                 :            :                 return;
     389                 :            : 
     390                 :         10 :         rte_memzone_free(eth_dev_shared_mz);
     391                 :         10 :         eth_dev_shared_mz = NULL;
     392                 :         10 :         eth_dev_shared_data = NULL;
     393                 :            : }
     394                 :            : 
     395                 :            : void
     396                 :         45 : eth_dev_rxq_release(struct rte_eth_dev *dev, uint16_t qid)
     397                 :            : {
     398                 :         45 :         void **rxq = dev->data->rx_queues;
     399                 :            : 
     400         [ +  - ]:         45 :         if (rxq[qid] == NULL)
     401                 :            :                 return;
     402                 :            : 
     403         [ -  + ]:         45 :         if (dev->dev_ops->rx_queue_release != NULL)
     404                 :          0 :                 dev->dev_ops->rx_queue_release(dev, qid);
     405                 :         45 :         rxq[qid] = NULL;
     406                 :            : }
     407                 :            : 
     408                 :            : void
     409                 :         45 : eth_dev_txq_release(struct rte_eth_dev *dev, uint16_t qid)
     410                 :            : {
     411                 :         45 :         void **txq = dev->data->tx_queues;
     412                 :            : 
     413         [ +  - ]:         45 :         if (txq[qid] == NULL)
     414                 :            :                 return;
     415                 :            : 
     416         [ -  + ]:         45 :         if (dev->dev_ops->tx_queue_release != NULL)
     417                 :          0 :                 dev->dev_ops->tx_queue_release(dev, qid);
     418                 :         45 :         txq[qid] = NULL;
     419                 :            : }
     420                 :            : 
     421                 :            : int
     422                 :         15 : eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
     423                 :            : {
     424                 :         15 :         uint16_t old_nb_queues = dev->data->nb_rx_queues;
     425                 :            :         unsigned int i;
     426                 :            : 
     427   [ +  +  +  - ]:         15 :         if (dev->data->rx_queues == NULL && nb_queues != 0) { /* first time configuration */
     428                 :          2 :                 dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues",
     429                 :            :                                 sizeof(dev->data->rx_queues[0]) *
     430                 :            :                                 RTE_MAX_QUEUES_PER_PORT,
     431                 :            :                                 RTE_CACHE_LINE_SIZE);
     432         [ -  + ]:          2 :                 if (dev->data->rx_queues == NULL) {
     433                 :          0 :                         dev->data->nb_rx_queues = 0;
     434                 :          0 :                         return -(ENOMEM);
     435                 :            :                 }
     436   [ +  -  +  - ]:         13 :         } else if (dev->data->rx_queues != NULL && nb_queues != 0) { /* re-configure */
     437         [ +  + ]:         18 :                 for (i = nb_queues; i < old_nb_queues; i++)
     438                 :          5 :                         eth_dev_rxq_release(dev, i);
     439                 :            : 
     440   [ #  #  #  # ]:          0 :         } else if (dev->data->rx_queues != NULL && nb_queues == 0) {
     441         [ #  # ]:          0 :                 for (i = nb_queues; i < old_nb_queues; i++)
     442                 :          0 :                         eth_dev_rxq_release(dev, i);
     443                 :            : 
     444                 :          0 :                 rte_free(dev->data->rx_queues);
     445                 :          0 :                 dev->data->rx_queues = NULL;
     446                 :            :         }
     447                 :         15 :         dev->data->nb_rx_queues = nb_queues;
     448                 :         15 :         return 0;
     449                 :            : }
     450                 :            : 
     451                 :            : int
     452                 :         15 : eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
     453                 :            : {
     454                 :         15 :         uint16_t old_nb_queues = dev->data->nb_tx_queues;
     455                 :            :         unsigned int i;
     456                 :            : 
     457   [ +  +  +  - ]:         15 :         if (dev->data->tx_queues == NULL && nb_queues != 0) { /* first time configuration */
     458                 :          2 :                 dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues",
     459                 :            :                                 sizeof(dev->data->tx_queues[0]) *
     460                 :            :                                 RTE_MAX_QUEUES_PER_PORT,
     461                 :            :                                 RTE_CACHE_LINE_SIZE);
     462         [ -  + ]:          2 :                 if (dev->data->tx_queues == NULL) {
     463                 :          0 :                         dev->data->nb_tx_queues = 0;
     464                 :          0 :                         return -(ENOMEM);
     465                 :            :                 }
     466   [ +  -  +  - ]:         13 :         } else if (dev->data->tx_queues != NULL && nb_queues != 0) { /* re-configure */
     467         [ +  + ]:         18 :                 for (i = nb_queues; i < old_nb_queues; i++)
     468                 :          5 :                         eth_dev_txq_release(dev, i);
     469                 :            : 
     470   [ #  #  #  # ]:          0 :         } else if (dev->data->tx_queues != NULL && nb_queues == 0) {
     471         [ #  # ]:          0 :                 for (i = nb_queues; i < old_nb_queues; i++)
     472                 :          0 :                         eth_dev_txq_release(dev, i);
     473                 :            : 
     474                 :          0 :                 rte_free(dev->data->tx_queues);
     475                 :          0 :                 dev->data->tx_queues = NULL;
     476                 :            :         }
     477                 :         15 :         dev->data->nb_tx_queues = nb_queues;
     478                 :         15 :         return 0;
     479                 :            : }

Generated by: LCOV version 1.14