git: 99adbd1b3f3b - main - gpioc: Fix handling of priv data during open

From: Tom Jones <thj_at_FreeBSD.org>
Date: Thu, 26 Sep 2024 09:16:36 UTC
The branch main has been updated by thj:

URL: https://cgit.FreeBSD.org/src/commit/?id=99adbd1b3f3b2c198a8994c9681655978a7d9a1f

commit 99adbd1b3f3b2c198a8994c9681655978a7d9a1f
Author:     Tom Jones <thj@FreeBSD.org>
AuthorDate: 2024-09-26 09:13:41 +0000
Commit:     Tom Jones <thj@FreeBSD.org>
CommitDate: 2024-09-26 09:16:17 +0000

    gpioc: Fix handling of priv data during open
    
    Fix the ordering of priv data creation with setting priv data. This
    handles failure better and resolves a panic when repeatedly running
    tools/tools/gpioevents.
    
    Explicitly initialise more fields in priv data while we are here.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D46568
---
 sys/dev/gpio/gpioc.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/sys/dev/gpio/gpioc.c b/sys/dev/gpio/gpioc.c
index 4ebf958d6974..b9d95338e211 100644
--- a/sys/dev/gpio/gpioc.c
+++ b/sys/dev/gpio/gpioc.c
@@ -677,19 +677,18 @@ static int
 gpioc_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
 {
 	struct gpioc_cdevpriv *priv;
-	int err;
+	int err = 0;
 
 	priv = malloc(sizeof(*priv), M_GPIOC, M_WAITOK | M_ZERO);
 	priv->sc = dev->si_drv1;
-	priv->report_option = GPIO_EVENT_REPORT_DETAIL;
-	err = devfs_set_cdevpriv(priv, gpioc_cdevpriv_dtor);
-	if (err != 0) {
-		gpioc_cdevpriv_dtor(priv);
-		return (err);
-	}
+
 	mtx_init(&priv->mtx, "gpioc priv", NULL, MTX_DEF);
 	knlist_init_mtx(&priv->selinfo.si_note, &priv->mtx);
 
+	priv->async = false;
+	priv->report_option = GPIO_EVENT_REPORT_DETAIL;
+	priv->sigio = NULL;
+
 	/*
 	 * Allocate a circular buffer for events.  The scheme we use for summary
 	 * reporting assumes there will always be a pair of events available to
@@ -701,7 +700,13 @@ gpioc_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
 	priv->events = malloc(priv->numevents * sizeof(struct gpio_event_detail),
 	    M_GPIOC, M_WAITOK | M_ZERO);
 
-	return (0);
+	priv->evidx_head = priv->evidx_tail = 0;
+	SLIST_INIT(&priv->pins);
+
+	err = devfs_set_cdevpriv(priv, gpioc_cdevpriv_dtor);
+	if (err != 0)
+		gpioc_cdevpriv_dtor(priv);
+	return (err);
 }
 
 static int