diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-5000.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 71 |
1 files changed, 64 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 878d6193b232..f3d139b663e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -93,6 +93,13 @@ static int iwl5000_apm_init(struct iwl_priv *priv) | |||
93 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | 93 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, |
94 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | 94 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); |
95 | 95 | ||
96 | /* Set FH wait treshold to maximum (HW error during stress W/A) */ | ||
97 | iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | ||
98 | |||
99 | /* enable HAP INTA to move device L1a -> L0s */ | ||
100 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
101 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
102 | |||
96 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); | 103 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); |
97 | 104 | ||
98 | /* set "initialization complete" bit to move adapter | 105 | /* set "initialization complete" bit to move adapter |
@@ -230,6 +237,16 @@ static void iwl5000_nic_config(struct iwl_priv *priv) | |||
230 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | 237 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | |
231 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | 238 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); |
232 | 239 | ||
240 | /* W/A : NIC is stuck in a reset state after Early PCIe power off | ||
241 | * (PCIe power is lost before PERST# is asserted), | ||
242 | * causing ME FW to lose ownership and not being able to obtain it back. | ||
243 | */ | ||
244 | iwl_grab_nic_access(priv); | ||
245 | iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, | ||
246 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | ||
247 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | ||
248 | iwl_release_nic_access(priv); | ||
249 | |||
233 | spin_unlock_irqrestore(&priv->lock, flags); | 250 | spin_unlock_irqrestore(&priv->lock, flags); |
234 | } | 251 | } |
235 | 252 | ||
@@ -924,8 +941,8 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
924 | len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | 941 | len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; |
925 | 942 | ||
926 | if (txq_id != IWL_CMD_QUEUE_NUM) { | 943 | if (txq_id != IWL_CMD_QUEUE_NUM) { |
927 | sta = txq->cmd[txq->q.write_ptr].cmd.tx.sta_id; | 944 | sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; |
928 | sec_ctl = txq->cmd[txq->q.write_ptr].cmd.tx.sec_ctl; | 945 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; |
929 | 946 | ||
930 | switch (sec_ctl & TX_CMD_SEC_MSK) { | 947 | switch (sec_ctl & TX_CMD_SEC_MSK) { |
931 | case TX_CMD_SEC_CCM: | 948 | case TX_CMD_SEC_CCM: |
@@ -964,7 +981,7 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | |||
964 | u8 sta = 0; | 981 | u8 sta = 0; |
965 | 982 | ||
966 | if (txq_id != IWL_CMD_QUEUE_NUM) | 983 | if (txq_id != IWL_CMD_QUEUE_NUM) |
967 | sta = txq->cmd[txq->q.read_ptr].cmd.tx.sta_id; | 984 | sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id; |
968 | 985 | ||
969 | shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr]. | 986 | shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr]. |
970 | val = cpu_to_le16(1 | (sta << 12)); | 987 | val = cpu_to_le16(1 | (sta << 12)); |
@@ -1131,7 +1148,7 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) | |||
1131 | 1148 | ||
1132 | static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | 1149 | static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) |
1133 | { | 1150 | { |
1134 | return le32_to_cpup((__le32*)&tx_resp->status + | 1151 | return le32_to_cpup((__le32 *)&tx_resp->status + |
1135 | tx_resp->frame_count) & MAX_SN; | 1152 | tx_resp->frame_count) & MAX_SN; |
1136 | } | 1153 | } |
1137 | 1154 | ||
@@ -1228,9 +1245,9 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
1228 | bitmap = bitmap << sh; | 1245 | bitmap = bitmap << sh; |
1229 | sh = 0; | 1246 | sh = 0; |
1230 | } | 1247 | } |
1231 | bitmap |= (1 << sh); | 1248 | bitmap |= 1ULL << sh; |
1232 | IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n", | 1249 | IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", |
1233 | start, (u32)(bitmap & 0xFFFFFFFF)); | 1250 | start, (unsigned long long)bitmap); |
1234 | } | 1251 | } |
1235 | 1252 | ||
1236 | agg->bitmap = bitmap; | 1253 | agg->bitmap = bitmap; |
@@ -1444,6 +1461,44 @@ static void iwl5000_temperature(struct iwl_priv *priv) | |||
1444 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | 1461 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); |
1445 | } | 1462 | } |
1446 | 1463 | ||
1464 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
1465 | static int iwl5000_calc_rssi(struct iwl_priv *priv, | ||
1466 | struct iwl_rx_phy_res *rx_resp) | ||
1467 | { | ||
1468 | /* data from PHY/DSP regarding signal strength, etc., | ||
1469 | * contents are always there, not configurable by host | ||
1470 | */ | ||
1471 | struct iwl5000_non_cfg_phy *ncphy = | ||
1472 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
1473 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | ||
1474 | u8 agc; | ||
1475 | |||
1476 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | ||
1477 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | ||
1478 | |||
1479 | /* Find max rssi among 3 possible receivers. | ||
1480 | * These values are measured by the digital signal processor (DSP). | ||
1481 | * They should stay fairly constant even as the signal strength varies, | ||
1482 | * if the radio's automatic gain control (AGC) is working right. | ||
1483 | * AGC value (see below) will provide the "interesting" info. | ||
1484 | */ | ||
1485 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | ||
1486 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | ||
1487 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | ||
1488 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | ||
1489 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | ||
1490 | |||
1491 | max_rssi = max_t(u32, rssi_a, rssi_b); | ||
1492 | max_rssi = max_t(u32, max_rssi, rssi_c); | ||
1493 | |||
1494 | IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
1495 | rssi_a, rssi_b, rssi_c, max_rssi, agc); | ||
1496 | |||
1497 | /* dBm = max_rssi dB - agc dB - constant. | ||
1498 | * Higher AGC (higher radio gain) means lower signal. */ | ||
1499 | return max_rssi - agc - IWL_RSSI_OFFSET; | ||
1500 | } | ||
1501 | |||
1447 | static struct iwl_hcmd_ops iwl5000_hcmd = { | 1502 | static struct iwl_hcmd_ops iwl5000_hcmd = { |
1448 | .rxon_assoc = iwl5000_send_rxon_assoc, | 1503 | .rxon_assoc = iwl5000_send_rxon_assoc, |
1449 | }; | 1504 | }; |
@@ -1454,6 +1509,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | |||
1454 | .gain_computation = iwl5000_gain_computation, | 1509 | .gain_computation = iwl5000_gain_computation, |
1455 | .chain_noise_reset = iwl5000_chain_noise_reset, | 1510 | .chain_noise_reset = iwl5000_chain_noise_reset, |
1456 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | 1511 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, |
1512 | .calc_rssi = iwl5000_calc_rssi, | ||
1457 | }; | 1513 | }; |
1458 | 1514 | ||
1459 | static struct iwl_lib_ops iwl5000_lib = { | 1515 | static struct iwl_lib_ops iwl5000_lib = { |
@@ -1474,6 +1530,7 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
1474 | .alive_notify = iwl5000_alive_notify, | 1530 | .alive_notify = iwl5000_alive_notify, |
1475 | .send_tx_power = iwl5000_send_tx_power, | 1531 | .send_tx_power = iwl5000_send_tx_power, |
1476 | .temperature = iwl5000_temperature, | 1532 | .temperature = iwl5000_temperature, |
1533 | .update_chain_flags = iwl4965_update_chain_flags, | ||
1477 | .apm_ops = { | 1534 | .apm_ops = { |
1478 | .init = iwl5000_apm_init, | 1535 | .init = iwl5000_apm_init, |
1479 | .reset = iwl5000_apm_reset, | 1536 | .reset = iwl5000_apm_reset, |