LCOV - code coverage report
Current view: top level - drivers/net/enetfec - enet_uio.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 78 0.0 %
Date: 2024-12-01 18:57:19 Functions: 0 5 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 36 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2021 NXP
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdbool.h>
       6                 :            : #include <stdint.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <unistd.h>
       9                 :            : #include <stdlib.h>
      10                 :            : #include <dirent.h>
      11                 :            : #include <string.h>
      12                 :            : #include <sys/mman.h>
      13                 :            : #include <errno.h>
      14                 :            : #include <fcntl.h>
      15                 :            : 
      16                 :            : #include <rte_common.h>
      17                 :            : #include <rte_malloc.h>
      18                 :            : #include "enet_pmd_logs.h"
      19                 :            : #include "enet_uio.h"
      20                 :            : 
      21                 :            : static struct uio_job enetfec_uio_job;
      22                 :            : static int enetfec_count;
      23                 :            : 
      24                 :            : /** @brief Checks if a file name contains a certain substring.
      25                 :            :  * This function assumes a filename format of: [text][number].
      26                 :            :  * @param [in]  filename    File name
      27                 :            :  * @param [in]  match       String to match in file name
      28                 :            :  *
      29                 :            :  * @retval true if file name matches the criteria
      30                 :            :  * @retval false if file name does not match the criteria
      31                 :            :  */
      32                 :            : static bool
      33                 :            : file_name_match_extract(const char filename[], const char match[])
      34                 :            : {
      35                 :            :         char *substr = NULL;
      36                 :            : 
      37                 :          0 :         substr = strstr(filename, match);
      38   [ #  #  #  # ]:          0 :         if (substr == NULL)
      39                 :            :                 return false;
      40                 :            : 
      41                 :            :         return true;
      42                 :            : }
      43                 :            : 
      44                 :            : /*
      45                 :            :  * @brief Reads first line from a file.
      46                 :            :  * Composes file name as: root/subdir/filename
      47                 :            :  *
      48                 :            :  * @param [in]  root     Root path
      49                 :            :  * @param [in]  subdir   Subdirectory name
      50                 :            :  * @param [in]  filename File name
      51                 :            :  * @param [out] line     The first line read from file.
      52                 :            :  *
      53                 :            :  * @retval 0 for success
      54                 :            :  * @retval other value for error
      55                 :            :  */
      56                 :            : static int
      57                 :          0 : file_read_first_line(const char root[], const char subdir[],
      58                 :            :                         const char filename[], char *line)
      59                 :            : {
      60                 :            :         char absolute_file_name[FEC_UIO_MAX_ATTR_FILE_NAME];
      61                 :            :         int fd = 0, ret = 0;
      62                 :            : 
      63                 :            :         /*compose the file name: root/subdir/filename */
      64                 :            :         memset(absolute_file_name, 0, sizeof(absolute_file_name));
      65                 :            :         snprintf(absolute_file_name, FEC_UIO_MAX_ATTR_FILE_NAME,
      66                 :            :                 "%s/%s/%s", root, subdir, filename);
      67                 :            : 
      68                 :            :         fd = open(absolute_file_name, O_RDONLY);
      69         [ #  # ]:          0 :         if (fd <= 0)
      70                 :          0 :                 ENETFEC_PMD_ERR("Error opening file %s", absolute_file_name);
      71                 :            : 
      72                 :            :         /* read UIO device name from first line in file */
      73                 :          0 :         ret = read(fd, line, FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH);
      74         [ #  # ]:          0 :         if (ret <= 0) {
      75                 :          0 :                 ENETFEC_PMD_ERR("Error reading file %s", absolute_file_name);
      76                 :          0 :                 return ret;
      77                 :            :         }
      78                 :          0 :         close(fd);
      79                 :            : 
      80                 :            :         /* NULL-ify string */
      81                 :          0 :         line[ret] = '\0';
      82                 :            : 
      83                 :          0 :         return 0;
      84                 :            : }
      85                 :            : 
      86                 :            : /*
      87                 :            :  * @brief Maps rx-tx bd range assigned for a bd ring.
      88                 :            :  *
      89                 :            :  * @param [in] uio_device_fd    UIO device file descriptor
      90                 :            :  * @param [in] uio_device_id    UIO device id
      91                 :            :  * @param [in] uio_map_id       UIO allows maximum 5 different mapping for
      92                 :            :                                 each device. Maps start with id 0.
      93                 :            :  * @param [out] map_size        Map size.
      94                 :            :  * @param [out] map_addr        Map physical address
      95                 :            :  *
      96                 :            :  * @retval  NULL if failed to map registers
      97                 :            :  * @retval  Virtual address for mapped register address range
      98                 :            :  */
      99                 :            : static void *
     100                 :          0 : uio_map_mem(int uio_device_fd, int uio_device_id,
     101                 :            :                 int uio_map_id, int *map_size, uint64_t *map_addr)
     102                 :            : {
     103                 :            :         void *mapped_address = NULL;
     104                 :            :         unsigned int uio_map_size = 0;
     105                 :            :         unsigned int uio_map_p_addr = 0;
     106                 :            :         char uio_sys_root[FEC_UIO_MAX_ATTR_FILE_NAME];
     107                 :            :         char uio_sys_map_subdir[FEC_UIO_MAX_ATTR_FILE_NAME];
     108                 :            :         char uio_map_size_str[FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH + 1];
     109                 :            :         char uio_map_p_addr_str[32];
     110                 :            :         int ret = 0;
     111                 :            : 
     112                 :            :         /* compose the file name: root/subdir/filename */
     113                 :            :         memset(uio_sys_root, 0, sizeof(uio_sys_root));
     114                 :            :         memset(uio_sys_map_subdir, 0, sizeof(uio_sys_map_subdir));
     115                 :            :         memset(uio_map_size_str, 0, sizeof(uio_map_size_str));
     116                 :            :         memset(uio_map_p_addr_str, 0, sizeof(uio_map_p_addr_str));
     117                 :            : 
     118                 :            :         /* Compose string: /sys/class/uio/uioX */
     119                 :            :         snprintf(uio_sys_root, sizeof(uio_sys_root), "%s/%s%d",
     120                 :            :                         FEC_UIO_DEVICE_SYS_ATTR_PATH, "uio", uio_device_id);
     121                 :            :         /* Compose string: maps/mapY */
     122                 :            :         snprintf(uio_sys_map_subdir, sizeof(uio_sys_map_subdir), "%s%d",
     123                 :            :                         FEC_UIO_DEVICE_SYS_MAP_ATTR, uio_map_id);
     124                 :            : 
     125                 :            :         /* Read first (and only) line from file
     126                 :            :          * /sys/class/uio/uioX/maps/mapY/size
     127                 :            :          */
     128                 :          0 :         ret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,
     129                 :            :                                 "size", uio_map_size_str);
     130         [ #  # ]:          0 :         if (ret < 0) {
     131                 :          0 :                 ENETFEC_PMD_ERR("file_read_first_line() failed");
     132                 :          0 :                 return NULL;
     133                 :            :         }
     134                 :          0 :         ret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,
     135                 :            :                                 "addr", uio_map_p_addr_str);
     136         [ #  # ]:          0 :         if (ret < 0) {
     137                 :          0 :                 ENETFEC_PMD_ERR("file_read_first_line() failed");
     138                 :          0 :                 return NULL;
     139                 :            :         }
     140                 :            :         /* Read mapping size and physical address expressed in hexa(base 16) */
     141                 :          0 :         uio_map_size = strtol(uio_map_size_str, NULL, 16);
     142                 :          0 :         uio_map_p_addr = strtol(uio_map_p_addr_str, NULL, 16);
     143                 :            : 
     144         [ #  # ]:          0 :         if (uio_map_id == 0) {
     145                 :            :                 /* Map the register address in user space when map_id is 0 */
     146                 :          0 :                 mapped_address = mmap(0 /*dynamically choose virtual address */,
     147                 :            :                                 uio_map_size, PROT_READ | PROT_WRITE,
     148                 :            :                                 MAP_SHARED, uio_device_fd, 0);
     149                 :            :         } else {
     150                 :            :                 /* Map the BD memory in user space */
     151                 :          0 :                 mapped_address = mmap(NULL, uio_map_size,
     152                 :            :                                 PROT_READ | PROT_WRITE,
     153                 :            :                                 MAP_SHARED, uio_device_fd, (1 * MAP_PAGE_SIZE));
     154                 :            :         }
     155                 :            : 
     156         [ #  # ]:          0 :         if (mapped_address == MAP_FAILED) {
     157                 :          0 :                 ENETFEC_PMD_ERR("Failed to map! errno = %d uio job fd = %d,"
     158                 :            :                         "uio device id = %d, uio map id = %d", errno,
     159                 :            :                         uio_device_fd, uio_device_id, uio_map_id);
     160                 :          0 :                 return NULL;
     161                 :            :         }
     162                 :            : 
     163                 :            :         /* Save the map size to use it later on for munmap-ing */
     164                 :          0 :         *map_size = uio_map_size;
     165                 :          0 :         *map_addr = uio_map_p_addr;
     166                 :          0 :         ENETFEC_PMD_INFO("UIO dev[%d] mapped region [id =%d] size 0x%x at %p",
     167                 :            :                 uio_device_id, uio_map_id, uio_map_size, mapped_address);
     168                 :            : 
     169                 :          0 :         return mapped_address;
     170                 :            : }
     171                 :            : 
     172                 :            : int
     173                 :          0 : config_enetfec_uio(struct enetfec_private *fep)
     174                 :            : {
     175                 :            :         char uio_device_file_name[32];
     176                 :            :         struct uio_job *uio_job = NULL;
     177                 :            : 
     178                 :            :         /* Mapping is done only one time */
     179         [ #  # ]:          0 :         if (enetfec_count > 0) {
     180                 :          0 :                 ENETFEC_PMD_INFO("Mapped!");
     181                 :          0 :                 return 0;
     182                 :            :         }
     183                 :            : 
     184                 :            :         uio_job = &enetfec_uio_job;
     185                 :            : 
     186                 :            :         /* Find UIO device created by ENETFEC-UIO kernel driver */
     187                 :            :         memset(uio_device_file_name, 0, sizeof(uio_device_file_name));
     188                 :          0 :         snprintf(uio_device_file_name, sizeof(uio_device_file_name), "%s%d",
     189                 :            :                         FEC_UIO_DEVICE_FILE_NAME, uio_job->uio_minor_number);
     190                 :            : 
     191                 :            :         /* Open device file */
     192                 :          0 :         uio_job->uio_fd = open(uio_device_file_name, O_RDWR);
     193         [ #  # ]:          0 :         if (uio_job->uio_fd < 0) {
     194                 :          0 :                 ENETFEC_PMD_WARN("Unable to open ENETFEC_UIO file");
     195                 :          0 :                 return -1;
     196                 :            :         }
     197                 :            : 
     198                 :          0 :         ENETFEC_PMD_INFO("US_UIO: Open device(%s) file with uio_fd = %d",
     199                 :            :                         uio_device_file_name, uio_job->uio_fd);
     200                 :            : 
     201                 :          0 :         fep->hw_baseaddr_v = uio_map_mem(uio_job->uio_fd,
     202                 :            :                 uio_job->uio_minor_number, FEC_UIO_REG_MAP_ID,
     203                 :            :                 &uio_job->map_size, &uio_job->map_addr);
     204         [ #  # ]:          0 :         if (fep->hw_baseaddr_v == NULL)
     205                 :            :                 return -ENOMEM;
     206                 :          0 :         fep->hw_baseaddr_p = uio_job->map_addr;
     207                 :          0 :         fep->reg_size = uio_job->map_size;
     208                 :            : 
     209                 :          0 :         fep->bd_addr_v = uio_map_mem(uio_job->uio_fd,
     210                 :            :                 uio_job->uio_minor_number, FEC_UIO_BD_MAP_ID,
     211                 :            :                 &uio_job->map_size, &uio_job->map_addr);
     212         [ #  # ]:          0 :         if (fep->hw_baseaddr_v == NULL)
     213                 :            :                 return -ENOMEM;
     214                 :          0 :         fep->bd_addr_p = (uint32_t)uio_job->map_addr;
     215                 :          0 :         fep->bd_size = uio_job->map_size;
     216                 :            : 
     217                 :          0 :         enetfec_count++;
     218                 :            : 
     219                 :          0 :         return 0;
     220                 :            : }
     221                 :            : 
     222                 :            : int
     223                 :          0 : enetfec_configure(void)
     224                 :            : {
     225                 :            :         char uio_name[32];
     226                 :          0 :         int uio_minor_number = -1;
     227                 :            :         int ret;
     228                 :            :         DIR *d = NULL;
     229                 :            :         struct dirent *dir;
     230                 :            : 
     231                 :          0 :         d = opendir(FEC_UIO_DEVICE_SYS_ATTR_PATH);
     232         [ #  # ]:          0 :         if (d == NULL) {
     233                 :          0 :                 ENETFEC_PMD_ERR("Error opening directory '%s': %s",
     234                 :            :                         FEC_UIO_DEVICE_SYS_ATTR_PATH, strerror(errno));
     235                 :          0 :                 return -1;
     236                 :            :         }
     237                 :            : 
     238                 :            :         /* Iterate through all subdirs */
     239         [ #  # ]:          0 :         while ((dir = readdir(d)) != NULL) {
     240         [ #  # ]:          0 :                 if (!strncmp(dir->d_name, ".", 1) ||
     241         [ #  # ]:          0 :                                 !strncmp(dir->d_name, "..", 2))
     242                 :          0 :                         continue;
     243                 :            : 
     244                 :            :                 if (file_name_match_extract(dir->d_name, "uio")) {
     245                 :            :                         /*
     246                 :            :                          * As substring <uio> was found in <d_name>
     247                 :            :                          * read number following <uio> substring in <d_name>
     248                 :            :                          */
     249                 :          0 :                         ret = sscanf(dir->d_name + strlen("uio"), "%d",
     250                 :            :                                                         &uio_minor_number);
     251         [ #  # ]:          0 :                         if (ret < 0)
     252                 :          0 :                                 ENETFEC_PMD_ERR("Error: not find minor number");
     253                 :            :                         /*
     254                 :            :                          * Open file uioX/name and read first line which
     255                 :            :                          * contains the name for the device. Based on the
     256                 :            :                          * name check if this UIO device is for enetfec.
     257                 :            :                          */
     258                 :            :                         memset(uio_name, 0, sizeof(uio_name));
     259                 :          0 :                         ret = file_read_first_line(FEC_UIO_DEVICE_SYS_ATTR_PATH,
     260                 :            :                                         dir->d_name, "name", uio_name);
     261         [ #  # ]:          0 :                         if (ret != 0) {
     262                 :          0 :                                 ENETFEC_PMD_INFO("file_read_first_line failed");
     263                 :          0 :                                 closedir(d);
     264                 :          0 :                                 return -1;
     265                 :            :                         }
     266                 :            : 
     267                 :            :                         if (file_name_match_extract(uio_name,
     268                 :            :                                                 FEC_UIO_DEVICE_NAME)) {
     269                 :          0 :                                 enetfec_uio_job.uio_minor_number =
     270                 :            :                                                         uio_minor_number;
     271                 :          0 :                                 ENETFEC_PMD_INFO("enetfec device uio name: %s",
     272                 :            :                                                  uio_name);
     273                 :            :                         }
     274                 :            :                 }
     275                 :            :         }
     276                 :          0 :         closedir(d);
     277                 :          0 :         return 0;
     278                 :            : }
     279                 :            : 
     280                 :            : void
     281                 :          0 : enetfec_cleanup(struct enetfec_private *fep)
     282                 :            : {
     283                 :          0 :         munmap(fep->hw_baseaddr_v, fep->cbus_size);
     284                 :          0 : }

Generated by: LCOV version 1.14