diff options
author | Len Brown <len.brown@intel.com> | 2005-12-06 17:31:30 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-12-06 17:31:30 -0500 |
commit | 3d5271f9883cba7b54762bc4fe027d4172f06db7 (patch) | |
tree | ab8a881a14478598a0c8bda0d26c62cdccfffd6d /arch/ia64/pci | |
parent | 378b2556f4e09fa6f87ff0cb5c4395ff28257d02 (diff) | |
parent | 9115a6c787596e687df03010d97fccc5e0762506 (diff) |
Pull release into acpica branch
Diffstat (limited to 'arch/ia64/pci')
-rw-r--r-- | arch/ia64/pci/pci.c | 164 |
1 files changed, 109 insertions, 55 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 9b5de589b82f..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 | ||
@@ -120,29 +120,6 @@ struct pci_ops pci_root_ops = { | |||
120 | .write = pci_write, | 120 | .write = pci_write, |
121 | }; | 121 | }; |
122 | 122 | ||
123 | #ifdef CONFIG_NUMA | ||
124 | extern acpi_status acpi_map_iosapic(acpi_handle, u32, void *, void **); | ||
125 | static void acpi_map_iosapics(void) | ||
126 | { | ||
127 | acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL); | ||
128 | } | ||
129 | #else | ||
130 | static void acpi_map_iosapics(void) | ||
131 | { | ||
132 | return; | ||
133 | } | ||
134 | #endif /* CONFIG_NUMA */ | ||
135 | |||
136 | static int __init | ||
137 | pci_acpi_init (void) | ||
138 | { | ||
139 | acpi_map_iosapics(); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | subsys_initcall(pci_acpi_init); | ||
145 | |||
146 | /* Called by ACPI when it finds a new root bus. */ | 123 | /* Called by ACPI when it finds a new root bus. */ |
147 | 124 | ||
148 | static struct pci_controller * __devinit | 125 | static struct pci_controller * __devinit |
@@ -160,35 +137,121 @@ alloc_pci_controller (int seg) | |||
160 | return controller; | 137 | return controller; |
161 | } | 138 | } |
162 | 139 | ||
163 | static u64 __devinit | 140 | struct pci_root_info { |
164 | 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) | ||
165 | { | 147 | { |
166 | u64 offset; | 148 | u64 mmio_base; |
167 | int sparse = 0; | ||
168 | int i; | 149 | int i; |
169 | 150 | ||
170 | if (addr->address_translation_offset == 0) | 151 | if (phys_base == 0) |
171 | return IO_SPACE_BASE(0); /* part of legacy IO space */ | 152 | return 0; /* legacy I/O port space */ |
172 | |||
173 | if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) | ||
174 | sparse = 1; | ||
175 | 153 | ||
176 | offset = (u64) ioremap(addr->address_translation_offset, 0); | 154 | mmio_base = (u64) ioremap(phys_base, 0); |
177 | for (i = 0; i < num_io_spaces; i++) | 155 | for (i = 0; i < num_io_spaces; i++) |
178 | if (io_space[i].mmio_base == offset && | 156 | if (io_space[i].mmio_base == mmio_base && |
179 | io_space[i].sparse == sparse) | 157 | io_space[i].sparse == sparse) |
180 | return IO_SPACE_BASE(i); | 158 | return i; |
181 | 159 | ||
182 | if (num_io_spaces == MAX_IO_SPACES) { | 160 | if (num_io_spaces == MAX_IO_SPACES) { |
183 | 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); | ||
184 | return ~0; | 163 | return ~0; |
185 | } | 164 | } |
186 | 165 | ||
187 | i = num_io_spaces++; | 166 | i = num_io_spaces++; |
188 | io_space[i].mmio_base = offset; | 167 | io_space[i].mmio_base = mmio_base; |
189 | io_space[i].sparse = sparse; | 168 | io_space[i].sparse = sparse; |
190 | 169 | ||
191 | 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; | ||
232 | } | ||
233 | |||
234 | static acpi_status __devinit resource_to_window(struct acpi_resource *resource, | ||
235 | struct acpi_resource_address64 *addr) | ||
236 | { | ||
237 | acpi_status status; | ||
238 | |||
239 | /* | ||
240 | * We're only interested in _CRS descriptors that are | ||
241 | * - address space descriptors for memory or I/O space | ||
242 | * - non-zero size | ||
243 | * - producers, i.e., the address space is routed downstream, | ||
244 | * not consumed by the bridge itself | ||
245 | */ | ||
246 | status = acpi_resource_to_address64(resource, addr); | ||
247 | if (ACPI_SUCCESS(status) && | ||
248 | (addr->resource_type == ACPI_MEMORY_RANGE || | ||
249 | addr->resource_type == ACPI_IO_RANGE) && | ||
250 | addr->address_length && | ||
251 | addr->producer_consumer == ACPI_PRODUCER) | ||
252 | return AE_OK; | ||
253 | |||
254 | return AE_ERROR; | ||
192 | } | 255 | } |
193 | 256 | ||
194 | static acpi_status __devinit | 257 | static acpi_status __devinit |
@@ -198,20 +261,13 @@ count_window (struct acpi_resource *resource, void *data) | |||
198 | struct acpi_resource_address64 addr; | 261 | struct acpi_resource_address64 addr; |
199 | acpi_status status; | 262 | acpi_status status; |
200 | 263 | ||
201 | status = acpi_resource_to_address64(resource, &addr); | 264 | status = resource_to_window(resource, &addr); |
202 | if (ACPI_SUCCESS(status)) | 265 | if (ACPI_SUCCESS(status)) |
203 | if (addr.resource_type == ACPI_MEMORY_RANGE || | 266 | (*windows)++; |
204 | addr.resource_type == ACPI_IO_RANGE) | ||
205 | (*windows)++; | ||
206 | 267 | ||
207 | return AE_OK; | 268 | return AE_OK; |
208 | } | 269 | } |
209 | 270 | ||
210 | struct pci_root_info { | ||
211 | struct pci_controller *controller; | ||
212 | char *name; | ||
213 | }; | ||
214 | |||
215 | 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) |
216 | { | 272 | { |
217 | struct pci_root_info *info = data; | 273 | struct pci_root_info *info = data; |
@@ -221,13 +277,11 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
221 | unsigned long flags, offset = 0; | 277 | unsigned long flags, offset = 0; |
222 | struct resource *root; | 278 | struct resource *root; |
223 | 279 | ||
224 | status = acpi_resource_to_address64(res, &addr); | 280 | /* Return AE_OK for non-window resources to keep scanning for more */ |
281 | status = resource_to_window(res, &addr); | ||
225 | if (!ACPI_SUCCESS(status)) | 282 | if (!ACPI_SUCCESS(status)) |
226 | return AE_OK; | 283 | return AE_OK; |
227 | 284 | ||
228 | if (!addr.address_length) | ||
229 | return AE_OK; | ||
230 | |||
231 | if (addr.resource_type == ACPI_MEMORY_RANGE) { | 285 | if (addr.resource_type == ACPI_MEMORY_RANGE) { |
232 | flags = IORESOURCE_MEM; | 286 | flags = IORESOURCE_MEM; |
233 | root = &iomem_resource; | 287 | root = &iomem_resource; |
@@ -235,7 +289,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
235 | } else if (addr.resource_type == ACPI_IO_RANGE) { | 289 | } else if (addr.resource_type == ACPI_IO_RANGE) { |
236 | flags = IORESOURCE_IO; | 290 | flags = IORESOURCE_IO; |
237 | root = &ioport_resource; | 291 | root = &ioport_resource; |
238 | offset = add_io_space(&addr); | 292 | offset = add_io_space(info, &addr); |
239 | if (offset == ~0) | 293 | if (offset == ~0) |
240 | return AE_OK; | 294 | return AE_OK; |
241 | } else | 295 | } else |
@@ -245,7 +299,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) | |||
245 | window->resource.name = info->name; | 299 | window->resource.name = info->name; |
246 | window->resource.flags = flags; | 300 | window->resource.flags = flags; |
247 | window->resource.start = addr.min_address_range + offset; | 301 | window->resource.start = addr.min_address_range + offset; |
248 | window->resource.end = addr.max_address_range + offset; | 302 | window->resource.end = window->resource.start + addr.address_length - 1; |
249 | window->resource.child = NULL; | 303 | window->resource.child = NULL; |
250 | window->offset = offset; | 304 | window->offset = offset; |
251 | 305 | ||
@@ -743,7 +797,7 @@ int pci_vector_resources(int last, int nr_released) | |||
743 | { | 797 | { |
744 | int count = nr_released; | 798 | int count = nr_released; |
745 | 799 | ||
746 | count += (IA64_LAST_DEVICE_VECTOR - last); | 800 | count += (IA64_LAST_DEVICE_VECTOR - last); |
747 | 801 | ||
748 | return count; | 802 | return count; |
749 | } | 803 | } |