[DEVICE MODEL] dev->dma_mask

Previous thread: [PATCH] IPMI: Support I/O resources in OF driver by Corey Minyard on Thursday, May 8, 2008 - 6:22 pm. (1 message)

Next thread: Re: [RFC][PATCH] md: avoid fullsync if a faulty member missed a dirty transition by Neil Brown on Thursday, May 8, 2008 - 6:40 pm. (4 messages)
From: Rene Herman
Date: Thursday, May 8, 2008 - 6:37 pm

Good day.

commit 8779f2fc3b84ebb6c5181fb13d702e9944c16069

"x86: don't try to allocate from DMA zone at first"

breaks all of ISA DMA. Or all of ALSA ISA DMA at least. All
ISA soundcards are silent following that commit -- no error
messages, everything appears fine, just silence.

It won't just revert due to 32/64 merge.

Rene.


--

From: Takashi Iwai
Date: Thursday, May 8, 2008 - 11:06 pm

At Fri, 09 May 2008 03:37:54 +0200,

Thanks for catching it.  Yeah, the patch looks buggy.  We had an
implicit assumption that dev = NULL for ISA devices that require 24bit
DMA.

How about the patch below?  It's against the latest Linus git tree.


thanks,

Takashi


[PATCH] x86: Fix dma_alloc_coherent() for ISA devices

The recent work on x86 dma_alloc_coherent() breaks the ISA DMA buffer
allocation, which is represented by "dev = NULL" and requires 24bit
DMA implicitly.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

---

diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 0c37f16..c5ef1af 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -385,11 +385,13 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
 	if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
 		return memory;
 
-	if (!dev)
+	if (!dev) {
 		dev = &fallback_dev;
+		gfp |= GFP_DMA;
+	}
 	dma_mask = dev->coherent_dma_mask;
 	if (dma_mask == 0)
-		dma_mask = DMA_32BIT_MASK;
+		dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK;
 
 	/* Device not DMA able */
 	if (dev->dma_mask == NULL)
@@ -403,7 +405,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
 	   larger than 16MB and in this case we have a chance of
 	   finding fitting memory in the next higher zone first. If
 	   not retry with true GFP_DMA. -AK */
-	if (dma_mask <= DMA_32BIT_MASK)
+	if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA))
 		gfp |= GFP_DMA32;
 #endif
 
--

From: Ingo Molnar
Date: Friday, May 9, 2008 - 1:55 am

good catch! Queued it up for testing. Jesse, do you concur?

	Ingo
--

From: Ingo Molnar
Date: Friday, May 9, 2008 - 1:58 am

here's the patch below, tidied up.

	Ingo

------------------------------->
Subject: x86/pci: fix broken ISA DMA
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 09 May 2008 08:06:55 +0200


That patch is buggy. We had an implicit assumption that
dev = NULL for ISA devices that require 24bit DMA.

The recent work on x86 dma_alloc_coherent() breaks the ISA DMA buffer
allocation, which is represented by "dev = NULL" and requires 24bit
DMA implicitly.

Bisected-by: Rene Herman <rene.herman@keyaccess.nl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/kernel/pci-dma.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Index: linux-x86.q/arch/x86/kernel/pci-dma.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-dma.c
+++ linux-x86.q/arch/x86/kernel/pci-dma.c
@@ -386,11 +386,13 @@ dma_alloc_coherent(struct device *dev, s
 	if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
 		return memory;
 
-	if (!dev)
+	if (!dev) {
 		dev = &fallback_dev;
+		gfp |= GFP_DMA;
+	}
 	dma_mask = dev->coherent_dma_mask;
 	if (dma_mask == 0)
-		dma_mask = DMA_32BIT_MASK;
+		dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK;
 
 	/* Device not DMA able */
 	if (dev->dma_mask == NULL)
@@ -404,7 +406,7 @@ dma_alloc_coherent(struct device *dev, s
 	   larger than 16MB and in this case we have a chance of
 	   finding fitting memory in the next higher zone first. If
 	   not retry with true GFP_DMA. -AK */
-	if (dma_mask <= DMA_32BIT_MASK)
+	if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA))
 		gfp |= GFP_DMA32;
 #endif
 
--

From: Jesse Barnes
Date: Friday, May 9, 2008 - 10:20 am

Patch looks good, applied to my 'for-linus' tree.

