Module Name: src
Committed By: jmcneill
Date: Sun Nov 12 13:56:20 UTC 2023
Modified Files:
src/sys/dev/pci: pci_resource.c
Log Message:
pci: Improve resource allocation for non-prefetchable BARs.
When allocating resources for PCI devices, use the following criteria:
- Prefetchable memory must be allocated from the prefetchable range
of the parent bridge.
- For 64-bit MMIO, try the prefetchable range first, and fallback to
the non-prefetchable range. The idea here is to preserve 32-bit resources
for 32-bit BARs.
- For 32-bit MMIO, try the non-prefetchable range first. If that fails,
make one last attempt at allocating from the prefetchable range, in the
event that it has resources below 4GB.
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/pci_resource.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_resource.c
diff -u src/sys/dev/pci/pci_resource.c:1.3 src/sys/dev/pci/pci_resource.c:1.4
--- src/sys/dev/pci/pci_resource.c:1.3 Sat Oct 15 20:11:44 2022
+++ src/sys/dev/pci/pci_resource.c Sun Nov 12 13:56:20 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_resource.c,v 1.3 2022/10/15 20:11:44 riastradh Exp $ */
+/* $NetBSD: pci_resource.c,v 1.4 2023/11/12 13:56:20 jmcneill Exp $ */
/*-
* Copyright (c) 2022 Jared McNeill <[email protected]>
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_resource.c,v 1.3 2022/10/15 20:11:44 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_resource.c,v 1.4 2023/11/12 13:56:20 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -684,13 +684,46 @@ pci_resource_init_device(struct pci_reso
KASSERT(pi->pi_type == PCI_MAPREG_TYPE_MEM);
error = ERANGE;
- if (pi->pi_mem.prefetch && res_pmem != NULL) {
- error = pci_resource_claim(res_pmem, pi->pi_base,
- pi->pi_base + pi->pi_size - 1);
- }
- if (error && res_mem != NULL) {
- error = pci_resource_claim(res_mem, pi->pi_base,
- pi->pi_base + pi->pi_size - 1);
+ if (pi->pi_mem.prefetch) {
+ /*
+ * Prefetchable memory must be allocated from the
+ * bridge's prefetchable region.
+ */
+ if (res_pmem != NULL) {
+ error = pci_resource_claim(res_pmem, pi->pi_base,
+ pi->pi_base + pi->pi_size - 1);
+ }
+ } else if (pi->pi_mem.memtype == PCI_MAPREG_MEM_TYPE_64BIT) {
+ /*
+ * Non-prefetchable 64-bit memory can be allocated from
+ * any range. Prefer allocations from the prefetchable
+ * region to save 32-bit only resources for 32-bit BARs.
+ */
+ if (res_pmem != NULL) {
+ error = pci_resource_claim(res_pmem, pi->pi_base,
+ pi->pi_base + pi->pi_size - 1);
+ }
+ if (error && res_mem != NULL) {
+ error = pci_resource_claim(res_mem, pi->pi_base,
+ pi->pi_base + pi->pi_size - 1);
+ }
+ } else {
+ /*
+ * Non-prefetchable 32-bit memory can be allocated from
+ * any range, provided that the range is below 4GB. Try
+ * the non-prefetchable range first, and if that fails,
+ * make one last attempt at allocating from the
+ * prefetchable range in case the platform provides
+ * memory below 4GB.
+ */
+ if (res_mem != NULL) {
+ error = pci_resource_claim(res_mem, pi->pi_base,
+ pi->pi_base + pi->pi_size - 1);
+ }
+ if (error && res_pmem != NULL) {
+ error = pci_resource_claim(res_pmem, pi->pi_base,
+ pi->pi_base + pi->pi_size - 1);
+ }
}
if (error) {
DPRINT("PCI: " PCI_SBDF_FMT " [device] mem"