Date: Thu, 4 Jul 2019 02:51:35 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r349714 - head/sys/dev/proto Message-ID: <201907040251.x642pZch099141@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907040251.x642pZch099141>