diff options
| -rw-r--r-- | CORE/CLD_TXRX/HTT/htt.h | 38 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_tx.c | 253 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_tx.h | 51 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_tx_desc.c | 31 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_tx_send.c | 119 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_txrx.c | 7 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_txrx_types.h | 1 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_debugfs_ocb.c | 32 | ||||
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.c | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/adf_os_time.h | 12 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h | 8 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 1 | ||||
| -rw-r--r-- | CORE/VOSS/inc/vos_api.h | 12 |
13 files changed, 459 insertions, 109 deletions
diff --git a/CORE/CLD_TXRX/HTT/htt.h b/CORE/CLD_TXRX/HTT/htt.h index 454603e09c50..03b75ffd129b 100644 --- a/CORE/CLD_TXRX/HTT/htt.h +++ b/CORE/CLD_TXRX/HTT/htt.h @@ -6237,17 +6237,19 @@ PREPACK struct htt_txq_group { * The following diagram shows the format of the TX completion indication sent * from the target to the host * - * |31 26| 25 | 24 |23 16| 15 |14 11|10 8|7 0| + * |31 27|26|25|24|23 16| 15 |14 11|10 8|7 0| * |-------------------------------------------------------------| - * header: | reserved |append1|append|num | t_i| tid |status| msg_type | + * header: | reserved |a2|a1|a0| num | t_i| tid |status | msg_type | * |-------------------------------------------------------------| * payload: | MSDU1 ID | MSDU0 ID | * |-------------------------------------------------------------| * : MSDU3 ID : MSDU2 ID : * |-------------------------------------------------------------| * | struct htt_tx_compl_ind_append_retries | - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * | struct htt_tx_compl_ind_append_txtstamp | + * |-------------------------------------------------------------| + * | struct htt_tx_compl_ind_append_txtstamp | + * |-------------------------------------------------------------| + * | struct htt_tx_compl_ind_append_txpower | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * The following field definitions describe the format of the TX completion @@ -6274,15 +6276,21 @@ PREPACK struct htt_txq_group { * Bits 23:16 * Purpose: the number of payload in this indication * Value: 1 to 255 - * - append + * - a0 - append0 * Bits 24:24 * Purpose: append the struct htt_tx_compl_ind_append_retries which contains - * the number of tx retries for one MSDU at the end of this message + * the number of tx retries for one MSDU after MSDU ID. * Value: 0 indicates no appending; 1 indicates appending - * - append1 + * - a1 - append1 * Bits 25:25 * Purpose: append the struct htt_tx_compl_ind_append_txtstamp which contains - * the timestamp info for each TX msdu id in payload + * the timestamp info for each TX msdu id in payload after append0. + * Value: 0 indicates no appending; 1 indicates appending + * - a2 - append2 + * Bits 26:26 + * Purpose: append the struct htt_tx_compl_ind_append_txpower which contains + * one or more tx power of each MSDUs after append1. + * The start of tx power(s) must be 4-bytes-word aligned. * Value: 0 indicates no appending; 1 indicates appending * Payload fields: * - hmsdu_id @@ -6303,6 +6311,8 @@ PREPACK struct htt_txq_group { #define HTT_TX_COMPL_IND_APPEND_M 0x01000000 #define HTT_TX_COMPL_IND_APPEND1_S 25 #define HTT_TX_COMPL_IND_APPEND1_M 0x02000000 +#define HTT_TX_COMPL_IND_APPEND2_S 26 +#define HTT_TX_COMPL_IND_APPEND2_M 0x04000000 #define HTT_TX_COMPL_IND_STATUS_SET(_info, _val) \ do { \ @@ -6347,7 +6357,13 @@ PREPACK struct htt_txq_group { } while (0) #define HTT_TX_COMPL_IND_APPEND1_GET(_info) \ (((_info) & HTT_TX_COMPL_IND_APPEND1_M) >> HTT_TX_COMPL_IND_APPEND1_S) - +#define HTT_TX_COMPL_IND_APPEND2_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_COMPL_IND_APPEND2, _val); \ + ((_info) |= ((_val) << HTT_TX_COMPL_IND_APPEND2_S)); \ + } while (0) +#define HTT_TX_COMPL_IND_APPEND2_GET(_info) \ + (((_info) & HTT_TX_COMPL_IND_APPEND2_M) >> HTT_TX_COMPL_IND_APPEND2_S) #define HTT_TX_COMPL_CTXT_SZ sizeof(A_UINT16) #define HTT_TX_COMPL_CTXT_NUM(_bytes) ((_bytes) >> 1) @@ -6390,6 +6406,10 @@ PREPACK struct htt_tx_compl_ind_append_txtstamp { A_UINT32 timestamp[1/*or more*/]; } POSTPACK; +PREPACK struct htt_tx_compl_ind_append_txpower { + A_UINT16 tx_power[1/*or more*/]; +} POSTPACK; + /** * @brief target -> host rate-control update indication message * diff --git a/CORE/CLD_TXRX/TXRX/ol_tx.c b/CORE/CLD_TXRX/TXRX/ol_tx.c index 00e2e06769e6..0521c0a4510a 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx.c +++ b/CORE/CLD_TXRX/TXRX/ol_tx.c @@ -56,25 +56,52 @@ #ifdef WLAN_FEATURE_DSRC #include "ol_tx.h" #include "adf_os_lock.h" +#include "adf_os_util.h" +#include "queue.h" -struct ol_tx_stats_ring_head { - adf_os_spinlock_t mutex; - uint8_t head; - uint8_t tail; -}; - +/** + * struct ol_tx_stats_ring_item - the item of a packet tx stats in the ring + * @list: list for all tx stats item in the ring + * @stats: a packet tx stats including fields from host and FW respectively + * @msdu_id: msdu ID used to match stats fields respectively from host and FW + * into a complete tx stats item + * @reserved: reserved to align to 4 bytes + */ struct ol_tx_stats_ring_item { + TAILQ_ENTRY(ol_tx_stats_ring_item) list; struct ol_tx_per_pkt_stats stats; uint16_t msdu_id; uint8_t reserved[2]; }; +/** + * struct ol_tx_stats_ring_head - the ring head of all tx stats + * @mutex: mutex to access it exclusively + * @free_list: list of free tx stats ring items + * @host_list: list of tx stats items only containing tx stats fields from host + * @comp_list: list of tx stats items containing complete tx stats fields + * from host and FW, items in this list can be dequeued to user + * @num_free: number of free tx stats items + * @num_host_stat: number of tx stats items only containing tx stats fields + * from host + * @num_comp_stat: number of tx stats items containing complete tx stats fields + */ +struct ol_tx_stats_ring_head { + adf_os_spinlock_t mutex; + TAILQ_HEAD(free_list, ol_tx_stats_ring_item) free_list; + TAILQ_HEAD(host_list, ol_tx_stats_ring_item) host_list; + TAILQ_HEAD(comp_list, ol_tx_stats_ring_item) comp_list; + uint8_t num_free; + uint8_t num_host_stat; + uint8_t num_comp_stat; +}; + #define TX_STATS_RING_SZ 32 #define INVALID_TX_MSDU_ID (-1) static struct ol_tx_stats_ring_head *tx_stats_ring_head; static struct ol_tx_stats_ring_item *tx_stats_ring; -static int ol_per_pkt_tx_stats_enabled = 0; +static bool __ol_per_pkt_tx_stats_enabled = false; static int ol_tx_stats_ring_init(void) { @@ -96,8 +123,17 @@ static int ol_tx_stats_ring_init(void) vos_mem_zero(head, sizeof(*head)); vos_mem_zero(ring, sizeof(*ring) * TX_STATS_RING_SZ); - for (i = 0; i < TX_STATS_RING_SZ; i++) + + TAILQ_INIT(&head->free_list); + TAILQ_INIT(&head->host_list); + TAILQ_INIT(&head->comp_list); + + for (i = 0; i < TX_STATS_RING_SZ; i++) { ring[i].msdu_id = INVALID_TX_MSDU_ID; + TAILQ_INSERT_HEAD(&head->free_list, &ring[i], list); + } + head->num_free = TX_STATS_RING_SZ; + adf_os_spinlock_init(&head->mutex); return 0; @@ -116,11 +152,11 @@ static void ol_tx_stats_ring_deinit(void) } } -void ol_per_pkt_tx_stats_enable(int enable) +void ol_per_pkt_tx_stats_enable(bool enable) { int ret = 0; - if (ol_per_pkt_tx_stats_enabled == !!enable) + if (__ol_per_pkt_tx_stats_enabled == enable) return; if (enable) @@ -129,15 +165,122 @@ void ol_per_pkt_tx_stats_enable(int enable) ol_tx_stats_ring_deinit(); if (!ret) - ol_per_pkt_tx_stats_enabled = !!enable; + __ol_per_pkt_tx_stats_enabled = enable; else - ol_per_pkt_tx_stats_enabled = 0; + __ol_per_pkt_tx_stats_enabled = false; adf_os_mb(); } +bool ol_per_pkt_tx_stats_enabled(void) +{ + return __ol_per_pkt_tx_stats_enabled; +} + +static inline int __free_list_empty(void) +{ + return TAILQ_EMPTY(&tx_stats_ring_head->free_list); +} + +static inline int __host_list_empty(void) +{ + return TAILQ_EMPTY(&tx_stats_ring_head->host_list); +} + +static inline int __comp_list_empty(void) +{ + return TAILQ_EMPTY(&tx_stats_ring_head->comp_list); +} + +static inline struct ol_tx_stats_ring_item *__get_ring_item(void) +{ + struct ol_tx_stats_ring_head *h = tx_stats_ring_head; + struct ol_tx_stats_ring_item *item = NULL; + + if (!__free_list_empty()) { + item = TAILQ_FIRST(&h->free_list); + TAILQ_REMOVE(&h->free_list, item, list); + h->num_free--; + } else if (!__comp_list_empty()) { + /* Discard the oldest one. */ + item = TAILQ_LAST(&h->comp_list, comp_list); + TAILQ_REMOVE(&h->comp_list, item, list); + h->num_comp_stat--; + } else if (!__host_list_empty()) { + item = TAILQ_LAST(&h->host_list, host_list); + TAILQ_REMOVE(&h->host_list, item, list); + h->num_host_stat--; + } + + return item; +} + +static inline struct ol_tx_stats_ring_item * +__get_ring_item_host(uint32_t msdu_id) +{ + struct ol_tx_stats_ring_head *h = tx_stats_ring_head; + struct ol_tx_stats_ring_item *item = NULL; + struct ol_tx_stats_ring_item *temp = NULL; + + if (__host_list_empty()) + goto exit; + + TAILQ_FOREACH_REVERSE(temp, &h->host_list, host_list, list) { + if (temp && (temp->msdu_id == msdu_id)) { + item = temp; + TAILQ_REMOVE(&h->host_list, item, list); + h->num_host_stat--; + goto exit; + } + } + +exit: + return item; +} + +static inline struct ol_tx_stats_ring_item *__get_ring_item_comp(void) +{ + struct ol_tx_stats_ring_head *h = tx_stats_ring_head; + struct ol_tx_stats_ring_item *item = NULL; + + if (__comp_list_empty()) + goto exit; + + item = TAILQ_LAST(&h->comp_list, comp_list); + TAILQ_REMOVE(&h->comp_list, item, list); + h->num_comp_stat--; + +exit: + return item; +} + +static inline void __put_ring_item_host(struct ol_tx_stats_ring_item *item) +{ + struct ol_tx_stats_ring_head *h = tx_stats_ring_head; + + TAILQ_INSERT_HEAD(&h->host_list, item, list); + h->num_host_stat++; +} + +static inline void __put_ring_item_comp(struct ol_tx_stats_ring_item *item) +{ + struct ol_tx_stats_ring_head *h = tx_stats_ring_head; + + TAILQ_INSERT_HEAD(&h->comp_list, item, list); + h->num_comp_stat++; +} + +static inline void __free_ring_item(struct ol_tx_stats_ring_item *item) +{ + struct ol_tx_stats_ring_head *h = tx_stats_ring_head; + + TAILQ_INSERT_HEAD(&h->free_list, item, list); + h->num_free++; +} + /** - * ol_tx_stats_ring_enque() - enqueue the tx per packet stats + * ol_tx_stats_ring_enque_host() - enqueue the tx stats fields of a packet + * collected from tx path of host driver * @msdu_id: ol_tx_desc_id * @chan_freq: channel freqency * @bandwidth: channel bandwith like 10 or 20MHz @@ -145,26 +288,23 @@ void ol_per_pkt_tx_stats_enable(int enable) * @datarate: data rate used * * This interface is for caller from TXRX layer in interrupt context. - * - * Return: None */ -void ol_tx_stats_ring_enque(uint32_t msdu_id, uint32_t chan_freq, - uint32_t bandwidth, uint8_t *mac_address, - uint8_t datarate, uint8_t power) +void ol_tx_stats_ring_enque_host(uint32_t msdu_id, uint32_t chan_freq, + uint32_t bandwidth, uint8_t *mac_address, + uint8_t datarate) { struct ol_tx_stats_ring_head *h = tx_stats_ring_head; - struct ol_tx_stats_ring_item *ring = tx_stats_ring; struct ol_tx_stats_ring_item *item; static uint32_t seq_no = 0; - if (!h || !ring) + if (!h) return; adf_os_spin_lock(&h->mutex); - item = &ring[h->head++]; - if (h->head == TX_STATS_RING_SZ) - h->head = 0; + item = __get_ring_item(); + if (!item) + goto exit; item->msdu_id = msdu_id; item->stats.seq_no = seq_no++; @@ -172,25 +312,44 @@ void ol_tx_stats_ring_enque(uint32_t msdu_id, uint32_t chan_freq, item->stats.bandwidth = bandwidth; vos_mem_copy(item->stats.mac_address, mac_address, 6); item->stats.datarate = datarate; - item->stats.tx_power = power; - - /* if ring is full, discard the oldest one. */ - if (h->head == h->tail) { - item = &ring[h->tail++]; - if (h->tail == TX_STATS_RING_SZ) - h->tail = 0; - item->msdu_id = INVALID_TX_MSDU_ID; - } + __put_ring_item_host(item); +exit: adf_os_spin_unlock(&h->mutex); +} + +/** + * ol_tx_stats_ring_enque_comp() - enqueue the tx power of a packet from FW + * to form a complete tx stats item, which can be delivered to user + * @msdu_id: ol_tx_desc_id + * @tx_power: tx power used from FW + * + * This interface is for caller from WMA layer context. + */ +void ol_tx_stats_ring_enque_comp(uint32_t msdu_id, uint32_t tx_power) +{ + struct ol_tx_stats_ring_head *h = tx_stats_ring_head; + struct ol_tx_stats_ring_item *item; + + if (!h) + return; + + adf_os_spin_lock(&h->mutex); + + item = __get_ring_item_host(msdu_id); + if (!item) + goto exit; + + item->stats.tx_power = (uint8_t)tx_power; + __put_ring_item_comp(item); - TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s(), msdu_id=%u,head=%u,tail=%u\n", - __func__, msdu_id, h->head, h->tail); +exit: + adf_os_spin_unlock(&h->mutex); } /** - * ol_tx_stats_ring_deque() - dequeue a tx per packet stats + * ol_tx_stats_ring_deque() - dequeue a complete tx stats item to user * @stats: tx per packet stats * * This interface is for caller from user space process context. @@ -200,25 +359,19 @@ void ol_tx_stats_ring_enque(uint32_t msdu_id, uint32_t chan_freq, int ol_tx_stats_ring_deque(struct ol_tx_per_pkt_stats *stats) { struct ol_tx_stats_ring_head *h = tx_stats_ring_head; - struct ol_tx_stats_ring_item *ring = tx_stats_ring; struct ol_tx_stats_ring_item *item; int ret = 0; - if (!h || !ring) + if (!h) return ret; adf_os_spin_lock(&h->mutex); - if (h->head == h->tail) { + item = __get_ring_item_comp(); + if (!item) goto exit; - } - item = &ring[h->tail++]; - if (h->tail == TX_STATS_RING_SZ) - h->tail = 0; - - TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s(), msdu_id=%u,head=%u,tail=%u\n", - __func__, item->msdu_id, h->head, h->tail); + __free_ring_item(item); vos_mem_copy(stats, &item->stats, sizeof(*stats)); item->msdu_id = INVALID_TX_MSDU_ID; @@ -226,7 +379,6 @@ int ol_tx_stats_ring_deque(struct ol_tx_per_pkt_stats *stats) exit: adf_os_spin_unlock(&h->mutex); - return ret; } #endif /* WLAN_FEATURE_DSRC */ @@ -888,7 +1040,7 @@ ol_collect_per_pkt_tx_stats(ol_txrx_vdev_handle vdev, struct ol_txrx_ocb_chan_info *chan_info; int i; - if (!ol_per_pkt_tx_stats_enabled) + if (!ol_per_pkt_tx_stats_enabled()) return; chan_info = &vdev->ocb_channel_info[0]; @@ -899,9 +1051,10 @@ ol_collect_per_pkt_tx_stats(ol_txrx_vdev_handle vdev, break; } } - ol_tx_stats_ring_enque(msdu_id, tx_ctrl->channel_freq, - chan_info->bandwidth, chan_info->mac_address, - tx_ctrl->datarate, tx_ctrl->pwr); + + ol_tx_stats_ring_enque_host(msdu_id, tx_ctrl->channel_freq, + chan_info->bandwidth, chan_info->mac_address, + tx_ctrl->datarate); } #else static void dsrc_update_broadcast_frame_sa(ol_txrx_vdev_handle vdev, diff --git a/CORE/CLD_TXRX/TXRX/ol_tx.h b/CORE/CLD_TXRX/TXRX/ol_tx.h index 08a625e75594..986efea00ba7 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx.h +++ b/CORE/CLD_TXRX/TXRX/ol_tx.h @@ -37,7 +37,15 @@ #include <ol_txrx_api.h> /* ol_txrx_vdev_handle */ #include <ol_txrx_types.h> /* ol_tx_desc_t, ol_txrx_msdu_info_t */ -#ifdef WLAN_FEATURE_DSRC +/** + * struct ol_tx_per_pkt_stats - tx stats info of each packet sent out + * @seq_no: sequential number + * @chan_freq: channel freqency that this packet used + * @bandwidth: channel bandwidth + * @datarate: data rate + * @tx_power: tx power + * @mac_address: source MAC address that this packet used + */ struct ol_tx_per_pkt_stats { uint32_t seq_no; uint32_t chan_freq; @@ -47,20 +55,51 @@ struct ol_tx_per_pkt_stats { uint8_t mac_address[6]; }; +#ifdef WLAN_FEATURE_DSRC void -ol_per_pkt_tx_stats_enable(int enable); +ol_per_pkt_tx_stats_enable(bool enable); + +bool +ol_per_pkt_tx_stats_enabled(void); void -ol_tx_stats_ring_enque(uint32_t msdu_id, uint32_t chan_freq, - uint32_t bandwidth, uint8_t *mac_address, - uint8_t datarate, uint8_t power); +ol_tx_stats_ring_enque_host(uint32_t msdu_id, uint32_t chan_freq, + uint32_t bandwidth, uint8_t *mac_address, + uint8_t datarate); + +void +ol_tx_stats_ring_enque_comp(uint32_t msdu_id, uint32_t tx_power); int ol_tx_stats_ring_deque(struct ol_tx_per_pkt_stats *stats); #else static inline void -ol_per_pkt_tx_stats_enable(int enable) +ol_per_pkt_tx_stats_enable(bool enable) +{ +} + +static inline bool +ol_per_pkt_tx_stats_enabled(void) +{ + return false; +} + +static inline void +ol_tx_stats_ring_enque_host(uint32_t msdu_id, uint32_t chan_freq, + uint32_t bandwidth, uint8_t *mac_address, + uint8_t datarate) +{ +} + +static inline void +ol_tx_stats_ring_enque_comp(uint32_t msdu_id, uint32_t tx_power) +{ +} + +static inline int +ol_tx_stats_ring_deque(struct ol_tx_per_pkt_stats *stats) { + return 0; } #endif /* WLAN_FEATURE_DSRC */ diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_desc.c b/CORE/CLD_TXRX/TXRX/ol_tx_desc.c index 793ef8baf1af..2c45b1f6bffe 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx_desc.c +++ b/CORE/CLD_TXRX/TXRX/ol_tx_desc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -111,6 +111,30 @@ ol_tx_desc_alloc_hl(struct ol_txrx_pdev_t *pdev, struct ol_txrx_vdev_t *vdev) return tx_desc; } +#ifdef WLAN_FEATURE_DSRC +static inline void +__ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) +{ + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = NULL; + if (pdev->tx_desc.freelist) { + pdev->tx_desc.last->next = + (union ol_tx_desc_list_elem_t *)tx_desc; + } else { + pdev->tx_desc.freelist = + (union ol_tx_desc_list_elem_t *)tx_desc; + } + pdev->tx_desc.last = (union ol_tx_desc_list_elem_t *)tx_desc; +} +#else +static inline void +__ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) +{ + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = + pdev->tx_desc.freelist; + pdev->tx_desc.freelist = (union ol_tx_desc_list_elem_t *)tx_desc; +} +#endif /* WLAN_FEATURE_DSRC */ + void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) { @@ -121,9 +145,8 @@ ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) tx_desc->entry_timestamp_ticks = 0xffffffff; #endif #endif - ((union ol_tx_desc_list_elem_t *)tx_desc)->next = - pdev->tx_desc.freelist; - pdev->tx_desc.freelist = (union ol_tx_desc_list_elem_t *) tx_desc; + + __ol_tx_desc_free(pdev, tx_desc); pdev->tx_desc.num_free++; #if defined(CONFIG_PER_VDEV_TX_DESC_POOL) diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_send.c b/CORE/CLD_TXRX/TXRX/ol_tx_send.c index dfcc640018b7..a12636092ac2 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx_send.c +++ b/CORE/CLD_TXRX/TXRX/ol_tx_send.c @@ -534,14 +534,42 @@ ol_tx_credit_completion_handler(ol_txrx_pdev_handle pdev, int credits) OL_TX_FLOW_CT_UNPAUSE_OS_Q(pdev); } +static inline int +ol_tx_get_retries_size(u_int32_t *msg_word, int num_msdus) +{ + struct htt_tx_compl_ind_append_retries *list = NULL; + int offset; + int i = 0; + + if (!HTT_TX_COMPL_IND_APPEND_GET(*msg_word)) + return 0; + + /* offset in 32 bits word */ + offset = 1 + ((num_msdus + 1) >> 1); + list = (struct htt_tx_compl_ind_append_retries *)(msg_word + offset); + while (list[i].flag && (i < num_msdus)) { + i++; + } + + return (i * sizeof(struct htt_tx_compl_ind_append_retries)) >> 2; +} + +static inline int +ol_tx_get_txtstamps_size(u_int32_t *msg_word, int num_msdus) +{ + if (!HTT_TX_COMPL_IND_APPEND1_GET(*msg_word)) + return 0; + + return (num_msdus * sizeof(struct htt_tx_compl_ind_append_txtstamp)) + >> 2; +} + #ifdef WLAN_FEATURE_TSF_PLUS -static inline struct htt_tx_compl_ind_append_txtstamp *ol_tx_get_txtstamps( - u_int32_t *msg_word, int num_msdus) +static inline struct htt_tx_compl_ind_append_txtstamp * +ol_tx_get_txtstamps(u_int32_t *msg_word, int num_msdus) { u_int32_t has_tx_tsf; - u_int32_t has_retry; struct htt_tx_compl_ind_append_txtstamp *txtstamp_list = NULL; - struct htt_tx_compl_ind_append_retries *retry_list = NULL; int offset_dwords; has_tx_tsf = HTT_TX_COMPL_IND_APPEND1_GET(*msg_word); @@ -549,30 +577,15 @@ static inline struct htt_tx_compl_ind_append_txtstamp *ol_tx_get_txtstamps( return NULL; offset_dwords = 1 + ((num_msdus + 1) >> 1); - - has_retry = HTT_TX_COMPL_IND_APPEND_GET(*msg_word); - if (has_retry) { - int retry_index = 0; - int width_for_each_retry = - (sizeof(struct htt_tx_compl_ind_append_retries) + - 3) >> 2; - - retry_list = (struct htt_tx_compl_ind_append_retries *) - (msg_word + offset_dwords); - while (retry_list) { - if (retry_list[retry_index++].flag == 0) - break; - } - offset_dwords += retry_index * width_for_each_retry; - } + offset_dwords += ol_tx_get_retries_size(msg_word, num_msdus); txtstamp_list = (struct htt_tx_compl_ind_append_txtstamp *) (msg_word + offset_dwords); return txtstamp_list; } -static inline void ol_tx_timestamp(ol_txrx_pdev_handle pdev, - adf_nbuf_t netbuf, u_int64_t ts) +static inline void +ol_tx_timestamp(ol_txrx_pdev_handle pdev, adf_nbuf_t netbuf, u_int64_t ts) { if (!netbuf) return; @@ -581,17 +594,60 @@ static inline void ol_tx_timestamp(ol_txrx_pdev_handle pdev, pdev->ol_tx_timestamp_cb(netbuf, ts); } #else -static inline struct htt_tx_compl_ind_append_txtstamp *ol_tx_get_txtstamps( - u_int32_t *msg_word, int num_msdus) +static inline struct htt_tx_compl_ind_append_txtstamp * +ol_tx_get_txtstamps(u_int32_t *msg_word, int num_msdus) { return NULL; } -static inline void ol_tx_timestamp(ol_txrx_pdev_handle pdev, - adf_nbuf_t netbuf, u_int64_t ts) +static inline void +ol_tx_timestamp(ol_txrx_pdev_handle pdev, adf_nbuf_t netbuf, u_int64_t ts) { } -#endif +#endif /* WLAN_FEATURE_TSF_PLUS */ + +#ifdef WLAN_FEATURE_DSRC +#define DSRC_INVALID_TX_POWER 0xffff + +static inline struct htt_tx_compl_ind_append_txpower * +ol_tx_get_txpowers(u_int32_t *msg_word, int num_msdus) +{ + struct htt_tx_compl_ind_append_txpower *txpower_list = NULL; + int offset_dwords; + + /* Check if tx power exists. */ + if (!HTT_TX_COMPL_IND_APPEND2_GET(*msg_word)) + return NULL; + + offset_dwords = 1 + ((num_msdus + 1) >> 1); + offset_dwords += ol_tx_get_retries_size(msg_word, num_msdus); + offset_dwords += ol_tx_get_txtstamps_size(msg_word, num_msdus); + txpower_list = (struct htt_tx_compl_ind_append_txpower *) + (msg_word + offset_dwords); + + return txpower_list; +} + +static inline void +ol_tx_power_handler(u_int16_t desc_id, u_int16_t tx_power) +{ + if (DSRC_INVALID_TX_POWER == tx_power) + return; + + ol_tx_stats_ring_enque_comp(desc_id, tx_power); +} +#else +static inline struct htt_tx_compl_ind_append_txpower * +ol_tx_get_txpowers(u_int32_t *msg_word, int num_msdus) +{ + return NULL; +} + +static inline void +ol_tx_power_handler(u_int16_t desc_id, u_int16_t tx_power) +{ +} +#endif /* WLAN_FEATURE_DSRC */ /* WARNING: ol_tx_inspect_handler()'s bahavior is similar to that of ol_tx_completion_handler(). * any change in ol_tx_completion_handler() must be mirrored in ol_tx_inspect_handler(). @@ -616,6 +672,7 @@ ol_tx_completion_handler( ol_tx_desc_list tx_descs; uint32_t is_tx_desc_freed = 0; struct htt_tx_compl_ind_append_txtstamp *txtstamp_list = NULL; + struct htt_tx_compl_ind_append_txpower *txpower_list = NULL; u_int32_t *msg_word = (u_int32_t *)msg; u_int16_t *desc_ids = (u_int16_t *)(msg_word + 1); @@ -631,8 +688,10 @@ ol_tx_completion_handler( } OL_TX_DELAY_COMPUTE(pdev, status, desc_ids, num_msdus); - if (status == htt_tx_status_ok) + if (status == htt_tx_status_ok) { txtstamp_list = ol_tx_get_txtstamps(msg_word, num_msdus); + txpower_list = ol_tx_get_txpowers(msg_word, num_msdus); + } trace_str = (status) ? "OT:C:F:" : "OT:C:S:"; for (i = 0; i < num_msdus; i++) { @@ -640,10 +699,14 @@ ol_tx_completion_handler( tx_desc = ol_tx_desc_find(pdev, tx_desc_id); tx_desc->status = status; netbuf = tx_desc->netbuf; + if (txtstamp_list) ol_tx_timestamp(pdev, netbuf, (u_int64_t)txtstamp_list->timestamp[i]); + if (txpower_list) + ol_tx_power_handler(tx_desc_id, txpower_list->tx_power[i]); + NBUF_UPDATE_TX_PKT_COUNT(netbuf, NBUF_TX_PKT_FREE); DPTRACE(adf_dp_trace_ptr(netbuf, ADF_DP_TRACE_FREE_PACKET_PTR_RECORD, diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c index 690bbbeaa9a6..3dd048bc3c3b 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx.c +++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -496,12 +496,13 @@ ol_txrx_pdev_attach( void *htt_tx_desc; u_int32_t paddr_lo; - if (i == (desc_pool_size - 1)) + if (i == (desc_pool_size - 1)) { c_element->next = NULL; - else + pdev->tx_desc.last = c_element; + } else { c_element->next = (union ol_tx_desc_list_elem_t *) ol_tx_desc_find(pdev, i + 1); - + } htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr_lo); if (! htt_tx_desc) { VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h index b0f572ef22c0..75974104ffe2 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h +++ b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h @@ -621,6 +621,7 @@ struct ol_txrx_pdev_t { u_int16_t pool_size; u_int16_t num_free; union ol_tx_desc_list_elem_t *freelist; + union ol_tx_desc_list_elem_t *last; uint32_t page_size; uint16_t desc_reserved_size; uint8_t page_divider; diff --git a/CORE/HDD/src/wlan_hdd_debugfs_ocb.c b/CORE/HDD/src/wlan_hdd_debugfs_ocb.c index 8c4fd1821825..9ea98101e1a5 100644 --- a/CORE/HDD/src/wlan_hdd_debugfs_ocb.c +++ b/CORE/HDD/src/wlan_hdd_debugfs_ocb.c @@ -22,7 +22,9 @@ #include "wlan_hdd_debugfs.h" #include "wlan_hdd_debugfs_ocb.h" #include "ol_tx.h" +#include "wma_api.h" #include "wlan_hdd_ocb.h" +#include "adf_os_time.h" #define WLAN_DSRC_COMMAND_MAX_SIZE 8 #define WLAN_DSRC_CHAN_STATS_ENABLE 1 @@ -332,6 +334,16 @@ int wlan_hdd_create_dsrc_chan_stats_file(hdd_adapter_t *adapter, return 0; } +static inline bool __tx_stats_enabled(void) +{ + return ol_per_pkt_tx_stats_enabled(); +} + +static inline void __enable_tx_stats(bool enable) +{ + ol_per_pkt_tx_stats_enable(enable); +} + /** * __per_pkt_tx_stats_read() - read DSRC per-packet tx stats by DSRC app * @file: file pointer @@ -361,6 +373,9 @@ static ssize_t __per_pkt_tx_stats_read(struct file *file, if (ret) return ret; + if (!__tx_stats_enabled()) + return ret; + ret = ol_tx_stats_ring_deque(&tx_stats); if (ret) { ret = sizeof(tx_stats); @@ -392,16 +407,21 @@ static ssize_t per_pkt_tx_stats_read(struct file *file, * * Return: 0 on success, error number otherwise */ -static int __enable_per_pkt_tx_stats(int enable) +static int __enable_per_pkt_tx_stats(bool enable) { - static int __enable = 0; int ret = 0; - if ((__enable && enable) || (!__enable && !enable)) + if (enable == __tx_stats_enabled()) return ret; - ol_per_pkt_tx_stats_enable(enable); - __enable = enable; + ret = process_wma_set_command(0, WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, + enable ? 1 : 0, PDEV_CMD); + if (!ret) { + adf_os_msleep(100); + __enable_tx_stats(enable); + } else { + hddLog(LOGE,FL("WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE failed")); + } return ret; } @@ -463,7 +483,7 @@ static ssize_t __per_pkt_tx_stats_write(struct file *file, goto failure; } - __enable_per_pkt_tx_stats((int)enable); + __enable_per_pkt_tx_stats(!!enable); vos_mem_free(cmd); EXIT(); diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c index 6e6360ece52b..dab571ea0a9e 100644 --- a/CORE/SERVICES/BMI/ol_fw.c +++ b/CORE/SERVICES/BMI/ol_fw.c @@ -2840,7 +2840,8 @@ ol_sdio_extra_initialization(struct ol_softc *scn) param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET | HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE); - if (!vos_is_ptp_tx_opt_enabled()) + if (!vos_is_ptp_tx_opt_enabled() && + !vos_is_ocb_per_pkt_tx_comp_msg_needed()) param |= HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET; /* enable TX completion to collect tx_desc for pktlog */ diff --git a/CORE/SERVICES/COMMON/adf/adf_os_time.h b/CORE/SERVICES/COMMON/adf/adf_os_time.h index 0c0c11189732..6c92692a5bf3 100644 --- a/CORE/SERVICES/COMMON/adf/adf_os_time.h +++ b/CORE/SERVICES/COMMON/adf/adf_os_time.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -117,6 +117,16 @@ adf_os_mdelay(int msecs) } /** + * adf_os_msleep() - sleep in milliseconds. + * @msecs: milliseconds to sleep + */ +static inline void +adf_os_msleep(int msecs) +{ + __adf_os_msleep(msecs); +} + +/** * @brief Check if _a is later than _b. */ #define adf_os_time_after(_a, _b) __adf_os_time_after(_a, _b) diff --git a/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h b/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h index d8e07af89614..7eda8c9583f1 100644 --- a/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h +++ b/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -103,6 +103,12 @@ __adf_os_mdelay(a_uint32_t msecs) mdelay(msecs); } +static inline void +__adf_os_msleep(a_uint32_t msecs) +{ + msleep(msecs); +} + /** * @brief Check if _a is later than _b. */ diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 63b2476022c8..93667eda3e53 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -17350,6 +17350,7 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, case WMI_PDEV_PARAM_ANT_DIV_SELFTEST: case WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL: case WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE: + case WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE: break; default: WMA_LOGE("Invalid wda_cli_set pdev command/Not" diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h index 6022e0a52e82..f1b77be7b990 100644 --- a/CORE/VOSS/inc/vos_api.h +++ b/CORE/VOSS/inc/vos_api.h @@ -356,6 +356,18 @@ static inline bool vos_is_ptp_tx_opt_enabled(void) } #endif +#ifdef WLAN_FEATURE_DSRC +static inline bool vos_is_ocb_per_pkt_tx_comp_msg_needed(void) +{ + return true; +} +#else +static inline bool vos_is_ocb_per_pkt_tx_comp_msg_needed(void) +{ + return false; +} +#endif + v_U64_t vos_get_monotonic_boottime(void); /** |