Thanks,
Jesse
--

From: Rene Herman
Date: Friday, May 9, 2008 - 5:03 am

Yes, works well. Thank you.

Rene.
--

From: Ingo Molnar
Date: Friday, May 9, 2008 - 5:28 am

great, thanks Rene for catching this! Added this line to the patch as 
well:

 Tested-by: Rene Herman <rene.herman@keyaccess.nl>

	Ingo
--

From: Rene Herman
Date: Friday, May 9, 2008 - 4:00 pm

Oh... it was rather significantly in the AM when I posted so I forgot to
mention in the haste to get this out of the way but it was Pete Clements
who reported the regression:

http://www.nabble.com/Lost-Sound-from-2.6.24-to-2.6.25----CS4236-ISA-tc17062547.html

He also tested it, so as long as we're name-mention-flattering around...

And this a good excuse to ask how you edit changelog after the fact. Just
reset/reapply and stuff or is there a "better" way? I fairly frequently
find myself wanting to do just that but it's a bit of a mess when there's
already commits on top.

Rene.

--

From: Ingo Molnar
Date: Tuesday, May 13, 2008 - 7:36 am

generally we prefer append-only repositories for public trees.

But as long as you've not pushed it out to others yet, i.e. it's a 
purely local development tree, you can use two methods:

If it's just one commit in some devel branch that you want to put into a 
'fixes' branch one you can use git-cherry-pick --edit to shuffle it 
over.

For more complex scenarios you can use git-rebase --interactive to 
rebase your commits and to edit them. Replace the command "pick" with 
"edit" to change/fix the commit message. "squash" can be used to fold 
fixes.

	Ingo
--

From: Rene Herman
Date: Tuesday, May 13, 2008 - 8:26 am

Many thanks. Had in fact failed to notice --edit and will definitely 
check out the interactive rebase. Sounds very useful.

Rene.
--

From: Pete Clements
Date: Friday, May 9, 2008 - 5:29 am

Quoting Rene Herman
  > On 09-05-08 08:06, Takashi Iwai wrote:
  > 
  > > Thanks for catching it.  Yeah, the patch looks buggy.  We had an
  > > implicit assumption that dev = NULL for ISA devices that require 24bit
  > > DMA.
  > > 
  > > How about the patch below?  It's against the latest Linus git tree.
  > 
  > Yes, works well. Thank you.
  > 
  > Rene.
  > 
Confirmed here also with git7. Thanks

-- 
Pete Clements 
--

From: Glauber Costa
Date: Friday, May 9, 2008 - 5:48 am

Woke up and saw it, got worried, but there is already a fix. ;-)


--

From: Bjorn Helgaas
Date: Tuesday, May 13, 2008 - 9:59 am

Naive question #1:  Why don't we have a struct device for these
ISA devices?  PNP builds a struct device with DMA_24BIT_MASK
for ISAPNP devices.

Naive question #2:  Do other architectures need similar fixes in

--

From: Alan Cox
Date: Tuesday, May 13, 2008 - 10:01 am

On Tue, 13 May 2008 10:59:32 -0600

Because nobody has done the needed work to get all the old ISA drivers
converted. I guess isa_device would actually be a platform_device
wrapper ?

--

From: Rene Herman
Date: Tuesday, May 13, 2008 - 10:33 am

No, isa_device is its own thing, on its own isa_bus (*). It has a struct 
device * readily available though...

Rene

(*) drivers/base/isa.c, and explanatory changelog at:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=a5117b...
--

From: Bjorn Helgaas
Date: Tuesday, May 13, 2008 - 4:18 pm

Thanks for the nice changelog.

isa_register_driver() currently doesn't set a DMA mask.  Should it?

I only see about 35 dma_alloc_coherent() calls that pass NULL.  I
guess even those would be a fair amount of work to change, and I
suppose there would be more that I missed.

Bjorn
--

From: Takashi Iwai
Date: Wednesday, May 14, 2008 - 2:25 am

At Tue, 13 May 2008 17:18:39 -0600,

There are 5 pci_alloc_consistent() with NULL, too.


Takashi
--

From: Rene Herman
Date: Wednesday, May 14, 2008 - 5:46 am

If it's going to be useful, definitely. The attached does not just set

   dev->dma_mask = &dev->coherent_dma_mask

