@@ -55,6 +55,12 @@ New Features
Also, make sure to start the actual text at the margin.
=======================================================
+* **Added new memory resource read/write APIs in PCI bus.**
+
+ Added new memory resource read/write APIs ``rte_pci_mem_rd32`` and
+ ``rte_pci_mem_wr32`` for applications to read/write PCI memory
+ resource.
+
* **Enabled new devargs parser.**
* Enabled devargs syntax
@@ -25,6 +25,7 @@
#include <rte_common.h>
#include <rte_devargs.h>
#include <rte_vfio.h>
+#include <rte_io.h>
#include "private.h"
@@ -777,6 +778,83 @@ rte_pci_set_bus_master(struct rte_pci_device *dev, bool enable)
return 0;
}
+static void *
+get_pci_mem_addr(const char *name, uint16_t idx, uint64_t offset)
+{
+ struct rte_pci_device *dev = NULL;
+ struct rte_pci_addr addr = {0};
+ struct rte_mem_resource *res = NULL;
+ bool found = false;
+
+ if (rte_pci_addr_parse(name, &addr)) {
+ RTE_LOG(ERR, EAL, "Wrong name format of PCI device (%s)", name);
+ return NULL;
+ }
+
+ FOREACH_DEVICE_ON_PCIBUS(dev) {
+ if (rte_pci_addr_cmp(&dev->addr, &addr)) {
+ continue;
+ } else {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ RTE_LOG(ERR, EAL, "Can not find the device (%s)", name);
+ return NULL;
+ }
+
+ res = &dev->mem_resource[idx];
+ if (idx >= PCI_MAX_RESOURCE || res->len == 0 || res->addr == NULL) {
+ RTE_LOG(ERR, EAL, "Invalid index of a mapped memory resourse");
+ return NULL;
+ }
+
+ if (offset + 4 > res->len) {
+ RTE_LOG(ERR, EAL, "Invalid offset of a memory resourse");
+ return NULL;
+ }
+
+ return (void *)((char *)res->addr + offset);
+}
+
+int
+rte_pci_mem_rd32(const char *name, uint16_t idx, uint32_t *data, uint64_t offset)
+{
+ void *reg_addr = NULL;
+
+ if (data == NULL) {
+ RTE_LOG(ERR, EAL, "NULL data buffer for PCI memory access");
+ return -EINVAL;
+ }
+
+ reg_addr = get_pci_mem_addr(name, idx, offset);
+ if (reg_addr == NULL)
+ return -EINVAL;
+
+ *data = rte_read32(reg_addr);
+ return 0;
+}
+
+int
+rte_pci_mem_wr32(const char *name, uint16_t idx, const uint32_t *data, uint64_t offset)
+{
+ void *reg_addr = NULL;
+
+ if (data == NULL) {
+ RTE_LOG(ERR, EAL, "NULL data buffer for PCI memory access");
+ return -EINVAL;
+ }
+
+ reg_addr = get_pci_mem_addr(name, idx, offset);
+ if (reg_addr == NULL)
+ return -EINVAL;
+
+ rte_write32(*data, reg_addr);
+ return 0;
+}
+
struct rte_pci_bus rte_pci_bus = {
.bus = {
.scan = rte_pci_scan,
@@ -392,6 +392,42 @@ void rte_pci_ioport_read(struct rte_pci_ioport *p,
void rte_pci_ioport_write(struct rte_pci_ioport *p,
const void *data, size_t len, off_t offset);
+/**
+ * Read 4 bytes from PCI memory resource.
+ *
+ * @param name
+ * PCI device name (e.g., 0000:18:00.0).
+ * @param idx
+ * Memory resource index.
+ * @param data
+ * Data buffer where the bytes should be read into.
+ * @param offset
+ * The offset into the PCI memory resource.
+ * @return
+ * 0 on success, negative value on error.
+ */
+__rte_experimental
+int
+rte_pci_mem_rd32(const char *name, uint16_t idx, uint32_t *data, uint64_t offset);
+
+/**
+ * Write 4 bytes to PCI memory resource.
+ *
+ * @param name
+ * PCI device name (e.g., 0000:18:00.0).
+ * @param idx
+ * Memory resource index.
+ * @param data
+ * Buffer of data that should be written to PCI memory.
+ * @param offset
+ * The offset into the PCI memory resource.
+ * @return
+ * 0 on success, negative value on error.
+ */
+__rte_experimental
+int
+rte_pci_mem_wr32(const char *name, uint16_t idx, const uint32_t *data, uint64_t offset);
+
#ifdef __cplusplus
}
#endif
@@ -24,4 +24,8 @@ EXPERIMENTAL {
# added in 21.08
rte_pci_set_bus_master;
+
+ # added in 21.11
+ rte_pci_mem_rd32;
+ rte_pci_mem_wr32;
};