diff options
Diffstat (limited to 'drivers/pci/endpoint')
-rw-r--r-- | drivers/pci/endpoint/functions/pci-epf-test.c | 28 | ||||
-rw-r--r-- | drivers/pci/endpoint/pci-epc-core.c | 32 | ||||
-rw-r--r-- | drivers/pci/endpoint/pci-epf-core.c | 56 |
3 files changed, 57 insertions, 59 deletions
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 64d8a17f8094..7cef85124325 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -70,7 +70,7 @@ struct pci_epf_test_data { bool linkup_notifier; }; -static int bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 }; +static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 }; static int pci_epf_test_copy(struct pci_epf_test *epf_test) { @@ -344,21 +344,23 @@ static void pci_epf_test_unbind(struct pci_epf *epf) { struct pci_epf_test *epf_test = epf_get_drvdata(epf); struct pci_epc *epc = epf->epc; + struct pci_epf_bar *epf_bar; int bar; cancel_delayed_work(&epf_test->cmd_handler); pci_epc_stop(epc); for (bar = BAR_0; bar <= BAR_5; bar++) { + epf_bar = &epf->bar[bar]; + if (epf_test->reg[bar]) { pci_epf_free_space(epf, epf_test->reg[bar], bar); - pci_epc_clear_bar(epc, epf->func_no, bar); + pci_epc_clear_bar(epc, epf->func_no, epf_bar); } } } static int pci_epf_test_set_bar(struct pci_epf *epf) { - int flags; int bar; int ret; struct pci_epf_bar *epf_bar; @@ -367,21 +369,27 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) struct pci_epf_test *epf_test = epf_get_drvdata(epf); enum pci_barno test_reg_bar = epf_test->test_reg_bar; - flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32; - if (sizeof(dma_addr_t) == 0x8) - flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; - for (bar = BAR_0; bar <= BAR_5; bar++) { epf_bar = &epf->bar[bar]; - ret = pci_epc_set_bar(epc, epf->func_no, bar, - epf_bar->phys_addr, - epf_bar->size, flags); + + epf_bar->flags |= upper_32_bits(epf_bar->size) ? + PCI_BASE_ADDRESS_MEM_TYPE_64 : + PCI_BASE_ADDRESS_MEM_TYPE_32; + + ret = pci_epc_set_bar(epc, epf->func_no, epf_bar); if (ret) { pci_epf_free_space(epf, epf_test->reg[bar], bar); dev_err(dev, "failed to set BAR%d\n", bar); if (bar == test_reg_bar) return ret; } + /* + * pci_epc_set_bar() sets PCI_BASE_ADDRESS_MEM_TYPE_64 + * if the specific implementation required a 64-bit BAR, + * even if we only requested a 32-bit BAR. + */ + if (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) + bar++; } return 0; diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index e245bba0ab53..b0ee42739c3c 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -276,22 +276,25 @@ EXPORT_SYMBOL_GPL(pci_epc_map_addr); * pci_epc_clear_bar() - reset the BAR * @epc: the EPC device for which the BAR has to be cleared * @func_no: the endpoint function number in the EPC device - * @bar: the BAR number that has to be reset + * @epf_bar: the struct epf_bar that contains the BAR information * * Invoke to reset the BAR of the endpoint device. */ -void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, int bar) +void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, + struct pci_epf_bar *epf_bar) { unsigned long flags; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || + (epf_bar->barno == BAR_5 && + epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)) return; if (!epc->ops->clear_bar) return; spin_lock_irqsave(&epc->lock, flags); - epc->ops->clear_bar(epc, func_no, bar); + epc->ops->clear_bar(epc, func_no, epf_bar); spin_unlock_irqrestore(&epc->lock, flags); } EXPORT_SYMBOL_GPL(pci_epc_clear_bar); @@ -300,26 +303,31 @@ EXPORT_SYMBOL_GPL(pci_epc_clear_bar); * pci_epc_set_bar() - configure BAR in order for host to assign PCI addr space * @epc: the EPC device on which BAR has to be configured * @func_no: the endpoint function number in the EPC device - * @bar: the BAR number that has to be configured - * @size: the size of the addr space - * @flags: specify memory allocation/io allocation/32bit address/64 bit address + * @epf_bar: the struct epf_bar that contains the BAR information * * Invoke to configure the BAR of the endpoint device. */ -int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, enum pci_barno bar, - dma_addr_t bar_phys, size_t size, int flags) +int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, + struct pci_epf_bar *epf_bar) { int ret; unsigned long irq_flags; - - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) + int flags = epf_bar->flags; + + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || + (epf_bar->barno == BAR_5 && + flags & PCI_BASE_ADDRESS_MEM_TYPE_64) || + (flags & PCI_BASE_ADDRESS_SPACE_IO && + flags & PCI_BASE_ADDRESS_IO_MASK) || + (upper_32_bits(epf_bar->size) && + !(flags & PCI_BASE_ADDRESS_MEM_TYPE_64))) return -EINVAL; if (!epc->ops->set_bar) return 0; spin_lock_irqsave(&epc->lock, irq_flags); - ret = epc->ops->set_bar(epc, func_no, bar, bar_phys, size, flags); + ret = epc->ops->set_bar(epc, func_no, epf_bar); spin_unlock_irqrestore(&epc->lock, irq_flags); return ret; diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c index 766ce1dca2ec..465b5f058b6d 100644 --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -98,6 +98,8 @@ void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar) epf->bar[bar].phys_addr = 0; epf->bar[bar].size = 0; + epf->bar[bar].barno = 0; + epf->bar[bar].flags = 0; } EXPORT_SYMBOL_GPL(pci_epf_free_space); @@ -126,6 +128,8 @@ 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].size = size; + epf->bar[bar].barno = bar; + epf->bar[bar].flags = PCI_BASE_ADDRESS_SPACE_MEMORY; return space; } @@ -200,29 +204,17 @@ struct pci_epf *pci_epf_create(const char *name) int ret; struct pci_epf *epf; struct device *dev; - char *func_name; - char *buf; + int len; epf = kzalloc(sizeof(*epf), GFP_KERNEL); - if (!epf) { - ret = -ENOMEM; - goto err_ret; - } - - buf = kstrdup(name, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto free_epf; - } - - func_name = buf; - buf = strchrnul(buf, '.'); - *buf = '\0'; + if (!epf) + return ERR_PTR(-ENOMEM); - epf->name = kstrdup(func_name, GFP_KERNEL); + len = strchrnul(name, '.') - name; + epf->name = kstrndup(name, len, GFP_KERNEL); if (!epf->name) { - ret = -ENOMEM; - goto free_func_name; + kfree(epf); + return ERR_PTR(-ENOMEM); } dev = &epf->dev; @@ -231,28 +223,18 @@ struct pci_epf *pci_epf_create(const char *name) dev->type = &pci_epf_type; ret = dev_set_name(dev, "%s", name); - if (ret) - goto put_dev; + if (ret) { + put_device(dev); + return ERR_PTR(ret); + } ret = device_add(dev); - if (ret) - goto put_dev; + if (ret) { + put_device(dev); + return ERR_PTR(ret); + } - kfree(func_name); return epf; - -put_dev: - put_device(dev); - kfree(epf->name); - -free_func_name: - kfree(func_name); - -free_epf: - kfree(epf); - -err_ret: - return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(pci_epf_create); |