PCI: endpoint: Add pci_epc_bar_size_to_rebar_cap()
authorNiklas Cassel <cassel@kernel.org>
Fri, 31 Jan 2025 18:29:51 +0000 (19:29 +0100)
committerKrzysztof Wilczyński <kwilczynski@kernel.org>
Sat, 8 Mar 2025 14:43:05 +0000 (14:43 +0000)
Add a helper function to convert a size to the representation used by the
Resizable BAR Capability Register.

Signed-off-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
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 <manivannan.sadhasivam@linaro.org>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
drivers/pci/endpoint/pci-epc-core.c
include/linux/pci-epc.h

index 10dfc716328ef7370d0166f71ae289d8ccd3bd79..88cb426d3aeceda673ed60b0c351e75f075a2421 100644 (file)
@@ -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
index 91ce39dc0fd441eb4c5cd54e9aecdf7653b30730..713348322dea4bcde711eca837184cc25df534ec 100644 (file)
@@ -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,