LCOV - code coverage report
Current view: top level - drivers/net/ena/base - ena_eth_com.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 53 0.0 %
Date: 2024-01-22 16:13:49 Functions: 0 3 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 40 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2015-2020 Amazon.com, Inc. or its affiliates.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #ifndef ENA_ETH_COM_H_
       7                 :            : #define ENA_ETH_COM_H_
       8                 :            : 
       9                 :            : #if defined(__cplusplus)
      10                 :            : extern "C" {
      11                 :            : #endif
      12                 :            : #include "ena_com.h"
      13                 :            : 
      14                 :            : /* we allow 2 DMA descriptors per LLQ entry */
      15                 :            : #define ENA_LLQ_ENTRY_DESC_CHUNK_SIZE   (2 * sizeof(struct ena_eth_io_tx_desc))
      16                 :            : #define ENA_LLQ_HEADER          (128UL - ENA_LLQ_ENTRY_DESC_CHUNK_SIZE)
      17                 :            : #define ENA_LLQ_LARGE_HEADER    (256UL - ENA_LLQ_ENTRY_DESC_CHUNK_SIZE)
      18                 :            : 
      19                 :            : struct ena_com_tx_ctx {
      20                 :            :         struct ena_com_tx_meta ena_meta;
      21                 :            :         struct ena_com_buf *ena_bufs;
      22                 :            :         /* For LLQ, header buffer - pushed to the device mem space */
      23                 :            :         void *push_header;
      24                 :            : 
      25                 :            :         enum ena_eth_io_l3_proto_index l3_proto;
      26                 :            :         enum ena_eth_io_l4_proto_index l4_proto;
      27                 :            :         u16 num_bufs;
      28                 :            :         u16 req_id;
      29                 :            :         /* For regular queue, indicate the size of the header
      30                 :            :          * For LLQ, indicate the size of the pushed buffer
      31                 :            :          */
      32                 :            :         u16 header_len;
      33                 :            : 
      34                 :            :         u8 meta_valid;
      35                 :            :         u8 tso_enable;
      36                 :            :         u8 l3_csum_enable;
      37                 :            :         u8 l4_csum_enable;
      38                 :            :         u8 l4_csum_partial;
      39                 :            :         u8 df; /* Don't fragment */
      40                 :            : };
      41                 :            : 
      42                 :            : struct ena_com_rx_ctx {
      43                 :            :         struct ena_com_rx_buf_info *ena_bufs;
      44                 :            :         enum ena_eth_io_l3_proto_index l3_proto;
      45                 :            :         enum ena_eth_io_l4_proto_index l4_proto;
      46                 :            :         bool l3_csum_err;
      47                 :            :         bool l4_csum_err;
      48                 :            :         u8 l4_csum_checked;
      49                 :            :         /* fragmented packet */
      50                 :            :         bool frag;
      51                 :            :         u32 hash;
      52                 :            :         u16 descs;
      53                 :            :         u16 max_bufs;
      54                 :            :         u8 pkt_offset;
      55                 :            : };
      56                 :            : 
      57                 :            : int ena_com_prepare_tx(struct ena_com_io_sq *io_sq,
      58                 :            :                        struct ena_com_tx_ctx *ena_tx_ctx,
      59                 :            :                        int *nb_hw_desc);
      60                 :            : 
      61                 :            : int ena_com_rx_pkt(struct ena_com_io_cq *io_cq,
      62                 :            :                    struct ena_com_io_sq *io_sq,
      63                 :            :                    struct ena_com_rx_ctx *ena_rx_ctx);
      64                 :            : 
      65                 :            : int ena_com_add_single_rx_desc(struct ena_com_io_sq *io_sq,
      66                 :            :                                struct ena_com_buf *ena_buf,
      67                 :            :                                u16 req_id);
      68                 :            : 
      69                 :            : bool ena_com_cq_empty(struct ena_com_io_cq *io_cq);
      70                 :            : 
      71                 :            : static inline void ena_com_unmask_intr(struct ena_com_io_cq *io_cq,
      72                 :            :                                        struct ena_eth_io_intr_reg *intr_reg)
      73                 :            : {
      74                 :          0 :         ENA_REG_WRITE32(io_cq->bus, intr_reg->intr_control, io_cq->unmask_reg);
      75                 :            : }
      76                 :            : 
      77                 :            : static inline int ena_com_free_q_entries(struct ena_com_io_sq *io_sq)
      78                 :            : {
      79                 :            :         u16 tail, next_to_comp, cnt;
      80                 :            : 
      81                 :          0 :         next_to_comp = io_sq->next_to_comp;
      82                 :          0 :         tail = io_sq->tail;
      83                 :          0 :         cnt = tail - next_to_comp;
      84                 :            : 
      85   [ #  #  #  # ]:          0 :         return io_sq->q_depth - 1 - cnt;
      86                 :            : }
      87                 :            : 
      88                 :            : /* Check if the submission queue has enough space to hold required_buffers */
      89                 :            : static inline bool ena_com_sq_have_enough_space(struct ena_com_io_sq *io_sq,
      90                 :            :                                                 u16 required_buffers)
      91                 :            : {
      92                 :            :         int temp;
      93                 :            : 
      94   [ #  #  #  # ]:          0 :         if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
      95                 :          0 :                 return ena_com_free_q_entries(io_sq) >= required_buffers;
      96                 :            : 
      97                 :            :         /* This calculation doesn't need to be 100% accurate. So to reduce
      98                 :            :          * the calculation overhead just Subtract 2 lines from the free descs
      99                 :            :          * (one for the header line and one to compensate the devision
     100                 :            :          * down calculation.
     101                 :            :          */
     102                 :          0 :         temp = required_buffers / io_sq->llq_info.descs_per_entry + 2;
     103                 :            : 
     104                 :          0 :         return ena_com_free_q_entries(io_sq) > temp;
     105                 :            : }
     106                 :            : 
     107                 :            : static inline bool ena_com_meta_desc_changed(struct ena_com_io_sq *io_sq,
     108                 :            :                                              struct ena_com_tx_ctx *ena_tx_ctx)
     109                 :            : {
     110         [ #  # ]:          0 :         if (!ena_tx_ctx->meta_valid)
     111                 :            :                 return false;
     112                 :            : 
     113         [ #  # ]:          0 :         return !!memcmp(&io_sq->cached_tx_meta,
     114                 :          0 :                         &ena_tx_ctx->ena_meta,
     115                 :            :                         sizeof(struct ena_com_tx_meta));
     116                 :            : }
     117                 :            : 
     118                 :            : static inline bool is_llq_max_tx_burst_exists(struct ena_com_io_sq *io_sq)
     119                 :            : {
     120   [ #  #  #  # ]:          0 :         return (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) &&
     121   [ #  #  #  # ]:          0 :                io_sq->llq_info.max_entries_in_tx_burst > 0;
     122                 :            : }
     123                 :            : 
     124         [ #  # ]:          0 : static inline bool ena_com_is_doorbell_needed(struct ena_com_io_sq *io_sq,
     125                 :            :                                               struct ena_com_tx_ctx *ena_tx_ctx)
     126                 :            : {
     127                 :            :         struct ena_com_llq_info *llq_info;
     128                 :            :         int descs_after_first_entry;
     129                 :            :         int num_entries_needed = 1;
     130                 :            :         u16 num_descs;
     131                 :            : 
     132         [ #  # ]:          0 :         if (!is_llq_max_tx_burst_exists(io_sq))
     133                 :            :                 return false;
     134                 :            : 
     135                 :            :         llq_info = &io_sq->llq_info;
     136                 :          0 :         num_descs = ena_tx_ctx->num_bufs;
     137                 :            : 
     138         [ #  # ]:          0 :         if (llq_info->disable_meta_caching ||
     139         [ #  # ]:          0 :             unlikely(ena_com_meta_desc_changed(io_sq, ena_tx_ctx)))
     140                 :          0 :                 ++num_descs;
     141                 :            : 
     142         [ #  # ]:          0 :         if (num_descs > llq_info->descs_num_before_header) {
     143                 :          0 :                 descs_after_first_entry = num_descs - llq_info->descs_num_before_header;
     144                 :          0 :                 num_entries_needed += DIV_ROUND_UP(descs_after_first_entry,
     145                 :            :                                                    llq_info->descs_per_entry);
     146                 :            :         }
     147                 :            : 
     148                 :          0 :         ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
     149                 :            :                     "Queue: %d num_descs: %d num_entries_needed: %d\n",
     150                 :            :                     io_sq->qid, num_descs, num_entries_needed);
     151                 :            : 
     152                 :          0 :         return num_entries_needed > io_sq->entries_in_tx_burst_left;
     153                 :            : }
     154                 :            : 
     155                 :          0 : static inline int ena_com_write_sq_doorbell(struct ena_com_io_sq *io_sq)
     156                 :            : {
     157                 :          0 :         u16 max_entries_in_tx_burst = io_sq->llq_info.max_entries_in_tx_burst;
     158                 :          0 :         u16 tail = io_sq->tail;
     159                 :            : 
     160                 :          0 :         ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
     161                 :            :                     "Write submission queue doorbell for queue: %d tail: %d\n",
     162                 :            :                     io_sq->qid, tail);
     163                 :            : 
     164                 :          0 :         ENA_REG_WRITE32(io_sq->bus, tail, io_sq->db_addr);
     165                 :            : 
     166         [ #  # ]:          0 :         if (is_llq_max_tx_burst_exists(io_sq)) {
     167                 :          0 :                 ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
     168                 :            :                             "Reset available entries in tx burst for queue %d to %d\n",
     169                 :            :                             io_sq->qid, max_entries_in_tx_burst);
     170                 :          0 :                 io_sq->entries_in_tx_burst_left = max_entries_in_tx_burst;
     171                 :            :         }
     172                 :            : 
     173                 :          0 :         return 0;
     174                 :            : }
     175                 :            : 
     176                 :            : static inline void ena_com_update_numa_node(struct ena_com_io_cq *io_cq,
     177                 :            :                                             u8 numa_node)
     178                 :            : {
     179                 :            :         struct ena_eth_io_numa_node_cfg_reg numa_cfg;
     180                 :            : 
     181         [ #  # ]:          0 :         if (!io_cq->numa_node_cfg_reg)
     182                 :            :                 return;
     183                 :            : 
     184                 :            :         numa_cfg.numa_cfg = (numa_node & ENA_ETH_IO_NUMA_NODE_CFG_REG_NUMA_MASK)
     185                 :          0 :                 | ENA_ETH_IO_NUMA_NODE_CFG_REG_ENABLED_MASK;
     186                 :            : 
     187                 :            :         ENA_REG_WRITE32(io_cq->bus, numa_cfg.numa_cfg, io_cq->numa_node_cfg_reg);
     188                 :            : }
     189                 :            : 
     190                 :            : static inline void ena_com_comp_ack(struct ena_com_io_sq *io_sq, u16 elem)
     191                 :            : {
     192                 :          0 :         io_sq->next_to_comp += elem;
     193                 :          0 : }
     194                 :            : 
     195                 :            : static inline void ena_com_cq_inc_head(struct ena_com_io_cq *io_cq)
     196                 :            : {
     197                 :          0 :         io_cq->head++;
     198                 :            : 
     199                 :            :         /* Switch phase bit in case of wrap around */
     200         [ #  # ]:          0 :         if (unlikely((io_cq->head & (io_cq->q_depth - 1)) == 0))
     201                 :          0 :                 io_cq->phase ^= 1;
     202                 :            : }
     203                 :            : 
     204                 :          0 : static inline int ena_com_tx_comp_req_id_get(struct ena_com_io_cq *io_cq,
     205                 :            :                                              u16 *req_id)
     206                 :            : {
     207                 :            :         u8 expected_phase, cdesc_phase;
     208                 :            :         struct ena_eth_io_tx_cdesc *cdesc;
     209                 :            :         u16 masked_head;
     210                 :            : 
     211                 :          0 :         masked_head = io_cq->head & (io_cq->q_depth - 1);
     212                 :          0 :         expected_phase = io_cq->phase;
     213                 :            : 
     214                 :          0 :         cdesc = (struct ena_eth_io_tx_cdesc *)
     215                 :          0 :                 ((uintptr_t)io_cq->cdesc_addr.virt_addr +
     216                 :          0 :                 (masked_head * io_cq->cdesc_entry_size_in_bytes));
     217                 :            : 
     218                 :            :         /* When the current completion descriptor phase isn't the same as the
     219                 :            :          * expected, it mean that the device still didn't update
     220                 :            :          * this completion.
     221                 :            :          */
     222                 :          0 :         cdesc_phase = READ_ONCE16(cdesc->flags) & ENA_ETH_IO_TX_CDESC_PHASE_MASK;
     223         [ #  # ]:          0 :         if (cdesc_phase != expected_phase)
     224                 :            :                 return ENA_COM_TRY_AGAIN;
     225                 :            : 
     226                 :            :         dma_rmb();
     227                 :            : 
     228                 :          0 :         *req_id = READ_ONCE16(cdesc->req_id);
     229         [ #  # ]:          0 :         if (unlikely(*req_id >= io_cq->q_depth)) {
     230                 :          0 :                 ena_trc_err(ena_com_io_cq_to_ena_dev(io_cq),
     231                 :            :                             "Invalid req id %d\n", cdesc->req_id);
     232                 :          0 :                 return ENA_COM_INVAL;
     233                 :            :         }
     234                 :            : 
     235                 :            :         ena_com_cq_inc_head(io_cq);
     236                 :            : 
     237                 :            :         return 0;
     238                 :            : }
     239                 :            : 
     240                 :            : #if defined(__cplusplus)
     241                 :            : }
     242                 :            : #endif
     243                 :            : #endif /* ENA_ETH_COM_H_ */

Generated by: LCOV version 1.14