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