linux dma_set_mask DMA寻址能力

原文来自:dma-api-howto.rst

如下:

DMA addressing capabilities
===========================

By default, the kernel assumes that your device can address 32-bits of DMA
addressing.  For a 64-bit capable device, this needs to be increased, and for
a device with limitations, it needs to be decreased.

Special note about PCI: PCI-X specification requires PCI-X devices to support
64-bit addressing (DAC) for all transactions.  And at least 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 set the DMA mask to inform the kernel about
your devices DMA addressing capabilities.

This is performed via a call to dma_set_mask_and_coherent()::

    int dma_set_mask_and_coherent(struct device *dev, u64 mask);

which will set the mask for both streaming and coherent APIs together.  If you
have some special requirements, then the following two separate calls can be
used instead:

    The setup for streaming mappings is performed via a call to
    dma_set_mask()::

        int dma_set_mask(struct device *dev, u64 mask);

    The setup for consistent allocations is performed via a call
    to dma_set_coherent_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 is a bit
mask describing which bits of an address your device supports.  Often the
device struct of your device is embedded in the bus-specific 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).

These calls usually return zero to indicated your device can perform DMA
properly on the machine given the address mask you provided, but they might
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 two options:

1) Use some non-DMA mode for data transfer, if possible.
2) Ignore this device and do not initialize it.

It is recommended that your driver print a kernel KERN_WARNING message when
setting the DMA mask fails.  In this manner, if a user of your driver reports
that performance is bad or that the device is not even detected, you can ask
them for the kernel messages to find out exactly why.

The standard 64-bit addressing device would do something like this::

    if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
        dev_warn(dev, "mydev: No suitable DMA available\n");
        goto ignore_this_device;
    }

If the device only supports 32-bit addressing for descriptors in the
coherent allocations, but supports full 64-bits for streaming mappings
it would look like this::

    if (dma_set_mask(dev, DMA_BIT_MASK(64))) {
        dev_warn(dev, "mydev: No suitable DMA available\n");
        goto ignore_this_device;
    }

The coherent mask will always be able to set the same or a smaller mask as
the streaming mask. However for the rare case that a device driver only
uses consistent allocations, one would have to check the return value from
dma_set_coherent_mask().

Finally, if your device can only drive the low 24-bits of
address you might do something like::

    if (dma_set_mask(dev, DMA_BIT_MASK(24))) {
        dev_warn(dev, "mydev: 24-bit DMA addressing not available\n");
        goto ignore_this_device;
    }

When dma_set_mask() or dma_set_mask_and_coherent() is successful, and
returns zero, the kernel saves away this mask you have provided.  The
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
mentioning in this documentation.  If your device supports multiple
functions (for example a sound card provides playback and record
functions) and the various different functions have _different_
DMA addressing limitations, you may wish to probe each mask and
only provide the functionality which the machine can handle.  It
is important that the last call to dma_set_mask() be for the
most specific mask.

Here is pseudo-code showing how this might be done::

    #define PLAYBACK_ADDRESS_BITS    DMA_BIT_MASK(32)
    #define RECORD_ADDRESS_BITS    DMA_BIT_MASK(24)

    struct my_sound_card *card;
    struct device *dev;

    ...
    if (!dma_set_mask(dev, PLAYBACK_ADDRESS_BITS)) {
        card->playback_enabled = 1;
    } else {
        card->playback_enabled = 0;
        dev_warn(dev, "%s: Playback disabled due to DMA limitations\n",
               card->name);
    }
    if (!dma_set_mask(dev, RECORD_ADDRESS_BITS)) {
        card->record_enabled = 1;
    } else {
        card->record_enabled = 0;
        dev_warn(dev, "%s: Record disabled due to DMA limitations\n",
               card->name);
    }

A sound card was used as an example here because this genre of PCI
devices seems to be littered with ISA chips given a PCI front end,
and thus retaining the 16MB DMA addressing limitations of ISA.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值