[RFC,3/5] pci/windows: split config I/O into series of fixed-size operations
Checks
Commit Message
PCI bus kernel driver mandates accessing config space in a series of
reads/writes by 4, 2, or 1 bytes. NETUIO driver checks this requirement
before performing config space I/O. Users of DPDK PCI bus driver,
however, access config space without regard for this requirement.
Make DPDK PCI bus driver split config I/O to a series of 4-, 2-,
or 1-byte reads/writes. Each of these operations is a syscall to netUIO.
Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
drivers/bus/pci/windows/pci.c | 45 ++++++++++++++++++++++++-----------
1 file changed, 31 insertions(+), 14 deletions(-)
@@ -200,6 +200,32 @@ int send_ioctl(HANDLE f, DWORD ioctl,
return ERROR_SUCCESS;
}
+static int
+pci_config_io_sized(HANDLE device, struct dpdk_pci_config_io *io,
+ void **buf, size_t *left_size, size_t access_size)
+{
+ uint64_t out;
+
+ io->access_size = access_size;
+
+ while (*left_size >= access_size) {
+ if (io->op == PCI_IO_WRITE)
+ memcpy(&io->data, *buf, access_size);
+
+ if (send_ioctl(device, IOCTL_NETUIO_PCI_CONFIG_IO,
+ io, sizeof(*io), &out, sizeof(out)) != ERROR_SUCCESS)
+ return -1;
+
+ if (io->op == PCI_IO_READ)
+ memcpy(*buf, &out, access_size);
+
+ io->offset += access_size;
+ *buf += access_size;
+ *left_size -= access_size;
+ }
+ return 0;
+}
+
/* Send IOCTL to driver to read/write PCI configuration space */
static
int pci_config_io(const struct rte_pci_device *dev, void *buf,
@@ -227,23 +253,14 @@ int pci_config_io(const struct rte_pci_device *dev, void *buf,
pci_io.dev_addr.dev_num = dev->addr.devid;
pci_io.dev_addr.func_num = dev->addr.function;
pci_io.offset = offset;
- pci_io.access_size = sizeof(UINT32);
pci_io.op = operation;
- if (operation == PCI_IO_WRITE)
- {
- pci_io.data.u32 = *(UINT32 UNALIGNED*)buf;
- }
-
- uint64_t outputbuf = 0;
- if (send_ioctl(f, IOCTL_NETUIO_PCI_CONFIG_IO, &pci_io, sizeof(pci_io),
- &outputbuf, sizeof(outputbuf)) != ERROR_SUCCESS)
+ if (pci_config_io_sized(f, &pci_io, &buf, &len, sizeof(uint32_t)) < 0)
+ goto error;
+ if (pci_config_io_sized(f, &pci_io, &buf, &len, sizeof(uint16_t)) < 0)
+ goto error;
+ if (pci_config_io_sized(f, &pci_io, &buf, &len, sizeof(uint8_t)) < 0)
goto error;
-
- if (operation == PCI_IO_READ)
- {
- memcpy(buf, &outputbuf, sizeof(UINT32));
- }
ret = 0;
error: