Skip to contentSkip to conversation

dma_ops->map_page == NULL

DISCUSSION Kári Davíðsson 6 participants 9 messages Jul 6, 2009 – Jul 8, 2009

lore
Share & tools
lore
#0 lore raw

I am doing a driver that uses dma_map_single().

After changing to to linux 2.6.29.3 I am getting segfaults in dma_map_single() because dma_ops->map_page is NULL. Actually dma_ops looks funky too.

The driver is an of_platform_driver which is declared as an child of the lbp (fsl,lpb) node of the device tree.

This is on powerpc 5200b platform.

rg
kd

#1 lore raw
Quoted 5 lines · On Tuesday 07 July 2009 03:51:00 K=E1ri Dav=ED=F0sson wrote:

I am doing a driver that uses dma_map_single().
=20
After changing to to linux 2.6.29.3 I am getting segfaults in dma_map_single() because dma_ops->map_page is NULL. Actually dma_ops looks funky too.

When the 32 and 64bit DMA code was merged in .28 , map_/unmap_page() was added in favour of map_/unmap_single() (which was later removed in .29) so you'll have to replace your calls to dma_map_single() with dma_map_page(). Just pass it the page and offset rather than the address.

Hope that helps!
Mark.

Quoted 8 lines

=20
The driver is an of_platform_driver which is declared as an child of the lbp (fsl,lpb) node of the device tree.
=20
This is on powerpc 5200b platform.
=20
rg
kd

#2 lore raw
Quoted 5 lines · Mark Nelson

When the 32 and 64bit DMA code was merged in .28 , map_/unmap_page() was added in favour of map_/unmap_single() (which was later removed in .29) so you'll have to replace your calls to dma_map_single() with dma_map_page(). Just pass it the page and offset rather than the address.

Wait a minute ... dma_map_single() should still work, it will just call dma_map_page() underneath. All dma_ops should have a ->map page callback.

Do you have any dma_ops set for your device at all ? I wonder how we set the dma_ops for platform devices nowadays ... We use to have this fallback to direct ops when the dma_ops are NULL but that is gone and I see no suitable replacement to set them on platform devices for embedded archs ... oops...

Kumar, Becky, what's the situation there ?

Cheers,
Ben.

#8 lore raw
In reply to Kári Davíðsson
Quoted 10 lines · On Mon, Jul 6, 2009 at 1:51 PM, K=E1ri Dav=ED=F0sson<[email protected]=…

I am doing a driver that uses dma_map_single().

After changing to to linux 2.6.29.3 I am getting segfaults in dma_map_single() because dma_ops->map_page is NULL. Actually dma_ops looks funky too.

The driver is an of_platform_driver which is declared as an child of the lbp (fsl,lpb) node of the device tree.

This is on powerpc 5200b platform.

I have hit this before, in my case the driver pointer was null. It faulted on dma_ops->map_page which had nothing to do with the real problem which was the null driver pointer. I spent a long time looking at this until I figured out that the reported error was bogus compared to the actual problem.

Quoted 9 lines

rg
kd

_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://lists.ozlabs.org/listinfo/linuxppc-dev

--=20
Jon Smirl
[email protected]

#3 lore raw
In reply to Benjamin Herrenschmidt
Quoted 17 lines · Benjamin Herrenschmidt
Quoted 5 lines · Mark Nelson

When the 32 and 64bit DMA code was merged in .28 , map_/unmap_page() was added in favour of map_/unmap_single() (which was later removed in .29) so you'll have to replace your calls to dma_map_single() with dma_map_page(). Just pass it the page and offset rather than the address.

Wait a minute ... dma_map_single() should still work, it will just call dma_map_page() underneath. All dma_ops should have a ->map page callback.

Do you have any dma_ops set for your device at all ? I wonder how we set the dma_ops for platform devices nowadays ... We use to have this fallback to direct ops when the dma_ops are NULL but that is gone and I see no suitable replacement to set them on platform devices for embedded archs ... oops...

Quoted 4 lines

Kumar, Becky, what's the situation there ?

Cheers,
Ben.

Is it possible the dev pointer is not valid? I can't remember if that was a .29 or .30 change that requires us to start passing a valid dev pointer to get the proper dma_ops.

- k

#4 lore raw

