git: 944eda42fa6e - main - openfirm: Add OF_device_unregister_xref

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Thu, 03 Apr 2025 14:05:57 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=944eda42fa6e449ec802958d41302e71a125ca5f

commit 944eda42fa6e449ec802958d41302e71a125ca5f
Author:     Emannuel Vadot <manu@FreeBSD.org>
AuthorDate: 2025-04-03 13:54:41 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-04-03 14:03:44 +0000

    openfirm: Add OF_device_unregister_xref
    
    When a device fails to attach, or a module is unloaded, we want to be
    able to unregister the xref as the device goes away.  While the device_t
    may still be valid, it won't be providing whatever functionality the
    consumer that follows the xref wants it for and thus, we should not
    keep it discoverable.
    
    [Commit message re-worded by kevans@]
    
    Reviewed by:    ian, imp
    Differential Revision:  https://reviews.freebsd.org/D22945
---
 share/man/man9/OF_device_from_xref.9 | 14 +++++++++++++-
 sys/dev/ofw/openfirm.c               | 19 +++++++++++++++++++
 sys/dev/ofw/openfirm.h               |  1 +
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/share/man/man9/OF_device_from_xref.9 b/share/man/man9/OF_device_from_xref.9
index 85a19df6641b..0b858866b654 100644
--- a/share/man/man9/OF_device_from_xref.9
+++ b/share/man/man9/OF_device_from_xref.9
@@ -23,19 +23,22 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd April 9, 2018
+.Dd April 3, 2025
 .Dt OF_DEVICE_FROM_XREF 9
 .Os
 .Sh NAME
 .Nm OF_device_from_xref ,
 .Nm OF_xref_from_device ,
 .Nm OF_device_register_xref
+.Nm OF_device_unregister_xref
 .Nd "manage mappings between xrefs and devices"
 .Sh SYNOPSIS
 .In dev/ofw/ofw_bus.h
 .In dev/ofw/ofw_bus_subr.h
 .Ft int
 .Fn OF_device_register_xref "phandle_t xref" "device_t dev"
+.Ft void
+.Fn OF_device_unregister_xref "phandle_t xref" "device_t dev"
 .Ft device_t
 .Fn OF_device_from_xref "phandle_t xref"
 .Ft phandle_t
@@ -57,6 +60,15 @@ If a mapping entry for
 already exists, it is replaced with the new one.
 The function always returns 0.
 .Pp
+.Fn OF_device_unregister_xref
+removes a map entry from the effective phandle
+.Fa xref
+to device
+.Fa dev .
+If a mapping entry for
+.Fa xref
+does not exists, it silently returns.
+.Pp
 .Fn OF_device_from_xref
 returns a device_t instance associated with the effective phandle
 .Fa xref .
diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c
index f9c73122b454..22e8d470e6c9 100644
--- a/sys/dev/ofw/openfirm.c
+++ b/sys/dev/ofw/openfirm.c
@@ -187,6 +187,15 @@ xrefinfo_add(phandle_t node, phandle_t xref, device_t dev)
 	return (xi);
 }
 
+static void
+xrefinfo_remove(struct xrefinfo *xi)
+{
+
+	mtx_lock(&xreflist_lock);
+	SLIST_REMOVE(&xreflist, xi, xrefinfo, next_entry);
+	mtx_unlock(&xreflist_lock);
+}
+
 /*
  * OFW install routines.  Highest priority wins, equal priority also
  * overrides allowing last-set to win.
@@ -704,6 +713,16 @@ OF_device_register_xref(phandle_t xref, device_t dev)
 	panic("Attempt to register device before xreflist_init");
 }
 
+void
+OF_device_unregister_xref(phandle_t xref, device_t dev)
+{
+	struct xrefinfo *xi;
+
+	if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL)
+		return;
+	xrefinfo_remove(xi);
+}
+
 /*  Call the method in the scope of a given instance. */
 int
 OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns,
diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h
index 30203404a6b0..4e2b035827cb 100644
--- a/sys/dev/ofw/openfirm.h
+++ b/sys/dev/ofw/openfirm.h
@@ -149,6 +149,7 @@ phandle_t	OF_xref_from_node(phandle_t node);
 device_t	OF_device_from_xref(phandle_t xref);
 phandle_t	OF_xref_from_device(device_t dev);
 int		OF_device_register_xref(phandle_t xref, device_t dev);
+void		OF_device_unregister_xref(phandle_t xref, device_t dev);
 
 /* Device I/O functions */
 ihandle_t	OF_open(const char *path);