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 37int hdf_cfgp2p_register_ndev(struct net_device *p2p_netdev, struct net_device *primary_netdev, struct wiphy *wiphy); 38int dhd_module_init(void); 39void dhd_module_exit(void); 40struct bcm_cfg80211; 41s32 wl_get_vif_macaddr(struct bcm_cfg80211 *cfg, u16 wl_iftype, u8 *mac_addr); 42 43struct NetDeviceInterFace *wal_get_net_p2p_ops(void); 44struct hdf_inf_map g_hdf_infmap[HDF_INF_MAX]; 45 46int g_hdf_ifidx = HDF_INF_WLAN0; 47int g_event_ifidx = HDF_INF_WLAN0; 48int g_scan_event_ifidx = HDF_INF_WLAN0; 49int g_conn_event_ifidx = HDF_INF_WLAN0; 50int g_mgmt_tx_event_ifidx = HDF_INF_P2P0; 51int bdh6_reset_driver_flag = 0; 52 53// BDH Wifi6 chip driver init 54int32_t InitBDH6Chip(struct HdfWlanDevice *device) 55{ 56 (void)device; 57 HDF_LOGW("bdh6: call InitBDH6Chip"); 58 return HDF_SUCCESS; 59} 60 61int32_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 71static 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 87int32_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 110static 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 137static 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 178int32_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 233int32_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