1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cerrno>
17 #include <cstdint>
18 #include <fcntl.h>
19 #include <sys/socket.h>
20 #include <netlink/genl/genl.h>
21 #include <netlink/genl/family.h>
22 #include <netlink/genl/ctrl.h>
23 #include <linux/rtnetlink.h>
24 #include <netpacket/packet.h>
25 #include <linux/filter.h>
26 #include <linux/errqueue.h>
27 #include <linux/pkt_sched.h>
28 #include <netlink/object-api.h>
29 #include <netlink/netlink.h>
30 #include <netlink/socket.h>
31 #include <unistd.h>
32 #include "sync.h"
33 #include "wifi_hal.h"
34 #include "common.h"
35 #include "cpp_bindings.h"
36 #include <sys/stat.h>
37
38 #define ARRAYSIZE(a) (unsigned char)(sizeof(a) / sizeof((a)[0]))
39
40 #define HAL_VERSION "DEFAULT vendor HAL"
41
42 typedef enum {
43 LOGGER_ATTRIBUTE_INVALID = 0,
44 LOGGER_ATTRIBUTE_DRIVER_VER = 1,
45 LOGGER_ATTRIBUTE_FW_VER = 2,
46 LOGGER_ATTRIBUTE_RING_ID = 3,
47 LOGGER_ATTRIBUTE_RING_NAME = 4,
48 LOGGER_ATTRIBUTE_RING_FLAGS = 5,
49 LOGGER_ATTRIBUTE_LOG_LEVEL = 6,
50 LOGGER_ATTRIBUTE_LOG_TIME_INTVAL = 7,
51 LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE = 8,
52 LOGGER_ATTRIBUTE_FW_DUMP_LEN = 9,
53 LOGGER_ATTRIBUTE_FW_DUMP_DATA = 10,
54 LOGGER_ATTRIBUTE_FW_ERR_CODE = 11,
55 LOGGER_ATTRIBUTE_RING_DATA = 12,
56 LOGGER_ATTRIBUTE_RING_STATUS = 13,
57 LOGGER_ATTRIBUTE_RING_NUM = 14,
58 LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN = 15,
59 LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA = 16,
60 LOGGER_ATTRIBUTE_PKT_FATE_NUM = 17,
61 LOGGER_ATTRIBUTE_PKT_FATE_DATA = 18,
62 LOGGER_ATTRIBUTE_HANG_REASON = 19,
63 /* Add new attributes just above this */
64 LOGGER_ATTRIBUTE_MAX
65 } LOGGER_ATTRIBUTE;
66
67 constexpr int32_t HAL_RESTART_ID = 2;
68
69 class SetRestartHandler : public WifiCommand {
70 VendorHalRestartHandler mHandler;
71 char *mBuff;
72 public:
SetRestartHandler(wifiHandle handle,int id,VendorHalRestartHandler handler)73 SetRestartHandler(wifiHandle handle, int id, VendorHalRestartHandler handler)
74 : WifiCommand("SetRestartHandler", handle, id), mHandler(handler), mBuff(nullptr)
75 { }
Start()76 int Start()
77 {
78 HDF_LOGI("Start Restart Handler");
79 RegisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
80 return HAL_SUCCESS;
81 }
Cancel()82 int Cancel() override
83 {
84 HDF_LOGI("Clear Restart Handler");
85
86 /* unregister alert handler */
87 UnregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
88 WifiUnregisterCmd(WifiHandle(), Id());
89 HDF_LOGI("Success to clear restarthandler");
90 return HAL_SUCCESS;
91 }
92
HandleResponse(WifiEvent & reply)93 int HandleResponse(WifiEvent& reply) override
94 {
95 /* Nothing to do on response! */
96 return NL_OK;
97 }
98
HandleEvent(WifiEvent & event)99 int HandleEvent(WifiEvent& event) override
100 {
101 nlattr *vendorData = event.GetAttribute(NL80211_ATTR_VENDOR_DATA);
102 int len = event.GetVendorDataLen();
103 int eventId = event.GetVendorSubcmd();
104 HDF_LOGI("Got event: %d", eventId);
105
106 if (vendorData == nullptr || len == 0) {
107 HDF_LOGE("No Debug data found");
108 return NL_SKIP;
109 }
110 if (eventId == BRCM_VENDOR_EVENT_HANGED) {
111 for (NlIterator it(vendorData); it.HasNext(); it.Next()) {
112 if (it.GetType() == LOGGER_ATTRIBUTE_HANG_REASON) {
113 mBuff = (char *)it.GetData();
114 } else {
115 HDF_LOGI("Ignoring invalid attribute type = %d, size = %d",
116 it.GetType(), it.GetLen());
117 }
118 }
119
120 if (*mHandler.onVendorHalRestart) {
121 (*mHandler.onVendorHalRestart)(mBuff);
122 HDF_LOGI("Hang event received.");
123 } else {
124 HDF_LOGI("No Restart handler registered");
125 }
126 }
127 return NL_OK;
128 }
129 };
130
131 class SubSystemRestart : public WifiCommand {
132 public:
SubSystemRestart(wifiInterfaceHandle iface)133 explicit SubSystemRestart(wifiInterfaceHandle iface)
134 : WifiCommand("SubSystemRestart", iface, 0)
135 { }
136
CreateRequest(WifiRequest & request)137 int CreateRequest(WifiRequest& request)
138 {
139 int result = request.Create(HAL_OUI, WIFI_SUBCMD_TRIGGER_SSR);
140 if (result < 0) {
141 return result;
142 }
143
144 nlattr *data = request.AttrStart(NL80211_ATTR_VENDOR_DATA);
145
146 request.AttrEnd(data);
147 return HAL_SUCCESS;
148 }
149
Create()150 int Create() override
151 {
152 WifiRequest request(FamilyId(), IfaceId());
153
154 int result = CreateRequest(request);
155 if (result < 0) {
156 HDF_LOGE("Failed to create ssr request result = %d\n", result);
157 return result;
158 }
159
160 result = RequestResponse(request);
161 if (result != HAL_SUCCESS) {
162 HDF_LOGE("Failed to register ssr response; result = %d\n", result);
163 }
164 return result;
165 }
166
167 protected:
HandleResponse(WifiEvent & reply)168 int HandleResponse(WifiEvent& reply) override
169 {
170 /* Nothing to do on response! */
171 return NL_OK;
172 }
173
HandleEvent(WifiEvent & event)174 int HandleEvent(WifiEvent& event) override
175 {
176 /* NO events to handle here! */
177 return NL_SKIP;
178 }
179 };
180
VendorHalSetRestartHandler(wifiHandle handle,VendorHalRestartHandler handler)181 WifiError VendorHalSetRestartHandler(wifiHandle handle, VendorHalRestartHandler handler)
182 {
183 HalInfo *info = nullptr;
184
185 info = (HalInfo *)handle;
186 if (info == nullptr) {
187 HDF_LOGE("Could not find hal info\n");
188 return HAL_UNKNOWN;
189 }
190
191 SetRestartHandler *cmd = new SetRestartHandler(handle, HAL_RESTART_ID, handler);
192 NULL_CHECK_RETURN(cmd, "memory allocation failure", HAL_OUT_OF_MEMORY);
193 WifiError result = WifiRegisterCmd(handle, HAL_RESTART_ID, cmd);
194 if (result != HAL_SUCCESS) {
195 cmd->ReleaseRef();
196 return result;
197 }
198
199 result = (WifiError)cmd->Start();
200 if (result != HAL_SUCCESS) {
201 WifiUnregisterCmd(handle, HAL_RESTART_ID);
202 cmd->ReleaseRef();
203 return result;
204 }
205
206 /* Cache the handler to use it for trigger subsystem restart */
207 HDF_LOGI("Register SSR handler");
208 info->restartHandler = handler;
209 return result;
210 }
211
TriggerVendorHalRestart(wifiHandle handle)212 WifiError TriggerVendorHalRestart(wifiHandle handle)
213 {
214 WifiError result = HAL_SUCCESS;
215 HalInfo *info = nullptr;
216 char errorStr[20];
217 SubSystemRestart *cmd = nullptr;
218 wifiInterfaceHandle *ifaceHandles = nullptr;
219 wifiInterfaceHandle wlan0Handle;
220 int numIfaceHandles = 0;
221
222 info = (HalInfo *)handle;
223 if (handle == NULL || info == nullptr) {
224 HDF_LOGE("Could not find hal info\n");
225 result = HAL_UNKNOWN;
226 goto exit;
227 }
228
229 HDF_LOGI("Trigger subsystem restart\n");
230
231 wlan0Handle = WifiGetWlanInterface((wifiHandle)handle, ifaceHandles, numIfaceHandles);
232
233 cmd = new SubSystemRestart(wlan0Handle);
234 NULL_CHECK_RETURN(cmd, "memory allocation failure", HAL_OUT_OF_MEMORY);
235
236 result = (WifiError)cmd->Create();
237 if (result != HAL_SUCCESS) {
238 cmd->ReleaseRef();
239 if (strncpy_s(errorStr, sizeof(errorStr), "HAL_UNKNOWN", sizeof("HAL_UNKNOWN")) != EOK) {
240 return result;
241 }
242 HDF_LOGE("Failed to create SSR");
243 return result;
244 }
245
246 if (strncpy_s(errorStr, sizeof(errorStr), "HAL_SUCCESS", sizeof("HAL_SUCCESS")) != EOK) {
247 goto exit;
248 }
249
250 exit:
251 if (cmd != nullptr) {
252 cmd->ReleaseRef();
253 }
254 if (info->restartHandler.onVendorHalRestart) {
255 HDF_LOGI("Trigger ssr handler registered handler");
256 (info->restartHandler.onVendorHalRestart)(errorStr);
257 } else {
258 HDF_LOGI("No trigger ssr handler registered");
259 }
260 return result;
261 }