Commit 4aa806b7 authored by Russell King's avatar Russell King

DMA-API: provide a helper to set both DMA and coherent DMA masks

Provide a helper to set both the DMA and coherent DMA masks to the
same value - this avoids duplicated code in a number of drivers,
sometimes with buggy error handling, and also allows us identify
which drivers do things differently.
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 272b98c6
...@@ -101,12 +101,21 @@ style to do this even if your device holds the default setting, ...@@ -101,12 +101,21 @@ style to do this even if your device holds the default setting,
because this shows that you did think about these issues wrt. your because this shows that you did think about these issues wrt. your
device. device.
The query is performed via a call to dma_set_mask(): The query is performed via a call to dma_set_mask_and_coherent():
int dma_set_mask_and_coherent(struct device *dev, u64 mask);
which will query the mask for both streaming and coherent APIs together.
If you have some special requirements, then the following two separate
queries can be used instead:
The query for streaming mappings is performed via a call to
dma_set_mask():
int dma_set_mask(struct device *dev, u64 mask); int dma_set_mask(struct device *dev, u64 mask);
The query for consistent allocations is performed via a call to The query for consistent allocations is performed via a call
dma_set_coherent_mask(): to dma_set_coherent_mask():
int dma_set_coherent_mask(struct device *dev, u64 mask); int dma_set_coherent_mask(struct device *dev, u64 mask);
...@@ -137,7 +146,7 @@ exactly why. ...@@ -137,7 +146,7 @@ exactly why.
The standard 32-bit addressing device would do something like this: The standard 32-bit addressing device would do something like this:
if (dma_set_mask(dev, DMA_BIT_MASK(32))) { if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
printk(KERN_WARNING printk(KERN_WARNING
"mydev: No suitable DMA available.\n"); "mydev: No suitable DMA available.\n");
goto ignore_this_device; goto ignore_this_device;
...@@ -171,22 +180,20 @@ the case would look like this: ...@@ -171,22 +180,20 @@ the case would look like this:
int using_dac, consistent_using_dac; int using_dac, consistent_using_dac;
if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
using_dac = 1; using_dac = 1;
consistent_using_dac = 1; consistent_using_dac = 1;
dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); } else if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
} else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
using_dac = 0; using_dac = 0;
consistent_using_dac = 0; consistent_using_dac = 0;
dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
} else { } else {
printk(KERN_WARNING printk(KERN_WARNING
"mydev: No suitable DMA available.\n"); "mydev: No suitable DMA available.\n");
goto ignore_this_device; goto ignore_this_device;
} }
dma_set_coherent_mask() will always be able to set the same or a The coherent coherent mask will always be able to set the same or a
smaller mask as dma_set_mask(). However for the rare case that a smaller mask as the streaming mask. However for the rare case that a
device driver only uses consistent allocations, one would have to device driver only uses consistent allocations, one would have to
check the return value from dma_set_coherent_mask(). check the return value from dma_set_coherent_mask().
...@@ -199,9 +206,9 @@ address you might do something like: ...@@ -199,9 +206,9 @@ address you might do something like:
goto ignore_this_device; goto ignore_this_device;
} }
When dma_set_mask() is successful, and returns zero, the kernel saves When dma_set_mask() or dma_set_mask_and_coherent() is successful, and
away this mask you have provided. The kernel will use this returns zero, the kernel saves away this mask you have provided. The
information later when you make DMA mappings. kernel will use this information later when you make DMA mappings.
There is a case which we are aware of at this time, which is worth There is a case which we are aware of at this time, which is worth
mentioning in this documentation. If your device supports multiple mentioning in this documentation. If your device supports multiple
......
...@@ -141,6 +141,14 @@ won't change the current mask settings. It is more intended as an ...@@ -141,6 +141,14 @@ won't change the current mask settings. It is more intended as an
internal API for use by the platform than an external API for use by internal API for use by the platform than an external API for use by
driver writers. driver writers.
int
dma_set_mask_and_coherent(struct device *dev, u64 mask)
Checks to see if the mask is possible and updates the device
streaming and coherent DMA mask parameters if it is.
Returns: 0 if successful and a negative error if not.
int int
dma_set_mask(struct device *dev, u64 mask) dma_set_mask(struct device *dev, u64 mask)
......
...@@ -97,6 +97,20 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask) ...@@ -97,6 +97,20 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask)
} }
#endif #endif
/*
* Set both the DMA mask and the coherent DMA mask to the same thing.
* Note that we don't check the return value from dma_set_coherent_mask()
* as the DMA API guarantees that the coherent DMA mask can be set to
* the same or smaller than the streaming DMA mask.
*/
static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
{
int rc = dma_set_mask(dev, mask);
if (rc == 0)
dma_set_coherent_mask(dev, mask);
return rc;
}
extern u64 dma_get_required_mask(struct device *dev); extern u64 dma_get_required_mask(struct device *dev);
static inline unsigned int dma_get_max_seg_size(struct device *dev) static inline unsigned int dma_get_max_seg_size(struct device *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment