kfree(buf->sgt_base);
}
dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+ put_device(buf->dev);
kfree(buf);
}
if (!buf)
return ERR_PTR(-ENOMEM);
+ /* align image size to PAGE_SIZE */
+ size = PAGE_ALIGN(size);
+
buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
if (!buf->vaddr) {
dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
return ERR_PTR(-ENOMEM);
}
- buf->dev = dev;
+ /* Prevent the device from being released while the buffer is used */
+ buf->dev = get_device(dev);
buf->size = size;
buf->handler.refcount = &buf->refcount;
struct vm_area_struct *vma;
struct sg_table *sgt;
unsigned long contig_size;
+ unsigned long dma_align = dma_get_cache_alignment();
+
+ /* Only cache aligned DMA transfers are reliable */
+ if (!IS_ALIGNED(vaddr | size, dma_align)) {
+ pr_debug("user data must be aligned to %lu bytes\n", dma_align);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!size) {
+ pr_debug("size is zero\n");
+ return ERR_PTR(-EINVAL);
+ }
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)