summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorTomasz Nowicki <tn@semihalf.com>2016-05-11 18:34:51 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-05-12 08:07:42 -0400
commitc5076cfe768998e9d395bc8486b29b18b0f99fd9 (patch)
tree94eaff672e0871147c33abf16edcbf0843078e25 /drivers/pci/pci.c
parent1958e7173df14ff50d75ed2fbd24b349d25caf80 (diff)
PCI, of: Move PCI I/O space management to PCI core code
No functional changes in this patch. PCI I/O space mapping code does not depend on OF; therefore it can be moved to PCI core code. This way we will be able to use it, e.g., in ACPI PCI code. Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Tomasz Nowicki <tn@semihalf.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> CC: Arnd Bergmann <arnd@arndb.de> CC: Liviu Dudau <Liviu.Dudau@arm.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 25e0327d4429..bc0c914b8afc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3021,6 +3021,121 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
3021} 3021}
3022EXPORT_SYMBOL(pci_request_regions_exclusive); 3022EXPORT_SYMBOL(pci_request_regions_exclusive);
3023 3023
3024#ifdef PCI_IOBASE
3025struct io_range {
3026 struct list_head list;
3027 phys_addr_t start;
3028 resource_size_t size;
3029};
3030
3031static LIST_HEAD(io_range_list);
3032static DEFINE_SPINLOCK(io_range_lock);
3033#endif
3034
3035/*
3036 * Record the PCI IO range (expressed as CPU physical address + size).
3037 * Return a negative value if an error has occured, zero otherwise
3038 */
3039int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
3040{
3041 int err = 0;
3042
3043#ifdef PCI_IOBASE
3044 struct io_range *range;
3045 resource_size_t allocated_size = 0;
3046
3047 /* check if the range hasn't been previously recorded */
3048 spin_lock(&io_range_lock);
3049 list_for_each_entry(range, &io_range_list, list) {
3050 if (addr >= range->start && addr + size <= range->start + size) {
3051 /* range already registered, bail out */
3052 goto end_register;
3053 }
3054 allocated_size += range->size;
3055 }
3056
3057 /* range not registed yet, check for available space */
3058 if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
3059 /* if it's too big check if 64K space can be reserved */
3060 if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
3061 err = -E2BIG;
3062 goto end_register;
3063 }
3064
3065 size = SZ_64K;
3066 pr_warn("Requested IO range too big, new size set to 64K\n");
3067 }
3068
3069 /* add the range to the list */
3070 range = kzalloc(sizeof(*range), GFP_ATOMIC);
3071 if (!range) {
3072 err = -ENOMEM;
3073 goto end_register;
3074 }
3075
3076 range->start = addr;
3077 range->size = size;
3078
3079 list_add_tail(&range->list, &io_range_list);
3080
3081end_register:
3082 spin_unlock(&io_range_lock);
3083#endif
3084
3085 return err;
3086}
3087
3088phys_addr_t pci_pio_to_address(unsigned long pio)
3089{
3090 phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
3091
3092#ifdef PCI_IOBASE
3093 struct io_range *range;
3094 resource_size_t allocated_size = 0;
3095
3096 if (pio > IO_SPACE_LIMIT)
3097 return address;
3098
3099 spin_lock(&io_range_lock);
3100 list_for_each_entry(range, &io_range_list, list) {
3101 if (pio >= allocated_size && pio < allocated_size + range->size) {
3102 address = range->start + pio - allocated_size;
3103 break;
3104 }
3105 allocated_size += range->size;
3106 }
3107 spin_unlock(&io_range_lock);
3108#endif
3109
3110 return address;
3111}
3112
3113unsigned long __weak pci_address_to_pio(phys_addr_t address)
3114{
3115#ifdef PCI_IOBASE
3116 struct io_range *res;
3117 resource_size_t offset = 0;
3118 unsigned long addr = -1;
3119
3120 spin_lock(&io_range_lock);
3121 list_for_each_entry(res, &io_range_list, list) {
3122 if (address >= res->start && address < res->start + res->size) {
3123 addr = address - res->start + offset;
3124 break;
3125 }
3126 offset += res->size;
3127 }
3128 spin_unlock(&io_range_lock);
3129
3130 return addr;
3131#else
3132 if (address > IO_SPACE_LIMIT)
3133 return (unsigned long)-1;
3134
3135 return (unsigned long) address;
3136#endif
3137}
3138
3024/** 3139/**
3025 * pci_remap_iospace - Remap the memory mapped I/O space 3140 * pci_remap_iospace - Remap the memory mapped I/O space
3026 * @res: Resource describing the I/O space 3141 * @res: Resource describing the I/O space