Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

PCI: endpoint: Add BAR subrange mapping support

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

authored by

Koichiro Den and committed by
Manivannan Sadhasivam
31fb9540 06a81c59

+35
+8
drivers/pci/endpoint/pci-epc-core.c
··· 596 596 if (!epc_features) 597 597 return -EINVAL; 598 598 599 + if (epf_bar->num_submap && !epf_bar->submap) 600 + return -EINVAL; 601 + 602 + if (epf_bar->num_submap && 603 + !(epc_features->dynamic_inbound_mapping && 604 + epc_features->subrange_mapping)) 605 + return -EINVAL; 606 + 599 607 if (epc_features->bar[bar].type == BAR_RESIZABLE && 600 608 (epf_bar->size < SZ_1M || (u64)epf_bar->size > (SZ_128G * 1024))) 601 609 return -EINVAL;
+4
include/linux/pci-epc.h
··· 227 227 * inbound mappings for an already configured BAR 228 228 * (i.e. allow calling pci_epc_set_bar() again 229 229 * without first calling pci_epc_clear_bar()) 230 + * @subrange_mapping: indicate if the EPC device can map inbound subranges for a 231 + * BAR. This feature depends on @dynamic_inbound_mapping 232 + * feature. 230 233 * @msi_capable: indicate if the endpoint function has MSI capability 231 234 * @msix_capable: indicate if the endpoint function has MSI-X capability 232 235 * @intx_capable: indicate if the endpoint can raise INTx interrupts ··· 239 236 struct pci_epc_features { 240 237 unsigned int linkup_notifier : 1; 241 238 unsigned int dynamic_inbound_mapping : 1; 239 + unsigned int subrange_mapping : 1; 242 240 unsigned int msi_capable : 1; 243 241 unsigned int msix_capable : 1; 244 242 unsigned int intx_capable : 1;
+23
include/linux/pci-epf.h
··· 111 111 #define to_pci_epf_driver(drv) container_of_const((drv), struct pci_epf_driver, driver) 112 112 113 113 /** 114 + * struct pci_epf_bar_submap - BAR subrange for inbound mapping 115 + * @phys_addr: target physical/DMA address for this subrange 116 + * @size: the size of the subrange to be mapped 117 + * 118 + * When pci_epf_bar.num_submap is >0, pci_epf_bar.submap describes the 119 + * complete BAR layout. This allows an EPC driver to program multiple 120 + * inbound translation windows for a single BAR when supported by the 121 + * controller. The array order defines the BAR layout (submap[0] at offset 122 + * 0, and each immediately follows the previous one). 123 + */ 124 + struct pci_epf_bar_submap { 125 + dma_addr_t phys_addr; 126 + size_t size; 127 + }; 128 + 129 + /** 114 130 * struct pci_epf_bar - represents the BAR of EPF device 115 131 * @phys_addr: physical address that should be mapped to the BAR 116 132 * @addr: virtual address corresponding to the @phys_addr ··· 135 119 * requirement 136 120 * @barno: BAR number 137 121 * @flags: flags that are set for the BAR 122 + * @num_submap: number of entries in @submap 123 + * @submap: array of subrange descriptors allocated by the caller. See 124 + * struct pci_epf_bar_submap for the semantics in detail. 138 125 */ 139 126 struct pci_epf_bar { 140 127 dma_addr_t phys_addr; ··· 146 127 size_t mem_size; 147 128 enum pci_barno barno; 148 129 int flags; 130 + 131 + /* Optional sub-range mapping */ 132 + unsigned int num_submap; 133 + struct pci_epf_bar_submap *submap; 149 134 }; 150 135 151 136 /**