diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 216a758cfdc9..3868d80e5f85 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1676,6 +1676,47 @@ struct hdd_fw_ver_info { uint32_t crmid; }; +/** + * The logic for get current index of history is dependent on this + * value being power of 2. + */ +#define WLAN_HDD_ADAPTER_OPS_HISTORY_MAX 4 +QDF_COMPILE_TIME_ASSERT(adapter_ops_history_size, + (WLAN_HDD_ADAPTER_OPS_HISTORY_MAX & + (WLAN_HDD_ADAPTER_OPS_HISTORY_MAX - 1)) == 0); + +/** + * enum hdd_adapter_ops_event - events for adapter ops history + * @WLAN_HDD_ADAPTER_OPS_WORK_POST: adapter ops work posted + * @WLAN_HDD_ADAPTER_OPS_WORK_SCHED: adapter ops work scheduled + */ +enum hdd_adapter_ops_event { + WLAN_HDD_ADAPTER_OPS_WORK_POST, + WLAN_HDD_ADAPTER_OPS_WORK_SCHED, +}; + +/** + * struct hdd_adapter_ops_record - record of adapter ops history + * @timestamp: time of the occurrence of event + * @event: event + * @vdev_id: vdev id corresponding to the event + */ +struct hdd_adapter_ops_record { + uint64_t timestamp; + enum hdd_adapter_ops_event event; + int vdev_id; +}; + +/** + * struct hdd_adapter_ops_history - history of adapter ops + * @index: index to store the next event + * @entry: array of events + */ +struct hdd_adapter_ops_history { + qdf_atomic_t index; + struct hdd_adapter_ops_record entry[WLAN_HDD_ADAPTER_OPS_HISTORY_MAX]; +}; + /** * struct hdd_context - hdd shared driver and psoc/device context * @psoc: object manager psoc context @@ -2027,6 +2068,7 @@ struct hdd_context { } dp_agg_param; int current_pcie_gen_speed; qdf_workqueue_t *adapter_ops_wq; + struct hdd_adapter_ops_history adapter_ops_history; }; /** @@ -2101,6 +2143,50 @@ struct hdd_channel_info { * Function declarations and documentation */ +/** + * wlan_hdd_history_get_next_index() - get next index to store the history + entry + * @curr_idx: current index + * @max_entries: max entries in the history + * + * Returns: The index at which record is to be stored in history + */ +static inline uint32_t wlan_hdd_history_get_next_index(qdf_atomic_t *curr_idx, + uint32_t max_entries) +{ + uint32_t idx = qdf_atomic_inc_return(curr_idx); + + return idx & (max_entries - 1); +} + +/** + * hdd_adapter_ops_record_event() - record an entry in the adapter ops history + * @hdd_ctx: pointer to hdd context + * @event: event + * @vdev_id: vdev id corresponding to event + * + * Returns: None + */ +static inline void +hdd_adapter_ops_record_event(struct hdd_context *hdd_ctx, + enum hdd_adapter_ops_event event, + int vdev_id) +{ + struct hdd_adapter_ops_history *adapter_hist; + struct hdd_adapter_ops_record *record; + uint32_t idx; + + adapter_hist = &hdd_ctx->adapter_ops_history; + + idx = wlan_hdd_history_get_next_index(&adapter_hist->index, + WLAN_HDD_ADAPTER_OPS_HISTORY_MAX); + + record = &adapter_hist->entry[idx]; + record->event = event; + record->vdev_id = vdev_id; + record->timestamp = qdf_get_log_timestamp(); +} + /** * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo * @adapter: HDD adapter diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index d551b945dae9..3f78835a9f00 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2750,6 +2750,9 @@ static inline void hdd_netif_queue_enable(struct hdd_adapter *adapter) struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); if (cdp_cfg_get(soc, cfg_dp_disable_legacy_mode_csum_offload)) { + hdd_adapter_ops_record_event(hdd_ctx, + WLAN_HDD_ADAPTER_OPS_WORK_POST, + adapter->vdev_id); qdf_queue_work(0, hdd_ctx->adapter_ops_wq, &adapter->netdev_features_update_work); } else { diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 8a785f79928c..95ed1adf7bca 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -10081,10 +10081,20 @@ __hdd_adapter_param_update_work(struct hdd_adapter *adapter) */ static void hdd_adapter_param_update_work(void *arg) { + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); struct hdd_adapter *adapter = arg; struct osif_vdev_sync *vdev_sync; int errno; + if (!hdd_ctx) { + hdd_err("Invalid hdd context"); + return; + } + + hdd_adapter_ops_record_event(hdd_ctx, + WLAN_HDD_ADAPTER_OPS_WORK_SCHED, + WLAN_INVALID_VDEV_ID); + if (hdd_validate_adapter(adapter)) { hdd_err("netdev features update request for invalid adapter"); return; @@ -11968,6 +11978,7 @@ struct hdd_context *hdd_context_create(struct device *dev) goto err_deinit_hdd_context; hdd_set_wlan_logging(hdd_ctx); + qdf_atomic_init(&hdd_ctx->adapter_ops_history.index); skip_multicast_logging: hdd_set_trace_level_for_each(hdd_ctx);