mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-28 06:44:36 -05:00
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: 2a9a801620 ("PCI: endpoint: Add support to specify alignment for buffers allocated to BARs")
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
[mani: commit message fixup]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
[bhelgaas: more specific subject, commit log, wrap comment to match file]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Link: https://patch.msgid.link/20250424-pci-ep-size-alignment-v5-1-2d4ec2af23f5@baylibre.com
This commit is contained in:
committed by
Bjorn Helgaas
parent
0af2f6be1b
commit
793908d60b
@@ -236,12 +236,13 @@ void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
|
||||
}
|
||||
|
||||
dev = epc->dev.parent;
|
||||
dma_free_coherent(dev, epf_bar[bar].size, addr,
|
||||
dma_free_coherent(dev, epf_bar[bar].aligned_size, addr,
|
||||
epf_bar[bar].phys_addr);
|
||||
|
||||
epf_bar[bar].phys_addr = 0;
|
||||
epf_bar[bar].addr = NULL;
|
||||
epf_bar[bar].size = 0;
|
||||
epf_bar[bar].aligned_size = 0;
|
||||
epf_bar[bar].barno = 0;
|
||||
epf_bar[bar].flags = 0;
|
||||
}
|
||||
@@ -264,7 +265,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
|
||||
enum pci_epc_interface_type type)
|
||||
{
|
||||
u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
|
||||
size_t align = epc_features->align;
|
||||
size_t aligned_size, align = epc_features->align;
|
||||
struct pci_epf_bar *epf_bar;
|
||||
dma_addr_t phys_addr;
|
||||
struct pci_epc *epc;
|
||||
@@ -285,12 +286,18 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
|
||||
return NULL;
|
||||
}
|
||||
size = bar_fixed_size;
|
||||
} else {
|
||||
/* BAR size must be power of two */
|
||||
size = roundup_pow_of_two(size);
|
||||
}
|
||||
|
||||
if (align)
|
||||
size = ALIGN(size, align);
|
||||
else
|
||||
size = roundup_pow_of_two(size);
|
||||
/*
|
||||
* Allocate enough memory to accommodate the iATU alignment
|
||||
* requirement. In most cases, this will be the same as .size but
|
||||
* it might be different if, for example, the fixed size of a BAR
|
||||
* is smaller than align.
|
||||
*/
|
||||
aligned_size = align ? ALIGN(size, align) : size;
|
||||
|
||||
if (type == PRIMARY_INTERFACE) {
|
||||
epc = epf->epc;
|
||||
@@ -301,7 +308,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
|
||||
}
|
||||
|
||||
dev = epc->dev.parent;
|
||||
space = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
|
||||
space = dma_alloc_coherent(dev, aligned_size, &phys_addr, GFP_KERNEL);
|
||||
if (!space) {
|
||||
dev_err(dev, "failed to allocate mem space\n");
|
||||
return NULL;
|
||||
@@ -310,6 +317,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
|
||||
epf_bar[bar].phys_addr = phys_addr;
|
||||
epf_bar[bar].addr = space;
|
||||
epf_bar[bar].size = size;
|
||||
epf_bar[bar].aligned_size = aligned_size;
|
||||
epf_bar[bar].barno = bar;
|
||||
if (upper_32_bits(size) || epc_features->bar[bar].only_64bit)
|
||||
epf_bar[bar].flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
|
||||
|
||||
@@ -114,6 +114,8 @@ struct pci_epf_driver {
|
||||
* @phys_addr: physical address that should be mapped to the BAR
|
||||
* @addr: virtual address corresponding to the @phys_addr
|
||||
* @size: the size of the address space present in BAR
|
||||
* @aligned_size: the size actually allocated to accommodate the iATU alignment
|
||||
* requirement
|
||||
* @barno: BAR number
|
||||
* @flags: flags that are set for the BAR
|
||||
*/
|
||||
@@ -121,6 +123,7 @@ struct pci_epf_bar {
|
||||
dma_addr_t phys_addr;
|
||||
void *addr;
|
||||
size_t size;
|
||||
size_t aligned_size;
|
||||
enum pci_barno barno;
|
||||
int flags;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user