dosmanak
dosmanak

Reputation: 508

struct device creation for dma_alloc_coherent with device_create

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

Answers (1)

eldukae
eldukae

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

Related Questions