res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
}
res->end = res->start + (unsigned long) sz;
- res->flags |= pci_calc_resource_flags(l);
+ res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
if (is_64bit_memory(l)) {
u32 szhi, lhi;
if (sz) {
res->flags = (l & IORESOURCE_ROM_ENABLE) |
IORESOURCE_MEM | IORESOURCE_PREFETCH |
- IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
+ IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
+ IORESOURCE_SIZEALIGN;
res->start = l & PCI_ROM_ADDRESS_MASK;
res->end = res->start + (unsigned long) sz;
}
res = list->res;
idx = res - &list->dev->resource[0];
if (pci_assign_resource(list->dev, idx)) {
+ /* FIXME: get rid of this */
res->start = 0;
res->end = 0;
res->flags = 0;
/* Alignment of the IO window is always 4K */
b_res->start = 4096;
b_res->end = b_res->start + size - 1;
+ b_res->flags |= IORESOURCE_STARTALIGN;
}
/* Calculate the size of the bus and minimal alignment which
}
b_res->start = min_align;
b_res->end = size + min_align - 1;
+ b_res->flags |= IORESOURCE_STARTALIGN;
return 1;
}
size = res->end - res->start + 1;
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
- /* The bridge resources are special, as their
- size != alignment. Sizing routines return
- required alignment in the "start" field. */
- align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
+
+ align = resource_alignment(res);
+ if (!align) {
+ printk(KERN_ERR "PCI: Cannot allocate resource (bogus "
+ "alignment) %d [%llx:%llx] (flags %lx) of %s\n",
+ resno, (unsigned long long)res->start,
+ (unsigned long long)res->end, res->flags,
+ pci_name(dev));
+ return -EINVAL;
+ }
/* First, try exact prefetching match.. */
ret = pci_bus_alloc_resource(bus, res, size, align, min,
res->flags & IORESOURCE_IO ? "I/O" : "mem",
resno, (unsigned long long)size,
(unsigned long long)res->start, pci_name(dev));
- } else if (resno < PCI_BRIDGE_RESOURCES) {
- pci_update_resource(dev, res, resno);
+ } else {
+ res->flags &= ~IORESOURCE_STARTALIGN;
+ if (resno < PCI_BRIDGE_RESOURCES)
+ pci_update_resource(dev, res, resno);
}
return ret;
if (r->flags & IORESOURCE_PCI_FIXED)
continue;
- r_align = r->end - r->start;
-
if (!(r->flags) || r->parent)
continue;
+
+ r_align = resource_alignment(r);
if (!r_align) {
- printk(KERN_WARNING "PCI: Ignore bogus resource %d "
- "[%llx:%llx] of %s\n",
+ printk(KERN_WARNING "PCI: bogus alignment of resource "
+ "%d [%llx:%llx] (flags %lx) of %s\n",
i, (unsigned long long)r->start,
- (unsigned long long)r->end, pci_name(dev));
+ (unsigned long long)r->end, r->flags,
+ pci_name(dev));
continue;
}
- r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
for (list = head; ; list = list->next) {
resource_size_t align = 0;
struct resource_list *ln = list->next;
- int idx;
- if (ln) {
- idx = ln->res - &ln->dev->resource[0];
- align = (idx < PCI_BRIDGE_RESOURCES) ?
- ln->res->end - ln->res->start + 1 :
- ln->res->start;
- }
+ if (ln)
+ align = resource_alignment(ln->res);
+
if (r_align > align) {
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp)
#define IORESOURCE_CACHEABLE 0x00004000
#define IORESOURCE_RANGELENGTH 0x00008000
#define IORESOURCE_SHADOWABLE 0x00010000
-#define IORESOURCE_BUS_HAS_VGA 0x00080000
+
+#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */
+#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000
void *alignf_data);
int adjust_resource(struct resource *res, resource_size_t start,
resource_size_t size);
+resource_size_t resource_alignment(struct resource *res);
/* Convenience shorthand with allocation */
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))
EXPORT_SYMBOL(adjust_resource);
+/**
+ * resource_alignment - calculate resource's alignment
+ * @res: resource pointer
+ *
+ * Returns alignment on success, 0 (invalid alignment) on failure.
+ */
+resource_size_t resource_alignment(struct resource *res)
+{
+ switch (res->flags & (IORESOURCE_SIZEALIGN | IORESOURCE_STARTALIGN)) {
+ case IORESOURCE_SIZEALIGN:
+ return res->end - res->start + 1;
+ case IORESOURCE_STARTALIGN:
+ return res->start;
+ default:
+ return 0;
+ }
+}
+
/*
* This is compatibility stuff for IO resources.
*