eal/bsd: fix read on PCI configuration space
authorTiwei Bie <tiwei.bie@intel.com>
Sun, 7 May 2017 13:33:34 +0000 (13:33 +0000)
committerThomas Monjalon <thomas@monjalon.net>
Wed, 10 May 2017 13:57:49 +0000 (15:57 +0200)
Some drivers (such as virtio) may need to read more than 4 bytes
data from PCI configuration space via rte_eal_pci_read_config().
But it will return with an error on FreeBSD when the expected
data length is bigger than the size of pi.pi_data whose type is
u_int32_t. This patch removes this limitation.

Fixes: 632b2d1deeed ("eal: provide functions to access PCI config")
Cc: stable@dpdk.org
Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
lib/librte_eal/bsdapp/eal/eal_pci.c

index 59ceb76..e321461 100644 (file)
@@ -459,6 +459,7 @@ int rte_pci_read_config(const struct rte_pci_device *dev,
                void *buf, size_t len, off_t offset)
 {
        int fd = -1;
+       int size;
        struct pci_io pi = {
                .pi_sel = {
                        .pc_domain = dev->addr.domain,
@@ -467,25 +468,28 @@ int rte_pci_read_config(const struct rte_pci_device *dev,
                        .pc_func = dev->addr.function,
                },
                .pi_reg = offset,
-               .pi_width = len,
        };
 
-       if (len == 3 || len > sizeof(pi.pi_data)) {
-               RTE_LOG(ERR, EAL, "%s(): invalid pci read length\n", __func__);
-               goto error;
-       }
-
        fd = open("/dev/pci", O_RDWR);
        if (fd < 0) {
                RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
                goto error;
        }
 
-       if (ioctl(fd, PCIOCREAD, &pi) < 0)
-               goto error;
+       while (len > 0) {
+               size = (len >= 4) ? 4 : ((len >= 2) ? 2 : 1);
+               pi.pi_width = size;
+
+               if (ioctl(fd, PCIOCREAD, &pi) < 0)
+                       goto error;
+               memcpy(buf, &pi.pi_data, size);
+
+               buf = (char *)buf + size;
+               pi.pi_reg += size;
+               len -= size;
+       }
        close(fd);
 
-       memcpy(buf, &pi.pi_data, len);
        return 0;
 
  error: