• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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