All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: Bug#436723: Playing sound hands on powerbook3, 5 with 2.6.21-2 kernel
       [not found] <20080114002111.2ef21467@phineus>
@ 2008-01-14  0:06 ` maximilian attems
  2008-01-14 11:05   ` Takashi Iwai
  0 siblings, 1 reply; 4+ messages in thread
From: maximilian attems @ 2008-01-14  0:06 UTC (permalink / raw)
  To: th.huth, 436723; +Cc: alsa-devel

[ adding alsa upstream on cc ]

On Mon, Jan 14, 2008 at 12:21:11AM +0100, th.huth@googlemail.com wrote:
> 
> Please have a look at
> https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.20/+bug/87652/comments/48
> and the corresponding patch to see wether this patch solves this sound
> issue.

woow, i thought to fire up "try newer kernel", but your patch still
applies to current linus git:
 ~/src/linux-2.6$ patch -p0 --dry-run < ~/pmac.c.diff 
 patching file sound/ppc/pmac.c
 Hunk #5 succeeded at 868 (offset -24 lines).
 Hunk #6 succeeded at 1207 (offset -47 lines).

so bringing that to upstream alsa radar.

-- 
maks

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Bug#436723: Playing sound hands on powerbook3, 5 with 2.6.21-2 kernel
  2008-01-14  0:06 ` Bug#436723: Playing sound hands on powerbook3, 5 with 2.6.21-2 kernel maximilian attems
@ 2008-01-14 11:05   ` Takashi Iwai
  2008-01-15 20:43     ` [PATCH] snd-powermac: handle dead DMA transfers th.huth
  0 siblings, 1 reply; 4+ messages in thread
From: Takashi Iwai @ 2008-01-14 11:05 UTC (permalink / raw)
  To: maximilian attems; +Cc: th.huth, 436723, alsa-devel

At Mon, 14 Jan 2008 01:06:41 +0100,
maximilian attems wrote:
> 
> [ adding alsa upstream on cc ]
> 
> On Mon, Jan 14, 2008 at 12:21:11AM +0100, th.huth@googlemail.com wrote:
> > 
> > Please have a look at
> > https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.20/+bug/87652/comments/48
> > and the corresponding patch to see wether this patch solves this sound
> > issue.
> 
> woow, i thought to fire up "try newer kernel", but your patch still
> applies to current linus git:
>  ~/src/linux-2.6$ patch -p0 --dry-run < ~/pmac.c.diff 
>  patching file sound/ppc/pmac.c
>  Hunk #5 succeeded at 868 (offset -24 lines).
>  Hunk #6 succeeded at 1207 (offset -47 lines).
> 
> so bringing that to upstream alsa radar.

Thanks for report.  I'm willing to apply it, but I'd need a proper
changelog and a sign-off to merge to the upstream.
Please post a patch to alsa-devel ML with them.


Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] snd-powermac: handle dead DMA transfers
  2008-01-14 11:05   ` Takashi Iwai
@ 2008-01-15 20:43     ` th.huth
  2008-01-16 14:58       ` Takashi Iwai
  0 siblings, 1 reply; 4+ messages in thread
From: th.huth @ 2008-01-15 20:43 UTC (permalink / raw)
  To: Takashi Iwai, alsa-devel

This patch provides the snd-powermac sound driver with the ability to handle
dead DMA transfers. If a dead DMA transfer is detected, the driver now sets
up a new DMA transfer to continue with the sound output at the point where the
old transfer died.

This dead DMA transfer handling has become necessary with recent kernels on
certain G4 PowerMacs. Please refer to the following URLs for more information:

 https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3126
 https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.20/+bug/87652
 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=436723

The patch is based on the dead DMA transfer handling code from the old dmasound
driver which can be found in the file sound/oss/dmasound/dmasound_awacs.c in
the Linux source code.

Signed-off-by: T. H. Huth <th.huth@googlemail.com>

--- alsa-kernel/ppc/pmac.c_original	2008-01-15 19:50:23.000000000 +0100
+++ alsa-kernel/ppc/pmac.c	2008-01-15 21:10:54.000000000 +0100
@@ -45,6 +45,18 @@ static int tumbler_freqs[1] = {
 	44100
 };
 
