Skip to content

Commit f71e2b6

Browse files
nxpfrankliMani-Sadhasivam
authored andcommitted
PCI: endpoint: Add pci_epf_get_required_bar_size() helper
Introduce pci_epf_get_required_bar_size() helper to get the required BAR size and backing memory size. This helper will be used to set a fixed MMIO address as the backing memory for a BAR. Since this helper returns both BAR size and the aligned memory size, use two parameters, 'bar_size' and 'aligned_mem_size' to avoid confusion. Signed-off-by: Frank Li <Frank.Li@nxp.com> [mani: renamed helper to pci_epf_get_required_bar_size(), reworded description] Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> Reviewed-by: Niklas Cassel <cassel@kernel.org> Link: https://patch.msgid.link/20251015-vntb_msi_doorbell-v6-2-9230298b1910@nxp.com
1 parent 4837688 commit f71e2b6

1 file changed

Lines changed: 46 additions & 28 deletions

File tree

drivers/pci/endpoint/pci-epf-core.c

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,48 @@ void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
208208
}
209209
EXPORT_SYMBOL_GPL(pci_epf_remove_vepf);
210210

211+
static int pci_epf_get_required_bar_size(struct pci_epf *epf, size_t *bar_size,
212+
size_t *aligned_mem_size,
213+
enum pci_barno bar,
214+
const struct pci_epc_features *epc_features,
215+
enum pci_epc_interface_type type)
216+
{
217+
u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
218+
size_t align = epc_features->align;
219+
size_t size = *bar_size;
220+
221+
if (size < 128)
222+
size = 128;
223+
224+
/* According to PCIe base spec, min size for a resizable BAR is 1 MB. */
225+
if (epc_features->bar[bar].type == BAR_RESIZABLE && size < SZ_1M)
226+
size = SZ_1M;
227+
228+
if (epc_features->bar[bar].type == BAR_FIXED && bar_fixed_size) {
229+
if (size > bar_fixed_size) {
230+
dev_err(&epf->dev,
231+
"requested BAR size is larger than fixed size\n");
232+
return -ENOMEM;
233+
}
234+
size = bar_fixed_size;
235+
} else {
236+
/* BAR size must be power of two */
237+
size = roundup_pow_of_two(size);
238+
}
239+
240+
*bar_size = size;
241+
242+
/*
243+
* The EPC's BAR start address must meet alignment requirements. In most
244+
* cases, the alignment will match the BAR size. However, differences
245+
* can occur—for example, when the fixed BAR size (e.g., 128 bytes) is
246+
* smaller than the required alignment (e.g., 4 KB).
247+
*/
248+
*aligned_mem_size = align ? ALIGN(size, align) : size;
249+
250+
return 0;
251+
}
252+
211253
/**
212254
* pci_epf_free_space() - free the allocated PCI EPF register space
213255
* @epf: the EPF device from whom to free the memory
@@ -264,40 +306,16 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
264306
const struct pci_epc_features *epc_features,
265307
enum pci_epc_interface_type type)
266308
{
267-
u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
268-
size_t mem_size, align = epc_features->align;
269309
struct pci_epf_bar *epf_bar;
270310
dma_addr_t phys_addr;
271311
struct pci_epc *epc;
272312
struct device *dev;
313+
size_t mem_size;
273314
void *space;
274315

275-
if (size < 128)
276-
size = 128;
277-
278-
/* According to PCIe base spec, min size for a resizable BAR is 1 MB. */
279-
if (epc_features->bar[bar].type == BAR_RESIZABLE && size < SZ_1M)
280-
size = SZ_1M;
281-
282-
if (epc_features->bar[bar].type == BAR_FIXED && bar_fixed_size) {
283-
if (size > bar_fixed_size) {
284-
dev_err(&epf->dev,
285-
"requested BAR size is larger than fixed size\n");
286-
return NULL;
287-
}
288-
size = bar_fixed_size;
289-
} else {
290-
/* BAR size must be power of two */
291-
size = roundup_pow_of_two(size);
292-
}
293-
294-
/*
295-
* Allocate enough memory to accommodate the iATU alignment
296-
* requirement. In most cases, this will be the same as .size but
297-
* it might be different if, for example, the fixed size of a BAR
298-
* is smaller than align.
299-
*/
300-
mem_size = align ? ALIGN(size, align) : size;
316+
if (pci_epf_get_required_bar_size(epf, &size, &mem_size, bar,
317+
epc_features, type))
318+
return NULL;
301319

302320
if (type == PRIMARY_INTERFACE) {
303321
epc = epf->epc;

0 commit comments

Comments
 (0)