Module Name: src Committed By: riastradh Date: Mon Dec 2 08:33:42 UTC 2019
Modified Files: src/sys/dev/pci: pci_map.c Log Message: Use BUS_SPACE_MAP_PREFETCHABLE only if BAR and driver agree on it. - A driver that expects prefetchable memory and knows to issue the needed bus_space_barrier calls can pass BUS_SPACE_MAP_PREFETCHABLE to indicate a desire to map the memory prefetchable if the BAR allows it. (A driver that _really wants_ BUS_SPACE_MAP_PREFETCHABLE even if the BAR claims _not_ to be prefetchable can use pci_mapreg_info and bus_space_map explicitly -- this is not different from what we have today.) - For a driver that _does not_ expect prefetchable memory, the appearance of the prefetchable bit in the BAR shouldn't cause it to use BUS_SPACE_MAP_PREFETCHABLE, because the driver will not issue the needed bus_space_barrier calls to get sensible results. Note: `Prefetchable' here, sometimes called `write-combining', means reads have no side effects, and writes are idempotent, so it is safe to issue reads out of order and safe to combine writes. Mappings with BUS_SPACE_MAP_PREFETCHABLE are often more weakly ordered than normal memory -- e.g., on x86, in WC-type memory regions, loads can be reordered with loads, stores can be reordered with stores, which is not possible with any other type of memory regions. Discussed on tech-kern a while ago: https://mail-index.NetBSD.org/tech-kern/2017/03/22/msg021678.html This is option A, which received the most support. This should help unconfuse drivers that do not expect prefetchable mappings, like Yamaguchi-san tripped over recently: https://mail-index.NetBSD.org/tech-kern/2019/12/02/msg025785.html To generate a diff of this commit: cvs rdiff -u -r1.37 -r1.38 src/sys/dev/pci/pci_map.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/pci_map.c diff -u src/sys/dev/pci/pci_map.c:1.37 src/sys/dev/pci/pci_map.c:1.38 --- src/sys/dev/pci/pci_map.c:1.37 Fri Mar 1 05:41:56 2019 +++ src/sys/dev/pci/pci_map.c Mon Dec 2 08:33:42 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_map.c,v 1.37 2019/03/01 05:41:56 msaitoh Exp $ */ +/* $NetBSD: pci_map.c,v 1.38 2019/12/02 08:33:42 riastradh Exp $ */ /*- * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_map.c,v 1.37 2019/03/01 05:41:56 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_map.c,v 1.38 2019/12/02 08:33:42 riastradh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -328,7 +328,25 @@ pci_mapreg_submap(const struct pci_attac if (realmaxsize < (offset + reqsize)) return 1; - if (bus_space_map(tag, base, reqsize, busflags | flags, &handle)) + /* + * If the BAR doesn't say prefetchable, assume the mapping + * cannot be prefetchable. In other words, we will use + * BUS_SPACE_MAP_PREFETCHABLE only if the driver requested it + * _and_ the BAR indicates it is prefetchable. + * + * Drivers that expect prefetchable memory will issue the + * appropriate barriers, whereas drivers that do not expect + * prefetchable memory will be terribly confused if the memory + * is mapped prefetchable. + * + * Drivers that want to override the BAR and map it with + * BUS_SPACE_MAP_PREFETCHABLE anyway can use pci_mapreg_map and + * bus_space_map explicitly. + */ + if (!ISSET(flags, BUS_SPACE_MAP_PREFETCHABLE)) + busflags &= ~BUS_SPACE_MAP_PREFETCHABLE; + + if (bus_space_map(tag, base, reqsize, busflags, &handle)) return 1; if (pci_mapreg_map_enable_decode) {