aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhichang Yuan <yuanzhichang@hisilicon.com>2018-03-14 14:15:53 -0400
committerBjorn Helgaas <helgaas@kernel.org>2018-04-04 09:42:46 -0400
commit5745392e0c2b78e0d73203281d5c42cbd6993194 (patch)
tree92b426448d08156a25b84582d7ad80c0e287d27a
parentfcfaab30933bd151bd8cb4dd07b3f11d885bb611 (diff)
PCI: Apply the new generic I/O management on PCI IO hosts
After introducing the new generic I/O space management (Logical PIO), the original PCI MMIO relevant helpers need to be updated based on the new interfaces defined in logical PIO. Adapt the corresponding code to match the changes introduced by logical PIO. Tested-by: dann frazier <dann.frazier@canonical.com> Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de> # earlier draft Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
-rw-r--r--drivers/pci/pci.c92
-rw-r--r--include/asm-generic/io.h2
2 files changed, 18 insertions, 76 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 07290a31370c..83a263fc9246 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -22,6 +22,7 @@
22#include <linux/spinlock.h> 22#include <linux/spinlock.h>
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/log2.h> 24#include <linux/log2.h>
25#include <linux/logic_pio.h>
25#include <linux/pci-aspm.h> 26#include <linux/pci-aspm.h>
26#include <linux/pm_wakeup.h> 27#include <linux/pm_wakeup.h>
27#include <linux/interrupt.h> 28#include <linux/interrupt.h>
@@ -3440,17 +3441,6 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
3440} 3441}
3441EXPORT_SYMBOL(pci_request_regions_exclusive); 3442EXPORT_SYMBOL(pci_request_regions_exclusive);
3442 3443
3443#ifdef PCI_IOBASE
3444struct io_range {
3445 struct list_head list;
3446 phys_addr_t start;
3447 resource_size_t size;
3448};
3449
3450static LIST_HEAD(io_range_list);
3451static DEFINE_SPINLOCK(io_range_lock);
3452#endif
3453
3454/* 3444/*
3455 * Record the PCI IO range (expressed as CPU physical address + size). 3445 * Record the PCI IO range (expressed as CPU physical address + size).
3456 * Return a negative value if an error has occured, zero otherwise 3446 * Return a negative value if an error has occured, zero otherwise
@@ -3458,51 +3448,28 @@ static DEFINE_SPINLOCK(io_range_lock);
3458int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, 3448int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
3459 resource_size_t size) 3449 resource_size_t size)
3460{ 3450{
3461 int err = 0; 3451 int ret = 0;
3462
3463#ifdef PCI_IOBASE 3452#ifdef PCI_IOBASE
3464 struct io_range *range; 3453 struct logic_pio_hwaddr *range;
3465 resource_size_t allocated_size = 0;
3466
3467 /* check if the range hasn't been previously recorded */
3468 spin_lock(&io_range_lock);
3469 list_for_each_entry(range, &io_range_list, list) {
3470 if (addr >= range->start && addr + size <= range->start + size) {
3471 /* range already registered, bail out */
3472 goto end_register;
3473 }
3474 allocated_size += range->size;
3475 }
3476 3454
3477 /* range not registed yet, check for available space */ 3455 if (!size || addr + size < addr)
3478 if (allocated_size + size - 1 > IO_SPACE_LIMIT) { 3456 return -EINVAL;
3479 /* if it's too big check if 64K space can be reserved */
3480 if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
3481 err = -E2BIG;
3482 goto end_register;
3483 }
3484
3485 size = SZ_64K;
3486 pr_warn("Requested IO range too big, new size set to 64K\n");
3487 }
3488 3457
3489 /* add the range to the list */
3490 range = kzalloc(sizeof(*range), GFP_ATOMIC); 3458 range = kzalloc(sizeof(*range), GFP_ATOMIC);
3491 if (!range) { 3459 if (!range)
3492 err = -ENOMEM; 3460 return -ENOMEM;
3493 goto end_register;
3494 }
3495 3461
3496 range->start = addr; 3462 range->fwnode = fwnode;
3497 range->size = size; 3463 range->size = size;
3464 range->hw_start = addr;
3465 range->flags = LOGIC_PIO_CPU_MMIO;
3498 3466
3499 list_add_tail(&range->list, &io_range_list); 3467 ret = logic_pio_register_range(range);
3500 3468 if (ret)
3501end_register: 3469 kfree(range);
3502 spin_unlock(&io_range_lock);
3503#endif 3470#endif
3504 3471
3505 return err; 3472 return ret;
3506} 3473}
3507 3474
3508phys_addr_t pci_pio_to_address(unsigned long pio) 3475phys_addr_t pci_pio_to_address(unsigned long pio)
@@ -3510,21 +3477,10 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
3510 phys_addr_t address = (phys_addr_t)OF_BAD_ADDR; 3477 phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
3511 3478
3512#ifdef PCI_IOBASE 3479#ifdef PCI_IOBASE
3513 struct io_range *range; 3480 if (pio >= MMIO_UPPER_LIMIT)
3514 resource_size_t allocated_size = 0;
3515
3516 if (pio > IO_SPACE_LIMIT)
3517 return address; 3481 return address;
3518 3482
3519 spin_lock(&io_range_lock); 3483 address = logic_pio_to_hwaddr(pio);
3520 list_for_each_entry(range, &io_range_list, list) {
3521 if (pio >= allocated_size && pio < allocated_size + range->size) {
3522 address = range->start + pio - allocated_size;
3523 break;
3524 }
3525 allocated_size += range->size;
3526 }
3527 spin_unlock(&io_range_lock);
3528#endif 3484#endif
3529 3485
3530 return address; 3486 return address;
@@ -3533,21 +3489,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
3533unsigned long __weak pci_address_to_pio(phys_addr_t address) 3489unsigned long __weak pci_address_to_pio(phys_addr_t address)
3534{ 3490{
3535#ifdef PCI_IOBASE 3491#ifdef PCI_IOBASE
3536 struct io_range *res; 3492 return logic_pio_trans_cpuaddr(address);
3537 resource_size_t offset = 0;
3538 unsigned long addr = -1;
3539
3540 spin_lock(&io_range_lock);
3541 list_for_each_entry(res, &io_range_list, list) {
3542 if (address >= res->start && address < res->start + res->size) {
3543 addr = address - res->start + offset;
3544 break;
3545 }
3546 offset += res->size;
3547 }
3548 spin_unlock(&io_range_lock);
3549
3550 return addr;
3551#else 3493#else
3552 if (address > IO_SPACE_LIMIT) 3494 if (address > IO_SPACE_LIMIT)
3553 return (unsigned long)-1; 3495 return (unsigned long)-1;
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index b7996a79d64b..5a5993166654 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -901,7 +901,7 @@ static inline void iounmap(void __iomem *addr)
901#define ioport_map ioport_map 901#define ioport_map ioport_map
902static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) 902static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
903{ 903{
904 return PCI_IOBASE + (port & IO_SPACE_LIMIT); 904 return PCI_IOBASE + (port & MMIO_UPPER_LIMIT);
905} 905}
906#endif 906#endif
907 907