LCOV - code coverage report
Current view: top level - drivers/dma/odm - odm.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 145 0.0 %
Date: 2026-07-01 18:02:41 Functions: 0 9 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 55 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2024 Marvell.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdint.h>
       6                 :            : 
       7                 :            : #include <bus_pci_driver.h>
       8                 :            : 
       9                 :            : #include <rte_io.h>
      10                 :            : #include <rte_malloc.h>
      11                 :            : 
      12                 :            : #include "odm.h"
      13                 :            : #include "odm_priv.h"
      14                 :            : 
      15                 :            : static void
      16                 :          0 : odm_vchan_resc_free(struct odm_dev *odm, int qno)
      17                 :            : {
      18                 :            :         struct odm_queue *vq = &odm->vq[qno];
      19                 :            : 
      20                 :          0 :         rte_memzone_free(vq->iring_mz);
      21                 :          0 :         rte_memzone_free(vq->cring_mz);
      22                 :          0 :         rte_free(vq->extra_ins_sz);
      23                 :            : 
      24                 :          0 :         vq->iring_mz = NULL;
      25                 :          0 :         vq->cring_mz = NULL;
      26                 :          0 :         vq->extra_ins_sz = NULL;
      27                 :          0 : }
      28                 :            : 
      29                 :            : static int
      30                 :          0 : send_mbox_to_pf(struct odm_dev *odm, union odm_mbox_msg *msg, union odm_mbox_msg *rsp)
      31                 :            : {
      32                 :            :         int retry_cnt = ODM_MBOX_RETRY_CNT;
      33                 :            :         union odm_mbox_msg pf_msg;
      34                 :            : 
      35                 :          0 :         msg->d.err = ODM_MBOX_ERR_CODE_MAX;
      36                 :          0 :         odm_write64(msg->u[0], odm->rbase + ODM_MBOX_VF_PF_DATA(0));
      37                 :          0 :         odm_write64(msg->u[1], odm->rbase + ODM_MBOX_VF_PF_DATA(1));
      38                 :            : 
      39                 :            :         pf_msg.u[0] = 0;
      40                 :            :         pf_msg.u[1] = 0;
      41                 :          0 :         pf_msg.u[0] = odm_read64(odm->rbase + ODM_MBOX_VF_PF_DATA(0));
      42                 :            : 
      43   [ #  #  #  # ]:          0 :         while (pf_msg.d.rsp == 0 && retry_cnt > 0) {
      44                 :          0 :                 pf_msg.u[0] = odm_read64(odm->rbase + ODM_MBOX_VF_PF_DATA(0));
      45                 :          0 :                 --retry_cnt;
      46                 :            :         }
      47                 :            : 
      48         [ #  # ]:          0 :         if (retry_cnt <= 0)
      49                 :            :                 return -EBADE;
      50                 :            : 
      51                 :            :         pf_msg.u[1] = odm_read64(odm->rbase + ODM_MBOX_VF_PF_DATA(1));
      52                 :            : 
      53         [ #  # ]:          0 :         if (rsp) {
      54                 :          0 :                 rsp->u[0] = pf_msg.u[0];
      55                 :          0 :                 rsp->u[1] = pf_msg.u[1];
      56                 :            :         }
      57                 :            : 
      58   [ #  #  #  # ]:          0 :         if (pf_msg.d.rsp == msg->d.err && pf_msg.d.err != 0)
      59                 :          0 :                 return -EBADE;
      60                 :            : 
      61                 :            :         return 0;
      62                 :            : }
      63                 :            : 
      64                 :            : static int
      65                 :          0 : odm_queue_ring_config(struct odm_dev *odm, int vchan, int isize, int csize)
      66                 :            : {
      67                 :          0 :         union odm_vdma_ring_cfg_s ring_cfg = {0};
      68                 :            :         struct odm_queue *vq = &odm->vq[vchan];
      69                 :            : 
      70   [ #  #  #  # ]:          0 :         if (vq->iring_mz == NULL || vq->cring_mz == NULL)
      71                 :            :                 return -EINVAL;
      72                 :            : 
      73                 :          0 :         ring_cfg.s.isize = (isize / 1024) - 1;
      74                 :          0 :         ring_cfg.s.csize = (csize / 1024) - 1;
      75                 :            : 
      76                 :          0 :         odm_write64(ring_cfg.u, odm->rbase + ODM_VDMA_RING_CFG(vchan));
      77                 :          0 :         odm_write64(vq->iring_mz->iova, odm->rbase + ODM_VDMA_IRING_BADDR(vchan));
      78                 :          0 :         odm_write64(vq->cring_mz->iova, odm->rbase + ODM_VDMA_CRING_BADDR(vchan));
      79                 :            : 
      80                 :          0 :         return 0;
      81                 :            : }
      82                 :            : 
      83                 :            : int
      84                 :          0 : odm_enable(struct odm_dev *odm)
      85                 :            : {
      86                 :            :         struct odm_queue *vq;
      87                 :            :         int qno, rc = 0;
      88                 :            : 
      89         [ #  # ]:          0 :         for (qno = 0; qno < odm->num_qs; qno++) {
      90                 :            :                 vq = &odm->vq[qno];
      91                 :            : 
      92                 :          0 :                 vq->desc_idx = vq->stats.completed_offset;
      93                 :          0 :                 vq->pending_submit_len = 0;
      94                 :          0 :                 vq->pending_submit_cnt = 0;
      95                 :          0 :                 vq->iring_head = 0;
      96                 :          0 :                 vq->cring_head = 0;
      97                 :          0 :                 vq->ins_ring_head = 0;
      98                 :          0 :                 vq->iring_sz_available = vq->iring_max_words;
      99                 :            : 
     100                 :          0 :                 rc = odm_queue_ring_config(odm, qno, vq->iring_max_words * 8,
     101                 :          0 :                                            vq->cring_max_entry * 4);
     102         [ #  # ]:          0 :                 if (rc < 0)
     103                 :            :                         break;
     104                 :            : 
     105                 :          0 :                 odm_write64(0x1, odm->rbase + ODM_VDMA_EN(qno));
     106                 :            :         }
     107                 :            : 
     108                 :          0 :         return rc;
     109                 :            : }
     110                 :            : 
     111                 :            : int
     112                 :          0 : odm_disable(struct odm_dev *odm)
     113                 :            : {
     114                 :            :         int qno, wait_cnt = ODM_IRING_IDLE_WAIT_CNT;
     115                 :            :         uint64_t val;
     116                 :            : 
     117                 :            :         /* Disable the queue and wait for the queue to became idle */
     118         [ #  # ]:          0 :         for (qno = 0; qno < odm->num_qs; qno++) {
     119                 :          0 :                 odm_write64(0x0, odm->rbase + ODM_VDMA_EN(qno));
     120                 :            :                 do {
     121         [ #  # ]:          0 :                         val = odm_read64(odm->rbase + ODM_VDMA_IRING_BADDR(qno));
     122   [ #  #  #  # ]:          0 :                 } while ((!(val & 1ULL << 63)) && (--wait_cnt > 0));
     123                 :            :         }
     124                 :            : 
     125                 :          0 :         return 0;
     126                 :            : }
     127                 :            : 
     128                 :            : static int
     129                 :          0 : odm_get_ext_port_type(const struct rte_dma_vchan_conf *conf, uint8_t *ext_port)
     130                 :            : {
     131                 :            :         uint8_t coreid;
     132                 :            : 
     133         [ #  # ]:          0 :         if (conf->src_port.port_type == RTE_DMA_PORT_PCIE) {
     134                 :          0 :                 coreid = conf->src_port.pcie.coreid;
     135         [ #  # ]:          0 :         } else if (conf->dst_port.port_type == RTE_DMA_PORT_PCIE) {
     136                 :          0 :                 coreid = conf->dst_port.pcie.coreid;
     137                 :            :         } else {
     138                 :          0 :                 *ext_port = ODM_EXT_PORT_NCB;
     139                 :          0 :                 return 0;
     140                 :            :         }
     141                 :            : 
     142      [ #  #  # ]:          0 :         switch (coreid) {
     143                 :          0 :         case 0:
     144                 :          0 :                 *ext_port = ODM_EXT_PORT_PEM0;
     145                 :          0 :                 return 0;
     146                 :          0 :         case 1:
     147                 :          0 :                 *ext_port = ODM_EXT_PORT_PEM1;
     148                 :          0 :                 return 0;
     149                 :          0 :         default:
     150                 :          0 :                 ODM_LOG(ERR, "Unsupported PCIe coreid %u (only 0 and 1 are valid)", coreid);
     151                 :          0 :                 return -EINVAL;
     152                 :            :         }
     153                 :            : }
     154                 :            : 
     155                 :            : int
     156                 :          0 : odm_vchan_setup(struct odm_dev *odm, int vchan, const struct rte_dma_vchan_conf *conf)
     157                 :            : {
     158                 :            :         struct odm_queue *vq = &odm->vq[vchan];
     159                 :            :         int isize, csize, max_nb_desc, rc = 0;
     160                 :            :         union odm_mbox_msg mbox_msg;
     161                 :            :         const struct rte_memzone *mz;
     162                 :            :         uint8_t ext_port;
     163                 :            :         char name[32];
     164                 :            : 
     165         [ #  # ]:          0 :         if (vq->iring_mz != NULL)
     166                 :          0 :                 odm_vchan_resc_free(odm, vchan);
     167                 :            : 
     168                 :          0 :         mbox_msg.u[0] = 0;
     169                 :          0 :         mbox_msg.u[1] = 0;
     170                 :            : 
     171   [ #  #  #  # ]:          0 :         switch (conf->direction) {
     172                 :          0 :         case RTE_DMA_DIR_DEV_TO_MEM:
     173                 :          0 :                 vq->xtype = ODM_XTYPE_INBOUND;
     174                 :          0 :                 break;
     175                 :          0 :         case RTE_DMA_DIR_MEM_TO_DEV:
     176                 :          0 :                 vq->xtype = ODM_XTYPE_OUTBOUND;
     177                 :          0 :                 break;
     178                 :          0 :         case RTE_DMA_DIR_MEM_TO_MEM:
     179                 :          0 :                 vq->xtype = ODM_XTYPE_INTERNAL;
     180                 :          0 :                 break;
     181                 :          0 :         default:
     182                 :          0 :                 ODM_LOG(ERR, "Unsupported DMA direction %d", conf->direction);
     183                 :          0 :                 return -EINVAL;
     184                 :            :         }
     185                 :            : 
     186                 :            :         /* ODM PF driver expects vfid starts from index 0 */
     187                 :          0 :         mbox_msg.q.vfid = odm->vfid;
     188                 :          0 :         mbox_msg.q.cmd = ODM_QUEUE_OPEN;
     189                 :          0 :         mbox_msg.q.qidx = vchan;
     190                 :          0 :         rc = odm_get_ext_port_type(conf, &ext_port);
     191         [ #  # ]:          0 :         if (rc < 0)
     192                 :            :                 return rc;
     193                 :          0 :         mbox_msg.q.ext_port = ext_port;
     194                 :          0 :         rc = send_mbox_to_pf(odm, &mbox_msg, &mbox_msg);
     195         [ #  # ]:          0 :         if (rc < 0)
     196                 :            :                 return rc;
     197                 :            : 
     198                 :            :         /* Determine instruction & completion ring sizes. */
     199                 :            : 
     200                 :            :         /* Create iring that can support nb_desc. Round up to a multiple of 1024. */
     201                 :          0 :         isize = RTE_ALIGN_CEIL(conf->nb_desc * ODM_IRING_ENTRY_SIZE_MAX * 8, 1024);
     202                 :          0 :         isize = RTE_MIN(isize, ODM_IRING_MAX_SIZE);
     203                 :          0 :         snprintf(name, sizeof(name), "vq%d_iring%d", odm->vfid, vchan);
     204                 :          0 :         mz = rte_memzone_reserve_aligned(name, isize, SOCKET_ID_ANY, 0, 1024);
     205         [ #  # ]:          0 :         if (mz == NULL)
     206                 :            :                 return -ENOMEM;
     207                 :          0 :         vq->iring_mz = mz;
     208                 :          0 :         vq->iring_max_words = isize / 8;
     209                 :            : 
     210                 :            :         /* Create cring that can support max instructions that can be inflight in hw. */
     211                 :          0 :         max_nb_desc = (isize / (ODM_IRING_ENTRY_SIZE_MIN * 8));
     212                 :          0 :         csize = RTE_ALIGN_CEIL(max_nb_desc * sizeof(union odm_cmpl_ent_s), 1024);
     213                 :          0 :         snprintf(name, sizeof(name), "vq%d_cring%d", odm->vfid, vchan);
     214                 :          0 :         mz = rte_memzone_reserve_aligned(name, csize, SOCKET_ID_ANY, 0, 1024);
     215         [ #  # ]:          0 :         if (mz == NULL) {
     216                 :            :                 rc = -ENOMEM;
     217                 :          0 :                 goto iring_free;
     218                 :            :         }
     219                 :          0 :         vq->cring_mz = mz;
     220                 :          0 :         vq->cring_max_entry = csize / 4;
     221                 :            : 
     222                 :            :         /* Allocate memory to track the size of each instruction. */
     223                 :          0 :         snprintf(name, sizeof(name), "vq%d_extra%d", odm->vfid, vchan);
     224                 :          0 :         vq->extra_ins_sz = rte_zmalloc(name, vq->cring_max_entry, 0);
     225         [ #  # ]:          0 :         if (vq->extra_ins_sz == NULL) {
     226                 :            :                 rc = -ENOMEM;
     227                 :          0 :                 goto cring_free;
     228                 :            :         }
     229                 :            : 
     230                 :          0 :         vq->stats = (struct vq_stats){0};
     231                 :          0 :         return rc;
     232                 :            : 
     233                 :            : cring_free:
     234                 :          0 :         rte_memzone_free(odm->vq[vchan].cring_mz);
     235                 :          0 :         vq->cring_mz = NULL;
     236                 :          0 : iring_free:
     237                 :          0 :         rte_memzone_free(odm->vq[vchan].iring_mz);
     238                 :          0 :         vq->iring_mz = NULL;
     239                 :            : 
     240                 :          0 :         return rc;
     241                 :            : }
     242                 :            : 
     243                 :            : int
     244                 :          0 : odm_dev_init(struct odm_dev *odm)
     245                 :            : {
     246                 :          0 :         struct rte_pci_device *pci_dev = odm->pci_dev;
     247                 :            :         union odm_mbox_msg mbox_msg;
     248                 :            :         uint16_t vfid;
     249                 :            :         int rc;
     250                 :            : 
     251                 :          0 :         odm->rbase = pci_dev->mem_resource[0].addr;
     252                 :          0 :         vfid = ((pci_dev->addr.devid & 0x1F) << 3) | (pci_dev->addr.function & 0x7);
     253                 :          0 :         vfid -= 1;
     254                 :          0 :         odm->vfid = vfid;
     255                 :          0 :         odm->num_qs = 0;
     256                 :            : 
     257                 :          0 :         mbox_msg.u[0] = 0;
     258                 :          0 :         mbox_msg.u[1] = 0;
     259                 :          0 :         mbox_msg.q.vfid = odm->vfid;
     260                 :          0 :         mbox_msg.q.cmd = ODM_DEV_INIT;
     261                 :          0 :         rc = send_mbox_to_pf(odm, &mbox_msg, &mbox_msg);
     262         [ #  # ]:          0 :         if (!rc)
     263                 :          0 :                 odm->max_qs = 1 << (4 - mbox_msg.d.nvfs);
     264                 :            : 
     265                 :          0 :         return rc;
     266                 :            : }
     267                 :            : 
     268                 :            : int
     269                 :          0 : odm_dev_fini(struct odm_dev *odm)
     270                 :            : {
     271                 :            :         union odm_mbox_msg mbox_msg;
     272                 :            :         int qno, rc = 0;
     273                 :            : 
     274                 :          0 :         mbox_msg.u[0] = 0;
     275                 :          0 :         mbox_msg.u[1] = 0;
     276                 :          0 :         mbox_msg.q.vfid = odm->vfid;
     277                 :          0 :         mbox_msg.q.cmd = ODM_DEV_CLOSE;
     278                 :          0 :         rc = send_mbox_to_pf(odm, &mbox_msg, &mbox_msg);
     279                 :            : 
     280         [ #  # ]:          0 :         for (qno = 0; qno < odm->num_qs; qno++)
     281                 :          0 :                 odm_vchan_resc_free(odm, qno);
     282                 :            : 
     283                 :          0 :         return rc;
     284                 :            : }

Generated by: LCOV version 1.14