diff options
Diffstat (limited to 'arch/ia64/pci/pci.c')
| -rw-r--r-- | arch/ia64/pci/pci.c | 106 |
1 files changed, 82 insertions, 24 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 017cfc3f4789..20d76fae24e8 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
| @@ -95,7 +95,7 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn, | |||
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static struct pci_raw_ops pci_sal_ops = { | 97 | static struct pci_raw_ops pci_sal_ops = { |
| 98 | .read = pci_sal_read, | 98 | .read = pci_sal_read, |
| 99 | .write = pci_sal_write | 99 | .write = pci_sal_write |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| @@ -137,35 +137,98 @@ alloc_pci_controller (int seg) | |||
| 137 | return controller; | 137 | return controller; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static u64 __devinit | 140 | struct pci_root_info { |
| 141 | add_io_space (struct acpi_resource_address64 *addr) | 141 | struct pci_controller *controller; |
| 142 | char *name; | ||
| 143 | }; | ||
| 144 | |||
| 145 | static unsigned int | ||
| 146 | new_space (u64 phys_base, int sparse) | ||
| 142 | { | 147 | { |
| 143 | u64 offset; | 148 | u64 mmio_base; |
| 144 | int sparse = 0; | ||
| 145 | int i; | 149 | int i; |
| 146 | 150 | ||
| 147 | if (addr->address_translation_offset == 0) | 151 | if (phys_base == 0) |
| 148 | return IO_SPACE_BASE(0); /* part of legacy IO space */ | 152 | return 0; /* legacy I/O port space */ |
| 149 | |||
| 150 | if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) | ||
| 151 | sparse = 1; | ||
| 152 | 153 | ||
| 153 | offset = (u64) ioremap(addr->address_translation_offset, 0); | 154 | mmio_base = (u64) ioremap(phys_base, 0); |
| 154 | for (i = 0; i < num_io_spaces; i++) | 155 | for (i = 0; i < num_io_spaces; i++) |
| 155 | if (io_space[i].mmio_base == offset && | 156 | if (io_space[i].mmio_base == mmio_base && |
| 156 | io_space[i].sparse == sparse) | 157 | io_space[i].sparse == sparse) |
| 157 | return IO_SPACE_BASE(i); | 158 | return i; |
| 158 | 159 | ||
| 159 | if (num_io_spaces == MAX_IO_SPACES) { | 160 | if (num_io_spaces == MAX_IO_SPACES) { |
| 160 | printk("Too many IO port spaces\n"); | 161 | printk(KERN_ERR "PCI: Too many IO port spaces " |
| 162 | "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES); | ||
| 161 | return ~0; | 163 | return ~0; |
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | i = num_io_spaces++; | 166 | i = num_io_spaces++; |
| 165 | io_space[i].mmio_base = offset; | 167 | io_space[i].mmio_base = mmio_base; |
| 166 | io_space[i].sparse = sparse; | 168 | io_space[i].sparse = sparse; |
| 167 | 169 | ||
| 168 | return IO_SPACE_BASE(i); | 170 | return i; |
| 171 | } | ||
| 172 | |||
| 173 | static u64 __devinit | ||
| 174 | add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr) | ||
| 175 | { | ||
| 176 | struct resource *resource; | ||
| 177 | char *name; | ||
| 178 | u64 base, min, max, base_port; | ||
| 179 | unsigned int sparse = 0, space_nr, len; | ||
| 180 | |||
| 181 | resource = kzalloc(sizeof(*resource), GFP_KERNEL); | ||
| 182 | if (!resource) { | ||
| 183 | printk(KERN_ERR "PCI: No memory for %s I/O port space\n", | ||
| 184 | info->name); | ||
| 185 | goto out; | ||
| 186 | } | ||
| 187 | |||
| 188 | len = strlen(info->name) + 32; | ||
| 189 | name = kzalloc(len, GFP_KERNEL); | ||
| 190 | if (!name) { | ||
| 191 | printk(KERN_ERR "PCI: No memory for %s I/O port space name\n", | ||
| 192 | info->name); | ||
| 193 | goto free_resource; | ||
| 194 | } | ||
| 195 | |||
| 196 | min = addr->min_address_range; | ||
| 197 | max = min + addr->address_length - 1; | ||
| 198 | if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) | ||
| 199 | sparse = 1; | ||
| 200 | |||
| 201 | space_nr = new_space(addr->address_translation_offset, sparse); | ||
| 202 | if (space_nr == ~0) | ||
| 203 | goto free_name; | ||
| 204 | |||
| 205 | base = __pa(io_space[space_nr].mmio_base); | ||
| 206 | base_port = IO_SPACE_BASE(space_nr); | ||
| 207 | snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name, | ||
| 208 | base_port + min, base_port + max); | ||
| 209 | |||
| 210 | /* | ||
| 211 | * The SDM guarantees the legacy 0-64K space is sparse, but if the | ||
| 212 | * mapping is done by the processor (not the bridge), ACPI may not | ||
| 213 | * mark it as sparse. | ||
| 214 | */ | ||
| 215 | if (space_nr == 0) | ||
| 216 | sparse = 1; | ||
| 217 | |||
| 218 | resource->name = name; | ||
| 219 | resource->flags = IORESOURCE_MEM; | ||
| 220 | resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min); | ||
| 221 | resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max); | ||
| 222 | insert_resource(&iomem_resource, resource); | ||
| 223 | |||
| 224 | return base_port; | ||
| 225 | |||
| 226 | free_name: | ||
| 227 | kfree(name); | ||
| 228 | free_resource: | ||
| 229 | kfree(resource); | ||
| 230 | out: | ||
| 231 | return ~0; | ||
| 169 | } | 232 | } |
| 170 | 233 | ||
| 171 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, | 234 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, |
| @@ -205,11 +268,6 @@ count_window (struct acpi_resource *resource, void *data) | |||
| 205 | return AE_OK; | 268 | return AE_OK; |
| 206 | } | 269 | } |
| 207 | 270 | ||
| 208 | struct pci_root_info { | ||
| 209 | struct pci_controller *controller; | ||
| 210 | char *name; | ||
| 211 | }; | ||
| 212 | |||
| 213 | static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | 271 | static __devinit acpi_status add_window(struct acpi_resource *res, void *data) |
| 214 | { | 272 | { |
| 215 | struct pci_root_info *info = data; | 273 | struct pci_root_info *info = data; |
| @@ -231,7 +289,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
| 231 | } else if (addr.resource_type == ACPI_IO_RANGE) { | 289 | } else if (addr.resource_type == ACPI_IO_RANGE) { |
| 232 | flags = IORESOURCE_IO; | 290 | flags = IORESOURCE_IO; |
| 233 | root = &ioport_resource; | 291 | root = &ioport_resource; |
| 234 | offset = add_io_space(&addr); | 292 | offset = add_io_space(info, &addr); |
| 235 | if (offset == ~0) | 293 | if (offset == ~0) |
| 236 | return AE_OK; | 294 | return AE_OK; |
| 237 | } else | 295 | } else |
| @@ -241,7 +299,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
| 241 | window->resource.name = info->name; | 299 | window->resource.name = info->name; |
| 242 | window->resource.flags = flags; | 300 | window->resource.flags = flags; |
| 243 | window->resource.start = addr.min_address_range + offset; | 301 | window->resource.start = addr.min_address_range + offset; |
| 244 | window->resource.end = addr.max_address_range + offset; | 302 | window->resource.end = window->resource.start + addr.address_length - 1; |
| 245 | window->resource.child = NULL; | 303 | window->resource.child = NULL; |
| 246 | window->offset = offset; | 304 | window->offset = offset; |
| 247 | 305 | ||
| @@ -739,7 +797,7 @@ int pci_vector_resources(int last, int nr_released) | |||
| 739 | { | 797 | { |
| 740 | int count = nr_released; | 798 | int count = nr_released; |
| 741 | 799 | ||
| 742 | count += (IA64_LAST_DEVICE_VECTOR - last); | 800 | count += (IA64_LAST_DEVICE_VECTOR - last); |
| 743 | 801 | ||
| 744 | return count; | 802 | return count; |
| 745 | } | 803 | } |
