diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/staging/media/atomisp/pci/base/refcount/src | |
parent | Initial commit. (diff) | |
download | linux-upstream.tar.xz linux-upstream.zip |
Adding upstream version 6.1.76.upstream/6.1.76upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/staging/media/atomisp/pci/base/refcount/src')
-rw-r--r-- | drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c b/drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c new file mode 100644 index 000000000..a9c881631 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "hmm.h" + +#include "ia_css_refcount.h" +#include "sh_css_defs.h" + +#include "platform_support.h" + +#include "assert_support.h" + +#include "ia_css_debug.h" + +/* TODO: enable for other memory aswell + now only for ia_css_ptr */ +struct ia_css_refcount_entry { + u32 count; + ia_css_ptr data; + s32 id; +}; + +struct ia_css_refcount_list { + u32 size; + struct ia_css_refcount_entry *items; +}; + +static struct ia_css_refcount_list myrefcount; + +static struct ia_css_refcount_entry *refcount_find_entry(ia_css_ptr ptr, + bool firstfree) +{ + u32 i; + + if (ptr == 0) + return NULL; + if (!myrefcount.items) { + ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, + "%s(): Ref count not initialized!\n", __func__); + return NULL; + } + + for (i = 0; i < myrefcount.size; i++) { + if ((&myrefcount.items[i])->data == 0) { + if (firstfree) { + /* for new entry */ + return &myrefcount.items[i]; + } + } + if ((&myrefcount.items[i])->data == ptr) { + /* found entry */ + return &myrefcount.items[i]; + } + } + return NULL; +} + +int ia_css_refcount_init(uint32_t size) +{ + int err = 0; + + if (size == 0) { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s(): Size of 0 for Ref count init!\n", __func__); + return -EINVAL; + } + if (myrefcount.items) { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s(): Ref count is already initialized\n", __func__); + return -EINVAL; + } + myrefcount.items = + kvmalloc(sizeof(struct ia_css_refcount_entry) * size, GFP_KERNEL); + if (!myrefcount.items) + err = -ENOMEM; + if (!err) { + memset(myrefcount.items, 0, + sizeof(struct ia_css_refcount_entry) * size); + myrefcount.size = size; + } + return err; +} + +void ia_css_refcount_uninit(void) +{ + struct ia_css_refcount_entry *entry; + u32 i; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s() entry\n", __func__); + for (i = 0; i < myrefcount.size; i++) { + /* driver verifier tool has issues with &arr[i] + and prefers arr + i; as these are actually equivalent + the line below uses + i + */ + entry = myrefcount.items + i; + if (entry->data != mmgr_NULL) { + /* ia_css_debug_dtrace(IA_CSS_DBG_TRACE, + "ia_css_refcount_uninit: freeing (%x)\n", + entry->data);*/ + hmm_free(entry->data); + entry->data = mmgr_NULL; + entry->count = 0; + entry->id = 0; + } + } + kvfree(myrefcount.items); + myrefcount.items = NULL; + myrefcount.size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s() leave\n", __func__); +} + +ia_css_ptr ia_css_refcount_increment(s32 id, ia_css_ptr ptr) +{ + struct ia_css_refcount_entry *entry; + + if (ptr == mmgr_NULL) + return ptr; + + entry = refcount_find_entry(ptr, false); + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s(%x) 0x%x\n", __func__, id, ptr); + + if (!entry) { + entry = refcount_find_entry(ptr, true); + assert(entry); + if (!entry) + return mmgr_NULL; + entry->id = id; + } + + if (entry->id != id) { + ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, + "%s(): Ref count IDS do not match!\n", __func__); + return mmgr_NULL; + } + + if (entry->data == ptr) + entry->count += 1; + else if (entry->data == mmgr_NULL) { + entry->data = ptr; + entry->count = 1; + } else + return mmgr_NULL; + + return ptr; +} + +bool ia_css_refcount_decrement(s32 id, ia_css_ptr ptr) +{ + struct ia_css_refcount_entry *entry; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s(%x) 0x%x\n", __func__, id, ptr); + + if (ptr == mmgr_NULL) + return false; + + entry = refcount_find_entry(ptr, false); + + if (entry) { + if (entry->id != id) { + ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, + "%s(): Ref count IDS do not match!\n", __func__); + return false; + } + if (entry->count > 0) { + entry->count -= 1; + if (entry->count == 0) { + /* ia_css_debug_dtrace(IA_CSS_DBEUG_TRACE, + "ia_css_refcount_decrement: freeing\n");*/ + hmm_free(ptr); + entry->data = mmgr_NULL; + entry->id = 0; + } + return true; + } + } + + /* SHOULD NOT HAPPEN: ptr not managed by refcount, or not + valid anymore */ + if (entry) + IA_CSS_ERROR("id %x, ptr 0x%x entry %p entry->id %x entry->count %d\n", + id, ptr, entry, entry->id, entry->count); + else + IA_CSS_ERROR("entry NULL\n"); + assert(false); + + return false; +} + +bool ia_css_refcount_is_single(ia_css_ptr ptr) +{ + struct ia_css_refcount_entry *entry; + + if (ptr == mmgr_NULL) + return false; + + entry = refcount_find_entry(ptr, false); + + if (entry) + return (entry->count == 1); + + return true; +} + +void ia_css_refcount_clear(s32 id, clear_func clear_func_ptr) +{ + struct ia_css_refcount_entry *entry; + u32 i; + u32 count = 0; + + assert(clear_func_ptr); + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s(%x)\n", + __func__, id); + + for (i = 0; i < myrefcount.size; i++) { + /* driver verifier tool has issues with &arr[i] + and prefers arr + i; as these are actually equivalent + the line below uses + i + */ + entry = myrefcount.items + i; + if ((entry->data != mmgr_NULL) && (entry->id == id)) { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s: %x: 0x%x\n", __func__, + id, entry->data); + if (clear_func_ptr) { + /* clear using provided function */ + clear_func_ptr(entry->data); + } else { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s: using hmm_free: no clear_func\n", __func__); + hmm_free(entry->data); + } + + if (entry->count != 0) { + IA_CSS_WARNING("Ref count for entry %x is not zero!", entry->id); + } + + assert(entry->count == 0); + + entry->data = mmgr_NULL; + entry->count = 0; + entry->id = 0; + count++; + } + } + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "%s(%x): cleared %d\n", __func__, id, + count); +} + +bool ia_css_refcount_is_valid(ia_css_ptr ptr) +{ + struct ia_css_refcount_entry *entry; + + if (ptr == mmgr_NULL) + return false; + + entry = refcount_find_entry(ptr, false); + + return entry; +} |