Yes the device pointer was invalid.

I was passing the of_device pointer instead of
the address of of_device->dev.

But I am sure this was working (passing of_device pointer) with earlier kernels.

Thanks for the help.

rg
kd

Quoted 25 lines · Kumar Gala
Quoted 15 lines · Benjamin Herrenschmidt
Quoted 4 lines · Mark Nelson

When the 32 and 64bit DMA code was merged in .28 , map_/ unmap_page() was added in favour of map_/unmap_single() (which was later removed in . 29) so you'll have to replace your calls to dma_map_single() with dma_map_page(). Just pass it the page and offset rather than the address.

Wait a minute ... dma_map_single() should still work, it will just call dma_map_page() underneath. All dma_ops should have a ->map page callback.

Do you have any dma_ops set for your device at all ? I wonder how we set the dma_ops for platform devices nowadays ... We use to have this fallback to direct ops when the dma_ops are NULL but that is gone and I see no suitable replacement to set them on platform devices for embedded archs ... oops...

Quoted 4 lines

Kumar, Becky, what's the situation there ?

Cheers,
Ben.

Is it possible the dev pointer is not valid? I can't remember if that was a .29 or .30 change that requires us to start passing a valid dev pointer to get the proper dma_ops.

- k

#6 lore raw
In reply to Kumar Gala
Quoted 16 lines · Kumar Gala
Quoted 13 lines · Benjamin Herrenschmidt
Quoted 5 lines · Mark Nelson

When the 32 and 64bit DMA code was merged in .28 , map_/unmap_page() was added in favour of map_/unmap_single() (which was later removed in .29) so you'll have to replace your calls to dma_map_single() with dma_map_page(). Just pass it the page and offset rather than the address.

Wait a minute ... dma_map_single() should still work, it will just call dma_map_page() underneath. All dma_ops should have a ->map page callback.

Quoted 5 lines
Quoted 5 lines

Do you have any dma_ops set for your device at all ? I wonder how we set the dma_ops for platform devices nowadays ... We use to have this fallback to direct ops when the dma_ops are NULL but that is gone and I see no suitable replacement to set them on platform devices for embedded archs ... oops...

There is a platform/of bus notifier that sets the dma_ops to a default value in arch/powerpc/kernel/setup-common.c.

Quoted 8 lines
Quoted 6 lines

Kumar, Becky, what's the situation there ?

Cheers,
Ben.

Is it possible the dev pointer is not valid? I can't remember if that was a .29 or .30 change that requires us to start passing a valid dev pointer to get the proper dma_ops.

I'm pretty sure that went into .29. And invalid dev pointer is the most likely culprit. IIRC, the usual cause of this is that you're passing in the *wrong* dev pointer. There are often struct hierarchies with, confusingly, multiple struct device pointers. You need the one which has archdata dma_ops setup properly. For an of device, you want the dev pointer that is part of the of_device struct.

If this isn't your problem, then please post some code so we can look at this further, and post a log of what's happening.

Cheers,
Becky

#5 lore raw
In reply to Kári Davíðsson
Quoted 5 lines · On Jul 7, 2009, at 10:24 AM, K=E1ri Dav=ED=F0sson wrote:

Yes the device pointer was invalid.

I was passing the of_device pointer instead of
the address of of_device->dev.

Quoted 7 lines

But I am sure this was working (passing of_device pointer) with earlier kernels.

Thanks for the help.

rg
kd

earlier kernels didn't care if the dev pointer was valid and thus let =20=

it pass if you didn't give the proper thing.

- k=

#7 lore raw
In reply to Benjamin Herrenschmidt
Quoted 10 lines · On Tuesday 07 July 2009 21:08:25 Benjamin Herrenschmidt wrote:
Quoted 5 lines · Mark Nelson

When the 32 and 64bit DMA code was merged in .28 , map_/unmap_page() was added in favour of map_/unmap_single() (which was later removed in .29) so you'll have to replace your calls to dma_map_single() with dma_map_page(). Just pass it the page and offset rather than the address.

Wait a minute ... dma_map_single() should still work, it will just call dma_map_page() underneath. All dma_ops should have a ->map page callback.

Sorry my mistake - I was thinking of when we removed the map/unmap_single() from the dma_mapping_ops.

Mark.