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 */
 

Reply via email to