/* * mac80211 glue code for mac80211 altobeam APOLLO drivers * * * Copyright (c) 2016, altobeam * Author: * * Based on apollo code * Copyright (c) 2010, ST-Ericsson * Author: Dmitry Tarnyagin * * Based on: * Copyright (c) 2006, Michael Wu * Copyright (c) 2007-2009, Christian Lamparter * Copyright 2008, Johannes Berg * * Based on: * - the islsm (softmac prism54) driver, which is: * Copyright 2004-2006 Jean-Baptiste Note , et al. * - stlc45xx driver * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifdef LINUX_OS /*Linux version 3.4.0 compilation*/ //#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) #include //#endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_ATBM_5G_PRETEND_2G #include #endif #endif #include "apollo.h" #include "sbus.h" #include "fwio.h" #include "hwio.h" #include "bh.h" #include "debug.h" #include "pm.h" #include "svn_version.h" #include "iface.h" #include "wsm.h" #include "atbm_ioctl.h" MODULE_AUTHOR("wifi_software "); MODULE_DESCRIPTION("Softmac altobeam apollo wifi common code"); MODULE_LICENSE("GPL"); MODULE_ALIAS("atbm_core"); //1: HIF-Disconect 0: Normal static int hif_sta = 0; module_param(hif_sta, int, 0644); extern int wifi_run_sta; module_param(wifi_run_sta, int, 0644); static int efuse = 0; module_param(efuse, int, 0644); static int driver_ver = DRIVER_VER; module_param(driver_ver, int, 0644); static int fw_ver = 0; module_param(fw_ver, int, 0644); #define verson_str(_ver) #_ver #define verson(ver) verson_str(ver) const char* hmac_ver = "HMAC_VER:"verson(DRIVER_VER); #ifdef CUSTOM_FEATURE_MAC /* To use macaddr and PS Mode of customers */ #define PATH_WIFI_MACADDR "/data/.mac.info" #define PATH_WIFI_PSM_INFO "/data/.psm.info" #define PATH_WIFI_EFUSE "/data/.efuse.info" //int access_file(char *path, char *buffer, int size, int isRead); #ifdef CUSTOM_FEATURE_PSM/* To control ps mode */ static int savedpsm = 0; #endif #endif /* * *atbm log level control fs * */ u32 atbm_printk_mask = ATBM_PRINTK_DEFAULT_MASK; module_param(atbm_printk_mask, int, 0644); static void atbm_configure_wifi_mode(struct atbm_common *hw_priv); void atbm_set_fw_ver(struct atbm_common *hw_priv) { fw_ver = hw_priv->wsm_caps.firmwareVersion; } static inline void __atbm_free_event_queue(struct list_head *list) { while (!list_empty(list)) { struct atbm_wsm_event *event = list_first_entry(list, struct atbm_wsm_event, link); list_del(&event->link); atbm_kfree(event); } } void atbm_free_event_queue(struct atbm_common *hw_priv) { LIST_HEAD(list); spin_lock_bh(&hw_priv->event_queue_lock); list_splice_init(&hw_priv->event_queue, &list); spin_unlock_bh(&hw_priv->event_queue_lock); __atbm_free_event_queue(&list); } int sdio_wakeup_reason = 0; struct sdio_customer_cmd_req { int cmd_id; char data[96]; }; void atbm_event_handler(struct work_struct *work) { struct atbm_common *hw_priv = container_of(work, struct atbm_common, event_handler); struct atbm_vif *priv = NULL; struct atbm_wsm_event *event; LIST_HEAD(list); spin_lock_bh(&hw_priv->event_queue_lock); list_splice_init(&hw_priv->event_queue, &list); spin_unlock_bh(&hw_priv->event_queue_lock); if(atbm_bh_is_term(hw_priv)) { goto event_handler_out; } mutex_lock(&hw_priv->conf_mutex); list_for_each_entry(event, &list, link) { if ((event->evt.eventId != WSM_EVENT_HOST_RMMOD) && (event->evt.eventId != WSM_EVENT_HOST_INSMOD) && (event->evt.eventId != WSM_EVENT_HOST_WAKEUP_REASON) && (event->evt.eventId != WSM_EVENT_HOST_DISCONN_REASON) && (event->evt.eventId != WSM_EVENT_HOST_CONN_ERR_REASON) && (event->evt.eventId != WSM_EVENT_ATCMD_RECIVE)){ priv = __ABwifi_hwpriv_to_vifpriv(hw_priv, event->if_id); if (!priv) { printk( "[CQM] Event for non existing interface, ignoring.\n"); continue; } } switch (event->evt.eventId) { case WSM_EVENT_ERROR: /* I even don't know what is it about.. */ //STUB(); break; case WSM_EVENT_BSS_LOST: { struct HostDisConnectEvent * hostevent = (struct HostDisConnectEvent *)event->evt.buffer; atbm_ioctl_connect_async(NULL, 0); #ifndef CONFIG_ATBM_SDIO_ATCMD if (priv->type == NL80211_IFTYPE_STATION){ atbm_sta_disconnect_event(priv,hostevent->bssid); } #endif break; } case WSM_EVENT_BSS_CONNECT: { struct HostConnectEvent * hostevent = (struct HostConnectEvent *)event->evt.buffer; printk( "hostevent->bssid %pM ipaddr %x\n",hostevent->bssid,hostevent->ipaddr); atbm_ioctl_connect_async(hostevent, 1); #ifndef CONFIG_ATBM_SDIO_ATCMD if (priv->type == NL80211_IFTYPE_STATION){ atbm_sta_connect_event(priv,hostevent); } else { atbm_configure_wifi_mode(priv->hw_priv); } #endif break; } case WSM_EVENT_STA_ADD: { #ifndef CONFIG_ATBM_SDIO_ATCMD atbm_sta_add_event(priv,*((int *)(event->evt.buffer))); #endif break; } case WSM_EVENT_STA_LOSS: { #ifndef CONFIG_ATBM_SDIO_ATCMD atbm_sta_loss_event(priv); #endif break; } case WSM_EVENT_SMT_SUCCESS: { printk("SMARTCONFIG SUCCESS.\n"); break; } case WSM_EVENT_SMT_FAIL: { printk("SMARTCONFIG FAIL.\n"); break; } case WSM_EVENT_ETF_RX_MSG: { printk("%s", event->evt.buffer); break; } case WSM_EVENT_FW_UART_MSG: { printk("%s", event->evt.buffer); break; } case WSM_EVENT_HOST_RMMOD: { atbm_ioctl_driver_async(0); break; } case WSM_EVENT_HOST_INSMOD: { atbm_ioctl_driver_async(1); break; } case WSM_EVENT_HOST_WAKEUP_REASON: { u8 reason = *((u8 *)event->evt.buffer); atbm_ioctl_wakeup_async(reason); sdio_wakeup_reason = reason; break; } case WSM_EVENT_HOST_DISCONN_REASON: { u8 reason = *((u8 *)event->evt.buffer); atbm_ioctl_disconn_async(reason); break; } case WSM_EVENT_HOST_CONN_ERR_REASON: { u8 reason = *((u8 *)event->evt.buffer); atbm_ioctl_conn_err_async(reason); break; } case WSM_EVENT_HOST_CUSTOMER_CMD_REQ: { struct sdio_customer_cmd_req *req = (struct sdio_customer_cmd_req *)(event->evt.buffer); printk("cmdid:%d data:%s\n", req->cmd_id, req->data); break; } case WSM_EVENT_HOST_CUSTOMER_PRIVATE: { atbm_ioctl_customer_private_event_async(event->evt.buffer); break; } #ifdef CONFIG_ATBM_SDIO_ATCMD case WSM_EVENT_ATCMD_RECIVE: { atbm_ioctl_atcmd_event_async(event->evt.buffer); break; } #endif } } mutex_unlock(&hw_priv->conf_mutex); event_handler_out: __atbm_free_event_queue(&list); } #ifdef TIME_DEBUG extern void jiffies_update(int is_first); #endif struct atbm_common *atbm_init_common(size_t hw_priv_data_len) { struct atbm_common *hw_priv; hw_priv = kzalloc(hw_priv_data_len,0); if (hw_priv==NULL){ printk("kzalloc(sizeof(atbm_common),0) error!!! \n"); return 0; } hw_priv->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM + 64 + 8 /* TKIP IV */ + 12 /* TKIP ICV and MIC */; hw_priv->workqueue = create_singlethread_workqueue("atbm_wq"); init_waitqueue_head(&hw_priv->wsm_cmd_wq); spin_lock_init(&hw_priv->event_queue_lock); INIT_LIST_HEAD(&hw_priv->event_queue); INIT_WORK(&hw_priv->event_handler, atbm_event_handler); mutex_init(&hw_priv->wsm_cmd_mux); mutex_init(&hw_priv->conf_mutex); #ifndef OPER_CLOCK_USE_SEM mutex_init(&hw_priv->wsm_oper_lock); #else sema_init(&hw_priv->wsm_oper_lock, 1); //init_timer(&hw_priv->wsm_pm_timer); //hw_priv->wsm_pm_timer.data = (unsigned long)hw_priv; //hw_priv->wsm_pm_timer.function = atbm_pm_timer; spin_lock_init(&hw_priv->wsm_pm_spin_lock); atomic_set(&hw_priv->wsm_pm_running, 0); #endif wsm_buf_init(&hw_priv->wsm_cmd_buf); spin_lock_init(&hw_priv->wsm_cmd.lock); #ifdef CONFIG_ATBM_SDIO_ATCMD atbm_sdio_atcmd_buf_init(hw_priv); #endif atbm_skb_queue_head_init(&hw_priv->rx_frame_queue); atbm_skb_queue_head_init(&hw_priv->tx_frame_queue); atbm_skb_queue_head_init(&hw_priv->rx_skb_queue); #ifndef CONFIG_ATBM_SDIO_ATCMD spin_lock_init(&hw_priv->rx_path_lock); sta_info_init(hw_priv); spin_lock_init(&hw_priv->tx_queue_lock); #endif return hw_priv; } EXPORT_SYMBOL_GPL(atbm_init_common); void atbm_free_common( struct atbm_common *dev) { if (dev->wsm_caps.firmwareVersion < 13549){ u16 val16; int ret; #ifdef TIME_DEBUG jiffies_update(0); #endif //hare sdio + iot,let lmac know host initial done .add by wp /* Set wakeup bit in device */ ret = atbm_reg_read_16(dev, ATBM_HIFREG_CONTROL_REG_ID, &val16); if (ret < 0) { atbm_dbg(ATBM_APOLLO_DBG_ERROR, "%s: set_wakeup: can't read " \ "control register.\n", __func__); goto out; } ret = atbm_reg_write_16(dev, ATBM_HIFREG_CONTROL_REG_ID, val16 & ~ATBM_HIFREG_CONT_WUP_BIT); if (ret < 0) { atbm_dbg(ATBM_APOLLO_DBG_ERROR, "%s: set_wakeup: can't write " \ "control register.\n", __func__); goto out; } } out: kfree(dev); } EXPORT_SYMBOL_GPL(atbm_free_common); void atbm_clear_wakeup_reg( struct atbm_common *dev) { u16 val16; int ret; //hare sdio + iot,let lmac know host initial done .add by wp /* Set wakeup bit in device */ ret = atbm_reg_read_16_for_sleep(dev, ATBM_HIFREG_CONTROL_REG_ID, &val16); if (ret < 0) { atbm_dbg(ATBM_APOLLO_DBG_ERROR, "%s: set_wakeup: can't read " \ "control register.\n", __func__); } ret = atbm_reg_write_16_for_sleep(dev, ATBM_HIFREG_CONTROL_REG_ID, val16 & ~ATBM_HIFREG_CONT_WUP_BIT); if (ret < 0) { atbm_dbg(ATBM_APOLLO_DBG_ERROR, "%s: set_wakeup: can't write " \ "control register.\n", __func__); } } void atbm_unregister_common(struct atbm_common *hw_priv) { atbm_printk_exit("atbm_unregister_common.++\n"); #ifdef TIME_DEBUG jiffies_update(0); #endif rtnl_lock(); atbm_remove_interfaces(hw_priv); rtnl_unlock(); #ifdef TIME_DEBUG jiffies_update(0); #endif if (hw_priv->wsm_caps.firmwareVersion < 13549) { hw_priv->sbus_ops->irq_unsubscribe(hw_priv->sbus_priv); } #ifdef TIME_DEBUG jiffies_update(0); #endif hw_priv->init_done = 0; if (hw_priv->wsm_caps.firmwareVersion < 13549) { hw_priv->close_driver = 1; if(hw_priv->sbus_ops->sbus_xmit_func_deinit) hw_priv->sbus_ops->sbus_xmit_func_deinit(hw_priv->sbus_priv); if(hw_priv->sbus_ops->sbus_rev_func_deinit) hw_priv->sbus_ops->sbus_rev_func_deinit(hw_priv->sbus_priv); } atbm_unregister_bh(hw_priv); //atbm_debug_release_common(hw_priv); atbm_rx_bh_flush(hw_priv); atbm_tx_bh_flush(hw_priv); mutex_destroy(&hw_priv->conf_mutex); flush_workqueue(hw_priv->workqueue); destroy_workqueue(hw_priv->workqueue); hw_priv->workqueue = NULL; #ifdef TIME_DEBUG jiffies_update(0); #endif wsm_buf_deinit(&hw_priv->wsm_cmd_buf); if (hw_priv->skb_cache) { atbm_dev_kfree_skb(hw_priv->skb_cache); hw_priv->skb_cache = NULL; } #ifdef CONFIG_PM atbm_pm_deinit(&hw_priv->pm_state); #endif atbm_printk_exit("atbm_unregister_common.--\n"); } void atbm_monitor_pc(struct atbm_common *hw_priv); int atbm_register_test_thread(struct atbm_common *hw_priv); //#ifdef RESET_CHANGE struct atbm_common *g_hw_priv=0; int hw_net_cfg_ok=0; //#endif static void atbm_get_mac_address(struct atbm_common *hw_priv) { struct wsm_sdio_getconfig_cnf cnf; wsm_get_config(hw_priv,&cnf,sizeof(cnf)); hw_priv->mac_addr[0] = cnf.macaddr[0]; hw_priv->mac_addr[1] = cnf.macaddr[1]; hw_priv->mac_addr[2] = cnf.macaddr[2]; hw_priv->mac_addr[3] = cnf.macaddr[3]; hw_priv->mac_addr[4] = cnf.macaddr[4]; hw_priv->mac_addr[5] = cnf.macaddr[5]; atbm_printk_init("atbm_get_mac_address.%x:%x:%x:%x:%x\n",hw_priv->mac_addr[1],hw_priv->mac_addr[2],hw_priv->mac_addr[3],hw_priv->mac_addr[4],hw_priv->mac_addr[5]); } static void atbm_configure_wifi_mode(struct atbm_common *hw_priv) { struct atbm_vif * vif; struct wsm_sdio_getconfig_cnf cnf; wsm_get_config(hw_priv,&cnf,sizeof(cnf)); vif =__ABwifi_hwpriv_to_vifpriv(hw_priv,0); if (vif != NULL){ if(cnf.WifiMode){ vif->type = NL80211_IFTYPE_AP; } else { vif->type = NL80211_IFTYPE_STATION; } atbm_printk_init("wifi mode:%s\n",cnf.WifiMode?"AP":"STA"); if (cnf.WifiMode){ struct wsm_ap_cfg_get_req apcfg_get; if (wsm_get_ap_cfg(hw_priv,&apcfg_get,sizeof(apcfg_get)) == 0){ if(apcfg_get.ap_cfg.key_mgmt == KEY_MGMT_NONE){ vif->ap_info.group_key.key_type = IEEE80211_ENC_TYPE; vif->ap_info.key.key_type = IEEE80211_ENC_TYPE; } else if((apcfg_get.ap_cfg.key_mgmt == KEY_MGMT_WEP) || (apcfg_get.ap_cfg.key_mgmt == KEY_MGMT_WEP_SHARED)){ atbm_printk_err("%s:wep\n",__func__); vif->ap_info.group_key.key_type = IEEE80211_ENC_WEP; vif->ap_info.key.key_type = IEEE80211_ENC_WEP; vif->ap_info.group_key.conf.iv_len = WEP_IV_LEN; vif->ap_info.group_key.conf.icv_len = WEP_ICV_LEN; vif->ap_info.key.conf.iv_len = WEP_IV_LEN; vif->ap_info.key.conf.icv_len = WEP_ICV_LEN; }else if(apcfg_get.ap_cfg.key_mgmt == KEY_MGMT_WPA){ atbm_printk_err("%s:tkip\n",__func__); vif->ap_info.group_key.key_type = IEEE80211_ENC_TKIP; vif->ap_info.key.key_type = IEEE80211_ENC_TKIP; vif->ap_info.group_key.conf.iv_len = TKIP_IV_LEN; vif->ap_info.group_key.conf.icv_len = TKIP_ICV_LEN; vif->ap_info.key.conf.iv_len = TKIP_IV_LEN; vif->ap_info.key.conf.icv_len = TKIP_ICV_LEN; }else if(apcfg_get.ap_cfg.key_mgmt == KEY_MGMT_WPA2){ atbm_printk_err("%s:aes\n",__func__); vif->ap_info.group_key.key_type = IEEE80211_ENC_AES; vif->ap_info.key.key_type = IEEE80211_ENC_AES; vif->ap_info.group_key.conf.iv_len = CCMP_HDR_LEN; vif->ap_info.group_key.conf.icv_len = CCMP_MIC_LEN; vif->ap_info.key.conf.iv_len = CCMP_HDR_LEN; vif->ap_info.key.conf.icv_len = CCMP_MIC_LEN; } memcpy(&vif->group_key,&vif->ap_info.group_key,sizeof(struct ieee80211_key)); } } } } #ifndef CONFIG_ATBM_SDIO_ATCMD void atbm_get_connectconfig(struct atbm_common *hw_priv) { struct wsm_sdio_getconfig_cnf cnf; struct atbm_vif *vif = NULL; wsm_get_config(hw_priv,&cnf,sizeof(cnf)); vif = __ABwifi_hwpriv_to_vifpriv(hw_priv,0); vif->connect_success = cnf.bconnect; if(vif->connect_success){ atbm_sta_connect_event(vif,&cnf.con_event); } atbm_printk_init("atbm_get_mac_address.%x:%x:%x:%x:%x\n",hw_priv->mac_addr[1],hw_priv->mac_addr[2],hw_priv->mac_addr[3],hw_priv->mac_addr[4],hw_priv->mac_addr[5]); } #endif void dump_mem(u8 *data, int len); void atbm_set_tcp_port_filter(struct atbm_common *hw_priv) { wsm_set_tcp_filter(hw_priv,&hw_priv->tcp_filter_req,sizeof(hw_priv->tcp_filter_req)); atbm_printk_init("tcp_port_filter addcnt.%x:\n",hw_priv->tcp_filter_req.des_cnt); //dump_mem((u8 *)(&hw_priv->tcp_filter_req),sizeof(hw_priv->tcp_filter_req)); } void atbm_set_psmode(struct atbm_common *hw_priv) { wsm_set_psmode(hw_priv,&hw_priv->ps_mode_req,sizeof(hw_priv->ps_mode_req)); } int atbm_notify_sta_connect_ok(struct atbm_common *hw_priv) { int ret = 0; struct wsm_generic_req notify_req; ret = wsm_host_network_ok_notify(hw_priv, ¬ify_req, sizeof(notify_req)); if (ret) { atbm_printk_err("%s: wsm_host_network_ok_notify err. can not receive any datas!\n", __func__); } return ret; } int atbm_core_probe(const struct sbus_ops *sbus_ops, struct sbus_priv *sbus, struct device *pdev, struct atbm_common **pself) { int err = -ENOMEM; struct atbm_common *hw_priv=NULL; int ret = 0; #ifdef TIME_DEBUG jiffies_update(0); #endif hw_priv = atbm_init_common(sizeof(struct atbm_common)); if (!hw_priv) goto err; atbm_hw_priv_assign_pointer(hw_priv); hw_priv->init_done = 0; hw_priv->sbus_ops = sbus_ops; hw_priv->sbus_priv = sbus; hw_priv->pdev = pdev; hw_priv->tcp_filter_req.Flags= HI_SDIO_FILTER_F_ICMP|HI_SDIO_FILTER_F_ARP|HI_SDIO_FILTER_F_DNS; hw_priv->tcp_filter_req.status= 0; hw_priv->tcp_filter_req.des_cnt = 1; hw_priv->tcp_filter_req.src_cnt = 1; hw_priv->tcp_filter_req.des_tcpport[0] = htons(5001); hw_priv->tcp_filter_req.src_tcpport[0] = htons(5001); hw_priv->ps_mode_req.powerave_level = 1; hw_priv->ps_mode_req.powersave_mode = HAL_NO_SLEEP; hw_priv->buf_force_rx=1; hw_priv->buf_force_tx=1; *pself = hw_priv; #ifdef CONFIG_PM err = atbm_pm_init(&hw_priv->pm_state, hw_priv); if (err) { atbm_dbg(ATBM_APOLLO_DBG_ERROR, "Cannot init PM. (%d).\n", err); goto err1; } #endif err = atbm_register_bh(hw_priv); if (err) goto err1; /* *init bus tx/rx */ #ifdef TIME_DEBUG jiffies_update(0); #endif if(hw_priv->sbus_ops->sbus_xmit_func_init) err = hw_priv->sbus_ops->sbus_xmit_func_init(hw_priv->sbus_priv); if(hw_priv->sbus_ops->sbus_rev_func_init) err |= hw_priv->sbus_ops->sbus_rev_func_init(hw_priv->sbus_priv); if(err){ atbm_printk_err("rev and xmit init err\n"); goto err1; } #ifdef TIME_DEBUG jiffies_update(0); #endif reload_fw: err = atbm_load_firmware(hw_priv); if (err){ atbm_printk_err("atbm_load_firmware ERROR!\n"); goto err2; } hw_priv->sbus_ops->lock(hw_priv->sbus_priv); WARN_ON(hw_priv->sbus_ops->set_block_size(hw_priv->sbus_priv,SDIO_BLOCK_SIZE)); atbm_printk_init("set_block_size=%d\n", SDIO_BLOCK_SIZE); hw_priv->sbus_ops->unlock(hw_priv->sbus_priv); hw_priv->init_done = 1; ret = hw_priv->sbus_ops->irq_subscribe(hw_priv->sbus_priv, (sbus_irq_handler)atbm_irq_handler, hw_priv); if (ret < 0) { atbm_dbg(ATBM_APOLLO_DBG_ERROR, "%s: can't register IRQ handler.\n", __func__); //goto out; } #ifdef TIME_DEBUG jiffies_update(0); #endif //fix mstar CVT suspend bug,in CVT mstar suspend wait_event_interruptible_timeout sometime will not delay { int loop =0; atbm_printk_always("mdelay wait wsm_startup_done !!\n"); while(hw_priv->wsm_caps.firmwareReady !=1){ //mdelay(10); schedule_timeout_interruptible(msecs_to_jiffies(1)); if(loop++>1200){ atbm_printk_init("wait_event_interruptible_timeout wsm_startup_done timeout ERROR !!\n"); atbm_monitor_pc(hw_priv); if(hw_priv->sbus_ops->sbus_reset_chip){ atbm_printk_err("reload fw\n"); if(hw_priv->sbus_ops->irq_unsubscribe) hw_priv->sbus_ops->irq_unsubscribe(hw_priv->sbus_priv); hw_priv->sbus_ops->sbus_reset_chip(hw_priv->sbus_priv); goto reload_fw; }else { err = -ETIMEDOUT; goto err3; } } } } if (err) { goto err3; } #ifdef TIME_DEBUG jiffies_update(0); #endif //mdelay(100); hw_priv->wsm_caps.firmwareReady = 1; atbm_get_mac_address(hw_priv); #ifdef CONFIG_PM atbm_pm_stay_awake(&hw_priv->pm_state, 6 * HZ); #endif //#ifdef CONFIG_PM //atbm_set_psmode(hw_priv); #ifdef TIME_DEBUG jiffies_update(0); #endif #ifdef CONFIG_ATBM_SDIO_ATCMD atbm_netdev_none(hw_priv); #else //CONFIG_ATBM_SDIO_ATCMD rtnl_lock(); err = atbm_netdev_add(hw_priv,"wlan0"); rtnl_unlock(); //atbm_setup_mac(hw_priv); #endif //CONFIG_ATBM_SDIO_ATCMD hw_net_cfg_ok = 1; #ifdef TIME_DEBUG jiffies_update(0); #endif atbm_configure_wifi_mode(hw_priv); return err; err3: //sbus_ops->reset(sbus); hw_priv->sbus_ops->irq_unsubscribe(hw_priv->sbus_priv); err2: atbm_unregister_bh(hw_priv); err1: /* *init bus tx/rx */ if(hw_priv->sbus_ops->sbus_xmit_func_deinit) hw_priv->sbus_ops->sbus_xmit_func_deinit(hw_priv->sbus_priv); if(hw_priv->sbus_ops->sbus_rev_func_deinit) hw_priv->sbus_ops->sbus_rev_func_deinit(hw_priv->sbus_priv); wsm_buf_deinit(&hw_priv->wsm_cmd_buf); #ifdef CONFIG_PM atbm_pm_deinit(&hw_priv->pm_state); #endif atbm_free_common(hw_priv); err: *pself=NULL; if(hw_priv) hw_priv->init_done = 0; return err; } EXPORT_SYMBOL_GPL(atbm_core_probe); void atbm_core_release(struct atbm_common *self) { atbm_unregister_common(self); atbm_free_common(self); hw_net_cfg_ok = 0; return; } EXPORT_SYMBOL_GPL(atbm_core_release); #ifdef CUSTOM_FEATURE_MAC /* To use macaddr and ps mode of customers */ #if 0 int access_file(char *path, char *buffer, int size, int isRead) { int ret=0; struct file *fp; mm_segment_t old_fs = get_fs(); if(isRead) fp = filp_open(path,O_RDONLY,S_IRUSR); else fp = filp_open(path,O_CREAT|O_WRONLY,S_IRUSR); if (IS_ERR(fp)) { atbm_printk_err("apollo wifi : can't open %s\n",path); return -1; } if(isRead) { if(fp->f_op->read == NULL) { atbm_printk_err("apollo wifi : Not allow to read\n"); return -2; } else { fp->f_pos = 0; set_fs(KERNEL_DS); ret = vfs_read(fp,buffer,size,&fp->f_pos); set_fs(old_fs); } } else { if(fp->f_op->write == NULL) { atbm_printk_err("apollo wifi : Not allow to write\n"); return -2; } else { fp->f_pos = 0; set_fs(KERNEL_DS); ret = vfs_write(fp,buffer,size,&fp->f_pos); set_fs(old_fs); } } filp_close(fp,NULL); atbm_printk_debug("apollo wifi : access_file return code(%d)\n",ret); return ret; } #endif #endif