LCOV - code coverage report
Current view: top level - drivers/net/cxgbe - sge.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 978 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 42 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 569 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2014-2018 Chelsio Communications.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <sys/queue.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <errno.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <string.h>
      11                 :            : #include <unistd.h>
      12                 :            : #include <stdarg.h>
      13                 :            : #include <inttypes.h>
      14                 :            : #include <netinet/in.h>
      15                 :            : 
      16                 :            : #include <rte_byteorder.h>
      17                 :            : #include <rte_common.h>
      18                 :            : #include <rte_cycles.h>
      19                 :            : #include <rte_interrupts.h>
      20                 :            : #include <rte_log.h>
      21                 :            : #include <rte_debug.h>
      22                 :            : #include <rte_pci.h>
      23                 :            : #include <rte_branch_prediction.h>
      24                 :            : #include <rte_memory.h>
      25                 :            : #include <rte_memzone.h>
      26                 :            : #include <rte_tailq.h>
      27                 :            : #include <rte_eal.h>
      28                 :            : #include <rte_alarm.h>
      29                 :            : #include <rte_ether.h>
      30                 :            : #include <ethdev_driver.h>
      31                 :            : #include <rte_malloc.h>
      32                 :            : #include <rte_random.h>
      33                 :            : #include <dev_driver.h>
      34                 :            : 
      35                 :            : #include "base/common.h"
      36                 :            : #include "base/t4_regs.h"
      37                 :            : #include "base/t4_msg.h"
      38                 :            : #include "cxgbe.h"
      39                 :            : 
      40                 :            : static inline void ship_tx_pkt_coalesce_wr(struct adapter *adap,
      41                 :            :                                            struct sge_eth_txq *txq);
      42                 :            : 
      43                 :            : /*
      44                 :            :  * Max number of Rx buffers we replenish at a time.
      45                 :            :  */
      46                 :            : #define MAX_RX_REFILL 64U
      47                 :            : 
      48                 :            : #define NOMEM_TMR_IDX (SGE_NTIMERS - 1)
      49                 :            : 
      50                 :            : /*
      51                 :            :  * Max Tx descriptor space we allow for an Ethernet packet to be inlined
      52                 :            :  * into a WR.
      53                 :            :  */
      54                 :            : #define MAX_IMM_TX_PKT_LEN 256
      55                 :            : 
      56                 :            : /*
      57                 :            :  * Max size of a WR sent through a control Tx queue.
      58                 :            :  */
      59                 :            : #define MAX_CTRL_WR_LEN SGE_MAX_WR_LEN
      60                 :            : 
      61                 :            : /*
      62                 :            :  * Bits 0..3 of rx_sw_desc.dma_addr have special meaning.  The hardware uses
      63                 :            :  * these to specify the buffer size as an index into the SGE Free List Buffer
      64                 :            :  * Size register array.  We also use bit 4, when the buffer has been unmapped
      65                 :            :  * for DMA, but this is of course never sent to the hardware and is only used
      66                 :            :  * to prevent double unmappings.  All of the above requires that the Free List
      67                 :            :  * Buffers which we allocate have the bottom 5 bits free (0) -- i.e. are
      68                 :            :  * 32-byte or a power of 2 greater in alignment.  Since the SGE's minimal
      69                 :            :  * Free List Buffer alignment is 32 bytes, this works out for us ...
      70                 :            :  */
      71                 :            : enum {
      72                 :            :         RX_BUF_FLAGS     = 0x1f,   /* bottom five bits are special */
      73                 :            :         RX_BUF_SIZE      = 0x0f,   /* bottom three bits are for buf sizes */
      74                 :            :         RX_UNMAPPED_BUF  = 0x10,   /* buffer is not mapped */
      75                 :            : };
      76                 :            : 
      77                 :            : /**
      78                 :            :  * txq_avail - return the number of available slots in a Tx queue
      79                 :            :  * @q: the Tx queue
      80                 :            :  *
      81                 :            :  * Returns the number of descriptors in a Tx queue available to write new
      82                 :            :  * packets.
      83                 :            :  */
      84                 :            : static inline unsigned int txq_avail(const struct sge_txq *q)
      85                 :            : {
      86                 :          0 :         return q->size - 1 - q->in_use;
      87                 :            : }
      88                 :            : 
      89                 :            : static int map_mbuf(struct rte_mbuf *mbuf, dma_addr_t *addr)
      90                 :            : {
      91                 :            :         struct rte_mbuf *m = mbuf;
      92                 :            : 
      93   [ #  #  #  # ]:          0 :         for (; m; m = m->next, addr++) {
      94   [ #  #  #  # ]:          0 :                 *addr = m->buf_iova + rte_pktmbuf_headroom(m);
      95   [ #  #  #  # ]:          0 :                 if (*addr == 0)
      96                 :          0 :                         goto out_err;
      97                 :            :         }
      98                 :            :         return 0;
      99                 :            : 
     100                 :            : out_err:
     101                 :          0 :         return -ENOMEM;
     102                 :            : }
     103                 :            : 
     104                 :            : /**
     105                 :            :  * free_tx_desc - reclaims Tx descriptors and their buffers
     106                 :            :  * @q: the Tx queue to reclaim descriptors from
     107                 :            :  * @n: the number of descriptors to reclaim
     108                 :            :  *
     109                 :            :  * Reclaims Tx descriptors from an SGE Tx queue and frees the associated
     110                 :            :  * Tx buffers.  Called with the Tx queue lock held.
     111                 :            :  */
     112                 :          0 : static void free_tx_desc(struct sge_txq *q, unsigned int n)
     113                 :            : {
     114                 :            :         struct tx_sw_desc *d;
     115                 :            :         unsigned int cidx = 0;
     116                 :            : 
     117                 :          0 :         d = &q->sdesc[cidx];
     118         [ #  # ]:          0 :         while (n--) {
     119         [ #  # ]:          0 :                 if (d->mbuf) {                       /* an SGL is present */
     120                 :          0 :                         rte_pktmbuf_free(d->mbuf);
     121                 :          0 :                         d->mbuf = NULL;
     122                 :            :                 }
     123         [ #  # ]:          0 :                 if (d->coalesce.idx) {
     124                 :            :                         int i;
     125                 :            : 
     126         [ #  # ]:          0 :                         for (i = 0; i < d->coalesce.idx; i++) {
     127                 :          0 :                                 rte_pktmbuf_free(d->coalesce.mbuf[i]);
     128                 :          0 :                                 d->coalesce.mbuf[i] = NULL;
     129                 :            :                         }
     130                 :          0 :                         d->coalesce.idx = 0;
     131                 :            :                 }
     132                 :          0 :                 ++d;
     133         [ #  # ]:          0 :                 if (++cidx == q->size) {
     134                 :            :                         cidx = 0;
     135                 :          0 :                         d = q->sdesc;
     136                 :            :                 }
     137                 :          0 :                 RTE_MBUF_PREFETCH_TO_FREE(&q->sdesc->mbuf->pool);
     138                 :            :         }
     139                 :          0 : }
     140                 :            : 
     141                 :          0 : static void reclaim_tx_desc(struct sge_txq *q, unsigned int n)
     142                 :            : {
     143                 :            :         struct tx_sw_desc *d;
     144                 :          0 :         unsigned int cidx = q->cidx;
     145                 :            : 
     146                 :          0 :         d = &q->sdesc[cidx];
     147         [ #  # ]:          0 :         while (n--) {
     148         [ #  # ]:          0 :                 if (d->mbuf) {                       /* an SGL is present */
     149                 :          0 :                         rte_pktmbuf_free(d->mbuf);
     150                 :          0 :                         d->mbuf = NULL;
     151                 :            :                 }
     152                 :          0 :                 ++d;
     153         [ #  # ]:          0 :                 if (++cidx == q->size) {
     154                 :            :                         cidx = 0;
     155                 :          0 :                         d = q->sdesc;
     156                 :            :                 }
     157                 :            :         }
     158                 :          0 :         q->cidx = cidx;
     159                 :          0 : }
     160                 :            : 
     161                 :            : /**
     162                 :            :  * fl_cap - return the capacity of a free-buffer list
     163                 :            :  * @fl: the FL
     164                 :            :  *
     165                 :            :  * Returns the capacity of a free-buffer list.  The capacity is less than
     166                 :            :  * the size because one descriptor needs to be left unpopulated, otherwise
     167                 :            :  * HW will think the FL is empty.
     168                 :            :  */
     169                 :            : static inline unsigned int fl_cap(const struct sge_fl *fl)
     170                 :            : {
     171                 :          0 :         return fl->size - 8;   /* 1 descriptor = 8 buffers */
     172                 :            : }
     173                 :            : 
     174                 :            : /**
     175                 :            :  * fl_starving - return whether a Free List is starving.
     176                 :            :  * @adapter: pointer to the adapter
     177                 :            :  * @fl: the Free List
     178                 :            :  *
     179                 :            :  * Tests specified Free List to see whether the number of buffers
     180                 :            :  * available to the hardware has fallen below our "starvation"
     181                 :            :  * threshold.
     182                 :            :  */
     183                 :            : static inline bool fl_starving(const struct adapter *adapter,
     184                 :            :                                const struct sge_fl *fl)
     185                 :            : {
     186                 :            :         const struct sge *s = &adapter->sge;
     187                 :            : 
     188                 :          0 :         return fl->avail - fl->pend_cred <= s->fl_starve_thres;
     189                 :            : }
     190                 :            : 
     191                 :            : static inline unsigned int get_buf_size(struct adapter *adapter,
     192                 :            :                                         const struct rx_sw_desc *d)
     193                 :            : {
     194                 :          0 :         return adapter->sge.fl_buffer_size[d->dma_addr & RX_BUF_SIZE];
     195                 :            : }
     196                 :            : 
     197                 :            : /**
     198                 :            :  * free_rx_bufs - free the Rx buffers on an SGE free list
     199                 :            :  * @q: the SGE free list to free buffers from
     200                 :            :  * @n: how many buffers to free
     201                 :            :  *
     202                 :            :  * Release the next @n buffers on an SGE free-buffer Rx queue.   The
     203                 :            :  * buffers must be made inaccessible to HW before calling this function.
     204                 :            :  */
     205                 :          0 : static void free_rx_bufs(struct sge_fl *q, int n)
     206                 :            : {
     207                 :          0 :         unsigned int cidx = q->cidx;
     208                 :            :         struct rx_sw_desc *d;
     209                 :            : 
     210                 :          0 :         d = &q->sdesc[cidx];
     211         [ #  # ]:          0 :         while (n--) {
     212         [ #  # ]:          0 :                 if (d->buf) {
     213                 :          0 :                         rte_pktmbuf_free(d->buf);
     214                 :          0 :                         d->buf = NULL;
     215                 :            :                 }
     216                 :          0 :                 ++d;
     217         [ #  # ]:          0 :                 if (++cidx == q->size) {
     218                 :            :                         cidx = 0;
     219                 :          0 :                         d = q->sdesc;
     220                 :            :                 }
     221                 :          0 :                 q->avail--;
     222                 :            :         }
     223                 :          0 :         q->cidx = cidx;
     224                 :          0 : }
     225                 :            : 
     226                 :            : /**
     227                 :            :  * unmap_rx_buf - unmap the current Rx buffer on an SGE free list
     228                 :            :  * @q: the SGE free list
     229                 :            :  *
     230                 :            :  * Unmap the current buffer on an SGE free-buffer Rx queue.   The
     231                 :            :  * buffer must be made inaccessible to HW before calling this function.
     232                 :            :  *
     233                 :            :  * This is similar to @free_rx_bufs above but does not free the buffer.
     234                 :            :  * Do note that the FL still loses any further access to the buffer.
     235                 :            :  */
     236                 :            : static void unmap_rx_buf(struct sge_fl *q)
     237                 :            : {
     238                 :          0 :         if (++q->cidx == q->size)
     239                 :          0 :                 q->cidx = 0;
     240                 :          0 :         q->avail--;
     241                 :            : }
     242                 :            : 
     243                 :          0 : static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
     244                 :            : {
     245         [ #  # ]:          0 :         if (q->pend_cred >= 64) {
     246                 :          0 :                 u32 val = adap->params.arch.sge_fl_db;
     247                 :            : 
     248         [ #  # ]:          0 :                 if (is_t4(adap->params.chip))
     249                 :          0 :                         val |= V_PIDX(q->pend_cred / 8);
     250                 :            :                 else
     251                 :          0 :                         val |= V_PIDX_T5(q->pend_cred / 8);
     252                 :            : 
     253                 :            :                 /*
     254                 :            :                  * Make sure all memory writes to the Free List queue are
     255                 :            :                  * committed before we tell the hardware about them.
     256                 :            :                  */
     257                 :            :                 wmb();
     258                 :            : 
     259                 :            :                 /*
     260                 :            :                  * If we don't have access to the new User Doorbell (T5+), use
     261                 :            :                  * the old doorbell mechanism; otherwise use the new BAR2
     262                 :            :                  * mechanism.
     263                 :            :                  */
     264         [ #  # ]:          0 :                 if (unlikely(!q->bar2_addr)) {
     265         [ #  # ]:          0 :                         u32 reg = is_pf4(adap) ? MYPF_REG(A_SGE_PF_KDOORBELL) :
     266                 :            :                                                  T4VF_SGE_BASE_ADDR +
     267                 :            :                                                  A_SGE_VF_KDOORBELL;
     268                 :            : 
     269                 :          0 :                         t4_write_reg_relaxed(adap, reg,
     270                 :          0 :                                              val | V_QID(q->cntxt_id));
     271                 :            :                 } else {
     272                 :          0 :                         writel_relaxed(val | V_QID(q->bar2_qid),
     273                 :          0 :                                        (void *)((uintptr_t)q->bar2_addr +
     274                 :            :                                        SGE_UDB_KDOORBELL));
     275                 :            : 
     276                 :            :                         /*
     277                 :            :                          * This Write memory Barrier will force the write to
     278                 :            :                          * the User Doorbell area to be flushed.
     279                 :            :                          */
     280                 :            :                         wmb();
     281                 :            :                 }
     282                 :          0 :                 q->pend_cred &= 7;
     283                 :            :         }
     284                 :          0 : }
     285                 :            : 
     286                 :            : static inline void set_rx_sw_desc(struct rx_sw_desc *sd, void *buf,
     287                 :            :                                   dma_addr_t mapping)
     288                 :            : {
     289                 :          0 :         sd->buf = buf;
     290                 :          0 :         sd->dma_addr = mapping;      /* includes size low bits */
     291                 :            : }
     292                 :            : 
     293                 :            : /**
     294                 :            :  * refill_fl_usembufs - refill an SGE Rx buffer ring with mbufs
     295                 :            :  * @adap: the adapter
     296                 :            :  * @q: the ring to refill
     297                 :            :  * @n: the number of new buffers to allocate
     298                 :            :  *
     299                 :            :  * (Re)populate an SGE free-buffer queue with up to @n new packet buffers,
     300                 :            :  * allocated with the supplied gfp flags.  The caller must assure that
     301                 :            :  * @n does not exceed the queue's capacity.  If afterwards the queue is
     302                 :            :  * found critically low mark it as starving in the bitmap of starving FLs.
     303                 :            :  *
     304                 :            :  * Returns the number of buffers allocated.
     305                 :            :  */
     306                 :          0 : static unsigned int refill_fl_usembufs(struct adapter *adap, struct sge_fl *q,
     307                 :            :                                        int n)
     308                 :          0 : {
     309                 :          0 :         struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, fl);
     310                 :          0 :         struct rx_sw_desc *sd = &q->sdesc[q->pidx];
     311                 :          0 :         __be64 *d = &q->desc[q->pidx];
     312                 :          0 :         struct rte_mbuf *buf_bulk[n];
     313                 :          0 :         unsigned int cred = q->avail;
     314                 :            :         int ret, i;
     315                 :            : 
     316         [ #  # ]:          0 :         ret = rte_mempool_get_bulk(rxq->rspq.mb_pool, (void *)buf_bulk, n);
     317         [ #  # ]:          0 :         if (unlikely(ret != 0)) {
     318                 :          0 :                 dev_debug(adap, "%s: failed to allocated fl entries in bulk ..\n",
     319                 :            :                           __func__);
     320                 :          0 :                 q->alloc_failed++;
     321                 :          0 :                 rxq->rspq.eth_dev->data->rx_mbuf_alloc_failed++;
     322                 :          0 :                 goto out;
     323                 :            :         }
     324                 :            : 
     325         [ #  # ]:          0 :         for (i = 0; i < n; i++) {
     326                 :          0 :                 struct rte_mbuf *mbuf = buf_bulk[i];
     327                 :            :                 dma_addr_t mapping;
     328                 :            : 
     329         [ #  # ]:          0 :                 if (!mbuf) {
     330                 :          0 :                         dev_debug(adap, "%s: mbuf alloc failed\n", __func__);
     331                 :          0 :                         q->alloc_failed++;
     332                 :          0 :                         rxq->rspq.eth_dev->data->rx_mbuf_alloc_failed++;
     333                 :          0 :                         goto out;
     334                 :            :                 }
     335                 :            : 
     336                 :            :                 rte_mbuf_refcnt_set(mbuf, 1);
     337                 :          0 :                 mbuf->data_off = RTE_PKTMBUF_HEADROOM;
     338                 :          0 :                 mbuf->next = NULL;
     339                 :          0 :                 mbuf->nb_segs = 1;
     340                 :          0 :                 mbuf->port = rxq->rspq.port_id;
     341                 :            : 
     342                 :          0 :                 mapping = (dma_addr_t)(mbuf->buf_iova + mbuf->data_off);
     343                 :          0 :                 mapping |= q->fl_buf_size_idx;
     344         [ #  # ]:          0 :                 *d++ = cpu_to_be64(mapping);
     345                 :            :                 set_rx_sw_desc(sd, mbuf, mapping);
     346                 :          0 :                 sd++;
     347                 :            : 
     348                 :          0 :                 q->avail++;
     349         [ #  # ]:          0 :                 if (++q->pidx == q->size) {
     350                 :          0 :                         q->pidx = 0;
     351                 :          0 :                         sd = q->sdesc;
     352                 :          0 :                         d = q->desc;
     353                 :            :                 }
     354                 :            :         }
     355                 :            : 
     356                 :          0 : out:    cred = q->avail - cred;
     357                 :          0 :         q->pend_cred += cred;
     358                 :          0 :         ring_fl_db(adap, q);
     359                 :            : 
     360         [ #  # ]:          0 :         if (unlikely(fl_starving(adap, q))) {
     361                 :            :                 /*
     362                 :            :                  * Make sure data has been written to free list
     363                 :            :                  */
     364                 :            :                 wmb();
     365                 :          0 :                 q->low++;
     366                 :            :         }
     367                 :            : 
     368                 :          0 :         return cred;
     369                 :            : }
     370                 :            : 
     371                 :            : /**
     372                 :            :  * refill_fl - refill an SGE Rx buffer ring with mbufs
     373                 :            :  * @adap: the adapter
     374                 :            :  * @q: the ring to refill
     375                 :            :  * @n: the number of new buffers to allocate
     376                 :            :  *
     377                 :            :  * (Re)populate an SGE free-buffer queue with up to @n new packet buffers,
     378                 :            :  * allocated with the supplied gfp flags.  The caller must assure that
     379                 :            :  * @n does not exceed the queue's capacity.  Returns the number of buffers
     380                 :            :  * allocated.
     381                 :            :  */
     382                 :            : static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n)
     383                 :            : {
     384                 :          0 :         return refill_fl_usembufs(adap, q, n);
     385                 :            : }
     386                 :            : 
     387                 :            : static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
     388                 :            : {
     389                 :            :         refill_fl(adap, fl, min(MAX_RX_REFILL, fl_cap(fl) - fl->avail));
     390                 :          0 : }
     391                 :            : 
     392                 :            : /*
     393                 :            :  * Return the number of reclaimable descriptors in a Tx queue.
     394                 :            :  */
     395                 :            : static inline int reclaimable(const struct sge_txq *q)
     396                 :            : {
     397                 :          0 :         int hw_cidx = ntohs(q->stat->cidx);
     398                 :            : 
     399                 :          0 :         hw_cidx -= q->cidx;
     400   [ #  #  #  # ]:          0 :         if (hw_cidx < 0)
     401                 :          0 :                 return hw_cidx + q->size;
     402                 :            :         return hw_cidx;
     403                 :            : }
     404                 :            : 
     405                 :            : /**
     406                 :            :  * reclaim_completed_tx - reclaims completed Tx descriptors
     407                 :            :  * @q: the Tx queue to reclaim completed descriptors from
     408                 :            :  *
     409                 :            :  * Reclaims Tx descriptors that the SGE has indicated it has processed.
     410                 :            :  */
     411         [ #  # ]:          0 : void reclaim_completed_tx(struct sge_txq *q)
     412                 :            : {
     413                 :          0 :         unsigned int avail = reclaimable(q);
     414                 :            : 
     415                 :            :         do {
     416                 :            :                 /* reclaim as much as possible */
     417                 :          0 :                 reclaim_tx_desc(q, avail);
     418         [ #  # ]:          0 :                 q->in_use -= avail;
     419                 :          0 :                 avail = reclaimable(q);
     420         [ #  # ]:          0 :         } while (avail);
     421                 :          0 : }
     422                 :            : 
     423                 :            : /**
     424                 :            :  * sgl_len - calculates the size of an SGL of the given capacity
     425                 :            :  * @n: the number of SGL entries
     426                 :            :  *
     427                 :            :  * Calculates the number of flits needed for a scatter/gather list that
     428                 :            :  * can hold the given number of entries.
     429                 :            :  */
     430                 :            : static inline unsigned int sgl_len(unsigned int n)
     431                 :            : {
     432                 :            :         /*
     433                 :            :          * A Direct Scatter Gather List uses 32-bit lengths and 64-bit PCI DMA
     434                 :            :          * addresses.  The DSGL Work Request starts off with a 32-bit DSGL
     435                 :            :          * ULPTX header, then Length0, then Address0, then, for 1 <= i <= N,
     436                 :            :          * repeated sequences of { Length[i], Length[i+1], Address[i],
     437                 :            :          * Address[i+1] } (this ensures that all addresses are on 64-bit
     438                 :            :          * boundaries).  If N is even, then Length[N+1] should be set to 0 and
     439                 :            :          * Address[N+1] is omitted.
     440                 :            :          *
     441                 :            :          * The following calculation incorporates all of the above.  It's
     442                 :            :          * somewhat hard to follow but, briefly: the "+2" accounts for the
     443                 :            :          * first two flits which include the DSGL header, Length0 and
     444                 :            :          * Address0; the "(3*(n-1))/2" covers the main body of list entries (3
     445                 :            :          * flits for every pair of the remaining N) +1 if (n-1) is odd; and
     446                 :            :          * finally the "+((n-1)&1)" adds the one remaining flit needed if
     447                 :            :          * (n-1) is odd ...
     448                 :            :          */
     449                 :          0 :         n--;
     450                 :          0 :         return (3 * n) / 2 + (n & 1) + 2;
     451                 :            : }
     452                 :            : 
     453                 :            : /**
     454                 :            :  * flits_to_desc - returns the num of Tx descriptors for the given flits
     455                 :            :  * @n: the number of flits
     456                 :            :  *
     457                 :            :  * Returns the number of Tx descriptors needed for the supplied number
     458                 :            :  * of flits.
     459                 :            :  */
     460                 :            : static inline unsigned int flits_to_desc(unsigned int n)
     461                 :            : {
     462                 :          0 :         return DIV_ROUND_UP(n, 8);
     463                 :            : }
     464                 :            : 
     465                 :            : /**
     466                 :            :  * is_eth_imm - can an Ethernet packet be sent as immediate data?
     467                 :            :  * @m: the packet
     468                 :            :  *
     469                 :            :  * Returns whether an Ethernet packet is small enough to fit as
     470                 :            :  * immediate data. Return value corresponds to the headroom required.
     471                 :            :  */
     472                 :            : static inline int is_eth_imm(const struct rte_mbuf *m)
     473                 :            : {
     474                 :          0 :         unsigned int hdrlen = (m->ol_flags & RTE_MBUF_F_TX_TCP_SEG) ?
     475                 :          0 :                               sizeof(struct cpl_tx_pkt_lso_core) : 0;
     476                 :            : 
     477                 :          0 :         hdrlen += sizeof(struct cpl_tx_pkt);
     478         [ #  # ]:          0 :         if (m->pkt_len <= MAX_IMM_TX_PKT_LEN - hdrlen)
     479                 :            :                 return hdrlen;
     480                 :            : 
     481                 :            :         return 0;
     482                 :            : }
     483                 :            : 
     484                 :            : /**
     485                 :            :  * calc_tx_flits - calculate the number of flits for a packet Tx WR
     486                 :            :  * @m: the packet
     487                 :            :  * @adap: adapter structure pointer
     488                 :            :  *
     489                 :            :  * Returns the number of flits needed for a Tx WR for the given Ethernet
     490                 :            :  * packet, including the needed WR and CPL headers.
     491                 :            :  */
     492         [ #  # ]:          0 : static inline unsigned int calc_tx_flits(const struct rte_mbuf *m,
     493                 :            :                                          struct adapter *adap)
     494                 :            : {
     495         [ #  # ]:          0 :         size_t wr_size = is_pf4(adap) ? sizeof(struct fw_eth_tx_pkt_wr) :
     496                 :            :                                         sizeof(struct fw_eth_tx_pkt_vm_wr);
     497                 :            :         unsigned int flits;
     498                 :            :         int hdrlen;
     499                 :            : 
     500                 :            :         /*
     501                 :            :          * If the mbuf is small enough, we can pump it out as a work request
     502                 :            :          * with only immediate data.  In that case we just have to have the
     503                 :            :          * TX Packet header plus the mbuf data in the Work Request.
     504                 :            :          */
     505                 :            : 
     506                 :            :         hdrlen = is_eth_imm(m);
     507                 :            :         if (hdrlen)
     508                 :          0 :                 return DIV_ROUND_UP(m->pkt_len + hdrlen, sizeof(__be64));
     509                 :            : 
     510                 :            :         /*
     511                 :            :          * Otherwise, we're going to have to construct a Scatter gather list
     512                 :            :          * of the mbuf body and fragments.  We also include the flits necessary
     513                 :            :          * for the TX Packet Work Request and CPL.  We always have a firmware
     514                 :            :          * Write Header (incorporated as part of the cpl_tx_pkt_lso and
     515                 :            :          * cpl_tx_pkt structures), followed by either a TX Packet Write CPL
     516                 :            :          * message or, if we're doing a Large Send Offload, an LSO CPL message
     517                 :            :          * with an embedded TX Packet Write CPL message.
     518                 :            :          */
     519                 :          0 :         flits = sgl_len(m->nb_segs);
     520         [ #  # ]:          0 :         if (m->tso_segsz)
     521                 :          0 :                 flits += (wr_size + sizeof(struct cpl_tx_pkt_lso_core) +
     522                 :          0 :                           sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
     523                 :            :         else
     524                 :          0 :                 flits += (wr_size +
     525                 :          0 :                           sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
     526                 :            :         return flits;
     527                 :            : }
     528                 :            : 
     529                 :            : /**
     530                 :            :  * write_sgl - populate a scatter/gather list for a packet
     531                 :            :  * @mbuf: the packet
     532                 :            :  * @q: the Tx queue we are writing into
     533                 :            :  * @sgl: starting location for writing the SGL
     534                 :            :  * @end: points right after the end of the SGL
     535                 :            :  * @start: start offset into mbuf main-body data to include in the SGL
     536                 :            :  * @addr: address of mapped region
     537                 :            :  *
     538                 :            :  * Generates a scatter/gather list for the buffers that make up a packet.
     539                 :            :  * The caller must provide adequate space for the SGL that will be written.
     540                 :            :  * The SGL includes all of the packet's page fragments and the data in its
     541                 :            :  * main body except for the first @start bytes.  @sgl must be 16-byte
     542                 :            :  * aligned and within a Tx descriptor with available space.  @end points
     543                 :            :  * write after the end of the SGL but does not account for any potential
     544                 :            :  * wrap around, i.e., @end > @sgl.
     545                 :            :  */
     546                 :          0 : static void write_sgl(struct rte_mbuf *mbuf, struct sge_txq *q,
     547                 :            :                       struct ulptx_sgl *sgl, u64 *end, unsigned int start,
     548                 :            :                       const dma_addr_t *addr)
     549                 :          0 : {
     550                 :            :         unsigned int i, len;
     551                 :            :         struct ulptx_sge_pair *to;
     552                 :            :         struct rte_mbuf *m = mbuf;
     553                 :          0 :         unsigned int nfrags = m->nb_segs;
     554                 :          0 :         struct ulptx_sge_pair buf[nfrags / 2];
     555                 :            : 
     556         [ #  # ]:          0 :         len = m->data_len - start;
     557                 :          0 :         sgl->len0 = htonl(len);
     558         [ #  # ]:          0 :         sgl->addr0 = rte_cpu_to_be_64(addr[0]);
     559                 :            : 
     560         [ #  # ]:          0 :         sgl->cmd_nsge = htonl(V_ULPTX_CMD(ULP_TX_SC_DSGL) |
     561                 :            :                               V_ULPTX_NSGE(nfrags));
     562         [ #  # ]:          0 :         if (likely(--nfrags == 0))
     563                 :          0 :                 return;
     564                 :            :         /*
     565                 :            :          * Most of the complexity below deals with the possibility we hit the
     566                 :            :          * end of the queue in the middle of writing the SGL.  For this case
     567                 :            :          * only we create the SGL in a temporary buffer and then copy it.
     568                 :            :          */
     569         [ #  # ]:          0 :         to = (u8 *)end > (u8 *)q->stat ? buf : sgl->sge;
     570                 :            : 
     571         [ #  # ]:          0 :         for (i = 0; nfrags >= 2; nfrags -= 2, to++) {
     572                 :          0 :                 m = m->next;
     573         [ #  # ]:          0 :                 to->len[0] = rte_cpu_to_be_32(m->data_len);
     574                 :          0 :                 to->addr[0] = rte_cpu_to_be_64(addr[++i]);
     575                 :          0 :                 m = m->next;
     576         [ #  # ]:          0 :                 to->len[1] = rte_cpu_to_be_32(m->data_len);
     577                 :          0 :                 to->addr[1] = rte_cpu_to_be_64(addr[++i]);
     578                 :            :         }
     579         [ #  # ]:          0 :         if (nfrags) {
     580                 :          0 :                 m = m->next;
     581         [ #  # ]:          0 :                 to->len[0] = rte_cpu_to_be_32(m->data_len);
     582                 :          0 :                 to->len[1] = rte_cpu_to_be_32(0);
     583         [ #  # ]:          0 :                 to->addr[0] = rte_cpu_to_be_64(addr[i + 1]);
     584                 :            :         }
     585         [ #  # ]:          0 :         if (unlikely((u8 *)end > (u8 *)q->stat)) {
     586                 :          0 :                 unsigned int part0 = RTE_PTR_DIFF((u8 *)q->stat,
     587                 :            :                                                   (u8 *)sgl->sge);
     588                 :            :                 unsigned int part1;
     589                 :            : 
     590         [ #  # ]:          0 :                 if (likely(part0))
     591                 :            :                         memcpy(sgl->sge, buf, part0);
     592                 :          0 :                 part1 = RTE_PTR_DIFF((u8 *)end, (u8 *)q->stat);
     593         [ #  # ]:          0 :                 rte_memcpy(q->desc, RTE_PTR_ADD((u8 *)buf, part0), part1);
     594                 :          0 :                 end = RTE_PTR_ADD((void *)q->desc, part1);
     595                 :            :         }
     596         [ #  # ]:          0 :         if ((uintptr_t)end & 8)           /* 0-pad to multiple of 16 */
     597                 :          0 :                 *(u64 *)end = 0;
     598                 :            : }
     599                 :            : 
     600                 :            : #define IDXDIFF(head, tail, wrap) \
     601                 :            :         ((head) >= (tail) ? (head) - (tail) : (wrap) - (tail) + (head))
     602                 :            : 
     603                 :            : #define Q_IDXDIFF(q, idx) IDXDIFF((q)->pidx, (q)->idx, (q)->size)
     604                 :            : #define R_IDXDIFF(q, idx) IDXDIFF((q)->cidx, (q)->idx, (q)->size)
     605                 :            : 
     606                 :            : #define PIDXDIFF(head, tail, wrap) \
     607                 :            :         ((tail) >= (head) ? (tail) - (head) : (wrap) - (head) + (tail))
     608                 :            : #define P_IDXDIFF(q, idx) PIDXDIFF((q)->cidx, idx, (q)->size)
     609                 :            : 
     610                 :            : /**
     611                 :            :  * ring_tx_db - ring a Tx queue's doorbell
     612                 :            :  * @adap: the adapter
     613                 :            :  * @q: the Tx queue
     614                 :            :  * @n: number of new descriptors to give to HW
     615                 :            :  *
     616                 :            :  * Ring the doorbell for a Tx queue.
     617                 :            :  */
     618                 :          0 : static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q)
     619                 :            : {
     620         [ #  # ]:          0 :         int n = Q_IDXDIFF(q, dbidx);
     621                 :            : 
     622                 :            :         /*
     623                 :            :          * Make sure that all writes to the TX Descriptors are committed
     624                 :            :          * before we tell the hardware about them.
     625                 :            :          */
     626                 :            :         rte_wmb();
     627                 :            : 
     628                 :            :         /*
     629                 :            :          * If we don't have access to the new User Doorbell (T5+), use the old
     630                 :            :          * doorbell mechanism; otherwise use the new BAR2 mechanism.
     631                 :            :          */
     632         [ #  # ]:          0 :         if (unlikely(!q->bar2_addr)) {
     633                 :          0 :                 u32 val = V_PIDX(n);
     634                 :            : 
     635                 :            :                 /*
     636                 :            :                  * For T4 we need to participate in the Doorbell Recovery
     637                 :            :                  * mechanism.
     638                 :            :                  */
     639         [ #  # ]:          0 :                 if (!q->db_disabled)
     640                 :          0 :                         t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
     641                 :          0 :                                      V_QID(q->cntxt_id) | val);
     642                 :            :                 else
     643                 :          0 :                         q->db_pidx_inc += n;
     644                 :          0 :                 q->db_pidx = q->pidx;
     645                 :            :         } else {
     646                 :          0 :                 u32 val = V_PIDX_T5(n);
     647                 :            : 
     648                 :            :                 /*
     649                 :            :                  * T4 and later chips share the same PIDX field offset within
     650                 :            :                  * the doorbell, but T5 and later shrank the field in order to
     651                 :            :                  * gain a bit for Doorbell Priority.  The field was absurdly
     652                 :            :                  * large in the first place (14 bits) so we just use the T5
     653                 :            :                  * and later limits and warn if a Queue ID is too large.
     654                 :            :                  */
     655         [ #  # ]:          0 :                 WARN_ON(val & F_DBPRIO);
     656                 :            : 
     657                 :          0 :                 writel(val | V_QID(q->bar2_qid),
     658                 :          0 :                        (void *)((uintptr_t)q->bar2_addr + SGE_UDB_KDOORBELL));
     659                 :            : 
     660                 :            :                 /*
     661                 :            :                  * This Write Memory Barrier will force the write to the User
     662                 :            :                  * Doorbell area to be flushed.  This is needed to prevent
     663                 :            :                  * writes on different CPUs for the same queue from hitting
     664                 :            :                  * the adapter out of order.  This is required when some Work
     665                 :            :                  * Requests take the Write Combine Gather Buffer path (user
     666                 :            :                  * doorbell area offset [SGE_UDB_WCDOORBELL..+63]) and some
     667                 :            :                  * take the traditional path where we simply increment the
     668                 :            :                  * PIDX (User Doorbell area SGE_UDB_KDOORBELL) and have the
     669                 :            :                  * hardware DMA read the actual Work Request.
     670                 :            :                  */
     671                 :            :                 rte_wmb();
     672                 :            :         }
     673                 :          0 :         q->dbidx = q->pidx;
     674                 :          0 : }
     675                 :            : 
     676                 :            : /*
     677                 :            :  * Figure out what HW csum a packet wants and return the appropriate control
     678                 :            :  * bits.
     679                 :            :  */
     680                 :          0 : static u64 hwcsum(enum chip_type chip, const struct rte_mbuf *m)
     681                 :            : {
     682                 :            :         int csum_type;
     683                 :            : 
     684         [ #  # ]:          0 :         if (m->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
     685      [ #  #  # ]:          0 :                 switch (m->ol_flags & RTE_MBUF_F_TX_L4_MASK) {
     686                 :            :                 case RTE_MBUF_F_TX_TCP_CKSUM:
     687                 :            :                         csum_type = TX_CSUM_TCPIP;
     688                 :            :                         break;
     689                 :          0 :                 case RTE_MBUF_F_TX_UDP_CKSUM:
     690                 :            :                         csum_type = TX_CSUM_UDPIP;
     691                 :          0 :                         break;
     692                 :          0 :                 default:
     693                 :          0 :                         goto nocsum;
     694                 :            :                 }
     695                 :            :         } else {
     696                 :          0 :                 goto nocsum;
     697                 :            :         }
     698                 :            : 
     699                 :            :         if (likely(csum_type >= TX_CSUM_TCPIP)) {
     700                 :          0 :                 u64 hdr_len = V_TXPKT_IPHDR_LEN(m->l3_len);
     701                 :          0 :                 int eth_hdr_len = m->l2_len;
     702                 :            : 
     703         [ #  # ]:          0 :                 if (CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5)
     704                 :          0 :                         hdr_len |= V_TXPKT_ETHHDR_LEN(eth_hdr_len);
     705                 :            :                 else
     706                 :          0 :                         hdr_len |= V_T6_TXPKT_ETHHDR_LEN(eth_hdr_len);
     707                 :          0 :                 return V_TXPKT_CSUM_TYPE(csum_type) | hdr_len;
     708                 :            :         }
     709                 :          0 : nocsum:
     710                 :            :         /*
     711                 :            :          * unknown protocol, disable HW csum
     712                 :            :          * and hope a bad packet is detected
     713                 :            :          */
     714                 :            :         return F_TXPKT_L4CSUM_DIS;
     715                 :            : }
     716                 :            : 
     717                 :            : static inline void txq_advance(struct sge_txq *q, unsigned int n)
     718                 :            : {
     719                 :          0 :         q->in_use += n;
     720                 :          0 :         q->pidx += n;
     721   [ #  #  #  # ]:          0 :         if (q->pidx >= q->size)
     722                 :          0 :                 q->pidx -= q->size;
     723                 :            : }
     724                 :            : 
     725                 :            : #define MAX_COALESCE_LEN 64000
     726                 :            : 
     727                 :            : static inline bool wraps_around(struct sge_txq *q, int ndesc)
     728                 :            : {
     729                 :          0 :         return (q->pidx + ndesc) > q->size ? true : false;
     730                 :            : }
     731                 :            : 
     732                 :          0 : static void tx_timer_cb(void *data)
     733                 :            : {
     734                 :            :         struct adapter *adap = (struct adapter *)data;
     735                 :          0 :         struct sge_eth_txq *txq = &adap->sge.ethtxq[0];
     736                 :            :         int i;
     737                 :            :         unsigned int coal_idx;
     738                 :            : 
     739                 :            :         /* monitor any pending tx */
     740         [ #  # ]:          0 :         for (i = 0; i < adap->sge.max_ethqsets; i++, txq++) {
     741         [ #  # ]:          0 :                 if (t4_os_trylock(&txq->txq_lock)) {
     742                 :          0 :                         coal_idx = txq->q.coalesce.idx;
     743         [ #  # ]:          0 :                         if (coal_idx) {
     744         [ #  # ]:          0 :                                 if (coal_idx == txq->q.last_coal_idx &&
     745         [ #  # ]:          0 :                                     txq->q.pidx == txq->q.last_pidx) {
     746                 :          0 :                                         ship_tx_pkt_coalesce_wr(adap, txq);
     747                 :            :                                 } else {
     748                 :          0 :                                         txq->q.last_coal_idx = coal_idx;
     749                 :          0 :                                         txq->q.last_pidx = txq->q.pidx;
     750                 :            :                                 }
     751                 :            :                         }
     752                 :            :                         t4_os_unlock(&txq->txq_lock);
     753                 :            :                 }
     754                 :            :         }
     755                 :          0 :         rte_eal_alarm_set(50, tx_timer_cb, (void *)adap);
     756                 :          0 : }
     757                 :            : 
     758                 :            : /**
     759                 :            :  * ship_tx_pkt_coalesce_wr - finalizes and ships a coalesce WR
     760                 :            :  * @ adap: adapter structure
     761                 :            :  * @txq: tx queue
     762                 :            :  *
     763                 :            :  * writes the different fields of the pkts WR and sends it.
     764                 :            :  */
     765                 :          0 : static inline void ship_tx_pkt_coalesce_wr(struct adapter *adap,
     766                 :            :                                            struct sge_eth_txq *txq)
     767                 :            : {
     768                 :            :         struct fw_eth_tx_pkts_vm_wr *vmwr;
     769                 :            :         const size_t fw_hdr_copy_len = (sizeof(vmwr->ethmacdst) +
     770                 :            :                                         sizeof(vmwr->ethmacsrc) +
     771                 :            :                                         sizeof(vmwr->ethtype) +
     772                 :            :                                         sizeof(vmwr->vlantci));
     773                 :            :         struct fw_eth_tx_pkts_wr *wr;
     774                 :          0 :         struct sge_txq *q = &txq->q;
     775                 :            :         unsigned int ndesc;
     776                 :            :         u32 wr_mid;
     777                 :            : 
     778                 :            :         /* fill the pkts WR header */
     779                 :          0 :         wr = (void *)&q->desc[q->pidx];
     780                 :            :         vmwr = (void *)&q->desc[q->pidx];
     781                 :            : 
     782         [ #  # ]:          0 :         wr_mid = V_FW_WR_LEN16(DIV_ROUND_UP(q->coalesce.flits, 2));
     783                 :            :         ndesc = flits_to_desc(q->coalesce.flits);
     784                 :          0 :         wr->equiq_to_len16 = htonl(wr_mid);
     785         [ #  # ]:          0 :         wr->plen = cpu_to_be16(q->coalesce.len);
     786                 :          0 :         wr->npkt = q->coalesce.idx;
     787         [ #  # ]:          0 :         wr->r3 = 0;
     788         [ #  # ]:          0 :         if (is_pf4(adap)) {
     789                 :          0 :                 wr->type = q->coalesce.type;
     790         [ #  # ]:          0 :                 if (likely(wr->type != 0))
     791                 :          0 :                         wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS2_WR));
     792                 :            :                 else
     793                 :          0 :                         wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS_WR));
     794                 :            :         } else {
     795                 :          0 :                 wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS_VM_WR));
     796                 :          0 :                 vmwr->r4 = 0;
     797                 :          0 :                 memcpy((void *)vmwr->ethmacdst, (void *)q->coalesce.ethmacdst,
     798                 :            :                        fw_hdr_copy_len);
     799                 :            :         }
     800                 :            : 
     801                 :            :         /* zero out coalesce structure members */
     802         [ #  # ]:          0 :         memset((void *)&q->coalesce, 0, sizeof(struct eth_coalesce));
     803                 :            : 
     804                 :            :         txq_advance(q, ndesc);
     805                 :          0 :         txq->stats.coal_wr++;
     806                 :          0 :         txq->stats.coal_pkts += wr->npkt;
     807                 :            : 
     808   [ #  #  #  # ]:          0 :         if (Q_IDXDIFF(q, equeidx) >= q->size / 2) {
     809                 :          0 :                 q->equeidx = q->pidx;
     810                 :          0 :                 wr_mid |= F_FW_WR_EQUEQ;
     811                 :          0 :                 wr->equiq_to_len16 = htonl(wr_mid);
     812                 :            :         }
     813                 :          0 :         ring_tx_db(adap, q);
     814                 :          0 : }
     815                 :            : 
     816                 :            : /**
     817                 :            :  * should_tx_packet_coalesce - decides whether to coalesce an mbuf or not
     818                 :            :  * @txq: tx queue where the mbuf is sent
     819                 :            :  * @mbuf: mbuf to be sent
     820                 :            :  * @nflits: return value for number of flits needed
     821                 :            :  * @adap: adapter structure
     822                 :            :  *
     823                 :            :  * This function decides if a packet should be coalesced or not.
     824                 :            :  */
     825                 :          0 : static inline int should_tx_packet_coalesce(struct sge_eth_txq *txq,
     826                 :            :                                             struct rte_mbuf *mbuf,
     827                 :            :                                             unsigned int *nflits,
     828                 :            :                                             struct adapter *adap)
     829                 :            : {
     830                 :            :         struct fw_eth_tx_pkts_vm_wr *wr;
     831                 :            :         const size_t fw_hdr_copy_len = (sizeof(wr->ethmacdst) +
     832                 :            :                                         sizeof(wr->ethmacsrc) +
     833                 :            :                                         sizeof(wr->ethtype) +
     834                 :            :                                         sizeof(wr->vlantci));
     835                 :            :         struct sge_txq *q = &txq->q;
     836                 :            :         unsigned int flits, ndesc;
     837                 :            :         unsigned char type = 0;
     838                 :            :         int credits, wr_size;
     839                 :            : 
     840                 :            :         /* use coal WR type 1 when no frags are present */
     841         [ #  # ]:          0 :         type = (mbuf->nb_segs == 1) ? 1 : 0;
     842         [ #  # ]:          0 :         if (!is_pf4(adap)) {
     843         [ #  # ]:          0 :                 if (!type)
     844                 :            :                         return 0;
     845                 :            : 
     846         [ #  # ]:          0 :                 if (q->coalesce.idx && memcmp((void *)q->coalesce.ethmacdst,
     847         [ #  # ]:          0 :                                               rte_pktmbuf_mtod(mbuf, void *),
     848                 :            :                                               fw_hdr_copy_len))
     849                 :          0 :                         ship_tx_pkt_coalesce_wr(adap, txq);
     850                 :            :         }
     851                 :            : 
     852   [ #  #  #  # ]:          0 :         if (unlikely(type != q->coalesce.type && q->coalesce.idx))
     853                 :          0 :                 ship_tx_pkt_coalesce_wr(adap, txq);
     854                 :            : 
     855                 :            :         /* calculate the number of flits required for coalescing this packet
     856                 :            :          * without the 2 flits of the WR header. These are added further down
     857                 :            :          * if we are just starting in new PKTS WR. sgl_len doesn't account for
     858                 :            :          * the possible 16 bytes alignment ULP TX commands so we do it here.
     859                 :            :          */
     860                 :          0 :         flits = (sgl_len(mbuf->nb_segs) + 1) & ~1U;
     861         [ #  # ]:          0 :         if (type == 0)
     862                 :          0 :                 flits += (sizeof(struct ulp_txpkt) +
     863                 :            :                           sizeof(struct ulptx_idata)) / sizeof(__be64);
     864                 :          0 :         flits += sizeof(struct cpl_tx_pkt_core) / sizeof(__be64);
     865                 :          0 :         *nflits = flits;
     866                 :            : 
     867                 :            :         /* If coalescing is on, the mbuf is added to a pkts WR */
     868         [ #  # ]:          0 :         if (q->coalesce.idx) {
     869                 :          0 :                 ndesc = DIV_ROUND_UP(q->coalesce.flits + flits, 8);
     870                 :          0 :                 credits = txq_avail(q) - ndesc;
     871                 :            : 
     872         [ #  # ]:          0 :                 if (unlikely(wraps_around(q, ndesc)))
     873                 :            :                         return 0;
     874                 :            : 
     875                 :            :                 /* If we are wrapping or this is last mbuf then, send the
     876                 :            :                  * already coalesced mbufs and let the non-coalesce pass
     877                 :            :                  * handle the mbuf.
     878                 :            :                  */
     879         [ #  # ]:          0 :                 if (unlikely(credits < 0)) {
     880                 :          0 :                         ship_tx_pkt_coalesce_wr(adap, txq);
     881                 :          0 :                         return -EBUSY;
     882                 :            :                 }
     883                 :            : 
     884                 :            :                 /* If the max coalesce len or the max WR len is reached
     885                 :            :                  * ship the WR and keep coalescing on.
     886                 :            :                  */
     887   [ #  #  #  # ]:          0 :                 if (unlikely((q->coalesce.len + mbuf->pkt_len >
     888                 :            :                                                 MAX_COALESCE_LEN) ||
     889                 :            :                              (q->coalesce.flits + flits >
     890                 :            :                               q->coalesce.max))) {
     891                 :          0 :                         ship_tx_pkt_coalesce_wr(adap, txq);
     892                 :          0 :                         goto new;
     893                 :            :                 }
     894                 :            :                 return 1;
     895                 :            :         }
     896                 :            : 
     897         [ #  # ]:          0 : new:
     898                 :            :         /* start a new pkts WR, the WR header is not filled below */
     899         [ #  # ]:          0 :         wr_size = is_pf4(adap) ? sizeof(struct fw_eth_tx_pkts_wr) :
     900                 :            :                                  sizeof(struct fw_eth_tx_pkts_vm_wr);
     901                 :          0 :         flits += wr_size / sizeof(__be64);
     902                 :          0 :         ndesc = flits_to_desc(q->coalesce.flits + flits);
     903                 :          0 :         credits = txq_avail(q) - ndesc;
     904                 :            : 
     905         [ #  # ]:          0 :         if (unlikely(wraps_around(q, ndesc)))
     906                 :            :                 return 0;
     907                 :            : 
     908         [ #  # ]:          0 :         if (unlikely(credits < 0))
     909                 :            :                 return -EBUSY;
     910                 :            : 
     911                 :          0 :         q->coalesce.flits += wr_size / sizeof(__be64);
     912                 :          0 :         q->coalesce.type = type;
     913                 :          0 :         q->coalesce.ptr = (unsigned char *)&q->desc[q->pidx] +
     914                 :            :                            q->coalesce.flits * sizeof(__be64);
     915         [ #  # ]:          0 :         if (!is_pf4(adap))
     916                 :          0 :                 memcpy((void *)q->coalesce.ethmacdst,
     917                 :          0 :                        rte_pktmbuf_mtod(mbuf, void *), fw_hdr_copy_len);
     918                 :            :         return 1;
     919                 :            : }
     920                 :            : 
     921                 :            : /**
     922                 :            :  * tx_do_packet_coalesce - add an mbuf to a coalesce WR
     923                 :            :  * @txq: sge_eth_txq used send the mbuf
     924                 :            :  * @mbuf: mbuf to be sent
     925                 :            :  * @flits: flits needed for this mbuf
     926                 :            :  * @adap: adapter structure
     927                 :            :  * @pi: port_info structure
     928                 :            :  * @addr: mapped address of the mbuf
     929                 :            :  *
     930                 :            :  * Adds an mbuf to be sent as part of a coalesce WR by filling a
     931                 :            :  * ulp_tx_pkt command, ulp_tx_sc_imm command, cpl message and
     932                 :            :  * ulp_tx_sc_dsgl command.
     933                 :            :  */
     934                 :          0 : static inline int tx_do_packet_coalesce(struct sge_eth_txq *txq,
     935                 :            :                                         struct rte_mbuf *mbuf,
     936                 :            :                                         int flits, struct adapter *adap,
     937                 :            :                                         const struct port_info *pi,
     938                 :            :                                         dma_addr_t *addr, uint16_t nb_pkts)
     939                 :            : {
     940                 :            :         u64 cntrl, *end;
     941                 :          0 :         struct sge_txq *q = &txq->q;
     942                 :            :         struct ulp_txpkt *mc;
     943                 :            :         struct ulptx_idata *sc_imm;
     944                 :            :         struct cpl_tx_pkt_core *cpl;
     945                 :            :         struct tx_sw_desc *sd;
     946                 :          0 :         unsigned int idx = q->coalesce.idx, len = mbuf->pkt_len;
     947                 :            : 
     948         [ #  # ]:          0 :         if (q->coalesce.type == 0) {
     949                 :          0 :                 mc = (struct ulp_txpkt *)q->coalesce.ptr;
     950                 :          0 :                 mc->cmd_dest = htonl(V_ULPTX_CMD(4) | V_ULP_TXPKT_DEST(0) |
     951                 :            :                                      V_ULP_TXPKT_FID(adap->sge.fw_evtq.cntxt_id) |
     952                 :            :                                      F_ULP_TXPKT_RO);
     953                 :          0 :                 mc->len = htonl(DIV_ROUND_UP(flits, 2));
     954                 :            :                 sc_imm = (struct ulptx_idata *)(mc + 1);
     955                 :          0 :                 sc_imm->cmd_more = htonl(V_ULPTX_CMD(ULP_TX_SC_IMM) |
     956                 :            :                                          F_ULP_TX_SC_MORE);
     957                 :          0 :                 sc_imm->len = htonl(sizeof(*cpl));
     958                 :          0 :                 end = (u64 *)mc + flits;
     959                 :          0 :                 cpl = (struct cpl_tx_pkt_core *)(sc_imm + 1);
     960                 :            :         } else {
     961                 :          0 :                 end = (u64 *)q->coalesce.ptr + flits;
     962                 :            :                 cpl = (struct cpl_tx_pkt_core *)q->coalesce.ptr;
     963                 :            :         }
     964                 :            : 
     965                 :            :         /* update coalesce structure for this txq */
     966                 :          0 :         q->coalesce.flits += flits;
     967                 :          0 :         q->coalesce.ptr += flits * sizeof(__be64);
     968                 :          0 :         q->coalesce.len += mbuf->pkt_len;
     969                 :            : 
     970                 :            :         /* fill the cpl message, same as in t4_eth_xmit, this should be kept
     971                 :            :          * similar to t4_eth_xmit
     972                 :            :          */
     973         [ #  # ]:          0 :         if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
     974                 :          0 :                 cntrl = hwcsum(adap->params.chip, mbuf) |
     975                 :            :                                F_TXPKT_IPCSUM_DIS;
     976                 :          0 :                 txq->stats.tx_cso++;
     977                 :            :         } else {
     978                 :            :                 cntrl = F_TXPKT_L4CSUM_DIS | F_TXPKT_IPCSUM_DIS;
     979                 :            :         }
     980                 :            : 
     981         [ #  # ]:          0 :         if (mbuf->ol_flags & RTE_MBUF_F_TX_VLAN) {
     982                 :          0 :                 txq->stats.vlan_ins++;
     983                 :          0 :                 cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(mbuf->vlan_tci);
     984                 :            :         }
     985                 :            : 
     986                 :            :         cpl->ctrl0 = htonl(V_TXPKT_OPCODE(CPL_TX_PKT_XT));
     987         [ #  # ]:          0 :         if (is_pf4(adap))
     988                 :          0 :                 cpl->ctrl0 |= htonl(V_TXPKT_INTF(pi->tx_chan) |
     989                 :            :                                     V_TXPKT_PF(adap->pf));
     990                 :            :         else
     991                 :          0 :                 cpl->ctrl0 |= htonl(V_TXPKT_INTF(pi->port_id));
     992                 :          0 :         cpl->pack = htons(0);
     993         [ #  # ]:          0 :         cpl->len = htons(len);
     994         [ #  # ]:          0 :         cpl->ctrl1 = cpu_to_be64(cntrl);
     995                 :          0 :         write_sgl(mbuf, q, (struct ulptx_sgl *)(cpl + 1), end, 0,  addr);
     996                 :          0 :         txq->stats.pkts++;
     997                 :          0 :         txq->stats.tx_bytes += len;
     998                 :            : 
     999                 :          0 :         sd = &q->sdesc[q->pidx + (idx >> 1)];
    1000         [ #  # ]:          0 :         if (!(idx & 1)) {
    1001         [ #  # ]:          0 :                 if (sd->coalesce.idx) {
    1002                 :            :                         int i;
    1003                 :            : 
    1004         [ #  # ]:          0 :                         for (i = 0; i < sd->coalesce.idx; i++) {
    1005                 :          0 :                                 rte_pktmbuf_free(sd->coalesce.mbuf[i]);
    1006                 :          0 :                                 sd->coalesce.mbuf[i] = NULL;
    1007                 :            :                         }
    1008                 :            :                 }
    1009                 :            :         }
    1010                 :            : 
    1011                 :            :         /* store pointers to the mbuf and the sgl used in free_tx_desc.
    1012                 :            :          * each tx desc can hold two pointers corresponding to the value
    1013                 :            :          * of ETH_COALESCE_PKT_PER_DESC
    1014                 :            :          */
    1015                 :          0 :         sd->coalesce.mbuf[idx & 1] = mbuf;
    1016                 :          0 :         sd->coalesce.sgl[idx & 1] = (struct ulptx_sgl *)(cpl + 1);
    1017                 :          0 :         sd->coalesce.idx = (idx & 1) + 1;
    1018                 :            : 
    1019                 :            :         /* Send the coalesced work request, only if max reached. However,
    1020                 :            :          * if lower latency is preferred over throughput, then don't wait
    1021                 :            :          * for coalescing the next Tx burst and send the packets now.
    1022                 :            :          */
    1023                 :          0 :         q->coalesce.idx++;
    1024         [ #  # ]:          0 :         if (q->coalesce.idx == adap->params.max_tx_coalesce_num ||
    1025   [ #  #  #  # ]:          0 :             (adap->devargs.tx_mode_latency && q->coalesce.idx >= nb_pkts))
    1026                 :          0 :                 ship_tx_pkt_coalesce_wr(adap, txq);
    1027                 :            : 
    1028                 :          0 :         return 0;
    1029                 :            : }
    1030                 :            : 
    1031                 :            : /**
    1032                 :            :  * t4_eth_xmit - add a packet to an Ethernet Tx queue
    1033                 :            :  * @txq: the egress queue
    1034                 :            :  * @mbuf: the packet
    1035                 :            :  *
    1036                 :            :  * Add a packet to an SGE Ethernet Tx queue.  Runs with softirqs disabled.
    1037                 :            :  */
    1038                 :          0 : int t4_eth_xmit(struct sge_eth_txq *txq, struct rte_mbuf *mbuf,
    1039                 :            :                 uint16_t nb_pkts)
    1040                 :          0 : {
    1041                 :            :         const struct port_info *pi;
    1042                 :            :         struct cpl_tx_pkt_lso_core *lso;
    1043                 :            :         struct adapter *adap;
    1044                 :            :         struct rte_mbuf *m = mbuf;
    1045                 :            :         struct fw_eth_tx_pkt_wr *wr;
    1046                 :            :         struct fw_eth_tx_pkt_vm_wr *vmwr;
    1047                 :            :         struct cpl_tx_pkt_core *cpl;
    1048                 :            :         struct tx_sw_desc *d;
    1049                 :          0 :         dma_addr_t addr[m->nb_segs];
    1050                 :            :         unsigned int flits, ndesc, cflits;
    1051                 :            :         int l3hdr_len, l4hdr_len, eth_xtra_len;
    1052                 :            :         int len, last_desc;
    1053                 :            :         int should_coal, credits;
    1054                 :            :         u32 wr_mid;
    1055                 :            :         u64 cntrl, *end;
    1056                 :            :         bool v6;
    1057                 :            :         u32 max_pkt_len;
    1058                 :            : 
    1059                 :            :         /* Reject xmit if queue is stopped */
    1060         [ #  # ]:          0 :         if (unlikely(txq->flags & EQ_STOPPED))
    1061                 :            :                 return -(EBUSY);
    1062                 :            : 
    1063                 :            :         /*
    1064                 :            :          * The chip min packet length is 10 octets but play safe and reject
    1065                 :            :          * anything shorter than an Ethernet header.
    1066                 :            :          */
    1067         [ #  # ]:          0 :         if (unlikely(m->pkt_len < RTE_ETHER_HDR_LEN)) {
    1068                 :          0 : out_free:
    1069                 :          0 :                 rte_pktmbuf_free(m);
    1070                 :          0 :                 return 0;
    1071                 :            :         }
    1072                 :            : 
    1073                 :          0 :         max_pkt_len = txq->data->mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
    1074         [ #  # ]:          0 :         if ((!(m->ol_flags & RTE_MBUF_F_TX_TCP_SEG)) &&
    1075         [ #  # ]:          0 :             (unlikely(m->pkt_len > max_pkt_len)))
    1076                 :          0 :                 goto out_free;
    1077                 :            : 
    1078                 :          0 :         pi = txq->data->dev_private;
    1079                 :          0 :         adap = pi->adapter;
    1080                 :            : 
    1081                 :            :         cntrl = F_TXPKT_L4CSUM_DIS | F_TXPKT_IPCSUM_DIS;
    1082                 :            :         /* align the end of coalesce WR to a 512 byte boundary */
    1083                 :          0 :         txq->q.coalesce.max = (8 - (txq->q.pidx & 7)) * 8;
    1084                 :            : 
    1085         [ #  # ]:          0 :         if ((m->ol_flags & RTE_MBUF_F_TX_TCP_SEG) == 0) {
    1086                 :          0 :                 should_coal = should_tx_packet_coalesce(txq, mbuf, &cflits, adap);
    1087         [ #  # ]:          0 :                 if (should_coal > 0) {
    1088         [ #  # ]:          0 :                         if (unlikely(map_mbuf(mbuf, addr) < 0)) {
    1089                 :          0 :                                 dev_warn(adap, "%s: mapping err for coalesce\n",
    1090                 :            :                                          __func__);
    1091                 :          0 :                                 txq->stats.mapping_err++;
    1092                 :          0 :                                 goto out_free;
    1093                 :            :                         }
    1094                 :          0 :                         return tx_do_packet_coalesce(txq, mbuf, cflits, adap,
    1095                 :            :                                                      pi, addr, nb_pkts);
    1096         [ #  # ]:          0 :                 } else if (should_coal < 0) {
    1097                 :            :                         return should_coal;
    1098                 :            :                 }
    1099                 :            :         }
    1100                 :            : 
    1101         [ #  # ]:          0 :         if (txq->q.coalesce.idx)
    1102                 :          0 :                 ship_tx_pkt_coalesce_wr(adap, txq);
    1103                 :            : 
    1104                 :          0 :         flits = calc_tx_flits(m, adap);
    1105                 :            :         ndesc = flits_to_desc(flits);
    1106                 :          0 :         credits = txq_avail(&txq->q) - ndesc;
    1107                 :            : 
    1108         [ #  # ]:          0 :         if (unlikely(credits < 0)) {
    1109                 :          0 :                 dev_debug(adap, "%s: Tx ring %u full; credits = %d\n",
    1110                 :            :                           __func__, txq->q.cntxt_id, credits);
    1111                 :          0 :                 return -EBUSY;
    1112                 :            :         }
    1113                 :            : 
    1114         [ #  # ]:          0 :         if (unlikely(map_mbuf(m, addr) < 0)) {
    1115                 :          0 :                 txq->stats.mapping_err++;
    1116                 :          0 :                 goto out_free;
    1117                 :            :         }
    1118                 :            : 
    1119                 :          0 :         wr_mid = V_FW_WR_LEN16(DIV_ROUND_UP(flits, 2));
    1120   [ #  #  #  # ]:          0 :         if (Q_IDXDIFF(&txq->q, equeidx)  >= 64) {
    1121                 :          0 :                 txq->q.equeidx = txq->q.pidx;
    1122                 :          0 :                 wr_mid |= F_FW_WR_EQUEQ;
    1123                 :            :         }
    1124                 :            : 
    1125         [ #  # ]:          0 :         wr = (void *)&txq->q.desc[txq->q.pidx];
    1126                 :            :         vmwr = (void *)&txq->q.desc[txq->q.pidx];
    1127         [ #  # ]:          0 :         wr->equiq_to_len16 = htonl(wr_mid);
    1128         [ #  # ]:          0 :         if (is_pf4(adap)) {
    1129                 :          0 :                 wr->r3 = rte_cpu_to_be_64(0);
    1130                 :          0 :                 end = (u64 *)wr + flits;
    1131                 :            :         } else {
    1132                 :            :                 const size_t fw_hdr_copy_len = (sizeof(vmwr->ethmacdst) +
    1133                 :            :                                                 sizeof(vmwr->ethmacsrc) +
    1134                 :            :                                                 sizeof(vmwr->ethtype) +
    1135                 :            :                                                 sizeof(vmwr->vlantci));
    1136                 :            : 
    1137                 :          0 :                 vmwr->r3[0] = rte_cpu_to_be_32(0);
    1138                 :          0 :                 vmwr->r3[1] = rte_cpu_to_be_32(0);
    1139                 :          0 :                 memcpy((void *)vmwr->ethmacdst, rte_pktmbuf_mtod(m, void *),
    1140                 :            :                        fw_hdr_copy_len);
    1141                 :          0 :                 end = (u64 *)vmwr + flits;
    1142                 :            :         }
    1143                 :            : 
    1144                 :            :         len = sizeof(*cpl);
    1145                 :            : 
    1146                 :            :         /* Coalescing skipped and we send through normal path */
    1147         [ #  # ]:          0 :         if (!(m->ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
    1148   [ #  #  #  # ]:          0 :                 wr->op_immdlen = htonl(V_FW_WR_OP(is_pf4(adap) ?
    1149                 :            :                                                   FW_ETH_TX_PKT_WR :
    1150                 :            :                                                   FW_ETH_TX_PKT_VM_WR) |
    1151                 :            :                                        V_FW_WR_IMMDLEN(len));
    1152         [ #  # ]:          0 :                 if (is_pf4(adap))
    1153                 :          0 :                         cpl = (void *)(wr + 1);
    1154                 :            :                 else
    1155                 :          0 :                         cpl = (void *)(vmwr + 1);
    1156         [ #  # ]:          0 :                 if (m->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
    1157                 :          0 :                         cntrl = hwcsum(adap->params.chip, m) |
    1158                 :            :                                 F_TXPKT_IPCSUM_DIS;
    1159                 :          0 :                         txq->stats.tx_cso++;
    1160                 :            :                 }
    1161                 :            :         } else {
    1162         [ #  # ]:          0 :                 if (is_pf4(adap))
    1163                 :          0 :                         lso = (void *)(wr + 1);
    1164                 :            :                 else
    1165                 :          0 :                         lso = (void *)(vmwr + 1);
    1166                 :          0 :                 v6 = (m->ol_flags & RTE_MBUF_F_TX_IPV6) != 0;
    1167                 :          0 :                 l3hdr_len = m->l3_len;
    1168                 :          0 :                 l4hdr_len = m->l4_len;
    1169                 :          0 :                 eth_xtra_len = m->l2_len - RTE_ETHER_HDR_LEN;
    1170                 :            :                 len += sizeof(*lso);
    1171   [ #  #  #  # ]:          0 :                 wr->op_immdlen = htonl(V_FW_WR_OP(is_pf4(adap) ?
    1172                 :            :                                                   FW_ETH_TX_PKT_WR :
    1173                 :            :                                                   FW_ETH_TX_PKT_VM_WR) |
    1174                 :            :                                        V_FW_WR_IMMDLEN(len));
    1175                 :          0 :                 lso->lso_ctrl = htonl(V_LSO_OPCODE(CPL_TX_PKT_LSO) |
    1176                 :            :                                       F_LSO_FIRST_SLICE | F_LSO_LAST_SLICE |
    1177                 :            :                                       V_LSO_IPV6(v6) |
    1178                 :            :                                       V_LSO_ETHHDR_LEN(eth_xtra_len / 4) |
    1179                 :            :                                       V_LSO_IPHDR_LEN(l3hdr_len / 4) |
    1180                 :            :                                       V_LSO_TCPHDR_LEN(l4hdr_len / 4));
    1181                 :          0 :                 lso->ipid_ofst = htons(0);
    1182         [ #  # ]:          0 :                 lso->mss = htons(m->tso_segsz);
    1183                 :          0 :                 lso->seqno_offset = htonl(0);
    1184         [ #  # ]:          0 :                 if (is_t4(adap->params.chip))
    1185                 :          0 :                         lso->len = htonl(m->pkt_len);
    1186                 :            :                 else
    1187                 :          0 :                         lso->len = htonl(V_LSO_T5_XFER_SIZE(m->pkt_len));
    1188                 :          0 :                 cpl = (void *)(lso + 1);
    1189                 :            : 
    1190         [ #  # ]:          0 :                 if (CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5)
    1191                 :          0 :                         cntrl = V_TXPKT_ETHHDR_LEN(eth_xtra_len);
    1192                 :            :                 else
    1193                 :          0 :                         cntrl = V_T6_TXPKT_ETHHDR_LEN(eth_xtra_len);
    1194                 :            : 
    1195         [ #  # ]:          0 :                 cntrl |= V_TXPKT_CSUM_TYPE(v6 ? TX_CSUM_TCPIP6 :
    1196                 :          0 :                                                 TX_CSUM_TCPIP) |
    1197                 :          0 :                          V_TXPKT_IPHDR_LEN(l3hdr_len);
    1198                 :          0 :                 txq->stats.tso++;
    1199                 :          0 :                 txq->stats.tx_cso += m->tso_segsz;
    1200                 :            :         }
    1201                 :            : 
    1202         [ #  # ]:          0 :         if (m->ol_flags & RTE_MBUF_F_TX_VLAN) {
    1203                 :          0 :                 txq->stats.vlan_ins++;
    1204                 :          0 :                 cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(m->vlan_tci);
    1205                 :            :         }
    1206                 :            : 
    1207                 :            :         cpl->ctrl0 = htonl(V_TXPKT_OPCODE(CPL_TX_PKT_XT));
    1208         [ #  # ]:          0 :         if (is_pf4(adap))
    1209                 :          0 :                 cpl->ctrl0 |= htonl(V_TXPKT_INTF(pi->tx_chan) |
    1210                 :            :                                     V_TXPKT_PF(adap->pf));
    1211                 :            :         else
    1212                 :          0 :                 cpl->ctrl0 |= htonl(V_TXPKT_INTF(pi->port_id) |
    1213                 :            :                                     V_TXPKT_PF(0));
    1214                 :            : 
    1215                 :          0 :         cpl->pack = htons(0);
    1216         [ #  # ]:          0 :         cpl->len = htons(m->pkt_len);
    1217         [ #  # ]:          0 :         cpl->ctrl1 = cpu_to_be64(cntrl);
    1218                 :            : 
    1219                 :          0 :         txq->stats.pkts++;
    1220                 :          0 :         txq->stats.tx_bytes += m->pkt_len;
    1221                 :          0 :         last_desc = txq->q.pidx + ndesc - 1;
    1222         [ #  # ]:          0 :         if (last_desc >= (int)txq->q.size)
    1223                 :          0 :                 last_desc -= txq->q.size;
    1224                 :            : 
    1225                 :          0 :         d = &txq->q.sdesc[last_desc];
    1226         [ #  # ]:          0 :         if (d->coalesce.idx) {
    1227                 :            :                 int i;
    1228                 :            : 
    1229         [ #  # ]:          0 :                 for (i = 0; i < d->coalesce.idx; i++) {
    1230                 :          0 :                         rte_pktmbuf_free(d->coalesce.mbuf[i]);
    1231                 :          0 :                         d->coalesce.mbuf[i] = NULL;
    1232                 :            :                 }
    1233                 :          0 :                 d->coalesce.idx = 0;
    1234                 :            :         }
    1235                 :          0 :         write_sgl(m, &txq->q, (struct ulptx_sgl *)(cpl + 1), end, 0,
    1236                 :            :                   addr);
    1237                 :          0 :         txq->q.sdesc[last_desc].mbuf = m;
    1238         [ #  # ]:          0 :         txq->q.sdesc[last_desc].sgl = (struct ulptx_sgl *)(cpl + 1);
    1239                 :            :         txq_advance(&txq->q, ndesc);
    1240                 :          0 :         ring_tx_db(adap, &txq->q);
    1241                 :          0 :         return 0;
    1242                 :            : }
    1243                 :            : 
    1244                 :            : /**
    1245                 :            :  * reclaim_completed_tx_imm - reclaim completed control-queue Tx descs
    1246                 :            :  * @q: the SGE control Tx queue
    1247                 :            :  *
    1248                 :            :  * This is a variant of reclaim_completed_tx() that is used for Tx queues
    1249                 :            :  * that send only immediate data (presently just the control queues) and
    1250                 :            :  * thus do not have any mbufs to release.
    1251                 :            :  */
    1252                 :            : static inline void reclaim_completed_tx_imm(struct sge_txq *q)
    1253                 :            : {
    1254         [ #  # ]:          0 :         int hw_cidx = ntohs(q->stat->cidx);
    1255                 :          0 :         int reclaim = hw_cidx - q->cidx;
    1256                 :            : 
    1257   [ #  #  #  # ]:          0 :         if (reclaim < 0)
    1258                 :          0 :                 reclaim += q->size;
    1259                 :            : 
    1260                 :          0 :         q->in_use -= reclaim;
    1261                 :          0 :         q->cidx = hw_cidx;
    1262                 :            : }
    1263                 :            : 
    1264                 :            : /**
    1265                 :            :  * is_imm - check whether a packet can be sent as immediate data
    1266                 :            :  * @mbuf: the packet
    1267                 :            :  *
    1268                 :            :  * Returns true if a packet can be sent as a WR with immediate data.
    1269                 :            :  */
    1270                 :            : static inline int is_imm(const struct rte_mbuf *mbuf)
    1271                 :            : {
    1272                 :          0 :         return mbuf->pkt_len <= MAX_CTRL_WR_LEN;
    1273                 :            : }
    1274                 :            : 
    1275                 :            : /**
    1276                 :            :  * inline_tx_mbuf: inline a packet's data into TX descriptors
    1277                 :            :  * @q: the TX queue where the packet will be inlined
    1278                 :            :  * @from: pointer to data portion of packet
    1279                 :            :  * @to: pointer after cpl where data has to be inlined
    1280                 :            :  * @len: length of data to inline
    1281                 :            :  *
    1282                 :            :  * Inline a packet's contents directly to TX descriptors, starting at
    1283                 :            :  * the given position within the TX DMA ring.
    1284                 :            :  * Most of the complexity of this operation is dealing with wrap arounds
    1285                 :            :  * in the middle of the packet we want to inline.
    1286                 :            :  */
    1287                 :          0 : static void inline_tx_mbuf(const struct sge_txq *q, caddr_t from, caddr_t *to,
    1288                 :            :                            int len)
    1289                 :            : {
    1290                 :          0 :         int left = RTE_PTR_DIFF(q->stat, *to);
    1291                 :            : 
    1292         [ #  # ]:          0 :         if (likely((uintptr_t)*to + len <= (uintptr_t)q->stat)) {
    1293                 :            :                 rte_memcpy(*to, from, len);
    1294                 :          0 :                 *to = RTE_PTR_ADD(*to, len);
    1295                 :            :         } else {
    1296         [ #  # ]:          0 :                 rte_memcpy(*to, from, left);
    1297                 :          0 :                 from = RTE_PTR_ADD(from, left);
    1298                 :          0 :                 left = len - left;
    1299         [ #  # ]:          0 :                 rte_memcpy((void *)q->desc, from, left);
    1300                 :          0 :                 *to = RTE_PTR_ADD((void *)q->desc, left);
    1301                 :            :         }
    1302                 :          0 : }
    1303                 :            : 
    1304                 :            : /**
    1305                 :            :  * ctrl_xmit - send a packet through an SGE control Tx queue
    1306                 :            :  * @q: the control queue
    1307                 :            :  * @mbuf: the packet
    1308                 :            :  *
    1309                 :            :  * Send a packet through an SGE control Tx queue.  Packets sent through
    1310                 :            :  * a control queue must fit entirely as immediate data.
    1311                 :            :  */
    1312                 :          0 : static int ctrl_xmit(struct sge_ctrl_txq *q, struct rte_mbuf *mbuf)
    1313                 :            : {
    1314                 :            :         unsigned int ndesc;
    1315                 :            :         struct fw_wr_hdr *wr;
    1316                 :            :         caddr_t dst;
    1317                 :            : 
    1318         [ #  # ]:          0 :         if (unlikely(!is_imm(mbuf))) {
    1319                 :          0 :                 WARN_ON(1);
    1320                 :          0 :                 rte_pktmbuf_free(mbuf);
    1321                 :          0 :                 return -1;
    1322                 :            :         }
    1323                 :            : 
    1324         [ #  # ]:          0 :         reclaim_completed_tx_imm(&q->q);
    1325                 :          0 :         ndesc = DIV_ROUND_UP(mbuf->pkt_len, sizeof(struct tx_desc));
    1326                 :          0 :         t4_os_lock(&q->ctrlq_lock);
    1327                 :            : 
    1328                 :          0 :         q->full = txq_avail(&q->q) < ndesc ? 1 : 0;
    1329         [ #  # ]:          0 :         if (unlikely(q->full)) {
    1330                 :            :                 t4_os_unlock(&q->ctrlq_lock);
    1331                 :          0 :                 return -1;
    1332                 :            :         }
    1333                 :            : 
    1334                 :          0 :         wr = (struct fw_wr_hdr *)&q->q.desc[q->q.pidx];
    1335                 :          0 :         dst = (void *)wr;
    1336                 :          0 :         inline_tx_mbuf(&q->q, rte_pktmbuf_mtod(mbuf, caddr_t),
    1337                 :          0 :                        &dst, mbuf->data_len);
    1338                 :            : 
    1339                 :            :         txq_advance(&q->q, ndesc);
    1340         [ #  # ]:          0 :         if (unlikely(txq_avail(&q->q) < 64))
    1341                 :          0 :                 wr->lo |= htonl(F_FW_WR_EQUEQ);
    1342                 :            : 
    1343                 :          0 :         q->txp++;
    1344                 :            : 
    1345                 :          0 :         ring_tx_db(q->adapter, &q->q);
    1346                 :            :         t4_os_unlock(&q->ctrlq_lock);
    1347                 :            : 
    1348                 :          0 :         rte_pktmbuf_free(mbuf);
    1349                 :          0 :         return 0;
    1350                 :            : }
    1351                 :            : 
    1352                 :            : /**
    1353                 :            :  * t4_mgmt_tx - send a management message
    1354                 :            :  * @q: the control queue
    1355                 :            :  * @mbuf: the packet containing the management message
    1356                 :            :  *
    1357                 :            :  * Send a management message through control queue.
    1358                 :            :  */
    1359                 :          0 : int t4_mgmt_tx(struct sge_ctrl_txq *q, struct rte_mbuf *mbuf)
    1360                 :            : {
    1361                 :          0 :         return ctrl_xmit(q, mbuf);
    1362                 :            : }
    1363                 :            : 
    1364                 :            : /**
    1365                 :            :  * alloc_ring - allocate resources for an SGE descriptor ring
    1366                 :            :  * @dev: the port associated with the queue
    1367                 :            :  * @z_name: memzone's name
    1368                 :            :  * @queue_id: queue index
    1369                 :            :  * @socket_id: preferred socket id for memory allocations
    1370                 :            :  * @nelem: the number of descriptors
    1371                 :            :  * @elem_size: the size of each descriptor
    1372                 :            :  * @stat_size: extra space in HW ring for status information
    1373                 :            :  * @sw_size: the size of the SW state associated with each ring element
    1374                 :            :  * @phys: the physical address of the allocated ring
    1375                 :            :  * @metadata: address of the array holding the SW state for the ring
    1376                 :            :  *
    1377                 :            :  * Allocates resources for an SGE descriptor ring, such as Tx queues,
    1378                 :            :  * free buffer lists, or response queues.  Each SGE ring requires
    1379                 :            :  * space for its HW descriptors plus, optionally, space for the SW state
    1380                 :            :  * associated with each HW entry (the metadata).  The function returns
    1381                 :            :  * three values: the virtual address for the HW ring (the return value
    1382                 :            :  * of the function), the bus address of the HW ring, and the address
    1383                 :            :  * of the SW ring.
    1384                 :            :  */
    1385                 :          0 : static void *alloc_ring(struct rte_eth_dev *dev, const char *z_name,
    1386                 :            :                         uint16_t queue_id, int socket_id, size_t nelem,
    1387                 :            :                         size_t elem_size, size_t stat_size, size_t sw_size,
    1388                 :            :                         dma_addr_t *phys, void *metadata)
    1389                 :            : {
    1390                 :          0 :         size_t len = CXGBE_MAX_RING_DESC_SIZE * elem_size + stat_size;
    1391                 :            :         char z_name_sw[RTE_MEMZONE_NAMESIZE];
    1392                 :            :         const struct rte_memzone *tz;
    1393                 :            :         void *s = NULL;
    1394                 :            : 
    1395                 :          0 :         snprintf(z_name_sw, sizeof(z_name_sw), "eth_p%d_q%d_%s_sw_ring",
    1396                 :          0 :                  dev->data->port_id, queue_id, z_name);
    1397                 :            : 
    1398                 :          0 :         dev_debug(adapter, "%s: nelem = %zu; elem_size = %zu; sw_size = %zu; "
    1399                 :            :                   "stat_size = %zu; queue_id = %u; socket_id = %d; z_name = %s;"
    1400                 :            :                   " z_name_sw = %s\n", __func__, nelem, elem_size, sw_size,
    1401                 :            :                   stat_size, queue_id, socket_id, z_name, z_name_sw);
    1402                 :            : 
    1403                 :            :         /*
    1404                 :            :          * Allocate TX/RX ring hardware descriptors. A memzone large enough to
    1405                 :            :          * handle the maximum ring size is allocated in order to allow for
    1406                 :            :          * resizing in later calls to the queue setup function.
    1407                 :            :          */
    1408                 :          0 :         tz = rte_eth_dma_zone_reserve(dev, z_name, queue_id, len, 4096,
    1409                 :            :                                       socket_id);
    1410         [ #  # ]:          0 :         if (!tz)
    1411                 :            :                 return NULL;
    1412                 :            : 
    1413         [ #  # ]:          0 :         memset(tz->addr, 0, len);
    1414         [ #  # ]:          0 :         if (sw_size) {
    1415                 :          0 :                 s = rte_zmalloc_socket(z_name_sw, nelem * sw_size,
    1416                 :            :                                        RTE_CACHE_LINE_SIZE, socket_id);
    1417                 :            : 
    1418         [ #  # ]:          0 :                 if (!s) {
    1419                 :          0 :                         dev_err(adapter, "%s: failed to get sw_ring memory\n",
    1420                 :            :                                 __func__);
    1421                 :          0 :                         return NULL;
    1422                 :            :                 }
    1423                 :            :         }
    1424         [ #  # ]:          0 :         if (metadata)
    1425                 :          0 :                 *(void **)metadata = s;
    1426                 :            : 
    1427                 :          0 :         *phys = (uint64_t)tz->iova;
    1428                 :          0 :         return tz->addr;
    1429                 :            : }
    1430                 :            : 
    1431                 :            : #define CXGB4_MSG_AN ((void *)1)
    1432                 :            : 
    1433                 :            : /**
    1434                 :            :  * rspq_next - advance to the next entry in a response queue
    1435                 :            :  * @q: the queue
    1436                 :            :  *
    1437                 :            :  * Updates the state of a response queue to advance it to the next entry.
    1438                 :            :  */
    1439                 :            : static inline void rspq_next(struct sge_rspq *q)
    1440                 :            : {
    1441                 :          0 :         q->cur_desc = (const __be64 *)((const char *)q->cur_desc + q->iqe_len);
    1442         [ #  # ]:          0 :         if (unlikely(++q->cidx == q->size)) {
    1443                 :          0 :                 q->cidx = 0;
    1444                 :          0 :                 q->gen ^= 1;
    1445                 :          0 :                 q->cur_desc = q->desc;
    1446                 :            :         }
    1447                 :            : }
    1448                 :            : 
    1449                 :            : static inline void cxgbe_set_mbuf_info(struct rte_mbuf *pkt, uint32_t ptype,
    1450                 :            :                                        uint64_t ol_flags)
    1451                 :            : {
    1452                 :          0 :         pkt->packet_type |= ptype;
    1453                 :          0 :         pkt->ol_flags |= ol_flags;
    1454                 :          0 : }
    1455                 :            : 
    1456                 :          0 : static inline void cxgbe_fill_mbuf_info(struct adapter *adap,
    1457                 :            :                                         const struct cpl_rx_pkt *cpl,
    1458                 :            :                                         struct rte_mbuf *pkt)
    1459                 :            : {
    1460                 :            :         bool csum_ok;
    1461                 :            :         u16 err_vec;
    1462                 :            : 
    1463         [ #  # ]:          0 :         if (adap->params.tp.rx_pkt_encap)
    1464                 :          0 :                 err_vec = G_T6_COMPR_RXERR_VEC(ntohs(cpl->err_vec));
    1465                 :            :         else
    1466                 :          0 :                 err_vec = ntohs(cpl->err_vec);
    1467                 :            : 
    1468   [ #  #  #  # ]:          0 :         csum_ok = cpl->csum_calc && !err_vec;
    1469                 :            : 
    1470         [ #  # ]:          0 :         if (cpl->vlan_ex)
    1471                 :            :                 cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L2_ETHER_VLAN,
    1472                 :            :                                     RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED);
    1473                 :            :         else
    1474                 :            :                 cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L2_ETHER, 0);
    1475                 :            : 
    1476         [ #  # ]:          0 :         if (cpl->l2info & htonl(F_RXF_IP))
    1477         [ #  # ]:          0 :                 cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L3_IPV4,
    1478                 :            :                                     csum_ok ? RTE_MBUF_F_RX_IP_CKSUM_GOOD :
    1479                 :            :                                     RTE_MBUF_F_RX_IP_CKSUM_BAD);
    1480         [ #  # ]:          0 :         else if (cpl->l2info & htonl(F_RXF_IP6))
    1481         [ #  # ]:          0 :                 cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L3_IPV6,
    1482                 :            :                                     csum_ok ? RTE_MBUF_F_RX_IP_CKSUM_GOOD :
    1483                 :            :                                     RTE_MBUF_F_RX_IP_CKSUM_BAD);
    1484                 :            : 
    1485         [ #  # ]:          0 :         if (cpl->l2info & htonl(F_RXF_TCP))
    1486         [ #  # ]:          0 :                 cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L4_TCP,
    1487                 :            :                                     csum_ok ? RTE_MBUF_F_RX_L4_CKSUM_GOOD :
    1488                 :            :                                     RTE_MBUF_F_RX_L4_CKSUM_BAD);
    1489         [ #  # ]:          0 :         else if (cpl->l2info & htonl(F_RXF_UDP))
    1490         [ #  # ]:          0 :                 cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L4_UDP,
    1491                 :            :                                     csum_ok ? RTE_MBUF_F_RX_L4_CKSUM_GOOD :
    1492                 :            :                                     RTE_MBUF_F_RX_L4_CKSUM_BAD);
    1493                 :          0 : }
    1494                 :            : 
    1495                 :            : /**
    1496                 :            :  * process_responses - process responses from an SGE response queue
    1497                 :            :  * @q: the ingress queue to process
    1498                 :            :  * @budget: how many responses can be processed in this round
    1499                 :            :  * @rx_pkts: mbuf to put the pkts
    1500                 :            :  *
    1501                 :            :  * Process responses from an SGE response queue up to the supplied budget.
    1502                 :            :  * Responses include received packets as well as control messages from FW
    1503                 :            :  * or HW.
    1504                 :            :  *
    1505                 :            :  * Additionally choose the interrupt holdoff time for the next interrupt
    1506                 :            :  * on this queue.  If the system is under memory shortage use a fairly
    1507                 :            :  * long delay to help recovery.
    1508                 :            :  */
    1509                 :          0 : static int process_responses(struct sge_rspq *q, int budget,
    1510                 :            :                              struct rte_mbuf **rx_pkts)
    1511                 :            : {
    1512                 :            :         int ret = 0, rsp_type;
    1513                 :            :         int budget_left = budget;
    1514                 :            :         const struct rsp_ctrl *rc;
    1515                 :          0 :         struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
    1516                 :            : 
    1517         [ #  # ]:          0 :         while (likely(budget_left)) {
    1518         [ #  # ]:          0 :                 if (q->cidx == ntohs(q->stat->pidx))
    1519                 :            :                         break;
    1520                 :            : 
    1521                 :          0 :                 rc = (const struct rsp_ctrl *)
    1522                 :          0 :                      ((const char *)q->cur_desc + (q->iqe_len - sizeof(*rc)));
    1523                 :            : 
    1524                 :            :                 /*
    1525                 :            :                  * Ensure response has been read
    1526                 :            :                  */
    1527                 :            :                 rmb();
    1528                 :          0 :                 rsp_type = G_RSPD_TYPE(rc->u.type_gen);
    1529                 :            : 
    1530         [ #  # ]:          0 :                 if (likely(rsp_type == X_RSPD_TYPE_FLBUF)) {
    1531                 :          0 :                         struct sge *s = &q->adapter->sge;
    1532                 :            :                         unsigned int stat_pidx;
    1533                 :            :                         int stat_pidx_diff;
    1534                 :            : 
    1535         [ #  # ]:          0 :                         stat_pidx = ntohs(q->stat->pidx);
    1536         [ #  # ]:          0 :                         stat_pidx_diff = P_IDXDIFF(q, stat_pidx);
    1537         [ #  # ]:          0 :                         while (stat_pidx_diff && budget_left) {
    1538                 :          0 :                                 const struct rx_sw_desc *rsd =
    1539                 :          0 :                                         &rxq->fl.sdesc[rxq->fl.cidx];
    1540                 :          0 :                                 const struct rss_header *rss_hdr =
    1541                 :            :                                         (const void *)q->cur_desc;
    1542                 :          0 :                                 const struct cpl_rx_pkt *cpl =
    1543                 :            :                                         (const void *)&q->cur_desc[1];
    1544                 :            :                                 struct rte_mbuf *pkt, *npkt;
    1545                 :            :                                 u32 len, bufsz;
    1546                 :            : 
    1547                 :          0 :                                 rc = (const struct rsp_ctrl *)
    1548                 :          0 :                                      ((const char *)q->cur_desc +
    1549                 :          0 :                                       (q->iqe_len - sizeof(*rc)));
    1550                 :            : 
    1551                 :          0 :                                 rsp_type = G_RSPD_TYPE(rc->u.type_gen);
    1552         [ #  # ]:          0 :                                 if (unlikely(rsp_type != X_RSPD_TYPE_FLBUF))
    1553                 :            :                                         break;
    1554                 :            : 
    1555         [ #  # ]:          0 :                                 len = ntohl(rc->pldbuflen_qid);
    1556         [ #  # ]:          0 :                                 BUG_ON(!(len & F_RSPD_NEWBUF));
    1557                 :          0 :                                 pkt = rsd->buf;
    1558                 :            :                                 npkt = pkt;
    1559                 :          0 :                                 len = G_RSPD_LEN(len);
    1560                 :          0 :                                 pkt->pkt_len = len;
    1561                 :            : 
    1562                 :            :                                 /* Chain mbufs into len if necessary */
    1563         [ #  # ]:          0 :                                 while (len) {
    1564                 :          0 :                                         struct rte_mbuf *new_pkt = rsd->buf;
    1565                 :            : 
    1566                 :          0 :                                         bufsz = min(get_buf_size(q->adapter,
    1567                 :            :                                                                  rsd), len);
    1568         [ #  # ]:          0 :                                         new_pkt->data_len = bufsz;
    1569                 :            :                                         unmap_rx_buf(&rxq->fl);
    1570                 :          0 :                                         len -= bufsz;
    1571                 :          0 :                                         npkt->next = new_pkt;
    1572                 :            :                                         npkt = new_pkt;
    1573                 :          0 :                                         pkt->nb_segs++;
    1574                 :          0 :                                         rsd = &rxq->fl.sdesc[rxq->fl.cidx];
    1575                 :            :                                 }
    1576                 :          0 :                                 npkt->next = NULL;
    1577                 :          0 :                                 pkt->nb_segs--;
    1578                 :            : 
    1579                 :          0 :                                 cxgbe_fill_mbuf_info(q->adapter, cpl, pkt);
    1580                 :            : 
    1581   [ #  #  #  # ]:          0 :                                 if (!rss_hdr->filter_tid &&
    1582                 :            :                                     rss_hdr->hash_type) {
    1583                 :          0 :                                         pkt->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
    1584                 :          0 :                                         pkt->hash.rss =
    1585                 :          0 :                                                 ntohl(rss_hdr->hash_val);
    1586                 :            :                                 }
    1587                 :            : 
    1588         [ #  # ]:          0 :                                 if (cpl->vlan_ex)
    1589                 :          0 :                                         pkt->vlan_tci = ntohs(cpl->vlan);
    1590                 :            : 
    1591         [ #  # ]:          0 :                                 rte_pktmbuf_adj(pkt, s->pktshift);
    1592                 :          0 :                                 rxq->stats.pkts++;
    1593                 :          0 :                                 rxq->stats.rx_bytes += pkt->pkt_len;
    1594         [ #  # ]:          0 :                                 rx_pkts[budget - budget_left] = pkt;
    1595                 :            : 
    1596                 :            :                                 rspq_next(q);
    1597                 :          0 :                                 budget_left--;
    1598                 :          0 :                                 stat_pidx_diff--;
    1599                 :            :                         }
    1600                 :          0 :                         continue;
    1601         [ #  # ]:          0 :                 } else if (likely(rsp_type == X_RSPD_TYPE_CPL)) {
    1602                 :          0 :                         ret = q->handler(q, q->cur_desc, NULL);
    1603                 :            :                 } else {
    1604                 :          0 :                         ret = q->handler(q, (const __be64 *)rc, CXGB4_MSG_AN);
    1605                 :            :                 }
    1606                 :            : 
    1607         [ #  # ]:          0 :                 if (unlikely(ret)) {
    1608                 :            :                         /* couldn't process descriptor, back off for recovery */
    1609                 :          0 :                         q->next_intr_params = V_QINTR_TIMER_IDX(NOMEM_TMR_IDX);
    1610                 :          0 :                         break;
    1611                 :            :                 }
    1612                 :            : 
    1613                 :            :                 rspq_next(q);
    1614                 :          0 :                 budget_left--;
    1615                 :            :         }
    1616                 :            : 
    1617                 :            :         /*
    1618                 :            :          * If this is a Response Queue with an associated Free List and
    1619                 :            :          * there's room for another chunk of new Free List buffer pointers,
    1620                 :            :          * refill the Free List.
    1621                 :            :          */
    1622                 :            : 
    1623   [ #  #  #  # ]:          0 :         if (q->offset >= 0 && fl_cap(&rxq->fl) - rxq->fl.avail >= 64)
    1624                 :          0 :                 __refill_fl(q->adapter, &rxq->fl);
    1625                 :            : 
    1626                 :          0 :         return budget - budget_left;
    1627                 :            : }
    1628                 :            : 
    1629                 :          0 : int cxgbe_poll(struct sge_rspq *q, struct rte_mbuf **rx_pkts,
    1630                 :            :                unsigned int budget, unsigned int *work_done)
    1631                 :            : {
    1632                 :          0 :         struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
    1633                 :            :         unsigned int cidx_inc;
    1634                 :            :         unsigned int params;
    1635                 :            :         u32 val;
    1636                 :            : 
    1637         [ #  # ]:          0 :         if (unlikely(rxq->flags & IQ_STOPPED)) {
    1638                 :          0 :                 *work_done = 0;
    1639                 :          0 :                 return 0;
    1640                 :            :         }
    1641                 :            : 
    1642                 :          0 :         *work_done = process_responses(q, budget, rx_pkts);
    1643                 :            : 
    1644         [ #  # ]:          0 :         if (*work_done) {
    1645         [ #  # ]:          0 :                 cidx_inc = R_IDXDIFF(q, gts_idx);
    1646                 :            : 
    1647   [ #  #  #  # ]:          0 :                 if (q->offset >= 0 && fl_cap(&rxq->fl) - rxq->fl.avail >= 64)
    1648                 :          0 :                         __refill_fl(q->adapter, &rxq->fl);
    1649                 :            : 
    1650                 :          0 :                 params = q->intr_params;
    1651                 :          0 :                 q->next_intr_params = params;
    1652                 :          0 :                 val = V_CIDXINC(cidx_inc) | V_SEINTARM(params);
    1653                 :            : 
    1654         [ #  # ]:          0 :                 if (unlikely(!q->bar2_addr)) {
    1655         [ #  # ]:          0 :                         u32 reg = is_pf4(q->adapter) ? MYPF_REG(A_SGE_PF_GTS) :
    1656                 :            :                                                        T4VF_SGE_BASE_ADDR +
    1657                 :            :                                                        A_SGE_VF_GTS;
    1658                 :            : 
    1659                 :          0 :                         t4_write_reg(q->adapter, reg,
    1660                 :          0 :                                      val | V_INGRESSQID((u32)q->cntxt_id));
    1661                 :            :                 } else {
    1662                 :          0 :                         writel(val | V_INGRESSQID(q->bar2_qid),
    1663                 :          0 :                                (void *)((uintptr_t)q->bar2_addr + SGE_UDB_GTS));
    1664                 :            :                         /* This Write memory Barrier will force the
    1665                 :            :                          * write to the User Doorbell area to be
    1666                 :            :                          * flushed.
    1667                 :            :                          */
    1668                 :            :                         wmb();
    1669                 :            :                 }
    1670                 :          0 :                 q->gts_idx = q->cidx;
    1671                 :            :         }
    1672                 :            :         return 0;
    1673                 :            : }
    1674                 :            : 
    1675                 :            : /**
    1676                 :            :  * bar2_address - return the BAR2 address for an SGE Queue's Registers
    1677                 :            :  * @adapter: the adapter
    1678                 :            :  * @qid: the SGE Queue ID
    1679                 :            :  * @qtype: the SGE Queue Type (Egress or Ingress)
    1680                 :            :  * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
    1681                 :            :  *
    1682                 :            :  * Returns the BAR2 address for the SGE Queue Registers associated with
    1683                 :            :  * @qid.  If BAR2 SGE Registers aren't available, returns NULL.  Also
    1684                 :            :  * returns the BAR2 Queue ID to be used with writes to the BAR2 SGE
    1685                 :            :  * Queue Registers.  If the BAR2 Queue ID is 0, then "Inferred Queue ID"
    1686                 :            :  * Registers are supported (e.g. the Write Combining Doorbell Buffer).
    1687                 :            :  */
    1688                 :            : static void __iomem *bar2_address(struct adapter *adapter, unsigned int qid,
    1689                 :            :                                   enum t4_bar2_qtype qtype,
    1690                 :            :                                   unsigned int *pbar2_qid)
    1691                 :            : {
    1692                 :            :         u64 bar2_qoffset;
    1693                 :            :         int ret;
    1694                 :            : 
    1695                 :          0 :         ret = t4_bar2_sge_qregs(adapter, qid, qtype, &bar2_qoffset, pbar2_qid);
    1696   [ #  #  #  #  :          0 :         if (ret)
                   #  # ]
    1697                 :            :                 return NULL;
    1698                 :            : 
    1699                 :          0 :         return adapter->bar2 + bar2_qoffset;
    1700                 :            : }
    1701                 :            : 
    1702                 :          0 : int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_eth_rxq *rxq)
    1703                 :            : {
    1704         [ #  # ]:          0 :         unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff;
    1705                 :            : 
    1706                 :          0 :         rxq->flags &= ~IQ_STOPPED;
    1707                 :          0 :         return t4_iq_start_stop(adap, adap->mbox, true, adap->pf, 0,
    1708                 :          0 :                                 rxq->rspq.cntxt_id, fl_id, 0xffff);
    1709                 :            : }
    1710                 :            : 
    1711                 :          0 : int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_eth_rxq *rxq)
    1712                 :            : {
    1713         [ #  # ]:          0 :         unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff;
    1714                 :            : 
    1715                 :          0 :         rxq->flags |= IQ_STOPPED;
    1716                 :          0 :         return t4_iq_start_stop(adap, adap->mbox, false, adap->pf, 0,
    1717                 :          0 :                                 rxq->rspq.cntxt_id, fl_id, 0xffff);
    1718                 :            : }
    1719                 :            : 
    1720         [ #  # ]:          0 : static int cxgbe_sge_fl_buf_size_index(const struct adapter *adap,
    1721                 :            :                                        struct rte_mempool *mp)
    1722                 :            : {
    1723                 :            :         int fl_buf_size, size, delta, min_delta = INT_MAX;
    1724                 :            :         unsigned int i, match = UINT_MAX;
    1725                 :            :         const struct sge *s = &adap->sge;
    1726                 :            : 
    1727                 :          0 :         size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM;
    1728         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(s->fl_buffer_size); i++) {
    1729                 :          0 :                 fl_buf_size = s->fl_buffer_size[i];
    1730         [ #  # ]:          0 :                 if (fl_buf_size > size || fl_buf_size == 0)
    1731                 :          0 :                         continue;
    1732                 :            : 
    1733                 :          0 :                 delta = size - fl_buf_size;
    1734         [ #  # ]:          0 :                 if (delta < 0)
    1735                 :          0 :                         delta = -delta;
    1736         [ #  # ]:          0 :                 if (delta < min_delta) {
    1737                 :            :                         min_delta = delta;
    1738                 :            :                         match = i;
    1739                 :            :                 }
    1740                 :            :         }
    1741                 :            : 
    1742         [ #  # ]:          0 :         if (match == UINT_MAX) {
    1743                 :          0 :                 dev_err(adap,
    1744                 :            :                         "Could not find valid buffer size for mbuf data room: %d\n",
    1745                 :            :                         size);
    1746                 :          0 :                 return -EINVAL;
    1747                 :            :         }
    1748                 :            : 
    1749                 :          0 :         return match;
    1750                 :            : }
    1751                 :            : 
    1752                 :            : /*
    1753                 :            :  * @intr_idx: MSI/MSI-X vector if >=0, -(absolute qid + 1) if < 0
    1754                 :            :  * @cong: < 0 -> no congestion feedback, >= 0 -> congestion channel map
    1755                 :            :  */
    1756                 :          0 : int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
    1757                 :            :                      struct rte_eth_dev *eth_dev, int intr_idx,
    1758                 :            :                      struct sge_fl *fl, rspq_handler_t hnd, int cong,
    1759                 :            :                      struct rte_mempool *mp, int queue_id, int socket_id)
    1760                 :            : {
    1761                 :          0 :         struct port_info *pi = eth_dev->data->dev_private;
    1762                 :            :         u8 pciechan, fl_buf_size_idx = 0;
    1763                 :            :         struct sge *s = &adap->sge;
    1764                 :            :         unsigned int nb_refill;
    1765                 :            :         struct fw_iq_cmd c;
    1766                 :            :         int ret, flsz = 0;
    1767                 :            : 
    1768         [ #  # ]:          0 :         if (fl != NULL) {
    1769                 :          0 :                 ret = cxgbe_sge_fl_buf_size_index(adap, mp);
    1770         [ #  # ]:          0 :                 if (ret < 0)
    1771                 :            :                         return ret;
    1772                 :            : 
    1773                 :          0 :                 fl_buf_size_idx = ret;
    1774                 :            :         }
    1775                 :            : 
    1776                 :            :         /* Size needs to be multiple of 16, including status entry. */
    1777                 :          0 :         iq->size = cxgbe_roundup(iq->size, 16);
    1778                 :            : 
    1779                 :          0 :         iq->desc = alloc_ring(eth_dev, fwevtq ? "fwq_ring" : "rx_ring",
    1780         [ #  # ]:          0 :                               queue_id, socket_id, iq->size, iq->iqe_len,
    1781                 :            :                               0, 0, &iq->phys_addr, NULL);
    1782         [ #  # ]:          0 :         if (!iq->desc)
    1783                 :            :                 return -ENOMEM;
    1784                 :            : 
    1785                 :            :         memset(&c, 0, sizeof(c));
    1786         [ #  # ]:          0 :         c.op_to_vfn = htonl(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST |
    1787                 :            :                             F_FW_CMD_WRITE | F_FW_CMD_EXEC);
    1788                 :            : 
    1789         [ #  # ]:          0 :         if (is_pf4(adap)) {
    1790                 :          0 :                 pciechan = pi->tx_chan;
    1791                 :          0 :                 c.op_to_vfn |= htonl(V_FW_IQ_CMD_PFN(adap->pf) |
    1792                 :            :                                      V_FW_IQ_CMD_VFN(0));
    1793         [ #  # ]:          0 :                 if (cong >= 0)
    1794                 :          0 :                         c.iqns_to_fl0congen =
    1795         [ #  # ]:          0 :                                 htonl(F_FW_IQ_CMD_IQFLINTCONGEN |
    1796                 :            :                                       V_FW_IQ_CMD_IQTYPE(cong ?
    1797                 :            :                                                          FW_IQ_IQTYPE_NIC :
    1798                 :            :                                                          FW_IQ_IQTYPE_OFLD) |
    1799                 :            :                                       F_FW_IQ_CMD_IQRO);
    1800                 :            :         } else {
    1801                 :          0 :                 pciechan = pi->port_id;
    1802                 :            :         }
    1803                 :            : 
    1804                 :          0 :         c.alloc_to_len16 = htonl(F_FW_IQ_CMD_ALLOC | F_FW_IQ_CMD_IQSTART |
    1805                 :            :                                  (sizeof(c) / 16));
    1806                 :          0 :         c.type_to_iqandstindex =
    1807         [ #  # ]:          0 :                 htonl(V_FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) |
    1808                 :            :                       V_FW_IQ_CMD_IQASYNCH(fwevtq) |
    1809                 :            :                       V_FW_IQ_CMD_VIID(pi->viid) |
    1810                 :            :                       V_FW_IQ_CMD_IQANDST(intr_idx < 0) |
    1811                 :            :                       V_FW_IQ_CMD_IQANUD(X_UPDATEDELIVERY_STATUS_PAGE) |
    1812                 :            :                       V_FW_IQ_CMD_IQANDSTINDEX(intr_idx >= 0 ? intr_idx :
    1813                 :            :                                                                -intr_idx - 1));
    1814                 :          0 :         c.iqdroprss_to_iqesize =
    1815         [ #  # ]:          0 :                 htons(V_FW_IQ_CMD_IQPCIECH(pciechan) |
    1816                 :            :                       F_FW_IQ_CMD_IQGTSMODE |
    1817                 :            :                       V_FW_IQ_CMD_IQINTCNTTHRESH(iq->pktcnt_idx) |
    1818                 :            :                       V_FW_IQ_CMD_IQESIZE(ilog2(iq->iqe_len) - 4));
    1819                 :          0 :         c.iqsize = htons(iq->size);
    1820         [ #  # ]:          0 :         c.iqaddr = cpu_to_be64(iq->phys_addr);
    1821                 :            : 
    1822         [ #  # ]:          0 :         if (fl) {
    1823                 :          0 :                 unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
    1824                 :            : 
    1825                 :            :                 /*
    1826                 :            :                  * Allocate the ring for the hardware free list (with space
    1827                 :            :                  * for its status page) along with the associated software
    1828                 :            :                  * descriptor ring.  The free list size needs to be a multiple
    1829                 :            :                  * of the Egress Queue Unit and at least 2 Egress Units larger
    1830                 :            :                  * than the SGE's Egress Congestion Threshold
    1831                 :            :                  * (fl_starve_thres - 1).
    1832                 :            :                  */
    1833         [ #  # ]:          0 :                 if (fl->size < s->fl_starve_thres - 1 + 2 * 8)
    1834                 :          0 :                         fl->size = s->fl_starve_thres - 1 + 2 * 8;
    1835                 :          0 :                 fl->size = cxgbe_roundup(fl->size, 8);
    1836                 :            : 
    1837                 :          0 :                 fl->desc = alloc_ring(eth_dev, "fl_ring", queue_id, socket_id,
    1838                 :          0 :                                       fl->size, sizeof(__be64), s->stat_len,
    1839                 :            :                                       sizeof(struct rx_sw_desc),
    1840                 :          0 :                                       &fl->addr, &fl->sdesc);
    1841         [ #  # ]:          0 :                 if (!fl->desc) {
    1842                 :            :                         ret = -ENOMEM;
    1843                 :          0 :                         goto err;
    1844                 :            :                 }
    1845                 :            : 
    1846                 :          0 :                 flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc);
    1847         [ #  # ]:          0 :                 c.iqns_to_fl0congen |=
    1848                 :            :                         htonl(V_FW_IQ_CMD_FL0HOSTFCMODE(X_HOSTFCMODE_NONE) |
    1849                 :            :                               F_FW_IQ_CMD_FL0FETCHRO | F_FW_IQ_CMD_FL0DATARO);
    1850   [ #  #  #  # ]:          0 :                 if (is_pf4(adap) && cong >= 0)
    1851                 :          0 :                         c.iqns_to_fl0congen |=
    1852                 :          0 :                                 htonl(V_FW_IQ_CMD_FL0CNGCHMAP(cong) |
    1853                 :            :                                       F_FW_IQ_CMD_FL0CONGCIF |
    1854                 :            :                                       F_FW_IQ_CMD_FL0CONGEN);
    1855                 :            : 
    1856                 :            :                 /* In T6, for egress queue type FL there is internal overhead
    1857                 :            :                  * of 16B for header going into FLM module.
    1858                 :            :                  * Hence maximum allowed burst size will be 448 bytes.
    1859                 :            :                  */
    1860                 :          0 :                 c.fl0dcaen_to_fl0cidxfthresh =
    1861   [ #  #  #  #  :          0 :                         htons(V_FW_IQ_CMD_FL0FBMIN(chip_ver <= CHELSIO_T5 ?
                   #  # ]
    1862                 :            :                                                    X_FETCHBURSTMIN_128B :
    1863                 :            :                                                    X_FETCHBURSTMIN_64B) |
    1864                 :            :                               V_FW_IQ_CMD_FL0FBMAX(chip_ver <= CHELSIO_T5 ?
    1865                 :            :                                                    X_FETCHBURSTMAX_512B :
    1866                 :            :                                                    X_FETCHBURSTMAX_256B));
    1867                 :          0 :                 c.fl0size = htons(flsz);
    1868         [ #  # ]:          0 :                 c.fl0addr = cpu_to_be64(fl->addr);
    1869                 :            :         }
    1870                 :            : 
    1871         [ #  # ]:          0 :         if (is_pf4(adap))
    1872                 :          0 :                 ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
    1873                 :            :         else
    1874                 :            :                 ret = t4vf_wr_mbox(adap, &c, sizeof(c), &c);
    1875         [ #  # ]:          0 :         if (ret)
    1876                 :          0 :                 goto err;
    1877                 :            : 
    1878                 :          0 :         iq->cur_desc = iq->desc;
    1879                 :          0 :         iq->cidx = 0;
    1880                 :          0 :         iq->gts_idx = 0;
    1881                 :          0 :         iq->gen = 1;
    1882                 :          0 :         iq->next_intr_params = iq->intr_params;
    1883                 :          0 :         iq->cntxt_id = ntohs(c.iqid);
    1884                 :          0 :         iq->abs_id = ntohs(c.physiqid);
    1885                 :          0 :         iq->bar2_addr = bar2_address(adap, iq->cntxt_id, T4_BAR2_QTYPE_INGRESS,
    1886                 :            :                                      &iq->bar2_qid);
    1887                 :          0 :         iq->size--;                           /* subtract status entry */
    1888                 :          0 :         iq->stat = (void *)&iq->desc[iq->size * 8];
    1889                 :          0 :         iq->eth_dev = eth_dev;
    1890                 :          0 :         iq->handler = hnd;
    1891                 :          0 :         iq->port_id = eth_dev->data->port_id;
    1892                 :          0 :         iq->mb_pool = mp;
    1893                 :            : 
    1894                 :            :         /* set offset to -1 to distinguish ingress queues without FL */
    1895         [ #  # ]:          0 :         iq->offset = fl ? 0 : -1;
    1896                 :            : 
    1897         [ #  # ]:          0 :         if (fl) {
    1898                 :          0 :                 fl->cntxt_id = ntohs(c.fl0id);
    1899                 :          0 :                 fl->avail = 0;
    1900                 :          0 :                 fl->pend_cred = 0;
    1901                 :          0 :                 fl->pidx = 0;
    1902                 :          0 :                 fl->cidx = 0;
    1903                 :          0 :                 fl->alloc_failed = 0;
    1904                 :          0 :                 fl->fl_buf_size_idx = fl_buf_size_idx;
    1905                 :            : 
    1906                 :            :                 /*
    1907                 :            :                  * Note, we must initialize the BAR2 Free List User Doorbell
    1908                 :            :                  * information before refilling the Free List!
    1909                 :            :                  */
    1910                 :          0 :                 fl->bar2_addr = bar2_address(adap, fl->cntxt_id,
    1911                 :            :                                              T4_BAR2_QTYPE_EGRESS,
    1912                 :            :                                              &fl->bar2_qid);
    1913                 :            : 
    1914                 :          0 :                 nb_refill = refill_fl(adap, fl, fl_cap(fl));
    1915         [ #  # ]:          0 :                 if (nb_refill != fl_cap(fl)) {
    1916                 :            :                         ret = -ENOMEM;
    1917                 :          0 :                         dev_err(adap, "%s: mbuf alloc failed with error: %d\n",
    1918                 :            :                                 __func__, ret);
    1919                 :          0 :                         goto refill_fl_err;
    1920                 :            :                 }
    1921                 :            :         }
    1922                 :            : 
    1923                 :            :         /*
    1924                 :            :          * For T5 and later we attempt to set up the Congestion Manager values
    1925                 :            :          * of the new RX Ethernet Queue.  This should really be handled by
    1926                 :            :          * firmware because it's more complex than any host driver wants to
    1927                 :            :          * get involved with and it's different per chip and this is almost
    1928                 :            :          * certainly wrong.  Formware would be wrong as well, but it would be
    1929                 :            :          * a lot easier to fix in one place ...  For now we do something very
    1930                 :            :          * simple (and hopefully less wrong).
    1931                 :            :          */
    1932   [ #  #  #  #  :          0 :         if (is_pf4(adap) && !is_t4(adap->params.chip) && cong >= 0) {
                   #  # ]
    1933                 :          0 :                 u8 cng_ch_bits_log = adap->params.arch.cng_ch_bits_log;
    1934                 :            :                 u32 param, val, ch_map = 0;
    1935                 :            :                 int i;
    1936                 :            : 
    1937                 :          0 :                 param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
    1938                 :          0 :                          V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_CONM_CTXT) |
    1939                 :          0 :                          V_FW_PARAMS_PARAM_YZ(iq->cntxt_id));
    1940         [ #  # ]:          0 :                 if (cong == 0) {
    1941                 :          0 :                         val = V_CONMCTXT_CNGTPMODE(X_CONMCTXT_CNGTPMODE_QUEUE);
    1942                 :            :                 } else {
    1943                 :            :                         val = V_CONMCTXT_CNGTPMODE(
    1944                 :            :                                         X_CONMCTXT_CNGTPMODE_CHANNEL);
    1945         [ #  # ]:          0 :                         for (i = 0; i < 4; i++) {
    1946         [ #  # ]:          0 :                                 if (cong & (1 << i))
    1947                 :          0 :                                         ch_map |= 1 << (i << cng_ch_bits_log);
    1948                 :            :                         }
    1949                 :          0 :                         val |= V_CONMCTXT_CNGCHMAP(ch_map);
    1950                 :            :                 }
    1951                 :          0 :                 ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1,
    1952                 :            :                                     &param, &val);
    1953         [ #  # ]:          0 :                 if (ret)
    1954                 :          0 :                         dev_warn(adap->pdev_dev, "Failed to set Congestion Manager Context for Ingress Queue %d: %d\n",
    1955                 :            :                                  iq->cntxt_id, -ret);
    1956                 :            :         }
    1957                 :            : 
    1958                 :            :         return 0;
    1959                 :            : 
    1960                 :            : refill_fl_err:
    1961                 :          0 :         t4_iq_free(adap, adap->mbox, adap->pf, 0, FW_IQ_TYPE_FL_INT_CAP,
    1962                 :          0 :                    iq->cntxt_id, fl->cntxt_id, 0xffff);
    1963                 :          0 : err:
    1964                 :          0 :         iq->cntxt_id = 0;
    1965                 :          0 :         iq->abs_id = 0;
    1966         [ #  # ]:          0 :         if (iq->desc)
    1967                 :          0 :                 iq->desc = NULL;
    1968                 :            : 
    1969   [ #  #  #  # ]:          0 :         if (fl && fl->desc) {
    1970                 :          0 :                 rte_free(fl->sdesc);
    1971                 :          0 :                 fl->cntxt_id = 0;
    1972                 :          0 :                 fl->sdesc = NULL;
    1973                 :          0 :                 fl->desc = NULL;
    1974                 :            :         }
    1975                 :            :         return ret;
    1976                 :            : }
    1977                 :            : 
    1978                 :          0 : static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id,
    1979                 :            :                      unsigned int abs_id)
    1980                 :            : {
    1981                 :          0 :         q->cntxt_id = id;
    1982                 :          0 :         q->abs_id = abs_id;
    1983                 :          0 :         q->bar2_addr = bar2_address(adap, q->cntxt_id, T4_BAR2_QTYPE_EGRESS,
    1984                 :            :                                     &q->bar2_qid);
    1985                 :          0 :         q->cidx = 0;
    1986                 :          0 :         q->pidx = 0;
    1987                 :          0 :         q->dbidx = 0;
    1988                 :          0 :         q->in_use = 0;
    1989                 :          0 :         q->equeidx = 0;
    1990                 :          0 :         q->coalesce.idx = 0;
    1991                 :          0 :         q->coalesce.len = 0;
    1992                 :          0 :         q->coalesce.flits = 0;
    1993                 :          0 :         q->last_coal_idx = 0;
    1994                 :          0 :         q->last_pidx = 0;
    1995                 :          0 :         q->stat = (void *)&q->desc[q->size];
    1996                 :          0 : }
    1997                 :            : 
    1998                 :          0 : int t4_sge_eth_txq_start(struct sge_eth_txq *txq)
    1999                 :            : {
    2000                 :            :         /*
    2001                 :            :          *  TODO: For flow-control, queue may be stopped waiting to reclaim
    2002                 :            :          *  credits.
    2003                 :            :          *  Ensure queue is in EQ_STOPPED state before starting it.
    2004                 :            :          */
    2005         [ #  # ]:          0 :         if (!(txq->flags & EQ_STOPPED))
    2006                 :            :                 return -(EBUSY);
    2007                 :            : 
    2008                 :          0 :         txq->flags &= ~EQ_STOPPED;
    2009                 :            : 
    2010                 :          0 :         return 0;
    2011                 :            : }
    2012                 :            : 
    2013                 :          0 : int t4_sge_eth_txq_stop(struct sge_eth_txq *txq)
    2014                 :            : {
    2015                 :          0 :         txq->flags |= EQ_STOPPED;
    2016                 :            : 
    2017                 :          0 :         return 0;
    2018                 :            : }
    2019                 :            : 
    2020                 :          0 : int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
    2021                 :            :                          struct rte_eth_dev *eth_dev, uint16_t queue_id,
    2022                 :            :                          unsigned int iqid, int socket_id)
    2023                 :            : {
    2024                 :            :         int ret, nentries;
    2025                 :            :         struct fw_eq_eth_cmd c;
    2026                 :            :         struct sge *s = &adap->sge;
    2027                 :          0 :         struct port_info *pi = eth_dev->data->dev_private;
    2028                 :            :         u8 pciechan;
    2029                 :            : 
    2030                 :            :         /* Add status entries */
    2031                 :          0 :         nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
    2032                 :            : 
    2033                 :          0 :         txq->q.desc = alloc_ring(eth_dev, "tx_ring", queue_id, socket_id,
    2034                 :            :                                  txq->q.size, sizeof(struct tx_desc),
    2035                 :            :                                  s->stat_len, sizeof(struct tx_sw_desc),
    2036                 :          0 :                                  &txq->q.phys_addr, &txq->q.sdesc);
    2037         [ #  # ]:          0 :         if (!txq->q.desc)
    2038                 :            :                 return -ENOMEM;
    2039                 :            : 
    2040                 :            :         memset(&c, 0, sizeof(c));
    2041         [ #  # ]:          0 :         c.op_to_vfn = htonl(V_FW_CMD_OP(FW_EQ_ETH_CMD) | F_FW_CMD_REQUEST |
    2042                 :            :                             F_FW_CMD_WRITE | F_FW_CMD_EXEC);
    2043         [ #  # ]:          0 :         if (is_pf4(adap)) {
    2044                 :          0 :                 pciechan = pi->tx_chan;
    2045                 :          0 :                 c.op_to_vfn |= htonl(V_FW_EQ_ETH_CMD_PFN(adap->pf) |
    2046                 :            :                                      V_FW_EQ_ETH_CMD_VFN(0));
    2047                 :            :         } else {
    2048                 :          0 :                 pciechan = pi->port_id;
    2049                 :            :         }
    2050                 :            : 
    2051                 :          0 :         c.alloc_to_len16 = htonl(F_FW_EQ_ETH_CMD_ALLOC |
    2052                 :            :                                  F_FW_EQ_ETH_CMD_EQSTART | (sizeof(c) / 16));
    2053         [ #  # ]:          0 :         c.autoequiqe_to_viid = htonl(F_FW_EQ_ETH_CMD_AUTOEQUEQE |
    2054                 :            :                                      V_FW_EQ_ETH_CMD_VIID(pi->viid));
    2055                 :          0 :         c.fetchszm_to_iqid =
    2056                 :          0 :                 htonl(V_FW_EQ_ETH_CMD_HOSTFCMODE(X_HOSTFCMODE_NONE) |
    2057                 :            :                       V_FW_EQ_ETH_CMD_PCIECHN(pciechan) |
    2058                 :            :                       F_FW_EQ_ETH_CMD_FETCHRO | V_FW_EQ_ETH_CMD_IQID(iqid));
    2059                 :          0 :         c.dcaen_to_eqsize =
    2060                 :          0 :                 htonl(V_FW_EQ_ETH_CMD_FBMIN(X_FETCHBURSTMIN_64B) |
    2061                 :            :                       V_FW_EQ_ETH_CMD_FBMAX(X_FETCHBURSTMAX_512B) |
    2062                 :            :                       V_FW_EQ_ETH_CMD_EQSIZE(nentries));
    2063         [ #  # ]:          0 :         c.eqaddr = rte_cpu_to_be_64(txq->q.phys_addr);
    2064                 :            : 
    2065         [ #  # ]:          0 :         if (is_pf4(adap))
    2066                 :          0 :                 ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
    2067                 :            :         else
    2068                 :            :                 ret = t4vf_wr_mbox(adap, &c, sizeof(c), &c);
    2069         [ #  # ]:          0 :         if (ret) {
    2070                 :          0 :                 rte_free(txq->q.sdesc);
    2071                 :          0 :                 txq->q.sdesc = NULL;
    2072                 :          0 :                 txq->q.desc = NULL;
    2073                 :          0 :                 return ret;
    2074                 :            :         }
    2075                 :            : 
    2076                 :          0 :         init_txq(adap, &txq->q, G_FW_EQ_ETH_CMD_EQID(ntohl(c.eqid_pkd)),
    2077                 :          0 :                  G_FW_EQ_ETH_CMD_PHYSEQID(ntohl(c.physeqid_pkd)));
    2078                 :          0 :         txq->stats.tso = 0;
    2079                 :          0 :         txq->stats.pkts = 0;
    2080                 :          0 :         txq->stats.tx_cso = 0;
    2081                 :          0 :         txq->stats.coal_wr = 0;
    2082                 :          0 :         txq->stats.vlan_ins = 0;
    2083                 :          0 :         txq->stats.tx_bytes = 0;
    2084                 :          0 :         txq->stats.coal_pkts = 0;
    2085                 :          0 :         txq->stats.mapping_err = 0;
    2086                 :          0 :         txq->flags |= EQ_STOPPED;
    2087                 :          0 :         txq->eth_dev = eth_dev;
    2088                 :          0 :         txq->data = eth_dev->data;
    2089                 :            :         t4_os_lock_init(&txq->txq_lock);
    2090                 :          0 :         return 0;
    2091                 :            : }
    2092                 :            : 
    2093                 :          0 : int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
    2094                 :            :                           struct rte_eth_dev *eth_dev, uint16_t queue_id,
    2095                 :            :                           unsigned int iqid, int socket_id)
    2096                 :            : {
    2097                 :            :         int ret, nentries;
    2098                 :            :         struct fw_eq_ctrl_cmd c;
    2099                 :            :         struct sge *s = &adap->sge;
    2100                 :          0 :         struct port_info *pi = eth_dev->data->dev_private;
    2101                 :            : 
    2102                 :            :         /* Add status entries */
    2103                 :          0 :         nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
    2104                 :            : 
    2105                 :          0 :         txq->q.desc = alloc_ring(eth_dev, "ctrl_tx_ring", queue_id,
    2106                 :            :                                  socket_id, txq->q.size, sizeof(struct tx_desc),
    2107                 :          0 :                                  0, 0, &txq->q.phys_addr, NULL);
    2108         [ #  # ]:          0 :         if (!txq->q.desc)
    2109                 :            :                 return -ENOMEM;
    2110                 :            : 
    2111                 :            :         memset(&c, 0, sizeof(c));
    2112         [ #  # ]:          0 :         c.op_to_vfn = htonl(V_FW_CMD_OP(FW_EQ_CTRL_CMD) | F_FW_CMD_REQUEST |
    2113                 :            :                             F_FW_CMD_WRITE | F_FW_CMD_EXEC |
    2114                 :            :                             V_FW_EQ_CTRL_CMD_PFN(adap->pf) |
    2115                 :            :                             V_FW_EQ_CTRL_CMD_VFN(0));
    2116                 :          0 :         c.alloc_to_len16 = htonl(F_FW_EQ_CTRL_CMD_ALLOC |
    2117                 :            :                                  F_FW_EQ_CTRL_CMD_EQSTART | (sizeof(c) / 16));
    2118                 :            :         c.cmpliqid_eqid = htonl(V_FW_EQ_CTRL_CMD_CMPLIQID(0));
    2119                 :            :         c.physeqid_pkd = htonl(0);
    2120                 :          0 :         c.fetchszm_to_iqid =
    2121                 :          0 :                 htonl(V_FW_EQ_CTRL_CMD_HOSTFCMODE(X_HOSTFCMODE_NONE) |
    2122                 :            :                       V_FW_EQ_CTRL_CMD_PCIECHN(pi->tx_chan) |
    2123                 :            :                       F_FW_EQ_CTRL_CMD_FETCHRO | V_FW_EQ_CTRL_CMD_IQID(iqid));
    2124                 :          0 :         c.dcaen_to_eqsize =
    2125                 :          0 :                 htonl(V_FW_EQ_CTRL_CMD_FBMIN(X_FETCHBURSTMIN_64B) |
    2126                 :            :                       V_FW_EQ_CTRL_CMD_FBMAX(X_FETCHBURSTMAX_512B) |
    2127                 :            :                       V_FW_EQ_CTRL_CMD_EQSIZE(nentries));
    2128         [ #  # ]:          0 :         c.eqaddr = cpu_to_be64(txq->q.phys_addr);
    2129                 :            : 
    2130                 :          0 :         ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
    2131         [ #  # ]:          0 :         if (ret) {
    2132                 :          0 :                 txq->q.desc = NULL;
    2133                 :          0 :                 return ret;
    2134                 :            :         }
    2135                 :            : 
    2136                 :          0 :         init_txq(adap, &txq->q, G_FW_EQ_CTRL_CMD_EQID(ntohl(c.cmpliqid_eqid)),
    2137                 :          0 :                  G_FW_EQ_CTRL_CMD_EQID(ntohl(c. physeqid_pkd)));
    2138                 :          0 :         txq->adapter = adap;
    2139                 :          0 :         txq->full = 0;
    2140                 :          0 :         return 0;
    2141                 :            : }
    2142                 :            : 
    2143                 :            : static void free_txq(struct sge_txq *q)
    2144                 :            : {
    2145                 :          0 :         q->cntxt_id = 0;
    2146                 :          0 :         q->sdesc = NULL;
    2147                 :          0 :         q->desc = NULL;
    2148                 :          0 : }
    2149                 :            : 
    2150                 :          0 : static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
    2151                 :            :                          struct sge_fl *fl)
    2152                 :            : {
    2153         [ #  # ]:          0 :         unsigned int fl_id = fl ? fl->cntxt_id : 0xffff;
    2154                 :            : 
    2155                 :          0 :         t4_iq_free(adap, adap->mbox, adap->pf, 0, FW_IQ_TYPE_FL_INT_CAP,
    2156                 :          0 :                    rq->cntxt_id, fl_id, 0xffff);
    2157                 :          0 :         rq->cntxt_id = 0;
    2158                 :          0 :         rq->abs_id = 0;
    2159                 :          0 :         rq->desc = NULL;
    2160                 :            : 
    2161         [ #  # ]:          0 :         if (fl) {
    2162                 :          0 :                 free_rx_bufs(fl, fl->avail);
    2163                 :          0 :                 rte_free(fl->sdesc);
    2164                 :          0 :                 fl->sdesc = NULL;
    2165                 :          0 :                 fl->cntxt_id = 0;
    2166                 :          0 :                 fl->desc = NULL;
    2167                 :            :         }
    2168                 :          0 : }
    2169                 :            : 
    2170                 :            : /*
    2171                 :            :  * Clear all queues of the port
    2172                 :            :  *
    2173                 :            :  * Note:  This function must only be called after rx and tx path
    2174                 :            :  * of the port have been disabled.
    2175                 :            :  */
    2176                 :          0 : void t4_sge_eth_clear_queues(struct port_info *pi)
    2177                 :            : {
    2178                 :          0 :         struct adapter *adap = pi->adapter;
    2179                 :            :         struct sge_eth_rxq *rxq;
    2180                 :            :         struct sge_eth_txq *txq;
    2181                 :            :         int i;
    2182                 :            : 
    2183                 :          0 :         rxq = &adap->sge.ethrxq[pi->first_rxqset];
    2184         [ #  # ]:          0 :         for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
    2185         [ #  # ]:          0 :                 if (rxq->rspq.desc)
    2186                 :          0 :                         t4_sge_eth_rxq_stop(adap, rxq);
    2187                 :            :         }
    2188                 :            : 
    2189                 :          0 :         txq = &adap->sge.ethtxq[pi->first_txqset];
    2190         [ #  # ]:          0 :         for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
    2191         [ #  # ]:          0 :                 if (txq->q.desc) {
    2192                 :          0 :                         struct sge_txq *q = &txq->q;
    2193                 :            : 
    2194                 :          0 :                         t4_sge_eth_txq_stop(txq);
    2195                 :          0 :                         reclaim_completed_tx(q);
    2196                 :          0 :                         free_tx_desc(q, q->size);
    2197                 :          0 :                         q->equeidx = q->pidx;
    2198                 :            :                 }
    2199                 :            :         }
    2200                 :          0 : }
    2201                 :            : 
    2202                 :          0 : void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq)
    2203                 :            : {
    2204         [ #  # ]:          0 :         if (rxq->rspq.desc) {
    2205                 :          0 :                 t4_sge_eth_rxq_stop(adap, rxq);
    2206         [ #  # ]:          0 :                 free_rspq_fl(adap, &rxq->rspq, rxq->fl.size ? &rxq->fl : NULL);
    2207                 :            :         }
    2208                 :          0 : }
    2209                 :            : 
    2210                 :          0 : void t4_sge_eth_txq_release(struct adapter *adap, struct sge_eth_txq *txq)
    2211                 :            : {
    2212         [ #  # ]:          0 :         if (txq->q.desc) {
    2213                 :          0 :                 t4_sge_eth_txq_stop(txq);
    2214                 :          0 :                 reclaim_completed_tx(&txq->q);
    2215                 :          0 :                 t4_eth_eq_free(adap, adap->mbox, adap->pf, 0, txq->q.cntxt_id);
    2216                 :          0 :                 free_tx_desc(&txq->q, txq->q.size);
    2217                 :          0 :                 rte_free(txq->q.sdesc);
    2218                 :            :                 free_txq(&txq->q);
    2219                 :            :         }
    2220                 :          0 : }
    2221                 :            : 
    2222                 :          0 : void t4_sge_eth_release_queues(struct port_info *pi)
    2223                 :            : {
    2224                 :          0 :         struct adapter *adap = pi->adapter;
    2225                 :            :         struct sge_eth_rxq *rxq;
    2226                 :            :         struct sge_eth_txq *txq;
    2227                 :            :         unsigned int i;
    2228                 :            : 
    2229                 :          0 :         rxq = &adap->sge.ethrxq[pi->first_rxqset];
    2230                 :            :         /* clean up Ethernet Tx/Rx queues */
    2231         [ #  # ]:          0 :         for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
    2232                 :            :                 /* Free only the queues allocated */
    2233         [ #  # ]:          0 :                 if (rxq->rspq.desc) {
    2234                 :          0 :                         t4_sge_eth_rxq_release(adap, rxq);
    2235                 :          0 :                         rte_eth_dma_zone_free(rxq->rspq.eth_dev, "fl_ring", i);
    2236                 :          0 :                         rte_eth_dma_zone_free(rxq->rspq.eth_dev, "rx_ring", i);
    2237                 :          0 :                         rxq->rspq.eth_dev = NULL;
    2238                 :            :                 }
    2239                 :            :         }
    2240                 :            : 
    2241                 :          0 :         txq = &adap->sge.ethtxq[pi->first_txqset];
    2242         [ #  # ]:          0 :         for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
    2243                 :            :                 /* Free only the queues allocated */
    2244         [ #  # ]:          0 :                 if (txq->q.desc) {
    2245                 :          0 :                         t4_sge_eth_txq_release(adap, txq);
    2246                 :          0 :                         rte_eth_dma_zone_free(txq->eth_dev, "tx_ring", i);
    2247                 :          0 :                         txq->eth_dev = NULL;
    2248                 :            :                 }
    2249                 :            :         }
    2250                 :          0 : }
    2251                 :            : 
    2252                 :          0 : void t4_sge_tx_monitor_start(struct adapter *adap)
    2253                 :            : {
    2254                 :          0 :         rte_eal_alarm_set(50, tx_timer_cb, (void *)adap);
    2255                 :          0 : }
    2256                 :            : 
    2257                 :          0 : void t4_sge_tx_monitor_stop(struct adapter *adap)
    2258                 :            : {
    2259                 :          0 :         rte_eal_alarm_cancel(tx_timer_cb, (void *)adap);
    2260                 :          0 : }
    2261                 :            : 
    2262                 :            : /**
    2263                 :            :  * t4_free_sge_resources - free SGE resources
    2264                 :            :  * @adap: the adapter
    2265                 :            :  *
    2266                 :            :  * Frees resources used by the SGE queue sets.
    2267                 :            :  */
    2268                 :          0 : void t4_free_sge_resources(struct adapter *adap)
    2269                 :            : {
    2270                 :            :         unsigned int i;
    2271                 :            : 
    2272                 :            :         /* clean up control Tx queues */
    2273         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
    2274                 :            :                 struct sge_ctrl_txq *cq = &adap->sge.ctrlq[i];
    2275                 :            : 
    2276         [ #  # ]:          0 :                 if (cq->q.desc) {
    2277                 :            :                         reclaim_completed_tx_imm(&cq->q);
    2278                 :          0 :                         t4_ctrl_eq_free(adap, adap->mbox, adap->pf, 0,
    2279                 :            :                                         cq->q.cntxt_id);
    2280                 :          0 :                         rte_eth_dma_zone_free(adap->eth_dev, "ctrl_tx_ring", i);
    2281                 :          0 :                         rte_mempool_free(cq->mb_pool);
    2282                 :            :                         free_txq(&cq->q);
    2283                 :            :                 }
    2284                 :            :         }
    2285                 :            : 
    2286                 :            :         /* clean up firmware event queue */
    2287         [ #  # ]:          0 :         if (adap->sge.fw_evtq.desc) {
    2288                 :          0 :                 free_rspq_fl(adap, &adap->sge.fw_evtq, NULL);
    2289                 :          0 :                 rte_eth_dma_zone_free(adap->eth_dev, "fwq_ring", 0);
    2290                 :            :         }
    2291                 :          0 : }
    2292                 :            : 
    2293                 :            : /**
    2294                 :            :  * t4_sge_init - initialize SGE
    2295                 :            :  * @adap: the adapter
    2296                 :            :  *
    2297                 :            :  * Performs SGE initialization needed every time after a chip reset.
    2298                 :            :  * We do not initialize any of the queues here, instead the driver
    2299                 :            :  * top-level must request those individually.
    2300                 :            :  *
    2301                 :            :  * Called in two different modes:
    2302                 :            :  *
    2303                 :            :  *  1. Perform actual hardware initialization and record hard-coded
    2304                 :            :  *     parameters which were used.  This gets used when we're the
    2305                 :            :  *     Master PF and the Firmware Configuration File support didn't
    2306                 :            :  *     work for some reason.
    2307                 :            :  *
    2308                 :            :  *  2. We're not the Master PF or initialization was performed with
    2309                 :            :  *     a Firmware Configuration File.  In this case we need to grab
    2310                 :            :  *     any of the SGE operating parameters that we need to have in
    2311                 :            :  *     order to do our job and make sure we can live with them ...
    2312                 :            :  */
    2313                 :          0 : static int t4_sge_init_soft(struct adapter *adap)
    2314                 :            : {
    2315                 :            :         u32 timer_value_0_and_1, timer_value_2_and_3, timer_value_4_and_5;
    2316                 :            :         struct sge *s = &adap->sge;
    2317                 :            :         u32 ingress_rx_threshold;
    2318                 :            :         u8 i;
    2319                 :            : 
    2320                 :            :         /*
    2321                 :            :          * Verify that CPL messages are going to the Ingress Queue for
    2322                 :            :          * process_responses() and that only packet data is going to the
    2323                 :            :          * Free Lists.
    2324                 :            :          */
    2325         [ #  # ]:          0 :         if ((t4_read_reg(adap, A_SGE_CONTROL) & F_RXPKTCPLMODE) !=
    2326                 :            :             V_RXPKTCPLMODE(X_RXPKTCPLMODE_SPLIT)) {
    2327                 :          0 :                 dev_err(adap, "bad SGE CPL MODE\n");
    2328                 :          0 :                 return -EINVAL;
    2329                 :            :         }
    2330                 :            : 
    2331                 :            :         /*
    2332                 :            :          * Read the Host Buffer Register Array indices that we want to
    2333                 :            :          * use ...
    2334                 :            :          */
    2335         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(s->fl_buffer_size); i++)
    2336                 :          0 :                 s->fl_buffer_size[i] = t4_read_reg(adap,
    2337                 :          0 :                                                    A_SGE_FL_BUFFER_SIZE0 +
    2338                 :            :                                                    i * sizeof(u32));
    2339                 :            : 
    2340                 :            :         /*
    2341                 :            :          * Retrieve our RX interrupt holdoff timer values and counter
    2342                 :            :          * threshold values from the SGE parameters.
    2343                 :            :          */
    2344                 :            :         timer_value_0_and_1 = t4_read_reg(adap, A_SGE_TIMER_VALUE_0_AND_1);
    2345                 :            :         timer_value_2_and_3 = t4_read_reg(adap, A_SGE_TIMER_VALUE_2_AND_3);
    2346                 :            :         timer_value_4_and_5 = t4_read_reg(adap, A_SGE_TIMER_VALUE_4_AND_5);
    2347                 :          0 :         s->timer_val[0] = core_ticks_to_us(adap,
    2348                 :            :                                            G_TIMERVALUE0(timer_value_0_and_1));
    2349                 :          0 :         s->timer_val[1] = core_ticks_to_us(adap,
    2350                 :            :                                            G_TIMERVALUE1(timer_value_0_and_1));
    2351                 :          0 :         s->timer_val[2] = core_ticks_to_us(adap,
    2352                 :            :                                            G_TIMERVALUE2(timer_value_2_and_3));
    2353                 :          0 :         s->timer_val[3] = core_ticks_to_us(adap,
    2354                 :            :                                            G_TIMERVALUE3(timer_value_2_and_3));
    2355                 :          0 :         s->timer_val[4] = core_ticks_to_us(adap,
    2356                 :            :                                            G_TIMERVALUE4(timer_value_4_and_5));
    2357                 :          0 :         s->timer_val[5] = core_ticks_to_us(adap,
    2358                 :            :                                            G_TIMERVALUE5(timer_value_4_and_5));
    2359                 :            : 
    2360                 :            :         ingress_rx_threshold = t4_read_reg(adap, A_SGE_INGRESS_RX_THRESHOLD);
    2361                 :          0 :         s->counter_val[0] = G_THRESHOLD_0(ingress_rx_threshold);
    2362                 :          0 :         s->counter_val[1] = G_THRESHOLD_1(ingress_rx_threshold);
    2363                 :          0 :         s->counter_val[2] = G_THRESHOLD_2(ingress_rx_threshold);
    2364                 :          0 :         s->counter_val[3] = G_THRESHOLD_3(ingress_rx_threshold);
    2365                 :            : 
    2366                 :          0 :         return 0;
    2367                 :            : }
    2368                 :            : 
    2369                 :          0 : int t4_sge_init(struct adapter *adap)
    2370                 :            : {
    2371                 :            :         struct sge *s = &adap->sge;
    2372                 :            :         u32 sge_control, sge_conm_ctrl;
    2373                 :            :         int ret, egress_threshold;
    2374                 :            : 
    2375                 :            :         /*
    2376                 :            :          * Ingress Padding Boundary and Egress Status Page Size are set up by
    2377                 :            :          * t4_fixup_host_params().
    2378                 :            :          */
    2379                 :            :         sge_control = t4_read_reg(adap, A_SGE_CONTROL);
    2380                 :          0 :         s->pktshift = G_PKTSHIFT(sge_control);
    2381         [ #  # ]:          0 :         s->stat_len = (sge_control & F_EGRSTATUSPAGESIZE) ? 128 : 64;
    2382                 :          0 :         ret = t4_sge_init_soft(adap);
    2383         [ #  # ]:          0 :         if (ret < 0) {
    2384                 :          0 :                 dev_err(adap, "%s: t4_sge_init_soft failed, error %d\n",
    2385                 :            :                         __func__, -ret);
    2386                 :          0 :                 return ret;
    2387                 :            :         }
    2388                 :            : 
    2389                 :            :         /*
    2390                 :            :          * A FL with <= fl_starve_thres buffers is starving and a periodic
    2391                 :            :          * timer will attempt to refill it.  This needs to be larger than the
    2392                 :            :          * SGE's Egress Congestion Threshold.  If it isn't, then we can get
    2393                 :            :          * stuck waiting for new packets while the SGE is waiting for us to
    2394                 :            :          * give it more Free List entries.  (Note that the SGE's Egress
    2395                 :            :          * Congestion Threshold is in units of 2 Free List pointers.)  For T4,
    2396                 :            :          * there was only a single field to control this.  For T5 there's the
    2397                 :            :          * original field which now only applies to Unpacked Mode Free List
    2398                 :            :          * buffers and a new field which only applies to Packed Mode Free List
    2399                 :            :          * buffers.
    2400                 :            :          */
    2401                 :            :         sge_conm_ctrl = t4_read_reg(adap, A_SGE_CONM_CTRL);
    2402   [ #  #  #  # ]:          0 :         if (is_t4(adap->params.chip) || adap->use_unpacked_mode)
    2403                 :          0 :                 egress_threshold = G_EGRTHRESHOLD(sge_conm_ctrl);
    2404                 :            :         else
    2405                 :          0 :                 egress_threshold = G_EGRTHRESHOLDPACKING(sge_conm_ctrl);
    2406                 :          0 :         s->fl_starve_thres = 2 * egress_threshold + 1;
    2407                 :            : 
    2408                 :          0 :         return 0;
    2409                 :            : }
    2410                 :            : 
    2411                 :          0 : int t4vf_sge_init(struct adapter *adap)
    2412                 :            : {
    2413                 :            :         struct sge_params *sge_params = &adap->params.sge;
    2414                 :            :         u32 sge_ingress_queues_per_page;
    2415                 :            :         u32 sge_egress_queues_per_page;
    2416                 :            :         u32 sge_ingress_rx_threshold;
    2417                 :            :         u32 sge_timer_value_0_and_1;
    2418                 :            :         u32 sge_timer_value_2_and_3;
    2419                 :            :         u32 sge_timer_value_4_and_5;
    2420                 :            :         u32 sge_congestion_control;
    2421                 :            :         struct sge *s = &adap->sge;
    2422                 :            :         unsigned int s_hps, s_qpp;
    2423                 :            :         u32 sge_host_page_size;
    2424                 :            :         u32 params[7], vals[7];
    2425                 :            :         u32 sge_control;
    2426                 :            :         int v;
    2427                 :            :         u8 i;
    2428                 :            : 
    2429                 :            :         /* query basic params from fw */
    2430                 :          0 :         params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2431                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL));
    2432                 :          0 :         params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2433                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE));
    2434                 :          0 :         params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2435                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1));
    2436                 :          0 :         params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2437                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3));
    2438                 :          0 :         params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2439                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5));
    2440                 :          0 :         v = t4vf_query_params(adap, 7, params, vals);
    2441         [ #  # ]:          0 :         if (v != FW_SUCCESS)
    2442                 :            :                 return v;
    2443                 :            : 
    2444                 :          0 :         sge_control = vals[0];
    2445                 :          0 :         sge_host_page_size = vals[1];
    2446                 :          0 :         sge_timer_value_0_and_1 = vals[2];
    2447                 :          0 :         sge_timer_value_2_and_3 = vals[3];
    2448                 :          0 :         sge_timer_value_4_and_5 = vals[4];
    2449                 :            : 
    2450         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(s->fl_buffer_size); i++) {
    2451                 :          0 :                 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2452                 :          0 :                              V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 +
    2453                 :            :                                                    i * sizeof(u32)));
    2454                 :          0 :                 v = t4vf_query_params(adap, 1, params, vals);
    2455         [ #  # ]:          0 :                 if (v != FW_SUCCESS)
    2456                 :          0 :                         return v;
    2457                 :            : 
    2458                 :          0 :                 s->fl_buffer_size[i] = vals[0];
    2459                 :            :         }
    2460                 :            : 
    2461                 :            :         /*
    2462                 :            :          * Start by vetting the basic SGE parameters which have been set up by
    2463                 :            :          * the Physical Function Driver.
    2464                 :            :          */
    2465                 :            : 
    2466         [ #  # ]:          0 :         if ((sge_control & F_RXPKTCPLMODE) !=
    2467                 :            :             V_RXPKTCPLMODE(X_RXPKTCPLMODE_SPLIT)) {
    2468                 :          0 :                 dev_err(adapter->pdev_dev, "bad SGE CPL MODE\n");
    2469                 :          0 :                 return -EINVAL;
    2470                 :            :         }
    2471                 :            : 
    2472                 :          0 :         params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2473                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD));
    2474                 :          0 :         params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2475                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL));
    2476                 :          0 :         v = t4vf_query_params(adap, 2, params, vals);
    2477         [ #  # ]:          0 :         if (v != FW_SUCCESS)
    2478                 :            :                 return v;
    2479                 :          0 :         sge_ingress_rx_threshold = vals[0];
    2480                 :          0 :         sge_congestion_control = vals[1];
    2481                 :          0 :         params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2482                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF));
    2483                 :          0 :         params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
    2484                 :            :                      V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF));
    2485                 :          0 :         v = t4vf_query_params(adap, 2, params, vals);
    2486         [ #  # ]:          0 :         if (v != FW_SUCCESS) {
    2487                 :          0 :                 dev_warn(adap, "Unable to get VF SGE Queues/Page; "
    2488                 :            :                          "probably old firmware.\n");
    2489                 :          0 :                 return v;
    2490                 :            :         }
    2491                 :          0 :         sge_egress_queues_per_page = vals[0];
    2492                 :          0 :         sge_ingress_queues_per_page = vals[1];
    2493                 :            : 
    2494                 :            :         /*
    2495                 :            :          * We need the Queues/Page for our VF.  This is based on the
    2496                 :            :          * PF from which we're instantiated and is indexed in the
    2497                 :            :          * register we just read.
    2498                 :            :          */
    2499                 :          0 :         s_hps = (S_HOSTPAGESIZEPF0 +
    2500                 :          0 :                  (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * adap->pf);
    2501                 :          0 :         sge_params->hps =
    2502                 :          0 :                 ((sge_host_page_size >> s_hps) & M_HOSTPAGESIZEPF0);
    2503                 :            : 
    2504                 :            :         s_qpp = (S_QUEUESPERPAGEPF0 +
    2505                 :            :                  (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * adap->pf);
    2506                 :          0 :         sge_params->eq_qpp =
    2507                 :          0 :                 ((sge_egress_queues_per_page >> s_qpp)
    2508                 :          0 :                  & M_QUEUESPERPAGEPF0);
    2509                 :          0 :         sge_params->iq_qpp =
    2510                 :          0 :                 ((sge_ingress_queues_per_page >> s_qpp)
    2511                 :          0 :                  & M_QUEUESPERPAGEPF0);
    2512                 :            : 
    2513                 :            :         /*
    2514                 :            :          * Now translate the queried parameters into our internal forms.
    2515                 :            :          */
    2516                 :          0 :         s->stat_len = ((sge_control & F_EGRSTATUSPAGESIZE)
    2517         [ #  # ]:          0 :                         ? 128 : 64);
    2518                 :          0 :         s->pktshift = G_PKTSHIFT(sge_control);
    2519                 :            : 
    2520                 :            :         /*
    2521                 :            :          * A FL with <= fl_starve_thres buffers is starving and a periodic
    2522                 :            :          * timer will attempt to refill it.  This needs to be larger than the
    2523                 :            :          * SGE's Egress Congestion Threshold.  If it isn't, then we can get
    2524                 :            :          * stuck waiting for new packets while the SGE is waiting for us to
    2525                 :            :          * give it more Free List entries.  (Note that the SGE's Egress
    2526                 :            :          * Congestion Threshold is in units of 2 Free List pointers.)
    2527                 :            :          */
    2528         [ #  # ]:          0 :         switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
    2529                 :          0 :         case CHELSIO_T5:
    2530                 :          0 :                 s->fl_starve_thres =
    2531                 :          0 :                         G_EGRTHRESHOLDPACKING(sge_congestion_control);
    2532                 :          0 :                 break;
    2533                 :          0 :         case CHELSIO_T6:
    2534                 :            :         default:
    2535                 :          0 :                 s->fl_starve_thres =
    2536                 :          0 :                         G_T6_EGRTHRESHOLDPACKING(sge_congestion_control);
    2537                 :          0 :                 break;
    2538                 :            :         }
    2539                 :          0 :         s->fl_starve_thres = s->fl_starve_thres * 2 + 1;
    2540                 :            : 
    2541                 :            :         /*
    2542                 :            :          * Save RX interrupt holdoff timer values and counter
    2543                 :            :          * threshold values from the SGE parameters.
    2544                 :            :          */
    2545                 :          0 :         s->timer_val[0] = core_ticks_to_us(adap,
    2546                 :            :                         G_TIMERVALUE0(sge_timer_value_0_and_1));
    2547                 :          0 :         s->timer_val[1] = core_ticks_to_us(adap,
    2548                 :            :                         G_TIMERVALUE1(sge_timer_value_0_and_1));
    2549                 :          0 :         s->timer_val[2] = core_ticks_to_us(adap,
    2550                 :            :                         G_TIMERVALUE2(sge_timer_value_2_and_3));
    2551                 :          0 :         s->timer_val[3] = core_ticks_to_us(adap,
    2552                 :            :                         G_TIMERVALUE3(sge_timer_value_2_and_3));
    2553                 :          0 :         s->timer_val[4] = core_ticks_to_us(adap,
    2554                 :            :                         G_TIMERVALUE4(sge_timer_value_4_and_5));
    2555                 :          0 :         s->timer_val[5] = core_ticks_to_us(adap,
    2556                 :            :                         G_TIMERVALUE5(sge_timer_value_4_and_5));
    2557                 :          0 :         s->counter_val[0] = G_THRESHOLD_0(sge_ingress_rx_threshold);
    2558                 :          0 :         s->counter_val[1] = G_THRESHOLD_1(sge_ingress_rx_threshold);
    2559                 :          0 :         s->counter_val[2] = G_THRESHOLD_2(sge_ingress_rx_threshold);
    2560                 :          0 :         s->counter_val[3] = G_THRESHOLD_3(sge_ingress_rx_threshold);
    2561                 :          0 :         return 0;
    2562                 :            : }

Generated by: LCOV version 1.14