numam-dpdk/lib/librte_pci/rte_pci.c
David Marchand e1ece60956 pci: move resource mapping to the PCI bus
As reported during 20.08 work for Windows, the pci_map_resource API was
built with the assumption that its flags would be passed to mmap().

This introduced a regression when adding the rte_mem_map API as reported
in the workaround commit 9d2b245937 ("pci: keep API compatibility with
mmap values").

This API was only used in the PCI bus code, so move it there.

There is no code change happening during the move.
The only change is in the pci_map_resource description where the
additional flags are now documented as rte_mem_map API flags:
- *      The additional flags for the mapping range.
+ *      The additional rte_mem_map() flags for the mapping range.

Signed-off-by: David Marchand <david.marchand@redhat.com>
Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
2020-09-21 10:12:10 +02:00

147 lines
3.3 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation.
* Copyright 2013-2014 6WIND S.A.
*/
#include <string.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/queue.h>
#include <rte_errno.h>
#include <rte_interrupts.h>
#include <rte_log.h>
#include <rte_bus.h>
#include <rte_eal_paging.h>
#include <rte_per_lcore.h>
#include <rte_memory.h>
#include <rte_eal.h>
#include <rte_string_fns.h>
#include <rte_common.h>
#include <rte_debug.h>
#include "rte_pci.h"
static inline const char *
get_u8_pciaddr_field(const char *in, void *_u8, char dlm)
{
unsigned long val;
uint8_t *u8 = _u8;
char *end;
/* empty string is an error though strtoul() returns 0 */
if (*in == '\0')
return NULL;
/* PCI field starting with spaces is forbidden.
* Negative wrap-around is not reported as an error by strtoul.
*/
if (*in == ' ' || *in == '-')
return NULL;
errno = 0;
val = strtoul(in, &end, 16);
if (errno != 0 || end[0] != dlm || val > UINT8_MAX) {
errno = errno ? errno : EINVAL;
return NULL;
}
*u8 = (uint8_t)val;
return end + 1;
}
static int
pci_bdf_parse(const char *input, struct rte_pci_addr *dev_addr)
{
const char *in = input;
dev_addr->domain = 0;
in = get_u8_pciaddr_field(in, &dev_addr->bus, ':');
if (in == NULL)
return -EINVAL;
in = get_u8_pciaddr_field(in, &dev_addr->devid, '.');
if (in == NULL)
return -EINVAL;
in = get_u8_pciaddr_field(in, &dev_addr->function, '\0');
if (in == NULL)
return -EINVAL;
return 0;
}
static int
pci_dbdf_parse(const char *input, struct rte_pci_addr *dev_addr)
{
const char *in = input;
unsigned long val;
char *end;
/* PCI id starting with spaces is forbidden.
* Negative wrap-around is not reported as an error by strtoul.
*/
if (*in == ' ' || *in == '-')
return -EINVAL;
errno = 0;
val = strtoul(in, &end, 16);
/* Empty string is not an error for strtoul, but the check
* end[0] != ':'
* will detect the issue.
*/
if (errno != 0 || end[0] != ':' || val > UINT32_MAX)
return -EINVAL;
dev_addr->domain = (uint32_t)val;
in = end + 1;
in = get_u8_pciaddr_field(in, &dev_addr->bus, ':');
if (in == NULL)
return -EINVAL;
in = get_u8_pciaddr_field(in, &dev_addr->devid, '.');
if (in == NULL)
return -EINVAL;
in = get_u8_pciaddr_field(in, &dev_addr->function, '\0');
if (in == NULL)
return -EINVAL;
return 0;
}
void
rte_pci_device_name(const struct rte_pci_addr *addr,
char *output, size_t size)
{
RTE_VERIFY(size >= PCI_PRI_STR_SIZE);
RTE_VERIFY(snprintf(output, size, PCI_PRI_FMT,
addr->domain, addr->bus,
addr->devid, addr->function) >= 0);
}
int
rte_pci_addr_cmp(const struct rte_pci_addr *addr,
const struct rte_pci_addr *addr2)
{
uint64_t dev_addr, dev_addr2;
if ((addr == NULL) || (addr2 == NULL))
return -1;
dev_addr = ((uint64_t)addr->domain << 24) |
(addr->bus << 16) | (addr->devid << 8) | addr->function;
dev_addr2 = ((uint64_t)addr2->domain << 24) |
(addr2->bus << 16) | (addr2->devid << 8) | addr2->function;
if (dev_addr > dev_addr2)
return 1;
else if (dev_addr < dev_addr2)
return -1;
else
return 0;
}
int
rte_pci_addr_parse(const char *str, struct rte_pci_addr *addr)
{
if (pci_bdf_parse(str, addr) == 0 ||
pci_dbdf_parse(str, addr) == 0)
return 0;
return -1;
}