| /* |
| * Samsung Exynos SoC series NPU driver |
| * |
| * Copyright (c) 2017 Samsung Electronics Co., Ltd. |
| * http://www.samsung.com/ |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| */ |
| |
| #include <linux/atomic.h> |
| #include "npu-util-msgidgen.h" |
| #include "npu-log.h" |
| |
| void msgid_pool_init(struct msgid_pool *handle) |
| { |
| int i; |
| BUG_ON(!handle); |
| |
| for (i = 0; i < NPU_MAX_MSG_ID_CNT; i++) |
| atomic_set(&handle->pool[i].occupied, 0); |
| |
| handle->magic = MSGID_POOL_MAGIC; |
| } |
| |
| /* Returns an unoccupied message ID from pool. |
| * returns -1 if there is not message ID available |
| */ |
| int msgid_issue(struct msgid_pool *handle) |
| { |
| int i; |
| BUG_ON(!handle); |
| BUG_ON(handle->magic != MSGID_POOL_MAGIC); |
| |
| for (i = 0; i < NPU_MAX_MSG_ID_CNT; i++) { |
| if (atomic_cmpxchg(&handle->pool[i].occupied, 0, 1) == 0) { |
| /* Find unused */ |
| #ifdef NPU_MAILBOX_MSG_ID_TIME_KEEPING |
| do_gettimeofdat(&handle->pool[i].tv_issued); |
| #endif |
| npu_dbg("issue(%d)\n", i); |
| return i; |
| } |
| } |
| /* No available MSG ID */ |
| npu_warn("no message ID available\n"); |
| return -1; |
| } |
| |
| int msgid_issue_save_ref(struct msgid_pool *handle, const int pt_type, void *ref) |
| { |
| int id = msgid_issue(handle); |
| npu_dbg("issue_ref(%d)\n", id); |
| if (id >= 0) { |
| handle->pool[id].ref = ref; |
| handle->pool[id].pt_type = pt_type; |
| } |
| return id; |
| } |
| |
| static inline int __msgid_claim(struct msgid_pool *handle, const int msg_id) |
| { |
| int occupied; |
| occupied = atomic_xchg(&handle->pool[msg_id].occupied, 0); |
| if (!occupied) { |
| npu_warn("claim for msg_id(%d), not occupied", msg_id); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| static inline void __validate_handle_msgid(struct msgid_pool *handle, const int msg_id) |
| { |
| BUG_ON(!handle); |
| BUG_ON(handle->magic != MSGID_POOL_MAGIC); |
| |
| BUG_ON(msg_id < 0); |
| BUG_ON(msg_id >= NPU_MAX_MSG_ID_CNT); |
| } |
| |
| /* Claim the issued request id and set to unoccupied status */ |
| void msgid_claim(struct msgid_pool *handle, const int msg_id) |
| { |
| __validate_handle_msgid(handle, msg_id); |
| npu_dbg("claim(%d)\n", msg_id); |
| __msgid_claim(handle, msg_id); |
| } |
| |
| /* Claim the issued request id and set to unoccupied status, and return its associated reference */ |
| void *msgid_claim_get_ref(struct msgid_pool *handle, const int msg_id, const int expected_type) |
| { |
| void *ref; |
| __validate_handle_msgid(handle, msg_id); |
| npu_dbg("claim_ref(%d)\n", msg_id); |
| BUG_ON(expected_type != handle->pool[msg_id].pt_type); |
| |
| ref = handle->pool[msg_id].ref; |
| if (__msgid_claim(handle, msg_id)) { |
| return NULL; |
| } |
| |
| return ref; |
| } |
| |
| int msgid_get_pt_type(struct msgid_pool *handle, const int msg_id) |
| { |
| BUG_ON(!handle); |
| __validate_handle_msgid(handle, msg_id); |
| |
| if (!atomic_read(&handle->pool[msg_id].occupied)) { |
| npu_warn("request pt_type for unoccupied msg_id(%d)", msg_id); |
| return -1; |
| } |
| return handle->pool[msg_id].pt_type; |
| } |