pci: consolidate address comparisons

This patch replaces pci_addr_comparison() and memcmp() of pci addresses by
rte_eal_compare_pci_addr().

To compare PCI addresses, rte_eal_compare_pci_addr() doesn't use memcmp().
This is because sizeof(struct rte_pci_addr) returns 6, but actually
this structure is like below.

struct rte_pci_addr {
        uint16_t domain;                /**< Device domain */
        uint8_t bus;                    /**< Device bus */
        uint8_t devid;                  /**< Device ID */
        uint8_t function;               /**< Device function. */
};

If the structure is dynamically allocated in a function without bzero,
last 1 byte may have value. As a result, memcmp may not work.
To avoid such a case, rte_eal_compare_pci_addr() compare following values.

        dev_addr = (addr->domain << 24) | (addr->bus << 16) |
                                (addr->devid << 8) | addr->function;

Signed-off-by: Tetsuya Mukawa <mukawa@igel.co.jp>
This commit is contained in:
Tetsuya Mukawa 2015-02-26 04:32:19 +09:00 committed by Thomas Monjalon
parent cc4fe5c45d
commit c0ce0577e8
5 changed files with 63 additions and 34 deletions

View File

@ -270,20 +270,6 @@ pci_uio_map_resource(struct rte_pci_device *dev)
return (0);
}
/* Compare two PCI device addresses. */
static int
pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2)
{
uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function;
uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function;
if (dev_addr > dev_addr2)
return 1;
else
return 0;
}
/* Scan one pci sysfs entry, and fill the devices list from it. */
static int
pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
@ -356,13 +342,24 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
}
else {
struct rte_pci_device *dev2 = NULL;
int ret;
TAILQ_FOREACH(dev2, &pci_device_list, next) {
if (pci_addr_comparison(&dev->addr, &dev2->addr))
ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
if (ret > 0)
continue;
else {
else if (ret < 0) {
TAILQ_INSERT_BEFORE(dev2, dev, next);
return 0;
} else { /* already registered */
/* update pt_driver */
dev2->pt_driver = dev->pt_driver;
dev2->max_vfs = dev->max_vfs;
memmove(dev2->mem_resource,
dev->mem_resource,
sizeof(dev->mem_resource));
free(dev);
return 0;
}
}
TAILQ_INSERT_TAIL(&pci_device_list, dev, next);

View File

@ -93,7 +93,7 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)
if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI &&
devargs->type != RTE_DEVTYPE_WHITELISTED_PCI)
continue;
if (!memcmp(&dev->addr, &devargs->pci.addr, sizeof(dev->addr)))
if (!rte_eal_compare_pci_addr(&dev->addr, &devargs->pci.addr))
return devargs;
}
return NULL;

View File

@ -270,6 +270,40 @@ eal_parse_pci_DomBDF(const char *input, struct rte_pci_addr *dev_addr)
}
#undef GET_PCIADDR_FIELD
/* Compare two PCI device addresses. */
/**
* Utility function to compare two PCI device addresses.
*
* @param addr
* The PCI Bus-Device-Function address to compare
* @param addr2
* The PCI Bus-Device-Function address to compare
* @return
* 0 on equal PCI address.
* Positive on addr is greater than addr2.
* Negative on addr is less than addr2, or error.
*/
static inline int
rte_eal_compare_pci_addr(struct rte_pci_addr *addr, struct rte_pci_addr *addr2)
{
uint64_t dev_addr, dev_addr2;
if ((addr == NULL) || (addr2 == NULL))
return -1;
dev_addr = (addr->domain << 24) | (addr->bus << 16) |
(addr->devid << 8) | addr->function;
dev_addr2 = (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;
}
/**
* Probe the PCI bus for registered drivers.
*

View File

@ -41,6 +41,7 @@
#include <rte_eal_memconfig.h>
#include <rte_malloc.h>
#include <rte_devargs.h>
#include <rte_memcpy.h>
#include "rte_pci_dev_ids.h"
#include "eal_filesystem.h"
@ -228,20 +229,6 @@ error:
return -1;
}
/* Compare two PCI device addresses. */
static int
pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2)
{
uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function;
uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function;
if (dev_addr > dev_addr2)
return 1;
else
return 0;
}
/* Scan one pci sysfs entry, and fill the devices list from it. */
static int
pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
@ -359,13 +346,24 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
}
else {
struct rte_pci_device *dev2 = NULL;
int ret;
TAILQ_FOREACH(dev2, &pci_device_list, next) {
if (pci_addr_comparison(&dev->addr, &dev2->addr))
ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
if (ret > 0)
continue;
else {
else if (ret < 0) {
TAILQ_INSERT_BEFORE(dev2, dev, next);
return 0;
} else { /* already registered */
/* update pt_driver */
dev2->pt_driver = dev->pt_driver;
dev2->max_vfs = dev->max_vfs;
memmove(dev2->mem_resource,
dev->mem_resource,
sizeof(dev->mem_resource));
free(dev);
return 0;
}
}
TAILQ_INSERT_TAIL(&pci_device_list, dev, next);

View File

@ -91,7 +91,7 @@ pci_uio_map_secondary(struct rte_pci_device *dev)
TAILQ_FOREACH(uio_res, pci_res_list, next) {
/* skip this element if it doesn't match our PCI address */
if (memcmp(&uio_res->pci_addr, &dev->addr, sizeof(dev->addr)))
if (rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr))
continue;
for (i = 0; i != uio_res->nb_maps; i++) {