Reputation: 508
I want to implement mmap method on DMAble memmory for my char driver. At first I would like to realize it with DMA API and then for PCI device.
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
dma_alloc_coherent's first argument is pointer to a struct device. For ISA or EISA it can be NULL, but I need valid device which supports DMA. Following code should make the work, but allocation fails.
/* register device in sysfs */
mmrmp->udev = device_create(mmrmp->class, NULL, mmrmp->major, NULL, DEVICE_NAME);
if (mmrmp->udev == NULL)
{
goto devcreate_failed;
}
printk(KERN_INFO "%s: Char driver initialized and added to the system at addr %p", __func__, mmrmp->udev);
if(dma_supported(mmrmp->udev,DMA_BIT_MASK(32)))
printk(KERN_INFO "device supports DMA");
else
printk(KERN_INFO "device does not support DMA");
if(is_device_dma_capable(mmrmp->udev))
printk(KERN_INFO "is_device_dma_capable: device supports DMA");
else
printk(KERN_INFO "is_device_dma_capable: device does not support DMA");
if (!dma_set_mask(mmrmp->udev, dma_get_required_mask(mmrmp->udev)))
printk(KERN_INFO "set DMA mask failed");
if ((mmrmp->dma_handle & dma_get_required_mask(mmrmp->udev)) == mmrmp->dma_handle)
printk(KERN_INFO "Allocated physical address is within DMA region");
mmrmp->data = dma_alloc_coherent(mmrmp->udev, PAGE_SIZE, &mmrmp->dma_handle, GFP_KERNEL);
Why dma_supported returns 1 and is_dma_capable_returns 0? How should I create my device to support dma_alloc_coherent?
Upvotes: 4
Views: 1828
Reputation: 91
Make sure the mmrmp->udev->dma_mask pointer
is not NULL. Initialize it as follows:
static const u64 dmamask = DMA_BIT_MASK(32);
mmrmp->udev->dma_mask = (u64 *)&dmamask;
mmrmp->udev->coherent_dma_mask = DMA_BIT_MASK(32);
Upvotes: 1