Hello,
From the book "Linux device drivers" (3rd edition), I find an
interesting rule for streaming DMA mapping:
Once a buffer has been mapped, it belongs to the device, not the
processor. Until
the buffer has been unmapped, the driver should not touch its contents
in any
way. Only after dma_unmap_single has been called is it safe for the
driver to
access the contents of the buffer (with one exception that we see shortly).
Among other things, this rule implies that a buffer being written to a
device cannot
be mapped until it contains all the data to write.
I find some violations about this rule, and there are two examples in
Linux-5.6:
=== EXAMPLE 1 ===
In vmxnet3_probe_device() in drivers/net/vmxnet3/vmxnet3_drv.c:
adapter->adapter_pa = dma_map_single(&adapter->pdev->dev, adapter,
sizeof(struct vmxnet3_adapter),
PCI_DMA_TODEVICE);
if (dma_mapping_error(&adapter->pdev->dev, adapter->adapter_pa)) {
dev_err(&pdev->dev, "Failed to map dma\n");
err = -EFAULT;
goto err_set_mask;
}
adapter->shared = dma_alloc_coherent(
&adapter->pdev->dev,
sizeof(struct Vmxnet3_DriverShared),
&adapter->shared_pa, GFP_KERNEL);
if (!adapter->shared) {
dev_err(&pdev->dev, "Failed to allocate memory\n");
err = -ENOMEM;
goto err_alloc_shared;
}
adapter->num_rx_queues = num_rx_queues;
adapter->num_tx_queues = num_tx_queues;
adapter->rx_buf_per_pkt = 1;
The variable "adapter" is mapped to streaming DMA, but its fields are
used before this variable is unmapped.
=== EXAMPLE 2 ===
In queue_skb() in drivers/atm/idt77252.c:
IDT77252_PRV_PADDR(skb) = dma_map_single(&card->pcidev->dev, skb->data,
skb->len, DMA_TO_DEVICE);
error = -EINVAL;
if (oam) {
if (skb->len != 52)
goto errout;
tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU;
tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
tbd->word_3 = 0x00000000;
tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
(skb->data[2] << 8) | (skb->data[3] << 0);
The array "skb->data" is mapped to streaming DMA, but its elements are
used before this array is unmapped.
Because I am not familiar with streaming DMA mapping, I wonder whether
these violations are real?
If they are real, what problems can they cause?
Thanks a lot :)
Best wishes,
Jia-Ju Bai