diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 158 |
1 files changed, 41 insertions, 117 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9afecb813716..22bb26985c2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -341,39 +341,6 @@ err: | |||
341 | return -EINVAL; | 341 | return -EINVAL; |
342 | 342 | ||
343 | } | 343 | } |
344 | int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) | ||
345 | { | ||
346 | int ret; | ||
347 | unsigned long flags; | ||
348 | |||
349 | spin_lock_irqsave(&priv->lock, flags); | ||
350 | ret = iwl_grab_nic_access(priv); | ||
351 | if (ret) { | ||
352 | spin_unlock_irqrestore(&priv->lock, flags); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | if (src == IWL_PWR_SRC_VAUX) { | ||
357 | u32 val; | ||
358 | ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE, | ||
359 | &val); | ||
360 | |||
361 | if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) { | ||
362 | iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, | ||
363 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, | ||
364 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
365 | } | ||
366 | } else { | ||
367 | iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, | ||
368 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, | ||
369 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
370 | } | ||
371 | |||
372 | iwl_release_nic_access(priv); | ||
373 | spin_unlock_irqrestore(&priv->lock, flags); | ||
374 | |||
375 | return ret; | ||
376 | } | ||
377 | 344 | ||
378 | /* | 345 | /* |
379 | * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask | 346 | * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask |
@@ -875,18 +842,6 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
875 | return 0; | 842 | return 0; |
876 | } | 843 | } |
877 | 844 | ||
878 | /* set card power command */ | ||
879 | static int iwl4965_set_power(struct iwl_priv *priv, | ||
880 | void *cmd) | ||
881 | { | ||
882 | int ret = 0; | ||
883 | |||
884 | ret = iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, | ||
885 | sizeof(struct iwl4965_powertable_cmd), | ||
886 | cmd, NULL); | ||
887 | return ret; | ||
888 | } | ||
889 | |||
890 | static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) | 845 | static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) |
891 | { | 846 | { |
892 | s32 sign = 1; | 847 | s32 sign = 1; |
@@ -1560,11 +1515,11 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, | |||
1560 | c, atten_value, power_index, | 1515 | c, atten_value, power_index, |
1561 | tx_power.s.radio_tx_gain[c], | 1516 | tx_power.s.radio_tx_gain[c], |
1562 | tx_power.s.dsp_predis_atten[c]); | 1517 | tx_power.s.dsp_predis_atten[c]); |
1563 | }/* for each chain */ | 1518 | } /* for each chain */ |
1564 | 1519 | ||
1565 | tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw); | 1520 | tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw); |
1566 | 1521 | ||
1567 | }/* for each rate */ | 1522 | } /* for each rate */ |
1568 | 1523 | ||
1569 | return 0; | 1524 | return 0; |
1570 | } | 1525 | } |
@@ -1701,38 +1656,6 @@ static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) | |||
1701 | return le32_to_cpu(s->rb_closed) & 0xFFF; | 1656 | return le32_to_cpu(s->rb_closed) & 0xFFF; |
1702 | } | 1657 | } |
1703 | 1658 | ||
1704 | unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, | ||
1705 | struct iwl_frame *frame, u8 rate) | ||
1706 | { | ||
1707 | struct iwl4965_tx_beacon_cmd *tx_beacon_cmd; | ||
1708 | unsigned int frame_size; | ||
1709 | |||
1710 | tx_beacon_cmd = &frame->u.beacon; | ||
1711 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | ||
1712 | |||
1713 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | ||
1714 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
1715 | |||
1716 | frame_size = iwl4965_fill_beacon_frame(priv, | ||
1717 | tx_beacon_cmd->frame, | ||
1718 | iwl_bcast_addr, | ||
1719 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | ||
1720 | |||
1721 | BUG_ON(frame_size > MAX_MPDU_SIZE); | ||
1722 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | ||
1723 | |||
1724 | if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) | ||
1725 | tx_beacon_cmd->tx.rate_n_flags = | ||
1726 | iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); | ||
1727 | else | ||
1728 | tx_beacon_cmd->tx.rate_n_flags = | ||
1729 | iwl_hw_set_rate_n_flags(rate, 0); | ||
1730 | |||
1731 | tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | | ||
1732 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK); | ||
1733 | return (sizeof(*tx_beacon_cmd) + frame_size); | ||
1734 | } | ||
1735 | |||
1736 | static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) | 1659 | static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) |
1737 | { | 1660 | { |
1738 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, | 1661 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, |
@@ -2079,39 +2002,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
2079 | return 0; | 2002 | return 0; |
2080 | } | 2003 | } |
2081 | 2004 | ||
2082 | int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, | ||
2083 | enum ieee80211_ampdu_mlme_action action, | ||
2084 | const u8 *addr, u16 tid, u16 *ssn) | ||
2085 | { | ||
2086 | struct iwl_priv *priv = hw->priv; | ||
2087 | DECLARE_MAC_BUF(mac); | ||
2088 | |||
2089 | IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", | ||
2090 | print_mac(mac, addr), tid); | ||
2091 | |||
2092 | if (!(priv->cfg->sku & IWL_SKU_N)) | ||
2093 | return -EACCES; | ||
2094 | |||
2095 | switch (action) { | ||
2096 | case IEEE80211_AMPDU_RX_START: | ||
2097 | IWL_DEBUG_HT("start Rx\n"); | ||
2098 | return iwl_rx_agg_start(priv, addr, tid, *ssn); | ||
2099 | case IEEE80211_AMPDU_RX_STOP: | ||
2100 | IWL_DEBUG_HT("stop Rx\n"); | ||
2101 | return iwl_rx_agg_stop(priv, addr, tid); | ||
2102 | case IEEE80211_AMPDU_TX_START: | ||
2103 | IWL_DEBUG_HT("start Tx\n"); | ||
2104 | return iwl_tx_agg_start(priv, addr, tid, ssn); | ||
2105 | case IEEE80211_AMPDU_TX_STOP: | ||
2106 | IWL_DEBUG_HT("stop Tx\n"); | ||
2107 | return iwl_tx_agg_stop(priv, addr, tid); | ||
2108 | default: | ||
2109 | IWL_DEBUG_HT("unknown\n"); | ||
2110 | return -EINVAL; | ||
2111 | break; | ||
2112 | } | ||
2113 | return 0; | ||
2114 | } | ||
2115 | 2005 | ||
2116 | static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) | 2006 | static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) |
2117 | { | 2007 | { |
@@ -2240,9 +2130,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
2240 | bitmap = bitmap << sh; | 2130 | bitmap = bitmap << sh; |
2241 | sh = 0; | 2131 | sh = 0; |
2242 | } | 2132 | } |
2243 | bitmap |= (1 << sh); | 2133 | bitmap |= 1ULL << sh; |
2244 | IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n", | 2134 | IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", |
2245 | start, (u32)(bitmap & 0xFFFFFFFF)); | 2135 | start, (unsigned long long)bitmap); |
2246 | } | 2136 | } |
2247 | 2137 | ||
2248 | agg->bitmap = bitmap; | 2138 | agg->bitmap = bitmap; |
@@ -2368,6 +2258,40 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2368 | IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); | 2258 | IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); |
2369 | } | 2259 | } |
2370 | 2260 | ||
2261 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | ||
2262 | struct iwl_rx_phy_res *rx_resp) | ||
2263 | { | ||
2264 | /* data from PHY/DSP regarding signal strength, etc., | ||
2265 | * contents are always there, not configurable by host. */ | ||
2266 | struct iwl4965_rx_non_cfg_phy *ncphy = | ||
2267 | (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
2268 | u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK) | ||
2269 | >> IWL49_AGC_DB_POS; | ||
2270 | |||
2271 | u32 valid_antennae = | ||
2272 | (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK) | ||
2273 | >> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET; | ||
2274 | u8 max_rssi = 0; | ||
2275 | u32 i; | ||
2276 | |||
2277 | /* Find max rssi among 3 possible receivers. | ||
2278 | * These values are measured by the digital signal processor (DSP). | ||
2279 | * They should stay fairly constant even as the signal strength varies, | ||
2280 | * if the radio's automatic gain control (AGC) is working right. | ||
2281 | * AGC value (see below) will provide the "interesting" info. */ | ||
2282 | for (i = 0; i < 3; i++) | ||
2283 | if (valid_antennae & (1 << i)) | ||
2284 | max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); | ||
2285 | |||
2286 | IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
2287 | ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], | ||
2288 | max_rssi, agc); | ||
2289 | |||
2290 | /* dBm = max_rssi dB - agc dB - constant. | ||
2291 | * Higher AGC (higher radio gain) means lower signal. */ | ||
2292 | return max_rssi - agc - IWL_RSSI_OFFSET; | ||
2293 | } | ||
2294 | |||
2371 | 2295 | ||
2372 | /* Set up 4965-specific Rx frame reply handlers */ | 2296 | /* Set up 4965-specific Rx frame reply handlers */ |
2373 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | 2297 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) |
@@ -2399,6 +2323,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2399 | .chain_noise_reset = iwl4965_chain_noise_reset, | 2323 | .chain_noise_reset = iwl4965_chain_noise_reset, |
2400 | .gain_computation = iwl4965_gain_computation, | 2324 | .gain_computation = iwl4965_gain_computation, |
2401 | .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, | 2325 | .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, |
2326 | .calc_rssi = iwl4965_calc_rssi, | ||
2402 | }; | 2327 | }; |
2403 | 2328 | ||
2404 | static struct iwl_lib_ops iwl4965_lib = { | 2329 | static struct iwl_lib_ops iwl4965_lib = { |
@@ -2440,7 +2365,6 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2440 | .check_version = iwl4965_eeprom_check_version, | 2365 | .check_version = iwl4965_eeprom_check_version, |
2441 | .query_addr = iwlcore_eeprom_query_addr, | 2366 | .query_addr = iwlcore_eeprom_query_addr, |
2442 | }, | 2367 | }, |
2443 | .set_power = iwl4965_set_power, | ||
2444 | .send_tx_power = iwl4965_send_tx_power, | 2368 | .send_tx_power = iwl4965_send_tx_power, |
2445 | .update_chain_flags = iwl4965_update_chain_flags, | 2369 | .update_chain_flags = iwl4965_update_chain_flags, |
2446 | .temperature = iwl4965_temperature_calib, | 2370 | .temperature = iwl4965_temperature_calib, |
@@ -2469,7 +2393,7 @@ MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | |||
2469 | module_param_named(disable, iwl4965_mod_params.disable, int, 0444); | 2393 | module_param_named(disable, iwl4965_mod_params.disable, int, 0444); |
2470 | MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); | 2394 | MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); |
2471 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); | 2395 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); |
2472 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n"); | 2396 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); |
2473 | module_param_named(debug, iwl4965_mod_params.debug, int, 0444); | 2397 | module_param_named(debug, iwl4965_mod_params.debug, int, 0444); |
2474 | MODULE_PARM_DESC(debug, "debug output mask"); | 2398 | MODULE_PARM_DESC(debug, "debug output mask"); |
2475 | module_param_named( | 2399 | module_param_named( |