qcacld-3.0: add device attribute 'tsf'

It will show the current host time and
the corresponding tsf when cat
'/sys/class/net/<iface_name>/tsf'
in the following format:
<tsf> <host time> <bssid>

Change-Id: I91332da950840433cf1b7e71f4add2249c8c21c4
CRs-Fixed: 2057693
This commit is contained in:
Yu Wang 2017-06-02 13:40:52 +08:00 • committed by Gerrit - the friendly Code Review server
commit 0ea10177f5

View file

@ -494,6 +494,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 > (U64_MAX - 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)
@ -532,6 +560,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)
qdf_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)
qdf_spin_unlock_bh(&adapter->host_target_sync_lock);
return ret;
}
static inline uint64_t hdd_get_monotonic_host_time(void)
{
struct timespec ts;
@ -540,6 +599,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.bytes);
return size;
}
static ssize_t hdd_wlan_tsf_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret;
cds_ssr_protect(__func__);
ret = __hdd_wlan_tsf_show(dev, attr, buf);
cds_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;
@ -589,6 +695,7 @@ static enum hdd_tsf_op_result hdd_tsf_sync_init(hdd_adapter_t *adapter)
{
QDF_STATUS ret;
hdd_context_t *hddctx;
struct net_device *net_dev;
if (!adapter)
return HDD_TSF_OP_FAIL;
@ -622,6 +729,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;
@ -634,6 +744,7 @@ static enum hdd_tsf_op_result hdd_tsf_sync_deinit(hdd_adapter_t *adapter)
{
QDF_STATUS ret;
hdd_context_t *hddctx;
struct net_device *net_dev;
if (!adapter)
return HDD_TSF_OP_FAIL;
@ -645,6 +756,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 = qdf_mc_timer_destroy(&adapter->host_target_sync_timer);
if (ret != QDF_STATUS_SUCCESS)
hdd_err("Failed to destroy timer, ret: %d", ret);