On Wed,  6 Jul 2022 13:21:55 +0530
Aman Kumar <aman.ku...@vvdntech.in> wrote:

> +/* parse a sysfs file containing one integer value */
> +static int parse_sysfs_value(const char *filename, uint32_t *val)
> +{
> +     FILE *f;
> +     char buf[BUFSIZ];
> +     char *end = NULL;
> +
> +     f = fopen(filename, "r");
> +     if (f == NULL) {
> +             PMD_DRV_LOG(ERR, "%s(): Failed to open sysfs file %s\n",
> +                             __func__, filename);
> +             return -1;
> +     }
> +
> +     if (fgets(buf, sizeof(buf), f) == NULL) {
> +             PMD_DRV_LOG(ERR, "%s(): Failed to read sysfs value %s\n",
> +                     __func__, filename);
> +             fclose(f);
> +             return -1;
> +     }
> +     *val = (uint32_t)strtoul(buf, &end, 0);
> +     if ((buf[0] == '\0') || end == NULL || (*end != '\n')) {
> +             PMD_DRV_LOG(ERR, "%s(): Failed to parse sysfs value %s\n",
> +                             __func__, filename);
> +             fclose(f);
> +             return -1;
> +     }
> +     fclose(f);
> +     return 0;
> +}

Why reinvent eal_parse_sysfs_value?

> +/* Split up a pci address into its constituent parts. */
> +static int parse_pci_addr_format(const char *buf,
> +             int bufsize, struct rte_pci_addr *addr)
> +{
> +     /* first split on ':' */
> +     union splitaddr {
> +             struct {
> +                     char *domain;
> +                     char *bus;
> +                     char *devid;
> +                     char *function;
> +             };
> +             /* last element-separator is "." not ":" */
> +             char *str[PCI_FMT_NVAL];
> +     } splitaddr;
> +
> +     char *buf_copy = strndup(buf, bufsize);
> +     if (buf_copy == NULL) {
> +             PMD_DRV_LOG(ERR, "Failed to get pci address duplicate copy\n");
> +             return -1;
> +     }
> +
> +     if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
> +                     != PCI_FMT_NVAL - 1) {
> +             PMD_DRV_LOG(ERR, "Failed to split pci address string\n");
> +             goto error;
> +     }
> +
> +     /* final split is on '.' between devid and function */
> +     splitaddr.function = strchr(splitaddr.devid, '.');
> +     if (splitaddr.function == NULL) {
> +             PMD_DRV_LOG(ERR, "Failed to split pci devid and function\n");
> +             goto error;
> +     }
> +     *splitaddr.function++ = '\0';
> +
> +     /* now convert to int values */
> +     addr->domain = strtoul(splitaddr.domain, NULL, 16);
> +     addr->bus = strtoul(splitaddr.bus, NULL, 16);
> +     addr->devid = strtoul(splitaddr.devid, NULL, 16);
> +     addr->function = strtoul(splitaddr.function, NULL, 10);
> +
> +     free(buf_copy); /* free the copy made with strdup */
> +     return 0;
> +
> +error:
> +     free(buf_copy);
> +     return -1;
> +}

Looks like you didn't see rte_pci_addr_parse..

