Removing broken drivers in sys/dev/sound/pci

Taku YAMAMOTO taku at tackymt.homeip.net
Wed Mar 21 09:57:01 UTC 2012


On Fri, 20 Jan 2012 18:09:57 +0100
Joel Dahl <joel at freebsd.org> wrote:

> Hi all,
> 
> I've been playing with a bunch of old sound cards I had lying around and I've
> come to the conlusion that maybe it's time to remove a few old drivers we
> currently have in the tree.

[snip]

> - snd_maestro
> 
> This driver seems to have been broken since 5.2.1 and there are currently
> 3 open PR's: kern/63204, kern/119973 and kern/122086. I decided to give it
> a try with an old ESS Maestro-2 that I have here and I got a bunch of errors
> when trying to kldload it on FreeBSD-CURRENT:
> 
> pcm1: <ESS Technology Maestro-2> port 0x1100-0x11ff irq 22 at device 11.0 on
> pci16 lock order reversal: (sleepable after non-sleepable)
>  1st 0xfffffe0008118050 ESS Technology Maestro-2 (snd_maestro softc) @
>  /usr/src/sys/modules/sound/driver/maestro/../../../../dev/sound/pci/maestro.c:1886
>  2nd 0xffffffff8111b900 ACPI PCI power methods (ACPI PCI power methods) @
>  /usr/src/sys/dev/acpica/acpi_pci.c:180
> KDB: stack backtrace:
> db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
> kdb_backtrace() at kdb_backtrace+0x37
> _witness_debugger() at _witness_debugger+0x2c
> witness_checkorder() at witness_checkorder+0x854
> _sx_xlock() at _sx_xlock+0x5d
> acpi_pci_set_powerstate_method() at acpi_pci_set_powerstate_method+0x6a
> agg_power() at agg_power+0xd0
> agg_attach() at agg_attach+0x608
> device_attach() at device_attach+0x69
> pci_driver_added() at pci_driver_added+0xda
> devclass_driver_added() at devclass_driver_added+0x75
> devclass_add_driver() at devclass_add_driver+0x10b
> module_register_init() at module_register_init+0x7d
> linker_load_module() at linker_load_module+0x9c3
> kern_kldload() at kern_kldload+0xac
> sys_kldload() at sys_kldload+0x84
> amd64_syscall() at amd64_syscall+0x39e
> Xfast_syscall() at Xfast_syscall+0xf7
> --- syscall (304, FreeBSD ELF64, sys_kldload), rip = 0x8008adc0c,
>  rsp = 0x7fffffffd5c8, rbp = 0x7fffffffdb48 ---
> pcm1: agg_rdcodec() RW_DONE timed out.
> pcm1: agg_rdcodec() PROGLESS timed out.
> pcm1: agg_wrcodec() PROGLESS timed out.
> pcm1: <Asahi Kasei AK4540 AC97 Codec>
> pcm1: agg_rdcodec() PROGLESS timed out.
> pcm1: agg_wrcodec() PROGLESS timed out.
> pci16: failed to set ACPI power state D2 on \\_SB_.PCI0.HUB_.SLT3: AE_BAD_PARAMETER
> 
> Playback does not work, which isn't all that surprising.

I, as the author of this driver, am interested in that you still have
actual hardware and trying to make it work.

To consider fixing this driver, your help would be very appriciated
because I no longer have this type of device handy.

First of all, the attached patch works for you?

-- 
-|-__   YAMAMOTO, Taku
 | __ <     <taku at tackymt.homeip.net>

      - A chicken is an egg's way of producing more eggs. -
-------------- next part --------------
--- sys/dev/sound/pci/maestro.c.orig	2011-11-08 00:43:11.000000000 +0900
+++ sys/dev/sound/pci/maestro.c	2012-03-21 18:50:26.719566045 +0900
@@ -173,6 +173,7 @@ struct agg_info {
 	volatile u_int		active;
 	struct agg_chinfo	pch[AGG_MAXPLAYCH];
 	struct agg_rchinfo	rch;
+	int			pwrcap; /* power cap config base */
 	volatile u_int8_t	curpwr;	/* current power status: D[0-3] */
 };
 
