summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-04-26 00:40:15 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-26 00:40:15 -0700
commit1eeddf8238b3f025b492dd414e23424e1e4cdcf0 (patch)
tree6517dcc83d74b5978cdfe6547d0b3a5dfd36b5fd
parent99681471f05c7744a4539a5152dd7a7c0f482713 (diff)
parente03d634ccafdecc776e9386686d9d3be285b236d (diff)
Merge "qcacld-2.0: add device attribute 'tsf'" into wlan-cld2.driver.lnx.1.0-dev
-rw-r--r--CORE/HDD/src/wlan_hdd_tsf.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/CORE/HDD/src/wlan_hdd_tsf.c b/CORE/HDD/src/wlan_hdd_tsf.c
index ad69034433c4..58fa15868c55 100644
--- a/CORE/HDD/src/wlan_hdd_tsf.c
+++ b/CORE/HDD/src/wlan_hdd_tsf.c
@@ -493,6 +493,34 @@ static inline int hdd_64bit_plus(uint64_t x, int64_t y, uint64_t *ret)
return 0;
}
+static inline int hdd_uint64_plus(uint64_t x, uint64_t y, uint64_t *ret)
+{
+ if (!ret)
+ return -EINVAL;
+
+ if (x > (MAX_UINT64 - y)) {
+ *ret = 0;
+ return -EINVAL;
+ }
+
+ *ret = x + y;
+ return 0;
+}
+
+static inline int hdd_uint64_minus(uint64_t x, uint64_t y, uint64_t *ret)
+{
+ if (!ret)
+ return -EINVAL;
+
+ if (x < y) {
+ *ret = 0;
+ return -EINVAL;
+ }
+
+ *ret = x - y;
+ return 0;
+}
+
static inline int32_t hdd_get_hosttime_from_targettime(
hdd_adapter_t *adapter, uint64_t target_time,
uint64_t *host_time)
@@ -531,6 +559,37 @@ static inline int32_t hdd_get_hosttime_from_targettime(
return ret;
}
+static inline int32_t hdd_get_targettime_from_hosttime(
+ hdd_adapter_t *adapter, uint64_t host_time,
+ uint64_t *target_time)
+{
+ int32_t ret = -EINVAL;
+ bool in_cap_state;
+
+ if (!adapter || host_time == 0)
+ return ret;
+
+ in_cap_state = hdd_tsf_is_in_cap(adapter);
+ if (in_cap_state)
+ spin_lock_bh(&adapter->host_target_sync_lock);
+
+ if (host_time < adapter->last_host_time)
+ ret = hdd_uint64_minus(adapter->last_target_time,
+ (adapter->last_host_time - host_time) /
+ HOST_TO_TARGET_TIME_RATIO,
+ target_time);
+ else
+ ret = hdd_uint64_plus(adapter->last_target_time,
+ (host_time - adapter->last_host_time) /
+ HOST_TO_TARGET_TIME_RATIO,
+ target_time);
+
+ if (in_cap_state)
+ spin_unlock_bh(&adapter->host_target_sync_lock);
+
+ return ret;
+}
+
static inline uint64_t hdd_get_monotonic_host_time(void)
{
struct timespec ts;
@@ -539,6 +598,53 @@ static inline uint64_t hdd_get_monotonic_host_time(void)
return timespec_to_ns(&ts);
}
+static ssize_t __hdd_wlan_tsf_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ hdd_station_ctx_t *hdd_sta_ctx;
+ hdd_adapter_t *adapter;
+ ssize_t size;
+ uint64_t host_time, target_time;
+
+ struct net_device *net_dev = container_of(dev, struct net_device, dev);
+
+ adapter = (hdd_adapter_t *)(netdev_priv(net_dev));
+ if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
+ return scnprintf(buf, PAGE_SIZE, "Invalid device\n");
+
+ if (!hdd_get_th_sync_status(adapter))
+ 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");
+
+ host_time = hdd_get_monotonic_host_time();
+ 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);
+ return size;
+}
+
+static ssize_t hdd_wlan_tsf_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+
+ vos_ssr_protect(__func__);
+ ret = __hdd_wlan_tsf_show(dev, attr, buf);
+ vos_ssr_unprotect(__func__);
+
+ return ret;
+}
+
+static DEVICE_ATTR(tsf, 0400, hdd_wlan_tsf_show, NULL);
+
static void hdd_capture_tsf_timer_expired_handler(void *arg)
{
uint32_t tsf_op_resp;
@@ -590,6 +696,7 @@ static enum hdd_tsf_op_result hdd_tsf_sync_init(hdd_adapter_t *adapter)
{
VOS_STATUS ret;
hdd_context_t *hddctx;
+ struct net_device *net_dev;
if (!adapter)
return HDD_TSF_OP_FAIL;
@@ -627,6 +734,9 @@ static enum hdd_tsf_op_result hdd_tsf_sync_init(hdd_adapter_t *adapter)
goto fail;
}
+ net_dev = adapter->dev;
+ if (net_dev)
+ device_create_file(&net_dev->dev, &dev_attr_tsf);
hdd_set_th_sync_status(adapter, true);
return HDD_TSF_OP_SUCC;
@@ -639,6 +749,7 @@ static enum hdd_tsf_op_result hdd_tsf_sync_deinit(hdd_adapter_t *adapter)
{
VOS_STATUS ret;
hdd_context_t *hddctx;
+ struct net_device *net_dev;
if (!adapter)
return HDD_TSF_OP_FAIL;
@@ -651,6 +762,13 @@ static enum hdd_tsf_op_result hdd_tsf_sync_deinit(hdd_adapter_t *adapter)
hdd_set_th_sync_status(adapter, false);
+ net_dev = adapter->dev;
+ if (net_dev) {
+ struct device *dev = &net_dev->dev;
+
+ device_remove_file(dev, &dev_attr_tsf);
+ }
+
ret = vos_timer_destroy(&adapter->host_target_sync_timer);
if (ret != VOS_STATUS_SUCCESS)
hddLog(VOS_TRACE_LEVEL_ERROR,