diff options
author | Star Chang <starchang@google.com> | 2022-08-04 01:36:15 +0000 |
---|---|---|
committer | Star Chang <starchang@google.com> | 2022-11-01 05:46:50 +0000 |
commit | 4e6c07be722421daa260cb66ffd667f4088d1e83 (patch) | |
tree | 4db3725769e6cbb0216d4c854fb593fadbd40fbc | |
parent | faff7aaa5abbd90893469aae842c74c9474ea3f4 (diff) | |
download | wlan_ptracker-4e6c07be722421daa260cb66ffd667f4088d1e83.tar.gz |
wlan_ptracker: add feature support
1. add debug information.
2. support twt parameters configure.
3. support force scene translate
4. add runtime disable twt setup.
Bug: 253348062
Test: ST-stability/WiFi regression/WiFi performance Test pass
Signed-off-by: Star Chang <starchang@google.com>
Change-Id: I581adca9787bd904ded2c70c38a2af19857daa8b
-rw-r--r-- | core.h | 2 | ||||
-rw-r--r-- | debugfs.h | 5 | ||||
-rw-r--r-- | dynamic_twt_manager.c | 535 | ||||
-rw-r--r-- | dynamic_twt_manager.h | 50 | ||||
-rw-r--r-- | main.c | 8 | ||||
-rw-r--r-- | scenes_fsm.c | 171 | ||||
-rw-r--r-- | scenes_fsm.h | 12 | ||||
-rw-r--r-- | tp_monitor.c | 39 | ||||
-rw-r--r-- | tp_monitor.h | 4 | ||||
-rw-r--r-- | wlan_ptracker_client.h | 9 |
10 files changed, 696 insertions, 139 deletions
@@ -29,7 +29,7 @@ struct wlan_ptracker_core { struct wlan_ptracker_debugfs debugfs; struct wlan_ptracker_fsm fsm; struct net_device *dev; - struct wlan_ptracker_client *client; + struct wlan_ptracker_client __rcu *client; u8 dscp_to_ac[DSCP_MAX]; }; #endif /* _WLAN_PTRACKER_CORE_H */ @@ -30,6 +30,11 @@ enum { ACTION_MAX, }; +struct scene_statistic { + u64 awake; + u64 asleep; +}; + struct history_entry { u32 state; bool valid; diff --git a/dynamic_twt_manager.c b/dynamic_twt_manager.c index 7f22219..e3f965a 100644 --- a/dynamic_twt_manager.c +++ b/dynamic_twt_manager.c @@ -7,30 +7,41 @@ * Author: Star Chang <starchang@google.com> */ #include <linux/debugfs.h> +#include <linux/workqueue.h> +#include <linux/delay.h> #include "core.h" static struct dytwt_manager dytwt_mgmt; #define dytwt_get_manager() (&dytwt_mgmt) +#define DYMAIC_TWT_CONFIG_ID 3 + +/* for tcp one pair case */ +#define TWT_IDLE_INTERVAL (500 * 1024) /* 512000 */ +#define TWT_IDLE_DURATION (256 * 32) /* 16384 */ +#define TWT_WEB_INTERVAL (104 * 1024) /* 106496 */ +#define TWT_WEB_DURATION (256 * 32) /* 8192 */ +#define TWT_YOUTUBE_INTERVAL (10 * 1024) /* 10240 */ +#define TWT_YOUTUBE_DURATION (256 * 32) /* 8192 */ + +#define TWT_REASON_MAX (WLAN_PTRACKER_NOTIFY_MAX + 1) static const char *const reason2str[WLAN_PTRACKER_NOTIFY_MAX] = { "tp", "scene_change", "scene_prep", "suspend", "sta_change", }; -#define DYMAIC_TWT_CONFIG_ID 3 -#define TWT_WAKE_DURATION 8192 -#define TWT_IDLE_INTERVAL 512000 -#define TWT_WEB_INTERVAL 106496 -#define TWT_YOUTUBE_INTERVAL 10240 +static const char *const state2str[WLAN_SCENE_MAX] = { + "Idle", "Web", "Youtube", "Low latency", "Throughput" +}; -static struct dytwt_scene_action dytwt_actions[WLAN_SCENE_MAX] = { +static struct dytwt_scene_action dytwt_actions[WLAN_SCENE_MAX + 1] = { { .action = TWT_ACTION_SETUP, .param = { .config_id = DYMAIC_TWT_CONFIG_ID, .nego_type = 0, .trigger_type = 0, - .wake_duration = TWT_WAKE_DURATION, + .wake_duration = TWT_IDLE_DURATION, .wake_interval = TWT_IDLE_INTERVAL, }, }, @@ -40,17 +51,17 @@ static struct dytwt_scene_action dytwt_actions[WLAN_SCENE_MAX] = { .config_id = DYMAIC_TWT_CONFIG_ID, .nego_type = 0, .trigger_type = 0, - .wake_duration = TWT_WAKE_DURATION, + .wake_duration = TWT_WEB_DURATION, .wake_interval = TWT_WEB_INTERVAL, }, }, { - .action = TWT_ACTION_SETUP, + .action = TWT_ACTION_TEARDOWN, .param = { .config_id = DYMAIC_TWT_CONFIG_ID, .nego_type = 0, .trigger_type = 0, - .wake_duration = TWT_WAKE_DURATION, + .wake_duration = TWT_YOUTUBE_DURATION, .wake_interval = TWT_YOUTUBE_INTERVAL, }, }, @@ -70,7 +81,19 @@ static struct dytwt_scene_action dytwt_actions[WLAN_SCENE_MAX] = { .trigger_type = 0, }, }, + /* used for force mode */ + { + .action = TWT_ACTION_SETUP, + .param = { + .config_id = DYMAIC_TWT_CONFIG_ID, + .nego_type = 0, + .trigger_type = 0, + .wake_duration = TWT_IDLE_DURATION, + .wake_interval = TWT_IDLE_INTERVAL, + }, + } }; +#define TWT_ACTION_SIZE ARRAY_SIZE(dytwt_actions) static int dytwt_client_twt_setup(struct wlan_ptracker_client *client, u32 state) { @@ -103,7 +126,7 @@ static int dytwt_client_twt_teardown(struct wlan_ptracker_client *client, u32 st static bool dytwt_client_twt_cap(struct wlan_ptracker_client *client) { struct dytwt_cap param; - struct wlan_ptracker_core *core = client->core; + struct dytwt_manager *dytwt = dytwt_get_manager(); int ret; if (!client->dytwt_ops) @@ -114,11 +137,29 @@ static bool dytwt_client_twt_cap(struct wlan_ptracker_client *client) ret = client->dytwt_ops->get_cap(client->priv, ¶m); + ptracker_dbg(dytwt->core, "%d, %d, %d, %d\n", param.device_cap, param.peer_cap, + param.link_speed, param.rssi); if (ret) return false; - ptracker_dbg(core, "device: %d, peer: %d\n", param.device_cap, param.peer_cap); - return param.peer_cap && param.device_cap; + if (!param.peer_cap || !param.device_cap) { + ptracker_err(dytwt->core, "dytwt is not enabled due to capability: %d, %d\n", + param.device_cap, param.peer_cap); + return false; + } + + if (param.rssi != 0 && param.rssi < dytwt->rssi_threshold) { + ptracker_err(dytwt->core, "dytwt is not enabled due to rssi %d < %d\n", + param.rssi, dytwt->rssi_threshold); + return false; + } + + if (param.link_speed < dytwt->link_threshold) { + ptracker_err(dytwt->core, "dytwt is not enabled due to linkspeed %d < %d\n", + param.link_speed, dytwt->link_threshold); + return false; + } + return true; } static int dytwt_client_twt_pwrstates(struct wlan_ptracker_client *client, @@ -133,6 +174,18 @@ static int dytwt_client_twt_pwrstates(struct wlan_ptracker_client *client, return client->dytwt_ops->get_pwrstates(client->priv, state); } +static int dytwt_client_twt_get_stats(struct wlan_ptracker_client *client, + struct dytwt_stats *stats) +{ + if (!client->dytwt_ops) + return -EINVAL; + + if (!client->dytwt_ops->get_stats) + return -EINVAL; + + return client->dytwt_ops->get_stats(client->priv, stats); +} + static inline void dytwt_record_get_pwr(u64 asleep, u64 awake, u64 *total, int *percent) { /* for percent */ @@ -146,29 +199,54 @@ static int dytwt_record_priv_read(void *cur, void *next, char *buf, int len) { struct dytwt_entry *c = cur; struct dytwt_entry *n = next; - int period_percent = 0, total_percent; - u64 period_time = 0, total_time; - - /* get total */ - dytwt_record_get_pwr(c->pwr.asleep, c->pwr.awake, &total_time, &total_percent); - - /* get period */ - if (n) { - u64 awake = n->pwr.awake > c->pwr.awake ? - (n->pwr.awake - c->pwr.awake) : c->pwr.awake; - u64 asleep = n->pwr.asleep > c->pwr.asleep ? - (n->pwr.asleep - c->pwr.asleep) : c->pwr.asleep; - dytwt_record_get_pwr(asleep, awake, &period_time, &period_percent); + struct dytwt_manager *dytwt = dytwt_get_manager(); + int period_percent, total_percent; + u64 period_time, total_time; + u64 awake, asleep; + + /* next is the current state */ + if (n->pwr.asleep < c->pwr.asleep) { + struct dytwt_pwr_state pwr; + dytwt_client_twt_pwrstates(dytwt->core->client, &pwr); + awake = pwr.awake - c->pwr.awake; + asleep = pwr.asleep - c->pwr.asleep; + /* get total */ + dytwt_record_get_pwr(pwr.asleep, pwr.awake, &total_time, &total_percent); + } else { + /* get period */ + awake = n->pwr.awake - c->pwr.awake; + asleep = n->pwr.asleep - c->pwr.asleep; + /* get total */ + dytwt_record_get_pwr(c->pwr.asleep, c->pwr.awake, &total_time, &total_percent); } + dytwt_record_get_pwr(asleep, awake, &period_time, &period_percent); return scnprintf(buf, len, - "Applied: %s, Time: %llu (%llu) ms, Percent: %d%% (%d%%) Reason: %s, Rate: %d\n", + "Applied: %s, Time: %llu (%llu) ms, Percent: %d%% (%d%%) Reason: %s, Rate: %d", c->apply ? "TRUE" : "FALSE", period_time, total_time, period_percent, total_percent, reason2str[c->reason], c->rate); } -static void dytwt_mgmt_history_store(struct wlan_ptracker_client *client, - struct dytwt_manager *dytwt, struct wlan_scene_event *msg, bool apply) +static void dytwt_counter_update(struct dytwt_manager *dytwt, struct dytwt_pwr_state *pwr) +{ + struct dytwt_counters *counter = &dytwt->counters; + struct dytwt_statistic *stat = &counter->scene[dytwt->prev]; + u64 asleep = pwr->asleep - counter->prev_asleep; + u64 awake = pwr->awake - counter->prev_awake; + u64 count = pwr->count - counter->prev_asleep_cnt; + + stat->asleep += asleep; + stat->awake += awake; + counter->prev_asleep = pwr->asleep; + counter->prev_awake = pwr->awake; + counter->prev_asleep_cnt = pwr->count; + counter->total_awake += awake; + counter->total_sleep += asleep; + counter->total_sleep_cnt += count; +} + +static void dytwt_mgmt_history_store(struct wlan_ptracker_client *client, struct dytwt_manager *dytwt, + struct wlan_scene_event *msg, bool apply) { struct dytwt_entry *entry; @@ -181,10 +259,77 @@ static void dytwt_mgmt_history_store(struct wlan_ptracker_client *client, entry->reason = msg->reason; entry->rate = msg->rate; dytwt_client_twt_pwrstates(client, &entry->pwr); + dytwt_counter_update(dytwt, &entry->pwr); /* prev will be used for decided teardown or not. */ dytwt->prev = msg->dst; } +/* This function is running in thread context */ +static int _dytwt_scene_change_handler(struct dytwt_manager *dytwt, + struct wlan_ptracker_client *client) +{ + struct wlan_ptracker_core *core = client->core; + struct wlan_scene_event *msg = &core->fsm.msg; + struct dytwt_scene_action *act; + bool apply = false; + u32 state = msg->dst; + int ret = 0; + + if (!(dytwt->feature_flag & BIT(FEATURE_FLAG_TWT))) + goto out; + + if (!dytwt_client_twt_cap(client)) { + ptracker_dbg(dytwt->core, "twt is not supported on device or peer\n"); + goto out; + } + + act = &dytwt_actions[state]; + + /* follow action to setup */ + if (act->action == TWT_ACTION_SETUP) { + ret = dytwt_client_twt_setup(client, state); + } else { + /* tear down was applied at state of "perpare_change". */ + apply = true; + } + apply = ret ? false : true; +out: + /* store record of history even twt is not applied */ + dytwt_mgmt_history_store(client, dytwt, msg, apply); + ptracker_dbg(dytwt->core, "twt setup for state: %d, reason: %s, ret: %d\n", + state, reason2str[msg->reason], ret); + return ret; +} + +static void dytwt_delay_setup(struct work_struct *work) +{ + struct dytwt_manager *dytwt = dytwt_get_manager(); + struct wlan_ptracker_core *core = dytwt->core; + struct wlan_ptracker_client *client; + + if (!core) + return; + + rcu_read_lock(); + client = rcu_dereference(core->client); + _dytwt_scene_change_handler(dytwt, client); + rcu_read_unlock(); +} + +#define TWT_WAIT_STA_READY_TIME 1000 +static int dytwt_scene_change_handler(struct wlan_ptracker_client *client) +{ + struct dytwt_manager *dytwt = dytwt_get_manager(); + struct wlan_ptracker_core *core = client->core; + struct wlan_scene_event *msg = &core->fsm.msg; + + if (msg->reason == WLAN_PTRACKER_NOTIFY_STA_CONNECT) + schedule_delayed_work(&dytwt->setup_wq, msecs_to_jiffies(TWT_WAIT_STA_READY_TIME)); + else + _dytwt_scene_change_handler(dytwt, client); + return 0; +} + #define TWT_HISTORY_BUF_SIZE 10240 static ssize_t twt_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -196,7 +341,7 @@ static ssize_t twt_read(struct file *file, char __user *userbuf, size_t count, l buf = vmalloc(TWT_HISTORY_BUF_SIZE); if (!buf) - return 0; + return -ENOMEM; len = wlan_ptracker_history_read(dytwt->hm, buf, TWT_HISTORY_BUF_SIZE); ret = simple_read_from_buffer(userbuf, count, ppos, buf, len); @@ -204,28 +349,136 @@ static ssize_t twt_read(struct file *file, char __user *userbuf, size_t count, l return ret; } -static void update_twt_flag(struct wlan_ptracker_core *core) +static const struct file_operations twt_ops = { + .open = simple_open, + .read = twt_read, + .llseek = generic_file_llseek, +}; + +static void dytwt_force_twt_setup(struct wlan_ptracker_client *client, struct dytwt_manager *dytwt) +{ + int ret = 0; + bool apply = false; + u32 state = dytwt->state; + struct wlan_scene_event msg; + struct dytwt_scene_action *act = &dytwt_actions[state]; + + switch(act->action) { + case TWT_ACTION_SETUP: + ret = dytwt_client_twt_setup(client, state); + break; + case TWT_ACTION_TEARDOWN: + ret = dytwt_client_twt_teardown(client, state); + break; + default: + break; + } + apply = ret ? false : true; + msg.dst = dytwt->state; + /* store record of history even twt is not applied */ + dytwt_mgmt_history_store(client, dytwt, &msg, apply); +} + +static inline void twt_enable(struct wlan_ptracker_client *client, bool enable) { struct dytwt_manager *dytwt = dytwt_get_manager(); - if (dytwt->feature_flag & BIT(FEATURE_FLAG_TWT)) - dytwt->feature_flag &= ~BIT(FEATURE_FLAG_TWT); - else + if (enable) { dytwt->feature_flag |= BIT(FEATURE_FLAG_TWT); + dytwt_scene_change_handler(client); + } else { + dytwt->state = WLAN_SCENE_TPUT; + dytwt_force_twt_setup(client, dytwt); + dytwt->feature_flag &= ~BIT(FEATURE_FLAG_TWT); + } +} + +#define DYTWT_RUNTIME_TIMER 2000 +static void dytwt_runtime(struct work_struct *work) +{ + struct dytwt_manager *dytwt = dytwt_get_manager(); + struct dytwt_scene_action *act; + struct wlan_ptracker_client *client; + + if (!dytwt->core) + goto end; + + if (dytwt->prev == WLAN_SCENE_MAX) + goto end; + + rcu_read_lock(); + client = rcu_dereference(dytwt->core->client); + + if (!client) + goto unlock; + + act = &dytwt_actions[dytwt->prev]; + if (act->action == TWT_ACTION_SETUP && !dytwt_client_twt_cap(client)) { + dytwt->state = WLAN_SCENE_TPUT; + ptracker_dbg(dytwt->core, "teardown twt due to hit threshold\n"); + dytwt_force_twt_setup(client, dytwt); + } +unlock: + rcu_read_unlock(); +end: + schedule_delayed_work(&dytwt->wq, msecs_to_jiffies(DYTWT_RUNTIME_TIMER)); +} + +static void update_twt_flag(struct wlan_ptracker_core *core, struct dytwt_manager *dytwt) +{ + twt_enable(core->client, !(dytwt->feature_flag & BIT(FEATURE_FLAG_TWT))); +} + +static void update_twt_parameters(struct dytwt_manager *dytwt) +{ + u32 state = dytwt->state; + struct dytwt_scene_action *cfg_act = &dytwt_actions[WLAN_SCENE_MAX]; + struct dytwt_scene_action *cur_act = &dytwt_actions[state]; + + cur_act->param.wake_duration = cfg_act->param.wake_duration; + cur_act->param.wake_interval = cfg_act->param.wake_interval; + cur_act->action = cfg_act->action; +} + +static void dytwt_stats_dump(struct wlan_ptracker_client *client, struct dytwt_manager *dytwt) +{ + struct dytwt_stats stats; + struct wlan_ptracker_core *core = dytwt->core; + + stats.config_id = DYMAIC_TWT_CONFIG_ID; + dytwt_client_twt_get_stats(client, &stats); + + ptracker_info(core, "rx_ucast_pkts: %d, rx_pkts_retried: %d\n", + stats.rx_ucast_pkts, stats.rx_pkts_retried); + ptracker_info(core, "rx_pkt_sz_avg: %d, rx_pkts_avg: %d\n", + stats.rx_pkt_sz_avg, stats.rx_pkts_avg); + ptracker_info(core, "rx_pkts_min: %d, rx_pkts_max: %d\n", + stats.rx_pkts_min, stats.rx_pkts_max); + ptracker_info(core, "tx_ucast_pkts: %d, tx_failures: %d\n", + stats.tx_ucast_pkts, stats.tx_failures); + ptracker_info(core, "tx_pkt_sz_avg: %d, tx_pkts_avg: %d\n", + stats.tx_pkt_sz_avg, stats.tx_pkts_avg); + ptracker_info(core, "tx_pkts_min: %d, tx_pkts_max: %d\n", + stats.tx_pkts_min, stats.tx_pkts_max); + ptracker_info(core, "sp_seq: %d, eosp_count: %d, eosp_dur_avg: %d\n", + stats.sp_seq, stats.eosp_count, stats.eosp_dur_avg); } static int dytwt_debugfs_action(struct wlan_ptracker_core *core, u32 action) { struct dytwt_pwr_state pwr_state; struct dytwt_manager *dytwt = dytwt_get_manager(); - struct wlan_ptracker_client *client = core->client; + struct wlan_ptracker_client *client; + + rcu_read_lock(); + client = rcu_dereference(core->client); + + if (!client) + goto unlock; switch (action) { - case TWT_TEST_SETUP: - dytwt_client_twt_setup(client, dytwt->state); - break; - case TWT_TEST_TEARDOWN: - dytwt_client_twt_teardown(client, dytwt->state); + case TWT_TEST_FORCE_STATE: + dytwt_force_twt_setup(client, dytwt); break; case TWT_TEST_CAP: dytwt_client_twt_cap(client); @@ -234,16 +487,25 @@ static int dytwt_debugfs_action(struct wlan_ptracker_core *core, u32 action) dytwt_client_twt_pwrstates(client, &pwr_state); break; case TWT_TEST_ONOFF: - update_twt_flag(core); + update_twt_flag(core, dytwt); + break; + case TWT_TEST_SET_PARAM: + update_twt_parameters(dytwt); + break; + case TWT_TEST_DUMP_STATS: + dytwt_stats_dump(client, dytwt); break; default: ptracker_err(core, "action %d is not supported!\n", action); return -ENOTSUPP; } +unlock: + rcu_read_unlock(); return 0; } -static ssize_t twt_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos) +static ssize_t twt_params_write(struct file *file, const char __user *buf, size_t len, + loff_t *ppos) { struct wlan_ptracker_core *core = file->private_data; u32 action; @@ -254,71 +516,140 @@ static ssize_t twt_write(struct file *file, const char __user *buf, size_t len, return dytwt_debugfs_action(core, action); } -static const struct file_operations twt_ops = { +static int dytwt_params_read(char *buf, int len) +{ + struct dytwt_scene_action *act; + struct dytwt_setup_param *param; + int count = 0; + int i; + + count += scnprintf(buf + count, len - count, + "===================\n"); + for (i = 0 ; i < TWT_ACTION_SIZE; i++) { + act = &dytwt_actions[i]; + param = &act->param; + count += scnprintf(buf + count, len - count, + "state: %d, action: %d\n", i, act->action); + count += scnprintf(buf + count, len - count, + "config_id: %d, nego_type: %d\n", + param->config_id, param->nego_type); + count += scnprintf(buf + count, len - count, + "wake_interval: %u\n", param->wake_interval); + count += scnprintf(buf + count, len - count, + "wake_duration: %u\n", param->wake_duration); + count += scnprintf(buf + count, len - count, + "===================\n"); + } + return count; +} + +#define TWT_PARAM_BUF_SIZE 1024 +static ssize_t twt_params_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) +{ + char *buf; + int len; + int ret; + + buf = vmalloc(TWT_PARAM_BUF_SIZE); + if (!buf) + return -ENOMEM; + len = dytwt_params_read(buf, TWT_PARAM_BUF_SIZE); + ret = simple_read_from_buffer(userbuf, count, ppos, buf, len); + vfree(buf); + return ret; +} + +static const struct file_operations twt_params_ops = { .open = simple_open, - .read = twt_read, - .write = twt_write, + .read = twt_params_read, + .write = twt_params_write, .llseek = generic_file_llseek, }; -/* This function is running in thread context */ -#define TWT_WAIT_STA_READY_TIME 1000 -static int dytwt_scene_change_handler(struct wlan_ptracker_client *client) +static int dytwt_statistic_read(char *buf, int len) { - struct wlan_ptracker_core *core = client->core; - struct wlan_scene_event *msg = &core->fsm.msg; - struct dytwt_scene_action *act; struct dytwt_manager *dytwt = dytwt_get_manager(); - bool apply = false; - u32 state = msg->dst; - int ret = 0; - - if (!(dytwt->feature_flag & BIT(FEATURE_FLAG_TWT))) - goto out; - - if (!dytwt_client_twt_cap(client)) { - ptracker_dbg(core, "twt is not supported on device or peer\n"); - goto out; + struct dytwt_counters *counter = &dytwt->counters; + struct dytwt_statistic *ds; + struct dytwt_pwr_state pwr; + int buf_count = 0; + int i, percent; + u64 total, awake, asleep, count; + + buf_count += scnprintf(buf + buf_count, len - buf_count, + "==== Dynamic TWT Setup Statistics ===\n"); + dytwt_client_twt_pwrstates(dytwt->core->client, &pwr); + for (i = 0 ; i < WLAN_SCENE_MAX; i++) { + ds = &counter->scene[i]; + awake = ds->awake; + asleep = ds->asleep; + if (i == dytwt->prev) { + awake += pwr.awake - counter->prev_awake; + asleep += pwr.asleep - counter->prev_asleep; + } + dytwt_record_get_pwr(asleep, awake, &total, &percent); + buf_count += scnprintf(buf + buf_count, len - buf_count, + "%s, total: %llu, awake: %llu, asleep: %llu (%d%%)\n", state2str[i], total, + awake / 1000, asleep / 1000, percent); } - act = &dytwt_actions[state]; - ptracker_dbg(core, "twt setup for state: %d, reason: %s!\n", - state, reason2str[msg->reason]); + awake = counter->total_awake + pwr.awake - counter->prev_awake; + asleep = counter->total_sleep + pwr.asleep - counter->prev_asleep; + count = counter->total_sleep_cnt + pwr.count - counter->prev_asleep_cnt; + dytwt_record_get_pwr(asleep, awake, &total, &percent); + buf_count += scnprintf(buf + buf_count, len - buf_count, + "All, total: %llu, awake: %llu, asleep: %llu (%d%%), sleep cnt: %llu\n", + total, awake / 1000, asleep / 1000, percent, count); + return buf_count; +} - /* wait for sta ready after connected. */ - if (msg->reason == WLAN_PTRACKER_NOTIFY_STA_CHANGE) - msleep(TWT_WAIT_STA_READY_TIME); +#define TWT_STATISTIC_SIZE 512 +static ssize_t twt_statistic_read(struct file *file, char __user *userbuf, size_t count, + loff_t *ppos) +{ + char *buf; + int len; + int ret; - /* follow action to setup */ - if (act->action == TWT_ACTION_SETUP) { - ret = dytwt_client_twt_setup(client, state); - } else { - /* tear down was apply during state of perpare change. */ - apply = true; - } - apply = ret ? false : true; -out: - /* store record of hostory even twt is not applid! */ - dytwt_mgmt_history_store(client, dytwt, msg, apply); + buf = vmalloc(TWT_STATISTIC_SIZE); + if (!buf) + return -ENOMEM; + + len = dytwt_statistic_read(buf, TWT_STATISTIC_SIZE); + ret = simple_read_from_buffer(userbuf, count, ppos, buf, len); + vfree(buf); return ret; } +static const struct file_operations twt_statistic_ops = { + .open = simple_open, + .read = twt_statistic_read, + .llseek = generic_file_llseek, +}; + static void dytwt_scene_change_prepare_handler(struct wlan_ptracker_client *client) { struct dytwt_manager *dytwt = dytwt_get_manager(); + u32 prev_state = dytwt->prev; + + if (!(dytwt->feature_flag & BIT(FEATURE_FLAG_TWT))) + return; /* prepare to change state teardown original setup first */ - if (dytwt->prev < WLAN_SCENE_LOW_LATENCY) + if (dytwt_actions[prev_state].action == TWT_ACTION_SETUP) dytwt_client_twt_teardown(client, dytwt->prev); } static int dytwt_notifier_handler(struct notifier_block *nb, unsigned long event, void *ptr) { struct wlan_ptracker_core *core = ptr; - struct wlan_ptracker_client *client = core->client; + struct wlan_ptracker_client *client; + struct dytwt_manager *dytwt = dytwt_get_manager(); + rcu_read_lock(); + client = rcu_dereference(core->client); if (!client) - return NOTIFY_OK; + goto unlock; switch (event) { case WLAN_PTRACKER_NOTIFY_SCENE_CHANGE: @@ -327,9 +658,23 @@ static int dytwt_notifier_handler(struct notifier_block *nb, unsigned long event case WLAN_PTRACKER_NOTIFY_SCENE_CHANGE_PREPARE: dytwt_scene_change_prepare_handler(client); break; + case WLAN_PTRACKER_NOTIFY_STA_CONNECT: + schedule_delayed_work(&dytwt->wq, msecs_to_jiffies(DYTWT_RUNTIME_TIMER)); + break; + case WLAN_PTRACKER_NOTIFY_STA_DISCONNECT: + cancel_delayed_work_sync(&dytwt->wq); + break; + case WLAN_PTRACKER_NOTIFY_DYTWT_ENABLE: + twt_enable(client, true); + break; + case WLAN_PTRACKER_NOTIFY_DYTWT_DISABLE: + twt_enable(client, false); + break; default: break; } +unlock: + rcu_read_unlock(); return NOTIFY_OK; } @@ -337,18 +682,28 @@ static int dytwt_debugfs_init(struct wlan_ptracker_core *core) { struct wlan_ptracker_debugfs *debugfs = &core->debugfs; struct dytwt_manager *dytwt = dytwt_get_manager(); + struct dytwt_scene_action *act = &dytwt_actions[WLAN_SCENE_MAX]; dytwt->feature_flag |= BIT(FEATURE_FLAG_TWT); dytwt->dir = debugfs_create_dir("twt", debugfs->root); if (!dytwt->dir) return -ENODEV; - debugfs_create_file("history", 0600, dytwt->dir, core, &twt_ops); - debugfs_create_u32("state", 0600, dytwt->dir, &dytwt->state); + + debugfs_create_file("history", 0666, dytwt->dir, core, &twt_ops); + debugfs_create_file("statistics", 0666, dytwt->dir, core, &twt_statistic_ops); + debugfs_create_file("twt_params", 0666, dytwt->dir, core, &twt_params_ops); + debugfs_create_u32("state", 0666, dytwt->dir, &dytwt->state); + debugfs_create_u32("wake_interval", 0666, dytwt->dir, &act->param.wake_interval); + debugfs_create_u32("wake_duration", 0666, dytwt->dir, &act->param.wake_duration); + debugfs_create_u32("action", 0666, dytwt->dir, &act->action); + debugfs_create_u32("feature_flag", 0666, dytwt->dir, &dytwt->feature_flag); return 0; } -#define DYTWT_RECORD_MAX 50 -static int dytwt_mgmt_init(void) +#define TWT_DEFAULT_MIN_LINK_SPEED (90000) +#define TWT_DEFAULT_MIN_RSSI (-70) +#define DYTWT_RECORD_MAX 30 +static int dytwt_mgmt_init(struct wlan_ptracker_core *core) { struct dytwt_manager *dytwt = dytwt_get_manager(); struct history_manager *hm; @@ -358,6 +713,11 @@ static int dytwt_mgmt_init(void) memset(dytwt, 0, sizeof(*dytwt)); dytwt->state = WLAN_SCENE_IDLE; dytwt->prev = WLAN_SCENE_MAX; + dytwt->core = core; + dytwt->link_threshold = TWT_DEFAULT_MIN_LINK_SPEED; + dytwt->rssi_threshold = TWT_DEFAULT_MIN_RSSI; + INIT_DELAYED_WORK(&dytwt->wq, dytwt_runtime); + INIT_DELAYED_WORK(&dytwt->setup_wq, dytwt_delay_setup); hm = wlan_ptracker_history_create(DYTWT_RECORD_MAX, sizeof(struct dytwt_entry)); if (!hm) return -ENOMEM; @@ -371,6 +731,8 @@ static void dytwt_mgmt_exit(void) { struct dytwt_manager *dytwt = dytwt_get_manager(); + cancel_delayed_work_sync(&dytwt->wq); + cancel_delayed_work_sync(&dytwt->setup_wq); if (dytwt->dir) debugfs_remove_recursive(dytwt->dir); @@ -385,7 +747,7 @@ static struct notifier_block twt_nb = { int dytwt_init(struct wlan_ptracker_core *core) { - dytwt_mgmt_init(); + dytwt_mgmt_init(core); dytwt_debugfs_init(core); return wlan_ptracker_register_notifier(&core->notifier, &twt_nb); } @@ -395,4 +757,3 @@ void dytwt_exit(struct wlan_ptracker_core *core) dytwt_mgmt_exit(); return wlan_ptracker_unregister_notifier(&core->notifier, &twt_nb); } - diff --git a/dynamic_twt_manager.h b/dynamic_twt_manager.h index fe8b289..a7ecd55 100644 --- a/dynamic_twt_manager.h +++ b/dynamic_twt_manager.h @@ -25,11 +25,33 @@ struct dytwt_setup_param { struct dytwt_cap { u16 device_cap; u16 peer_cap; + u32 rssi; + int link_speed; }; struct dytwt_pwr_state { u64 awake; u64 asleep; + u64 count; +}; + +struct dytwt_stats { + u32 config_id; + u32 sp_seq; /* sequence number of the service period */ + u32 tx_ucast_pkts; /* Number of unicast Tx packets in TWT SPs */ + u32 tx_pkts_min; /* Minimum number of Tx packets in a TWT SP */ + u32 tx_pkts_max; /* Maximum number of Tx packets in a TWT SP */ + u32 tx_pkts_avg; /* Average number of Tx packets in each TWT SP */ + u32 tx_failures; /* Tx packets failure count */ + u32 rx_ucast_pkts; /* Number of unicast Rx packets in TWT SPs */ + u32 rx_pkts_min; /* Minimum number of Rx packets in a TWT SP */ + u32 rx_pkts_max; /* Maximum number of Rx packets in a TWT SP */ + u32 rx_pkts_avg; /* Average number of Rx packets in each TWT SP */ + u32 rx_pkts_retried; /* retried Rx packets count */ + u32 tx_pkt_sz_avg; /* Average Tx packet size in TWT SPs */ + u32 rx_pkt_sz_avg; /* Average Rx Packet size in TWT SPs */ + u32 eosp_dur_avg; /* Average Wake duration in SPs ended due to EOSP */ + u32 eosp_count; /* Count of TWT SPs ended due to EOSP */ }; struct dytwt_client_ops { @@ -37,6 +59,7 @@ struct dytwt_client_ops { int (*teardown)(void *priv, struct dytwt_setup_param *param); int (*get_cap)(void *priv, struct dytwt_cap *cap); int (*get_pwrstates)(void *priv, struct dytwt_pwr_state *state); + int (*get_stats)(void *priv, struct dytwt_stats *stats); }; enum { @@ -46,11 +69,12 @@ enum { }; enum { - TWT_TEST_SETUP, - TWT_TEST_TEARDOWN, + TWT_TEST_FORCE_STATE = 1, TWT_TEST_CAP, TWT_TEST_PWRSTATS, TWT_TEST_ONOFF, + TWT_TEST_SET_PARAM, + TWT_TEST_DUMP_STATS, TWT_TEST_MAX, }; @@ -68,12 +92,34 @@ struct dytwt_entry { struct dytwt_pwr_state pwr; } __align(void *); +struct dytwt_statistic { + u64 awake; + u64 asleep; +}; + +#define DYTWT_COUNTER_MAX 6 +#define DYTWT_COUNTER_TOTAL 5 +struct dytwt_counters { + u64 total_awake; + u64 total_sleep; + u64 total_sleep_cnt; + u64 prev_awake; + u64 prev_asleep; + u64 prev_asleep_cnt; + struct dytwt_statistic scene[DYTWT_COUNTER_MAX]; +}; struct dytwt_manager { u32 prev; u32 feature_flag; u32 state; struct history_manager *hm; + u32 rssi_threshold; + u32 link_threshold; + struct delayed_work wq; + struct delayed_work setup_wq; + struct wlan_ptracker_core *core; + struct dytwt_counters counters; struct dentry *dir; }; @@ -82,7 +82,9 @@ int wlan_ptracker_register_client(struct wlan_ptracker_client *client) struct wlan_ptracker_core *core = get_core(); if (!core->client) { - core->client = client; + rcu_read_lock(); + rcu_assign_pointer(core->client, client); + rcu_read_unlock(); client->cb = client_event_handler; } return 0; @@ -95,7 +97,9 @@ void wlan_ptracker_unregister_client(struct wlan_ptracker_client *client) if (core->client == client) { client->cb = NULL; - core->client = NULL; + rcu_read_lock(); + rcu_assign_pointer(core->client, NULL); + rcu_read_unlock(); } } EXPORT_SYMBOL_GPL(wlan_ptracker_unregister_client); diff --git a/scenes_fsm.c b/scenes_fsm.c index 991863e..768c75d 100644 --- a/scenes_fsm.c +++ b/scenes_fsm.c @@ -6,12 +6,12 @@ * * Author: Star Chang <starchang@google.com> */ +#include <linux/debugfs.h> #include "core.h" -#define fsm_to_core(fsm) \ - (container_of(fsm, struct wlan_ptracker_core, fsm)) +#define fsm_to_core(fsm) (container_of(fsm, struct wlan_ptracker_core, fsm)) -static const struct wlan_state_condition conditions[FSM_STATE_MAX] = { +static struct wlan_state_condition conditions[FSM_STATE_MAX] = { { .scene = WLAN_SCENE_IDLE, .ac_mask = WMM_AC_ALL_MASK, @@ -22,14 +22,13 @@ static const struct wlan_state_condition conditions[FSM_STATE_MAX] = { .scene = WLAN_SCENE_WEB, .ac_mask = WMM_AC_ALL_MASK, .min_tp_threshold = 1000, - .max_tp_threshold = 10000, + .max_tp_threshold = 9000, }, { .scene = WLAN_SCENE_YOUTUBE, .ac_mask = WMM_AC_ALL_MASK, - /* Total >= 10 Mbps && < 50 Mbps */ - .min_tp_threshold = 10000, - .max_tp_threshold = 50000, + .min_tp_threshold = 9000, + .max_tp_threshold = 60000, }, { .scene = WLAN_SCENE_LOW_LATENCY, @@ -41,8 +40,7 @@ static const struct wlan_state_condition conditions[FSM_STATE_MAX] = { { .scene = WLAN_SCENE_TPUT, .ac_mask = WMM_AC_ALL_MASK, - /* Total >= 50 Mbps */ - .min_tp_threshold = 50000, + .min_tp_threshold = 60000, .max_tp_threshold = __INT_MAX__, }, }; @@ -53,7 +51,7 @@ static int fsm_thread(void *param) struct wlan_scene_event *msg = &fsm->msg; struct wlan_ptracker_core *core = fsm_to_core(fsm); - while (1) { + while (fsm->thread_run) { set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) { ptracker_info(core, "kthread is stopped\n"); @@ -61,26 +59,14 @@ static int fsm_thread(void *param) } wait_for_completion(&fsm->event); ptracker_dbg(core, "state: %d, trans state %d -> %d, rate %llu\n", - msg->state, msg->src, msg->dst, msg->rate); - - /* - * Request twice of transmit events are happing then trans state, - * to make sure the state is stable enough. - * first time: confirm is false, send prepare first. - * (ex: twt can tear down original setup first) - * second time: confirm is true and change the state to dst. - */ - if (fsm->confirm) { - wlan_ptracker_call_chain(&core->notifier, - WLAN_PTRACKER_NOTIFY_SCENE_CHANGE, core); - msg->state = msg->dst; - fsm->confirm = false; - } else { - /* call notifier chain */ - wlan_ptracker_call_chain(&core->notifier, + msg->state, msg->src, msg->dst, msg->rate); + wlan_ptracker_call_chain(&core->notifier, WLAN_PTRACKER_NOTIFY_SCENE_CHANGE_PREPARE, core); - fsm->confirm = true; - } + fsm->confirm = true; + wlan_ptracker_call_chain(&core->notifier, + WLAN_PTRACKER_NOTIFY_SCENE_CHANGE, core); + msg->state = msg->dst; + fsm->confirm = false; } return 0; } @@ -149,15 +135,20 @@ static void scenes_fsm_decision(struct wlan_ptracker_core *core, u32 type) /* reset check */ if (type == WLAN_PTRACKER_NOTIFY_SUSPEND) { fsm->reset_cnt++; - except = !(fsm->reset_cnt % RESET_THRESHOLD); + except = (fsm->reset_cnt >= RESET_THRESHOLD) ? true : false; } /* check state isn't change and not first time do nothing */ - if (new_state == msg->state && type != WLAN_PTRACKER_NOTIFY_STA_CHANGE) + if (new_state == msg->state && + type != WLAN_PTRACKER_NOTIFY_STA_CONNECT) return; /* new state must higher then current state */ - if (new_state < msg->state && !except) + if (new_state < msg->state && !except) { + ptracker_dbg(core, + "state not change since new state %d < old state %d and reset_cnt is %d\n", + new_state, msg->state, fsm->reset_cnt); return; + } ptracker_dbg(core, "type %d, reset_cnt %d, %d -> %d\n", type, fsm->reset_cnt, msg->state, new_state); @@ -180,6 +171,7 @@ static int scene_notifier_handler(struct notifier_block *nb, { struct wlan_ptracker_core *core = ptr; struct wlan_ptracker_notifier *notifier = &core->notifier; + struct wlan_ptracker_fsm *fsm = &core->fsm; /* * Events of suspen and sta change will block wlan driver @@ -187,11 +179,14 @@ static int scene_notifier_handler(struct notifier_block *nb, */ switch (event) { case WLAN_PTRACKER_NOTIFY_SUSPEND: +#ifdef TP_DEBUG ptracker_dbg(core, "update time (%d)\n", jiffies_to_msecs(jiffies - notifier->prev_event)); +#endif notifier->prev_event = jiffies; - case WLAN_PTRACKER_NOTIFY_STA_CHANGE: + case WLAN_PTRACKER_NOTIFY_STA_CONNECT: case WLAN_PTRACKER_NOTIFY_TP: + fsm->confirm = true; scenes_fsm_decision(core, event); break; default: @@ -205,6 +200,107 @@ static struct notifier_block scene_nb = { .notifier_call = scene_notifier_handler, }; +static int scene_cond_set(struct wlan_ptracker_fsm *fsm) +{ + struct wlan_state_condition *param = &conditions[fsm->state]; + + param->ac_mask = fsm->ac_mask; + param->max_tp_threshold = fsm->max_tput; + param->min_tp_threshold = fsm->min_tput; + return 0; +} + +static int scene_debugfs_action(struct wlan_ptracker_core *core, u32 action) +{ + struct wlan_ptracker_fsm *fsm = &core->fsm; + switch (action) { + case SCENE_TEST_SET_PARAM: + scene_cond_set(fsm); + break; + default: + ptracker_err(core, "action %d is not supported\n", action); + break; + } + return 0; +} + +static ssize_t scene_params_write(struct file *file, + const char __user *buf, size_t len, loff_t *ppos) +{ + struct wlan_ptracker_core *core = file->private_data; + u32 action; + + if (kstrtouint_from_user(buf, len, 10, &action)) + return -EFAULT; + + /* active action */ + scene_debugfs_action(core, action); + return 0; +} + +static int _scene_params_read(char *buf, int len) +{ + struct wlan_state_condition *param; + int count = 0; + int i; + + count += scnprintf(buf + count, len - count, + "===================\n"); + for (i = 0 ; i < FSM_STATE_MAX; i++) { + param = &conditions[i]; + count += scnprintf(buf + count, len - count, + "state: %d, ac_mask: %#0X\n", i, param->ac_mask); + count += scnprintf(buf + count, len - count, + "min_tp_threshold: %u\n", param->min_tp_threshold); + count += scnprintf(buf + count, len - count, + "max_tp_threshold: %u\n", param->max_tp_threshold); + count += scnprintf(buf + count, len - count, + "===================\n"); + } + return count; +} + +#define SCENE_PARAM_BUF_SIZE 1024 +static ssize_t scene_params_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char *buf; + int len; + int ret; + + buf = vmalloc(SCENE_PARAM_BUF_SIZE); + if (!buf) + return -ENOMEM; + len = _scene_params_read(buf, SCENE_PARAM_BUF_SIZE); + ret = simple_read_from_buffer(userbuf, count, ppos, buf, len); + vfree(buf); + return ret; +} + +static const struct file_operations scene_params_ops = { + .open = simple_open, + .read = scene_params_read, + .write = scene_params_write, + .llseek = generic_file_llseek, +}; + +static int scene_debugfs_init(struct wlan_ptracker_core *core) +{ + struct wlan_ptracker_debugfs *debugfs = &core->debugfs; + struct wlan_ptracker_fsm *fsm = &core->fsm; + + fsm->dir = debugfs_create_dir("scene", debugfs->root); + if (!fsm->dir) + return -ENODEV; + + debugfs_create_file("scene_params", 0600, fsm->dir, core, &scene_params_ops); + debugfs_create_u32("state", 0600, fsm->dir, &fsm->state); + debugfs_create_u32("min_tput", 0600, fsm->dir, &fsm->min_tput); + debugfs_create_u32("max_tput", 0600, fsm->dir, &fsm->max_tput); + debugfs_create_u32("ac_mask", 0600, fsm->dir, &fsm->ac_mask); + return 0; +} + int scenes_fsm_init(struct wlan_ptracker_fsm *fsm) { struct wlan_scene_event *msg = &fsm->msg; @@ -221,6 +317,7 @@ int scenes_fsm_init(struct wlan_ptracker_fsm *fsm) msg->src = WLAN_SCENE_IDLE; msg->state = WLAN_SCENE_IDLE; mutex_init(&msg->lock); + scene_debugfs_init(core); /*scene event notifier handler from client */ ret = wlan_ptracker_register_notifier(&core->notifier, &scene_nb); @@ -236,6 +333,7 @@ int scenes_fsm_init(struct wlan_ptracker_fsm *fsm) ptracker_err(core, "unable to start kernel thread %d\n", ret); return ret; } + fsm->thread_run = true; wake_up_process(fsm->fsm_thread); return 0; } @@ -244,15 +342,18 @@ void scenes_fsm_exit(struct wlan_ptracker_fsm *fsm) { struct wlan_ptracker_core *core = fsm_to_core(fsm); + if (fsm->dir) + debugfs_remove_recursive(fsm->dir); + wlan_ptracker_unregister_notifier(&core->notifier, &scene_nb); + fsm->thread_run = false; + complete(&fsm->event); if (fsm->fsm_thread) { int ret = kthread_stop(fsm->fsm_thread); fsm->fsm_thread = NULL; if (ret) ptracker_err(core, "stop thread fail: %d\n", ret); } - complete(&fsm->event); fsm->conditions = NULL; fsm->reset_cnt = 0; } - diff --git a/scenes_fsm.h b/scenes_fsm.h index b79a78f..49b1a23 100644 --- a/scenes_fsm.h +++ b/scenes_fsm.h @@ -34,6 +34,11 @@ enum { FSM_STATE_MAX }; +enum { + SCENE_TEST_SET_PARAM, + SCENE_TEST_MAX, +}; + struct wlan_state_condition { u32 scene; u32 ac_mask; @@ -56,10 +61,17 @@ struct wlan_scene_event { struct wlan_ptracker_fsm { int reset_cnt; bool confirm; + bool thread_run; struct completion event; struct wlan_scene_event msg; struct task_struct *fsm_thread; const struct wlan_state_condition *conditions; + /* debug usage */ + struct dentry *dir; + u32 state; + u32 min_tput; + u32 max_tput; + u32 ac_mask; }; extern int scenes_fsm_init(struct wlan_ptracker_fsm *fsm); diff --git a/tp_monitor.c b/tp_monitor.c index 6e04d73..0fac073 100644 --- a/tp_monitor.c +++ b/tp_monitor.c @@ -28,6 +28,12 @@ static void tp_rate_pps_update(struct tp_monitor_counts *counts) count->pps = cur_cnt - count->pre_packet_cnt; count->pre_packet_cnt = cur_cnt; count->pre_packet_bytes = cur_bytes; +#ifdef TP_DEBUG + count->max_packet_bytes = max(count->max_packet_bytes, count->packet_bytes); + count->max_packet_cnt = max(count->max_packet_cnt, count->packet_cnt); + count->max_pps = max(count->max_pps, count->pps); + count->max_rate = max(count->max_rate, count->rate); +#endif /* TP_DEBUG */ } } @@ -141,10 +147,14 @@ static int tp_show(struct seq_file *s, void *unused) seq_printf(s, "AC %d ->\n", i); else seq_puts(s, "Total ->\n"); - seq_printf(s, "packet_cnt : %llu\n", counter->packet_cnt); - seq_printf(s, "packet_bytes : %llu\n", counter->packet_bytes); - seq_printf(s, "rate (Kbits) : %llu\n", counter->rate / 1000); - seq_printf(s, "pps : %llu\n", counter->pps); + seq_printf(s, "packet_cnt : %llu (%llu)\n", + counter->packet_cnt, counter->max_packet_cnt); + seq_printf(s, "packet_bytes : %llu (%llu)\n", + counter->packet_bytes, counter->max_packet_bytes); + seq_printf(s, "rate (Kbits) : %llu (%llu)\n", + counter->rate / 1000, counter->max_rate / 1000); + seq_printf(s, "pps : %llu (%llu)\n", + counter->pps, counter->pps); } return 0; } @@ -165,17 +175,26 @@ static int tp_monitor_debugfs_init(struct wlan_ptracker_core *core) { struct wlan_ptracker_debugfs *debugfs = &core->debugfs; struct tp_monitor_stats *stats = &core->tp; - struct wlan_ptracker_client *client = core->client; + struct wlan_ptracker_client *client; + int ret = 0; - if (!client) - return 0; + rcu_read_lock(); + client = rcu_dereference(core->client); + if (!client) { + ret = -ENODEV; + goto out; + } stats->dir = debugfs_create_dir(client->ifname, debugfs->root); - if (!stats->dir) - return -ENODEV; + if (!stats->dir) { + ret = -ENODEV; + goto out; + } debugfs_create_u32("log_level", 0600, stats->dir, &stats->debug); debugfs_create_file("tx", 0400, stats->dir, &stats->tx, &counter_ops); debugfs_create_file("rx", 0400, stats->dir, &stats->rx, &counter_ops); - return 0; +out: + rcu_read_unlock(); + return ret; } int tp_monitor_init(struct tp_monitor_stats *stats) diff --git a/tp_monitor.h b/tp_monitor.h index 05319a1..1694099 100644 --- a/tp_monitor.h +++ b/tp_monitor.h @@ -29,6 +29,10 @@ struct tp_monitor_counts { u64 pre_packet_cnt; u64 rate; u64 pps; + u64 max_pps; + u64 max_packet_cnt; + u64 max_packet_bytes; + u64 max_rate; }; struct tp_monitor_stats { diff --git a/wlan_ptracker_client.h b/wlan_ptracker_client.h index 4933960..c4cc3aa 100644 --- a/wlan_ptracker_client.h +++ b/wlan_ptracker_client.h @@ -18,10 +18,16 @@ enum { WLAN_PTRACKER_NOTIFY_SCENE_CHANGE, WLAN_PTRACKER_NOTIFY_SCENE_CHANGE_PREPARE, WLAN_PTRACKER_NOTIFY_SUSPEND, - WLAN_PTRACKER_NOTIFY_STA_CHANGE, + WLAN_PTRACKER_NOTIFY_STA_CONNECT, + WLAN_PTRACKER_NOTIFY_STA_DISCONNECT, + WLAN_PTRACKER_NOTIFY_DYTWT_ENABLE, + WLAN_PTRACKER_NOTIFY_DYTWT_DISABLE, WLAN_PTRACKER_NOTIFY_MAX, }; +/* backword compatible */ +#define WLAN_PTRACKER_NOTIFY_SUSPEN WLAN_PTRACKER_NOTIFY_SUSPEND + struct wlan_ptracker_client { void *priv; void *core; @@ -34,4 +40,3 @@ extern int wlan_ptracker_register_client(struct wlan_ptracker_client *client); extern void wlan_ptracker_unregister_client(struct wlan_ptracker_client *client); #endif /*__WLAN_PTRACKER_CLIENT_H*/ - |