diff --git a/htc/htc.c b/htc/htc.c index 6924717008..1159ac91c7 100644 --- a/htc/htc.c +++ b/htc/htc.c @@ -27,6 +27,7 @@ #include "htc_debug.h" #include "htc_internal.h" +#include "htc_credit_history.h" #include #include /* qdf_nbuf_t */ #include /* qdf_print */ @@ -274,10 +275,10 @@ HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo, } htc_runtime_pm_init(target); + htc_credit_history_init(); qdf_spinlock_create(&target->HTCLock); qdf_spinlock_create(&target->HTCRxLock); qdf_spinlock_create(&target->HTCTxLock); - qdf_spinlock_create(&target->HTCCreditLock); for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->endpoint[i]; qdf_spinlock_create(&pEndpoint->lookup_queue_lock); diff --git a/htc/htc_api.h b/htc/htc_api.h index f616e608a3..fdc1708476 100644 --- a/htc/htc_api.h +++ b/htc/htc_api.h @@ -815,9 +815,24 @@ void htc_set_wmi_endpoint_count(HTC_HANDLE htc_handle, uint8_t wmi_ep_count); */ uint8_t htc_get_wmi_endpoint_count(HTC_HANDLE htc_handle); -#ifdef WMI_INTERFACE_EVENT_LOGGING +/** + * htc_print_credit_history: print HTC credit history in buffer + * @htc: HTC handle + * @count: Number of lines to be copied + * @print: Print callback to print in the buffer + * @print_priv: any data required by the print method, e.g. a file handle + * + * return: None + */ +#ifdef FEATURE_HTC_CREDIT_HISTORY void htc_print_credit_history(HTC_HANDLE htc, uint32_t count, qdf_abstract_print * print, void *print_priv); +#else +static inline +void htc_print_credit_history(HTC_HANDLE htc, uint32_t count, + qdf_abstract_print *print, void *print_priv) +{ + print(print_priv, "HTC Credit History Feature is disabled"); +} #endif - #endif /* _HTC_API_H_ */ diff --git a/htc/htc_credit_history.c b/htc/htc_credit_history.c new file mode 100644 index 0000000000..74d5a4d9e1 --- /dev/null +++ b/htc/htc_credit_history.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "htc_debug.h" +#include "htc_internal.h" +#include "htc_credit_history.h" +#include + +struct HTC_CREDIT_HISTORY { + enum htc_credit_exchange_type type; + uint64_t time; + uint32_t tx_credit; + uint32_t htc_tx_queue_depth; +}; + +static qdf_spinlock_t g_htc_credit_lock; +static uint32_t g_htc_credit_history_idx; +static uint32_t g_htc_credit_history_length; +static +struct HTC_CREDIT_HISTORY htc_credit_history_buffer[HTC_CREDIT_HISTORY_MAX]; + + +#ifdef QCA_WIFI_NAPIER_EMULATION +#define HTC_EMULATION_DELAY_IN_MS 20 +/** + * htc_add_delay(): Adds a delay in before proceeding, only for emulation + * + * Return: None + */ +static inline void htc_add_emulation_delay(void) +{ + qdf_mdelay(HTC_EMULATION_DELAY_IN_MS); +} +#else +static inline void htc_add_emulation_delay(void) +{ +} +#endif + +void htc_credit_history_init(void) +{ + qdf_spinlock_create(&g_htc_credit_lock); + g_htc_credit_history_idx = 0; + g_htc_credit_history_length = 0; +} + +/** + * htc_credit_record() - records tx que state & credit transactions + * @type: type of echange can be HTC_REQUEST_CREDIT + * or HTC_PROCESS_CREDIT_REPORT + * @tx_credits: current number of tx_credits + * @htc_tx_queue_depth: current hct tx queue depth + * + * This function records the credits and pending commands whenever a command is + * sent or credits are returned. Call this after the credits have been updated + * according to the transaction. Call this before dequeing commands. + * + * Consider making this function accept an HTC_ENDPOINT and find the current + * credits and queue depth itself. + * + */ +void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit, + uint32_t htc_tx_queue_depth) +{ + qdf_spin_lock_bh(&g_htc_credit_lock); + if (g_htc_credit_history_idx >= HTC_CREDIT_HISTORY_MAX) + g_htc_credit_history_idx = 0; + + htc_credit_history_buffer[g_htc_credit_history_idx].type = type; + htc_credit_history_buffer[g_htc_credit_history_idx].time = + qdf_get_log_timestamp(); + htc_credit_history_buffer[g_htc_credit_history_idx].tx_credit = + tx_credit; + htc_credit_history_buffer[g_htc_credit_history_idx].htc_tx_queue_depth = + htc_tx_queue_depth; + + g_htc_credit_history_idx++; + g_htc_credit_history_length++; + htc_add_emulation_delay(); + qdf_spin_unlock_bh(&g_htc_credit_lock); +} + +void htc_print_credit_history(HTC_HANDLE htc, uint32_t count, + qdf_abstract_print *print, void *print_priv) +{ + uint32_t idx; + + print(print_priv, "HTC Credit History (count %u)", count); + qdf_spin_lock_bh(&g_htc_credit_lock); + + if (count > HTC_CREDIT_HISTORY_MAX) + count = HTC_CREDIT_HISTORY_MAX; + if (count > g_htc_credit_history_length) + count = g_htc_credit_history_length; + + /* subtract count from index, and wrap if necessary */ + idx = HTC_CREDIT_HISTORY_MAX + g_htc_credit_history_idx - count; + idx %= HTC_CREDIT_HISTORY_MAX; + + print(print_priv, + "Time (seconds) Type Credits Queue Depth"); + while (count) { + struct HTC_CREDIT_HISTORY *hist = + &htc_credit_history_buffer[idx]; + uint64_t secs, usecs; + + qdf_log_timestamp_to_secs(hist->time, &secs, &usecs); + print(print_priv, "% 8lld.%06lld %-25s %-7.d %d", + secs, + usecs, + htc_credit_exchange_type_str(hist->type), + hist->tx_credit, + hist->htc_tx_queue_depth); + + --count; + ++idx; + if (idx >= HTC_CREDIT_HISTORY_MAX) + idx = 0; + } + + qdf_spin_unlock_bh(&g_htc_credit_lock); +} diff --git a/htc/htc_credit_history.h b/htc/htc_credit_history.h new file mode 100644 index 0000000000..0cbd1d8cef --- /dev/null +++ b/htc/htc_credit_history.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _HTC_CREDIT_HISTORY_H_ +#define _HTC_CREDIT_HISTORY_H_ + +#include "htc_internal.h" + +#ifdef FEATURE_HTC_CREDIT_HISTORY + +/** + * htc_credit_history_init(): Init helper function to initialize HTC credit + * history buffers and variable. + * Return: None + */ + +void htc_credit_history_init(void); +void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit, + uint32_t htc_tx_queue_depth); + +#else /* FEATURE_HTC_CREDIT_HISTORY */ + +static inline +void htc_credit_history_init(void) +{ +} + +static inline +void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit, + uint32_t htc_tx_queue_depth) +{ } +#endif /* FEATURE_HTC_CREDIT_HISTORY */ +#endif /* _HTC_CREDIT_HISTORY_H_ */ diff --git a/htc/htc_internal.h b/htc/htc_internal.h index cf56da56ae..ffcb7bb79a 100644 --- a/htc/htc_internal.h +++ b/htc/htc_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -118,13 +118,6 @@ htc_credit_exchange_type_str(enum htc_credit_exchange_type type) } } -struct HTC_CREDIT_HISTORY { - enum htc_credit_exchange_type type; - uint64_t time; - uint32_t tx_credit; - uint32_t htc_tx_queue_depth; -}; - typedef struct _HTC_ENDPOINT { HTC_ENDPOINT_ID Id; @@ -275,8 +268,6 @@ do { \ #define UNLOCK_HTC_RX(t) qdf_spin_unlock_bh(&(t)->HTCRxLock) #define LOCK_HTC_TX(t) qdf_spin_lock_bh(&(t)->HTCTxLock) #define UNLOCK_HTC_TX(t) qdf_spin_unlock_bh(&(t)->HTCTxLock) -#define LOCK_HTC_CREDIT(t) qdf_spin_lock_bh(&(t)->HTCCreditLock) -#define UNLOCK_HTC_CREDIT(t) qdf_spin_unlock_bh(&(t)->HTCCreditLock) #define LOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_lock_bh(&(t)->lookup_queue_lock) #define UNLOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_unlock_bh(&(t)->lookup_queue_lock) @@ -328,9 +319,6 @@ void htc_send_complete_check_cleanup(void *context); void htc_kick_queues(void *context); #endif -void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit, - uint32_t htc_tx_queue_depth); - static inline void htc_send_complete_poll_timer_stop(HTC_ENDPOINT * pEndpoint) { LOCK_HTC_TX(pEndpoint->target); diff --git a/htc/htc_recv.c b/htc/htc_recv.c index 1c5c357a52..e177ca32dd 100644 --- a/htc/htc_recv.c +++ b/htc/htc_recv.c @@ -27,6 +27,7 @@ #include "htc_debug.h" #include "htc_internal.h" +#include "htc_credit_history.h" #include /* qdf_nbuf_t */ /* HTC Control message receive timeout msec */ @@ -428,12 +429,10 @@ QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf, case HTC_MSG_WAKEUP_FROM_SUSPEND_ID: AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Received initial wake up")); - LOCK_HTC_CREDIT(target); htc_credit_record(HTC_INITIAL_WAKE_UP, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH( - &pEndpoint->TxQueue)); - UNLOCK_HTC_CREDIT(target); + &pEndpoint->TxQueue)); info = &target->HTCInitInfo; if (info && info->target_initial_wakeup_cb) info->target_initial_wakeup_cb( @@ -445,12 +444,10 @@ QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf, #endif case HTC_MSG_SEND_SUSPEND_COMPLETE: wow_nack = false; - LOCK_HTC_CREDIT(target); htc_credit_record(HTC_SUSPEND_ACK, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH( - &pEndpoint->TxQueue)); - UNLOCK_HTC_CREDIT(target); + &pEndpoint->TxQueue)); target->HTCInitInfo.TargetSendSuspendComplete( target->HTCInitInfo.target_psoc, wow_nack); @@ -458,13 +455,10 @@ QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf, break; case HTC_MSG_NACK_SUSPEND: wow_nack = true; - LOCK_HTC_CREDIT(target); htc_credit_record(HTC_SUSPEND_ACK, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH( - &pEndpoint->TxQueue)); - UNLOCK_HTC_CREDIT(target); - + &pEndpoint->TxQueue)); target->HTCInitInfo.TargetSendSuspendComplete( target->HTCInitInfo.target_psoc, wow_nack); diff --git a/htc/htc_send.c b/htc/htc_send.c index 257d8d8a9c..376454a188 100644 --- a/htc/htc_send.c +++ b/htc/htc_send.c @@ -27,6 +27,7 @@ #include "htc_debug.h" #include "htc_internal.h" +#include "htc_credit_history.h" #include /* qdf_mem_malloc */ #include /* qdf_nbuf_t */ #include "qdf_module.h" @@ -53,11 +54,6 @@ static unsigned int ep_debug_mask = (1 << ENDPOINT_0) | (1 << ENDPOINT_1) | (1 << ENDPOINT_2); #endif -/* HTC Control Path Credit History */ -uint32_t g_htc_credit_history_idx; -uint32_t g_htc_credit_history_length; -struct HTC_CREDIT_HISTORY htc_credit_history_buffer[HTC_CREDIT_HISTORY_MAX]; - #ifdef QCA_WIFI_NAPIER_EMULATION #define HTC_EMULATION_DELAY_IN_MS 20 /** @@ -75,84 +71,6 @@ static inline void htc_add_emulation_delay(void) } #endif -/** - * htc_credit_record() - records tx que state & credit transactions - * @type: type of echange can be HTC_REQUEST_CREDIT - * or HTC_PROCESS_CREDIT_REPORT - * @tx_credits: current number of tx_credits - * @htc_tx_queue_depth: current hct tx queue depth - * - * This function records the credits and pending commands whenever a command is - * sent or credits are returned. Call this after the credits have been updated - * according to the transaction. Call this before dequeing commands. - * - * Consider making this function accept an HTC_ENDPOINT and find the current - * credits and queue depth itself. - * - * Consider moving the LOCK_HTC_CREDIT(target); logic into this func as well - */ -void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit, - uint32_t htc_tx_queue_depth) { - if (HTC_CREDIT_HISTORY_MAX <= g_htc_credit_history_idx) - g_htc_credit_history_idx = 0; - - htc_credit_history_buffer[g_htc_credit_history_idx].type = type; - htc_credit_history_buffer[g_htc_credit_history_idx].time = - qdf_get_log_timestamp(); - htc_credit_history_buffer[g_htc_credit_history_idx].tx_credit = - tx_credit; - htc_credit_history_buffer[g_htc_credit_history_idx].htc_tx_queue_depth = - htc_tx_queue_depth; - - g_htc_credit_history_idx++; - g_htc_credit_history_length++; - htc_add_emulation_delay(); -} - -#ifdef WMI_INTERFACE_EVENT_LOGGING -void htc_print_credit_history(HTC_HANDLE htc, uint32_t count, - qdf_abstract_print *print, void *print_priv) -{ - uint32_t idx; - HTC_TARGET *target; - - target = GET_HTC_TARGET_FROM_HANDLE(htc); - LOCK_HTC_CREDIT(target); - - if (count > HTC_CREDIT_HISTORY_MAX) - count = HTC_CREDIT_HISTORY_MAX; - if (count > g_htc_credit_history_length) - count = g_htc_credit_history_length; - - /* subtract count from index, and wrap if necessary */ - idx = HTC_CREDIT_HISTORY_MAX + g_htc_credit_history_idx - count; - idx %= HTC_CREDIT_HISTORY_MAX; - - print(print_priv, - "Time (seconds) Type Credits Queue Depth"); - while (count) { - struct HTC_CREDIT_HISTORY *hist = - &htc_credit_history_buffer[idx]; - uint64_t secs, usecs; - - qdf_log_timestamp_to_secs(hist->time, &secs, &usecs); - print(print_priv, "% 8lld.%06lld %-25s %-7.d %d", - secs, - usecs, - htc_credit_exchange_type_str(hist->type), - hist->tx_credit, - hist->htc_tx_queue_depth); - - --count; - ++idx; - if (idx >= HTC_CREDIT_HISTORY_MAX) - idx = 0; - } - - UNLOCK_HTC_CREDIT(target); -} -#endif /* WMI_INTERFACE_EVENT_LOGGING */ - void htc_dump_counter_info(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); @@ -909,16 +827,12 @@ static void get_htc_send_packets_credit_based(HTC_TARGET *target, pEndpoint->TxCreditsPerMaxMsg) { /* tell the target we need credits ASAP! */ sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; - if (pEndpoint->service_id == WMI_CONTROL_SVC) { - LOCK_HTC_CREDIT(target); htc_credit_record(HTC_REQUEST_CREDIT, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH - (tx_queue)); - UNLOCK_HTC_CREDIT(target); + (tx_queue)); } - INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1); #if DEBUG_CREDIT @@ -2241,16 +2155,12 @@ void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, #endif pEndpoint->TxCredits += rpt_credits; - if (pEndpoint->service_id == WMI_CONTROL_SVC) { - LOCK_HTC_CREDIT(target); htc_credit_record(HTC_PROCESS_CREDIT_REPORT, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint-> - TxQueue)); - UNLOCK_HTC_CREDIT(target); + TxQueue)); } - if (pEndpoint->TxCredits && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) { UNLOCK_HTC_TX(target);