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; }