@@ -277,6 +278,10 @@ agg_sleep(struct agg_info *sc, const cha
 {
 	int timo;
 
+	if (cold) {
+		DELAY(1000 * msec);
+		return;
+	}
 	timo = msec * hz / 1000;
 	if (timo == 0)
 		timo = 1;
@@ -334,12 +339,13 @@ agg_wr(struct agg_info *sc, int regno, u
 static int
 agg_codec_wait4idle(struct agg_info *ess)
 {
-	unsigned t = 26;
+	unsigned t = 50; /* was 26; not enough for some codecs? */
 
 	while (AGG_RD(ess, PORT_CODEC_STAT, 1) & CODEC_STAT_MASK) {
 		if (--t == 0)
 			return EBUSY;
-		DELAY(2);	/* 20.8us / 13 */
+		/*DELAY(2);*/	/* 20.8us / 13 */
+		DELAY(5);
 	}
 	return 0;
 }
@@ -359,6 +365,7 @@ agg_rdcodec(struct agg_info *ess, int re
 
 	AGG_WR(ess, PORT_CODEC_CMD, CODEC_CMD_READ | regno, 1);
 	/*DELAY(21);	* AC97 cycle = 20.8usec */
+	DELAY(10);
 
 	/* Wait for data retrieve */
 	if (!agg_codec_wait4idle(ess)) {
@@ -384,6 +391,7 @@ agg_wrcodec(struct agg_info *ess, int re
 
 	AGG_WR(ess, PORT_CODEC_REG, data, 2);
 	AGG_WR(ess, PORT_CODEC_CMD, CODEC_CMD_WRITE | regno, 1);
+	DELAY(10);
 
 	/* Wait for write completion */
 	if (agg_codec_wait4idle(ess)) {
@@ -575,6 +583,13 @@ agg_stopclock(struct agg_info *ess, int 
 	}
 }
 
+static void
+agg_pci_set_powerstate(struct agg_info *ess, uint8_t state)
+{
+	if (ess->pwrcap != -1)
+		pci_write_config(ess->dev, ess->pwrcap + PCIR_POWER_STATUS,
+		    state, 1);
+}
 
 /* -----------------------------
  * Controller.
@@ -591,13 +606,15 @@ agg_initcodec(struct agg_info* ess)
 	}
 	/* XXX - 2nd codec should be looked at. */
 	AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_AC97_SWRESET, 4);
-	DELAY(2);
+	DELAY(5);
+	AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
+	DELAY(5);
 	AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED, 4);
 	DELAY(50);
 
 	if (agg_rdcodec(ess, 0) < 0) {
 		AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
-		DELAY(21);
+		DELAY(25);
 
 		/* Try cold reset. */
 		device_printf(ess->dev, "will perform cold reset.\n");
@@ -608,9 +625,9 @@ agg_initcodec(struct agg_info* ess)
 		AGG_WR(ess, PORT_GPIO_MASK, 0xff6, 2);
 		AGG_WR(ess, PORT_GPIO_DIR, data | 0x009, 2);
 		AGG_WR(ess, PORT_GPIO_DATA, 0x000, 2);
-		DELAY(2);
+		DELAY(5);
 		AGG_WR(ess, PORT_GPIO_DATA, 0x001, 2);
-		DELAY(1);
+		DELAY(5);
 		AGG_WR(ess, PORT_GPIO_DATA, 0x009, 2);
 		agg_sleep(ess, "agginicd", 500);
 		AGG_WR(ess, PORT_GPIO_DIR, data, 2);
@@ -758,7 +775,7 @@ agg_power(struct agg_info *ess, int stat
 	case PCI_POWERSTATE_D1:
 		switch (lastpwr) {
 		case PCI_POWERSTATE_D2:
-			pci_set_powerstate(ess->dev, status);
+			agg_pci_set_powerstate(ess, status);
 			/* Turn on PCM-related parts. */
 			agg_wrcodec(ess, AC97_REG_POWER, 0);
 			DELAY(100);
@@ -778,13 +795,13 @@ agg_power(struct agg_info *ess, int stat
 			break;
 		case PCI_POWERSTATE_D3:
 			/* Initialize. */
-			pci_set_powerstate(ess->dev, PCI_POWERSTATE_D0);
+			agg_pci_set_powerstate(ess, PCI_POWERSTATE_D0);
 			DELAY(100);
 			agg_init(ess);
 			/* FALLTHROUGH */
 		case PCI_POWERSTATE_D0:
 		case PCI_POWERSTATE_D1:
-			pci_set_powerstate(ess->dev, status);
+			agg_pci_set_powerstate(ess, status);
 			break;
 		}
 		break;
@@ -792,7 +809,7 @@ agg_power(struct agg_info *ess, int stat
 		switch (lastpwr) {
 		case PCI_POWERSTATE_D3:
 			/* Initialize. */
-			pci_set_powerstate(ess->dev, PCI_POWERSTATE_D0);
+			agg_pci_set_powerstate(ess, PCI_POWERSTATE_D0);
 			DELAY(100);
 			agg_init(ess);
 			/* FALLTHROUGH */
@@ -807,7 +824,7 @@ agg_power(struct agg_info *ess, int stat
 			DELAY(100);
 			break;
 		}
-		pci_set_powerstate(ess->dev, status);
+		agg_pci_set_powerstate(ess, status);
 		break;
 	case PCI_POWERSTATE_D3:
 		/* Entirely power down. */
@@ -819,7 +836,7 @@ agg_power(struct agg_info *ess, int stat
 			wp_stoptimer(ess);
 		AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
 		AGG_WR(ess, PORT_HOSTINT_STAT, 0xff, 1);
-		pci_set_powerstate(ess->dev, status);
+		agg_pci_set_powerstate(ess, status);
 		break;
 	default:
 		/* Invalid power state; let it ignored. */
@@ -1842,7 +1859,11 @@ agg_attach(device_t dev)
 
 	/* State D0-uninitialized. */
 	ess->curpwr = PCI_POWERSTATE_D3;
-	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+	/*pci_set_powerstate(dev, PCI_POWERSTATE_D0);*/
+
+	/* Locate PCI power management config. */
+	ess->pwrcap = -1;
+	pci_find_cap(dev, PCIY_PMG, &ess->pwrcap);
 
 	data = pci_read_config(dev, PCIR_COMMAND, 2);
 	data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);


More information about the freebsd-multimedia mailing list