1 /*
2 * hdfinit_bdh.c
3 *
4 * hdf driver
5 *
6 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 #include <uapi/linux/nl80211.h>
24 #include <securec.h>
25 #include <asm/byteorder.h>
26 #include <linux/kernel.h>
27
28 #include "hdf_wifi_product.h"
29 #include "wifi_mac80211_ops.h"
30 #include "hdf_wlan_utils.h"
31 #include "hdf_wl_interface.h"
32 #include "net_bdh_adpater.h"
33 #include "hdf_public_ap6275s.h"
34 #include "eapol.h"
35
36 #define HDF_LOG_TAG BDH6Driver
37 int hdf_cfgp2p_register_ndev(struct net_device *p2p_netdev, struct net_device *primary_netdev, struct wiphy *wiphy);
38 int dhd_module_init(void);
39 void dhd_module_exit(void);
40 struct bcm_cfg80211;
41 s32 wl_get_vif_macaddr(struct bcm_cfg80211 *cfg, u16 wl_iftype, u8 *mac_addr);
42
43 struct NetDeviceInterFace *wal_get_net_p2p_ops(void);
44 struct hdf_inf_map g_hdf_infmap[HDF_INF_MAX];
45
46 int g_hdf_ifidx = HDF_INF_WLAN0;
47 int g_event_ifidx = HDF_INF_WLAN0;
48 int g_scan_event_ifidx = HDF_INF_WLAN0;
49 int g_conn_event_ifidx = HDF_INF_WLAN0;
50 int g_mgmt_tx_event_ifidx = HDF_INF_P2P0;
51 int bdh6_reset_driver_flag = 0;
52
53 // BDH Wifi6 chip driver init
InitBDH6Chip(struct HdfWlanDevice * device)54 int32_t InitBDH6Chip(struct HdfWlanDevice *device)
55 {
56 (void)device;
57 HDF_LOGW("bdh6: call InitBDH6Chip");
58 return HDF_SUCCESS;
59 }
60
DeinitBDH6Chip(struct HdfWlanDevice * device)61 int32_t DeinitBDH6Chip(struct HdfWlanDevice *device)
62 {
63 int32_t ret = HDF_SUCCESS;
64 (void)device;
65 if (ret != 0) {
66 HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret);
67 }
68 return ret;
69 }
70
HdfInfMapInit(void)71 static void HdfInfMapInit(void)
72 {
73 int32_t i = 0;
74
75 memset_s(g_hdf_infmap, sizeof(g_hdf_infmap), 0, sizeof(g_hdf_infmap));
76 for (i = 0; i < HDF_INF_MAX; i ++) {
77 INIT_WORK(&g_hdf_infmap[i].eapolEvent.eapol_report, eapol_report_handler);
78 NetBufQueueInit(&g_hdf_infmap[i].eapolEvent.eapolQueue);
79 g_hdf_infmap[i].eapolEvent.idx = i;
80 }
81 g_hdf_ifidx = HDF_INF_WLAN0; // master interface
82 }
83
84 #define WIFI_IMAGE_FILE_NAME "/vendor/etc/firmware/fw_bcm43752a2_ag.bin"
85 #define CK_WF_IMG_MAX_CNT 2
86 #define CK_WF_IMG_DELAY_MS 500
CheckWiFiImageFile(const char * filename)87 int32_t CheckWiFiImageFile(const char *filename)
88 {
89 struct file *fp = NULL;
90 int32_t icnt = 0;
91
92 while (icnt ++ <= CK_WF_IMG_MAX_CNT) {
93 fp = filp_open(filename, O_RDONLY, 0);
94 if (IS_ERR(fp)) {
95 HDF_LOGE("%s:open %s failed, cnt=%d, error=%d", __func__, filename, icnt, PTR_ERR(fp));
96 fp = NULL;
97 OsalMSleep(CK_WF_IMG_DELAY_MS);
98 } else {
99 filp_close(fp, NULL);
100 fp = NULL;
101 HDF_LOGE("%s:open %s success, cnt=%d", __func__, filename, icnt);
102 return 0;
103 }
104 }
105
106 HDF_LOGE("%s:open %s failed, cnt=%d reach to max times", __func__, filename, icnt);
107 return -1;
108 }
109
InitPrimaryInterface(struct NetDevice * netDevice,struct net_device * netdev)110 static int32_t InitPrimaryInterface(struct NetDevice *netDevice, struct net_device *netdev)
111 {
112 int32_t ret = 0;
113 int32_t private_data_size = 0;
114 struct HdfWifiNetDeviceData *data = NULL;
115 // Init primary interface wlan0
116
117 data = GetPlatformData(netDevice);
118 if (data == NULL) {
119 HDF_LOGE("%s:netdevice data null!", __func__);
120 return HDF_FAILURE;
121 }
122
123 hdf_bdh6_netdev_init(netDevice);
124 netDevice->classDriverPriv = data;
125 private_data_size = get_dhd_priv_data_size(); // create bdh6 private object
126 netDevice->mlPriv = kzalloc(private_data_size, GFP_KERNEL);
127 if (netDevice->mlPriv == NULL) {
128 HDF_LOGE("%s:kzalloc mlPriv failed", __func__);
129 return HDF_FAILURE;
130 }
131
132 set_krn_netdev(netDevice, netdev, g_hdf_ifidx);
133 dhd_module_init();
134 return HDF_SUCCESS;
135 }
136
InitP2pInterface(struct NetDevice * netDevice,struct net_device * netdev)137 static int32_t InitP2pInterface(struct NetDevice *netDevice, struct net_device *netdev)
138 {
139 int32_t ret = 0;
140 struct wiphy *wiphy = NULL;
141 struct net_device *p2p_netdev = NULL;
142 struct NetDevice *p2p_hnetdev = NULL;
143 struct bcm_cfg80211 *cfg = NULL;
144 WifiIfAdd ifAdd;
145
146 memset_s(&ifAdd, sizeof(ifAdd), 0, sizeof(ifAdd));
147 if (snprintf_s(ifAdd.ifName, IFNAMSIZ, IFNAMSIZ - 1, "p2p%d", 0) < 0) {
148 HDF_LOGE("%s:format ifName failed!", __func__);
149 return HDF_FAILURE;
150 }
151
152 ifAdd.type = NL80211_IFTYPE_P2P_DEVICE;
153 // Init interface p2p0
154 ret = P2pInitNetdev(netDevice, &ifAdd, sizeof(void *), HDF_INF_P2P0);
155 if (ret != 0) {
156 HDF_LOGE("%s:P2pInitNetdev %s failed", __func__, ifAdd.ifName);
157 return HDF_FAILURE;
158 }
159 wiphy = get_linux_wiphy_ndev(netdev);
160 if (wiphy == NULL) {
161 HDF_LOGE("%s:get wlan0 wiphy failed", __func__);
162 return HDF_FAILURE;
163 }
164 p2p_hnetdev = get_hdf_netdev(g_hdf_ifidx);
165 p2p_netdev = get_krn_netdev(g_hdf_ifidx);
166 p2p_netdev->ieee80211_ptr = NULL;
167 p2p_hnetdev->ieee80211Ptr = p2p_netdev->ieee80211_ptr;
168 cfg = wiphy_priv(wiphy); // update mac from wdev address
169 wl_get_vif_macaddr(cfg, 7, p2p_hnetdev->macAddr); // WL_IF_TYPE_P2P_DISC = 7
170 memcpy_s(p2p_netdev->dev_addr, p2p_netdev->addr_len, p2p_hnetdev->macAddr, MAC_ADDR_SIZE);
171 p2p_hnetdev->netDeviceIf = wal_get_net_p2p_ops(); // reset netdev_ops
172 hdf_cfgp2p_register_ndev(p2p_netdev, netdev, wiphy);
173 ret = NetDeviceAdd(p2p_hnetdev); // Call linux register_netdev()
174 HDF_LOGI("NetDeviceAdd %s ret = %d", p2p_hnetdev->name, ret);
175 return ret;
176 }
177
BDH6Init(struct HdfChipDriver * chipDriver,struct NetDevice * netDevice)178 int32_t BDH6Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
179 {
180 int32_t ret = 0;
181 struct net_device *netdev = NULL;
182 struct net_device *p2p_netdev = NULL;
183 struct NetDevice *p2p_hnetdev = NULL;
184
185 (void)chipDriver;
186 HDF_LOGI("bdh6: call BDH6Init");
187 HdfInfMapInit();
188
189 // Init primary interface wlan0
190 if (netDevice == NULL) {
191 HDF_LOGE("%s netdevice is null!", __func__);
192 return HDF_FAILURE;
193 }
194
195 netdev = GetLinuxInfByNetDevice(netDevice);
196 if (netdev == NULL) {
197 HDF_LOGE("%s net_device is null!", __func__);
198 return HDF_FAILURE;
199 }
200
201 ret = InitPrimaryInterface(netDevice, netdev);
202 if (ret != HDF_SUCCESS) {
203 return HDF_FAILURE;
204 }
205
206 ret = InitP2pInterface(netDevice, netdev);
207 if (ret != HDF_SUCCESS) {
208 return HDF_FAILURE;
209 }
210 p2p_hnetdev = get_hdf_netdev(g_hdf_ifidx);
211 p2p_netdev = get_krn_netdev(g_hdf_ifidx);
212
213 if (bdh6_reset_driver_flag) {
214 p2p_hnetdev->netDeviceIf->open(p2p_hnetdev);
215 rtnl_lock();
216 dev_open(netdev, NULL);
217 rtnl_unlock();
218 rtnl_lock();
219 dev_open(p2p_netdev, NULL);
220 rtnl_unlock();
221 rtnl_lock();
222 if (start_p2p_completed) {
223 start_p2p_completed = 0;
224 hdf_start_p2p_device();
225 }
226 rtnl_unlock();
227 bdh6_reset_driver_flag = 0;
228 HDF_LOGI("%s: reset driver ok", __func__);
229 }
230 return HDF_SUCCESS;
231 }
232
BDH6Deinit(struct HdfChipDriver * chipDriver,struct NetDevice * netDevice)233 int32_t BDH6Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
234 {
235 // free p2p0
236 int32_t i = 0;
237 struct NetDevice *p2p_hnetdev = get_hdf_netdev(HDF_INF_P2P0);
238 (void)chipDriver;
239 kfree(p2p_hnetdev->mlPriv);
240 p2p_hnetdev->mlPriv = NULL;
241 DestroyEapolData(p2p_hnetdev);
242 if (NetDeviceDelete(p2p_hnetdev) != 0) {
243 return HDF_FAILURE;
244 }
245 if (NetDeviceDeInit(p2p_hnetdev) != 0) {
246 return HDF_FAILURE;
247 }
248
249 hdf_bdh6_netdev_stop(netDevice);
250 dhd_module_exit();
251
252 // free primary wlan0
253 kfree(netDevice->mlPriv);
254 netDevice->mlPriv = NULL;
255 DestroyEapolData(netDevice);
256
257 for (i = 0; i < HDF_INF_MAX; i ++) {
258 cancel_work_sync(&g_hdf_infmap[i].eapolEvent.eapol_report);
259 NetBufQueueClear(&g_hdf_infmap[i].eapolEvent.eapolQueue);
260 }
261 bdh6_reset_driver_flag = 1;
262 HDF_LOGI("%s: ok", __func__);
263
264 return HDF_SUCCESS;
265 }
266
267