From 2b379e8d35f6396b15b49b1bd60872c225cb5e8f Mon Sep 17 00:00:00 2001 From: Alexander Leidinger Date: Sun, 31 Jul 2005 11:04:36 +0000 Subject: [PATCH] * Add locking / MPSAFE. Submitted by: Ariff Abdullah Tested by: netchild --- sys/dev/sound/pci/via82c686.c | 44 ++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c index 0ae12041eb38..bf348e9e6150 100644 --- a/sys/dev/sound/pci/via82c686.c +++ b/sys/dev/sound/pci/via82c686.c @@ -86,6 +86,7 @@ struct via_info { struct via_chinfo pch, rch; struct via_dma_op *sgd_table; u_int16_t codec_caps; + struct mtx *lock; }; static u_int32_t via_fmt[] = { @@ -244,6 +245,7 @@ viachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel * struct via_info *via = devinfo; struct via_chinfo *ch; + snd_mtxlock(via->lock); if (dir == PCMDIR_PLAY) { ch = &via->pch; ch->base = VIA_PLAY_DMAOPS_BASE; @@ -267,8 +269,12 @@ viachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel * ch->buffer = b; ch->dir = dir; - if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) + if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) { + snd_mtxunlock(via->lock); return NULL; + } + snd_mtxunlock(via->lock); + return ch; } @@ -286,10 +292,12 @@ viachan_setformat(kobj_t obj, void *data, u_int32_t format) mode_set |= VIA_RPMODE_16BIT; DEB(printf("set format: dir = %d, format=%x\n", ch->dir, format)); + snd_mtxlock(via->lock); mode = via_rd(via, ch->mode, 1); mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO); mode |= mode_set; via_wr(via, ch->mode, mode, 1); + snd_mtxunlock(via->lock); return 0; } @@ -321,9 +329,12 @@ static int viachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) { struct via_chinfo *ch = data; + struct via_info *via = ch->parent; + snd_mtxlock(via->lock); ch->blksz = blocksize; sndbuf_resize(ch->buffer, SEGS_PER_CHAN, ch->blksz); + snd_mtxunlock(via->lock); return ch->blksz; } @@ -339,6 +350,7 @@ viachan_trigger(kobj_t obj, void *data, int go) if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) return 0; + snd_mtxlock(via->lock); ado = ch->sgd_table; DEB(printf("ado located at va=%p pa=%x\n", ado, sgd_addr)); @@ -349,6 +361,8 @@ viachan_trigger(kobj_t obj, void *data, int go) } else via_wr(via, ch->ctrl, VIA_RPCTRL_TERMINATE, 1); + snd_mtxunlock(via->lock); + DEB(printf("viachan_trigger: go=%d\n", go)); return 0; } @@ -362,6 +376,7 @@ viachan_getptr(kobj_t obj, void *data) bus_addr_t sgd_addr = ch->sgd_addr; int ptr, base, base1, len, seg; + snd_mtxlock(via->lock); ado = ch->sgd_table; base1 = via_rd(via, ch->base, 4); len = via_rd(via, ch->count, 4); @@ -385,6 +400,7 @@ viachan_getptr(kobj_t obj, void *data) /* so don't return any part line - it isn't in RAM yet */ ptr = ptr & ~0x1f; } + snd_mtxunlock(via->lock); DEB(printf("return ptr=%d\n", ptr)); return ptr; @@ -417,22 +433,25 @@ static void via_intr(void *p) { struct via_info *via = p; - int st; /* DEB(printf("viachan_intr\n")); */ /* Read channel */ - st = via_rd(via, VIA_PLAY_STAT, 1); - if (st & VIA_RPSTAT_INTR) { + snd_mtxlock(via->lock); + if (via_rd(via, VIA_PLAY_STAT, 1) & VIA_RPSTAT_INTR) { via_wr(via, VIA_PLAY_STAT, VIA_RPSTAT_INTR, 1); + snd_mtxunlock(via->lock); chn_intr(via->pch.channel); + snd_mtxlock(via->lock); } /* Write channel */ - st = via_rd(via, VIA_RECORD_STAT, 1); - if (st & VIA_RPSTAT_INTR) { + if (via_rd(via, VIA_RECORD_STAT, 1) & VIA_RPSTAT_INTR) { via_wr(via, VIA_RECORD_STAT, VIA_RPSTAT_INTR, 1); + snd_mtxunlock(via->lock); chn_intr(via->rch.channel); + return; } + snd_mtxunlock(via->lock); } /* @@ -468,6 +487,7 @@ via_attach(device_t dev) device_printf(dev, "cannot allocate softc\n"); return ENXIO; } + via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); /* Get resources */ data = pci_read_config(dev, PCIR_COMMAND, 2); @@ -521,7 +541,7 @@ via_attach(device_t dev) via->irqid = 0; via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid, RF_ACTIVE | RF_SHAREABLE); - if (!via->irq || snd_setup_intr(dev, via->irq, 0, via_intr, via, &via->ih)) { + if (!via->irq || snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) { device_printf(dev, "unable to map interrupt\n"); goto bad; } @@ -546,8 +566,8 @@ via_attach(device_t dev) /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, - /*flags*/0, /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, &via->parent_dmat) != 0) { + /*flags*/0, /*lockfunc*/NULL, + /*lockarg*/NULL, &via->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } @@ -563,8 +583,8 @@ via_attach(device_t dev) /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/NSEGS * sizeof(struct via_dma_op), /*nsegments*/1, /*maxsegz*/0x3ffff, - /*flags*/0, /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, &via->sgd_dmat) != 0) { + /*flags*/0, /*lockfunc*/NULL, + /*lockarg*/NULL, &via->sgd_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } @@ -594,6 +614,7 @@ bad: if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); + if (via->lock) snd_mtxfree(via->lock); if (via) free(via, M_DEVBUF); return ENXIO; } @@ -615,6 +636,7 @@ via_detach(device_t dev) bus_dma_tag_destroy(via->parent_dmat); bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); bus_dma_tag_destroy(via->sgd_dmat); + snd_mtxfree(via->lock); free(via, M_DEVBUF); return 0; }