blob: 74d5a4d9e13b73e2f7bfd2bd1e164c43b46d33a9 [file] [log] [blame]
Rachit Kankane1bc11492018-01-24 18:48:17 +05301/*
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
33struct 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
40static qdf_spinlock_t g_htc_credit_lock;
41static uint32_t g_htc_credit_history_idx;
42static uint32_t g_htc_credit_history_length;
43static
44struct 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 */
54static inline void htc_add_emulation_delay(void)
55{
56 qdf_mdelay(HTC_EMULATION_DELAY_IN_MS);
57}
58#else
59static inline void htc_add_emulation_delay(void)
60{
61}
62#endif
63
64void 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 */
86void 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
107void 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}