> +/* Get max pci bus number from the corresponding pci bridge device */
> +static int get_max_pci_bus_num(uint8_t start_bus, uint8_t *end_bus)
> +{
> +     char dirname[PATH_MAX];
> +     char filename[PATH_MAX];
> +     char cfgname[PATH_MAX];
> +     struct rte_pci_addr addr;
> +     struct dirent *dp;
> +     uint32_t pci_class_code;
> +     uint8_t sec_bus_num, sub_bus_num;
> +     DIR *dir;
> +     int ret, fd;
> +
> +     /* Initialize end bus number to zero */
> +     *end_bus = 0;
> +
> +     /* Open pci devices directory */
> +     dir = opendir(rte_pci_get_sysfs_path());
> +     if (dir == NULL) {
> +             PMD_DRV_LOG(ERR, "%s(): opendir failed\n",
> +                     __func__);
> +             return -1;
> +     }
> +
> +     while ((dp = readdir(dir)) != NULL) {
> +             if (dp->d_name[0] == '.')
> +                     continue;
> +
> +             /* Split pci address to get bus, devid and function numbers */
> +             if (parse_pci_addr_format(dp->d_name,
> +                             sizeof(dp->d_name), &addr) != 0)
> +                     continue;
> +
> +             snprintf(dirname, sizeof(dirname), "%s/%s",
> +                             rte_pci_get_sysfs_path(), dp->d_name);
> +
> +             /* get class code */
> +             snprintf(filename, sizeof(filename), "%s/class", dirname);
> +             if (parse_sysfs_value(filename, &pci_class_code) < 0) {
> +                     PMD_DRV_LOG(ERR, "Failed to get pci class code\n");
> +                     goto error;
> +             }
> +
> +             /* Get max pci number from pci bridge device */
> +             if ((((pci_class_code >> PCI_CONFIG_CLASS_CODE_SHIFT) & 0xFF) ==
> +                             PCI_CONFIG_BRIDGE_DEVICE)) {
> +                     snprintf(cfgname, sizeof(cfgname),
> +                                     "%s/config", dirname);
> +                     fd = open(cfgname, O_RDWR);
> +                     if (fd < 0) {
> +                             PMD_DRV_LOG(ERR, "Failed to open %s\n",
> +                                     cfgname);
> +                             goto error;
> +                     }
> +
> +                     /* get secondary bus number */
> +                     ret = pread(fd, &sec_bus_num, sizeof(uint8_t),
> +                                             PCI_SECONDARY_BUS);
> +                     if (ret == -1) {
> +                             PMD_DRV_LOG(ERR, "Failed to read secondary bus 
> number\n");
> +                             close(fd);
> +                             goto error;
> +                     }
> +
> +                     /* get subordinate bus number */
> +                     ret = pread(fd, &sub_bus_num, sizeof(uint8_t),
> +                                             PCI_SUBORDINATE_BUS);
> +                     if (ret == -1) {
> +                             PMD_DRV_LOG(ERR, "Failed to read subordinate 
> bus number\n");
> +                             close(fd);
> +                             goto error;
> +                     }
> +
> +                     /* Get max bus number by checking if given bus number
> +                      * falls in between secondary and subordinate bus
> +                      * numbers of this pci bridge device.
> +                      */
> +                     if (start_bus >= sec_bus_num &&
> +                         start_bus <= sub_bus_num) {
> +                             *end_bus = sub_bus_num;
> +                             close(fd);
> +                             closedir(dir);
> +                             return 0;
> +                     }
> +
> +                     close(fd);
> +             }
> +     }
> +
> +error:
> +     closedir(dir);
> +     return -1;
> +}
> +
>  /**
>   * DPDK callback to register a PCI device.
>   *
> @@ -39,7 +232,12 @@ static struct rte_pci_id qdma_pci_id_tbl[] = {
>   */
>  static int qdma_eth_dev_init(struct rte_eth_dev *dev)
>  {
> +     struct qdma_pci_dev *dma_priv;
> +     uint8_t *baseaddr;
> +     int i, idx, ret;
>       struct rte_pci_device *pci_dev;
> +     uint16_t num_vfs;
> +     uint8_t max_pci_bus = 0;
>  
>       /* sanity checks */
>       if (dev == NULL)
> @@ -59,6 +257,88 @@ static int qdma_eth_dev_init(struct rte_eth_dev *dev)
>       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
>               return 0;
>  
> +     /* allocate space for a single Ethernet MAC address */
> +     dev->data->mac_addrs = rte_zmalloc("qdma", RTE_ETHER_ADDR_LEN * 1, 0);
> +     if (dev->data->mac_addrs == NULL)
> +             return -ENOMEM;
> +
> +     /* Copy some dummy Ethernet MAC address for QDMA device
> +      * This will change in real NIC device...
> +      * TODO: Read MAC from EEPROM
> +      */
> +     for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i)
> +             dev->data->mac_addrs[0].addr_bytes[i] = 0x15 + i;

If you don't have a real EEPROM to read, use rte_eth_random_addr() instead.

> +
> +     /* Init system & device */
> +     dma_priv = (struct qdma_pci_dev *)dev->data->dev_private;
> +     dma_priv->is_vf = 0;
> +     dma_priv->is_master = 0;
> +     dma_priv->vf_online_count = 0;
> +     dma_priv->timer_count = DEFAULT_TIMER_CNT_TRIG_MODE_TIMER;
> +
> +     dma_priv->en_desc_prefetch = 0; /* Keep prefetch default to 0 */
> +     dma_priv->cmpt_desc_len = 0;
> +     dma_priv->c2h_bypass_mode = 0;
> +     dma_priv->h2c_bypass_mode = 0;
> +
> +     dma_priv->config_bar_idx = DEFAULT_PF_CONFIG_BAR;
> +     dma_priv->bypass_bar_idx = BAR_ID_INVALID;
> +     dma_priv->user_bar_idx = BAR_ID_INVALID;
> +
> +     /* Check and handle device devargs */
> +     if (qdma_check_kvargs(dev->device->devargs, dma_priv)) {
> +             PMD_DRV_LOG(INFO, "devargs failed\n");
> +             rte_free(dev->data->mac_addrs);
> +             return -EINVAL;
> +     }
> +
> +     /* Store BAR address and length of Config BAR */
> +     baseaddr = (uint8_t *)
> +                     pci_dev->mem_resource[dma_priv->config_bar_idx].addr;
> +     dma_priv->bar_addr[dma_priv->config_bar_idx] = baseaddr;
> +
> +     idx = qdma_identify_bars(dev);
> +     if (idx < 0) {
> +             rte_free(dev->data->mac_addrs);
> +             return -EINVAL;
> +     }
> +
> +     /* Store BAR address and length of AXI Master Lite BAR(user bar) */
> +     if (dma_priv->user_bar_idx >= 0) {
> +             baseaddr = (uint8_t *)
> +                         pci_dev->mem_resource[dma_priv->user_bar_idx].addr;
> +             dma_priv->bar_addr[dma_priv->user_bar_idx] = baseaddr;
> +     }
> +
> +     PMD_DRV_LOG(INFO, "QDMA device driver probe:");
> +
> +     ret = get_max_pci_bus_num(pci_dev->addr.bus, &max_pci_bus);
> +     if (ret != 0 && !max_pci_bus) {
> +             PMD_DRV_LOG(ERR, "Failed to get max pci bus number\n");
> +             rte_free(dev->data->mac_addrs);
> +             return -EINVAL;
> +     }
> +     PMD_DRV_LOG(INFO, "PCI max bus number : 0x%x", max_pci_bus);
> +
> +     if (!dma_priv->reset_in_progress) {
> +             num_vfs = pci_dev->max_vfs;
> +             if (num_vfs) {
> +                     dma_priv->vfinfo = rte_zmalloc("vfinfo",
> +                             sizeof(struct qdma_vf_info) * num_vfs, 0);
> +                     if (dma_priv->vfinfo == NULL) {
> +                             PMD_DRV_LOG(ERR, "Cannot allocate memory for 
> private VF info\n");
> +                             return -ENOMEM;
> +                     }
> +
> +                     /* Mark all VFs with invalid function id mapping*/
> +                     for (i = 0; i < num_vfs; i++)
> +                             dma_priv->vfinfo[i].func_id =
> +                                     QDMA_FUNC_ID_INVALID;
> +             }
> +     }
> +
> +     dma_priv->reset_in_progress = 0;
> +
>       return 0;
>  }

Reply via email to