/** * @brief This function handles disconnect event. it * reports disconnect to upper layer, clean tx/rx packets, * reset link state etc. * * @param priv A pointer to wlan_private structure * @return n/a */ void libertas_mac_event_disconnected(wlan_private * priv) { wlan_adapter *adapter = priv->adapter; union iwreq_data wrqu; if (adapter->connect_status != LIBERTAS_CONNECTED) return; lbs_deb_enter(LBS_DEB_CMD); memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; /* * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. * It causes problem in the Supplicant */ msleep_interruptible(1000); wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); /* Free Tx and Rx packets */ kfree_skb(priv->adapter->currenttxskb); priv->adapter->currenttxskb = NULL; /* report disconnect to upper layer */ netif_stop_queue(priv->dev); netif_carrier_off(priv->dev); /* reset SNR/NF/RSSI values */ memset(adapter->SNR, 0x00, sizeof(adapter->SNR)); memset(adapter->NF, 0x00, sizeof(adapter->NF)); memset(adapter->RSSI, 0x00, sizeof(adapter->RSSI)); memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR)); memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF)); adapter->nextSNRNF = 0; adapter->numSNRNF = 0; lbs_deb_cmd("current SSID '%s', length %u\n", escape_essid(adapter->curbssparams.ssid, adapter->curbssparams.ssid_len), adapter->curbssparams.ssid_len); adapter->connect_status = LIBERTAS_DISCONNECTED; /* Clear out associated SSID and BSSID since connection is * no longer valid. */ memset(&adapter->curbssparams.bssid, 0, ETH_ALEN); memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE); adapter->curbssparams.ssid_len = 0; if (adapter->psstate != PS_STATE_FULL_POWER) { /* make firmware to exit PS mode */ lbs_deb_cmd("disconnected, so exit PS mode\n"); libertas_ps_wakeup(priv, 0); } lbs_deb_leave(LBS_DEB_CMD); }
static int __init lbs_init_module(void) { lbs_deb_enter(LBS_DEB_MAIN); memset(&confirm_sleep, 0, sizeof(confirm_sleep)); confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE); confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep)); confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED); lbs_debugfs_init(); lbs_deb_leave(LBS_DEB_MAIN); return 0; }
static void lbs_free_adapter(struct lbs_private *priv) { lbs_deb_enter(LBS_DEB_MAIN); lbs_free_cmd_buffer(priv); kfifo_free(&priv->event_fifo); del_timer(&priv->command_timer); del_timer(&priv->auto_deepsleep_timer); lbs_deb_leave(LBS_DEB_MAIN); }
static int wlan_cmd_802_11_get_stat(wlan_private * priv, struct cmd_ds_command *cmd) { lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(CMD_802_11_GET_STAT); cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN); lbs_deb_leave(LBS_DEB_CMD); return 0; }
int lbs_exit_auto_deep_sleep(struct lbs_private *priv) { lbs_deb_enter(LBS_DEB_SDIO); priv->is_auto_deep_sleep_enabled = 0; priv->auto_deep_sleep_timeout = 0; del_timer(&priv->auto_deepsleep_timer); lbs_deb_leave(LBS_DEB_SDIO); return 0; }
/*********************************************************************************************** ****函数名:lbs_ps_wakeup ****描述:用于唤醒网卡sleep模式 ****参数:priv:全局驱动变量 ****返回:无 ***********************************************************************************************/ void lbs_ps_wakeup(struct lbs_private *priv) { __le32 Localpsmode; int wait_option=CMD_OPTION_WAITFORRSP; lbs_deb_enter(LBS_DEB_HOST); Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM); lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,//发送命令退出低功耗模式 CMD_SUBCMD_EXIT_PS, wait_option, 0, &Localpsmode); lbs_deb_leave(LBS_DEB_HOST); }
static int wlan_cmd_hw_spec(wlan_private * priv, struct cmd_ds_command *cmd) { struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec; lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(CMD_GET_HW_SPEC); cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN); memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN); lbs_deb_leave(LBS_DEB_CMD); return 0; }
/*********************************************************************************************** ****函数名:lbs_ps_sleep ****描述:用于基础网络模式下,进入sleep状态,AP将为其缓存报文 ****参数:priv:全局驱动变量 ****返回:无 ***********************************************************************************************/ void lbs_ps_sleep(struct lbs_private *priv) { int wait_option=CMD_OPTION_WAITFORRSP; lbs_deb_enter(LBS_DEB_HOST); /* * PS is currently supported only in Infrastructure mode * Remove this check if it is to be supported in IBSS mode also */ lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL); lbs_deb_leave(LBS_DEB_HOST); }
int lbs_enter_auto_deep_sleep(struct lbs_private *priv) { lbs_deb_enter(LBS_DEB_SDIO); priv->is_auto_deep_sleep_enabled = 1; if (priv->is_deep_sleep) priv->wakeup_dev_required = 1; mod_timer(&priv->auto_deepsleep_timer , jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000); lbs_deb_leave(LBS_DEB_SDIO); return 0; }
static int wlan_cmd_802_11_reset(wlan_private * priv, struct cmd_ds_command *cmd, int cmd_action) { struct cmd_ds_802_11_reset *reset = &cmd->params.reset; lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(CMD_802_11_RESET); cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN); reset->action = cpu_to_le16(cmd_action); lbs_deb_leave(LBS_DEB_CMD); return 0; }
/** * @brief This function sends Exit_PS command to firmware. * * @param priv A pointer to wlan_private structure * @param wait_option wait response or not * @return n/a */ void libertas_ps_wakeup(wlan_private * priv, int wait_option) { __le32 Localpsmode; lbs_deb_enter(LBS_DEB_HOST); Localpsmode = cpu_to_le32(WLAN802_11POWERMODECAM); libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE, CMD_SUBCMD_EXIT_PS, wait_option, 0, &Localpsmode); lbs_deb_leave(LBS_DEB_HOST); }
static void if_usb_exit_module(void) { struct usb_card_rec *cardp, *cardp_temp; lbs_deb_enter(LBS_DEB_MAIN); list_for_each_entry_safe(cardp, cardp_temp, &usb_devices, list) if_usb_reset_device((wlan_private *) cardp->priv); /* API unregisters the driver from USB subsystem */ usb_deregister(&if_usb_driver); lbs_deb_leave(LBS_DEB_MAIN); }
static int wlan_ret_get_log(wlan_private * priv, struct cmd_ds_command *resp) { struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_CMD); /* Stored little-endian */ memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log)); lbs_deb_leave(LBS_DEB_CMD); return 0; }
static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv, struct cmd_ds_command *resp) { struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp; lbs_deb_enter(LBS_DEB_CMD); priv->txpowerlevel = le16_to_cpu(rtp->currentlevel); lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel); lbs_deb_leave(LBS_DEB_CMD); return 0; }
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) { lbs_deb_enter(LBS_DEB_THREAD); if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; /* Swap buffers by flipping the response index */ BUG_ON(resp_idx > 1); priv->resp_idx = resp_idx; wake_up(&priv->waitq); lbs_deb_leave(LBS_DEB_THREAD); }
/** * @brief This function initializes the command node. * * @param priv A pointer to wlan_private structure * @param ptempnode A pointer to cmd_ctrl_node structure * @param cmd_oid cmd oid: treated as sub command * @param wait_option wait option: wait response or not * @param pdata_buf A pointer to informaion buffer * @return 0 or -1 */ void libertas_set_cmd_ctrl_node(wlan_private * priv, struct cmd_ctrl_node *ptempnode, u32 cmd_oid, u16 wait_option, void *pdata_buf) { lbs_deb_enter(LBS_DEB_HOST); if (!ptempnode) return; ptempnode->cmd_oid = cmd_oid; ptempnode->wait_option = wait_option; ptempnode->pdata_buf = pdata_buf; lbs_deb_leave(LBS_DEB_HOST); }
static int wlan_ret_802_11_stat(wlan_private * priv, struct cmd_ds_command *resp) { lbs_deb_enter(LBS_DEB_CMD); /* currently adapter->wlan802_11Stat is unused struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat; wlan_adapter *adapter = priv->adapter; // TODO Convert it to Big endian befor copy memcpy(&adapter->wlan802_11Stat, p11Stat, sizeof(struct cmd_ds_802_11_get_stat)); */ lbs_deb_leave(LBS_DEB_CMD); return 0; }
static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv, struct cmd_ds_command *resp) { struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_CMD); if (rates->action == CMD_ACT_GET) { adapter->enablehwauto = le16_to_cpu(rates->enablehwauto); adapter->ratebitmap = le16_to_cpu(rates->bitmap); } lbs_deb_leave(LBS_DEB_CMD); return 0; }
/** * @brief This function register usb device and initialize parameter * @param priv pointer to wlan_private * @return 0 or -1 */ static int if_usb_register_dev(wlan_private * priv) { struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; lbs_deb_enter(LBS_DEB_USB); cardp->priv = priv; cardp->eth_dev = priv->dev; priv->hotplug_device = &(cardp->udev->dev); lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n", cardp->udev); lbs_deb_leave(LBS_DEB_USB); return 0; }
void lbs_queue_event(struct lbs_private *priv, u32 event) { //unsigned long flags; lbs_deb_enter(LBS_DEB_THREAD); //spin_lock_irqsave(&priv->driver_lock, flags); if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; __kfifo_put(priv->event_fifo, (unsigned char *)&event, sizeof(u32)); //wake_up_interruptible(&priv->waitq); lbs_thread(priv); //spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_leave(LBS_DEB_THREAD); }
/** * @brief This function handles disconnect event. it * reports disconnect to upper layer, clean tx/rx packets, * reset link state etc. * * @param priv A pointer to struct lbs_private structure * @return n/a */ void lbs_mac_event_disconnected(struct lbs_private *priv) { if (priv->connect_status != LBS_CONNECTED) return; lbs_deb_enter(LBS_DEB_ASSOC); /* * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. * It causes problem in the Supplicant */ msleep_interruptible(1000); lbs_send_disconnect_notification(priv); /* report disconnect to upper layer */ netif_stop_queue(priv->dev); netif_carrier_off(priv->dev); /* Free Tx and Rx packets */ kfree_skb(priv->currenttxskb); priv->currenttxskb = NULL; priv->tx_pending_len = 0; /* reset SNR/NF/RSSI values */ memset(priv->SNR, 0x00, sizeof(priv->SNR)); memset(priv->NF, 0x00, sizeof(priv->NF)); memset(priv->RSSI, 0x00, sizeof(priv->RSSI)); memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); priv->nextSNRNF = 0; priv->numSNRNF = 0; priv->connect_status = LBS_DISCONNECTED; /* Clear out associated SSID and BSSID since connection is * no longer valid. */ memset(&priv->curbssparams.bssid, 0, ETH_ALEN); memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN); priv->curbssparams.ssid_len = 0; if (priv->psstate != PS_STATE_FULL_POWER) { /* make firmware to exit PS mode */ lbs_deb_cmd("disconnected, so exit PS mode\n"); lbs_ps_wakeup(priv, 0); } lbs_deb_leave(LBS_DEB_ASSOC); }
static int libertas_ret_802_11_enable_rsn(wlan_private * priv, struct cmd_ds_command *resp) { struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn; wlan_adapter *adapter = priv->adapter; u32 * pdata_buf = adapter->cur_cmd->pdata_buf; lbs_deb_enter(LBS_DEB_CMD); if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) { if (pdata_buf) *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable); } lbs_deb_leave(LBS_DEB_CMD); return 0; }
static int if_usb_resume(struct usb_interface *intf) { struct usb_card_rec *cardp = usb_get_intfdata(intf); wlan_private *priv = cardp->priv; lbs_deb_enter(LBS_DEB_USB); cardp->rx_urb_recall = 0; if_usb_submit_rx_urb(cardp->priv); netif_device_attach(cardp->eth_dev); netif_device_attach(priv->mesh_dev); lbs_deb_leave(LBS_DEB_USB); return 0; }
static int wlan_cmd_mac_control(wlan_private * priv, struct cmd_ds_command *cmd) { struct cmd_ds_mac_control *mac = &cmd->params.macctrl; lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(CMD_MAC_CONTROL); cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN); mac->action = cpu_to_le16(priv->adapter->currentpacketfilter); lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n", le16_to_cpu(mac->action), le16_to_cpu(cmd->size)); lbs_deb_leave(LBS_DEB_CMD); return 0; }
/** * lbs_tx_lockup_handler - handles the timeout of the passing of TX frames * to the hardware. This is known to frequently happen with SD8686 when * waking up after a Wake-on-WLAN-triggered resume. * * @data: &struct lbs_private pointer */ static void lbs_tx_lockup_handler(unsigned long data) { struct lbs_private *priv = (struct lbs_private *)data; unsigned long flags; lbs_deb_enter(LBS_DEB_TX); spin_lock_irqsave(&priv->driver_lock, flags); netdev_info(priv->dev, "TX lockup detected\n"); if (priv->reset_card) priv->reset_card(priv); priv->dnld_sent = DNLD_RES_RECEIVED; wake_up_interruptible(&priv->waitq); spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_leave(LBS_DEB_TX); }
static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, struct cmd_ds_mesh_access *cmd) { int ret; lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); cmd->hdr.result = 0; cmd->action = cpu_to_le16(cmd_action); ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); lbs_deb_leave(LBS_DEB_CMD); return ret; }
void lbs_remove_mesh(struct lbs_private *priv) { struct net_device *mesh_dev; mesh_dev = priv->mesh_dev; if (!mesh_dev) return; lbs_deb_enter(LBS_DEB_MESH); netif_stop_queue(mesh_dev); netif_carrier_off(mesh_dev); sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); lbs_persist_config_remove(mesh_dev); unregister_netdev(mesh_dev); priv->mesh_dev = NULL; free_netdev(mesh_dev); lbs_deb_leave(LBS_DEB_MESH); }
/** * @brief This function handles MIC failure event. * * @param priv A pointer to struct lbs_private structure * @para event the event id * @return n/a */ static void handle_mic_failureevent(struct lbs_private *priv, u32 event) { char buf[50]; lbs_deb_enter(LBS_DEB_CMD); memset(buf, 0, sizeof(buf)); sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) { strcat(buf, "unicast "); } else { strcat(buf, "multicast "); } lbs_send_iwevcustom_event(priv, buf); lbs_deb_leave(LBS_DEB_CMD); }
/** * @brief This function cleans command node. * * @param ptempnode A pointer to cmdCtrlNode structure * @return n/a */ static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode) { lbs_deb_enter(LBS_DEB_HOST); if (!ptempnode) return; ptempnode->cmdwaitqwoken = 1; wake_up_interruptible(&ptempnode->cmdwait_q); ptempnode->status = 0; ptempnode->cmd_oid = (u32) 0; ptempnode->wait_option = 0; ptempnode->pdata_buf = NULL; if (ptempnode->bufvirtualaddr != NULL) memset(ptempnode->bufvirtualaddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER); lbs_deb_leave(LBS_DEB_HOST); }
void lbs_remove_card(struct lbs_private *priv) { struct net_device *dev = priv->dev; lbs_deb_enter(LBS_DEB_MAIN); lbs_remove_mesh(priv); if (priv->wiphy_registered) lbs_scan_deinit(priv); lbs_wait_for_firmware_load(priv); /* worker thread destruction blocks on the in-flight command which * should have been cleared already in lbs_stop_card(). */ lbs_deb_main("destroying worker thread\n"); destroy_workqueue(priv->work_thread); lbs_deb_main("done destroying worker thread\n"); if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); } if (priv->is_deep_sleep) { priv->is_deep_sleep = 0; wake_up_interruptible(&priv->ds_awake_q); } priv->is_host_sleep_configured = 0; priv->is_host_sleep_activated = 0; wake_up_interruptible(&priv->host_sleep_q); /* Stop the thread servicing the interrupts */ priv->surpriseremoved = 1; kthread_stop(priv->main_thread); lbs_free_adapter(priv); lbs_cfg_free(priv); free_netdev(dev); lbs_deb_leave(LBS_DEB_MAIN); }