From: Phani R Burra <phani.r.burra@intel.com>
Add memory related support functions for drivers to access MMIO space and
allocate/free dma buffers.
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Phani R Burra <phani.r.burra@intel.com>
Co-developed-by: Victor Raj <victor.raj@intel.com>
Signed-off-by: Victor Raj <victor.raj@intel.com>
Co-developed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Co-developed-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
Co-developed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
---
drivers/net/ethernet/intel/libie/Kconfig | 6 +
drivers/net/ethernet/intel/libie/Makefile | 4 +
drivers/net/ethernet/intel/libie/pci.c | 184 ++++++++++++++++++++++
include/linux/intel/libie/pci.h | 54 +++++++
4 files changed, 248 insertions(+)
create mode 100644 drivers/net/ethernet/intel/libie/pci.c
create mode 100644 include/linux/intel/libie/pci.h
diff --git a/drivers/net/ethernet/intel/libie/Kconfig b/drivers/net/ethernet/intel/libie/Kconfig
index 33aff6bc8f81..20fa45feb946 100644
--- a/drivers/net/ethernet/intel/libie/Kconfig
+++ b/drivers/net/ethernet/intel/libie/Kconfig
@@ -8,3 +8,9 @@ config LIBIE
libie (Intel Ethernet library) is a common library built on top of
libeth and containing vendor-specific routines shared between several
Intel Ethernet drivers.
+
+config LIBIE_PCI
+ tristate
+ help
+ Helper functions for management of PCI resources belonging
+ to networking devices.
diff --git a/drivers/net/ethernet/intel/libie/Makefile b/drivers/net/ethernet/intel/libie/Makefile
index ffd27fab916a..c20aeea1f67c 100644
--- a/drivers/net/ethernet/intel/libie/Makefile
+++ b/drivers/net/ethernet/intel/libie/Makefile
@@ -4,3 +4,7 @@
obj-$(CONFIG_LIBIE) += libie.o
libie-y := rx.o
+
+obj-$(CONFIG_LIBIE_PCI) += libie_pci.o
+
+libie_pci-y := pci.o
diff --git a/drivers/net/ethernet/intel/libie/pci.c b/drivers/net/ethernet/intel/libie/pci.c
new file mode 100644
index 000000000000..727ce7b200a5
--- /dev/null
+++ b/drivers/net/ethernet/intel/libie/pci.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2025 Intel Corporation */
+
+#include <linux/intel/libie/pci.h>
+
+/**
+ * libie_find_mmio_region - find if MMIO region is present in the list
+ * @mmio_list: list that contains MMIO region info
+ * @offset: MMIO region start offset
+ * @bar_idx: BAR index where the offset to search
+ *
+ * Return: MMIO region pointer or NULL if the region info is not present.
+ */
+static struct libie_pci_mmio_region *
+libie_find_mmio_region(const struct list_head *mmio_list,
+ resource_size_t offset, int bar_idx)
+{
+ struct libie_pci_mmio_region *mr;
+
+ list_for_each_entry(mr, mmio_list, list)
+ if (mr->bar_idx == bar_idx && mr->offset == offset)
+ return mr;
+
+ return NULL;
+}
+
+/**
+ * __libie_pci_get_mmio_addr - get the MMIO virtual address
+ * @mmio_info: contains list of MMIO regions
+ * @offset: register offset of find
+ * @num_args: number of additional arguments present
+ *
+ * This function finds the virtual address of a register offset by iterating
+ * through the non-linear MMIO regions that are mapped by the driver.
+ *
+ * Return: valid MMIO virtual address or NULL.
+ */
+void __iomem *__libie_pci_get_mmio_addr(struct libie_mmio_info *mmio_info,
+ resource_size_t offset,
+ int num_args, ...)
+{
+ struct libie_pci_mmio_region *mr;
+ int bar_idx = 0;
+ va_list args;
+
+ if (num_args) {
+ va_start(args, num_args);
+ bar_idx = va_arg(args, int);
+ va_end(args);
+ }
+
+ list_for_each_entry(mr, &mmio_info->mmio_list, list)
+ if (bar_idx == mr->bar_idx && offset >= mr->offset &&
+ offset < mr->offset + mr->size) {
+ offset -= mr->offset;
+
+ return mr->addr + offset;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_NS_GPL(__libie_pci_get_mmio_addr, "LIBIE_PCI");
+
+/**
+ * __libie_pci_map_mmio_region - map PCI device MMIO region
+ * @mmio_info: struct to store the mapped MMIO region
+ * @offset: MMIO region start offset
+ * @size: MMIO region size
+ * @num_args: number of additional arguments present
+ *
+ * Return: true on success, false on memory map failure.
+ */
+bool __libie_pci_map_mmio_region(struct libie_mmio_info *mmio_info,
+ resource_size_t offset,
+ resource_size_t size, int num_args, ...)
+{
+ struct pci_dev *pdev = mmio_info->pdev;
+ struct libie_pci_mmio_region *mr;
+ resource_size_t pa;
+ void __iomem *va;
+ int bar_idx = 0;
+ va_list args;
+
+ if (num_args) {
+ va_start(args, num_args);
+ bar_idx = va_arg(args, int);
+ va_end(args);
+ }
+
+ mr = libie_find_mmio_region(&mmio_info->mmio_list, offset, bar_idx);
+ if (mr) {
+ pci_warn(pdev, "Mapping of BAR%u with offset %llu already exists\n",
+ bar_idx, (unsigned long long)offset);
+ return true;
+ }
+
+ pa = pci_resource_start(pdev, bar_idx) + offset;
+ va = ioremap(pa, size);
+ if (!va) {
+ pci_err(pdev, "Failed to allocate BAR%u region\n", bar_idx);
+ return false;
+ }
+
+ mr = kvzalloc(sizeof(*mr), GFP_KERNEL);
+ if (!mr) {
+ iounmap(va);
+ return false;
+ }
+
+ mr->addr = va;
+ mr->offset = offset;
+ mr->size = size;
+ mr->bar_idx = bar_idx;
+
+ list_add_tail(&mr->list, &mmio_info->mmio_list);
+
+ return true;
+}
+EXPORT_SYMBOL_NS_GPL(__libie_pci_map_mmio_region, "LIBIE_PCI");
+
+/**
+ * libie_pci_unmap_all_mmio_regions - unmap all PCI device MMIO regions
+ * @mmio_info: contains list of MMIO regions to unmap
+ */
+void libie_pci_unmap_all_mmio_regions(struct libie_mmio_info *mmio_info)
+{
+ struct libie_pci_mmio_region *mr, *tmp;
+
+ list_for_each_entry_safe(mr, tmp, &mmio_info->mmio_list, list) {
+ iounmap(mr->addr);
+ list_del(&mr->list);
+ kfree(mr);
+ }
+}
+EXPORT_SYMBOL_NS_GPL(libie_pci_unmap_all_mmio_regions, "LIBIE_PCI");
+
+/**
+ * libie_pci_init_dev - enable and reserve PCI regions of the device
+ * @pdev: PCI device information
+ *
+ * Return: %0 on success, -%errno on failure.
+ */
+int libie_pci_init_dev(struct pci_dev *pdev)
+{
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ err = pci_request_mem_regions(pdev, pci_name(pdev));
+ if (err)
+ goto disable_dev;
+
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (err)
+ goto rel_regions;
+
+ pci_set_master(pdev);
+
+ return 0;
+
+rel_regions:
+ pci_release_regions(pdev);
+disable_dev:
+ pci_disable_device(pdev);
+
+ return err;
+}
+EXPORT_SYMBOL_NS_GPL(libie_pci_init_dev, "LIBIE_PCI");
+
+/**
+ * libie_pci_deinit_dev - disable and release the PCI regions of the device
+ * @pdev: PCI device information
+ */
+void libie_pci_deinit_dev(struct pci_dev *pdev)
+{
+ pci_disable_device(pdev);
+ pci_release_regions(pdev);
+}
+EXPORT_SYMBOL_NS_GPL(libie_pci_deinit_dev, "LIBIE_PCI");
+
+MODULE_DESCRIPTION("Common Ethernet PCI library");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/intel/libie/pci.h b/include/linux/intel/libie/pci.h
new file mode 100644
index 000000000000..4601205adc22
--- /dev/null
+++ b/include/linux/intel/libie/pci.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (C) 2025 Intel Corporation */
+
+#ifndef __LIBIE_PCI_H
+#define __LIBIE_PCI_H
+
+#include <linux/pci.h>
+
+/**
+ * struct libie_pci_mmio_region - structure for MMIO region info
+ * @list: used to add a MMIO region to the list of MMIO regions in
+ * libie_mmio_info
+ * @addr: virtual address of MMIO region start
+ * @offset: start offset of the MMIO region
+ * @size: size of the MMIO region
+ * @bar_idx: BAR index to which the MMIO region belongs to
+ */
+struct libie_pci_mmio_region {
+ struct list_head list;
+ void __iomem *addr;
+ resource_size_t offset;
+ resource_size_t size;
+ u16 bar_idx;
+};
+
+/**
+ * struct libie_mmio_info - contains list of MMIO regions
+ * @pdev: PCI device pointer
+ * @mmio_list: list of MMIO regions
+ */
+struct libie_mmio_info {
+ struct pci_dev *pdev;
+ struct list_head mmio_list;
+};
+
+#define libie_pci_map_mmio_region(mmio_info, offset, size, ...) \
+ __libie_pci_map_mmio_region(mmio_info, offset, size, \
+ COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)
+
+#define libie_pci_get_mmio_addr(mmio_info, offset, ...) \
+ __libie_pci_get_mmio_addr(mmio_info, offset, \
+ COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)
+
+bool __libie_pci_map_mmio_region(struct libie_mmio_info *mmio_info,
+ resource_size_t offset, resource_size_t size,
+ int num_args, ...);
+void __iomem *__libie_pci_get_mmio_addr(struct libie_mmio_info *mmio_info,
+ resource_size_t region_offset,
+ int num_args, ...);
+void libie_pci_unmap_all_mmio_regions(struct libie_mmio_info *mmio_info);
+int libie_pci_init_dev(struct pci_dev *pdev);
+void libie_pci_deinit_dev(struct pci_dev *pdev);
+
+#endif /* __LIBIE_PCI_H */
--
2.47.0
On Thu, Apr 24, 2025 at 01:32:26PM +0200, Larysa Zaremba wrote: > From: Phani R Burra <phani.r.burra@intel.com> > > Add memory related support functions for drivers to access MMIO space and > allocate/free dma buffers. > > Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> > Signed-off-by: Phani R Burra <phani.r.burra@intel.com> > Co-developed-by: Victor Raj <victor.raj@intel.com> > Signed-off-by: Victor Raj <victor.raj@intel.com> > Co-developed-by: Sridhar Samudrala <sridhar.samudrala@intel.com> > Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com> > Co-developed-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com> > Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com> > Co-developed-by: Larysa Zaremba <larysa.zaremba@intel.com> > Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com> ... > diff --git a/include/linux/intel/libie/pci.h b/include/linux/intel/libie/pci.h ... > +#define libie_pci_map_mmio_region(mmio_info, offset, size, ...) \ > + __libie_pci_map_mmio_region(mmio_info, offset, size, \ > + COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__) > + > +#define libie_pci_get_mmio_addr(mmio_info, offset, ...) \ > + __libie_pci_get_mmio_addr(mmio_info, offset, \ > + COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__) Perhaps I'm missing something terribly obvious. But it seems to me that both libie_pci_map_mmio_region() and libie_pci_get_mmio_addr() are always called with the same number of arguments in this patchset. And if so, perhaps the va_args handling would be best dropped. > + > +bool __libie_pci_map_mmio_region(struct libie_mmio_info *mmio_info, > + resource_size_t offset, resource_size_t size, > + int num_args, ...); > +void __iomem *__libie_pci_get_mmio_addr(struct libie_mmio_info *mmio_info, > + resource_size_t region_offset, > + int num_args, ...); > +void libie_pci_unmap_all_mmio_regions(struct libie_mmio_info *mmio_info); > +int libie_pci_init_dev(struct pci_dev *pdev); > +void libie_pci_deinit_dev(struct pci_dev *pdev); > + > +#endif /* __LIBIE_PCI_H */ > -- > 2.47.0 >
On Mon, Apr 28, 2025 at 05:56:57PM +0100, Simon Horman wrote: > On Thu, Apr 24, 2025 at 01:32:26PM +0200, Larysa Zaremba wrote: > > From: Phani R Burra <phani.r.burra@intel.com> > > > > Add memory related support functions for drivers to access MMIO space and > > allocate/free dma buffers. > > > > Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> > > Signed-off-by: Phani R Burra <phani.r.burra@intel.com> > > Co-developed-by: Victor Raj <victor.raj@intel.com> > > Signed-off-by: Victor Raj <victor.raj@intel.com> > > Co-developed-by: Sridhar Samudrala <sridhar.samudrala@intel.com> > > Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com> > > Co-developed-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com> > > Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com> > > Co-developed-by: Larysa Zaremba <larysa.zaremba@intel.com> > > Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com> > > ... > > > diff --git a/include/linux/intel/libie/pci.h b/include/linux/intel/libie/pci.h > > ... > > > +#define libie_pci_map_mmio_region(mmio_info, offset, size, ...) \ > > + __libie_pci_map_mmio_region(mmio_info, offset, size, \ > > + COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__) > > + > > +#define libie_pci_get_mmio_addr(mmio_info, offset, ...) \ > > + __libie_pci_get_mmio_addr(mmio_info, offset, \ > > + COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__) > > Perhaps I'm missing something terribly obvious. But it seems to me that > both libie_pci_map_mmio_region() and libie_pci_get_mmio_addr() are always > called with the same number of arguments in this patchset. This is true. > And if so, > perhaps the va_args handling would be best dropped. > For now (but this will change), we do not map BAR indexes other than zero, therefore it is the default less-argument variant, this looks nicer than adding ', 0);'. Still, it does not feel right to hardcode the library function to use BAR0 only, hence the variadic macro. > > + > > +bool __libie_pci_map_mmio_region(struct libie_mmio_info *mmio_info, > > + resource_size_t offset, resource_size_t size, > > + int num_args, ...); > > +void __iomem *__libie_pci_get_mmio_addr(struct libie_mmio_info *mmio_info, > > + resource_size_t region_offset, > > + int num_args, ...); > > +void libie_pci_unmap_all_mmio_regions(struct libie_mmio_info *mmio_info); > > +int libie_pci_init_dev(struct pci_dev *pdev); > > +void libie_pci_deinit_dev(struct pci_dev *pdev); > > + > > +#endif /* __LIBIE_PCI_H */ > > -- > > 2.47.0 > > >
On Mon, May 05, 2025 at 08:56:18AM +0200, Larysa Zaremba wrote: > On Mon, Apr 28, 2025 at 05:56:57PM +0100, Simon Horman wrote: > > On Thu, Apr 24, 2025 at 01:32:26PM +0200, Larysa Zaremba wrote: > > > From: Phani R Burra <phani.r.burra@intel.com> > > > > > > Add memory related support functions for drivers to access MMIO space and > > > allocate/free dma buffers. > > > > > > Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> > > > Signed-off-by: Phani R Burra <phani.r.burra@intel.com> > > > Co-developed-by: Victor Raj <victor.raj@intel.com> > > > Signed-off-by: Victor Raj <victor.raj@intel.com> > > > Co-developed-by: Sridhar Samudrala <sridhar.samudrala@intel.com> > > > Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com> > > > Co-developed-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com> > > > Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com> > > > Co-developed-by: Larysa Zaremba <larysa.zaremba@intel.com> > > > Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com> > > > > ... > > > > > diff --git a/include/linux/intel/libie/pci.h b/include/linux/intel/libie/pci.h > > > > ... > > > > > +#define libie_pci_map_mmio_region(mmio_info, offset, size, ...) \ > > > + __libie_pci_map_mmio_region(mmio_info, offset, size, \ > > > + COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__) > > > + > > > +#define libie_pci_get_mmio_addr(mmio_info, offset, ...) \ > > > + __libie_pci_get_mmio_addr(mmio_info, offset, \ > > > + COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__) > > > > Perhaps I'm missing something terribly obvious. But it seems to me that > > both libie_pci_map_mmio_region() and libie_pci_get_mmio_addr() are always > > called with the same number of arguments in this patchset. > > This is true. > > > And if so, > > perhaps the va_args handling would be best dropped. > > > > For now (but this will change), we do not map BAR indexes other than zero, > therefore it is the default less-argument variant, this looks nicer than adding > ', 0);'. Still, it does not feel right to hardcode the library function to use > BAR0 only, hence the variadic macro. Thanks for the clarification. I would slightly lead towards adding va_args support when it is needed. But I understand if you want to stick with the approach that you have taken in this patch. > > > > + > > > +bool __libie_pci_map_mmio_region(struct libie_mmio_info *mmio_info, > > > + resource_size_t offset, resource_size_t size, > > > + int num_args, ...); > > > +void __iomem *__libie_pci_get_mmio_addr(struct libie_mmio_info *mmio_info, > > > + resource_size_t region_offset, > > > + int num_args, ...); > > > +void libie_pci_unmap_all_mmio_regions(struct libie_mmio_info *mmio_info); > > > +int libie_pci_init_dev(struct pci_dev *pdev); > > > +void libie_pci_deinit_dev(struct pci_dev *pdev); > > > + > > > +#endif /* __LIBIE_PCI_H */ > > > -- > > > 2.47.0 > > > > > >
© 2016 - 2026 Red Hat, Inc.