aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-4965.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c158
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}
344int 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 */
879static 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
890static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) 845static 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
1704unsigned 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
1736static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) 1659static 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
2082int 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
2116static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) 2006static 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
2261static 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 */
2373static void iwl4965_rx_handler_setup(struct iwl_priv *priv) 2297static 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
2404static struct iwl_lib_ops iwl4965_lib = { 2329static 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])");
2469module_param_named(disable, iwl4965_mod_params.disable, int, 0444); 2393module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
2470MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); 2394MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
2471module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); 2395module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
2472MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n"); 2396MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
2473module_param_named(debug, iwl4965_mod_params.debug, int, 0444); 2397module_param_named(debug, iwl4965_mod_params.debug, int, 0444);
2474MODULE_PARM_DESC(debug, "debug output mask"); 2398MODULE_PARM_DESC(debug, "debug output mask");
2475module_param_named( 2399module_param_named(