summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>2021-05-12 23:22:32 +0000
committerthorpej <thorpej@NetBSD.org>2021-05-12 23:22:32 +0000
commitc9e3fb791622deb2fd1b7960735b59878ee8ff98 (patch)
tree6f9586323d83079ccab50d4924ac8c6d7131ae43 /sys/dev
parentfdc5668ec1a83c8cd8574f5130233c93d4d6615b (diff)
- Define a device call for PCI bus instances to fetch a direct child's
device handle given the device's device/function #s (extracted from a pcitag_t). Use it to associate the handle with the child device at config_found() time. - Implement this device call for ACPI and OpenFirmware. - Enable the OpenFirmware variant for evbarm FDT, macppc, ofppc, sparc64. - Obsolete acpi_device_register(); it is no longer needed. - Obsolete setting the OpenFirmware handle in PCI devices in the sparc64 device_register(); it is no longer needed.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi/acpi.c41
-rw-r--r--sys/dev/acpi/acpi_pci.c40
-rw-r--r--sys/dev/acpi/acpivar.h3
-rw-r--r--sys/dev/ofw/files.ofw5
-rw-r--r--sys/dev/ofw/ofw_pci_subr.c86
-rw-r--r--sys/dev/pci/pci.c28
-rw-r--r--sys/dev/pci/pcivar.h27
7 files changed, 183 insertions, 47 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index e22ae4d4cd3..640f2a98774 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi.c,v 1.291 2021/04/24 23:36:52 thorpej Exp $ */
+/* $NetBSD: acpi.c,v 1.292 2021/05/12 23:22:33 thorpej Exp $ */
/*-
* Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.291 2021/04/24 23:36:52 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.292 2021/05/12 23:22:33 thorpej Exp $");
#include "pci.h"
#include "opt_acpi.h"
@@ -1146,43 +1146,6 @@ acpi_print(void *aux, const char *pnp)
}
/*
- * acpi_device_register --
- * Called by the platform device_register() routine when
- * attaching devices.
- */
-void
-acpi_device_register(device_t dev, void *v)
-{
- /* All we do here is set the devhandle in the device_t. */
- device_t parent = device_parent(dev);
- ACPI_HANDLE hdl = NULL;
-
- if (device_is_a(parent, "pci")) {
- const struct pci_attach_args *pa = v;
- struct acpi_devnode *ad;
- u_int segment;
-
-#ifdef __HAVE_PCI_GET_SEGMENT
- segment = pci_get_segment(pa->pa_pc);
-#else
- segment = 0;
-#endif /* __HAVE_PCI_GET_SEGMENT */
-
- ad = acpi_pcidev_find(segment,
- pa->pa_bus, pa->pa_device, pa->pa_function);
- if (ad == NULL || (hdl = ad->ad_handle) == NULL) {
- aprint_debug_dev(dev, "no matching ACPI node\n");
- return;
- }
- } else {
- return;
- }
- KASSERT(hdl != NULL);
-
- device_set_handle(dev, devhandle_from_acpi(hdl));
-}
-
-/*
* Notify.
*/
static void
diff --git a/sys/dev/acpi/acpi_pci.c b/sys/dev/acpi/acpi_pci.c
index 5ad32a05db9..b9beea0c7da 100644
--- a/sys/dev/acpi/acpi_pci.c
+++ b/sys/dev/acpi/acpi_pci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci.c,v 1.30 2021/01/14 14:37:17 thorpej Exp $ */
+/* $NetBSD: acpi_pci.c,v 1.31 2021/05/12 23:22:33 thorpej Exp $ */
/*
* Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.30 2021/01/14 14:37:17 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.31 2021/05/12 23:22:33 thorpej Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -542,3 +542,39 @@ acpi_pci_ignore_boot_config(ACPI_HANDLE handle)
return ret;
}
+
+/*
+ * acpi_pci_bus_get_child_devhandle:
+ *
+ * Implements the "pci-bus-get-child-devhandle" device call for
+ * ACPI device handles
+ */
+static int
+acpi_pci_bus_get_child_devhandle(device_t dev, devhandle_t call_handle, void *v)
+{
+ struct pci_bus_get_child_devhandle_args *args = v;
+ struct acpi_devnode *ad;
+ ACPI_HANDLE hdl;
+ int b, d, f;
+ u_int segment;
+
+#ifdef __HAVE_PCI_GET_SEGMENT
+ segment = pci_get_segment(args->pc);
+#else
+ segment = 0;
+#endif /* __HAVE_PCI_GET_SEGMENT */
+
+ pci_decompose_tag(args->pc, args->tag, &b, &d, &f);
+
+ ad = acpi_pcidev_find(segment, b, d, f);
+
+ if (ad != NULL && (hdl = ad->ad_handle) != NULL) {
+ /* Found it! */
+ args->devhandle = devhandle_from_acpi(hdl);
+ return 0;
+ }
+
+ return ENODEV;
+}
+ACPI_DEVICE_CALL_REGISTER("pci-bus-get-child-devhandle",
+ acpi_pci_bus_get_child_devhandle)
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
index 85cce6c8327..b52edf20254 100644
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: acpivar.h,v 1.85 2021/02/04 21:39:00 thorpej Exp $ */
+/* $NetBSD: acpivar.h,v 1.86 2021/05/12 23:22:33 thorpej Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -319,7 +319,6 @@ const struct device_compatible_entry *
const struct device_compatible_entry *);
bool acpi_device_present(ACPI_HANDLE);
-void acpi_device_register(device_t, void *);
int acpi_reset(void);
diff --git a/sys/dev/ofw/files.ofw b/sys/dev/ofw/files.ofw
index 80c0b63809c..2d89595cd09 100644
--- a/sys/dev/ofw/files.ofw
+++ b/sys/dev/ofw/files.ofw
@@ -1,4 +1,4 @@
-# $NetBSD: files.ofw,v 1.16 2021/02/04 20:19:09 thorpej Exp $
+# $NetBSD: files.ofw,v 1.17 2021/05/12 23:22:33 thorpej Exp $
#
# First cut on Openfirmware interface
#
@@ -17,6 +17,9 @@ file dev/ofw/ofw_i2c_subr.c ofbus | openfirm | ofw_subr
file dev/ofw/ofw_network_subr.c of_network_dev
file dev/ofw/ofw_spi_subr.c ofbus | openfirm | ofw_subr
+# Let individual ports pull this in, as necessary.
+#file dev/ofw/ofw_pci_subr.c ofbus | openfirm | ofw_subr
+
# Generic disk support
device ofdisk: disk
attach ofdisk at ofbus
diff --git a/sys/dev/ofw/ofw_pci_subr.c b/sys/dev/ofw/ofw_pci_subr.c
new file mode 100644
index 00000000000..5e0086fb20a
--- /dev/null
+++ b/sys/dev/ofw/ofw_pci_subr.c
@@ -0,0 +1,86 @@
+/* $NetBSD: ofw_pci_subr.c,v 1.1 2021/05/12 23:22:33 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ofw_pci_subr.c,v 1.1 2021/05/12 23:22:33 thorpej Exp $");
+
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/endian.h>
+#include <sys/errno.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+
+static int
+ofw_pci_bus_get_child_devhandle(device_t dev, devhandle_t call_handle, void *v)
+{
+ struct pci_bus_get_child_devhandle_args *args = v;
+ int phandle = devhandle_to_of(call_handle);
+ struct ofw_pci_register opr;
+ int d, f, len;
+ uint32_t phys_hi;
+
+ /*
+ * No need to compare the bus number; we are searching
+ * only direct children of the specified node. Skipping
+ * the bus number comparison allows us to dodge a slight
+ * difference between the OpenFirmware and FDT PCI bindings
+ * as it relates to PCI-PCI bridges.
+ */
+
+ pci_decompose_tag(args->pc, args->tag, NULL, &d, &f);
+
+ for (phandle = OF_child(phandle); phandle != 0;
+ phandle = OF_peer(phandle)) {
+ len = OF_getprop(phandle, "reg", &opr, sizeof(opr));
+ if (len < sizeof(opr)) {
+ continue;
+ }
+
+ phys_hi = be32toh(opr.phys_hi);
+
+ if (d != OFW_PCI_PHYS_HI_DEVICE(phys_hi) ||
+ f != OFW_PCI_PHYS_HI_FUNCTION(phys_hi)) {
+ continue;
+ }
+
+ /* Found it! */
+ args->devhandle = devhandle_from_of(phandle);
+ return 0;
+ }
+
+ return ENODEV;
+}
+OF_DEVICE_CALL_REGISTER("pci-bus-get-child-devhandle",
+ ofw_pci_bus_get_child_devhandle)
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index d58fad02fa0..cbc42332e63 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pci.c,v 1.159 2021/04/24 23:36:57 thorpej Exp $ */
+/* $NetBSD: pci.c,v 1.160 2021/05/12 23:22:33 thorpej Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.159 2021/04/24 23:36:57 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.160 2021/05/12 23:22:33 thorpej Exp $");
#ifdef _KERNEL_OPT
#include "opt_pci.h"
@@ -267,6 +267,27 @@ pciprint(void *aux, const char *pnp)
return UNCONF;
}
+static devhandle_t
+pci_bus_get_child_devhandle(struct pci_softc *sc, pcitag_t tag)
+{
+ struct pci_bus_get_child_devhandle_args args = {
+ .pc = sc->sc_pc,
+ .tag = tag,
+ };
+
+ if (device_call(sc->sc_dev, "pci-bus-get-child-devhandle",
+ &args) != 0) {
+ /*
+ * The call is either not supported or the requested
+ * device was not found in the platform device tree.
+ * Return an invalid handle.
+ */
+ devhandle_invalidate(&args.devhandle);
+ }
+
+ return args.devhandle;
+}
+
int
pci_probe_device(struct pci_softc *sc, pcitag_t tag,
int (*match)(const struct pci_attach_args *),
@@ -415,6 +436,8 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
}
pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
+ devhandle_t devhandle = pci_bus_get_child_devhandle(sc, pa.pa_tag);
+
#ifdef __HAVE_PCI_MSI_MSIX
if (pci_get_ht_capability(pc, tag, PCI_HT_CAP_MSIMAP, &off, &cap)) {
/*
@@ -464,6 +487,7 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
c->c_dev = config_found(sc->sc_dev, &pa, pciprint,
CFARG_SUBMATCH, config_stdsubmatch,
CFARG_LOCATORS, locs,
+ CFARG_DEVHANDLE, devhandle,
CFARG_EOL);
ret = (c->c_dev != NULL);
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index f611fda8f5c..a4ff36c498c 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pcivar.h,v 1.114 2021/01/27 05:00:16 thorpej Exp $ */
+/* $NetBSD: pcivar.h,v 1.115 2021/05/12 23:22:33 thorpej Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@@ -277,6 +277,31 @@ struct pci_softc {
#define PCI_SC_DEVICESC(d, f) sc_devices[(d) * 8 + (f)]
};
+/*
+ * pci-bus-get-child-devhandle device call
+ *
+ * Called to get the device handle for a device, represented
+ * by the pcitag_t with the PCI segment represented by the
+ * pci_chipset_tag_t. The PCI bus's device_t is the one
+ * passed to device_call(), and the device whose handle is
+ * being requested must be a direct child of that bus,
+ * otherwise the behavior is undefined.
+ *
+ * Call returns 0 if successful, or an error code upon failure:
+ *
+ * ENOTSUP The device handle implementation for the
+ * PCI bus does not support this device call.
+ *
+ * ENODEV The PCI device represented by the pcitag_t
+ * was not found in a bus-scoped search of the
+ * platform device tree.
+ */
+struct pci_bus_get_child_devhandle_args {
+ pci_chipset_tag_t pc; /* IN */
+ pcitag_t tag; /* IN */
+ devhandle_t devhandle; /* OUT */
+};
+
extern struct cfdriver pci_cd;
extern bool pci_mapreg_map_enable_decode;