📄 iwl4965-base.c
字号:
*pos++ = WLAN_EID_HT_CAPABILITY; *pos++ = sizeof(struct ieee80211_ht_capability); iwl_set_ht_capab(NULL, (struct ieee80211_ht_capability *)pos, use_wide_chan); len += 2 + sizeof(struct ieee80211_ht_capability); }#endif /*CONFIG_IWLWIFI_HT */ fill_end: return (u16)len;}/* * QoS support*/#ifdef CONFIG_IWLWIFI_QOSstatic int iwl_send_qos_params_command(struct iwl_priv *priv, struct iwl_qosparam_cmd *qos){ return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM, sizeof(struct iwl_qosparam_cmd), qos);}static void iwl_reset_qos(struct iwl_priv *priv){ u16 cw_min = 15; u16 cw_max = 1023; u8 aifs = 2; u8 is_legacy = 0; unsigned long flags; int i; spin_lock_irqsave(&priv->lock, flags); priv->qos_data.qos_active = 0; if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; if (!(priv->active_rate & 0xfff0)) { cw_min = 31; is_legacy = 1; } } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) { cw_min = 31; is_legacy = 1; } if (priv->qos_data.qos_active) aifs = 3; priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; if (priv->qos_data.qos_active) { i = 1; priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); priv->qos_data.def_qos_parm.ac[i].aifsn = 7; priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; i = 2; priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16((cw_min + 1) / 2 - 1); priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); priv->qos_data.def_qos_parm.ac[i].aifsn = 2; if (is_legacy) priv->qos_data.def_qos_parm.ac[i].edca_txop = cpu_to_le16(6016); else priv->qos_data.def_qos_parm.ac[i].edca_txop = cpu_to_le16(3008); priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; i = 3; priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16((cw_min + 1) / 4 - 1); priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16((cw_max + 1) / 2 - 1); priv->qos_data.def_qos_parm.ac[i].aifsn = 2; priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; if (is_legacy) priv->qos_data.def_qos_parm.ac[i].edca_txop = cpu_to_le16(3264); else priv->qos_data.def_qos_parm.ac[i].edca_txop = cpu_to_le16(1504); } else { for (i = 1; i < 4; i++) { priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; } } IWL_DEBUG_QOS("set QoS to default \n"); spin_unlock_irqrestore(&priv->lock, flags);}static void iwl_activate_qos(struct iwl_priv *priv, u8 force){ unsigned long flags; if (priv == NULL) return; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (!priv->qos_data.qos_enable) return; spin_lock_irqsave(&priv->lock, flags); priv->qos_data.def_qos_parm.qos_flags = 0; if (priv->qos_data.qos_cap.q_AP.queue_request && !priv->qos_data.qos_cap.q_AP.txop_request) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TXOP_TYPE_MSK; if (priv->qos_data.qos_active) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; spin_unlock_irqrestore(&priv->lock, flags); if (force || iwl_is_associated(priv)) { IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n", priv->qos_data.qos_active); iwl_send_qos_params_command(priv, &(priv->qos_data.def_qos_parm)); }}#endif /* CONFIG_IWLWIFI_QOS *//* * Power management (not Tx power!) functions */#define MSEC_TO_USEC 1024#define NOSLP __constant_cpu_to_le16(0), 0, 0#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0#define SLP_TIMEOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ __constant_cpu_to_le32(X1), \ __constant_cpu_to_le32(X2), \ __constant_cpu_to_le32(X3), \ __constant_cpu_to_le32(X4)}/* default power management (not Tx power) table values *//* for tim 0-10 */static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = { {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0}, {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0}, {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1}, {{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}};/* for tim > 10 */static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = { {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), SLP_VEC(2, 6, 9, 9, 0xFF)}, 0}, {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, {{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}};int iwl_power_init_handle(struct iwl_priv *priv){ int rc = 0, i; struct iwl_power_mgr *pow_data; int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC; u16 pci_pm; IWL_DEBUG_POWER("Initialize power \n"); pow_data = &(priv->power_data); memset(pow_data, 0, sizeof(*pow_data)); pow_data->active_index = IWL_POWER_RANGE_0; pow_data->dtim_val = 0xffff; memcpy(&pow_data->pwr_range_0[0], &range_0[0], size); memcpy(&pow_data->pwr_range_1[0], &range_1[0], size); rc = pci_read_config_word(priv->pci_dev, PCI_LINK_CTRL, &pci_pm); if (rc != 0) return 0; else { struct iwl_powertable_cmd *cmd; IWL_DEBUG_POWER("adjust power command flags\n"); for (i = 0; i < IWL_POWER_AC; i++) { cmd = &pow_data->pwr_range_0[i].cmd; if (pci_pm & 0x1) cmd->flags &= ~IWL_POWER_PCI_PM_MSK; else cmd->flags |= IWL_POWER_PCI_PM_MSK; } } return rc;}static int iwl_update_power_cmd(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, u32 mode){ int rc = 0, i; u8 skip; u32 max_sleep = 0; struct iwl_power_vec_entry *range; u8 period = 0; struct iwl_power_mgr *pow_data; if (mode > IWL_POWER_INDEX_5) { IWL_DEBUG_POWER("Error invalid power mode \n"); return -1; } pow_data = &(priv->power_data); if (pow_data->active_index == IWL_POWER_RANGE_0) range = &pow_data->pwr_range_0[0]; else range = &pow_data->pwr_range_1[1]; memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));#ifdef IWL_MAC80211_DISABLE if (priv->assoc_network != NULL) { unsigned long flags; period = priv->assoc_network->tim.tim_period; }#endif /*IWL_MAC80211_DISABLE */ skip = range[mode].no_dtim; if (period == 0) { period = 1; skip = 0; } if (skip == 0) { max_sleep = period; cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; } else { __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; } for (i = 0; i < IWL_POWER_VEC_SIZE; i++) { if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) cmd->sleep_interval[i] = cpu_to_le32(max_sleep); } IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags); IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n", le32_to_cpu(cmd->sleep_interval[0]), le32_to_cpu(cmd->sleep_interval[1]), le32_to_cpu(cmd->sleep_interval[2]), le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); return rc;}static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode){ u32 final_mode = mode; int rc; struct iwl_powertable_cmd cmd; /* If on battery, set to 3, * if plugged into AC power, set to CAM ("continuosly aware mode"), * else user level */ switch (mode) { case IWL_POWER_BATTERY: final_mode = IWL_POWER_INDEX_3; break; case IWL_POWER_AC: final_mode = IWL_POWER_MODE_CAM; break; default: final_mode = mode; break; } cmd.keep_alive_beacons = 0; iwl_update_power_cmd(priv, &cmd, final_mode); rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd); if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); else set_bit(STATUS_POWER_PMI, &priv->status); return rc;}int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header){ /* Filter incoming packets to determine if they are targeted toward * this network, discarding packets coming from ourselves */ switch (priv->iw_mode) { case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ /* packets from our adapter are dropped (echo) */ if (!compare_ether_addr(header->addr2, priv->mac_addr)) return 0; /* {broad,multi}cast packets to our IBSS go through */ if (is_multicast_ether_addr(header->addr1)) return !compare_ether_addr(header->addr3, priv->bssid); /* packets to our adapter go through */ return !compare_ether_addr(header->addr1, priv->mac_addr); case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ /* packets from our adapter are dropped (echo) */ if (!compare_ether_addr(header->addr3, priv->mac_addr)) return 0; /* {broad,multi}cast packets to our BSS go through */ if (is_multicast_ether_addr(header->addr1)) return !compare_ether_addr(header->addr2, priv->bssid); /* packets to our adapter go through */ return !compare_ether_addr(header->addr1, priv->mac_addr); } return 1;}#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #xconst char *iwl_get_tx_fail_reason(u32 status){ switch (status & TX_STATUS_MSK) { case TX_STATUS_SUCCESS: return "SUCCESS"; TX_STATUS_ENTRY(SHORT_LIMIT); TX_STATUS_ENTRY(LONG_LIMIT); TX_STATUS_ENTRY(FIFO_UNDERRUN); TX_STATUS_ENTRY(MGMNT_ABORT); TX_STATUS_ENTRY(NEXT_FRAG); TX_STATUS_ENTRY(LIFE_EXPIRE); TX_STATUS_ENTRY(DEST_PS); TX_STATUS_ENTRY(ABORTED); TX_STATUS_ENTRY(BT_RETRY); TX_STATUS_ENTRY(STA_INVALID); TX_STATUS_ENTRY(FRAG_DROPPED); TX_STATUS_ENTRY(TID_DISABLE); TX_STATUS_ENTRY(FRAME_FLUSHED); TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); TX_STATUS_ENTRY(TX_LOCKED); TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); } return "UNKNOWN";}/** * iwl_scan_cancel - Cancel any currently executing HW scan * * NOTE: priv->mutex is not required before calling this function */static int iwl_scan_cancel(struct iwl_priv *priv){ if (!test_bit(STATUS_SCAN_HW, &priv->status)) { clear_bit(STATUS_SCANNING, &priv->status); return 0; } if (test_bit(STATUS_SCANNING, &priv->status)) { if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN("Queuing scan abort.\n"); set_bit(STATUS_SCAN_ABORTING, &priv->status); queue_work(priv->workqueue, &priv->abort_scan); } else IWL_DEBUG_SCAN("Scan abort already in progress.\n"); return test_bit(STATUS_SCANNING, &priv->status); } return 0;}/** * iwl_scan_cancel_timeout - Cancel any currently executing HW scan * @ms: amount of time to wait (in milliseconds) for scan to abort * * NOTE: priv->mutex must be held before calling this function */static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms){ unsigned long now = jiffies; int ret; ret = iwl_scan_cancel(priv); if (ret && ms) { mutex_unlock(&priv->mutex); while (!time_after(jiffies, now + msecs_to_jiffies(ms)) && test_bit(STATUS_SCANNING, &priv->status)) msleep(1); mutex_lock(&priv->mutex); return test_bit(STATUS_SCANNING, &priv->status); } return ret;}static void iwl_sequence_reset(struct iwl_priv *priv){ /* Reset ieee stats */ /* We don't reset the net_device_stats (ieee->stats) on * re-association */ priv->last_seq_num = -1; priv->last_frag_num = -1; priv->last_packet_time = 0; iwl_scan_cancel(priv);}#define MAX_UCODE_BEACON_INTERVAL 4096#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA)static __le16 iwl_adjust_beacon_interval(u16 beacon_val){ u16 new_val = 0; u16 beacon_factor = 0; beacon_factor = (beacon_val + MAX_UCODE_BEACON_INTERVAL) / MAX_UCODE_BEACON_INTERVAL; new_val = beacon_val / beacon_factor; return cpu_to_le16(new_val);}static void iwl_setup_rxon_timing(struct iwl_priv *priv){ u64 interval_tm_unit; u64 tsf, result; unsigned long flags; struct ieee80211_conf *conf = NULL; u16 beacon_int = 0; conf = ieee80211_get_hw_conf(priv->hw); spin_lock_irqsave(&priv->lock, flags); priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1); priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0); priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -