qcacld-3.0: Add changes to read tsf via scratch register

Read TSF via scratch registers instead of WMI commands. Added framework
to initialize/de-initialize the deferred context for register reads.

Change-Id: Id5309bf3117f04fb3d321ddd3af50e4bdf223561
CRs-Fixed: 3287534
This commit is contained in:
Amit Mehta
2022-09-08 03:40:19 -07:00
committed by Madan Koyyalamudi
parent 5d10c60628
commit 8d830534f3
4 changed files with 285 additions and 60 deletions

View File

@@ -1155,6 +1155,14 @@ struct hdd_adapter {
uint64_t cur_target_global_tsf_time; uint64_t cur_target_global_tsf_time;
uint64_t last_target_global_tsf_time; uint64_t last_target_global_tsf_time;
qdf_mc_timer_t host_capture_req_timer; qdf_mc_timer_t host_capture_req_timer;
#ifdef QCA_GET_TSF_VIA_REG
/* TSF id as obtained from FW report */
int tsf_id;
/* mac_id as obtained from FW report */
int tsf_mac_id;
/* flag indicating whether tsf details are valid */
qdf_atomic_t tsf_details_valid;
#endif
#ifdef WLAN_FEATURE_TSF_PLUS #ifdef WLAN_FEATURE_TSF_PLUS
/* spin lock for read/write timestamps */ /* spin lock for read/write timestamps */
qdf_spinlock_t host_target_sync_lock; qdf_spinlock_t host_target_sync_lock;

View File

@@ -45,7 +45,7 @@
static int tsf_gpio_irq_num = -1; static int tsf_gpio_irq_num = -1;
#endif #endif
#endif #endif
static struct completion tsf_sync_get_completion_evt; static qdf_event_t tsf_sync_get_completion_evt;
#define WLAN_TSF_SYNC_GET_TIMEOUT 2000 #define WLAN_TSF_SYNC_GET_TIMEOUT 2000
#define WLAN_HDD_CAPTURE_TSF_REQ_TIMEOUT_MS 500 #define WLAN_HDD_CAPTURE_TSF_REQ_TIMEOUT_MS 500
#define WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS 100 #define WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS 100
@@ -68,6 +68,29 @@ hdd_update_timestamp(struct hdd_adapter *adapter,
#endif #endif
#endif #endif
#ifdef QCA_GET_TSF_VIA_REG
static inline void hdd_update_tsf(struct hdd_adapter *adapter, uint64_t tsf);
/**
* struct hdd_tsf_report - TSF report filled in by DP layer
* @vdev_id: vdev id for which TSF values is to be read
* @tsf_id: tsf if used to read TSF report
* @mac_id: lmac_id for which TSF values are read
* @tsf: 64 bit tsf value as read from scratch registers
* @tsf_sync_soc_time: host qtimer time when scratch registers are read
*
* The structure is used by the upper layers to pass vdev_id, tsf_id and mac_id
* information to DP layer and get tsf time and host time when TSF was read.
*/
struct hdd_tsf_report {
uint32_t vdev_id;
uint32_t tsf_id;
uint32_t mac_id;
uint64_t tsf;
uint64_t tsf_sync_soc_time;
};
#endif
/** /**
* enum hdd_tsf_op_result - result of tsf operation * enum hdd_tsf_op_result - result of tsf operation
* *
@@ -488,10 +511,205 @@ static bool hdd_tsf_cap_sync_send(struct hdd_adapter *adapter)
} }
#endif #endif
#ifdef WLAN_FEATURE_TSF_TIMER_SYNC
/**
* hdd_convert_qtime_to_us() - convert qtime to us
* @time: QTIMER ticks for adrastea and us for Lithium
*
* This function converts qtime to us.
*
* Return: Time in microseconds
*/
static inline uint64_t
hdd_convert_qtime_to_us(uint64_t time)
{
return time;
}
#else
static inline uint64_t
hdd_convert_qtime_to_us(uint64_t time)
{
return qdf_log_timestamp_to_usecs(time);
}
#endif
/**
* hdd_capture_tsf_internal_via_wmi() - convert qtime to us
* @adapter: pointer to adapter
* @buf: in case of failure update with fail
* @len: buffer length
*
* Return: result of tsf operation
*/
static enum hdd_tsf_op_result
hdd_capture_tsf_internal_via_wmi(struct hdd_adapter *adapter, uint32_t *buf,
int len)
{
int ret;
struct hdd_context *hddctx = adapter->hdd_ctx;
ret = wma_cli_set_command((int)adapter->vdev_id,
(int)GEN_PARAM_CAPTURE_TSF,
adapter->vdev_id, GEN_CMD);
if (ret != QDF_STATUS_SUCCESS) {
hdd_err("cap tsf fail");
buf[0] = TSF_CAPTURE_FAIL;
hddctx->cap_tsf_context = NULL;
qdf_atomic_set(&hddctx->cap_tsf_flag, 0);
qdf_mc_timer_stop(&adapter->host_capture_req_timer);
qdf_mc_timer_destroy(&adapter->host_capture_req_timer);
}
return HDD_TSF_OP_SUCC;
}
#ifndef QCA_GET_TSF_VIA_REG
static inline
enum hdd_tsf_op_result _hdd_capture_tsf_internal(struct hdd_adapter *adapter,
uint32_t *buf, int len)
{
return hdd_capture_tsf_internal_via_wmi(adapter, buf, len);
}
static inline void wlan_hdd_tsf_reg_update_details(struct hdd_adapter *adapter,
struct stsf *ptsf)
{
}
#else
static inline int hdd_tsf_reg_is_details_valid(struct hdd_adapter *adapter)
{
return qdf_atomic_read(&adapter->tsf_details_valid);
}
static inline void
wlan_hdd_tsf_reg_update_details(struct hdd_adapter *adapter, struct stsf *ptsf)
{
if (!qdf_atomic_read(&adapter->tsf_details_valid)) {
if (ptsf->tsf_id_valid) {
adapter->tsf_id = ptsf->tsf_id;
adapter->tsf_mac_id = ptsf->mac_id;
qdf_atomic_set(&adapter->tsf_details_valid, 1);
}
}
hdd_info("tsf_id %u tsf_id_valid %u mac_id %u mac_id_valid %u",
ptsf->tsf_id, ptsf->tsf_id_valid, ptsf->mac_id,
ptsf->mac_id_valid);
}
static inline
QDF_STATUS wlan_hdd_tsf_reg_get(struct hdd_adapter *adapter,
struct hdd_tsf_report *tsf_report)
{
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
uint64_t tsf_time = 0;
uint64_t tsf_sync_soc_time = 0;
if (qdf_unlikely(!soc))
return QDF_STATUS_E_INVAL;
cdp_get_tsf_time(soc, tsf_report->tsf_id, tsf_report->mac_id,
&tsf_time, &tsf_sync_soc_time);
/* fill in the report */
tsf_report->tsf = tsf_time;
tsf_report->tsf_sync_soc_time = tsf_sync_soc_time;
return QDF_STATUS_SUCCESS;
}
/**
* wlan_hdd_tsf_reg_process_report() - Process tsf report
* @adapter: pointer to the adapter
* @tsf_report: pointer to tsf report
*
* This function process the tsf report received and update tsf
* value received via scratch register read to adapter
*
* Return: 0 for success or 1 in case of failure
*/
static enum hdd_tsf_op_result
wlan_hdd_tsf_reg_process_report(struct hdd_adapter *adapter,
struct hdd_tsf_report *tsf_report)
{
QDF_STATUS status;
QDF_TIMER_STATE capture_req_timer_status;
qdf_mc_timer_t *capture_timer;
if (!tsf_report->tsf && !tsf_report->tsf_sync_soc_time) {
hdd_err("Invalid TSF report");
return HDD_TSF_OP_FAIL;
}
if (!hdd_tsf_is_initialized(adapter)) {
hdd_err("tsf is not init, ignore tsf event");
return HDD_TSF_OP_FAIL;
}
hdd_info("device_mode is %d", adapter->device_mode);
capture_timer = &adapter->host_capture_req_timer;
capture_req_timer_status =
qdf_mc_timer_get_current_state(capture_timer);
if (capture_req_timer_status == QDF_TIMER_STATE_UNUSED) {
hdd_warn("invalid timer status");
return HDD_TSF_OP_FAIL;
}
qdf_mc_timer_stop(capture_timer);
status = qdf_mc_timer_destroy(capture_timer);
if (status != QDF_STATUS_SUCCESS)
hdd_warn("destroy cap req timer fail, ret: %d", status);
adapter->cur_target_time = tsf_report->tsf;
adapter->cur_tsf_sync_soc_time = tsf_report->tsf_sync_soc_time *
NSEC_PER_USEC;
qdf_event_set(&tsf_sync_get_completion_evt);
hdd_update_tsf(adapter, adapter->cur_target_time);
hdd_info("vdev id=%u, tsf=%llu", adapter->vdev_id, tsf_report->tsf);
return HDD_TSF_OP_SUCC;
}
static enum hdd_tsf_op_result
hdd_capture_tsf_internal_via_reg(struct hdd_adapter *adapter, uint32_t *buf,
int len)
{
struct hdd_tsf_report tsf_report;
if (!hdd_tsf_reg_is_details_valid(adapter)) {
hdd_warn("TSF reg details are not valid!");
return HDD_TSF_OP_FAIL;
}
qdf_mem_zero(&tsf_report, sizeof(tsf_report));
tsf_report.vdev_id = adapter->vdev_id;
tsf_report.tsf_id = adapter->tsf_id;
tsf_report.mac_id = adapter->tsf_mac_id;
if (wlan_hdd_tsf_reg_get(adapter, &tsf_report)) {
hdd_warn("Unable to get tsf report");
return HDD_TSF_OP_FAIL;
}
return wlan_hdd_tsf_reg_process_report(adapter, &tsf_report);
}
static inline
enum hdd_tsf_op_result _hdd_capture_tsf_internal(struct hdd_adapter *adapter,
uint32_t *buf, int len)
{
if (!qdf_atomic_read(&adapter->tsf_details_valid))
return hdd_capture_tsf_internal_via_wmi(adapter, buf, len);
else
return hdd_capture_tsf_internal_via_reg(adapter, buf, len);
}
#endif /* QCA_GET_TSF_VIA_REG */
static enum hdd_tsf_op_result hdd_capture_tsf_internal( static enum hdd_tsf_op_result hdd_capture_tsf_internal(
struct hdd_adapter *adapter, uint32_t *buf, int len) struct hdd_adapter *adapter, uint32_t *buf, int len)
{ {
int ret; enum hdd_tsf_op_result ret;
struct hdd_context *hddctx; struct hdd_context *hddctx;
qdf_mc_timer_t *cap_timer; qdf_mc_timer_t *cap_timer;
@@ -509,6 +727,11 @@ static enum hdd_tsf_op_result hdd_capture_tsf_internal(
return HDD_TSF_OP_FAIL; return HDD_TSF_OP_FAIL;
} }
if (wlan_hdd_validate_context(hddctx)) {
hdd_err("hdd context validation failed");
return HDD_TSF_OP_FAIL;
}
if (!hdd_tsf_is_initialized(adapter)) { if (!hdd_tsf_is_initialized(adapter)) {
buf[0] = TSF_NOT_READY; buf[0] = TSF_NOT_READY;
return HDD_TSF_OP_SUCC; return HDD_TSF_OP_SUCC;
@@ -538,26 +761,14 @@ static enum hdd_tsf_op_result hdd_capture_tsf_internal(
adapter->cur_target_time = 0; adapter->cur_target_time = 0;
buf[0] = TSF_RETURN; buf[0] = TSF_RETURN;
init_completion(&tsf_sync_get_completion_evt);
if (hdd_tsf_cap_sync_send(adapter)) if (hdd_tsf_cap_sync_send(adapter))
return HDD_TSF_OP_SUCC; return HDD_TSF_OP_SUCC;
ret = wma_cli_set_command((int)adapter->vdev_id, ret = _hdd_capture_tsf_internal(adapter, buf, len);
(int)GEN_PARAM_CAPTURE_TSF,
adapter->vdev_id, GEN_CMD);
if (QDF_STATUS_SUCCESS != ret) {
hdd_err("cap tsf fail");
buf[0] = TSF_CAPTURE_FAIL;
hddctx->cap_tsf_context = NULL;
qdf_atomic_set(&hddctx->cap_tsf_flag, 0);
qdf_mc_timer_stop(&adapter->host_capture_req_timer);
qdf_mc_timer_destroy(&adapter->host_capture_req_timer);
return HDD_TSF_OP_SUCC;
}
hdd_info("-ioctl return cap tsf cmd"); hdd_info("-ioctl return cap tsf cmd");
return HDD_TSF_OP_SUCC;
return ret;
} }
static enum hdd_tsf_op_result hdd_indicate_tsf_internal( static enum hdd_tsf_op_result hdd_indicate_tsf_internal(
@@ -2425,29 +2636,6 @@ static void wlan_hdd_phc_deinit(struct hdd_context *hdd_ctx)
} }
#endif /* WLAN_FEATURE_TSF_PTP */ #endif /* WLAN_FEATURE_TSF_PTP */
#ifdef WLAN_FEATURE_TSF_TIMER_SYNC
/**
* hdd_convert_qtime_to_us() - convert qtime to us
* @time: QTIMER ticks for adrastea and us for Lithium
*
* This function converts qtime to us.
*
* Return: Time in microseconds
*/
static inline uint64_t
hdd_convert_qtime_to_us(uint64_t time)
{
return time;
}
#else
static inline uint64_t
hdd_convert_qtime_to_us(uint64_t time)
{
return qdf_log_timestamp_to_usecs(time);
}
#endif
#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY #ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
static int hdd_set_tsf_auto_report(struct hdd_adapter *adapter, bool ena) static int hdd_set_tsf_auto_report(struct hdd_adapter *adapter, bool ena)
{ {
@@ -2635,7 +2823,10 @@ int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
ptsf->soc_timer_low); ptsf->soc_timer_low);
adapter->cur_tsf_sync_soc_time = adapter->cur_tsf_sync_soc_time =
hdd_convert_qtime_to_us(tsf_sync_soc_time) * NSEC_PER_USEC; hdd_convert_qtime_to_us(tsf_sync_soc_time) * NSEC_PER_USEC;
complete(&tsf_sync_get_completion_evt);
wlan_hdd_tsf_reg_update_details(adapter, ptsf);
qdf_event_set(&tsf_sync_get_completion_evt);
hdd_update_tsf(adapter, adapter->cur_target_time); 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", hdd_info("Vdev=%u, tsf_low=%u, tsf_high=%u ptsf->soc_timer_low=%u ptsf->soc_timer_high=%u",
ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high, ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high,
@@ -2671,7 +2862,8 @@ static int __wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
struct hdd_tsf_op_response tsf_op_resp; struct hdd_tsf_op_response tsf_op_resp;
struct nlattr *attr; struct nlattr *attr;
enum hdd_tsf_get_state value; enum hdd_tsf_get_state value;
int status, ret; int status;
QDF_STATUS ret;
struct sk_buff *reply_skb; struct sk_buff *reply_skb;
uint32_t tsf_cmd; uint32_t tsf_cmd;
@@ -2705,6 +2897,9 @@ static int __wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
status = hdd_handle_tsf_auto_report(adapter, tsf_cmd); status = hdd_handle_tsf_auto_report(adapter, tsf_cmd);
if (status != -EINVAL) if (status != -EINVAL)
goto end; goto end;
ret = qdf_event_reset(&tsf_sync_get_completion_evt);
if (QDF_IS_STATUS_ERROR(ret))
hdd_warn("failed to reset tsf_sync_get_completion_evt");
if (tsf_cmd == QCA_TSF_CAPTURE || tsf_cmd == QCA_TSF_SYNC_GET) { if (tsf_cmd == QCA_TSF_CAPTURE || tsf_cmd == QCA_TSF_SYNC_GET) {
hdd_capture_tsf(adapter, &value, 1); hdd_capture_tsf(adapter, &value, 1);
@@ -2735,9 +2930,9 @@ static int __wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
goto end; goto end;
if (tsf_cmd == QCA_TSF_SYNC_GET) { if (tsf_cmd == QCA_TSF_SYNC_GET) {
ret = wait_for_completion_timeout(&tsf_sync_get_completion_evt, ret = qdf_wait_single_event(&tsf_sync_get_completion_evt,
msecs_to_jiffies(WLAN_TSF_SYNC_GET_TIMEOUT)); WLAN_TSF_SYNC_GET_TIMEOUT);
if (ret == 0) { if (QDF_IS_STATUS_ERROR(ret)) {
status = -ETIMEDOUT; status = -ETIMEDOUT;
goto end; goto end;
} }
@@ -2829,6 +3024,12 @@ void wlan_hdd_tsf_init(struct hdd_context *hdd_ctx)
if (hdd_tsf_is_ptp_enabled(hdd_ctx)) if (hdd_tsf_is_ptp_enabled(hdd_ctx))
wlan_hdd_phc_init(hdd_ctx); wlan_hdd_phc_init(hdd_ctx);
status = qdf_event_create(&tsf_sync_get_completion_evt);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_debug("failed to create tsf_sync_get_completion_evt");
goto fail;
}
return; return;
fail: fail:
@@ -2837,12 +3038,18 @@ fail:
void wlan_hdd_tsf_deinit(struct hdd_context *hdd_ctx) void wlan_hdd_tsf_deinit(struct hdd_context *hdd_ctx)
{ {
QDF_STATUS status;
if (!hdd_ctx) if (!hdd_ctx)
return; return;
if (!qdf_atomic_read(&hdd_ctx->tsf_ready_flag)) if (!qdf_atomic_read(&hdd_ctx->tsf_ready_flag))
return; return;
status = qdf_event_destroy(&tsf_sync_get_completion_evt);
if (QDF_IS_STATUS_ERROR(status))
hdd_debug("failed to destroy tsf_sync_get_completion_evt");
if (hdd_tsf_is_ptp_enabled(hdd_ctx)) if (hdd_tsf_is_ptp_enabled(hdd_ctx))
wlan_hdd_phc_deinit(hdd_ctx); wlan_hdd_phc_deinit(hdd_ctx);
wlan_hdd_tsf_plus_deinit(hdd_ctx); wlan_hdd_tsf_plus_deinit(hdd_ctx);

View File

@@ -3882,8 +3882,10 @@ struct sir_sme_ext_cng_chan_ind {
* @global_tsf_high: high 32bits of tsf64 * @global_tsf_high: high 32bits of tsf64
* @mac_id: MAC identifier * @mac_id: MAC identifier
* @mac_id_valid: Indicate if mac_id is valid or not * @mac_id_valid: Indicate if mac_id is valid or not
* @tsf_id: TSF-ID corresponding to the TSF value
* @tsf_id_valid: flag indicating whether TSD-ID is valid
* *
* driver use this struct to store the tsf info * Driver uses this structure to store the tsf information.
*/ */
struct stsf { struct stsf {
uint32_t vdev_id; uint32_t vdev_id;
@@ -3893,10 +3895,10 @@ struct stsf {
uint32_t soc_timer_high; uint32_t soc_timer_high;
uint32_t global_tsf_low; uint32_t global_tsf_low;
uint32_t global_tsf_high; uint32_t global_tsf_high;
#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
uint32_t mac_id; uint32_t mac_id;
uint32_t mac_id_valid; uint32_t mac_id_valid;
#endif uint32_t tsf_id;
uint32_t tsf_id_valid;
}; };
#define SIR_BCN_FLT_MAX_ELEMS_IE_LIST 8 #define SIR_BCN_FLT_MAX_ELEMS_IE_LIST 8

View File

@@ -315,22 +315,29 @@ end:
#ifdef WLAN_FEATURE_TSF #ifdef WLAN_FEATURE_TSF
#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY #if defined(WLAN_FEATURE_TSF_UPLINK_DELAY) || defined(QCA_GET_TSF_VIA_REG)
static void wma_vdev_tsf_set_mac_id(struct stsf *ptsf, uint32_t mac_id, static inline void
uint32_t mac_id_valid) wma_vdev_tsf_set_mac_id_tsf_id(struct stsf *ptsf, uint32_t mac_id,
uint32_t mac_id_valid, uint32_t tsf_id,
uint32_t tsf_id_valid)
{ {
ptsf->mac_id = mac_id; ptsf->mac_id = mac_id;
ptsf->mac_id_valid = mac_id_valid; ptsf->mac_id_valid = mac_id_valid;
ptsf->tsf_id = tsf_id;
ptsf->tsf_id_valid = tsf_id_valid;
wma_nofl_debug("mac_id %d mac_id_valid %d", ptsf->mac_id, wma_nofl_debug("mac_id %d mac_id_valid %d tsf_id %d tsf_id_valid %d",
ptsf->mac_id_valid); ptsf->mac_id, ptsf->mac_id_valid, ptsf->tsf_id,
ptsf->tsf_id_valid);
} }
#else /* !WLAN_FEATURE_TSF_UPLINK_DELAY */ #else /* !WLAN_FEATURE_TSF_UPLINK_DELAY || !QCA_GET_TSF_VIA_REG*/
static inline void wma_vdev_tsf_set_mac_id(struct stsf *ptsf, uint32_t mac_id, static inline void
uint32_t mac_id_valid) wma_vdev_tsf_set_mac_id_tsf_id(struct stsf *ptsf, uint32_t mac_id,
uint32_t mac_id_valid, uint32_t tsf_id,
uint32_t tsf_id_valid)
{ {
} }
#endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */ #endif /* WLAN_FEATURE_TSF_UPLINK_DELAY || QCA_GET_TSF_VIA_REG*/
/** /**
* wma_vdev_tsf_handler() - handle tsf event indicated by FW * wma_vdev_tsf_handler() - handle tsf event indicated by FW
@@ -372,9 +379,10 @@ int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
ptsf->global_tsf_low, ptsf->global_tsf_high, ptsf->global_tsf_low, ptsf->global_tsf_high,
ptsf->soc_timer_low, ptsf->soc_timer_high); ptsf->soc_timer_low, ptsf->soc_timer_high);
wma_vdev_tsf_set_mac_id(ptsf, tsf_event->mac_id, wma_vdev_tsf_set_mac_id_tsf_id(ptsf, tsf_event->mac_id,
tsf_event->mac_id_valid); tsf_event->mac_id_valid,
tsf_event->tsf_id,
tsf_event->tsf_id_valid);
tsf_msg.type = eWNI_SME_TSF_EVENT; tsf_msg.type = eWNI_SME_TSF_EVENT;
tsf_msg.bodyptr = ptsf; tsf_msg.bodyptr = ptsf;
tsf_msg.bodyval = 0; tsf_msg.bodyval = 0;