1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * 4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc. 5 * 6 * 7 * Permission to use, copy, modify, and/or distribute this software for 8 * any purpose with or without fee is hereby granted, provided that the 9 * above copyright notice and this permission notice appear in all 10 * copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 * PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * This file was originally distributed by Qualcomm Atheros, Inc. 24 * under proprietary terms before Copyright ownership was assigned 25 * to the Linux Foundation. 26 */ 27 28 #include "htc_debug.h" 29 #include "htc_internal.h" 30 #include "htc_credit_history.h" 31 #include <qdf_lock.h> 32 33 struct HTC_CREDIT_HISTORY { 34 enum htc_credit_exchange_type type; 35 uint64_t time; 36 uint32_t tx_credit; 37 uint32_t htc_tx_queue_depth; 38 }; 39 40 static qdf_spinlock_t g_htc_credit_lock; 41 static uint32_t g_htc_credit_history_idx; 42 static uint32_t g_htc_credit_history_length; 43 static 44 struct HTC_CREDIT_HISTORY htc_credit_history_buffer[HTC_CREDIT_HISTORY_MAX]; 45 46 47 #ifdef QCA_WIFI_NAPIER_EMULATION 48 #define HTC_EMULATION_DELAY_IN_MS 20 49 /** 50 * htc_add_delay(): Adds a delay in before proceeding, only for emulation 51 * 52 * Return: None 53 */ 54 static inline void htc_add_emulation_delay(void) 55 { 56 qdf_mdelay(HTC_EMULATION_DELAY_IN_MS); 57 } 58 #else 59 static inline void htc_add_emulation_delay(void) 60 { 61 } 62 #endif 63 64 void htc_credit_history_init(void) 65 { 66 qdf_spinlock_create(&g_htc_credit_lock); 67 g_htc_credit_history_idx = 0; 68 g_htc_credit_history_length = 0; 69 } 70 71 /** 72 * htc_credit_record() - records tx que state & credit transactions 73 * @type: type of echange can be HTC_REQUEST_CREDIT 74 * or HTC_PROCESS_CREDIT_REPORT 75 * @tx_credits: current number of tx_credits 76 * @htc_tx_queue_depth: current hct tx queue depth 77 * 78 * This function records the credits and pending commands whenever a command is 79 * sent or credits are returned. Call this after the credits have been updated 80 * according to the transaction. Call this before dequeing commands. 81 * 82 * Consider making this function accept an HTC_ENDPOINT and find the current 83 * credits and queue depth itself. 84 * 85 */ 86 void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit, 87 uint32_t htc_tx_queue_depth) 88 { 89 qdf_spin_lock_bh(&g_htc_credit_lock); 90 if (g_htc_credit_history_idx >= HTC_CREDIT_HISTORY_MAX) 91 g_htc_credit_history_idx = 0; 92 93 htc_credit_history_buffer[g_htc_credit_history_idx].type = type; 94 htc_credit_history_buffer[g_htc_credit_history_idx].time = 95 qdf_get_log_timestamp(); 96 htc_credit_history_buffer[g_htc_credit_history_idx].tx_credit = 97 tx_credit; 98 htc_credit_history_buffer[g_htc_credit_history_idx].htc_tx_queue_depth = 99 htc_tx_queue_depth; 100 101 g_htc_credit_history_idx++; 102 g_htc_credit_history_length++; 103 htc_add_emulation_delay(); 104 qdf_spin_unlock_bh(&g_htc_credit_lock); 105 } 106 107 void htc_print_credit_history(HTC_HANDLE htc, uint32_t count, 108 qdf_abstract_print *print, void *print_priv) 109 { 110 uint32_t idx; 111 112 print(print_priv, "HTC Credit History (count %u)", count); 113 qdf_spin_lock_bh(&g_htc_credit_lock); 114 115 if (count > HTC_CREDIT_HISTORY_MAX) 116 count = HTC_CREDIT_HISTORY_MAX; 117 if (count > g_htc_credit_history_length) 118 count = g_htc_credit_history_length; 119 120 /* subtract count from index, and wrap if necessary */ 121 idx = HTC_CREDIT_HISTORY_MAX + g_htc_credit_history_idx - count; 122 idx %= HTC_CREDIT_HISTORY_MAX; 123 124 print(print_priv, 125 "Time (seconds) Type Credits Queue Depth"); 126 while (count) { 127 struct HTC_CREDIT_HISTORY *hist = 128 &htc_credit_history_buffer[idx]; 129 uint64_t secs, usecs; 130 131 qdf_log_timestamp_to_secs(hist->time, &secs, &usecs); 132 print(print_priv, "% 8lld.%06lld %-25s %-7.d %d", 133 secs, 134 usecs, 135 htc_credit_exchange_type_str(hist->type), 136 hist->tx_credit, 137 hist->htc_tx_queue_depth); 138 139 --count; 140 ++idx; 141 if (idx >= HTC_CREDIT_HISTORY_MAX) 142 idx = 0; 143 } 144 145 qdf_spin_unlock_bh(&g_htc_credit_lock); 146 } 147