diff options
| author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-04-26 00:40:15 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-04-26 00:40:15 -0700 |
| commit | 1eeddf8238b3f025b492dd414e23424e1e4cdcf0 (patch) | |
| tree | 6517dcc83d74b5978cdfe6547d0b3a5dfd36b5fd | |
| parent | 99681471f05c7744a4539a5152dd7a7c0f482713 (diff) | |
| parent | e03d634ccafdecc776e9386686d9d3be285b236d (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.c | 118 |
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, |
