Module Name: src Committed By: christos Date: Sun Jun 25 16:07:48 UTC 2017
Modified Files: src/sys/dev/pci: yds.c ydsvar.h Log Message: PR/52331: ydc driver: sleep-under-spin-mutex bugs in yds_allocmem Don't hold the spin interrupt mutex while calling yds_init from resume. Instead use a flag to short-circuit the interrupt while disabled. To generate a diff of this commit: cvs rdiff -u -r1.58 -r1.59 src/sys/dev/pci/yds.c cvs rdiff -u -r1.11 -r1.12 src/sys/dev/pci/ydsvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/yds.c diff -u src/sys/dev/pci/yds.c:1.58 src/sys/dev/pci/yds.c:1.59 --- src/sys/dev/pci/yds.c:1.58 Wed May 31 22:45:11 2017 +++ src/sys/dev/pci/yds.c Sun Jun 25 12:07:48 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: yds.c,v 1.58 2017/06/01 02:45:11 chs Exp $ */ +/* $NetBSD: yds.c,v 1.59 2017/06/25 16:07:48 christos Exp $ */ /* * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: yds.c,v 1.58 2017/06/01 02:45:11 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: yds.c,v 1.59 2017/06/25 16:07:48 christos Exp $"); #include "mpu.h" @@ -688,6 +688,7 @@ yds_suspend(device_t dv, const pmf_qual_ mutex_enter(&sc->sc_lock); mutex_spin_enter(&sc->sc_intr_lock); + sc->sc_enabled = 0; sc->sc_dsctrl = pci_conf_read(pc, tag, YDS_PCI_DSCTRL); sc->sc_legacy = pci_conf_read(pc, tag, YDS_PCI_LEGACY); sc->sc_ba[0] = pci_conf_read(pc, tag, YDS_PCI_FM_BA); @@ -718,14 +719,15 @@ yds_resume(device_t dv, const pmf_qual_t PCI_COMMAND_MASTER_ENABLE); pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg); reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + mutex_spin_exit(&sc->sc_intr_lock); if (yds_init(sc)) { aprint_error_dev(dv, "reinitialize failed\n"); - mutex_spin_exit(&sc->sc_intr_lock); mutex_exit(&sc->sc_lock); return false; } pci_conf_write(pc, tag, YDS_PCI_DSCTRL, sc->sc_dsctrl); + sc->sc_enabled = 1; mutex_spin_exit(&sc->sc_intr_lock); sc->sc_codec[0].codec_if->vtbl->restore_ports(sc->sc_codec[0].codec_if); mutex_exit(&sc->sc_lock); @@ -785,6 +787,7 @@ yds_attach(device_t parent, device_t sel } aprint_normal_dev(self, "interrupting at %s\n", intrstr); + sc->sc_enabled = 0; sc->sc_dmatag = pa->pa_dmat; sc->sc_pc = pc; sc->sc_pcitag = pa->pa_tag; @@ -940,6 +943,10 @@ detected: if (!pmf_device_register(self, yds_suspend, yds_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); + + mutex_spin_enter(&sc->sc_intr_lock); + sc->sc_enabled = 1; + mutex_spin_exit(&sc->sc_intr_lock); } static int @@ -1046,6 +1053,10 @@ yds_intr(void *p) u_int status; mutex_spin_enter(&sc->sc_intr_lock); + if (!sc->sc_enabled) { + mutex_spin_exit(&sc->sc_intr_lock); + return 0; + } status = YREAD4(sc, YDS_STATUS); DPRINTFN(1, ("yds_intr: status=%08x\n", status)); Index: src/sys/dev/pci/ydsvar.h diff -u src/sys/dev/pci/ydsvar.h:1.11 src/sys/dev/pci/ydsvar.h:1.12 --- src/sys/dev/pci/ydsvar.h:1.11 Wed Nov 23 18:07:36 2011 +++ src/sys/dev/pci/ydsvar.h Sun Jun 25 12:07:48 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ydsvar.h,v 1.11 2011/11/23 23:07:36 jmcneill Exp $ */ +/* $NetBSD: ydsvar.h,v 1.12 2017/06/25 16:07:48 christos Exp $ */ /* * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto. @@ -66,6 +66,7 @@ struct yds_softc { bus_space_handle_t memh; bus_dma_tag_t sc_dmatag; /* DMA tag */ u_int sc_flags; + int sc_enabled; struct yds_codec_softc sc_codec[2]; /* Primary/Secondary AC97 */