Skip to content

Commit 793908d

Browse files
jbrun3tbjorn-helgaas
authored andcommitted
PCI: endpoint: Retain fixed-size BAR size as well as aligned size
When allocating space for an endpoint function on a BAR with a fixed size, the size saved in 'struct pci_epf_bar.size' should be the fixed size as expected by pci_epc_set_bar(). However, if pci_epf_alloc_space() increased the allocation size to accommodate iATU alignment requirements, it previously saved the larger aligned size in .size, which broke pci_epc_set_bar(). To solve this, keep the fixed BAR size in .size and save the aligned size in a new .aligned_size for use when deallocating it. Fixes: 2a9a801 ("PCI: endpoint: Add support to specify alignment for buffers allocated to BARs") Signed-off-by: Jerome Brunet <[email protected]> [mani: commit message fixup] Signed-off-by: Manivannan Sadhasivam <[email protected]> [bhelgaas: more specific subject, commit log, wrap comment to match file] Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Niklas Cassel <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 0af2f6b commit 793908d

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,13 @@ void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
236236
}
237237

238238
dev = epc->dev.parent;
239-
dma_free_coherent(dev, epf_bar[bar].size, addr,
239+
dma_free_coherent(dev, epf_bar[bar].aligned_size, addr,
240240
epf_bar[bar].phys_addr);
241241

242242
epf_bar[bar].phys_addr = 0;
243243
epf_bar[bar].addr = NULL;
244244
epf_bar[bar].size = 0;
245+
epf_bar[bar].aligned_size = 0;
245246
epf_bar[bar].barno = 0;
246247
epf_bar[bar].flags = 0;
247248
}
@@ -264,7 +265,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
264265
enum pci_epc_interface_type type)
265266
{
266267
u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
267-
size_t align = epc_features->align;
268+
size_t aligned_size, align = epc_features->align;
268269
struct pci_epf_bar *epf_bar;
269270
dma_addr_t phys_addr;
270271
struct pci_epc *epc;
@@ -285,12 +286,18 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
285286
return NULL;
286287
}
287288
size = bar_fixed_size;
289+
} else {
290+
/* BAR size must be power of two */
291+
size = roundup_pow_of_two(size);
288292
}
289293

290-
if (align)
291-
size = ALIGN(size, align);
292-
else
293-
size = roundup_pow_of_two(size);
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+
aligned_size = align ? ALIGN(size, align) : size;
294301

295302
if (type == PRIMARY_INTERFACE) {
296303
epc = epf->epc;
@@ -301,7 +308,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
301308
}
302309

303310
dev = epc->dev.parent;
304-
space = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
311+
space = dma_alloc_coherent(dev, aligned_size, &phys_addr, GFP_KERNEL);
305312
if (!space) {
306313
dev_err(dev, "failed to allocate mem space\n");
307314
return NULL;
@@ -310,6 +317,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
310317
epf_bar[bar].phys_addr = phys_addr;
311318
epf_bar[bar].addr = space;
312319
epf_bar[bar].size = size;
320+
epf_bar[bar].aligned_size = aligned_size;
313321
epf_bar[bar].barno = bar;
314322
if (upper_32_bits(size) || epc_features->bar[bar].only_64bit)
315323
epf_bar[bar].flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;

include/linux/pci-epf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,16 @@ struct pci_epf_driver {
114114
* @phys_addr: physical address that should be mapped to the BAR
115115
* @addr: virtual address corresponding to the @phys_addr
116116
* @size: the size of the address space present in BAR
117+
* @aligned_size: the size actually allocated to accommodate the iATU alignment
118+
* requirement
117119
* @barno: BAR number
118120
* @flags: flags that are set for the BAR
119121
*/
120122
struct pci_epf_bar {
121123
dma_addr_t phys_addr;
122124
void *addr;
123125
size_t size;
126+
size_t aligned_size;
124127
enum pci_barno barno;
125128
int flags;
126129
};

0 commit comments

Comments
 (0)