+
+/*
+ * we will allocate a single 'emergency' dbdma cmd block to use if the
+ * tx status comes up "DEAD".  This happens on some PowerComputing Pmac
+ * clones, either owing to a bug in dbdma or some interaction between
+ * IDE and sound.  However, this measure would deal with DEAD status if
+ * it appeared elsewhere.
+ */
+static struct pmac_dbdma emergency_dbdma;
+static int emergency_in_use;
+
+
 /*
  * allocate DBDMA command arrays
  */
@@ -376,6 +388,75 @@ static snd_pcm_uframes_t snd_pmac_captur
 
 
 /*
+ * Handle DEAD DMA transfers:
+ * if the TX status comes up "DEAD" - reported on some Power Computing machines
+ * we need to re-start the dbdma - but from a different physical start address
+ * and with a different transfer length.  It would get very messy to do this
+ * with the normal dbdma_cmd blocks - we would have to re-write the buffer start
+ * addresses each time.  So, we will keep a single dbdma_cmd block which can be
+ * fiddled with.
+ * When DEAD status is first reported the content of the faulted dbdma block is
+ * copied into the emergency buffer and we note that the buffer is in use.
+ * we then bump the start physical address by the amount that was successfully
+ * output before it died.
+ * On any subsequent DEAD result we just do the bump-ups (we know that we are
+ * already using the emergency dbdma_cmd).
+ * CHECK: this just tries to "do it".  It is possible that we should abandon
+ * xfers when the number of residual bytes gets below a certain value - I can
+ * see that this might cause a loop-forever if a too small transfer causes
+ * DEAD status.  However this is a TODO for now - we'll see what gets reported.
+ * When we get a successful transfer result with the emergency buffer we just
+ * pretend that it completed using the original dmdma_cmd and carry on.  The
+ * 'next_cmd' field will already point back to the original loop of blocks.
+ */
+static inline void snd_pmac_pcm_dead_xfer(struct pmac_stream *rec,
+					  volatile struct dbdma_cmd __iomem *cp)
+{
+	unsigned short req, res ;
+	unsigned int phy ;
+
+	/* printk(KERN_WARNING "snd-powermac: DMA died - patching it up!\n"); */
+
+	/* to clear DEAD status we must first clear RUN
+	   set it to quiescent to be on the safe side */
+	(void)in_le32(&rec->dma->status);
+	out_le32(&rec->dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
+
+	if (!emergency_in_use) { /* new problem */
+		memcpy((void *)emergency_dbdma.cmds, (void *)cp,
+		       sizeof(struct dbdma_cmd));
+		emergency_in_use = 1;
+		st_le16(&cp->xfer_status, 0);
+		st_le16(&cp->req_count, rec->period_size);
+		cp = emergency_dbdma.cmds;
+	}
+
+	/* now bump the values to reflect the amount
+	   we haven't yet shifted */
+	req = ld_le16(&cp->req_count);
+	res = ld_le16(&cp->res_count);
+	phy = ld_le32(&cp->phy_addr);
+	phy += (req - res);
+	st_le16(&cp->req_count, res);
+	st_le16(&cp->res_count, 0);
+	st_le16(&cp->xfer_status, 0);
+	st_le32(&cp->phy_addr, phy);
+
+	st_le32(&cp->cmd_dep, rec->cmd.addr
+		+ sizeof(struct dbdma_cmd)*((rec->cur_period+1)%rec->nperiods));
+
+	st_le16(&cp->command, OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS);
+
+	/* point at our patched up command block */
+	out_le32(&rec->dma->cmdptr, emergency_dbdma.addr);
+
+	/* we must re-start the controller */
+	(void)in_le32(&rec->dma->status);
+	/* should complete clearing the DEAD status */
+	out_le32(&rec->dma->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
+}
+
+/*
  * update playback/capture pointer from interrupts
  */
 static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec)
@@ -386,11 +467,27 @@ static void snd_pmac_pcm_update(struct s
 
 	spin_lock(&chip->reg_lock);
 	if (rec->running) {
-		cp = &rec->cmd.cmds[rec->cur_period];
 		for (c = 0; c < rec->nperiods; c++) { /* at most all fragments */
+
+			if (emergency_in_use)   /* already using DEAD xfer? */
+				cp = emergency_dbdma.cmds;
+			else
+				cp = &rec->cmd.cmds[rec->cur_period];
+
 			stat = ld_le16(&cp->xfer_status);
+
+			if (stat & DEAD) {
+				snd_pmac_pcm_dead_xfer(rec, cp);
+				break; /* this block is still going */
+			}
+
+			if (emergency_in_use) {
+				emergency_in_use = 0 ; /* done that */
+			}
+
 			if (! (stat & ACTIVE))
 				break;
+
 			/*printk("update frag %d\n", rec->cur_period);*/
 			st_le16(&cp->xfer_status, 0);
 			st_le16(&cp->req_count, rec->period_size);
@@ -398,9 +495,8 @@ static void snd_pmac_pcm_update(struct s
 			rec->cur_period++;
 			if (rec->cur_period >= rec->nperiods) {
 				rec->cur_period = 0;
-				cp = rec->cmd.cmds;
-			} else
-				cp++;
+			}
+
 			spin_unlock(&chip->reg_lock);
 			snd_pcm_period_elapsed(rec->substream);
 			spin_lock(&chip->reg_lock);
@@ -770,6 +866,7 @@ static int snd_pmac_free(struct snd_pmac
 	snd_pmac_dbdma_free(chip, &chip->playback.cmd);
 	snd_pmac_dbdma_free(chip, &chip->capture.cmd);
 	snd_pmac_dbdma_free(chip, &chip->extra_dma);
+	snd_pmac_dbdma_free(chip, &emergency_dbdma);
 	if (chip->macio_base)
 		iounmap(chip->macio_base);
 	if (chip->latch_base)
@@ -1108,7 +1205,8 @@ int __init snd_pmac_new(struct snd_card 
 
 	if (snd_pmac_dbdma_alloc(chip, &chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 ||
 	    snd_pmac_dbdma_alloc(chip, &chip->capture.cmd, PMAC_MAX_FRAGS + 1) < 0 ||
-	    snd_pmac_dbdma_alloc(chip, &chip->extra_dma, 2) < 0) {
+	    snd_pmac_dbdma_alloc(chip, &chip->extra_dma, 2) < 0 ||
+	    snd_pmac_dbdma_alloc(chip, &emergency_dbdma, 2) < 0) {
 		err = -ENOMEM;
 		goto __error;
 	}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] snd-powermac: handle dead DMA transfers
  2008-01-15 20:43     ` [PATCH] snd-powermac: handle dead DMA transfers th.huth
@ 2008-01-16 14:58       ` Takashi Iwai
  0 siblings, 0 replies; 4+ messages in thread
From: Takashi Iwai @ 2008-01-16 14:58 UTC (permalink / raw)
  To: th.huth; +Cc: alsa-devel

At Tue, 15 Jan 2008 21:43:44 +0100,
th.huth@googlemail.com wrote:
> 
> This patch provides the snd-powermac sound driver with the ability to handle
> dead DMA transfers. If a dead DMA transfer is detected, the driver now sets
> up a new DMA transfer to continue with the sound output at the point where the
> old transfer died.
> 
> This dead DMA transfer handling has become necessary with recent kernels on
> certain G4 PowerMacs. Please refer to the following URLs for more information:
> 
>  https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3126
>  https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.20/+bug/87652
>  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=436723
> 
> The patch is based on the dead DMA transfer handling code from the old dmasound
> driver which can be found in the file sound/oss/dmasound/dmasound_awacs.c in
> the Linux source code.
> 
> Signed-off-by: T. H. Huth <th.huth@googlemail.com>

Thanks, applied to ALSA HG tree now.


Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-01-16 14:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20080114002111.2ef21467@phineus>
2008-01-14  0:06 ` Bug#436723: Playing sound hands on powerbook3, 5 with 2.6.21-2 kernel maximilian attems
2008-01-14 11:05   ` Takashi Iwai
2008-01-15 20:43     ` [PATCH] snd-powermac: handle dead DMA transfers th.huth
2008-01-16 14:58       ` Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.