Module Name: src
Committed By: matt
Date: Sat Oct 20 06:09:07 UTC 2012
Modified Files:
src/sys/dev/pci: pciconf.c
Log Message:
Enforce alignments for buses.
To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/dev/pci/pciconf.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/pciconf.c
diff -u src/sys/dev/pci/pciconf.c:1.35 src/sys/dev/pci/pciconf.c:1.36
--- src/sys/dev/pci/pciconf.c:1.35 Sat Oct 20 05:33:00 2012
+++ src/sys/dev/pci/pciconf.c Sat Oct 20 06:09:07 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: pciconf.c,v 1.35 2012/10/20 05:33:00 matt Exp $ */
+/* $NetBSD: pciconf.c,v 1.36 2012/10/20 06:09:07 matt Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.35 2012/10/20 05:33:00 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.36 2012/10/20 06:09:07 matt Exp $");
#include "opt_pci.h"
@@ -131,6 +131,9 @@ typedef struct _s_pciconf_bus_t {
int swiz;
int io_32bit;
int pmem_64bit;
+ int io_align;
+ int mem_align;
+ int pmem_align;
int ndevs;
pciconf_dev_t device[MAX_CONF_DEV];
@@ -324,6 +327,10 @@ query_bus(pciconf_bus_t *parent, pciconf
pb->parent_bus = parent;
alloc_busno(parent, pb);
+ pb->mem_align = 0x100000; /* 1M alignment */
+ pb->pmem_align = 0x100000; /* 1M alignment */
+ pb->io_align = 0x1000; /* 4K alignment */
+
set_busreg(parent->pc, pd->tag, parent->busno, pb->busno, 0xff);
pb->swiz = parent->swiz + dev;
@@ -371,12 +378,14 @@ query_bus(pciconf_bus_t *parent, pciconf
parent->niowin);
goto err;
}
- pb->io_total |= 0xfff; /* Round up */
+ pb->io_total |= pb->io_align - 1; /* Round up */
pi = get_io_desc(parent, pb->io_total);
pi->dev = pd;
pi->reg = 0;
pi->size = pb->io_total;
- pi->align = 0x1000; /* 4K alignment */
+ pi->align = pb->io_align; /* 4K min alignment */
+ if (parent->io_align < pb->io_align)
+ parent->io_align = pb->io_align;
pi->prefetch = 0;
parent->niowin++;
parent->io_total += pb->io_total;
@@ -388,12 +397,14 @@ query_bus(pciconf_bus_t *parent, pciconf
parent->nmemwin);
goto err;
}
- pb->mem_total |= 0xfffff; /* Round up */
+ pb->mem_total |= pb->mem_align-1; /* Round up */
pm = get_mem_desc(parent, pb->mem_total);
pm->dev = pd;
pm->reg = 0;
pm->size = pb->mem_total;
- pm->align = 0x100000; /* 1M alignment */
+ pm->align = pb->mem_align; /* 1M min alignment */
+ if (parent->mem_align < pb->mem_align)
+ parent->mem_align = pb->mem_align;
pm->prefetch = 0;
parent->nmemwin++;
parent->mem_total += pb->mem_total;
@@ -404,12 +415,14 @@ query_bus(pciconf_bus_t *parent, pciconf
printf("pciconf: too many MEM windows\n");
goto err;
}
- pb->pmem_total |= 0xfffff; /* Round up */
+ pb->pmem_total |= pb->pmem_align-1; /* Round up */
pm = get_mem_desc(parent, pb->pmem_total);
pm->dev = pd;
pm->reg = 0;
pm->size = pb->pmem_total;
- pm->align = 0x100000; /* 1M alignment */
+ pm->align = pb->pmem_align; /* 1M alignment */
+ if (parent->pmem_align < pb->pmem_align)
+ parent->pmem_align = pb->pmem_align;
pm->prefetch = 1;
parent->nmemwin++;
parent->pmem_total += pb->pmem_total;
@@ -550,6 +563,8 @@ pci_do_device_query(pciconf_bus_t *pb, p
pi->reg = br;
pi->size = (u_int64_t) size;
pi->align = 4;
+ if (pb->io_align < pi->size)
+ pb->io_align = pi->size;
pi->prefetch = 0;
if (pci_conf_debug) {
print_tag(pb->pc, tag);
@@ -593,7 +608,7 @@ pci_do_device_query(pciconf_bus_t *pb, p
} else {
if (pci_conf_debug) {
print_tag(pb->pc, tag);
- printf("MEM%d BAR 0x%x has size %lx\n",
+ printf("MEM%d BAR 0x%x has size %#lx\n",
PCI_MAPREG_MEM_TYPE(mask) ==
PCI_MAPREG_MEM_TYPE_64BIT ?
64 : 32, br, (unsigned long)size);
@@ -619,8 +634,12 @@ pci_do_device_query(pciconf_bus_t *pb, p
pb->nmemwin++;
if (pm->prefetch) {
pb->pmem_total += size;
+ if (pb->pmem_align < pm->size)
+ pb->pmem_align = pm->size;
} else {
pb->mem_total += size;
+ if (pb->mem_align < pm->size)
+ pb->mem_align = pm->size;
}
}
}
@@ -681,12 +700,12 @@ pci_allocate_range(struct extent *ex, u_
r = extent_alloc(ex, amt, align, 0, EX_NOWAIT, &addr);
if (r) {
- addr = (u_long) -1;
- printf("extent_alloc(%p, %" PRIu64 ", %d) returned %d\n",
+ printf("extent_alloc(%p, %#" PRIx64 ", %#x) returned %d\n",
ex, amt, align, r);
extent_print(ex);
+ return ~0ULL;
}
- return (pcireg_t) addr;
+ return addr;
}
static int
@@ -702,7 +721,7 @@ setup_iowins(pciconf_bus_t *pb)
pd = pi->dev;
pi->address = pci_allocate_range(pb->ioext, pi->size,
pi->align);
- if (pi->address == -1) {
+ if (~pi->address == 0) {
print_tag(pd->pc, pd->tag);
printf("Failed to allocate PCI I/O space (%"
PRIu64 " req)\n", pi->size);
@@ -752,7 +771,7 @@ setup_memwins(pciconf_bus_t *pb)
pd = pm->dev;
ex = (pm->prefetch) ? pb->pmemext : pb->memext;
pm->address = pci_allocate_range(ex, pm->size, pm->align);
- if (pm->address == -1) {
+ if (~pm->address == 0) {
print_tag(pd->pc, pd->tag);
printf(
"Failed to allocate PCI memory space (%" PRIu64
@@ -994,8 +1013,8 @@ configure_bus(pciconf_bus_t *pb)
* of free memory ranges from the m.d. system.
*/
if (setup_iowins(pb) || setup_memwins(pb)) {
- printf("PCI bus configuration failed: ");
- printf("unable to assign all I/O and memory ranges.");
+ printf("PCI bus configuration failed: "
+ "unable to assign all I/O and memory ranges.\n");
return -1;
}