From: Niklas Cassel Date: Fri, 31 Jan 2025 18:29:51 +0000 (+0100) Subject: PCI: endpoint: Add pci_epc_bar_size_to_rebar_cap() X-Git-Tag: block-6.15-20250403~40^2~19^2~8 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=4eb208424c9c49dc3298a45e8db7cf43fdf15600;p=linux-block.git PCI: endpoint: Add pci_epc_bar_size_to_rebar_cap() Add a helper function to convert a size to the representation used by the Resizable BAR Capability Register. Signed-off-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250131182949.465530-11-cassel@kernel.org [mani: squashed the change that added PCIe spec reference to comments from https://lore.kernel.org/linux-pci/20250219171454.2903059-2-cassel@kernel.org] Signed-off-by: Manivannan Sadhasivam Signed-off-by: Krzysztof WilczyƄski --- diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 10dfc716328e..88cb426d3aec 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -638,6 +638,33 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, } EXPORT_SYMBOL_GPL(pci_epc_set_bar); +/** + * pci_epc_bar_size_to_rebar_cap() - convert a size to the representation used + * by the Resizable BAR Capability Register + * @size: the size to convert + * @cap: where to store the result + * + * Returns 0 on success and a negative error code in case of error. + */ +int pci_epc_bar_size_to_rebar_cap(size_t size, u32 *cap) +{ + /* + * As per PCIe r6.0, sec 7.8.6.2, min size for a resizable BAR is 1 MB, + * thus disallow a requested BAR size smaller than 1 MB. + * Disallow a requested BAR size larger than 128 TB. + */ + if (size < SZ_1M || (u64)size > (SZ_128G * 1024)) + return -EINVAL; + + *cap = ilog2(size) - ilog2(SZ_1M); + + /* Sizes in REBAR_CAP start at BIT(4). */ + *cap = BIT(*cap + 4); + + return 0; +} +EXPORT_SYMBOL_GPL(pci_epc_bar_size_to_rebar_cap); + /** * pci_epc_write_header() - write standard configuration header * @epc: the EPC device to which the configuration header should be written diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 91ce39dc0fd4..713348322dea 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -275,6 +275,7 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf, enum pci_epc_interface_type type); int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_header *hdr); +int pci_epc_bar_size_to_rebar_cap(size_t size, u32 *cap); int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_bar *epf_bar); void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,