diff options
Diffstat (limited to 'drivers/pci/endpoint/pci-epf-core.c')
-rw-r--r-- | drivers/pci/endpoint/pci-epf-core.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c index 2c32de667937..50bc2892a36c 100644 --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -17,7 +17,7 @@ static DEFINE_MUTEX(pci_epf_mutex); -static struct bus_type pci_epf_bus_type; +static const struct bus_type pci_epf_bus_type; static const struct device_type pci_epf_type; /** @@ -202,6 +202,7 @@ void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf) mutex_lock(&epf_pf->lock); clear_bit(epf_vf->vfunc_no, &epf_pf->vfunction_num_map); + epf_vf->epf_pf = NULL; list_del(&epf_vf->list); mutex_unlock(&epf_pf->lock); } @@ -251,14 +252,19 @@ EXPORT_SYMBOL_GPL(pci_epf_free_space); * @epf: the EPF device to whom allocate the memory * @size: the size of the memory that has to be allocated * @bar: the BAR number corresponding to the allocated register space - * @align: alignment size for the allocation region + * @epc_features: the features provided by the EPC specific to this EPF * @type: Identifies if the allocation is for primary EPC or secondary EPC * * Invoke to allocate memory for the PCI EPF register space. + * Flag PCI_BASE_ADDRESS_MEM_TYPE_64 will automatically get set if the BAR + * can only be a 64-bit BAR, or if the requested size is larger than 2 GB. */ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar, - size_t align, enum pci_epc_interface_type type) + const struct pci_epc_features *epc_features, + enum pci_epc_interface_type type) { + u64 bar_fixed_size = epc_features->bar[bar].fixed_size; + size_t align = epc_features->align; struct pci_epf_bar *epf_bar; dma_addr_t phys_addr; struct pci_epc *epc; @@ -268,6 +274,15 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar, if (size < 128) size = 128; + if (epc_features->bar[bar].type == BAR_FIXED && bar_fixed_size) { + if (size > bar_fixed_size) { + dev_err(&epf->dev, + "requested BAR size is larger than fixed size\n"); + return NULL; + } + size = bar_fixed_size; + } + if (align) size = ALIGN(size, align); else @@ -292,9 +307,10 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar, epf_bar[bar].addr = space; epf_bar[bar].size = size; epf_bar[bar].barno = bar; - epf_bar[bar].flags |= upper_32_bits(size) ? - PCI_BASE_ADDRESS_MEM_TYPE_64 : - PCI_BASE_ADDRESS_MEM_TYPE_32; + if (upper_32_bits(size) || epc_features->bar[bar].only_64bit) + epf_bar[bar].flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; + else + epf_bar[bar].flags |= PCI_BASE_ADDRESS_MEM_TYPE_32; return space; } @@ -473,10 +489,10 @@ pci_epf_match_id(const struct pci_epf_device_id *id, const struct pci_epf *epf) return NULL; } -static int pci_epf_device_match(struct device *dev, struct device_driver *drv) +static int pci_epf_device_match(struct device *dev, const struct device_driver *drv) { struct pci_epf *epf = to_pci_epf(dev); - struct pci_epf_driver *driver = to_pci_epf_driver(drv); + const struct pci_epf_driver *driver = to_pci_epf_driver(drv); if (driver->id_table) return !!pci_epf_match_id(driver->id_table, epf); @@ -507,7 +523,7 @@ static void pci_epf_device_remove(struct device *dev) epf->driver = NULL; } -static struct bus_type pci_epf_bus_type = { +static const struct bus_type pci_epf_bus_type = { .name = "pci-epf", .match = pci_epf_device_match, .probe = pci_epf_device_probe, |