From ea08eeccae9297f7aabd2ef7f0c2517ac4549acc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:18:26 +0000
Subject: [PATCH] write in 30M
---
kernel/drivers/dma-buf/dma-buf-cache.c | 102 +++++++++++++++++++++++++++++++-------------------
1 files changed, 63 insertions(+), 39 deletions(-)
diff --git a/kernel/drivers/dma-buf/dma-buf-cache.c b/kernel/drivers/dma-buf/dma-buf-cache.c
index 7bfa6a5..5ec8896 100644
--- a/kernel/drivers/dma-buf/dma-buf-cache.c
+++ b/kernel/drivers/dma-buf/dma-buf-cache.c
@@ -8,9 +8,10 @@
#undef CONFIG_DMABUF_CACHE
#include <linux/dma-buf-cache.h>
+/* NOTE: dma-buf-cache APIs are not irq safe, please DO NOT run in irq context !! */
+
struct dma_buf_cache_list {
struct list_head head;
- struct mutex lock;
};
struct dma_buf_cache {
@@ -25,9 +26,10 @@
struct dma_buf_cache_list *data;
struct dma_buf_cache *cache, *tmp;
+ mutex_lock(&dmabuf->cache_lock);
+
data = dmabuf->dtor_data;
- mutex_lock(&data->lock);
list_for_each_entry_safe(cache, tmp, &data->head, list) {
if (!IS_ERR_OR_NULL(cache->sg_table))
dma_buf_unmap_attachment(cache->attach,
@@ -37,9 +39,9 @@
dma_buf_detach(dmabuf, cache->attach);
list_del(&cache->list);
kfree(cache);
-
}
- mutex_unlock(&data->lock);
+
+ mutex_unlock(&dmabuf->cache_lock);
kfree(data);
return 0;
@@ -57,14 +59,10 @@
data = dmabuf->dtor_data;
- mutex_lock(&data->lock);
list_for_each_entry(cache, &data->head, list) {
- if (cache->attach == attach) {
- mutex_unlock(&data->lock);
+ if (cache->attach == attach)
return cache;
- }
}
- mutex_unlock(&data->lock);
return NULL;
}
@@ -74,9 +72,13 @@
{
struct dma_buf_cache *cache;
+ mutex_lock(&dmabuf->cache_lock);
+
cache = dma_buf_cache_get_cache(attach);
if (!cache)
dma_buf_detach(dmabuf, attach);
+
+ mutex_unlock(&dmabuf->cache_lock);
}
EXPORT_SYMBOL(dma_buf_cache_detach);
@@ -87,49 +89,58 @@
struct dma_buf_cache_list *data;
struct dma_buf_cache *cache;
+ mutex_lock(&dmabuf->cache_lock);
+
if (!dmabuf->dtor) {
data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- return ERR_PTR(-ENOMEM);
-
- mutex_init(&data->lock);
+ if (!data) {
+ attach = ERR_PTR(-ENOMEM);
+ goto err_data;
+ }
INIT_LIST_HEAD(&data->head);
-
dma_buf_set_destructor(dmabuf, dma_buf_cache_destructor, data);
}
- if (dmabuf->dtor && dmabuf->dtor != dma_buf_cache_destructor)
- return dma_buf_attach(dmabuf, dev);
+ if (dmabuf->dtor && dmabuf->dtor != dma_buf_cache_destructor) {
+ attach = dma_buf_attach(dmabuf, dev);
+ goto attach_done;
+ }
data = dmabuf->dtor_data;
- mutex_lock(&data->lock);
list_for_each_entry(cache, &data->head, list) {
if (cache->attach->dev == dev) {
/* Already attached */
- mutex_unlock(&data->lock);
- return cache->attach;
+ attach = cache->attach;
+ goto attach_done;
}
}
- mutex_unlock(&data->lock);
cache = kzalloc(sizeof(*cache), GFP_KERNEL);
- if (!cache)
- return ERR_PTR(-ENOMEM);
-
+ if (!cache) {
+ attach = ERR_PTR(-ENOMEM);
+ goto err_cache;
+ }
/* Cache attachment */
attach = dma_buf_attach(dmabuf, dev);
- if (IS_ERR_OR_NULL(attach)) {
- kfree(cache);
- return attach;
- }
+ if (IS_ERR_OR_NULL(attach))
+ goto err_attach;
cache->attach = attach;
- mutex_lock(&data->lock);
list_add(&cache->list, &data->head);
- mutex_unlock(&data->lock);
- return cache->attach;
+attach_done:
+ mutex_unlock(&dmabuf->cache_lock);
+ return attach;
+
+err_attach:
+ kfree(cache);
+err_cache:
+ kfree(data);
+ dma_buf_set_destructor(dmabuf, NULL, NULL);
+err_data:
+ mutex_unlock(&dmabuf->cache_lock);
+ return attach;
}
EXPORT_SYMBOL(dma_buf_cache_attach);
@@ -137,38 +148,51 @@
struct sg_table *sg_table,
enum dma_data_direction direction)
{
+ struct dma_buf *dmabuf = attach->dmabuf;
struct dma_buf_cache *cache;
+
+ mutex_lock(&dmabuf->cache_lock);
cache = dma_buf_cache_get_cache(attach);
if (!cache)
dma_buf_unmap_attachment(attach, sg_table, direction);
+
+ mutex_unlock(&dmabuf->cache_lock);
}
EXPORT_SYMBOL(dma_buf_cache_unmap_attachment);
struct sg_table *dma_buf_cache_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
{
+ struct dma_buf *dmabuf = attach->dmabuf;
struct dma_buf_cache *cache;
+ struct sg_table *sg_table;
+
+ mutex_lock(&dmabuf->cache_lock);
cache = dma_buf_cache_get_cache(attach);
- if (!cache)
- return dma_buf_map_attachment(attach, direction);
-
+ if (!cache) {
+ sg_table = dma_buf_map_attachment(attach, direction);
+ goto map_done;
+ }
if (cache->sg_table) {
/* Already mapped */
- if (cache->direction == direction)
- return cache->sg_table;
-
+ if (cache->direction == direction) {
+ sg_table = cache->sg_table;
+ goto map_done;
+ }
/* Different directions */
dma_buf_unmap_attachment(attach, cache->sg_table,
cache->direction);
-
}
/* Cache map */
- cache->sg_table = dma_buf_map_attachment(attach, direction);
+ sg_table = dma_buf_map_attachment(attach, direction);
+ cache->sg_table = sg_table;
cache->direction = direction;
- return cache->sg_table;
+map_done:
+ mutex_unlock(&dmabuf->cache_lock);
+ return sg_table;
}
EXPORT_SYMBOL(dma_buf_cache_map_attachment);
--
Gitblit v1.6.2