/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -596,6 +596,14 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, 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; diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 4c8516756c568..c021c7af175fd 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -227,6 +227,9 @@ struct pci_epc_bar_desc { * 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 @@ -236,6 +239,7 @@ struct pci_epc_bar_desc { 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; diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h index 48f68c4dcfa5e..7737a7c03260d 100644 --- a/include/linux/pci-epf.h +++ b/include/linux/pci-epf.h @@ -110,6 +110,22 @@ struct pci_epf_driver { #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 @@ -119,6 +135,9 @@ struct pci_epf_driver { * 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; @@ -127,6 +146,10 @@ struct pci_epf_bar { size_t mem_size; enum pci_barno barno; int flags; + + /* Optional sub-range mapping */ + unsigned int num_submap; + struct pci_epf_bar_submap *submap; }; /** -- 2.51.0[PATCH 6.19 395/781] PCI: endpoint: Add BAR subrange mapping supportGreg Kroah-Hartman undefinedstable@vger.kernel.org undefined undefined undefined undefined undefined undefinedŇ †™U