svn commit: r349714 - head/sys/dev/proto
Marcel Moolenaar
marcel at FreeBSD.org
Thu Jul 4 02:51:36 UTC 2019
Author: marcel
Date: Thu Jul 4 02:51:34 2019
New Revision: 349714
URL: https://svnweb.freebsd.org/changeset/base/349714
Log:
Lock busdma operations and serialize detach against open/close
Use sx to allow M_WAITOK allocations (suggested by markj).
admbugs: 782
Reviewed by: markj
Modified:
head/sys/dev/proto/proto.h
head/sys/dev/proto/proto_busdma.c
head/sys/dev/proto/proto_busdma.h
head/sys/dev/proto/proto_core.c
Modified: head/sys/dev/proto/proto.h
==============================================================================
--- head/sys/dev/proto/proto.h Wed Jul 3 22:41:54 2019 (r349713)
+++ head/sys/dev/proto/proto.h Thu Jul 4 02:51:34 2019 (r349714)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014, 2015 Marcel Moolenaar
+ * Copyright (c) 2014, 2015, 2019 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,8 @@
#define PROTO_RES_BUSDMA 11
struct proto_res {
- int r_type;
+ u_int r_type:8;
+ u_int r_opened:1;
int r_rid;
union {
struct resource *res;
@@ -47,13 +48,14 @@ struct proto_res {
void *cookie;
struct cdev *cdev;
} r_u;
- uintptr_t r_opened;
};
struct proto_softc {
device_t sc_dev;
struct proto_res sc_res[PROTO_RES_MAX];
int sc_rescnt;
+ int sc_opencnt;
+ struct mtx sc_mtx;
};
extern devclass_t proto_devclass;
Modified: head/sys/dev/proto/proto_busdma.c
==============================================================================
--- head/sys/dev/proto/proto_busdma.c Wed Jul 3 22:41:54 2019 (r349713)
+++ head/sys/dev/proto/proto_busdma.c Thu Jul 4 02:51:34 2019 (r349714)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2015 Marcel Moolenaar
+ * Copyright (c) 2015, 2019 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/queue.h>
#include <sys/rman.h>
#include <sys/sbuf.h>
+#include <sys/sx.h>
#include <sys/uio.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -355,6 +356,7 @@ proto_busdma_attach(struct proto_softc *sc)
struct proto_busdma *busdma;
busdma = malloc(sizeof(*busdma), M_PROTO_BUSDMA, M_WAITOK | M_ZERO);
+ sx_init(&busdma->sxlck, "proto-busdma");
return (busdma);
}
@@ -363,6 +365,7 @@ proto_busdma_detach(struct proto_softc *sc, struct pro
{
proto_busdma_cleanup(sc, busdma);
+ sx_destroy(&busdma->sxlck);
free(busdma, M_PROTO_BUSDMA);
return (0);
}
@@ -373,10 +376,12 @@ proto_busdma_cleanup(struct proto_softc *sc, struct pr
struct proto_md *md, *md1;
struct proto_tag *tag, *tag1;
+ sx_xlock(&busdma->sxlck);
LIST_FOREACH_SAFE(md, &busdma->mds, mds, md1)
proto_busdma_md_destroy_internal(busdma, md);
LIST_FOREACH_SAFE(tag, &busdma->tags, tags, tag1)
proto_busdma_tag_destroy(busdma, tag);
+ sx_xunlock(&busdma->sxlck);
return (0);
}
@@ -388,6 +393,8 @@ proto_busdma_ioctl(struct proto_softc *sc, struct prot
struct proto_md *md;
int error;
+ sx_xlock(&busdma->sxlck);
+
error = 0;
switch (ioc->request) {
case PROTO_IOC_BUSDMA_TAG_CREATE:
@@ -470,6 +477,9 @@ proto_busdma_ioctl(struct proto_softc *sc, struct prot
error = EINVAL;
break;
}
+
+ sx_xunlock(&busdma->sxlck);
+
return (error);
}
@@ -477,11 +487,20 @@ int
proto_busdma_mmap_allowed(struct proto_busdma *busdma, vm_paddr_t physaddr)
{
struct proto_md *md;
+ int result;
+ sx_xlock(&busdma->sxlck);
+
+ result = 0;
LIST_FOREACH(md, &busdma->mds, mds) {
if (physaddr >= trunc_page(md->physaddr) &&
- physaddr <= trunc_page(md->physaddr + md->tag->maxsz))
- return (1);
+ physaddr <= trunc_page(md->physaddr + md->tag->maxsz)) {
+ result = 1;
+ break;
+ }
}
- return (0);
+
+ sx_xunlock(&busdma->sxlck);
+
+ return (result);
}
Modified: head/sys/dev/proto/proto_busdma.h
==============================================================================
--- head/sys/dev/proto/proto_busdma.h Wed Jul 3 22:41:54 2019 (r349713)
+++ head/sys/dev/proto/proto_busdma.h Thu Jul 4 02:51:34 2019 (r349714)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2015 Marcel Moolenaar
+ * Copyright (c) 2015, 2019 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,7 @@ struct proto_busdma {
LIST_HEAD(,proto_tag) tags;
LIST_HEAD(,proto_md) mds;
bus_dma_tag_t bd_roottag;
+ struct sx sxlck;
};
struct proto_busdma *proto_busdma_attach(struct proto_softc *);
Modified: head/sys/dev/proto/proto_core.c
==============================================================================
--- head/sys/dev/proto/proto_core.c Wed Jul 3 22:41:54 2019 (r349713)
+++ head/sys/dev/proto/proto_core.c Thu Jul 4 02:51:34 2019 (r349714)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014, 2015 Marcel Moolenaar
+ * Copyright (c) 2014, 2015, 2019 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -184,6 +184,7 @@ proto_attach(device_t dev)
sc = device_get_softc(dev);
sc->sc_dev = dev;
+ mtx_init(&sc->sc_mtx, "proto-softc", NULL, MTX_DEF);
for (res = 0; res < sc->sc_rescnt; res++) {
r = sc->sc_res + res;
@@ -231,15 +232,16 @@ proto_detach(device_t dev)
sc = device_get_softc(dev);
- /* Don't detach if we have open device files. */
- for (res = 0; res < sc->sc_rescnt; res++) {
- r = sc->sc_res + res;
- if (r->r_opened)
- return (EBUSY);
- }
+ mtx_lock(&sc->sc_mtx);
+ if (sc->sc_opencnt == 0)
+ sc->sc_opencnt = -1;
+ mtx_unlock(&sc->sc_mtx);
+ if (sc->sc_opencnt > 0)
+ return (EBUSY);
for (res = 0; res < sc->sc_rescnt; res++) {
r = sc->sc_res + res;
+
switch (r->r_type) {
case SYS_RES_IRQ:
/* XXX TODO */
@@ -252,21 +254,25 @@ proto_detach(device_t dev)
break;
case SYS_RES_MEMORY:
case SYS_RES_IOPORT:
+ destroy_dev(r->r_u.cdev);
bus_release_resource(dev, r->r_type, r->r_rid,
r->r_d.res);
- destroy_dev(r->r_u.cdev);
break;
case PROTO_RES_PCICFG:
destroy_dev(r->r_u.cdev);
break;
case PROTO_RES_BUSDMA:
- proto_busdma_detach(sc, r->r_d.busdma);
destroy_dev(r->r_u.cdev);
+ proto_busdma_detach(sc, r->r_d.busdma);
break;
}
r->r_type = PROTO_RES_UNUSED;
}
+ mtx_lock(&sc->sc_mtx);
sc->sc_rescnt = 0;
+ sc->sc_opencnt = 0;
+ mtx_unlock(&sc->sc_mtx);
+ mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -278,11 +284,23 @@ static int
proto_open(struct cdev *cdev, int oflags, int devtype, struct thread *td)
{
struct proto_res *r;
+ struct proto_softc *sc;
+ int error;
- r = cdev->si_drv2;
- if (!atomic_cmpset_acq_ptr(&r->r_opened, 0UL, (uintptr_t)td->td_proc))
- return (EBUSY);
- return (0);
+ sc = cdev->si_drv1;
+ mtx_lock(&sc->sc_mtx);
+ if (sc->sc_opencnt >= 0) {
+ r = cdev->si_drv2;
+ if (!r->r_opened) {
+ r->r_opened = 1;
+ sc->sc_opencnt++;
+ error = 0;
+ } else
+ error = EBUSY;
+ } else
+ error = ENXIO;
+ mtx_unlock(&sc->sc_mtx);
+ return (error);
}
static int
@@ -290,14 +308,24 @@ proto_close(struct cdev *cdev, int fflag, int devtype,
{
struct proto_res *r;
struct proto_softc *sc;
+ int error;
sc = cdev->si_drv1;
- r = cdev->si_drv2;
- if (!atomic_cmpset_acq_ptr(&r->r_opened, (uintptr_t)td->td_proc, 0UL))
- return (ENXIO);
- if (r->r_type == PROTO_RES_BUSDMA)
- proto_busdma_cleanup(sc, r->r_d.busdma);
- return (0);
+ mtx_lock(&sc->sc_mtx);
+ if (sc->sc_opencnt > 0) {
+ r = cdev->si_drv2;
+ if (r->r_opened) {
+ if (r->r_type == PROTO_RES_BUSDMA)
+ proto_busdma_cleanup(sc, r->r_d.busdma);
+ r->r_opened = 0;
+ sc->sc_opencnt--;
+ error = 0;
+ } else
+ error = ENXIO;
+ } else
+ error = ENXIO;
+ mtx_unlock(&sc->sc_mtx);
+ return (error);
}
static int
More information about the svn-src-all
mailing list