pcimmap: if the requested page is marked prefetchable in a child device's

BAR, pass the BUS_SPACE_MAP_PREFETCHABLE flag down to bus_space_mmap
This commit is contained in:
jmcneill 2011-02-10 12:37:58 +00:00
parent b94121255b
commit 61ccff524d
3 changed files with 58 additions and 9 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pci.c,v 1.131 2011/02/01 19:37:37 dyoung Exp $ */
/* $NetBSD: pci.c,v 1.132 2011/02/10 12:37:58 jmcneill Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.131 2011/02/01 19:37:37 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.132 2011/02/10 12:37:58 jmcneill Exp $");
#include "opt_pci.h"
@ -272,8 +272,8 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
{
pci_chipset_tag_t pc = sc->sc_pc;
struct pci_attach_args pa;
pcireg_t id, csr, class, intr, bhlcr;
int ret, pin, bus, device, function;
pcireg_t id, csr, class, intr, bhlcr, bar;
int ret, pin, bus, device, function, i, width;
int locs[PCICF_NLOCS];
pci_decompose_tag(pc, tag, &bus, &device, &function);
@ -297,6 +297,27 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
if (PCI_VENDOR(id) == 0)
return 0;
/* Collect memory range info */
memset(sc->PCI_SC_DEVICESC(device, function).c_range, 0,
sizeof(sc->PCI_SC_DEVICESC(device, function).c_range));
i = 0;
for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += width) {
int type = pci_mapreg_type(pc, tag, bar);
struct pci_range *r;
width = 4;
if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) {
if (PCI_MAPREG_MEM_TYPE(type) ==
PCI_MAPREG_MEM_TYPE_64BIT)
width = 8;
r = &sc->PCI_SC_DEVICESC(device, function).c_range[i++];
if (pci_mapreg_info(pc, tag, bar, type,
&r->r_offset, &r->r_size, &r->r_flags) != 0)
break;
}
}
pa.pa_iot = sc->sc_iot;
pa.pa_memt = sc->sc_memt;
pa.pa_dmat = sc->sc_dmat;

View File

@ -1,4 +1,4 @@
/* $NetBSD: pci_usrreq.c,v 1.22 2009/07/30 04:38:24 macallan Exp $ */
/* $NetBSD: pci_usrreq.c,v 1.23 2011/02/10 12:37:58 jmcneill Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pci_usrreq.c,v 1.22 2009/07/30 04:38:24 macallan Exp $");
__KERNEL_RCSID(0, "$NetBSD: pci_usrreq.c,v 1.23 2011/02/10 12:37:58 jmcneill Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -114,6 +114,10 @@ static paddr_t
pcimmap(dev_t dev, off_t offset, int prot)
{
struct pci_softc *sc = device_lookup_private(&pci_cd, minor(dev));
struct pci_child *c;
struct pci_range *r;
int flags = 0;
int device, range;
if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER,
NULL) != 0) {
@ -124,7 +128,7 @@ pcimmap(dev_t dev, off_t offset, int prot)
* take the offset to be the address on the bus,
* and pass 0 as the offset into that range.
*
* XXX Need a way to deal with linear/prefetchable/etc.
* XXX Need a way to deal with linear/etc.
*
* XXX we rely on MD mmap() methods to enforce limits since these
* are hidden in *_tag_t structs if they exist at all
@ -145,7 +149,24 @@ pcimmap(dev_t dev, off_t offset, int prot)
0, prot, 0);
}
#endif /* PCI_MAGIC_IO_RANGE */
return bus_space_mmap(sc->sc_memt, offset, 0, prot, 0);
for (device = 0; device < __arraycount(sc->sc_devices); device++) {
c = &sc->sc_devices[device];
if (c->c_dev == NULL)
continue;
for (range = 0; range < __arraycount(c->c_range); range++) {
r = &c->c_range[range];
if (r->r_size == 0)
break;
if (offset >= r->r_offset &&
offset < r->r_offset + r->r_size) {
flags = r->r_flags;
break;
}
}
}
return bus_space_mmap(sc->sc_memt, offset, 0, prot, flags);
}
const struct cdevsw pci_cdevsw = {

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcivar.h,v 1.90 2010/06/09 02:39:32 mrg Exp $ */
/* $NetBSD: pcivar.h,v 1.91 2011/02/10 12:37:58 jmcneill Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -196,11 +196,18 @@ struct pci_conf_state {
pcireg_t reg[16];
};
struct pci_range {
bus_addr_t r_offset;
bus_size_t r_size;
int r_flags;
};
struct pci_child {
device_t c_dev;
bool c_psok;
pcireg_t c_powerstate;
struct pci_conf_state c_conf;
struct pci_range c_range[8];
};
struct pci_softc {