aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-res.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/setup-res.c')
-rw-r--r--drivers/pci/setup-res.c87
1 files changed, 67 insertions, 20 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 4be7ccf7e3ae..7d35cdf4579f 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -137,10 +137,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
137 137
138 size = res->end - res->start + 1; 138 size = res->end - res->start + 1;
139 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; 139 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
140 /* The bridge resources are special, as their 140
141 size != alignment. Sizing routines return 141 align = resource_alignment(res);
142 required alignment in the "start" field. */ 142 if (!align) {
143 align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start; 143 printk(KERN_ERR "PCI: Cannot allocate resource (bogus "
144 "alignment) %d [%llx:%llx] (flags %lx) of %s\n",
145 resno, (unsigned long long)res->start,
146 (unsigned long long)res->end, res->flags,
147 pci_name(dev));
148 return -EINVAL;
149 }
144 150
145 /* First, try exact prefetching match.. */ 151 /* First, try exact prefetching match.. */
146 ret = pci_bus_alloc_resource(bus, res, size, align, min, 152 ret = pci_bus_alloc_resource(bus, res, size, align, min,
@@ -164,14 +170,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
164 res->flags & IORESOURCE_IO ? "I/O" : "mem", 170 res->flags & IORESOURCE_IO ? "I/O" : "mem",
165 resno, (unsigned long long)size, 171 resno, (unsigned long long)size,
166 (unsigned long long)res->start, pci_name(dev)); 172 (unsigned long long)res->start, pci_name(dev));
167 } else if (resno < PCI_BRIDGE_RESOURCES) { 173 } else {
168 pci_update_resource(dev, res, resno); 174 res->flags &= ~IORESOURCE_STARTALIGN;
175 if (resno < PCI_BRIDGE_RESOURCES)
176 pci_update_resource(dev, res, resno);
169 } 177 }
170 178
171 return ret; 179 return ret;
172} 180}
173 181
174#ifdef CONFIG_EMBEDDED 182#if 0
175int pci_assign_resource_fixed(struct pci_dev *dev, int resno) 183int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
176{ 184{
177 struct pci_bus *bus = dev->bus; 185 struct pci_bus *bus = dev->bus;
@@ -226,29 +234,25 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
226 if (r->flags & IORESOURCE_PCI_FIXED) 234 if (r->flags & IORESOURCE_PCI_FIXED)
227 continue; 235 continue;
228 236
229 r_align = r->end - r->start;
230
231 if (!(r->flags) || r->parent) 237 if (!(r->flags) || r->parent)
232 continue; 238 continue;
239
240 r_align = resource_alignment(r);
233 if (!r_align) { 241 if (!r_align) {
234 printk(KERN_WARNING "PCI: Ignore bogus resource %d " 242 printk(KERN_WARNING "PCI: bogus alignment of resource "
235 "[%llx:%llx] of %s\n", 243 "%d [%llx:%llx] (flags %lx) of %s\n",
236 i, (unsigned long long)r->start, 244 i, (unsigned long long)r->start,
237 (unsigned long long)r->end, pci_name(dev)); 245 (unsigned long long)r->end, r->flags,
246 pci_name(dev));
238 continue; 247 continue;
239 } 248 }
240 r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
241 for (list = head; ; list = list->next) { 249 for (list = head; ; list = list->next) {
242 resource_size_t align = 0; 250 resource_size_t align = 0;
243 struct resource_list *ln = list->next; 251 struct resource_list *ln = list->next;
244 int idx;
245 252
246 if (ln) { 253 if (ln)
247 idx = ln->res - &ln->dev->resource[0]; 254 align = resource_alignment(ln->res);
248 align = (idx < PCI_BRIDGE_RESOURCES) ? 255
249 ln->res->end - ln->res->start + 1 :
250 ln->res->start;
251 }
252 if (r_align > align) { 256 if (r_align > align) {
253 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); 257 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
254 if (!tmp) 258 if (!tmp)
@@ -263,3 +267,46 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
263 } 267 }
264 } 268 }
265} 269}
270
271int pci_enable_resources(struct pci_dev *dev, int mask)
272{
273 u16 cmd, old_cmd;
274 int i;
275 struct resource *r;
276
277 pci_read_config_word(dev, PCI_COMMAND, &cmd);
278 old_cmd = cmd;
279
280 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
281 if (!(mask & (1 << i)))
282 continue;
283
284 r = &dev->resource[i];
285
286 if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
287 continue;
288 if ((i == PCI_ROM_RESOURCE) &&
289 (!(r->flags & IORESOURCE_ROM_ENABLE)))
290 continue;
291
292 if (!r->parent) {
293 dev_err(&dev->dev, "device not available because of "
294 "BAR %d [%llx:%llx] collisions\n", i,
295 (unsigned long long) r->start,
296 (unsigned long long) r->end);
297 return -EINVAL;
298 }
299
300 if (r->flags & IORESOURCE_IO)
301 cmd |= PCI_COMMAND_IO;
302 if (r->flags & IORESOURCE_MEM)
303 cmd |= PCI_COMMAND_MEMORY;
304 }
305
306 if (cmd != old_cmd) {
307 dev_info(&dev->dev, "enabling device (%04x -> %04x)\n",
308 old_cmd, cmd);
309 pci_write_config_word(dev, PCI_COMMAND, cmd);
310 }
311 return 0;
312}