summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbings <bings@codeaurora.org>2018-12-19 10:18:27 +0800
committerbings <bings@codeaurora.org>2018-12-25 10:24:16 +0800
commite9be2a2cf3079c4147baaacecd7965a8eb062117 (patch)
tree1689da48be78e53d81c051f6a20e6b4737d5d684
parent76cf07f7b64eba74d0c1d74351a14c3ef0512664 (diff)
qcacld-2.0: Add gettime of PTP for NON-QC platform
Implement NON-QC platform TSF and TSF PLUS. Implement gettime of PTP. Implement TSF PLUS for SAP/GO. Change-Id: Id4f41a94256a8f035ae408c168c246569185c534 CRs-Fixed: 2356609
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg.h10
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h8
-rw-r--r--CORE/HDD/inc/wlan_hdd_tsf.h17
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c7
-rw-r--r--CORE/HDD/src/wlan_hdd_hostapd.c11
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c7
-rw-r--r--CORE/HDD/src/wlan_hdd_tsf.c318
-rw-r--r--Kbuild9
8 files changed, 370 insertions, 17 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index e9961b2decaa..98f2f2be228a 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -4153,6 +4153,13 @@ FG_BTC_BT_INTERVAL_PAGE_P2P_STA_DEFAULT
#define TSF_GPIO_PIN_INVALID (255)
#define CFG_SET_TSF_GPIO_PIN_DEFAULT (TSF_GPIO_PIN_INVALID)
+#ifdef WLAN_FEATURE_TSF
+/* GPIO pin to toogle when capture tsf in host side */
+#define CFG_SET_TSF_GPIO_PIN_HOST_NAME "gtsf_gpio_pin_host"
+#define CFG_SET_TSF_GPIO_PIN_HOST_MIN (0)
+#define CFG_SET_TSF_GPIO_PIN_HOST_MAX (254)
+#define CFG_SET_TSF_GPIO_PIN_HOST_DEFAULT (45)
+
#ifdef WLAN_FEATURE_TSF_PLUS
/* PTP options */
#define CFG_SET_TSF_PTP_OPT_NAME "gtsf_ptp_options"
@@ -4164,6 +4171,7 @@ FG_BTC_BT_INTERVAL_PAGE_P2P_STA_DEFAULT
#define CFG_SET_TSF_DBG_FS (0x8)
#define CFG_SET_TSF_PTP_OPT_DEFAULT (0xf)
#endif
+#endif
#define CFG_MULTICAST_HOST_FW_MSGS "gMulticastHostFwMsgs"
#define CFG_MULTICAST_HOST_FW_MSGS_MIN (0)
@@ -6257,7 +6265,7 @@ struct hdd_config {
uint8_t inform_bss_rssi_raw;
#ifdef WLAN_FEATURE_TSF
uint32_t tsf_gpio_pin;
-
+ uint32_t tsf_gpio_pin_host;
#ifdef WLAN_FEATURE_TSF_PLUS
uint8_t tsf_ptp_options;
#endif /* WLAN_FEATURE_TSF_PLUS */
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index de6e6cd77ff1..15b1975fecaa 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -51,6 +51,10 @@
#include <wlan_hdd_wmm.h>
#include <wlan_hdd_cfg.h>
#include <linux/spinlock.h>
+#ifdef WLAN_FEATURE_TSF_PTP
+#include <linux/ptp_classify.h>
+#include <linux/ptp_clock_kernel.h>
+#endif
#include <wlan_hdd_ftm.h>
#ifdef FEATURE_WLAN_TDLS
#include "wlan_hdd_tdls.h"
@@ -2138,6 +2142,10 @@ struct hdd_context_s
/* the context that is capturing tsf */
hdd_adapter_t *cap_tsf_context;
#endif
+#ifdef WLAN_FEATURE_TSF_PTP
+ struct ptp_clock_info ptp_cinfo;
+ struct ptp_clock *ptp_clock;
+#endif
/* flag to show whether moniotr mode is enabled */
bool is_mon_enable;
v_MACADDR_t hw_macaddr;
diff --git a/CORE/HDD/inc/wlan_hdd_tsf.h b/CORE/HDD/inc/wlan_hdd_tsf.h
index 6cabf3b90245..a1a329b87fc4 100644
--- a/CORE/HDD/inc/wlan_hdd_tsf.h
+++ b/CORE/HDD/inc/wlan_hdd_tsf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015,2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015,2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -91,6 +91,15 @@ int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len);
* Return: Describe the execute result of this routine
*/
int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len);
+
+/**
+ * wlan_get_ts_info() - return ts info to uplayer
+ * @dev: pointer to net_device
+ * @info: pointer to ethtool_ts_info
+ *
+ * Return: Describe the execute result of this routine
+ */
+int wlan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info);
#else
static inline void
wlan_hdd_tsf_init(hdd_context_t *hdd_ctx)
@@ -112,6 +121,12 @@ hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
{
return -ENOTSUPP;
}
+
+static inline int
+wlan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+{
+ return -ENOTSUPP;
+}
#endif
#if defined(WLAN_FEATURE_TSF_PLUS) && defined(WLAN_FEATURE_TSF)
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index ec651ed6804a..6fc2a9472f0f 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -4564,6 +4564,13 @@ REG_TABLE_ENTRY g_registry_table[] =
CFG_INFORM_BSS_RSSI_RAW_MIN,
CFG_INFORM_BSS_RSSI_RAW_MAX),
#ifdef WLAN_FEATURE_TSF
+ REG_VARIABLE(CFG_SET_TSF_GPIO_PIN_HOST_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, tsf_gpio_pin_host,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_SET_TSF_GPIO_PIN_HOST_DEFAULT,
+ CFG_SET_TSF_GPIO_PIN_HOST_MIN,
+ CFG_SET_TSF_GPIO_PIN_HOST_MAX),
+
REG_VARIABLE(CFG_SET_TSF_GPIO_PIN_NAME, WLAN_PARAM_Integer,
hdd_config_t, tsf_gpio_pin,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 59c720332334..eba0907fd06a 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -60,6 +60,7 @@
#include <vos_api.h>
#include <vos_sched.h>
#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
#include <wlan_hdd_includes.h>
#include <qc_sap_ioctl.h>
#include <wlan_hdd_hostapd.h>
@@ -2326,6 +2327,7 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa
pHddApCtx->operatingChannel);
pHostapdState->bssState = BSS_START;
+ hdd_start_tsf_sync(pHostapdAdapter);
/* Set default key index */
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -3146,7 +3148,7 @@ stopbss :
/* Change the BSS state now since, as we are shutting things down,
* we don't want interfaces to become re-enabled */
pHostapdState->bssState = BSS_STOP;
-
+ hdd_stop_tsf_sync(pHostapdAdapter);
if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff)
{
if (VOS_TIMER_STATE_RUNNING == pHddApCtx->hdd_ap_inactivity_timer.state)
@@ -7692,6 +7694,10 @@ const struct iw_handler_def hostapd_handler_def = {
.get_wireless_stats = NULL,
};
+static const struct ethtool_ops wlan_hostapd_ethtool_ops = {
+ .get_ts_info = wlan_get_ts_info,
+};
+
struct net_device_ops net_ops_struct = {
.ndo_open = hdd_hostapd_open,
.ndo_stop = hdd_hostapd_stop,
@@ -7712,7 +7718,8 @@ static int hdd_set_hostapd(hdd_adapter_t *pAdapter)
void hdd_set_ap_ops( struct net_device *pWlanHostapdDev )
{
- pWlanHostapdDev->netdev_ops = &net_ops_struct;
+ pWlanHostapdDev->netdev_ops = &net_ops_struct;
+ pWlanHostapdDev->ethtool_ops = &wlan_hostapd_ethtool_ops;
}
VOS_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter, bool reinit)
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index c7dae7df518a..c012af8e15a3 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -93,6 +93,7 @@
#include <linux/ctype.h>
#include <linux/compat.h>
#include <linux/pm_qos.h>
+#include <linux/ethtool.h>
#ifdef MSM_PLATFORM
#ifdef CONFIG_CNSS
#include <soc/qcom/subsystem_restart.h>
@@ -10851,6 +10852,10 @@ static v_U16_t hdd_select_queue(struct net_device *dev,
return hdd_wmm_select_queue(dev, skb);
}
+static const struct ethtool_ops wlan_ethtool_ops = {
+ .get_ts_info = wlan_get_ts_info,
+};
+
static struct net_device_ops wlan_drv_ops = {
.ndo_open = hdd_open,
.ndo_stop = hdd_stop,
@@ -10889,6 +10894,7 @@ void hdd_set_station_ops( struct net_device *pWlanDev )
pWlanDev->netdev_ops = &wlan_mon_drv_ops;
else
pWlanDev->netdev_ops = &wlan_drv_ops;
+ pWlanDev->ethtool_ops = &wlan_ethtool_ops;
}
void hdd_set_monitor_ops(struct net_device *pwlan_dev)
@@ -13308,7 +13314,6 @@ void hdd_connect_result(struct net_device *dev,
{
hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
struct cfg80211_bss *bss = NULL;
-
if (WLAN_STATUS_SUCCESS == status) {
struct ieee80211_channel *chan;
int freq;
diff --git a/CORE/HDD/src/wlan_hdd_tsf.c b/CORE/HDD/src/wlan_hdd_tsf.c
index 31d902fbb422..6ad7f14af2c6 100644
--- a/CORE/HDD/src/wlan_hdd_tsf.c
+++ b/CORE/HDD/src/wlan_hdd_tsf.c
@@ -33,7 +33,10 @@
#include "wlan_hdd_tsf.h"
#include "wma_api.h"
#include <linux/errqueue.h>
-
+#if defined(CONFIG_NON_QC_PLATFORM)
+#include <linux/gpio.h>
+int irq_tsf = -1;
+#endif
/**
* enum hdd_tsf_op_result - result of tsf operation
*
@@ -207,7 +210,6 @@ static enum hdd_tsf_op_result hdd_indicate_tsf_internal(
{
int ret;
hdd_context_t *hddctx;
-
if (adapter == NULL || buf == NULL) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("invalid pointer"));
@@ -280,13 +282,21 @@ static enum hdd_tsf_op_result hdd_indicate_tsf_internal(
* to distinguish 32-bit overflow case, this inverval should:
* equal or less than (1/2 * OVERFLOW_INDICATOR32 us)
*/
+#if defined(CONFIG_NON_QC_PLATFORM)
+#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 2
+#else
#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 10
+#endif
#define WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS 100
#define OVERFLOW_INDICATOR32 (((int64_t)0x1) << 32)
#define MAX_UINT64 ((uint64_t)0xffffffffffffffff)
#define MASK_UINT32 0xffffffff
#define CAP_TSF_TIMER_FIX_SEC 1
+#if defined(CONFIG_NON_QC_PLATFORM)
+#define WLAN_HDD_CAPTURE_TSF_RESYNC_INTERVAL 1
+#else
#define WLAN_HDD_CAPTURE_TSF_RESYNC_INTERVAL 9
+#endif
/**
* TS_STATUS - timestamp status
@@ -414,9 +424,13 @@ enum hdd_ts_status hdd_check_timestamp_status(
/* the deviation should be smaller than a threshold */
if (delta_ns > MAX_ALLOWED_DEVIATION_NS) {
hddLog(VOS_TRACE_LEVEL_ERROR,
- FL("Invalid timestamps - delta: %llu ns"), delta_ns);
+ FL("Invalid timestamps - delta: %llu ns"), delta_ns);
return HDD_TS_STATUS_INVALID;
+ } else {
+ hddLog(VOS_TRACE_LEVEL_DEBUG,
+ FL("valid timestamps - delta: %llu ns"), delta_ns);
}
+
return HDD_TS_STATUS_READY;
}
@@ -641,10 +655,12 @@ static ssize_t __hdd_wlan_tsf_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
hdd_station_ctx_t *hdd_sta_ctx;
+ hdd_ap_ctx_t *hdd_ap_ctx;
hdd_adapter_t *adapter;
hdd_context_t *hdd_ctx;
ssize_t size;
uint64_t host_time, target_time;
+ uint8_t *bssid;
struct net_device *net_dev = container_of(dev, struct net_device, dev);
@@ -656,22 +672,32 @@ static ssize_t __hdd_wlan_tsf_show(struct device *dev,
return scnprintf(buf, PAGE_SIZE,
"TSF sync is not initialized\n");
- hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
- if (eConnectionState_Associated != hdd_sta_ctx->conn_info.connState)
- return scnprintf(buf, PAGE_SIZE, "NOT connected\n");
-
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
if (!hdd_ctx)
return scnprintf(buf, PAGE_SIZE, "Invalid HDD context\n");
+ if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
+ adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
+ hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (eConnectionState_Associated !=
+ hdd_sta_ctx->conn_info.connState)
+ return scnprintf(buf, PAGE_SIZE, "NOT connected\n");
+ bssid = hdd_sta_ctx->conn_info.bssId;
+ } else if (adapter->device_mode == WLAN_HDD_SOFTAP ||
+ adapter->device_mode == WLAN_HDD_P2P_GO) {
+ hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
+ bssid = hdd_ap_ctx->sapConfig.self_macaddr.bytes;
+ } else {
+ return scnprintf(buf, PAGE_SIZE, "Invalid interface\n");
+ }
+
host_time = hdd_get_monotonic_host_time(hdd_ctx);
if (hdd_get_targettime_from_hosttime(adapter, host_time,
&target_time))
size = scnprintf(buf, PAGE_SIZE, "Invalid timestamp\n");
else
size = scnprintf(buf, PAGE_SIZE, "%s%llu %llu %pM\n",
- buf, target_time, host_time,
- hdd_sta_ctx->conn_info.bssId);
+ buf, target_time, host_time, bssid);
return size;
}
@@ -711,6 +737,10 @@ static irqreturn_t hdd_tsf_captured_irq_handler(int irq, void *arg)
if (!arg)
return IRQ_NONE;
+#if defined(CONFIG_NON_QC_PLATFORM)
+ if (irq != irq_tsf)
+ return IRQ_NONE;
+#endif
hdd_ctx = (hdd_context_t *)arg;
host_time = hdd_get_monotonic_host_time(hdd_ctx);
@@ -1046,6 +1076,99 @@ static inline int __hdd_indicate_tsf(hdd_adapter_t *adapter,
return 0;
}
+#if defined(CONFIG_NON_QC_PLATFORM)
+/**
+ * wlan_hdd_tsf_plus_init() - tsf plus init
+ * @hdd_ctx: pointer to the hdd_contex.
+ *
+ * Return: Describe the execute result of this routine
+ */
+static inline
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(hdd_context_t *hdd_ctx)
+{
+ int ret;
+
+ if (!HDD_TSF_IS_PTP_ENABLED(hdd_ctx)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("To enable TSF_PLUS, set gtsf_ptp_options in ini"));
+ goto fail;
+ }
+
+ if (hdd_ctx->cfg_ini->tsf_gpio_pin_host == TSF_GPIO_PIN_INVALID) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("gpio host pin is invalid %d"),
+ hdd_ctx->cfg_ini->tsf_gpio_pin_host);
+ goto fail;
+ }
+
+ ret = gpio_request(hdd_ctx->cfg_ini->tsf_gpio_pin_host, "wlan_tsf");
+ if (ret) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("%s: fail to request irq, gpio %d\n"), __func__,
+ hdd_ctx->cfg_ini->tsf_gpio_pin_host);
+ goto fail;
+ }
+
+ ret = gpio_direction_input(hdd_ctx->cfg_ini->tsf_gpio_pin_host);
+ if (ret) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to set gpio dir %d\n"), ret);
+ goto fail_free_gpio;
+ }
+
+ irq_tsf = gpio_to_irq(hdd_ctx->cfg_ini->tsf_gpio_pin_host);
+ if (irq_tsf < 0) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("%s: fail to get irq: %d\n"), __func__, irq_tsf);
+ goto fail_free_gpio;
+ }
+
+ ret = request_irq(irq_tsf, hdd_tsf_captured_irq_handler,
+ IRQF_SHARED | IRQF_TRIGGER_RISING, "wlan_tsf",
+ (void *)hdd_ctx);
+
+ if (ret) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to register irq handler: %d"), ret);
+ goto fail_free_gpio;
+ }
+
+ if (HDD_TSF_IS_TX_SET(hdd_ctx))
+ ol_register_timestamp_callback(hdd_tx_timestamp);
+
+ return HDD_TSF_OP_SUCC;
+
+fail_free_gpio:
+ gpio_free(hdd_ctx->cfg_ini->tsf_gpio_pin_host);
+fail:
+ irq_tsf = -1;
+ return HDD_TSF_OP_FAIL;
+}
+
+/**
+ * wlan_hdd_tsf_plus_deinit() - tsf plus deinit
+ * @hdd_ctx: pointer to the hdd_contex.
+ *
+ * Return: Describe the execute result of this routine
+ */
+static inline
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(hdd_context_t *hdd_ctx)
+{
+ if (!HDD_TSF_IS_PTP_ENABLED(hdd_ctx))
+ return HDD_TSF_OP_SUCC;
+
+ if (HDD_TSF_IS_TX_SET(hdd_ctx))
+ ol_deregister_timestamp_callback();
+
+ if (irq_tsf >= 0) {
+ free_irq(irq_tsf, (void *)hdd_ctx);
+ irq_tsf = -1;
+ gpio_free(hdd_ctx->cfg_ini->tsf_gpio_pin_host);
+ }
+
+ return HDD_TSF_OP_SUCC;
+}
+#else
static inline
enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(hdd_context_t *hdd_ctx)
{
@@ -1056,7 +1179,6 @@ enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(hdd_context_t *hdd_ctx)
FL("To enable TSF_PLUS, set gtsf_ptp_options in ini"));
return HDD_TSF_OP_FAIL;
}
-
ret = cnss_common_register_tsf_captured_handler(
hdd_ctx->parent_dev,
hdd_tsf_captured_irq_handler,
@@ -1066,7 +1188,6 @@ enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(hdd_context_t *hdd_ctx)
FL("Failed to register irq handler: %d"), ret);
return HDD_TSF_OP_FAIL;
}
-
if (HDD_TSF_IS_TX_SET(hdd_ctx))
ol_register_timestamp_callback(hdd_tx_timestamp);
@@ -1096,6 +1217,7 @@ enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(hdd_context_t *hdd_ctx)
return HDD_TSF_OP_SUCC;
}
+#endif
void hdd_tsf_notify_wlan_state_change(hdd_adapter_t *adapter,
eConnectionState old_state,
@@ -1191,6 +1313,176 @@ int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
return __hdd_indicate_tsf(adapter, buf, len);
}
+#ifdef WLAN_FEATURE_TSF_PTP
+int wlan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+
+{
+ hdd_adapter_t *adapter = netdev_priv(dev);
+ hdd_context_t *hdd_ctx;
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ if (!hdd_ctx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid hdd context"));
+ return -EINVAL;
+ }
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ if (hdd_ctx->ptp_clock)
+ info->phc_index = ptp_clock_index(hdd_ctx->ptp_clock);
+ else
+ info->phc_index = -1;
+
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
+/**
+ * wlan_ptp_gettime() - return fw ts info to uplayer
+ * @ptp: pointer to ptp_clock_info.
+ * @ts: pointer to timespec.
+ *
+ * Return: Describe the execute result of this routine
+ */
+static int wlan_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ uint64_t host_time, target_time = 0;
+ VosContextType *pVosContext = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ hdd_adapter_t *adapter = NULL;
+
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL);
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD,
+ pVosContext);
+ if (!pHddCtx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid hdd context"));
+ return -EINVAL;
+ }
+
+ adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
+ if (!adapter) {
+ adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
+ if (!adapter) {
+ adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP);
+ if (!adapter)
+ adapter = hdd_get_adapter(pHddCtx,
+ WLAN_HDD_INFRA_STATION);
+ }
+ }
+
+ host_time = hdd_get_monotonic_host_time(pHddCtx);
+ if (hdd_get_targettime_from_hosttime(adapter, host_time,
+ &target_time)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("get invalid target timestamp"));
+ return -EINVAL;
+ } else {
+ *ts = ns_to_timespec(target_time * NSEC_PER_USEC);
+ }
+
+ return 0;
+}
+
+/**
+ * wlan_hdd_phc_init() - phc init
+ * @hdd_ctx: pointer to the hdd_contex.
+ *
+ * Return: NULL
+ */
+static void wlan_hdd_phc_init(hdd_context_t *hdd_ctx)
+{
+ hdd_ctx->ptp_cinfo.gettime = wlan_ptp_gettime;
+
+ hdd_ctx->ptp_clock = ptp_clock_register(&hdd_ctx->ptp_cinfo,
+ hdd_ctx->parent_dev);
+}
+
+/**
+ * wlan_hdd_phc_deinit() - phc deinit
+ * @hdd_ctx: pointer to the hdd_contex.
+ *
+ * Return: NULL
+ */
+static void wlan_hdd_phc_deinit(hdd_context_t *hdd_ctx)
+{
+ hdd_ctx->ptp_cinfo.gettime = NULL;
+
+ if (hdd_ctx->ptp_clock) {
+ ptp_clock_unregister(hdd_ctx->ptp_clock);
+ hdd_ctx->ptp_clock = NULL;
+ }
+}
+#else
+static int wlan_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+ uint64_t host_time, target_time = 0;
+ VosContextType *pVosContext = NULL;
+ hdd_context_t *pHddCtx = NULL;
+ hdd_adapter_t *adapter = NULL;
+
+ pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL);
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD,
+ pVosContext);
+ if (!pHddCtx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid hdd context"));
+ return -EINVAL;
+ }
+
+ adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
+ if (!adapter) {
+ adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
+ if (!adapter) {
+ adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP);
+ if (!adapter)
+ adapter = hdd_get_adapter(pHddCtx,
+ WLAN_HDD_INFRA_STATION);
+ }
+ }
+
+ host_time = hdd_get_monotonic_host_time(pHddCtx);
+ if (hdd_get_targettime_from_hosttime(adapter, host_time,
+ &target_time)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("get invalid target timestamp"));
+ return -EINVAL;
+ } else {
+ *ts = ns_to_timespec64(target_time * NSEC_PER_USEC);
+ }
+
+ return 0;
+}
+
+static void wlan_hdd_phc_init(hdd_context_t *hdd_ctx)
+{
+ hdd_ctx->ptp_cinfo.gettime64 = wlan_ptp_gettime;
+ hdd_ctx->ptp_clock = ptp_clock_register(&hdd_ctx->ptp_cinfo,
+ hdd_ctx->parent_dev);
+}
+
+static void wlan_hdd_phc_deinit(hdd_context_t *hdd_ctx)
+{
+ hdd_ctx->ptp_cinfo.gettime64 = NULL;
+
+ if (hdd_ctx->ptp_clock) {
+ ptp_clock_unregister(hdd_ctx->ptp_clock);
+ hdd_ctx->ptp_clock = NULL;
+ }
+}
+#endif
+#else
+int wlan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+{
+ return -ENOTSUPP;
+}
+
+static void wlan_hdd_phc_init(hdd_context_t *hdd_ctx)
+{
+}
+
+static void wlan_hdd_phc_deinit(hdd_context_t *hdd_ctx)
+{
+}
+#endif
+
/**
* hdd_get_tsf_cb() - handle tsf callback
*
@@ -1210,7 +1502,6 @@ static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
hdd_adapter_t *adapter;
int status;
VOS_TIMER_STATE capture_req_timer_status;
-
if (pcb_cxt == NULL || ptsf == NULL) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("HDD context is not valid"));
@@ -1298,6 +1589,8 @@ void wlan_hdd_tsf_init(hdd_context_t *hdd_ctx)
if (wlan_hdd_tsf_plus_init(hdd_ctx) != HDD_TSF_OP_SUCC)
goto fail;
+ wlan_hdd_phc_init(hdd_ctx);
+
return;
fail:
@@ -1325,6 +1618,7 @@ void wlan_hdd_tsf_deinit(hdd_context_t *hdd_ctx)
hal_status);
}
+ wlan_hdd_phc_deinit(hdd_ctx);
wlan_hdd_tsf_plus_deinit(hdd_ctx);
vos_status = hdd_get_front_adapter(hdd_ctx, &adapternode_ptr);
diff --git a/Kbuild b/Kbuild
index 883995074e9e..e919a4d887a7 100644
--- a/Kbuild
+++ b/Kbuild
@@ -477,6 +477,11 @@ ifeq ($(CONFIG_QCOM_TDLS),y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tdls.o
endif
+ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
+CONFIG_WLAN_SYNC_TSF_PLUS := y
+CONFIG_WLAN_SYNC_TSF_PTP := y
+endif
+
ifeq ($(CONFIG_WLAN_SYNC_TSF_PLUS), y)
CONFIG_WLAN_SYNC_TSF := y
endif
@@ -1618,6 +1623,10 @@ ifeq ($(CONFIG_WLAN_SYNC_TSF_PLUS), y)
CDEFINES += -DWLAN_FEATURE_TSF_PLUS
endif
+ifeq ($(CONFIG_WLAN_SYNC_TSF_PTP), y)
+CDEFINES += -DWLAN_FEATURE_TSF_PTP
+endif
+
# Enable target dump for non-qualcomm platform
ifeq ($(CONFIG_NON_QC_PLATFORM), y)
CDEFINES += -DCONFIG_NON_QC_PLATFORM