blob: cfded7ab1b179c1cda28814ab102995521c2f25e [file] [log] [blame]
Arun Kumar Khandavalli055ab702020-03-27 19:32:38 +05301/*
2 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16#include <qdf_hang_event_notifier.h>
17#include <qdf_notifier.h>
18#include <wlan_hdd_hang_event.h>
19#include <wlan_objmgr_vdev_obj.h>
20#include "wlan_hdd_object_manager.h"
21#include <qdf_types.h>
22
23struct hdd_hang_event_fixed_param {
Arun Kumar Khandavalli17d6d8f2020-08-12 17:34:41 +053024 uint16_t tlv_header;
Arun Kumar Khandavalli055ab702020-03-27 19:32:38 +053025 uint8_t vdev_id;
26 uint8_t vdev_opmode;
27 uint8_t vdev_state;
28 uint8_t vdev_substate;
29} qdf_packed;
30
31struct hdd_scan_fixed_param {
Arun Kumar Khandavalli17d6d8f2020-08-12 17:34:41 +053032 uint16_t tlv_header;
Arun Kumar Khandavalli055ab702020-03-27 19:32:38 +053033 uint8_t last_scan_reject_vdev_id;
34 enum scan_reject_states last_scan_reject_reason;
35 unsigned long last_scan_reject_timestamp;
36 uint8_t scan_reject_cnt;
37} qdf_packed;
38
39static int wlan_hdd_recovery_notifier_call(struct notifier_block *block,
40 unsigned long state,
41 void *data)
42{
43 qdf_notif_block *notif_block = qdf_container_of(block, qdf_notif_block,
44 notif_block);
45 struct hdd_context *hdd_ctx;
46 struct qdf_notifer_data *hdd_hang_data = data;
47 uint8_t *hdd_buf_ptr;
48 struct hdd_adapter *adapter;
49 uint32_t total_len;
50 struct wlan_objmgr_vdev *vdev;
51 struct hdd_hang_event_fixed_param *cmd;
52 struct hdd_scan_fixed_param *cmd_scan;
53
54 if (!data)
55 return NOTIFY_STOP_MASK;
56
57 hdd_ctx = notif_block->priv_data;
58 if (!hdd_ctx)
59 return NOTIFY_STOP_MASK;
60
Arun Kumar Khandavalli055ab702020-03-27 19:32:38 +053061 if (state == QDF_SCAN_ATTEMPT_FAILURES) {
62 total_len = sizeof(*cmd_scan);
63 hdd_buf_ptr = hdd_hang_data->hang_data + hdd_hang_data->offset;
Kai Liu0851b642020-10-20 20:03:27 +080064 if (hdd_hang_data->offset + total_len > QDF_WLAN_HANG_FW_OFFSET)
65 return NOTIFY_STOP_MASK;
Arun Kumar Khandavalli055ab702020-03-27 19:32:38 +053066 cmd_scan = (struct hdd_scan_fixed_param *)hdd_buf_ptr;
67 QDF_HANG_EVT_SET_HDR(&cmd_scan->tlv_header,
68 HANG_EVT_TAG_OS_IF_SCAN,
69 QDF_HANG_GET_STRUCT_TLVLEN(struct hdd_scan_fixed_param));
70 cmd_scan->last_scan_reject_vdev_id =
71 hdd_ctx->last_scan_reject_vdev_id;
72 cmd_scan->last_scan_reject_reason =
73 hdd_ctx->last_scan_reject_reason;
74 cmd_scan->scan_reject_cnt =
75 hdd_ctx->scan_reject_cnt;
76 hdd_hang_data->offset += total_len;
77 }
78
79 hdd_for_each_adapter_dev_held(hdd_ctx, adapter) {
80 vdev = hdd_objmgr_get_vdev(adapter);
81 if (!vdev) {
82 dev_put(adapter->dev);
83 continue;
84 }
85 total_len = sizeof(*cmd);
86 hdd_buf_ptr = hdd_hang_data->hang_data + hdd_hang_data->offset;
Kai Liu0851b642020-10-20 20:03:27 +080087 if (hdd_hang_data->offset + total_len >
88 QDF_WLAN_HANG_FW_OFFSET) {
89 hdd_objmgr_put_vdev(vdev);
90 dev_put(adapter->dev);
91 return NOTIFY_STOP_MASK;
92 }
Arun Kumar Khandavalli055ab702020-03-27 19:32:38 +053093 cmd = (struct hdd_hang_event_fixed_param *)hdd_buf_ptr;
94 QDF_HANG_EVT_SET_HDR(&cmd->tlv_header,
95 HANG_EVT_TAG_OS_IF,
96 QDF_HANG_GET_STRUCT_TLVLEN(struct hdd_hang_event_fixed_param));
97 cmd->vdev_id = wlan_vdev_get_id(vdev);
98 cmd->vdev_opmode = wlan_vdev_mlme_get_opmode(vdev);
99 cmd->vdev_state = wlan_vdev_mlme_get_state(vdev);
100 cmd->vdev_substate = wlan_vdev_mlme_get_substate(vdev);
101 hdd_hang_data->offset += total_len;
102 hdd_objmgr_put_vdev(vdev);
103 dev_put(adapter->dev);
104 }
105
106 return NOTIFY_OK;
107}
108
109static qdf_notif_block hdd_recovery_notifier = {
110 .notif_block.notifier_call = wlan_hdd_recovery_notifier_call,
111};
112
113QDF_STATUS wlan_hdd_hang_event_notifier_register(struct hdd_context *hdd_ctx)
114{
115 hdd_recovery_notifier.priv_data = hdd_ctx;
116 return qdf_hang_event_register_notifier(&hdd_recovery_notifier);
117}
118
119QDF_STATUS wlan_hdd_hang_event_notifier_unregister(void)
120{
121 return qdf_hang_event_unregister_notifier(&hdd_recovery_notifier);
122}