From a8fd170e7ae417b11c59c951b4ceff1137cd535f Mon Sep 17 00:00:00 2001 From: Jiani Liu Date: Wed, 1 May 2019 10:07:10 +0800 Subject: [PATCH] qcacld-3.0: Add PTP timestamp socket options RX support Host need to fill netbuf with qtime instead of tsf. So host first need to set enable_ppdu_end to 1, so that FW will pass ppdu_end contents to host, and host can translate tsf64_time into qtime. The tsf64_time is new added to fw struture, so host will need add it accordingly to struct hdd_adapter, and keep it updated in time synchronization function . Change-Id: Ib19ac1411c4e17624c012f188297c9f2122642d2 CRs-Fixed: 2444456 --- core/dp/htt/htt_h2t.c | 2 + core/dp/htt/htt_rx.c | 7 +++ core/dp/ol/inc/ol_htt_rx_api.h | 14 +++++ core/dp/txrx/ol_rx.c | 39 ++++++++++++++ core/hdd/inc/wlan_hdd_main.h | 2 + core/hdd/src/wlan_hdd_tsf.c | 94 ++++++++++++++++++++++++++++++++-- core/mac/inc/sir_api.h | 4 ++ 7 files changed, 159 insertions(+), 3 deletions(-) diff --git a/core/dp/htt/htt_h2t.c b/core/dp/htt/htt_h2t.c index dc4e143768e1..31445546655f 100644 --- a/core/dp/htt/htt_h2t.c +++ b/core/dp/htt/htt_h2t.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -540,6 +541,7 @@ QDF_STATUS htt_h2t_rx_ring_cfg_msg_ll(struct htt_pdev_t *pdev) __func__, __LINE__); } + htt_rx_enable_ppdu_end(&enable_ppdu_end); HTT_RX_RING_CFG_ENABLED_802_11_HDR_SET(*msg_word, enable_hdr); HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_PPDU_START_SET(*msg_word, enable_ppdu_start); diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index b0155023347d..efc583d100a6 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -422,3 +422,10 @@ void htt_deregister_rx_pkt_dump_callback(struct htt_pdev_t *pdev) pdev->rx_pkt_dump_cb = NULL; } #endif + +#ifdef WLAN_FEATURE_TSF_PLUS +void htt_rx_enable_ppdu_end(int *enable_ppdu_end) +{ + *enable_ppdu_end = 1; +} +#endif diff --git a/core/dp/ol/inc/ol_htt_rx_api.h b/core/dp/ol/inc/ol_htt_rx_api.h index dbb85fecac92..3554b3467d95 100644 --- a/core/dp/ol/inc/ol_htt_rx_api.h +++ b/core/dp/ol/inc/ol_htt_rx_api.h @@ -1007,4 +1007,18 @@ uint32_t htt_rx_amsdu_rx_in_order_get_pktlog(qdf_nbuf_t rx_ind_msg); * Return: QDF_STATUS */ QDF_STATUS htt_rx_update_smmu_map(struct htt_pdev_t *pdev, bool map); + +/** htt_tx_enable_ppdu_end + * @enable_ppdu_end - set it to 1 if WLAN_FEATURE_TSF_PLUS is defined, + * else do nothing + */ +#ifdef WLAN_FEATURE_TSF_PLUS +void htt_rx_enable_ppdu_end(int *enable_ppdu_end); +#else +static inline +void htt_rx_enable_ppdu_end(int *enable_ppdu_end) +{ +} +#endif + #endif /* _OL_HTT_RX_API__H_ */ diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c index a1de0d283a45..3c609a285c6b 100644 --- a/core/dp/txrx/ol_rx.c +++ b/core/dp/txrx/ol_rx.c @@ -54,6 +54,7 @@ #include "pktlog_ac_fmt.h" #include #include +#include #ifndef OL_RX_INDICATION_MAX_RECORDS #define OL_RX_INDICATION_MAX_RECORDS 2048 @@ -1118,6 +1119,7 @@ ol_rx_filter(struct ol_txrx_vdev_t *vdev, #endif #ifdef WLAN_FEATURE_TSF_PLUS +#ifdef CONFIG_HL_SUPPORT static inline void ol_rx_timestamp(struct cdp_cfg *cfg_pdev, void *rx_desc, qdf_nbuf_t msdu) { @@ -1135,6 +1137,32 @@ static inline void ol_rx_timestamp(struct cdp_cfg *cfg_pdev, NSEC_PER_USEC); } #else +static inline void ol_rx_timestamp(struct cdp_cfg *cfg_pdev, + void *rx_desc, qdf_nbuf_t msdu) +{ + struct htt_host_rx_desc_base *rx_mpdu_desc = rx_desc; + uint32_t tsf64_low32, tsf64_high32; + uint64_t tsf64, tsf64_ns; + + if (!ol_cfg_is_ptp_rx_opt_enabled(cfg_pdev)) + return; + + if (!rx_mpdu_desc || !msdu) + return; + + tsf64_low32 = rx_mpdu_desc->ppdu_end.wb_timestamp_lower_32; + tsf64_high32 = rx_mpdu_desc->ppdu_end.wb_timestamp_upper_32; + + tsf64 = (uint64_t)tsf64_high32 << 32 | tsf64_low32; + if (tsf64 * NSEC_PER_USEC < tsf64) + tsf64_ns = 0; + else + tsf64_ns = tsf64 * NSEC_PER_USEC; + + msdu->tstamp = ns_to_ktime(tsf64_ns); +} +#endif +#else static inline void ol_rx_timestamp(struct cdp_cfg *cfg_pdev, void *rx_desc, qdf_nbuf_t msdu) { @@ -1425,6 +1453,8 @@ ol_rx_in_order_indication_handler(ol_txrx_pdev_handle pdev, uint32_t msdu_count; uint8_t pktlog_bit; uint32_t filled = 0; + struct htt_host_rx_desc_base *rx_desc; + qdf_nbuf_t loop_msdu; if (tid >= OL_TXRX_NUM_EXT_TIDS) { ol_txrx_err("invalid tid, %u", tid); @@ -1509,6 +1539,15 @@ ol_rx_in_order_indication_handler(ol_txrx_pdev_handle pdev, } return; } + /*Loop msdu to fill tstamp with tsf64 time in ol_rx_timestamp*/ + loop_msdu = head_msdu; + while (loop_msdu) { + qdf_nbuf_t msdu = head_msdu; + + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, loop_msdu); + ol_rx_timestamp(pdev->ctrl_pdev, rx_desc, msdu); + loop_msdu = qdf_nbuf_next(loop_msdu); + } peer->rx_opt_proc(vdev, peer, tid, head_msdu); } diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 806d2c1a0e99..3c94bcd7ed8b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1230,6 +1230,8 @@ struct hdd_adapter { uint64_t cur_target_time; uint64_t cur_tsf_sync_soc_time; uint64_t last_tsf_sync_soc_time; + uint64_t cur_target_global_tsf_time; + uint64_t last_target_global_tsf_time; qdf_mc_timer_t host_capture_req_timer; #ifdef WLAN_FEATURE_TSF_PLUS /* spin lock for read/write timestamps */ diff --git a/core/hdd/src/wlan_hdd_tsf.c b/core/hdd/src/wlan_hdd_tsf.c index 8149cca26228..42fed2ea0d95 100644 --- a/core/hdd/src/wlan_hdd_tsf.c +++ b/core/hdd/src/wlan_hdd_tsf.c @@ -664,6 +664,60 @@ static inline int32_t hdd_get_targettime_from_hosttime( return ret; } +/** + * hdd_get_soctime_from_tsf64time() - return get status + * + * @adapter: Adapter pointer + * @tsf64_time: current tsf64time, us + * @soc_time: current soc time(qtime), ns + * + * This function get current soc time from current tsf64 time + * Returun int32_t value to tell get success or fail. + * + * Return: + * 0: success + * other: fail + * + */ +static inline int32_t hdd_get_soctime_from_tsf64time( + struct hdd_adapter *adapter, uint64_t tsf64_time, + uint64_t *soc_time) +{ + int32_t ret = -EINVAL; + uint64_t delta64_tsf64time; + uint64_t delta64_soctime; + bool in_cap_state; + + in_cap_state = hdd_tsf_is_in_cap(adapter); + + /* + * To avoid check the lock when it's not capturing tsf + * (the tstamp-pair won't be changed) + */ + if (in_cap_state) + qdf_spin_lock_bh(&adapter->host_target_sync_lock); + + /* at present, target_time is 64bit (g_tsf64), us*/ + if (tsf64_time > adapter->last_target_global_tsf_time) + delta64_tsf64time = tsf64_time - + adapter->last_target_global_tsf_time; + else { + if (in_cap_state) + qdf_spin_unlock_bh(&adapter->host_target_sync_lock); + return -EINVAL; + } + + delta64_soctime = delta64_tsf64time * NSEC_PER_USEC; + + /* soc_time (ns)*/ + ret = hdd_uint64_plus(adapter->last_tsf_sync_soc_time, + delta64_soctime, soc_time); + if (in_cap_state) + qdf_spin_unlock_bh(&adapter->host_target_sync_lock); + + return ret; +} + static inline uint64_t hdd_get_monotonic_host_time(struct hdd_context *hdd_ctx) { @@ -811,12 +865,16 @@ static void hdd_update_timestamp(struct hdd_adapter *adapter) */ case HDD_TS_STATUS_READY: adapter->last_target_time = adapter->cur_target_time; + adapter->last_target_global_tsf_time = + adapter->cur_target_global_tsf_time; adapter->last_tsf_sync_soc_time = adapter->cur_tsf_sync_soc_time; adapter->cur_target_time = 0; + adapter->cur_target_global_tsf_time = 0; adapter->cur_tsf_sync_soc_time = 0; - hdd_info("ts-pair updated: target: %llu; Qtime: %llu", + hdd_info("ts-pair updated: target: %llu; g_target:%llu, Qtime: %llu", adapter->last_target_time, + adapter->last_target_global_tsf_time, adapter->last_tsf_sync_soc_time); /* @@ -1171,6 +1229,7 @@ static enum hdd_tsf_op_result hdd_tsf_sync_deinit(struct hdd_adapter *adapter) return HDD_TSF_OP_SUCC; } +#ifdef CONFIG_HL_SUPPORT static inline enum hdd_tsf_op_result hdd_netbuf_timestamp(qdf_nbuf_t netbuf, uint64_t target_time) @@ -1196,6 +1255,34 @@ enum hdd_tsf_op_result hdd_netbuf_timestamp(qdf_nbuf_t netbuf, return HDD_TSF_OP_FAIL; } +#else +static inline +enum hdd_tsf_op_result hdd_netbuf_timestamp(qdf_nbuf_t netbuf, + uint64_t target_time) +{ + struct hdd_adapter *adapter; + struct net_device *net_dev = netbuf->dev; + + if (!net_dev) + return HDD_TSF_OP_FAIL; + + adapter = (struct hdd_adapter *)(netdev_priv(net_dev)); + if (adapter && adapter->magic == WLAN_HDD_ADAPTER_MAGIC && + hdd_get_th_sync_status(adapter)) { + uint64_t tsf64_time = target_time; + uint64_t soc_time = 0;/*ns*/ + int32_t ret = hdd_get_soctime_from_tsf64time(adapter, + tsf64_time, &soc_time); + if (!ret) { + netbuf->tstamp = soc_time; + return HDD_TSF_OP_SUCC; + } + } + + return HDD_TSF_OP_FAIL; +} +#endif + int hdd_start_tsf_sync(struct hdd_adapter *adapter) { enum hdd_tsf_op_result ret; @@ -1819,12 +1906,13 @@ int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf) adapter->cur_target_time = ((uint64_t)ptsf->tsf_high << 32 | ptsf->tsf_low); + adapter->cur_target_global_tsf_time = + ((uint64_t)ptsf->global_tsf_high << 32 | + ptsf->global_tsf_low); tsf_sync_soc_time = ((uint64_t)ptsf->soc_timer_high << 32 | ptsf->soc_timer_low); - adapter->cur_tsf_sync_soc_time = qdf_log_timestamp_to_usecs(tsf_sync_soc_time) * NSEC_PER_USEC; - complete(&tsf_sync_get_completion_evt); hdd_update_tsf(adapter, adapter->cur_target_time); hdd_info("Vdev=%u, tsf_low=%u, tsf_high=%u ptsf->soc_timer_low=%u ptsf->soc_timer_high=%u", diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 680027526bc1..8ad81d99552a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -4525,6 +4525,8 @@ struct sir_sme_ext_cng_chan_ind { * @tsf_high: high 32bits of tsf * @soc_timer_low: low 32bits of synced SOC timer value * @soc_timer_high: high 32bits of synced SOC timer value + * @global_tsf_low: low 32bits of tsf64 + * @global_tsf_high: high 32bits of tsf64 * * driver use this struct to store the tsf info */ @@ -4534,6 +4536,8 @@ struct stsf { uint32_t tsf_high; uint32_t soc_timer_low; uint32_t soc_timer_high; + uint32_t global_tsf_low; + uint32_t global_tsf_high; }; #define SIR_BCN_FLT_MAX_ELEMS_IE_LIST 8