qcacld-3.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
CRs-Fixed: 2399624
Change-Id: Id4f41a94256a8f035ae408c168c246569185c534
diff --git a/Kbuild b/Kbuild
index 64a02f9..94de5cf 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2209,6 +2209,8 @@
cppflags-$(CONFIG_FEATURE_HL_DBS_GROUP_CREDIT_SHARING) += -DFEATURE_HL_DBS_GROUP_CREDIT_SHARING
cppflags-$(CONFIG_CREDIT_REP_THROUGH_CREDIT_UPDATE) += -DCONFIG_CREDIT_REP_THROUGH_CREDIT_UPDATE
+cppflags-$(CONFIG_WLAN_SYNC_TSF_PTP) += -DWLAN_FEATURE_TSF_PTP
+cppflags-$(CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ) += -DWLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
cppflags-$(CONFIG_TX_DESC_HI_PRIO_RESERVE) += -DCONFIG_TX_DESC_HI_PRIO_RESERVE
#Enable FW logs through ini
diff --git a/components/fw_offload/core/inc/wlan_fw_offload_main.h b/components/fw_offload/core/inc/wlan_fw_offload_main.h
index 84bc8eb..824afa3 100644
--- a/components/fw_offload/core/inc/wlan_fw_offload_main.h
+++ b/components/fw_offload/core/inc/wlan_fw_offload_main.h
@@ -158,6 +158,7 @@
* @enable_fw_module_log_level_num: enablefw module log level num
* @is_rate_limit_enabled: Enable/disable RA rate limited
* @tsf_gpio_pin: TSF GPIO Pin config
+ * @tsf_irq_host_gpio_pin: TSF GPIO Pin config
* @tsf_ptp_options: TSF Plus feature options config
* @lprx_enable: LPRx feature enable config
* @sae_enable: SAE feature enable config
@@ -196,6 +197,9 @@
uint32_t tsf_gpio_pin;
#ifdef WLAN_FEATURE_TSF_PLUS
uint32_t tsf_ptp_options;
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+ uint32_t tsf_irq_host_gpio_pin;
+#endif
#endif
#endif
bool lprx_enable;
diff --git a/components/fw_offload/core/src/wlan_fw_offload_main.c b/components/fw_offload/core/src/wlan_fw_offload_main.c
index 860789e..4a1305f 100644
--- a/components/fw_offload/core/src/wlan_fw_offload_main.c
+++ b/components/fw_offload/core/src/wlan_fw_offload_main.c
@@ -356,6 +356,32 @@
}
#endif
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+/**
+ * ucfg_fwol_fetch_tsf_irq_host_gpio_pin: Populate the
+ * tsf_irq_host_gpio_pin from cfg
+ * @psoc: The global psoc handler
+ * @fwol_cfg: The cfg structure
+ *
+ * This function is used to populate the cfg value of host platform
+ * gpio pin configured to receive tsf interrupt from fw.
+ *
+ * Return: none
+ */
+static void
+ucfg_fwol_fetch_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_cfg *fwol_cfg)
+{
+ fwol_cfg->tsf_irq_host_gpio_pin =
+ cfg_get(psoc, CFG_SET_TSF_IRQ_HOST_GPIO_PIN);
+}
+#else
+static void
+ucfg_fwol_fetch_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_cfg *fwol_cfg)
+{
+}
+#endif
/**
* ucfg_fwol_init_sae_cfg: Populate the sae control config from cfg
* @psoc: The global psoc handler
@@ -448,6 +474,7 @@
fwol_init_adapt_dwelltime_in_cfg(psoc, &fwol_cfg->dwelltime_params);
ucfg_fwol_fetch_ra_filter(psoc, fwol_cfg);
ucfg_fwol_fetch_tsf_gpio_pin(psoc, fwol_cfg);
+ ucfg_fwol_fetch_tsf_irq_host_gpio_pin(psoc, fwol_cfg);
ucfg_fwol_fetch_dhcp_server_settings(psoc, fwol_cfg);
return status;
diff --git a/components/fw_offload/dispatcher/inc/cfg_fwol_generic.h b/components/fw_offload/dispatcher/inc/cfg_fwol_generic.h
index b37bf19..d090008 100644
--- a/components/fw_offload/dispatcher/inc/cfg_fwol_generic.h
+++ b/components/fw_offload/dispatcher/inc/cfg_fwol_generic.h
@@ -434,6 +434,34 @@
CFG_VALUE_OR_DEFAULT, \
"GPIO pin to toggle when capture tsf")
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+/* <ini>
+ * gtsf_irq_host_gpio_pin
+ * @Min: 0
+ * @Max: 254
+ * @Default: 255
+ *
+ * TSF irq GPIO pin of host platform
+ *
+ * Related: None
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_SET_TSF_IRQ_HOST_GPIO_PIN CFG_INI_INT( \
+ "gtsf_irq_host_gpio_pin", \
+ 0, \
+ 254, \
+ 255, \
+ CFG_VALUE_OR_DEFAULT, \
+ "TSF irq GPIO pin of host platform")
+
+#define __CFG_SET_TSF_IRQ_HOST_GPIO_PIN CFG(CFG_SET_TSF_IRQ_HOST_GPIO_PIN)
+#else
+#define __CFG_SET_TSF_IRQ_HOST_GPIO_PIN
+#endif
+
#if defined(WLAN_FEATURE_TSF) && defined(WLAN_FEATURE_TSF_PLUS)
/* <ini>
* gtsf_ptp_options: TSF Plus feature options
@@ -464,6 +492,7 @@
0xf, \
CFG_VALUE_OR_DEFAULT, \
"TSF Plus feature options")
+
#define __CFG_SET_TSF_PTP_OPT CFG(CFG_SET_TSF_PTP_OPT)
#else
#define __CFG_SET_TSF_PTP_OPT
@@ -655,6 +684,7 @@
CFG(CFG_ENABLE_FW_MODULE_LOG_LEVEL) \
CFG(CFG_RA_FILTER_ENABLE) \
CFG(CFG_SET_TSF_GPIO_PIN) \
+ __CFG_SET_TSF_IRQ_HOST_GPIO_PIN \
__CFG_SET_TSF_PTP_OPT \
CFG(CFG_LPRX) \
__CFG_IS_SAE_ENABLED \
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
index a29a161..32b14db 100644
--- a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
@@ -304,6 +304,19 @@
QDF_STATUS ucfg_fwol_get_tsf_gpio_pin(struct wlan_objmgr_psoc *psoc,
uint32_t *tsf_gpio_pin);
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+/**
+ * ucfg_fwol_get_tsf_irq_host_gpio_pin() - Assigns tsf_irq_host_gpio_pin value
+ * @psoc: pointer to the psoc object
+ *
+ * Return: QDF Status
+ */
+
+QDF_STATUS
+ucfg_fwol_get_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
+ uint32_t *tsf_irq_host_gpio_pin);
+#endif
+
#ifdef DHCP_SERVER_OFFLOAD
/**
* ucfg_fwol_get_enable_dhcp_server_offload()-Assign enable_dhcp_server_offload
diff --git a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
index ed270b6..fc7f59a 100644
--- a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
+++ b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
@@ -558,6 +558,27 @@
*tsf_ptp_options = fwol_obj->cfg.tsf_ptp_options;
return QDF_STATUS_SUCCESS;
}
+
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+QDF_STATUS
+ucfg_fwol_get_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
+ uint32_t *tsf_irq_host_gpio_pin)
+{
+ struct wlan_fwol_psoc_obj *fwol_obj;
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL obj");
+ *tsf_irq_host_gpio_pin =
+ cfg_default(CFG_SET_TSF_IRQ_HOST_GPIO_PIN);
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ *tsf_irq_host_gpio_pin = fwol_obj->cfg.tsf_irq_host_gpio_pin;
+ return QDF_STATUS_SUCCESS;
+}
+
+#endif
#endif
#else
QDF_STATUS ucfg_fwol_get_tsf_gpio_pin(struct wlan_objmgr_psoc *psoc,
@@ -571,6 +592,7 @@
{
return QDF_STATUS_E_NOSUPPORT;
}
+
#endif
QDF_STATUS ucfg_fwol_get_lprx_enable(struct wlan_objmgr_psoc *psoc,
@@ -594,6 +616,7 @@
{
return cfg_get(psoc, CFG_IS_SAE_ENABLED);
}
+
#else
bool ucfg_fwol_get_sae_enable(struct wlan_objmgr_psoc *psoc)
{
diff --git a/configs/genoa.pci.debug_defconfig b/configs/genoa.pci.debug_defconfig
index d64cb5f..d8edee4 100644
--- a/configs/genoa.pci.debug_defconfig
+++ b/configs/genoa.pci.debug_defconfig
@@ -47,6 +47,13 @@
CONFIG_WLAN_POWER_DEBUGFS := y
endif
+ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
+ CONFIG_WLAN_SYNC_TSF_PLUS := y
+ CONFIG_WLAN_SYNC_TSF_PTP := y
+ CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
+endif
+
+
ifeq ($(CONFIG_SLUB_DEBUG_ON), y)
CONFIG_DESC_DUP_DETECT_DEBUG := y
CONFIG_DEBUG_RX_RING_BUFFER := y
diff --git a/configs/genoa.pci.perf_defconfig b/configs/genoa.pci.perf_defconfig
index 0c6617e..f76490c 100644
--- a/configs/genoa.pci.perf_defconfig
+++ b/configs/genoa.pci.perf_defconfig
@@ -46,6 +46,12 @@
CONFIG_WLAN_POWER_DEBUGFS := n
endif
+ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
+ CONFIG_WLAN_SYNC_TSF_PLUS := y
+ CONFIG_WLAN_SYNC_TSF_PTP := y
+ CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
+endif
+
ifeq ($(CONFIG_SLUB_DEBUG_ON), y)
CONFIG_DESC_DUP_DETECT_DEBUG := n
CONFIG_DEBUG_RX_RING_BUFFER := n
diff --git a/configs/genoa.usb.debug_defconfig b/configs/genoa.usb.debug_defconfig
index f6cd57e..ca4720e 100644
--- a/configs/genoa.usb.debug_defconfig
+++ b/configs/genoa.usb.debug_defconfig
@@ -27,6 +27,12 @@
CONFIG_WLAN_POWER_DEBUGFS := y
endif
+ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
+ CONFIG_WLAN_SYNC_TSF_PLUS := y
+ CONFIG_WLAN_SYNC_TSF_PTP := y
+ CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
+endif
+
# Features gets enabled on slub debug
CONFIG_WLAN_DEBUG_CRASH_INJECT := y
CONFIG_FEATURE_MEMDUMP_ENABLE := y
diff --git a/configs/genoa.usb.perf_defconfig b/configs/genoa.usb.perf_defconfig
index 5cfd4ca..de73a4a 100644
--- a/configs/genoa.usb.perf_defconfig
+++ b/configs/genoa.usb.perf_defconfig
@@ -32,6 +32,11 @@
CONFIG_LEAK_DETECTION := n
endif
+ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
+ CONFIG_WLAN_SYNC_TSF_PLUS := y
+ CONFIG_WLAN_SYNC_TSF_PTP := y
+ CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
+endif
CONFIG_ENABLE_SIZE_OPTIMIZE := y
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index d855172..057101c 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -61,6 +61,10 @@
#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
#include <linux/wakelock.h>
#endif
+#ifdef WLAN_FEATURE_TSF_PTP
+#include <linux/ptp_classify.h>
+#include <linux/ptp_clock_kernel.h>
+#endif
#include <wlan_hdd_ftm.h>
#include "wlan_hdd_tdls.h"
#include "wlan_hdd_tsf.h"
@@ -1807,6 +1811,10 @@
/* the context that is capturing tsf */
struct hdd_adapter *cap_tsf_context;
#endif
+#ifdef WLAN_FEATURE_TSF_PTP
+ struct ptp_clock_info ptp_cinfo;
+ struct ptp_clock *ptp_clock;
+#endif
uint8_t bt_a2dp_active:1;
uint8_t bt_vo_active:1;
enum band_info curr_band;
diff --git a/core/hdd/inc/wlan_hdd_tsf.h b/core/hdd/inc/wlan_hdd_tsf.h
index 81235ec..547e19d 100644
--- a/core/hdd/inc/wlan_hdd_tsf.h
+++ b/core/hdd/inc/wlan_hdd_tsf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -316,4 +316,15 @@
}
#endif
+#ifdef WLAN_FEATURE_TSF_PTP
+/**
+ * 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);
+
+#endif
#endif
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index 3606d98..05dcdee 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -36,6 +36,7 @@
#include <cds_sched.h>
#include <linux/etherdevice.h>
#include "osif_sync.h"
+#include <linux/ethtool.h>
#include <wlan_hdd_includes.h>
#include <qc_sap_ioctl.h>
#include "osif_sync.h"
@@ -1896,6 +1897,7 @@
ap_ctx->operating_channel);
hostapd_state->bss_state = BSS_START;
+ hdd_start_tsf_sync(adapter);
/* Set default key index */
hdd_debug("default key index %hu", ap_ctx->wep_def_key_idx);
@@ -2642,6 +2644,7 @@
* re-enabled
*/
hostapd_state->bss_state = BSS_STOP;
+ hdd_stop_tsf_sync(adapter);
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
wlan_hdd_auto_shutdown_enable(hdd_ctx, true);
@@ -3162,6 +3165,12 @@
}
#endif
+#ifdef WLAN_FEATURE_TSF_PTP
+static const struct ethtool_ops wlan_hostapd_ethtool_ops = {
+ .get_ts_info = wlan_get_ts_info,
+};
+#endif
+
const struct net_device_ops net_ops_struct = {
.ndo_open = hdd_hostapd_open,
.ndo_stop = hdd_hostapd_stop,
@@ -3175,10 +3184,18 @@
.ndo_select_queue = hdd_select_queue,
};
+#ifdef WLAN_FEATURE_TSF_PTP
+void hdd_set_ap_ops(struct net_device *dev)
+{
+ dev->netdev_ops = &net_ops_struct;
+ dev->ethtool_ops = &wlan_hostapd_ethtool_ops;
+}
+#else
void hdd_set_ap_ops(struct net_device *dev)
{
dev->netdev_ops = &net_ops_struct;
}
+#endif
bool hdd_sap_create_ctx(struct hdd_adapter *adapter)
{
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index c3f798e..7d6000e 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -79,6 +79,7 @@
#include <linux/ctype.h>
#include <linux/compat.h>
#include <linux/reboot.h>
+#include <linux/ethtool.h>
#ifdef MSM_PLATFORM
#include <soc/qcom/subsystem_restart.h>
#endif
@@ -3743,6 +3744,12 @@
osif_vdev_sync_op_stop(vdev_sync);
}
+#ifdef WLAN_FEATURE_TSF_PTP
+static const struct ethtool_ops wlan_ethtool_ops = {
+ .get_ts_info = wlan_get_ts_info,
+};
+#endif
+
static const struct net_device_ops wlan_drv_ops = {
.ndo_open = hdd_open,
.ndo_stop = hdd_stop,
@@ -3764,6 +3771,7 @@
.ndo_get_stats = hdd_get_stats,
};
+#ifdef WLAN_FEATURE_TSF_PTP
/**
* hdd_set_station_ops() - update net_device ops for monitor mode
* @dev: Handle to struct net_device to be updated.
@@ -3771,17 +3779,37 @@
*/
void hdd_set_station_ops(struct net_device *dev)
{
- if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
+ if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
+ dev->netdev_ops = &wlan_mon_drv_ops;
+ } else {
+ dev->netdev_ops = &wlan_drv_ops;
+ dev->ethtool_ops = &wlan_ethtool_ops;
+ }
+}
+#else
+void hdd_set_station_ops(struct net_device *dev)
+{
+ if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
dev->netdev_ops = &wlan_mon_drv_ops;
else
dev->netdev_ops = &wlan_drv_ops;
}
+
+#endif
+#else
+#ifdef WLAN_FEATURE_TSF_PTP
+void hdd_set_station_ops(struct net_device *dev)
+{
+ dev->netdev_ops = &wlan_drv_ops;
+ dev->ethtool_ops = &wlan_ethtool_ops;
+}
#else
void hdd_set_station_ops(struct net_device *dev)
{
dev->netdev_ops = &wlan_drv_ops;
}
#endif
+#endif
/**
* hdd_alloc_station_adapter() - allocate the station hdd adapter
diff --git a/core/hdd/src/wlan_hdd_tsf.c b/core/hdd/src/wlan_hdd_tsf.c
index 1cd28ad..8149cca 100644
--- a/core/hdd/src/wlan_hdd_tsf.c
+++ b/core/hdd/src/wlan_hdd_tsf.c
@@ -27,6 +27,10 @@
#include "wlan_fwol_ucfg_api.h"
#include <qca_vendor.h>
#include <linux/errqueue.h>
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+#include <linux/gpio.h>
+static int tsf_gpio_irq_num = -1;
+#endif
#include "ol_txrx_api.h"
static struct completion tsf_sync_get_completion_evt;
@@ -35,6 +39,16 @@
#define WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS 100
#define WLAN_HDD_SOFTAP_INTERVEL_TIMES 100
+#ifdef WLAN_FEATURE_TSF_PLUS
+#ifdef WLAN_FEATURE_TSF_PLUS_NOIRQ
+static void hdd_update_timestamp(struct hdd_adapter *adapter);
+#else
+static void
+hdd_update_timestamp(struct hdd_adapter *adapter,
+ uint64_t target_time, uint64_t host_time);
+#endif
+#endif
+
/**
* enum hdd_tsf_op_result - result of tsf operation
*
@@ -116,6 +130,7 @@
return true;
}
+#if defined(WLAN_FEATURE_TSF_PLUS_NOIRQ) && defined(WLAN_FEATURE_TSF_PLUS)
/**
* hdd_tsf_reset_gpio() - Reset TSF GPIO used for host timer sync
* @adapter: pointer to adapter
@@ -125,7 +140,6 @@
*
* Return: TSF_RETURN on Success, TSF_RESET_GPIO_FAIL on failure
*/
-#if defined(WLAN_FEATURE_TSF_PLUS_NOIRQ) && defined(WLAN_FEATURE_TSF_PLUS)
static int hdd_tsf_reset_gpio(struct hdd_adapter *adapter)
{
/* No GPIO Host timer sync for integrated WIFI Device */
@@ -145,7 +159,54 @@
{
return QDF_STATUS_SUCCESS;
}
+#else
+static int hdd_tsf_reset_gpio(struct hdd_adapter *adapter)
+{
+ int ret;
+ ret = wma_cli_set_command((int)adapter->vdev_id,
+ (int)GEN_PARAM_RESET_TSF_GPIO,
+ adapter->vdev_id,
+ GEN_CMD);
+
+ if (ret != 0) {
+ hdd_err("tsf reset GPIO fail ");
+ ret = TSF_RESET_GPIO_FAIL;
+ } else {
+ ret = TSF_RETURN;
+ }
+ return ret;
+}
+
+/**
+ * hdd_tsf_set_gpio() - Set TSF GPIO used for host timer sync
+ * @hdd_ctx: pointer to hdd context
+ *
+ * This function check GPIO and set GPIO as IRQ to FW side on
+ * none Adrastea arch
+ *
+ * Return: QDF_STATUS_SUCCESS on Success, others on Failure.
+ */
+static QDF_STATUS hdd_tsf_set_gpio(struct hdd_context *hdd_ctx)
+{
+ QDF_STATUS status;
+ uint32_t tsf_gpio_pin = TSF_GPIO_PIN_INVALID;
+
+ status = ucfg_fwol_get_tsf_gpio_pin(hdd_ctx->psoc, &tsf_gpio_pin);
+ if (QDF_IS_STATUS_ERROR(status))
+ return QDF_STATUS_E_INVAL;
+
+ if (tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
+ return QDF_STATUS_E_INVAL;
+
+ status = sme_set_tsf_gpio(hdd_ctx->mac_handle,
+ tsf_gpio_pin);
+
+ return status;
+}
+#endif
+
+#ifdef WLAN_FEATURE_TSF_PLUS
bool hdd_tsf_is_ptp_enabled(struct hdd_context *hdd)
{
uint32_t tsf_ptp_options;
@@ -200,51 +261,6 @@
else
return false;
}
-
-#else
-static int hdd_tsf_reset_gpio(struct hdd_adapter *adapter)
-{
- int ret;
-
- ret = wma_cli_set_command((int)adapter->vdev_id,
- (int)GEN_PARAM_RESET_TSF_GPIO, adapter->vdev_id,
- GEN_CMD);
-
- if (ret != 0) {
- hdd_err("tsf reset GPIO fail ");
- ret = TSF_RESET_GPIO_FAIL;
- } else {
- ret = TSF_RETURN;
- }
- return ret;
-}
-
-/**
- * hdd_tsf_set_gpio() - Set TSF GPIO used for host timer sync
- * @hdd_ctx: pointer to hdd context
- *
- * This function check GPIO and set GPIO as IRQ to FW side on
- * none Adrastea arch
- *
- * Return: QDF_STATUS_SUCCESS on Success, others on Failure.
- */
-static QDF_STATUS hdd_tsf_set_gpio(struct hdd_context *hdd_ctx)
-{
- QDF_STATUS status;
- uint32_t tsf_gpio_pin = TSF_GPIO_PIN_INVALID;
-
- status = ucfg_fwol_get_tsf_gpio_pin(hdd_ctx->psoc, &tsf_gpio_pin);
- if (QDF_IS_STATUS_ERROR(status))
- return QDF_STATUS_E_INVAL;
-
- if (tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
- return QDF_STATUS_E_INVAL;
-
- status = sme_set_tsf_gpio(hdd_ctx->mac_handle,
- tsf_gpio_pin);
-
- return status;
-}
#endif
static enum hdd_tsf_op_result hdd_capture_tsf_internal(
@@ -387,7 +403,11 @@
/* to distinguish 32-bit overflow case, this inverval should:
* equal or less than (1/2 * OVERFLOW_INDICATOR32 us)
*/
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 2
+#else
#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 10
+#endif
#define OVERFLOW_INDICATOR32 (((int64_t)0x1) << 32)
#define CAP_TSF_TIMER_FIX_SEC 1
@@ -674,6 +694,9 @@
if (!arg)
return IRQ_NONE;
+ if (irq != tsf_gpio_irq_num)
+ return IRQ_NONE;
+
hdd_ctx = (struct hdd_context *)arg;
host_time = hdd_get_monotonic_host_time(hdd_ctx);
@@ -1344,6 +1367,99 @@
return HDD_TSF_OP_SUCC;
}
#else
+#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
+static
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(struct hdd_context *hdd_ctx)
+{
+ int ret;
+ QDF_STATUS status;
+ uint32_t tsf_irq_gpio_pin = TSF_GPIO_PIN_INVALID;
+
+ if (!hdd_tsf_is_ptp_enabled(hdd_ctx)) {
+ hdd_info("To enable TSF_PLUS, set gtsf_ptp_options in ini");
+ goto fail;
+ }
+
+ status = ucfg_fwol_get_tsf_irq_host_gpio_pin(hdd_ctx->psoc,
+ &tsf_irq_gpio_pin);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ hdd_err("tsf gpio irq host pin error");
+ goto fail;
+ }
+
+ if (tsf_irq_gpio_pin == TSF_GPIO_PIN_INVALID) {
+ hdd_err("gpio host pin is invalid");
+ goto fail;
+ }
+
+ ret = gpio_request(tsf_irq_gpio_pin, "wlan_tsf");
+ if (ret) {
+ hdd_err("gpio host pin is invalid");
+ goto fail;
+ }
+
+ ret = gpio_direction_input(tsf_irq_gpio_pin);
+ if (ret) {
+ hdd_err("gpio host pin is invalid");
+ goto fail_free_gpio;
+ }
+
+ tsf_gpio_irq_num = gpio_to_irq(tsf_irq_gpio_pin);
+ if (tsf_gpio_irq_num < 0) {
+ hdd_err("fail to get irq: %d", tsf_gpio_irq_num);
+ goto fail_free_gpio;
+ }
+
+ ret = request_irq(tsf_gpio_irq_num, hdd_tsf_captured_irq_handler,
+ IRQF_SHARED | IRQF_TRIGGER_RISING, "wlan_tsf",
+ hdd_ctx);
+
+ if (ret) {
+ hdd_err("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(tsf_irq_gpio_pin);
+fail:
+ tsf_gpio_irq_num = -1;
+ return HDD_TSF_OP_FAIL;
+}
+
+static
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(struct hdd_context *hdd_ctx)
+{
+ QDF_STATUS status;
+ uint32_t tsf_irq_gpio_pin = TSF_GPIO_PIN_INVALID;
+
+ if (!hdd_tsf_is_ptp_enabled(hdd_ctx))
+ return HDD_TSF_OP_SUCC;
+
+ status = ucfg_fwol_get_tsf_irq_host_gpio_pin(hdd_ctx->psoc,
+ &tsf_irq_gpio_pin);
+ if (QDF_IS_STATUS_ERROR(status))
+ return QDF_STATUS_E_INVAL;
+
+ if (tsf_irq_gpio_pin == TSF_GPIO_PIN_INVALID)
+ return QDF_STATUS_E_INVAL;
+
+ if (hdd_tsf_is_tx_set(hdd_ctx))
+ ol_deregister_timestamp_callback();
+
+ if (tsf_gpio_irq_num >= 0) {
+ free_irq(tsf_gpio_irq_num, hdd_ctx);
+ tsf_gpio_irq_num = -1;
+ gpio_free(tsf_irq_gpio_pin);
+ }
+
+ return HDD_TSF_OP_SUCC;
+}
+#else
static inline
enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(struct hdd_context *hdd_ctx)
{
@@ -1392,6 +1508,7 @@
}
#endif
+#endif
void hdd_tsf_notify_wlan_state_change(struct hdd_adapter *adapter,
eConnectionState old_state,
eConnectionState new_state)
@@ -1448,6 +1565,197 @@
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)
+
+{
+ struct hdd_adapter *adapter = netdev_priv(dev);
+ struct osif_vdev_sync *vdev_sync;
+ struct hdd_context *hdd_ctx;
+ int errno;
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ errno = wlan_hdd_validate_context(hdd_ctx);
+ if (errno)
+ return -EINVAL;
+
+ errno = osif_vdev_sync_op_start(dev, &vdev_sync);
+ if (errno)
+ return -EAGAIN;
+
+ 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;
+
+ osif_vdev_sync_op_stop(vdev_sync);
+ return 0;
+}
+
+#if (KERNEL_VERSION(4, 1, 0) > LINUX_VERSION_CODE)
+/**
+ * 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;
+ struct hdd_context *hdd_ctx;
+ struct hdd_adapter *adapter;
+ uint32_t tsf_reg_read_enabled;
+ struct osif_psoc_sync *psoc_sync;
+ int errno, status = 0;
+
+ hdd_ctx = qdf_container_of(ptp, struct hdd_context, ptp_cinfo);
+ errno = wlan_hdd_validate_context(hdd_ctx);
+ if (errno)
+ return -EINVAL;
+
+ errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
+ if (errno)
+ return -EAGAIN;
+
+ adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_GO_MODE);
+ if (!adapter) {
+ adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_CLIENT_MODE);
+ if (!adapter) {
+ adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
+ if (!adapter)
+ adapter = hdd_get_adapter(hdd_ctx,
+ QDF_STA_MODE);
+ if (!adapter) {
+ status = -EOPNOTSUPP;
+ goto end;
+ }
+ }
+ }
+
+ host_time = hdd_get_monotonic_host_time(hdd_ctx);
+ if (hdd_get_targettime_from_hosttime(adapter, host_time,
+ &target_time)) {
+ hdd_err("get invalid target timestamp");
+ status = -EINVAL;
+ goto end;
+ }
+ *ts = ns_to_timespec(target_time * NSEC_PER_USEC);
+
+end:
+ osif_psoc_sync_op_stop(psoc_sync);
+ return status;
+}
+
+/**
+ * wlan_hdd_phc_init() - phc init
+ * @hdd_ctx: pointer to the hdd_contex.
+ *
+ * Return: NULL
+ */
+static void wlan_hdd_phc_init(struct hdd_context *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(struct hdd_context *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;
+ struct hdd_context *hdd_ctx;
+ struct hdd_adapter *adapter;
+ struct osif_psoc_sync *psoc_sync;
+ int errno, status = 0;
+
+ hdd_ctx = qdf_container_of(ptp, struct hdd_context, ptp_cinfo);
+ errno = wlan_hdd_validate_context(hdd_ctx);
+ if (errno)
+ return -EINVAL;
+
+ errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
+ if (errno)
+ return -EAGAIN;
+
+ adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_GO_MODE);
+ if (!adapter) {
+ adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_CLIENT_MODE);
+ if (!adapter) {
+ adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
+ if (!adapter)
+ adapter = hdd_get_adapter(hdd_ctx,
+ QDF_STA_MODE);
+ if (!adapter) {
+ status = -EOPNOTSUPP;
+ goto end;
+ }
+ }
+ }
+
+ host_time = hdd_get_monotonic_host_time(hdd_ctx);
+ if (hdd_get_targettime_from_hosttime(adapter, host_time,
+ &target_time)) {
+ hdd_err("get invalid target timestamp");
+ status = -EINVAL;
+ goto end;
+ }
+ *ts = ns_to_timespec64(target_time * NSEC_PER_USEC);
+
+end:
+ osif_psoc_sync_op_stop(psoc_sync);
+ return status;
+}
+
+static void wlan_hdd_phc_init(struct hdd_context *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(struct hdd_context *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
+
+static void wlan_hdd_phc_init(struct hdd_context *hdd_ctx)
+{
+}
+
+static void wlan_hdd_phc_deinit(struct hdd_context *hdd_ctx)
+{
+}
+#endif /* WLAN_FEATURE_TSF_PTP */
+
/**
* hdd_get_tsf_cb() - handle tsf callback
* @pcb_cxt: pointer to the hdd_contex
@@ -1516,6 +1824,7 @@
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",
@@ -1550,7 +1859,7 @@
struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_TSF_MAX + 1];
int status, ret;
struct sk_buff *reply_skb;
- uint32_t tsf_op_resp[3], tsf_cmd;
+ uint32_t tsf_op_resp[3] = {0}, tsf_cmd;
hdd_enter_dev(wdev->netdev);
@@ -1699,6 +2008,8 @@
if (wlan_hdd_tsf_plus_init(hdd_ctx) != HDD_TSF_OP_SUCC)
goto fail;
+ wlan_hdd_phc_init(hdd_ctx);
+
return;
fail:
@@ -1713,6 +2024,7 @@
if (!qdf_atomic_read(&hdd_ctx->tsf_ready_flag))
return;
+ wlan_hdd_phc_deinit(hdd_ctx);
wlan_hdd_tsf_plus_deinit(hdd_ctx);
qdf_atomic_set(&hdd_ctx->tsf_ready_flag, 0);
qdf_atomic_set(&hdd_ctx->cap_tsf_flag, 0);