Some endpoint platforms have only a small number of usable BARs. At the
same time, EPF drivers (e.g. vNTB) may need multiple independent inbound
regions (control/scratchpad, one or more memory windows, and optionally
MSI or other feature-related regions). Subrange mapping allows these to
share a single BAR without consuming additional BARs that may not be
available, or forcing a fragile layout by aggressively packing into a
single contiguous memory range.
Extend the PCI endpoint core to support mapping subranges within a BAR.
Add an optional 'submap' field in struct pci_epf_bar so an endpoint
function driver can request inbound mappings that fully cover the BAR.
Introduce a new EPC feature bit, subrange_mapping, and reject submap
requests from pci_epc_set_bar() unless the controller advertises both
subrange_mapping and dynamic_inbound_mapping features.
The submap array describes the complete BAR layout (no overlaps and no
gaps are allowed to avoid exposing untranslated address ranges). This
provides the generic infrastructure needed to map multiple logical
regions into a single BAR at different offsets, without assuming a
controller-specific inbound address translation mechanism.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Link: https://patch.msgid.link/20260124145012.2794108-3-den@valinux.co.jp
if (!epc_features)
return -EINVAL;
+ if (epf_bar->num_submap && !epf_bar->submap)
+ return -EINVAL;
+
+ if (epf_bar->num_submap &&
+ !(epc_features->dynamic_inbound_mapping &&
+ epc_features->subrange_mapping))
+ return -EINVAL;
+
if (epc_features->bar[bar].type == BAR_RESIZABLE &&
(epf_bar->size < SZ_1M || (u64)epf_bar->size > (SZ_128G * 1024)))
return -EINVAL;
* inbound mappings for an already configured BAR
* (i.e. allow calling pci_epc_set_bar() again
* without first calling pci_epc_clear_bar())
+ * @subrange_mapping: indicate if the EPC device can map inbound subranges for a
+ * BAR. This feature depends on @dynamic_inbound_mapping
+ * feature.
* @msi_capable: indicate if the endpoint function has MSI capability
* @msix_capable: indicate if the endpoint function has MSI-X capability
* @intx_capable: indicate if the endpoint can raise INTx interrupts
struct pci_epc_features {
unsigned int linkup_notifier : 1;
unsigned int dynamic_inbound_mapping : 1;
+ unsigned int subrange_mapping : 1;
unsigned int msi_capable : 1;
unsigned int msix_capable : 1;
unsigned int intx_capable : 1;
#define to_pci_epf_driver(drv) container_of_const((drv), struct pci_epf_driver, driver)
+/**
+ * struct pci_epf_bar_submap - BAR subrange for inbound mapping
+ * @phys_addr: target physical/DMA address for this subrange
+ * @size: the size of the subrange to be mapped
+ *
+ * When pci_epf_bar.num_submap is >0, pci_epf_bar.submap describes the
+ * complete BAR layout. This allows an EPC driver to program multiple
+ * inbound translation windows for a single BAR when supported by the
+ * controller. The array order defines the BAR layout (submap[0] at offset
+ * 0, and each immediately follows the previous one).
+ */
+struct pci_epf_bar_submap {
+ dma_addr_t phys_addr;
+ size_t size;
+};
+
/**
* struct pci_epf_bar - represents the BAR of EPF device
* @phys_addr: physical address that should be mapped to the BAR
* requirement
* @barno: BAR number
* @flags: flags that are set for the BAR
+ * @num_submap: number of entries in @submap
+ * @submap: array of subrange descriptors allocated by the caller. See
+ * struct pci_epf_bar_submap for the semantics in detail.
*/
struct pci_epf_bar {
dma_addr_t phys_addr;
size_t mem_size;
enum pci_barno barno;
int flags;
+
+ /* Optional sub-range mapping */
+ unsigned int num_submap;
+ struct pci_epf_bar_submap *submap;
};
/**