as in the fallback_dev when dma_alloc_coherent() is passed a NULL device 
only due to the mask juggling in snd_dma_hack_alloc_coherent() (which 
wouldn't break, but...) but introduces its own copy in struct isa_dev 
same as struct pnp_dev. As far as I'm aware, there's no actual reason 
for keeping it other than that and if the hack could go I'd rather lose 
the private mask copy again also.

(the device model still uses a plain u64 by the way but I guess the 
clean type would be a dma64_addr_t)


At least the ALSA one isn't passing a literal NULL it seems. But yes, 
current NULL-hack reinstatement (it's been merged by Linus already) is 
definitely the correct fix for now.

Would like a comment on the snd_dma_hack_alloc_coherent thing first (no 
signoff...) but other than that I'll submit this in preparation for it 
being useful, I guess?

Rene.
From: Takashi Iwai
Date: Wednesday, May 14, 2008 - 6:01 am

At Wed, 14 May 2008 14:46:44 +0200,

The snd_dma_hack_alloc_coherent() is gone in the latest ALSA tree.

Yes.  We need to fix the caller of snd_pcm_lib_preallocate_pages*()
under sound/isa.  Currently it's called with snd_dma_isa_data(), which
is expanded to NULL.  Replace it with a proper device pointer should
suffice.


Takashi
--

From: Rene Herman
Date: Wednesday, May 14, 2008 - 8:40 am

Like this? With this (on top of the previous patch setting the dma_mask 
ofcourse) legacy ISA actually appears to be fine but it's then ISAPnP 
which goes bonkers again. Sigh. Getting an allocation failure. Don't 
understand why yet since pnp_alloc_dev() definitely sets the mask 
already. Will stare...

Rene.
From: Takashi Iwai
Date: Wednesday, May 14, 2008 - 8:53 am

At Wed, 14 May 2008 17:40:55 +0200,

Check the master branch of the following tree for the latest ALSA:

I prefer passing the device pointer directly.

Note that snd_dma_isa_data() is just for making the code compatible
more easily with older kernels in alsa-driver tree.  Otherwise we'd
need a patch file for each source file.  But, the patch-file approach


thanks,

Takashi
--

From: Rene Herman
Date: Wednesday, May 14, 2008 - 11:41 am

On 14-05-08 17:40, Rene Herman wrote:


You're in a maze of struct device *s, all alike... I was passing the 
pnp_card->dev instead of the initialized pnp_dev->dev.

And, not doing so brings out a difference between ISAPnP and legacy ISA 
again insofar that legacy ISA does not consist of cards with multiple 
devices. We just have the single struct device * for the ISA device.

This therefore would be the easiest solution (and works fine) but seems 
a bit of a hack. Bjorn, do you have an opinion? If I abstract things out 
a bit more I might be able to do this nicer. One might on the other hand 
argue that the dma_mask is going to be constant for all card devices so 
might as well just use the card dev.

sound/{isa,oss} together with drivers/isdn/hisax/ are the only pnp_card 
users.

diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index a762a41..a2842a7 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
 #include <linux/pnp.h>
 #include "base.h"

@@ -167,6 +168,9 @@ struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnp
 	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
 		card->number);

+	card->dev.coherent_dma_mask = DMA_24BIT_MASK;
+	card->dev.dma_mask = &card->dev.coherent_dma_mask;
+
 	dev_id = pnp_add_card_id(card, pnpid);
 	if (!dev_id) {
 		kfree(card);

--

From: Bjorn Helgaas
Date: Wednesday, May 14, 2008 - 11:50 am

I agree, it seems a bit of a hack to use a DMA mask from the card
instead of from the device, since the driver should be programming
the device to do the DMA.

But I know very little about pnp_card in general, so don't attach too


--

From: Rene Herman
Date: Wednesday, May 14, 2008 - 12:09 pm

Okay, I'll sit on this for a bit. Right now we're using a global device even 
but this is exactly about cleaning that up so couldn't convince myself. Will 
see what happens when I try to make it nice...

Rene.
--

From: Rene Herman
Date: Friday, May 30, 2008 - 2:15 pm

It gets uglier. ALSA ISA drivers (for cards that exist both as legacy 
and as ISAPnP at least) keep a merged legacy/isapnp model; PnP is used 
mostly for initializing global variables that the same old legacy probe 
routines then reference. This means that beyond that global resource 
init step the specific struct device is no longer available. Without 
restructuring too many things really only fixable through other hacks 
again such as a global dma_dev[] array or some such.

 From the viewpoint of PnP itself setting the dma_mask for a pnp_card (a 
pnp_dev collection) makes isolated sense so if no objections, I'll 
submit the attached after all. From the ALSA side we'd then pass the 
card dev (which we'd also do for isa_dev) and keep in mind that we might 
want to get more specific if over time structure permits it.

struct snd_pcm already has its own struct device * which would be the 
right one here but it's setting that which gets ugly...

Rene.
From: Rene Herman
Date: Friday, May 30, 2008 - 2:28 pm

On 30-05-08 23:15, Rene Herman wrote:


... this note by the way I believe pnp_dev might as well get rid of its 
dma_mask as well. As far I've googled up the history of that the reason 
why dev->dma_mask is a pointer is only that it's been moved into struct 
device from struct pci_dev where the latter location was kept as the 
main one so as to not upset then current code.

Everyone else seems to have then faithfully cloned pci_dev and stuck it 
in their private structs as well but for no good reason it would appear.

And in the case of the PnP ISA masks, we're talking about constant 
masks, dictated by the shared global DMA controller and not the card 
itself (there are a few ISA cards that do their own busmastering but 
they're special) so the mask might as well just point to the coherent mask.

Unless I'm missing something ofcourse...

Rene.
--

From: Bjorn Helgaas
Date: Friday, May 30, 2008 - 2:43 pm

Looks good to me.  It does sound like a lot of work and possibly
more risk than it's worth to fix up some of this stuff.

I do still wonder whether any non-x86 architectures need similar
fixes in dma_alloc_coherent(), i.e., check for dev==NULL and fall
back to a 24-bit DMA mask.

Acked-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
--

From: Rene Herman
Date: Friday, May 30, 2008 - 3:11 pm

Fairly invasive at least. The good thing though is that with the recent 
pnp_manual_config_dev() removal the PnP drivers have no actual need/use 
for this global variable model anymore and now I have a great excuse for 

Hrmmpf. Good question. In sound/isa, we've had a but of alpha spottyness 

Thanks. I'll assume Andrew picks it up from the CC...

Rene.
--

From: Rene Herman
Date: Friday, May 30, 2008 - 3:37 pm

On 31-05-08 00:11, Rene Herman wrote:


And here's the ISA one...

Rene.
From: Andrew Morton
Date: Friday, May 30, 2008 - 3:55 pm

On Sat, 31 May 2008 00:37:05 +0200



Argh.  Could we please be better with the changelogs?

This one tells us briefly what the patch does, but it deosn't tell us
why it does it.  It doesn't tell us whether it fixes some bug (and if
so what that bug is) and it gives me no means of determining whether
the patch is needed in 2.6.26 or in 2.6.25.x.

Ditto pnp-set-the-pnp_card-dma_mask-for-use-by-isapnp-cards.patch
--

From: Rene Herman
Date: Friday, May 30, 2008 - 4:50 pm

If you already knew what it was about these were nicely concise and to 
the point...

Yaya. I'll resend.

Rene.
--

From: Rene Herman
Date: Friday, May 30, 2008 - 4:54 pm

From: Takashi Iwai
Date: Saturday, May 31, 2008 - 1:55 am

At Sat, 31 May 2008 01:54:10 +0200,

Acked-by: Takashi Iwai <tiwai@suse.de>


thanks,

--

From: Rene Herman
Date: Friday, May 30, 2008 - 4:55 pm

[Empty message]
From: Takashi Iwai
Date: Saturday, May 31, 2008 - 1:56 am

At Sat, 31 May 2008 01:55:52 +0200,

Acked-by: Takashi Iwai <tiwai@suse.de>


--

From: Bjorn Helgaas
Date: Wednesday, May 14, 2008 - 8:26 am

Yes, I like this patch.
--

Previous thread: [PATCH] IPMI: Support I/O resources in OF driver by Corey Minyard on Thursday, May 8, 2008 - 6:22 pm. (1 message)

Next thread: Re: [RFC][PATCH] md: avoid fullsync if a faulty member missed a dirty transition by Neil Brown on Thursday, May 8, 2008 - 6:40 pm. (4 messages)