aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-11-25 16:27:49 +0000
committerMark Johnston <markj@FreeBSD.org>2021-11-25 16:36:33 +0000
commit437ea82ce7fc3e664447b9e7d08f5c135a7e2f31 (patch)
tree2821409200f31db875d1f5a9a52c588a119cd68b
parent52d973f52c07b94909a6487be373c269988dc151 (diff)
downloadsrc-437ea82ce7fc3e664447b9e7d08f5c135a7e2f31.tar.gz
src-437ea82ce7fc3e664447b9e7d08f5c135a7e2f31.zip
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
-rw-r--r--sys/dev/agp/agp.c33
-rw-r--r--sys/dev/agp/agppriv.h1
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 */
};