18d6344f9Sopenharmony_ci/* 28d6344f9Sopenharmony_ci * hdfinit_bdh.c 38d6344f9Sopenharmony_ci * 48d6344f9Sopenharmony_ci * hdf driver 58d6344f9Sopenharmony_ci * 68d6344f9Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 78d6344f9Sopenharmony_ci * 88d6344f9Sopenharmony_ci * This program is free software; you can redistribute it and/or 98d6344f9Sopenharmony_ci * modify it under the terms of the GNU General Public License 108d6344f9Sopenharmony_ci * as published by the Free Software Foundation; either version 2 118d6344f9Sopenharmony_ci * of the License, or (at your option) any later version. 128d6344f9Sopenharmony_ci * 138d6344f9Sopenharmony_ci * This program is distributed in the hope that it will be useful, 148d6344f9Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 158d6344f9Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 168d6344f9Sopenharmony_ci * GNU General Public License for more details. 178d6344f9Sopenharmony_ci * 188d6344f9Sopenharmony_ci * You should have received a copy of the GNU General Public License 198d6344f9Sopenharmony_ci * along with this program; if not, write to the Free Software 208d6344f9Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 218d6344f9Sopenharmony_ci */ 228d6344f9Sopenharmony_ci 238d6344f9Sopenharmony_ci#include <uapi/linux/nl80211.h> 248d6344f9Sopenharmony_ci#include <securec.h> 258d6344f9Sopenharmony_ci#include <asm/byteorder.h> 268d6344f9Sopenharmony_ci#include <linux/kernel.h> 278d6344f9Sopenharmony_ci 288d6344f9Sopenharmony_ci#include "hdf_wifi_product.h" 298d6344f9Sopenharmony_ci#include "wifi_mac80211_ops.h" 308d6344f9Sopenharmony_ci#include "hdf_wlan_utils.h" 318d6344f9Sopenharmony_ci#include "hdf_wl_interface.h" 328d6344f9Sopenharmony_ci#include "net_bdh_adpater.h" 338d6344f9Sopenharmony_ci#include "hdf_public_ap6275s.h" 348d6344f9Sopenharmony_ci#include "eapol.h" 358d6344f9Sopenharmony_ci 368d6344f9Sopenharmony_ci#define HDF_LOG_TAG BDH6Driver 378d6344f9Sopenharmony_ciint hdf_cfgp2p_register_ndev(struct net_device *p2p_netdev, struct net_device *primary_netdev, struct wiphy *wiphy); 388d6344f9Sopenharmony_ciint dhd_module_init(void); 398d6344f9Sopenharmony_civoid dhd_module_exit(void); 408d6344f9Sopenharmony_cistruct bcm_cfg80211; 418d6344f9Sopenharmony_cis32 wl_get_vif_macaddr(struct bcm_cfg80211 *cfg, u16 wl_iftype, u8 *mac_addr); 428d6344f9Sopenharmony_ci 438d6344f9Sopenharmony_cistruct NetDeviceInterFace *wal_get_net_p2p_ops(void); 448d6344f9Sopenharmony_cistruct hdf_inf_map g_hdf_infmap[HDF_INF_MAX]; 458d6344f9Sopenharmony_ci 468d6344f9Sopenharmony_ciint g_hdf_ifidx = HDF_INF_WLAN0; 478d6344f9Sopenharmony_ciint g_event_ifidx = HDF_INF_WLAN0; 488d6344f9Sopenharmony_ciint g_scan_event_ifidx = HDF_INF_WLAN0; 498d6344f9Sopenharmony_ciint g_conn_event_ifidx = HDF_INF_WLAN0; 508d6344f9Sopenharmony_ciint g_mgmt_tx_event_ifidx = HDF_INF_P2P0; 518d6344f9Sopenharmony_ciint bdh6_reset_driver_flag = 0; 528d6344f9Sopenharmony_ci 538d6344f9Sopenharmony_ci// BDH Wifi6 chip driver init 548d6344f9Sopenharmony_ciint32_t InitBDH6Chip(struct HdfWlanDevice *device) 558d6344f9Sopenharmony_ci{ 568d6344f9Sopenharmony_ci (void)device; 578d6344f9Sopenharmony_ci HDF_LOGW("bdh6: call InitBDH6Chip"); 588d6344f9Sopenharmony_ci return HDF_SUCCESS; 598d6344f9Sopenharmony_ci} 608d6344f9Sopenharmony_ci 618d6344f9Sopenharmony_ciint32_t DeinitBDH6Chip(struct HdfWlanDevice *device) 628d6344f9Sopenharmony_ci{ 638d6344f9Sopenharmony_ci int32_t ret = HDF_SUCCESS; 648d6344f9Sopenharmony_ci (void)device; 658d6344f9Sopenharmony_ci if (ret != 0) { 668d6344f9Sopenharmony_ci HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); 678d6344f9Sopenharmony_ci } 688d6344f9Sopenharmony_ci return ret; 698d6344f9Sopenharmony_ci} 708d6344f9Sopenharmony_ci 718d6344f9Sopenharmony_cistatic void HdfInfMapInit(void) 728d6344f9Sopenharmony_ci{ 738d6344f9Sopenharmony_ci int32_t i = 0; 748d6344f9Sopenharmony_ci 758d6344f9Sopenharmony_ci memset_s(g_hdf_infmap, sizeof(g_hdf_infmap), 0, sizeof(g_hdf_infmap)); 768d6344f9Sopenharmony_ci for (i = 0; i < HDF_INF_MAX; i ++) { 778d6344f9Sopenharmony_ci INIT_WORK(&g_hdf_infmap[i].eapolEvent.eapol_report, eapol_report_handler); 788d6344f9Sopenharmony_ci NetBufQueueInit(&g_hdf_infmap[i].eapolEvent.eapolQueue); 798d6344f9Sopenharmony_ci g_hdf_infmap[i].eapolEvent.idx = i; 808d6344f9Sopenharmony_ci } 818d6344f9Sopenharmony_ci g_hdf_ifidx = HDF_INF_WLAN0; // master interface 828d6344f9Sopenharmony_ci} 838d6344f9Sopenharmony_ci 848d6344f9Sopenharmony_ci#define WIFI_IMAGE_FILE_NAME "/vendor/etc/firmware/fw_bcm43752a2_ag.bin" 858d6344f9Sopenharmony_ci#define CK_WF_IMG_MAX_CNT 2 868d6344f9Sopenharmony_ci#define CK_WF_IMG_DELAY_MS 500 878d6344f9Sopenharmony_ciint32_t CheckWiFiImageFile(const char *filename) 888d6344f9Sopenharmony_ci{ 898d6344f9Sopenharmony_ci struct file *fp = NULL; 908d6344f9Sopenharmony_ci int32_t icnt = 0; 918d6344f9Sopenharmony_ci 928d6344f9Sopenharmony_ci while (icnt ++ <= CK_WF_IMG_MAX_CNT) { 938d6344f9Sopenharmony_ci fp = filp_open(filename, O_RDONLY, 0); 948d6344f9Sopenharmony_ci if (IS_ERR(fp)) { 958d6344f9Sopenharmony_ci HDF_LOGE("%s:open %s failed, cnt=%d, error=%d", __func__, filename, icnt, PTR_ERR(fp)); 968d6344f9Sopenharmony_ci fp = NULL; 978d6344f9Sopenharmony_ci OsalMSleep(CK_WF_IMG_DELAY_MS); 988d6344f9Sopenharmony_ci } else { 998d6344f9Sopenharmony_ci filp_close(fp, NULL); 1008d6344f9Sopenharmony_ci fp = NULL; 1018d6344f9Sopenharmony_ci HDF_LOGE("%s:open %s success, cnt=%d", __func__, filename, icnt); 1028d6344f9Sopenharmony_ci return 0; 1038d6344f9Sopenharmony_ci } 1048d6344f9Sopenharmony_ci } 1058d6344f9Sopenharmony_ci 1068d6344f9Sopenharmony_ci HDF_LOGE("%s:open %s failed, cnt=%d reach to max times", __func__, filename, icnt); 1078d6344f9Sopenharmony_ci return -1; 1088d6344f9Sopenharmony_ci} 1098d6344f9Sopenharmony_ci 1108d6344f9Sopenharmony_cistatic int32_t InitPrimaryInterface(struct NetDevice *netDevice, struct net_device *netdev) 1118d6344f9Sopenharmony_ci{ 1128d6344f9Sopenharmony_ci int32_t ret = 0; 1138d6344f9Sopenharmony_ci int32_t private_data_size = 0; 1148d6344f9Sopenharmony_ci struct HdfWifiNetDeviceData *data = NULL; 1158d6344f9Sopenharmony_ci // Init primary interface wlan0 1168d6344f9Sopenharmony_ci 1178d6344f9Sopenharmony_ci data = GetPlatformData(netDevice); 1188d6344f9Sopenharmony_ci if (data == NULL) { 1198d6344f9Sopenharmony_ci HDF_LOGE("%s:netdevice data null!", __func__); 1208d6344f9Sopenharmony_ci return HDF_FAILURE; 1218d6344f9Sopenharmony_ci } 1228d6344f9Sopenharmony_ci 1238d6344f9Sopenharmony_ci hdf_bdh6_netdev_init(netDevice); 1248d6344f9Sopenharmony_ci netDevice->classDriverPriv = data; 1258d6344f9Sopenharmony_ci private_data_size = get_dhd_priv_data_size(); // create bdh6 private object 1268d6344f9Sopenharmony_ci netDevice->mlPriv = kzalloc(private_data_size, GFP_KERNEL); 1278d6344f9Sopenharmony_ci if (netDevice->mlPriv == NULL) { 1288d6344f9Sopenharmony_ci HDF_LOGE("%s:kzalloc mlPriv failed", __func__); 1298d6344f9Sopenharmony_ci return HDF_FAILURE; 1308d6344f9Sopenharmony_ci } 1318d6344f9Sopenharmony_ci 1328d6344f9Sopenharmony_ci set_krn_netdev(netDevice, netdev, g_hdf_ifidx); 1338d6344f9Sopenharmony_ci dhd_module_init(); 1348d6344f9Sopenharmony_ci return HDF_SUCCESS; 1358d6344f9Sopenharmony_ci} 1368d6344f9Sopenharmony_ci 1378d6344f9Sopenharmony_cistatic int32_t InitP2pInterface(struct NetDevice *netDevice, struct net_device *netdev) 1388d6344f9Sopenharmony_ci{ 1398d6344f9Sopenharmony_ci int32_t ret = 0; 1408d6344f9Sopenharmony_ci struct wiphy *wiphy = NULL; 1418d6344f9Sopenharmony_ci struct net_device *p2p_netdev = NULL; 1428d6344f9Sopenharmony_ci struct NetDevice *p2p_hnetdev = NULL; 1438d6344f9Sopenharmony_ci struct bcm_cfg80211 *cfg = NULL; 1448d6344f9Sopenharmony_ci WifiIfAdd ifAdd; 1458d6344f9Sopenharmony_ci 1468d6344f9Sopenharmony_ci memset_s(&ifAdd, sizeof(ifAdd), 0, sizeof(ifAdd)); 1478d6344f9Sopenharmony_ci if (snprintf_s(ifAdd.ifName, IFNAMSIZ, IFNAMSIZ - 1, "p2p%d", 0) < 0) { 1488d6344f9Sopenharmony_ci HDF_LOGE("%s:format ifName failed!", __func__); 1498d6344f9Sopenharmony_ci return HDF_FAILURE; 1508d6344f9Sopenharmony_ci } 1518d6344f9Sopenharmony_ci 1528d6344f9Sopenharmony_ci ifAdd.type = NL80211_IFTYPE_P2P_DEVICE; 1538d6344f9Sopenharmony_ci // Init interface p2p0 1548d6344f9Sopenharmony_ci ret = P2pInitNetdev(netDevice, &ifAdd, sizeof(void *), HDF_INF_P2P0); 1558d6344f9Sopenharmony_ci if (ret != 0) { 1568d6344f9Sopenharmony_ci HDF_LOGE("%s:P2pInitNetdev %s failed", __func__, ifAdd.ifName); 1578d6344f9Sopenharmony_ci return HDF_FAILURE; 1588d6344f9Sopenharmony_ci } 1598d6344f9Sopenharmony_ci wiphy = get_linux_wiphy_ndev(netdev); 1608d6344f9Sopenharmony_ci if (wiphy == NULL) { 1618d6344f9Sopenharmony_ci HDF_LOGE("%s:get wlan0 wiphy failed", __func__); 1628d6344f9Sopenharmony_ci return HDF_FAILURE; 1638d6344f9Sopenharmony_ci } 1648d6344f9Sopenharmony_ci p2p_hnetdev = get_hdf_netdev(g_hdf_ifidx); 1658d6344f9Sopenharmony_ci p2p_netdev = get_krn_netdev(g_hdf_ifidx); 1668d6344f9Sopenharmony_ci p2p_netdev->ieee80211_ptr = NULL; 1678d6344f9Sopenharmony_ci p2p_hnetdev->ieee80211Ptr = p2p_netdev->ieee80211_ptr; 1688d6344f9Sopenharmony_ci cfg = wiphy_priv(wiphy); // update mac from wdev address 1698d6344f9Sopenharmony_ci wl_get_vif_macaddr(cfg, 7, p2p_hnetdev->macAddr); // WL_IF_TYPE_P2P_DISC = 7 1708d6344f9Sopenharmony_ci memcpy_s(p2p_netdev->dev_addr, p2p_netdev->addr_len, p2p_hnetdev->macAddr, MAC_ADDR_SIZE); 1718d6344f9Sopenharmony_ci p2p_hnetdev->netDeviceIf = wal_get_net_p2p_ops(); // reset netdev_ops 1728d6344f9Sopenharmony_ci hdf_cfgp2p_register_ndev(p2p_netdev, netdev, wiphy); 1738d6344f9Sopenharmony_ci ret = NetDeviceAdd(p2p_hnetdev); // Call linux register_netdev() 1748d6344f9Sopenharmony_ci HDF_LOGI("NetDeviceAdd %s ret = %d", p2p_hnetdev->name, ret); 1758d6344f9Sopenharmony_ci return ret; 1768d6344f9Sopenharmony_ci} 1778d6344f9Sopenharmony_ci 1788d6344f9Sopenharmony_ciint32_t BDH6Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) 1798d6344f9Sopenharmony_ci{ 1808d6344f9Sopenharmony_ci int32_t ret = 0; 1818d6344f9Sopenharmony_ci struct net_device *netdev = NULL; 1828d6344f9Sopenharmony_ci struct net_device *p2p_netdev = NULL; 1838d6344f9Sopenharmony_ci struct NetDevice *p2p_hnetdev = NULL; 1848d6344f9Sopenharmony_ci 1858d6344f9Sopenharmony_ci (void)chipDriver; 1868d6344f9Sopenharmony_ci HDF_LOGI("bdh6: call BDH6Init"); 1878d6344f9Sopenharmony_ci HdfInfMapInit(); 1888d6344f9Sopenharmony_ci 1898d6344f9Sopenharmony_ci // Init primary interface wlan0 1908d6344f9Sopenharmony_ci if (netDevice == NULL) { 1918d6344f9Sopenharmony_ci HDF_LOGE("%s netdevice is null!", __func__); 1928d6344f9Sopenharmony_ci return HDF_FAILURE; 1938d6344f9Sopenharmony_ci } 1948d6344f9Sopenharmony_ci 1958d6344f9Sopenharmony_ci netdev = GetLinuxInfByNetDevice(netDevice); 1968d6344f9Sopenharmony_ci if (netdev == NULL) { 1978d6344f9Sopenharmony_ci HDF_LOGE("%s net_device is null!", __func__); 1988d6344f9Sopenharmony_ci return HDF_FAILURE; 1998d6344f9Sopenharmony_ci } 2008d6344f9Sopenharmony_ci 2018d6344f9Sopenharmony_ci ret = InitPrimaryInterface(netDevice, netdev); 2028d6344f9Sopenharmony_ci if (ret != HDF_SUCCESS) { 2038d6344f9Sopenharmony_ci return HDF_FAILURE; 2048d6344f9Sopenharmony_ci } 2058d6344f9Sopenharmony_ci 2068d6344f9Sopenharmony_ci ret = InitP2pInterface(netDevice, netdev); 2078d6344f9Sopenharmony_ci if (ret != HDF_SUCCESS) { 2088d6344f9Sopenharmony_ci return HDF_FAILURE; 2098d6344f9Sopenharmony_ci } 2108d6344f9Sopenharmony_ci p2p_hnetdev = get_hdf_netdev(g_hdf_ifidx); 2118d6344f9Sopenharmony_ci p2p_netdev = get_krn_netdev(g_hdf_ifidx); 2128d6344f9Sopenharmony_ci 2138d6344f9Sopenharmony_ci if (bdh6_reset_driver_flag) { 2148d6344f9Sopenharmony_ci p2p_hnetdev->netDeviceIf->open(p2p_hnetdev); 2158d6344f9Sopenharmony_ci rtnl_lock(); 2168d6344f9Sopenharmony_ci dev_open(netdev, NULL); 2178d6344f9Sopenharmony_ci rtnl_unlock(); 2188d6344f9Sopenharmony_ci rtnl_lock(); 2198d6344f9Sopenharmony_ci dev_open(p2p_netdev, NULL); 2208d6344f9Sopenharmony_ci rtnl_unlock(); 2218d6344f9Sopenharmony_ci rtnl_lock(); 2228d6344f9Sopenharmony_ci if (start_p2p_completed) { 2238d6344f9Sopenharmony_ci start_p2p_completed = 0; 2248d6344f9Sopenharmony_ci hdf_start_p2p_device(); 2258d6344f9Sopenharmony_ci } 2268d6344f9Sopenharmony_ci rtnl_unlock(); 2278d6344f9Sopenharmony_ci bdh6_reset_driver_flag = 0; 2288d6344f9Sopenharmony_ci HDF_LOGI("%s: reset driver ok", __func__); 2298d6344f9Sopenharmony_ci } 2308d6344f9Sopenharmony_ci return HDF_SUCCESS; 2318d6344f9Sopenharmony_ci} 2328d6344f9Sopenharmony_ci 2338d6344f9Sopenharmony_ciint32_t BDH6Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) 2348d6344f9Sopenharmony_ci{ 2358d6344f9Sopenharmony_ci // free p2p0 2368d6344f9Sopenharmony_ci int32_t i = 0; 2378d6344f9Sopenharmony_ci struct NetDevice *p2p_hnetdev = get_hdf_netdev(HDF_INF_P2P0); 2388d6344f9Sopenharmony_ci (void)chipDriver; 2398d6344f9Sopenharmony_ci kfree(p2p_hnetdev->mlPriv); 2408d6344f9Sopenharmony_ci p2p_hnetdev->mlPriv = NULL; 2418d6344f9Sopenharmony_ci DestroyEapolData(p2p_hnetdev); 2428d6344f9Sopenharmony_ci if (NetDeviceDelete(p2p_hnetdev) != 0) { 2438d6344f9Sopenharmony_ci return HDF_FAILURE; 2448d6344f9Sopenharmony_ci } 2458d6344f9Sopenharmony_ci if (NetDeviceDeInit(p2p_hnetdev) != 0) { 2468d6344f9Sopenharmony_ci return HDF_FAILURE; 2478d6344f9Sopenharmony_ci } 2488d6344f9Sopenharmony_ci 2498d6344f9Sopenharmony_ci hdf_bdh6_netdev_stop(netDevice); 2508d6344f9Sopenharmony_ci dhd_module_exit(); 2518d6344f9Sopenharmony_ci 2528d6344f9Sopenharmony_ci // free primary wlan0 2538d6344f9Sopenharmony_ci kfree(netDevice->mlPriv); 2548d6344f9Sopenharmony_ci netDevice->mlPriv = NULL; 2558d6344f9Sopenharmony_ci DestroyEapolData(netDevice); 2568d6344f9Sopenharmony_ci 2578d6344f9Sopenharmony_ci for (i = 0; i < HDF_INF_MAX; i ++) { 2588d6344f9Sopenharmony_ci cancel_work_sync(&g_hdf_infmap[i].eapolEvent.eapol_report); 2598d6344f9Sopenharmony_ci NetBufQueueClear(&g_hdf_infmap[i].eapolEvent.eapolQueue); 2608d6344f9Sopenharmony_ci } 2618d6344f9Sopenharmony_ci bdh6_reset_driver_flag = 1; 2628d6344f9Sopenharmony_ci HDF_LOGI("%s: ok", __func__); 2638d6344f9Sopenharmony_ci 2648d6344f9Sopenharmony_ci return HDF_SUCCESS; 2658d6344f9Sopenharmony_ci} 2668d6344f9Sopenharmony_ci 267