Commit 9eb9e96e authored by Christoph Hellwig's avatar Christoph Hellwig

Documentation/DMA-API-HOWTO: update dma_mask sections

We don't require drivers to guess a DMA mask that might actually
match the system capabilities any more, so fix up the documentation
to clear this up.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 24132a41
...@@ -146,114 +146,75 @@ What about block I/O and networking buffers? The block I/O and ...@@ -146,114 +146,75 @@ What about block I/O and networking buffers? The block I/O and
networking subsystems make sure that the buffers they use are valid networking subsystems make sure that the buffers they use are valid
for you to DMA from/to. for you to DMA from/to.
DMA addressing limitations DMA addressing capabilities
========================== ==========================
Does your device have any DMA addressing limitations? For example, is By default, the kernel assumes that your device can address 32-bits of DMA
your device only capable of driving the low order 24-bits of address? addressing. For a 64-bit capable device, this needs to be increased, and for
If so, you need to inform the kernel of this fact. a device with limitations, it needs to be decreased.
By default, the kernel assumes that your device can address the full Special note about PCI: PCI-X specification requires PCI-X devices to support
32-bits. For a 64-bit capable device, this needs to be increased. 64-bit addressing (DAC) for all transactions. And at least one platform (SGI
And for a device with limitations, as discussed in the previous SN2) requires 64-bit consistent allocations to operate correctly when the IO
paragraph, it needs to be decreased. bus is in PCI-X mode.
Special note about PCI: PCI-X specification requires PCI-X devices to For correct operation, you must set the DMA mask to inform the kernel about
support 64-bit addressing (DAC) for all transactions. And at least your devices DMA addressing capabilities.
one platform (SGI SN2) requires 64-bit consistent allocations to
operate correctly when the IO bus is in PCI-X mode.
For correct operation, you must interrogate the kernel in your device This is performed via a call to dma_set_mask_and_coherent()::
probe routine to see if the DMA controller on the machine can properly
support the DMA addressing limitation your device has. It is good
style to do this even if your device holds the default setting,
because this shows that you did think about these issues wrt. your
device.
The query is performed via a call to dma_set_mask_and_coherent()::
int dma_set_mask_and_coherent(struct device *dev, u64 mask); int dma_set_mask_and_coherent(struct device *dev, u64 mask);
which will query the mask for both streaming and coherent APIs together. which will set the mask for both streaming and coherent APIs together. If you
If you have some special requirements, then the following two separate have some special requirements, then the following two separate calls can be
queries can be used instead: used instead:
The query for streaming mappings is performed via a call to The setup for streaming mappings is performed via a call to
dma_set_mask():: 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 The setup for consistent allocations is performed via a call
to 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);
Here, dev is a pointer to the device struct of your device, and mask Here, dev is a pointer to the device struct of your device, and mask is a bit
is a bit mask describing which bits of an address your device mask describing which bits of an address your device supports. Often the
supports. It returns zero if your card can perform DMA properly on device struct of your device is embedded in the bus-specific device struct of
the machine given the address mask you provided. In general, the your device. For example, &pdev->dev is a pointer to the device struct of a
device struct of your device is embedded in the bus-specific device PCI device (pdev is a pointer to the PCI device struct of your device).
struct of your device. For example, &pdev->dev is a pointer to the
device struct of a PCI device (pdev is a pointer to the PCI device
struct of your device).
If it returns non-zero, your device cannot perform DMA properly on These calls usually return zero to indicated your device can perform DMA
this platform, and attempting to do so will result in undefined properly on the machine given the address mask you provided, but they might
behavior. You must either use a different mask, or not use DMA. return an error if the mask is too small to be supportable on the given
system. If it returns non-zero, your device cannot perform DMA properly on
this platform, and attempting to do so will result in undefined behavior.
You must not use DMA on this device unless the dma_set_mask family of
functions has returned success.
This means that in the failure case, you have three options: This means that in the failure case, you have two options:
1) Use another DMA mask, if possible (see below). 1) Use some non-DMA mode for data transfer, if possible.
2) Use some non-DMA mode for data transfer, if possible. 2) Ignore this device and do not initialize it.
3) Ignore this device and do not initialize it.
It is recommended that your driver print a kernel KERN_WARNING message It is recommended that your driver print a kernel KERN_WARNING message when
when you end up performing either #2 or #3. In this manner, if a user setting the DMA mask fails. In this manner, if a user of your driver reports
of your driver reports that performance is bad or that the device is not that performance is bad or that the device is not even detected, you can ask
even detected, you can ask them for the kernel messages to find out them for the kernel messages to find out exactly why.
exactly why.
The standard 32-bit addressing device would do something like this:: The standard 64-bit addressing device would do something like this::
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
dev_warn(dev, "mydev: No suitable DMA available\n"); dev_warn(dev, "mydev: No suitable DMA available\n");
goto ignore_this_device; goto ignore_this_device;
} }
Another common scenario is a 64-bit capable device. The approach here If the device only supports 32-bit addressing for descriptors in the
is to try for 64-bit addressing, but back down to a 32-bit mask that coherent allocations, but supports full 64-bits for streaming mappings
should not fail. The kernel may fail the 64-bit mask not because the it would look like this:
platform is not capable of 64-bit addressing. Rather, it may fail in
this case simply because 32-bit addressing is done more efficiently
than 64-bit addressing. For example, Sparc64 PCI SAC addressing is
more efficient than DAC addressing.
Here is how you would handle a 64-bit capable device which can drive
all 64-bits when accessing streaming DMA::
int using_dac;
if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { if (dma_set_mask(dev, DMA_BIT_MASK(64))) {
using_dac = 1;
} else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
using_dac = 0;
} else {
dev_warn(dev, "mydev: No suitable DMA available\n");
goto ignore_this_device;
}
If a card is capable of using 64-bit consistent allocations as well,
the case would look like this::
int using_dac, consistent_using_dac;
if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
using_dac = 1;
consistent_using_dac = 1;
} else if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
using_dac = 0;
consistent_using_dac = 0;
} else {
dev_warn(dev, "mydev: No suitable DMA available\n"); dev_warn(dev, "mydev: No suitable DMA available\n");
goto ignore_this_device; goto ignore_this_device;
} }
......
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