@@ -224,6 +224,28 @@ static int add_to_unpin_list(struct list_head *unpin_list,
return 0;
}
+static __always_inline int init_udmabuf(struct udmabuf *ubuf, pgoff_t pgcnt)
+{
+ INIT_LIST_HEAD(&ubuf->unpin_list);
+
+ ubuf->folios = kvmalloc_array(pgcnt, sizeof(*ubuf->folios), GFP_KERNEL);
+ if (!ubuf->folios)
+ return -ENOMEM;
+
+ ubuf->offsets = kvcalloc(pgcnt, sizeof(*ubuf->offsets), GFP_KERNEL);
+ if (!ubuf->offsets)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static __always_inline void deinit_udmabuf(struct udmabuf *ubuf)
+{
+ unpin_all_folios(&ubuf->unpin_list);
+ kvfree(ubuf->offsets);
+ kvfree(ubuf->folios);
+}
+
static void release_udmabuf(struct dma_buf *buf)
{
struct udmabuf *ubuf = buf->priv;
@@ -232,9 +254,7 @@ static void release_udmabuf(struct dma_buf *buf)
if (ubuf->sg)
put_sg_table(dev, ubuf->sg, DMA_BIDIRECTIONAL);
- unpin_all_folios(&ubuf->unpin_list);
- kvfree(ubuf->offsets);
- kvfree(ubuf->folios);
+ deinit_udmabuf(ubuf);
kfree(ubuf);
}
@@ -395,33 +415,24 @@ static long udmabuf_create(struct miscdevice *device,
if (!ubuf)
return -ENOMEM;
- INIT_LIST_HEAD(&ubuf->unpin_list);
pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT;
for (i = 0; i < head->count; i++) {
if (!PAGE_ALIGNED(list[i].offset))
- goto err;
+ goto err_noinit;
if (!PAGE_ALIGNED(list[i].size))
- goto err;
+ goto err_noinit;
pgcnt += list[i].size >> PAGE_SHIFT;
if (pgcnt > pglimit)
- goto err;
+ goto err_noinit;
}
if (!pgcnt)
- goto err;
+ goto err_noinit;
- ubuf->folios = kvmalloc_array(pgcnt, sizeof(*ubuf->folios), GFP_KERNEL);
- if (!ubuf->folios) {
- ret = -ENOMEM;
+ ret = init_udmabuf(ubuf, pgcnt);
+ if (ret)
goto err;
- }
-
- ubuf->offsets = kvcalloc(pgcnt, sizeof(*ubuf->offsets), GFP_KERNEL);
- if (!ubuf->offsets) {
- ret = -ENOMEM;
- goto err;
- }
for (i = 0; i < head->count; i++) {
struct file *memfd = fget(list[i].memfd);
@@ -452,9 +463,8 @@ static long udmabuf_create(struct miscdevice *device,
return ret;
err:
- unpin_all_folios(&ubuf->unpin_list);
- kvfree(ubuf->offsets);
- kvfree(ubuf->folios);
+ deinit_udmabuf(ubuf);
+err_noinit:
kfree(ubuf);
return ret;
}