LCOV - code coverage report
Current view: top level - drivers/event/sw - sw_evdev_scheduler.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 232 237 97.9 %
Date: 2025-03-01 20:23:48 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 132 188 70.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2016-2017 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_ring.h>
       6                 :            : #include <rte_hash_crc.h>
       7                 :            : #include <rte_event_ring.h>
       8                 :            : #include "sw_evdev.h"
       9                 :            : #include "iq_chunk.h"
      10                 :            : #include "event_ring.h"
      11                 :            : 
      12                 :            : #define SW_IQS_MASK (SW_IQS_MAX-1)
      13                 :            : 
      14                 :            : /* Retrieve the highest priority IQ or -1 if no pkts available. Doing the
      15                 :            :  * CLZ twice is faster than caching the value due to data dependencies
      16                 :            :  */
      17                 :            : #define PKT_MASK_TO_IQ(pkts) \
      18                 :            :         (rte_ctz32(pkts | (1 << SW_IQS_MAX)))
      19                 :            : 
      20                 :            : #if SW_IQS_MAX != 4
      21                 :            : #error Misconfigured PRIO_TO_IQ caused by SW_IQS_MAX value change
      22                 :            : #endif
      23                 :            : #define PRIO_TO_IQ(prio) (prio >> 6)
      24                 :            : 
      25                 :            : #define MAX_PER_IQ_DEQUEUE 48
      26                 :            : #define FLOWID_MASK (SW_QID_NUM_FIDS-1)
      27                 :            : /* use cheap bit mixing, we only need to lose a few bits */
      28                 :            : #define SW_HASH_FLOWID(f) (((f) ^ (f >> 10)) & FLOWID_MASK)
      29                 :            : 
      30                 :            : 
      31                 :            : static inline uint32_t
      32                 :       4187 : sw_schedule_atomic_to_cq(struct sw_evdev *sw, struct sw_qid * const qid,
      33                 :            :                 uint32_t iq_num, unsigned int count)
      34                 :            : {
      35                 :            :         struct rte_event qes[MAX_PER_IQ_DEQUEUE]; /* count <= MAX */
      36                 :            :         struct rte_event blocked_qes[MAX_PER_IQ_DEQUEUE];
      37                 :            :         uint32_t nb_blocked = 0;
      38                 :            :         uint32_t i;
      39                 :            : 
      40                 :            :         if (count > MAX_PER_IQ_DEQUEUE)
      41                 :            :                 count = MAX_PER_IQ_DEQUEUE;
      42                 :            : 
      43                 :            :         /* This is the QID ID. The QID ID is static, hence it can be
      44                 :            :          * used to identify the stage of processing in history lists etc
      45                 :            :          */
      46                 :       4187 :         uint32_t qid_id = qid->id;
      47                 :            : 
      48                 :       4187 :         iq_dequeue_burst(sw, &qid->iq[iq_num], qes, count);
      49         [ +  + ]:       8593 :         for (i = 0; i < count; i++) {
      50                 :            :                 const struct rte_event *qe = &qes[i];
      51                 :       4406 :                 const uint16_t flow_id = SW_HASH_FLOWID(qes[i].flow_id);
      52                 :       4406 :                 struct sw_fid_t *fid = &qid->fids[flow_id];
      53                 :       4406 :                 int cq = fid->cq;
      54                 :            : 
      55         [ +  + ]:       4406 :                 if (cq < 0) {
      56                 :            :                         uint32_t cq_idx;
      57         [ +  + ]:       4153 :                         if (qid->cq_next_tx >= qid->cq_num_mapped_cqs)
      58                 :       4099 :                                 qid->cq_next_tx = 0;
      59                 :       4153 :                         cq_idx = qid->cq_next_tx++;
      60                 :            : 
      61                 :       4153 :                         cq = qid->cq_map[cq_idx];
      62                 :            : 
      63                 :            :                         /* find least used */
      64                 :       4153 :                         int cq_free_cnt = sw->cq_ring_space[cq];
      65         [ +  + ]:       8324 :                         for (cq_idx = 0; cq_idx < qid->cq_num_mapped_cqs;
      66                 :       4171 :                                         cq_idx++) {
      67                 :       4171 :                                 int test_cq = qid->cq_map[cq_idx];
      68                 :       4171 :                                 int test_cq_free = sw->cq_ring_space[test_cq];
      69         [ +  + ]:       4171 :                                 if (test_cq_free > cq_free_cnt) {
      70                 :            :                                         cq = test_cq;
      71                 :            :                                         cq_free_cnt = test_cq_free;
      72                 :            :                                 }
      73                 :            :                         }
      74                 :            : 
      75                 :       4153 :                         fid->cq = cq; /* this pins early */
      76                 :            :                 }
      77                 :            : 
      78         [ +  + ]:       4406 :                 if (sw->cq_ring_space[cq] == 0 ||
      79         [ -  + ]:       4241 :                                 sw->ports[cq].inflights == SW_PORT_HIST_LIST) {
      80                 :        165 :                         blocked_qes[nb_blocked++] = *qe;
      81                 :            :                         continue;
      82                 :            :                 }
      83                 :            : 
      84                 :            :                 struct sw_port *p = &sw->ports[cq];
      85                 :            : 
      86                 :            :                 /* at this point we can queue up the packet on the cq_buf */
      87                 :       4241 :                 fid->pcount++;
      88                 :       4241 :                 p->cq_buf[p->cq_buf_count++] = *qe;
      89                 :       4241 :                 p->inflights++;
      90                 :       4241 :                 sw->cq_ring_space[cq]--;
      91                 :            : 
      92                 :       4241 :                 int head = (p->hist_head++ & (SW_PORT_HIST_LIST-1));
      93                 :       4241 :                 p->hist_list[head] = (struct sw_hist_list_entry) {
      94                 :            :                         .qid = qid_id,
      95                 :            :                         .fid = flow_id,
      96                 :            :                 };
      97                 :            : 
      98                 :       4241 :                 p->stats.tx_pkts++;
      99                 :       4241 :                 qid->stats.tx_pkts++;
     100                 :       4241 :                 qid->to_port[cq]++;
     101                 :            : 
     102                 :            :                 /* if we just filled in the last slot, flush the buffer */
     103         [ +  + ]:       4241 :                 if (sw->cq_ring_space[cq] == 0) {
     104                 :          2 :                         struct rte_event_ring *worker = p->cq_worker_ring;
     105   [ -  +  -  -  :          2 :                         rte_event_ring_enqueue_burst(worker, p->cq_buf,
                      - ]
     106                 :            :                                         p->cq_buf_count,
     107                 :            :                                         &sw->cq_ring_space[cq]);
     108                 :          2 :                         p->cq_buf_count = 0;
     109                 :            :                 }
     110                 :            :         }
     111                 :            :         iq_put_back(sw, &qid->iq[iq_num], blocked_qes, nb_blocked);
     112                 :            : 
     113                 :       4187 :         return count - nb_blocked;
     114                 :            : }
     115                 :            : 
     116                 :            : static inline uint32_t
     117                 :          7 : sw_schedule_parallel_to_cq(struct sw_evdev *sw, struct sw_qid * const qid,
     118                 :            :                 uint32_t iq_num, unsigned int count, int keep_order)
     119                 :            : {
     120                 :            :         uint32_t i;
     121                 :          7 :         uint32_t cq_idx = qid->cq_next_tx;
     122                 :            : 
     123                 :            :         /* This is the QID ID. The QID ID is static, hence it can be
     124                 :            :          * used to identify the stage of processing in history lists etc
     125                 :            :          */
     126                 :          7 :         uint32_t qid_id = qid->id;
     127                 :            : 
     128                 :            :         if (count > MAX_PER_IQ_DEQUEUE)
     129                 :            :                 count = MAX_PER_IQ_DEQUEUE;
     130                 :            : 
     131         [ +  + ]:          7 :         if (keep_order)
     132                 :            :                 /* only schedule as many as we have reorder buffer entries */
     133                 :          4 :                 count = RTE_MIN(count,
     134                 :            :                                 rob_ring_count(qid->reorder_buffer_freelist));
     135                 :            : 
     136         [ +  + ]:         18 :         for (i = 0; i < count; i++) {
     137                 :            :                 const struct rte_event *qe = iq_peek(&qid->iq[iq_num]);
     138                 :            :                 uint32_t cq_check_count = 0;
     139                 :            :                 uint32_t cq;
     140                 :            : 
     141                 :            :                 /*
     142                 :            :                  *  for parallel, just send to next available CQ in round-robin
     143                 :            :                  * fashion. So scan for an available CQ. If all CQs are full
     144                 :            :                  * just return and move on to next QID
     145                 :            :                  */
     146                 :            :                 do {
     147         [ -  + ]:         11 :                         if (++cq_check_count > qid->cq_num_mapped_cqs)
     148                 :          0 :                                 goto exit;
     149         [ +  + ]:         11 :                         if (cq_idx >= qid->cq_num_mapped_cqs)
     150                 :            :                                 cq_idx = 0;
     151                 :         11 :                         cq = qid->cq_map[cq_idx++];
     152                 :            : 
     153   [ -  +  -  + ]:         11 :                 } while (sw->ports[cq].inflights == SW_PORT_HIST_LIST ||
     154                 :            :                                 rte_event_ring_free_count(
     155         [ -  + ]:         11 :                                         sw->ports[cq].cq_worker_ring) == 0);
     156                 :            : 
     157                 :            :                 struct sw_port *p = &sw->ports[cq];
     158         [ +  - ]:         11 :                 if (sw->cq_ring_space[cq] == 0 ||
     159                 :            :                                 p->inflights == SW_PORT_HIST_LIST)
     160                 :            :                         break;
     161                 :            : 
     162                 :         11 :                 sw->cq_ring_space[cq]--;
     163                 :            : 
     164                 :         11 :                 qid->stats.tx_pkts++;
     165                 :            : 
     166                 :         11 :                 const int head = (p->hist_head & (SW_PORT_HIST_LIST-1));
     167                 :         11 :                 p->hist_list[head] = (struct sw_hist_list_entry) {
     168                 :            :                         .qid = qid_id,
     169                 :         11 :                         .fid = SW_HASH_FLOWID(qe->flow_id),
     170                 :            :                 };
     171                 :            : 
     172         [ +  + ]:         11 :                 if (keep_order)
     173         [ +  - ]:          6 :                         rob_ring_dequeue(qid->reorder_buffer_freelist,
     174                 :            :                                         (void *)&p->hist_list[head].rob_entry);
     175                 :            : 
     176         [ -  + ]:         11 :                 sw->ports[cq].cq_buf[sw->ports[cq].cq_buf_count++] = *qe;
     177                 :            :                 iq_pop(sw, &qid->iq[iq_num]);
     178                 :            : 
     179                 :         11 :                 rte_compiler_barrier();
     180                 :         11 :                 p->inflights++;
     181                 :         11 :                 p->stats.tx_pkts++;
     182                 :         11 :                 p->hist_head++;
     183                 :            :         }
     184                 :          7 : exit:
     185                 :          7 :         qid->cq_next_tx = cq_idx;
     186                 :          7 :         return i;
     187                 :            : }
     188                 :            : 
     189                 :            : static uint32_t
     190                 :       5101 : sw_schedule_dir_to_cq(struct sw_evdev *sw, struct sw_qid * const qid,
     191                 :            :                 uint32_t iq_num, unsigned int count __rte_unused)
     192                 :            : {
     193                 :       5101 :         uint32_t cq_id = qid->cq_map[0];
     194                 :            :         struct sw_port *port = &sw->ports[cq_id];
     195                 :            : 
     196                 :            :         /* get max burst enq size for cq_ring */
     197                 :       5101 :         uint32_t count_free = sw->cq_ring_space[cq_id];
     198         [ +  - ]:       5101 :         if (count_free == 0)
     199                 :            :                 return 0;
     200                 :            : 
     201                 :            :         /* burst dequeue from the QID IQ ring */
     202                 :            :         struct sw_iq *iq = &qid->iq[iq_num];
     203                 :      10202 :         uint32_t ret = iq_dequeue_burst(sw, iq,
     204                 :       5101 :                         &port->cq_buf[port->cq_buf_count], count_free);
     205                 :       5101 :         port->cq_buf_count += ret;
     206                 :            : 
     207                 :            :         /* Update QID, Port and Total TX stats */
     208                 :       5101 :         qid->stats.tx_pkts += ret;
     209                 :       5101 :         port->stats.tx_pkts += ret;
     210                 :            : 
     211                 :            :         /* Subtract credits from cached value */
     212                 :       5101 :         sw->cq_ring_space[cq_id] -= ret;
     213                 :            : 
     214                 :       5101 :         return ret;
     215                 :            : }
     216                 :            : 
     217                 :            : static uint32_t
     218                 :    4212902 : sw_schedule_qid_to_cq(struct sw_evdev *sw)
     219                 :            : {
     220                 :            :         uint32_t pkts = 0;
     221                 :            :         uint32_t qid_idx;
     222                 :            : 
     223                 :    4212902 :         sw->sched_cq_qid_called++;
     224                 :            : 
     225         [ +  + ]:   12636529 :         for (qid_idx = 0; qid_idx < sw->qid_count; qid_idx++) {
     226                 :    8423627 :                 struct sw_qid *qid = sw->qids_prioritized[qid_idx];
     227                 :            : 
     228                 :    8423627 :                 int type = qid->type;
     229         [ +  + ]:    8423627 :                 int iq_num = PKT_MASK_TO_IQ(qid->iq_pkt_mask);
     230                 :            : 
     231                 :            :                 /* zero mapped CQs indicates directed */
     232   [ +  +  -  + ]:    8423627 :                 if (iq_num >= SW_IQS_MAX || qid->cq_num_mapped_cqs == 0)
     233                 :    8414330 :                         continue;
     234                 :            : 
     235                 :            :                 uint32_t pkts_done = 0;
     236                 :       9297 :                 uint32_t count = iq_count(&qid->iq[iq_num]);
     237                 :            : 
     238         [ +  + ]:       9297 :                 if (count >= sw->sched_min_burst) {
     239         [ +  + ]:       9295 :                         if (type == SW_SCHED_TYPE_DIRECT)
     240                 :       5101 :                                 pkts_done += sw_schedule_dir_to_cq(sw, qid,
     241                 :            :                                                 iq_num, count);
     242         [ +  + ]:       4194 :                         else if (type == RTE_SCHED_TYPE_ATOMIC)
     243                 :       4187 :                                 pkts_done += sw_schedule_atomic_to_cq(sw, qid,
     244                 :            :                                                 iq_num, count);
     245                 :            :                         else
     246                 :          7 :                                 pkts_done += sw_schedule_parallel_to_cq(sw, qid,
     247                 :            :                                                 iq_num, count,
     248                 :            :                                                 type == RTE_SCHED_TYPE_ORDERED);
     249                 :            :                 }
     250                 :            : 
     251                 :            :                 /* Check if the IQ that was polled is now empty, and unset it
     252                 :            :                  * in the IQ mask if its empty.
     253                 :            :                  */
     254                 :       9297 :                 int all_done = (pkts_done == count);
     255                 :            : 
     256                 :       9297 :                 qid->iq_pkt_mask &= ~(all_done << (iq_num));
     257                 :       9297 :                 pkts += pkts_done;
     258                 :            :         }
     259                 :            : 
     260                 :    4212902 :         return pkts;
     261                 :            : }
     262                 :            : 
     263                 :            : /* This function will perform re-ordering of packets, and injecting into
     264                 :            :  * the appropriate QID IQ. As LB and DIR QIDs are in the same array, but *NOT*
     265                 :            :  * contiguous in that array, this function accepts a "range" of QIDs to scan.
     266                 :            :  */
     267                 :            : static uint16_t
     268                 :    4212909 : sw_schedule_reorder(struct sw_evdev *sw, int qid_start, int qid_end)
     269                 :            : {
     270                 :            :         /* Perform egress reordering */
     271                 :            :         struct rte_event *qe;
     272                 :            :         uint32_t pkts_iter = 0;
     273                 :            : 
     274         [ +  + ]:   12636544 :         for (; qid_start < qid_end; qid_start++) {
     275                 :            :                 struct sw_qid *qid = &sw->qids[qid_start];
     276                 :            :                 unsigned int i, num_entries_in_use;
     277                 :            : 
     278         [ +  + ]:    8423635 :                 if (qid->type != RTE_SCHED_TYPE_ORDERED)
     279                 :    4212926 :                         continue;
     280                 :            : 
     281                 :            :                 num_entries_in_use = rob_ring_free_count(
     282         [ -  + ]:    4210709 :                                         qid->reorder_buffer_freelist);
     283                 :            : 
     284         [ -  + ]:    4210709 :                 if (num_entries_in_use < sw->sched_min_burst)
     285                 :            :                         num_entries_in_use = 0;
     286                 :            : 
     287         [ +  - ]:    4210715 :                 for (i = 0; i < num_entries_in_use; i++) {
     288                 :            :                         struct reorder_buffer_entry *entry;
     289                 :            :                         int j;
     290                 :            : 
     291                 :    4210715 :                         entry = &qid->reorder_buffer[qid->reorder_buffer_index];
     292                 :            : 
     293         [ +  + ]:    4210715 :                         if (!entry->ready)
     294                 :            :                                 break;
     295                 :            : 
     296         [ +  + ]:          9 :                         for (j = 0; j < entry->num_fragments; j++) {
     297                 :            :                                 uint16_t dest_qid;
     298                 :            :                                 uint16_t dest_iq;
     299                 :            : 
     300                 :          3 :                                 int idx = entry->fragment_index + j;
     301                 :            :                                 qe = &entry->fragments[idx];
     302                 :            : 
     303                 :          3 :                                 dest_qid = qe->queue_id;
     304                 :          3 :                                 dest_iq  = PRIO_TO_IQ(qe->priority);
     305                 :            : 
     306         [ -  + ]:          3 :                                 if (dest_qid >= sw->qid_count) {
     307                 :          0 :                                         sw->stats.rx_dropped++;
     308                 :          0 :                                         continue;
     309                 :            :                                 }
     310                 :            : 
     311                 :          3 :                                 pkts_iter++;
     312                 :            : 
     313                 :          3 :                                 struct sw_qid *q = &sw->qids[dest_qid];
     314         [ -  + ]:          3 :                                 struct sw_iq *iq = &q->iq[dest_iq];
     315                 :            : 
     316                 :            :                                 /* we checked for space above, so enqueue must
     317                 :            :                                  * succeed
     318                 :            :                                  */
     319                 :            :                                 iq_enqueue(sw, iq, qe);
     320                 :          3 :                                 q->iq_pkt_mask |= (1 << (dest_iq));
     321                 :          3 :                                 q->iq_pkt_count[dest_iq]++;
     322                 :          3 :                                 q->stats.rx_pkts++;
     323                 :            :                         }
     324                 :            : 
     325                 :          6 :                         entry->ready = (j != entry->num_fragments);
     326                 :          6 :                         entry->num_fragments -= j;
     327                 :          6 :                         entry->fragment_index += j;
     328                 :            : 
     329         [ +  - ]:          6 :                         if (!entry->ready) {
     330         [ +  - ]:          6 :                                 entry->fragment_index = 0;
     331                 :            : 
     332                 :            :                                 rob_ring_enqueue(
     333                 :            :                                                 qid->reorder_buffer_freelist,
     334                 :            :                                                 entry);
     335                 :            : 
     336                 :          6 :                                 qid->reorder_buffer_index++;
     337                 :          6 :                                 qid->reorder_buffer_index %= qid->window_size;
     338                 :            :                         }
     339                 :            :                 }
     340                 :            :         }
     341                 :    4212909 :         return pkts_iter;
     342                 :            : }
     343                 :            : 
     344                 :            : static __rte_always_inline void
     345                 :            : sw_refill_pp_buf(struct sw_evdev *sw, struct sw_port *port)
     346                 :            : {
     347                 :            :         RTE_SET_USED(sw);
     348                 :    8423806 :         struct rte_event_ring *worker = port->rx_worker_ring;
     349                 :    8423806 :         port->pp_buf_start = 0;
     350   [ -  -  -  -  :    8423806 :         port->pp_buf_count = rte_event_ring_dequeue_burst(worker, port->pp_buf,
          -  -  +  -  -  
          -  -  +  -  -  
          -  -  +  -  -  
                      - ]
     351                 :            :                         sw->sched_deq_burst_size, NULL);
     352                 :    8423806 : }
     353                 :            : 
     354                 :            : static __rte_always_inline uint32_t
     355                 :            : __pull_port_lb(struct sw_evdev *sw, uint32_t port_id, int allow_reorder)
     356                 :            : {
     357                 :            :         static struct reorder_buffer_entry dummy_rob;
     358                 :            :         uint32_t pkts_iter = 0;
     359                 :            :         struct sw_port *port = &sw->ports[port_id];
     360                 :            : 
     361                 :            :         /* If shadow ring has 0 pkts, pull from worker ring */
     362   [ +  -  +  - ]:    4219291 :         if (!sw->refill_once_per_iter && port->pp_buf_count == 0)
     363                 :            :                 sw_refill_pp_buf(sw, port);
     364                 :            : 
     365   [ +  +  +  + ]:    4227859 :         while (port->pp_buf_count) {
     366                 :       8568 :                 const struct rte_event *qe = &port->pp_buf[port->pp_buf_start];
     367                 :            :                 struct sw_hist_list_entry *hist_entry = NULL;
     368                 :       8568 :                 uint8_t flags = qe->op;
     369                 :            :                 const uint16_t eop = !(flags & QE_FLAG_NOT_EOP);
     370                 :            :                 int needs_reorder = 0;
     371                 :            :                 /* if no-reordering, having PARTIAL == NEW */
     372                 :            :                 if (!allow_reorder && !eop)
     373                 :            :                         flags = QE_FLAG_VALID;
     374                 :            : 
     375                 :       8568 :                 uint32_t iq_num = PRIO_TO_IQ(qe->priority);
     376                 :       8568 :                 struct sw_qid *qid = &sw->qids[qe->queue_id];
     377                 :            : 
     378                 :            :                 /* now process based on flags. Note that for directed
     379                 :            :                  * queues, the enqueue_flush masks off all but the
     380                 :            :                  * valid flag. This makes FWD and PARTIAL enqueues just
     381                 :            :                  * NEW type, and makes DROPS no-op calls.
     382                 :            :                  */
     383   [ +  +  +  +  :       8568 :                 if ((flags & QE_FLAG_COMPLETE) && port->inflights > 0) {
             +  +  +  + ]
     384                 :       4217 :                         const uint32_t hist_tail = port->hist_tail &
     385                 :            :                                         (SW_PORT_HIST_LIST - 1);
     386                 :            : 
     387                 :       4105 :                         hist_entry = &port->hist_list[hist_tail];
     388                 :       4217 :                         const uint32_t hist_qid = hist_entry->qid;
     389                 :       4217 :                         const uint32_t hist_fid = hist_entry->fid;
     390                 :            : 
     391                 :            :                         struct sw_fid_t *fid =
     392                 :            :                                 &sw->qids[hist_qid].fids[hist_fid];
     393                 :       4217 :                         fid->pcount -= eop;
     394   [ +  +  +  + ]:       4217 :                         if (fid->pcount == 0)
     395                 :       4118 :                                 fid->cq = -1;
     396                 :            : 
     397                 :            :                         if (allow_reorder) {
     398                 :            :                                 /* set reorder ready if an ordered QID */
     399                 :            :                                 uintptr_t rob_ptr =
     400                 :       4105 :                                         (uintptr_t)hist_entry->rob_entry;
     401                 :       4105 :                                 const uintptr_t valid = (rob_ptr != 0);
     402                 :       4105 :                                 needs_reorder = valid;
     403                 :            :                                 rob_ptr |=
     404                 :       4105 :                                         ((valid - 1) & (uintptr_t)&dummy_rob);
     405                 :       4105 :                                 struct reorder_buffer_entry *tmp_rob_ptr =
     406                 :            :                                         (struct reorder_buffer_entry *)rob_ptr;
     407                 :       4105 :                                 tmp_rob_ptr->ready = eop * needs_reorder;
     408                 :            :                         }
     409                 :            : 
     410                 :       4217 :                         port->inflights -= eop;
     411                 :       4217 :                         port->hist_tail += eop;
     412                 :            :                 }
     413   [ +  +  +  + ]:       8568 :                 if (flags & QE_FLAG_VALID) {
     414                 :       8452 :                         port->stats.rx_pkts++;
     415                 :            : 
     416         [ +  + ]:       4103 :                         if (allow_reorder && needs_reorder) {
     417                 :          3 :                                 struct reorder_buffer_entry *rob_entry =
     418                 :            :                                                 hist_entry->rob_entry;
     419                 :            : 
     420                 :            :                                 /* Although fragmentation not currently
     421                 :            :                                  * supported by eventdev API, we support it
     422                 :            :                                  * here. Open: How do we alert the user that
     423                 :            :                                  * they've exceeded max frags?
     424                 :            :                                  */
     425                 :          3 :                                 int num_frag = rob_entry->num_fragments;
     426         [ -  + ]:          3 :                                 if (num_frag == SW_FRAGMENTS_MAX)
     427                 :          0 :                                         sw->stats.rx_dropped++;
     428                 :            :                                 else {
     429                 :          3 :                                         int idx = rob_entry->num_fragments++;
     430                 :          3 :                                         rob_entry->fragments[idx] = *qe;
     431                 :            :                                 }
     432                 :          3 :                                 goto end_qe;
     433                 :            :                         }
     434                 :            : 
     435                 :            :                         /* Use the iq_num from above to push the QE
     436                 :            :                          * into the qid at the right priority
     437                 :            :                          */
     438                 :            : 
     439   [ +  +  +  + ]:       8449 :                         qid->iq_pkt_mask |= (1 << (iq_num));
     440                 :            :                         iq_enqueue(sw, &qid->iq[iq_num], qe);
     441                 :       8449 :                         qid->iq_pkt_count[iq_num]++;
     442                 :       8449 :                         qid->stats.rx_pkts++;
     443                 :       8449 :                         pkts_iter++;
     444                 :            :                 }
     445                 :            : 
     446                 :        116 : end_qe:
     447                 :       8568 :                 port->pp_buf_start++;
     448                 :       8568 :                 port->pp_buf_count--;
     449                 :            :         } /* while (avail_qes) */
     450                 :            : 
     451                 :            :         return pkts_iter;
     452                 :            : }
     453                 :            : 
     454                 :            : static uint32_t
     455         [ +  - ]:       8221 : sw_schedule_pull_port_lb(struct sw_evdev *sw, uint32_t port_id)
     456                 :            : {
     457                 :       8221 :         return __pull_port_lb(sw, port_id, 1);
     458                 :            : }
     459                 :            : 
     460                 :            : static uint32_t
     461         [ +  - ]:    4211070 : sw_schedule_pull_port_no_reorder(struct sw_evdev *sw, uint32_t port_id)
     462                 :            : {
     463                 :    4211070 :         return __pull_port_lb(sw, port_id, 0);
     464                 :            : }
     465                 :            : 
     466                 :            : static uint32_t
     467                 :    4204515 : sw_schedule_pull_port_dir(struct sw_evdev *sw, uint32_t port_id)
     468                 :            : {
     469                 :            :         uint32_t pkts_iter = 0;
     470                 :            :         struct sw_port *port = &sw->ports[port_id];
     471                 :            : 
     472                 :            :         /* If shadow ring has 0 pkts, pull from worker ring */
     473   [ +  -  +  - ]:    4204515 :         if (!sw->refill_once_per_iter && port->pp_buf_count == 0)
     474                 :            :                 sw_refill_pp_buf(sw, port);
     475                 :            : 
     476         [ +  + ]:    4209616 :         while (port->pp_buf_count) {
     477                 :       5101 :                 const struct rte_event *qe = &port->pp_buf[port->pp_buf_start];
     478                 :       5101 :                 uint8_t flags = qe->op;
     479                 :            : 
     480         [ +  + ]:       5101 :                 if ((flags & QE_FLAG_VALID) == 0)
     481                 :       4098 :                         goto end_qe;
     482                 :            : 
     483                 :       1003 :                 uint32_t iq_num = PRIO_TO_IQ(qe->priority);
     484                 :       1003 :                 struct sw_qid *qid = &sw->qids[qe->queue_id];
     485                 :            :                 struct sw_iq *iq = &qid->iq[iq_num];
     486                 :            : 
     487                 :       1003 :                 port->stats.rx_pkts++;
     488                 :            : 
     489                 :            :                 /* Use the iq_num from above to push the QE
     490                 :            :                  * into the qid at the right priority
     491                 :            :                  */
     492         [ +  + ]:       1003 :                 qid->iq_pkt_mask |= (1 << (iq_num));
     493                 :            :                 iq_enqueue(sw, iq, qe);
     494                 :       1003 :                 qid->iq_pkt_count[iq_num]++;
     495                 :       1003 :                 qid->stats.rx_pkts++;
     496                 :       1003 :                 pkts_iter++;
     497                 :            : 
     498                 :       5101 : end_qe:
     499                 :       5101 :                 port->pp_buf_start++;
     500                 :       5101 :                 port->pp_buf_count--;
     501                 :            :         } /* while port->pp_buf_count */
     502                 :            : 
     503                 :    4204515 :         return pkts_iter;
     504                 :            : }
     505                 :            : 
     506                 :            : int32_t
     507         [ +  - ]:    4203616 : sw_event_schedule(struct rte_eventdev *dev)
     508                 :            : {
     509                 :            :         struct sw_evdev *sw = sw_pmd_priv(dev);
     510                 :            :         uint32_t in_pkts, out_pkts;
     511                 :            :         uint32_t out_pkts_total = 0, in_pkts_total = 0;
     512                 :    4203616 :         int32_t sched_quanta = sw->sched_quanta;
     513                 :            :         uint32_t i;
     514                 :            : 
     515                 :    4203616 :         sw->sched_called++;
     516         [ +  - ]:    4203616 :         if (unlikely(!sw->started))
     517                 :            :                 return -EAGAIN;
     518                 :            : 
     519                 :            :         do {
     520                 :            :                 uint32_t in_pkts_this_iteration = 0;
     521                 :            : 
     522                 :            :                 /* Pull from rx_ring for ports */
     523                 :            :                 do {
     524                 :            :                         in_pkts = 0;
     525         [ +  + ]:   12636715 :                         for (i = 0; i < sw->port_count; i++) {
     526                 :            :                                 /* ack the unlinks in progress as done */
     527         [ +  + ]:    8423806 :                                 if (sw->ports[i].unlinks_in_progress)
     528                 :          2 :                                         sw->ports[i].unlinks_in_progress = 0;
     529                 :            : 
     530         [ +  + ]:    8423806 :                                 if (sw->ports[i].is_directed)
     531                 :    4204515 :                                         in_pkts += sw_schedule_pull_port_dir(sw, i);
     532         [ +  + ]:    4219291 :                                 else if (sw->ports[i].num_ordered_qids > 0)
     533                 :       8221 :                                         in_pkts += sw_schedule_pull_port_lb(sw, i);
     534                 :            :                                 else
     535                 :    4211070 :                                         in_pkts += sw_schedule_pull_port_no_reorder(sw, i);
     536                 :            :                         }
     537                 :            : 
     538                 :            :                         /* QID scan for re-ordered */
     539                 :    8425818 :                         in_pkts += sw_schedule_reorder(sw, 0,
     540                 :    4212909 :                                         sw->qid_count);
     541                 :    4212909 :                         in_pkts_this_iteration += in_pkts;
     542                 :    4212909 :                 } while (in_pkts > 4 &&
     543         [ +  + ]:    4212909 :                                 (int)in_pkts_this_iteration < sched_quanta);
     544                 :            : 
     545                 :    4212902 :                 out_pkts = sw_schedule_qid_to_cq(sw);
     546                 :    4212902 :                 out_pkts_total += out_pkts;
     547                 :    4212902 :                 in_pkts_total += in_pkts_this_iteration;
     548                 :            : 
     549         [ +  + ]:    4212902 :                 if (in_pkts == 0 && out_pkts == 0)
     550                 :            :                         break;
     551         [ +  - ]:       9286 :         } while ((int)out_pkts_total < sched_quanta);
     552                 :            : 
     553                 :    4203616 :         sw->stats.tx_pkts += out_pkts_total;
     554                 :    4203616 :         sw->stats.rx_pkts += in_pkts_total;
     555                 :            : 
     556                 :    4203616 :         sw->sched_no_iq_enqueues += (in_pkts_total == 0);
     557                 :    4203616 :         sw->sched_no_cq_enqueues += (out_pkts_total == 0);
     558                 :            : 
     559                 :    4203616 :         uint64_t work_done = (in_pkts_total + out_pkts_total) != 0;
     560                 :    4203616 :         sw->sched_progress_last_iter = work_done;
     561                 :            : 
     562                 :            :         uint64_t cqs_scheds_last_iter = 0;
     563                 :            : 
     564                 :            :         /* push all the internal buffered QEs in port->cq_ring to the
     565                 :            :          * worker cores: aka, do the ring transfers batched.
     566                 :            :          */
     567                 :            :         int no_enq = 1;
     568         [ +  + ]:   12609849 :         for (i = 0; i < sw->port_count; i++) {
     569                 :            :                 struct sw_port *port = &sw->ports[i];
     570                 :    8406233 :                 struct rte_event_ring *worker = port->cq_worker_ring;
     571                 :            : 
     572                 :            :                 /* If shadow ring has 0 pkts, pull from worker ring */
     573   [ -  +  -  - ]:    8406233 :                 if (sw->refill_once_per_iter && port->pp_buf_count == 0)
     574                 :            :                         sw_refill_pp_buf(sw, port);
     575                 :            : 
     576         [ +  + ]:    8406233 :                 if (port->cq_buf_count >= sw->sched_min_burst) {
     577                 :            :                         rte_event_ring_enqueue_burst(worker,
     578   [ -  +  -  -  :       9293 :                                         port->cq_buf,
                      - ]
     579                 :            :                                         port->cq_buf_count,
     580                 :            :                                         &sw->cq_ring_space[i]);
     581                 :       9293 :                         port->cq_buf_count = 0;
     582                 :            :                         no_enq = 0;
     583                 :       9293 :                         cqs_scheds_last_iter |= (1ULL << i);
     584                 :            :                 } else {
     585                 :    8396940 :                         sw->cq_ring_space[i] =
     586                 :    8396940 :                                         rte_event_ring_free_count(worker) -
     587                 :            :                                         port->cq_buf_count;
     588                 :            :                 }
     589                 :            :         }
     590                 :            : 
     591         [ +  + ]:    4203616 :         if (no_enq) {
     592         [ +  + ]:    4194338 :                 if (unlikely(sw->sched_flush_count > SCHED_NO_ENQ_CYCLE_FLUSH))
     593                 :    4189952 :                         sw->sched_min_burst = 1;
     594                 :            :                 else
     595                 :       4386 :                         sw->sched_flush_count++;
     596                 :            :         } else {
     597         [ +  + ]:       9278 :                 if (sw->sched_flush_count)
     598                 :       4126 :                         sw->sched_flush_count--;
     599                 :            :                 else
     600                 :       5152 :                         sw->sched_min_burst = sw->sched_min_burst_size;
     601                 :            :         }
     602                 :            : 
     603                 :            :         /* Provide stats on what eventdev ports were scheduled to this
     604                 :            :          * iteration. If more than 64 ports are active, always report that
     605                 :            :          * all Eventdev ports have been scheduled events.
     606                 :            :          */
     607                 :    4203616 :         sw->sched_last_iter_bitmask = cqs_scheds_last_iter;
     608         [ -  + ]:    4203616 :         if (unlikely(sw->port_count >= 64))
     609                 :          0 :                 sw->sched_last_iter_bitmask = UINT64_MAX;
     610                 :            : 
     611         [ +  + ]:    4203616 :         return work_done ? 0 : -EAGAIN;
     612                 :            : }

Generated by: LCOV version 1.14