aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/pci/pci.c106
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
97static struct pci_raw_ops pci_sal_ops = { 97static 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
140static u64 __devinit 140struct pci_root_info {
141add_io_space (struct acpi_resource_address64 *addr) 141 struct pci_controller *controller;
142 char *name;
143};
144
145static unsigned int
146new_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
173static u64 __devinit
174add_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
226free_name:
227 kfree(name);
228free_resource:
229 kfree(resource);
230out:
231 return ~0;
169} 232}
170 233
171static acpi_status __devinit resource_to_window(struct acpi_resource *resource, 234static 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
208struct pci_root_info {
209 struct pci_controller *controller;
210 char *name;
211};
212
213static __devinit acpi_status add_window(struct acpi_resource *res, void *data) 271static __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}