📄 main.c
字号:
struct net_device *dev){ wlan_private *priv = dev->priv; int ret; lbs_deb_enter(LBS_DEB_MESH); if(priv->adapter->monitormode != WLAN_MONITOR_OFF) { netif_stop_queue(dev); return -EOPNOTSUPP; } SET_MESH_FRAME(skb); ret = libertas_hard_start_xmit(skb, priv->dev); lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); return ret;}/** * @brief Mark non-mesh packets and handover them to libertas_hard_start_xmit * */static int libertas_pre_start_xmit(struct sk_buff *skb, struct net_device *dev){ wlan_private *priv = dev->priv; int ret; lbs_deb_enter(LBS_DEB_NET); if(priv->adapter->monitormode != WLAN_MONITOR_OFF) { netif_stop_queue(dev); return -EOPNOTSUPP; } UNSET_MESH_FRAME(skb); ret = libertas_hard_start_xmit(skb, dev); lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); return ret;}static void libertas_tx_timeout(struct net_device *dev){ wlan_private *priv = (wlan_private *) dev->priv; lbs_deb_enter(LBS_DEB_TX); lbs_pr_err("tx watch dog timeout\n"); priv->dnld_sent = DNLD_RES_RECEIVED; dev->trans_start = jiffies; if (priv->adapter->currenttxskb) { if (priv->adapter->monitormode != WLAN_MONITOR_OFF) { /* If we are here, we have not received feedback from the previous packet. Assume TX_FAIL and move on. */ priv->adapter->eventcause = 0x01000000; libertas_send_tx_feedback(priv); } else wake_up_interruptible(&priv->waitq); } else if (priv->adapter->connect_status == LIBERTAS_CONNECTED) { netif_wake_queue(priv->dev); if (priv->mesh_dev) netif_wake_queue(priv->mesh_dev); } lbs_deb_leave(LBS_DEB_TX);}/** * @brief This function returns the network statistics * * @param dev A pointer to wlan_private structure * @return A pointer to net_device_stats structure */static struct net_device_stats *libertas_get_stats(struct net_device *dev){ wlan_private *priv = (wlan_private *) dev->priv; return &priv->stats;}static int libertas_set_mac_address(struct net_device *dev, void *addr){ int ret = 0; wlan_private *priv = (wlan_private *) dev->priv; wlan_adapter *adapter = priv->adapter; struct sockaddr *phwaddr = addr; lbs_deb_enter(LBS_DEB_NET); /* In case it was called from the mesh device */ dev = priv->dev ; memset(adapter->current_addr, 0, ETH_ALEN); /* dev->dev_addr is 8 bytes */ lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN); lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN); memcpy(adapter->current_addr, phwaddr->sa_data, ETH_ALEN); ret = libertas_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS, CMD_ACT_SET, CMD_OPTION_WAITFORRSP, 0, NULL); if (ret) { lbs_deb_net("set MAC address failed\n"); ret = -1; goto done; } lbs_deb_hex(LBS_DEB_NET, "adapter->macaddr", adapter->current_addr, ETH_ALEN); memcpy(dev->dev_addr, adapter->current_addr, ETH_ALEN); if (priv->mesh_dev) memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);done: lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); return ret;}static int libertas_copy_multicast_address(wlan_adapter * adapter, struct net_device *dev){ int i = 0; struct dev_mc_list *mcptr = dev->mc_list; for (i = 0; i < dev->mc_count; i++) { memcpy(&adapter->multicastlist[i], mcptr->dmi_addr, ETH_ALEN); mcptr = mcptr->next; } return i;}static void libertas_set_multicast_list(struct net_device *dev){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; int oldpacketfilter; DECLARE_MAC_BUF(mac); lbs_deb_enter(LBS_DEB_NET); oldpacketfilter = adapter->currentpacketfilter; if (dev->flags & IFF_PROMISC) { lbs_deb_net("enable promiscuous mode\n"); adapter->currentpacketfilter |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; adapter->currentpacketfilter &= ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | CMD_ACT_MAC_MULTICAST_ENABLE); } else { /* Multicast */ adapter->currentpacketfilter &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; if (dev->flags & IFF_ALLMULTI || dev->mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { lbs_deb_net( "enabling all multicast\n"); adapter->currentpacketfilter |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; adapter->currentpacketfilter &= ~CMD_ACT_MAC_MULTICAST_ENABLE; } else { adapter->currentpacketfilter &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; if (!dev->mc_count) { lbs_deb_net("no multicast addresses, " "disabling multicast\n"); adapter->currentpacketfilter &= ~CMD_ACT_MAC_MULTICAST_ENABLE; } else { int i; adapter->currentpacketfilter |= CMD_ACT_MAC_MULTICAST_ENABLE; adapter->nr_of_multicastmacaddr = libertas_copy_multicast_address(adapter, dev); lbs_deb_net("multicast addresses: %d\n", dev->mc_count); for (i = 0; i < dev->mc_count; i++) { lbs_deb_net("Multicast address %d:%s\n", i, print_mac(mac, adapter->multicastlist[i])); } /* send multicast addresses to firmware */ libertas_prepare_and_send_command(priv, CMD_MAC_MULTICAST_ADR, CMD_ACT_SET, 0, 0, NULL); } } } if (adapter->currentpacketfilter != oldpacketfilter) { libertas_set_mac_packet_filter(priv); } lbs_deb_leave(LBS_DEB_NET);}/** * @brief This function handles the major jobs in the WLAN driver. * It handles all events generated by firmware, RX data received * from firmware and TX data sent from kernel. * * @param data A pointer to wlan_thread structure * @return 0 */static int libertas_thread(void *data){ struct net_device *dev = data; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; wait_queue_t wait; u8 ireg = 0; lbs_deb_enter(LBS_DEB_THREAD); init_waitqueue_entry(&wait, current); set_freezable(); for (;;) { lbs_deb_thread( "main-thread 111: intcounter=%d " "currenttxskb=%p dnld_sent=%d\n", adapter->intcounter, adapter->currenttxskb, priv->dnld_sent); add_wait_queue(&priv->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_lock_irq(&adapter->driver_lock); if ((adapter->psstate == PS_STATE_SLEEP) || (!adapter->intcounter && (priv->dnld_sent || adapter->cur_cmd || list_empty(&adapter->cmdpendingq)))) { lbs_deb_thread( "main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", adapter->connect_status, adapter->intcounter, adapter->psmode, adapter->psstate); spin_unlock_irq(&adapter->driver_lock); schedule(); } else spin_unlock_irq(&adapter->driver_lock); lbs_deb_thread( "main-thread 222 (waking up): intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, adapter->currenttxskb, priv->dnld_sent); set_current_state(TASK_RUNNING); remove_wait_queue(&priv->waitq, &wait); try_to_freeze(); lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, adapter->currenttxskb, priv->dnld_sent); if (kthread_should_stop() || adapter->surpriseremoved) { lbs_deb_thread( "main-thread: break from main thread: surpriseremoved=0x%x\n", adapter->surpriseremoved); break; } spin_lock_irq(&adapter->driver_lock); if (adapter->intcounter) { u8 int_status; adapter->intcounter = 0; int_status = priv->hw_get_int_status(priv, &ireg); if (int_status) { lbs_deb_thread( "main-thread: reading HOST_INT_STATUS_REG failed\n"); spin_unlock_irq(&adapter->driver_lock); continue; } adapter->hisregcpy |= ireg; } lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, adapter->currenttxskb, priv->dnld_sent); /* command response? */ if (adapter->hisregcpy & MRVDRV_CMD_UPLD_RDY) { lbs_deb_thread("main-thread: cmd response ready\n"); adapter->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY; spin_unlock_irq(&adapter->driver_lock); libertas_process_rx_command(priv); spin_lock_irq(&adapter->driver_lock); } /* Any Card Event */ if (adapter->hisregcpy & MRVDRV_CARDEVENT) { lbs_deb_thread("main-thread: Card Event Activity\n"); adapter->hisregcpy &= ~MRVDRV_CARDEVENT; if (priv->hw_read_event_cause(priv)) { lbs_pr_alert( "main-thread: hw_read_event_cause failed\n"); spin_unlock_irq(&adapter->driver_lock); continue; } spin_unlock_irq(&adapter->driver_lock); libertas_process_event(priv); } else spin_unlock_irq(&adapter->driver_lock); /* Check if we need to confirm Sleep Request received previously */ if (adapter->psstate == PS_STATE_PRE_SLEEP) { if (!priv->dnld_sent && !adapter->cur_cmd) { if (adapter->connect_status == LIBERTAS_CONNECTED) { lbs_deb_thread( "main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p " "dnld_sent=%d cur_cmd=%p, confirm now\n", adapter->intcounter, adapter->currenttxskb, priv->dnld_sent, adapter->cur_cmd); libertas_ps_confirm_sleep(priv, (u16) adapter->psmode); } else { /* workaround for firmware sending * deauth/linkloss event immediately * after sleep request, remove this * after firmware fixes it */ adapter->psstate = PS_STATE_AWAKE; lbs_pr_alert( "main-thread: ignore PS_SleepConfirm in non-connected state\n"); } } } /* The PS state is changed during processing of Sleep Request * event above */ if ((priv->adapter->psstate == PS_STATE_SLEEP) || (priv->adapter->psstate == PS_STATE_PRE_SLEEP)) continue; /* Execute the next command */ if (!priv->dnld_sent && !priv->adapter->cur_cmd) libertas_execute_next_command(priv); /* Wake-up command waiters which can't sleep in * libertas_prepare_and_send_command */ if (!adapter->nr_cmd_pending) wake_up_all(&adapter->cmd_pending); libertas_tx_runqueue(priv); } del_timer(&adapter->command_timer); adapter->nr_cmd_pending = 0; wake_up_all(&adapter->cmd_pending); lbs_deb_leave(LBS_DEB_THREAD); return 0;}/** * @brief This function downloads firmware image, gets * HW spec from firmware and set basic parameters to * firmware. * * @param priv A pointer to wlan_private structure * @return 0 or -1 */static int wlan_setup_firmware(wlan_private * priv){ int ret = -1; wlan_adapter *adapter = priv->adapter; struct cmd_ds_mesh_access mesh_access; lbs_deb_enter(LBS_DEB_FW); /* * Read MAC address from HW */ memset(adapter->current_addr, 0xff, ETH_ALEN); ret = libertas_prepare_and_send_command(priv, CMD_GET_HW_SPEC, 0, CMD_OPTION_WAITFORRSP, 0, NULL); if (ret) { ret = -1; goto done; } libertas_set_mac_packet_filter(priv); /* Get the supported Data rates */ ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE, CMD_ACT_GET_TX_RATE, CMD_OPTION_WAITFORRSP, 0, NULL); if (ret) { ret = -1; goto done; } /* Disable mesh autostart */ if (priv->mesh_dev) { memset(&mesh_access, 0, sizeof(mesh_access)); mesh_access.data[0] = cpu_to_le32(0); ret = libertas_prepare_and_send_command(priv, CMD_MESH_ACCESS, CMD_ACT_MESH_SET_AUTOSTART_ENABLED, CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access); if (ret) { ret = -1; goto done; } priv->mesh_autostart_enabled = 0; } /* Set the boot2 version in firmware */ ret = libertas_prepare_and_send_command(priv, CMD_SET_BOOT2_VER, 0, CMD_OPTION_WAITFORRSP, 0, NULL); ret = 0;done: lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); return ret;}/** * This function handles the timeout of command sending. * It will re-send the same command again. */static void command_timer_fn(unsigned long data){ wlan_private *priv = (wlan_private *)data; wlan_adapter *adapter = priv->adapter; struct cmd_ctrl_node *ptempnode; struct cmd_ds_command *cmd; unsigned long flags; ptempnode = adapter->cur_cmd; if (ptempnode == NULL) { lbs_deb_fw("ptempnode empty\n"); return; } cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr; if (!cmd) { lbs_deb_fw("cmd is NULL\n"); return; } lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command); if (!adapter->fw_ready) return; spin_lock_irqsave(&adapter->driver_lock, flags); adapter->cur_cmd = NULL; spin_unlock_irqrestore(&adapter->driver_lock, flags); lbs_deb_fw("re-sending same command because of timeout\n"); libertas_queue_cmd(adapter, ptempnode, 0); wake_up_interruptible(&priv->waitq); return;}static int libertas_init_adapter(wlan_private * priv){ wlan_adapter *adapter = priv->adapter; size_t bufsize; int i, ret = 0; /* Allocate buffer to store the BSSID list */ bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); adapter->networks = kzalloc(bufsize, GFP_KERNEL); if (!adapter->networks) { lbs_pr_err("Out of memory allocating beacons\n"); ret = -1; goto out; } /* Initialize scan result lists */ INIT_LIST_HEAD(&adapter->network_free_list); INIT_LIST_HEAD(&adapter->network_list); for (i = 0; i < MAX_NETWORK_COUNT; i++) { list_add_tail(&adapter->networks[i].list, &adapter->network_free_list); } adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum); adapter->libertas_ps_confirm_sleep.command = cpu_to_le16(CMD_802_11_PS_MODE); adapter->libertas_ps_confirm_sleep.size = cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); adapter->libertas_ps_confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); memset(adapter->current_addr, 0xff, ETH_ALEN); adapter->connect_status = LIBERTAS_DISCONNECTED; adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; adapter->mode = IW_MODE_INFRA; adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; adapter->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; adapter->radioon = RADIO_ON; adapter->auto_rate = 1; adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; adapter->psmode = WLAN802_11POWERMODECAM; adapter->psstate = PS_STATE_FULL_POWER; mutex_init(&adapter->lock); memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*)); adapter->tx_queue_idx = 0; spin_lock_init(&adapter->txqueue_lock); setup_timer(&adapter->command_timer, command_timer_fn, (unsigned long)priv);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -