xref: /wlan-dirver/qca-wifi-host-cmn/htc/htc_credit_history.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
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