Module Name:    src
Committed By:   jmcneill
Date:           Thu Feb 10 12:37:58 UTC 2011

Modified Files:
        src/sys/dev/pci: pci.c pci_usrreq.c pcivar.h

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.131 -r1.132 src/sys/dev/pci/pci.c
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/pci/pci_usrreq.c
cvs rdiff -u -r1.90 -r1.91 src/sys/dev/pci/pcivar.h

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/pci.c
diff -u src/sys/dev/pci/pci.c:1.131 src/sys/dev/pci/pci.c:1.132
--- src/sys/dev/pci/pci.c:1.131	Tue Feb  1 19:37:37 2011
+++ src/sys/dev/pci/pci.c	Thu Feb 10 12:37:58 2011
@@ -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_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 @@
 	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;

Index: src/sys/dev/pci/pci_usrreq.c
diff -u src/sys/dev/pci/pci_usrreq.c:1.22 src/sys/dev/pci/pci_usrreq.c:1.23
--- src/sys/dev/pci/pci_usrreq.c:1.22	Thu Jul 30 04:38:24 2009
+++ src/sys/dev/pci/pci_usrreq.c	Thu Feb 10 12:37:58 2011
@@ -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 @@
 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 @@
 	 * 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 @@
 		    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 = {

Index: src/sys/dev/pci/pcivar.h
diff -u src/sys/dev/pci/pcivar.h:1.90 src/sys/dev/pci/pcivar.h:1.91
--- src/sys/dev/pci/pcivar.h:1.90	Wed Jun  9 02:39:32 2010
+++ src/sys/dev/pci/pcivar.h	Thu Feb 10 12:37:58 2011
@@ -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 @@
 	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 {

Reply via email to