From ceb357b9644941ee2418a0100fec2009984177f8 Mon Sep 17 00:00:00 2001 From: Yu Wang Date: Thu, 1 Jun 2017 12:04:18 +0800 Subject: [PATCH] qcacld-3.0: time stamp msdu with precise rx/tx time Get tx/rx tsf time for each msdu, and then time stamp the msdu with the corresponding host time. Change-Id: I7af80318b60c28d53e95fbe545e82da4191544b6 CRs-Fixed: 2057693 --- core/bmi/src/ol_fw_common.c | 13 ++++- core/dp/htt/htt_t2h.c | 4 +- core/dp/ol/inc/ol_txrx_api.h | 26 ++++++++- core/dp/ol/inc/ol_txrx_htt_api.h | 6 +- core/dp/txrx/ol_rx.c | 21 +++++++ core/dp/txrx/ol_tx_send.c | 97 +++++++++++++++++++++++++++++++- core/dp/txrx/ol_txrx_types.h | 4 ++ core/hdd/src/wlan_hdd_tsf.c | 3 + core/hdd/src/wlan_hdd_tx_rx.c | 3 +- 9 files changed, 164 insertions(+), 13 deletions(-) diff --git a/core/bmi/src/ol_fw_common.c b/core/bmi/src/ol_fw_common.c index f79e450bef..848d8b4764 100644 --- a/core/bmi/src/ol_fw_common.c +++ b/core/bmi/src/ol_fw_common.c @@ -96,6 +96,15 @@ ol_usb_extra_initialization(struct ol_context *ol_ctx) return status; } +#if defined(WLAN_FEATURE_TSF_PLUS) +#define SDIO_HI_ACS_FLAGS (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET | \ + HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE) +#else +#define SDIO_HI_ACS_FLAGS (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET | \ + HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET | \ + HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE) +#endif + /*Setting SDIO block size, mbox ISR yield limit for SDIO based HIF*/ static QDF_STATUS ol_sdio_extra_initialization(struct ol_context *ol_ctx) @@ -163,9 +172,7 @@ QDF_STATUS ol_sdio_extra_initialization(struct ol_context *ol_ctx) goto exit; } - param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET| - HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET| - HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE); + param |= SDIO_HI_ACS_FLAGS; bmi_write_memory(hif_hia_item_address(target_type, offsetof(struct host_interest_s, diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index fdd4baac3c..5fe1bc2322 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -681,7 +681,7 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) } ol_tx_completion_handler(pdev->txrx_pdev, num_msdus, - status, msg_word + 1); + status, msg_word); HTT_TX_SCHED(pdev); break; } @@ -905,7 +905,7 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus, } } ol_tx_completion_handler(pdev->txrx_pdev, num_msdus, - status, msg_word + 1); + status, msg_word); break; } diff --git a/core/dp/ol/inc/ol_txrx_api.h b/core/dp/ol/inc/ol_txrx_api.h index b0d56ee1df..6182105ddd 100644 --- a/core/dp/ol/inc/ol_txrx_api.h +++ b/core/dp/ol/inc/ol_txrx_api.h @@ -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. * @@ -66,4 +66,28 @@ void ol_register_packetdump_callback(tp_ol_packetdump_cb ol_tx_packetdump_cb, tp_ol_packetdump_cb ol_rx_packetdump_cb); void ol_deregister_packetdump_callback(void); +#ifdef WLAN_FEATURE_TSF_PLUS +typedef int (*tp_ol_timestamp_cb)(qdf_nbuf_t netbuf, uint64_t target_time); + +/** + * ol_register_timestamp_callback() - set callbacks for timestamp tx msdu. + * @ol_tx_timestamp_cb: callback function for time stamp tx msdu + * + * This function register timestamp callback, the callback will + * be called when tx a msdu + * + * Return: nothing + */ +void ol_register_timestamp_callback(tp_ol_timestamp_cb ol_tx_timestamp_cb); + +/** + * ol_deregister_timestamp_callback() - reset callbacks for timestamp + * tx msdu to NULL. + * + * This function reset the timestamp callbacks for tx + * + * Return: nothing + */ +void ol_deregister_timestamp_callback(void); +#endif #endif /* _OL_TXRX_API__H_ */ diff --git a/core/dp/ol/inc/ol_txrx_htt_api.h b/core/dp/ol/inc/ol_txrx_htt_api.h index c5faf59f37..3d22f1b070 100644 --- a/core/dp/ol/inc/ol_txrx_htt_api.h +++ b/core/dp/ol/inc/ol_txrx_htt_api.h @@ -150,14 +150,12 @@ enum htt_tx_status { * @param num_msdus - how many MSDUs are referenced by the tx completion * message * @param status - whether transmission was successful - * @param tx_msdu_id_iterator - abstract method of finding the IDs for the - * individual MSDUs referenced by the tx completion message, via the - * htt_tx_compl_desc_id API function + * @param msg_word - the tx completion message */ void ol_tx_completion_handler(ol_txrx_pdev_handle pdev, int num_msdus, - enum htt_tx_status status, void *tx_msdu_id_iterator); + enum htt_tx_status status, void *msg_word); void ol_tx_credit_completion_handler(ol_txrx_pdev_handle pdev, int credits); diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c index 41b0b9cfad..b4d51da141 100644 --- a/core/dp/txrx/ol_rx.c +++ b/core/dp/txrx/ol_rx.c @@ -1135,6 +1135,25 @@ ol_rx_filter(struct ol_txrx_vdev_t *vdev, return FILTER_STATUS_REJECT; } +#ifdef WLAN_FEATURE_TSF_PLUS +static inline void ol_rx_timestamp(void *rx_desc, qdf_nbuf_t msdu) +{ + struct htt_rx_ppdu_desc_t *rx_ppdu_desc; + + if (!rx_desc || !msdu) + return; + + rx_ppdu_desc = (struct htt_rx_ppdu_desc_t *)((uint8_t *)(rx_desc) - + HTT_RX_IND_HL_BYTES + HTT_RX_IND_HDR_PREFIX_BYTES); + msdu->tstamp = ns_to_ktime((u_int64_t)rx_ppdu_desc->tsf32 * + NSEC_PER_USEC); +} +#else +static inline void ol_rx_timestamp(void *rx_desc, qdf_nbuf_t msdu) +{ +} +#endif + void ol_rx_deliver(struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer, unsigned int tid, @@ -1315,6 +1334,8 @@ DONE: OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, rx_desc, OL_RX_ERR_NONE); TXRX_STATS_MSDU_INCR(vdev->pdev, rx.delivered, msdu); + + ol_rx_timestamp(rx_desc, msdu); OL_TXRX_LIST_APPEND(deliver_list_head, deliver_list_tail, msdu); } diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index 8b3c8c823e..7664b8ea59 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -555,6 +555,65 @@ void ol_tx_credit_completion_handler(ol_txrx_pdev_handle pdev, int credits) ol_tx_flow_ct_unpause_os_q(pdev); } +#ifdef WLAN_FEATURE_TSF_PLUS +static inline struct htt_tx_compl_ind_append_tx_tstamp *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_tx_tstamp *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); + if (num_msdus <= 0 || !has_tx_tsf) + 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; + } + txtstamp_list = (struct htt_tx_compl_ind_append_tx_tstamp *) + (msg_word + offset_dwords); + + return txtstamp_list; +} + +static inline void ol_tx_timestamp(ol_txrx_pdev_handle pdev, + qdf_nbuf_t netbuf, u_int64_t ts) +{ + if (!netbuf) + return; + + if (pdev->ol_tx_timestamp_cb) + pdev->ol_tx_timestamp_cb(netbuf, ts); +} +#else +static inline struct htt_tx_compl_ind_append_tx_tstamp *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, + qdf_nbuf_t netbuf, u_int64_t ts) +{ +} +#endif + /** * WARNING: ol_tx_inspect_handler()'s bahavior is similar to that of * ol_tx_completion_handler(). @@ -564,16 +623,18 @@ void ol_tx_credit_completion_handler(ol_txrx_pdev_handle pdev, int credits) void ol_tx_completion_handler(ol_txrx_pdev_handle pdev, int num_msdus, - enum htt_tx_status status, void *tx_desc_id_iterator) + enum htt_tx_status status, void *msg) { int i; - uint16_t *desc_ids = (uint16_t *) tx_desc_id_iterator; uint16_t tx_desc_id; struct ol_tx_desc_t *tx_desc; uint32_t byte_cnt = 0; qdf_nbuf_t netbuf; tp_ol_packetdump_cb packetdump_cb; uint32_t is_tx_desc_freed = 0; + struct htt_tx_compl_ind_append_tx_tstamp *txtstamp_list = NULL; + u_int32_t *msg_word = (u_int32_t *)msg; + u_int16_t *desc_ids = (u_int16_t *)(msg_word + 1); union ol_tx_desc_list_elem_t *lcl_freelist = NULL; union ol_tx_desc_list_elem_t *tx_desc_last = NULL; @@ -581,12 +642,20 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev, TAILQ_INIT(&tx_descs); ol_tx_delay_compute(pdev, status, desc_ids, num_msdus); + if (status == htt_tx_status_ok) + txtstamp_list = ol_tx_get_txtstamps(msg_word, num_msdus); for (i = 0; i < num_msdus; i++) { tx_desc_id = desc_ids[i]; 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] + ); + QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_FREE); if (tx_desc->pkt_type != OL_TX_FRM_TSO) { @@ -1309,3 +1378,27 @@ void ol_deregister_packetdump_callback(void) pdev->ol_tx_packetdump_cb = NULL; pdev->ol_rx_packetdump_cb = NULL; } + +#ifdef WLAN_FEATURE_TSF_PLUS +void ol_register_timestamp_callback(tp_ol_timestamp_cb ol_tx_timestamp_cb) +{ + ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX); + + if (!pdev) { + ol_txrx_err("%s: pdev is NULL", __func__); + return; + } + pdev->ol_tx_timestamp_cb = ol_tx_timestamp_cb; +} + +void ol_deregister_timestamp_callback(void) +{ + ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX); + + if (!pdev) { + ol_txrx_err("%s: pdev is NULL", __func__); + return; + } + pdev->ol_tx_timestamp_cb = NULL; +} +#endif diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 9b7eadfc6f..969c01da2f 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -676,6 +676,10 @@ struct ol_txrx_pdev_t { tp_ol_packetdump_cb ol_tx_packetdump_cb; tp_ol_packetdump_cb ol_rx_packetdump_cb; +#ifdef WLAN_FEATURE_TSF_PLUS + tp_ol_timestamp_cb ol_tx_timestamp_cb; +#endif + struct { uint16_t pool_size; uint16_t num_free; diff --git a/core/hdd/src/wlan_hdd_tsf.c b/core/hdd/src/wlan_hdd_tsf.c index 0cd36bda88..89658935ac 100644 --- a/core/hdd/src/wlan_hdd_tsf.c +++ b/core/hdd/src/wlan_hdd_tsf.c @@ -831,6 +831,8 @@ enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(hdd_context_t *hdd_ctx) hdd_err("Failed to register irq handler: %d", ret); return HDD_TSF_OP_FAIL; } + + ol_register_timestamp_callback(hdd_tx_timestamp); return HDD_TSF_OP_SUCC; } @@ -839,6 +841,7 @@ enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(hdd_context_t *hdd_ctx) { int ret; + ol_deregister_timestamp_callback(); ret = cnss_common_unregister_tsf_captured_handler( hdd_ctx->parent_dev, (void *)hdd_ctx); diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index a7bb5ca363..a9a4990c09 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -63,6 +63,7 @@ #include #include "wlan_hdd_rx_monitor.h" #include "wlan_hdd_power.h" +#include #ifdef QCA_LL_TX_FLOW_CONTROL_V2 /* @@ -1253,6 +1254,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) */ qdf_net_buf_debug_release_skb(skb); + hdd_rx_timestamp(skb, ktime_to_us(skb->tstamp)); if (HDD_LRO_NO_RX == hdd_lro_rx(pHddCtx, pAdapter, skb)) { if (hdd_napi_enabled(HDD_NAPI_ANY) && @@ -1267,7 +1269,6 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) else ++pAdapter->hdd_stats.hddTxRxStats. rxRefused[cpu_index]; - } else { ++pAdapter->hdd_stats.hddTxRxStats. rxDelivered[cpu_index];