Index: sys/dev/proto/proto.h =================================================================== --- sys/dev/proto/proto.h +++ sys/dev/proto/proto.h @@ -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 @@ 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; Index: sys/dev/proto/proto_busdma.h =================================================================== --- sys/dev/proto/proto_busdma.h +++ sys/dev/proto/proto_busdma.h @@ -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 @@ 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 *); Index: sys/dev/proto/proto_busdma.c =================================================================== --- sys/dev/proto/proto_busdma.c +++ sys/dev/proto/proto_busdma.c @@ -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 @@ #include #include #include +#include #include #include #include @@ -355,6 +356,7 @@ 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_cleanup(sc, busdma); + sx_destroy(&busdma->sxlck); free(busdma, M_PROTO_BUSDMA); return (0); } @@ -373,10 +376,12 @@ 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 @@ 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 @@ error = EINVAL; break; } + + sx_xunlock(&busdma->sxlck); + return (error); } @@ -477,11 +487,20 @@ 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); } Index: sys/dev/proto/proto_core.c =================================================================== --- sys/dev/proto/proto_core.c +++ sys/dev/proto/proto_core.c @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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