git: 437ea82ce7fc - main - agp: Handle multiple devices more gracefully

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 25 Nov 2021 16:37:15 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=437ea82ce7fc3e664447b9e7d08f5c135a7e2f31

commit 437ea82ce7fc3e664447b9e7d08f5c135a7e2f31
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-11-25 16:27:49 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-11-25 16:36:33 +0000

    agp: Handle multiple devices more gracefully
    
    Currently agp(4) effectively assumes that only one driver instance
    exists, as the generic attach routine attempts to create /dev/agpgart
    and triggers a panic if it already exists.  Instead, handle this
    situation by creating /dev/agpgart<unit> and making /dev/agpgart an
    alias of /dev/agpgart0 for compatibility.
    
    PR:             187015
    Reviewed by:    imp, kib
    Tested by:      Yoshihiro Ota <ota@j.email.ne.jp> (earlier version)
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D33068
---
 sys/dev/agp/agp.c     | 33 ++++++++++++++++++++++++++++-----
 sys/dev/agp/agppriv.h |  1 +
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c
index aaae2176f85a..39e9d5dd64e7 100644
--- a/sys/dev/agp/agp.c
+++ b/sys/dev/agp/agp.c
@@ -205,8 +205,9 @@ agp_set_aperture_resource(device_t dev, int rid)
 int
 agp_generic_attach(device_t dev)
 {
+	struct make_dev_args mdargs;
 	struct agp_softc *sc = device_get_softc(dev);
-	int i;
+	int error, i, unit;
 	u_int memsize;
 
 	/*
@@ -250,11 +251,31 @@ agp_generic_attach(device_t dev)
 	TAILQ_INIT(&sc->as_memory);
 	sc->as_nextid = 1;
 
-	sc->as_devnode = make_dev(&agp_cdevsw,
-	    0, UID_ROOT, GID_WHEEL, 0600, "agpgart");
-	sc->as_devnode->si_drv1 = dev;
+	sc->as_devalias = NULL;
 
-	return 0;
+	make_dev_args_init(&mdargs);
+	mdargs.mda_devsw = &agp_cdevsw;
+	mdargs.mda_uid = UID_ROOT;
+	mdargs.mda_gid = GID_WHEEL;
+	mdargs.mda_mode = 0600;
+	mdargs.mda_si_drv1 = sc;
+	mdargs.mda_si_drv2 = NULL;
+
+	unit = device_get_unit(dev);
+	error = make_dev_s(&mdargs, &sc->as_devnode, "agpgart%d", unit);
+	if (error == 0) {
+		/*
+		 * Create an alias for the first device that shows up.
+		 */
+		if (unit == 0) {
+			(void)make_dev_alias_p(MAKEDEV_CHECKNAME,
+			    &sc->as_devalias, sc->as_devnode, "agpgart");
+		}
+	} else {
+		agp_free_res(dev);
+	}
+
+	return error;
 }
 
 void
@@ -263,6 +284,8 @@ agp_free_cdev(device_t dev)
 	struct agp_softc *sc = device_get_softc(dev);
 
 	destroy_dev(sc->as_devnode);
+	if (sc->as_devalias != NULL)
+		destroy_dev(sc->as_devalias);
 }
 
 void
diff --git a/sys/dev/agp/agppriv.h b/sys/dev/agp/agppriv.h
index f6fa3c5526bd..525f4bced245 100644
--- a/sys/dev/agp/agppriv.h
+++ b/sys/dev/agp/agppriv.h
@@ -76,6 +76,7 @@ struct agp_softc {
 	int			as_nextid;	/* next memory block id */
 	int			as_isopen;	/* user device is open */
 	struct cdev		*as_devnode;	/* from make_dev */
+	struct cdev		*as_devalias;
 	struct mtx		as_lock;	/* lock for access to GATT */
 };