1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2021-2023, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <bitstring.h> 8 #include <kernel/interrupt.h> 9 #include <kernel/notif.h> 10 #include <kernel/spinlock.h> 11 #include <trace.h> 12 #include <types_ext.h> 13 14 static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1); 15 static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1); 16 static unsigned int notif_default_lock = SPINLOCK_UNLOCK; 17 18 TEE_Result notif_alloc_async_value(uint32_t *val) 19 { 20 static bool alloc_values_inited; 21 uint32_t old_itr_status = 0; 22 int bit = 0; 23 24 assert(interrupt_can_raise_pi(interrupt_get_main_chip())); 25 26 old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 27 28 if (!alloc_values_inited) { 29 bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF); 30 alloc_values_inited = true; 31 } 32 33 bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); 34 if (bit >= 0) { 35 *val = bit; 36 bit_set(notif_alloc_values, bit); 37 } 38 39 cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 40 41 if (bit < 0) 42 return TEE_ERROR_OUT_OF_MEMORY; 43 44 return TEE_SUCCESS; 45 } 46 47 void notif_free_async_value(uint32_t val) 48 { 49 uint32_t old_itr_status = 0; 50 51 old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 52 53 assert(val < NOTIF_ASYNC_VALUE_MAX); 54 assert(bit_test(notif_alloc_values, val)); 55 bit_clear(notif_alloc_values, val); 56 57 cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 58 } 59 60 uint32_t notif_get_value(bool *value_valid, bool *value_pending) 61 { 62 uint32_t old_itr_status = 0; 63 uint32_t res = 0; 64 int bit = 0; 65 66 old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 67 68 bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); 69 *value_valid = (bit >= 0); 70 if (!*value_valid) { 71 *value_pending = false; 72 goto out; 73 } 74 75 res = bit; 76 bit_clear(notif_values, res); 77 bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); 78 *value_pending = (bit >= 0); 79 out: 80 cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 81 82 return res; 83 } 84 85 void notif_send_async(uint32_t value) 86 { 87 uint32_t old_itr_status = 0; 88 struct itr_chip *itr_chip = interrupt_get_main_chip(); 89 90 assert(value <= NOTIF_ASYNC_VALUE_MAX); 91 old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 92 93 DMSG("0x%"PRIx32, value); 94 bit_set(notif_values, value); 95 interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID); 96 97 cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 98 } 99